@optifye/dashboard-core 6.1.7 → 6.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +74 -7
- package/dist/index.mjs +74 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23095,7 +23095,14 @@ var S3ClipsService = class {
|
|
|
23095
23095
|
}
|
|
23096
23096
|
const limitPerCategory = limit ? Math.min(Math.max(limit, 1), this.maxLimitPerCategory) : this.defaultLimitPerCategory;
|
|
23097
23097
|
const shouldFetchAll = category === "missing_quality_check" || category === "low_value";
|
|
23098
|
-
|
|
23098
|
+
let initialFetchLimit;
|
|
23099
|
+
if (shouldFetchAll) {
|
|
23100
|
+
initialFetchLimit = void 0;
|
|
23101
|
+
} else if (category) {
|
|
23102
|
+
initialFetchLimit = Math.min(limitPerCategory * 3, this.maxInitialFetch);
|
|
23103
|
+
} else {
|
|
23104
|
+
initialFetchLimit = this.maxInitialFetch;
|
|
23105
|
+
}
|
|
23099
23106
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId, maxKeys: initialFetchLimit });
|
|
23100
23107
|
if (s3Uris.length === 0) {
|
|
23101
23108
|
console.log(`S3ClipsService: No HLS playlists found for workspace ${workspaceId} on date ${date}, shift ${shiftId}`);
|
|
@@ -23221,6 +23228,9 @@ var S3ClipsService = class {
|
|
|
23221
23228
|
return videos;
|
|
23222
23229
|
}
|
|
23223
23230
|
};
|
|
23231
|
+
|
|
23232
|
+
// src/lib/cache/clipsCache.ts
|
|
23233
|
+
var clipsCache = {};
|
|
23224
23234
|
var BottlenecksContent = ({
|
|
23225
23235
|
workspaceId,
|
|
23226
23236
|
workspaceName,
|
|
@@ -23240,6 +23250,7 @@ var BottlenecksContent = ({
|
|
|
23240
23250
|
const videoRef = React19.useRef(null);
|
|
23241
23251
|
const fullscreenContainerRef = React19.useRef(null);
|
|
23242
23252
|
const timestampFilterRef = React19.useRef(null);
|
|
23253
|
+
const hlsRef = React19.useRef(null);
|
|
23243
23254
|
const [isPlaying, setIsPlaying] = React19.useState(false);
|
|
23244
23255
|
const [currentTime, setCurrentTime] = React19.useState(0);
|
|
23245
23256
|
const [duration, setDuration] = React19.useState(0);
|
|
@@ -23288,21 +23299,36 @@ var BottlenecksContent = ({
|
|
|
23288
23299
|
if (timestampEnd) {
|
|
23289
23300
|
timestampEndFull = `${operationalDate}T${timestampEnd}:00`;
|
|
23290
23301
|
}
|
|
23291
|
-
const
|
|
23302
|
+
const cacheKey = `${workspaceId}-${operationalDate}-${shift || "all"}-all-meta-1000-${timestampStartFull || ""}-${timestampEndFull || ""}`;
|
|
23303
|
+
const existingEntry = clipsCache[cacheKey];
|
|
23304
|
+
if (existingEntry?.status === "resolved" && existingEntry.data) {
|
|
23305
|
+
setAllVideos(existingEntry.data);
|
|
23306
|
+
return;
|
|
23307
|
+
}
|
|
23308
|
+
if (existingEntry?.status === "pending" && existingEntry.promise) {
|
|
23309
|
+
setIsLoading(true);
|
|
23310
|
+
existingEntry.promise.then((data) => {
|
|
23311
|
+
setAllVideos(data);
|
|
23312
|
+
setIsLoading(false);
|
|
23313
|
+
}).catch(() => setIsLoading(false));
|
|
23314
|
+
return;
|
|
23315
|
+
}
|
|
23316
|
+
setIsLoading(true);
|
|
23317
|
+
const fetchPromise = s3ClipsService.fetchClips({
|
|
23292
23318
|
workspaceId,
|
|
23293
23319
|
date: operationalDate,
|
|
23294
23320
|
shift: shift?.toString(),
|
|
23295
|
-
// Pass the shift parameter
|
|
23296
23321
|
mode: "full",
|
|
23297
23322
|
includeCycleTime: true,
|
|
23298
23323
|
includeMetadata: true,
|
|
23299
|
-
// Always include metadata for timestamp info
|
|
23300
23324
|
limit: 1e3,
|
|
23301
|
-
// Reasonable limit for UI performance
|
|
23302
23325
|
timestampStart: timestampStartFull,
|
|
23303
23326
|
timestampEnd: timestampEndFull
|
|
23304
23327
|
});
|
|
23305
|
-
|
|
23328
|
+
clipsCache[cacheKey] = { status: "pending", promise: fetchPromise };
|
|
23329
|
+
const videos = await fetchPromise;
|
|
23330
|
+
clipsCache[cacheKey] = { status: "resolved", data: videos };
|
|
23331
|
+
if (videos.length > 0) {
|
|
23306
23332
|
preloadVideoUrl2(videos[0].src);
|
|
23307
23333
|
const firstHigh = videos.find((v) => v.type === "bottleneck" && v.severity === "high");
|
|
23308
23334
|
const firstMed = videos.find((v) => v.type === "bottleneck" && v.severity === "medium");
|
|
@@ -23326,6 +23352,8 @@ var BottlenecksContent = ({
|
|
|
23326
23352
|
].filter(Boolean));
|
|
23327
23353
|
}
|
|
23328
23354
|
setAllVideos(videos);
|
|
23355
|
+
setIsLoading(false);
|
|
23356
|
+
return;
|
|
23329
23357
|
} catch (err) {
|
|
23330
23358
|
console.error("Error fetching HLS clips from S3:", err);
|
|
23331
23359
|
setError("Failed to load clips from storage. Please try again.");
|
|
@@ -23445,6 +23473,14 @@ var BottlenecksContent = ({
|
|
|
23445
23473
|
} else {
|
|
23446
23474
|
import('hls.js').then(({ default: Hls3 }) => {
|
|
23447
23475
|
if (Hls3.isSupported()) {
|
|
23476
|
+
if (hlsRef.current) {
|
|
23477
|
+
try {
|
|
23478
|
+
hlsRef.current.destroy();
|
|
23479
|
+
} catch (err) {
|
|
23480
|
+
console.warn("Failed to destroy previous HLS instance", err);
|
|
23481
|
+
}
|
|
23482
|
+
hlsRef.current = null;
|
|
23483
|
+
}
|
|
23448
23484
|
const hls = new Hls3({
|
|
23449
23485
|
// Add CORS and error handling configuration
|
|
23450
23486
|
xhrSetup: (xhr, url) => {
|
|
@@ -23487,7 +23523,8 @@ var BottlenecksContent = ({
|
|
|
23487
23523
|
testBandwidth: false,
|
|
23488
23524
|
// Error recovery configuration
|
|
23489
23525
|
capLevelOnFPSDrop: false,
|
|
23490
|
-
capLevelToPlayerSize:
|
|
23526
|
+
capLevelToPlayerSize: true,
|
|
23527
|
+
abrEwmaDefaultEstimate: 5e5
|
|
23491
23528
|
});
|
|
23492
23529
|
hls.on(Hls3.Events.ERROR, (event, data) => {
|
|
23493
23530
|
console.error("HLS.js error:", data);
|
|
@@ -23615,6 +23652,13 @@ var BottlenecksContent = ({
|
|
|
23615
23652
|
video.removeEventListener("loadedmetadata", onLoadedMetadata);
|
|
23616
23653
|
video.removeEventListener("ended", onEnded);
|
|
23617
23654
|
video.removeEventListener("error", onError);
|
|
23655
|
+
if (hlsRef.current) {
|
|
23656
|
+
try {
|
|
23657
|
+
hlsRef.current.destroy();
|
|
23658
|
+
} catch (e) {
|
|
23659
|
+
}
|
|
23660
|
+
hlsRef.current = null;
|
|
23661
|
+
}
|
|
23618
23662
|
};
|
|
23619
23663
|
} else if (videoRef.current) {
|
|
23620
23664
|
videoRef.current.pause();
|
|
@@ -33423,6 +33467,29 @@ var WorkspaceDetailView = ({
|
|
|
33423
33467
|
const isHistoricView = Boolean(date && parsedShiftId !== void 0);
|
|
33424
33468
|
const initialTab = getInitialTab(sourceType, defaultTab, fromMonthly, date);
|
|
33425
33469
|
const [activeTab, setActiveTab] = React19.useState(initialTab);
|
|
33470
|
+
const dashboardConfig = useDashboardConfig();
|
|
33471
|
+
React19.useEffect(() => {
|
|
33472
|
+
if (!dashboardConfig?.s3Config) return;
|
|
33473
|
+
const operationalDate2 = date || getOperationalDate();
|
|
33474
|
+
const cacheKey = `${workspaceId}-${operationalDate2}-${shift || "all"}-all-meta-1000--`;
|
|
33475
|
+
if (clipsCache[cacheKey]?.status) return;
|
|
33476
|
+
const service = new S3ClipsService(dashboardConfig);
|
|
33477
|
+
const promise = service.fetchClips({
|
|
33478
|
+
workspaceId,
|
|
33479
|
+
date: operationalDate2,
|
|
33480
|
+
shift: shift?.toString(),
|
|
33481
|
+
mode: "full",
|
|
33482
|
+
includeCycleTime: true,
|
|
33483
|
+
includeMetadata: true,
|
|
33484
|
+
limit: 1e3
|
|
33485
|
+
});
|
|
33486
|
+
clipsCache[cacheKey] = { status: "pending", promise };
|
|
33487
|
+
promise.then((videos) => {
|
|
33488
|
+
clipsCache[cacheKey] = { status: "resolved", data: videos };
|
|
33489
|
+
}).catch((err) => {
|
|
33490
|
+
clipsCache[cacheKey] = { status: "rejected", error: err };
|
|
33491
|
+
});
|
|
33492
|
+
}, [workspaceId, date, shift, dashboardConfig]);
|
|
33426
33493
|
const [isTransitioning, setIsTransitioning] = React19.useState(false);
|
|
33427
33494
|
const [usingFallbackData, setUsingFallbackData] = React19.useState(false);
|
|
33428
33495
|
const [showIdleTime, setShowIdleTime] = React19.useState(false);
|
package/dist/index.mjs
CHANGED
|
@@ -23066,7 +23066,14 @@ var S3ClipsService = class {
|
|
|
23066
23066
|
}
|
|
23067
23067
|
const limitPerCategory = limit ? Math.min(Math.max(limit, 1), this.maxLimitPerCategory) : this.defaultLimitPerCategory;
|
|
23068
23068
|
const shouldFetchAll = category === "missing_quality_check" || category === "low_value";
|
|
23069
|
-
|
|
23069
|
+
let initialFetchLimit;
|
|
23070
|
+
if (shouldFetchAll) {
|
|
23071
|
+
initialFetchLimit = void 0;
|
|
23072
|
+
} else if (category) {
|
|
23073
|
+
initialFetchLimit = Math.min(limitPerCategory * 3, this.maxInitialFetch);
|
|
23074
|
+
} else {
|
|
23075
|
+
initialFetchLimit = this.maxInitialFetch;
|
|
23076
|
+
}
|
|
23070
23077
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId, maxKeys: initialFetchLimit });
|
|
23071
23078
|
if (s3Uris.length === 0) {
|
|
23072
23079
|
console.log(`S3ClipsService: No HLS playlists found for workspace ${workspaceId} on date ${date}, shift ${shiftId}`);
|
|
@@ -23192,6 +23199,9 @@ var S3ClipsService = class {
|
|
|
23192
23199
|
return videos;
|
|
23193
23200
|
}
|
|
23194
23201
|
};
|
|
23202
|
+
|
|
23203
|
+
// src/lib/cache/clipsCache.ts
|
|
23204
|
+
var clipsCache = {};
|
|
23195
23205
|
var BottlenecksContent = ({
|
|
23196
23206
|
workspaceId,
|
|
23197
23207
|
workspaceName,
|
|
@@ -23211,6 +23221,7 @@ var BottlenecksContent = ({
|
|
|
23211
23221
|
const videoRef = useRef(null);
|
|
23212
23222
|
const fullscreenContainerRef = useRef(null);
|
|
23213
23223
|
const timestampFilterRef = useRef(null);
|
|
23224
|
+
const hlsRef = useRef(null);
|
|
23214
23225
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
23215
23226
|
const [currentTime, setCurrentTime] = useState(0);
|
|
23216
23227
|
const [duration, setDuration] = useState(0);
|
|
@@ -23259,21 +23270,36 @@ var BottlenecksContent = ({
|
|
|
23259
23270
|
if (timestampEnd) {
|
|
23260
23271
|
timestampEndFull = `${operationalDate}T${timestampEnd}:00`;
|
|
23261
23272
|
}
|
|
23262
|
-
const
|
|
23273
|
+
const cacheKey = `${workspaceId}-${operationalDate}-${shift || "all"}-all-meta-1000-${timestampStartFull || ""}-${timestampEndFull || ""}`;
|
|
23274
|
+
const existingEntry = clipsCache[cacheKey];
|
|
23275
|
+
if (existingEntry?.status === "resolved" && existingEntry.data) {
|
|
23276
|
+
setAllVideos(existingEntry.data);
|
|
23277
|
+
return;
|
|
23278
|
+
}
|
|
23279
|
+
if (existingEntry?.status === "pending" && existingEntry.promise) {
|
|
23280
|
+
setIsLoading(true);
|
|
23281
|
+
existingEntry.promise.then((data) => {
|
|
23282
|
+
setAllVideos(data);
|
|
23283
|
+
setIsLoading(false);
|
|
23284
|
+
}).catch(() => setIsLoading(false));
|
|
23285
|
+
return;
|
|
23286
|
+
}
|
|
23287
|
+
setIsLoading(true);
|
|
23288
|
+
const fetchPromise = s3ClipsService.fetchClips({
|
|
23263
23289
|
workspaceId,
|
|
23264
23290
|
date: operationalDate,
|
|
23265
23291
|
shift: shift?.toString(),
|
|
23266
|
-
// Pass the shift parameter
|
|
23267
23292
|
mode: "full",
|
|
23268
23293
|
includeCycleTime: true,
|
|
23269
23294
|
includeMetadata: true,
|
|
23270
|
-
// Always include metadata for timestamp info
|
|
23271
23295
|
limit: 1e3,
|
|
23272
|
-
// Reasonable limit for UI performance
|
|
23273
23296
|
timestampStart: timestampStartFull,
|
|
23274
23297
|
timestampEnd: timestampEndFull
|
|
23275
23298
|
});
|
|
23276
|
-
|
|
23299
|
+
clipsCache[cacheKey] = { status: "pending", promise: fetchPromise };
|
|
23300
|
+
const videos = await fetchPromise;
|
|
23301
|
+
clipsCache[cacheKey] = { status: "resolved", data: videos };
|
|
23302
|
+
if (videos.length > 0) {
|
|
23277
23303
|
preloadVideoUrl2(videos[0].src);
|
|
23278
23304
|
const firstHigh = videos.find((v) => v.type === "bottleneck" && v.severity === "high");
|
|
23279
23305
|
const firstMed = videos.find((v) => v.type === "bottleneck" && v.severity === "medium");
|
|
@@ -23297,6 +23323,8 @@ var BottlenecksContent = ({
|
|
|
23297
23323
|
].filter(Boolean));
|
|
23298
23324
|
}
|
|
23299
23325
|
setAllVideos(videos);
|
|
23326
|
+
setIsLoading(false);
|
|
23327
|
+
return;
|
|
23300
23328
|
} catch (err) {
|
|
23301
23329
|
console.error("Error fetching HLS clips from S3:", err);
|
|
23302
23330
|
setError("Failed to load clips from storage. Please try again.");
|
|
@@ -23416,6 +23444,14 @@ var BottlenecksContent = ({
|
|
|
23416
23444
|
} else {
|
|
23417
23445
|
import('hls.js').then(({ default: Hls3 }) => {
|
|
23418
23446
|
if (Hls3.isSupported()) {
|
|
23447
|
+
if (hlsRef.current) {
|
|
23448
|
+
try {
|
|
23449
|
+
hlsRef.current.destroy();
|
|
23450
|
+
} catch (err) {
|
|
23451
|
+
console.warn("Failed to destroy previous HLS instance", err);
|
|
23452
|
+
}
|
|
23453
|
+
hlsRef.current = null;
|
|
23454
|
+
}
|
|
23419
23455
|
const hls = new Hls3({
|
|
23420
23456
|
// Add CORS and error handling configuration
|
|
23421
23457
|
xhrSetup: (xhr, url) => {
|
|
@@ -23458,7 +23494,8 @@ var BottlenecksContent = ({
|
|
|
23458
23494
|
testBandwidth: false,
|
|
23459
23495
|
// Error recovery configuration
|
|
23460
23496
|
capLevelOnFPSDrop: false,
|
|
23461
|
-
capLevelToPlayerSize:
|
|
23497
|
+
capLevelToPlayerSize: true,
|
|
23498
|
+
abrEwmaDefaultEstimate: 5e5
|
|
23462
23499
|
});
|
|
23463
23500
|
hls.on(Hls3.Events.ERROR, (event, data) => {
|
|
23464
23501
|
console.error("HLS.js error:", data);
|
|
@@ -23586,6 +23623,13 @@ var BottlenecksContent = ({
|
|
|
23586
23623
|
video.removeEventListener("loadedmetadata", onLoadedMetadata);
|
|
23587
23624
|
video.removeEventListener("ended", onEnded);
|
|
23588
23625
|
video.removeEventListener("error", onError);
|
|
23626
|
+
if (hlsRef.current) {
|
|
23627
|
+
try {
|
|
23628
|
+
hlsRef.current.destroy();
|
|
23629
|
+
} catch (e) {
|
|
23630
|
+
}
|
|
23631
|
+
hlsRef.current = null;
|
|
23632
|
+
}
|
|
23589
23633
|
};
|
|
23590
23634
|
} else if (videoRef.current) {
|
|
23591
23635
|
videoRef.current.pause();
|
|
@@ -33394,6 +33438,29 @@ var WorkspaceDetailView = ({
|
|
|
33394
33438
|
const isHistoricView = Boolean(date && parsedShiftId !== void 0);
|
|
33395
33439
|
const initialTab = getInitialTab(sourceType, defaultTab, fromMonthly, date);
|
|
33396
33440
|
const [activeTab, setActiveTab] = useState(initialTab);
|
|
33441
|
+
const dashboardConfig = useDashboardConfig();
|
|
33442
|
+
useEffect(() => {
|
|
33443
|
+
if (!dashboardConfig?.s3Config) return;
|
|
33444
|
+
const operationalDate2 = date || getOperationalDate();
|
|
33445
|
+
const cacheKey = `${workspaceId}-${operationalDate2}-${shift || "all"}-all-meta-1000--`;
|
|
33446
|
+
if (clipsCache[cacheKey]?.status) return;
|
|
33447
|
+
const service = new S3ClipsService(dashboardConfig);
|
|
33448
|
+
const promise = service.fetchClips({
|
|
33449
|
+
workspaceId,
|
|
33450
|
+
date: operationalDate2,
|
|
33451
|
+
shift: shift?.toString(),
|
|
33452
|
+
mode: "full",
|
|
33453
|
+
includeCycleTime: true,
|
|
33454
|
+
includeMetadata: true,
|
|
33455
|
+
limit: 1e3
|
|
33456
|
+
});
|
|
33457
|
+
clipsCache[cacheKey] = { status: "pending", promise };
|
|
33458
|
+
promise.then((videos) => {
|
|
33459
|
+
clipsCache[cacheKey] = { status: "resolved", data: videos };
|
|
33460
|
+
}).catch((err) => {
|
|
33461
|
+
clipsCache[cacheKey] = { status: "rejected", error: err };
|
|
33462
|
+
});
|
|
33463
|
+
}, [workspaceId, date, shift, dashboardConfig]);
|
|
33397
33464
|
const [isTransitioning, setIsTransitioning] = useState(false);
|
|
33398
33465
|
const [usingFallbackData, setUsingFallbackData] = useState(false);
|
|
33399
33466
|
const [showIdleTime, setShowIdleTime] = useState(false);
|