@optifye/dashboard-core 6.0.1 → 6.0.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 +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +65 -42
- package/dist/index.mjs +65 -42
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -201,7 +201,10 @@ interface ShiftConfig {
|
|
|
201
201
|
transitionPeriodMinutes?: number;
|
|
202
202
|
}
|
|
203
203
|
interface WorkspaceConfig {
|
|
204
|
+
/** @deprecated Use lineDisplayNames for multi-line support */
|
|
204
205
|
displayNames?: Record<string, string>;
|
|
206
|
+
/** Line-aware display names: lineId -> workspaceId -> displayName */
|
|
207
|
+
lineDisplayNames?: Record<string, Record<string, string>>;
|
|
205
208
|
specialWorkspaces?: {
|
|
206
209
|
startId?: number;
|
|
207
210
|
endId?: number;
|
|
@@ -254,6 +257,17 @@ interface S3Config {
|
|
|
254
257
|
/** Workspace-specific category overrides by UUID */
|
|
255
258
|
workspaceOverrides?: Record<string, SOPCategory[]>;
|
|
256
259
|
};
|
|
260
|
+
/** Processing configuration for S3 clips */
|
|
261
|
+
processing?: {
|
|
262
|
+
/** Default limit per category when fetching clips (default: 30) */
|
|
263
|
+
defaultLimitPerCategory?: number;
|
|
264
|
+
/** Maximum allowed limit per category (default: 1000) */
|
|
265
|
+
maxLimitPerCategory?: number;
|
|
266
|
+
/** Number of concurrent video processing operations (default: 10) */
|
|
267
|
+
concurrencyLimit?: number;
|
|
268
|
+
/** Maximum initial fetch limit for S3 listing (default: 60) */
|
|
269
|
+
maxInitialFetch?: number;
|
|
270
|
+
};
|
|
257
271
|
}
|
|
258
272
|
interface VideoCroppingRect {
|
|
259
273
|
/** X offset as percentage (0-100) from left */
|
|
@@ -275,7 +289,10 @@ interface VideoConfig {
|
|
|
275
289
|
/** HLS stream URLs for workspaces */
|
|
276
290
|
hlsUrls?: {
|
|
277
291
|
defaultHlsUrl?: string;
|
|
292
|
+
/** @deprecated Use lineWorkspaceHlsUrls for multi-line support */
|
|
278
293
|
workspaceHlsUrls?: Record<string, string>;
|
|
294
|
+
/** Line-aware workspace HLS URLs: lineId -> workspaceName -> URL */
|
|
295
|
+
lineWorkspaceHlsUrls?: Record<string, Record<string, string>>;
|
|
279
296
|
};
|
|
280
297
|
/** Video cropping configuration */
|
|
281
298
|
cropping?: VideoCroppingConfig;
|
|
@@ -830,6 +847,10 @@ interface LeaderboardDetailViewProps {
|
|
|
830
847
|
* Second line ID reference (Line 2)
|
|
831
848
|
*/
|
|
832
849
|
line2Id?: string;
|
|
850
|
+
/**
|
|
851
|
+
* Mapping of line IDs to their display names
|
|
852
|
+
*/
|
|
853
|
+
lineNames?: Record<string, string>;
|
|
833
854
|
/**
|
|
834
855
|
* Optional className for custom styling
|
|
835
856
|
*/
|
|
@@ -2603,18 +2624,20 @@ locale?: string) => string;
|
|
|
2603
2624
|
*
|
|
2604
2625
|
* @param workspaceId - The workspace ID (e.g., 'WS01').
|
|
2605
2626
|
* @param workspaceConfig - The WorkspaceConfig object from the dashboard configuration.
|
|
2627
|
+
* @param lineId - Optional line ID for line-aware display names.
|
|
2606
2628
|
* @returns The display name from the config, or a fallback based on the ID.
|
|
2607
2629
|
*/
|
|
2608
|
-
declare const getConfigurableWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig) => string;
|
|
2630
|
+
declare const getConfigurableWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig, lineId?: string) => string;
|
|
2609
2631
|
/**
|
|
2610
2632
|
* Gets a potentially shortened or specific part of the workspace display name.
|
|
2611
2633
|
* (The logic here might need adjustment based on actual naming conventions used).
|
|
2612
2634
|
*
|
|
2613
2635
|
* @param workspaceId - The workspace ID (e.g., 'WS01').
|
|
2614
2636
|
* @param workspaceConfig - The WorkspaceConfig object from the dashboard configuration.
|
|
2637
|
+
* @param lineId - Optional line ID for line-aware display names.
|
|
2615
2638
|
* @returns A potentially shortened name, or the full display name, or a fallback.
|
|
2616
2639
|
*/
|
|
2617
|
-
declare const getConfigurableShortWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig) => string;
|
|
2640
|
+
declare const getConfigurableShortWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig, lineId?: string) => string;
|
|
2618
2641
|
|
|
2619
2642
|
/**
|
|
2620
2643
|
* @internal
|
|
@@ -2642,6 +2665,7 @@ interface WorkspaceUrlMapping {
|
|
|
2642
2665
|
urlName: string;
|
|
2643
2666
|
workspaceId: string;
|
|
2644
2667
|
workspaceName: string;
|
|
2668
|
+
lineId?: string;
|
|
2645
2669
|
}
|
|
2646
2670
|
declare const toUrlFriendlyName: (workspaceName: string | undefined) => string;
|
|
2647
2671
|
declare const fromUrlFriendlyName: (urlName: string) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -201,7 +201,10 @@ interface ShiftConfig {
|
|
|
201
201
|
transitionPeriodMinutes?: number;
|
|
202
202
|
}
|
|
203
203
|
interface WorkspaceConfig {
|
|
204
|
+
/** @deprecated Use lineDisplayNames for multi-line support */
|
|
204
205
|
displayNames?: Record<string, string>;
|
|
206
|
+
/** Line-aware display names: lineId -> workspaceId -> displayName */
|
|
207
|
+
lineDisplayNames?: Record<string, Record<string, string>>;
|
|
205
208
|
specialWorkspaces?: {
|
|
206
209
|
startId?: number;
|
|
207
210
|
endId?: number;
|
|
@@ -254,6 +257,17 @@ interface S3Config {
|
|
|
254
257
|
/** Workspace-specific category overrides by UUID */
|
|
255
258
|
workspaceOverrides?: Record<string, SOPCategory[]>;
|
|
256
259
|
};
|
|
260
|
+
/** Processing configuration for S3 clips */
|
|
261
|
+
processing?: {
|
|
262
|
+
/** Default limit per category when fetching clips (default: 30) */
|
|
263
|
+
defaultLimitPerCategory?: number;
|
|
264
|
+
/** Maximum allowed limit per category (default: 1000) */
|
|
265
|
+
maxLimitPerCategory?: number;
|
|
266
|
+
/** Number of concurrent video processing operations (default: 10) */
|
|
267
|
+
concurrencyLimit?: number;
|
|
268
|
+
/** Maximum initial fetch limit for S3 listing (default: 60) */
|
|
269
|
+
maxInitialFetch?: number;
|
|
270
|
+
};
|
|
257
271
|
}
|
|
258
272
|
interface VideoCroppingRect {
|
|
259
273
|
/** X offset as percentage (0-100) from left */
|
|
@@ -275,7 +289,10 @@ interface VideoConfig {
|
|
|
275
289
|
/** HLS stream URLs for workspaces */
|
|
276
290
|
hlsUrls?: {
|
|
277
291
|
defaultHlsUrl?: string;
|
|
292
|
+
/** @deprecated Use lineWorkspaceHlsUrls for multi-line support */
|
|
278
293
|
workspaceHlsUrls?: Record<string, string>;
|
|
294
|
+
/** Line-aware workspace HLS URLs: lineId -> workspaceName -> URL */
|
|
295
|
+
lineWorkspaceHlsUrls?: Record<string, Record<string, string>>;
|
|
279
296
|
};
|
|
280
297
|
/** Video cropping configuration */
|
|
281
298
|
cropping?: VideoCroppingConfig;
|
|
@@ -830,6 +847,10 @@ interface LeaderboardDetailViewProps {
|
|
|
830
847
|
* Second line ID reference (Line 2)
|
|
831
848
|
*/
|
|
832
849
|
line2Id?: string;
|
|
850
|
+
/**
|
|
851
|
+
* Mapping of line IDs to their display names
|
|
852
|
+
*/
|
|
853
|
+
lineNames?: Record<string, string>;
|
|
833
854
|
/**
|
|
834
855
|
* Optional className for custom styling
|
|
835
856
|
*/
|
|
@@ -2603,18 +2624,20 @@ locale?: string) => string;
|
|
|
2603
2624
|
*
|
|
2604
2625
|
* @param workspaceId - The workspace ID (e.g., 'WS01').
|
|
2605
2626
|
* @param workspaceConfig - The WorkspaceConfig object from the dashboard configuration.
|
|
2627
|
+
* @param lineId - Optional line ID for line-aware display names.
|
|
2606
2628
|
* @returns The display name from the config, or a fallback based on the ID.
|
|
2607
2629
|
*/
|
|
2608
|
-
declare const getConfigurableWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig) => string;
|
|
2630
|
+
declare const getConfigurableWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig, lineId?: string) => string;
|
|
2609
2631
|
/**
|
|
2610
2632
|
* Gets a potentially shortened or specific part of the workspace display name.
|
|
2611
2633
|
* (The logic here might need adjustment based on actual naming conventions used).
|
|
2612
2634
|
*
|
|
2613
2635
|
* @param workspaceId - The workspace ID (e.g., 'WS01').
|
|
2614
2636
|
* @param workspaceConfig - The WorkspaceConfig object from the dashboard configuration.
|
|
2637
|
+
* @param lineId - Optional line ID for line-aware display names.
|
|
2615
2638
|
* @returns A potentially shortened name, or the full display name, or a fallback.
|
|
2616
2639
|
*/
|
|
2617
|
-
declare const getConfigurableShortWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig) => string;
|
|
2640
|
+
declare const getConfigurableShortWorkspaceDisplayName: (workspaceId: string, workspaceConfig?: WorkspaceConfig, lineId?: string) => string;
|
|
2618
2641
|
|
|
2619
2642
|
/**
|
|
2620
2643
|
* @internal
|
|
@@ -2642,6 +2665,7 @@ interface WorkspaceUrlMapping {
|
|
|
2642
2665
|
urlName: string;
|
|
2643
2666
|
workspaceId: string;
|
|
2644
2667
|
workspaceName: string;
|
|
2668
|
+
lineId?: string;
|
|
2645
2669
|
}
|
|
2646
2670
|
declare const toUrlFriendlyName: (workspaceName: string | undefined) => string;
|
|
2647
2671
|
declare const fromUrlFriendlyName: (urlName: string) => string;
|
package/dist/index.js
CHANGED
|
@@ -161,6 +161,9 @@ var DEFAULT_AUTH_CONFIG = {
|
|
|
161
161
|
// Defaults related to auth providers, redirects etc.
|
|
162
162
|
};
|
|
163
163
|
var DEFAULT_VIDEO_CONFIG = {
|
|
164
|
+
hlsUrls: {
|
|
165
|
+
lineWorkspaceHlsUrls: {}
|
|
166
|
+
},
|
|
164
167
|
canvasConfig: {
|
|
165
168
|
fps: 30,
|
|
166
169
|
useRAF: true
|
|
@@ -5125,19 +5128,23 @@ var useActiveBreaks = (lineIds) => {
|
|
|
5125
5128
|
const checkActiveBreaks = React14.useCallback(async () => {
|
|
5126
5129
|
try {
|
|
5127
5130
|
setError(null);
|
|
5128
|
-
|
|
5131
|
+
const validLineIds = lineIds.filter(
|
|
5132
|
+
(id3) => id3 && id3 !== "factory" && id3 !== "all" && // Basic UUID format check
|
|
5133
|
+
id3.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
|
|
5134
|
+
);
|
|
5135
|
+
if (!validLineIds || validLineIds.length === 0) {
|
|
5129
5136
|
setActiveBreaks([]);
|
|
5130
5137
|
setIsLoading(false);
|
|
5131
5138
|
return;
|
|
5132
5139
|
}
|
|
5133
5140
|
const currentMinutes = getCurrentTimeInMinutes();
|
|
5134
|
-
const { data: dayShifts, error: dayError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id",
|
|
5135
|
-
const { data: nightShifts, error: nightError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id",
|
|
5141
|
+
const { data: dayShifts, error: dayError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id", validLineIds);
|
|
5142
|
+
const { data: nightShifts, error: nightError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id", validLineIds);
|
|
5136
5143
|
if (dayError || nightError) {
|
|
5137
5144
|
throw new Error("Failed to fetch shift configurations");
|
|
5138
5145
|
}
|
|
5139
5146
|
const foundActiveBreaks = [];
|
|
5140
|
-
for (const lineId of
|
|
5147
|
+
for (const lineId of validLineIds) {
|
|
5141
5148
|
const dayShift = dayShifts?.find((s) => s.line_id === lineId);
|
|
5142
5149
|
const nightShift = nightShifts?.find((s) => s.line_id === lineId);
|
|
5143
5150
|
if (!dayShift || !nightShift) continue;
|
|
@@ -5621,12 +5628,18 @@ var FALLBACK_DISPLAY_NAMES = {
|
|
|
5621
5628
|
"WS03": "Filling station"
|
|
5622
5629
|
// ... Add others if known defaults are useful
|
|
5623
5630
|
};
|
|
5624
|
-
var getConfigurableWorkspaceDisplayName = (workspaceId, workspaceConfig) => {
|
|
5631
|
+
var getConfigurableWorkspaceDisplayName = (workspaceId, workspaceConfig, lineId) => {
|
|
5632
|
+
if (lineId && workspaceConfig?.lineDisplayNames?.[lineId]) {
|
|
5633
|
+
const lineDisplayNames = workspaceConfig.lineDisplayNames[lineId];
|
|
5634
|
+
if (lineDisplayNames[workspaceId]) {
|
|
5635
|
+
return lineDisplayNames[workspaceId];
|
|
5636
|
+
}
|
|
5637
|
+
}
|
|
5625
5638
|
const displayNames = workspaceConfig?.displayNames || FALLBACK_DISPLAY_NAMES;
|
|
5626
5639
|
return displayNames[workspaceId] || workspaceId.replace(/^WS/i, "") || workspaceId;
|
|
5627
5640
|
};
|
|
5628
|
-
var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig) => {
|
|
5629
|
-
const fullName = getConfigurableWorkspaceDisplayName(workspaceId, workspaceConfig);
|
|
5641
|
+
var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig, lineId) => {
|
|
5642
|
+
const fullName = getConfigurableWorkspaceDisplayName(workspaceId, workspaceConfig, lineId);
|
|
5630
5643
|
const match = fullName.match(/([A-Z]\d+(?:-\w+)?)/i);
|
|
5631
5644
|
if (match && match[0]) {
|
|
5632
5645
|
return match[0];
|
|
@@ -17631,18 +17644,6 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17631
17644
|
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay && prevProps.cropping?.x === nextProps.cropping?.x && prevProps.cropping?.y === nextProps.cropping?.y && prevProps.cropping?.width === nextProps.cropping?.width && prevProps.cropping?.height === nextProps.cropping?.height;
|
|
17632
17645
|
});
|
|
17633
17646
|
VideoCard.displayName = "VideoCard";
|
|
17634
|
-
var DEFAULT_WORKSPACE_HLS_URLS = {
|
|
17635
|
-
"WS1": "https://dnh-hls.optifye.ai/cam1/index.m3u8",
|
|
17636
|
-
"WS2": "https://dnh-hls.optifye.ai/cam2/index.m3u8",
|
|
17637
|
-
"WS3": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
17638
|
-
"WS4": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
17639
|
-
"WS01": "https://59.144.218.58:8443/camera6.m3u8",
|
|
17640
|
-
"WS02": "https://59.144.218.58:8443/camera2.m3u8",
|
|
17641
|
-
"WS03": "https://59.144.218.58:8443/camera3.m3u8",
|
|
17642
|
-
"WS04": "https://59.144.218.58:8443/camera4.m3u8",
|
|
17643
|
-
"WS05": "https://59.144.218.58:8443/camera1.m3u8",
|
|
17644
|
-
"WS06": "https://59.144.218.58:8443/camera5.m3u8"
|
|
17645
|
-
};
|
|
17646
17647
|
var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
|
|
17647
17648
|
var VideoGridView = React14__namespace.default.memo(({
|
|
17648
17649
|
workspaces,
|
|
@@ -17656,13 +17657,20 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17656
17657
|
const [gridCols, setGridCols] = React14.useState(4);
|
|
17657
17658
|
const [visibleWorkspaces, setVisibleWorkspaces] = React14.useState(/* @__PURE__ */ new Set());
|
|
17658
17659
|
const videoConfig = useVideoConfig();
|
|
17659
|
-
const { cropping, canvasConfig } = videoConfig;
|
|
17660
|
+
const { cropping, canvasConfig, hlsUrls } = videoConfig;
|
|
17660
17661
|
const mergedVideoSources = {
|
|
17661
|
-
defaultHlsUrl: videoSources.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17662
|
-
workspaceHlsUrls: { ...
|
|
17662
|
+
defaultHlsUrl: videoSources.defaultHlsUrl || hlsUrls?.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17663
|
+
workspaceHlsUrls: { ...videoSources.workspaceHlsUrls, ...hlsUrls?.workspaceHlsUrls },
|
|
17664
|
+
lineWorkspaceHlsUrls: hlsUrls?.lineWorkspaceHlsUrls || {}
|
|
17663
17665
|
};
|
|
17664
|
-
const getWorkspaceHlsUrl = React14.useCallback((workspaceName) => {
|
|
17666
|
+
const getWorkspaceHlsUrl = React14.useCallback((workspaceName, lineId) => {
|
|
17665
17667
|
const wsName = workspaceName.toUpperCase();
|
|
17668
|
+
if (lineId && mergedVideoSources.lineWorkspaceHlsUrls[lineId]) {
|
|
17669
|
+
const lineUrls = mergedVideoSources.lineWorkspaceHlsUrls[lineId];
|
|
17670
|
+
if (lineUrls[wsName]) {
|
|
17671
|
+
return lineUrls[wsName];
|
|
17672
|
+
}
|
|
17673
|
+
}
|
|
17666
17674
|
return mergedVideoSources.workspaceHlsUrls[wsName] || mergedVideoSources.defaultHlsUrl;
|
|
17667
17675
|
}, [mergedVideoSources]);
|
|
17668
17676
|
const getWorkspaceCropping = React14.useCallback((workspaceName) => {
|
|
@@ -17822,7 +17830,7 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17822
17830
|
VideoCard,
|
|
17823
17831
|
{
|
|
17824
17832
|
workspace,
|
|
17825
|
-
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name),
|
|
17833
|
+
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name, workspace.line_id),
|
|
17826
17834
|
shouldPlay: isVisible,
|
|
17827
17835
|
onClick: () => handleWorkspaceClick(workspace),
|
|
17828
17836
|
onFatalError: throttledReloadDashboard,
|
|
@@ -21546,6 +21554,11 @@ var S3ClipsService = class {
|
|
|
21546
21554
|
if (!config.s3Config) {
|
|
21547
21555
|
throw new Error("S3 configuration is required");
|
|
21548
21556
|
}
|
|
21557
|
+
const processing = config.s3Config.processing || {};
|
|
21558
|
+
this.defaultLimitPerCategory = processing.defaultLimitPerCategory || 30;
|
|
21559
|
+
this.maxLimitPerCategory = processing.maxLimitPerCategory || 1e3;
|
|
21560
|
+
this.concurrencyLimit = processing.concurrencyLimit || 10;
|
|
21561
|
+
this.maxInitialFetch = processing.maxInitialFetch || 60;
|
|
21549
21562
|
const region = this.validateAndSanitizeRegion(config.s3Config.region);
|
|
21550
21563
|
console.log(`S3ClipsService: Using AWS region: ${region}`);
|
|
21551
21564
|
this.s3Client = new clientS3.S3Client({
|
|
@@ -21830,9 +21843,9 @@ var S3ClipsService = class {
|
|
|
21830
21843
|
}
|
|
21831
21844
|
return summary;
|
|
21832
21845
|
}
|
|
21833
|
-
const limitPerCategory = limit ? Math.min(Math.max(limit, 1),
|
|
21846
|
+
const limitPerCategory = limit ? Math.min(Math.max(limit, 1), this.maxLimitPerCategory) : this.defaultLimitPerCategory;
|
|
21834
21847
|
const shouldFetchAll = category === "missing_quality_check" || category === "low_value";
|
|
21835
|
-
const initialFetchLimit = shouldFetchAll ? void 0 : category ? limitPerCategory * 3 : void 0;
|
|
21848
|
+
const initialFetchLimit = shouldFetchAll ? void 0 : category ? Math.min(limitPerCategory * 3, this.maxInitialFetch) : void 0;
|
|
21836
21849
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId, maxKeys: initialFetchLimit });
|
|
21837
21850
|
if (s3Uris.length === 0) {
|
|
21838
21851
|
console.log(`S3ClipsService: No HLS playlists found for workspace ${workspaceId} on date ${date}, shift ${shiftId}`);
|
|
@@ -21900,12 +21913,11 @@ var S3ClipsService = class {
|
|
|
21900
21913
|
}
|
|
21901
21914
|
console.log(`S3ClipsService: Total filtered URIs across all categories: ${filteredUris.length}`);
|
|
21902
21915
|
}
|
|
21903
|
-
const concurrencyLimit = 10;
|
|
21904
21916
|
let processedCount = 0;
|
|
21905
21917
|
const videoResults = [];
|
|
21906
21918
|
console.log(`S3ClipsService: Processing ${filteredUris.length} URIs for ${category || "all categories"} with limit ${limitPerCategory} per category`);
|
|
21907
|
-
for (let i = 0; i < filteredUris.length; i += concurrencyLimit) {
|
|
21908
|
-
const batch = filteredUris.slice(i, i + concurrencyLimit);
|
|
21919
|
+
for (let i = 0; i < filteredUris.length; i += this.concurrencyLimit) {
|
|
21920
|
+
const batch = filteredUris.slice(i, i + this.concurrencyLimit);
|
|
21909
21921
|
const batchPromises = batch.map(async (uri, batchIndex) => {
|
|
21910
21922
|
const index = i + batchIndex;
|
|
21911
21923
|
const result = await this.processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime || false, includeMetadata || (!!timestampStart || !!timestampEnd));
|
|
@@ -22468,7 +22480,7 @@ var BottlenecksContent = ({
|
|
|
22468
22480
|
return "Cycle Completion";
|
|
22469
22481
|
case "bottleneck":
|
|
22470
22482
|
default:
|
|
22471
|
-
return "
|
|
22483
|
+
return "";
|
|
22472
22484
|
}
|
|
22473
22485
|
};
|
|
22474
22486
|
const getColorClasses = (color2) => {
|
|
@@ -27386,11 +27398,17 @@ function HomeView({
|
|
|
27386
27398
|
lineId: selectedLineId,
|
|
27387
27399
|
onLineMetricsUpdate
|
|
27388
27400
|
});
|
|
27401
|
+
const lineIdsForBreaks = React14.useMemo(() => {
|
|
27402
|
+
if (selectedLineId === factoryViewId) {
|
|
27403
|
+
return allLineIds;
|
|
27404
|
+
}
|
|
27405
|
+
return [selectedLineId];
|
|
27406
|
+
}, [selectedLineId, factoryViewId, allLineIds]);
|
|
27389
27407
|
const {
|
|
27390
27408
|
activeBreaks,
|
|
27391
27409
|
isLoading: breaksLoading,
|
|
27392
27410
|
error: breaksError
|
|
27393
|
-
} = useActiveBreaks(
|
|
27411
|
+
} = useActiveBreaks(lineIdsForBreaks);
|
|
27394
27412
|
const memoizedWorkspaceMetrics = React14.useMemo(() => workspaceMetrics, [
|
|
27395
27413
|
// Only update reference if meaningful properties change
|
|
27396
27414
|
workspaceMetrics.length,
|
|
@@ -28657,8 +28675,7 @@ var MobileWorkspaceCard = React14.memo(({
|
|
|
28657
28675
|
cardClass,
|
|
28658
28676
|
onWorkspaceClick,
|
|
28659
28677
|
getMedalIcon,
|
|
28660
|
-
|
|
28661
|
-
line2Id
|
|
28678
|
+
getLineName
|
|
28662
28679
|
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28663
28680
|
"div",
|
|
28664
28681
|
{
|
|
@@ -28676,7 +28693,7 @@ var MobileWorkspaceCard = React14.memo(({
|
|
|
28676
28693
|
] }),
|
|
28677
28694
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
28678
28695
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-gray-900", children: getWorkspaceDisplayName(workspace.workspace_name) }),
|
|
28679
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: workspace.line_id
|
|
28696
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: getLineName(workspace.line_id) })
|
|
28680
28697
|
] })
|
|
28681
28698
|
] }),
|
|
28682
28699
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
@@ -28714,8 +28731,7 @@ var DesktopWorkspaceRow = React14.memo(({
|
|
|
28714
28731
|
rowClass,
|
|
28715
28732
|
onWorkspaceClick,
|
|
28716
28733
|
getMedalIcon,
|
|
28717
|
-
|
|
28718
|
-
line2Id
|
|
28734
|
+
getLineName
|
|
28719
28735
|
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28720
28736
|
"tr",
|
|
28721
28737
|
{
|
|
@@ -28727,7 +28743,7 @@ var DesktopWorkspaceRow = React14.memo(({
|
|
|
28727
28743
|
getMedalIcon(index + 1)
|
|
28728
28744
|
] }) }),
|
|
28729
28745
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: getWorkspaceDisplayName(workspace.workspace_name) }) }),
|
|
28730
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.line_id
|
|
28746
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: getLineName(workspace.line_id) }) }),
|
|
28731
28747
|
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium whitespace-nowrap", children: [
|
|
28732
28748
|
(workspace.efficiency || 0).toFixed(1),
|
|
28733
28749
|
"%"
|
|
@@ -28755,10 +28771,19 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28755
28771
|
onWorkspaceClick,
|
|
28756
28772
|
line1Id = "",
|
|
28757
28773
|
line2Id = "",
|
|
28774
|
+
lineNames = {},
|
|
28758
28775
|
className = ""
|
|
28759
28776
|
}) => {
|
|
28760
28777
|
const navigation = useNavigation();
|
|
28761
28778
|
const [sortAscending, setSortAscending] = React14.useState(false);
|
|
28779
|
+
const getLineName = React14.useCallback((lineId2) => {
|
|
28780
|
+
if (lineNames[lineId2]) {
|
|
28781
|
+
return lineNames[lineId2];
|
|
28782
|
+
}
|
|
28783
|
+
if (lineId2 === line1Id) return "Line 1";
|
|
28784
|
+
if (lineId2 === line2Id) return "Line 2";
|
|
28785
|
+
return lineId2;
|
|
28786
|
+
}, [lineNames, line1Id, line2Id]);
|
|
28762
28787
|
const handleSortToggle = React14.useCallback(() => {
|
|
28763
28788
|
setSortAscending(!sortAscending);
|
|
28764
28789
|
}, [sortAscending]);
|
|
@@ -28932,8 +28957,7 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28932
28957
|
cardClass,
|
|
28933
28958
|
onWorkspaceClick: handleWorkspaceClick,
|
|
28934
28959
|
getMedalIcon,
|
|
28935
|
-
|
|
28936
|
-
line2Id
|
|
28960
|
+
getLineName
|
|
28937
28961
|
},
|
|
28938
28962
|
ws.workspace_uuid
|
|
28939
28963
|
);
|
|
@@ -28958,8 +28982,7 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28958
28982
|
rowClass,
|
|
28959
28983
|
onWorkspaceClick: handleWorkspaceClick,
|
|
28960
28984
|
getMedalIcon,
|
|
28961
|
-
|
|
28962
|
-
line2Id
|
|
28985
|
+
getLineName
|
|
28963
28986
|
},
|
|
28964
28987
|
ws.workspace_uuid
|
|
28965
28988
|
);
|
|
@@ -28968,7 +28991,7 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28968
28991
|
] })
|
|
28969
28992
|
] });
|
|
28970
28993
|
}, (prevProps, nextProps) => {
|
|
28971
|
-
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
|
|
28994
|
+
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
|
|
28972
28995
|
});
|
|
28973
28996
|
LeaderboardDetailView.displayName = "LeaderboardDetailView";
|
|
28974
28997
|
var LeaderboardDetailView_default = LeaderboardDetailView;
|
package/dist/index.mjs
CHANGED
|
@@ -132,6 +132,9 @@ var DEFAULT_AUTH_CONFIG = {
|
|
|
132
132
|
// Defaults related to auth providers, redirects etc.
|
|
133
133
|
};
|
|
134
134
|
var DEFAULT_VIDEO_CONFIG = {
|
|
135
|
+
hlsUrls: {
|
|
136
|
+
lineWorkspaceHlsUrls: {}
|
|
137
|
+
},
|
|
135
138
|
canvasConfig: {
|
|
136
139
|
fps: 30,
|
|
137
140
|
useRAF: true
|
|
@@ -5096,19 +5099,23 @@ var useActiveBreaks = (lineIds) => {
|
|
|
5096
5099
|
const checkActiveBreaks = useCallback(async () => {
|
|
5097
5100
|
try {
|
|
5098
5101
|
setError(null);
|
|
5099
|
-
|
|
5102
|
+
const validLineIds = lineIds.filter(
|
|
5103
|
+
(id3) => id3 && id3 !== "factory" && id3 !== "all" && // Basic UUID format check
|
|
5104
|
+
id3.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
|
|
5105
|
+
);
|
|
5106
|
+
if (!validLineIds || validLineIds.length === 0) {
|
|
5100
5107
|
setActiveBreaks([]);
|
|
5101
5108
|
setIsLoading(false);
|
|
5102
5109
|
return;
|
|
5103
5110
|
}
|
|
5104
5111
|
const currentMinutes = getCurrentTimeInMinutes();
|
|
5105
|
-
const { data: dayShifts, error: dayError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id",
|
|
5106
|
-
const { data: nightShifts, error: nightError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id",
|
|
5112
|
+
const { data: dayShifts, error: dayError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id", validLineIds);
|
|
5113
|
+
const { data: nightShifts, error: nightError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id", validLineIds);
|
|
5107
5114
|
if (dayError || nightError) {
|
|
5108
5115
|
throw new Error("Failed to fetch shift configurations");
|
|
5109
5116
|
}
|
|
5110
5117
|
const foundActiveBreaks = [];
|
|
5111
|
-
for (const lineId of
|
|
5118
|
+
for (const lineId of validLineIds) {
|
|
5112
5119
|
const dayShift = dayShifts?.find((s) => s.line_id === lineId);
|
|
5113
5120
|
const nightShift = nightShifts?.find((s) => s.line_id === lineId);
|
|
5114
5121
|
if (!dayShift || !nightShift) continue;
|
|
@@ -5592,12 +5599,18 @@ var FALLBACK_DISPLAY_NAMES = {
|
|
|
5592
5599
|
"WS03": "Filling station"
|
|
5593
5600
|
// ... Add others if known defaults are useful
|
|
5594
5601
|
};
|
|
5595
|
-
var getConfigurableWorkspaceDisplayName = (workspaceId, workspaceConfig) => {
|
|
5602
|
+
var getConfigurableWorkspaceDisplayName = (workspaceId, workspaceConfig, lineId) => {
|
|
5603
|
+
if (lineId && workspaceConfig?.lineDisplayNames?.[lineId]) {
|
|
5604
|
+
const lineDisplayNames = workspaceConfig.lineDisplayNames[lineId];
|
|
5605
|
+
if (lineDisplayNames[workspaceId]) {
|
|
5606
|
+
return lineDisplayNames[workspaceId];
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
5596
5609
|
const displayNames = workspaceConfig?.displayNames || FALLBACK_DISPLAY_NAMES;
|
|
5597
5610
|
return displayNames[workspaceId] || workspaceId.replace(/^WS/i, "") || workspaceId;
|
|
5598
5611
|
};
|
|
5599
|
-
var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig) => {
|
|
5600
|
-
const fullName = getConfigurableWorkspaceDisplayName(workspaceId, workspaceConfig);
|
|
5612
|
+
var getConfigurableShortWorkspaceDisplayName = (workspaceId, workspaceConfig, lineId) => {
|
|
5613
|
+
const fullName = getConfigurableWorkspaceDisplayName(workspaceId, workspaceConfig, lineId);
|
|
5601
5614
|
const match = fullName.match(/([A-Z]\d+(?:-\w+)?)/i);
|
|
5602
5615
|
if (match && match[0]) {
|
|
5603
5616
|
return match[0];
|
|
@@ -17602,18 +17615,6 @@ var VideoCard = React14__default.memo(({
|
|
|
17602
17615
|
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay && prevProps.cropping?.x === nextProps.cropping?.x && prevProps.cropping?.y === nextProps.cropping?.y && prevProps.cropping?.width === nextProps.cropping?.width && prevProps.cropping?.height === nextProps.cropping?.height;
|
|
17603
17616
|
});
|
|
17604
17617
|
VideoCard.displayName = "VideoCard";
|
|
17605
|
-
var DEFAULT_WORKSPACE_HLS_URLS = {
|
|
17606
|
-
"WS1": "https://dnh-hls.optifye.ai/cam1/index.m3u8",
|
|
17607
|
-
"WS2": "https://dnh-hls.optifye.ai/cam2/index.m3u8",
|
|
17608
|
-
"WS3": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
17609
|
-
"WS4": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
17610
|
-
"WS01": "https://59.144.218.58:8443/camera6.m3u8",
|
|
17611
|
-
"WS02": "https://59.144.218.58:8443/camera2.m3u8",
|
|
17612
|
-
"WS03": "https://59.144.218.58:8443/camera3.m3u8",
|
|
17613
|
-
"WS04": "https://59.144.218.58:8443/camera4.m3u8",
|
|
17614
|
-
"WS05": "https://59.144.218.58:8443/camera1.m3u8",
|
|
17615
|
-
"WS06": "https://59.144.218.58:8443/camera5.m3u8"
|
|
17616
|
-
};
|
|
17617
17618
|
var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
|
|
17618
17619
|
var VideoGridView = React14__default.memo(({
|
|
17619
17620
|
workspaces,
|
|
@@ -17627,13 +17628,20 @@ var VideoGridView = React14__default.memo(({
|
|
|
17627
17628
|
const [gridCols, setGridCols] = useState(4);
|
|
17628
17629
|
const [visibleWorkspaces, setVisibleWorkspaces] = useState(/* @__PURE__ */ new Set());
|
|
17629
17630
|
const videoConfig = useVideoConfig();
|
|
17630
|
-
const { cropping, canvasConfig } = videoConfig;
|
|
17631
|
+
const { cropping, canvasConfig, hlsUrls } = videoConfig;
|
|
17631
17632
|
const mergedVideoSources = {
|
|
17632
|
-
defaultHlsUrl: videoSources.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17633
|
-
workspaceHlsUrls: { ...
|
|
17633
|
+
defaultHlsUrl: videoSources.defaultHlsUrl || hlsUrls?.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17634
|
+
workspaceHlsUrls: { ...videoSources.workspaceHlsUrls, ...hlsUrls?.workspaceHlsUrls },
|
|
17635
|
+
lineWorkspaceHlsUrls: hlsUrls?.lineWorkspaceHlsUrls || {}
|
|
17634
17636
|
};
|
|
17635
|
-
const getWorkspaceHlsUrl = useCallback((workspaceName) => {
|
|
17637
|
+
const getWorkspaceHlsUrl = useCallback((workspaceName, lineId) => {
|
|
17636
17638
|
const wsName = workspaceName.toUpperCase();
|
|
17639
|
+
if (lineId && mergedVideoSources.lineWorkspaceHlsUrls[lineId]) {
|
|
17640
|
+
const lineUrls = mergedVideoSources.lineWorkspaceHlsUrls[lineId];
|
|
17641
|
+
if (lineUrls[wsName]) {
|
|
17642
|
+
return lineUrls[wsName];
|
|
17643
|
+
}
|
|
17644
|
+
}
|
|
17637
17645
|
return mergedVideoSources.workspaceHlsUrls[wsName] || mergedVideoSources.defaultHlsUrl;
|
|
17638
17646
|
}, [mergedVideoSources]);
|
|
17639
17647
|
const getWorkspaceCropping = useCallback((workspaceName) => {
|
|
@@ -17793,7 +17801,7 @@ var VideoGridView = React14__default.memo(({
|
|
|
17793
17801
|
VideoCard,
|
|
17794
17802
|
{
|
|
17795
17803
|
workspace,
|
|
17796
|
-
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name),
|
|
17804
|
+
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name, workspace.line_id),
|
|
17797
17805
|
shouldPlay: isVisible,
|
|
17798
17806
|
onClick: () => handleWorkspaceClick(workspace),
|
|
17799
17807
|
onFatalError: throttledReloadDashboard,
|
|
@@ -21517,6 +21525,11 @@ var S3ClipsService = class {
|
|
|
21517
21525
|
if (!config.s3Config) {
|
|
21518
21526
|
throw new Error("S3 configuration is required");
|
|
21519
21527
|
}
|
|
21528
|
+
const processing = config.s3Config.processing || {};
|
|
21529
|
+
this.defaultLimitPerCategory = processing.defaultLimitPerCategory || 30;
|
|
21530
|
+
this.maxLimitPerCategory = processing.maxLimitPerCategory || 1e3;
|
|
21531
|
+
this.concurrencyLimit = processing.concurrencyLimit || 10;
|
|
21532
|
+
this.maxInitialFetch = processing.maxInitialFetch || 60;
|
|
21520
21533
|
const region = this.validateAndSanitizeRegion(config.s3Config.region);
|
|
21521
21534
|
console.log(`S3ClipsService: Using AWS region: ${region}`);
|
|
21522
21535
|
this.s3Client = new S3Client({
|
|
@@ -21801,9 +21814,9 @@ var S3ClipsService = class {
|
|
|
21801
21814
|
}
|
|
21802
21815
|
return summary;
|
|
21803
21816
|
}
|
|
21804
|
-
const limitPerCategory = limit ? Math.min(Math.max(limit, 1),
|
|
21817
|
+
const limitPerCategory = limit ? Math.min(Math.max(limit, 1), this.maxLimitPerCategory) : this.defaultLimitPerCategory;
|
|
21805
21818
|
const shouldFetchAll = category === "missing_quality_check" || category === "low_value";
|
|
21806
|
-
const initialFetchLimit = shouldFetchAll ? void 0 : category ? limitPerCategory * 3 : void 0;
|
|
21819
|
+
const initialFetchLimit = shouldFetchAll ? void 0 : category ? Math.min(limitPerCategory * 3, this.maxInitialFetch) : void 0;
|
|
21807
21820
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId, maxKeys: initialFetchLimit });
|
|
21808
21821
|
if (s3Uris.length === 0) {
|
|
21809
21822
|
console.log(`S3ClipsService: No HLS playlists found for workspace ${workspaceId} on date ${date}, shift ${shiftId}`);
|
|
@@ -21871,12 +21884,11 @@ var S3ClipsService = class {
|
|
|
21871
21884
|
}
|
|
21872
21885
|
console.log(`S3ClipsService: Total filtered URIs across all categories: ${filteredUris.length}`);
|
|
21873
21886
|
}
|
|
21874
|
-
const concurrencyLimit = 10;
|
|
21875
21887
|
let processedCount = 0;
|
|
21876
21888
|
const videoResults = [];
|
|
21877
21889
|
console.log(`S3ClipsService: Processing ${filteredUris.length} URIs for ${category || "all categories"} with limit ${limitPerCategory} per category`);
|
|
21878
|
-
for (let i = 0; i < filteredUris.length; i += concurrencyLimit) {
|
|
21879
|
-
const batch = filteredUris.slice(i, i + concurrencyLimit);
|
|
21890
|
+
for (let i = 0; i < filteredUris.length; i += this.concurrencyLimit) {
|
|
21891
|
+
const batch = filteredUris.slice(i, i + this.concurrencyLimit);
|
|
21880
21892
|
const batchPromises = batch.map(async (uri, batchIndex) => {
|
|
21881
21893
|
const index = i + batchIndex;
|
|
21882
21894
|
const result = await this.processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime || false, includeMetadata || (!!timestampStart || !!timestampEnd));
|
|
@@ -22439,7 +22451,7 @@ var BottlenecksContent = ({
|
|
|
22439
22451
|
return "Cycle Completion";
|
|
22440
22452
|
case "bottleneck":
|
|
22441
22453
|
default:
|
|
22442
|
-
return "
|
|
22454
|
+
return "";
|
|
22443
22455
|
}
|
|
22444
22456
|
};
|
|
22445
22457
|
const getColorClasses = (color2) => {
|
|
@@ -27357,11 +27369,17 @@ function HomeView({
|
|
|
27357
27369
|
lineId: selectedLineId,
|
|
27358
27370
|
onLineMetricsUpdate
|
|
27359
27371
|
});
|
|
27372
|
+
const lineIdsForBreaks = useMemo(() => {
|
|
27373
|
+
if (selectedLineId === factoryViewId) {
|
|
27374
|
+
return allLineIds;
|
|
27375
|
+
}
|
|
27376
|
+
return [selectedLineId];
|
|
27377
|
+
}, [selectedLineId, factoryViewId, allLineIds]);
|
|
27360
27378
|
const {
|
|
27361
27379
|
activeBreaks,
|
|
27362
27380
|
isLoading: breaksLoading,
|
|
27363
27381
|
error: breaksError
|
|
27364
|
-
} = useActiveBreaks(
|
|
27382
|
+
} = useActiveBreaks(lineIdsForBreaks);
|
|
27365
27383
|
const memoizedWorkspaceMetrics = useMemo(() => workspaceMetrics, [
|
|
27366
27384
|
// Only update reference if meaningful properties change
|
|
27367
27385
|
workspaceMetrics.length,
|
|
@@ -28628,8 +28646,7 @@ var MobileWorkspaceCard = memo(({
|
|
|
28628
28646
|
cardClass,
|
|
28629
28647
|
onWorkspaceClick,
|
|
28630
28648
|
getMedalIcon,
|
|
28631
|
-
|
|
28632
|
-
line2Id
|
|
28649
|
+
getLineName
|
|
28633
28650
|
}) => /* @__PURE__ */ jsxs(
|
|
28634
28651
|
"div",
|
|
28635
28652
|
{
|
|
@@ -28647,7 +28664,7 @@ var MobileWorkspaceCard = memo(({
|
|
|
28647
28664
|
] }),
|
|
28648
28665
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
28649
28666
|
/* @__PURE__ */ jsx("div", { className: "font-semibold text-gray-900", children: getWorkspaceDisplayName(workspace.workspace_name) }),
|
|
28650
|
-
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: workspace.line_id
|
|
28667
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: getLineName(workspace.line_id) })
|
|
28651
28668
|
] })
|
|
28652
28669
|
] }),
|
|
28653
28670
|
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
@@ -28685,8 +28702,7 @@ var DesktopWorkspaceRow = memo(({
|
|
|
28685
28702
|
rowClass,
|
|
28686
28703
|
onWorkspaceClick,
|
|
28687
28704
|
getMedalIcon,
|
|
28688
|
-
|
|
28689
|
-
line2Id
|
|
28705
|
+
getLineName
|
|
28690
28706
|
}) => /* @__PURE__ */ jsxs(
|
|
28691
28707
|
"tr",
|
|
28692
28708
|
{
|
|
@@ -28698,7 +28714,7 @@ var DesktopWorkspaceRow = memo(({
|
|
|
28698
28714
|
getMedalIcon(index + 1)
|
|
28699
28715
|
] }) }),
|
|
28700
28716
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: getWorkspaceDisplayName(workspace.workspace_name) }) }),
|
|
28701
|
-
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: workspace.line_id
|
|
28717
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: getLineName(workspace.line_id) }) }),
|
|
28702
28718
|
/* @__PURE__ */ jsxs("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium whitespace-nowrap", children: [
|
|
28703
28719
|
(workspace.efficiency || 0).toFixed(1),
|
|
28704
28720
|
"%"
|
|
@@ -28726,10 +28742,19 @@ var LeaderboardDetailView = memo(({
|
|
|
28726
28742
|
onWorkspaceClick,
|
|
28727
28743
|
line1Id = "",
|
|
28728
28744
|
line2Id = "",
|
|
28745
|
+
lineNames = {},
|
|
28729
28746
|
className = ""
|
|
28730
28747
|
}) => {
|
|
28731
28748
|
const navigation = useNavigation();
|
|
28732
28749
|
const [sortAscending, setSortAscending] = useState(false);
|
|
28750
|
+
const getLineName = useCallback((lineId2) => {
|
|
28751
|
+
if (lineNames[lineId2]) {
|
|
28752
|
+
return lineNames[lineId2];
|
|
28753
|
+
}
|
|
28754
|
+
if (lineId2 === line1Id) return "Line 1";
|
|
28755
|
+
if (lineId2 === line2Id) return "Line 2";
|
|
28756
|
+
return lineId2;
|
|
28757
|
+
}, [lineNames, line1Id, line2Id]);
|
|
28733
28758
|
const handleSortToggle = useCallback(() => {
|
|
28734
28759
|
setSortAscending(!sortAscending);
|
|
28735
28760
|
}, [sortAscending]);
|
|
@@ -28903,8 +28928,7 @@ var LeaderboardDetailView = memo(({
|
|
|
28903
28928
|
cardClass,
|
|
28904
28929
|
onWorkspaceClick: handleWorkspaceClick,
|
|
28905
28930
|
getMedalIcon,
|
|
28906
|
-
|
|
28907
|
-
line2Id
|
|
28931
|
+
getLineName
|
|
28908
28932
|
},
|
|
28909
28933
|
ws.workspace_uuid
|
|
28910
28934
|
);
|
|
@@ -28929,8 +28953,7 @@ var LeaderboardDetailView = memo(({
|
|
|
28929
28953
|
rowClass,
|
|
28930
28954
|
onWorkspaceClick: handleWorkspaceClick,
|
|
28931
28955
|
getMedalIcon,
|
|
28932
|
-
|
|
28933
|
-
line2Id
|
|
28956
|
+
getLineName
|
|
28934
28957
|
},
|
|
28935
28958
|
ws.workspace_uuid
|
|
28936
28959
|
);
|
|
@@ -28939,7 +28962,7 @@ var LeaderboardDetailView = memo(({
|
|
|
28939
28962
|
] })
|
|
28940
28963
|
] });
|
|
28941
28964
|
}, (prevProps, nextProps) => {
|
|
28942
|
-
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
|
|
28965
|
+
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
|
|
28943
28966
|
});
|
|
28944
28967
|
LeaderboardDetailView.displayName = "LeaderboardDetailView";
|
|
28945
28968
|
var LeaderboardDetailView_default = LeaderboardDetailView;
|