@optifye/dashboard-core 6.5.1 → 6.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +92 -29
- package/dist/index.mjs +92 -29
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1232,6 +1232,14 @@ declare class S3ClipsService {
|
|
|
1232
1232
|
* Fetch clips (main method for compatibility)
|
|
1233
1233
|
*/
|
|
1234
1234
|
fetchClips(params: S3ClipsAPIParams): Promise<BottleneckVideoData[] | VideoSummary>;
|
|
1235
|
+
/**
|
|
1236
|
+
* Batch fetch multiple videos in parallel
|
|
1237
|
+
*/
|
|
1238
|
+
batchFetchVideos(workspaceId: string, date: string, shiftId: string | number, requests: Array<{
|
|
1239
|
+
category: string;
|
|
1240
|
+
index: number;
|
|
1241
|
+
includeMetadata?: boolean;
|
|
1242
|
+
}>): Promise<BottleneckVideoData[]>;
|
|
1235
1243
|
/**
|
|
1236
1244
|
* Get videos page using pagination API
|
|
1237
1245
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1232,6 +1232,14 @@ declare class S3ClipsService {
|
|
|
1232
1232
|
* Fetch clips (main method for compatibility)
|
|
1233
1233
|
*/
|
|
1234
1234
|
fetchClips(params: S3ClipsAPIParams): Promise<BottleneckVideoData[] | VideoSummary>;
|
|
1235
|
+
/**
|
|
1236
|
+
* Batch fetch multiple videos in parallel
|
|
1237
|
+
*/
|
|
1238
|
+
batchFetchVideos(workspaceId: string, date: string, shiftId: string | number, requests: Array<{
|
|
1239
|
+
category: string;
|
|
1240
|
+
index: number;
|
|
1241
|
+
includeMetadata?: boolean;
|
|
1242
|
+
}>): Promise<BottleneckVideoData[]>;
|
|
1235
1243
|
/**
|
|
1236
1244
|
* Get videos page using pagination API
|
|
1237
1245
|
*/
|
package/dist/index.js
CHANGED
|
@@ -4152,6 +4152,23 @@ var S3ClipsAPIClient = class {
|
|
|
4152
4152
|
};
|
|
4153
4153
|
});
|
|
4154
4154
|
}
|
|
4155
|
+
/**
|
|
4156
|
+
* Batch fetch multiple videos in parallel
|
|
4157
|
+
*/
|
|
4158
|
+
async batchFetchVideos(workspaceId, date, shiftId, requests) {
|
|
4159
|
+
const batchKey = `batch:${workspaceId}:${date}:${shiftId}:${requests.length}`;
|
|
4160
|
+
return this.deduplicate(batchKey, async () => {
|
|
4161
|
+
const response = await this.fetchWithAuth("/api/clips/batch", {
|
|
4162
|
+
workspaceId,
|
|
4163
|
+
date,
|
|
4164
|
+
shift: shiftId.toString(),
|
|
4165
|
+
requests,
|
|
4166
|
+
sopCategories: this.sopCategories
|
|
4167
|
+
});
|
|
4168
|
+
console.log(`[S3ClipsAPIClient] Batch fetched ${response.videos.length} videos in ${response.performance.duration}ms`);
|
|
4169
|
+
return response.videos;
|
|
4170
|
+
});
|
|
4171
|
+
}
|
|
4155
4172
|
/**
|
|
4156
4173
|
* Convert S3 URI to CloudFront URL
|
|
4157
4174
|
* In the API client, URLs are already signed from the server
|
|
@@ -4435,6 +4452,23 @@ var S3ClipsService = class {
|
|
|
4435
4452
|
);
|
|
4436
4453
|
return result.videos;
|
|
4437
4454
|
}
|
|
4455
|
+
/**
|
|
4456
|
+
* Batch fetch multiple videos in parallel
|
|
4457
|
+
*/
|
|
4458
|
+
async batchFetchVideos(workspaceId, date, shiftId, requests) {
|
|
4459
|
+
try {
|
|
4460
|
+
const results = await this.apiClient.batchFetchVideos(
|
|
4461
|
+
workspaceId,
|
|
4462
|
+
date,
|
|
4463
|
+
shiftId,
|
|
4464
|
+
requests
|
|
4465
|
+
);
|
|
4466
|
+
return results.map((r2) => r2.video).filter((v) => v !== null);
|
|
4467
|
+
} catch (error) {
|
|
4468
|
+
console.error("[S3ClipsService] Error batch fetching videos:", error);
|
|
4469
|
+
return [];
|
|
4470
|
+
}
|
|
4471
|
+
}
|
|
4438
4472
|
/**
|
|
4439
4473
|
* Get videos page using pagination API
|
|
4440
4474
|
*/
|
|
@@ -27024,44 +27058,73 @@ var BottlenecksContent = ({
|
|
|
27024
27058
|
if (indicesToLoad.length === 0) return;
|
|
27025
27059
|
console.log(`[ensureVideosLoaded] Preloading ${indicesToLoad.length} videos around index ${centerIndex}: [${indicesToLoad.join(", ")}]`);
|
|
27026
27060
|
indicesToLoad.forEach((idx) => loadingVideosRef.current.add(idx));
|
|
27027
|
-
const
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
|
|
27033
|
-
|
|
27061
|
+
const operationalDate = date || getOperationalDate();
|
|
27062
|
+
const shiftStr = effectiveShift;
|
|
27063
|
+
console.log(`[ensureVideosLoaded] Batch fetching ${indicesToLoad.length} videos in parallel`);
|
|
27064
|
+
try {
|
|
27065
|
+
const batchRequests = indicesToLoad.map((index) => ({
|
|
27066
|
+
category: effectiveFilter,
|
|
27067
|
+
index,
|
|
27068
|
+
includeMetadata: false
|
|
27069
|
+
// No metadata during bulk preloading
|
|
27070
|
+
}));
|
|
27071
|
+
const videos = await s3ClipsService.batchFetchVideos(
|
|
27072
|
+
workspaceId,
|
|
27073
|
+
operationalDate,
|
|
27074
|
+
shiftStr,
|
|
27075
|
+
batchRequests
|
|
27076
|
+
);
|
|
27077
|
+
if (videos.length > 0 && isMountedRef.current) {
|
|
27078
|
+
videos.forEach((video, idx) => {
|
|
27079
|
+
if (video) {
|
|
27080
|
+
setAllVideos((prev) => {
|
|
27081
|
+
const exists = prev.some((v) => v.id === video.id);
|
|
27082
|
+
if (!exists) {
|
|
27083
|
+
return [...prev, video];
|
|
27084
|
+
}
|
|
27085
|
+
return prev;
|
|
27086
|
+
});
|
|
27087
|
+
const originalIndex = indicesToLoad[idx];
|
|
27088
|
+
loadedIndices.add(originalIndex);
|
|
27089
|
+
preloadVideoUrl(video.src);
|
|
27090
|
+
}
|
|
27091
|
+
});
|
|
27092
|
+
console.log(`[ensureVideosLoaded] Successfully loaded ${videos.length} videos in batch`);
|
|
27093
|
+
}
|
|
27094
|
+
} catch (error2) {
|
|
27095
|
+
console.error("[ensureVideosLoaded] Batch fetch failed:", error2);
|
|
27096
|
+
const loadPromises = indicesToLoad.map(async (index) => {
|
|
27097
|
+
try {
|
|
27098
|
+
const video = await s3ClipsService.getClipByIndex(
|
|
27034
27099
|
workspaceId,
|
|
27035
27100
|
operationalDate,
|
|
27036
27101
|
shiftStr,
|
|
27037
27102
|
effectiveFilter,
|
|
27038
27103
|
index,
|
|
27039
27104
|
true,
|
|
27040
|
-
// includeCycleTime
|
|
27105
|
+
// includeCycleTime
|
|
27041
27106
|
false
|
|
27042
|
-
// includeMetadata
|
|
27107
|
+
// includeMetadata
|
|
27043
27108
|
);
|
|
27109
|
+
if (video && isMountedRef.current) {
|
|
27110
|
+
setAllVideos((prev) => {
|
|
27111
|
+
const exists = prev.some((v) => v.id === video.id);
|
|
27112
|
+
if (!exists) {
|
|
27113
|
+
return [...prev, video];
|
|
27114
|
+
}
|
|
27115
|
+
return prev;
|
|
27116
|
+
});
|
|
27117
|
+
loadedIndices.add(index);
|
|
27118
|
+
preloadVideoUrl(video.src);
|
|
27119
|
+
}
|
|
27120
|
+
} catch (err) {
|
|
27121
|
+
console.warn(`[ensureVideosLoaded] Failed to load video at index ${index}:`, err);
|
|
27044
27122
|
}
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
27050
|
-
}
|
|
27051
|
-
return prev;
|
|
27052
|
-
});
|
|
27053
|
-
loadedIndices.add(index);
|
|
27054
|
-
preloadVideoUrl(video.src);
|
|
27055
|
-
}
|
|
27056
|
-
} catch (error2) {
|
|
27057
|
-
console.warn(`[ensureVideosLoaded] Failed to load video at index ${index}:`, error2);
|
|
27058
|
-
} finally {
|
|
27059
|
-
loadingVideosRef.current.delete(index);
|
|
27060
|
-
}
|
|
27061
|
-
});
|
|
27062
|
-
Promise.all(loadPromises).catch((err) => {
|
|
27063
|
-
console.warn("[ensureVideosLoaded] Some videos failed to preload:", err);
|
|
27064
|
-
});
|
|
27123
|
+
});
|
|
27124
|
+
await Promise.all(loadPromises);
|
|
27125
|
+
} finally {
|
|
27126
|
+
indicesToLoad.forEach((idx) => loadingVideosRef.current.delete(idx));
|
|
27127
|
+
}
|
|
27065
27128
|
}, [s3ClipsService, workspaceId, clipCounts, sopCategories, date, effectiveShift]);
|
|
27066
27129
|
const loadFirstVideoForCategory = React19.useCallback(async (category) => {
|
|
27067
27130
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
package/dist/index.mjs
CHANGED
|
@@ -4122,6 +4122,23 @@ var S3ClipsAPIClient = class {
|
|
|
4122
4122
|
};
|
|
4123
4123
|
});
|
|
4124
4124
|
}
|
|
4125
|
+
/**
|
|
4126
|
+
* Batch fetch multiple videos in parallel
|
|
4127
|
+
*/
|
|
4128
|
+
async batchFetchVideos(workspaceId, date, shiftId, requests) {
|
|
4129
|
+
const batchKey = `batch:${workspaceId}:${date}:${shiftId}:${requests.length}`;
|
|
4130
|
+
return this.deduplicate(batchKey, async () => {
|
|
4131
|
+
const response = await this.fetchWithAuth("/api/clips/batch", {
|
|
4132
|
+
workspaceId,
|
|
4133
|
+
date,
|
|
4134
|
+
shift: shiftId.toString(),
|
|
4135
|
+
requests,
|
|
4136
|
+
sopCategories: this.sopCategories
|
|
4137
|
+
});
|
|
4138
|
+
console.log(`[S3ClipsAPIClient] Batch fetched ${response.videos.length} videos in ${response.performance.duration}ms`);
|
|
4139
|
+
return response.videos;
|
|
4140
|
+
});
|
|
4141
|
+
}
|
|
4125
4142
|
/**
|
|
4126
4143
|
* Convert S3 URI to CloudFront URL
|
|
4127
4144
|
* In the API client, URLs are already signed from the server
|
|
@@ -4405,6 +4422,23 @@ var S3ClipsService = class {
|
|
|
4405
4422
|
);
|
|
4406
4423
|
return result.videos;
|
|
4407
4424
|
}
|
|
4425
|
+
/**
|
|
4426
|
+
* Batch fetch multiple videos in parallel
|
|
4427
|
+
*/
|
|
4428
|
+
async batchFetchVideos(workspaceId, date, shiftId, requests) {
|
|
4429
|
+
try {
|
|
4430
|
+
const results = await this.apiClient.batchFetchVideos(
|
|
4431
|
+
workspaceId,
|
|
4432
|
+
date,
|
|
4433
|
+
shiftId,
|
|
4434
|
+
requests
|
|
4435
|
+
);
|
|
4436
|
+
return results.map((r2) => r2.video).filter((v) => v !== null);
|
|
4437
|
+
} catch (error) {
|
|
4438
|
+
console.error("[S3ClipsService] Error batch fetching videos:", error);
|
|
4439
|
+
return [];
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4408
4442
|
/**
|
|
4409
4443
|
* Get videos page using pagination API
|
|
4410
4444
|
*/
|
|
@@ -26994,44 +27028,73 @@ var BottlenecksContent = ({
|
|
|
26994
27028
|
if (indicesToLoad.length === 0) return;
|
|
26995
27029
|
console.log(`[ensureVideosLoaded] Preloading ${indicesToLoad.length} videos around index ${centerIndex}: [${indicesToLoad.join(", ")}]`);
|
|
26996
27030
|
indicesToLoad.forEach((idx) => loadingVideosRef.current.add(idx));
|
|
26997
|
-
const
|
|
26998
|
-
|
|
26999
|
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27002
|
-
|
|
27003
|
-
|
|
27031
|
+
const operationalDate = date || getOperationalDate();
|
|
27032
|
+
const shiftStr = effectiveShift;
|
|
27033
|
+
console.log(`[ensureVideosLoaded] Batch fetching ${indicesToLoad.length} videos in parallel`);
|
|
27034
|
+
try {
|
|
27035
|
+
const batchRequests = indicesToLoad.map((index) => ({
|
|
27036
|
+
category: effectiveFilter,
|
|
27037
|
+
index,
|
|
27038
|
+
includeMetadata: false
|
|
27039
|
+
// No metadata during bulk preloading
|
|
27040
|
+
}));
|
|
27041
|
+
const videos = await s3ClipsService.batchFetchVideos(
|
|
27042
|
+
workspaceId,
|
|
27043
|
+
operationalDate,
|
|
27044
|
+
shiftStr,
|
|
27045
|
+
batchRequests
|
|
27046
|
+
);
|
|
27047
|
+
if (videos.length > 0 && isMountedRef.current) {
|
|
27048
|
+
videos.forEach((video, idx) => {
|
|
27049
|
+
if (video) {
|
|
27050
|
+
setAllVideos((prev) => {
|
|
27051
|
+
const exists = prev.some((v) => v.id === video.id);
|
|
27052
|
+
if (!exists) {
|
|
27053
|
+
return [...prev, video];
|
|
27054
|
+
}
|
|
27055
|
+
return prev;
|
|
27056
|
+
});
|
|
27057
|
+
const originalIndex = indicesToLoad[idx];
|
|
27058
|
+
loadedIndices.add(originalIndex);
|
|
27059
|
+
preloadVideoUrl(video.src);
|
|
27060
|
+
}
|
|
27061
|
+
});
|
|
27062
|
+
console.log(`[ensureVideosLoaded] Successfully loaded ${videos.length} videos in batch`);
|
|
27063
|
+
}
|
|
27064
|
+
} catch (error2) {
|
|
27065
|
+
console.error("[ensureVideosLoaded] Batch fetch failed:", error2);
|
|
27066
|
+
const loadPromises = indicesToLoad.map(async (index) => {
|
|
27067
|
+
try {
|
|
27068
|
+
const video = await s3ClipsService.getClipByIndex(
|
|
27004
27069
|
workspaceId,
|
|
27005
27070
|
operationalDate,
|
|
27006
27071
|
shiftStr,
|
|
27007
27072
|
effectiveFilter,
|
|
27008
27073
|
index,
|
|
27009
27074
|
true,
|
|
27010
|
-
// includeCycleTime
|
|
27075
|
+
// includeCycleTime
|
|
27011
27076
|
false
|
|
27012
|
-
// includeMetadata
|
|
27077
|
+
// includeMetadata
|
|
27013
27078
|
);
|
|
27079
|
+
if (video && isMountedRef.current) {
|
|
27080
|
+
setAllVideos((prev) => {
|
|
27081
|
+
const exists = prev.some((v) => v.id === video.id);
|
|
27082
|
+
if (!exists) {
|
|
27083
|
+
return [...prev, video];
|
|
27084
|
+
}
|
|
27085
|
+
return prev;
|
|
27086
|
+
});
|
|
27087
|
+
loadedIndices.add(index);
|
|
27088
|
+
preloadVideoUrl(video.src);
|
|
27089
|
+
}
|
|
27090
|
+
} catch (err) {
|
|
27091
|
+
console.warn(`[ensureVideosLoaded] Failed to load video at index ${index}:`, err);
|
|
27014
27092
|
}
|
|
27015
|
-
|
|
27016
|
-
|
|
27017
|
-
|
|
27018
|
-
|
|
27019
|
-
|
|
27020
|
-
}
|
|
27021
|
-
return prev;
|
|
27022
|
-
});
|
|
27023
|
-
loadedIndices.add(index);
|
|
27024
|
-
preloadVideoUrl(video.src);
|
|
27025
|
-
}
|
|
27026
|
-
} catch (error2) {
|
|
27027
|
-
console.warn(`[ensureVideosLoaded] Failed to load video at index ${index}:`, error2);
|
|
27028
|
-
} finally {
|
|
27029
|
-
loadingVideosRef.current.delete(index);
|
|
27030
|
-
}
|
|
27031
|
-
});
|
|
27032
|
-
Promise.all(loadPromises).catch((err) => {
|
|
27033
|
-
console.warn("[ensureVideosLoaded] Some videos failed to preload:", err);
|
|
27034
|
-
});
|
|
27093
|
+
});
|
|
27094
|
+
await Promise.all(loadPromises);
|
|
27095
|
+
} finally {
|
|
27096
|
+
indicesToLoad.forEach((idx) => loadingVideosRef.current.delete(idx));
|
|
27097
|
+
}
|
|
27035
27098
|
}, [s3ClipsService, workspaceId, clipCounts, sopCategories, date, effectiveShift]);
|
|
27036
27099
|
const loadFirstVideoForCategory = useCallback(async (category) => {
|
|
27037
27100
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|