@optifye/dashboard-core 6.0.0 → 6.0.1
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 +28 -7
- package/dist/index.d.ts +28 -7
- package/dist/index.js +210 -233
- package/dist/index.mjs +210 -233
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1027,7 +1027,7 @@ var dashboardService = {
|
|
|
1027
1027
|
const formattedStartDate = formatDate(startDate);
|
|
1028
1028
|
const formattedEndDate = formatDate(endDate);
|
|
1029
1029
|
try {
|
|
1030
|
-
const { data, error } = await supabase.from(metricsTable).select("date, shift_id, efficiency, total_output, avg_cycle_time, ideal_output, avg_pph, pph_threshold, workspace_rank").eq("workspace_id", workspaceUuid).gte("date", formattedStartDate).lte("date", formattedEndDate).order("date", { ascending: true }).order("shift_id", { ascending: true });
|
|
1030
|
+
const { data, error } = await supabase.from(metricsTable).select("date, shift_id, efficiency, total_output, avg_cycle_time, ideal_output, avg_pph, pph_threshold, workspace_rank, idle_time").eq("workspace_id", workspaceUuid).gte("date", formattedStartDate).lte("date", formattedEndDate).order("date", { ascending: true }).order("shift_id", { ascending: true });
|
|
1031
1031
|
if (error) throw error;
|
|
1032
1032
|
if (!data) return [];
|
|
1033
1033
|
const transformedData = data.map((item) => ({
|
|
@@ -1040,7 +1040,8 @@ var dashboardService = {
|
|
|
1040
1040
|
ideal_output: item.ideal_output || 0,
|
|
1041
1041
|
avg_pph: item.avg_pph || 0,
|
|
1042
1042
|
pph_threshold: item.pph_threshold || 0,
|
|
1043
|
-
workspace_rank: item.workspace_rank || 0
|
|
1043
|
+
workspace_rank: item.workspace_rank || 0,
|
|
1044
|
+
idle_time: item.idle_time || 0
|
|
1044
1045
|
}));
|
|
1045
1046
|
return transformedData;
|
|
1046
1047
|
} catch (err) {
|
|
@@ -17520,7 +17521,6 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17520
17521
|
});
|
|
17521
17522
|
}
|
|
17522
17523
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
17523
|
-
workspace.workspace_uuid || workspace.workspace_name;
|
|
17524
17524
|
const getEfficiencyOverlayColor = (efficiency) => {
|
|
17525
17525
|
if (efficiency >= 80) {
|
|
17526
17526
|
return "bg-[#00D654]/25";
|
|
@@ -17648,7 +17648,6 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17648
17648
|
workspaces,
|
|
17649
17649
|
selectedLine,
|
|
17650
17650
|
className = "",
|
|
17651
|
-
lineIdMapping = {},
|
|
17652
17651
|
videoSources = {}
|
|
17653
17652
|
}) => {
|
|
17654
17653
|
const router$1 = router.useRouter();
|
|
@@ -17797,16 +17796,17 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17797
17796
|
minHeight: "100%"
|
|
17798
17797
|
},
|
|
17799
17798
|
children: filteredWorkspaces.sort((a, b) => {
|
|
17800
|
-
|
|
17801
|
-
|
|
17802
|
-
|
|
17803
|
-
|
|
17804
|
-
|
|
17805
|
-
|
|
17806
|
-
|
|
17807
|
-
|
|
17799
|
+
if (a.line_id !== b.line_id) {
|
|
17800
|
+
return (a.line_id || "").localeCompare(b.line_id || "");
|
|
17801
|
+
}
|
|
17802
|
+
const aMatch = a.workspace_name.match(/WS(\d+)/);
|
|
17803
|
+
const bMatch = b.workspace_name.match(/WS(\d+)/);
|
|
17804
|
+
if (aMatch && bMatch) {
|
|
17805
|
+
const aNum = parseInt(aMatch[1]);
|
|
17806
|
+
const bNum = parseInt(bMatch[1]);
|
|
17807
|
+
return aNum - bNum;
|
|
17808
17808
|
}
|
|
17809
|
-
return
|
|
17809
|
+
return a.workspace_name.localeCompare(b.workspace_name);
|
|
17810
17810
|
}).map((workspace) => {
|
|
17811
17811
|
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
17812
17812
|
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
@@ -21394,7 +21394,7 @@ function isValidShiftId(shiftId) {
|
|
|
21394
21394
|
}
|
|
21395
21395
|
|
|
21396
21396
|
// src/lib/api/s3-clips-parser.ts
|
|
21397
|
-
function parseS3Uri(s3Uri) {
|
|
21397
|
+
function parseS3Uri(s3Uri, sopCategories) {
|
|
21398
21398
|
const path = new URL(s3Uri).pathname;
|
|
21399
21399
|
const parts = path.split("/").filter((p) => p);
|
|
21400
21400
|
console.log("S3 URI:", s3Uri);
|
|
@@ -21434,6 +21434,27 @@ function parseS3Uri(s3Uri) {
|
|
|
21434
21434
|
let description = "Analysis Clip";
|
|
21435
21435
|
const normalizedViolationType = violationType.toLowerCase().trim();
|
|
21436
21436
|
console.log(`Parsing violation type: "${violationType}" (normalized: "${normalizedViolationType}") from path: ${s3Uri}`);
|
|
21437
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
21438
|
+
const matchedCategory = sopCategories.find((category) => {
|
|
21439
|
+
const categoryId = category.id.toLowerCase();
|
|
21440
|
+
const s3FolderName = (category.s3FolderName || category.id).toLowerCase();
|
|
21441
|
+
return categoryId === normalizedViolationType || s3FolderName === normalizedViolationType || // Also check for partial matches for flexibility
|
|
21442
|
+
normalizedViolationType.includes(categoryId) || normalizedViolationType.includes(s3FolderName);
|
|
21443
|
+
});
|
|
21444
|
+
if (matchedCategory) {
|
|
21445
|
+
type = matchedCategory.id;
|
|
21446
|
+
description = matchedCategory.description || matchedCategory.label;
|
|
21447
|
+
if (matchedCategory.color.includes("red")) {
|
|
21448
|
+
severity = "high";
|
|
21449
|
+
} else if (matchedCategory.color.includes("yellow") || matchedCategory.color.includes("orange")) {
|
|
21450
|
+
severity = "medium";
|
|
21451
|
+
} else {
|
|
21452
|
+
severity = "low";
|
|
21453
|
+
}
|
|
21454
|
+
console.log(`Matched SOP category: ${matchedCategory.id} for violation type: ${violationType}`);
|
|
21455
|
+
return { timestamp, severity, description, type, originalUri: s3Uri };
|
|
21456
|
+
}
|
|
21457
|
+
}
|
|
21437
21458
|
switch (normalizedViolationType) {
|
|
21438
21459
|
case "idle_time":
|
|
21439
21460
|
case "idle":
|
|
@@ -21673,11 +21694,23 @@ var S3ClipsService = class {
|
|
|
21673
21694
|
const key = url.pathname.startsWith("/") ? url.pathname.substring(1) : url.pathname;
|
|
21674
21695
|
return `${this.config.s3Config.cloudFrontDomain}/${key}`;
|
|
21675
21696
|
}
|
|
21697
|
+
/**
|
|
21698
|
+
* Gets SOP categories for a specific workspace
|
|
21699
|
+
*/
|
|
21700
|
+
getSOPCategories(workspaceId) {
|
|
21701
|
+
const sopConfig = this.config.s3Config?.sopCategories;
|
|
21702
|
+
if (!sopConfig) return void 0;
|
|
21703
|
+
if (sopConfig.workspaceOverrides && sopConfig.workspaceOverrides[workspaceId]) {
|
|
21704
|
+
return sopConfig.workspaceOverrides[workspaceId];
|
|
21705
|
+
}
|
|
21706
|
+
return sopConfig.default;
|
|
21707
|
+
}
|
|
21676
21708
|
/**
|
|
21677
21709
|
* Processes a single video completely
|
|
21678
21710
|
*/
|
|
21679
21711
|
async processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime, includeMetadata = false) {
|
|
21680
|
-
const
|
|
21712
|
+
const sopCategories = this.getSOPCategories(workspaceId);
|
|
21713
|
+
const parsedInfo = parseS3Uri(uri, sopCategories);
|
|
21681
21714
|
if (!parsedInfo) {
|
|
21682
21715
|
console.warn(`Skipping URI due to parsing failure: ${uri}`);
|
|
21683
21716
|
return null;
|
|
@@ -21710,27 +21743,32 @@ var S3ClipsService = class {
|
|
|
21710
21743
|
async getVideoSummary(workspaceId, date, shiftId) {
|
|
21711
21744
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId });
|
|
21712
21745
|
console.log(`S3ClipsService getVideoSummary: Processing ${s3Uris.length} total URIs for accurate category counts`);
|
|
21713
|
-
const
|
|
21714
|
-
|
|
21715
|
-
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
|
|
21730
|
-
|
|
21731
|
-
|
|
21746
|
+
const sopCategories = this.getSOPCategories(workspaceId);
|
|
21747
|
+
const counts = { total: 0 };
|
|
21748
|
+
const samples = {};
|
|
21749
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
21750
|
+
sopCategories.forEach((category) => {
|
|
21751
|
+
counts[category.id] = 0;
|
|
21752
|
+
samples[category.id] = null;
|
|
21753
|
+
});
|
|
21754
|
+
} else {
|
|
21755
|
+
counts.best_cycle_time = 0;
|
|
21756
|
+
counts.worst_cycle_time = 0;
|
|
21757
|
+
counts.bottleneck = 0;
|
|
21758
|
+
counts.low_value = 0;
|
|
21759
|
+
counts.long_cycle_time = 0;
|
|
21760
|
+
counts.missing_quality_check = 0;
|
|
21761
|
+
counts.cycle_completions = 0;
|
|
21762
|
+
samples.best_cycle_time = null;
|
|
21763
|
+
samples.worst_cycle_time = null;
|
|
21764
|
+
samples.bottleneck = null;
|
|
21765
|
+
samples.low_value = null;
|
|
21766
|
+
samples.long_cycle_time = null;
|
|
21767
|
+
samples.missing_quality_check = null;
|
|
21768
|
+
samples.cycle_completions = null;
|
|
21769
|
+
}
|
|
21732
21770
|
for (const uri of s3Uris) {
|
|
21733
|
-
const parsedInfo = parseS3Uri(uri);
|
|
21771
|
+
const parsedInfo = parseS3Uri(uri, sopCategories);
|
|
21734
21772
|
if (parsedInfo) {
|
|
21735
21773
|
const { type } = parsedInfo;
|
|
21736
21774
|
counts[type] = (counts[type] || 0) + 1;
|
|
@@ -21943,6 +21981,14 @@ var BottlenecksContent = ({
|
|
|
21943
21981
|
className
|
|
21944
21982
|
}) => {
|
|
21945
21983
|
const dashboardConfig = useDashboardConfig();
|
|
21984
|
+
const sopCategories = React14__namespace.default.useMemo(() => {
|
|
21985
|
+
const sopConfig = dashboardConfig?.s3Config?.sopCategories;
|
|
21986
|
+
if (!sopConfig) return null;
|
|
21987
|
+
if (sopConfig.workspaceOverrides && sopConfig.workspaceOverrides[workspaceId]) {
|
|
21988
|
+
return sopConfig.workspaceOverrides[workspaceId];
|
|
21989
|
+
}
|
|
21990
|
+
return sopConfig.default;
|
|
21991
|
+
}, [dashboardConfig, workspaceId]);
|
|
21946
21992
|
const videoRef = React14.useRef(null);
|
|
21947
21993
|
const fullscreenContainerRef = React14.useRef(null);
|
|
21948
21994
|
const timestampFilterRef = React14.useRef(null);
|
|
@@ -21951,7 +21997,9 @@ var BottlenecksContent = ({
|
|
|
21951
21997
|
const [duration, setDuration] = React14.useState(0);
|
|
21952
21998
|
const [isFullscreen, setIsFullscreen] = React14.useState(false);
|
|
21953
21999
|
const [currentIndex, setCurrentIndex] = React14.useState(0);
|
|
21954
|
-
const [activeFilter, setActiveFilter] = React14.useState(
|
|
22000
|
+
const [activeFilter, setActiveFilter] = React14.useState(
|
|
22001
|
+
sopCategories && sopCategories.length > 0 ? sopCategories[0].id : "low_value"
|
|
22002
|
+
);
|
|
21955
22003
|
const [allVideos, setAllVideos] = React14.useState([]);
|
|
21956
22004
|
const [isLoading, setIsLoading] = React14.useState(true);
|
|
21957
22005
|
const [error, setError] = React14.useState(null);
|
|
@@ -22063,27 +22111,41 @@ var BottlenecksContent = ({
|
|
|
22063
22111
|
let filtered = [];
|
|
22064
22112
|
if (activeFilter === "all") {
|
|
22065
22113
|
filtered = [...allVideos];
|
|
22066
|
-
} else if (activeFilter === "low_value") {
|
|
22067
|
-
filtered = allVideos.filter((video) => video.type === "low_value");
|
|
22068
|
-
} else if (activeFilter === "sop_deviations") {
|
|
22069
|
-
filtered = allVideos.filter((video) => video.type === "missing_quality_check");
|
|
22070
|
-
} else if (activeFilter === "best_cycle_time") {
|
|
22071
|
-
filtered = allVideos.filter((video) => video.type === "best_cycle_time");
|
|
22072
|
-
} else if (activeFilter === "worst_cycle_time") {
|
|
22073
|
-
filtered = allVideos.filter((video) => video.type === "worst_cycle_time");
|
|
22074
|
-
} else if (activeFilter === "cycle_completions") {
|
|
22075
|
-
filtered = allVideos.filter((video) => video.type === "cycle_completions");
|
|
22076
|
-
} else if (activeFilter === "long_cycle_time") {
|
|
22077
|
-
filtered = allVideos.filter(
|
|
22078
|
-
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22079
|
-
);
|
|
22080
22114
|
} else {
|
|
22081
|
-
|
|
22115
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
22116
|
+
const selectedCategory = sopCategories.find((cat) => cat.id === activeFilter);
|
|
22117
|
+
if (selectedCategory) {
|
|
22118
|
+
filtered = allVideos.filter((video) => video.type === selectedCategory.id);
|
|
22119
|
+
if (selectedCategory.id === "long_cycle_time") {
|
|
22120
|
+
filtered = allVideos.filter(
|
|
22121
|
+
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22122
|
+
);
|
|
22123
|
+
}
|
|
22124
|
+
}
|
|
22125
|
+
} else {
|
|
22126
|
+
if (activeFilter === "low_value") {
|
|
22127
|
+
filtered = allVideos.filter((video) => video.type === "low_value");
|
|
22128
|
+
} else if (activeFilter === "sop_deviations") {
|
|
22129
|
+
filtered = allVideos.filter((video) => video.type === "missing_quality_check");
|
|
22130
|
+
} else if (activeFilter === "best_cycle_time") {
|
|
22131
|
+
filtered = allVideos.filter((video) => video.type === "best_cycle_time");
|
|
22132
|
+
} else if (activeFilter === "worst_cycle_time") {
|
|
22133
|
+
filtered = allVideos.filter((video) => video.type === "worst_cycle_time");
|
|
22134
|
+
} else if (activeFilter === "cycle_completions") {
|
|
22135
|
+
filtered = allVideos.filter((video) => video.type === "cycle_completions");
|
|
22136
|
+
} else if (activeFilter === "long_cycle_time") {
|
|
22137
|
+
filtered = allVideos.filter(
|
|
22138
|
+
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22139
|
+
);
|
|
22140
|
+
} else {
|
|
22141
|
+
filtered = allVideos.filter((video) => video.type === "bottleneck" && video.severity === activeFilter);
|
|
22142
|
+
}
|
|
22143
|
+
}
|
|
22082
22144
|
}
|
|
22083
22145
|
return filtered.sort((a, b) => {
|
|
22084
22146
|
return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
|
|
22085
22147
|
});
|
|
22086
|
-
}, [activeFilter, allVideos]);
|
|
22148
|
+
}, [activeFilter, allVideos, sopCategories]);
|
|
22087
22149
|
React14.useEffect(() => {
|
|
22088
22150
|
if (filteredVideos.length === 0) return;
|
|
22089
22151
|
const upcoming = [];
|
|
@@ -22357,35 +22419,34 @@ var BottlenecksContent = ({
|
|
|
22357
22419
|
}
|
|
22358
22420
|
};
|
|
22359
22421
|
const clipCounts = React14.useMemo(() => {
|
|
22360
|
-
if (!allVideos) return {
|
|
22361
|
-
|
|
22362
|
-
|
|
22363
|
-
|
|
22364
|
-
|
|
22365
|
-
|
|
22366
|
-
|
|
22367
|
-
|
|
22368
|
-
|
|
22369
|
-
|
|
22370
|
-
|
|
22371
|
-
|
|
22372
|
-
}
|
|
22373
|
-
|
|
22374
|
-
|
|
22375
|
-
|
|
22376
|
-
|
|
22377
|
-
|
|
22378
|
-
|
|
22379
|
-
|
|
22380
|
-
|
|
22381
|
-
|
|
22382
|
-
longCycleTimes: allVideos.filter(
|
|
22422
|
+
if (!allVideos) return {};
|
|
22423
|
+
const counts = { total: allVideos.length };
|
|
22424
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
22425
|
+
sopCategories.forEach((category) => {
|
|
22426
|
+
if (category.id === "long_cycle_time") {
|
|
22427
|
+
counts[category.id] = allVideos.filter(
|
|
22428
|
+
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22429
|
+
).length;
|
|
22430
|
+
} else {
|
|
22431
|
+
counts[category.id] = allVideos.filter((video) => video.type === category.id).length;
|
|
22432
|
+
}
|
|
22433
|
+
});
|
|
22434
|
+
} else {
|
|
22435
|
+
counts.bottlenecks = allVideos.filter((video) => video.type === "bottleneck").length;
|
|
22436
|
+
counts.lowValue = allVideos.filter((video) => video.type === "low_value").length;
|
|
22437
|
+
counts.highSeverity = allVideos.filter((video) => video.severity === "high" && video.type === "bottleneck").length;
|
|
22438
|
+
counts.mediumSeverity = allVideos.filter((video) => video.severity === "medium" && video.type === "bottleneck").length;
|
|
22439
|
+
counts.lowSeverity = allVideos.filter((video) => video.severity === "low" && video.type === "bottleneck").length;
|
|
22440
|
+
counts.sopDeviations = allVideos.filter((video) => video.type === "missing_quality_check").length;
|
|
22441
|
+
counts.bestCycleTimes = allVideos.filter((video) => video.type === "best_cycle_time").length;
|
|
22442
|
+
counts.worstCycleTimes = allVideos.filter((video) => video.type === "worst_cycle_time").length;
|
|
22443
|
+
counts.longCycleTimes = allVideos.filter(
|
|
22383
22444
|
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22384
|
-
).length
|
|
22385
|
-
cycleCompletions
|
|
22386
|
-
|
|
22387
|
-
|
|
22388
|
-
}, [allVideos]);
|
|
22445
|
+
).length;
|
|
22446
|
+
counts.cycleCompletions = allVideos.filter((video) => video.type === "cycle_completions").length;
|
|
22447
|
+
}
|
|
22448
|
+
return counts;
|
|
22449
|
+
}, [allVideos, sopCategories]);
|
|
22389
22450
|
const currentVideo = React14.useMemo(() => {
|
|
22390
22451
|
if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
|
|
22391
22452
|
return null;
|
|
@@ -22410,6 +22471,19 @@ var BottlenecksContent = ({
|
|
|
22410
22471
|
return "Bottleneck";
|
|
22411
22472
|
}
|
|
22412
22473
|
};
|
|
22474
|
+
const getColorClasses = (color2) => {
|
|
22475
|
+
const colorMap = {
|
|
22476
|
+
purple: { text: "text-purple-500", bg: "bg-purple-500", dot: "bg-purple-500" },
|
|
22477
|
+
green: { text: "text-green-600", bg: "bg-green-600", dot: "bg-green-600" },
|
|
22478
|
+
red: { text: "text-red-700", bg: "bg-red-700", dot: "bg-red-700" },
|
|
22479
|
+
"red-dark": { text: "text-red-500", bg: "bg-red-500", dot: "bg-red-500" },
|
|
22480
|
+
blue: { text: "text-blue-600", bg: "bg-blue-600", dot: "bg-blue-600" },
|
|
22481
|
+
orange: { text: "text-orange-600", bg: "bg-orange-600", dot: "bg-orange-600" },
|
|
22482
|
+
yellow: { text: "text-yellow-600", bg: "bg-yellow-600", dot: "bg-yellow-600" },
|
|
22483
|
+
gray: { text: "text-gray-600", bg: "bg-gray-600", dot: "bg-gray-600" }
|
|
22484
|
+
};
|
|
22485
|
+
return colorMap[color2] || colorMap.gray;
|
|
22486
|
+
};
|
|
22413
22487
|
const formatTimeOnly = (time2) => {
|
|
22414
22488
|
if (!time2) return "";
|
|
22415
22489
|
try {
|
|
@@ -22439,162 +22513,62 @@ var BottlenecksContent = ({
|
|
|
22439
22513
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 max-w-md", children: error })
|
|
22440
22514
|
] });
|
|
22441
22515
|
}
|
|
22516
|
+
const categoriesToShow = sopCategories && sopCategories.length > 0 ? sopCategories : [
|
|
22517
|
+
// Default hardcoded categories if no configuration
|
|
22518
|
+
{ id: "low_value", label: "Idle Moments", color: "purple", subtitle: "Idle time detected" },
|
|
22519
|
+
{ id: "best_cycle_time", label: "Best Cycle Time", color: "green", subtitle: "Fastest cycle today" },
|
|
22520
|
+
{ id: "worst_cycle_time", label: "Worst Cycle Time", color: "red", subtitle: "Slowest cycle today" },
|
|
22521
|
+
{ id: "long_cycle_time", label: "Long Cycle Time", color: "red-dark", subtitle: "Above standard cycle times" },
|
|
22522
|
+
{ id: "cycle_completions", label: "Cycle Completions", color: "blue", subtitle: "Completed production cycles" }
|
|
22523
|
+
];
|
|
22442
22524
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4 h-[calc(100vh-12rem)]", children: [
|
|
22443
|
-
/* @__PURE__ */ jsxRuntime.
|
|
22444
|
-
|
|
22445
|
-
|
|
22446
|
-
|
|
22447
|
-
onClick: () => {
|
|
22448
|
-
setActiveFilter("low_value");
|
|
22449
|
-
trackCoreEvent("Idle Moments Filter Clicked", {
|
|
22450
|
-
workspaceId,
|
|
22451
|
-
workspaceName,
|
|
22452
|
-
date,
|
|
22453
|
-
filterType: "low_value",
|
|
22454
|
-
clipCount: clipCounts.lowValue
|
|
22455
|
-
});
|
|
22456
|
-
},
|
|
22457
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "low_value" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22458
|
-
"aria-label": `Filter by Idle Moments (${clipCounts.lowValue} clips)`,
|
|
22459
|
-
role: "button",
|
|
22460
|
-
tabIndex: 0,
|
|
22461
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("low_value"),
|
|
22462
|
-
children: [
|
|
22463
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "low_value" ? "text-blue-600" : ""}`, children: "Idle Moments" }) }),
|
|
22464
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22465
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-purple-500", children: clipCounts.lowValue }),
|
|
22466
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22467
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-purple-500 mr-1.5" }),
|
|
22468
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Idle time detected" })
|
|
22469
|
-
] })
|
|
22470
|
-
] }) })
|
|
22471
|
-
]
|
|
22472
|
-
}
|
|
22473
|
-
),
|
|
22474
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22475
|
-
Card2,
|
|
22476
|
-
{
|
|
22477
|
-
onClick: () => {
|
|
22478
|
-
setActiveFilter("best_cycle_time");
|
|
22479
|
-
trackCoreEvent("Best Cycle Time Filter Clicked", {
|
|
22480
|
-
workspaceId,
|
|
22481
|
-
workspaceName,
|
|
22482
|
-
date,
|
|
22483
|
-
filterType: "best_cycle_time",
|
|
22484
|
-
clipCount: clipCounts.bestCycleTimes
|
|
22485
|
-
});
|
|
22486
|
-
},
|
|
22487
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "best_cycle_time" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22488
|
-
"aria-label": `Filter by Best Cycle Time (${clipCounts.bestCycleTimes} clips)`,
|
|
22489
|
-
role: "button",
|
|
22490
|
-
tabIndex: 0,
|
|
22491
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("best_cycle_time"),
|
|
22492
|
-
children: [
|
|
22493
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "best_cycle_time" ? "text-blue-600" : ""}`, children: "Best Cycle Time" }) }),
|
|
22494
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22495
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-green-600", children: clipCounts.bestCycleTimes }),
|
|
22496
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22497
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-green-600 mr-1.5" }),
|
|
22498
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Fastest cycle today" })
|
|
22499
|
-
] })
|
|
22500
|
-
] }) })
|
|
22501
|
-
]
|
|
22502
|
-
}
|
|
22503
|
-
),
|
|
22504
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22525
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `grid grid-cols-1 sm:grid-cols-2 ${categoriesToShow.length <= 5 ? "lg:grid-cols-5" : "lg:grid-cols-6"} gap-3 mb-4`, children: categoriesToShow.map((category) => {
|
|
22526
|
+
const colorClasses = getColorClasses(category.color);
|
|
22527
|
+
const count = clipCounts[category.id] || 0;
|
|
22528
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22505
22529
|
Card2,
|
|
22506
22530
|
{
|
|
22507
22531
|
onClick: () => {
|
|
22508
|
-
setActiveFilter(
|
|
22509
|
-
trackCoreEvent(
|
|
22532
|
+
setActiveFilter(category.id);
|
|
22533
|
+
trackCoreEvent(`${category.label} Filter Clicked`, {
|
|
22510
22534
|
workspaceId,
|
|
22511
22535
|
workspaceName,
|
|
22512
22536
|
date,
|
|
22513
|
-
filterType:
|
|
22514
|
-
clipCount:
|
|
22537
|
+
filterType: category.id,
|
|
22538
|
+
clipCount: count
|
|
22515
22539
|
});
|
|
22516
22540
|
},
|
|
22517
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter ===
|
|
22518
|
-
"aria-label": `Filter by
|
|
22541
|
+
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === category.id ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22542
|
+
"aria-label": `Filter by ${category.label} (${count} clips)`,
|
|
22519
22543
|
role: "button",
|
|
22520
22544
|
tabIndex: 0,
|
|
22521
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter(
|
|
22545
|
+
onKeyDown: (e) => e.key === "Enter" && setActiveFilter(category.id),
|
|
22522
22546
|
children: [
|
|
22523
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter ===
|
|
22547
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === category.id ? "text-blue-600" : ""}`, children: category.label }) }),
|
|
22524
22548
|
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22525
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className:
|
|
22549
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-3xl font-bold ${colorClasses.text}`, children: count }),
|
|
22526
22550
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22527
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
22528
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
22551
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-2 w-2 rounded-full ${colorClasses.dot} mr-1.5` }),
|
|
22552
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: category.subtitle || category.description || category.label })
|
|
22529
22553
|
] })
|
|
22530
22554
|
] }) })
|
|
22531
22555
|
]
|
|
22532
|
-
}
|
|
22533
|
-
|
|
22534
|
-
|
|
22535
|
-
|
|
22536
|
-
{
|
|
22537
|
-
onClick: () => {
|
|
22538
|
-
setActiveFilter("long_cycle_time");
|
|
22539
|
-
trackCoreEvent("Long Cycle Time Filter Clicked", {
|
|
22540
|
-
workspaceId,
|
|
22541
|
-
workspaceName,
|
|
22542
|
-
date,
|
|
22543
|
-
filterType: "long_cycle_time",
|
|
22544
|
-
clipCount: clipCounts.longCycleTimes
|
|
22545
|
-
});
|
|
22546
|
-
},
|
|
22547
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "long_cycle_time" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22548
|
-
"aria-label": `Filter by Long Cycle Time Bottlenecks (${clipCounts.longCycleTimes} clips)`,
|
|
22549
|
-
role: "button",
|
|
22550
|
-
tabIndex: 0,
|
|
22551
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("long_cycle_time"),
|
|
22552
|
-
children: [
|
|
22553
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "long_cycle_time" ? "text-blue-600" : ""}`, children: "Long Cycle Time" }) }),
|
|
22554
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22555
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-red-500", children: clipCounts.longCycleTimes }),
|
|
22556
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22557
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-red-500 mr-1.5" }),
|
|
22558
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Above standard cycle times" })
|
|
22559
|
-
] })
|
|
22560
|
-
] }) })
|
|
22561
|
-
]
|
|
22562
|
-
}
|
|
22563
|
-
),
|
|
22564
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22565
|
-
Card2,
|
|
22566
|
-
{
|
|
22567
|
-
onClick: () => {
|
|
22568
|
-
setActiveFilter("cycle_completions");
|
|
22569
|
-
trackCoreEvent("Cycle Completions Filter Clicked", {
|
|
22570
|
-
workspaceId,
|
|
22571
|
-
workspaceName,
|
|
22572
|
-
date,
|
|
22573
|
-
filterType: "cycle_completions",
|
|
22574
|
-
clipCount: clipCounts.cycleCompletions
|
|
22575
|
-
});
|
|
22576
|
-
},
|
|
22577
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "cycle_completions" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22578
|
-
"aria-label": `Filter by Cycle Completions (${clipCounts.cycleCompletions} clips)`,
|
|
22579
|
-
role: "button",
|
|
22580
|
-
tabIndex: 0,
|
|
22581
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("cycle_completions"),
|
|
22582
|
-
children: [
|
|
22583
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "cycle_completions" ? "text-blue-600" : ""}`, children: "Cycle Completions" }) }),
|
|
22584
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22585
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-blue-600", children: clipCounts.cycleCompletions }),
|
|
22586
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22587
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-blue-600 mr-1.5" }),
|
|
22588
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Completed production cycles" })
|
|
22589
|
-
] })
|
|
22590
|
-
] }) })
|
|
22591
|
-
]
|
|
22592
|
-
}
|
|
22593
|
-
)
|
|
22594
|
-
] }),
|
|
22556
|
+
},
|
|
22557
|
+
category.id
|
|
22558
|
+
);
|
|
22559
|
+
}) }),
|
|
22595
22560
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm overflow-hidden", style: { height: "calc(100% - 8.5rem)" }, children: [
|
|
22596
22561
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
|
|
22597
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-800", children:
|
|
22562
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-800", children: (() => {
|
|
22563
|
+
if (activeFilter === "all") {
|
|
22564
|
+
return `All Clips (${clipCounts.total || 0})`;
|
|
22565
|
+
}
|
|
22566
|
+
const activeCategory = categoriesToShow.find((cat) => cat.id === activeFilter);
|
|
22567
|
+
if (activeCategory) {
|
|
22568
|
+
return `${activeCategory.label} (${clipCounts[activeCategory.id] || 0})`;
|
|
22569
|
+
}
|
|
22570
|
+
return activeFilter === "low_value" ? `Idle Moments (${clipCounts.lowValue || 0})` : activeFilter === "best_cycle_time" ? `Best Cycle Time (${clipCounts.bestCycleTimes || 0})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Time (${clipCounts.worstCycleTimes || 0})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes || 0})` : activeFilter === "cycle_completions" ? `Cycle Completions (${clipCounts.cycleCompletions || 0})` : `All Clips (${clipCounts.total || 0})`;
|
|
22571
|
+
})() }),
|
|
22598
22572
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
22599
22573
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: timestampFilterRef, children: [
|
|
22600
22574
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -24970,14 +24944,6 @@ var AIAgentView = () => {
|
|
|
24970
24944
|
return newMap;
|
|
24971
24945
|
});
|
|
24972
24946
|
},
|
|
24973
|
-
onReasoning: (text) => {
|
|
24974
|
-
setStreamingStates((prev) => {
|
|
24975
|
-
const newMap = new Map(prev);
|
|
24976
|
-
const current = newMap.get(currentThreadId) || { message: "", reasoning: "" };
|
|
24977
|
-
newMap.set(currentThreadId, { ...current, reasoning: current.reasoning + text });
|
|
24978
|
-
return newMap;
|
|
24979
|
-
});
|
|
24980
|
-
},
|
|
24981
24947
|
onComplete: async (messageId) => {
|
|
24982
24948
|
if (currentThreadId && !currentThreadId.startsWith("temp-")) {
|
|
24983
24949
|
const updatedMessages = await getAllThreadMessages(currentThreadId);
|
|
@@ -27366,14 +27332,20 @@ function HomeView({
|
|
|
27366
27332
|
}) {
|
|
27367
27333
|
const [isHydrated, setIsHydrated] = React14.useState(false);
|
|
27368
27334
|
const availableLineIds = React14.useMemo(() => [factoryViewId, ...allLineIds], [factoryViewId, allLineIds]);
|
|
27369
|
-
const [selectedLineId, setSelectedLineId] = React14.useState(
|
|
27335
|
+
const [selectedLineId, setSelectedLineId] = React14.useState(factoryViewId);
|
|
27370
27336
|
const [isChangingFilter, setIsChangingFilter] = React14.useState(false);
|
|
27371
27337
|
const [errorMessage, setErrorMessage] = React14.useState(null);
|
|
27372
27338
|
const [displayNamesInitialized, setDisplayNamesInitialized] = React14.useState(false);
|
|
27373
27339
|
React14.useEffect(() => {
|
|
27374
27340
|
const initDisplayNames = async () => {
|
|
27375
27341
|
try {
|
|
27376
|
-
|
|
27342
|
+
if (selectedLineId === factoryViewId) {
|
|
27343
|
+
for (const lineId of allLineIds) {
|
|
27344
|
+
await preInitializeWorkspaceDisplayNames(lineId);
|
|
27345
|
+
}
|
|
27346
|
+
} else {
|
|
27347
|
+
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
27348
|
+
}
|
|
27377
27349
|
setDisplayNamesInitialized(true);
|
|
27378
27350
|
} catch (error) {
|
|
27379
27351
|
console.error("Failed to pre-initialize workspace display names:", error);
|
|
@@ -27381,7 +27353,7 @@ function HomeView({
|
|
|
27381
27353
|
}
|
|
27382
27354
|
};
|
|
27383
27355
|
initDisplayNames();
|
|
27384
|
-
}, [selectedLineId]);
|
|
27356
|
+
}, [selectedLineId, factoryViewId, allLineIds]);
|
|
27385
27357
|
const {
|
|
27386
27358
|
displayNames: workspaceDisplayNames,
|
|
27387
27359
|
loading: displayNamesLoading,
|
|
@@ -27461,10 +27433,15 @@ function HomeView({
|
|
|
27461
27433
|
const lineTitle = React14.useMemo(() => {
|
|
27462
27434
|
return factoryName;
|
|
27463
27435
|
}, [factoryName]);
|
|
27464
|
-
const lineSelectorComponent = React14.useMemo(() =>
|
|
27465
|
-
|
|
27466
|
-
|
|
27467
|
-
|
|
27436
|
+
const lineSelectorComponent = React14.useMemo(() => {
|
|
27437
|
+
if (allLineIds.length <= 1) {
|
|
27438
|
+
return null;
|
|
27439
|
+
}
|
|
27440
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Select, { onValueChange: handleLineChange, defaultValue: selectedLineId, children: [
|
|
27441
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full sm:w-[200px] bg-white border border-gray-200 shadow-sm rounded-md h-9 text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select a line" }) }),
|
|
27442
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "z-50 bg-white shadow-lg border border-gray-200 rounded-md", children: availableLineIds.map((id3) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: id3, children: lineNames[id3] || (id3 === factoryViewId ? "All Lines" : `Line ${id3.substring(0, 4)}`) }, id3)) })
|
|
27443
|
+
] });
|
|
27444
|
+
}, [availableLineIds, handleLineChange, selectedLineId, lineNames, factoryViewId, allLineIds.length]);
|
|
27468
27445
|
const isLoading = !isHydrated || metricsLoading || kpisLoading || isChangingFilter || displayNamesLoading || !displayNamesInitialized;
|
|
27469
27446
|
if (isLoading) {
|
|
27470
27447
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-screen bg-slate-50", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingPageCmp, { message: "Loading dashboard..." }) });
|
|
@@ -27500,7 +27477,7 @@ function HomeView({
|
|
|
27500
27477
|
}
|
|
27501
27478
|
) }) }),
|
|
27502
27479
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative", children: [
|
|
27503
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-2 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
|
|
27480
|
+
lineSelectorComponent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-2 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
|
|
27504
27481
|
memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children: React14__namespace.default.createElement(WorkspaceGrid, {
|
|
27505
27482
|
workspaces: memoizedWorkspaceMetrics,
|
|
27506
27483
|
lineNames,
|