@optifye/dashboard-core 6.12.51 → 6.12.52
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/automation.js +2 -0
- package/dist/automation.js.map +1 -0
- package/dist/automation.mjs +2 -0
- package/dist/automation.mjs.map +1 -0
- package/dist/index.css +1 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +73 -33
- package/dist/index.d.ts +73 -33
- package/dist/index.js +2621 -548
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2622 -550
- package/dist/index.mjs.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { EventEmitter } from 'events';
|
|
|
10
10
|
import { createClient, REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js';
|
|
11
11
|
import Hls, { Events, ErrorTypes } from 'hls.js';
|
|
12
12
|
import useSWR from 'swr';
|
|
13
|
-
import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, RefreshCw, ArrowUpDown, X, Coffee, Plus, Filter, ArrowUp, ArrowDown, ArrowRight, HelpCircle, ClipboardX, Activity, Wrench, UserX, Clock, Package, Monitor, CheckCircle2, ArrowLeft, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle,
|
|
13
|
+
import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, RefreshCw, ArrowUpDown, X, Coffee, Plus, Filter, ArrowUp, ArrowDown, ArrowRight, HelpCircle, ClipboardX, Activity, Wrench, UserX, Clock, Package, Monitor, CheckCircle2, ArrowLeft, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, Palette, LockKeyhole, XCircle, Search, Edit2, TrendingDown, FolderOpen, Folder, ArrowDownWideNarrow, Tag, Sliders, Layers, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Video, Copy, Lightbulb, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, ExternalLink, Flame, Crown, Medal } from 'lucide-react';
|
|
14
14
|
import { memo, noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds } from 'motion-utils';
|
|
15
15
|
import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, Customized, Cell, PieChart, Pie, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
|
|
16
16
|
import { Slot } from '@radix-ui/react-slot';
|
|
@@ -6038,7 +6038,8 @@ var getAuthToken2 = async () => {
|
|
|
6038
6038
|
var workspaceService = {
|
|
6039
6039
|
// Cache for workspace display names to avoid repeated API calls
|
|
6040
6040
|
_workspaceDisplayNamesCache: /* @__PURE__ */ new Map(),
|
|
6041
|
-
|
|
6041
|
+
_workspaceDisplayNamesInFlight: /* @__PURE__ */ new Map(),
|
|
6042
|
+
_workspaceDisplayNamesByLineInFlight: /* @__PURE__ */ new Map(),
|
|
6042
6043
|
_cacheExpiryMs: 5 * 60 * 1e3,
|
|
6043
6044
|
// 5 minutes cache
|
|
6044
6045
|
// Cache for workspace lists to avoid repeated API calls (line configuration changes infrequently)
|
|
@@ -6297,12 +6298,74 @@ var workspaceService = {
|
|
|
6297
6298
|
* Returns a map of workspace_id -> display_name
|
|
6298
6299
|
*/
|
|
6299
6300
|
async getWorkspaceDisplayNames(companyId, lineId) {
|
|
6300
|
-
|
|
6301
|
+
const cacheKey = `${companyId || "all"}::${lineId || "all"}`;
|
|
6302
|
+
const existingInFlight = this._workspaceDisplayNamesInFlight.get(cacheKey);
|
|
6303
|
+
if (existingInFlight) {
|
|
6304
|
+
return existingInFlight;
|
|
6305
|
+
}
|
|
6306
|
+
const fetchPromise = (async () => {
|
|
6307
|
+
try {
|
|
6308
|
+
const token = await getAuthToken2();
|
|
6309
|
+
const apiUrl = getBackendUrl2();
|
|
6310
|
+
const params = new URLSearchParams();
|
|
6311
|
+
if (companyId) params.append("company_id", companyId);
|
|
6312
|
+
if (lineId) params.append("line_id", lineId);
|
|
6313
|
+
const response = await fetch(`${apiUrl}/api/workspaces/display-names?${params.toString()}`, {
|
|
6314
|
+
headers: {
|
|
6315
|
+
"Authorization": `Bearer ${token}`,
|
|
6316
|
+
"Content-Type": "application/json"
|
|
6317
|
+
}
|
|
6318
|
+
});
|
|
6319
|
+
if (!response.ok) {
|
|
6320
|
+
const errorText = await response.text();
|
|
6321
|
+
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
6322
|
+
}
|
|
6323
|
+
const data = await response.json();
|
|
6324
|
+
const displayNamesMap = /* @__PURE__ */ new Map();
|
|
6325
|
+
if (data.display_names) {
|
|
6326
|
+
Object.entries(data.display_names).forEach(([key, value]) => {
|
|
6327
|
+
displayNamesMap.set(key, value);
|
|
6328
|
+
});
|
|
6329
|
+
}
|
|
6330
|
+
this._workspaceDisplayNamesCache.set(cacheKey, {
|
|
6331
|
+
displayNames: displayNamesMap,
|
|
6332
|
+
timestamp: Date.now()
|
|
6333
|
+
});
|
|
6334
|
+
return displayNamesMap;
|
|
6335
|
+
} catch (error) {
|
|
6336
|
+
console.error("Error fetching workspace display names:", error);
|
|
6337
|
+
addSentryBreadcrumb("Workspace display-name fallback failed", {
|
|
6338
|
+
surface: "workspace_display_names",
|
|
6339
|
+
route: "/api/workspaces/display-names",
|
|
6340
|
+
severity: "warning",
|
|
6341
|
+
extras: {
|
|
6342
|
+
company_id: companyId || null,
|
|
6343
|
+
line_id: lineId || null,
|
|
6344
|
+
pathname: typeof window !== "undefined" ? window.location.pathname : "unknown",
|
|
6345
|
+
error_message: error instanceof Error ? error.message : String(error)
|
|
6346
|
+
}
|
|
6347
|
+
});
|
|
6348
|
+
throw error;
|
|
6349
|
+
} finally {
|
|
6350
|
+
this._workspaceDisplayNamesInFlight.delete(cacheKey);
|
|
6351
|
+
}
|
|
6352
|
+
})();
|
|
6353
|
+
this._workspaceDisplayNamesInFlight.set(cacheKey, fetchPromise);
|
|
6354
|
+
return fetchPromise;
|
|
6355
|
+
},
|
|
6356
|
+
async getWorkspaceDisplayNamesByLine(companyId, lineIds) {
|
|
6357
|
+
const normalizedLineIds = Array.from(new Set((lineIds || []).filter(Boolean))).sort();
|
|
6358
|
+
const cacheKey = `${companyId || "all"}::byLine::${normalizedLineIds.join(",") || "all"}`;
|
|
6359
|
+
const existingInFlight = this._workspaceDisplayNamesByLineInFlight.get(cacheKey);
|
|
6360
|
+
if (existingInFlight) {
|
|
6361
|
+
return existingInFlight;
|
|
6362
|
+
}
|
|
6363
|
+
const fetchPromise = (async () => {
|
|
6301
6364
|
const token = await getAuthToken2();
|
|
6302
6365
|
const apiUrl = getBackendUrl2();
|
|
6303
6366
|
const params = new URLSearchParams();
|
|
6304
6367
|
if (companyId) params.append("company_id", companyId);
|
|
6305
|
-
if (
|
|
6368
|
+
if (normalizedLineIds.length > 0) params.append("line_ids", normalizedLineIds.join(","));
|
|
6306
6369
|
const response = await fetch(`${apiUrl}/api/workspaces/display-names?${params.toString()}`, {
|
|
6307
6370
|
headers: {
|
|
6308
6371
|
"Authorization": `Bearer ${token}`,
|
|
@@ -6314,39 +6377,32 @@ var workspaceService = {
|
|
|
6314
6377
|
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
6315
6378
|
}
|
|
6316
6379
|
const data = await response.json();
|
|
6317
|
-
const
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6380
|
+
const source = data.display_names_by_line || {};
|
|
6381
|
+
const byLine = /* @__PURE__ */ new Map();
|
|
6382
|
+
Object.entries(source).forEach(([lineId, displayNames]) => {
|
|
6383
|
+
if (normalizedLineIds.length > 0 && !normalizedLineIds.includes(lineId)) return;
|
|
6384
|
+
const lineMap = /* @__PURE__ */ new Map();
|
|
6385
|
+
Object.entries(displayNames).forEach(([workspaceId, displayName]) => {
|
|
6386
|
+
lineMap.set(workspaceId, displayName);
|
|
6321
6387
|
});
|
|
6322
|
-
|
|
6323
|
-
this._workspaceDisplayNamesCache = displayNamesMap;
|
|
6324
|
-
this._cacheTimestamp = Date.now();
|
|
6325
|
-
return displayNamesMap;
|
|
6326
|
-
} catch (error) {
|
|
6327
|
-
console.error("Error fetching workspace display names:", error);
|
|
6328
|
-
addSentryBreadcrumb("Workspace display-name fallback failed", {
|
|
6329
|
-
surface: "workspace_display_names",
|
|
6330
|
-
route: "/api/workspaces/display-names",
|
|
6331
|
-
severity: "warning",
|
|
6332
|
-
extras: {
|
|
6333
|
-
company_id: companyId || null,
|
|
6334
|
-
line_id: lineId || null,
|
|
6335
|
-
pathname: typeof window !== "undefined" ? window.location.pathname : "unknown",
|
|
6336
|
-
error_message: error instanceof Error ? error.message : String(error)
|
|
6337
|
-
}
|
|
6388
|
+
byLine.set(lineId, lineMap);
|
|
6338
6389
|
});
|
|
6339
|
-
|
|
6340
|
-
}
|
|
6390
|
+
return byLine;
|
|
6391
|
+
})().finally(() => {
|
|
6392
|
+
this._workspaceDisplayNamesByLineInFlight.delete(cacheKey);
|
|
6393
|
+
});
|
|
6394
|
+
this._workspaceDisplayNamesByLineInFlight.set(cacheKey, fetchPromise);
|
|
6395
|
+
return fetchPromise;
|
|
6341
6396
|
},
|
|
6342
6397
|
/**
|
|
6343
6398
|
* Gets cached workspace display names (with cache expiry)
|
|
6344
6399
|
*/
|
|
6345
6400
|
async getCachedWorkspaceDisplayNames(companyId, lineId) {
|
|
6346
6401
|
const now4 = Date.now();
|
|
6347
|
-
const
|
|
6348
|
-
|
|
6349
|
-
|
|
6402
|
+
const cacheKey = `${companyId || "all"}::${lineId || "all"}`;
|
|
6403
|
+
const cached = this._workspaceDisplayNamesCache.get(cacheKey);
|
|
6404
|
+
if (cached && now4 - cached.timestamp < this._cacheExpiryMs && cached.displayNames.size > 0) {
|
|
6405
|
+
return cached.displayNames;
|
|
6350
6406
|
}
|
|
6351
6407
|
return this.getWorkspaceDisplayNames(companyId, lineId);
|
|
6352
6408
|
},
|
|
@@ -6367,7 +6423,8 @@ var workspaceService = {
|
|
|
6367
6423
|
*/
|
|
6368
6424
|
clearWorkspaceDisplayNamesCache() {
|
|
6369
6425
|
this._workspaceDisplayNamesCache.clear();
|
|
6370
|
-
this.
|
|
6426
|
+
this._workspaceDisplayNamesInFlight.clear();
|
|
6427
|
+
this._workspaceDisplayNamesByLineInFlight.clear();
|
|
6371
6428
|
},
|
|
6372
6429
|
clearWorkspacesCache() {
|
|
6373
6430
|
this._workspacesCache.clear();
|
|
@@ -6873,10 +6930,16 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
6873
6930
|
hasBackendUrl() {
|
|
6874
6931
|
return Boolean(process.env.NEXT_PUBLIC_BACKEND_URL);
|
|
6875
6932
|
}
|
|
6933
|
+
isCanonicalDate(value) {
|
|
6934
|
+
return typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value);
|
|
6935
|
+
}
|
|
6876
6936
|
async fetchBackendWorkspaceUptimeSummaries(companyId, lineIds, date, shiftId, timezone) {
|
|
6877
6937
|
if (!this.hasBackendUrl()) {
|
|
6878
6938
|
return null;
|
|
6879
6939
|
}
|
|
6940
|
+
if (!this.isCanonicalDate(date)) {
|
|
6941
|
+
return null;
|
|
6942
|
+
}
|
|
6880
6943
|
const supabase = _getSupabaseInstance();
|
|
6881
6944
|
if (!supabase) throw new Error("Supabase client not initialized");
|
|
6882
6945
|
const params = new URLSearchParams({
|
|
@@ -6926,6 +6989,9 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
6926
6989
|
if (!this.hasBackendUrl()) {
|
|
6927
6990
|
return null;
|
|
6928
6991
|
}
|
|
6992
|
+
if (!this.isCanonicalDate(date)) {
|
|
6993
|
+
return null;
|
|
6994
|
+
}
|
|
6929
6995
|
const supabase = _getSupabaseInstance();
|
|
6930
6996
|
if (!supabase) throw new Error("Supabase client not initialized");
|
|
6931
6997
|
const params = new URLSearchParams({
|
|
@@ -7660,6 +7726,24 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
7660
7726
|
const currentTiming = this.getShiftTiming(timezone, shiftConfig);
|
|
7661
7727
|
const queryDate = overrideDate ?? currentTiming.date;
|
|
7662
7728
|
const queryShiftId = overrideShiftId ?? currentTiming.shiftId;
|
|
7729
|
+
if (!this.isCanonicalDate(queryDate)) {
|
|
7730
|
+
return {
|
|
7731
|
+
shiftId: queryShiftId,
|
|
7732
|
+
shiftLabel: currentTiming.shiftLabel,
|
|
7733
|
+
shiftStart: formatInTimeZone(currentTiming.shiftStartDate, timezone, "yyyy-MM-dd'T'HH:mm:ssXXX"),
|
|
7734
|
+
shiftEnd: formatInTimeZone(currentTiming.shiftEndDate, timezone, "yyyy-MM-dd'T'HH:mm:ssXXX"),
|
|
7735
|
+
totalMinutes: currentTiming.totalMinutes,
|
|
7736
|
+
completedMinutes: currentTiming.completedMinutes,
|
|
7737
|
+
uptimeMinutes: 0,
|
|
7738
|
+
downtimeMinutes: 0,
|
|
7739
|
+
pendingMinutes: currentTiming.pendingMinutes,
|
|
7740
|
+
uptimePercentage: 0,
|
|
7741
|
+
hasData: false,
|
|
7742
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7743
|
+
points: [],
|
|
7744
|
+
downtimeSegments: []
|
|
7745
|
+
};
|
|
7746
|
+
}
|
|
7663
7747
|
if (lineId) {
|
|
7664
7748
|
const backendTimeline = await this.fetchBackendWorkspaceUptimeTimeline(
|
|
7665
7749
|
workspaceId,
|
|
@@ -7882,6 +7966,9 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
7882
7966
|
const defaultTimezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
|
|
7883
7967
|
const shiftConfig = passedShiftConfig || dashboardConfig?.shiftConfig;
|
|
7884
7968
|
const effectiveTimezone = timezone || shiftConfig?.timezone || defaultTimezone;
|
|
7969
|
+
if (overrideDate !== void 0 && !this.isCanonicalDate(overrideDate)) {
|
|
7970
|
+
return /* @__PURE__ */ new Map();
|
|
7971
|
+
}
|
|
7885
7972
|
if (lineShiftConfigs && lineShiftConfigs.size > 0) {
|
|
7886
7973
|
return this.calculateWorkspaceUptimeMultiLine(
|
|
7887
7974
|
companyId,
|
|
@@ -11974,85 +12061,290 @@ function formatReasonLabel(reason) {
|
|
|
11974
12061
|
return reason.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
11975
12062
|
}
|
|
11976
12063
|
|
|
12064
|
+
// src/lib/services/sessionActivityAccumulator.ts
|
|
12065
|
+
var TRACKED_ACTIVITY_EVENTS = ["mousemove", "pointermove", "keydown", "click", "scroll", "wheel", "touchstart"];
|
|
12066
|
+
function createSessionData(sessionId, userId, companyId, now4, isVisible, isFocused) {
|
|
12067
|
+
return {
|
|
12068
|
+
sessionId,
|
|
12069
|
+
userId,
|
|
12070
|
+
companyId,
|
|
12071
|
+
startedAt: now4,
|
|
12072
|
+
lastTick: now4,
|
|
12073
|
+
cumulativeTotalMs: 0,
|
|
12074
|
+
cumulativeActiveMs: 0,
|
|
12075
|
+
cumulativePassiveMs: 0,
|
|
12076
|
+
lastActivityAt: null,
|
|
12077
|
+
isUserActive: false,
|
|
12078
|
+
isVisible,
|
|
12079
|
+
isFocused,
|
|
12080
|
+
state: "ACTIVE",
|
|
12081
|
+
currentSegment: null,
|
|
12082
|
+
pendingSegments: [],
|
|
12083
|
+
segmentCounter: 0
|
|
12084
|
+
};
|
|
12085
|
+
}
|
|
12086
|
+
var SessionActivityAccumulator = class {
|
|
12087
|
+
constructor(idleThresholdMs, getDashboardView) {
|
|
12088
|
+
this.idleThresholdMs = idleThresholdMs;
|
|
12089
|
+
this.getDashboardView = getDashboardView;
|
|
12090
|
+
}
|
|
12091
|
+
shouldTrackTime(session) {
|
|
12092
|
+
if (!session) return false;
|
|
12093
|
+
return session.state === "ACTIVE" && session.isVisible && session.isFocused;
|
|
12094
|
+
}
|
|
12095
|
+
getActivityState(session, now4) {
|
|
12096
|
+
if (!session.lastActivityAt) {
|
|
12097
|
+
return "passive";
|
|
12098
|
+
}
|
|
12099
|
+
const timeSinceActivity = now4.getTime() - session.lastActivityAt.getTime();
|
|
12100
|
+
return timeSinceActivity <= this.idleThresholdMs ? "active" : "passive";
|
|
12101
|
+
}
|
|
12102
|
+
updateTimes(session, now4 = /* @__PURE__ */ new Date()) {
|
|
12103
|
+
if (!session || session.state === "ENDED") return;
|
|
12104
|
+
const elapsed = now4.getTime() - session.lastTick.getTime();
|
|
12105
|
+
if (elapsed <= 0) return;
|
|
12106
|
+
if (!this.shouldTrackTime(session)) {
|
|
12107
|
+
this.flushCurrentSegment(session, now4);
|
|
12108
|
+
session.lastTick = now4;
|
|
12109
|
+
return;
|
|
12110
|
+
}
|
|
12111
|
+
let cursor = new Date(session.lastTick);
|
|
12112
|
+
const idleCutoff = session.lastActivityAt ? new Date(session.lastActivityAt.getTime() + this.idleThresholdMs) : null;
|
|
12113
|
+
if (idleCutoff && cursor < idleCutoff && now4 > idleCutoff) {
|
|
12114
|
+
this.addTrackedDuration(session, "active", cursor, idleCutoff);
|
|
12115
|
+
cursor = idleCutoff;
|
|
12116
|
+
}
|
|
12117
|
+
this.addTrackedDuration(session, this.getActivityState(session, now4), cursor, now4);
|
|
12118
|
+
session.lastTick = now4;
|
|
12119
|
+
}
|
|
12120
|
+
flushCurrentSegment(session, endAt) {
|
|
12121
|
+
if (!session?.currentSegment) return;
|
|
12122
|
+
const current = session.currentSegment;
|
|
12123
|
+
const currentEndMs = new Date(current.segment_end_at).getTime();
|
|
12124
|
+
if (endAt.getTime() > currentEndMs) {
|
|
12125
|
+
current.duration_ms += endAt.getTime() - currentEndMs;
|
|
12126
|
+
current.segment_end_at = endAt.toISOString();
|
|
12127
|
+
}
|
|
12128
|
+
if (current.duration_ms > 0) {
|
|
12129
|
+
session.pendingSegments.push(current);
|
|
12130
|
+
}
|
|
12131
|
+
session.currentSegment = null;
|
|
12132
|
+
}
|
|
12133
|
+
addTrackedDuration(session, state, start, end) {
|
|
12134
|
+
const durationMs = end.getTime() - start.getTime();
|
|
12135
|
+
if (durationMs <= 0) return;
|
|
12136
|
+
session.cumulativeTotalMs += durationMs;
|
|
12137
|
+
if (state === "active") {
|
|
12138
|
+
session.cumulativeActiveMs += durationMs;
|
|
12139
|
+
session.isUserActive = true;
|
|
12140
|
+
} else {
|
|
12141
|
+
session.cumulativePassiveMs += durationMs;
|
|
12142
|
+
session.isUserActive = false;
|
|
12143
|
+
}
|
|
12144
|
+
this.addSegmentDuration(session, state, start, end);
|
|
12145
|
+
}
|
|
12146
|
+
addSegmentDuration(session, state, start, end) {
|
|
12147
|
+
const durationMs = end.getTime() - start.getTime();
|
|
12148
|
+
if (durationMs <= 0) return;
|
|
12149
|
+
const dashboardView = this.getDashboardView();
|
|
12150
|
+
const current = session.currentSegment;
|
|
12151
|
+
if (current && current.state === state && current.dashboard_view === dashboardView && current.segment_end_at === start.toISOString()) {
|
|
12152
|
+
current.segment_end_at = end.toISOString();
|
|
12153
|
+
current.duration_ms += durationMs;
|
|
12154
|
+
return;
|
|
12155
|
+
}
|
|
12156
|
+
this.flushCurrentSegment(session, start);
|
|
12157
|
+
session.segmentCounter += 1;
|
|
12158
|
+
session.currentSegment = {
|
|
12159
|
+
client_segment_id: `${session.sessionId}_seg_${session.segmentCounter}`,
|
|
12160
|
+
segment_start_at: start.toISOString(),
|
|
12161
|
+
segment_end_at: end.toISOString(),
|
|
12162
|
+
state,
|
|
12163
|
+
duration_ms: durationMs,
|
|
12164
|
+
dashboard_view: dashboardView,
|
|
12165
|
+
tracker_version: 2
|
|
12166
|
+
};
|
|
12167
|
+
}
|
|
12168
|
+
};
|
|
12169
|
+
|
|
12170
|
+
// src/lib/services/sessionTrackerTransport.ts
|
|
12171
|
+
var SessionTrackerTransport = class {
|
|
12172
|
+
constructor(config, trackerVersion, maxSegmentsPerRequest) {
|
|
12173
|
+
this.config = config;
|
|
12174
|
+
this.trackerVersion = trackerVersion;
|
|
12175
|
+
this.maxSegmentsPerRequest = maxSegmentsPerRequest;
|
|
12176
|
+
}
|
|
12177
|
+
async sendStartSession(session) {
|
|
12178
|
+
const token = await this.config.getAccessToken();
|
|
12179
|
+
if (!token) {
|
|
12180
|
+
console.warn("[SessionTracker] No access token, skipping start session API call");
|
|
12181
|
+
return;
|
|
12182
|
+
}
|
|
12183
|
+
await fetch(`${this.config.apiBaseUrl}/api/sessions/start`, {
|
|
12184
|
+
method: "POST",
|
|
12185
|
+
headers: this.authHeaders(token),
|
|
12186
|
+
body: JSON.stringify({
|
|
12187
|
+
session_id: session.sessionId,
|
|
12188
|
+
user_agent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
|
|
12189
|
+
dashboard_view: this.getDashboardView(),
|
|
12190
|
+
tracker_version: this.trackerVersion
|
|
12191
|
+
})
|
|
12192
|
+
});
|
|
12193
|
+
}
|
|
12194
|
+
async sendHeartbeat(session) {
|
|
12195
|
+
const token = await this.config.getAccessToken();
|
|
12196
|
+
if (!token) return null;
|
|
12197
|
+
const segmentsToSend = session.pendingSegments.slice(0, this.maxSegmentsPerRequest);
|
|
12198
|
+
const sentSegmentIds = new Set(segmentsToSend.map((segment) => segment.client_segment_id));
|
|
12199
|
+
const response = await fetch(`${this.config.apiBaseUrl}/api/sessions/heartbeat`, {
|
|
12200
|
+
method: "POST",
|
|
12201
|
+
headers: this.authHeaders(token),
|
|
12202
|
+
body: JSON.stringify({
|
|
12203
|
+
session_id: session.sessionId,
|
|
12204
|
+
cumulative_total_ms: session.cumulativeTotalMs,
|
|
12205
|
+
cumulative_active_ms: session.cumulativeActiveMs,
|
|
12206
|
+
cumulative_passive_ms: session.cumulativePassiveMs,
|
|
12207
|
+
visibility_state: typeof document !== "undefined" ? document.visibilityState : "visible",
|
|
12208
|
+
is_user_active: session.isUserActive,
|
|
12209
|
+
dashboard_view: this.getDashboardView(),
|
|
12210
|
+
tracker_version: this.trackerVersion,
|
|
12211
|
+
activity_segments: segmentsToSend
|
|
12212
|
+
})
|
|
12213
|
+
});
|
|
12214
|
+
const payload = await response.json().catch(() => ({}));
|
|
12215
|
+
return {
|
|
12216
|
+
ok: response.ok,
|
|
12217
|
+
acknowledged: payload?.acknowledged === false ? false : payload?.acknowledged === true ? true : null,
|
|
12218
|
+
sentSegmentIds
|
|
12219
|
+
};
|
|
12220
|
+
}
|
|
12221
|
+
async sendEndSession(session, reason, keepalive) {
|
|
12222
|
+
const token = keepalive && this.config.getCachedAccessToken ? this.config.getCachedAccessToken() : await this.config.getAccessToken();
|
|
12223
|
+
if (!token) {
|
|
12224
|
+
console.warn("[SessionTracker] No access token, skipping end session API call");
|
|
12225
|
+
return false;
|
|
12226
|
+
}
|
|
12227
|
+
const response = await fetch(`${this.config.apiBaseUrl}/api/sessions/end`, {
|
|
12228
|
+
method: "POST",
|
|
12229
|
+
keepalive,
|
|
12230
|
+
headers: this.authHeaders(token),
|
|
12231
|
+
body: JSON.stringify({
|
|
12232
|
+
session_id: session.sessionId,
|
|
12233
|
+
end_reason: reason,
|
|
12234
|
+
final_total_ms: session.cumulativeTotalMs,
|
|
12235
|
+
final_active_ms: session.cumulativeActiveMs,
|
|
12236
|
+
final_passive_ms: session.cumulativePassiveMs,
|
|
12237
|
+
tracker_version: this.trackerVersion,
|
|
12238
|
+
activity_segments: session.pendingSegments.slice(0, this.maxSegmentsPerRequest)
|
|
12239
|
+
})
|
|
12240
|
+
});
|
|
12241
|
+
return response.ok;
|
|
12242
|
+
}
|
|
12243
|
+
authHeaders(token) {
|
|
12244
|
+
return {
|
|
12245
|
+
"Content-Type": "application/json",
|
|
12246
|
+
"Authorization": `Bearer ${token}`
|
|
12247
|
+
};
|
|
12248
|
+
}
|
|
12249
|
+
getDashboardView() {
|
|
12250
|
+
return typeof window !== "undefined" ? window.location.pathname : void 0;
|
|
12251
|
+
}
|
|
12252
|
+
};
|
|
12253
|
+
|
|
11977
12254
|
// src/lib/services/sessionTracker.ts
|
|
11978
12255
|
function generateSessionId() {
|
|
11979
12256
|
return `sess_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
|
11980
12257
|
}
|
|
12258
|
+
function isDebugEnabled() {
|
|
12259
|
+
return typeof process !== "undefined" && process.env.NEXT_PUBLIC_DEBUG_DASHBOARD === "true";
|
|
12260
|
+
}
|
|
12261
|
+
function debugLog(message, data) {
|
|
12262
|
+
if (isDebugEnabled()) {
|
|
12263
|
+
console.log(`[SessionTracker] ${message}`, data || {});
|
|
12264
|
+
}
|
|
12265
|
+
}
|
|
11981
12266
|
var SessionTracker = class {
|
|
11982
12267
|
constructor(config) {
|
|
11983
12268
|
this.session = null;
|
|
11984
12269
|
this.heartbeatInterval = null;
|
|
11985
|
-
this.graceTimeout = null;
|
|
11986
12270
|
this.tickInterval = null;
|
|
11987
|
-
|
|
12271
|
+
this.heartbeatInFlight = false;
|
|
12272
|
+
this.pendingForcedHeartbeat = false;
|
|
12273
|
+
this.TRACKER_VERSION = 2;
|
|
11988
12274
|
this.HEARTBEAT_INTERVAL_MS = 3e4;
|
|
11989
|
-
// 30 seconds
|
|
11990
|
-
this.HIDDEN_GRACE_PERIOD_MS = 3e5;
|
|
11991
|
-
// 5 minutes
|
|
11992
12275
|
this.IDLE_THRESHOLD_MS = 3e4;
|
|
11993
|
-
// 30 seconds without activity = passive
|
|
11994
12276
|
this.TICK_INTERVAL_MS = 1e3;
|
|
12277
|
+
this.MAX_SEGMENTS_PER_REQUEST = 200;
|
|
11995
12278
|
this.config = config;
|
|
12279
|
+
this.activityAccumulator = new SessionActivityAccumulator(
|
|
12280
|
+
this.IDLE_THRESHOLD_MS,
|
|
12281
|
+
() => this.getDashboardView()
|
|
12282
|
+
);
|
|
12283
|
+
this.transport = new SessionTrackerTransport(
|
|
12284
|
+
this.config,
|
|
12285
|
+
this.TRACKER_VERSION,
|
|
12286
|
+
this.MAX_SEGMENTS_PER_REQUEST
|
|
12287
|
+
);
|
|
11996
12288
|
this.boundHandleActivity = this.handleUserActivity.bind(this);
|
|
11997
12289
|
this.boundHandleVisibility = this.handleVisibilityChange.bind(this);
|
|
11998
12290
|
this.boundHandleBeforeUnload = this.handleBeforeUnload.bind(this);
|
|
12291
|
+
this.boundHandlePageHide = this.handlePageHide.bind(this);
|
|
12292
|
+
this.boundHandlePageShow = this.handlePageShow.bind(this);
|
|
11999
12293
|
this.boundHandleFocus = this.handleWindowFocus.bind(this);
|
|
12000
12294
|
this.boundHandleBlur = this.handleWindowBlur.bind(this);
|
|
12001
12295
|
}
|
|
12002
|
-
/**
|
|
12003
|
-
* Start a new session
|
|
12004
|
-
*/
|
|
12005
12296
|
async startSession(userId, companyId) {
|
|
12006
12297
|
if (this.session && this.session.state !== "ENDED") {
|
|
12007
|
-
|
|
12298
|
+
debugLog("Session already active, ignoring start", { sessionId: this.session.sessionId });
|
|
12008
12299
|
return;
|
|
12009
12300
|
}
|
|
12010
12301
|
const sessionId = generateSessionId();
|
|
12011
12302
|
const now4 = /* @__PURE__ */ new Date();
|
|
12012
|
-
this.session =
|
|
12303
|
+
this.session = createSessionData(
|
|
12013
12304
|
sessionId,
|
|
12014
12305
|
userId,
|
|
12015
12306
|
companyId,
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12307
|
+
now4,
|
|
12308
|
+
this.getDocumentVisibility(),
|
|
12309
|
+
this.getWindowFocus()
|
|
12310
|
+
);
|
|
12311
|
+
await this.sendStartSession();
|
|
12312
|
+
if (!this.session || this.session.sessionId !== sessionId) {
|
|
12313
|
+
return;
|
|
12314
|
+
}
|
|
12315
|
+
if (this.session.state === "ENDED") {
|
|
12316
|
+
await this.sendEndSession(this.session.endReason || "navigation");
|
|
12317
|
+
debugLog("Session start completed after local end", { sessionId });
|
|
12318
|
+
return;
|
|
12319
|
+
}
|
|
12320
|
+
const trackingStart = /* @__PURE__ */ new Date();
|
|
12321
|
+
this.session.lastTick = trackingStart;
|
|
12322
|
+
this.session.isVisible = this.getDocumentVisibility();
|
|
12323
|
+
this.session.isFocused = this.getWindowFocus();
|
|
12028
12324
|
this.setupActivityListeners();
|
|
12029
12325
|
this.setupVisibilityListener();
|
|
12030
12326
|
this.setupFocusListeners();
|
|
12031
|
-
this.
|
|
12327
|
+
this.setupPageLifecycleListeners();
|
|
12032
12328
|
this.startTimeTick();
|
|
12033
12329
|
this.startHeartbeat();
|
|
12034
|
-
await this.sendStartSession();
|
|
12035
12330
|
this.config.onSessionStart?.(sessionId);
|
|
12036
|
-
|
|
12331
|
+
debugLog("Session started", { sessionId });
|
|
12037
12332
|
}
|
|
12038
|
-
/**
|
|
12039
|
-
* End the current session
|
|
12040
|
-
*/
|
|
12041
12333
|
async endSession(reason) {
|
|
12042
12334
|
if (!this.session || this.session.state === "ENDED") {
|
|
12043
12335
|
return;
|
|
12044
12336
|
}
|
|
12045
12337
|
const sessionId = this.session.sessionId;
|
|
12046
12338
|
this.updateTimes();
|
|
12339
|
+
this.flushCurrentSegment(/* @__PURE__ */ new Date());
|
|
12340
|
+
this.session.endReason = reason;
|
|
12341
|
+
await this.drainPendingSegmentsBeforeEnd();
|
|
12047
12342
|
this.session.state = "ENDED";
|
|
12048
12343
|
this.cleanup();
|
|
12049
12344
|
await this.sendEndSession(reason);
|
|
12050
12345
|
this.config.onSessionEnd?.(sessionId, reason);
|
|
12051
|
-
|
|
12346
|
+
debugLog("Session ended", { sessionId, reason });
|
|
12052
12347
|
}
|
|
12053
|
-
/**
|
|
12054
|
-
* Get current session stats (for debugging/display)
|
|
12055
|
-
*/
|
|
12056
12348
|
getSessionStats() {
|
|
12057
12349
|
if (!this.session) return null;
|
|
12058
12350
|
return {
|
|
@@ -12061,11 +12353,9 @@ var SessionTracker = class {
|
|
|
12061
12353
|
passiveMs: this.session.cumulativePassiveMs
|
|
12062
12354
|
};
|
|
12063
12355
|
}
|
|
12064
|
-
// ===== Private Methods =====
|
|
12065
12356
|
setupActivityListeners() {
|
|
12066
12357
|
if (typeof window === "undefined") return;
|
|
12067
|
-
|
|
12068
|
-
events.forEach((event) => {
|
|
12358
|
+
TRACKED_ACTIVITY_EVENTS.forEach((event) => {
|
|
12069
12359
|
window.addEventListener(event, this.boundHandleActivity, { passive: true });
|
|
12070
12360
|
});
|
|
12071
12361
|
}
|
|
@@ -12078,71 +12368,100 @@ var SessionTracker = class {
|
|
|
12078
12368
|
window.addEventListener("focus", this.boundHandleFocus);
|
|
12079
12369
|
window.addEventListener("blur", this.boundHandleBlur);
|
|
12080
12370
|
}
|
|
12081
|
-
|
|
12371
|
+
setupPageLifecycleListeners() {
|
|
12082
12372
|
if (typeof window === "undefined") return;
|
|
12083
12373
|
window.addEventListener("beforeunload", this.boundHandleBeforeUnload);
|
|
12374
|
+
window.addEventListener("pagehide", this.boundHandlePageHide);
|
|
12375
|
+
window.addEventListener("pageshow", this.boundHandlePageShow);
|
|
12084
12376
|
}
|
|
12085
|
-
handleUserActivity() {
|
|
12377
|
+
handleUserActivity(event) {
|
|
12086
12378
|
if (!this.session || this.session.state === "ENDED") return;
|
|
12379
|
+
if ("isTrusted" in event && event.isTrusted === false) return;
|
|
12380
|
+
this.updateTimes();
|
|
12087
12381
|
this.session.lastActivityAt = /* @__PURE__ */ new Date();
|
|
12088
12382
|
this.session.isUserActive = true;
|
|
12089
12383
|
}
|
|
12090
12384
|
handleVisibilityChange() {
|
|
12091
12385
|
if (!this.session || this.session.state === "ENDED") return;
|
|
12386
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
12387
|
+
this.updateTimes(now4);
|
|
12092
12388
|
if (document.visibilityState === "hidden") {
|
|
12093
|
-
this.
|
|
12094
|
-
this.session.state = "BACKGROUND_GRACE";
|
|
12389
|
+
this.flushCurrentSegment(now4);
|
|
12095
12390
|
this.session.isVisible = false;
|
|
12096
12391
|
this.session.isFocused = false;
|
|
12097
|
-
this.session.
|
|
12098
|
-
this.
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
if (this.graceTimeout) {
|
|
12104
|
-
clearTimeout(this.graceTimeout);
|
|
12105
|
-
this.graceTimeout = null;
|
|
12106
|
-
}
|
|
12107
|
-
this.session.hiddenSince = null;
|
|
12108
|
-
this.session.state = "ACTIVE";
|
|
12109
|
-
this.session.isVisible = true;
|
|
12110
|
-
this.session.isFocused = typeof document !== "undefined" && typeof document.hasFocus === "function" ? document.hasFocus() : true;
|
|
12111
|
-
this.session.lastActivityAt = /* @__PURE__ */ new Date();
|
|
12112
|
-
this.session.isUserActive = true;
|
|
12113
|
-
this.session.lastTick = /* @__PURE__ */ new Date();
|
|
12114
|
-
console.log("[SessionTracker] Tab visible again");
|
|
12392
|
+
this.session.isUserActive = false;
|
|
12393
|
+
this.session.lastActivityAt = null;
|
|
12394
|
+
this.session.lastTick = now4;
|
|
12395
|
+
void this.sendHeartbeat(true);
|
|
12396
|
+
debugLog("Tab hidden");
|
|
12397
|
+
return;
|
|
12115
12398
|
}
|
|
12399
|
+
this.session.isVisible = true;
|
|
12400
|
+
this.session.isFocused = this.getWindowFocus();
|
|
12401
|
+
this.session.isUserActive = false;
|
|
12402
|
+
this.session.lastActivityAt = null;
|
|
12403
|
+
this.session.lastTick = now4;
|
|
12404
|
+
void this.sendHeartbeat(true);
|
|
12405
|
+
debugLog("Tab visible");
|
|
12116
12406
|
}
|
|
12117
12407
|
handleWindowFocus() {
|
|
12118
12408
|
if (!this.session || this.session.state === "ENDED") return;
|
|
12409
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
12410
|
+
this.updateTimes(now4);
|
|
12119
12411
|
this.session.isFocused = true;
|
|
12120
|
-
this.session.
|
|
12121
|
-
this.session.
|
|
12122
|
-
this.session.lastTick =
|
|
12412
|
+
this.session.isUserActive = false;
|
|
12413
|
+
this.session.lastActivityAt = null;
|
|
12414
|
+
this.session.lastTick = now4;
|
|
12415
|
+
void this.sendHeartbeat(true);
|
|
12123
12416
|
}
|
|
12124
12417
|
handleWindowBlur() {
|
|
12125
12418
|
if (!this.session || this.session.state === "ENDED") return;
|
|
12419
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
12420
|
+
this.updateTimes(now4);
|
|
12421
|
+
this.flushCurrentSegment(now4);
|
|
12126
12422
|
this.session.isFocused = false;
|
|
12127
|
-
this.session.
|
|
12423
|
+
this.session.isUserActive = false;
|
|
12424
|
+
this.session.lastActivityAt = null;
|
|
12425
|
+
this.session.lastTick = now4;
|
|
12426
|
+
void this.sendHeartbeat(true);
|
|
12128
12427
|
}
|
|
12129
|
-
handleBeforeUnload(
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
12138
|
-
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
12142
|
-
|
|
12143
|
-
this.
|
|
12144
|
-
|
|
12428
|
+
handleBeforeUnload() {
|
|
12429
|
+
this.finalizeWithKeepalive("tab_close");
|
|
12430
|
+
}
|
|
12431
|
+
handlePageHide(event) {
|
|
12432
|
+
if (event.persisted) {
|
|
12433
|
+
if (!this.session || this.session.state === "ENDED") return;
|
|
12434
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
12435
|
+
this.updateTimes(now4);
|
|
12436
|
+
this.flushCurrentSegment(now4);
|
|
12437
|
+
this.session.isVisible = false;
|
|
12438
|
+
this.session.isFocused = false;
|
|
12439
|
+
this.session.isUserActive = false;
|
|
12440
|
+
this.session.lastActivityAt = null;
|
|
12441
|
+
this.session.lastTick = now4;
|
|
12442
|
+
void this.sendHeartbeat(true);
|
|
12443
|
+
return;
|
|
12145
12444
|
}
|
|
12445
|
+
this.finalizeWithKeepalive("pagehide");
|
|
12446
|
+
}
|
|
12447
|
+
handlePageShow(event) {
|
|
12448
|
+
if (!event.persisted || !this.session || this.session.state === "ENDED") return;
|
|
12449
|
+
const now4 = /* @__PURE__ */ new Date();
|
|
12450
|
+
this.session.isVisible = this.getDocumentVisibility();
|
|
12451
|
+
this.session.isFocused = this.getWindowFocus();
|
|
12452
|
+
this.session.isUserActive = false;
|
|
12453
|
+
this.session.lastActivityAt = null;
|
|
12454
|
+
this.session.lastTick = now4;
|
|
12455
|
+
void this.sendHeartbeat(true);
|
|
12456
|
+
}
|
|
12457
|
+
finalizeWithKeepalive(reason) {
|
|
12458
|
+
if (!this.session || this.session.state === "ENDED") return;
|
|
12459
|
+
this.updateTimes();
|
|
12460
|
+
this.flushCurrentSegment(/* @__PURE__ */ new Date());
|
|
12461
|
+
this.session.endReason = reason;
|
|
12462
|
+
this.session.state = "ENDED";
|
|
12463
|
+
void this.sendEndSession(reason, true);
|
|
12464
|
+
this.cleanup();
|
|
12146
12465
|
}
|
|
12147
12466
|
startTimeTick() {
|
|
12148
12467
|
this.tickInterval = setInterval(() => {
|
|
@@ -12150,30 +12469,17 @@ var SessionTracker = class {
|
|
|
12150
12469
|
}, this.TICK_INTERVAL_MS);
|
|
12151
12470
|
}
|
|
12152
12471
|
shouldTrackTime() {
|
|
12153
|
-
|
|
12154
|
-
const stateAllowsTracking = this.session.state === "ACTIVE" || this.session.state === "BACKGROUND_GRACE";
|
|
12155
|
-
return stateAllowsTracking && this.session.isVisible && this.session.isFocused;
|
|
12472
|
+
return this.activityAccumulator.shouldTrackTime(this.session);
|
|
12156
12473
|
}
|
|
12157
|
-
|
|
12158
|
-
if (!this.session
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
this.session.cumulativeTotalMs += elapsed;
|
|
12167
|
-
const timeSinceActivity = now4.getTime() - this.session.lastActivityAt.getTime();
|
|
12168
|
-
if (timeSinceActivity < this.IDLE_THRESHOLD_MS) {
|
|
12169
|
-
this.session.cumulativeActiveMs += elapsed;
|
|
12170
|
-
this.session.isUserActive = true;
|
|
12171
|
-
} else {
|
|
12172
|
-
this.session.cumulativePassiveMs += elapsed;
|
|
12173
|
-
this.session.isUserActive = false;
|
|
12174
|
-
}
|
|
12175
|
-
}
|
|
12176
|
-
this.session.lastTick = now4;
|
|
12474
|
+
getActivityState(now4) {
|
|
12475
|
+
if (!this.session) return "passive";
|
|
12476
|
+
return this.activityAccumulator.getActivityState(this.session, now4);
|
|
12477
|
+
}
|
|
12478
|
+
updateTimes(now4 = /* @__PURE__ */ new Date()) {
|
|
12479
|
+
this.activityAccumulator.updateTimes(this.session, now4);
|
|
12480
|
+
}
|
|
12481
|
+
flushCurrentSegment(endAt) {
|
|
12482
|
+
this.activityAccumulator.flushCurrentSegment(this.session, endAt);
|
|
12177
12483
|
}
|
|
12178
12484
|
startHeartbeat() {
|
|
12179
12485
|
this.heartbeatInterval = setInterval(async () => {
|
|
@@ -12183,75 +12489,70 @@ var SessionTracker = class {
|
|
|
12183
12489
|
async sendStartSession() {
|
|
12184
12490
|
if (!this.session) return;
|
|
12185
12491
|
try {
|
|
12186
|
-
|
|
12187
|
-
if (!token) {
|
|
12188
|
-
console.warn("[SessionTracker] No access token, skipping start session API call");
|
|
12189
|
-
return;
|
|
12190
|
-
}
|
|
12191
|
-
await fetch(`${this.config.apiBaseUrl}/api/sessions/start`, {
|
|
12192
|
-
method: "POST",
|
|
12193
|
-
headers: {
|
|
12194
|
-
"Content-Type": "application/json",
|
|
12195
|
-
"Authorization": `Bearer ${token}`
|
|
12196
|
-
},
|
|
12197
|
-
body: JSON.stringify({
|
|
12198
|
-
session_id: this.session.sessionId,
|
|
12199
|
-
user_agent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
|
|
12200
|
-
dashboard_view: typeof window !== "undefined" ? window.location.pathname : void 0
|
|
12201
|
-
})
|
|
12202
|
-
});
|
|
12492
|
+
await this.transport.sendStartSession(this.session);
|
|
12203
12493
|
} catch (error) {
|
|
12204
12494
|
console.error("[SessionTracker] Failed to send start session:", error);
|
|
12205
12495
|
}
|
|
12206
12496
|
}
|
|
12207
|
-
async sendHeartbeat() {
|
|
12497
|
+
async sendHeartbeat(force = false, allowReplacement = true) {
|
|
12498
|
+
if (this.heartbeatInFlight) {
|
|
12499
|
+
this.pendingForcedHeartbeat || (this.pendingForcedHeartbeat = force);
|
|
12500
|
+
return;
|
|
12501
|
+
}
|
|
12208
12502
|
if (!this.session || this.session.state === "ENDED") return;
|
|
12503
|
+
this.heartbeatInFlight = true;
|
|
12209
12504
|
try {
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
|
|
12227
|
-
});
|
|
12505
|
+
this.updateTimes();
|
|
12506
|
+
this.flushCurrentSegment(/* @__PURE__ */ new Date());
|
|
12507
|
+
if (!force && !this.shouldTrackTime()) return;
|
|
12508
|
+
const result = await this.transport.sendHeartbeat(this.session);
|
|
12509
|
+
if (!result) return;
|
|
12510
|
+
if (result.ok && result.acknowledged !== false) {
|
|
12511
|
+
debugLog("Heartbeat acknowledged", { segments: result.sentSegmentIds.size });
|
|
12512
|
+
this.session.pendingSegments = this.session.pendingSegments.filter(
|
|
12513
|
+
(segment) => !result.sentSegmentIds.has(segment.client_segment_id)
|
|
12514
|
+
);
|
|
12515
|
+
} else if (result.ok && result.acknowledged === false && allowReplacement && this.shouldTrackTime()) {
|
|
12516
|
+
const { userId, companyId, sessionId } = this.session;
|
|
12517
|
+
this.session.state = "ENDED";
|
|
12518
|
+
this.cleanup();
|
|
12519
|
+
debugLog("Heartbeat not acknowledged, starting replacement session", { sessionId });
|
|
12520
|
+
await this.startSession(userId, companyId);
|
|
12521
|
+
}
|
|
12228
12522
|
} catch (error) {
|
|
12229
12523
|
console.error("[SessionTracker] Failed to send heartbeat:", error);
|
|
12524
|
+
} finally {
|
|
12525
|
+
this.heartbeatInFlight = false;
|
|
12526
|
+
if (this.pendingForcedHeartbeat && this.session?.state !== "ENDED") {
|
|
12527
|
+
this.pendingForcedHeartbeat = false;
|
|
12528
|
+
void this.sendHeartbeat(true);
|
|
12529
|
+
}
|
|
12230
12530
|
}
|
|
12231
12531
|
}
|
|
12232
|
-
async
|
|
12532
|
+
async drainPendingSegmentsBeforeEnd() {
|
|
12533
|
+
if (!this.session) return;
|
|
12534
|
+
let guard = 0;
|
|
12535
|
+
while (this.session.state !== "ENDED" && this.session.pendingSegments.length > this.MAX_SEGMENTS_PER_REQUEST && guard < 20) {
|
|
12536
|
+
const pendingBefore = this.session.pendingSegments.length;
|
|
12537
|
+
await this.sendHeartbeat(true, false);
|
|
12538
|
+
if (!this.session || this.session.pendingSegments.length >= pendingBefore) {
|
|
12539
|
+
break;
|
|
12540
|
+
}
|
|
12541
|
+
guard += 1;
|
|
12542
|
+
}
|
|
12543
|
+
}
|
|
12544
|
+
async sendEndSession(reason, keepalive = false) {
|
|
12233
12545
|
if (!this.session) return;
|
|
12234
12546
|
try {
|
|
12235
|
-
const
|
|
12236
|
-
if (
|
|
12237
|
-
|
|
12238
|
-
return;
|
|
12547
|
+
const ok = await this.transport.sendEndSession(this.session, reason, keepalive);
|
|
12548
|
+
if (ok) {
|
|
12549
|
+
this.session.pendingSegments = this.session.pendingSegments.slice(this.MAX_SEGMENTS_PER_REQUEST);
|
|
12239
12550
|
}
|
|
12240
|
-
await fetch(`${this.config.apiBaseUrl}/api/sessions/end`, {
|
|
12241
|
-
method: "POST",
|
|
12242
|
-
headers: {
|
|
12243
|
-
"Content-Type": "application/json",
|
|
12244
|
-
"Authorization": `Bearer ${token}`
|
|
12245
|
-
},
|
|
12246
|
-
body: JSON.stringify({
|
|
12247
|
-
session_id: this.session.sessionId,
|
|
12248
|
-
end_reason: reason,
|
|
12249
|
-
final_total_ms: this.session.cumulativeTotalMs,
|
|
12250
|
-
final_active_ms: this.session.cumulativeActiveMs,
|
|
12251
|
-
final_passive_ms: this.session.cumulativePassiveMs
|
|
12252
|
-
})
|
|
12253
|
-
});
|
|
12254
12551
|
} catch (error) {
|
|
12552
|
+
if (keepalive) {
|
|
12553
|
+
debugLog("Keepalive end session failed after page lifecycle transition", { reason });
|
|
12554
|
+
return;
|
|
12555
|
+
}
|
|
12255
12556
|
console.error("[SessionTracker] Failed to send end session:", error);
|
|
12256
12557
|
}
|
|
12257
12558
|
}
|
|
@@ -12264,23 +12565,29 @@ var SessionTracker = class {
|
|
|
12264
12565
|
clearInterval(this.tickInterval);
|
|
12265
12566
|
this.tickInterval = null;
|
|
12266
12567
|
}
|
|
12267
|
-
if (this.graceTimeout) {
|
|
12268
|
-
clearTimeout(this.graceTimeout);
|
|
12269
|
-
this.graceTimeout = null;
|
|
12270
|
-
}
|
|
12271
12568
|
if (typeof window !== "undefined") {
|
|
12272
|
-
|
|
12273
|
-
events.forEach((event) => {
|
|
12569
|
+
TRACKED_ACTIVITY_EVENTS.forEach((event) => {
|
|
12274
12570
|
window.removeEventListener(event, this.boundHandleActivity);
|
|
12275
12571
|
});
|
|
12276
12572
|
window.removeEventListener("focus", this.boundHandleFocus);
|
|
12277
12573
|
window.removeEventListener("blur", this.boundHandleBlur);
|
|
12278
12574
|
window.removeEventListener("beforeunload", this.boundHandleBeforeUnload);
|
|
12575
|
+
window.removeEventListener("pagehide", this.boundHandlePageHide);
|
|
12576
|
+
window.removeEventListener("pageshow", this.boundHandlePageShow);
|
|
12279
12577
|
}
|
|
12280
12578
|
if (typeof document !== "undefined") {
|
|
12281
12579
|
document.removeEventListener("visibilitychange", this.boundHandleVisibility);
|
|
12282
12580
|
}
|
|
12283
12581
|
}
|
|
12582
|
+
getDashboardView() {
|
|
12583
|
+
return typeof window !== "undefined" ? window.location.pathname : void 0;
|
|
12584
|
+
}
|
|
12585
|
+
getDocumentVisibility() {
|
|
12586
|
+
return typeof document !== "undefined" ? document.visibilityState === "visible" : true;
|
|
12587
|
+
}
|
|
12588
|
+
getWindowFocus() {
|
|
12589
|
+
return typeof document !== "undefined" && typeof document.hasFocus === "function" ? document.hasFocus() : true;
|
|
12590
|
+
}
|
|
12284
12591
|
};
|
|
12285
12592
|
function createSessionTracker(config) {
|
|
12286
12593
|
return new SessionTracker(config);
|
|
@@ -13286,15 +13593,43 @@ function useSessionTracking(options = {}) {
|
|
|
13286
13593
|
const trackerRef = useRef(null);
|
|
13287
13594
|
const isTrackingRef = useRef(false);
|
|
13288
13595
|
const initRef = useRef(false);
|
|
13289
|
-
const
|
|
13290
|
-
|
|
13596
|
+
const accessTokenRef = useRef(null);
|
|
13597
|
+
const isAuthenticatedRef = useRef(isAuthenticated);
|
|
13598
|
+
const onSessionStartRef = useRef(onSessionStart);
|
|
13599
|
+
const onSessionEndRef = useRef(onSessionEnd);
|
|
13600
|
+
const apiBaseUrl2 = config?.apiBaseUrl || process.env.NEXT_PUBLIC_API_BASE_URL || "";
|
|
13601
|
+
isAuthenticatedRef.current = isAuthenticated;
|
|
13602
|
+
useEffect(() => {
|
|
13603
|
+
if (session?.access_token) {
|
|
13604
|
+
accessTokenRef.current = session.access_token;
|
|
13605
|
+
}
|
|
13291
13606
|
}, [session?.access_token]);
|
|
13607
|
+
useEffect(() => {
|
|
13608
|
+
onSessionStartRef.current = onSessionStart;
|
|
13609
|
+
}, [onSessionStart]);
|
|
13610
|
+
useEffect(() => {
|
|
13611
|
+
onSessionEndRef.current = onSessionEnd;
|
|
13612
|
+
}, [onSessionEnd]);
|
|
13613
|
+
const getAccessToken2 = useCallback(async () => {
|
|
13614
|
+
return accessTokenRef.current;
|
|
13615
|
+
}, []);
|
|
13616
|
+
const endCurrentTracker = useCallback((reason) => {
|
|
13617
|
+
const tracker = trackerRef.current;
|
|
13618
|
+
if (!tracker) return null;
|
|
13619
|
+
const tokenForEndingSession = accessTokenRef.current;
|
|
13620
|
+
trackerRef.current = null;
|
|
13621
|
+
isTrackingRef.current = false;
|
|
13622
|
+
return tracker.endSession(reason).finally(() => {
|
|
13623
|
+
if (reason === "logout" && !isAuthenticatedRef.current && accessTokenRef.current === tokenForEndingSession) {
|
|
13624
|
+
accessTokenRef.current = null;
|
|
13625
|
+
}
|
|
13626
|
+
});
|
|
13627
|
+
}, []);
|
|
13292
13628
|
useEffect(() => {
|
|
13293
13629
|
if (!enabled || !isAuthenticated || !user || !session || initRef.current) {
|
|
13294
13630
|
return;
|
|
13295
13631
|
}
|
|
13296
13632
|
initRef.current = true;
|
|
13297
|
-
const apiBaseUrl2 = config?.apiBaseUrl || process.env.NEXT_PUBLIC_API_BASE_URL || "";
|
|
13298
13633
|
if (!apiBaseUrl2) {
|
|
13299
13634
|
console.warn("[useSessionTracking] No API base URL configured, session tracking disabled");
|
|
13300
13635
|
return;
|
|
@@ -13302,41 +13637,34 @@ function useSessionTracking(options = {}) {
|
|
|
13302
13637
|
const tracker = createSessionTracker({
|
|
13303
13638
|
apiBaseUrl: apiBaseUrl2,
|
|
13304
13639
|
getAccessToken: getAccessToken2,
|
|
13640
|
+
getCachedAccessToken: () => accessTokenRef.current,
|
|
13305
13641
|
onSessionStart: (sessionId) => {
|
|
13306
13642
|
isTrackingRef.current = true;
|
|
13307
|
-
|
|
13643
|
+
onSessionStartRef.current?.(sessionId);
|
|
13308
13644
|
},
|
|
13309
13645
|
onSessionEnd: (sessionId, reason) => {
|
|
13310
13646
|
isTrackingRef.current = false;
|
|
13311
|
-
|
|
13647
|
+
onSessionEndRef.current?.(sessionId, reason);
|
|
13312
13648
|
}
|
|
13313
13649
|
});
|
|
13314
13650
|
trackerRef.current = tracker;
|
|
13315
13651
|
const companyId = user?.company_id || user?.properties?.company_id || null;
|
|
13316
13652
|
tracker.startSession(user.id, companyId);
|
|
13317
13653
|
return () => {
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
trackerRef.current = null;
|
|
13321
|
-
}
|
|
13654
|
+
const reason = isAuthenticatedRef.current ? "navigation" : "logout";
|
|
13655
|
+
void endCurrentTracker(reason);
|
|
13322
13656
|
initRef.current = false;
|
|
13323
13657
|
isTrackingRef.current = false;
|
|
13324
13658
|
};
|
|
13325
|
-
}, [enabled, isAuthenticated, user?.id,
|
|
13659
|
+
}, [enabled, isAuthenticated, user?.id, apiBaseUrl2, getAccessToken2, endCurrentTracker]);
|
|
13326
13660
|
useEffect(() => {
|
|
13327
13661
|
if (!isAuthenticated && trackerRef.current && isTrackingRef.current) {
|
|
13328
|
-
|
|
13329
|
-
trackerRef.current = null;
|
|
13330
|
-
isTrackingRef.current = false;
|
|
13662
|
+
void endCurrentTracker("logout");
|
|
13331
13663
|
}
|
|
13332
|
-
}, [isAuthenticated]);
|
|
13664
|
+
}, [isAuthenticated, endCurrentTracker]);
|
|
13333
13665
|
const endSession = useCallback(async (reason) => {
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
trackerRef.current = null;
|
|
13337
|
-
isTrackingRef.current = false;
|
|
13338
|
-
}
|
|
13339
|
-
}, []);
|
|
13666
|
+
await endCurrentTracker(reason);
|
|
13667
|
+
}, [endCurrentTracker]);
|
|
13340
13668
|
const sessionStats = trackerRef.current?.getSessionStats() || null;
|
|
13341
13669
|
return {
|
|
13342
13670
|
sessionStats,
|
|
@@ -17435,7 +17763,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
17435
17763
|
return Number.isFinite(parsed) ? parsed : DEFAULT_MAX_MANIFEST_AGE_MS;
|
|
17436
17764
|
})();
|
|
17437
17765
|
const manifestStaleThresholdMs = maxManifestAgeMs > 0 ? Math.min(maxManifestAgeMs, SEGMENT_MAX_AGE_MS) : SEGMENT_MAX_AGE_MS;
|
|
17438
|
-
const
|
|
17766
|
+
const debugLog2 = (...args) => {
|
|
17439
17767
|
if (debugEnabled) {
|
|
17440
17768
|
console.log(...args);
|
|
17441
17769
|
}
|
|
@@ -17617,7 +17945,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
17617
17945
|
return;
|
|
17618
17946
|
}
|
|
17619
17947
|
} catch (error) {
|
|
17620
|
-
|
|
17948
|
+
debugLog2("[HLS] Stale manifest poll failed", error);
|
|
17621
17949
|
}
|
|
17622
17950
|
staleManifestPollDelayRef.current = Math.min(
|
|
17623
17951
|
staleManifestPollDelayRef.current + 5e3,
|
|
@@ -17967,7 +18295,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
17967
18295
|
}
|
|
17968
18296
|
return true;
|
|
17969
18297
|
} catch (error) {
|
|
17970
|
-
|
|
18298
|
+
debugLog2("[HLS] Manifest freshness check failed", error);
|
|
17971
18299
|
{
|
|
17972
18300
|
markStaleStream("manifest freshness check failed");
|
|
17973
18301
|
return false;
|
|
@@ -18013,7 +18341,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18013
18341
|
};
|
|
18014
18342
|
const softRestart = (reason) => {
|
|
18015
18343
|
if (staleManifestTriggeredRef.current) {
|
|
18016
|
-
|
|
18344
|
+
debugLog2("[HLS] Skip soft restart while manifest is stale", reason);
|
|
18017
18345
|
return;
|
|
18018
18346
|
}
|
|
18019
18347
|
console.warn(`[HLS] Soft restart: ${reason}`);
|
|
@@ -18046,7 +18374,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18046
18374
|
};
|
|
18047
18375
|
const hardRestart = (reason) => {
|
|
18048
18376
|
if (staleManifestTriggeredRef.current) {
|
|
18049
|
-
|
|
18377
|
+
debugLog2("[HLS] Skip hard restart while manifest is stale", reason);
|
|
18050
18378
|
return;
|
|
18051
18379
|
}
|
|
18052
18380
|
console.warn(`[HLS] Hard restart: ${reason}`);
|
|
@@ -18300,7 +18628,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18300
18628
|
hls.loadSource(resolvedHlsSrc);
|
|
18301
18629
|
activeStreamUrlRef.current = resolvedHlsSrc;
|
|
18302
18630
|
hls.on(Hls.Events.ERROR, (_, data) => {
|
|
18303
|
-
|
|
18631
|
+
debugLog2("[HLS] Error", {
|
|
18304
18632
|
type: data.type,
|
|
18305
18633
|
details: data.details,
|
|
18306
18634
|
fatal: data.fatal,
|
|
@@ -18308,7 +18636,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18308
18636
|
frag: data.frag?.sn
|
|
18309
18637
|
});
|
|
18310
18638
|
if (data.type === Hls.ErrorTypes.MEDIA_ERROR && data.details === Hls.ErrorDetails.BUFFER_STALLED_ERROR) {
|
|
18311
|
-
|
|
18639
|
+
debugLog2("[HLS] Buffer stalled, waiting for next segment");
|
|
18312
18640
|
attemptPlay();
|
|
18313
18641
|
return;
|
|
18314
18642
|
}
|
|
@@ -18452,7 +18780,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18452
18780
|
}
|
|
18453
18781
|
}
|
|
18454
18782
|
}
|
|
18455
|
-
|
|
18783
|
+
debugLog2("[HLS] Level loaded", {
|
|
18456
18784
|
targetduration: details.targetduration,
|
|
18457
18785
|
edge: details.edge,
|
|
18458
18786
|
fragments: data.details?.fragments?.length
|
|
@@ -18848,6 +19176,7 @@ var isInitializing = false;
|
|
|
18848
19176
|
var initializedWithLineIds = [];
|
|
18849
19177
|
var missingLineContextWarnings = /* @__PURE__ */ new Set();
|
|
18850
19178
|
var lineLoadPromises = /* @__PURE__ */ new Map();
|
|
19179
|
+
var GLOBAL_CACHE_KEY = "global";
|
|
18851
19180
|
var initializationPromise = null;
|
|
18852
19181
|
var workspaceDisplayNamesListeners = /* @__PURE__ */ new Set();
|
|
18853
19182
|
var notifyWorkspaceDisplayNamesListeners = (changedLineId) => {
|
|
@@ -18869,6 +19198,22 @@ var storeLineDisplayNames = (lineId, lineDisplayNamesMap) => {
|
|
|
18869
19198
|
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
18870
19199
|
});
|
|
18871
19200
|
};
|
|
19201
|
+
var storeGlobalDisplayNames = (displayNamesMap) => {
|
|
19202
|
+
runtimeWorkspaceDisplayNames[GLOBAL_CACHE_KEY] = {};
|
|
19203
|
+
displayNamesMap.forEach((displayName, workspaceId) => {
|
|
19204
|
+
runtimeWorkspaceDisplayNames[GLOBAL_CACHE_KEY][workspaceId] = displayName;
|
|
19205
|
+
});
|
|
19206
|
+
};
|
|
19207
|
+
var storeDisplayNamesByLine = (displayNamesByLine, requestedLineIds = []) => {
|
|
19208
|
+
displayNamesByLine.forEach((lineDisplayNamesMap, lineId) => {
|
|
19209
|
+
storeLineDisplayNames(lineId, lineDisplayNamesMap);
|
|
19210
|
+
});
|
|
19211
|
+
requestedLineIds.forEach((lineId) => {
|
|
19212
|
+
if (!runtimeWorkspaceDisplayNames[lineId]) {
|
|
19213
|
+
runtimeWorkspaceDisplayNames[lineId] = {};
|
|
19214
|
+
}
|
|
19215
|
+
});
|
|
19216
|
+
};
|
|
18872
19217
|
var ensureLineWorkspaceDisplayNamesLoaded = async (lineId) => {
|
|
18873
19218
|
if (!lineId || runtimeWorkspaceDisplayNames[lineId]) {
|
|
18874
19219
|
return;
|
|
@@ -18952,7 +19297,11 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
18952
19297
|
console.log("\u{1F504} Target line IDs for workspace filtering:", targetLineIds);
|
|
18953
19298
|
runtimeWorkspaceDisplayNames = {};
|
|
18954
19299
|
lineLoadPromises.clear();
|
|
18955
|
-
if (targetLineIds.length >
|
|
19300
|
+
if (targetLineIds.length > 1) {
|
|
19301
|
+
const displayNamesByLine = await workspaceService.getWorkspaceDisplayNamesByLine(void 0, targetLineIds);
|
|
19302
|
+
storeDisplayNamesByLine(displayNamesByLine, targetLineIds);
|
|
19303
|
+
console.log(`\u2705 Stored display names for ${displayNamesByLine.size} authorized lines`);
|
|
19304
|
+
} else if (targetLineIds.length === 1) {
|
|
18956
19305
|
const results = await Promise.all(
|
|
18957
19306
|
targetLineIds.map(async (lineId) => {
|
|
18958
19307
|
console.log(`\u{1F504} Fetching workspaces for line: ${lineId}`);
|
|
@@ -18967,10 +19316,7 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
18967
19316
|
} else {
|
|
18968
19317
|
console.warn("\u26A0\uFE0F No line IDs found, fetching all workspaces (less efficient)");
|
|
18969
19318
|
const allWorkspacesMap = await workspaceService.getWorkspaceDisplayNames();
|
|
18970
|
-
|
|
18971
|
-
allWorkspacesMap.forEach((displayName, workspaceId) => {
|
|
18972
|
-
runtimeWorkspaceDisplayNames["global"][workspaceId] = displayName;
|
|
18973
|
-
});
|
|
19319
|
+
storeGlobalDisplayNames(allWorkspacesMap);
|
|
18974
19320
|
}
|
|
18975
19321
|
isInitialized = true;
|
|
18976
19322
|
initializedWithLineIds = targetLineIds;
|
|
@@ -18986,6 +19332,37 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
18986
19332
|
})();
|
|
18987
19333
|
await initializationPromise;
|
|
18988
19334
|
}
|
|
19335
|
+
var preInitializeWorkspaceDisplayNamesForLines = async (lineIds) => {
|
|
19336
|
+
const uniqueLineIds = Array.from(new Set((lineIds || []).filter(Boolean)));
|
|
19337
|
+
if (uniqueLineIds.length === 0) {
|
|
19338
|
+
await preInitializeWorkspaceDisplayNames();
|
|
19339
|
+
return;
|
|
19340
|
+
}
|
|
19341
|
+
if (uniqueLineIds.length === 1) {
|
|
19342
|
+
await preInitializeWorkspaceDisplayNames(uniqueLineIds[0]);
|
|
19343
|
+
return;
|
|
19344
|
+
}
|
|
19345
|
+
if (isInitialized && uniqueLineIds.every((lineId) => Boolean(runtimeWorkspaceDisplayNames[lineId]))) {
|
|
19346
|
+
return;
|
|
19347
|
+
}
|
|
19348
|
+
if (initializationPromise) {
|
|
19349
|
+
await initializationPromise;
|
|
19350
|
+
if (uniqueLineIds.every((lineId) => Boolean(runtimeWorkspaceDisplayNames[lineId]))) {
|
|
19351
|
+
return;
|
|
19352
|
+
}
|
|
19353
|
+
}
|
|
19354
|
+
isInitializing = true;
|
|
19355
|
+
initializationPromise = workspaceService.getWorkspaceDisplayNamesByLine(void 0, uniqueLineIds).then((displayNamesByLine) => {
|
|
19356
|
+
storeDisplayNamesByLine(displayNamesByLine, uniqueLineIds);
|
|
19357
|
+
initializedWithLineIds = uniqueLineIds;
|
|
19358
|
+
isInitialized = true;
|
|
19359
|
+
notifyWorkspaceDisplayNamesListeners();
|
|
19360
|
+
}).finally(() => {
|
|
19361
|
+
isInitializing = false;
|
|
19362
|
+
initializationPromise = null;
|
|
19363
|
+
});
|
|
19364
|
+
await initializationPromise;
|
|
19365
|
+
};
|
|
18989
19366
|
var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
18990
19367
|
console.log("\u{1F504} preInitializeWorkspaceDisplayNames called for lineId:", lineId);
|
|
18991
19368
|
if (isInitialized) {
|
|
@@ -38720,6 +39097,7 @@ var HourlyOutputChartComponent = ({
|
|
|
38720
39097
|
timeRange: data2.timeRange,
|
|
38721
39098
|
startTime,
|
|
38722
39099
|
endTime,
|
|
39100
|
+
timezone,
|
|
38723
39101
|
output: Math.round(data2.originalOutput || 0),
|
|
38724
39102
|
target: data2.target,
|
|
38725
39103
|
status: data2.status
|
|
@@ -38893,6 +39271,7 @@ var HourlyOutputChartComponent = ({
|
|
|
38893
39271
|
timeRange: entry.timeRange,
|
|
38894
39272
|
startTime,
|
|
38895
39273
|
endTime,
|
|
39274
|
+
timezone,
|
|
38896
39275
|
output: Math.round(entry.originalOutput || 0),
|
|
38897
39276
|
target: entry.target,
|
|
38898
39277
|
status: entry.status
|
|
@@ -42360,6 +42739,65 @@ var buildPrefetchedExplorerMetadata = (activeFilter, metadataCategoryId, categor
|
|
|
42360
42739
|
};
|
|
42361
42740
|
};
|
|
42362
42741
|
var shouldDeferClipPlayerRender = (cropLoading, workspaceCrop) => cropLoading && workspaceCrop === null;
|
|
42742
|
+
var parseSortableCycleTime = (value) => {
|
|
42743
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
42744
|
+
return value;
|
|
42745
|
+
}
|
|
42746
|
+
if (typeof value === "string") {
|
|
42747
|
+
const parsed = Number(value);
|
|
42748
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
42749
|
+
}
|
|
42750
|
+
return null;
|
|
42751
|
+
};
|
|
42752
|
+
var readSortableCycleTime = (clip) => {
|
|
42753
|
+
const candidate = clip;
|
|
42754
|
+
return parseSortableCycleTime(candidate?.cycleTimeSeconds) ?? parseSortableCycleTime(candidate?.cycle_time_seconds) ?? parseSortableCycleTime(candidate?.duration) ?? parseSortableCycleTime(
|
|
42755
|
+
candidate?.original_task_metadata?.cycle_time
|
|
42756
|
+
) ?? null;
|
|
42757
|
+
};
|
|
42758
|
+
var readSortableTimestamp = (clip) => {
|
|
42759
|
+
const candidate = clip;
|
|
42760
|
+
const timestamp = candidate?.creation_timestamp || candidate?.timestamp || candidate?.clip_timestamp || candidate?.clip_end_time || candidate?.clip_start_time;
|
|
42761
|
+
if (typeof timestamp !== "string") {
|
|
42762
|
+
return 0;
|
|
42763
|
+
}
|
|
42764
|
+
const parsed = new Date(timestamp).getTime();
|
|
42765
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
42766
|
+
};
|
|
42767
|
+
var sortPercentileCycleClipsForDisplay = (categoryId, clips) => {
|
|
42768
|
+
if (categoryId !== "fast-cycles" && categoryId !== "slow-cycles") {
|
|
42769
|
+
return [...clips];
|
|
42770
|
+
}
|
|
42771
|
+
return [...clips].sort((left, right) => {
|
|
42772
|
+
const leftCycleTime = readSortableCycleTime(left);
|
|
42773
|
+
const rightCycleTime = readSortableCycleTime(right);
|
|
42774
|
+
const leftMissingCycleTime = leftCycleTime === null;
|
|
42775
|
+
const rightMissingCycleTime = rightCycleTime === null;
|
|
42776
|
+
if (leftMissingCycleTime !== rightMissingCycleTime) {
|
|
42777
|
+
return leftMissingCycleTime ? 1 : -1;
|
|
42778
|
+
}
|
|
42779
|
+
if (leftCycleTime !== null && rightCycleTime !== null && leftCycleTime !== rightCycleTime) {
|
|
42780
|
+
return categoryId === "fast-cycles" ? leftCycleTime - rightCycleTime : rightCycleTime - leftCycleTime;
|
|
42781
|
+
}
|
|
42782
|
+
return readSortableTimestamp(right) - readSortableTimestamp(left);
|
|
42783
|
+
});
|
|
42784
|
+
};
|
|
42785
|
+
var resolveInitialClipCategory = (categoryCandidates, clipTypes = [], counts = {}) => {
|
|
42786
|
+
const candidates = Array.from(
|
|
42787
|
+
new Set(
|
|
42788
|
+
categoryCandidates.filter((candidate) => Boolean(candidate)).map((candidate) => candidate.trim()).filter(Boolean)
|
|
42789
|
+
)
|
|
42790
|
+
);
|
|
42791
|
+
if (candidates.length === 0) {
|
|
42792
|
+
return null;
|
|
42793
|
+
}
|
|
42794
|
+
const availableCategories = /* @__PURE__ */ new Set();
|
|
42795
|
+
clipTypes.forEach((type) => {
|
|
42796
|
+
if (type?.type) availableCategories.add(String(type.type));
|
|
42797
|
+
if (type?.id) availableCategories.add(String(type.id));
|
|
42798
|
+
});
|
|
42799
|
+
return candidates.find((candidate) => (counts[candidate] || 0) > 0) || candidates.find((candidate) => availableCategories.has(candidate)) || null;
|
|
42800
|
+
};
|
|
42363
42801
|
var getCategoryMetadataLoadPlanForFilterChange = ({
|
|
42364
42802
|
activeFilter,
|
|
42365
42803
|
currentClipId,
|
|
@@ -42371,6 +42809,12 @@ var getCategoryMetadataLoadPlanForFilterChange = ({
|
|
|
42371
42809
|
if (activeFilter === "recent_flow_red_streak" && categoryTotal > 0) {
|
|
42372
42810
|
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
42373
42811
|
}
|
|
42812
|
+
if (activeFilter === "fast-cycles" || activeFilter === "slow-cycles") {
|
|
42813
|
+
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
42814
|
+
}
|
|
42815
|
+
if (categoryTotal > 0 && activeFilter === "cycle_completion") {
|
|
42816
|
+
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
42817
|
+
}
|
|
42374
42818
|
return {
|
|
42375
42819
|
shouldLoad: Boolean(currentClipId),
|
|
42376
42820
|
autoLoadFirstVideo: false
|
|
@@ -46208,6 +46652,36 @@ var CLIP_METADATA_PAGE_SIZE = 50;
|
|
|
46208
46652
|
var RECENT_FLOW_RED_STREAK_CLIP_TYPE2 = "recent_flow_red_streak";
|
|
46209
46653
|
var RECENT_FLOW_RED_STREAK_DISPLAY_LABEL = "Low moments";
|
|
46210
46654
|
var RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE = "Moments of low efficiency";
|
|
46655
|
+
var REQUIRED_HOURLY_HANDOFF_CATEGORIES = {
|
|
46656
|
+
cycle_completion: {
|
|
46657
|
+
id: "cycle_completion",
|
|
46658
|
+
label: "Cycle Completion",
|
|
46659
|
+
description: "Successfully completed production cycles",
|
|
46660
|
+
color: "green",
|
|
46661
|
+
icon: "check-circle"
|
|
46662
|
+
},
|
|
46663
|
+
idle_time: {
|
|
46664
|
+
id: "idle_time",
|
|
46665
|
+
label: "Idle Time",
|
|
46666
|
+
description: "Idle periods",
|
|
46667
|
+
color: "purple",
|
|
46668
|
+
icon: "clock"
|
|
46669
|
+
},
|
|
46670
|
+
[RECENT_FLOW_RED_STREAK_CLIP_TYPE2]: {
|
|
46671
|
+
id: RECENT_FLOW_RED_STREAK_CLIP_TYPE2,
|
|
46672
|
+
label: RECENT_FLOW_RED_STREAK_DISPLAY_LABEL,
|
|
46673
|
+
description: RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE,
|
|
46674
|
+
color: "red",
|
|
46675
|
+
icon: "alert-triangle"
|
|
46676
|
+
}
|
|
46677
|
+
};
|
|
46678
|
+
var REQUIRED_HOURLY_FILTER_CATEGORY_IDS = [
|
|
46679
|
+
RECENT_FLOW_RED_STREAK_CLIP_TYPE2,
|
|
46680
|
+
"cycle_completion",
|
|
46681
|
+
"fast-cycles",
|
|
46682
|
+
"slow-cycles",
|
|
46683
|
+
"idle_time"
|
|
46684
|
+
];
|
|
46211
46685
|
var parseCycleTime = (value) => {
|
|
46212
46686
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
46213
46687
|
return value;
|
|
@@ -46236,6 +46710,21 @@ var formatDurationLabel = (seconds) => {
|
|
|
46236
46710
|
}
|
|
46237
46711
|
return `${Math.round(roundedSeconds / 60)} min`;
|
|
46238
46712
|
};
|
|
46713
|
+
var timeValueToMinutes = (value) => {
|
|
46714
|
+
const [hourValue, minuteValue] = value.substring(0, 5).split(":").map(Number);
|
|
46715
|
+
if (!Number.isInteger(hourValue) || !Number.isInteger(minuteValue) || hourValue < 0 || hourValue > 23 || minuteValue < 0 || minuteValue > 59) {
|
|
46716
|
+
return null;
|
|
46717
|
+
}
|
|
46718
|
+
return hourValue * 60 + minuteValue;
|
|
46719
|
+
};
|
|
46720
|
+
var isMinuteInTimeWindow = (minute, startValue, endValue) => {
|
|
46721
|
+
const startMinute = timeValueToMinutes(startValue);
|
|
46722
|
+
const endMinute = timeValueToMinutes(endValue);
|
|
46723
|
+
if (startMinute === null || endMinute === null) {
|
|
46724
|
+
return true;
|
|
46725
|
+
}
|
|
46726
|
+
return endMinute > startMinute ? minute >= startMinute && minute < endMinute : minute >= startMinute || minute < endMinute;
|
|
46727
|
+
};
|
|
46239
46728
|
var sortRedFlowMetadata = (clips) => {
|
|
46240
46729
|
return clips.slice().sort((left, right) => {
|
|
46241
46730
|
const getOutputShortfall = (clip) => {
|
|
@@ -46260,6 +46749,27 @@ var sortRedFlowMetadata = (clips) => {
|
|
|
46260
46749
|
return (Number.isFinite(rightTime) ? rightTime : 0) - (Number.isFinite(leftTime) ? leftTime : 0);
|
|
46261
46750
|
});
|
|
46262
46751
|
};
|
|
46752
|
+
var buildClipMetadataFromVideo = (video, index) => ({
|
|
46753
|
+
id: video.id,
|
|
46754
|
+
clipId: video.id,
|
|
46755
|
+
clip_timestamp: video.creation_timestamp || video.timestamp,
|
|
46756
|
+
description: video.description,
|
|
46757
|
+
severity: video.severity,
|
|
46758
|
+
category: video.type,
|
|
46759
|
+
duration: typeof video.duration === "number" ? video.duration : typeof video.cycle_time_seconds === "number" ? video.cycle_time_seconds : void 0,
|
|
46760
|
+
clip_start_time: video.clip_start_time,
|
|
46761
|
+
clip_end_time: video.clip_end_time,
|
|
46762
|
+
index,
|
|
46763
|
+
idle_start_time: video.idle_start_time,
|
|
46764
|
+
idle_end_time: video.idle_end_time,
|
|
46765
|
+
cycle_item_count: null,
|
|
46766
|
+
red_flow_timeline: video.red_flow_timeline,
|
|
46767
|
+
red_flow_severity_score: video.red_flow_severity_score,
|
|
46768
|
+
red_flow_output_shortfall_units: video.red_flow_output_shortfall_units,
|
|
46769
|
+
red_flow_worst_minute: video.red_flow_worst_minute,
|
|
46770
|
+
red_flow_explanation_summary: video.red_flow_explanation_summary,
|
|
46771
|
+
red_flow_explanation: video.red_flow_explanation
|
|
46772
|
+
});
|
|
46263
46773
|
var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
|
|
46264
46774
|
if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
|
|
46265
46775
|
return null;
|
|
@@ -46338,6 +46848,8 @@ var FileManagerFilters = ({
|
|
|
46338
46848
|
idleTimeVlmEnabled = false,
|
|
46339
46849
|
showPercentileCycleFilters = true,
|
|
46340
46850
|
prefetchedClipMetadata,
|
|
46851
|
+
prefetchedClipTotals,
|
|
46852
|
+
prefetchedPercentileClips,
|
|
46341
46853
|
externallyManagedLoadingCategories,
|
|
46342
46854
|
activeCategoryLoading,
|
|
46343
46855
|
idleClipSort = "latest",
|
|
@@ -46345,6 +46857,7 @@ var FileManagerFilters = ({
|
|
|
46345
46857
|
initialTimeFilter
|
|
46346
46858
|
}) => {
|
|
46347
46859
|
const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
|
|
46860
|
+
const [activeInitialTimeFilter, setActiveInitialTimeFilter] = useState(initialTimeFilter ?? null);
|
|
46348
46861
|
const [startTime, setStartTime] = useState(initialTimeFilter?.startTime ?? "");
|
|
46349
46862
|
const [endTime, setEndTime] = useState(initialTimeFilter?.endTime ?? "");
|
|
46350
46863
|
const [isTimeFilterActive, setIsTimeFilterActive] = useState(
|
|
@@ -46359,14 +46872,93 @@ var FileManagerFilters = ({
|
|
|
46359
46872
|
const [showIdleLabelFilterModal, setShowIdleLabelFilterModal] = useState(false);
|
|
46360
46873
|
const [isLoadingIdleReasonOptions, setIsLoadingIdleReasonOptions] = useState(false);
|
|
46361
46874
|
const timezone = useAppTimezone();
|
|
46875
|
+
const activeTimeFilterTimezone = activeInitialTimeFilter?.timezone || initialTimeFilter?.timezone || timezone;
|
|
46876
|
+
const activeTimeFilterKey = useMemo(() => startTime && endTime && isTimeFilterActive ? `${startTime}-${endTime}-${activeTimeFilterTimezone}` : "none", [activeTimeFilterTimezone, endTime, isTimeFilterActive, startTime]);
|
|
46877
|
+
const initialTimeFilterCategoryIds = useMemo(() => {
|
|
46878
|
+
if (!activeInitialTimeFilter) {
|
|
46879
|
+
return [];
|
|
46880
|
+
}
|
|
46881
|
+
return Array.from(new Set([
|
|
46882
|
+
activeInitialTimeFilter.categoryId,
|
|
46883
|
+
...activeInitialTimeFilter.categoryIds || []
|
|
46884
|
+
].filter((value) => typeof value === "string" && value.length > 0)));
|
|
46885
|
+
}, [activeInitialTimeFilter]);
|
|
46886
|
+
const requiredHourlyFilterCategoryIds = useMemo(() => {
|
|
46887
|
+
if (initialTimeFilterCategoryIds.length > 0) {
|
|
46888
|
+
return initialTimeFilterCategoryIds;
|
|
46889
|
+
}
|
|
46890
|
+
if (!isTimeFilterActive || !startTime || !endTime) {
|
|
46891
|
+
return [];
|
|
46892
|
+
}
|
|
46893
|
+
return REQUIRED_HOURLY_FILTER_CATEGORY_IDS;
|
|
46894
|
+
}, [endTime, initialTimeFilterCategoryIds, isTimeFilterActive, startTime]);
|
|
46895
|
+
const categoriesForTree = useMemo(() => {
|
|
46896
|
+
if (requiredHourlyFilterCategoryIds.length === 0) {
|
|
46897
|
+
return categories;
|
|
46898
|
+
}
|
|
46899
|
+
const existingCategoryIds = new Set(categories.map((category) => category.id));
|
|
46900
|
+
const mergedCategories = [...categories];
|
|
46901
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
46902
|
+
const fallbackCategory = REQUIRED_HOURLY_HANDOFF_CATEGORIES[categoryId];
|
|
46903
|
+
if (!fallbackCategory || existingCategoryIds.has(categoryId)) {
|
|
46904
|
+
return;
|
|
46905
|
+
}
|
|
46906
|
+
mergedCategories.push(fallbackCategory);
|
|
46907
|
+
existingCategoryIds.add(categoryId);
|
|
46908
|
+
});
|
|
46909
|
+
return mergedCategories;
|
|
46910
|
+
}, [categories, requiredHourlyFilterCategoryIds]);
|
|
46362
46911
|
const supabase = useSupabase();
|
|
46363
46912
|
const [clipMetadata, setClipMetadata] = useState({});
|
|
46913
|
+
const [scopedCategoryTotals, setScopedCategoryTotals] = useState({});
|
|
46364
46914
|
const [loadingCategories, setLoadingCategories] = useState(/* @__PURE__ */ new Set());
|
|
46915
|
+
const isCategoryScopedByTimeFilter = useCallback((categoryId) => {
|
|
46916
|
+
if (!startTime || !endTime || !isTimeFilterActive) {
|
|
46917
|
+
return false;
|
|
46918
|
+
}
|
|
46919
|
+
if (!activeInitialTimeFilter) {
|
|
46920
|
+
return true;
|
|
46921
|
+
}
|
|
46922
|
+
if (activeFilter === categoryId || activeInitialTimeFilter.categoryId === categoryId) {
|
|
46923
|
+
return true;
|
|
46924
|
+
}
|
|
46925
|
+
return Boolean(activeInitialTimeFilter.categoryIds?.includes(categoryId));
|
|
46926
|
+
}, [
|
|
46927
|
+
activeFilter,
|
|
46928
|
+
activeInitialTimeFilter,
|
|
46929
|
+
endTime,
|
|
46930
|
+
isTimeFilterActive,
|
|
46931
|
+
startTime
|
|
46932
|
+
]);
|
|
46933
|
+
const isRequiredHourlyFilterCategory = useCallback((categoryId) => requiredHourlyFilterCategoryIds.includes(categoryId), [requiredHourlyFilterCategoryIds]);
|
|
46934
|
+
const manualHourlySnapshotKey = useMemo(() => {
|
|
46935
|
+
if (activeInitialTimeFilter || !isTimeFilterActive || !startTime || !endTime || !workspaceId || !date || shift === void 0) {
|
|
46936
|
+
return null;
|
|
46937
|
+
}
|
|
46938
|
+
return `${workspaceId}:${date}:${shift}:${startTime}:${endTime}:${activeTimeFilterTimezone}`;
|
|
46939
|
+
}, [
|
|
46940
|
+
activeInitialTimeFilter,
|
|
46941
|
+
activeTimeFilterTimezone,
|
|
46942
|
+
date,
|
|
46943
|
+
endTime,
|
|
46944
|
+
isTimeFilterActive,
|
|
46945
|
+
shift,
|
|
46946
|
+
startTime,
|
|
46947
|
+
workspaceId
|
|
46948
|
+
]);
|
|
46949
|
+
const manualHourlySnapshotAppliedKeyRef = useRef(null);
|
|
46950
|
+
const manualHourlySnapshotInFlightKeyRef = useRef(null);
|
|
46951
|
+
const [manualHourlySnapshotFailureKey, setManualHourlySnapshotFailureKey] = useState(null);
|
|
46952
|
+
const isManualHourlySnapshotPending = Boolean(
|
|
46953
|
+
manualHourlySnapshotKey && manualHourlySnapshotAppliedKeyRef.current !== manualHourlySnapshotKey && manualHourlySnapshotFailureKey !== manualHourlySnapshotKey
|
|
46954
|
+
);
|
|
46365
46955
|
const [categoryPages, setCategoryPages] = useState({});
|
|
46366
46956
|
const [categoryHasMore, setCategoryHasMore] = useState({});
|
|
46367
46957
|
const [localClipClassifications, setLocalClipClassifications] = useState({});
|
|
46368
46958
|
const clipMetadataRef = useRef({});
|
|
46369
46959
|
const inFlightMetadataRequestsRef = useRef(/* @__PURE__ */ new Set());
|
|
46960
|
+
const inFlightPercentileClipRequestsRef = useRef(/* @__PURE__ */ new Set());
|
|
46961
|
+
const autoSelectedScopedClipRef = useRef(null);
|
|
46370
46962
|
const previousIdleClipSortRef = useRef(idleClipSort);
|
|
46371
46963
|
const mergedClipClassifications = useMemo(() => ({
|
|
46372
46964
|
...clipClassifications || {},
|
|
@@ -46379,12 +46971,14 @@ var FileManagerFilters = ({
|
|
|
46379
46971
|
if (!initialTimeFilter?.startTime || !initialTimeFilter?.endTime) {
|
|
46380
46972
|
return;
|
|
46381
46973
|
}
|
|
46974
|
+
setActiveInitialTimeFilter(initialTimeFilter);
|
|
46382
46975
|
setStartTime(initialTimeFilter.startTime);
|
|
46383
46976
|
setEndTime(initialTimeFilter.endTime);
|
|
46384
46977
|
setIsTimeFilterActive(true);
|
|
46385
46978
|
setShowTimeFilterModal(false);
|
|
46386
46979
|
setStartSearchTerm("");
|
|
46387
46980
|
setEndSearchTerm("");
|
|
46981
|
+
setScopedCategoryTotals({});
|
|
46388
46982
|
}, [initialTimeFilter?.startTime, initialTimeFilter?.endTime]);
|
|
46389
46983
|
useEffect(() => {
|
|
46390
46984
|
if (previousIdleClipSortRef.current === idleClipSort) {
|
|
@@ -46416,18 +47010,66 @@ var FileManagerFilters = ({
|
|
|
46416
47010
|
return next;
|
|
46417
47011
|
});
|
|
46418
47012
|
}, [idleClipSort]);
|
|
47013
|
+
useEffect(() => {
|
|
47014
|
+
manualHourlySnapshotAppliedKeyRef.current = null;
|
|
47015
|
+
manualHourlySnapshotInFlightKeyRef.current = null;
|
|
47016
|
+
setManualHourlySnapshotFailureKey(null);
|
|
47017
|
+
setScopedCategoryTotals({});
|
|
47018
|
+
setClipMetadata({});
|
|
47019
|
+
setCategoryPages({});
|
|
47020
|
+
setCategoryHasMore({});
|
|
47021
|
+
setPercentileClips({});
|
|
47022
|
+
setPercentileCounts({
|
|
47023
|
+
"fast-cycles": null,
|
|
47024
|
+
"slow-cycles": null
|
|
47025
|
+
});
|
|
47026
|
+
}, [activeTimeFilterKey]);
|
|
46419
47027
|
const isCategoryExternallyManaged = useCallback((categoryId) => {
|
|
46420
47028
|
if (!categoryId) {
|
|
46421
47029
|
return false;
|
|
46422
47030
|
}
|
|
46423
|
-
if (
|
|
47031
|
+
if (isManualHourlySnapshotPending && requiredHourlyFilterCategoryIds.includes(categoryId)) {
|
|
47032
|
+
return true;
|
|
47033
|
+
}
|
|
47034
|
+
if (prefetchedClipMetadata && Array.isArray(prefetchedClipMetadata[categoryId]) && (prefetchedClipMetadata[categoryId].length > 0 || typeof prefetchedClipTotals?.[categoryId] === "number")) {
|
|
47035
|
+
return true;
|
|
47036
|
+
}
|
|
47037
|
+
if (prefetchedPercentileClips && Array.isArray(prefetchedPercentileClips[categoryId]) && (prefetchedPercentileClips[categoryId].length > 0 || isCategoryScopedByTimeFilter(categoryId) && typeof prefetchedClipTotals?.[categoryId] === "number")) {
|
|
46424
47038
|
return true;
|
|
46425
47039
|
}
|
|
46426
47040
|
if (externallyManagedLoadingCategories?.[categoryId]) {
|
|
46427
47041
|
return true;
|
|
46428
47042
|
}
|
|
46429
47043
|
return false;
|
|
46430
|
-
}, [
|
|
47044
|
+
}, [
|
|
47045
|
+
externallyManagedLoadingCategories,
|
|
47046
|
+
isManualHourlySnapshotPending,
|
|
47047
|
+
isCategoryScopedByTimeFilter,
|
|
47048
|
+
prefetchedClipMetadata,
|
|
47049
|
+
prefetchedClipTotals,
|
|
47050
|
+
prefetchedPercentileClips,
|
|
47051
|
+
requiredHourlyFilterCategoryIds
|
|
47052
|
+
]);
|
|
47053
|
+
const getAvailableClipMetadata = useCallback((categoryId) => {
|
|
47054
|
+
const localClips = clipMetadata[categoryId];
|
|
47055
|
+
if (Array.isArray(localClips) && localClips.length > 0) {
|
|
47056
|
+
return localClips;
|
|
47057
|
+
}
|
|
47058
|
+
const prefetchedClips = prefetchedClipMetadata?.[categoryId];
|
|
47059
|
+
if (Array.isArray(prefetchedClips) && prefetchedClips.length > 0) {
|
|
47060
|
+
return prefetchedClips;
|
|
47061
|
+
}
|
|
47062
|
+
return [];
|
|
47063
|
+
}, [clipMetadata, prefetchedClipMetadata]);
|
|
47064
|
+
const hasKnownClipMetadata = useCallback((categoryId) => {
|
|
47065
|
+
if (Array.isArray(clipMetadata[categoryId])) {
|
|
47066
|
+
return true;
|
|
47067
|
+
}
|
|
47068
|
+
if (Array.isArray(prefetchedClipMetadata?.[categoryId])) {
|
|
47069
|
+
return true;
|
|
47070
|
+
}
|
|
47071
|
+
return typeof prefetchedClipTotals?.[categoryId] === "number";
|
|
47072
|
+
}, [clipMetadata, prefetchedClipMetadata, prefetchedClipTotals]);
|
|
46431
47073
|
useEffect(() => {
|
|
46432
47074
|
if (!prefetchedClipMetadata) {
|
|
46433
47075
|
return;
|
|
@@ -46450,6 +47092,22 @@ var FileManagerFilters = ({
|
|
|
46450
47092
|
});
|
|
46451
47093
|
return changed ? next : prev;
|
|
46452
47094
|
});
|
|
47095
|
+
setScopedCategoryTotals((prev) => {
|
|
47096
|
+
let changed = false;
|
|
47097
|
+
const next = { ...prev };
|
|
47098
|
+
Object.entries(prefetchedClipMetadata).forEach(([categoryId, clips]) => {
|
|
47099
|
+
if (!Array.isArray(clips) || !isCategoryScopedByTimeFilter(categoryId)) {
|
|
47100
|
+
return;
|
|
47101
|
+
}
|
|
47102
|
+
const nextTotal = typeof prefetchedClipTotals?.[categoryId] === "number" ? Math.max(0, prefetchedClipTotals[categoryId]) : clips.length;
|
|
47103
|
+
if (next[categoryId] === nextTotal) {
|
|
47104
|
+
return;
|
|
47105
|
+
}
|
|
47106
|
+
next[categoryId] = nextTotal;
|
|
47107
|
+
changed = true;
|
|
47108
|
+
});
|
|
47109
|
+
return changed ? next : prev;
|
|
47110
|
+
});
|
|
46453
47111
|
setCategoryPages((prev) => {
|
|
46454
47112
|
let changed = false;
|
|
46455
47113
|
const next = { ...prev };
|
|
@@ -46474,7 +47132,7 @@ var FileManagerFilters = ({
|
|
|
46474
47132
|
return;
|
|
46475
47133
|
}
|
|
46476
47134
|
const knownTotal = typeof counts?.[categoryId] === "number" ? counts[categoryId] : null;
|
|
46477
|
-
const inferredHasMore = knownTotal !== null ? clips.length < knownTotal : prev[categoryId];
|
|
47135
|
+
const inferredHasMore = isCategoryScopedByTimeFilter(categoryId) ? false : knownTotal !== null ? clips.length < knownTotal : prev[categoryId];
|
|
46478
47136
|
if (typeof inferredHasMore !== "boolean" || next[categoryId] === inferredHasMore) {
|
|
46479
47137
|
return;
|
|
46480
47138
|
}
|
|
@@ -46483,8 +47141,68 @@ var FileManagerFilters = ({
|
|
|
46483
47141
|
});
|
|
46484
47142
|
return changed ? next : prev;
|
|
46485
47143
|
});
|
|
46486
|
-
}, [prefetchedClipMetadata, counts]);
|
|
47144
|
+
}, [prefetchedClipMetadata, prefetchedClipTotals, counts, isCategoryScopedByTimeFilter]);
|
|
47145
|
+
useEffect(() => {
|
|
47146
|
+
if (!prefetchedPercentileClips) {
|
|
47147
|
+
return;
|
|
47148
|
+
}
|
|
47149
|
+
setPercentileClips((prev) => {
|
|
47150
|
+
let changed = false;
|
|
47151
|
+
const next = { ...prev };
|
|
47152
|
+
["fast-cycles", "slow-cycles"].forEach((categoryId) => {
|
|
47153
|
+
const clips = prefetchedPercentileClips[categoryId];
|
|
47154
|
+
if (!Array.isArray(clips)) {
|
|
47155
|
+
return;
|
|
47156
|
+
}
|
|
47157
|
+
const previousClips = prev[categoryId] || [];
|
|
47158
|
+
const previousSignature = previousClips.map((clip) => clip.id).join("|");
|
|
47159
|
+
const nextSignature = clips.map((clip) => clip.id).join("|");
|
|
47160
|
+
if (previousSignature === nextSignature) {
|
|
47161
|
+
return;
|
|
47162
|
+
}
|
|
47163
|
+
next[categoryId] = clips;
|
|
47164
|
+
changed = true;
|
|
47165
|
+
});
|
|
47166
|
+
return changed ? next : prev;
|
|
47167
|
+
});
|
|
47168
|
+
setPercentileCounts((prev) => {
|
|
47169
|
+
let changed = false;
|
|
47170
|
+
const next = { ...prev };
|
|
47171
|
+
["fast-cycles", "slow-cycles"].forEach((categoryId) => {
|
|
47172
|
+
const clips = prefetchedPercentileClips[categoryId];
|
|
47173
|
+
if (!Array.isArray(clips)) {
|
|
47174
|
+
return;
|
|
47175
|
+
}
|
|
47176
|
+
const nextTotal = typeof prefetchedClipTotals?.[categoryId] === "number" ? Math.max(0, prefetchedClipTotals[categoryId]) : clips.length;
|
|
47177
|
+
if (next[categoryId] === nextTotal) {
|
|
47178
|
+
return;
|
|
47179
|
+
}
|
|
47180
|
+
next[categoryId] = nextTotal;
|
|
47181
|
+
changed = true;
|
|
47182
|
+
});
|
|
47183
|
+
return changed ? next : prev;
|
|
47184
|
+
});
|
|
47185
|
+
}, [prefetchedClipTotals, prefetchedPercentileClips]);
|
|
46487
47186
|
const { state: filterState } = useClipFilter();
|
|
47187
|
+
const shouldShowCategory = useCallback((categoryId) => {
|
|
47188
|
+
switch (categoryId) {
|
|
47189
|
+
case "fast-cycles":
|
|
47190
|
+
return showPercentileCycleFilters && filterState.showFastCycles;
|
|
47191
|
+
case "slow-cycles":
|
|
47192
|
+
return showPercentileCycleFilters && filterState.showSlowCycles;
|
|
47193
|
+
case "longest-idles":
|
|
47194
|
+
return false;
|
|
47195
|
+
// filterState.showLongestIdles; // Temporarily disabled
|
|
47196
|
+
case "cycle_completion":
|
|
47197
|
+
return filterState.showCycleCompletion;
|
|
47198
|
+
case "idle_time":
|
|
47199
|
+
return filterState.showIdleTime;
|
|
47200
|
+
case "sop_deviations":
|
|
47201
|
+
return filterState.showSopDeviations;
|
|
47202
|
+
default:
|
|
47203
|
+
return true;
|
|
47204
|
+
}
|
|
47205
|
+
}, [filterState, showPercentileCycleFilters]);
|
|
46488
47206
|
const [percentileCounts, setPercentileCounts] = useState({
|
|
46489
47207
|
"fast-cycles": null,
|
|
46490
47208
|
"slow-cycles": null
|
|
@@ -46594,11 +47312,12 @@ var FileManagerFilters = ({
|
|
|
46594
47312
|
return null;
|
|
46595
47313
|
}
|
|
46596
47314
|
}, [supabase]);
|
|
46597
|
-
const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
|
|
47315
|
+
const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"}-${activeTimeFilterKey}`, [activeTimeFilterKey, idleClipSort]);
|
|
46598
47316
|
const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
|
|
46599
47317
|
if (!workspaceId || !date || shift === void 0) {
|
|
46600
47318
|
throw new Error("Missing required params for clip metadata fetch");
|
|
46601
47319
|
}
|
|
47320
|
+
const shouldScopeToTimeFilter = isCategoryScopedByTimeFilter(categoryId);
|
|
46602
47321
|
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
46603
47322
|
method: "POST",
|
|
46604
47323
|
headers: {
|
|
@@ -46612,9 +47331,12 @@ var FileManagerFilters = ({
|
|
|
46612
47331
|
category: categoryId,
|
|
46613
47332
|
page,
|
|
46614
47333
|
limit: CLIP_METADATA_PAGE_SIZE,
|
|
46615
|
-
knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
|
|
47334
|
+
knownTotal: shouldScopeToTimeFilter ? null : typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
|
|
46616
47335
|
snapshotDateTime,
|
|
46617
47336
|
snapshotClipId,
|
|
47337
|
+
startTime: shouldScopeToTimeFilter ? startTime : void 0,
|
|
47338
|
+
endTime: shouldScopeToTimeFilter ? endTime : void 0,
|
|
47339
|
+
timeFilterTimezone: shouldScopeToTimeFilter ? activeTimeFilterTimezone : void 0,
|
|
46618
47340
|
sort: categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
|
|
46619
47341
|
}),
|
|
46620
47342
|
redirectReason: "session_expired"
|
|
@@ -46623,7 +47345,20 @@ var FileManagerFilters = ({
|
|
|
46623
47345
|
throw new Error(`API error: ${response.status}`);
|
|
46624
47346
|
}
|
|
46625
47347
|
return response.json();
|
|
46626
|
-
}, [
|
|
47348
|
+
}, [
|
|
47349
|
+
activeTimeFilterTimezone,
|
|
47350
|
+
endTime,
|
|
47351
|
+
isCategoryScopedByTimeFilter,
|
|
47352
|
+
startTime,
|
|
47353
|
+
workspaceId,
|
|
47354
|
+
date,
|
|
47355
|
+
shift,
|
|
47356
|
+
counts,
|
|
47357
|
+
snapshotDateTime,
|
|
47358
|
+
snapshotClipId,
|
|
47359
|
+
idleClipSort,
|
|
47360
|
+
supabase
|
|
47361
|
+
]);
|
|
46627
47362
|
const seedIdleClassifications = useCallback(async (clips) => {
|
|
46628
47363
|
if (!idleTimeVlmEnabled || clips.length === 0) {
|
|
46629
47364
|
return;
|
|
@@ -46691,6 +47426,12 @@ var FileManagerFilters = ({
|
|
|
46691
47426
|
...prev,
|
|
46692
47427
|
[categoryId]: page === 1 ? data.clips : [...prev[categoryId] || [], ...data.clips]
|
|
46693
47428
|
}));
|
|
47429
|
+
if (isCategoryScopedByTimeFilter(categoryId)) {
|
|
47430
|
+
setScopedCategoryTotals((prev) => ({
|
|
47431
|
+
...prev,
|
|
47432
|
+
[categoryId]: Math.max(0, Number(data.total || 0))
|
|
47433
|
+
}));
|
|
47434
|
+
}
|
|
46694
47435
|
if (categoryId === "idle_time" && idleTimeVlmEnabled) {
|
|
46695
47436
|
await seedIdleClassifications(data.clips || []);
|
|
46696
47437
|
}
|
|
@@ -46707,7 +47448,94 @@ var FileManagerFilters = ({
|
|
|
46707
47448
|
return newSet;
|
|
46708
47449
|
});
|
|
46709
47450
|
}
|
|
46710
|
-
}, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey]);
|
|
47451
|
+
}, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey, isCategoryScopedByTimeFilter]);
|
|
47452
|
+
useCallback(async (categoryId) => {
|
|
47453
|
+
if (!workspaceId || !date || shift === void 0) {
|
|
47454
|
+
console.warn("[FileManager] Missing required params for full clip metadata fetch");
|
|
47455
|
+
return;
|
|
47456
|
+
}
|
|
47457
|
+
const loadingKey = `${getMetadataLoadingKey(categoryId, 1)}-all`;
|
|
47458
|
+
if (inFlightMetadataRequestsRef.current.has(loadingKey)) {
|
|
47459
|
+
return;
|
|
47460
|
+
}
|
|
47461
|
+
inFlightMetadataRequestsRef.current.add(loadingKey);
|
|
47462
|
+
setLoadingCategories((prev) => /* @__PURE__ */ new Set([...prev, loadingKey]));
|
|
47463
|
+
try {
|
|
47464
|
+
let accumulatedClips = [];
|
|
47465
|
+
let currentPage = 0;
|
|
47466
|
+
let hasMore = true;
|
|
47467
|
+
while (hasMore) {
|
|
47468
|
+
const nextPage = currentPage + 1;
|
|
47469
|
+
const pageData = await fetchClipMetadataPage(categoryId, nextPage);
|
|
47470
|
+
const pageClips = pageData.clips || [];
|
|
47471
|
+
accumulatedClips = [...accumulatedClips, ...pageClips];
|
|
47472
|
+
currentPage = nextPage;
|
|
47473
|
+
hasMore = Boolean(pageData.hasMore && pageClips.length > 0);
|
|
47474
|
+
}
|
|
47475
|
+
const dedupedClips = accumulatedClips.filter((clip, index, arr) => {
|
|
47476
|
+
const clipKey = clip.clipId || clip.id;
|
|
47477
|
+
return arr.findIndex((item) => (item.clipId || item.id) === clipKey) === index;
|
|
47478
|
+
});
|
|
47479
|
+
setClipMetadata((prev) => ({
|
|
47480
|
+
...prev,
|
|
47481
|
+
[categoryId]: dedupedClips
|
|
47482
|
+
}));
|
|
47483
|
+
setCategoryPages((prev) => ({ ...prev, [categoryId]: Math.max(currentPage, 1) }));
|
|
47484
|
+
setCategoryHasMore((prev) => ({ ...prev, [categoryId]: false }));
|
|
47485
|
+
if (categoryId === "idle_time" && idleTimeVlmEnabled) {
|
|
47486
|
+
await seedIdleClassifications(dedupedClips);
|
|
47487
|
+
}
|
|
47488
|
+
console.log(`[FileManager] Loaded all ${dedupedClips.length} clips for ${categoryId} due to chart time filter`);
|
|
47489
|
+
} catch (error) {
|
|
47490
|
+
console.error("[FileManager] Error fetching full clip metadata:", error);
|
|
47491
|
+
} finally {
|
|
47492
|
+
inFlightMetadataRequestsRef.current.delete(loadingKey);
|
|
47493
|
+
setLoadingCategories((prev) => {
|
|
47494
|
+
const newSet = new Set(prev);
|
|
47495
|
+
newSet.delete(loadingKey);
|
|
47496
|
+
return newSet;
|
|
47497
|
+
});
|
|
47498
|
+
}
|
|
47499
|
+
}, [
|
|
47500
|
+
workspaceId,
|
|
47501
|
+
date,
|
|
47502
|
+
shift,
|
|
47503
|
+
fetchClipMetadataPage,
|
|
47504
|
+
idleTimeVlmEnabled,
|
|
47505
|
+
seedIdleClassifications,
|
|
47506
|
+
getMetadataLoadingKey
|
|
47507
|
+
]);
|
|
47508
|
+
const isInitialTimeFilterCategory = useCallback((categoryId) => {
|
|
47509
|
+
if (!startTime || !endTime || !activeInitialTimeFilter) {
|
|
47510
|
+
return false;
|
|
47511
|
+
}
|
|
47512
|
+
if (activeFilter === categoryId) {
|
|
47513
|
+
return true;
|
|
47514
|
+
}
|
|
47515
|
+
if (activeInitialTimeFilter.categoryId === categoryId) {
|
|
47516
|
+
return true;
|
|
47517
|
+
}
|
|
47518
|
+
return Array.isArray(activeInitialTimeFilter.categoryIds) && activeInitialTimeFilter.categoryIds.includes(categoryId);
|
|
47519
|
+
}, [
|
|
47520
|
+
activeFilter,
|
|
47521
|
+
activeInitialTimeFilter,
|
|
47522
|
+
endTime,
|
|
47523
|
+
startTime
|
|
47524
|
+
]);
|
|
47525
|
+
const hasCompleteMetadataForInitialTimeFilter = useCallback((categoryId) => {
|
|
47526
|
+
if (!isInitialTimeFilterCategory(categoryId)) {
|
|
47527
|
+
return true;
|
|
47528
|
+
}
|
|
47529
|
+
const loadedClips = clipMetadataRef.current[categoryId] || [];
|
|
47530
|
+
const knownTotal = typeof scopedCategoryTotals[categoryId] === "number" ? scopedCategoryTotals[categoryId] : null;
|
|
47531
|
+
if (categoryHasMore[categoryId]) {
|
|
47532
|
+
return false;
|
|
47533
|
+
}
|
|
47534
|
+
if (knownTotal !== null && loadedClips.length < knownTotal) {
|
|
47535
|
+
return false;
|
|
47536
|
+
}
|
|
47537
|
+
return loadedClips.length > 0 || knownTotal === 0;
|
|
47538
|
+
}, [categoryHasMore, isInitialTimeFilterCategory, scopedCategoryTotals]);
|
|
46711
47539
|
const ensureAllIdleTimeClipMetadataLoaded = useCallback(async () => {
|
|
46712
47540
|
if (!workspaceId || !date || shift === void 0) {
|
|
46713
47541
|
return;
|
|
@@ -46773,6 +47601,12 @@ var FileManagerFilters = ({
|
|
|
46773
47601
|
console.warn("[FileManager] Missing required params for percentile clips fetch");
|
|
46774
47602
|
return;
|
|
46775
47603
|
}
|
|
47604
|
+
const shouldScopeToTimeFilter = isCategoryScopedByTimeFilter(type);
|
|
47605
|
+
const requestKey = `${type}:${date}:${shift}:${filterState.percentile}:${shouldScopeToTimeFilter ? activeTimeFilterKey : "unscoped"}`;
|
|
47606
|
+
if (inFlightPercentileClipRequestsRef.current.has(requestKey)) {
|
|
47607
|
+
return;
|
|
47608
|
+
}
|
|
47609
|
+
inFlightPercentileClipRequestsRef.current.add(requestKey);
|
|
46776
47610
|
try {
|
|
46777
47611
|
const startDate = `${date}T00:00:00Z`;
|
|
46778
47612
|
const endDate = `${date}T23:59:59Z`;
|
|
@@ -46788,7 +47622,10 @@ var FileManagerFilters = ({
|
|
|
46788
47622
|
endDate,
|
|
46789
47623
|
percentile: filterState.percentile,
|
|
46790
47624
|
shiftId: shift,
|
|
46791
|
-
limit:
|
|
47625
|
+
limit: shouldScopeToTimeFilter ? 500 : 100,
|
|
47626
|
+
startTime: shouldScopeToTimeFilter ? startTime : void 0,
|
|
47627
|
+
endTime: shouldScopeToTimeFilter ? endTime : void 0,
|
|
47628
|
+
timeFilterTimezone: shouldScopeToTimeFilter ? activeTimeFilterTimezone : void 0,
|
|
46792
47629
|
// The actual percentile action (fast-cycles, slow-cycles, idle-times)
|
|
46793
47630
|
percentileAction: type
|
|
46794
47631
|
}),
|
|
@@ -46803,7 +47640,7 @@ var FileManagerFilters = ({
|
|
|
46803
47640
|
[type]: data.clips || []
|
|
46804
47641
|
}));
|
|
46805
47642
|
setPercentileCounts((prev) => {
|
|
46806
|
-
if (typeof prev[type] === "number") {
|
|
47643
|
+
if (!shouldScopeToTimeFilter && typeof prev[type] === "number") {
|
|
46807
47644
|
return prev;
|
|
46808
47645
|
}
|
|
46809
47646
|
return {
|
|
@@ -46814,8 +47651,206 @@ var FileManagerFilters = ({
|
|
|
46814
47651
|
console.log(`[FileManager] Loaded ${data.clips?.length || 0} ${type} clips (percentile: ${filterState.percentile}%)`);
|
|
46815
47652
|
} catch (error) {
|
|
46816
47653
|
console.error(`[FileManager] Error fetching ${type} clips:`, error);
|
|
47654
|
+
} finally {
|
|
47655
|
+
inFlightPercentileClipRequestsRef.current.delete(requestKey);
|
|
47656
|
+
}
|
|
47657
|
+
}, [
|
|
47658
|
+
activeTimeFilterTimezone,
|
|
47659
|
+
activeTimeFilterKey,
|
|
47660
|
+
endTime,
|
|
47661
|
+
isCategoryScopedByTimeFilter,
|
|
47662
|
+
startTime,
|
|
47663
|
+
workspaceId,
|
|
47664
|
+
date,
|
|
47665
|
+
shift,
|
|
47666
|
+
filterState.percentile,
|
|
47667
|
+
showPercentileCycleFilters,
|
|
47668
|
+
supabase
|
|
47669
|
+
]);
|
|
47670
|
+
useEffect(() => {
|
|
47671
|
+
if (!manualHourlySnapshotKey) {
|
|
47672
|
+
return;
|
|
47673
|
+
}
|
|
47674
|
+
if (manualHourlySnapshotAppliedKeyRef.current === manualHourlySnapshotKey) {
|
|
47675
|
+
return;
|
|
47676
|
+
}
|
|
47677
|
+
if (manualHourlySnapshotInFlightKeyRef.current === manualHourlySnapshotKey) {
|
|
47678
|
+
return;
|
|
47679
|
+
}
|
|
47680
|
+
manualHourlySnapshotInFlightKeyRef.current = manualHourlySnapshotKey;
|
|
47681
|
+
setManualHourlySnapshotFailureKey((prev) => prev === manualHourlySnapshotKey ? null : prev);
|
|
47682
|
+
const applyHourlySnapshot = async () => {
|
|
47683
|
+
try {
|
|
47684
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
47685
|
+
method: "POST",
|
|
47686
|
+
headers: {
|
|
47687
|
+
"Content-Type": "application/json"
|
|
47688
|
+
},
|
|
47689
|
+
body: JSON.stringify({
|
|
47690
|
+
action: "hourly-snapshot",
|
|
47691
|
+
workspaceId,
|
|
47692
|
+
date,
|
|
47693
|
+
shift,
|
|
47694
|
+
startTime,
|
|
47695
|
+
endTime,
|
|
47696
|
+
timeFilterTimezone: activeTimeFilterTimezone
|
|
47697
|
+
}),
|
|
47698
|
+
redirectReason: "session_expired"
|
|
47699
|
+
});
|
|
47700
|
+
if (!response.ok) {
|
|
47701
|
+
throw new Error(`API error: ${response.status}`);
|
|
47702
|
+
}
|
|
47703
|
+
const snapshot = await response.json();
|
|
47704
|
+
const metadataByCategory = snapshot?.metadataByCategory && typeof snapshot.metadataByCategory === "object" ? snapshot.metadataByCategory : {};
|
|
47705
|
+
const percentileClipsByCategory = snapshot?.percentileClipsByCategory && typeof snapshot.percentileClipsByCategory === "object" ? snapshot.percentileClipsByCategory : {};
|
|
47706
|
+
const rawTotalsByCategory = snapshot?.totalsByCategory && typeof snapshot.totalsByCategory === "object" ? snapshot.totalsByCategory : {};
|
|
47707
|
+
const totalsByCategory = requiredHourlyFilterCategoryIds.reduce((accumulator, categoryId) => {
|
|
47708
|
+
const rawTotal = rawTotalsByCategory[categoryId];
|
|
47709
|
+
if (typeof rawTotal === "number" && Number.isFinite(rawTotal)) {
|
|
47710
|
+
accumulator[categoryId] = Math.max(0, rawTotal);
|
|
47711
|
+
return accumulator;
|
|
47712
|
+
}
|
|
47713
|
+
if (categoryId === "fast-cycles" || categoryId === "slow-cycles") {
|
|
47714
|
+
accumulator[categoryId] = Array.isArray(percentileClipsByCategory[categoryId]) ? percentileClipsByCategory[categoryId].length : 0;
|
|
47715
|
+
return accumulator;
|
|
47716
|
+
}
|
|
47717
|
+
accumulator[categoryId] = Array.isArray(metadataByCategory[categoryId]) ? metadataByCategory[categoryId].length : 0;
|
|
47718
|
+
return accumulator;
|
|
47719
|
+
}, {});
|
|
47720
|
+
setClipMetadata((prev) => {
|
|
47721
|
+
const next = { ...prev };
|
|
47722
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
47723
|
+
if (categoryId === "fast-cycles" || categoryId === "slow-cycles") {
|
|
47724
|
+
return;
|
|
47725
|
+
}
|
|
47726
|
+
next[categoryId] = Array.isArray(metadataByCategory[categoryId]) ? metadataByCategory[categoryId] : [];
|
|
47727
|
+
});
|
|
47728
|
+
return next;
|
|
47729
|
+
});
|
|
47730
|
+
setScopedCategoryTotals((prev) => ({
|
|
47731
|
+
...prev,
|
|
47732
|
+
...totalsByCategory
|
|
47733
|
+
}));
|
|
47734
|
+
if (showPercentileCycleFilters) {
|
|
47735
|
+
setPercentileClips((prev) => ({
|
|
47736
|
+
...prev,
|
|
47737
|
+
"fast-cycles": Array.isArray(percentileClipsByCategory["fast-cycles"]) ? percentileClipsByCategory["fast-cycles"] : [],
|
|
47738
|
+
"slow-cycles": Array.isArray(percentileClipsByCategory["slow-cycles"]) ? percentileClipsByCategory["slow-cycles"] : []
|
|
47739
|
+
}));
|
|
47740
|
+
setPercentileCounts((prev) => ({
|
|
47741
|
+
...prev,
|
|
47742
|
+
"fast-cycles": totalsByCategory["fast-cycles"] ?? 0,
|
|
47743
|
+
"slow-cycles": totalsByCategory["slow-cycles"] ?? 0
|
|
47744
|
+
}));
|
|
47745
|
+
}
|
|
47746
|
+
setCategoryPages((prev) => {
|
|
47747
|
+
const next = { ...prev };
|
|
47748
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
47749
|
+
next[categoryId] = 1;
|
|
47750
|
+
});
|
|
47751
|
+
return next;
|
|
47752
|
+
});
|
|
47753
|
+
setCategoryHasMore((prev) => {
|
|
47754
|
+
const next = { ...prev };
|
|
47755
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
47756
|
+
next[categoryId] = false;
|
|
47757
|
+
});
|
|
47758
|
+
return next;
|
|
47759
|
+
});
|
|
47760
|
+
const idleClips = metadataByCategory.idle_time;
|
|
47761
|
+
if (Array.isArray(idleClips) && idleClips.length > 0) {
|
|
47762
|
+
await seedIdleClassifications(idleClips);
|
|
47763
|
+
}
|
|
47764
|
+
manualHourlySnapshotAppliedKeyRef.current = manualHourlySnapshotKey;
|
|
47765
|
+
setManualHourlySnapshotFailureKey((prev) => prev === manualHourlySnapshotKey ? null : prev);
|
|
47766
|
+
} catch (error) {
|
|
47767
|
+
console.error("[FileManager] Error fetching manual hourly snapshot:", error);
|
|
47768
|
+
setManualHourlySnapshotFailureKey(manualHourlySnapshotKey);
|
|
47769
|
+
} finally {
|
|
47770
|
+
if (manualHourlySnapshotInFlightKeyRef.current === manualHourlySnapshotKey) {
|
|
47771
|
+
manualHourlySnapshotInFlightKeyRef.current = null;
|
|
47772
|
+
}
|
|
47773
|
+
}
|
|
47774
|
+
};
|
|
47775
|
+
void applyHourlySnapshot();
|
|
47776
|
+
}, [
|
|
47777
|
+
activeTimeFilterTimezone,
|
|
47778
|
+
date,
|
|
47779
|
+
endTime,
|
|
47780
|
+
manualHourlySnapshotKey,
|
|
47781
|
+
requiredHourlyFilterCategoryIds,
|
|
47782
|
+
seedIdleClassifications,
|
|
47783
|
+
shift,
|
|
47784
|
+
showPercentileCycleFilters,
|
|
47785
|
+
startTime,
|
|
47786
|
+
supabase,
|
|
47787
|
+
workspaceId
|
|
47788
|
+
]);
|
|
47789
|
+
useEffect(() => {
|
|
47790
|
+
if (!startTime || !endTime || !activeInitialTimeFilter || initialTimeFilterCategoryIds.length === 0) {
|
|
47791
|
+
return;
|
|
46817
47792
|
}
|
|
46818
|
-
|
|
47793
|
+
initialTimeFilterCategoryIds.forEach((categoryId) => {
|
|
47794
|
+
if (categoryId === "fast-cycles" || categoryId === "slow-cycles") {
|
|
47795
|
+
const hasScopedPercentileResult = typeof percentileCounts[categoryId] === "number";
|
|
47796
|
+
if (!isCategoryExternallyManaged(categoryId) && !hasScopedPercentileResult && showPercentileCycleFilters) {
|
|
47797
|
+
fetchPercentileClips(categoryId);
|
|
47798
|
+
}
|
|
47799
|
+
return;
|
|
47800
|
+
}
|
|
47801
|
+
if (isCategoryExternallyManaged(categoryId)) {
|
|
47802
|
+
return;
|
|
47803
|
+
}
|
|
47804
|
+
if (!hasCompleteMetadataForInitialTimeFilter(categoryId)) {
|
|
47805
|
+
fetchClipMetadata(categoryId, 1);
|
|
47806
|
+
}
|
|
47807
|
+
});
|
|
47808
|
+
}, [
|
|
47809
|
+
activeInitialTimeFilter,
|
|
47810
|
+
endTime,
|
|
47811
|
+
fetchClipMetadata,
|
|
47812
|
+
fetchPercentileClips,
|
|
47813
|
+
hasCompleteMetadataForInitialTimeFilter,
|
|
47814
|
+
initialTimeFilterCategoryIds,
|
|
47815
|
+
isCategoryExternallyManaged,
|
|
47816
|
+
percentileCounts,
|
|
47817
|
+
showPercentileCycleFilters,
|
|
47818
|
+
startTime
|
|
47819
|
+
]);
|
|
47820
|
+
useEffect(() => {
|
|
47821
|
+
if (!startTime || !endTime || !isTimeFilterActive || activeInitialTimeFilter) {
|
|
47822
|
+
return;
|
|
47823
|
+
}
|
|
47824
|
+
categoriesForTree.forEach((category) => {
|
|
47825
|
+
if (!shouldShowCategory(category.id) || isCategoryExternallyManaged(category.id)) {
|
|
47826
|
+
return;
|
|
47827
|
+
}
|
|
47828
|
+
if (typeof scopedCategoryTotals[category.id] !== "number") {
|
|
47829
|
+
fetchClipMetadata(category.id, 1);
|
|
47830
|
+
}
|
|
47831
|
+
});
|
|
47832
|
+
if (showPercentileCycleFilters) {
|
|
47833
|
+
if (!isCategoryExternallyManaged("fast-cycles") && typeof percentileCounts["fast-cycles"] !== "number") {
|
|
47834
|
+
fetchPercentileClips("fast-cycles");
|
|
47835
|
+
}
|
|
47836
|
+
if (!isCategoryExternallyManaged("slow-cycles") && typeof percentileCounts["slow-cycles"] !== "number") {
|
|
47837
|
+
fetchPercentileClips("slow-cycles");
|
|
47838
|
+
}
|
|
47839
|
+
}
|
|
47840
|
+
}, [
|
|
47841
|
+
activeInitialTimeFilter,
|
|
47842
|
+
categoriesForTree,
|
|
47843
|
+
endTime,
|
|
47844
|
+
fetchClipMetadata,
|
|
47845
|
+
fetchPercentileClips,
|
|
47846
|
+
isCategoryExternallyManaged,
|
|
47847
|
+
isTimeFilterActive,
|
|
47848
|
+
percentileCounts,
|
|
47849
|
+
scopedCategoryTotals,
|
|
47850
|
+
shouldShowCategory,
|
|
47851
|
+
showPercentileCycleFilters,
|
|
47852
|
+
startTime
|
|
47853
|
+
]);
|
|
46819
47854
|
const percentileCountsKey = useMemo(() => {
|
|
46820
47855
|
if (!workspaceId || !date || shift === void 0) {
|
|
46821
47856
|
return null;
|
|
@@ -46838,12 +47873,15 @@ var FileManagerFilters = ({
|
|
|
46838
47873
|
}
|
|
46839
47874
|
percentileCountsKeyRef.current = percentileCountsKey;
|
|
46840
47875
|
percentilePrefetchRef.current = { key: null, types: /* @__PURE__ */ new Set() };
|
|
47876
|
+
if (prefetchedPercentileClips && (Array.isArray(prefetchedPercentileClips["fast-cycles"]) || Array.isArray(prefetchedPercentileClips["slow-cycles"]))) {
|
|
47877
|
+
return;
|
|
47878
|
+
}
|
|
46841
47879
|
setPercentileCounts({
|
|
46842
47880
|
"fast-cycles": null,
|
|
46843
47881
|
"slow-cycles": null
|
|
46844
47882
|
});
|
|
46845
47883
|
setPercentileClips({});
|
|
46846
|
-
}, [showPercentileCycleFilters, percentileCountsKey]);
|
|
47884
|
+
}, [prefetchedPercentileClips, showPercentileCycleFilters, percentileCountsKey]);
|
|
46847
47885
|
useEffect(() => {
|
|
46848
47886
|
if (!showPercentileCycleFilters) {
|
|
46849
47887
|
return;
|
|
@@ -46899,11 +47937,20 @@ var FileManagerFilters = ({
|
|
|
46899
47937
|
const data = await response.json();
|
|
46900
47938
|
const fastCycles = data?.counts?.["fast-cycles"];
|
|
46901
47939
|
const slowCycles = data?.counts?.["slow-cycles"];
|
|
46902
|
-
|
|
46903
|
-
|
|
46904
|
-
|
|
46905
|
-
|
|
46906
|
-
|
|
47940
|
+
if (typeof fastCycles === "number" || typeof slowCycles === "number") {
|
|
47941
|
+
setPercentileCounts((prev) => {
|
|
47942
|
+
const nextFastCycles = typeof fastCycles === "number" ? fastCycles : prev["fast-cycles"];
|
|
47943
|
+
const nextSlowCycles = typeof slowCycles === "number" ? slowCycles : prev["slow-cycles"];
|
|
47944
|
+
if (prev["fast-cycles"] === nextFastCycles && prev["slow-cycles"] === nextSlowCycles) {
|
|
47945
|
+
return prev;
|
|
47946
|
+
}
|
|
47947
|
+
return {
|
|
47948
|
+
...prev,
|
|
47949
|
+
"fast-cycles": nextFastCycles,
|
|
47950
|
+
"slow-cycles": nextSlowCycles
|
|
47951
|
+
};
|
|
47952
|
+
});
|
|
47953
|
+
}
|
|
46907
47954
|
if (options?.prefetchClips) {
|
|
46908
47955
|
if (percentilePrefetchRef.current.key !== requestKey) {
|
|
46909
47956
|
percentilePrefetchRef.current = { key: requestKey, types: /* @__PURE__ */ new Set() };
|
|
@@ -46922,37 +47969,30 @@ var FileManagerFilters = ({
|
|
|
46922
47969
|
}
|
|
46923
47970
|
}, [workspaceId, date, shift, filterState.percentile, showPercentileCycleFilters, supabase, percentileCounts, percentileClips, fetchPercentileClips]);
|
|
46924
47971
|
useEffect(() => {
|
|
46925
|
-
if (!showPercentileCycleFilters || !isReady || !percentileCountsKey) {
|
|
47972
|
+
if (!showPercentileCycleFilters || !isReady || !percentileCountsKey || isTimeFilterActive) {
|
|
46926
47973
|
return;
|
|
46927
47974
|
}
|
|
46928
|
-
|
|
46929
|
-
|
|
46930
|
-
|
|
46931
|
-
if (
|
|
46932
|
-
|
|
46933
|
-
} else {
|
|
46934
|
-
setTimeout(schedule, 0);
|
|
46935
|
-
}
|
|
46936
|
-
}, [showPercentileCycleFilters, isReady, percentileCountsKey, fetchPercentileCounts]);
|
|
46937
|
-
const shouldShowCategory = useCallback((categoryId) => {
|
|
46938
|
-
switch (categoryId) {
|
|
46939
|
-
case "fast-cycles":
|
|
46940
|
-
return showPercentileCycleFilters && filterState.showFastCycles;
|
|
46941
|
-
case "slow-cycles":
|
|
46942
|
-
return showPercentileCycleFilters && filterState.showSlowCycles;
|
|
46943
|
-
case "longest-idles":
|
|
46944
|
-
return false;
|
|
46945
|
-
// filterState.showLongestIdles; // Temporarily disabled
|
|
46946
|
-
case "cycle_completion":
|
|
46947
|
-
return filterState.showCycleCompletion;
|
|
46948
|
-
case "idle_time":
|
|
46949
|
-
return filterState.showIdleTime;
|
|
46950
|
-
case "sop_deviations":
|
|
46951
|
-
return filterState.showSopDeviations;
|
|
46952
|
-
default:
|
|
46953
|
-
return true;
|
|
47975
|
+
fetchPercentileCounts({ prefetchClips: true });
|
|
47976
|
+
}, [showPercentileCycleFilters, isReady, percentileCountsKey, fetchPercentileCounts, isTimeFilterActive]);
|
|
47977
|
+
useEffect(() => {
|
|
47978
|
+
if (!isReady || isTimeFilterActive || activeFilter !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
47979
|
+
return;
|
|
46954
47980
|
}
|
|
46955
|
-
|
|
47981
|
+
["cycle_completion", "idle_time"].forEach((categoryId) => {
|
|
47982
|
+
if ((counts?.[categoryId] || 0) <= 0 || hasKnownClipMetadata(categoryId) || isCategoryExternallyManaged(categoryId)) {
|
|
47983
|
+
return;
|
|
47984
|
+
}
|
|
47985
|
+
fetchClipMetadata(categoryId, 1);
|
|
47986
|
+
});
|
|
47987
|
+
}, [
|
|
47988
|
+
activeFilter,
|
|
47989
|
+
counts,
|
|
47990
|
+
fetchClipMetadata,
|
|
47991
|
+
hasKnownClipMetadata,
|
|
47992
|
+
isCategoryExternallyManaged,
|
|
47993
|
+
isReady,
|
|
47994
|
+
isTimeFilterActive
|
|
47995
|
+
]);
|
|
46956
47996
|
const getPercentileIcon = useCallback((type, isExpanded, colorClasses) => {
|
|
46957
47997
|
const iconMap = {
|
|
46958
47998
|
"fast-cycles": { icon: TrendingUp, color: "text-green-600" },
|
|
@@ -46981,12 +48021,29 @@ var FileManagerFilters = ({
|
|
|
46981
48021
|
newExpanded.add(activeFilter);
|
|
46982
48022
|
return newExpanded;
|
|
46983
48023
|
});
|
|
46984
|
-
const category =
|
|
46985
|
-
if (category
|
|
46986
|
-
|
|
48024
|
+
const category = categoriesForTree.find((cat) => cat.id === activeFilter);
|
|
48025
|
+
if (category) {
|
|
48026
|
+
if (isInitialTimeFilterCategory(activeFilter) && !isCategoryExternallyManaged(activeFilter) && !hasCompleteMetadataForInitialTimeFilter(activeFilter)) {
|
|
48027
|
+
fetchClipMetadata(activeFilter, 1);
|
|
48028
|
+
} else if (!isCategoryExternallyManaged(activeFilter) && !clipMetadataRef.current[activeFilter]) {
|
|
48029
|
+
fetchClipMetadata(activeFilter, 1);
|
|
48030
|
+
}
|
|
46987
48031
|
}
|
|
46988
48032
|
}
|
|
46989
48033
|
}, [activeFilter]);
|
|
48034
|
+
useEffect(() => {
|
|
48035
|
+
const requestedCategory = activeFilter;
|
|
48036
|
+
if (!requestedCategory || !isInitialTimeFilterCategory(requestedCategory) || isCategoryExternallyManaged(requestedCategory) || hasCompleteMetadataForInitialTimeFilter(requestedCategory)) {
|
|
48037
|
+
return;
|
|
48038
|
+
}
|
|
48039
|
+
fetchClipMetadata(requestedCategory, 1);
|
|
48040
|
+
}, [
|
|
48041
|
+
activeFilter,
|
|
48042
|
+
fetchClipMetadata,
|
|
48043
|
+
hasCompleteMetadataForInitialTimeFilter,
|
|
48044
|
+
isCategoryExternallyManaged,
|
|
48045
|
+
isInitialTimeFilterCategory
|
|
48046
|
+
]);
|
|
46990
48047
|
useEffect(() => {
|
|
46991
48048
|
const handleEscape = (e) => {
|
|
46992
48049
|
if (e.key === "Escape") {
|
|
@@ -47050,25 +48107,34 @@ var FileManagerFilters = ({
|
|
|
47050
48107
|
}
|
|
47051
48108
|
try {
|
|
47052
48109
|
const clipDate = new Date(clipTimestamp);
|
|
47053
|
-
const
|
|
48110
|
+
const clipParts = new Intl.DateTimeFormat("en-US", {
|
|
47054
48111
|
hour12: false,
|
|
47055
48112
|
hour: "2-digit",
|
|
47056
48113
|
minute: "2-digit",
|
|
47057
|
-
timeZone:
|
|
47058
|
-
});
|
|
47059
|
-
|
|
48114
|
+
timeZone: activeTimeFilterTimezone
|
|
48115
|
+
}).formatToParts(clipDate);
|
|
48116
|
+
const hourValue = clipParts.find((part) => part.type === "hour")?.value;
|
|
48117
|
+
const minuteValue = clipParts.find((part) => part.type === "minute")?.value;
|
|
48118
|
+
const clipMinute = timeValueToMinutes(`${hourValue}:${minuteValue}`);
|
|
48119
|
+
return clipMinute === null ? false : isMinuteInTimeWindow(clipMinute, startTime, endTime);
|
|
47060
48120
|
} catch (error) {
|
|
47061
48121
|
console.error("[FileManager] Error parsing clip timestamp:", error);
|
|
47062
48122
|
return true;
|
|
47063
48123
|
}
|
|
47064
|
-
}, [isTimeFilterActive, startTime, endTime,
|
|
48124
|
+
}, [isTimeFilterActive, startTime, endTime, activeTimeFilterTimezone]);
|
|
47065
48125
|
const filterTree = useMemo(() => {
|
|
47066
48126
|
const tree = [];
|
|
47067
48127
|
const regularCategoryNodes = [];
|
|
47068
|
-
|
|
48128
|
+
categoriesForTree.forEach((category) => {
|
|
48129
|
+
if (category.id === "fast-cycles" || category.id === "slow-cycles") {
|
|
48130
|
+
return;
|
|
48131
|
+
}
|
|
47069
48132
|
const categoryCount = counts?.[category.id] || 0;
|
|
47070
|
-
const
|
|
47071
|
-
|
|
48133
|
+
const categoryMetadataClips = getAvailableClipMetadata(category.id);
|
|
48134
|
+
const categoryVideoFallbackClips = categoryMetadataClips.length === 0 && isInitialTimeFilterCategory(category.id) ? videos.filter((video) => video.type === category.id).map(buildClipMetadataFromVideo).filter((clip) => isClipInTimeRange(clip.clip_timestamp)) : [];
|
|
48135
|
+
const categoryClips = categoryMetadataClips.length > 0 ? categoryMetadataClips : categoryVideoFallbackClips;
|
|
48136
|
+
const timeFilteredClips = categoryClips.filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
48137
|
+
let filteredClips = timeFilteredClips;
|
|
47072
48138
|
if (category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
47073
48139
|
filteredClips = sortRedFlowMetadata(filteredClips);
|
|
47074
48140
|
}
|
|
@@ -47078,9 +48144,22 @@ var FileManagerFilters = ({
|
|
|
47078
48144
|
return classification?.label === idleLabelFilter;
|
|
47079
48145
|
});
|
|
47080
48146
|
}
|
|
47081
|
-
const
|
|
48147
|
+
const scopedTotal = typeof scopedCategoryTotals[category.id] === "number" ? scopedCategoryTotals[category.id] : null;
|
|
48148
|
+
const isScopedByTimeFilter = isCategoryScopedByTimeFilter(category.id);
|
|
48149
|
+
const scopedPageLoaded = isScopedByTimeFilter && typeof scopedCategoryTotals[category.id] === "number";
|
|
48150
|
+
const scopedResponseHadOutOfHourClips = categoryClips.length > filteredClips.length;
|
|
48151
|
+
const shouldTrustScopedTotal = !scopedResponseHadOutOfHourClips || Boolean(categoryHasMore[category.id]);
|
|
48152
|
+
const isCategoryMetadataLoading = Array.from(loadingCategories).some((key) => key.startsWith(`${category.id}-`));
|
|
48153
|
+
const isScopedTotalPending = isTimeFilterActive && isScopedByTimeFilter && scopedTotal === null;
|
|
48154
|
+
const displayCount = isScopedTotalPending ? null : isTimeFilterActive && isScopedByTimeFilter && scopedTotal !== null ? shouldTrustScopedTotal ? scopedTotal : filteredClips.length : isTimeFilterActive || category.id === "idle_time" && idleLabelFilter ? filteredClips.length : categoryCount;
|
|
48155
|
+
const shouldShowScopedEmptyCategory = Boolean(
|
|
48156
|
+
scopedPageLoaded && !isCategoryMetadataLoading && !categoryHasMore[category.id] && filteredClips.length === 0 && (isRequiredHourlyFilterCategory(category.id) || activeFilter === category.id)
|
|
48157
|
+
);
|
|
48158
|
+
const shouldShowScopedLoadingCategory = Boolean(
|
|
48159
|
+
isScopedTotalPending && (isRequiredHourlyFilterCategory(category.id) || !activeInitialTimeFilter || activeFilter === category.id)
|
|
48160
|
+
);
|
|
47082
48161
|
const shouldShowEmptyIdleTime = category.id === "idle_time" && idleLabelFilter;
|
|
47083
|
-
if ((displayCount > 0 || shouldShowEmptyIdleTime) && shouldShowCategory(category.id)) {
|
|
48162
|
+
if ((typeof displayCount === "number" && displayCount > 0 || shouldShowEmptyIdleTime || isCategoryMetadataLoading || shouldShowScopedEmptyCategory || shouldShowScopedLoadingCategory) && shouldShowCategory(category.id)) {
|
|
47084
48163
|
const colorClasses = getColorClasses(category.color);
|
|
47085
48164
|
const clipNodes = filteredClips.map((clip, index) => {
|
|
47086
48165
|
const cycleTime = extractCycleTimeSeconds(clip);
|
|
@@ -47090,7 +48169,7 @@ var FileManagerFilters = ({
|
|
|
47090
48169
|
const baseTimeLabel = formatClipExplorerTimeLabel({
|
|
47091
48170
|
categoryId: category.id,
|
|
47092
48171
|
clipTimestamp: clip.clip_timestamp,
|
|
47093
|
-
timezone,
|
|
48172
|
+
timezone: activeTimeFilterTimezone,
|
|
47094
48173
|
durationSeconds: idleDuration ?? clip.duration,
|
|
47095
48174
|
idleStartTime: clip.idle_start_time,
|
|
47096
48175
|
idleEndTime: clip.idle_end_time,
|
|
@@ -47128,6 +48207,7 @@ var FileManagerFilters = ({
|
|
|
47128
48207
|
type: "category",
|
|
47129
48208
|
count: displayCount,
|
|
47130
48209
|
// Use filtered count when time filter is active
|
|
48210
|
+
countLoading: isScopedTotalPending || isCategoryMetadataLoading && scopedTotal === null,
|
|
47131
48211
|
children: clipNodes,
|
|
47132
48212
|
// Use clip nodes from metadata
|
|
47133
48213
|
icon: expandedNodes.has(category.id) ? /* @__PURE__ */ jsx(FolderOpen, { className: `h-4 w-4 ${colorClasses.text}` }) : getCategoryIcon(category.icon, colorClasses),
|
|
@@ -47135,10 +48215,18 @@ var FileManagerFilters = ({
|
|
|
47135
48215
|
});
|
|
47136
48216
|
}
|
|
47137
48217
|
});
|
|
47138
|
-
const filteredFastCycles = (
|
|
47139
|
-
|
|
48218
|
+
const filteredFastCycles = sortPercentileCycleClipsForDisplay(
|
|
48219
|
+
"fast-cycles",
|
|
48220
|
+
(percentileClips["fast-cycles"] || []).filter((clip) => isClipInTimeRange(clip.creation_timestamp || ""))
|
|
48221
|
+
);
|
|
48222
|
+
const filteredSlowCycles = sortPercentileCycleClipsForDisplay(
|
|
48223
|
+
"slow-cycles",
|
|
48224
|
+
(percentileClips["slow-cycles"] || []).filter((clip) => isClipInTimeRange(clip.creation_timestamp || ""))
|
|
48225
|
+
);
|
|
47140
48226
|
const fastCount = typeof percentileCounts["fast-cycles"] === "number" ? percentileCounts["fast-cycles"] : null;
|
|
47141
48227
|
const slowCount = typeof percentileCounts["slow-cycles"] === "number" ? percentileCounts["slow-cycles"] : null;
|
|
48228
|
+
const isFastCountPending = showPercentileCycleFilters && fastCount === null;
|
|
48229
|
+
const isSlowCountPending = showPercentileCycleFilters && slowCount === null;
|
|
47142
48230
|
const percentileCategories = showPercentileCycleFilters ? [
|
|
47143
48231
|
{
|
|
47144
48232
|
id: "fast-cycles",
|
|
@@ -47147,6 +48235,7 @@ var FileManagerFilters = ({
|
|
|
47147
48235
|
description: "Top 10% fastest performance",
|
|
47148
48236
|
type: "percentile-category",
|
|
47149
48237
|
count: isTimeFilterActive ? fastCount === null && filteredFastCycles.length === 0 ? null : filteredFastCycles.length : fastCount,
|
|
48238
|
+
countLoading: isFastCountPending,
|
|
47150
48239
|
icon: getPercentileIcon("fast-cycles", expandedNodes.has("fast-cycles"), { text: "text-green-600" }),
|
|
47151
48240
|
color: "green",
|
|
47152
48241
|
percentileType: "fast-cycles",
|
|
@@ -47158,7 +48247,7 @@ var FileManagerFilters = ({
|
|
|
47158
48247
|
label: `${formatClipExplorerTimeLabel({
|
|
47159
48248
|
categoryId: "fast-cycles",
|
|
47160
48249
|
clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
|
|
47161
|
-
timezone,
|
|
48250
|
+
timezone: activeTimeFilterTimezone,
|
|
47162
48251
|
durationSeconds: cycleTime
|
|
47163
48252
|
})}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
47164
48253
|
type: "video",
|
|
@@ -47178,6 +48267,7 @@ var FileManagerFilters = ({
|
|
|
47178
48267
|
description: "Bottom 10% slowest performance",
|
|
47179
48268
|
type: "percentile-category",
|
|
47180
48269
|
count: isTimeFilterActive ? slowCount === null && filteredSlowCycles.length === 0 ? null : filteredSlowCycles.length : slowCount,
|
|
48270
|
+
countLoading: isSlowCountPending,
|
|
47181
48271
|
icon: getPercentileIcon("slow-cycles", expandedNodes.has("slow-cycles"), { text: "text-red-600" }),
|
|
47182
48272
|
color: "red",
|
|
47183
48273
|
percentileType: "slow-cycles",
|
|
@@ -47189,7 +48279,7 @@ var FileManagerFilters = ({
|
|
|
47189
48279
|
label: `${formatClipExplorerTimeLabel({
|
|
47190
48280
|
categoryId: "slow-cycles",
|
|
47191
48281
|
clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
|
|
47192
|
-
timezone,
|
|
48282
|
+
timezone: activeTimeFilterTimezone,
|
|
47193
48283
|
durationSeconds: cycleTime
|
|
47194
48284
|
})}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
47195
48285
|
type: "video",
|
|
@@ -47220,7 +48310,7 @@ var FileManagerFilters = ({
|
|
|
47220
48310
|
hour12: true,
|
|
47221
48311
|
hour: 'numeric',
|
|
47222
48312
|
minute: '2-digit',
|
|
47223
|
-
timeZone:
|
|
48313
|
+
timeZone: activeTimeFilterTimezone
|
|
47224
48314
|
});
|
|
47225
48315
|
|
|
47226
48316
|
return {
|
|
@@ -47239,7 +48329,11 @@ var FileManagerFilters = ({
|
|
|
47239
48329
|
const orderedIds = [RECENT_FLOW_RED_STREAK_CLIP_TYPE2, "cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
47240
48330
|
orderedIds.forEach((orderedId) => {
|
|
47241
48331
|
const percentileCategory = percentileCategories.find((cat) => cat.id === orderedId);
|
|
47242
|
-
const shouldIncludePercentile = percentileCategory ? typeof percentileCategory.count === "number"
|
|
48332
|
+
const shouldIncludePercentile = percentileCategory ? typeof percentileCategory.count === "number" || Boolean(
|
|
48333
|
+
isTimeFilterActive && isRequiredHourlyFilterCategory(orderedId) && typeof percentileCategory.count === "number" && percentileCategory.count === 0
|
|
48334
|
+
) || Boolean(
|
|
48335
|
+
percentileCategory.countLoading && (isRequiredHourlyFilterCategory(orderedId) || !activeInitialTimeFilter || activeFilter === orderedId)
|
|
48336
|
+
) : false;
|
|
47243
48337
|
if (percentileCategory && shouldIncludePercentile && shouldShowCategory(orderedId)) {
|
|
47244
48338
|
tree.push(percentileCategory);
|
|
47245
48339
|
}
|
|
@@ -47254,23 +48348,263 @@ var FileManagerFilters = ({
|
|
|
47254
48348
|
}
|
|
47255
48349
|
});
|
|
47256
48350
|
percentileCategories.forEach((category) => {
|
|
47257
|
-
const shouldIncludePercentile = typeof category.count === "number"
|
|
48351
|
+
const shouldIncludePercentile = typeof category.count === "number" || Boolean(
|
|
48352
|
+
isTimeFilterActive && isRequiredHourlyFilterCategory(category.id) && typeof category.count === "number" && category.count === 0
|
|
48353
|
+
) || Boolean(
|
|
48354
|
+
category.countLoading && (isRequiredHourlyFilterCategory(category.id) || !activeInitialTimeFilter || activeFilter === category.id)
|
|
48355
|
+
);
|
|
47258
48356
|
if (!orderedIds.includes(category.id) && shouldIncludePercentile && shouldShowCategory(category.id)) {
|
|
47259
48357
|
tree.push(category);
|
|
47260
48358
|
}
|
|
47261
48359
|
});
|
|
47262
48360
|
return tree;
|
|
47263
|
-
}, [
|
|
48361
|
+
}, [categoriesForTree, expandedNodes, counts, getAvailableClipMetadata, percentileCounts, percentileClips, shouldShowCategory, getPercentileIcon, isClipInTimeRange, isTimeFilterActive, showPercentileCycleFilters, loadingCategories, activeTimeFilterTimezone, isInitialTimeFilterCategory, isRequiredHourlyFilterCategory, hasCompleteMetadataForInitialTimeFilter, scopedCategoryTotals, isCategoryScopedByTimeFilter, categoryHasMore, activeFilter]);
|
|
48362
|
+
const chartHandoffVideoFallbackTree = useMemo(() => {
|
|
48363
|
+
if (!startTime || !endTime || !activeInitialTimeFilter || !activeFilter) {
|
|
48364
|
+
return [];
|
|
48365
|
+
}
|
|
48366
|
+
const fallbackCategory = categoriesForTree.find((category) => category.id === activeFilter) || categoriesForTree.find((category) => videos.some((video) => video.type === category.id));
|
|
48367
|
+
if (!fallbackCategory) {
|
|
48368
|
+
return [];
|
|
48369
|
+
}
|
|
48370
|
+
const fallbackVideos = videos.filter((video) => video.type === fallbackCategory.id);
|
|
48371
|
+
const sourceVideos = fallbackVideos.map(buildClipMetadataFromVideo).filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
48372
|
+
if (sourceVideos.length === 0) {
|
|
48373
|
+
return [];
|
|
48374
|
+
}
|
|
48375
|
+
const colorClasses = getColorClasses(fallbackCategory.color);
|
|
48376
|
+
const clipNodes = sourceVideos.map((clip, index) => {
|
|
48377
|
+
const cycleTime = extractCycleTimeSeconds(clip);
|
|
48378
|
+
const baseTimeLabel = formatClipExplorerTimeLabel({
|
|
48379
|
+
categoryId: fallbackCategory.id,
|
|
48380
|
+
clipTimestamp: clip.clip_timestamp,
|
|
48381
|
+
timezone: activeTimeFilterTimezone,
|
|
48382
|
+
durationSeconds: clip.duration,
|
|
48383
|
+
idleStartTime: clip.idle_start_time,
|
|
48384
|
+
idleEndTime: clip.idle_end_time,
|
|
48385
|
+
clipStartTime: clip.clip_start_time,
|
|
48386
|
+
clipEndTime: clip.clip_end_time
|
|
48387
|
+
});
|
|
48388
|
+
const displayLabel = `${baseTimeLabel}${clip.duration && fallbackCategory.id !== "idle_time" && fallbackCategory.id !== "low_value" && fallbackCategory.id !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
|
|
48389
|
+
return {
|
|
48390
|
+
id: clip.id,
|
|
48391
|
+
label: displayLabel,
|
|
48392
|
+
type: "video",
|
|
48393
|
+
icon: getSeverityIcon(clip.severity, fallbackCategory.id, cycleTime, resolvedTargetCycleTime, clip.clipId),
|
|
48394
|
+
timestamp: clip.clip_timestamp,
|
|
48395
|
+
severity: clip.severity,
|
|
48396
|
+
clipId: clip.clipId,
|
|
48397
|
+
categoryId: fallbackCategory.id,
|
|
48398
|
+
clipPosition: index + 1,
|
|
48399
|
+
cycleTimeSeconds: cycleTime,
|
|
48400
|
+
duration: clip.duration,
|
|
48401
|
+
cycleItemCount: null,
|
|
48402
|
+
redFlowSeverityScore: clip.red_flow_severity_score ?? null,
|
|
48403
|
+
redFlowExplanationSummary: clip.red_flow_explanation_summary ?? clip.red_flow_explanation?.summary ?? null
|
|
48404
|
+
};
|
|
48405
|
+
});
|
|
48406
|
+
return [{
|
|
48407
|
+
id: activeFilter,
|
|
48408
|
+
label: fallbackCategory.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_LABEL : fallbackCategory.label,
|
|
48409
|
+
subtitle: fallbackCategory.subtitle || fallbackCategory.description,
|
|
48410
|
+
description: fallbackCategory.description,
|
|
48411
|
+
type: "category",
|
|
48412
|
+
count: clipNodes.length,
|
|
48413
|
+
children: clipNodes,
|
|
48414
|
+
icon: /* @__PURE__ */ jsx(FolderOpen, { className: `h-4 w-4 ${colorClasses.text}` }),
|
|
48415
|
+
color: fallbackCategory.color
|
|
48416
|
+
}];
|
|
48417
|
+
}, [
|
|
48418
|
+
activeFilter,
|
|
48419
|
+
activeInitialTimeFilter,
|
|
48420
|
+
activeTimeFilterTimezone,
|
|
48421
|
+
categoriesForTree,
|
|
48422
|
+
counts,
|
|
48423
|
+
currentVideoId,
|
|
48424
|
+
endTime,
|
|
48425
|
+
getDisplayValue,
|
|
48426
|
+
isClipInTimeRange,
|
|
48427
|
+
resolvedTargetCycleTime,
|
|
48428
|
+
startTime,
|
|
48429
|
+
videos
|
|
48430
|
+
]);
|
|
48431
|
+
const displayedFilterTree = useMemo(() => {
|
|
48432
|
+
if (chartHandoffVideoFallbackTree.length === 0) {
|
|
48433
|
+
return filterTree;
|
|
48434
|
+
}
|
|
48435
|
+
if (filterTree.length === 0) {
|
|
48436
|
+
return chartHandoffVideoFallbackTree;
|
|
48437
|
+
}
|
|
48438
|
+
const fallbackNode = chartHandoffVideoFallbackTree[0];
|
|
48439
|
+
const activeNode = filterTree.find((node) => node.id === activeFilter);
|
|
48440
|
+
const activeNodeHasChildren = (activeNode?.children?.length || 0) > 0;
|
|
48441
|
+
const shouldReplaceActiveNode = Boolean(
|
|
48442
|
+
activeFilter && fallbackNode && activeNode && !activeNodeHasChildren && isInitialTimeFilterCategory(activeFilter)
|
|
48443
|
+
);
|
|
48444
|
+
if (!shouldReplaceActiveNode) {
|
|
48445
|
+
return filterTree;
|
|
48446
|
+
}
|
|
48447
|
+
return filterTree.map((node) => node.id === activeFilter ? fallbackNode : node);
|
|
48448
|
+
}, [activeFilter, chartHandoffVideoFallbackTree, filterTree, isInitialTimeFilterCategory]);
|
|
48449
|
+
const getSelectionContextForNodes = useCallback((categoryId, clipNodes) => {
|
|
48450
|
+
const normalizeSeverity = (severity) => severity === "low" || severity === "medium" || severity === "high" ? severity : "medium";
|
|
48451
|
+
const scopedNodes = clipNodes.filter((node) => node.type === "video" && Boolean(node.clipId || node.id));
|
|
48452
|
+
const scopedNodeClips = scopedNodes.map((node, index) => ({
|
|
48453
|
+
id: node.clipId || node.id,
|
|
48454
|
+
clipId: node.clipId || node.id,
|
|
48455
|
+
clip_timestamp: node.timestamp || "",
|
|
48456
|
+
creation_timestamp: node.timestamp || "",
|
|
48457
|
+
description: node.label,
|
|
48458
|
+
severity: normalizeSeverity(node.severity),
|
|
48459
|
+
category: categoryId,
|
|
48460
|
+
duration: node.duration,
|
|
48461
|
+
cycle_time_seconds: node.cycleTimeSeconds,
|
|
48462
|
+
index
|
|
48463
|
+
}));
|
|
48464
|
+
const categoryClips = getAvailableClipMetadata(categoryId);
|
|
48465
|
+
const contextClips = isCategoryScopedByTimeFilter(categoryId) && scopedNodeClips.length > 0 ? scopedNodeClips : categoryClips.length > 0 ? categoryClips : scopedNodeClips;
|
|
48466
|
+
const scopedTotal = scopedCategoryTotals[categoryId];
|
|
48467
|
+
const total = typeof scopedTotal === "number" ? scopedTotal : counts?.[categoryId];
|
|
48468
|
+
return contextClips.length ? { clips: contextClips, total } : void 0;
|
|
48469
|
+
}, [counts, getAvailableClipMetadata, isCategoryScopedByTimeFilter, scopedCategoryTotals]);
|
|
48470
|
+
useEffect(() => {
|
|
48471
|
+
if (!activeInitialTimeFilter || !startTime || !endTime || currentVideoId || !onClipSelect) {
|
|
48472
|
+
return;
|
|
48473
|
+
}
|
|
48474
|
+
const categoryPriority = Array.from(new Set([
|
|
48475
|
+
activeInitialTimeFilter.categoryId,
|
|
48476
|
+
activeFilter,
|
|
48477
|
+
...activeInitialTimeFilter.categoryIds || []
|
|
48478
|
+
].filter((value) => typeof value === "string" && value.length > 0)));
|
|
48479
|
+
const preferredCategoryId = categoryPriority[0];
|
|
48480
|
+
const orderedCategoryNodes = displayedFilterTree.filter((categoryNode) => isInitialTimeFilterCategory(categoryNode.id)).sort((left, right) => {
|
|
48481
|
+
const leftIndex = categoryPriority.indexOf(left.id);
|
|
48482
|
+
const rightIndex = categoryPriority.indexOf(right.id);
|
|
48483
|
+
const leftPriority = leftIndex === -1 ? Number.MAX_SAFE_INTEGER : leftIndex;
|
|
48484
|
+
const rightPriority = rightIndex === -1 ? Number.MAX_SAFE_INTEGER : rightIndex;
|
|
48485
|
+
return leftPriority - rightPriority;
|
|
48486
|
+
});
|
|
48487
|
+
const preferredCategoryNode = preferredCategoryId ? orderedCategoryNodes.find((categoryNode) => categoryNode.id === preferredCategoryId) : void 0;
|
|
48488
|
+
if (preferredCategoryId && !preferredCategoryNode) {
|
|
48489
|
+
const preferredKnownTotal = preferredCategoryId === "fast-cycles" || preferredCategoryId === "slow-cycles" ? percentileCounts[preferredCategoryId] : scopedCategoryTotals[preferredCategoryId];
|
|
48490
|
+
if (preferredKnownTotal !== 0) {
|
|
48491
|
+
return;
|
|
48492
|
+
}
|
|
48493
|
+
}
|
|
48494
|
+
const preferredFirstClipNode = preferredCategoryNode?.children?.find((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48495
|
+
if (preferredCategoryId && preferredCategoryNode && !preferredFirstClipNode) {
|
|
48496
|
+
const preferredKnownTotal = preferredCategoryId === "fast-cycles" || preferredCategoryId === "slow-cycles" ? percentileCounts[preferredCategoryId] : scopedCategoryTotals[preferredCategoryId];
|
|
48497
|
+
if (preferredKnownTotal !== 0) {
|
|
48498
|
+
return;
|
|
48499
|
+
}
|
|
48500
|
+
}
|
|
48501
|
+
for (const categoryNode of orderedCategoryNodes) {
|
|
48502
|
+
const firstClipNode = categoryNode.children?.find((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48503
|
+
if (!firstClipNode?.clipId || !firstClipNode.categoryId) {
|
|
48504
|
+
continue;
|
|
48505
|
+
}
|
|
48506
|
+
const selectionKey = `${activeTimeFilterKey}:${firstClipNode.categoryId}:${firstClipNode.clipId}:${currentVideoId || "none"}`;
|
|
48507
|
+
if (autoSelectedScopedClipRef.current === selectionKey) {
|
|
48508
|
+
return;
|
|
48509
|
+
}
|
|
48510
|
+
autoSelectedScopedClipRef.current = selectionKey;
|
|
48511
|
+
const selectionContext = getSelectionContextForNodes(firstClipNode.categoryId, categoryNode.children || []);
|
|
48512
|
+
onClipSelect(
|
|
48513
|
+
firstClipNode.categoryId,
|
|
48514
|
+
firstClipNode.clipId,
|
|
48515
|
+
firstClipNode.clipPosition,
|
|
48516
|
+
selectionContext
|
|
48517
|
+
);
|
|
48518
|
+
return;
|
|
48519
|
+
}
|
|
48520
|
+
}, [
|
|
48521
|
+
activeInitialTimeFilter,
|
|
48522
|
+
activeFilter,
|
|
48523
|
+
activeTimeFilterKey,
|
|
48524
|
+
currentVideoId,
|
|
48525
|
+
displayedFilterTree,
|
|
48526
|
+
endTime,
|
|
48527
|
+
getSelectionContextForNodes,
|
|
48528
|
+
isInitialTimeFilterCategory,
|
|
48529
|
+
onClipSelect,
|
|
48530
|
+
percentileCounts,
|
|
48531
|
+
scopedCategoryTotals,
|
|
48532
|
+
startTime
|
|
48533
|
+
]);
|
|
48534
|
+
const isChartHandoffLoading = useMemo(() => {
|
|
48535
|
+
if (!startTime || !endTime || !activeInitialTimeFilter || !activeFilter || !isInitialTimeFilterCategory(activeFilter)) {
|
|
48536
|
+
return false;
|
|
48537
|
+
}
|
|
48538
|
+
const pageOneLoadingKey = getMetadataLoadingKey(activeFilter, 1);
|
|
48539
|
+
return Boolean(
|
|
48540
|
+
activeCategoryLoading || Array.from(loadingCategories).some((key) => key === pageOneLoadingKey || key.startsWith(`${pageOneLoadingKey}-all`))
|
|
48541
|
+
);
|
|
48542
|
+
}, [
|
|
48543
|
+
activeCategoryLoading,
|
|
48544
|
+
activeFilter,
|
|
48545
|
+
activeInitialTimeFilter,
|
|
48546
|
+
endTime,
|
|
48547
|
+
getMetadataLoadingKey,
|
|
48548
|
+
isInitialTimeFilterCategory,
|
|
48549
|
+
loadingCategories,
|
|
48550
|
+
startTime
|
|
48551
|
+
]);
|
|
48552
|
+
useEffect(() => {
|
|
48553
|
+
if (!isTimeFilterActive || !startTime || !endTime || !activeFilter || activeFilter === "all" || !onClipSelect) {
|
|
48554
|
+
return;
|
|
48555
|
+
}
|
|
48556
|
+
const activeCategoryNode = displayedFilterTree.find((categoryNode) => categoryNode.id === activeFilter);
|
|
48557
|
+
const activeClipNodes = (activeCategoryNode?.children || []).filter((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48558
|
+
if (activeClipNodes.length === 0) {
|
|
48559
|
+
return;
|
|
48560
|
+
}
|
|
48561
|
+
const currentClipIsVisible = Boolean(
|
|
48562
|
+
currentVideoId && activeClipNodes.some((child) => (child.clipId || child.id) === currentVideoId)
|
|
48563
|
+
);
|
|
48564
|
+
if (currentClipIsVisible) {
|
|
48565
|
+
return;
|
|
48566
|
+
}
|
|
48567
|
+
const firstClipNode = activeClipNodes[0];
|
|
48568
|
+
if (!firstClipNode?.clipId || !firstClipNode.categoryId) {
|
|
48569
|
+
return;
|
|
48570
|
+
}
|
|
48571
|
+
const selectionKey = `${activeTimeFilterKey}:${firstClipNode.categoryId}:${firstClipNode.clipId}:${currentVideoId || "none"}`;
|
|
48572
|
+
if (autoSelectedScopedClipRef.current === selectionKey) {
|
|
48573
|
+
return;
|
|
48574
|
+
}
|
|
48575
|
+
autoSelectedScopedClipRef.current = selectionKey;
|
|
48576
|
+
const selectionContext = getSelectionContextForNodes(firstClipNode.categoryId, activeClipNodes);
|
|
48577
|
+
onClipSelect(
|
|
48578
|
+
firstClipNode.categoryId,
|
|
48579
|
+
firstClipNode.clipId,
|
|
48580
|
+
firstClipNode.clipPosition,
|
|
48581
|
+
selectionContext
|
|
48582
|
+
);
|
|
48583
|
+
}, [
|
|
48584
|
+
activeFilter,
|
|
48585
|
+
activeTimeFilterKey,
|
|
48586
|
+
currentVideoId,
|
|
48587
|
+
displayedFilterTree,
|
|
48588
|
+
endTime,
|
|
48589
|
+
getSelectionContextForNodes,
|
|
48590
|
+
isTimeFilterActive,
|
|
48591
|
+
onClipSelect,
|
|
48592
|
+
startTime
|
|
48593
|
+
]);
|
|
47264
48594
|
const toggleExpanded = (nodeId) => {
|
|
47265
48595
|
const newExpanded = new Set(expandedNodes);
|
|
47266
48596
|
if (newExpanded.has(nodeId)) {
|
|
47267
48597
|
newExpanded.delete(nodeId);
|
|
47268
48598
|
} else {
|
|
47269
48599
|
newExpanded.add(nodeId);
|
|
47270
|
-
const category =
|
|
47271
|
-
if (category
|
|
48600
|
+
const category = categoriesForTree.find((cat) => cat.id === nodeId);
|
|
48601
|
+
if (category) {
|
|
47272
48602
|
console.log(`[FileManager] Fetching clips for expanded category: ${nodeId}`);
|
|
47273
|
-
|
|
48603
|
+
if (isInitialTimeFilterCategory(nodeId) && !hasCompleteMetadataForInitialTimeFilter(nodeId)) {
|
|
48604
|
+
fetchClipMetadata(nodeId, 1);
|
|
48605
|
+
} else if (!hasKnownClipMetadata(nodeId) && !isCategoryExternallyManaged(nodeId)) {
|
|
48606
|
+
fetchClipMetadata(nodeId, 1);
|
|
48607
|
+
}
|
|
47274
48608
|
}
|
|
47275
48609
|
if (!isCategoryExternallyManaged(nodeId) && showPercentileCycleFilters && nodeId === "fast-cycles" && (percentileClips["fast-cycles"] || []).length === 0) {
|
|
47276
48610
|
fetchPercentileClips("fast-cycles");
|
|
@@ -47288,10 +48622,14 @@ var FileManagerFilters = ({
|
|
|
47288
48622
|
newExpanded.delete(node.id);
|
|
47289
48623
|
} else {
|
|
47290
48624
|
newExpanded.add(node.id);
|
|
47291
|
-
const category =
|
|
47292
|
-
if (category
|
|
48625
|
+
const category = categoriesForTree.find((cat) => cat.id === node.id);
|
|
48626
|
+
if (category) {
|
|
47293
48627
|
console.log(`[FileManager] Fetching clips for expanded category: ${node.id}`);
|
|
47294
|
-
|
|
48628
|
+
if (isInitialTimeFilterCategory(node.id) && !hasCompleteMetadataForInitialTimeFilter(node.id)) {
|
|
48629
|
+
fetchClipMetadata(node.id, 1);
|
|
48630
|
+
} else if (!hasKnownClipMetadata(node.id) && !isCategoryExternallyManaged(node.id)) {
|
|
48631
|
+
fetchClipMetadata(node.id, 1);
|
|
48632
|
+
}
|
|
47295
48633
|
}
|
|
47296
48634
|
if (!isCategoryExternallyManaged(node.id) && showPercentileCycleFilters && node.id === "fast-cycles" && (percentileClips["fast-cycles"] || []).length === 0) {
|
|
47297
48635
|
fetchPercentileClips("fast-cycles");
|
|
@@ -47301,7 +48639,21 @@ var FileManagerFilters = ({
|
|
|
47301
48639
|
}
|
|
47302
48640
|
}
|
|
47303
48641
|
setExpandedNodes(newExpanded);
|
|
47304
|
-
|
|
48642
|
+
if (node.id !== activeFilter) {
|
|
48643
|
+
onFilterChange(node.id);
|
|
48644
|
+
}
|
|
48645
|
+
if (isCategoryScopedByTimeFilter(node.id) && onClipSelect && node.children?.length) {
|
|
48646
|
+
const firstClipNode = node.children.find((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48647
|
+
if (firstClipNode?.clipId && firstClipNode.categoryId) {
|
|
48648
|
+
const selectionContext = getSelectionContextForNodes(firstClipNode.categoryId, node.children);
|
|
48649
|
+
onClipSelect(
|
|
48650
|
+
firstClipNode.categoryId,
|
|
48651
|
+
firstClipNode.clipId,
|
|
48652
|
+
firstClipNode.clipPosition,
|
|
48653
|
+
selectionContext
|
|
48654
|
+
);
|
|
48655
|
+
}
|
|
48656
|
+
}
|
|
47305
48657
|
if (node.id === "fast-cycles") {
|
|
47306
48658
|
trackCoreEvent("Fast Clips Clicked", {
|
|
47307
48659
|
workspaceId,
|
|
@@ -47339,8 +48691,11 @@ var FileManagerFilters = ({
|
|
|
47339
48691
|
} else if (node.type === "video") {
|
|
47340
48692
|
if (onClipSelect && node.categoryId !== void 0 && node.clipId !== void 0) {
|
|
47341
48693
|
console.log(`[FileManager] Selecting clip: category=${node.categoryId}, clipId=${node.clipId}, position=${node.clipPosition}`);
|
|
47342
|
-
const
|
|
47343
|
-
const selectionContext =
|
|
48694
|
+
const categoryNode = displayedFilterTree.find((candidate) => candidate.id === node.categoryId);
|
|
48695
|
+
const selectionContext = getSelectionContextForNodes(
|
|
48696
|
+
node.categoryId,
|
|
48697
|
+
categoryNode?.children || [node]
|
|
48698
|
+
);
|
|
47344
48699
|
onClipSelect(node.categoryId, node.clipId, node.clipPosition, selectionContext);
|
|
47345
48700
|
} else {
|
|
47346
48701
|
const videoIndex = videos.findIndex((v) => v.id === node.id);
|
|
@@ -47353,24 +48708,40 @@ var FileManagerFilters = ({
|
|
|
47353
48708
|
const renderNode = (node, depth = 0) => {
|
|
47354
48709
|
const isExpanded = expandedNodes.has(node.id);
|
|
47355
48710
|
const isActive = activeFilter === node.id;
|
|
47356
|
-
const
|
|
47357
|
-
const
|
|
47358
|
-
|
|
47359
|
-
|
|
48711
|
+
const nodeClipId = node.clipId || node.id;
|
|
48712
|
+
const isCurrentVideo = Boolean(
|
|
48713
|
+
node.type === "video" && currentVideoId && currentVideoId === nodeClipId
|
|
48714
|
+
);
|
|
48715
|
+
const isCountUnknown = Boolean(
|
|
48716
|
+
(node.type === "category" || node.type === "percentile-category") && (node.count === null || node.countLoading)
|
|
48717
|
+
);
|
|
48718
|
+
const hasRenderedChildren = (node.children?.length || 0) > 0;
|
|
47360
48719
|
const loadedPage = categoryPages[node.id] || 0;
|
|
47361
48720
|
const pageOneLoadingKey = getMetadataLoadingKey(node.id, 1);
|
|
47362
48721
|
const nextMetadataPage = loadedPage + 1;
|
|
47363
48722
|
const nextLoadMorePage = (categoryPages[node.id] || 1) + 1;
|
|
47364
48723
|
const isPageOneLoading = loadingCategories.has(pageOneLoadingKey);
|
|
48724
|
+
const isFullCategoryLoading = Array.from(loadingCategories).some((key) => key.startsWith(`${pageOneLoadingKey}-all`));
|
|
47365
48725
|
const isLoadMoreLoading = loadedPage > 0 && loadingCategories.has(getMetadataLoadingKey(node.id, nextMetadataPage));
|
|
48726
|
+
const isNodeLoading = Boolean(
|
|
48727
|
+
isPageOneLoading || isFullCategoryLoading || activeCategoryLoading && node.id === activeFilter
|
|
48728
|
+
);
|
|
48729
|
+
const totalForLoadMore = isCategoryScopedByTimeFilter(node.id) && typeof scopedCategoryTotals[node.id] === "number" ? scopedCategoryTotals[node.id] : counts?.[node.id] || 0;
|
|
47366
48730
|
const showInitialLoadingState = Boolean(
|
|
47367
|
-
isExpanded && !
|
|
48731
|
+
isExpanded && !hasRenderedChildren && (node.type === "category" || node.type === "percentile-category") && isNodeLoading
|
|
48732
|
+
);
|
|
48733
|
+
const showScopedEmptyState = Boolean(
|
|
48734
|
+
isExpanded && !hasRenderedChildren && !isNodeLoading && !categoryHasMore[node.id] && isCategoryScopedByTimeFilter(node.id) && (node.type === "category" || node.type === "percentile-category")
|
|
47368
48735
|
);
|
|
48736
|
+
const hasChildren = isCountUnknown || (node.count || 0) > 0 || isNodeLoading || showScopedEmptyState;
|
|
47369
48737
|
const colorClasses = node.color ? getColorClasses(node.color) : null;
|
|
47370
48738
|
return /* @__PURE__ */ jsxs("div", { className: "select-none animate-in", children: [
|
|
47371
48739
|
/* @__PURE__ */ jsxs(
|
|
47372
48740
|
"div",
|
|
47373
48741
|
{
|
|
48742
|
+
"aria-current": isCurrentVideo ? "true" : void 0,
|
|
48743
|
+
"data-qa-clips-row-clip-id": node.type === "video" ? nodeClipId : void 0,
|
|
48744
|
+
"data-qa-clips-row-category-id": node.type === "video" ? node.categoryId : void 0,
|
|
47374
48745
|
className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-blue-50 to-blue-50/60 border border-blue-200/50 shadow-md shadow-blue-100/20" : ""}`} ${node.type === "video" ? "ml-6" : ""}`,
|
|
47375
48746
|
onClick: () => handleNodeClick(node),
|
|
47376
48747
|
children: [
|
|
@@ -47406,7 +48777,7 @@ var FileManagerFilters = ({
|
|
|
47406
48777
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
|
|
47407
48778
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
47408
48779
|
/* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-blue-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
|
|
47409
|
-
node.type === "category" && (node.subtitle ||
|
|
48780
|
+
node.type === "category" && (node.subtitle || categoriesForTree.find((c) => c.id === node.id)?.description) && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle || categoriesForTree.find((c) => c.id === node.id)?.description }),
|
|
47410
48781
|
node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
|
|
47411
48782
|
node.type === "video" && (node.severity || node.categoryId === "cycle_completion" || node.categoryId === "idle_time" || node.categoryId === "low_value" || node.categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) && /* @__PURE__ */ jsx("div", { className: "text-xs mt-0.5 font-medium", children: node.categoryId === "idle_time" ? (
|
|
47412
48783
|
// Show root cause label for idle time clips (text only, icon is on the left)
|
|
@@ -47442,7 +48813,7 @@ var FileManagerFilters = ({
|
|
|
47442
48813
|
})()
|
|
47443
48814
|
) })
|
|
47444
48815
|
] }),
|
|
47445
|
-
node.count !== void 0 && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children:
|
|
48816
|
+
node.count !== void 0 && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children: isCountUnknown ? /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : node.count }) })
|
|
47446
48817
|
] })
|
|
47447
48818
|
]
|
|
47448
48819
|
}
|
|
@@ -47453,6 +48824,7 @@ var FileManagerFilters = ({
|
|
|
47453
48824
|
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
47454
48825
|
"Loading clips..."
|
|
47455
48826
|
] }) }),
|
|
48827
|
+
showScopedEmptyState && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center text-sm text-slate-500", children: "No clips found" }),
|
|
47456
48828
|
isLoadMoreLoading && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
|
|
47457
48829
|
/* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
|
|
47458
48830
|
"Loading more clips..."
|
|
@@ -47467,7 +48839,7 @@ var FileManagerFilters = ({
|
|
|
47467
48839
|
className: "w-full py-2 px-3 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors duration-200 text-center",
|
|
47468
48840
|
children: [
|
|
47469
48841
|
"Load more clips (",
|
|
47470
|
-
(
|
|
48842
|
+
Math.max(0, totalForLoadMore - getAvailableClipMetadata(node.id).length),
|
|
47471
48843
|
" remaining)"
|
|
47472
48844
|
]
|
|
47473
48845
|
}
|
|
@@ -47530,6 +48902,8 @@ var FileManagerFilters = ({
|
|
|
47530
48902
|
e.stopPropagation();
|
|
47531
48903
|
setStartTime("");
|
|
47532
48904
|
setEndTime("");
|
|
48905
|
+
setActiveInitialTimeFilter(null);
|
|
48906
|
+
setScopedCategoryTotals({});
|
|
47533
48907
|
setIsTimeFilterActive(false);
|
|
47534
48908
|
},
|
|
47535
48909
|
className: "rounded-full p-0.5 transition-colors hover:bg-blue-100",
|
|
@@ -47663,6 +49037,8 @@ var FileManagerFilters = ({
|
|
|
47663
49037
|
onClick: () => {
|
|
47664
49038
|
setStartTime("");
|
|
47665
49039
|
setEndTime("");
|
|
49040
|
+
setActiveInitialTimeFilter(null);
|
|
49041
|
+
setScopedCategoryTotals({});
|
|
47666
49042
|
setStartSearchTerm("");
|
|
47667
49043
|
setEndSearchTerm("");
|
|
47668
49044
|
setIsTimeFilterActive(false);
|
|
@@ -47751,8 +49127,13 @@ var FileManagerFilters = ({
|
|
|
47751
49127
|
)
|
|
47752
49128
|
] }),
|
|
47753
49129
|
/* @__PURE__ */ jsxs("div", { className: "px-4 py-3 flex-1 min-h-0 overflow-y-auto scrollbar-thin", children: [
|
|
47754
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-2", children:
|
|
47755
|
-
|
|
49130
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: displayedFilterTree.map((node) => renderNode(node)) }),
|
|
49131
|
+
displayedFilterTree.length === 0 && isChartHandoffLoading && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
49132
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx(Loader2, { className: "h-8 w-8 animate-spin text-blue-500" }) }),
|
|
49133
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "Loading clips..." }),
|
|
49134
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Finding clips from the selected hour" })
|
|
49135
|
+
] }),
|
|
49136
|
+
displayedFilterTree.length === 0 && !isChartHandoffLoading && (startTime || endTime) && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
47756
49137
|
/* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(Clock, { className: "h-12 w-12 mx-auto" }) }),
|
|
47757
49138
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips found" }),
|
|
47758
49139
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 mb-4", children: "No clips match the selected time range" }),
|
|
@@ -47762,6 +49143,8 @@ var FileManagerFilters = ({
|
|
|
47762
49143
|
onClick: () => {
|
|
47763
49144
|
setStartTime("");
|
|
47764
49145
|
setEndTime("");
|
|
49146
|
+
setActiveInitialTimeFilter(null);
|
|
49147
|
+
setScopedCategoryTotals({});
|
|
47765
49148
|
setIsTimeFilterActive(false);
|
|
47766
49149
|
},
|
|
47767
49150
|
className: "inline-flex items-center px-4 py-2 bg-blue-50 text-blue-600 text-sm font-medium rounded-lg hover:bg-blue-100 transition-colors duration-200",
|
|
@@ -47769,12 +49152,12 @@ var FileManagerFilters = ({
|
|
|
47769
49152
|
}
|
|
47770
49153
|
)
|
|
47771
49154
|
] }),
|
|
47772
|
-
|
|
49155
|
+
displayedFilterTree.length === 0 && !startTime && !endTime && categories.length === 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
47773
49156
|
/* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(HelpCircle, { className: "h-12 w-12 mx-auto" }) }),
|
|
47774
49157
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clip types available" }),
|
|
47775
49158
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Loading clip categories..." })
|
|
47776
49159
|
] }),
|
|
47777
|
-
|
|
49160
|
+
displayedFilterTree.length === 0 && !startTime && !endTime && categories.length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
47778
49161
|
/* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(Play, { className: "h-12 w-12 mx-auto" }) }),
|
|
47779
49162
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips available" }),
|
|
47780
49163
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "No clips found for the selected time period" })
|
|
@@ -48181,6 +49564,65 @@ function useClipsRealtimeUpdates({
|
|
|
48181
49564
|
}
|
|
48182
49565
|
var LOW_EFFICIENCY_CATEGORY_ID = "recent_flow_red_streak";
|
|
48183
49566
|
var LOW_EFFICIENCY_AI_SUMMARY_ENABLED = process.env.NEXT_PUBLIC_LOW_EFFICIENCY_AI_SUMMARY_ENABLED === "true";
|
|
49567
|
+
var timeValueToMinutes2 = (value) => {
|
|
49568
|
+
const [hourValue, minuteValue] = value.substring(0, 5).split(":").map(Number);
|
|
49569
|
+
if (!Number.isInteger(hourValue) || !Number.isInteger(minuteValue) || hourValue < 0 || hourValue > 23 || minuteValue < 0 || minuteValue > 59) {
|
|
49570
|
+
return null;
|
|
49571
|
+
}
|
|
49572
|
+
return hourValue * 60 + minuteValue;
|
|
49573
|
+
};
|
|
49574
|
+
var isMinuteInTimeWindow2 = (minute, startValue, endValue) => {
|
|
49575
|
+
const startMinute = timeValueToMinutes2(startValue);
|
|
49576
|
+
const endMinute = timeValueToMinutes2(endValue);
|
|
49577
|
+
if (startMinute === null || endMinute === null) {
|
|
49578
|
+
return true;
|
|
49579
|
+
}
|
|
49580
|
+
return endMinute > startMinute ? minute >= startMinute && minute < endMinute : minute >= startMinute || minute < endMinute;
|
|
49581
|
+
};
|
|
49582
|
+
var CHART_HANDOFF_CATEGORY_FALLBACKS = {
|
|
49583
|
+
cycle_completion: {
|
|
49584
|
+
label: "Cycle Completion",
|
|
49585
|
+
description: "Successfully completed production cycles",
|
|
49586
|
+
color: "blue",
|
|
49587
|
+
icon: "check-circle"
|
|
49588
|
+
},
|
|
49589
|
+
"fast-cycles": {
|
|
49590
|
+
label: "Fast Cycles",
|
|
49591
|
+
description: "Fastest cycle clips",
|
|
49592
|
+
color: "green",
|
|
49593
|
+
icon: "trending-up"
|
|
49594
|
+
},
|
|
49595
|
+
"slow-cycles": {
|
|
49596
|
+
label: "Slow Cycles",
|
|
49597
|
+
description: "Slowest cycle clips",
|
|
49598
|
+
color: "red",
|
|
49599
|
+
icon: "trending-down"
|
|
49600
|
+
},
|
|
49601
|
+
idle_time: {
|
|
49602
|
+
label: "Idle Time",
|
|
49603
|
+
description: "Low value activities and idle moments",
|
|
49604
|
+
color: "amber",
|
|
49605
|
+
icon: "clock"
|
|
49606
|
+
},
|
|
49607
|
+
recent_flow_red_streak: {
|
|
49608
|
+
label: "Low moments",
|
|
49609
|
+
description: "Moments of low efficiency",
|
|
49610
|
+
color: "rose",
|
|
49611
|
+
icon: "alert-triangle"
|
|
49612
|
+
},
|
|
49613
|
+
worst_cycle_time: {
|
|
49614
|
+
label: "Slow Cycles",
|
|
49615
|
+
description: "Slowest cycle clips",
|
|
49616
|
+
color: "red",
|
|
49617
|
+
icon: "trending-down"
|
|
49618
|
+
},
|
|
49619
|
+
best_cycle_time: {
|
|
49620
|
+
label: "Fast Cycles",
|
|
49621
|
+
description: "Fastest cycle clips",
|
|
49622
|
+
color: "green",
|
|
49623
|
+
icon: "trending-up"
|
|
49624
|
+
}
|
|
49625
|
+
};
|
|
48184
49626
|
var parseFiniteNumber2 = (value) => {
|
|
48185
49627
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
48186
49628
|
return value;
|
|
@@ -48228,6 +49670,7 @@ var BottlenecksContent = ({
|
|
|
48228
49670
|
ticketId,
|
|
48229
49671
|
prefetchedPercentileCounts,
|
|
48230
49672
|
lowMomentsPrefetch,
|
|
49673
|
+
initialTimePrefetch,
|
|
48231
49674
|
initialTimeFilter
|
|
48232
49675
|
}) => {
|
|
48233
49676
|
console.log("\u{1F3AB} [BottlenecksContent] Rendered with ticketId:", ticketId || "NONE", "workspaceId:", workspaceId, "date:", date, "shift:", shift);
|
|
@@ -48440,6 +49883,108 @@ var BottlenecksContent = ({
|
|
|
48440
49883
|
enabled: isEffectiveShiftReady
|
|
48441
49884
|
});
|
|
48442
49885
|
const isLowMomentsCategoryAvailable = useMemo(() => Array.isArray(clipTypes) && clipTypes.some((type) => type?.type === LOW_EFFICIENCY_CATEGORY_ID || type?.id === LOW_EFFICIENCY_CATEGORY_ID), [clipTypes]);
|
|
49886
|
+
const requestedInitialCategoryCandidates = useMemo(() => {
|
|
49887
|
+
const requestedCategories = [
|
|
49888
|
+
...Array.isArray(initialTimeFilter?.categoryIds) ? initialTimeFilter.categoryIds : [],
|
|
49889
|
+
initialTimeFilter?.categoryId
|
|
49890
|
+
];
|
|
49891
|
+
return Array.from(
|
|
49892
|
+
new Set(
|
|
49893
|
+
requestedCategories.filter((category) => Boolean(category)).map((category) => category.trim()).filter(Boolean)
|
|
49894
|
+
)
|
|
49895
|
+
);
|
|
49896
|
+
}, [initialTimeFilter?.categoryId, initialTimeFilter?.categoryIds]);
|
|
49897
|
+
const hasInitialTimeHandoff = Boolean(initialTimeFilter?.startTime && initialTimeFilter?.endTime);
|
|
49898
|
+
const initialTimeHandoffCategorySet = useMemo(() => new Set(requestedInitialCategoryCandidates), [requestedInitialCategoryCandidates]);
|
|
49899
|
+
const isInitialTimeHandoffCategory = useCallback((categoryId) => Boolean(
|
|
49900
|
+
hasInitialTimeHandoff && categoryId && (initialTimeHandoffCategorySet.size === 0 || initialTimeHandoffCategorySet.has(categoryId))
|
|
49901
|
+
), [hasInitialTimeHandoff, initialTimeHandoffCategorySet]);
|
|
49902
|
+
const isTimestampInInitialTimeHandoff = useCallback((timestamp) => {
|
|
49903
|
+
if (!hasInitialTimeHandoff || !initialTimeFilter?.startTime || !initialTimeFilter?.endTime || !timestamp) {
|
|
49904
|
+
return true;
|
|
49905
|
+
}
|
|
49906
|
+
try {
|
|
49907
|
+
const clipDate = new Date(timestamp);
|
|
49908
|
+
if (Number.isNaN(clipDate.getTime())) {
|
|
49909
|
+
return false;
|
|
49910
|
+
}
|
|
49911
|
+
const clipParts = new Intl.DateTimeFormat("en-US", {
|
|
49912
|
+
hour12: false,
|
|
49913
|
+
hour: "2-digit",
|
|
49914
|
+
minute: "2-digit",
|
|
49915
|
+
timeZone: initialTimeFilter.timezone || timezone
|
|
49916
|
+
}).formatToParts(clipDate);
|
|
49917
|
+
const hourValue = clipParts.find((part) => part.type === "hour")?.value;
|
|
49918
|
+
const minuteValue = clipParts.find((part) => part.type === "minute")?.value;
|
|
49919
|
+
const clipMinute = timeValueToMinutes2(`${hourValue}:${minuteValue}`);
|
|
49920
|
+
return clipMinute === null ? false : isMinuteInTimeWindow2(clipMinute, initialTimeFilter.startTime, initialTimeFilter.endTime);
|
|
49921
|
+
} catch {
|
|
49922
|
+
return false;
|
|
49923
|
+
}
|
|
49924
|
+
}, [
|
|
49925
|
+
hasInitialTimeHandoff,
|
|
49926
|
+
initialTimeFilter?.endTime,
|
|
49927
|
+
initialTimeFilter?.startTime,
|
|
49928
|
+
initialTimeFilter?.timezone,
|
|
49929
|
+
timezone
|
|
49930
|
+
]);
|
|
49931
|
+
const resolvedInitialCategory = useMemo(() => resolveInitialClipCategory(requestedInitialCategoryCandidates, clipTypes, dynamicCounts), [clipTypes, dynamicCounts, requestedInitialCategoryCandidates]);
|
|
49932
|
+
const initialTimeFilterKey = useMemo(() => hasInitialTimeHandoff ? [
|
|
49933
|
+
initialTimeFilter?.startTime,
|
|
49934
|
+
initialTimeFilter?.endTime,
|
|
49935
|
+
initialTimeFilter?.timezone || timezone,
|
|
49936
|
+
initialTimeFilter?.categoryId || "",
|
|
49937
|
+
...initialTimeFilter?.categoryIds || []
|
|
49938
|
+
].join("|") : "", [
|
|
49939
|
+
hasInitialTimeHandoff,
|
|
49940
|
+
initialTimeFilter?.categoryId,
|
|
49941
|
+
initialTimeFilter?.categoryIds,
|
|
49942
|
+
initialTimeFilter?.endTime,
|
|
49943
|
+
initialTimeFilter?.startTime,
|
|
49944
|
+
initialTimeFilter?.timezone,
|
|
49945
|
+
timezone
|
|
49946
|
+
]);
|
|
49947
|
+
const preferredInitialTimeCategory = resolvedInitialCategory || requestedInitialCategoryCandidates[0] || "";
|
|
49948
|
+
useEffect(() => {
|
|
49949
|
+
if (!initialTimeFilterKey) {
|
|
49950
|
+
return;
|
|
49951
|
+
}
|
|
49952
|
+
setPendingVideo(null);
|
|
49953
|
+
setAllVideos([]);
|
|
49954
|
+
setCurrentIndex(0);
|
|
49955
|
+
setCurrentClipId(null);
|
|
49956
|
+
currentClipIdRef.current = null;
|
|
49957
|
+
setCurrentMetadataIndex(0);
|
|
49958
|
+
currentMetadataIndexRef.current = 0;
|
|
49959
|
+
setCurrentPosition(0);
|
|
49960
|
+
currentPositionRef.current = 0;
|
|
49961
|
+
setCurrentTotal(0);
|
|
49962
|
+
currentTotalRef.current = 0;
|
|
49963
|
+
setCategoryMetadata([]);
|
|
49964
|
+
categoryMetadataRef.current = [];
|
|
49965
|
+
setCategoryMetadataCategoryId(null);
|
|
49966
|
+
setCategoryMetadataSort(null);
|
|
49967
|
+
clearRetryTimeout();
|
|
49968
|
+
navigationLockRef.current = false;
|
|
49969
|
+
loadingCategoryRef.current = null;
|
|
49970
|
+
if (loadingTimeoutRef.current) {
|
|
49971
|
+
clearTimeout(loadingTimeoutRef.current);
|
|
49972
|
+
loadingTimeoutRef.current = null;
|
|
49973
|
+
}
|
|
49974
|
+
setIsTransitioning(false);
|
|
49975
|
+
setIsNavigating(false);
|
|
49976
|
+
setIsCategoryLoading(false);
|
|
49977
|
+
if (preferredInitialTimeCategory) {
|
|
49978
|
+
setInitialFilter(preferredInitialTimeCategory);
|
|
49979
|
+
updateActiveFilter(preferredInitialTimeCategory);
|
|
49980
|
+
previousFilterRef.current = "";
|
|
49981
|
+
}
|
|
49982
|
+
}, [
|
|
49983
|
+
clearRetryTimeout,
|
|
49984
|
+
initialTimeFilterKey,
|
|
49985
|
+
preferredInitialTimeCategory,
|
|
49986
|
+
updateActiveFilter
|
|
49987
|
+
]);
|
|
48443
49988
|
console.log("[BottlenecksContent] Clip types data:", {
|
|
48444
49989
|
clipTypes,
|
|
48445
49990
|
clipTypesLength: clipTypes?.length,
|
|
@@ -48487,6 +50032,15 @@ var BottlenecksContent = ({
|
|
|
48487
50032
|
}
|
|
48488
50033
|
});
|
|
48489
50034
|
useEffect(() => {
|
|
50035
|
+
if (resolvedInitialCategory) {
|
|
50036
|
+
if (initialFilter !== resolvedInitialCategory) {
|
|
50037
|
+
setInitialFilter(resolvedInitialCategory);
|
|
50038
|
+
}
|
|
50039
|
+
if (activeFilterRef.current !== resolvedInitialCategory) {
|
|
50040
|
+
updateActiveFilter(resolvedInitialCategory);
|
|
50041
|
+
}
|
|
50042
|
+
return;
|
|
50043
|
+
}
|
|
48490
50044
|
if (initialFilter) {
|
|
48491
50045
|
return;
|
|
48492
50046
|
}
|
|
@@ -48503,7 +50057,15 @@ var BottlenecksContent = ({
|
|
|
48503
50057
|
activeFilterRef.current = defaultCategory;
|
|
48504
50058
|
return;
|
|
48505
50059
|
}
|
|
48506
|
-
}, [
|
|
50060
|
+
}, [
|
|
50061
|
+
clipTypes,
|
|
50062
|
+
dynamicCounts,
|
|
50063
|
+
defaultCategory,
|
|
50064
|
+
initialFilter,
|
|
50065
|
+
isLowMomentsCategoryAvailable,
|
|
50066
|
+
resolvedInitialCategory,
|
|
50067
|
+
updateActiveFilter
|
|
50068
|
+
]);
|
|
48507
50069
|
const mergedCounts = useMemo(() => {
|
|
48508
50070
|
return { ...dynamicCounts };
|
|
48509
50071
|
}, [dynamicCounts]);
|
|
@@ -48552,6 +50114,9 @@ var BottlenecksContent = ({
|
|
|
48552
50114
|
const loadFirstVideoForCategory = useCallback(async (category) => {
|
|
48553
50115
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current || !isEffectiveShiftReady) return;
|
|
48554
50116
|
const targetCategory = category || activeFilterRef.current;
|
|
50117
|
+
if (targetCategory === "fast-cycles" || targetCategory === "slow-cycles") {
|
|
50118
|
+
return;
|
|
50119
|
+
}
|
|
48555
50120
|
const operationKey = `loadFirstVideo:${targetCategory}:${effectiveDateString}:${effectiveShiftId}`;
|
|
48556
50121
|
if (loadingCategoryRef.current === targetCategory || fetchInProgressRef.current.has(operationKey)) {
|
|
48557
50122
|
console.log(`[BottlenecksContent] Load first video already in progress for ${targetCategory}`);
|
|
@@ -48997,8 +50562,9 @@ var BottlenecksContent = ({
|
|
|
48997
50562
|
});
|
|
48998
50563
|
}
|
|
48999
50564
|
setVisibleCategoryMetadata(categoryId, cachedMetadata);
|
|
49000
|
-
|
|
49001
|
-
|
|
50565
|
+
const cachedAutoloadCandidates = isInitialTimeHandoffCategory(categoryId) ? cachedMetadata.filter((clip) => isTimestampInInitialTimeHandoff(clip.clip_timestamp || clip.creation_timestamp || clip.timestamp)) : cachedMetadata;
|
|
50566
|
+
if (autoLoadFirstVideo && cachedAutoloadCandidates.length > 0 && s3ClipsService) {
|
|
50567
|
+
const firstClipMeta = cachedAutoloadCandidates[0];
|
|
49002
50568
|
const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
|
|
49003
50569
|
const prefetchedFirstVideo = matchingLowMomentsPrefetch?.firstVideo ?? null;
|
|
49004
50570
|
try {
|
|
@@ -49037,7 +50603,10 @@ var BottlenecksContent = ({
|
|
|
49037
50603
|
endDate: `${resolvedDate}T23:59:59Z`,
|
|
49038
50604
|
percentile: 10,
|
|
49039
50605
|
shiftId: effectiveShiftId,
|
|
49040
|
-
limit: 100
|
|
50606
|
+
limit: isInitialTimeHandoffCategory(categoryId) ? 500 : 100,
|
|
50607
|
+
startTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.startTime : void 0,
|
|
50608
|
+
endTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.endTime : void 0,
|
|
50609
|
+
timeFilterTimezone: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.timezone || timezone : void 0
|
|
49041
50610
|
}),
|
|
49042
50611
|
redirectReason: "session_expired"
|
|
49043
50612
|
});
|
|
@@ -49054,10 +50623,13 @@ var BottlenecksContent = ({
|
|
|
49054
50623
|
shift: effectiveShiftId,
|
|
49055
50624
|
category: categoryId,
|
|
49056
50625
|
page: 1,
|
|
49057
|
-
limit: 100,
|
|
49058
|
-
knownTotal: mergedCounts[categoryId] ?? null,
|
|
50626
|
+
limit: isInitialTimeHandoffCategory(categoryId) ? 500 : 100,
|
|
50627
|
+
knownTotal: isInitialTimeHandoffCategory(categoryId) ? null : mergedCounts[categoryId] ?? null,
|
|
49059
50628
|
snapshotDateTime,
|
|
49060
50629
|
snapshotClipId,
|
|
50630
|
+
startTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.startTime : void 0,
|
|
50631
|
+
endTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.endTime : void 0,
|
|
50632
|
+
timeFilterTimezone: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.timezone || timezone : void 0,
|
|
49061
50633
|
sort: categoryId === LOW_EFFICIENCY_CATEGORY_ID ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
|
|
49062
50634
|
}),
|
|
49063
50635
|
redirectReason: "session_expired"
|
|
@@ -49070,7 +50642,8 @@ var BottlenecksContent = ({
|
|
|
49070
50642
|
if (categoryData.clips && isMountedRef.current) {
|
|
49071
50643
|
let metadataClips;
|
|
49072
50644
|
if (isPercentileCategory(categoryId)) {
|
|
49073
|
-
|
|
50645
|
+
const sortedPercentileClips = sortPercentileCycleClipsForDisplay(categoryId, categoryData.clips);
|
|
50646
|
+
metadataClips = sortedPercentileClips.map((clip, index) => ({
|
|
49074
50647
|
id: clip.id,
|
|
49075
50648
|
clipId: clip.id,
|
|
49076
50649
|
clip_timestamp: clip.creation_timestamp || clip.timestamp,
|
|
@@ -49117,8 +50690,9 @@ var BottlenecksContent = ({
|
|
|
49117
50690
|
}));
|
|
49118
50691
|
setVisibleCategoryMetadata(categoryId, metadataClips);
|
|
49119
50692
|
console.log(`[BottlenecksContent] Loaded metadata for ${categoryId}: ${metadataClips.length} clips`);
|
|
49120
|
-
|
|
49121
|
-
|
|
50693
|
+
const autoloadCandidates = isInitialTimeHandoffCategory(categoryId) ? metadataClips.filter((clip) => isTimestampInInitialTimeHandoff(clip.clip_timestamp || clip.creation_timestamp || clip.timestamp)) : metadataClips;
|
|
50694
|
+
if (autoLoadFirstVideo && autoloadCandidates.length > 0 && s3ClipsService) {
|
|
50695
|
+
const firstClipMeta = autoloadCandidates[0];
|
|
49122
50696
|
const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
|
|
49123
50697
|
try {
|
|
49124
50698
|
const video = await s3ClipsService.getClipById(firstClipId);
|
|
@@ -49152,7 +50726,7 @@ var BottlenecksContent = ({
|
|
|
49152
50726
|
setIsCategoryLoading(false);
|
|
49153
50727
|
}
|
|
49154
50728
|
}
|
|
49155
|
-
}, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata, lowMomentsPrefetch, applyPrefetchedFirstVideo, applyMetadataSnapshot, isLowMomentsCategoryAvailable]);
|
|
50729
|
+
}, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata, lowMomentsPrefetch, applyPrefetchedFirstVideo, applyMetadataSnapshot, isLowMomentsCategoryAvailable, isInitialTimeHandoffCategory, isTimestampInInitialTimeHandoff, initialTimeFilter?.endTime, initialTimeFilter?.startTime, initialTimeFilter?.timezone, timezone]);
|
|
49156
50730
|
useEffect(() => {
|
|
49157
50731
|
if (activeFilter !== LOW_EFFICIENCY_CATEGORY_ID || !isLowMomentsCategoryAvailable) {
|
|
49158
50732
|
return;
|
|
@@ -49184,6 +50758,37 @@ var BottlenecksContent = ({
|
|
|
49184
50758
|
applyMetadataSnapshot,
|
|
49185
50759
|
isLowMomentsCategoryAvailable
|
|
49186
50760
|
]);
|
|
50761
|
+
useEffect(() => {
|
|
50762
|
+
if (!initialTimeFilter?.startTime || !initialTimeFilter?.endTime || !initialTimePrefetch || initialTimePrefetch.loading || initialTimePrefetch.categoryId !== activeFilter) {
|
|
50763
|
+
return;
|
|
50764
|
+
}
|
|
50765
|
+
if (initialTimePrefetch.metadata.length > 0) {
|
|
50766
|
+
applyMetadataSnapshot(
|
|
50767
|
+
initialTimePrefetch.categoryId,
|
|
50768
|
+
initialTimePrefetch.metadata,
|
|
50769
|
+
initialTimePrefetch.total
|
|
50770
|
+
);
|
|
50771
|
+
}
|
|
50772
|
+
if (initialTimePrefetch.firstVideo && isTimestampInInitialTimeHandoff(
|
|
50773
|
+
initialTimePrefetch.firstVideo.creation_timestamp || initialTimePrefetch.firstVideo.timestamp
|
|
50774
|
+
)) {
|
|
50775
|
+
applyPrefetchedFirstVideo(initialTimePrefetch.firstVideo);
|
|
50776
|
+
if (isMountedRef.current) {
|
|
50777
|
+
setIsCategoryLoading(false);
|
|
50778
|
+
setIsInitialLoading(false);
|
|
50779
|
+
setIsTransitioning(false);
|
|
50780
|
+
setIsNavigating(false);
|
|
50781
|
+
}
|
|
50782
|
+
}
|
|
50783
|
+
}, [
|
|
50784
|
+
activeFilter,
|
|
50785
|
+
applyMetadataSnapshot,
|
|
50786
|
+
applyPrefetchedFirstVideo,
|
|
50787
|
+
initialTimeFilter?.endTime,
|
|
50788
|
+
initialTimeFilter?.startTime,
|
|
50789
|
+
initialTimePrefetch,
|
|
50790
|
+
isTimestampInInitialTimeHandoff
|
|
50791
|
+
]);
|
|
49187
50792
|
useEffect(() => {
|
|
49188
50793
|
if (previousIdleClipSortRef.current === idleClipSort) {
|
|
49189
50794
|
return;
|
|
@@ -49223,7 +50828,7 @@ var BottlenecksContent = ({
|
|
|
49223
50828
|
currentTotalRef.current = total;
|
|
49224
50829
|
setCurrentTotal(total);
|
|
49225
50830
|
previousFilterRef.current = activeFilter;
|
|
49226
|
-
const metadataLoadPlan = getCategoryMetadataLoadPlanForFilterChange({
|
|
50831
|
+
const metadataLoadPlan = isInitialTimeHandoffCategory(activeFilter) ? { shouldLoad: false, autoLoadFirstVideo: false } : getCategoryMetadataLoadPlanForFilterChange({
|
|
49227
50832
|
activeFilter,
|
|
49228
50833
|
currentClipId,
|
|
49229
50834
|
categoryTotal: total
|
|
@@ -49247,7 +50852,7 @@ var BottlenecksContent = ({
|
|
|
49247
50852
|
}
|
|
49248
50853
|
}
|
|
49249
50854
|
}
|
|
49250
|
-
}, [activeFilter, allVideos, mergedCounts, currentClipId, loadCategoryMetadata]);
|
|
50855
|
+
}, [activeFilter, allVideos, mergedCounts, currentClipId, loadCategoryMetadata, isInitialTimeHandoffCategory]);
|
|
49251
50856
|
useEffect(() => {
|
|
49252
50857
|
if (!currentClipId || activeFilter === "all") {
|
|
49253
50858
|
return;
|
|
@@ -49275,10 +50880,19 @@ var BottlenecksContent = ({
|
|
|
49275
50880
|
console.warn("[BottlenecksContent] Error disposing player:", e);
|
|
49276
50881
|
}
|
|
49277
50882
|
}
|
|
49278
|
-
loadingTimeoutRef.current
|
|
50883
|
+
if (loadingTimeoutRef.current) {
|
|
50884
|
+
clearTimeout(loadingTimeoutRef.current);
|
|
50885
|
+
loadingTimeoutRef.current = null;
|
|
50886
|
+
}
|
|
50887
|
+
const loadingTimeout = setTimeout(() => {
|
|
50888
|
+
if (loadingTimeoutRef.current !== loadingTimeout) {
|
|
50889
|
+
return;
|
|
50890
|
+
}
|
|
50891
|
+
loadingTimeoutRef.current = null;
|
|
49279
50892
|
console.warn("[BottlenecksContent] Loading timeout - clearing stuck loading state");
|
|
49280
50893
|
clearLoadingState();
|
|
49281
50894
|
}, 2e3);
|
|
50895
|
+
loadingTimeoutRef.current = loadingTimeout;
|
|
49282
50896
|
if (activeFilterRef.current !== categoryId) {
|
|
49283
50897
|
updateActiveFilter(categoryId);
|
|
49284
50898
|
}
|
|
@@ -49298,17 +50912,20 @@ var BottlenecksContent = ({
|
|
|
49298
50912
|
setCurrentClipId(clipId);
|
|
49299
50913
|
setAllVideos([video]);
|
|
49300
50914
|
setCurrentIndex(0);
|
|
50915
|
+
clearLoadingState();
|
|
49301
50916
|
} else {
|
|
49302
50917
|
throw new Error(`Failed to load video data for clip ${clipId}`);
|
|
49303
50918
|
}
|
|
49304
50919
|
await metadataPromise;
|
|
49305
50920
|
let metadataArray = categoryMetadataRef.current;
|
|
49306
|
-
const
|
|
49307
|
-
|
|
50921
|
+
const getMetadataClipId = (clip) => clip?.clipId || clip?.id;
|
|
50922
|
+
const metadataHasClip = (clips) => clips.some((clip) => getMetadataClipId(clip) === clipId);
|
|
50923
|
+
const fallbackHasClip = fallbackMetadata?.some((clip) => getMetadataClipId(clip) === clipId);
|
|
50924
|
+
if ((metadataArray.length === 0 || !metadataHasClip(metadataArray)) && fallbackHasClip) {
|
|
49308
50925
|
applyMetadataSnapshot(categoryId, fallbackMetadata, fallbackTotal);
|
|
49309
50926
|
metadataArray = fallbackMetadata;
|
|
49310
50927
|
}
|
|
49311
|
-
if (metadataArray.length === 0 || !metadataArray
|
|
50928
|
+
if (metadataArray.length === 0 || !metadataHasClip(metadataArray)) {
|
|
49312
50929
|
if (!fallbackHasClip) {
|
|
49313
50930
|
console.warn(`[BottlenecksContent] Clip ${clipId} not found in metadata for ${categoryId} (cache hit: ${metadataArray.length > 0}) - forcing refresh`);
|
|
49314
50931
|
await loadCategoryMetadata(categoryId, false, true);
|
|
@@ -49327,7 +50944,7 @@ var BottlenecksContent = ({
|
|
|
49327
50944
|
}
|
|
49328
50945
|
return;
|
|
49329
50946
|
}
|
|
49330
|
-
const clickedClipIndex = metadataArray.findIndex((clip) => clip
|
|
50947
|
+
const clickedClipIndex = metadataArray.findIndex((clip) => getMetadataClipId(clip) === clipId);
|
|
49331
50948
|
if (clickedClipIndex === -1) {
|
|
49332
50949
|
console.warn(`[BottlenecksContent] Clip ${clipId} not found after metadata refresh`);
|
|
49333
50950
|
if (!shouldUseMetadataNavigation(categoryId)) {
|
|
@@ -49715,6 +51332,32 @@ var BottlenecksContent = ({
|
|
|
49715
51332
|
}
|
|
49716
51333
|
return filteredVideos[currentIndex];
|
|
49717
51334
|
}, [filteredVideos, currentIndex]);
|
|
51335
|
+
const currentVideoMatchesInitialTimeHandoff = useMemo(() => {
|
|
51336
|
+
if (!hasInitialTimeHandoff) {
|
|
51337
|
+
return true;
|
|
51338
|
+
}
|
|
51339
|
+
if (!currentVideo) {
|
|
51340
|
+
return false;
|
|
51341
|
+
}
|
|
51342
|
+
if (!isInitialTimeHandoffCategory(activeFilter) || !isInitialTimeHandoffCategory(currentVideo.type)) {
|
|
51343
|
+
return false;
|
|
51344
|
+
}
|
|
51345
|
+
return isTimestampInInitialTimeHandoff(
|
|
51346
|
+
currentVideo.creation_timestamp || currentVideo.timestamp || currentVideo.clip_end_time || currentVideo.clip_start_time
|
|
51347
|
+
);
|
|
51348
|
+
}, [
|
|
51349
|
+
activeFilter,
|
|
51350
|
+
currentVideo,
|
|
51351
|
+
hasInitialTimeHandoff,
|
|
51352
|
+
isInitialTimeHandoffCategory,
|
|
51353
|
+
isTimestampInInitialTimeHandoff
|
|
51354
|
+
]);
|
|
51355
|
+
const shouldHoldInitialTimeHandoffVideo = Boolean(
|
|
51356
|
+
hasInitialTimeHandoff && !currentVideoMatchesInitialTimeHandoff && (isCategoryLoading || filteredVideos.length > 0 || (mergedCounts[activeFilter] || 0) > 0)
|
|
51357
|
+
);
|
|
51358
|
+
const canRenderCurrentVideo = Boolean(
|
|
51359
|
+
filteredVideos.length > 0 && currentVideo && !isFullscreen && !shouldHoldInitialTimeHandoffVideo
|
|
51360
|
+
);
|
|
49718
51361
|
const currentLowEfficiencyClipId = currentVideo?.id || currentClipId || null;
|
|
49719
51362
|
const isCurrentLowEfficiencyClip = Boolean(
|
|
49720
51363
|
currentVideo?.type === "recent_flow_red_streak" || currentVideo?.red_flow_timeline
|
|
@@ -49881,11 +51524,111 @@ var BottlenecksContent = ({
|
|
|
49881
51524
|
}
|
|
49882
51525
|
return currentPosition;
|
|
49883
51526
|
}, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
|
|
49884
|
-
const
|
|
51527
|
+
const initialTimePrefetchedMetadata = useMemo(() => {
|
|
51528
|
+
if (!initialTimeFilter?.startTime || !initialTimeFilter?.endTime || !initialTimePrefetch || initialTimePrefetch.loading) {
|
|
51529
|
+
return void 0;
|
|
51530
|
+
}
|
|
51531
|
+
if (initialTimePrefetch.metadataByCategory) {
|
|
51532
|
+
return initialTimePrefetch.metadataByCategory;
|
|
51533
|
+
}
|
|
51534
|
+
if (initialTimePrefetch.categoryId === activeFilter && initialTimePrefetch.metadata.length > 0) {
|
|
51535
|
+
return { [activeFilter]: initialTimePrefetch.metadata };
|
|
51536
|
+
}
|
|
51537
|
+
return void 0;
|
|
51538
|
+
}, [
|
|
49885
51539
|
activeFilter,
|
|
51540
|
+
initialTimePrefetch,
|
|
51541
|
+
initialTimeFilter?.endTime,
|
|
51542
|
+
initialTimeFilter?.startTime
|
|
51543
|
+
]);
|
|
51544
|
+
const prefetchedExplorerMetadata = useMemo(() => {
|
|
51545
|
+
if (initialTimePrefetchedMetadata) {
|
|
51546
|
+
return initialTimePrefetchedMetadata;
|
|
51547
|
+
}
|
|
51548
|
+
if (activeFilter === LOW_EFFICIENCY_CATEGORY_ID && isLowMomentsCategoryAvailable && lowMomentsPrefetch?.key?.startsWith(`${LOW_EFFICIENCY_CATEGORY_ID}-${workspaceId}-${effectiveDateString}-${effectiveShiftId}-`) && !lowMomentsPrefetch.loading && lowMomentsPrefetch.metadata.length > 0) {
|
|
51549
|
+
return { [LOW_EFFICIENCY_CATEGORY_ID]: lowMomentsPrefetch.metadata };
|
|
51550
|
+
}
|
|
51551
|
+
if (activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort) {
|
|
51552
|
+
return void 0;
|
|
51553
|
+
}
|
|
51554
|
+
const metadataSnapshot = buildPrefetchedExplorerMetadata(
|
|
51555
|
+
activeFilter,
|
|
51556
|
+
categoryMetadataCategoryId,
|
|
51557
|
+
categoryMetadata
|
|
51558
|
+
);
|
|
51559
|
+
if (metadataSnapshot) {
|
|
51560
|
+
return metadataSnapshot;
|
|
51561
|
+
}
|
|
51562
|
+
if (initialTimeFilter?.startTime && initialTimeFilter?.endTime && currentVideo && currentVideo.type === activeFilter) {
|
|
51563
|
+
return {
|
|
51564
|
+
[activeFilter]: [{
|
|
51565
|
+
id: currentVideo.id,
|
|
51566
|
+
clipId: currentVideo.id,
|
|
51567
|
+
clip_timestamp: currentVideo.creation_timestamp || currentVideo.timestamp,
|
|
51568
|
+
description: currentVideo.description,
|
|
51569
|
+
severity: currentVideo.severity,
|
|
51570
|
+
category: activeFilter,
|
|
51571
|
+
duration: typeof currentVideo.duration === "number" ? currentVideo.duration : typeof currentVideo.cycle_time_seconds === "number" ? currentVideo.cycle_time_seconds : void 0,
|
|
51572
|
+
clip_start_time: currentVideo.clip_start_time,
|
|
51573
|
+
clip_end_time: currentVideo.clip_end_time,
|
|
51574
|
+
index: 0,
|
|
51575
|
+
idle_start_time: currentVideo.idle_start_time,
|
|
51576
|
+
idle_end_time: currentVideo.idle_end_time,
|
|
51577
|
+
cycle_item_count: null,
|
|
51578
|
+
red_flow_timeline: currentVideo.red_flow_timeline,
|
|
51579
|
+
red_flow_severity_score: currentVideo.red_flow_severity_score,
|
|
51580
|
+
red_flow_output_shortfall_units: currentVideo.red_flow_output_shortfall_units,
|
|
51581
|
+
red_flow_worst_minute: currentVideo.red_flow_worst_minute,
|
|
51582
|
+
red_flow_explanation_summary: currentVideo.red_flow_explanation_summary,
|
|
51583
|
+
red_flow_explanation: currentVideo.red_flow_explanation
|
|
51584
|
+
}]
|
|
51585
|
+
};
|
|
51586
|
+
}
|
|
51587
|
+
return void 0;
|
|
51588
|
+
}, [
|
|
51589
|
+
activeFilter,
|
|
51590
|
+
categoryMetadata,
|
|
49886
51591
|
categoryMetadataCategoryId,
|
|
49887
|
-
|
|
49888
|
-
|
|
51592
|
+
categoryMetadataSort,
|
|
51593
|
+
currentVideo,
|
|
51594
|
+
idleClipSort,
|
|
51595
|
+
initialTimePrefetchedMetadata,
|
|
51596
|
+
initialTimePrefetch,
|
|
51597
|
+
initialTimeFilter?.endTime,
|
|
51598
|
+
initialTimeFilter?.startTime,
|
|
51599
|
+
lowMomentsPrefetch,
|
|
51600
|
+
workspaceId,
|
|
51601
|
+
effectiveDateString,
|
|
51602
|
+
effectiveShiftId,
|
|
51603
|
+
isLowMomentsCategoryAvailable
|
|
51604
|
+
]);
|
|
51605
|
+
const externallyManagedLoadingCategories = useMemo(() => {
|
|
51606
|
+
const managedCategories = {
|
|
51607
|
+
recent_flow_red_streak: Boolean(
|
|
51608
|
+
activeFilter === LOW_EFFICIENCY_CATEGORY_ID && isLowMomentsCategoryAvailable && lowMomentsPrefetch?.key?.startsWith(`${LOW_EFFICIENCY_CATEGORY_ID}-${workspaceId}-${effectiveDateString}-${effectiveShiftId}-`) && lowMomentsPrefetch.loading
|
|
51609
|
+
)
|
|
51610
|
+
};
|
|
51611
|
+
const isInitialTimeHandoffPending = Boolean(
|
|
51612
|
+
initialTimeFilter?.startTime && initialTimeFilter?.endTime && requestedInitialCategoryCandidates.length > 0 && (!initialTimePrefetch || initialTimePrefetch.loading)
|
|
51613
|
+
);
|
|
51614
|
+
if (isInitialTimeHandoffPending) {
|
|
51615
|
+
requestedInitialCategoryCandidates.forEach((categoryId) => {
|
|
51616
|
+
managedCategories[categoryId] = true;
|
|
51617
|
+
});
|
|
51618
|
+
}
|
|
51619
|
+
return managedCategories;
|
|
51620
|
+
}, [
|
|
51621
|
+
activeFilter,
|
|
51622
|
+
effectiveDateString,
|
|
51623
|
+
effectiveShiftId,
|
|
51624
|
+
initialTimeFilter?.endTime,
|
|
51625
|
+
initialTimeFilter?.startTime,
|
|
51626
|
+
initialTimePrefetch,
|
|
51627
|
+
isLowMomentsCategoryAvailable,
|
|
51628
|
+
lowMomentsPrefetch,
|
|
51629
|
+
requestedInitialCategoryCandidates,
|
|
51630
|
+
workspaceId
|
|
51631
|
+
]);
|
|
49889
51632
|
const classificationClipIds = useMemo(() => {
|
|
49890
51633
|
if (!idleTimeVlmEnabled) {
|
|
49891
51634
|
return [];
|
|
@@ -50295,7 +52038,7 @@ var BottlenecksContent = ({
|
|
|
50295
52038
|
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: "S3 configuration is required to load video clips. Please check your dashboard configuration." })
|
|
50296
52039
|
] });
|
|
50297
52040
|
}
|
|
50298
|
-
if (clipTypesLoading && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
52041
|
+
if (!hasInitialTimeHandoff && clipTypesLoading && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
50299
52042
|
return /* @__PURE__ */ jsx("div", { className: "flex-grow p-4 flex items-center justify-center min-h-[calc(100dvh-12rem)]", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading clips..." }) });
|
|
50300
52043
|
}
|
|
50301
52044
|
if (error && error.type === "fatal" && !hasInitialLoad || clipTypesError) {
|
|
@@ -50305,7 +52048,30 @@ var BottlenecksContent = ({
|
|
|
50305
52048
|
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: error?.message || clipTypesError })
|
|
50306
52049
|
] });
|
|
50307
52050
|
}
|
|
50308
|
-
const categoriesToShow =
|
|
52051
|
+
const categoriesToShow = (() => {
|
|
52052
|
+
const categories = clipTypes.length > 0 ? [...clipTypes] : [];
|
|
52053
|
+
const existingTypes = new Set(categories.map((category) => category.type));
|
|
52054
|
+
requestedInitialCategoryCandidates.forEach((categoryType) => {
|
|
52055
|
+
if (existingTypes.has(categoryType) || !hasInitialTimeHandoff && (mergedCounts[categoryType] || 0) <= 0) {
|
|
52056
|
+
return;
|
|
52057
|
+
}
|
|
52058
|
+
const fallback = CHART_HANDOFF_CATEGORY_FALLBACKS[categoryType];
|
|
52059
|
+
if (!fallback) {
|
|
52060
|
+
return;
|
|
52061
|
+
}
|
|
52062
|
+
categories.push({
|
|
52063
|
+
id: categoryType,
|
|
52064
|
+
type: categoryType,
|
|
52065
|
+
label: fallback.label,
|
|
52066
|
+
description: fallback.description,
|
|
52067
|
+
color: fallback.color,
|
|
52068
|
+
icon: fallback.icon,
|
|
52069
|
+
sort_order: 50
|
|
52070
|
+
});
|
|
52071
|
+
existingTypes.add(categoryType);
|
|
52072
|
+
});
|
|
52073
|
+
return categories;
|
|
52074
|
+
})();
|
|
50309
52075
|
console.log("[BottlenecksContent] Categories to show:", {
|
|
50310
52076
|
categoriesToShow,
|
|
50311
52077
|
categoriesToShowLength: categoriesToShow?.length,
|
|
@@ -50324,190 +52090,204 @@ var BottlenecksContent = ({
|
|
|
50324
52090
|
}
|
|
50325
52091
|
),
|
|
50326
52092
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:h-full", children: [
|
|
50327
|
-
/* @__PURE__ */ jsx(
|
|
50328
|
-
|
|
50329
|
-
|
|
50330
|
-
|
|
50331
|
-
|
|
50332
|
-
|
|
50333
|
-
|
|
50334
|
-
|
|
50335
|
-
|
|
50336
|
-
|
|
50337
|
-
|
|
52093
|
+
/* @__PURE__ */ jsx(
|
|
52094
|
+
"div",
|
|
52095
|
+
{
|
|
52096
|
+
className: "min-w-0 w-full lg:flex-[3] lg:h-full",
|
|
52097
|
+
"data-qa-clips-active-filter": activeFilter || "",
|
|
52098
|
+
"data-qa-clips-current-video-type": currentVideo?.type || "",
|
|
52099
|
+
"data-qa-clips-current-video-id": currentVideo?.id || "",
|
|
52100
|
+
"data-qa-clips-current-clip-id": currentClipId || "",
|
|
52101
|
+
"data-qa-clips-filtered-count": filteredVideos.length,
|
|
52102
|
+
"data-qa-clips-all-count": allVideos.length,
|
|
52103
|
+
"data-qa-clips-current-video-matches-hour": String(currentVideoMatchesInitialTimeHandoff),
|
|
52104
|
+
"data-qa-clips-hold-hour-video": String(shouldHoldInitialTimeHandoffVideo),
|
|
52105
|
+
children: /* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg shadow-sm overflow-hidden lg:h-full", children: canRenderCurrentVideo && currentVideo ? /* @__PURE__ */ jsx("div", { className: "p-4 lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative group lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full aspect-video lg:aspect-auto lg:h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
|
|
52106
|
+
/* @__PURE__ */ jsx(
|
|
52107
|
+
"div",
|
|
50338
52108
|
{
|
|
50339
|
-
ref: videoRef,
|
|
50340
|
-
src: currentVideo.src,
|
|
50341
|
-
poster: "",
|
|
50342
52109
|
className: "w-full h-full",
|
|
50343
|
-
|
|
50344
|
-
|
|
50345
|
-
|
|
50346
|
-
loop: false,
|
|
50347
|
-
externalLoadingControl: true,
|
|
50348
|
-
onReady: handleVideoReady,
|
|
50349
|
-
onPlay: handleVideoPlay,
|
|
50350
|
-
onPause: handleVideoPause,
|
|
50351
|
-
onTimeUpdate: handleTimeUpdate,
|
|
50352
|
-
onDurationChange: handleDurationChange,
|
|
50353
|
-
onEnded: handleVideoEnded,
|
|
50354
|
-
onError: handleVideoError,
|
|
50355
|
-
onLoadedData: handleLoadedData,
|
|
50356
|
-
onPlaying: handleVideoPlaying,
|
|
50357
|
-
onLoadingChange: handleVideoLoadingChange,
|
|
50358
|
-
onShare: handleShareClip,
|
|
50359
|
-
isShareLoading,
|
|
50360
|
-
isShareCopied,
|
|
50361
|
-
timelineAnnotations: currentVideo.red_flow_timeline,
|
|
50362
|
-
timelineExplanation: currentVideo.red_flow_explanation,
|
|
50363
|
-
timelineTimezone: timezone,
|
|
50364
|
-
options: videoPlayerOptions
|
|
50365
|
-
},
|
|
50366
|
-
`${currentVideo.id}-${playerInstanceNonce}-inline`
|
|
50367
|
-
)
|
|
50368
|
-
}
|
|
50369
|
-
),
|
|
50370
|
-
currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
|
|
50371
|
-
RedFlowDiagnosticOverlay,
|
|
50372
|
-
{
|
|
50373
|
-
timeline: currentVideo.red_flow_timeline,
|
|
50374
|
-
explanation: currentVideo.red_flow_explanation,
|
|
50375
|
-
aiSummary: currentLowEfficiencyAiSummary,
|
|
50376
|
-
aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
|
|
50377
|
-
aiSummaryError: currentLowEfficiencyAiSummaryError,
|
|
50378
|
-
className: "right-4 top-4"
|
|
50379
|
-
}
|
|
50380
|
-
) : null,
|
|
50381
|
-
showBlockingVideoLoader && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
50382
|
-
!shouldDeferPlayerRenderForCrop && !isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
50383
|
-
error && error.type === "retrying" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-40 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
50384
|
-
/* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md" }),
|
|
50385
|
-
/* @__PURE__ */ jsx("p", { className: "text-white text-sm mt-4 font-medium", children: error.message })
|
|
50386
|
-
] }) }),
|
|
50387
|
-
error && error.type === "fatal" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/90 text-white p-4", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-md", children: [
|
|
50388
|
-
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto mb-4 text-red-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 16.5c-.77.833.192 2.5 1.732 2.5z" }) }),
|
|
50389
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: error.code === 3 ? "Stream Corrupted" : error.code === 4 ? "Format Not Supported" : error.code === 2 ? "Network Error" : error.code === 1 ? "Loading Interrupted" : "Playback Error" }),
|
|
50390
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-6", children: error.message }),
|
|
50391
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
50392
|
-
error.canSkip && /* @__PURE__ */ jsx(
|
|
50393
|
-
"button",
|
|
50394
|
-
{
|
|
50395
|
-
onClick: () => {
|
|
50396
|
-
setError(null);
|
|
50397
|
-
videoRetryCountRef.current = 0;
|
|
50398
|
-
handleNext();
|
|
52110
|
+
style: {
|
|
52111
|
+
opacity: isTransitioning ? 0 : 1,
|
|
52112
|
+
transition: "opacity 0.1s ease-in-out"
|
|
50399
52113
|
},
|
|
50400
|
-
|
|
50401
|
-
|
|
52114
|
+
children: !shouldDeferPlayerRenderForCrop && /* @__PURE__ */ jsx(
|
|
52115
|
+
CroppedVideoPlayer,
|
|
52116
|
+
{
|
|
52117
|
+
ref: videoRef,
|
|
52118
|
+
src: currentVideo.src,
|
|
52119
|
+
poster: "",
|
|
52120
|
+
className: "w-full h-full",
|
|
52121
|
+
crop: workspaceCrop?.crop,
|
|
52122
|
+
autoplay: true,
|
|
52123
|
+
playsInline: true,
|
|
52124
|
+
loop: false,
|
|
52125
|
+
externalLoadingControl: true,
|
|
52126
|
+
onReady: handleVideoReady,
|
|
52127
|
+
onPlay: handleVideoPlay,
|
|
52128
|
+
onPause: handleVideoPause,
|
|
52129
|
+
onTimeUpdate: handleTimeUpdate,
|
|
52130
|
+
onDurationChange: handleDurationChange,
|
|
52131
|
+
onEnded: handleVideoEnded,
|
|
52132
|
+
onError: handleVideoError,
|
|
52133
|
+
onLoadedData: handleLoadedData,
|
|
52134
|
+
onPlaying: handleVideoPlaying,
|
|
52135
|
+
onLoadingChange: handleVideoLoadingChange,
|
|
52136
|
+
onShare: handleShareClip,
|
|
52137
|
+
isShareLoading,
|
|
52138
|
+
isShareCopied,
|
|
52139
|
+
timelineAnnotations: currentVideo.red_flow_timeline,
|
|
52140
|
+
timelineExplanation: currentVideo.red_flow_explanation,
|
|
52141
|
+
timelineTimezone: timezone,
|
|
52142
|
+
options: videoPlayerOptions
|
|
52143
|
+
},
|
|
52144
|
+
`${currentVideo.id}-${playerInstanceNonce}-inline`
|
|
52145
|
+
)
|
|
50402
52146
|
}
|
|
50403
52147
|
),
|
|
50404
|
-
|
|
50405
|
-
|
|
52148
|
+
currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
|
|
52149
|
+
RedFlowDiagnosticOverlay,
|
|
50406
52150
|
{
|
|
50407
|
-
|
|
50408
|
-
|
|
50409
|
-
|
|
50410
|
-
|
|
50411
|
-
|
|
50412
|
-
|
|
52151
|
+
timeline: currentVideo.red_flow_timeline,
|
|
52152
|
+
explanation: currentVideo.red_flow_explanation,
|
|
52153
|
+
aiSummary: currentLowEfficiencyAiSummary,
|
|
52154
|
+
aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
|
|
52155
|
+
aiSummaryError: currentLowEfficiencyAiSummaryError,
|
|
52156
|
+
className: "right-4 top-4"
|
|
50413
52157
|
}
|
|
50414
|
-
)
|
|
50415
|
-
|
|
50416
|
-
|
|
50417
|
-
|
|
50418
|
-
|
|
50419
|
-
|
|
50420
|
-
|
|
50421
|
-
|
|
50422
|
-
|
|
50423
|
-
|
|
50424
|
-
|
|
50425
|
-
|
|
50426
|
-
|
|
50427
|
-
|
|
50428
|
-
|
|
50429
|
-
|
|
50430
|
-
|
|
50431
|
-
|
|
50432
|
-
|
|
50433
|
-
|
|
50434
|
-
|
|
50435
|
-
|
|
50436
|
-
|
|
50437
|
-
|
|
50438
|
-
|
|
50439
|
-
|
|
50440
|
-
|
|
50441
|
-
|
|
50442
|
-
|
|
50443
|
-
|
|
50444
|
-
|
|
52158
|
+
) : null,
|
|
52159
|
+
showBlockingVideoLoader && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
52160
|
+
!shouldDeferPlayerRenderForCrop && !isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
52161
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-40 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
52162
|
+
/* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md" }),
|
|
52163
|
+
/* @__PURE__ */ jsx("p", { className: "text-white text-sm mt-4 font-medium", children: error.message })
|
|
52164
|
+
] }) }),
|
|
52165
|
+
error && error.type === "fatal" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/90 text-white p-4", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-md", children: [
|
|
52166
|
+
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto mb-4 text-red-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 16.5c-.77.833.192 2.5 1.732 2.5z" }) }),
|
|
52167
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: error.code === 3 ? "Stream Corrupted" : error.code === 4 ? "Format Not Supported" : error.code === 2 ? "Network Error" : error.code === 1 ? "Loading Interrupted" : "Playback Error" }),
|
|
52168
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-6", children: error.message }),
|
|
52169
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
52170
|
+
error.canSkip && /* @__PURE__ */ jsx(
|
|
52171
|
+
"button",
|
|
52172
|
+
{
|
|
52173
|
+
onClick: () => {
|
|
52174
|
+
setError(null);
|
|
52175
|
+
videoRetryCountRef.current = 0;
|
|
52176
|
+
handleNext();
|
|
52177
|
+
},
|
|
52178
|
+
className: "px-5 py-2.5 bg-blue-600 hover:bg-blue-700 rounded-md text-sm font-medium transition-colors",
|
|
52179
|
+
children: "Skip to Next Clip"
|
|
52180
|
+
}
|
|
52181
|
+
),
|
|
52182
|
+
error.canRetry && /* @__PURE__ */ jsx(
|
|
52183
|
+
"button",
|
|
52184
|
+
{
|
|
52185
|
+
onClick: () => {
|
|
52186
|
+
videoRetryCountRef.current = 0;
|
|
52187
|
+
restartCurrentClipPlayback();
|
|
52188
|
+
},
|
|
52189
|
+
className: "px-5 py-2.5 bg-gray-600 hover:bg-gray-700 rounded-md text-sm font-medium transition-colors",
|
|
52190
|
+
children: "Retry"
|
|
52191
|
+
}
|
|
52192
|
+
)
|
|
52193
|
+
] })
|
|
52194
|
+
] }) }),
|
|
52195
|
+
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? currentVideo.type === "idle_time" ? (
|
|
52196
|
+
// Show full colored badge for idle time
|
|
52197
|
+
(() => {
|
|
52198
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
52199
|
+
const confidence = getIdleTimeConfidence(currentVideo);
|
|
52200
|
+
const config = getRootCauseConfig(classification);
|
|
52201
|
+
if (!config) return null;
|
|
52202
|
+
const IconComponent = config.Icon;
|
|
52203
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52204
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10", children: /* @__PURE__ */ jsxs("div", { className: `inline-flex max-w-[18rem] items-center gap-1.5 rounded-md border px-2.5 py-1.5 shadow-lg ${config.bgColor} ${config.borderColor}`, children: [
|
|
52205
|
+
/* @__PURE__ */ jsx(IconComponent, { className: `h-3.5 w-3.5 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
52206
|
+
/* @__PURE__ */ jsx("span", { className: `truncate font-medium text-xs ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
52207
|
+
] }) }),
|
|
52208
|
+
idleTimeVlmEnabled && confidence !== null && (() => {
|
|
52209
|
+
const confidencePercent = confidence * 100;
|
|
52210
|
+
let confidenceLabel = "Low";
|
|
52211
|
+
let confidenceColor = "text-red-500";
|
|
52212
|
+
if (confidencePercent > 95) {
|
|
52213
|
+
confidenceLabel = "High";
|
|
52214
|
+
confidenceColor = "text-green-500";
|
|
52215
|
+
} else if (confidencePercent >= 91) {
|
|
52216
|
+
confidenceLabel = "Medium";
|
|
52217
|
+
confidenceColor = "text-yellow-500";
|
|
52218
|
+
}
|
|
52219
|
+
return /* @__PURE__ */ jsx("div", { className: "absolute top-3 right-3 z-10", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg bg-black/70 backdrop-blur-sm shadow-lg border border-white/10", children: /* @__PURE__ */ jsxs("span", { className: "font-medium text-xs text-white", children: [
|
|
52220
|
+
"AI Confidence: ",
|
|
52221
|
+
/* @__PURE__ */ jsx("span", { className: confidenceColor, children: confidenceLabel })
|
|
52222
|
+
] }) }) });
|
|
52223
|
+
})()
|
|
52224
|
+
] });
|
|
50445
52225
|
})()
|
|
50446
|
-
|
|
50447
|
-
|
|
50448
|
-
|
|
50449
|
-
|
|
50450
|
-
|
|
50451
|
-
|
|
50452
|
-
|
|
50453
|
-
|
|
50454
|
-
|
|
50455
|
-
|
|
50456
|
-
|
|
50457
|
-
|
|
50458
|
-
|
|
50459
|
-
|
|
50460
|
-
|
|
50461
|
-
|
|
50462
|
-
|
|
50463
|
-
|
|
50464
|
-
|
|
50465
|
-
|
|
50466
|
-
|
|
50467
|
-
|
|
50468
|
-
|
|
50469
|
-
|
|
50470
|
-
|
|
50471
|
-
|
|
50472
|
-
|
|
50473
|
-
|
|
50474
|
-
|
|
50475
|
-
|
|
50476
|
-
|
|
50477
|
-
|
|
50478
|
-
|
|
50479
|
-
|
|
50480
|
-
|
|
50481
|
-
|
|
50482
|
-
|
|
50483
|
-
|
|
50484
|
-
] }) })
|
|
50485
|
-
|
|
50486
|
-
|
|
50487
|
-
/* Priority 5: Show "no clips found" only if we have counts and there are truly no clips for workspace */
|
|
50488
|
-
hasInitialLoad && Object.keys(mergedCounts).length > 0 && Object.values(mergedCounts).every((count) => count === 0) ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
50489
|
-
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
50490
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Clips Found" }),
|
|
50491
|
-
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There were no video clips found for this workspace today." })
|
|
50492
|
-
] }) }) : (
|
|
50493
|
-
/* Priority 5.5: Show "no folder selected" if activeFilter is empty */
|
|
50494
|
-
hasInitialLoad && !activeFilter ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
50495
|
-
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
50496
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Folder Selected" }),
|
|
50497
|
-
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "Please select a folder to view clips." })
|
|
50498
|
-
] }) }) : (
|
|
50499
|
-
/* Priority 6: Show "no matching clips" only if we have data loaded and specifically no clips for this filter */
|
|
50500
|
-
hasInitialLoad && (mergedCounts[activeFilter] || 0) === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
52226
|
+
) : /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
52227
|
+
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" ? "bg-purple-400" : isPercentileCategory(activeFilterRef.current) ? activeFilterRef.current === "fast-cycles" ? "bg-green-600" : activeFilterRef.current === "slow-cycles" ? "bg-red-700" : "bg-orange-500" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-gray-500"} mr-2 animate-pulse` }),
|
|
52228
|
+
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds ? /* @__PURE__ */ jsxs("span", { className: "opacity-90 font-mono bg-black/30 px-2 py-0.5 rounded", children: [
|
|
52229
|
+
"Cycle time: ",
|
|
52230
|
+
currentVideo.cycle_time_seconds.toFixed(1),
|
|
52231
|
+
"s"
|
|
52232
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52233
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
|
|
52234
|
+
/* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
52235
|
+
] })
|
|
52236
|
+
] }) }) : (
|
|
52237
|
+
/* Right side display for other video types */
|
|
52238
|
+
currentVideo.type === "idle_time" ? (
|
|
52239
|
+
// Show full colored badge for idle time
|
|
52240
|
+
(() => {
|
|
52241
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
52242
|
+
const confidence = getIdleTimeConfidence(currentVideo);
|
|
52243
|
+
const config = getRootCauseConfig(classification);
|
|
52244
|
+
if (!config) return null;
|
|
52245
|
+
const IconComponent = config.Icon;
|
|
52246
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52247
|
+
idleTimeVlmEnabled && confidence !== null && /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg bg-black/70 backdrop-blur-sm shadow-lg border border-white/10", children: /* @__PURE__ */ jsxs("span", { className: "font-medium text-xs text-white", children: [
|
|
52248
|
+
"AI Confidence: ",
|
|
52249
|
+
(confidence * 100).toFixed(0),
|
|
52250
|
+
"%"
|
|
52251
|
+
] }) }) }),
|
|
52252
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsx("div", { className: "absolute top-3 right-3 z-10", children: /* @__PURE__ */ jsxs("div", { className: `inline-flex max-w-[18rem] items-center gap-1.5 rounded-md border px-2.5 py-1.5 shadow-lg ${config.bgColor} ${config.borderColor}`, children: [
|
|
52253
|
+
/* @__PURE__ */ jsx(IconComponent, { className: `h-3.5 w-3.5 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
52254
|
+
/* @__PURE__ */ jsx("span", { className: `truncate font-medium text-xs ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
52255
|
+
] }) })
|
|
52256
|
+
] });
|
|
52257
|
+
})()
|
|
52258
|
+
) : /* @__PURE__ */ jsx("div", { className: `absolute top-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs ${currentVideo.type === "recent_flow_red_streak" ? "left-3" : "right-3"}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
52259
|
+
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
|
|
52260
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
|
|
52261
|
+
currentVideo.type !== "recent_flow_red_streak" && /* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
52262
|
+
] }) })
|
|
52263
|
+
)
|
|
52264
|
+
] }) }) }) : shouldHoldInitialTimeHandoffVideo ? /* @__PURE__ */ jsx("div", { className: "p-4 lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full min-h-[220px] sm:min-h-[320px] lg:min-h-0 lg:h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading clips..." }) }) }) }) : (
|
|
52265
|
+
/* Priority 5: Show "no clips found" only if we have counts and there are truly no clips for workspace */
|
|
52266
|
+
hasInitialLoad && Object.keys(mergedCounts).length > 0 && Object.values(mergedCounts).every((count) => count === 0) ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
50501
52267
|
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
50502
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No
|
|
50503
|
-
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There
|
|
52268
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Clips Found" }),
|
|
52269
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There were no video clips found for this workspace today." })
|
|
50504
52270
|
] }) }) : (
|
|
50505
|
-
/* Priority
|
|
50506
|
-
|
|
52271
|
+
/* Priority 5.5: Show "no folder selected" if activeFilter is empty */
|
|
52272
|
+
hasInitialLoad && !activeFilter ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
52273
|
+
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
52274
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Folder Selected" }),
|
|
52275
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "Please select a folder to view clips." })
|
|
52276
|
+
] }) }) : (
|
|
52277
|
+
/* Priority 6: Show "no matching clips" only if we have data loaded and specifically no clips for this filter */
|
|
52278
|
+
hasInitialLoad && (mergedCounts[activeFilter] || 0) === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
52279
|
+
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
52280
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Matching Clips" }),
|
|
52281
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There are no clips matching the selected filter." })
|
|
52282
|
+
] }) }) : (
|
|
52283
|
+
/* Priority 7: Default loading state for any other case */
|
|
52284
|
+
/* @__PURE__ */ jsx("div", { className: "p-4 lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full min-h-[220px] sm:min-h-[320px] lg:min-h-0 lg:h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading..." }) }) }) })
|
|
52285
|
+
)
|
|
52286
|
+
)
|
|
50507
52287
|
)
|
|
50508
|
-
)
|
|
50509
|
-
|
|
50510
|
-
)
|
|
52288
|
+
) })
|
|
52289
|
+
}
|
|
52290
|
+
),
|
|
50511
52291
|
/* @__PURE__ */ jsx("div", { className: "w-full lg:flex-shrink-0 lg:flex-[1] lg:min-w-[280px] lg:max-w-[320px] lg:h-full", children: triageMode ? (
|
|
50512
52292
|
/* Triage Mode - Direct tile view for cycle completions and idle time */
|
|
50513
52293
|
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm h-full overflow-hidden flex flex-col", children: [
|
|
@@ -50642,7 +52422,7 @@ var BottlenecksContent = ({
|
|
|
50642
52422
|
})),
|
|
50643
52423
|
videos: allVideos || [],
|
|
50644
52424
|
activeFilter,
|
|
50645
|
-
currentVideoId: currentVideo?.id,
|
|
52425
|
+
currentVideoId: currentVideo?.id || currentClipId || void 0,
|
|
50646
52426
|
counts: mergedCounts,
|
|
50647
52427
|
isReady: hasInitialLoad,
|
|
50648
52428
|
prefetchedPercentileCounts: isFastSlowClipFiltersEnabled ? prefetchedPercentileCounts || void 0 : void 0,
|
|
@@ -50656,11 +52436,9 @@ var BottlenecksContent = ({
|
|
|
50656
52436
|
idleTimeVlmEnabled,
|
|
50657
52437
|
showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
|
|
50658
52438
|
prefetchedClipMetadata: prefetchedExplorerMetadata,
|
|
50659
|
-
|
|
50660
|
-
|
|
50661
|
-
|
|
50662
|
-
)
|
|
50663
|
-
},
|
|
52439
|
+
prefetchedClipTotals: initialTimePrefetch?.loading ? void 0 : initialTimePrefetch?.totalsByCategory,
|
|
52440
|
+
prefetchedPercentileClips: initialTimePrefetch?.loading ? void 0 : initialTimePrefetch?.percentileClipsByCategory,
|
|
52441
|
+
externallyManagedLoadingCategories,
|
|
50664
52442
|
activeCategoryLoading: isCategoryLoading,
|
|
50665
52443
|
idleClipSort,
|
|
50666
52444
|
onIdleClipSortChange: setIdleClipSort,
|
|
@@ -70474,9 +72252,7 @@ function withWorkspaceDisplayNames(Component3, options = {}) {
|
|
|
70474
72252
|
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
70475
72253
|
}
|
|
70476
72254
|
} else if (lineIdArray.length > 0) {
|
|
70477
|
-
await
|
|
70478
|
-
lineIdArray.map((lineId) => preInitializeWorkspaceDisplayNames(lineId))
|
|
70479
|
-
);
|
|
72255
|
+
await preInitializeWorkspaceDisplayNamesForLines(lineIdArray);
|
|
70480
72256
|
} else {
|
|
70481
72257
|
await preInitializeWorkspaceDisplayNames();
|
|
70482
72258
|
}
|
|
@@ -80940,7 +82716,6 @@ var TargetsViewUI = ({
|
|
|
80940
82716
|
skuRequired = false,
|
|
80941
82717
|
onUpdateWorkspaceSelectedSku
|
|
80942
82718
|
}) => {
|
|
80943
|
-
const { displayNames: workspaceDisplayNames } = useWorkspaceDisplayNames();
|
|
80944
82719
|
const mobileMenuContext = useMobileMenu();
|
|
80945
82720
|
useHideMobileHeader(!!mobileMenuContext);
|
|
80946
82721
|
if (isLoading) {
|
|
@@ -81122,7 +82897,7 @@ var TargetsViewUI = ({
|
|
|
81122
82897
|
] })
|
|
81123
82898
|
] }) }),
|
|
81124
82899
|
/* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-100", children: line.workspaces.map((workspace) => {
|
|
81125
|
-
const formattedName =
|
|
82900
|
+
const formattedName = workspace.displayName || formatWorkspaceName(workspace.name, lineId);
|
|
81126
82901
|
const realSkuOptions = (workspace.skuRows || []).filter((r2) => !r2.is_dummy);
|
|
81127
82902
|
const showSkuDropdown = !!onUpdateWorkspaceSelectedSku && realSkuOptions.length >= 1;
|
|
81128
82903
|
const isPlanLocked = !!workspace.productionPlanLock?.locked;
|
|
@@ -81673,6 +83448,7 @@ var TargetsView = ({
|
|
|
81673
83448
|
return {
|
|
81674
83449
|
id: ws.id,
|
|
81675
83450
|
name: ws.workspace_id,
|
|
83451
|
+
displayName: ws.display_name || ws.workspace_id,
|
|
81676
83452
|
targetPPH: selectedRow?.pph_threshold ?? (threshold?.pph_threshold ? Math.round(threshold.pph_threshold) : ""),
|
|
81677
83453
|
targetCycleTime: selectedRow?.ideal_cycle_time ?? (threshold?.ideal_cycle_time ?? ""),
|
|
81678
83454
|
targetDayOutput: selectedRow?.total_day_output ?? (threshold?.total_day_output ?? ""),
|
|
@@ -81731,6 +83507,7 @@ var TargetsView = ({
|
|
|
81731
83507
|
return {
|
|
81732
83508
|
id: ws.id,
|
|
81733
83509
|
name: ws.workspace_id,
|
|
83510
|
+
displayName: ws.display_name || ws.workspace_id,
|
|
81734
83511
|
targetPPH: "",
|
|
81735
83512
|
targetCycleTime: "",
|
|
81736
83513
|
targetDayOutput: "",
|
|
@@ -82211,15 +83988,31 @@ var TargetsView = ({
|
|
|
82211
83988
|
const handleUpdateWorkspaceDisplayName = useCallback(async (workspaceId, displayName) => {
|
|
82212
83989
|
try {
|
|
82213
83990
|
const updated = await workspaceService.updateWorkspaceDisplayName(workspaceId, displayName);
|
|
83991
|
+
const nextDisplayName = updated?.display_name || displayName;
|
|
83992
|
+
setAllShiftsData((prev) => {
|
|
83993
|
+
const next = { ...prev };
|
|
83994
|
+
Object.entries(prev).forEach(([shiftId, shiftData]) => {
|
|
83995
|
+
const numericShiftId = Number(shiftId);
|
|
83996
|
+
const updatedShiftData = {};
|
|
83997
|
+
Object.entries(shiftData).forEach(([lineId, line]) => {
|
|
83998
|
+
updatedShiftData[lineId] = {
|
|
83999
|
+
...line,
|
|
84000
|
+
workspaces: line.workspaces.map(
|
|
84001
|
+
(ws) => ws.id === workspaceId ? { ...ws, displayName: nextDisplayName } : ws
|
|
84002
|
+
)
|
|
84003
|
+
};
|
|
84004
|
+
});
|
|
84005
|
+
next[numericShiftId] = updatedShiftData;
|
|
84006
|
+
});
|
|
84007
|
+
return next;
|
|
84008
|
+
});
|
|
82214
84009
|
if (updated?.line_id && updated?.workspace_id) {
|
|
82215
84010
|
upsertWorkspaceDisplayNameInCache({
|
|
82216
84011
|
lineId: updated.line_id,
|
|
82217
84012
|
workspaceId: updated.workspace_id,
|
|
82218
|
-
displayName:
|
|
84013
|
+
displayName: nextDisplayName,
|
|
82219
84014
|
enabled: updated?.enable
|
|
82220
84015
|
});
|
|
82221
|
-
} else {
|
|
82222
|
-
await forceRefreshWorkspaceDisplayNames();
|
|
82223
84016
|
}
|
|
82224
84017
|
toast.success("Workspace name updated successfully");
|
|
82225
84018
|
} catch (error) {
|
|
@@ -82263,9 +84056,8 @@ var TargetsView = ({
|
|
|
82263
84056
|
}
|
|
82264
84057
|
);
|
|
82265
84058
|
};
|
|
82266
|
-
var
|
|
82267
|
-
var
|
|
82268
|
-
var AuthenticatedTargetsView = withAuth(React125__default.memo(TargetsViewWithDisplayNames));
|
|
84059
|
+
var TargetsView_default = TargetsView;
|
|
84060
|
+
var AuthenticatedTargetsView = withAuth(React125__default.memo(TargetsView));
|
|
82269
84061
|
function useTimezone(options = {}) {
|
|
82270
84062
|
const dashboardConfig = useDashboardConfig();
|
|
82271
84063
|
const workspaceConfig = useWorkspaceConfig();
|
|
@@ -82445,17 +84237,22 @@ var WorkspaceHourSummaryPanel = ({
|
|
|
82445
84237
|
return;
|
|
82446
84238
|
}
|
|
82447
84239
|
autoSummaryKeyRef.current = requestKey;
|
|
82448
|
-
|
|
82449
|
-
|
|
82450
|
-
|
|
82451
|
-
|
|
82452
|
-
|
|
82453
|
-
|
|
82454
|
-
|
|
82455
|
-
|
|
82456
|
-
|
|
82457
|
-
|
|
82458
|
-
|
|
84240
|
+
const summaryTimer = window.setTimeout(() => {
|
|
84241
|
+
void summarize({
|
|
84242
|
+
workspaceId,
|
|
84243
|
+
companyId,
|
|
84244
|
+
date,
|
|
84245
|
+
shiftId,
|
|
84246
|
+
hourIndex: selectedHour.hourIndex,
|
|
84247
|
+
hourStart: selectedHour.startTime,
|
|
84248
|
+
hourEnd: selectedHour.endTime,
|
|
84249
|
+
forceRefresh: false,
|
|
84250
|
+
selectionSource: selectedHour.source ?? "unknown"
|
|
84251
|
+
}).catch(() => void 0);
|
|
84252
|
+
}, 1500);
|
|
84253
|
+
return () => {
|
|
84254
|
+
window.clearTimeout(summaryTimer);
|
|
84255
|
+
};
|
|
82459
84256
|
}, [canSummarize, companyId, date, selectedHour, selectedKey, shiftId, summarize, workspaceId]);
|
|
82460
84257
|
if (!selectedHour) {
|
|
82461
84258
|
return null;
|
|
@@ -82639,10 +84436,18 @@ var WorkspaceDetailView = ({
|
|
|
82639
84436
|
setSelectedHour(null);
|
|
82640
84437
|
}, [workspaceId, date, shift]);
|
|
82641
84438
|
const dashboardConfig = useDashboardConfig();
|
|
84439
|
+
const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
|
|
82642
84440
|
const { legend: efficiencyLegend } = useEfficiencyLegend();
|
|
82643
84441
|
const prewarmedClipsRef = useRef(/* @__PURE__ */ new Set());
|
|
82644
84442
|
const prewarmInFlightRef = useRef(/* @__PURE__ */ new Set());
|
|
82645
84443
|
const [lowMomentsPrefetch, setLowMomentsPrefetch] = useState(null);
|
|
84444
|
+
const selectedHourClipPrefetchInFlightRef = useRef(/* @__PURE__ */ new Set());
|
|
84445
|
+
const selectedHourClipPrefetchAbortRef = useRef(null);
|
|
84446
|
+
const [initialTimePrefetch, setInitialTimePrefetch] = useState(null);
|
|
84447
|
+
const {
|
|
84448
|
+
isFastSlowClipFiltersEnabled,
|
|
84449
|
+
isResolved: isFastSlowClipFiltersResolved
|
|
84450
|
+
} = useCompanyFastSlowClipFiltersEnabled();
|
|
82646
84451
|
const [aiSummaryHour, setAiSummaryHour] = useState(null);
|
|
82647
84452
|
const buildHourlyOutputActionTrackingProps = useCallback((payload) => ({
|
|
82648
84453
|
workspace_id: workspaceId,
|
|
@@ -82672,24 +84477,286 @@ var WorkspaceDetailView = ({
|
|
|
82672
84477
|
timezone,
|
|
82673
84478
|
workspaceId
|
|
82674
84479
|
]);
|
|
84480
|
+
const prefetchClipsForSelectedHour = useCallback((hour) => {
|
|
84481
|
+
if (!isClipsEnabled || !dashboardConfig?.s3Config || !workspaceId || !supabase) {
|
|
84482
|
+
return;
|
|
84483
|
+
}
|
|
84484
|
+
const resolvedDate = date || getOperationalDate(timezone);
|
|
84485
|
+
const resolvedShiftId = parsedShiftId ?? selectedShift;
|
|
84486
|
+
if (!resolvedDate || resolvedShiftId === null || resolvedShiftId === void 0) {
|
|
84487
|
+
return;
|
|
84488
|
+
}
|
|
84489
|
+
const categoryId = "cycle_completion";
|
|
84490
|
+
const regularCategoryIds = ["cycle_completion", "idle_time", "recent_flow_red_streak"];
|
|
84491
|
+
const percentileCategoryIds = isFastSlowClipFiltersEnabled ? ["fast-cycles", "slow-cycles"] : [];
|
|
84492
|
+
const allPrefetchCategoryIds = [...regularCategoryIds, ...percentileCategoryIds];
|
|
84493
|
+
const effectiveTimezone = hour.timezone || timezone;
|
|
84494
|
+
const prefetchKey = [
|
|
84495
|
+
workspaceId,
|
|
84496
|
+
resolvedDate,
|
|
84497
|
+
resolvedShiftId,
|
|
84498
|
+
hour.startTime,
|
|
84499
|
+
hour.endTime,
|
|
84500
|
+
effectiveTimezone || "",
|
|
84501
|
+
allPrefetchCategoryIds.join(",")
|
|
84502
|
+
].join("|");
|
|
84503
|
+
if (initialTimePrefetch?.key === prefetchKey && !initialTimePrefetch.loading) {
|
|
84504
|
+
return;
|
|
84505
|
+
}
|
|
84506
|
+
if (selectedHourClipPrefetchInFlightRef.current.has(prefetchKey)) {
|
|
84507
|
+
return;
|
|
84508
|
+
}
|
|
84509
|
+
selectedHourClipPrefetchAbortRef.current?.abort();
|
|
84510
|
+
const controller = new AbortController();
|
|
84511
|
+
selectedHourClipPrefetchAbortRef.current = controller;
|
|
84512
|
+
selectedHourClipPrefetchInFlightRef.current.add(prefetchKey);
|
|
84513
|
+
const existingSnapshot = initialTimePrefetch?.key === prefetchKey ? initialTimePrefetch : null;
|
|
84514
|
+
setInitialTimePrefetch({
|
|
84515
|
+
key: prefetchKey,
|
|
84516
|
+
categoryId,
|
|
84517
|
+
metadata: existingSnapshot?.metadata || [],
|
|
84518
|
+
metadataByCategory: existingSnapshot?.metadataByCategory || {},
|
|
84519
|
+
totalsByCategory: existingSnapshot?.totalsByCategory || {},
|
|
84520
|
+
percentileClipsByCategory: existingSnapshot?.percentileClipsByCategory || {},
|
|
84521
|
+
firstVideo: existingSnapshot?.firstVideo || null,
|
|
84522
|
+
total: existingSnapshot?.total || 0,
|
|
84523
|
+
loading: true,
|
|
84524
|
+
error: null
|
|
84525
|
+
});
|
|
84526
|
+
const s3Service = videoPrefetchManager.getS3Service(dashboardConfig);
|
|
84527
|
+
const fetchHourlySnapshot = async () => {
|
|
84528
|
+
try {
|
|
84529
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
84530
|
+
method: "POST",
|
|
84531
|
+
headers: {
|
|
84532
|
+
"Content-Type": "application/json"
|
|
84533
|
+
},
|
|
84534
|
+
body: JSON.stringify({
|
|
84535
|
+
action: "hourly-snapshot",
|
|
84536
|
+
workspaceId,
|
|
84537
|
+
date: resolvedDate,
|
|
84538
|
+
shift: resolvedShiftId,
|
|
84539
|
+
startTime: hour.startTime,
|
|
84540
|
+
endTime: hour.endTime,
|
|
84541
|
+
timeFilterTimezone: effectiveTimezone
|
|
84542
|
+
}),
|
|
84543
|
+
signal: controller.signal,
|
|
84544
|
+
redirectReason: "session_expired"
|
|
84545
|
+
});
|
|
84546
|
+
if (!response.ok) {
|
|
84547
|
+
return false;
|
|
84548
|
+
}
|
|
84549
|
+
const snapshot = await response.json();
|
|
84550
|
+
const metadataByCategory = snapshot?.metadataByCategory && typeof snapshot.metadataByCategory === "object" ? snapshot.metadataByCategory : {};
|
|
84551
|
+
const percentileClipsByCategory = snapshot?.percentileClipsByCategory && typeof snapshot.percentileClipsByCategory === "object" ? snapshot.percentileClipsByCategory : {};
|
|
84552
|
+
const totalsByCategory = snapshot?.totalsByCategory && typeof snapshot.totalsByCategory === "object" ? Object.entries(snapshot.totalsByCategory).reduce((accumulator, [key, value]) => {
|
|
84553
|
+
const total = Number(value);
|
|
84554
|
+
accumulator[key] = Number.isFinite(total) ? Math.max(0, total) : 0;
|
|
84555
|
+
return accumulator;
|
|
84556
|
+
}, {}) : {};
|
|
84557
|
+
const snapshotCategoryId = typeof snapshot?.categoryId === "string" ? snapshot.categoryId : categoryId;
|
|
84558
|
+
const metadata = Array.isArray(snapshot?.metadata) ? snapshot.metadata : Array.isArray(metadataByCategory[snapshotCategoryId]) ? metadataByCategory[snapshotCategoryId] : [];
|
|
84559
|
+
if (controller.signal.aborted) {
|
|
84560
|
+
return true;
|
|
84561
|
+
}
|
|
84562
|
+
setInitialTimePrefetch({
|
|
84563
|
+
key: prefetchKey,
|
|
84564
|
+
categoryId: snapshotCategoryId,
|
|
84565
|
+
metadata,
|
|
84566
|
+
metadataByCategory,
|
|
84567
|
+
totalsByCategory,
|
|
84568
|
+
percentileClipsByCategory,
|
|
84569
|
+
firstVideo: snapshot?.firstVideo || null,
|
|
84570
|
+
total: typeof totalsByCategory[snapshotCategoryId] === "number" ? totalsByCategory[snapshotCategoryId] : metadata.length,
|
|
84571
|
+
loading: false,
|
|
84572
|
+
error: null
|
|
84573
|
+
});
|
|
84574
|
+
return true;
|
|
84575
|
+
} catch (error2) {
|
|
84576
|
+
if (error2.name === "AbortError") {
|
|
84577
|
+
return true;
|
|
84578
|
+
}
|
|
84579
|
+
console.warn("[WorkspaceDetailView] Hourly clips snapshot failed; falling back to category prefetch:", error2);
|
|
84580
|
+
return false;
|
|
84581
|
+
}
|
|
84582
|
+
};
|
|
84583
|
+
const fetchRegularCategory = async (prefetchCategoryId) => {
|
|
84584
|
+
const metadataResponse = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
84585
|
+
method: "POST",
|
|
84586
|
+
headers: {
|
|
84587
|
+
"Content-Type": "application/json"
|
|
84588
|
+
},
|
|
84589
|
+
body: JSON.stringify({
|
|
84590
|
+
action: "clip-metadata",
|
|
84591
|
+
workspaceId,
|
|
84592
|
+
date: resolvedDate,
|
|
84593
|
+
shift: resolvedShiftId,
|
|
84594
|
+
category: prefetchCategoryId,
|
|
84595
|
+
page: 1,
|
|
84596
|
+
limit: 500,
|
|
84597
|
+
knownTotal: null,
|
|
84598
|
+
startTime: hour.startTime,
|
|
84599
|
+
endTime: hour.endTime,
|
|
84600
|
+
timeFilterTimezone: effectiveTimezone,
|
|
84601
|
+
sort: prefetchCategoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : "latest"
|
|
84602
|
+
}),
|
|
84603
|
+
signal: controller.signal,
|
|
84604
|
+
redirectReason: "session_expired"
|
|
84605
|
+
});
|
|
84606
|
+
if (!metadataResponse.ok) {
|
|
84607
|
+
throw new Error(`Hourly clips metadata prefetch failed for ${prefetchCategoryId}: ${metadataResponse.status}`);
|
|
84608
|
+
}
|
|
84609
|
+
const metadataData = await metadataResponse.json();
|
|
84610
|
+
return {
|
|
84611
|
+
categoryId: prefetchCategoryId,
|
|
84612
|
+
clips: Array.isArray(metadataData?.clips) ? metadataData.clips : [],
|
|
84613
|
+
total: typeof metadataData?.total === "number" ? metadataData.total : 0
|
|
84614
|
+
};
|
|
84615
|
+
};
|
|
84616
|
+
const fetchPercentileCategory = async (prefetchCategoryId) => {
|
|
84617
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
84618
|
+
method: "POST",
|
|
84619
|
+
headers: {
|
|
84620
|
+
"Content-Type": "application/json"
|
|
84621
|
+
},
|
|
84622
|
+
body: JSON.stringify({
|
|
84623
|
+
action: "percentile-clips",
|
|
84624
|
+
workspaceId,
|
|
84625
|
+
startDate: `${resolvedDate}T00:00:00Z`,
|
|
84626
|
+
endDate: `${resolvedDate}T23:59:59Z`,
|
|
84627
|
+
percentile: 10,
|
|
84628
|
+
shiftId: resolvedShiftId,
|
|
84629
|
+
limit: 500,
|
|
84630
|
+
startTime: hour.startTime,
|
|
84631
|
+
endTime: hour.endTime,
|
|
84632
|
+
timeFilterTimezone: effectiveTimezone,
|
|
84633
|
+
percentileAction: prefetchCategoryId
|
|
84634
|
+
}),
|
|
84635
|
+
signal: controller.signal,
|
|
84636
|
+
redirectReason: "session_expired"
|
|
84637
|
+
});
|
|
84638
|
+
if (!response.ok) {
|
|
84639
|
+
throw new Error(`Hourly percentile clips prefetch failed for ${prefetchCategoryId}: ${response.status}`);
|
|
84640
|
+
}
|
|
84641
|
+
const data = await response.json();
|
|
84642
|
+
return {
|
|
84643
|
+
categoryId: prefetchCategoryId,
|
|
84644
|
+
clips: Array.isArray(data?.clips) ? data.clips : [],
|
|
84645
|
+
total: typeof data?.total === "number" ? data.total : 0
|
|
84646
|
+
};
|
|
84647
|
+
};
|
|
84648
|
+
const runPrefetch = async () => {
|
|
84649
|
+
try {
|
|
84650
|
+
const snapshotLoaded = await fetchHourlySnapshot();
|
|
84651
|
+
if (snapshotLoaded) {
|
|
84652
|
+
return;
|
|
84653
|
+
}
|
|
84654
|
+
const cycleCompletionPromise = fetchRegularCategory("cycle_completion");
|
|
84655
|
+
let resolvedFirstVideo = null;
|
|
84656
|
+
const firstVideoPromise = cycleCompletionPromise.then(async (cycleResponse) => {
|
|
84657
|
+
const firstClipId = cycleResponse.clips[0]?.clipId || cycleResponse.clips[0]?.id || null;
|
|
84658
|
+
if (!firstClipId) {
|
|
84659
|
+
return null;
|
|
84660
|
+
}
|
|
84661
|
+
const video = await s3Service.getClipById(firstClipId);
|
|
84662
|
+
resolvedFirstVideo = video;
|
|
84663
|
+
if (!controller.signal.aborted) {
|
|
84664
|
+
setInitialTimePrefetch((prev) => prev?.key === prefetchKey ? {
|
|
84665
|
+
...prev,
|
|
84666
|
+
firstVideo: video
|
|
84667
|
+
} : prev);
|
|
84668
|
+
}
|
|
84669
|
+
return video;
|
|
84670
|
+
}).catch((error2) => {
|
|
84671
|
+
if (error2.name !== "AbortError") {
|
|
84672
|
+
console.warn("[WorkspaceDetailView] Hourly first clip prefetch failed:", error2);
|
|
84673
|
+
}
|
|
84674
|
+
return null;
|
|
84675
|
+
});
|
|
84676
|
+
const percentileResponsesPromise = Promise.all(percentileCategoryIds.map(fetchPercentileCategory));
|
|
84677
|
+
const regularResponses = await Promise.all([
|
|
84678
|
+
cycleCompletionPromise,
|
|
84679
|
+
fetchRegularCategory("idle_time"),
|
|
84680
|
+
fetchRegularCategory("recent_flow_red_streak")
|
|
84681
|
+
]);
|
|
84682
|
+
const percentileResponses = await percentileResponsesPromise;
|
|
84683
|
+
const metadataByCategory = regularResponses.reduce((accumulator, response) => {
|
|
84684
|
+
accumulator[response.categoryId] = response.clips;
|
|
84685
|
+
return accumulator;
|
|
84686
|
+
}, {});
|
|
84687
|
+
const percentileClipsByCategory = percentileResponses.reduce((accumulator, response) => {
|
|
84688
|
+
accumulator[response.categoryId] = response.clips;
|
|
84689
|
+
return accumulator;
|
|
84690
|
+
}, {});
|
|
84691
|
+
const totalsByCategory = [...regularResponses, ...percentileResponses].reduce((accumulator, response) => {
|
|
84692
|
+
accumulator[response.categoryId] = Math.max(0, Number(response.total || 0));
|
|
84693
|
+
return accumulator;
|
|
84694
|
+
}, {});
|
|
84695
|
+
const metadata = metadataByCategory[categoryId] || [];
|
|
84696
|
+
if (controller.signal.aborted) {
|
|
84697
|
+
return;
|
|
84698
|
+
}
|
|
84699
|
+
setInitialTimePrefetch({
|
|
84700
|
+
key: prefetchKey,
|
|
84701
|
+
categoryId,
|
|
84702
|
+
metadata,
|
|
84703
|
+
metadataByCategory,
|
|
84704
|
+
totalsByCategory,
|
|
84705
|
+
percentileClipsByCategory,
|
|
84706
|
+
firstVideo: resolvedFirstVideo,
|
|
84707
|
+
total: typeof totalsByCategory[categoryId] === "number" ? totalsByCategory[categoryId] : metadata.length,
|
|
84708
|
+
loading: false,
|
|
84709
|
+
error: null
|
|
84710
|
+
});
|
|
84711
|
+
void firstVideoPromise;
|
|
84712
|
+
} catch (error2) {
|
|
84713
|
+
if (error2.name === "AbortError") {
|
|
84714
|
+
return;
|
|
84715
|
+
}
|
|
84716
|
+
console.warn("[WorkspaceDetailView] Hourly clips prefetch failed:", error2);
|
|
84717
|
+
setInitialTimePrefetch((prev) => prev?.key === prefetchKey ? {
|
|
84718
|
+
...prev,
|
|
84719
|
+
loading: false,
|
|
84720
|
+
error: error2 instanceof Error ? error2.message : "Hourly clips prefetch failed"
|
|
84721
|
+
} : prev);
|
|
84722
|
+
} finally {
|
|
84723
|
+
selectedHourClipPrefetchInFlightRef.current.delete(prefetchKey);
|
|
84724
|
+
}
|
|
84725
|
+
};
|
|
84726
|
+
void runPrefetch();
|
|
84727
|
+
}, [
|
|
84728
|
+
dashboardConfig,
|
|
84729
|
+
date,
|
|
84730
|
+
initialTimePrefetch,
|
|
84731
|
+
isFastSlowClipFiltersEnabled,
|
|
84732
|
+
isClipsEnabled,
|
|
84733
|
+
parsedShiftId,
|
|
84734
|
+
selectedShift,
|
|
84735
|
+
supabase,
|
|
84736
|
+
timezone,
|
|
84737
|
+
workspaceId
|
|
84738
|
+
]);
|
|
82675
84739
|
const handleOutputHourSelect = useCallback((payload) => {
|
|
82676
|
-
|
|
84740
|
+
const hour = {
|
|
82677
84741
|
source: "output",
|
|
82678
84742
|
hourIndex: payload.hourIndex,
|
|
82679
84743
|
timeRange: payload.timeRange,
|
|
82680
84744
|
startTime: payload.startTime,
|
|
82681
84745
|
endTime: payload.endTime,
|
|
84746
|
+
timezone: payload.timezone,
|
|
82682
84747
|
status: payload.status,
|
|
82683
84748
|
output: payload.output,
|
|
82684
84749
|
target: payload.target
|
|
82685
|
-
}
|
|
82686
|
-
|
|
84750
|
+
};
|
|
84751
|
+
setSelectedHour(hour);
|
|
84752
|
+
prefetchClipsForSelectedHour(hour);
|
|
84753
|
+
}, [prefetchClipsForSelectedHour]);
|
|
82687
84754
|
const handleAiSummaryClick = useCallback((payload) => {
|
|
82688
84755
|
trackCoreEvent("Hourly Output Ask AI Clicked", buildHourlyOutputActionTrackingProps(payload));
|
|
82689
84756
|
setAiSummaryHour(payload);
|
|
82690
84757
|
}, [buildHourlyOutputActionTrackingProps]);
|
|
82691
84758
|
const handleCycleHourSelect = useCallback((payload) => {
|
|
82692
|
-
|
|
84759
|
+
const hour = {
|
|
82693
84760
|
source: "cycle",
|
|
82694
84761
|
hourIndex: payload.hourIndex,
|
|
82695
84762
|
timeRange: payload.timeRange,
|
|
@@ -82699,17 +84766,23 @@ var WorkspaceDetailView = ({
|
|
|
82699
84766
|
cycleTime: payload.cycleTime,
|
|
82700
84767
|
idealCycleTime: payload.idealCycleTime,
|
|
82701
84768
|
idleMinutes: payload.idleMinutes
|
|
82702
|
-
}
|
|
82703
|
-
|
|
84769
|
+
};
|
|
84770
|
+
setSelectedHour(hour);
|
|
84771
|
+
prefetchClipsForSelectedHour(hour);
|
|
84772
|
+
}, [prefetchClipsForSelectedHour]);
|
|
82704
84773
|
const handleOpenClipsForHour = useCallback((hour) => {
|
|
84774
|
+
prefetchClipsForSelectedHour(hour);
|
|
82705
84775
|
setPendingClipHourFilter({
|
|
82706
84776
|
startTime: hour.startTime,
|
|
82707
84777
|
endTime: hour.endTime,
|
|
82708
84778
|
sourceLabel: hour.timeRange,
|
|
82709
|
-
status: hour.status === "below_target" || hour.status === "above_standard" ? "below_target" : "met_target"
|
|
84779
|
+
status: hour.status === "below_target" || hour.status === "above_standard" ? "below_target" : "met_target",
|
|
84780
|
+
timezone: hour.timezone,
|
|
84781
|
+
categoryId: "cycle_completion",
|
|
84782
|
+
categoryIds: ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time", "recent_flow_red_streak"]
|
|
82710
84783
|
});
|
|
82711
84784
|
setActiveTab("bottlenecks");
|
|
82712
|
-
}, []);
|
|
84785
|
+
}, [prefetchClipsForSelectedHour]);
|
|
82713
84786
|
const handleWatchClipsFromChart = useCallback((payload) => {
|
|
82714
84787
|
trackCoreEvent("Hourly Output Watch Clips Clicked", buildHourlyOutputActionTrackingProps(payload));
|
|
82715
84788
|
handleOpenClipsForHour({
|
|
@@ -82718,6 +84791,7 @@ var WorkspaceDetailView = ({
|
|
|
82718
84791
|
timeRange: payload.timeRange,
|
|
82719
84792
|
startTime: payload.startTime,
|
|
82720
84793
|
endTime: payload.endTime,
|
|
84794
|
+
timezone: payload.timezone,
|
|
82721
84795
|
status: payload.status,
|
|
82722
84796
|
output: payload.output,
|
|
82723
84797
|
target: payload.target
|
|
@@ -82740,11 +84814,6 @@ var WorkspaceDetailView = ({
|
|
|
82740
84814
|
startDate: isFullRange ? void 0 : rangeStart,
|
|
82741
84815
|
endDate: isFullRange ? void 0 : rangeEnd
|
|
82742
84816
|
});
|
|
82743
|
-
const {
|
|
82744
|
-
isFastSlowClipFiltersEnabled,
|
|
82745
|
-
isResolved: isFastSlowClipFiltersResolved
|
|
82746
|
-
} = useCompanyFastSlowClipFiltersEnabled();
|
|
82747
|
-
const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
|
|
82748
84817
|
dashboardConfig?.supervisorConfig?.enabled || false;
|
|
82749
84818
|
const routedLineId = lineId || selectedLineId;
|
|
82750
84819
|
const latestCachedDetailedMetrics = useMemo(() => {
|
|
@@ -84491,6 +86560,7 @@ var WorkspaceDetailView = ({
|
|
|
84491
86560
|
workspaceMetrics: detailedWorkspaceMetrics || void 0,
|
|
84492
86561
|
prefetchedPercentileCounts: isFastSlowClipFiltersEnabled ? prefetchedPercentileCounts : null,
|
|
84493
86562
|
lowMomentsPrefetch,
|
|
86563
|
+
initialTimePrefetch,
|
|
84494
86564
|
initialTimeFilter: pendingClipHourFilter,
|
|
84495
86565
|
className: "h-[calc(100vh-10rem)]"
|
|
84496
86566
|
}
|
|
@@ -94048,4 +96118,6 @@ var RecentFlowSnapshotGrid = ({
|
|
|
94048
96118
|
);
|
|
94049
96119
|
};
|
|
94050
96120
|
|
|
94051
|
-
export { ACTION_FAMILIES, ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPI_SIGNAL_LABELS, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LineOvertakeNotificationManager, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProductionPlanApiError, ProductionPlanView_default as ProductionPlanView, ProfileView_default as ProfileView, ROOT_DASHBOARD_EVENT_NAMES, RecentFlowSnapshotGrid, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SENTRY_HANDLED_EVENT_SESSION_LIMIT, SENTRY_HANDLED_EVENT_WINDOW_MS, SENTRY_QUOTA_STORAGE_KEY, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, addSentryBreadcrumb, aggregateKPIsFromLineMetricsRows, aggregateLineSignals, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildKpiLineHierarchy, buildLegacyLineOvertakeEventKey, buildLineLeaderboardRows, buildLineOvertakeEventKey, buildLineSkuBreakdown, buildShiftGroupsKey, canPermissionEditProductionPlan, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleEditProductionPlan, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureHandledFrontendException, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, combineLineMetricsRows, countRealSkus, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, detectLineOvertakeEvents, fetchIdleTimeReasons, fetchLineDummySkuId, fetchLineSkuCatalog, filterDataByDateKeyRange, filterRealSkuBreakdown, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDateKeyFromValue, getDayDateKey, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getKpiSignalLabel, getKpiSignalStatus, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getMonthlyTrendComparisonLabel, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isIgnorableFrontendError, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRealSku, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeDateKeyRangeUnbounded, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, pickPreferredLineMetricsRow, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, productionPlanService, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSentryQuotaForTests, resetSubscriptionManager, resolveDefaultSkuId, resolveLiveSkuId, s3VideoPreloader, selectPreferredLineMetricsRow, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyFastSlowClipFiltersEnabled, useCompanyHasVlmEnabledLine, useCompanyUsersUsage, useCompanyWorkspaceHourAiSummaryEnabled, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceHourSummary, useWorkspaceLightTimeline, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|
|
96121
|
+
export { ACTION_FAMILIES, ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AvatarUpload, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPI_SIGNAL_LABELS, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LineOvertakeNotificationManager, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProductionPlanApiError, ProductionPlanView_default as ProductionPlanView, ProfileView_default as ProfileView, ROOT_DASHBOARD_EVENT_NAMES, RecentFlowSnapshotGrid, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SENTRY_HANDLED_EVENT_SESSION_LIMIT, SENTRY_HANDLED_EVENT_WINDOW_MS, SENTRY_QUOTA_STORAGE_KEY, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, addSentryBreadcrumb, aggregateKPIsFromLineMetricsRows, aggregateLineSignals, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildKpiLineHierarchy, buildLegacyLineOvertakeEventKey, buildLineLeaderboardRows, buildLineOvertakeEventKey, buildLineSkuBreakdown, buildShiftGroupsKey, canPermissionEditProductionPlan, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleEditProductionPlan, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureHandledFrontendException, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, combineLineMetricsRows, countRealSkus, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, detectLineOvertakeEvents, fetchIdleTimeReasons, fetchLineDummySkuId, fetchLineSkuCatalog, filterDataByDateKeyRange, filterRealSkuBreakdown, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDateKeyFromValue, getDayDateKey, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getKpiSignalLabel, getKpiSignalStatus, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getMonthlyTrendComparisonLabel, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isIgnorableFrontendError, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRealSku, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeDateKeyRangeUnbounded, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, pickPreferredLineMetricsRow, preInitializeWorkspaceDisplayNames, preInitializeWorkspaceDisplayNamesForLines, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, productionPlanService, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSentryQuotaForTests, resetSubscriptionManager, resolveDefaultSkuId, resolveLiveSkuId, s3VideoPreloader, selectPreferredLineMetricsRow, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyFastSlowClipFiltersEnabled, useCompanyHasVlmEnabledLine, useCompanyUsersUsage, useCompanyWorkspaceHourAiSummaryEnabled, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceHourSummary, useWorkspaceLightTimeline, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|
|
96122
|
+
//# sourceMappingURL=index.mjs.map
|
|
96123
|
+
//# sourceMappingURL=index.mjs.map
|