@optifye/dashboard-core 6.12.51 → 6.12.53
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 -11
- 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 +2660 -594
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2661 -596
- 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
|
+
}
|
|
12530
|
+
}
|
|
12531
|
+
}
|
|
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;
|
|
12230
12542
|
}
|
|
12231
12543
|
}
|
|
12232
|
-
async sendEndSession(reason) {
|
|
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,
|
|
@@ -15648,6 +15976,10 @@ var useDashboardMetrics = ({
|
|
|
15648
15976
|
}
|
|
15649
15977
|
const isFactory = currentLineIdToUse === factoryViewId;
|
|
15650
15978
|
const targetLineIds = isFactory ? targetFactoryLineIds : [currentLineIdToUse];
|
|
15979
|
+
if (isFactory && targetLineIds.length > 0 && !shiftGroupsKey) {
|
|
15980
|
+
logDebug("[useDashboardMetrics] Skipping fetch: factory shift groups are not ready");
|
|
15981
|
+
return;
|
|
15982
|
+
}
|
|
15651
15983
|
const targetLineIdsKey = targetLineIds.slice().sort().join(",");
|
|
15652
15984
|
const effectiveBlueComparisonLineIds = normalizedBlueComparisonLineIds.length ? normalizedBlueComparisonLineIds : targetLineIds;
|
|
15653
15985
|
const blueComparisonLineIdsKey = effectiveBlueComparisonLineIds.slice().sort().join(",");
|
|
@@ -15712,7 +16044,7 @@ var useDashboardMetrics = ({
|
|
|
15712
16044
|
const qaGreenStreakParams = qaGreenStreakParamString ? `&${qaGreenStreakParamString}` : "";
|
|
15713
16045
|
const buildMetricsEndpoint = (params) => {
|
|
15714
16046
|
const lineIdsParam = isFactory ? `line_ids=${params.groupLineIds.join(",")}` : `line_id=${params.groupLineIds[0]}`;
|
|
15715
|
-
const blueComparisonParam =
|
|
16047
|
+
const blueComparisonParam = normalizedBlueComparisonLineIds.length ? `&blue_comparison_line_ids=${normalizedBlueComparisonLineIds.join(",")}` : "";
|
|
15716
16048
|
const selectorParam = normalizedSelectorLineIds.length ? `&selector_line_ids=${encodeURIComponent(normalizedSelectorLineIds.join(","))}` : "";
|
|
15717
16049
|
return `/api/dashboard/metrics?${lineIdsParam}${blueComparisonParam}${selectorParam}&date=${params.date}&shift_id=${params.shiftId}&company_id=${companyId}${forceParam}${qaGreenStreakParams}`;
|
|
15718
16050
|
};
|
|
@@ -17435,7 +17767,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
17435
17767
|
return Number.isFinite(parsed) ? parsed : DEFAULT_MAX_MANIFEST_AGE_MS;
|
|
17436
17768
|
})();
|
|
17437
17769
|
const manifestStaleThresholdMs = maxManifestAgeMs > 0 ? Math.min(maxManifestAgeMs, SEGMENT_MAX_AGE_MS) : SEGMENT_MAX_AGE_MS;
|
|
17438
|
-
const
|
|
17770
|
+
const debugLog2 = (...args) => {
|
|
17439
17771
|
if (debugEnabled) {
|
|
17440
17772
|
console.log(...args);
|
|
17441
17773
|
}
|
|
@@ -17617,7 +17949,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
17617
17949
|
return;
|
|
17618
17950
|
}
|
|
17619
17951
|
} catch (error) {
|
|
17620
|
-
|
|
17952
|
+
debugLog2("[HLS] Stale manifest poll failed", error);
|
|
17621
17953
|
}
|
|
17622
17954
|
staleManifestPollDelayRef.current = Math.min(
|
|
17623
17955
|
staleManifestPollDelayRef.current + 5e3,
|
|
@@ -17967,7 +18299,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
17967
18299
|
}
|
|
17968
18300
|
return true;
|
|
17969
18301
|
} catch (error) {
|
|
17970
|
-
|
|
18302
|
+
debugLog2("[HLS] Manifest freshness check failed", error);
|
|
17971
18303
|
{
|
|
17972
18304
|
markStaleStream("manifest freshness check failed");
|
|
17973
18305
|
return false;
|
|
@@ -18013,7 +18345,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18013
18345
|
};
|
|
18014
18346
|
const softRestart = (reason) => {
|
|
18015
18347
|
if (staleManifestTriggeredRef.current) {
|
|
18016
|
-
|
|
18348
|
+
debugLog2("[HLS] Skip soft restart while manifest is stale", reason);
|
|
18017
18349
|
return;
|
|
18018
18350
|
}
|
|
18019
18351
|
console.warn(`[HLS] Soft restart: ${reason}`);
|
|
@@ -18046,7 +18378,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18046
18378
|
};
|
|
18047
18379
|
const hardRestart = (reason) => {
|
|
18048
18380
|
if (staleManifestTriggeredRef.current) {
|
|
18049
|
-
|
|
18381
|
+
debugLog2("[HLS] Skip hard restart while manifest is stale", reason);
|
|
18050
18382
|
return;
|
|
18051
18383
|
}
|
|
18052
18384
|
console.warn(`[HLS] Hard restart: ${reason}`);
|
|
@@ -18300,7 +18632,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18300
18632
|
hls.loadSource(resolvedHlsSrc);
|
|
18301
18633
|
activeStreamUrlRef.current = resolvedHlsSrc;
|
|
18302
18634
|
hls.on(Hls.Events.ERROR, (_, data) => {
|
|
18303
|
-
|
|
18635
|
+
debugLog2("[HLS] Error", {
|
|
18304
18636
|
type: data.type,
|
|
18305
18637
|
details: data.details,
|
|
18306
18638
|
fatal: data.fatal,
|
|
@@ -18308,7 +18640,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18308
18640
|
frag: data.frag?.sn
|
|
18309
18641
|
});
|
|
18310
18642
|
if (data.type === Hls.ErrorTypes.MEDIA_ERROR && data.details === Hls.ErrorDetails.BUFFER_STALLED_ERROR) {
|
|
18311
|
-
|
|
18643
|
+
debugLog2("[HLS] Buffer stalled, waiting for next segment");
|
|
18312
18644
|
attemptPlay();
|
|
18313
18645
|
return;
|
|
18314
18646
|
}
|
|
@@ -18452,7 +18784,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError, hlsConfig }) {
|
|
|
18452
18784
|
}
|
|
18453
18785
|
}
|
|
18454
18786
|
}
|
|
18455
|
-
|
|
18787
|
+
debugLog2("[HLS] Level loaded", {
|
|
18456
18788
|
targetduration: details.targetduration,
|
|
18457
18789
|
edge: details.edge,
|
|
18458
18790
|
fragments: data.details?.fragments?.length
|
|
@@ -18848,6 +19180,7 @@ var isInitializing = false;
|
|
|
18848
19180
|
var initializedWithLineIds = [];
|
|
18849
19181
|
var missingLineContextWarnings = /* @__PURE__ */ new Set();
|
|
18850
19182
|
var lineLoadPromises = /* @__PURE__ */ new Map();
|
|
19183
|
+
var GLOBAL_CACHE_KEY = "global";
|
|
18851
19184
|
var initializationPromise = null;
|
|
18852
19185
|
var workspaceDisplayNamesListeners = /* @__PURE__ */ new Set();
|
|
18853
19186
|
var notifyWorkspaceDisplayNamesListeners = (changedLineId) => {
|
|
@@ -18869,6 +19202,22 @@ var storeLineDisplayNames = (lineId, lineDisplayNamesMap) => {
|
|
|
18869
19202
|
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
18870
19203
|
});
|
|
18871
19204
|
};
|
|
19205
|
+
var storeGlobalDisplayNames = (displayNamesMap) => {
|
|
19206
|
+
runtimeWorkspaceDisplayNames[GLOBAL_CACHE_KEY] = {};
|
|
19207
|
+
displayNamesMap.forEach((displayName, workspaceId) => {
|
|
19208
|
+
runtimeWorkspaceDisplayNames[GLOBAL_CACHE_KEY][workspaceId] = displayName;
|
|
19209
|
+
});
|
|
19210
|
+
};
|
|
19211
|
+
var storeDisplayNamesByLine = (displayNamesByLine, requestedLineIds = []) => {
|
|
19212
|
+
displayNamesByLine.forEach((lineDisplayNamesMap, lineId) => {
|
|
19213
|
+
storeLineDisplayNames(lineId, lineDisplayNamesMap);
|
|
19214
|
+
});
|
|
19215
|
+
requestedLineIds.forEach((lineId) => {
|
|
19216
|
+
if (!runtimeWorkspaceDisplayNames[lineId]) {
|
|
19217
|
+
runtimeWorkspaceDisplayNames[lineId] = {};
|
|
19218
|
+
}
|
|
19219
|
+
});
|
|
19220
|
+
};
|
|
18872
19221
|
var ensureLineWorkspaceDisplayNamesLoaded = async (lineId) => {
|
|
18873
19222
|
if (!lineId || runtimeWorkspaceDisplayNames[lineId]) {
|
|
18874
19223
|
return;
|
|
@@ -18952,7 +19301,11 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
18952
19301
|
console.log("\u{1F504} Target line IDs for workspace filtering:", targetLineIds);
|
|
18953
19302
|
runtimeWorkspaceDisplayNames = {};
|
|
18954
19303
|
lineLoadPromises.clear();
|
|
18955
|
-
if (targetLineIds.length >
|
|
19304
|
+
if (targetLineIds.length > 1) {
|
|
19305
|
+
const displayNamesByLine = await workspaceService.getWorkspaceDisplayNamesByLine(void 0, targetLineIds);
|
|
19306
|
+
storeDisplayNamesByLine(displayNamesByLine, targetLineIds);
|
|
19307
|
+
console.log(`\u2705 Stored display names for ${displayNamesByLine.size} authorized lines`);
|
|
19308
|
+
} else if (targetLineIds.length === 1) {
|
|
18956
19309
|
const results = await Promise.all(
|
|
18957
19310
|
targetLineIds.map(async (lineId) => {
|
|
18958
19311
|
console.log(`\u{1F504} Fetching workspaces for line: ${lineId}`);
|
|
@@ -18967,10 +19320,7 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
18967
19320
|
} else {
|
|
18968
19321
|
console.warn("\u26A0\uFE0F No line IDs found, fetching all workspaces (less efficient)");
|
|
18969
19322
|
const allWorkspacesMap = await workspaceService.getWorkspaceDisplayNames();
|
|
18970
|
-
|
|
18971
|
-
allWorkspacesMap.forEach((displayName, workspaceId) => {
|
|
18972
|
-
runtimeWorkspaceDisplayNames["global"][workspaceId] = displayName;
|
|
18973
|
-
});
|
|
19323
|
+
storeGlobalDisplayNames(allWorkspacesMap);
|
|
18974
19324
|
}
|
|
18975
19325
|
isInitialized = true;
|
|
18976
19326
|
initializedWithLineIds = targetLineIds;
|
|
@@ -18986,6 +19336,37 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
18986
19336
|
})();
|
|
18987
19337
|
await initializationPromise;
|
|
18988
19338
|
}
|
|
19339
|
+
var preInitializeWorkspaceDisplayNamesForLines = async (lineIds) => {
|
|
19340
|
+
const uniqueLineIds = Array.from(new Set((lineIds || []).filter(Boolean)));
|
|
19341
|
+
if (uniqueLineIds.length === 0) {
|
|
19342
|
+
await preInitializeWorkspaceDisplayNames();
|
|
19343
|
+
return;
|
|
19344
|
+
}
|
|
19345
|
+
if (uniqueLineIds.length === 1) {
|
|
19346
|
+
await preInitializeWorkspaceDisplayNames(uniqueLineIds[0]);
|
|
19347
|
+
return;
|
|
19348
|
+
}
|
|
19349
|
+
if (isInitialized && uniqueLineIds.every((lineId) => Boolean(runtimeWorkspaceDisplayNames[lineId]))) {
|
|
19350
|
+
return;
|
|
19351
|
+
}
|
|
19352
|
+
if (initializationPromise) {
|
|
19353
|
+
await initializationPromise;
|
|
19354
|
+
if (uniqueLineIds.every((lineId) => Boolean(runtimeWorkspaceDisplayNames[lineId]))) {
|
|
19355
|
+
return;
|
|
19356
|
+
}
|
|
19357
|
+
}
|
|
19358
|
+
isInitializing = true;
|
|
19359
|
+
initializationPromise = workspaceService.getWorkspaceDisplayNamesByLine(void 0, uniqueLineIds).then((displayNamesByLine) => {
|
|
19360
|
+
storeDisplayNamesByLine(displayNamesByLine, uniqueLineIds);
|
|
19361
|
+
initializedWithLineIds = uniqueLineIds;
|
|
19362
|
+
isInitialized = true;
|
|
19363
|
+
notifyWorkspaceDisplayNamesListeners();
|
|
19364
|
+
}).finally(() => {
|
|
19365
|
+
isInitializing = false;
|
|
19366
|
+
initializationPromise = null;
|
|
19367
|
+
});
|
|
19368
|
+
await initializationPromise;
|
|
19369
|
+
};
|
|
18989
19370
|
var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
18990
19371
|
console.log("\u{1F504} preInitializeWorkspaceDisplayNames called for lineId:", lineId);
|
|
18991
19372
|
if (isInitialized) {
|
|
@@ -38720,6 +39101,7 @@ var HourlyOutputChartComponent = ({
|
|
|
38720
39101
|
timeRange: data2.timeRange,
|
|
38721
39102
|
startTime,
|
|
38722
39103
|
endTime,
|
|
39104
|
+
timezone,
|
|
38723
39105
|
output: Math.round(data2.originalOutput || 0),
|
|
38724
39106
|
target: data2.target,
|
|
38725
39107
|
status: data2.status
|
|
@@ -38893,6 +39275,7 @@ var HourlyOutputChartComponent = ({
|
|
|
38893
39275
|
timeRange: entry.timeRange,
|
|
38894
39276
|
startTime,
|
|
38895
39277
|
endTime,
|
|
39278
|
+
timezone,
|
|
38896
39279
|
output: Math.round(entry.originalOutput || 0),
|
|
38897
39280
|
target: entry.target,
|
|
38898
39281
|
status: entry.status
|
|
@@ -42360,6 +42743,65 @@ var buildPrefetchedExplorerMetadata = (activeFilter, metadataCategoryId, categor
|
|
|
42360
42743
|
};
|
|
42361
42744
|
};
|
|
42362
42745
|
var shouldDeferClipPlayerRender = (cropLoading, workspaceCrop) => cropLoading && workspaceCrop === null;
|
|
42746
|
+
var parseSortableCycleTime = (value) => {
|
|
42747
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
42748
|
+
return value;
|
|
42749
|
+
}
|
|
42750
|
+
if (typeof value === "string") {
|
|
42751
|
+
const parsed = Number(value);
|
|
42752
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
42753
|
+
}
|
|
42754
|
+
return null;
|
|
42755
|
+
};
|
|
42756
|
+
var readSortableCycleTime = (clip) => {
|
|
42757
|
+
const candidate = clip;
|
|
42758
|
+
return parseSortableCycleTime(candidate?.cycleTimeSeconds) ?? parseSortableCycleTime(candidate?.cycle_time_seconds) ?? parseSortableCycleTime(candidate?.duration) ?? parseSortableCycleTime(
|
|
42759
|
+
candidate?.original_task_metadata?.cycle_time
|
|
42760
|
+
) ?? null;
|
|
42761
|
+
};
|
|
42762
|
+
var readSortableTimestamp = (clip) => {
|
|
42763
|
+
const candidate = clip;
|
|
42764
|
+
const timestamp = candidate?.creation_timestamp || candidate?.timestamp || candidate?.clip_timestamp || candidate?.clip_end_time || candidate?.clip_start_time;
|
|
42765
|
+
if (typeof timestamp !== "string") {
|
|
42766
|
+
return 0;
|
|
42767
|
+
}
|
|
42768
|
+
const parsed = new Date(timestamp).getTime();
|
|
42769
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
42770
|
+
};
|
|
42771
|
+
var sortPercentileCycleClipsForDisplay = (categoryId, clips) => {
|
|
42772
|
+
if (categoryId !== "fast-cycles" && categoryId !== "slow-cycles") {
|
|
42773
|
+
return [...clips];
|
|
42774
|
+
}
|
|
42775
|
+
return [...clips].sort((left, right) => {
|
|
42776
|
+
const leftCycleTime = readSortableCycleTime(left);
|
|
42777
|
+
const rightCycleTime = readSortableCycleTime(right);
|
|
42778
|
+
const leftMissingCycleTime = leftCycleTime === null;
|
|
42779
|
+
const rightMissingCycleTime = rightCycleTime === null;
|
|
42780
|
+
if (leftMissingCycleTime !== rightMissingCycleTime) {
|
|
42781
|
+
return leftMissingCycleTime ? 1 : -1;
|
|
42782
|
+
}
|
|
42783
|
+
if (leftCycleTime !== null && rightCycleTime !== null && leftCycleTime !== rightCycleTime) {
|
|
42784
|
+
return categoryId === "fast-cycles" ? leftCycleTime - rightCycleTime : rightCycleTime - leftCycleTime;
|
|
42785
|
+
}
|
|
42786
|
+
return readSortableTimestamp(right) - readSortableTimestamp(left);
|
|
42787
|
+
});
|
|
42788
|
+
};
|
|
42789
|
+
var resolveInitialClipCategory = (categoryCandidates, clipTypes = [], counts = {}) => {
|
|
42790
|
+
const candidates = Array.from(
|
|
42791
|
+
new Set(
|
|
42792
|
+
categoryCandidates.filter((candidate) => Boolean(candidate)).map((candidate) => candidate.trim()).filter(Boolean)
|
|
42793
|
+
)
|
|
42794
|
+
);
|
|
42795
|
+
if (candidates.length === 0) {
|
|
42796
|
+
return null;
|
|
42797
|
+
}
|
|
42798
|
+
const availableCategories = /* @__PURE__ */ new Set();
|
|
42799
|
+
clipTypes.forEach((type) => {
|
|
42800
|
+
if (type?.type) availableCategories.add(String(type.type));
|
|
42801
|
+
if (type?.id) availableCategories.add(String(type.id));
|
|
42802
|
+
});
|
|
42803
|
+
return candidates.find((candidate) => (counts[candidate] || 0) > 0) || candidates.find((candidate) => availableCategories.has(candidate)) || null;
|
|
42804
|
+
};
|
|
42363
42805
|
var getCategoryMetadataLoadPlanForFilterChange = ({
|
|
42364
42806
|
activeFilter,
|
|
42365
42807
|
currentClipId,
|
|
@@ -42371,6 +42813,12 @@ var getCategoryMetadataLoadPlanForFilterChange = ({
|
|
|
42371
42813
|
if (activeFilter === "recent_flow_red_streak" && categoryTotal > 0) {
|
|
42372
42814
|
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
42373
42815
|
}
|
|
42816
|
+
if (activeFilter === "fast-cycles" || activeFilter === "slow-cycles") {
|
|
42817
|
+
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
42818
|
+
}
|
|
42819
|
+
if (categoryTotal > 0 && activeFilter === "cycle_completion") {
|
|
42820
|
+
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
42821
|
+
}
|
|
42374
42822
|
return {
|
|
42375
42823
|
shouldLoad: Boolean(currentClipId),
|
|
42376
42824
|
autoLoadFirstVideo: false
|
|
@@ -46208,6 +46656,36 @@ var CLIP_METADATA_PAGE_SIZE = 50;
|
|
|
46208
46656
|
var RECENT_FLOW_RED_STREAK_CLIP_TYPE2 = "recent_flow_red_streak";
|
|
46209
46657
|
var RECENT_FLOW_RED_STREAK_DISPLAY_LABEL = "Low moments";
|
|
46210
46658
|
var RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE = "Moments of low efficiency";
|
|
46659
|
+
var REQUIRED_HOURLY_HANDOFF_CATEGORIES = {
|
|
46660
|
+
cycle_completion: {
|
|
46661
|
+
id: "cycle_completion",
|
|
46662
|
+
label: "Cycle Completion",
|
|
46663
|
+
description: "Successfully completed production cycles",
|
|
46664
|
+
color: "green",
|
|
46665
|
+
icon: "check-circle"
|
|
46666
|
+
},
|
|
46667
|
+
idle_time: {
|
|
46668
|
+
id: "idle_time",
|
|
46669
|
+
label: "Idle Time",
|
|
46670
|
+
description: "Idle periods",
|
|
46671
|
+
color: "purple",
|
|
46672
|
+
icon: "clock"
|
|
46673
|
+
},
|
|
46674
|
+
[RECENT_FLOW_RED_STREAK_CLIP_TYPE2]: {
|
|
46675
|
+
id: RECENT_FLOW_RED_STREAK_CLIP_TYPE2,
|
|
46676
|
+
label: RECENT_FLOW_RED_STREAK_DISPLAY_LABEL,
|
|
46677
|
+
description: RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE,
|
|
46678
|
+
color: "red",
|
|
46679
|
+
icon: "alert-triangle"
|
|
46680
|
+
}
|
|
46681
|
+
};
|
|
46682
|
+
var REQUIRED_HOURLY_FILTER_CATEGORY_IDS = [
|
|
46683
|
+
RECENT_FLOW_RED_STREAK_CLIP_TYPE2,
|
|
46684
|
+
"cycle_completion",
|
|
46685
|
+
"fast-cycles",
|
|
46686
|
+
"slow-cycles",
|
|
46687
|
+
"idle_time"
|
|
46688
|
+
];
|
|
46211
46689
|
var parseCycleTime = (value) => {
|
|
46212
46690
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
46213
46691
|
return value;
|
|
@@ -46236,6 +46714,21 @@ var formatDurationLabel = (seconds) => {
|
|
|
46236
46714
|
}
|
|
46237
46715
|
return `${Math.round(roundedSeconds / 60)} min`;
|
|
46238
46716
|
};
|
|
46717
|
+
var timeValueToMinutes = (value) => {
|
|
46718
|
+
const [hourValue, minuteValue] = value.substring(0, 5).split(":").map(Number);
|
|
46719
|
+
if (!Number.isInteger(hourValue) || !Number.isInteger(minuteValue) || hourValue < 0 || hourValue > 23 || minuteValue < 0 || minuteValue > 59) {
|
|
46720
|
+
return null;
|
|
46721
|
+
}
|
|
46722
|
+
return hourValue * 60 + minuteValue;
|
|
46723
|
+
};
|
|
46724
|
+
var isMinuteInTimeWindow = (minute, startValue, endValue) => {
|
|
46725
|
+
const startMinute = timeValueToMinutes(startValue);
|
|
46726
|
+
const endMinute = timeValueToMinutes(endValue);
|
|
46727
|
+
if (startMinute === null || endMinute === null) {
|
|
46728
|
+
return true;
|
|
46729
|
+
}
|
|
46730
|
+
return endMinute > startMinute ? minute >= startMinute && minute < endMinute : minute >= startMinute || minute < endMinute;
|
|
46731
|
+
};
|
|
46239
46732
|
var sortRedFlowMetadata = (clips) => {
|
|
46240
46733
|
return clips.slice().sort((left, right) => {
|
|
46241
46734
|
const getOutputShortfall = (clip) => {
|
|
@@ -46260,6 +46753,27 @@ var sortRedFlowMetadata = (clips) => {
|
|
|
46260
46753
|
return (Number.isFinite(rightTime) ? rightTime : 0) - (Number.isFinite(leftTime) ? leftTime : 0);
|
|
46261
46754
|
});
|
|
46262
46755
|
};
|
|
46756
|
+
var buildClipMetadataFromVideo = (video, index) => ({
|
|
46757
|
+
id: video.id,
|
|
46758
|
+
clipId: video.id,
|
|
46759
|
+
clip_timestamp: video.creation_timestamp || video.timestamp,
|
|
46760
|
+
description: video.description,
|
|
46761
|
+
severity: video.severity,
|
|
46762
|
+
category: video.type,
|
|
46763
|
+
duration: typeof video.duration === "number" ? video.duration : typeof video.cycle_time_seconds === "number" ? video.cycle_time_seconds : void 0,
|
|
46764
|
+
clip_start_time: video.clip_start_time,
|
|
46765
|
+
clip_end_time: video.clip_end_time,
|
|
46766
|
+
index,
|
|
46767
|
+
idle_start_time: video.idle_start_time,
|
|
46768
|
+
idle_end_time: video.idle_end_time,
|
|
46769
|
+
cycle_item_count: null,
|
|
46770
|
+
red_flow_timeline: video.red_flow_timeline,
|
|
46771
|
+
red_flow_severity_score: video.red_flow_severity_score,
|
|
46772
|
+
red_flow_output_shortfall_units: video.red_flow_output_shortfall_units,
|
|
46773
|
+
red_flow_worst_minute: video.red_flow_worst_minute,
|
|
46774
|
+
red_flow_explanation_summary: video.red_flow_explanation_summary,
|
|
46775
|
+
red_flow_explanation: video.red_flow_explanation
|
|
46776
|
+
});
|
|
46263
46777
|
var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
|
|
46264
46778
|
if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
|
|
46265
46779
|
return null;
|
|
@@ -46338,6 +46852,8 @@ var FileManagerFilters = ({
|
|
|
46338
46852
|
idleTimeVlmEnabled = false,
|
|
46339
46853
|
showPercentileCycleFilters = true,
|
|
46340
46854
|
prefetchedClipMetadata,
|
|
46855
|
+
prefetchedClipTotals,
|
|
46856
|
+
prefetchedPercentileClips,
|
|
46341
46857
|
externallyManagedLoadingCategories,
|
|
46342
46858
|
activeCategoryLoading,
|
|
46343
46859
|
idleClipSort = "latest",
|
|
@@ -46345,6 +46861,7 @@ var FileManagerFilters = ({
|
|
|
46345
46861
|
initialTimeFilter
|
|
46346
46862
|
}) => {
|
|
46347
46863
|
const [expandedNodes, setExpandedNodes] = useState(/* @__PURE__ */ new Set());
|
|
46864
|
+
const [activeInitialTimeFilter, setActiveInitialTimeFilter] = useState(initialTimeFilter ?? null);
|
|
46348
46865
|
const [startTime, setStartTime] = useState(initialTimeFilter?.startTime ?? "");
|
|
46349
46866
|
const [endTime, setEndTime] = useState(initialTimeFilter?.endTime ?? "");
|
|
46350
46867
|
const [isTimeFilterActive, setIsTimeFilterActive] = useState(
|
|
@@ -46359,14 +46876,93 @@ var FileManagerFilters = ({
|
|
|
46359
46876
|
const [showIdleLabelFilterModal, setShowIdleLabelFilterModal] = useState(false);
|
|
46360
46877
|
const [isLoadingIdleReasonOptions, setIsLoadingIdleReasonOptions] = useState(false);
|
|
46361
46878
|
const timezone = useAppTimezone();
|
|
46879
|
+
const activeTimeFilterTimezone = activeInitialTimeFilter?.timezone || initialTimeFilter?.timezone || timezone;
|
|
46880
|
+
const activeTimeFilterKey = useMemo(() => startTime && endTime && isTimeFilterActive ? `${startTime}-${endTime}-${activeTimeFilterTimezone}` : "none", [activeTimeFilterTimezone, endTime, isTimeFilterActive, startTime]);
|
|
46881
|
+
const initialTimeFilterCategoryIds = useMemo(() => {
|
|
46882
|
+
if (!activeInitialTimeFilter) {
|
|
46883
|
+
return [];
|
|
46884
|
+
}
|
|
46885
|
+
return Array.from(new Set([
|
|
46886
|
+
activeInitialTimeFilter.categoryId,
|
|
46887
|
+
...activeInitialTimeFilter.categoryIds || []
|
|
46888
|
+
].filter((value) => typeof value === "string" && value.length > 0)));
|
|
46889
|
+
}, [activeInitialTimeFilter]);
|
|
46890
|
+
const requiredHourlyFilterCategoryIds = useMemo(() => {
|
|
46891
|
+
if (initialTimeFilterCategoryIds.length > 0) {
|
|
46892
|
+
return initialTimeFilterCategoryIds;
|
|
46893
|
+
}
|
|
46894
|
+
if (!isTimeFilterActive || !startTime || !endTime) {
|
|
46895
|
+
return [];
|
|
46896
|
+
}
|
|
46897
|
+
return REQUIRED_HOURLY_FILTER_CATEGORY_IDS;
|
|
46898
|
+
}, [endTime, initialTimeFilterCategoryIds, isTimeFilterActive, startTime]);
|
|
46899
|
+
const categoriesForTree = useMemo(() => {
|
|
46900
|
+
if (requiredHourlyFilterCategoryIds.length === 0) {
|
|
46901
|
+
return categories;
|
|
46902
|
+
}
|
|
46903
|
+
const existingCategoryIds = new Set(categories.map((category) => category.id));
|
|
46904
|
+
const mergedCategories = [...categories];
|
|
46905
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
46906
|
+
const fallbackCategory = REQUIRED_HOURLY_HANDOFF_CATEGORIES[categoryId];
|
|
46907
|
+
if (!fallbackCategory || existingCategoryIds.has(categoryId)) {
|
|
46908
|
+
return;
|
|
46909
|
+
}
|
|
46910
|
+
mergedCategories.push(fallbackCategory);
|
|
46911
|
+
existingCategoryIds.add(categoryId);
|
|
46912
|
+
});
|
|
46913
|
+
return mergedCategories;
|
|
46914
|
+
}, [categories, requiredHourlyFilterCategoryIds]);
|
|
46362
46915
|
const supabase = useSupabase();
|
|
46363
46916
|
const [clipMetadata, setClipMetadata] = useState({});
|
|
46917
|
+
const [scopedCategoryTotals, setScopedCategoryTotals] = useState({});
|
|
46364
46918
|
const [loadingCategories, setLoadingCategories] = useState(/* @__PURE__ */ new Set());
|
|
46919
|
+
const isCategoryScopedByTimeFilter = useCallback((categoryId) => {
|
|
46920
|
+
if (!startTime || !endTime || !isTimeFilterActive) {
|
|
46921
|
+
return false;
|
|
46922
|
+
}
|
|
46923
|
+
if (!activeInitialTimeFilter) {
|
|
46924
|
+
return true;
|
|
46925
|
+
}
|
|
46926
|
+
if (activeFilter === categoryId || activeInitialTimeFilter.categoryId === categoryId) {
|
|
46927
|
+
return true;
|
|
46928
|
+
}
|
|
46929
|
+
return Boolean(activeInitialTimeFilter.categoryIds?.includes(categoryId));
|
|
46930
|
+
}, [
|
|
46931
|
+
activeFilter,
|
|
46932
|
+
activeInitialTimeFilter,
|
|
46933
|
+
endTime,
|
|
46934
|
+
isTimeFilterActive,
|
|
46935
|
+
startTime
|
|
46936
|
+
]);
|
|
46937
|
+
const isRequiredHourlyFilterCategory = useCallback((categoryId) => requiredHourlyFilterCategoryIds.includes(categoryId), [requiredHourlyFilterCategoryIds]);
|
|
46938
|
+
const manualHourlySnapshotKey = useMemo(() => {
|
|
46939
|
+
if (activeInitialTimeFilter || !isTimeFilterActive || !startTime || !endTime || !workspaceId || !date || shift === void 0) {
|
|
46940
|
+
return null;
|
|
46941
|
+
}
|
|
46942
|
+
return `${workspaceId}:${date}:${shift}:${startTime}:${endTime}:${activeTimeFilterTimezone}`;
|
|
46943
|
+
}, [
|
|
46944
|
+
activeInitialTimeFilter,
|
|
46945
|
+
activeTimeFilterTimezone,
|
|
46946
|
+
date,
|
|
46947
|
+
endTime,
|
|
46948
|
+
isTimeFilterActive,
|
|
46949
|
+
shift,
|
|
46950
|
+
startTime,
|
|
46951
|
+
workspaceId
|
|
46952
|
+
]);
|
|
46953
|
+
const manualHourlySnapshotAppliedKeyRef = useRef(null);
|
|
46954
|
+
const manualHourlySnapshotInFlightKeyRef = useRef(null);
|
|
46955
|
+
const [manualHourlySnapshotFailureKey, setManualHourlySnapshotFailureKey] = useState(null);
|
|
46956
|
+
const isManualHourlySnapshotPending = Boolean(
|
|
46957
|
+
manualHourlySnapshotKey && manualHourlySnapshotAppliedKeyRef.current !== manualHourlySnapshotKey && manualHourlySnapshotFailureKey !== manualHourlySnapshotKey
|
|
46958
|
+
);
|
|
46365
46959
|
const [categoryPages, setCategoryPages] = useState({});
|
|
46366
46960
|
const [categoryHasMore, setCategoryHasMore] = useState({});
|
|
46367
46961
|
const [localClipClassifications, setLocalClipClassifications] = useState({});
|
|
46368
46962
|
const clipMetadataRef = useRef({});
|
|
46369
46963
|
const inFlightMetadataRequestsRef = useRef(/* @__PURE__ */ new Set());
|
|
46964
|
+
const inFlightPercentileClipRequestsRef = useRef(/* @__PURE__ */ new Set());
|
|
46965
|
+
const autoSelectedScopedClipRef = useRef(null);
|
|
46370
46966
|
const previousIdleClipSortRef = useRef(idleClipSort);
|
|
46371
46967
|
const mergedClipClassifications = useMemo(() => ({
|
|
46372
46968
|
...clipClassifications || {},
|
|
@@ -46379,12 +46975,14 @@ var FileManagerFilters = ({
|
|
|
46379
46975
|
if (!initialTimeFilter?.startTime || !initialTimeFilter?.endTime) {
|
|
46380
46976
|
return;
|
|
46381
46977
|
}
|
|
46978
|
+
setActiveInitialTimeFilter(initialTimeFilter);
|
|
46382
46979
|
setStartTime(initialTimeFilter.startTime);
|
|
46383
46980
|
setEndTime(initialTimeFilter.endTime);
|
|
46384
46981
|
setIsTimeFilterActive(true);
|
|
46385
46982
|
setShowTimeFilterModal(false);
|
|
46386
46983
|
setStartSearchTerm("");
|
|
46387
46984
|
setEndSearchTerm("");
|
|
46985
|
+
setScopedCategoryTotals({});
|
|
46388
46986
|
}, [initialTimeFilter?.startTime, initialTimeFilter?.endTime]);
|
|
46389
46987
|
useEffect(() => {
|
|
46390
46988
|
if (previousIdleClipSortRef.current === idleClipSort) {
|
|
@@ -46416,18 +47014,66 @@ var FileManagerFilters = ({
|
|
|
46416
47014
|
return next;
|
|
46417
47015
|
});
|
|
46418
47016
|
}, [idleClipSort]);
|
|
47017
|
+
useEffect(() => {
|
|
47018
|
+
manualHourlySnapshotAppliedKeyRef.current = null;
|
|
47019
|
+
manualHourlySnapshotInFlightKeyRef.current = null;
|
|
47020
|
+
setManualHourlySnapshotFailureKey(null);
|
|
47021
|
+
setScopedCategoryTotals({});
|
|
47022
|
+
setClipMetadata({});
|
|
47023
|
+
setCategoryPages({});
|
|
47024
|
+
setCategoryHasMore({});
|
|
47025
|
+
setPercentileClips({});
|
|
47026
|
+
setPercentileCounts({
|
|
47027
|
+
"fast-cycles": null,
|
|
47028
|
+
"slow-cycles": null
|
|
47029
|
+
});
|
|
47030
|
+
}, [activeTimeFilterKey]);
|
|
46419
47031
|
const isCategoryExternallyManaged = useCallback((categoryId) => {
|
|
46420
47032
|
if (!categoryId) {
|
|
46421
47033
|
return false;
|
|
46422
47034
|
}
|
|
46423
|
-
if (
|
|
47035
|
+
if (isManualHourlySnapshotPending && requiredHourlyFilterCategoryIds.includes(categoryId)) {
|
|
47036
|
+
return true;
|
|
47037
|
+
}
|
|
47038
|
+
if (prefetchedClipMetadata && Array.isArray(prefetchedClipMetadata[categoryId]) && (prefetchedClipMetadata[categoryId].length > 0 || typeof prefetchedClipTotals?.[categoryId] === "number")) {
|
|
47039
|
+
return true;
|
|
47040
|
+
}
|
|
47041
|
+
if (prefetchedPercentileClips && Array.isArray(prefetchedPercentileClips[categoryId]) && (prefetchedPercentileClips[categoryId].length > 0 || isCategoryScopedByTimeFilter(categoryId) && typeof prefetchedClipTotals?.[categoryId] === "number")) {
|
|
46424
47042
|
return true;
|
|
46425
47043
|
}
|
|
46426
47044
|
if (externallyManagedLoadingCategories?.[categoryId]) {
|
|
46427
47045
|
return true;
|
|
46428
47046
|
}
|
|
46429
47047
|
return false;
|
|
46430
|
-
}, [
|
|
47048
|
+
}, [
|
|
47049
|
+
externallyManagedLoadingCategories,
|
|
47050
|
+
isManualHourlySnapshotPending,
|
|
47051
|
+
isCategoryScopedByTimeFilter,
|
|
47052
|
+
prefetchedClipMetadata,
|
|
47053
|
+
prefetchedClipTotals,
|
|
47054
|
+
prefetchedPercentileClips,
|
|
47055
|
+
requiredHourlyFilterCategoryIds
|
|
47056
|
+
]);
|
|
47057
|
+
const getAvailableClipMetadata = useCallback((categoryId) => {
|
|
47058
|
+
const localClips = clipMetadata[categoryId];
|
|
47059
|
+
if (Array.isArray(localClips) && localClips.length > 0) {
|
|
47060
|
+
return localClips;
|
|
47061
|
+
}
|
|
47062
|
+
const prefetchedClips = prefetchedClipMetadata?.[categoryId];
|
|
47063
|
+
if (Array.isArray(prefetchedClips) && prefetchedClips.length > 0) {
|
|
47064
|
+
return prefetchedClips;
|
|
47065
|
+
}
|
|
47066
|
+
return [];
|
|
47067
|
+
}, [clipMetadata, prefetchedClipMetadata]);
|
|
47068
|
+
const hasKnownClipMetadata = useCallback((categoryId) => {
|
|
47069
|
+
if (Array.isArray(clipMetadata[categoryId])) {
|
|
47070
|
+
return true;
|
|
47071
|
+
}
|
|
47072
|
+
if (Array.isArray(prefetchedClipMetadata?.[categoryId])) {
|
|
47073
|
+
return true;
|
|
47074
|
+
}
|
|
47075
|
+
return typeof prefetchedClipTotals?.[categoryId] === "number";
|
|
47076
|
+
}, [clipMetadata, prefetchedClipMetadata, prefetchedClipTotals]);
|
|
46431
47077
|
useEffect(() => {
|
|
46432
47078
|
if (!prefetchedClipMetadata) {
|
|
46433
47079
|
return;
|
|
@@ -46450,6 +47096,22 @@ var FileManagerFilters = ({
|
|
|
46450
47096
|
});
|
|
46451
47097
|
return changed ? next : prev;
|
|
46452
47098
|
});
|
|
47099
|
+
setScopedCategoryTotals((prev) => {
|
|
47100
|
+
let changed = false;
|
|
47101
|
+
const next = { ...prev };
|
|
47102
|
+
Object.entries(prefetchedClipMetadata).forEach(([categoryId, clips]) => {
|
|
47103
|
+
if (!Array.isArray(clips) || !isCategoryScopedByTimeFilter(categoryId)) {
|
|
47104
|
+
return;
|
|
47105
|
+
}
|
|
47106
|
+
const nextTotal = typeof prefetchedClipTotals?.[categoryId] === "number" ? Math.max(0, prefetchedClipTotals[categoryId]) : clips.length;
|
|
47107
|
+
if (next[categoryId] === nextTotal) {
|
|
47108
|
+
return;
|
|
47109
|
+
}
|
|
47110
|
+
next[categoryId] = nextTotal;
|
|
47111
|
+
changed = true;
|
|
47112
|
+
});
|
|
47113
|
+
return changed ? next : prev;
|
|
47114
|
+
});
|
|
46453
47115
|
setCategoryPages((prev) => {
|
|
46454
47116
|
let changed = false;
|
|
46455
47117
|
const next = { ...prev };
|
|
@@ -46474,7 +47136,7 @@ var FileManagerFilters = ({
|
|
|
46474
47136
|
return;
|
|
46475
47137
|
}
|
|
46476
47138
|
const knownTotal = typeof counts?.[categoryId] === "number" ? counts[categoryId] : null;
|
|
46477
|
-
const inferredHasMore = knownTotal !== null ? clips.length < knownTotal : prev[categoryId];
|
|
47139
|
+
const inferredHasMore = isCategoryScopedByTimeFilter(categoryId) ? false : knownTotal !== null ? clips.length < knownTotal : prev[categoryId];
|
|
46478
47140
|
if (typeof inferredHasMore !== "boolean" || next[categoryId] === inferredHasMore) {
|
|
46479
47141
|
return;
|
|
46480
47142
|
}
|
|
@@ -46483,8 +47145,68 @@ var FileManagerFilters = ({
|
|
|
46483
47145
|
});
|
|
46484
47146
|
return changed ? next : prev;
|
|
46485
47147
|
});
|
|
46486
|
-
}, [prefetchedClipMetadata, counts]);
|
|
47148
|
+
}, [prefetchedClipMetadata, prefetchedClipTotals, counts, isCategoryScopedByTimeFilter]);
|
|
47149
|
+
useEffect(() => {
|
|
47150
|
+
if (!prefetchedPercentileClips) {
|
|
47151
|
+
return;
|
|
47152
|
+
}
|
|
47153
|
+
setPercentileClips((prev) => {
|
|
47154
|
+
let changed = false;
|
|
47155
|
+
const next = { ...prev };
|
|
47156
|
+
["fast-cycles", "slow-cycles"].forEach((categoryId) => {
|
|
47157
|
+
const clips = prefetchedPercentileClips[categoryId];
|
|
47158
|
+
if (!Array.isArray(clips)) {
|
|
47159
|
+
return;
|
|
47160
|
+
}
|
|
47161
|
+
const previousClips = prev[categoryId] || [];
|
|
47162
|
+
const previousSignature = previousClips.map((clip) => clip.id).join("|");
|
|
47163
|
+
const nextSignature = clips.map((clip) => clip.id).join("|");
|
|
47164
|
+
if (previousSignature === nextSignature) {
|
|
47165
|
+
return;
|
|
47166
|
+
}
|
|
47167
|
+
next[categoryId] = clips;
|
|
47168
|
+
changed = true;
|
|
47169
|
+
});
|
|
47170
|
+
return changed ? next : prev;
|
|
47171
|
+
});
|
|
47172
|
+
setPercentileCounts((prev) => {
|
|
47173
|
+
let changed = false;
|
|
47174
|
+
const next = { ...prev };
|
|
47175
|
+
["fast-cycles", "slow-cycles"].forEach((categoryId) => {
|
|
47176
|
+
const clips = prefetchedPercentileClips[categoryId];
|
|
47177
|
+
if (!Array.isArray(clips)) {
|
|
47178
|
+
return;
|
|
47179
|
+
}
|
|
47180
|
+
const nextTotal = typeof prefetchedClipTotals?.[categoryId] === "number" ? Math.max(0, prefetchedClipTotals[categoryId]) : clips.length;
|
|
47181
|
+
if (next[categoryId] === nextTotal) {
|
|
47182
|
+
return;
|
|
47183
|
+
}
|
|
47184
|
+
next[categoryId] = nextTotal;
|
|
47185
|
+
changed = true;
|
|
47186
|
+
});
|
|
47187
|
+
return changed ? next : prev;
|
|
47188
|
+
});
|
|
47189
|
+
}, [prefetchedClipTotals, prefetchedPercentileClips]);
|
|
46487
47190
|
const { state: filterState } = useClipFilter();
|
|
47191
|
+
const shouldShowCategory = useCallback((categoryId) => {
|
|
47192
|
+
switch (categoryId) {
|
|
47193
|
+
case "fast-cycles":
|
|
47194
|
+
return showPercentileCycleFilters && filterState.showFastCycles;
|
|
47195
|
+
case "slow-cycles":
|
|
47196
|
+
return showPercentileCycleFilters && filterState.showSlowCycles;
|
|
47197
|
+
case "longest-idles":
|
|
47198
|
+
return false;
|
|
47199
|
+
// filterState.showLongestIdles; // Temporarily disabled
|
|
47200
|
+
case "cycle_completion":
|
|
47201
|
+
return filterState.showCycleCompletion;
|
|
47202
|
+
case "idle_time":
|
|
47203
|
+
return filterState.showIdleTime;
|
|
47204
|
+
case "sop_deviations":
|
|
47205
|
+
return filterState.showSopDeviations;
|
|
47206
|
+
default:
|
|
47207
|
+
return true;
|
|
47208
|
+
}
|
|
47209
|
+
}, [filterState, showPercentileCycleFilters]);
|
|
46488
47210
|
const [percentileCounts, setPercentileCounts] = useState({
|
|
46489
47211
|
"fast-cycles": null,
|
|
46490
47212
|
"slow-cycles": null
|
|
@@ -46594,11 +47316,12 @@ var FileManagerFilters = ({
|
|
|
46594
47316
|
return null;
|
|
46595
47317
|
}
|
|
46596
47318
|
}, [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]);
|
|
47319
|
+
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
47320
|
const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
|
|
46599
47321
|
if (!workspaceId || !date || shift === void 0) {
|
|
46600
47322
|
throw new Error("Missing required params for clip metadata fetch");
|
|
46601
47323
|
}
|
|
47324
|
+
const shouldScopeToTimeFilter = isCategoryScopedByTimeFilter(categoryId);
|
|
46602
47325
|
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
46603
47326
|
method: "POST",
|
|
46604
47327
|
headers: {
|
|
@@ -46612,9 +47335,12 @@ var FileManagerFilters = ({
|
|
|
46612
47335
|
category: categoryId,
|
|
46613
47336
|
page,
|
|
46614
47337
|
limit: CLIP_METADATA_PAGE_SIZE,
|
|
46615
|
-
knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
|
|
47338
|
+
knownTotal: shouldScopeToTimeFilter ? null : typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
|
|
46616
47339
|
snapshotDateTime,
|
|
46617
47340
|
snapshotClipId,
|
|
47341
|
+
startTime: shouldScopeToTimeFilter ? startTime : void 0,
|
|
47342
|
+
endTime: shouldScopeToTimeFilter ? endTime : void 0,
|
|
47343
|
+
timeFilterTimezone: shouldScopeToTimeFilter ? activeTimeFilterTimezone : void 0,
|
|
46618
47344
|
sort: categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
|
|
46619
47345
|
}),
|
|
46620
47346
|
redirectReason: "session_expired"
|
|
@@ -46623,7 +47349,20 @@ var FileManagerFilters = ({
|
|
|
46623
47349
|
throw new Error(`API error: ${response.status}`);
|
|
46624
47350
|
}
|
|
46625
47351
|
return response.json();
|
|
46626
|
-
}, [
|
|
47352
|
+
}, [
|
|
47353
|
+
activeTimeFilterTimezone,
|
|
47354
|
+
endTime,
|
|
47355
|
+
isCategoryScopedByTimeFilter,
|
|
47356
|
+
startTime,
|
|
47357
|
+
workspaceId,
|
|
47358
|
+
date,
|
|
47359
|
+
shift,
|
|
47360
|
+
counts,
|
|
47361
|
+
snapshotDateTime,
|
|
47362
|
+
snapshotClipId,
|
|
47363
|
+
idleClipSort,
|
|
47364
|
+
supabase
|
|
47365
|
+
]);
|
|
46627
47366
|
const seedIdleClassifications = useCallback(async (clips) => {
|
|
46628
47367
|
if (!idleTimeVlmEnabled || clips.length === 0) {
|
|
46629
47368
|
return;
|
|
@@ -46691,6 +47430,12 @@ var FileManagerFilters = ({
|
|
|
46691
47430
|
...prev,
|
|
46692
47431
|
[categoryId]: page === 1 ? data.clips : [...prev[categoryId] || [], ...data.clips]
|
|
46693
47432
|
}));
|
|
47433
|
+
if (isCategoryScopedByTimeFilter(categoryId)) {
|
|
47434
|
+
setScopedCategoryTotals((prev) => ({
|
|
47435
|
+
...prev,
|
|
47436
|
+
[categoryId]: Math.max(0, Number(data.total || 0))
|
|
47437
|
+
}));
|
|
47438
|
+
}
|
|
46694
47439
|
if (categoryId === "idle_time" && idleTimeVlmEnabled) {
|
|
46695
47440
|
await seedIdleClassifications(data.clips || []);
|
|
46696
47441
|
}
|
|
@@ -46707,7 +47452,94 @@ var FileManagerFilters = ({
|
|
|
46707
47452
|
return newSet;
|
|
46708
47453
|
});
|
|
46709
47454
|
}
|
|
46710
|
-
}, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey]);
|
|
47455
|
+
}, [workspaceId, date, shift, fetchClipMetadataPage, idleTimeVlmEnabled, seedIdleClassifications, getMetadataLoadingKey, isCategoryScopedByTimeFilter]);
|
|
47456
|
+
useCallback(async (categoryId) => {
|
|
47457
|
+
if (!workspaceId || !date || shift === void 0) {
|
|
47458
|
+
console.warn("[FileManager] Missing required params for full clip metadata fetch");
|
|
47459
|
+
return;
|
|
47460
|
+
}
|
|
47461
|
+
const loadingKey = `${getMetadataLoadingKey(categoryId, 1)}-all`;
|
|
47462
|
+
if (inFlightMetadataRequestsRef.current.has(loadingKey)) {
|
|
47463
|
+
return;
|
|
47464
|
+
}
|
|
47465
|
+
inFlightMetadataRequestsRef.current.add(loadingKey);
|
|
47466
|
+
setLoadingCategories((prev) => /* @__PURE__ */ new Set([...prev, loadingKey]));
|
|
47467
|
+
try {
|
|
47468
|
+
let accumulatedClips = [];
|
|
47469
|
+
let currentPage = 0;
|
|
47470
|
+
let hasMore = true;
|
|
47471
|
+
while (hasMore) {
|
|
47472
|
+
const nextPage = currentPage + 1;
|
|
47473
|
+
const pageData = await fetchClipMetadataPage(categoryId, nextPage);
|
|
47474
|
+
const pageClips = pageData.clips || [];
|
|
47475
|
+
accumulatedClips = [...accumulatedClips, ...pageClips];
|
|
47476
|
+
currentPage = nextPage;
|
|
47477
|
+
hasMore = Boolean(pageData.hasMore && pageClips.length > 0);
|
|
47478
|
+
}
|
|
47479
|
+
const dedupedClips = accumulatedClips.filter((clip, index, arr) => {
|
|
47480
|
+
const clipKey = clip.clipId || clip.id;
|
|
47481
|
+
return arr.findIndex((item) => (item.clipId || item.id) === clipKey) === index;
|
|
47482
|
+
});
|
|
47483
|
+
setClipMetadata((prev) => ({
|
|
47484
|
+
...prev,
|
|
47485
|
+
[categoryId]: dedupedClips
|
|
47486
|
+
}));
|
|
47487
|
+
setCategoryPages((prev) => ({ ...prev, [categoryId]: Math.max(currentPage, 1) }));
|
|
47488
|
+
setCategoryHasMore((prev) => ({ ...prev, [categoryId]: false }));
|
|
47489
|
+
if (categoryId === "idle_time" && idleTimeVlmEnabled) {
|
|
47490
|
+
await seedIdleClassifications(dedupedClips);
|
|
47491
|
+
}
|
|
47492
|
+
console.log(`[FileManager] Loaded all ${dedupedClips.length} clips for ${categoryId} due to chart time filter`);
|
|
47493
|
+
} catch (error) {
|
|
47494
|
+
console.error("[FileManager] Error fetching full clip metadata:", error);
|
|
47495
|
+
} finally {
|
|
47496
|
+
inFlightMetadataRequestsRef.current.delete(loadingKey);
|
|
47497
|
+
setLoadingCategories((prev) => {
|
|
47498
|
+
const newSet = new Set(prev);
|
|
47499
|
+
newSet.delete(loadingKey);
|
|
47500
|
+
return newSet;
|
|
47501
|
+
});
|
|
47502
|
+
}
|
|
47503
|
+
}, [
|
|
47504
|
+
workspaceId,
|
|
47505
|
+
date,
|
|
47506
|
+
shift,
|
|
47507
|
+
fetchClipMetadataPage,
|
|
47508
|
+
idleTimeVlmEnabled,
|
|
47509
|
+
seedIdleClassifications,
|
|
47510
|
+
getMetadataLoadingKey
|
|
47511
|
+
]);
|
|
47512
|
+
const isInitialTimeFilterCategory = useCallback((categoryId) => {
|
|
47513
|
+
if (!startTime || !endTime || !activeInitialTimeFilter) {
|
|
47514
|
+
return false;
|
|
47515
|
+
}
|
|
47516
|
+
if (activeFilter === categoryId) {
|
|
47517
|
+
return true;
|
|
47518
|
+
}
|
|
47519
|
+
if (activeInitialTimeFilter.categoryId === categoryId) {
|
|
47520
|
+
return true;
|
|
47521
|
+
}
|
|
47522
|
+
return Array.isArray(activeInitialTimeFilter.categoryIds) && activeInitialTimeFilter.categoryIds.includes(categoryId);
|
|
47523
|
+
}, [
|
|
47524
|
+
activeFilter,
|
|
47525
|
+
activeInitialTimeFilter,
|
|
47526
|
+
endTime,
|
|
47527
|
+
startTime
|
|
47528
|
+
]);
|
|
47529
|
+
const hasCompleteMetadataForInitialTimeFilter = useCallback((categoryId) => {
|
|
47530
|
+
if (!isInitialTimeFilterCategory(categoryId)) {
|
|
47531
|
+
return true;
|
|
47532
|
+
}
|
|
47533
|
+
const loadedClips = clipMetadataRef.current[categoryId] || [];
|
|
47534
|
+
const knownTotal = typeof scopedCategoryTotals[categoryId] === "number" ? scopedCategoryTotals[categoryId] : null;
|
|
47535
|
+
if (categoryHasMore[categoryId]) {
|
|
47536
|
+
return false;
|
|
47537
|
+
}
|
|
47538
|
+
if (knownTotal !== null && loadedClips.length < knownTotal) {
|
|
47539
|
+
return false;
|
|
47540
|
+
}
|
|
47541
|
+
return loadedClips.length > 0 || knownTotal === 0;
|
|
47542
|
+
}, [categoryHasMore, isInitialTimeFilterCategory, scopedCategoryTotals]);
|
|
46711
47543
|
const ensureAllIdleTimeClipMetadataLoaded = useCallback(async () => {
|
|
46712
47544
|
if (!workspaceId || !date || shift === void 0) {
|
|
46713
47545
|
return;
|
|
@@ -46773,6 +47605,12 @@ var FileManagerFilters = ({
|
|
|
46773
47605
|
console.warn("[FileManager] Missing required params for percentile clips fetch");
|
|
46774
47606
|
return;
|
|
46775
47607
|
}
|
|
47608
|
+
const shouldScopeToTimeFilter = isCategoryScopedByTimeFilter(type);
|
|
47609
|
+
const requestKey = `${type}:${date}:${shift}:${filterState.percentile}:${shouldScopeToTimeFilter ? activeTimeFilterKey : "unscoped"}`;
|
|
47610
|
+
if (inFlightPercentileClipRequestsRef.current.has(requestKey)) {
|
|
47611
|
+
return;
|
|
47612
|
+
}
|
|
47613
|
+
inFlightPercentileClipRequestsRef.current.add(requestKey);
|
|
46776
47614
|
try {
|
|
46777
47615
|
const startDate = `${date}T00:00:00Z`;
|
|
46778
47616
|
const endDate = `${date}T23:59:59Z`;
|
|
@@ -46788,7 +47626,10 @@ var FileManagerFilters = ({
|
|
|
46788
47626
|
endDate,
|
|
46789
47627
|
percentile: filterState.percentile,
|
|
46790
47628
|
shiftId: shift,
|
|
46791
|
-
limit:
|
|
47629
|
+
limit: shouldScopeToTimeFilter ? 500 : 100,
|
|
47630
|
+
startTime: shouldScopeToTimeFilter ? startTime : void 0,
|
|
47631
|
+
endTime: shouldScopeToTimeFilter ? endTime : void 0,
|
|
47632
|
+
timeFilterTimezone: shouldScopeToTimeFilter ? activeTimeFilterTimezone : void 0,
|
|
46792
47633
|
// The actual percentile action (fast-cycles, slow-cycles, idle-times)
|
|
46793
47634
|
percentileAction: type
|
|
46794
47635
|
}),
|
|
@@ -46803,7 +47644,7 @@ var FileManagerFilters = ({
|
|
|
46803
47644
|
[type]: data.clips || []
|
|
46804
47645
|
}));
|
|
46805
47646
|
setPercentileCounts((prev) => {
|
|
46806
|
-
if (typeof prev[type] === "number") {
|
|
47647
|
+
if (!shouldScopeToTimeFilter && typeof prev[type] === "number") {
|
|
46807
47648
|
return prev;
|
|
46808
47649
|
}
|
|
46809
47650
|
return {
|
|
@@ -46814,8 +47655,206 @@ var FileManagerFilters = ({
|
|
|
46814
47655
|
console.log(`[FileManager] Loaded ${data.clips?.length || 0} ${type} clips (percentile: ${filterState.percentile}%)`);
|
|
46815
47656
|
} catch (error) {
|
|
46816
47657
|
console.error(`[FileManager] Error fetching ${type} clips:`, error);
|
|
47658
|
+
} finally {
|
|
47659
|
+
inFlightPercentileClipRequestsRef.current.delete(requestKey);
|
|
47660
|
+
}
|
|
47661
|
+
}, [
|
|
47662
|
+
activeTimeFilterTimezone,
|
|
47663
|
+
activeTimeFilterKey,
|
|
47664
|
+
endTime,
|
|
47665
|
+
isCategoryScopedByTimeFilter,
|
|
47666
|
+
startTime,
|
|
47667
|
+
workspaceId,
|
|
47668
|
+
date,
|
|
47669
|
+
shift,
|
|
47670
|
+
filterState.percentile,
|
|
47671
|
+
showPercentileCycleFilters,
|
|
47672
|
+
supabase
|
|
47673
|
+
]);
|
|
47674
|
+
useEffect(() => {
|
|
47675
|
+
if (!manualHourlySnapshotKey) {
|
|
47676
|
+
return;
|
|
47677
|
+
}
|
|
47678
|
+
if (manualHourlySnapshotAppliedKeyRef.current === manualHourlySnapshotKey) {
|
|
47679
|
+
return;
|
|
47680
|
+
}
|
|
47681
|
+
if (manualHourlySnapshotInFlightKeyRef.current === manualHourlySnapshotKey) {
|
|
47682
|
+
return;
|
|
47683
|
+
}
|
|
47684
|
+
manualHourlySnapshotInFlightKeyRef.current = manualHourlySnapshotKey;
|
|
47685
|
+
setManualHourlySnapshotFailureKey((prev) => prev === manualHourlySnapshotKey ? null : prev);
|
|
47686
|
+
const applyHourlySnapshot = async () => {
|
|
47687
|
+
try {
|
|
47688
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
47689
|
+
method: "POST",
|
|
47690
|
+
headers: {
|
|
47691
|
+
"Content-Type": "application/json"
|
|
47692
|
+
},
|
|
47693
|
+
body: JSON.stringify({
|
|
47694
|
+
action: "hourly-snapshot",
|
|
47695
|
+
workspaceId,
|
|
47696
|
+
date,
|
|
47697
|
+
shift,
|
|
47698
|
+
startTime,
|
|
47699
|
+
endTime,
|
|
47700
|
+
timeFilterTimezone: activeTimeFilterTimezone
|
|
47701
|
+
}),
|
|
47702
|
+
redirectReason: "session_expired"
|
|
47703
|
+
});
|
|
47704
|
+
if (!response.ok) {
|
|
47705
|
+
throw new Error(`API error: ${response.status}`);
|
|
47706
|
+
}
|
|
47707
|
+
const snapshot = await response.json();
|
|
47708
|
+
const metadataByCategory = snapshot?.metadataByCategory && typeof snapshot.metadataByCategory === "object" ? snapshot.metadataByCategory : {};
|
|
47709
|
+
const percentileClipsByCategory = snapshot?.percentileClipsByCategory && typeof snapshot.percentileClipsByCategory === "object" ? snapshot.percentileClipsByCategory : {};
|
|
47710
|
+
const rawTotalsByCategory = snapshot?.totalsByCategory && typeof snapshot.totalsByCategory === "object" ? snapshot.totalsByCategory : {};
|
|
47711
|
+
const totalsByCategory = requiredHourlyFilterCategoryIds.reduce((accumulator, categoryId) => {
|
|
47712
|
+
const rawTotal = rawTotalsByCategory[categoryId];
|
|
47713
|
+
if (typeof rawTotal === "number" && Number.isFinite(rawTotal)) {
|
|
47714
|
+
accumulator[categoryId] = Math.max(0, rawTotal);
|
|
47715
|
+
return accumulator;
|
|
47716
|
+
}
|
|
47717
|
+
if (categoryId === "fast-cycles" || categoryId === "slow-cycles") {
|
|
47718
|
+
accumulator[categoryId] = Array.isArray(percentileClipsByCategory[categoryId]) ? percentileClipsByCategory[categoryId].length : 0;
|
|
47719
|
+
return accumulator;
|
|
47720
|
+
}
|
|
47721
|
+
accumulator[categoryId] = Array.isArray(metadataByCategory[categoryId]) ? metadataByCategory[categoryId].length : 0;
|
|
47722
|
+
return accumulator;
|
|
47723
|
+
}, {});
|
|
47724
|
+
setClipMetadata((prev) => {
|
|
47725
|
+
const next = { ...prev };
|
|
47726
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
47727
|
+
if (categoryId === "fast-cycles" || categoryId === "slow-cycles") {
|
|
47728
|
+
return;
|
|
47729
|
+
}
|
|
47730
|
+
next[categoryId] = Array.isArray(metadataByCategory[categoryId]) ? metadataByCategory[categoryId] : [];
|
|
47731
|
+
});
|
|
47732
|
+
return next;
|
|
47733
|
+
});
|
|
47734
|
+
setScopedCategoryTotals((prev) => ({
|
|
47735
|
+
...prev,
|
|
47736
|
+
...totalsByCategory
|
|
47737
|
+
}));
|
|
47738
|
+
if (showPercentileCycleFilters) {
|
|
47739
|
+
setPercentileClips((prev) => ({
|
|
47740
|
+
...prev,
|
|
47741
|
+
"fast-cycles": Array.isArray(percentileClipsByCategory["fast-cycles"]) ? percentileClipsByCategory["fast-cycles"] : [],
|
|
47742
|
+
"slow-cycles": Array.isArray(percentileClipsByCategory["slow-cycles"]) ? percentileClipsByCategory["slow-cycles"] : []
|
|
47743
|
+
}));
|
|
47744
|
+
setPercentileCounts((prev) => ({
|
|
47745
|
+
...prev,
|
|
47746
|
+
"fast-cycles": totalsByCategory["fast-cycles"] ?? 0,
|
|
47747
|
+
"slow-cycles": totalsByCategory["slow-cycles"] ?? 0
|
|
47748
|
+
}));
|
|
47749
|
+
}
|
|
47750
|
+
setCategoryPages((prev) => {
|
|
47751
|
+
const next = { ...prev };
|
|
47752
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
47753
|
+
next[categoryId] = 1;
|
|
47754
|
+
});
|
|
47755
|
+
return next;
|
|
47756
|
+
});
|
|
47757
|
+
setCategoryHasMore((prev) => {
|
|
47758
|
+
const next = { ...prev };
|
|
47759
|
+
requiredHourlyFilterCategoryIds.forEach((categoryId) => {
|
|
47760
|
+
next[categoryId] = false;
|
|
47761
|
+
});
|
|
47762
|
+
return next;
|
|
47763
|
+
});
|
|
47764
|
+
const idleClips = metadataByCategory.idle_time;
|
|
47765
|
+
if (Array.isArray(idleClips) && idleClips.length > 0) {
|
|
47766
|
+
await seedIdleClassifications(idleClips);
|
|
47767
|
+
}
|
|
47768
|
+
manualHourlySnapshotAppliedKeyRef.current = manualHourlySnapshotKey;
|
|
47769
|
+
setManualHourlySnapshotFailureKey((prev) => prev === manualHourlySnapshotKey ? null : prev);
|
|
47770
|
+
} catch (error) {
|
|
47771
|
+
console.error("[FileManager] Error fetching manual hourly snapshot:", error);
|
|
47772
|
+
setManualHourlySnapshotFailureKey(manualHourlySnapshotKey);
|
|
47773
|
+
} finally {
|
|
47774
|
+
if (manualHourlySnapshotInFlightKeyRef.current === manualHourlySnapshotKey) {
|
|
47775
|
+
manualHourlySnapshotInFlightKeyRef.current = null;
|
|
47776
|
+
}
|
|
47777
|
+
}
|
|
47778
|
+
};
|
|
47779
|
+
void applyHourlySnapshot();
|
|
47780
|
+
}, [
|
|
47781
|
+
activeTimeFilterTimezone,
|
|
47782
|
+
date,
|
|
47783
|
+
endTime,
|
|
47784
|
+
manualHourlySnapshotKey,
|
|
47785
|
+
requiredHourlyFilterCategoryIds,
|
|
47786
|
+
seedIdleClassifications,
|
|
47787
|
+
shift,
|
|
47788
|
+
showPercentileCycleFilters,
|
|
47789
|
+
startTime,
|
|
47790
|
+
supabase,
|
|
47791
|
+
workspaceId
|
|
47792
|
+
]);
|
|
47793
|
+
useEffect(() => {
|
|
47794
|
+
if (!startTime || !endTime || !activeInitialTimeFilter || initialTimeFilterCategoryIds.length === 0) {
|
|
47795
|
+
return;
|
|
46817
47796
|
}
|
|
46818
|
-
|
|
47797
|
+
initialTimeFilterCategoryIds.forEach((categoryId) => {
|
|
47798
|
+
if (categoryId === "fast-cycles" || categoryId === "slow-cycles") {
|
|
47799
|
+
const hasScopedPercentileResult = typeof percentileCounts[categoryId] === "number";
|
|
47800
|
+
if (!isCategoryExternallyManaged(categoryId) && !hasScopedPercentileResult && showPercentileCycleFilters) {
|
|
47801
|
+
fetchPercentileClips(categoryId);
|
|
47802
|
+
}
|
|
47803
|
+
return;
|
|
47804
|
+
}
|
|
47805
|
+
if (isCategoryExternallyManaged(categoryId)) {
|
|
47806
|
+
return;
|
|
47807
|
+
}
|
|
47808
|
+
if (!hasCompleteMetadataForInitialTimeFilter(categoryId)) {
|
|
47809
|
+
fetchClipMetadata(categoryId, 1);
|
|
47810
|
+
}
|
|
47811
|
+
});
|
|
47812
|
+
}, [
|
|
47813
|
+
activeInitialTimeFilter,
|
|
47814
|
+
endTime,
|
|
47815
|
+
fetchClipMetadata,
|
|
47816
|
+
fetchPercentileClips,
|
|
47817
|
+
hasCompleteMetadataForInitialTimeFilter,
|
|
47818
|
+
initialTimeFilterCategoryIds,
|
|
47819
|
+
isCategoryExternallyManaged,
|
|
47820
|
+
percentileCounts,
|
|
47821
|
+
showPercentileCycleFilters,
|
|
47822
|
+
startTime
|
|
47823
|
+
]);
|
|
47824
|
+
useEffect(() => {
|
|
47825
|
+
if (!startTime || !endTime || !isTimeFilterActive || activeInitialTimeFilter) {
|
|
47826
|
+
return;
|
|
47827
|
+
}
|
|
47828
|
+
categoriesForTree.forEach((category) => {
|
|
47829
|
+
if (!shouldShowCategory(category.id) || isCategoryExternallyManaged(category.id)) {
|
|
47830
|
+
return;
|
|
47831
|
+
}
|
|
47832
|
+
if (typeof scopedCategoryTotals[category.id] !== "number") {
|
|
47833
|
+
fetchClipMetadata(category.id, 1);
|
|
47834
|
+
}
|
|
47835
|
+
});
|
|
47836
|
+
if (showPercentileCycleFilters) {
|
|
47837
|
+
if (!isCategoryExternallyManaged("fast-cycles") && typeof percentileCounts["fast-cycles"] !== "number") {
|
|
47838
|
+
fetchPercentileClips("fast-cycles");
|
|
47839
|
+
}
|
|
47840
|
+
if (!isCategoryExternallyManaged("slow-cycles") && typeof percentileCounts["slow-cycles"] !== "number") {
|
|
47841
|
+
fetchPercentileClips("slow-cycles");
|
|
47842
|
+
}
|
|
47843
|
+
}
|
|
47844
|
+
}, [
|
|
47845
|
+
activeInitialTimeFilter,
|
|
47846
|
+
categoriesForTree,
|
|
47847
|
+
endTime,
|
|
47848
|
+
fetchClipMetadata,
|
|
47849
|
+
fetchPercentileClips,
|
|
47850
|
+
isCategoryExternallyManaged,
|
|
47851
|
+
isTimeFilterActive,
|
|
47852
|
+
percentileCounts,
|
|
47853
|
+
scopedCategoryTotals,
|
|
47854
|
+
shouldShowCategory,
|
|
47855
|
+
showPercentileCycleFilters,
|
|
47856
|
+
startTime
|
|
47857
|
+
]);
|
|
46819
47858
|
const percentileCountsKey = useMemo(() => {
|
|
46820
47859
|
if (!workspaceId || !date || shift === void 0) {
|
|
46821
47860
|
return null;
|
|
@@ -46838,12 +47877,15 @@ var FileManagerFilters = ({
|
|
|
46838
47877
|
}
|
|
46839
47878
|
percentileCountsKeyRef.current = percentileCountsKey;
|
|
46840
47879
|
percentilePrefetchRef.current = { key: null, types: /* @__PURE__ */ new Set() };
|
|
47880
|
+
if (prefetchedPercentileClips && (Array.isArray(prefetchedPercentileClips["fast-cycles"]) || Array.isArray(prefetchedPercentileClips["slow-cycles"]))) {
|
|
47881
|
+
return;
|
|
47882
|
+
}
|
|
46841
47883
|
setPercentileCounts({
|
|
46842
47884
|
"fast-cycles": null,
|
|
46843
47885
|
"slow-cycles": null
|
|
46844
47886
|
});
|
|
46845
47887
|
setPercentileClips({});
|
|
46846
|
-
}, [showPercentileCycleFilters, percentileCountsKey]);
|
|
47888
|
+
}, [prefetchedPercentileClips, showPercentileCycleFilters, percentileCountsKey]);
|
|
46847
47889
|
useEffect(() => {
|
|
46848
47890
|
if (!showPercentileCycleFilters) {
|
|
46849
47891
|
return;
|
|
@@ -46899,11 +47941,20 @@ var FileManagerFilters = ({
|
|
|
46899
47941
|
const data = await response.json();
|
|
46900
47942
|
const fastCycles = data?.counts?.["fast-cycles"];
|
|
46901
47943
|
const slowCycles = data?.counts?.["slow-cycles"];
|
|
46902
|
-
|
|
46903
|
-
|
|
46904
|
-
|
|
46905
|
-
|
|
46906
|
-
|
|
47944
|
+
if (typeof fastCycles === "number" || typeof slowCycles === "number") {
|
|
47945
|
+
setPercentileCounts((prev) => {
|
|
47946
|
+
const nextFastCycles = typeof fastCycles === "number" ? fastCycles : prev["fast-cycles"];
|
|
47947
|
+
const nextSlowCycles = typeof slowCycles === "number" ? slowCycles : prev["slow-cycles"];
|
|
47948
|
+
if (prev["fast-cycles"] === nextFastCycles && prev["slow-cycles"] === nextSlowCycles) {
|
|
47949
|
+
return prev;
|
|
47950
|
+
}
|
|
47951
|
+
return {
|
|
47952
|
+
...prev,
|
|
47953
|
+
"fast-cycles": nextFastCycles,
|
|
47954
|
+
"slow-cycles": nextSlowCycles
|
|
47955
|
+
};
|
|
47956
|
+
});
|
|
47957
|
+
}
|
|
46907
47958
|
if (options?.prefetchClips) {
|
|
46908
47959
|
if (percentilePrefetchRef.current.key !== requestKey) {
|
|
46909
47960
|
percentilePrefetchRef.current = { key: requestKey, types: /* @__PURE__ */ new Set() };
|
|
@@ -46922,37 +47973,30 @@ var FileManagerFilters = ({
|
|
|
46922
47973
|
}
|
|
46923
47974
|
}, [workspaceId, date, shift, filterState.percentile, showPercentileCycleFilters, supabase, percentileCounts, percentileClips, fetchPercentileClips]);
|
|
46924
47975
|
useEffect(() => {
|
|
46925
|
-
if (!showPercentileCycleFilters || !isReady || !percentileCountsKey) {
|
|
47976
|
+
if (!showPercentileCycleFilters || !isReady || !percentileCountsKey || isTimeFilterActive) {
|
|
46926
47977
|
return;
|
|
46927
47978
|
}
|
|
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;
|
|
47979
|
+
fetchPercentileCounts({ prefetchClips: true });
|
|
47980
|
+
}, [showPercentileCycleFilters, isReady, percentileCountsKey, fetchPercentileCounts, isTimeFilterActive]);
|
|
47981
|
+
useEffect(() => {
|
|
47982
|
+
if (!isReady || isTimeFilterActive || activeFilter !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
47983
|
+
return;
|
|
46954
47984
|
}
|
|
46955
|
-
|
|
47985
|
+
["cycle_completion", "idle_time"].forEach((categoryId) => {
|
|
47986
|
+
if ((counts?.[categoryId] || 0) <= 0 || hasKnownClipMetadata(categoryId) || isCategoryExternallyManaged(categoryId)) {
|
|
47987
|
+
return;
|
|
47988
|
+
}
|
|
47989
|
+
fetchClipMetadata(categoryId, 1);
|
|
47990
|
+
});
|
|
47991
|
+
}, [
|
|
47992
|
+
activeFilter,
|
|
47993
|
+
counts,
|
|
47994
|
+
fetchClipMetadata,
|
|
47995
|
+
hasKnownClipMetadata,
|
|
47996
|
+
isCategoryExternallyManaged,
|
|
47997
|
+
isReady,
|
|
47998
|
+
isTimeFilterActive
|
|
47999
|
+
]);
|
|
46956
48000
|
const getPercentileIcon = useCallback((type, isExpanded, colorClasses) => {
|
|
46957
48001
|
const iconMap = {
|
|
46958
48002
|
"fast-cycles": { icon: TrendingUp, color: "text-green-600" },
|
|
@@ -46981,12 +48025,29 @@ var FileManagerFilters = ({
|
|
|
46981
48025
|
newExpanded.add(activeFilter);
|
|
46982
48026
|
return newExpanded;
|
|
46983
48027
|
});
|
|
46984
|
-
const category =
|
|
46985
|
-
if (category
|
|
46986
|
-
|
|
48028
|
+
const category = categoriesForTree.find((cat) => cat.id === activeFilter);
|
|
48029
|
+
if (category) {
|
|
48030
|
+
if (isInitialTimeFilterCategory(activeFilter) && !isCategoryExternallyManaged(activeFilter) && !hasCompleteMetadataForInitialTimeFilter(activeFilter)) {
|
|
48031
|
+
fetchClipMetadata(activeFilter, 1);
|
|
48032
|
+
} else if (!isCategoryExternallyManaged(activeFilter) && !clipMetadataRef.current[activeFilter]) {
|
|
48033
|
+
fetchClipMetadata(activeFilter, 1);
|
|
48034
|
+
}
|
|
46987
48035
|
}
|
|
46988
48036
|
}
|
|
46989
48037
|
}, [activeFilter]);
|
|
48038
|
+
useEffect(() => {
|
|
48039
|
+
const requestedCategory = activeFilter;
|
|
48040
|
+
if (!requestedCategory || !isInitialTimeFilterCategory(requestedCategory) || isCategoryExternallyManaged(requestedCategory) || hasCompleteMetadataForInitialTimeFilter(requestedCategory)) {
|
|
48041
|
+
return;
|
|
48042
|
+
}
|
|
48043
|
+
fetchClipMetadata(requestedCategory, 1);
|
|
48044
|
+
}, [
|
|
48045
|
+
activeFilter,
|
|
48046
|
+
fetchClipMetadata,
|
|
48047
|
+
hasCompleteMetadataForInitialTimeFilter,
|
|
48048
|
+
isCategoryExternallyManaged,
|
|
48049
|
+
isInitialTimeFilterCategory
|
|
48050
|
+
]);
|
|
46990
48051
|
useEffect(() => {
|
|
46991
48052
|
const handleEscape = (e) => {
|
|
46992
48053
|
if (e.key === "Escape") {
|
|
@@ -47050,25 +48111,34 @@ var FileManagerFilters = ({
|
|
|
47050
48111
|
}
|
|
47051
48112
|
try {
|
|
47052
48113
|
const clipDate = new Date(clipTimestamp);
|
|
47053
|
-
const
|
|
48114
|
+
const clipParts = new Intl.DateTimeFormat("en-US", {
|
|
47054
48115
|
hour12: false,
|
|
47055
48116
|
hour: "2-digit",
|
|
47056
48117
|
minute: "2-digit",
|
|
47057
|
-
timeZone:
|
|
47058
|
-
});
|
|
47059
|
-
|
|
48118
|
+
timeZone: activeTimeFilterTimezone
|
|
48119
|
+
}).formatToParts(clipDate);
|
|
48120
|
+
const hourValue = clipParts.find((part) => part.type === "hour")?.value;
|
|
48121
|
+
const minuteValue = clipParts.find((part) => part.type === "minute")?.value;
|
|
48122
|
+
const clipMinute = timeValueToMinutes(`${hourValue}:${minuteValue}`);
|
|
48123
|
+
return clipMinute === null ? false : isMinuteInTimeWindow(clipMinute, startTime, endTime);
|
|
47060
48124
|
} catch (error) {
|
|
47061
48125
|
console.error("[FileManager] Error parsing clip timestamp:", error);
|
|
47062
48126
|
return true;
|
|
47063
48127
|
}
|
|
47064
|
-
}, [isTimeFilterActive, startTime, endTime,
|
|
48128
|
+
}, [isTimeFilterActive, startTime, endTime, activeTimeFilterTimezone]);
|
|
47065
48129
|
const filterTree = useMemo(() => {
|
|
47066
48130
|
const tree = [];
|
|
47067
48131
|
const regularCategoryNodes = [];
|
|
47068
|
-
|
|
48132
|
+
categoriesForTree.forEach((category) => {
|
|
48133
|
+
if (category.id === "fast-cycles" || category.id === "slow-cycles") {
|
|
48134
|
+
return;
|
|
48135
|
+
}
|
|
47069
48136
|
const categoryCount = counts?.[category.id] || 0;
|
|
47070
|
-
const
|
|
47071
|
-
|
|
48137
|
+
const categoryMetadataClips = getAvailableClipMetadata(category.id);
|
|
48138
|
+
const categoryVideoFallbackClips = categoryMetadataClips.length === 0 && isInitialTimeFilterCategory(category.id) ? videos.filter((video) => video.type === category.id).map(buildClipMetadataFromVideo).filter((clip) => isClipInTimeRange(clip.clip_timestamp)) : [];
|
|
48139
|
+
const categoryClips = categoryMetadataClips.length > 0 ? categoryMetadataClips : categoryVideoFallbackClips;
|
|
48140
|
+
const timeFilteredClips = categoryClips.filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
48141
|
+
let filteredClips = timeFilteredClips;
|
|
47072
48142
|
if (category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
47073
48143
|
filteredClips = sortRedFlowMetadata(filteredClips);
|
|
47074
48144
|
}
|
|
@@ -47078,9 +48148,22 @@ var FileManagerFilters = ({
|
|
|
47078
48148
|
return classification?.label === idleLabelFilter;
|
|
47079
48149
|
});
|
|
47080
48150
|
}
|
|
47081
|
-
const
|
|
48151
|
+
const scopedTotal = typeof scopedCategoryTotals[category.id] === "number" ? scopedCategoryTotals[category.id] : null;
|
|
48152
|
+
const isScopedByTimeFilter = isCategoryScopedByTimeFilter(category.id);
|
|
48153
|
+
const scopedPageLoaded = isScopedByTimeFilter && typeof scopedCategoryTotals[category.id] === "number";
|
|
48154
|
+
const scopedResponseHadOutOfHourClips = categoryClips.length > filteredClips.length;
|
|
48155
|
+
const shouldTrustScopedTotal = !scopedResponseHadOutOfHourClips || Boolean(categoryHasMore[category.id]);
|
|
48156
|
+
const isCategoryMetadataLoading = Array.from(loadingCategories).some((key) => key.startsWith(`${category.id}-`));
|
|
48157
|
+
const isScopedTotalPending = isTimeFilterActive && isScopedByTimeFilter && scopedTotal === null;
|
|
48158
|
+
const displayCount = isScopedTotalPending ? null : isTimeFilterActive && isScopedByTimeFilter && scopedTotal !== null ? shouldTrustScopedTotal ? scopedTotal : filteredClips.length : isTimeFilterActive || category.id === "idle_time" && idleLabelFilter ? filteredClips.length : categoryCount;
|
|
48159
|
+
const shouldShowScopedEmptyCategory = Boolean(
|
|
48160
|
+
scopedPageLoaded && !isCategoryMetadataLoading && !categoryHasMore[category.id] && filteredClips.length === 0 && (isRequiredHourlyFilterCategory(category.id) || activeFilter === category.id)
|
|
48161
|
+
);
|
|
48162
|
+
const shouldShowScopedLoadingCategory = Boolean(
|
|
48163
|
+
isScopedTotalPending && (isRequiredHourlyFilterCategory(category.id) || !activeInitialTimeFilter || activeFilter === category.id)
|
|
48164
|
+
);
|
|
47082
48165
|
const shouldShowEmptyIdleTime = category.id === "idle_time" && idleLabelFilter;
|
|
47083
|
-
if ((displayCount > 0 || shouldShowEmptyIdleTime) && shouldShowCategory(category.id)) {
|
|
48166
|
+
if ((typeof displayCount === "number" && displayCount > 0 || shouldShowEmptyIdleTime || isCategoryMetadataLoading || shouldShowScopedEmptyCategory || shouldShowScopedLoadingCategory) && shouldShowCategory(category.id)) {
|
|
47084
48167
|
const colorClasses = getColorClasses(category.color);
|
|
47085
48168
|
const clipNodes = filteredClips.map((clip, index) => {
|
|
47086
48169
|
const cycleTime = extractCycleTimeSeconds(clip);
|
|
@@ -47090,7 +48173,7 @@ var FileManagerFilters = ({
|
|
|
47090
48173
|
const baseTimeLabel = formatClipExplorerTimeLabel({
|
|
47091
48174
|
categoryId: category.id,
|
|
47092
48175
|
clipTimestamp: clip.clip_timestamp,
|
|
47093
|
-
timezone,
|
|
48176
|
+
timezone: activeTimeFilterTimezone,
|
|
47094
48177
|
durationSeconds: idleDuration ?? clip.duration,
|
|
47095
48178
|
idleStartTime: clip.idle_start_time,
|
|
47096
48179
|
idleEndTime: clip.idle_end_time,
|
|
@@ -47128,6 +48211,7 @@ var FileManagerFilters = ({
|
|
|
47128
48211
|
type: "category",
|
|
47129
48212
|
count: displayCount,
|
|
47130
48213
|
// Use filtered count when time filter is active
|
|
48214
|
+
countLoading: isScopedTotalPending || isCategoryMetadataLoading && scopedTotal === null,
|
|
47131
48215
|
children: clipNodes,
|
|
47132
48216
|
// Use clip nodes from metadata
|
|
47133
48217
|
icon: expandedNodes.has(category.id) ? /* @__PURE__ */ jsx(FolderOpen, { className: `h-4 w-4 ${colorClasses.text}` }) : getCategoryIcon(category.icon, colorClasses),
|
|
@@ -47135,10 +48219,18 @@ var FileManagerFilters = ({
|
|
|
47135
48219
|
});
|
|
47136
48220
|
}
|
|
47137
48221
|
});
|
|
47138
|
-
const filteredFastCycles = (
|
|
47139
|
-
|
|
48222
|
+
const filteredFastCycles = sortPercentileCycleClipsForDisplay(
|
|
48223
|
+
"fast-cycles",
|
|
48224
|
+
(percentileClips["fast-cycles"] || []).filter((clip) => isClipInTimeRange(clip.creation_timestamp || ""))
|
|
48225
|
+
);
|
|
48226
|
+
const filteredSlowCycles = sortPercentileCycleClipsForDisplay(
|
|
48227
|
+
"slow-cycles",
|
|
48228
|
+
(percentileClips["slow-cycles"] || []).filter((clip) => isClipInTimeRange(clip.creation_timestamp || ""))
|
|
48229
|
+
);
|
|
47140
48230
|
const fastCount = typeof percentileCounts["fast-cycles"] === "number" ? percentileCounts["fast-cycles"] : null;
|
|
47141
48231
|
const slowCount = typeof percentileCounts["slow-cycles"] === "number" ? percentileCounts["slow-cycles"] : null;
|
|
48232
|
+
const isFastCountPending = showPercentileCycleFilters && fastCount === null;
|
|
48233
|
+
const isSlowCountPending = showPercentileCycleFilters && slowCount === null;
|
|
47142
48234
|
const percentileCategories = showPercentileCycleFilters ? [
|
|
47143
48235
|
{
|
|
47144
48236
|
id: "fast-cycles",
|
|
@@ -47147,6 +48239,7 @@ var FileManagerFilters = ({
|
|
|
47147
48239
|
description: "Top 10% fastest performance",
|
|
47148
48240
|
type: "percentile-category",
|
|
47149
48241
|
count: isTimeFilterActive ? fastCount === null && filteredFastCycles.length === 0 ? null : filteredFastCycles.length : fastCount,
|
|
48242
|
+
countLoading: isFastCountPending,
|
|
47150
48243
|
icon: getPercentileIcon("fast-cycles", expandedNodes.has("fast-cycles"), { text: "text-green-600" }),
|
|
47151
48244
|
color: "green",
|
|
47152
48245
|
percentileType: "fast-cycles",
|
|
@@ -47158,7 +48251,7 @@ var FileManagerFilters = ({
|
|
|
47158
48251
|
label: `${formatClipExplorerTimeLabel({
|
|
47159
48252
|
categoryId: "fast-cycles",
|
|
47160
48253
|
clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
|
|
47161
|
-
timezone,
|
|
48254
|
+
timezone: activeTimeFilterTimezone,
|
|
47162
48255
|
durationSeconds: cycleTime
|
|
47163
48256
|
})}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
47164
48257
|
type: "video",
|
|
@@ -47178,6 +48271,7 @@ var FileManagerFilters = ({
|
|
|
47178
48271
|
description: "Bottom 10% slowest performance",
|
|
47179
48272
|
type: "percentile-category",
|
|
47180
48273
|
count: isTimeFilterActive ? slowCount === null && filteredSlowCycles.length === 0 ? null : filteredSlowCycles.length : slowCount,
|
|
48274
|
+
countLoading: isSlowCountPending,
|
|
47181
48275
|
icon: getPercentileIcon("slow-cycles", expandedNodes.has("slow-cycles"), { text: "text-red-600" }),
|
|
47182
48276
|
color: "red",
|
|
47183
48277
|
percentileType: "slow-cycles",
|
|
@@ -47189,7 +48283,7 @@ var FileManagerFilters = ({
|
|
|
47189
48283
|
label: `${formatClipExplorerTimeLabel({
|
|
47190
48284
|
categoryId: "slow-cycles",
|
|
47191
48285
|
clipTimestamp: clip.creation_timestamp || clip.timestamp || "",
|
|
47192
|
-
timezone,
|
|
48286
|
+
timezone: activeTimeFilterTimezone,
|
|
47193
48287
|
durationSeconds: cycleTime
|
|
47194
48288
|
})}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
47195
48289
|
type: "video",
|
|
@@ -47220,7 +48314,7 @@ var FileManagerFilters = ({
|
|
|
47220
48314
|
hour12: true,
|
|
47221
48315
|
hour: 'numeric',
|
|
47222
48316
|
minute: '2-digit',
|
|
47223
|
-
timeZone:
|
|
48317
|
+
timeZone: activeTimeFilterTimezone
|
|
47224
48318
|
});
|
|
47225
48319
|
|
|
47226
48320
|
return {
|
|
@@ -47239,7 +48333,11 @@ var FileManagerFilters = ({
|
|
|
47239
48333
|
const orderedIds = [RECENT_FLOW_RED_STREAK_CLIP_TYPE2, "cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
47240
48334
|
orderedIds.forEach((orderedId) => {
|
|
47241
48335
|
const percentileCategory = percentileCategories.find((cat) => cat.id === orderedId);
|
|
47242
|
-
const shouldIncludePercentile = percentileCategory ? typeof percentileCategory.count === "number"
|
|
48336
|
+
const shouldIncludePercentile = percentileCategory ? typeof percentileCategory.count === "number" || Boolean(
|
|
48337
|
+
isTimeFilterActive && isRequiredHourlyFilterCategory(orderedId) && typeof percentileCategory.count === "number" && percentileCategory.count === 0
|
|
48338
|
+
) || Boolean(
|
|
48339
|
+
percentileCategory.countLoading && (isRequiredHourlyFilterCategory(orderedId) || !activeInitialTimeFilter || activeFilter === orderedId)
|
|
48340
|
+
) : false;
|
|
47243
48341
|
if (percentileCategory && shouldIncludePercentile && shouldShowCategory(orderedId)) {
|
|
47244
48342
|
tree.push(percentileCategory);
|
|
47245
48343
|
}
|
|
@@ -47254,23 +48352,263 @@ var FileManagerFilters = ({
|
|
|
47254
48352
|
}
|
|
47255
48353
|
});
|
|
47256
48354
|
percentileCategories.forEach((category) => {
|
|
47257
|
-
const shouldIncludePercentile = typeof category.count === "number"
|
|
48355
|
+
const shouldIncludePercentile = typeof category.count === "number" || Boolean(
|
|
48356
|
+
isTimeFilterActive && isRequiredHourlyFilterCategory(category.id) && typeof category.count === "number" && category.count === 0
|
|
48357
|
+
) || Boolean(
|
|
48358
|
+
category.countLoading && (isRequiredHourlyFilterCategory(category.id) || !activeInitialTimeFilter || activeFilter === category.id)
|
|
48359
|
+
);
|
|
47258
48360
|
if (!orderedIds.includes(category.id) && shouldIncludePercentile && shouldShowCategory(category.id)) {
|
|
47259
48361
|
tree.push(category);
|
|
47260
48362
|
}
|
|
47261
48363
|
});
|
|
47262
48364
|
return tree;
|
|
47263
|
-
}, [
|
|
48365
|
+
}, [categoriesForTree, expandedNodes, counts, getAvailableClipMetadata, percentileCounts, percentileClips, shouldShowCategory, getPercentileIcon, isClipInTimeRange, isTimeFilterActive, showPercentileCycleFilters, loadingCategories, activeTimeFilterTimezone, isInitialTimeFilterCategory, isRequiredHourlyFilterCategory, hasCompleteMetadataForInitialTimeFilter, scopedCategoryTotals, isCategoryScopedByTimeFilter, categoryHasMore, activeFilter]);
|
|
48366
|
+
const chartHandoffVideoFallbackTree = useMemo(() => {
|
|
48367
|
+
if (!startTime || !endTime || !activeInitialTimeFilter || !activeFilter) {
|
|
48368
|
+
return [];
|
|
48369
|
+
}
|
|
48370
|
+
const fallbackCategory = categoriesForTree.find((category) => category.id === activeFilter) || categoriesForTree.find((category) => videos.some((video) => video.type === category.id));
|
|
48371
|
+
if (!fallbackCategory) {
|
|
48372
|
+
return [];
|
|
48373
|
+
}
|
|
48374
|
+
const fallbackVideos = videos.filter((video) => video.type === fallbackCategory.id);
|
|
48375
|
+
const sourceVideos = fallbackVideos.map(buildClipMetadataFromVideo).filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
48376
|
+
if (sourceVideos.length === 0) {
|
|
48377
|
+
return [];
|
|
48378
|
+
}
|
|
48379
|
+
const colorClasses = getColorClasses(fallbackCategory.color);
|
|
48380
|
+
const clipNodes = sourceVideos.map((clip, index) => {
|
|
48381
|
+
const cycleTime = extractCycleTimeSeconds(clip);
|
|
48382
|
+
const baseTimeLabel = formatClipExplorerTimeLabel({
|
|
48383
|
+
categoryId: fallbackCategory.id,
|
|
48384
|
+
clipTimestamp: clip.clip_timestamp,
|
|
48385
|
+
timezone: activeTimeFilterTimezone,
|
|
48386
|
+
durationSeconds: clip.duration,
|
|
48387
|
+
idleStartTime: clip.idle_start_time,
|
|
48388
|
+
idleEndTime: clip.idle_end_time,
|
|
48389
|
+
clipStartTime: clip.clip_start_time,
|
|
48390
|
+
clipEndTime: clip.clip_end_time
|
|
48391
|
+
});
|
|
48392
|
+
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)` : ""}`;
|
|
48393
|
+
return {
|
|
48394
|
+
id: clip.id,
|
|
48395
|
+
label: displayLabel,
|
|
48396
|
+
type: "video",
|
|
48397
|
+
icon: getSeverityIcon(clip.severity, fallbackCategory.id, cycleTime, resolvedTargetCycleTime, clip.clipId),
|
|
48398
|
+
timestamp: clip.clip_timestamp,
|
|
48399
|
+
severity: clip.severity,
|
|
48400
|
+
clipId: clip.clipId,
|
|
48401
|
+
categoryId: fallbackCategory.id,
|
|
48402
|
+
clipPosition: index + 1,
|
|
48403
|
+
cycleTimeSeconds: cycleTime,
|
|
48404
|
+
duration: clip.duration,
|
|
48405
|
+
cycleItemCount: null,
|
|
48406
|
+
redFlowSeverityScore: clip.red_flow_severity_score ?? null,
|
|
48407
|
+
redFlowExplanationSummary: clip.red_flow_explanation_summary ?? clip.red_flow_explanation?.summary ?? null
|
|
48408
|
+
};
|
|
48409
|
+
});
|
|
48410
|
+
return [{
|
|
48411
|
+
id: activeFilter,
|
|
48412
|
+
label: fallbackCategory.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_LABEL : fallbackCategory.label,
|
|
48413
|
+
subtitle: fallbackCategory.subtitle || fallbackCategory.description,
|
|
48414
|
+
description: fallbackCategory.description,
|
|
48415
|
+
type: "category",
|
|
48416
|
+
count: clipNodes.length,
|
|
48417
|
+
children: clipNodes,
|
|
48418
|
+
icon: /* @__PURE__ */ jsx(FolderOpen, { className: `h-4 w-4 ${colorClasses.text}` }),
|
|
48419
|
+
color: fallbackCategory.color
|
|
48420
|
+
}];
|
|
48421
|
+
}, [
|
|
48422
|
+
activeFilter,
|
|
48423
|
+
activeInitialTimeFilter,
|
|
48424
|
+
activeTimeFilterTimezone,
|
|
48425
|
+
categoriesForTree,
|
|
48426
|
+
counts,
|
|
48427
|
+
currentVideoId,
|
|
48428
|
+
endTime,
|
|
48429
|
+
getDisplayValue,
|
|
48430
|
+
isClipInTimeRange,
|
|
48431
|
+
resolvedTargetCycleTime,
|
|
48432
|
+
startTime,
|
|
48433
|
+
videos
|
|
48434
|
+
]);
|
|
48435
|
+
const displayedFilterTree = useMemo(() => {
|
|
48436
|
+
if (chartHandoffVideoFallbackTree.length === 0) {
|
|
48437
|
+
return filterTree;
|
|
48438
|
+
}
|
|
48439
|
+
if (filterTree.length === 0) {
|
|
48440
|
+
return chartHandoffVideoFallbackTree;
|
|
48441
|
+
}
|
|
48442
|
+
const fallbackNode = chartHandoffVideoFallbackTree[0];
|
|
48443
|
+
const activeNode = filterTree.find((node) => node.id === activeFilter);
|
|
48444
|
+
const activeNodeHasChildren = (activeNode?.children?.length || 0) > 0;
|
|
48445
|
+
const shouldReplaceActiveNode = Boolean(
|
|
48446
|
+
activeFilter && fallbackNode && activeNode && !activeNodeHasChildren && isInitialTimeFilterCategory(activeFilter)
|
|
48447
|
+
);
|
|
48448
|
+
if (!shouldReplaceActiveNode) {
|
|
48449
|
+
return filterTree;
|
|
48450
|
+
}
|
|
48451
|
+
return filterTree.map((node) => node.id === activeFilter ? fallbackNode : node);
|
|
48452
|
+
}, [activeFilter, chartHandoffVideoFallbackTree, filterTree, isInitialTimeFilterCategory]);
|
|
48453
|
+
const getSelectionContextForNodes = useCallback((categoryId, clipNodes) => {
|
|
48454
|
+
const normalizeSeverity = (severity) => severity === "low" || severity === "medium" || severity === "high" ? severity : "medium";
|
|
48455
|
+
const scopedNodes = clipNodes.filter((node) => node.type === "video" && Boolean(node.clipId || node.id));
|
|
48456
|
+
const scopedNodeClips = scopedNodes.map((node, index) => ({
|
|
48457
|
+
id: node.clipId || node.id,
|
|
48458
|
+
clipId: node.clipId || node.id,
|
|
48459
|
+
clip_timestamp: node.timestamp || "",
|
|
48460
|
+
creation_timestamp: node.timestamp || "",
|
|
48461
|
+
description: node.label,
|
|
48462
|
+
severity: normalizeSeverity(node.severity),
|
|
48463
|
+
category: categoryId,
|
|
48464
|
+
duration: node.duration,
|
|
48465
|
+
cycle_time_seconds: node.cycleTimeSeconds,
|
|
48466
|
+
index
|
|
48467
|
+
}));
|
|
48468
|
+
const categoryClips = getAvailableClipMetadata(categoryId);
|
|
48469
|
+
const contextClips = isCategoryScopedByTimeFilter(categoryId) && scopedNodeClips.length > 0 ? scopedNodeClips : categoryClips.length > 0 ? categoryClips : scopedNodeClips;
|
|
48470
|
+
const scopedTotal = scopedCategoryTotals[categoryId];
|
|
48471
|
+
const total = typeof scopedTotal === "number" ? scopedTotal : counts?.[categoryId];
|
|
48472
|
+
return contextClips.length ? { clips: contextClips, total } : void 0;
|
|
48473
|
+
}, [counts, getAvailableClipMetadata, isCategoryScopedByTimeFilter, scopedCategoryTotals]);
|
|
48474
|
+
useEffect(() => {
|
|
48475
|
+
if (!activeInitialTimeFilter || !startTime || !endTime || currentVideoId || !onClipSelect) {
|
|
48476
|
+
return;
|
|
48477
|
+
}
|
|
48478
|
+
const categoryPriority = Array.from(new Set([
|
|
48479
|
+
activeInitialTimeFilter.categoryId,
|
|
48480
|
+
activeFilter,
|
|
48481
|
+
...activeInitialTimeFilter.categoryIds || []
|
|
48482
|
+
].filter((value) => typeof value === "string" && value.length > 0)));
|
|
48483
|
+
const preferredCategoryId = categoryPriority[0];
|
|
48484
|
+
const orderedCategoryNodes = displayedFilterTree.filter((categoryNode) => isInitialTimeFilterCategory(categoryNode.id)).sort((left, right) => {
|
|
48485
|
+
const leftIndex = categoryPriority.indexOf(left.id);
|
|
48486
|
+
const rightIndex = categoryPriority.indexOf(right.id);
|
|
48487
|
+
const leftPriority = leftIndex === -1 ? Number.MAX_SAFE_INTEGER : leftIndex;
|
|
48488
|
+
const rightPriority = rightIndex === -1 ? Number.MAX_SAFE_INTEGER : rightIndex;
|
|
48489
|
+
return leftPriority - rightPriority;
|
|
48490
|
+
});
|
|
48491
|
+
const preferredCategoryNode = preferredCategoryId ? orderedCategoryNodes.find((categoryNode) => categoryNode.id === preferredCategoryId) : void 0;
|
|
48492
|
+
if (preferredCategoryId && !preferredCategoryNode) {
|
|
48493
|
+
const preferredKnownTotal = preferredCategoryId === "fast-cycles" || preferredCategoryId === "slow-cycles" ? percentileCounts[preferredCategoryId] : scopedCategoryTotals[preferredCategoryId];
|
|
48494
|
+
if (preferredKnownTotal !== 0) {
|
|
48495
|
+
return;
|
|
48496
|
+
}
|
|
48497
|
+
}
|
|
48498
|
+
const preferredFirstClipNode = preferredCategoryNode?.children?.find((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48499
|
+
if (preferredCategoryId && preferredCategoryNode && !preferredFirstClipNode) {
|
|
48500
|
+
const preferredKnownTotal = preferredCategoryId === "fast-cycles" || preferredCategoryId === "slow-cycles" ? percentileCounts[preferredCategoryId] : scopedCategoryTotals[preferredCategoryId];
|
|
48501
|
+
if (preferredKnownTotal !== 0) {
|
|
48502
|
+
return;
|
|
48503
|
+
}
|
|
48504
|
+
}
|
|
48505
|
+
for (const categoryNode of orderedCategoryNodes) {
|
|
48506
|
+
const firstClipNode = categoryNode.children?.find((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48507
|
+
if (!firstClipNode?.clipId || !firstClipNode.categoryId) {
|
|
48508
|
+
continue;
|
|
48509
|
+
}
|
|
48510
|
+
const selectionKey = `${activeTimeFilterKey}:${firstClipNode.categoryId}:${firstClipNode.clipId}:${currentVideoId || "none"}`;
|
|
48511
|
+
if (autoSelectedScopedClipRef.current === selectionKey) {
|
|
48512
|
+
return;
|
|
48513
|
+
}
|
|
48514
|
+
autoSelectedScopedClipRef.current = selectionKey;
|
|
48515
|
+
const selectionContext = getSelectionContextForNodes(firstClipNode.categoryId, categoryNode.children || []);
|
|
48516
|
+
onClipSelect(
|
|
48517
|
+
firstClipNode.categoryId,
|
|
48518
|
+
firstClipNode.clipId,
|
|
48519
|
+
firstClipNode.clipPosition,
|
|
48520
|
+
selectionContext
|
|
48521
|
+
);
|
|
48522
|
+
return;
|
|
48523
|
+
}
|
|
48524
|
+
}, [
|
|
48525
|
+
activeInitialTimeFilter,
|
|
48526
|
+
activeFilter,
|
|
48527
|
+
activeTimeFilterKey,
|
|
48528
|
+
currentVideoId,
|
|
48529
|
+
displayedFilterTree,
|
|
48530
|
+
endTime,
|
|
48531
|
+
getSelectionContextForNodes,
|
|
48532
|
+
isInitialTimeFilterCategory,
|
|
48533
|
+
onClipSelect,
|
|
48534
|
+
percentileCounts,
|
|
48535
|
+
scopedCategoryTotals,
|
|
48536
|
+
startTime
|
|
48537
|
+
]);
|
|
48538
|
+
const isChartHandoffLoading = useMemo(() => {
|
|
48539
|
+
if (!startTime || !endTime || !activeInitialTimeFilter || !activeFilter || !isInitialTimeFilterCategory(activeFilter)) {
|
|
48540
|
+
return false;
|
|
48541
|
+
}
|
|
48542
|
+
const pageOneLoadingKey = getMetadataLoadingKey(activeFilter, 1);
|
|
48543
|
+
return Boolean(
|
|
48544
|
+
activeCategoryLoading || Array.from(loadingCategories).some((key) => key === pageOneLoadingKey || key.startsWith(`${pageOneLoadingKey}-all`))
|
|
48545
|
+
);
|
|
48546
|
+
}, [
|
|
48547
|
+
activeCategoryLoading,
|
|
48548
|
+
activeFilter,
|
|
48549
|
+
activeInitialTimeFilter,
|
|
48550
|
+
endTime,
|
|
48551
|
+
getMetadataLoadingKey,
|
|
48552
|
+
isInitialTimeFilterCategory,
|
|
48553
|
+
loadingCategories,
|
|
48554
|
+
startTime
|
|
48555
|
+
]);
|
|
48556
|
+
useEffect(() => {
|
|
48557
|
+
if (!isTimeFilterActive || !startTime || !endTime || !activeFilter || activeFilter === "all" || !onClipSelect) {
|
|
48558
|
+
return;
|
|
48559
|
+
}
|
|
48560
|
+
const activeCategoryNode = displayedFilterTree.find((categoryNode) => categoryNode.id === activeFilter);
|
|
48561
|
+
const activeClipNodes = (activeCategoryNode?.children || []).filter((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48562
|
+
if (activeClipNodes.length === 0) {
|
|
48563
|
+
return;
|
|
48564
|
+
}
|
|
48565
|
+
const currentClipIsVisible = Boolean(
|
|
48566
|
+
currentVideoId && activeClipNodes.some((child) => (child.clipId || child.id) === currentVideoId)
|
|
48567
|
+
);
|
|
48568
|
+
if (currentClipIsVisible) {
|
|
48569
|
+
return;
|
|
48570
|
+
}
|
|
48571
|
+
const firstClipNode = activeClipNodes[0];
|
|
48572
|
+
if (!firstClipNode?.clipId || !firstClipNode.categoryId) {
|
|
48573
|
+
return;
|
|
48574
|
+
}
|
|
48575
|
+
const selectionKey = `${activeTimeFilterKey}:${firstClipNode.categoryId}:${firstClipNode.clipId}:${currentVideoId || "none"}`;
|
|
48576
|
+
if (autoSelectedScopedClipRef.current === selectionKey) {
|
|
48577
|
+
return;
|
|
48578
|
+
}
|
|
48579
|
+
autoSelectedScopedClipRef.current = selectionKey;
|
|
48580
|
+
const selectionContext = getSelectionContextForNodes(firstClipNode.categoryId, activeClipNodes);
|
|
48581
|
+
onClipSelect(
|
|
48582
|
+
firstClipNode.categoryId,
|
|
48583
|
+
firstClipNode.clipId,
|
|
48584
|
+
firstClipNode.clipPosition,
|
|
48585
|
+
selectionContext
|
|
48586
|
+
);
|
|
48587
|
+
}, [
|
|
48588
|
+
activeFilter,
|
|
48589
|
+
activeTimeFilterKey,
|
|
48590
|
+
currentVideoId,
|
|
48591
|
+
displayedFilterTree,
|
|
48592
|
+
endTime,
|
|
48593
|
+
getSelectionContextForNodes,
|
|
48594
|
+
isTimeFilterActive,
|
|
48595
|
+
onClipSelect,
|
|
48596
|
+
startTime
|
|
48597
|
+
]);
|
|
47264
48598
|
const toggleExpanded = (nodeId) => {
|
|
47265
48599
|
const newExpanded = new Set(expandedNodes);
|
|
47266
48600
|
if (newExpanded.has(nodeId)) {
|
|
47267
48601
|
newExpanded.delete(nodeId);
|
|
47268
48602
|
} else {
|
|
47269
48603
|
newExpanded.add(nodeId);
|
|
47270
|
-
const category =
|
|
47271
|
-
if (category
|
|
48604
|
+
const category = categoriesForTree.find((cat) => cat.id === nodeId);
|
|
48605
|
+
if (category) {
|
|
47272
48606
|
console.log(`[FileManager] Fetching clips for expanded category: ${nodeId}`);
|
|
47273
|
-
|
|
48607
|
+
if (isInitialTimeFilterCategory(nodeId) && !hasCompleteMetadataForInitialTimeFilter(nodeId)) {
|
|
48608
|
+
fetchClipMetadata(nodeId, 1);
|
|
48609
|
+
} else if (!hasKnownClipMetadata(nodeId) && !isCategoryExternallyManaged(nodeId)) {
|
|
48610
|
+
fetchClipMetadata(nodeId, 1);
|
|
48611
|
+
}
|
|
47274
48612
|
}
|
|
47275
48613
|
if (!isCategoryExternallyManaged(nodeId) && showPercentileCycleFilters && nodeId === "fast-cycles" && (percentileClips["fast-cycles"] || []).length === 0) {
|
|
47276
48614
|
fetchPercentileClips("fast-cycles");
|
|
@@ -47288,10 +48626,14 @@ var FileManagerFilters = ({
|
|
|
47288
48626
|
newExpanded.delete(node.id);
|
|
47289
48627
|
} else {
|
|
47290
48628
|
newExpanded.add(node.id);
|
|
47291
|
-
const category =
|
|
47292
|
-
if (category
|
|
48629
|
+
const category = categoriesForTree.find((cat) => cat.id === node.id);
|
|
48630
|
+
if (category) {
|
|
47293
48631
|
console.log(`[FileManager] Fetching clips for expanded category: ${node.id}`);
|
|
47294
|
-
|
|
48632
|
+
if (isInitialTimeFilterCategory(node.id) && !hasCompleteMetadataForInitialTimeFilter(node.id)) {
|
|
48633
|
+
fetchClipMetadata(node.id, 1);
|
|
48634
|
+
} else if (!hasKnownClipMetadata(node.id) && !isCategoryExternallyManaged(node.id)) {
|
|
48635
|
+
fetchClipMetadata(node.id, 1);
|
|
48636
|
+
}
|
|
47295
48637
|
}
|
|
47296
48638
|
if (!isCategoryExternallyManaged(node.id) && showPercentileCycleFilters && node.id === "fast-cycles" && (percentileClips["fast-cycles"] || []).length === 0) {
|
|
47297
48639
|
fetchPercentileClips("fast-cycles");
|
|
@@ -47301,7 +48643,21 @@ var FileManagerFilters = ({
|
|
|
47301
48643
|
}
|
|
47302
48644
|
}
|
|
47303
48645
|
setExpandedNodes(newExpanded);
|
|
47304
|
-
|
|
48646
|
+
if (node.id !== activeFilter) {
|
|
48647
|
+
onFilterChange(node.id);
|
|
48648
|
+
}
|
|
48649
|
+
if (isCategoryScopedByTimeFilter(node.id) && onClipSelect && node.children?.length) {
|
|
48650
|
+
const firstClipNode = node.children.find((child) => child.type === "video" && Boolean(child.clipId) && Boolean(child.categoryId));
|
|
48651
|
+
if (firstClipNode?.clipId && firstClipNode.categoryId) {
|
|
48652
|
+
const selectionContext = getSelectionContextForNodes(firstClipNode.categoryId, node.children);
|
|
48653
|
+
onClipSelect(
|
|
48654
|
+
firstClipNode.categoryId,
|
|
48655
|
+
firstClipNode.clipId,
|
|
48656
|
+
firstClipNode.clipPosition,
|
|
48657
|
+
selectionContext
|
|
48658
|
+
);
|
|
48659
|
+
}
|
|
48660
|
+
}
|
|
47305
48661
|
if (node.id === "fast-cycles") {
|
|
47306
48662
|
trackCoreEvent("Fast Clips Clicked", {
|
|
47307
48663
|
workspaceId,
|
|
@@ -47339,8 +48695,11 @@ var FileManagerFilters = ({
|
|
|
47339
48695
|
} else if (node.type === "video") {
|
|
47340
48696
|
if (onClipSelect && node.categoryId !== void 0 && node.clipId !== void 0) {
|
|
47341
48697
|
console.log(`[FileManager] Selecting clip: category=${node.categoryId}, clipId=${node.clipId}, position=${node.clipPosition}`);
|
|
47342
|
-
const
|
|
47343
|
-
const selectionContext =
|
|
48698
|
+
const categoryNode = displayedFilterTree.find((candidate) => candidate.id === node.categoryId);
|
|
48699
|
+
const selectionContext = getSelectionContextForNodes(
|
|
48700
|
+
node.categoryId,
|
|
48701
|
+
categoryNode?.children || [node]
|
|
48702
|
+
);
|
|
47344
48703
|
onClipSelect(node.categoryId, node.clipId, node.clipPosition, selectionContext);
|
|
47345
48704
|
} else {
|
|
47346
48705
|
const videoIndex = videos.findIndex((v) => v.id === node.id);
|
|
@@ -47353,24 +48712,40 @@ var FileManagerFilters = ({
|
|
|
47353
48712
|
const renderNode = (node, depth = 0) => {
|
|
47354
48713
|
const isExpanded = expandedNodes.has(node.id);
|
|
47355
48714
|
const isActive = activeFilter === node.id;
|
|
47356
|
-
const
|
|
47357
|
-
const
|
|
47358
|
-
|
|
47359
|
-
|
|
48715
|
+
const nodeClipId = node.clipId || node.id;
|
|
48716
|
+
const isCurrentVideo = Boolean(
|
|
48717
|
+
node.type === "video" && currentVideoId && currentVideoId === nodeClipId
|
|
48718
|
+
);
|
|
48719
|
+
const isCountUnknown = Boolean(
|
|
48720
|
+
(node.type === "category" || node.type === "percentile-category") && (node.count === null || node.countLoading)
|
|
48721
|
+
);
|
|
48722
|
+
const hasRenderedChildren = (node.children?.length || 0) > 0;
|
|
47360
48723
|
const loadedPage = categoryPages[node.id] || 0;
|
|
47361
48724
|
const pageOneLoadingKey = getMetadataLoadingKey(node.id, 1);
|
|
47362
48725
|
const nextMetadataPage = loadedPage + 1;
|
|
47363
48726
|
const nextLoadMorePage = (categoryPages[node.id] || 1) + 1;
|
|
47364
48727
|
const isPageOneLoading = loadingCategories.has(pageOneLoadingKey);
|
|
48728
|
+
const isFullCategoryLoading = Array.from(loadingCategories).some((key) => key.startsWith(`${pageOneLoadingKey}-all`));
|
|
47365
48729
|
const isLoadMoreLoading = loadedPage > 0 && loadingCategories.has(getMetadataLoadingKey(node.id, nextMetadataPage));
|
|
48730
|
+
const isNodeLoading = Boolean(
|
|
48731
|
+
isPageOneLoading || isFullCategoryLoading || activeCategoryLoading && node.id === activeFilter
|
|
48732
|
+
);
|
|
48733
|
+
const totalForLoadMore = isCategoryScopedByTimeFilter(node.id) && typeof scopedCategoryTotals[node.id] === "number" ? scopedCategoryTotals[node.id] : counts?.[node.id] || 0;
|
|
47366
48734
|
const showInitialLoadingState = Boolean(
|
|
47367
|
-
isExpanded && !
|
|
48735
|
+
isExpanded && !hasRenderedChildren && (node.type === "category" || node.type === "percentile-category") && isNodeLoading
|
|
48736
|
+
);
|
|
48737
|
+
const showScopedEmptyState = Boolean(
|
|
48738
|
+
isExpanded && !hasRenderedChildren && !isNodeLoading && !categoryHasMore[node.id] && isCategoryScopedByTimeFilter(node.id) && (node.type === "category" || node.type === "percentile-category")
|
|
47368
48739
|
);
|
|
48740
|
+
const hasChildren = isCountUnknown || (node.count || 0) > 0 || isNodeLoading || showScopedEmptyState;
|
|
47369
48741
|
const colorClasses = node.color ? getColorClasses(node.color) : null;
|
|
47370
48742
|
return /* @__PURE__ */ jsxs("div", { className: "select-none animate-in", children: [
|
|
47371
48743
|
/* @__PURE__ */ jsxs(
|
|
47372
48744
|
"div",
|
|
47373
48745
|
{
|
|
48746
|
+
"aria-current": isCurrentVideo ? "true" : void 0,
|
|
48747
|
+
"data-qa-clips-row-clip-id": node.type === "video" ? nodeClipId : void 0,
|
|
48748
|
+
"data-qa-clips-row-category-id": node.type === "video" ? node.categoryId : void 0,
|
|
47374
48749
|
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
48750
|
onClick: () => handleNodeClick(node),
|
|
47376
48751
|
children: [
|
|
@@ -47406,7 +48781,7 @@ var FileManagerFilters = ({
|
|
|
47406
48781
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
|
|
47407
48782
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
47408
48783
|
/* @__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 ||
|
|
48784
|
+
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
48785
|
node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
|
|
47411
48786
|
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
48787
|
// Show root cause label for idle time clips (text only, icon is on the left)
|
|
@@ -47442,7 +48817,7 @@ var FileManagerFilters = ({
|
|
|
47442
48817
|
})()
|
|
47443
48818
|
) })
|
|
47444
48819
|
] }),
|
|
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:
|
|
48820
|
+
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
48821
|
] })
|
|
47447
48822
|
]
|
|
47448
48823
|
}
|
|
@@ -47453,6 +48828,7 @@ var FileManagerFilters = ({
|
|
|
47453
48828
|
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
47454
48829
|
"Loading clips..."
|
|
47455
48830
|
] }) }),
|
|
48831
|
+
showScopedEmptyState && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center text-sm text-slate-500", children: "No clips found" }),
|
|
47456
48832
|
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
48833
|
/* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
|
|
47458
48834
|
"Loading more clips..."
|
|
@@ -47467,7 +48843,7 @@ var FileManagerFilters = ({
|
|
|
47467
48843
|
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
48844
|
children: [
|
|
47469
48845
|
"Load more clips (",
|
|
47470
|
-
(
|
|
48846
|
+
Math.max(0, totalForLoadMore - getAvailableClipMetadata(node.id).length),
|
|
47471
48847
|
" remaining)"
|
|
47472
48848
|
]
|
|
47473
48849
|
}
|
|
@@ -47530,6 +48906,8 @@ var FileManagerFilters = ({
|
|
|
47530
48906
|
e.stopPropagation();
|
|
47531
48907
|
setStartTime("");
|
|
47532
48908
|
setEndTime("");
|
|
48909
|
+
setActiveInitialTimeFilter(null);
|
|
48910
|
+
setScopedCategoryTotals({});
|
|
47533
48911
|
setIsTimeFilterActive(false);
|
|
47534
48912
|
},
|
|
47535
48913
|
className: "rounded-full p-0.5 transition-colors hover:bg-blue-100",
|
|
@@ -47663,6 +49041,8 @@ var FileManagerFilters = ({
|
|
|
47663
49041
|
onClick: () => {
|
|
47664
49042
|
setStartTime("");
|
|
47665
49043
|
setEndTime("");
|
|
49044
|
+
setActiveInitialTimeFilter(null);
|
|
49045
|
+
setScopedCategoryTotals({});
|
|
47666
49046
|
setStartSearchTerm("");
|
|
47667
49047
|
setEndSearchTerm("");
|
|
47668
49048
|
setIsTimeFilterActive(false);
|
|
@@ -47751,8 +49131,13 @@ var FileManagerFilters = ({
|
|
|
47751
49131
|
)
|
|
47752
49132
|
] }),
|
|
47753
49133
|
/* @__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
|
-
|
|
49134
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: displayedFilterTree.map((node) => renderNode(node)) }),
|
|
49135
|
+
displayedFilterTree.length === 0 && isChartHandoffLoading && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
49136
|
+
/* @__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" }) }),
|
|
49137
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "Loading clips..." }),
|
|
49138
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Finding clips from the selected hour" })
|
|
49139
|
+
] }),
|
|
49140
|
+
displayedFilterTree.length === 0 && !isChartHandoffLoading && (startTime || endTime) && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
47756
49141
|
/* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(Clock, { className: "h-12 w-12 mx-auto" }) }),
|
|
47757
49142
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips found" }),
|
|
47758
49143
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 mb-4", children: "No clips match the selected time range" }),
|
|
@@ -47762,6 +49147,8 @@ var FileManagerFilters = ({
|
|
|
47762
49147
|
onClick: () => {
|
|
47763
49148
|
setStartTime("");
|
|
47764
49149
|
setEndTime("");
|
|
49150
|
+
setActiveInitialTimeFilter(null);
|
|
49151
|
+
setScopedCategoryTotals({});
|
|
47765
49152
|
setIsTimeFilterActive(false);
|
|
47766
49153
|
},
|
|
47767
49154
|
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 +49156,12 @@ var FileManagerFilters = ({
|
|
|
47769
49156
|
}
|
|
47770
49157
|
)
|
|
47771
49158
|
] }),
|
|
47772
|
-
|
|
49159
|
+
displayedFilterTree.length === 0 && !startTime && !endTime && categories.length === 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
47773
49160
|
/* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(HelpCircle, { className: "h-12 w-12 mx-auto" }) }),
|
|
47774
49161
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clip types available" }),
|
|
47775
49162
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Loading clip categories..." })
|
|
47776
49163
|
] }),
|
|
47777
|
-
|
|
49164
|
+
displayedFilterTree.length === 0 && !startTime && !endTime && categories.length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-12", children: [
|
|
47778
49165
|
/* @__PURE__ */ jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsx(Play, { className: "h-12 w-12 mx-auto" }) }),
|
|
47779
49166
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips available" }),
|
|
47780
49167
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "No clips found for the selected time period" })
|
|
@@ -48181,6 +49568,65 @@ function useClipsRealtimeUpdates({
|
|
|
48181
49568
|
}
|
|
48182
49569
|
var LOW_EFFICIENCY_CATEGORY_ID = "recent_flow_red_streak";
|
|
48183
49570
|
var LOW_EFFICIENCY_AI_SUMMARY_ENABLED = process.env.NEXT_PUBLIC_LOW_EFFICIENCY_AI_SUMMARY_ENABLED === "true";
|
|
49571
|
+
var timeValueToMinutes2 = (value) => {
|
|
49572
|
+
const [hourValue, minuteValue] = value.substring(0, 5).split(":").map(Number);
|
|
49573
|
+
if (!Number.isInteger(hourValue) || !Number.isInteger(minuteValue) || hourValue < 0 || hourValue > 23 || minuteValue < 0 || minuteValue > 59) {
|
|
49574
|
+
return null;
|
|
49575
|
+
}
|
|
49576
|
+
return hourValue * 60 + minuteValue;
|
|
49577
|
+
};
|
|
49578
|
+
var isMinuteInTimeWindow2 = (minute, startValue, endValue) => {
|
|
49579
|
+
const startMinute = timeValueToMinutes2(startValue);
|
|
49580
|
+
const endMinute = timeValueToMinutes2(endValue);
|
|
49581
|
+
if (startMinute === null || endMinute === null) {
|
|
49582
|
+
return true;
|
|
49583
|
+
}
|
|
49584
|
+
return endMinute > startMinute ? minute >= startMinute && minute < endMinute : minute >= startMinute || minute < endMinute;
|
|
49585
|
+
};
|
|
49586
|
+
var CHART_HANDOFF_CATEGORY_FALLBACKS = {
|
|
49587
|
+
cycle_completion: {
|
|
49588
|
+
label: "Cycle Completion",
|
|
49589
|
+
description: "Successfully completed production cycles",
|
|
49590
|
+
color: "blue",
|
|
49591
|
+
icon: "check-circle"
|
|
49592
|
+
},
|
|
49593
|
+
"fast-cycles": {
|
|
49594
|
+
label: "Fast Cycles",
|
|
49595
|
+
description: "Fastest cycle clips",
|
|
49596
|
+
color: "green",
|
|
49597
|
+
icon: "trending-up"
|
|
49598
|
+
},
|
|
49599
|
+
"slow-cycles": {
|
|
49600
|
+
label: "Slow Cycles",
|
|
49601
|
+
description: "Slowest cycle clips",
|
|
49602
|
+
color: "red",
|
|
49603
|
+
icon: "trending-down"
|
|
49604
|
+
},
|
|
49605
|
+
idle_time: {
|
|
49606
|
+
label: "Idle Time",
|
|
49607
|
+
description: "Low value activities and idle moments",
|
|
49608
|
+
color: "amber",
|
|
49609
|
+
icon: "clock"
|
|
49610
|
+
},
|
|
49611
|
+
recent_flow_red_streak: {
|
|
49612
|
+
label: "Low moments",
|
|
49613
|
+
description: "Moments of low efficiency",
|
|
49614
|
+
color: "rose",
|
|
49615
|
+
icon: "alert-triangle"
|
|
49616
|
+
},
|
|
49617
|
+
worst_cycle_time: {
|
|
49618
|
+
label: "Slow Cycles",
|
|
49619
|
+
description: "Slowest cycle clips",
|
|
49620
|
+
color: "red",
|
|
49621
|
+
icon: "trending-down"
|
|
49622
|
+
},
|
|
49623
|
+
best_cycle_time: {
|
|
49624
|
+
label: "Fast Cycles",
|
|
49625
|
+
description: "Fastest cycle clips",
|
|
49626
|
+
color: "green",
|
|
49627
|
+
icon: "trending-up"
|
|
49628
|
+
}
|
|
49629
|
+
};
|
|
48184
49630
|
var parseFiniteNumber2 = (value) => {
|
|
48185
49631
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
48186
49632
|
return value;
|
|
@@ -48228,6 +49674,7 @@ var BottlenecksContent = ({
|
|
|
48228
49674
|
ticketId,
|
|
48229
49675
|
prefetchedPercentileCounts,
|
|
48230
49676
|
lowMomentsPrefetch,
|
|
49677
|
+
initialTimePrefetch,
|
|
48231
49678
|
initialTimeFilter
|
|
48232
49679
|
}) => {
|
|
48233
49680
|
console.log("\u{1F3AB} [BottlenecksContent] Rendered with ticketId:", ticketId || "NONE", "workspaceId:", workspaceId, "date:", date, "shift:", shift);
|
|
@@ -48440,6 +49887,108 @@ var BottlenecksContent = ({
|
|
|
48440
49887
|
enabled: isEffectiveShiftReady
|
|
48441
49888
|
});
|
|
48442
49889
|
const isLowMomentsCategoryAvailable = useMemo(() => Array.isArray(clipTypes) && clipTypes.some((type) => type?.type === LOW_EFFICIENCY_CATEGORY_ID || type?.id === LOW_EFFICIENCY_CATEGORY_ID), [clipTypes]);
|
|
49890
|
+
const requestedInitialCategoryCandidates = useMemo(() => {
|
|
49891
|
+
const requestedCategories = [
|
|
49892
|
+
...Array.isArray(initialTimeFilter?.categoryIds) ? initialTimeFilter.categoryIds : [],
|
|
49893
|
+
initialTimeFilter?.categoryId
|
|
49894
|
+
];
|
|
49895
|
+
return Array.from(
|
|
49896
|
+
new Set(
|
|
49897
|
+
requestedCategories.filter((category) => Boolean(category)).map((category) => category.trim()).filter(Boolean)
|
|
49898
|
+
)
|
|
49899
|
+
);
|
|
49900
|
+
}, [initialTimeFilter?.categoryId, initialTimeFilter?.categoryIds]);
|
|
49901
|
+
const hasInitialTimeHandoff = Boolean(initialTimeFilter?.startTime && initialTimeFilter?.endTime);
|
|
49902
|
+
const initialTimeHandoffCategorySet = useMemo(() => new Set(requestedInitialCategoryCandidates), [requestedInitialCategoryCandidates]);
|
|
49903
|
+
const isInitialTimeHandoffCategory = useCallback((categoryId) => Boolean(
|
|
49904
|
+
hasInitialTimeHandoff && categoryId && (initialTimeHandoffCategorySet.size === 0 || initialTimeHandoffCategorySet.has(categoryId))
|
|
49905
|
+
), [hasInitialTimeHandoff, initialTimeHandoffCategorySet]);
|
|
49906
|
+
const isTimestampInInitialTimeHandoff = useCallback((timestamp) => {
|
|
49907
|
+
if (!hasInitialTimeHandoff || !initialTimeFilter?.startTime || !initialTimeFilter?.endTime || !timestamp) {
|
|
49908
|
+
return true;
|
|
49909
|
+
}
|
|
49910
|
+
try {
|
|
49911
|
+
const clipDate = new Date(timestamp);
|
|
49912
|
+
if (Number.isNaN(clipDate.getTime())) {
|
|
49913
|
+
return false;
|
|
49914
|
+
}
|
|
49915
|
+
const clipParts = new Intl.DateTimeFormat("en-US", {
|
|
49916
|
+
hour12: false,
|
|
49917
|
+
hour: "2-digit",
|
|
49918
|
+
minute: "2-digit",
|
|
49919
|
+
timeZone: initialTimeFilter.timezone || timezone
|
|
49920
|
+
}).formatToParts(clipDate);
|
|
49921
|
+
const hourValue = clipParts.find((part) => part.type === "hour")?.value;
|
|
49922
|
+
const minuteValue = clipParts.find((part) => part.type === "minute")?.value;
|
|
49923
|
+
const clipMinute = timeValueToMinutes2(`${hourValue}:${minuteValue}`);
|
|
49924
|
+
return clipMinute === null ? false : isMinuteInTimeWindow2(clipMinute, initialTimeFilter.startTime, initialTimeFilter.endTime);
|
|
49925
|
+
} catch {
|
|
49926
|
+
return false;
|
|
49927
|
+
}
|
|
49928
|
+
}, [
|
|
49929
|
+
hasInitialTimeHandoff,
|
|
49930
|
+
initialTimeFilter?.endTime,
|
|
49931
|
+
initialTimeFilter?.startTime,
|
|
49932
|
+
initialTimeFilter?.timezone,
|
|
49933
|
+
timezone
|
|
49934
|
+
]);
|
|
49935
|
+
const resolvedInitialCategory = useMemo(() => resolveInitialClipCategory(requestedInitialCategoryCandidates, clipTypes, dynamicCounts), [clipTypes, dynamicCounts, requestedInitialCategoryCandidates]);
|
|
49936
|
+
const initialTimeFilterKey = useMemo(() => hasInitialTimeHandoff ? [
|
|
49937
|
+
initialTimeFilter?.startTime,
|
|
49938
|
+
initialTimeFilter?.endTime,
|
|
49939
|
+
initialTimeFilter?.timezone || timezone,
|
|
49940
|
+
initialTimeFilter?.categoryId || "",
|
|
49941
|
+
...initialTimeFilter?.categoryIds || []
|
|
49942
|
+
].join("|") : "", [
|
|
49943
|
+
hasInitialTimeHandoff,
|
|
49944
|
+
initialTimeFilter?.categoryId,
|
|
49945
|
+
initialTimeFilter?.categoryIds,
|
|
49946
|
+
initialTimeFilter?.endTime,
|
|
49947
|
+
initialTimeFilter?.startTime,
|
|
49948
|
+
initialTimeFilter?.timezone,
|
|
49949
|
+
timezone
|
|
49950
|
+
]);
|
|
49951
|
+
const preferredInitialTimeCategory = resolvedInitialCategory || requestedInitialCategoryCandidates[0] || "";
|
|
49952
|
+
useEffect(() => {
|
|
49953
|
+
if (!initialTimeFilterKey) {
|
|
49954
|
+
return;
|
|
49955
|
+
}
|
|
49956
|
+
setPendingVideo(null);
|
|
49957
|
+
setAllVideos([]);
|
|
49958
|
+
setCurrentIndex(0);
|
|
49959
|
+
setCurrentClipId(null);
|
|
49960
|
+
currentClipIdRef.current = null;
|
|
49961
|
+
setCurrentMetadataIndex(0);
|
|
49962
|
+
currentMetadataIndexRef.current = 0;
|
|
49963
|
+
setCurrentPosition(0);
|
|
49964
|
+
currentPositionRef.current = 0;
|
|
49965
|
+
setCurrentTotal(0);
|
|
49966
|
+
currentTotalRef.current = 0;
|
|
49967
|
+
setCategoryMetadata([]);
|
|
49968
|
+
categoryMetadataRef.current = [];
|
|
49969
|
+
setCategoryMetadataCategoryId(null);
|
|
49970
|
+
setCategoryMetadataSort(null);
|
|
49971
|
+
clearRetryTimeout();
|
|
49972
|
+
navigationLockRef.current = false;
|
|
49973
|
+
loadingCategoryRef.current = null;
|
|
49974
|
+
if (loadingTimeoutRef.current) {
|
|
49975
|
+
clearTimeout(loadingTimeoutRef.current);
|
|
49976
|
+
loadingTimeoutRef.current = null;
|
|
49977
|
+
}
|
|
49978
|
+
setIsTransitioning(false);
|
|
49979
|
+
setIsNavigating(false);
|
|
49980
|
+
setIsCategoryLoading(false);
|
|
49981
|
+
if (preferredInitialTimeCategory) {
|
|
49982
|
+
setInitialFilter(preferredInitialTimeCategory);
|
|
49983
|
+
updateActiveFilter(preferredInitialTimeCategory);
|
|
49984
|
+
previousFilterRef.current = "";
|
|
49985
|
+
}
|
|
49986
|
+
}, [
|
|
49987
|
+
clearRetryTimeout,
|
|
49988
|
+
initialTimeFilterKey,
|
|
49989
|
+
preferredInitialTimeCategory,
|
|
49990
|
+
updateActiveFilter
|
|
49991
|
+
]);
|
|
48443
49992
|
console.log("[BottlenecksContent] Clip types data:", {
|
|
48444
49993
|
clipTypes,
|
|
48445
49994
|
clipTypesLength: clipTypes?.length,
|
|
@@ -48487,6 +50036,15 @@ var BottlenecksContent = ({
|
|
|
48487
50036
|
}
|
|
48488
50037
|
});
|
|
48489
50038
|
useEffect(() => {
|
|
50039
|
+
if (resolvedInitialCategory) {
|
|
50040
|
+
if (initialFilter !== resolvedInitialCategory) {
|
|
50041
|
+
setInitialFilter(resolvedInitialCategory);
|
|
50042
|
+
}
|
|
50043
|
+
if (activeFilterRef.current !== resolvedInitialCategory) {
|
|
50044
|
+
updateActiveFilter(resolvedInitialCategory);
|
|
50045
|
+
}
|
|
50046
|
+
return;
|
|
50047
|
+
}
|
|
48490
50048
|
if (initialFilter) {
|
|
48491
50049
|
return;
|
|
48492
50050
|
}
|
|
@@ -48503,7 +50061,15 @@ var BottlenecksContent = ({
|
|
|
48503
50061
|
activeFilterRef.current = defaultCategory;
|
|
48504
50062
|
return;
|
|
48505
50063
|
}
|
|
48506
|
-
}, [
|
|
50064
|
+
}, [
|
|
50065
|
+
clipTypes,
|
|
50066
|
+
dynamicCounts,
|
|
50067
|
+
defaultCategory,
|
|
50068
|
+
initialFilter,
|
|
50069
|
+
isLowMomentsCategoryAvailable,
|
|
50070
|
+
resolvedInitialCategory,
|
|
50071
|
+
updateActiveFilter
|
|
50072
|
+
]);
|
|
48507
50073
|
const mergedCounts = useMemo(() => {
|
|
48508
50074
|
return { ...dynamicCounts };
|
|
48509
50075
|
}, [dynamicCounts]);
|
|
@@ -48552,6 +50118,9 @@ var BottlenecksContent = ({
|
|
|
48552
50118
|
const loadFirstVideoForCategory = useCallback(async (category) => {
|
|
48553
50119
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current || !isEffectiveShiftReady) return;
|
|
48554
50120
|
const targetCategory = category || activeFilterRef.current;
|
|
50121
|
+
if (targetCategory === "fast-cycles" || targetCategory === "slow-cycles") {
|
|
50122
|
+
return;
|
|
50123
|
+
}
|
|
48555
50124
|
const operationKey = `loadFirstVideo:${targetCategory}:${effectiveDateString}:${effectiveShiftId}`;
|
|
48556
50125
|
if (loadingCategoryRef.current === targetCategory || fetchInProgressRef.current.has(operationKey)) {
|
|
48557
50126
|
console.log(`[BottlenecksContent] Load first video already in progress for ${targetCategory}`);
|
|
@@ -48997,8 +50566,9 @@ var BottlenecksContent = ({
|
|
|
48997
50566
|
});
|
|
48998
50567
|
}
|
|
48999
50568
|
setVisibleCategoryMetadata(categoryId, cachedMetadata);
|
|
49000
|
-
|
|
49001
|
-
|
|
50569
|
+
const cachedAutoloadCandidates = isInitialTimeHandoffCategory(categoryId) ? cachedMetadata.filter((clip) => isTimestampInInitialTimeHandoff(clip.clip_timestamp || clip.creation_timestamp || clip.timestamp)) : cachedMetadata;
|
|
50570
|
+
if (autoLoadFirstVideo && cachedAutoloadCandidates.length > 0 && s3ClipsService) {
|
|
50571
|
+
const firstClipMeta = cachedAutoloadCandidates[0];
|
|
49002
50572
|
const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
|
|
49003
50573
|
const prefetchedFirstVideo = matchingLowMomentsPrefetch?.firstVideo ?? null;
|
|
49004
50574
|
try {
|
|
@@ -49037,7 +50607,10 @@ var BottlenecksContent = ({
|
|
|
49037
50607
|
endDate: `${resolvedDate}T23:59:59Z`,
|
|
49038
50608
|
percentile: 10,
|
|
49039
50609
|
shiftId: effectiveShiftId,
|
|
49040
|
-
limit: 100
|
|
50610
|
+
limit: isInitialTimeHandoffCategory(categoryId) ? 500 : 100,
|
|
50611
|
+
startTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.startTime : void 0,
|
|
50612
|
+
endTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.endTime : void 0,
|
|
50613
|
+
timeFilterTimezone: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.timezone || timezone : void 0
|
|
49041
50614
|
}),
|
|
49042
50615
|
redirectReason: "session_expired"
|
|
49043
50616
|
});
|
|
@@ -49054,10 +50627,13 @@ var BottlenecksContent = ({
|
|
|
49054
50627
|
shift: effectiveShiftId,
|
|
49055
50628
|
category: categoryId,
|
|
49056
50629
|
page: 1,
|
|
49057
|
-
limit: 100,
|
|
49058
|
-
knownTotal: mergedCounts[categoryId] ?? null,
|
|
50630
|
+
limit: isInitialTimeHandoffCategory(categoryId) ? 500 : 100,
|
|
50631
|
+
knownTotal: isInitialTimeHandoffCategory(categoryId) ? null : mergedCounts[categoryId] ?? null,
|
|
49059
50632
|
snapshotDateTime,
|
|
49060
50633
|
snapshotClipId,
|
|
50634
|
+
startTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.startTime : void 0,
|
|
50635
|
+
endTime: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.endTime : void 0,
|
|
50636
|
+
timeFilterTimezone: isInitialTimeHandoffCategory(categoryId) ? initialTimeFilter?.timezone || timezone : void 0,
|
|
49061
50637
|
sort: categoryId === LOW_EFFICIENCY_CATEGORY_ID ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
|
|
49062
50638
|
}),
|
|
49063
50639
|
redirectReason: "session_expired"
|
|
@@ -49070,7 +50646,8 @@ var BottlenecksContent = ({
|
|
|
49070
50646
|
if (categoryData.clips && isMountedRef.current) {
|
|
49071
50647
|
let metadataClips;
|
|
49072
50648
|
if (isPercentileCategory(categoryId)) {
|
|
49073
|
-
|
|
50649
|
+
const sortedPercentileClips = sortPercentileCycleClipsForDisplay(categoryId, categoryData.clips);
|
|
50650
|
+
metadataClips = sortedPercentileClips.map((clip, index) => ({
|
|
49074
50651
|
id: clip.id,
|
|
49075
50652
|
clipId: clip.id,
|
|
49076
50653
|
clip_timestamp: clip.creation_timestamp || clip.timestamp,
|
|
@@ -49117,8 +50694,9 @@ var BottlenecksContent = ({
|
|
|
49117
50694
|
}));
|
|
49118
50695
|
setVisibleCategoryMetadata(categoryId, metadataClips);
|
|
49119
50696
|
console.log(`[BottlenecksContent] Loaded metadata for ${categoryId}: ${metadataClips.length} clips`);
|
|
49120
|
-
|
|
49121
|
-
|
|
50697
|
+
const autoloadCandidates = isInitialTimeHandoffCategory(categoryId) ? metadataClips.filter((clip) => isTimestampInInitialTimeHandoff(clip.clip_timestamp || clip.creation_timestamp || clip.timestamp)) : metadataClips;
|
|
50698
|
+
if (autoLoadFirstVideo && autoloadCandidates.length > 0 && s3ClipsService) {
|
|
50699
|
+
const firstClipMeta = autoloadCandidates[0];
|
|
49122
50700
|
const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
|
|
49123
50701
|
try {
|
|
49124
50702
|
const video = await s3ClipsService.getClipById(firstClipId);
|
|
@@ -49152,7 +50730,7 @@ var BottlenecksContent = ({
|
|
|
49152
50730
|
setIsCategoryLoading(false);
|
|
49153
50731
|
}
|
|
49154
50732
|
}
|
|
49155
|
-
}, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata, lowMomentsPrefetch, applyPrefetchedFirstVideo, applyMetadataSnapshot, isLowMomentsCategoryAvailable]);
|
|
50733
|
+
}, [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
50734
|
useEffect(() => {
|
|
49157
50735
|
if (activeFilter !== LOW_EFFICIENCY_CATEGORY_ID || !isLowMomentsCategoryAvailable) {
|
|
49158
50736
|
return;
|
|
@@ -49184,6 +50762,37 @@ var BottlenecksContent = ({
|
|
|
49184
50762
|
applyMetadataSnapshot,
|
|
49185
50763
|
isLowMomentsCategoryAvailable
|
|
49186
50764
|
]);
|
|
50765
|
+
useEffect(() => {
|
|
50766
|
+
if (!initialTimeFilter?.startTime || !initialTimeFilter?.endTime || !initialTimePrefetch || initialTimePrefetch.loading || initialTimePrefetch.categoryId !== activeFilter) {
|
|
50767
|
+
return;
|
|
50768
|
+
}
|
|
50769
|
+
if (initialTimePrefetch.metadata.length > 0) {
|
|
50770
|
+
applyMetadataSnapshot(
|
|
50771
|
+
initialTimePrefetch.categoryId,
|
|
50772
|
+
initialTimePrefetch.metadata,
|
|
50773
|
+
initialTimePrefetch.total
|
|
50774
|
+
);
|
|
50775
|
+
}
|
|
50776
|
+
if (initialTimePrefetch.firstVideo && isTimestampInInitialTimeHandoff(
|
|
50777
|
+
initialTimePrefetch.firstVideo.creation_timestamp || initialTimePrefetch.firstVideo.timestamp
|
|
50778
|
+
)) {
|
|
50779
|
+
applyPrefetchedFirstVideo(initialTimePrefetch.firstVideo);
|
|
50780
|
+
if (isMountedRef.current) {
|
|
50781
|
+
setIsCategoryLoading(false);
|
|
50782
|
+
setIsInitialLoading(false);
|
|
50783
|
+
setIsTransitioning(false);
|
|
50784
|
+
setIsNavigating(false);
|
|
50785
|
+
}
|
|
50786
|
+
}
|
|
50787
|
+
}, [
|
|
50788
|
+
activeFilter,
|
|
50789
|
+
applyMetadataSnapshot,
|
|
50790
|
+
applyPrefetchedFirstVideo,
|
|
50791
|
+
initialTimeFilter?.endTime,
|
|
50792
|
+
initialTimeFilter?.startTime,
|
|
50793
|
+
initialTimePrefetch,
|
|
50794
|
+
isTimestampInInitialTimeHandoff
|
|
50795
|
+
]);
|
|
49187
50796
|
useEffect(() => {
|
|
49188
50797
|
if (previousIdleClipSortRef.current === idleClipSort) {
|
|
49189
50798
|
return;
|
|
@@ -49223,7 +50832,7 @@ var BottlenecksContent = ({
|
|
|
49223
50832
|
currentTotalRef.current = total;
|
|
49224
50833
|
setCurrentTotal(total);
|
|
49225
50834
|
previousFilterRef.current = activeFilter;
|
|
49226
|
-
const metadataLoadPlan = getCategoryMetadataLoadPlanForFilterChange({
|
|
50835
|
+
const metadataLoadPlan = isInitialTimeHandoffCategory(activeFilter) ? { shouldLoad: false, autoLoadFirstVideo: false } : getCategoryMetadataLoadPlanForFilterChange({
|
|
49227
50836
|
activeFilter,
|
|
49228
50837
|
currentClipId,
|
|
49229
50838
|
categoryTotal: total
|
|
@@ -49247,7 +50856,7 @@ var BottlenecksContent = ({
|
|
|
49247
50856
|
}
|
|
49248
50857
|
}
|
|
49249
50858
|
}
|
|
49250
|
-
}, [activeFilter, allVideos, mergedCounts, currentClipId, loadCategoryMetadata]);
|
|
50859
|
+
}, [activeFilter, allVideos, mergedCounts, currentClipId, loadCategoryMetadata, isInitialTimeHandoffCategory]);
|
|
49251
50860
|
useEffect(() => {
|
|
49252
50861
|
if (!currentClipId || activeFilter === "all") {
|
|
49253
50862
|
return;
|
|
@@ -49275,10 +50884,19 @@ var BottlenecksContent = ({
|
|
|
49275
50884
|
console.warn("[BottlenecksContent] Error disposing player:", e);
|
|
49276
50885
|
}
|
|
49277
50886
|
}
|
|
49278
|
-
loadingTimeoutRef.current
|
|
50887
|
+
if (loadingTimeoutRef.current) {
|
|
50888
|
+
clearTimeout(loadingTimeoutRef.current);
|
|
50889
|
+
loadingTimeoutRef.current = null;
|
|
50890
|
+
}
|
|
50891
|
+
const loadingTimeout = setTimeout(() => {
|
|
50892
|
+
if (loadingTimeoutRef.current !== loadingTimeout) {
|
|
50893
|
+
return;
|
|
50894
|
+
}
|
|
50895
|
+
loadingTimeoutRef.current = null;
|
|
49279
50896
|
console.warn("[BottlenecksContent] Loading timeout - clearing stuck loading state");
|
|
49280
50897
|
clearLoadingState();
|
|
49281
50898
|
}, 2e3);
|
|
50899
|
+
loadingTimeoutRef.current = loadingTimeout;
|
|
49282
50900
|
if (activeFilterRef.current !== categoryId) {
|
|
49283
50901
|
updateActiveFilter(categoryId);
|
|
49284
50902
|
}
|
|
@@ -49298,17 +50916,20 @@ var BottlenecksContent = ({
|
|
|
49298
50916
|
setCurrentClipId(clipId);
|
|
49299
50917
|
setAllVideos([video]);
|
|
49300
50918
|
setCurrentIndex(0);
|
|
50919
|
+
clearLoadingState();
|
|
49301
50920
|
} else {
|
|
49302
50921
|
throw new Error(`Failed to load video data for clip ${clipId}`);
|
|
49303
50922
|
}
|
|
49304
50923
|
await metadataPromise;
|
|
49305
50924
|
let metadataArray = categoryMetadataRef.current;
|
|
49306
|
-
const
|
|
49307
|
-
|
|
50925
|
+
const getMetadataClipId = (clip) => clip?.clipId || clip?.id;
|
|
50926
|
+
const metadataHasClip = (clips) => clips.some((clip) => getMetadataClipId(clip) === clipId);
|
|
50927
|
+
const fallbackHasClip = fallbackMetadata?.some((clip) => getMetadataClipId(clip) === clipId);
|
|
50928
|
+
if ((metadataArray.length === 0 || !metadataHasClip(metadataArray)) && fallbackHasClip) {
|
|
49308
50929
|
applyMetadataSnapshot(categoryId, fallbackMetadata, fallbackTotal);
|
|
49309
50930
|
metadataArray = fallbackMetadata;
|
|
49310
50931
|
}
|
|
49311
|
-
if (metadataArray.length === 0 || !metadataArray
|
|
50932
|
+
if (metadataArray.length === 0 || !metadataHasClip(metadataArray)) {
|
|
49312
50933
|
if (!fallbackHasClip) {
|
|
49313
50934
|
console.warn(`[BottlenecksContent] Clip ${clipId} not found in metadata for ${categoryId} (cache hit: ${metadataArray.length > 0}) - forcing refresh`);
|
|
49314
50935
|
await loadCategoryMetadata(categoryId, false, true);
|
|
@@ -49327,7 +50948,7 @@ var BottlenecksContent = ({
|
|
|
49327
50948
|
}
|
|
49328
50949
|
return;
|
|
49329
50950
|
}
|
|
49330
|
-
const clickedClipIndex = metadataArray.findIndex((clip) => clip
|
|
50951
|
+
const clickedClipIndex = metadataArray.findIndex((clip) => getMetadataClipId(clip) === clipId);
|
|
49331
50952
|
if (clickedClipIndex === -1) {
|
|
49332
50953
|
console.warn(`[BottlenecksContent] Clip ${clipId} not found after metadata refresh`);
|
|
49333
50954
|
if (!shouldUseMetadataNavigation(categoryId)) {
|
|
@@ -49715,6 +51336,32 @@ var BottlenecksContent = ({
|
|
|
49715
51336
|
}
|
|
49716
51337
|
return filteredVideos[currentIndex];
|
|
49717
51338
|
}, [filteredVideos, currentIndex]);
|
|
51339
|
+
const currentVideoMatchesInitialTimeHandoff = useMemo(() => {
|
|
51340
|
+
if (!hasInitialTimeHandoff) {
|
|
51341
|
+
return true;
|
|
51342
|
+
}
|
|
51343
|
+
if (!currentVideo) {
|
|
51344
|
+
return false;
|
|
51345
|
+
}
|
|
51346
|
+
if (!isInitialTimeHandoffCategory(activeFilter) || !isInitialTimeHandoffCategory(currentVideo.type)) {
|
|
51347
|
+
return false;
|
|
51348
|
+
}
|
|
51349
|
+
return isTimestampInInitialTimeHandoff(
|
|
51350
|
+
currentVideo.creation_timestamp || currentVideo.timestamp || currentVideo.clip_end_time || currentVideo.clip_start_time
|
|
51351
|
+
);
|
|
51352
|
+
}, [
|
|
51353
|
+
activeFilter,
|
|
51354
|
+
currentVideo,
|
|
51355
|
+
hasInitialTimeHandoff,
|
|
51356
|
+
isInitialTimeHandoffCategory,
|
|
51357
|
+
isTimestampInInitialTimeHandoff
|
|
51358
|
+
]);
|
|
51359
|
+
const shouldHoldInitialTimeHandoffVideo = Boolean(
|
|
51360
|
+
hasInitialTimeHandoff && !currentVideoMatchesInitialTimeHandoff && (isCategoryLoading || filteredVideos.length > 0 || (mergedCounts[activeFilter] || 0) > 0)
|
|
51361
|
+
);
|
|
51362
|
+
const canRenderCurrentVideo = Boolean(
|
|
51363
|
+
filteredVideos.length > 0 && currentVideo && !isFullscreen && !shouldHoldInitialTimeHandoffVideo
|
|
51364
|
+
);
|
|
49718
51365
|
const currentLowEfficiencyClipId = currentVideo?.id || currentClipId || null;
|
|
49719
51366
|
const isCurrentLowEfficiencyClip = Boolean(
|
|
49720
51367
|
currentVideo?.type === "recent_flow_red_streak" || currentVideo?.red_flow_timeline
|
|
@@ -49881,11 +51528,111 @@ var BottlenecksContent = ({
|
|
|
49881
51528
|
}
|
|
49882
51529
|
return currentPosition;
|
|
49883
51530
|
}, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
|
|
49884
|
-
const
|
|
51531
|
+
const initialTimePrefetchedMetadata = useMemo(() => {
|
|
51532
|
+
if (!initialTimeFilter?.startTime || !initialTimeFilter?.endTime || !initialTimePrefetch || initialTimePrefetch.loading) {
|
|
51533
|
+
return void 0;
|
|
51534
|
+
}
|
|
51535
|
+
if (initialTimePrefetch.metadataByCategory) {
|
|
51536
|
+
return initialTimePrefetch.metadataByCategory;
|
|
51537
|
+
}
|
|
51538
|
+
if (initialTimePrefetch.categoryId === activeFilter && initialTimePrefetch.metadata.length > 0) {
|
|
51539
|
+
return { [activeFilter]: initialTimePrefetch.metadata };
|
|
51540
|
+
}
|
|
51541
|
+
return void 0;
|
|
51542
|
+
}, [
|
|
49885
51543
|
activeFilter,
|
|
51544
|
+
initialTimePrefetch,
|
|
51545
|
+
initialTimeFilter?.endTime,
|
|
51546
|
+
initialTimeFilter?.startTime
|
|
51547
|
+
]);
|
|
51548
|
+
const prefetchedExplorerMetadata = useMemo(() => {
|
|
51549
|
+
if (initialTimePrefetchedMetadata) {
|
|
51550
|
+
return initialTimePrefetchedMetadata;
|
|
51551
|
+
}
|
|
51552
|
+
if (activeFilter === LOW_EFFICIENCY_CATEGORY_ID && isLowMomentsCategoryAvailable && lowMomentsPrefetch?.key?.startsWith(`${LOW_EFFICIENCY_CATEGORY_ID}-${workspaceId}-${effectiveDateString}-${effectiveShiftId}-`) && !lowMomentsPrefetch.loading && lowMomentsPrefetch.metadata.length > 0) {
|
|
51553
|
+
return { [LOW_EFFICIENCY_CATEGORY_ID]: lowMomentsPrefetch.metadata };
|
|
51554
|
+
}
|
|
51555
|
+
if (activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort) {
|
|
51556
|
+
return void 0;
|
|
51557
|
+
}
|
|
51558
|
+
const metadataSnapshot = buildPrefetchedExplorerMetadata(
|
|
51559
|
+
activeFilter,
|
|
51560
|
+
categoryMetadataCategoryId,
|
|
51561
|
+
categoryMetadata
|
|
51562
|
+
);
|
|
51563
|
+
if (metadataSnapshot) {
|
|
51564
|
+
return metadataSnapshot;
|
|
51565
|
+
}
|
|
51566
|
+
if (initialTimeFilter?.startTime && initialTimeFilter?.endTime && currentVideo && currentVideo.type === activeFilter) {
|
|
51567
|
+
return {
|
|
51568
|
+
[activeFilter]: [{
|
|
51569
|
+
id: currentVideo.id,
|
|
51570
|
+
clipId: currentVideo.id,
|
|
51571
|
+
clip_timestamp: currentVideo.creation_timestamp || currentVideo.timestamp,
|
|
51572
|
+
description: currentVideo.description,
|
|
51573
|
+
severity: currentVideo.severity,
|
|
51574
|
+
category: activeFilter,
|
|
51575
|
+
duration: typeof currentVideo.duration === "number" ? currentVideo.duration : typeof currentVideo.cycle_time_seconds === "number" ? currentVideo.cycle_time_seconds : void 0,
|
|
51576
|
+
clip_start_time: currentVideo.clip_start_time,
|
|
51577
|
+
clip_end_time: currentVideo.clip_end_time,
|
|
51578
|
+
index: 0,
|
|
51579
|
+
idle_start_time: currentVideo.idle_start_time,
|
|
51580
|
+
idle_end_time: currentVideo.idle_end_time,
|
|
51581
|
+
cycle_item_count: null,
|
|
51582
|
+
red_flow_timeline: currentVideo.red_flow_timeline,
|
|
51583
|
+
red_flow_severity_score: currentVideo.red_flow_severity_score,
|
|
51584
|
+
red_flow_output_shortfall_units: currentVideo.red_flow_output_shortfall_units,
|
|
51585
|
+
red_flow_worst_minute: currentVideo.red_flow_worst_minute,
|
|
51586
|
+
red_flow_explanation_summary: currentVideo.red_flow_explanation_summary,
|
|
51587
|
+
red_flow_explanation: currentVideo.red_flow_explanation
|
|
51588
|
+
}]
|
|
51589
|
+
};
|
|
51590
|
+
}
|
|
51591
|
+
return void 0;
|
|
51592
|
+
}, [
|
|
51593
|
+
activeFilter,
|
|
51594
|
+
categoryMetadata,
|
|
49886
51595
|
categoryMetadataCategoryId,
|
|
49887
|
-
|
|
49888
|
-
|
|
51596
|
+
categoryMetadataSort,
|
|
51597
|
+
currentVideo,
|
|
51598
|
+
idleClipSort,
|
|
51599
|
+
initialTimePrefetchedMetadata,
|
|
51600
|
+
initialTimePrefetch,
|
|
51601
|
+
initialTimeFilter?.endTime,
|
|
51602
|
+
initialTimeFilter?.startTime,
|
|
51603
|
+
lowMomentsPrefetch,
|
|
51604
|
+
workspaceId,
|
|
51605
|
+
effectiveDateString,
|
|
51606
|
+
effectiveShiftId,
|
|
51607
|
+
isLowMomentsCategoryAvailable
|
|
51608
|
+
]);
|
|
51609
|
+
const externallyManagedLoadingCategories = useMemo(() => {
|
|
51610
|
+
const managedCategories = {
|
|
51611
|
+
recent_flow_red_streak: Boolean(
|
|
51612
|
+
activeFilter === LOW_EFFICIENCY_CATEGORY_ID && isLowMomentsCategoryAvailable && lowMomentsPrefetch?.key?.startsWith(`${LOW_EFFICIENCY_CATEGORY_ID}-${workspaceId}-${effectiveDateString}-${effectiveShiftId}-`) && lowMomentsPrefetch.loading
|
|
51613
|
+
)
|
|
51614
|
+
};
|
|
51615
|
+
const isInitialTimeHandoffPending = Boolean(
|
|
51616
|
+
initialTimeFilter?.startTime && initialTimeFilter?.endTime && requestedInitialCategoryCandidates.length > 0 && (!initialTimePrefetch || initialTimePrefetch.loading)
|
|
51617
|
+
);
|
|
51618
|
+
if (isInitialTimeHandoffPending) {
|
|
51619
|
+
requestedInitialCategoryCandidates.forEach((categoryId) => {
|
|
51620
|
+
managedCategories[categoryId] = true;
|
|
51621
|
+
});
|
|
51622
|
+
}
|
|
51623
|
+
return managedCategories;
|
|
51624
|
+
}, [
|
|
51625
|
+
activeFilter,
|
|
51626
|
+
effectiveDateString,
|
|
51627
|
+
effectiveShiftId,
|
|
51628
|
+
initialTimeFilter?.endTime,
|
|
51629
|
+
initialTimeFilter?.startTime,
|
|
51630
|
+
initialTimePrefetch,
|
|
51631
|
+
isLowMomentsCategoryAvailable,
|
|
51632
|
+
lowMomentsPrefetch,
|
|
51633
|
+
requestedInitialCategoryCandidates,
|
|
51634
|
+
workspaceId
|
|
51635
|
+
]);
|
|
49889
51636
|
const classificationClipIds = useMemo(() => {
|
|
49890
51637
|
if (!idleTimeVlmEnabled) {
|
|
49891
51638
|
return [];
|
|
@@ -50295,7 +52042,7 @@ var BottlenecksContent = ({
|
|
|
50295
52042
|
/* @__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
52043
|
] });
|
|
50297
52044
|
}
|
|
50298
|
-
if (clipTypesLoading && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
52045
|
+
if (!hasInitialTimeHandoff && clipTypesLoading && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
50299
52046
|
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
52047
|
}
|
|
50301
52048
|
if (error && error.type === "fatal" && !hasInitialLoad || clipTypesError) {
|
|
@@ -50305,7 +52052,30 @@ var BottlenecksContent = ({
|
|
|
50305
52052
|
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: error?.message || clipTypesError })
|
|
50306
52053
|
] });
|
|
50307
52054
|
}
|
|
50308
|
-
const categoriesToShow =
|
|
52055
|
+
const categoriesToShow = (() => {
|
|
52056
|
+
const categories = clipTypes.length > 0 ? [...clipTypes] : [];
|
|
52057
|
+
const existingTypes = new Set(categories.map((category) => category.type));
|
|
52058
|
+
requestedInitialCategoryCandidates.forEach((categoryType) => {
|
|
52059
|
+
if (existingTypes.has(categoryType) || !hasInitialTimeHandoff && (mergedCounts[categoryType] || 0) <= 0) {
|
|
52060
|
+
return;
|
|
52061
|
+
}
|
|
52062
|
+
const fallback = CHART_HANDOFF_CATEGORY_FALLBACKS[categoryType];
|
|
52063
|
+
if (!fallback) {
|
|
52064
|
+
return;
|
|
52065
|
+
}
|
|
52066
|
+
categories.push({
|
|
52067
|
+
id: categoryType,
|
|
52068
|
+
type: categoryType,
|
|
52069
|
+
label: fallback.label,
|
|
52070
|
+
description: fallback.description,
|
|
52071
|
+
color: fallback.color,
|
|
52072
|
+
icon: fallback.icon,
|
|
52073
|
+
sort_order: 50
|
|
52074
|
+
});
|
|
52075
|
+
existingTypes.add(categoryType);
|
|
52076
|
+
});
|
|
52077
|
+
return categories;
|
|
52078
|
+
})();
|
|
50309
52079
|
console.log("[BottlenecksContent] Categories to show:", {
|
|
50310
52080
|
categoriesToShow,
|
|
50311
52081
|
categoriesToShowLength: categoriesToShow?.length,
|
|
@@ -50324,190 +52094,204 @@ var BottlenecksContent = ({
|
|
|
50324
52094
|
}
|
|
50325
52095
|
),
|
|
50326
52096
|
/* @__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
|
-
|
|
52097
|
+
/* @__PURE__ */ jsx(
|
|
52098
|
+
"div",
|
|
52099
|
+
{
|
|
52100
|
+
className: "min-w-0 w-full lg:flex-[3] lg:h-full",
|
|
52101
|
+
"data-qa-clips-active-filter": activeFilter || "",
|
|
52102
|
+
"data-qa-clips-current-video-type": currentVideo?.type || "",
|
|
52103
|
+
"data-qa-clips-current-video-id": currentVideo?.id || "",
|
|
52104
|
+
"data-qa-clips-current-clip-id": currentClipId || "",
|
|
52105
|
+
"data-qa-clips-filtered-count": filteredVideos.length,
|
|
52106
|
+
"data-qa-clips-all-count": allVideos.length,
|
|
52107
|
+
"data-qa-clips-current-video-matches-hour": String(currentVideoMatchesInitialTimeHandoff),
|
|
52108
|
+
"data-qa-clips-hold-hour-video": String(shouldHoldInitialTimeHandoffVideo),
|
|
52109
|
+
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: [
|
|
52110
|
+
/* @__PURE__ */ jsx(
|
|
52111
|
+
"div",
|
|
50338
52112
|
{
|
|
50339
|
-
ref: videoRef,
|
|
50340
|
-
src: currentVideo.src,
|
|
50341
|
-
poster: "",
|
|
50342
52113
|
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();
|
|
52114
|
+
style: {
|
|
52115
|
+
opacity: isTransitioning ? 0 : 1,
|
|
52116
|
+
transition: "opacity 0.1s ease-in-out"
|
|
50399
52117
|
},
|
|
50400
|
-
|
|
50401
|
-
|
|
52118
|
+
children: !shouldDeferPlayerRenderForCrop && /* @__PURE__ */ jsx(
|
|
52119
|
+
CroppedVideoPlayer,
|
|
52120
|
+
{
|
|
52121
|
+
ref: videoRef,
|
|
52122
|
+
src: currentVideo.src,
|
|
52123
|
+
poster: "",
|
|
52124
|
+
className: "w-full h-full",
|
|
52125
|
+
crop: workspaceCrop?.crop,
|
|
52126
|
+
autoplay: true,
|
|
52127
|
+
playsInline: true,
|
|
52128
|
+
loop: false,
|
|
52129
|
+
externalLoadingControl: true,
|
|
52130
|
+
onReady: handleVideoReady,
|
|
52131
|
+
onPlay: handleVideoPlay,
|
|
52132
|
+
onPause: handleVideoPause,
|
|
52133
|
+
onTimeUpdate: handleTimeUpdate,
|
|
52134
|
+
onDurationChange: handleDurationChange,
|
|
52135
|
+
onEnded: handleVideoEnded,
|
|
52136
|
+
onError: handleVideoError,
|
|
52137
|
+
onLoadedData: handleLoadedData,
|
|
52138
|
+
onPlaying: handleVideoPlaying,
|
|
52139
|
+
onLoadingChange: handleVideoLoadingChange,
|
|
52140
|
+
onShare: handleShareClip,
|
|
52141
|
+
isShareLoading,
|
|
52142
|
+
isShareCopied,
|
|
52143
|
+
timelineAnnotations: currentVideo.red_flow_timeline,
|
|
52144
|
+
timelineExplanation: currentVideo.red_flow_explanation,
|
|
52145
|
+
timelineTimezone: timezone,
|
|
52146
|
+
options: videoPlayerOptions
|
|
52147
|
+
},
|
|
52148
|
+
`${currentVideo.id}-${playerInstanceNonce}-inline`
|
|
52149
|
+
)
|
|
50402
52150
|
}
|
|
50403
52151
|
),
|
|
50404
|
-
|
|
50405
|
-
|
|
52152
|
+
currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
|
|
52153
|
+
RedFlowDiagnosticOverlay,
|
|
50406
52154
|
{
|
|
50407
|
-
|
|
50408
|
-
|
|
50409
|
-
|
|
50410
|
-
|
|
50411
|
-
|
|
50412
|
-
|
|
52155
|
+
timeline: currentVideo.red_flow_timeline,
|
|
52156
|
+
explanation: currentVideo.red_flow_explanation,
|
|
52157
|
+
aiSummary: currentLowEfficiencyAiSummary,
|
|
52158
|
+
aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
|
|
52159
|
+
aiSummaryError: currentLowEfficiencyAiSummaryError,
|
|
52160
|
+
className: "right-4 top-4"
|
|
50413
52161
|
}
|
|
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
|
-
|
|
52162
|
+
) : null,
|
|
52163
|
+
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..." }) }),
|
|
52164
|
+
!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..." }) }),
|
|
52165
|
+
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: [
|
|
52166
|
+
/* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md" }),
|
|
52167
|
+
/* @__PURE__ */ jsx("p", { className: "text-white text-sm mt-4 font-medium", children: error.message })
|
|
52168
|
+
] }) }),
|
|
52169
|
+
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: [
|
|
52170
|
+
/* @__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" }) }),
|
|
52171
|
+
/* @__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" }),
|
|
52172
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-6", children: error.message }),
|
|
52173
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
52174
|
+
error.canSkip && /* @__PURE__ */ jsx(
|
|
52175
|
+
"button",
|
|
52176
|
+
{
|
|
52177
|
+
onClick: () => {
|
|
52178
|
+
setError(null);
|
|
52179
|
+
videoRetryCountRef.current = 0;
|
|
52180
|
+
handleNext();
|
|
52181
|
+
},
|
|
52182
|
+
className: "px-5 py-2.5 bg-blue-600 hover:bg-blue-700 rounded-md text-sm font-medium transition-colors",
|
|
52183
|
+
children: "Skip to Next Clip"
|
|
52184
|
+
}
|
|
52185
|
+
),
|
|
52186
|
+
error.canRetry && /* @__PURE__ */ jsx(
|
|
52187
|
+
"button",
|
|
52188
|
+
{
|
|
52189
|
+
onClick: () => {
|
|
52190
|
+
videoRetryCountRef.current = 0;
|
|
52191
|
+
restartCurrentClipPlayback();
|
|
52192
|
+
},
|
|
52193
|
+
className: "px-5 py-2.5 bg-gray-600 hover:bg-gray-700 rounded-md text-sm font-medium transition-colors",
|
|
52194
|
+
children: "Retry"
|
|
52195
|
+
}
|
|
52196
|
+
)
|
|
52197
|
+
] })
|
|
52198
|
+
] }) }),
|
|
52199
|
+
(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" ? (
|
|
52200
|
+
// Show full colored badge for idle time
|
|
52201
|
+
(() => {
|
|
52202
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
52203
|
+
const confidence = getIdleTimeConfidence(currentVideo);
|
|
52204
|
+
const config = getRootCauseConfig(classification);
|
|
52205
|
+
if (!config) return null;
|
|
52206
|
+
const IconComponent = config.Icon;
|
|
52207
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52208
|
+
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: [
|
|
52209
|
+
/* @__PURE__ */ jsx(IconComponent, { className: `h-3.5 w-3.5 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
52210
|
+
/* @__PURE__ */ jsx("span", { className: `truncate font-medium text-xs ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
52211
|
+
] }) }),
|
|
52212
|
+
idleTimeVlmEnabled && confidence !== null && (() => {
|
|
52213
|
+
const confidencePercent = confidence * 100;
|
|
52214
|
+
let confidenceLabel = "Low";
|
|
52215
|
+
let confidenceColor = "text-red-500";
|
|
52216
|
+
if (confidencePercent > 95) {
|
|
52217
|
+
confidenceLabel = "High";
|
|
52218
|
+
confidenceColor = "text-green-500";
|
|
52219
|
+
} else if (confidencePercent >= 91) {
|
|
52220
|
+
confidenceLabel = "Medium";
|
|
52221
|
+
confidenceColor = "text-yellow-500";
|
|
52222
|
+
}
|
|
52223
|
+
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: [
|
|
52224
|
+
"AI Confidence: ",
|
|
52225
|
+
/* @__PURE__ */ jsx("span", { className: confidenceColor, children: confidenceLabel })
|
|
52226
|
+
] }) }) });
|
|
52227
|
+
})()
|
|
52228
|
+
] });
|
|
50445
52229
|
})()
|
|
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: [
|
|
52230
|
+
) : /* @__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: [
|
|
52231
|
+
/* @__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` }),
|
|
52232
|
+
(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: [
|
|
52233
|
+
"Cycle time: ",
|
|
52234
|
+
currentVideo.cycle_time_seconds.toFixed(1),
|
|
52235
|
+
"s"
|
|
52236
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52237
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
|
|
52238
|
+
/* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
52239
|
+
] })
|
|
52240
|
+
] }) }) : (
|
|
52241
|
+
/* Right side display for other video types */
|
|
52242
|
+
currentVideo.type === "idle_time" ? (
|
|
52243
|
+
// Show full colored badge for idle time
|
|
52244
|
+
(() => {
|
|
52245
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
52246
|
+
const confidence = getIdleTimeConfidence(currentVideo);
|
|
52247
|
+
const config = getRootCauseConfig(classification);
|
|
52248
|
+
if (!config) return null;
|
|
52249
|
+
const IconComponent = config.Icon;
|
|
52250
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52251
|
+
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: [
|
|
52252
|
+
"AI Confidence: ",
|
|
52253
|
+
(confidence * 100).toFixed(0),
|
|
52254
|
+
"%"
|
|
52255
|
+
] }) }) }),
|
|
52256
|
+
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: [
|
|
52257
|
+
/* @__PURE__ */ jsx(IconComponent, { className: `h-3.5 w-3.5 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
52258
|
+
/* @__PURE__ */ jsx("span", { className: `truncate font-medium text-xs ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
52259
|
+
] }) })
|
|
52260
|
+
] });
|
|
52261
|
+
})()
|
|
52262
|
+
) : /* @__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: [
|
|
52263
|
+
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
|
|
52264
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
|
|
52265
|
+
currentVideo.type !== "recent_flow_red_streak" && /* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
52266
|
+
] }) })
|
|
52267
|
+
)
|
|
52268
|
+
] }) }) }) : 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..." }) }) }) }) : (
|
|
52269
|
+
/* Priority 5: Show "no clips found" only if we have counts and there are truly no clips for workspace */
|
|
52270
|
+
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
52271
|
/* @__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
|
|
52272
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Clips Found" }),
|
|
52273
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There were no video clips found for this workspace today." })
|
|
50504
52274
|
] }) }) : (
|
|
50505
|
-
/* Priority
|
|
50506
|
-
|
|
52275
|
+
/* Priority 5.5: Show "no folder selected" if activeFilter is empty */
|
|
52276
|
+
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: [
|
|
52277
|
+
/* @__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" }) }),
|
|
52278
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Folder Selected" }),
|
|
52279
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "Please select a folder to view clips." })
|
|
52280
|
+
] }) }) : (
|
|
52281
|
+
/* Priority 6: Show "no matching clips" only if we have data loaded and specifically no clips for this filter */
|
|
52282
|
+
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: [
|
|
52283
|
+
/* @__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" }) }),
|
|
52284
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Matching Clips" }),
|
|
52285
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There are no clips matching the selected filter." })
|
|
52286
|
+
] }) }) : (
|
|
52287
|
+
/* Priority 7: Default loading state for any other case */
|
|
52288
|
+
/* @__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..." }) }) }) })
|
|
52289
|
+
)
|
|
52290
|
+
)
|
|
50507
52291
|
)
|
|
50508
|
-
)
|
|
50509
|
-
|
|
50510
|
-
)
|
|
52292
|
+
) })
|
|
52293
|
+
}
|
|
52294
|
+
),
|
|
50511
52295
|
/* @__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
52296
|
/* Triage Mode - Direct tile view for cycle completions and idle time */
|
|
50513
52297
|
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm h-full overflow-hidden flex flex-col", children: [
|
|
@@ -50642,7 +52426,7 @@ var BottlenecksContent = ({
|
|
|
50642
52426
|
})),
|
|
50643
52427
|
videos: allVideos || [],
|
|
50644
52428
|
activeFilter,
|
|
50645
|
-
currentVideoId: currentVideo?.id,
|
|
52429
|
+
currentVideoId: currentVideo?.id || currentClipId || void 0,
|
|
50646
52430
|
counts: mergedCounts,
|
|
50647
52431
|
isReady: hasInitialLoad,
|
|
50648
52432
|
prefetchedPercentileCounts: isFastSlowClipFiltersEnabled ? prefetchedPercentileCounts || void 0 : void 0,
|
|
@@ -50656,11 +52440,9 @@ var BottlenecksContent = ({
|
|
|
50656
52440
|
idleTimeVlmEnabled,
|
|
50657
52441
|
showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
|
|
50658
52442
|
prefetchedClipMetadata: prefetchedExplorerMetadata,
|
|
50659
|
-
|
|
50660
|
-
|
|
50661
|
-
|
|
50662
|
-
)
|
|
50663
|
-
},
|
|
52443
|
+
prefetchedClipTotals: initialTimePrefetch?.loading ? void 0 : initialTimePrefetch?.totalsByCategory,
|
|
52444
|
+
prefetchedPercentileClips: initialTimePrefetch?.loading ? void 0 : initialTimePrefetch?.percentileClipsByCategory,
|
|
52445
|
+
externallyManagedLoadingCategories,
|
|
50664
52446
|
activeCategoryLoading: isCategoryLoading,
|
|
50665
52447
|
idleClipSort,
|
|
50666
52448
|
onIdleClipSortChange: setIdleClipSort,
|
|
@@ -68453,17 +70235,7 @@ var setSessionSeenValue = (key) => {
|
|
|
68453
70235
|
};
|
|
68454
70236
|
var buildAllGreenCelebrationSeenKey = (identity) => `${ALL_GREEN_CELEBRATION_SEEN_PREFIX}${identity}`;
|
|
68455
70237
|
var buildAllGreenMilestoneSeenKey = (identity, milestoneSeconds) => `${ALL_GREEN_MILESTONE_SEEN_PREFIX}${identity}:${milestoneSeconds}`;
|
|
68456
|
-
var LINE_SELECTOR_INDICATOR_VERSION = "
|
|
68457
|
-
var LineSelectorIncidentIcon = ({ lineId }) => /* @__PURE__ */ jsx(
|
|
68458
|
-
"span",
|
|
68459
|
-
{
|
|
68460
|
-
"data-testid": `line-selector-incident-icon-${lineId}`,
|
|
68461
|
-
"aria-label": "Line needs attention",
|
|
68462
|
-
role: "img",
|
|
68463
|
-
className: "inline-flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full border border-rose-200 bg-white text-[13px] font-semibold leading-none text-rose-600 shadow-[0_1px_2px_rgba(15,23,42,0.06)]",
|
|
68464
|
-
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "-mt-px", children: "!" })
|
|
68465
|
-
}
|
|
68466
|
-
);
|
|
70238
|
+
var LINE_SELECTOR_INDICATOR_VERSION = "line_signal_dots_v1";
|
|
68467
70239
|
var LoadingPageCmp = LoadingPage_default;
|
|
68468
70240
|
var LoadingOverlayCmp = LoadingOverlay_default;
|
|
68469
70241
|
function HomeView({
|
|
@@ -68803,8 +70575,8 @@ function HomeView({
|
|
|
68803
70575
|
const currentIsCurrentScopeResolved = isBootstrapMonitorMode ? bootstrapMonitor.isCurrentScopeResolved : legacyIsCurrentScopeResolved;
|
|
68804
70576
|
const currentMetricsError = isBootstrapMonitorMode ? bootstrapMonitor.error : legacyMetricsError;
|
|
68805
70577
|
const currentRefetchMetrics = isBootstrapMonitorMode ? bootstrapMonitor.refetch : refetchLegacyMetrics;
|
|
68806
|
-
const
|
|
68807
|
-
const
|
|
70578
|
+
const lineSelectorSignalStatusByLine = useMemo(() => {
|
|
70579
|
+
const statusByLine = /* @__PURE__ */ new Map();
|
|
68808
70580
|
const legend = currentEfficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
68809
70581
|
const addRows = (rows) => {
|
|
68810
70582
|
(rows || []).forEach((row) => {
|
|
@@ -68812,40 +70584,36 @@ function HomeView({
|
|
|
68812
70584
|
if (!lineId) {
|
|
68813
70585
|
return;
|
|
68814
70586
|
}
|
|
68815
|
-
if (row?.red_flow_incident?.active === true) {
|
|
68816
|
-
indicatorByLine.set(lineId, "incident");
|
|
68817
|
-
return;
|
|
68818
|
-
}
|
|
68819
|
-
if (indicatorByLine.get(lineId) === "incident") {
|
|
68820
|
-
return;
|
|
68821
|
-
}
|
|
68822
70587
|
const status = getKpiSignalStatus(row?.line_signal, legend);
|
|
68823
|
-
if (status
|
|
68824
|
-
|
|
70588
|
+
if (status) {
|
|
70589
|
+
statusByLine.set(lineId, status);
|
|
68825
70590
|
}
|
|
68826
70591
|
});
|
|
68827
70592
|
};
|
|
68828
70593
|
addRows(currentSelectorLineMetrics);
|
|
68829
70594
|
addRows(currentLineMetrics);
|
|
68830
|
-
return
|
|
70595
|
+
return statusByLine;
|
|
68831
70596
|
}, [currentEfficiencyLegend, currentLineMetrics, currentSelectorLineMetrics]);
|
|
68832
|
-
const
|
|
68833
|
-
let
|
|
68834
|
-
let
|
|
70597
|
+
const lineSelectorSignalDotStats = useMemo(() => {
|
|
70598
|
+
let stableSignalLineCount = 0;
|
|
70599
|
+
let warningSignalLineCount = 0;
|
|
70600
|
+
let attentionSignalLineCount = 0;
|
|
68835
70601
|
visibleLineIds.forEach((lineId) => {
|
|
68836
|
-
const
|
|
68837
|
-
if (
|
|
68838
|
-
|
|
68839
|
-
} else if (
|
|
68840
|
-
|
|
70602
|
+
const status = lineSelectorSignalStatusByLine.get(lineId);
|
|
70603
|
+
if (status === "stable") {
|
|
70604
|
+
stableSignalLineCount += 1;
|
|
70605
|
+
} else if (status === "warning") {
|
|
70606
|
+
warningSignalLineCount += 1;
|
|
70607
|
+
} else if (status === "attention") {
|
|
70608
|
+
attentionSignalLineCount += 1;
|
|
68841
70609
|
}
|
|
68842
70610
|
});
|
|
68843
70611
|
return {
|
|
68844
|
-
|
|
68845
|
-
|
|
68846
|
-
|
|
70612
|
+
stableSignalLineCount,
|
|
70613
|
+
warningSignalLineCount,
|
|
70614
|
+
attentionSignalLineCount
|
|
68847
70615
|
};
|
|
68848
|
-
}, [
|
|
70616
|
+
}, [lineSelectorSignalStatusByLine, visibleLineIds]);
|
|
68849
70617
|
const metricsDisplayNames = useMemo(() => {
|
|
68850
70618
|
const nextDisplayNames = {};
|
|
68851
70619
|
currentWorkspaceMetrics.forEach((workspace) => {
|
|
@@ -69702,12 +71470,13 @@ function HomeView({
|
|
|
69702
71470
|
new_line_ids: normalizedLineIds,
|
|
69703
71471
|
selected_line_count: normalizedLineIds.length,
|
|
69704
71472
|
selection_mode: isAllLinesSelection(normalizedLineIds) ? "all" : normalizedLineIds.length === 1 ? "single" : "custom",
|
|
69705
|
-
|
|
69706
|
-
|
|
71473
|
+
stable_signal_line_count: lineSelectorSignalDotStats.stableSignalLineCount,
|
|
71474
|
+
warning_signal_line_count: lineSelectorSignalDotStats.warningSignalLineCount,
|
|
71475
|
+
attention_signal_line_count: lineSelectorSignalDotStats.attentionSignalLineCount,
|
|
69707
71476
|
selector_indicator_version: LINE_SELECTOR_INDICATOR_VERSION,
|
|
69708
71477
|
line_name: getLineSelectionLabel(normalizedLineIds)
|
|
69709
71478
|
});
|
|
69710
|
-
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope,
|
|
71479
|
+
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, lineSelectorSignalDotStats, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
|
|
69711
71480
|
useCallback(() => {
|
|
69712
71481
|
updateSelectedLineIds(visibleLineIds);
|
|
69713
71482
|
}, [updateSelectedLineIds, visibleLineIds]);
|
|
@@ -69766,8 +71535,9 @@ function HomeView({
|
|
|
69766
71535
|
selected_line_ids: selectedLineIds,
|
|
69767
71536
|
selected_line_count: selectedLineIds.length,
|
|
69768
71537
|
is_all_lines: isAllLinesSelection(selectedLineIds),
|
|
69769
|
-
|
|
69770
|
-
|
|
71538
|
+
stable_signal_line_count: lineSelectorSignalDotStats.stableSignalLineCount,
|
|
71539
|
+
warning_signal_line_count: lineSelectorSignalDotStats.warningSignalLineCount,
|
|
71540
|
+
attention_signal_line_count: lineSelectorSignalDotStats.attentionSignalLineCount,
|
|
69771
71541
|
selector_indicator_version: LINE_SELECTOR_INDICATOR_VERSION
|
|
69772
71542
|
});
|
|
69773
71543
|
}
|
|
@@ -69809,7 +71579,8 @@ function HomeView({
|
|
|
69809
71579
|
] }),
|
|
69810
71580
|
/* @__PURE__ */ jsx("div", { className: "max-h-56 space-y-0.5 overflow-y-auto pr-1", children: visibleLineIds.map((lineId) => {
|
|
69811
71581
|
const isChecked = pendingSelectedLineIds.includes(lineId);
|
|
69812
|
-
const
|
|
71582
|
+
const signalStatus = lineSelectorSignalStatusByLine.get(lineId);
|
|
71583
|
+
const signalDotClass = signalStatus === "stable" ? "bg-green-500" : signalStatus === "warning" ? "bg-yellow-400" : signalStatus === "attention" ? "bg-red-500" : "";
|
|
69813
71584
|
const lineLabel = mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}`;
|
|
69814
71585
|
return /* @__PURE__ */ jsxs(
|
|
69815
71586
|
"label",
|
|
@@ -69837,11 +71608,11 @@ function HomeView({
|
|
|
69837
71608
|
}
|
|
69838
71609
|
),
|
|
69839
71610
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: lineLabel }),
|
|
69840
|
-
/* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 flex-shrink-0 items-center justify-center", children:
|
|
71611
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-2.5 w-2.5 flex-shrink-0 items-center justify-center", children: signalStatus ? /* @__PURE__ */ jsx(
|
|
69841
71612
|
"span",
|
|
69842
71613
|
{
|
|
69843
71614
|
"data-testid": `line-selector-signal-dot-${lineId}`,
|
|
69844
|
-
className:
|
|
71615
|
+
className: `h-2 w-2 rounded-full ${signalDotClass}`,
|
|
69845
71616
|
"aria-hidden": "true"
|
|
69846
71617
|
}
|
|
69847
71618
|
) : null })
|
|
@@ -69873,8 +71644,8 @@ function HomeView({
|
|
|
69873
71644
|
mergedLineNames,
|
|
69874
71645
|
selectedLineIds,
|
|
69875
71646
|
pendingSelectedLineIds,
|
|
69876
|
-
|
|
69877
|
-
|
|
71647
|
+
lineSelectorSignalStatusByLine,
|
|
71648
|
+
lineSelectorSignalDotStats,
|
|
69878
71649
|
displayMode,
|
|
69879
71650
|
slideshowActiveLineId,
|
|
69880
71651
|
visibleLineIds,
|
|
@@ -70474,9 +72245,7 @@ function withWorkspaceDisplayNames(Component3, options = {}) {
|
|
|
70474
72245
|
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
70475
72246
|
}
|
|
70476
72247
|
} else if (lineIdArray.length > 0) {
|
|
70477
|
-
await
|
|
70478
|
-
lineIdArray.map((lineId) => preInitializeWorkspaceDisplayNames(lineId))
|
|
70479
|
-
);
|
|
72248
|
+
await preInitializeWorkspaceDisplayNamesForLines(lineIdArray);
|
|
70480
72249
|
} else {
|
|
70481
72250
|
await preInitializeWorkspaceDisplayNames();
|
|
70482
72251
|
}
|
|
@@ -80940,7 +82709,6 @@ var TargetsViewUI = ({
|
|
|
80940
82709
|
skuRequired = false,
|
|
80941
82710
|
onUpdateWorkspaceSelectedSku
|
|
80942
82711
|
}) => {
|
|
80943
|
-
const { displayNames: workspaceDisplayNames } = useWorkspaceDisplayNames();
|
|
80944
82712
|
const mobileMenuContext = useMobileMenu();
|
|
80945
82713
|
useHideMobileHeader(!!mobileMenuContext);
|
|
80946
82714
|
if (isLoading) {
|
|
@@ -81122,7 +82890,7 @@ var TargetsViewUI = ({
|
|
|
81122
82890
|
] })
|
|
81123
82891
|
] }) }),
|
|
81124
82892
|
/* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-100", children: line.workspaces.map((workspace) => {
|
|
81125
|
-
const formattedName =
|
|
82893
|
+
const formattedName = workspace.displayName || formatWorkspaceName(workspace.name, lineId);
|
|
81126
82894
|
const realSkuOptions = (workspace.skuRows || []).filter((r2) => !r2.is_dummy);
|
|
81127
82895
|
const showSkuDropdown = !!onUpdateWorkspaceSelectedSku && realSkuOptions.length >= 1;
|
|
81128
82896
|
const isPlanLocked = !!workspace.productionPlanLock?.locked;
|
|
@@ -81673,6 +83441,7 @@ var TargetsView = ({
|
|
|
81673
83441
|
return {
|
|
81674
83442
|
id: ws.id,
|
|
81675
83443
|
name: ws.workspace_id,
|
|
83444
|
+
displayName: ws.display_name || ws.workspace_id,
|
|
81676
83445
|
targetPPH: selectedRow?.pph_threshold ?? (threshold?.pph_threshold ? Math.round(threshold.pph_threshold) : ""),
|
|
81677
83446
|
targetCycleTime: selectedRow?.ideal_cycle_time ?? (threshold?.ideal_cycle_time ?? ""),
|
|
81678
83447
|
targetDayOutput: selectedRow?.total_day_output ?? (threshold?.total_day_output ?? ""),
|
|
@@ -81731,6 +83500,7 @@ var TargetsView = ({
|
|
|
81731
83500
|
return {
|
|
81732
83501
|
id: ws.id,
|
|
81733
83502
|
name: ws.workspace_id,
|
|
83503
|
+
displayName: ws.display_name || ws.workspace_id,
|
|
81734
83504
|
targetPPH: "",
|
|
81735
83505
|
targetCycleTime: "",
|
|
81736
83506
|
targetDayOutput: "",
|
|
@@ -82211,15 +83981,31 @@ var TargetsView = ({
|
|
|
82211
83981
|
const handleUpdateWorkspaceDisplayName = useCallback(async (workspaceId, displayName) => {
|
|
82212
83982
|
try {
|
|
82213
83983
|
const updated = await workspaceService.updateWorkspaceDisplayName(workspaceId, displayName);
|
|
83984
|
+
const nextDisplayName = updated?.display_name || displayName;
|
|
83985
|
+
setAllShiftsData((prev) => {
|
|
83986
|
+
const next = { ...prev };
|
|
83987
|
+
Object.entries(prev).forEach(([shiftId, shiftData]) => {
|
|
83988
|
+
const numericShiftId = Number(shiftId);
|
|
83989
|
+
const updatedShiftData = {};
|
|
83990
|
+
Object.entries(shiftData).forEach(([lineId, line]) => {
|
|
83991
|
+
updatedShiftData[lineId] = {
|
|
83992
|
+
...line,
|
|
83993
|
+
workspaces: line.workspaces.map(
|
|
83994
|
+
(ws) => ws.id === workspaceId ? { ...ws, displayName: nextDisplayName } : ws
|
|
83995
|
+
)
|
|
83996
|
+
};
|
|
83997
|
+
});
|
|
83998
|
+
next[numericShiftId] = updatedShiftData;
|
|
83999
|
+
});
|
|
84000
|
+
return next;
|
|
84001
|
+
});
|
|
82214
84002
|
if (updated?.line_id && updated?.workspace_id) {
|
|
82215
84003
|
upsertWorkspaceDisplayNameInCache({
|
|
82216
84004
|
lineId: updated.line_id,
|
|
82217
84005
|
workspaceId: updated.workspace_id,
|
|
82218
|
-
displayName:
|
|
84006
|
+
displayName: nextDisplayName,
|
|
82219
84007
|
enabled: updated?.enable
|
|
82220
84008
|
});
|
|
82221
|
-
} else {
|
|
82222
|
-
await forceRefreshWorkspaceDisplayNames();
|
|
82223
84009
|
}
|
|
82224
84010
|
toast.success("Workspace name updated successfully");
|
|
82225
84011
|
} catch (error) {
|
|
@@ -82263,9 +84049,8 @@ var TargetsView = ({
|
|
|
82263
84049
|
}
|
|
82264
84050
|
);
|
|
82265
84051
|
};
|
|
82266
|
-
var
|
|
82267
|
-
var
|
|
82268
|
-
var AuthenticatedTargetsView = withAuth(React125__default.memo(TargetsViewWithDisplayNames));
|
|
84052
|
+
var TargetsView_default = TargetsView;
|
|
84053
|
+
var AuthenticatedTargetsView = withAuth(React125__default.memo(TargetsView));
|
|
82269
84054
|
function useTimezone(options = {}) {
|
|
82270
84055
|
const dashboardConfig = useDashboardConfig();
|
|
82271
84056
|
const workspaceConfig = useWorkspaceConfig();
|
|
@@ -82445,17 +84230,22 @@ var WorkspaceHourSummaryPanel = ({
|
|
|
82445
84230
|
return;
|
|
82446
84231
|
}
|
|
82447
84232
|
autoSummaryKeyRef.current = requestKey;
|
|
82448
|
-
|
|
82449
|
-
|
|
82450
|
-
|
|
82451
|
-
|
|
82452
|
-
|
|
82453
|
-
|
|
82454
|
-
|
|
82455
|
-
|
|
82456
|
-
|
|
82457
|
-
|
|
82458
|
-
|
|
84233
|
+
const summaryTimer = window.setTimeout(() => {
|
|
84234
|
+
void summarize({
|
|
84235
|
+
workspaceId,
|
|
84236
|
+
companyId,
|
|
84237
|
+
date,
|
|
84238
|
+
shiftId,
|
|
84239
|
+
hourIndex: selectedHour.hourIndex,
|
|
84240
|
+
hourStart: selectedHour.startTime,
|
|
84241
|
+
hourEnd: selectedHour.endTime,
|
|
84242
|
+
forceRefresh: false,
|
|
84243
|
+
selectionSource: selectedHour.source ?? "unknown"
|
|
84244
|
+
}).catch(() => void 0);
|
|
84245
|
+
}, 1500);
|
|
84246
|
+
return () => {
|
|
84247
|
+
window.clearTimeout(summaryTimer);
|
|
84248
|
+
};
|
|
82459
84249
|
}, [canSummarize, companyId, date, selectedHour, selectedKey, shiftId, summarize, workspaceId]);
|
|
82460
84250
|
if (!selectedHour) {
|
|
82461
84251
|
return null;
|
|
@@ -82639,10 +84429,18 @@ var WorkspaceDetailView = ({
|
|
|
82639
84429
|
setSelectedHour(null);
|
|
82640
84430
|
}, [workspaceId, date, shift]);
|
|
82641
84431
|
const dashboardConfig = useDashboardConfig();
|
|
84432
|
+
const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
|
|
82642
84433
|
const { legend: efficiencyLegend } = useEfficiencyLegend();
|
|
82643
84434
|
const prewarmedClipsRef = useRef(/* @__PURE__ */ new Set());
|
|
82644
84435
|
const prewarmInFlightRef = useRef(/* @__PURE__ */ new Set());
|
|
82645
84436
|
const [lowMomentsPrefetch, setLowMomentsPrefetch] = useState(null);
|
|
84437
|
+
const selectedHourClipPrefetchInFlightRef = useRef(/* @__PURE__ */ new Set());
|
|
84438
|
+
const selectedHourClipPrefetchAbortRef = useRef(null);
|
|
84439
|
+
const [initialTimePrefetch, setInitialTimePrefetch] = useState(null);
|
|
84440
|
+
const {
|
|
84441
|
+
isFastSlowClipFiltersEnabled,
|
|
84442
|
+
isResolved: isFastSlowClipFiltersResolved
|
|
84443
|
+
} = useCompanyFastSlowClipFiltersEnabled();
|
|
82646
84444
|
const [aiSummaryHour, setAiSummaryHour] = useState(null);
|
|
82647
84445
|
const buildHourlyOutputActionTrackingProps = useCallback((payload) => ({
|
|
82648
84446
|
workspace_id: workspaceId,
|
|
@@ -82672,24 +84470,286 @@ var WorkspaceDetailView = ({
|
|
|
82672
84470
|
timezone,
|
|
82673
84471
|
workspaceId
|
|
82674
84472
|
]);
|
|
84473
|
+
const prefetchClipsForSelectedHour = useCallback((hour) => {
|
|
84474
|
+
if (!isClipsEnabled || !dashboardConfig?.s3Config || !workspaceId || !supabase) {
|
|
84475
|
+
return;
|
|
84476
|
+
}
|
|
84477
|
+
const resolvedDate = date || getOperationalDate(timezone);
|
|
84478
|
+
const resolvedShiftId = parsedShiftId ?? selectedShift;
|
|
84479
|
+
if (!resolvedDate || resolvedShiftId === null || resolvedShiftId === void 0) {
|
|
84480
|
+
return;
|
|
84481
|
+
}
|
|
84482
|
+
const categoryId = "cycle_completion";
|
|
84483
|
+
const regularCategoryIds = ["cycle_completion", "idle_time", "recent_flow_red_streak"];
|
|
84484
|
+
const percentileCategoryIds = isFastSlowClipFiltersEnabled ? ["fast-cycles", "slow-cycles"] : [];
|
|
84485
|
+
const allPrefetchCategoryIds = [...regularCategoryIds, ...percentileCategoryIds];
|
|
84486
|
+
const effectiveTimezone = hour.timezone || timezone;
|
|
84487
|
+
const prefetchKey = [
|
|
84488
|
+
workspaceId,
|
|
84489
|
+
resolvedDate,
|
|
84490
|
+
resolvedShiftId,
|
|
84491
|
+
hour.startTime,
|
|
84492
|
+
hour.endTime,
|
|
84493
|
+
effectiveTimezone || "",
|
|
84494
|
+
allPrefetchCategoryIds.join(",")
|
|
84495
|
+
].join("|");
|
|
84496
|
+
if (initialTimePrefetch?.key === prefetchKey && !initialTimePrefetch.loading) {
|
|
84497
|
+
return;
|
|
84498
|
+
}
|
|
84499
|
+
if (selectedHourClipPrefetchInFlightRef.current.has(prefetchKey)) {
|
|
84500
|
+
return;
|
|
84501
|
+
}
|
|
84502
|
+
selectedHourClipPrefetchAbortRef.current?.abort();
|
|
84503
|
+
const controller = new AbortController();
|
|
84504
|
+
selectedHourClipPrefetchAbortRef.current = controller;
|
|
84505
|
+
selectedHourClipPrefetchInFlightRef.current.add(prefetchKey);
|
|
84506
|
+
const existingSnapshot = initialTimePrefetch?.key === prefetchKey ? initialTimePrefetch : null;
|
|
84507
|
+
setInitialTimePrefetch({
|
|
84508
|
+
key: prefetchKey,
|
|
84509
|
+
categoryId,
|
|
84510
|
+
metadata: existingSnapshot?.metadata || [],
|
|
84511
|
+
metadataByCategory: existingSnapshot?.metadataByCategory || {},
|
|
84512
|
+
totalsByCategory: existingSnapshot?.totalsByCategory || {},
|
|
84513
|
+
percentileClipsByCategory: existingSnapshot?.percentileClipsByCategory || {},
|
|
84514
|
+
firstVideo: existingSnapshot?.firstVideo || null,
|
|
84515
|
+
total: existingSnapshot?.total || 0,
|
|
84516
|
+
loading: true,
|
|
84517
|
+
error: null
|
|
84518
|
+
});
|
|
84519
|
+
const s3Service = videoPrefetchManager.getS3Service(dashboardConfig);
|
|
84520
|
+
const fetchHourlySnapshot = async () => {
|
|
84521
|
+
try {
|
|
84522
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
84523
|
+
method: "POST",
|
|
84524
|
+
headers: {
|
|
84525
|
+
"Content-Type": "application/json"
|
|
84526
|
+
},
|
|
84527
|
+
body: JSON.stringify({
|
|
84528
|
+
action: "hourly-snapshot",
|
|
84529
|
+
workspaceId,
|
|
84530
|
+
date: resolvedDate,
|
|
84531
|
+
shift: resolvedShiftId,
|
|
84532
|
+
startTime: hour.startTime,
|
|
84533
|
+
endTime: hour.endTime,
|
|
84534
|
+
timeFilterTimezone: effectiveTimezone
|
|
84535
|
+
}),
|
|
84536
|
+
signal: controller.signal,
|
|
84537
|
+
redirectReason: "session_expired"
|
|
84538
|
+
});
|
|
84539
|
+
if (!response.ok) {
|
|
84540
|
+
return false;
|
|
84541
|
+
}
|
|
84542
|
+
const snapshot = await response.json();
|
|
84543
|
+
const metadataByCategory = snapshot?.metadataByCategory && typeof snapshot.metadataByCategory === "object" ? snapshot.metadataByCategory : {};
|
|
84544
|
+
const percentileClipsByCategory = snapshot?.percentileClipsByCategory && typeof snapshot.percentileClipsByCategory === "object" ? snapshot.percentileClipsByCategory : {};
|
|
84545
|
+
const totalsByCategory = snapshot?.totalsByCategory && typeof snapshot.totalsByCategory === "object" ? Object.entries(snapshot.totalsByCategory).reduce((accumulator, [key, value]) => {
|
|
84546
|
+
const total = Number(value);
|
|
84547
|
+
accumulator[key] = Number.isFinite(total) ? Math.max(0, total) : 0;
|
|
84548
|
+
return accumulator;
|
|
84549
|
+
}, {}) : {};
|
|
84550
|
+
const snapshotCategoryId = typeof snapshot?.categoryId === "string" ? snapshot.categoryId : categoryId;
|
|
84551
|
+
const metadata = Array.isArray(snapshot?.metadata) ? snapshot.metadata : Array.isArray(metadataByCategory[snapshotCategoryId]) ? metadataByCategory[snapshotCategoryId] : [];
|
|
84552
|
+
if (controller.signal.aborted) {
|
|
84553
|
+
return true;
|
|
84554
|
+
}
|
|
84555
|
+
setInitialTimePrefetch({
|
|
84556
|
+
key: prefetchKey,
|
|
84557
|
+
categoryId: snapshotCategoryId,
|
|
84558
|
+
metadata,
|
|
84559
|
+
metadataByCategory,
|
|
84560
|
+
totalsByCategory,
|
|
84561
|
+
percentileClipsByCategory,
|
|
84562
|
+
firstVideo: snapshot?.firstVideo || null,
|
|
84563
|
+
total: typeof totalsByCategory[snapshotCategoryId] === "number" ? totalsByCategory[snapshotCategoryId] : metadata.length,
|
|
84564
|
+
loading: false,
|
|
84565
|
+
error: null
|
|
84566
|
+
});
|
|
84567
|
+
return true;
|
|
84568
|
+
} catch (error2) {
|
|
84569
|
+
if (error2.name === "AbortError") {
|
|
84570
|
+
return true;
|
|
84571
|
+
}
|
|
84572
|
+
console.warn("[WorkspaceDetailView] Hourly clips snapshot failed; falling back to category prefetch:", error2);
|
|
84573
|
+
return false;
|
|
84574
|
+
}
|
|
84575
|
+
};
|
|
84576
|
+
const fetchRegularCategory = async (prefetchCategoryId) => {
|
|
84577
|
+
const metadataResponse = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
84578
|
+
method: "POST",
|
|
84579
|
+
headers: {
|
|
84580
|
+
"Content-Type": "application/json"
|
|
84581
|
+
},
|
|
84582
|
+
body: JSON.stringify({
|
|
84583
|
+
action: "clip-metadata",
|
|
84584
|
+
workspaceId,
|
|
84585
|
+
date: resolvedDate,
|
|
84586
|
+
shift: resolvedShiftId,
|
|
84587
|
+
category: prefetchCategoryId,
|
|
84588
|
+
page: 1,
|
|
84589
|
+
limit: 500,
|
|
84590
|
+
knownTotal: null,
|
|
84591
|
+
startTime: hour.startTime,
|
|
84592
|
+
endTime: hour.endTime,
|
|
84593
|
+
timeFilterTimezone: effectiveTimezone,
|
|
84594
|
+
sort: prefetchCategoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : "latest"
|
|
84595
|
+
}),
|
|
84596
|
+
signal: controller.signal,
|
|
84597
|
+
redirectReason: "session_expired"
|
|
84598
|
+
});
|
|
84599
|
+
if (!metadataResponse.ok) {
|
|
84600
|
+
throw new Error(`Hourly clips metadata prefetch failed for ${prefetchCategoryId}: ${metadataResponse.status}`);
|
|
84601
|
+
}
|
|
84602
|
+
const metadataData = await metadataResponse.json();
|
|
84603
|
+
return {
|
|
84604
|
+
categoryId: prefetchCategoryId,
|
|
84605
|
+
clips: Array.isArray(metadataData?.clips) ? metadataData.clips : [],
|
|
84606
|
+
total: typeof metadataData?.total === "number" ? metadataData.total : 0
|
|
84607
|
+
};
|
|
84608
|
+
};
|
|
84609
|
+
const fetchPercentileCategory = async (prefetchCategoryId) => {
|
|
84610
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
84611
|
+
method: "POST",
|
|
84612
|
+
headers: {
|
|
84613
|
+
"Content-Type": "application/json"
|
|
84614
|
+
},
|
|
84615
|
+
body: JSON.stringify({
|
|
84616
|
+
action: "percentile-clips",
|
|
84617
|
+
workspaceId,
|
|
84618
|
+
startDate: `${resolvedDate}T00:00:00Z`,
|
|
84619
|
+
endDate: `${resolvedDate}T23:59:59Z`,
|
|
84620
|
+
percentile: 10,
|
|
84621
|
+
shiftId: resolvedShiftId,
|
|
84622
|
+
limit: 500,
|
|
84623
|
+
startTime: hour.startTime,
|
|
84624
|
+
endTime: hour.endTime,
|
|
84625
|
+
timeFilterTimezone: effectiveTimezone,
|
|
84626
|
+
percentileAction: prefetchCategoryId
|
|
84627
|
+
}),
|
|
84628
|
+
signal: controller.signal,
|
|
84629
|
+
redirectReason: "session_expired"
|
|
84630
|
+
});
|
|
84631
|
+
if (!response.ok) {
|
|
84632
|
+
throw new Error(`Hourly percentile clips prefetch failed for ${prefetchCategoryId}: ${response.status}`);
|
|
84633
|
+
}
|
|
84634
|
+
const data = await response.json();
|
|
84635
|
+
return {
|
|
84636
|
+
categoryId: prefetchCategoryId,
|
|
84637
|
+
clips: Array.isArray(data?.clips) ? data.clips : [],
|
|
84638
|
+
total: typeof data?.total === "number" ? data.total : 0
|
|
84639
|
+
};
|
|
84640
|
+
};
|
|
84641
|
+
const runPrefetch = async () => {
|
|
84642
|
+
try {
|
|
84643
|
+
const snapshotLoaded = await fetchHourlySnapshot();
|
|
84644
|
+
if (snapshotLoaded) {
|
|
84645
|
+
return;
|
|
84646
|
+
}
|
|
84647
|
+
const cycleCompletionPromise = fetchRegularCategory("cycle_completion");
|
|
84648
|
+
let resolvedFirstVideo = null;
|
|
84649
|
+
const firstVideoPromise = cycleCompletionPromise.then(async (cycleResponse) => {
|
|
84650
|
+
const firstClipId = cycleResponse.clips[0]?.clipId || cycleResponse.clips[0]?.id || null;
|
|
84651
|
+
if (!firstClipId) {
|
|
84652
|
+
return null;
|
|
84653
|
+
}
|
|
84654
|
+
const video = await s3Service.getClipById(firstClipId);
|
|
84655
|
+
resolvedFirstVideo = video;
|
|
84656
|
+
if (!controller.signal.aborted) {
|
|
84657
|
+
setInitialTimePrefetch((prev) => prev?.key === prefetchKey ? {
|
|
84658
|
+
...prev,
|
|
84659
|
+
firstVideo: video
|
|
84660
|
+
} : prev);
|
|
84661
|
+
}
|
|
84662
|
+
return video;
|
|
84663
|
+
}).catch((error2) => {
|
|
84664
|
+
if (error2.name !== "AbortError") {
|
|
84665
|
+
console.warn("[WorkspaceDetailView] Hourly first clip prefetch failed:", error2);
|
|
84666
|
+
}
|
|
84667
|
+
return null;
|
|
84668
|
+
});
|
|
84669
|
+
const percentileResponsesPromise = Promise.all(percentileCategoryIds.map(fetchPercentileCategory));
|
|
84670
|
+
const regularResponses = await Promise.all([
|
|
84671
|
+
cycleCompletionPromise,
|
|
84672
|
+
fetchRegularCategory("idle_time"),
|
|
84673
|
+
fetchRegularCategory("recent_flow_red_streak")
|
|
84674
|
+
]);
|
|
84675
|
+
const percentileResponses = await percentileResponsesPromise;
|
|
84676
|
+
const metadataByCategory = regularResponses.reduce((accumulator, response) => {
|
|
84677
|
+
accumulator[response.categoryId] = response.clips;
|
|
84678
|
+
return accumulator;
|
|
84679
|
+
}, {});
|
|
84680
|
+
const percentileClipsByCategory = percentileResponses.reduce((accumulator, response) => {
|
|
84681
|
+
accumulator[response.categoryId] = response.clips;
|
|
84682
|
+
return accumulator;
|
|
84683
|
+
}, {});
|
|
84684
|
+
const totalsByCategory = [...regularResponses, ...percentileResponses].reduce((accumulator, response) => {
|
|
84685
|
+
accumulator[response.categoryId] = Math.max(0, Number(response.total || 0));
|
|
84686
|
+
return accumulator;
|
|
84687
|
+
}, {});
|
|
84688
|
+
const metadata = metadataByCategory[categoryId] || [];
|
|
84689
|
+
if (controller.signal.aborted) {
|
|
84690
|
+
return;
|
|
84691
|
+
}
|
|
84692
|
+
setInitialTimePrefetch({
|
|
84693
|
+
key: prefetchKey,
|
|
84694
|
+
categoryId,
|
|
84695
|
+
metadata,
|
|
84696
|
+
metadataByCategory,
|
|
84697
|
+
totalsByCategory,
|
|
84698
|
+
percentileClipsByCategory,
|
|
84699
|
+
firstVideo: resolvedFirstVideo,
|
|
84700
|
+
total: typeof totalsByCategory[categoryId] === "number" ? totalsByCategory[categoryId] : metadata.length,
|
|
84701
|
+
loading: false,
|
|
84702
|
+
error: null
|
|
84703
|
+
});
|
|
84704
|
+
void firstVideoPromise;
|
|
84705
|
+
} catch (error2) {
|
|
84706
|
+
if (error2.name === "AbortError") {
|
|
84707
|
+
return;
|
|
84708
|
+
}
|
|
84709
|
+
console.warn("[WorkspaceDetailView] Hourly clips prefetch failed:", error2);
|
|
84710
|
+
setInitialTimePrefetch((prev) => prev?.key === prefetchKey ? {
|
|
84711
|
+
...prev,
|
|
84712
|
+
loading: false,
|
|
84713
|
+
error: error2 instanceof Error ? error2.message : "Hourly clips prefetch failed"
|
|
84714
|
+
} : prev);
|
|
84715
|
+
} finally {
|
|
84716
|
+
selectedHourClipPrefetchInFlightRef.current.delete(prefetchKey);
|
|
84717
|
+
}
|
|
84718
|
+
};
|
|
84719
|
+
void runPrefetch();
|
|
84720
|
+
}, [
|
|
84721
|
+
dashboardConfig,
|
|
84722
|
+
date,
|
|
84723
|
+
initialTimePrefetch,
|
|
84724
|
+
isFastSlowClipFiltersEnabled,
|
|
84725
|
+
isClipsEnabled,
|
|
84726
|
+
parsedShiftId,
|
|
84727
|
+
selectedShift,
|
|
84728
|
+
supabase,
|
|
84729
|
+
timezone,
|
|
84730
|
+
workspaceId
|
|
84731
|
+
]);
|
|
82675
84732
|
const handleOutputHourSelect = useCallback((payload) => {
|
|
82676
|
-
|
|
84733
|
+
const hour = {
|
|
82677
84734
|
source: "output",
|
|
82678
84735
|
hourIndex: payload.hourIndex,
|
|
82679
84736
|
timeRange: payload.timeRange,
|
|
82680
84737
|
startTime: payload.startTime,
|
|
82681
84738
|
endTime: payload.endTime,
|
|
84739
|
+
timezone: payload.timezone,
|
|
82682
84740
|
status: payload.status,
|
|
82683
84741
|
output: payload.output,
|
|
82684
84742
|
target: payload.target
|
|
82685
|
-
}
|
|
82686
|
-
|
|
84743
|
+
};
|
|
84744
|
+
setSelectedHour(hour);
|
|
84745
|
+
prefetchClipsForSelectedHour(hour);
|
|
84746
|
+
}, [prefetchClipsForSelectedHour]);
|
|
82687
84747
|
const handleAiSummaryClick = useCallback((payload) => {
|
|
82688
84748
|
trackCoreEvent("Hourly Output Ask AI Clicked", buildHourlyOutputActionTrackingProps(payload));
|
|
82689
84749
|
setAiSummaryHour(payload);
|
|
82690
84750
|
}, [buildHourlyOutputActionTrackingProps]);
|
|
82691
84751
|
const handleCycleHourSelect = useCallback((payload) => {
|
|
82692
|
-
|
|
84752
|
+
const hour = {
|
|
82693
84753
|
source: "cycle",
|
|
82694
84754
|
hourIndex: payload.hourIndex,
|
|
82695
84755
|
timeRange: payload.timeRange,
|
|
@@ -82699,17 +84759,23 @@ var WorkspaceDetailView = ({
|
|
|
82699
84759
|
cycleTime: payload.cycleTime,
|
|
82700
84760
|
idealCycleTime: payload.idealCycleTime,
|
|
82701
84761
|
idleMinutes: payload.idleMinutes
|
|
82702
|
-
}
|
|
82703
|
-
|
|
84762
|
+
};
|
|
84763
|
+
setSelectedHour(hour);
|
|
84764
|
+
prefetchClipsForSelectedHour(hour);
|
|
84765
|
+
}, [prefetchClipsForSelectedHour]);
|
|
82704
84766
|
const handleOpenClipsForHour = useCallback((hour) => {
|
|
84767
|
+
prefetchClipsForSelectedHour(hour);
|
|
82705
84768
|
setPendingClipHourFilter({
|
|
82706
84769
|
startTime: hour.startTime,
|
|
82707
84770
|
endTime: hour.endTime,
|
|
82708
84771
|
sourceLabel: hour.timeRange,
|
|
82709
|
-
status: hour.status === "below_target" || hour.status === "above_standard" ? "below_target" : "met_target"
|
|
84772
|
+
status: hour.status === "below_target" || hour.status === "above_standard" ? "below_target" : "met_target",
|
|
84773
|
+
timezone: hour.timezone,
|
|
84774
|
+
categoryId: "cycle_completion",
|
|
84775
|
+
categoryIds: ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time", "recent_flow_red_streak"]
|
|
82710
84776
|
});
|
|
82711
84777
|
setActiveTab("bottlenecks");
|
|
82712
|
-
}, []);
|
|
84778
|
+
}, [prefetchClipsForSelectedHour]);
|
|
82713
84779
|
const handleWatchClipsFromChart = useCallback((payload) => {
|
|
82714
84780
|
trackCoreEvent("Hourly Output Watch Clips Clicked", buildHourlyOutputActionTrackingProps(payload));
|
|
82715
84781
|
handleOpenClipsForHour({
|
|
@@ -82718,6 +84784,7 @@ var WorkspaceDetailView = ({
|
|
|
82718
84784
|
timeRange: payload.timeRange,
|
|
82719
84785
|
startTime: payload.startTime,
|
|
82720
84786
|
endTime: payload.endTime,
|
|
84787
|
+
timezone: payload.timezone,
|
|
82721
84788
|
status: payload.status,
|
|
82722
84789
|
output: payload.output,
|
|
82723
84790
|
target: payload.target
|
|
@@ -82740,11 +84807,6 @@ var WorkspaceDetailView = ({
|
|
|
82740
84807
|
startDate: isFullRange ? void 0 : rangeStart,
|
|
82741
84808
|
endDate: isFullRange ? void 0 : rangeEnd
|
|
82742
84809
|
});
|
|
82743
|
-
const {
|
|
82744
|
-
isFastSlowClipFiltersEnabled,
|
|
82745
|
-
isResolved: isFastSlowClipFiltersResolved
|
|
82746
|
-
} = useCompanyFastSlowClipFiltersEnabled();
|
|
82747
|
-
const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
|
|
82748
84810
|
dashboardConfig?.supervisorConfig?.enabled || false;
|
|
82749
84811
|
const routedLineId = lineId || selectedLineId;
|
|
82750
84812
|
const latestCachedDetailedMetrics = useMemo(() => {
|
|
@@ -84491,6 +86553,7 @@ var WorkspaceDetailView = ({
|
|
|
84491
86553
|
workspaceMetrics: detailedWorkspaceMetrics || void 0,
|
|
84492
86554
|
prefetchedPercentileCounts: isFastSlowClipFiltersEnabled ? prefetchedPercentileCounts : null,
|
|
84493
86555
|
lowMomentsPrefetch,
|
|
86556
|
+
initialTimePrefetch,
|
|
84494
86557
|
initialTimeFilter: pendingClipHourFilter,
|
|
84495
86558
|
className: "h-[calc(100vh-10rem)]"
|
|
84496
86559
|
}
|
|
@@ -94048,4 +96111,6 @@ var RecentFlowSnapshotGrid = ({
|
|
|
94048
96111
|
);
|
|
94049
96112
|
};
|
|
94050
96113
|
|
|
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 };
|
|
96114
|
+
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 };
|
|
96115
|
+
//# sourceMappingURL=index.mjs.map
|
|
96116
|
+
//# sourceMappingURL=index.mjs.map
|