dp-widgets-framework 1.5.8 → 1.6.0
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.esm.js +185 -29
- package/dist/index.js +184 -28
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as LabelPrimitive from '@radix-ui/react-label';
|
|
|
7
7
|
import { cva } from 'class-variance-authority';
|
|
8
8
|
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
9
9
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
10
|
-
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw, Send, X, AlignVerticalSpaceAround, LineChart as LineChart$1, PieChart as PieChart$1, Table, FileText, SlidersHorizontal,
|
|
10
|
+
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw, Send, Loader2, X, AlignVerticalSpaceAround, LineChart as LineChart$1, PieChart as PieChart$1, Table, FileText, SlidersHorizontal, GripHorizontal, Edit, MessageCircleX, Edit2 } from 'lucide-react';
|
|
11
11
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
12
12
|
import { Slot } from '@radix-ui/react-slot';
|
|
13
13
|
import { debounce as debounce$1 } from 'lodash';
|
|
@@ -1986,6 +1986,29 @@ function WidgetPalette({ widgetBackendUrl } = {}) {
|
|
|
1986
1986
|
}, className: "cursor-move hover:bg-accent transition-colors", children: jsxRuntimeExports.jsx(CardContent, { className: "p-3", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [React__default.createElement(widget.icon, {}), jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("h4", { className: "font-medium text-sm", children: widget.name }), jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: widget.description })] })] }) }) }, widget.type))) }) })] }));
|
|
1987
1987
|
}
|
|
1988
1988
|
|
|
1989
|
+
const badgeVariants = cva("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
|
|
1990
|
+
variants: {
|
|
1991
|
+
variant: {
|
|
1992
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
1993
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
1994
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
1995
|
+
outline: "text-foreground",
|
|
1996
|
+
// Filter status variants
|
|
1997
|
+
success: "border-transparent bg-green-100 text-green-800 hover:bg-green-200",
|
|
1998
|
+
warning: "border-transparent bg-amber-100 text-amber-800 hover:bg-amber-200",
|
|
1999
|
+
muted: "border-transparent bg-gray-100 text-gray-600 hover:bg-gray-200",
|
|
2000
|
+
error: "border-transparent bg-red-100 text-red-800 hover:bg-red-200",
|
|
2001
|
+
},
|
|
2002
|
+
},
|
|
2003
|
+
defaultVariants: {
|
|
2004
|
+
variant: "default",
|
|
2005
|
+
},
|
|
2006
|
+
});
|
|
2007
|
+
function Badge(_a) {
|
|
2008
|
+
var { className, variant } = _a, props = __rest(_a, ["className", "variant"]);
|
|
2009
|
+
return (jsxRuntimeExports.jsx("div", Object.assign({ className: cn(badgeVariants({ variant }), className) }, props)));
|
|
2010
|
+
}
|
|
2011
|
+
|
|
1989
2012
|
const borderRadiusMap$2 = {
|
|
1990
2013
|
none: "0px",
|
|
1991
2014
|
rounded: "0.375rem",
|
|
@@ -39327,6 +39350,10 @@ const parseAndUpdateFilterState = (apiResponse, setFilterState) => {
|
|
|
39327
39350
|
if (filterData.agent_message) {
|
|
39328
39351
|
newFilterState.agent_message = filterData.agent_message;
|
|
39329
39352
|
}
|
|
39353
|
+
// Handle error key as a fallback for agent_message
|
|
39354
|
+
if (filterData.error && !newFilterState.agent_message) {
|
|
39355
|
+
newFilterState.agent_message = filterData.error;
|
|
39356
|
+
}
|
|
39330
39357
|
// Handle confirmation state
|
|
39331
39358
|
if (filterData.status) {
|
|
39332
39359
|
newFilterState.status = filterData.status;
|
|
@@ -39382,15 +39409,17 @@ function TableSelectionConfirmation({ ambiguousColumns, resolvedColumns, message
|
|
|
39382
39409
|
onConfirm(selectedTables);
|
|
39383
39410
|
};
|
|
39384
39411
|
const allSelected = ambiguousColumns.every((col) => selectedTables[col.column]);
|
|
39385
|
-
return (jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full p-4 bg-white", children: [jsxRuntimeExports.jsxs("div", { className: "mb-4", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold text-gray-800 mb-2", children: "Table Selection Required" }), message && (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 mb-4 whitespace-pre-line", children: message }))] }), resolvedColumns && resolvedColumns.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "mb-4 p-3 bg-green-50 border border-green-200 rounded-lg", children: [jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-green-800 mb-2", children: "Already Resolved Columns:" }), jsxRuntimeExports.jsx("div", { className: "space-y-1", children: resolvedColumns.map((col) => (jsxRuntimeExports.jsxs("div", { className: "text-sm text-green-700", children: [jsxRuntimeExports.jsx("span", { className: "font-medium", children: col.column }), " \u2192 ", jsxRuntimeExports.jsx("span", { className: "text-green-600", children: col.table_name })] }, col.column))) })] })), jsxRuntimeExports.jsx(
|
|
39412
|
+
return (jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full p-4 bg-white overflow-hidden", children: [jsxRuntimeExports.jsxs("div", { className: "mb-4 flex-shrink-0", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold text-gray-800 mb-2", children: "Table Selection Required" }), message && (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 mb-4 whitespace-pre-line", children: message }))] }), resolvedColumns && resolvedColumns.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "mb-4 p-3 bg-green-50 border border-green-200 rounded-lg flex-shrink-0", children: [jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-green-800 mb-2", children: "Already Resolved Columns:" }), jsxRuntimeExports.jsx("div", { className: "space-y-1", children: resolvedColumns.map((col) => (jsxRuntimeExports.jsxs("div", { className: "text-sm text-green-700", children: [jsxRuntimeExports.jsx("span", { className: "font-medium", children: col.column }), " \u2192 ", jsxRuntimeExports.jsx("span", { className: "text-green-600", children: col.table_name })] }, col.column))) })] })), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto mb-4 min-h-0 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent", children: jsxRuntimeExports.jsx("div", { className: "space-y-4", children: ambiguousColumns.map((col) => (jsxRuntimeExports.jsxs("div", { className: "border border-gray-200 rounded-lg p-3", children: [jsxRuntimeExports.jsx("label", { className: "block mb-2", children: jsxRuntimeExports.jsxs("span", { className: "text-sm font-medium text-gray-700", children: ["Column: ", jsxRuntimeExports.jsx("span", { className: "text-primary-600", children: col.column })] }) }), jsxRuntimeExports.jsxs("select", { value: selectedTables[col.column] || '', onChange: (e) => {
|
|
39386
39413
|
setSelectedTables((prev) => (Object.assign(Object.assign({}, prev), { [col.column]: e.target.value })));
|
|
39387
|
-
}, className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500", children: [jsxRuntimeExports.jsx("option", { value: "", children: "Select a table..." }), col.tables.map((table) => (jsxRuntimeExports.jsx("option", { value: table, children: table }, table)))] })] }, col.column))) }) }), jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-3 border-t border-gray-200", children: [jsxRuntimeExports.jsx(Button, { onClick: onCancel, variant: "outline", className: "flex-1", children: "Cancel" }), jsxRuntimeExports.jsx(Button, { onClick: handleSubmit, disabled: !allSelected, className: "flex-1 bg-primary-600 hover:bg-primary-700 text-white disabled:bg-gray-400", children: "Confirm Selection" })] })] }));
|
|
39414
|
+
}, className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500", children: [jsxRuntimeExports.jsx("option", { value: "", children: "Select a table..." }), col.tables.map((table) => (jsxRuntimeExports.jsx("option", { value: table, children: table }, table)))] })] }, col.column))) }) }), jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-3 border-t border-gray-200 flex-shrink-0", children: [jsxRuntimeExports.jsx(Button, { onClick: onCancel, variant: "outline", className: "flex-1", children: "Cancel" }), jsxRuntimeExports.jsx(Button, { onClick: handleSubmit, disabled: !allSelected, className: "flex-1 bg-primary-600 hover:bg-primary-700 text-white disabled:bg-gray-400", children: "Confirm Selection" })] })] }));
|
|
39388
39415
|
}
|
|
39389
39416
|
function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appendMessage, query, isFirstLoad, widgetBackendUrl, widgetId, startLoadingTimeout, clearLoadingTimeout, filterState, onApplyFilters, isEditing = false, }) {
|
|
39417
|
+
var _a;
|
|
39390
39418
|
const hasCalledRef = useRef(false);
|
|
39391
39419
|
const [expandedGroups, setExpandedGroups] = useState({});
|
|
39392
39420
|
const [selectedFilters, setSelectedFilters] = useState({});
|
|
39393
39421
|
const [searchQueries, setSearchQueries] = useState({});
|
|
39422
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
39394
39423
|
const isEmpty = filterGroups.length === 0;
|
|
39395
39424
|
const handleRefresh = async () => {
|
|
39396
39425
|
if (query) {
|
|
@@ -39428,6 +39457,29 @@ function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appe
|
|
|
39428
39457
|
});
|
|
39429
39458
|
setExpandedGroups(initialExpanded);
|
|
39430
39459
|
}, [filterGroups]);
|
|
39460
|
+
// Initialize selected filters from widget.config.filters
|
|
39461
|
+
useEffect(() => {
|
|
39462
|
+
var _a;
|
|
39463
|
+
if (((_a = widget.config) === null || _a === void 0 ? void 0 : _a.filters) && filterGroups.length > 0) {
|
|
39464
|
+
const initialSelectedFilters = {};
|
|
39465
|
+
Object.entries(widget.config.filters).forEach(([groupId, labels]) => {
|
|
39466
|
+
const group = filterGroups.find(g => g.id === groupId);
|
|
39467
|
+
if (group && Array.isArray(labels)) {
|
|
39468
|
+
// Convert labels back to option IDs
|
|
39469
|
+
const optionIds = labels
|
|
39470
|
+
.map(label => {
|
|
39471
|
+
const option = group.options.find(opt => opt.label === label);
|
|
39472
|
+
return option === null || option === void 0 ? void 0 : option.id;
|
|
39473
|
+
})
|
|
39474
|
+
.filter((id) => id !== undefined);
|
|
39475
|
+
if (optionIds.length > 0) {
|
|
39476
|
+
initialSelectedFilters[groupId] = optionIds;
|
|
39477
|
+
}
|
|
39478
|
+
}
|
|
39479
|
+
});
|
|
39480
|
+
setSelectedFilters(initialSelectedFilters);
|
|
39481
|
+
}
|
|
39482
|
+
}, [(_a = widget.config) === null || _a === void 0 ? void 0 : _a.filters, filterGroups]);
|
|
39431
39483
|
const toggleGroup = (groupId) => {
|
|
39432
39484
|
setExpandedGroups((prev) => (Object.assign(Object.assign({}, prev), { [groupId]: !prev[groupId] })));
|
|
39433
39485
|
};
|
|
@@ -39474,24 +39526,24 @@ function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appe
|
|
|
39474
39526
|
if (isEmpty) {
|
|
39475
39527
|
return createLoadingComponent$4();
|
|
39476
39528
|
}
|
|
39477
|
-
return (jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col bg-white rounded-lg", children: [showHeader && (jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntimeExports.jsx(Bot, { className: "h-4 w-4" }), jsxRuntimeExports.jsx("h3", { className: "font-semibold text-gray-800", children: "Filters" })] }) })), jsxRuntimeExports.jsx(
|
|
39529
|
+
return (jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col bg-white rounded-lg overflow-hidden", children: [showHeader && (jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-b border-gray-100 flex-shrink-0", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntimeExports.jsx(Bot, { className: "h-4 w-4" }), jsxRuntimeExports.jsx("h3", { className: "font-semibold text-gray-800", children: "Filters" })] }) })), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto min-h-0 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent", children: jsxRuntimeExports.jsx("div", { className: "p-2", children: filterGroups.map((group) => {
|
|
39478
39530
|
const isExpanded = expandedGroups[group.id];
|
|
39479
39531
|
const selectedCount = getSelectedCount(group.id);
|
|
39480
39532
|
const filteredOptions = getFilteredOptions(group);
|
|
39481
39533
|
return (jsxRuntimeExports.jsxs("div", { className: "mb-2 border border-gray-100 rounded-lg overflow-hidden", children: [jsxRuntimeExports.jsxs("button", { onClick: () => toggleGroup(group.id), className: cn("w-full flex items-center justify-between px-3 py-2.5", "bg-gray-50 hover:bg-gray-100 transition-colors", "focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-inset"), children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [isExpanded ? (jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4 text-primary-600" })) : (jsxRuntimeExports.jsx(ChevronRight, { className: "w-4 h-4 text-gray-500" })), jsxRuntimeExports.jsx("span", { className: "font-medium text-sm text-gray-700", children: group.name }), selectedCount > 0 && (jsxRuntimeExports.jsx("span", { className: "ml-1 px-1.5 py-0.5 text-xs font-medium bg-primary-100 text-primary-700 rounded-full", children: selectedCount }))] }), selectedCount > 0 && (jsxRuntimeExports.jsx("button", { onClick: (e) => {
|
|
39482
39534
|
e.stopPropagation();
|
|
39483
39535
|
clearGroupFilters(group.id);
|
|
39484
|
-
}, className: "text-xs text-primary-600 hover:text-primary-800 hover:underline", children: "Clear" }))] }), jsxRuntimeExports.jsx("div", { className: cn("overflow-hidden transition-all duration-200 ease-in-out", isExpanded ? "max-h-[
|
|
39536
|
+
}, className: "text-xs text-primary-600 hover:text-primary-800 hover:underline", children: "Clear" }))] }), jsxRuntimeExports.jsx("div", { className: cn("overflow-hidden transition-all duration-200 ease-in-out", isExpanded ? "max-h-[500px]" : "max-h-0"), children: jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 bg-white", children: [group.options.length > 5 && (jsxRuntimeExports.jsxs("div", { className: "relative mb-2", children: [jsxRuntimeExports.jsx(Search, { className: "absolute left-2.5 top-1/2 transform -translate-y-1/2 w-3.5 h-3.5 text-gray-400" }), jsxRuntimeExports.jsx(Input, { type: "text", placeholder: `Search ${group.name.toLowerCase()}...`, value: searchQueries[group.id] || "", onChange: (e) => handleSearchChange(group.id, e.target.value), className: "pl-8 h-8 text-sm border-gray-200 focus:border-primary-400 focus:ring-primary-400" })] })), jsxRuntimeExports.jsx("div", { className: "space-y-1 max-h-[350px] overflow-y-auto pr-1 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent", children: filteredOptions.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500 py-2 text-center", children: "No options found" })) : (filteredOptions.map((option) => {
|
|
39485
39537
|
var _a;
|
|
39486
39538
|
const isChecked = ((_a = selectedFilters[group.id]) === null || _a === void 0 ? void 0 : _a.includes(option.id)) || false;
|
|
39487
39539
|
return (jsxRuntimeExports.jsxs("label", { className: cn("flex items-center gap-2.5 px-2 py-1.5 rounded-md cursor-pointer", "hover:bg-gray-50 transition-colors", isChecked && "bg-primary-50"), children: [jsxRuntimeExports.jsx(Checkbox, { checked: isChecked, onCheckedChange: (checked) => handleCheckboxChange(group.id, option.id, checked), className: cn("h-4 w-4 rounded border-gray-300", "data-[state=checked]:bg-primary-600 data-[state=checked]:border-primary-600") }), jsxRuntimeExports.jsx("span", { className: cn("text-sm flex-1 truncate", isChecked ? "text-primary-700 font-medium" : "text-gray-600"), title: option.label, children: option.label }), option.count !== undefined && (jsxRuntimeExports.jsxs("span", { className: "text-xs text-gray-400", children: ["(", option.count, ")"] }))] }, option.id));
|
|
39488
39540
|
})) })] }) })] }, group.id));
|
|
39489
|
-
}) }) }), jsxRuntimeExports.jsx("div", { className: "px-4 py-2 border-t border-gray-100 bg-gray-50", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [Object.values(selectedFilters).some((arr) => arr.length > 0) ? (jsxRuntimeExports.jsx("button", { onClick: () => {
|
|
39541
|
+
}) }) }), jsxRuntimeExports.jsx("div", { className: "px-4 py-2 border-t border-gray-100 bg-gray-50 flex-shrink-0", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [Object.values(selectedFilters).some((arr) => arr.length > 0) ? (jsxRuntimeExports.jsx("button", { onClick: () => {
|
|
39490
39542
|
setSelectedFilters({});
|
|
39491
39543
|
if (onFilterChange) {
|
|
39492
39544
|
onFilterChange({});
|
|
39493
39545
|
}
|
|
39494
|
-
}, className: "py-1.5 text-sm font-medium text-primary-600 hover:text-primary-800 hover:bg-primary-50 rounded-md transition-colors px-2", children: "Clear All Filters" })) : (jsxRuntimeExports.jsx("div", {})), jsxRuntimeExports.jsx(Button, { onClick: () => {
|
|
39546
|
+
}, className: "py-1.5 text-sm font-medium text-primary-600 hover:text-primary-800 hover:bg-primary-50 rounded-md transition-colors px-2", children: "Clear All Filters" })) : (jsxRuntimeExports.jsx("div", {})), jsxRuntimeExports.jsx(Button, { onClick: async () => {
|
|
39495
39547
|
// Convert option IDs back to original label values
|
|
39496
39548
|
const filtersWithLabels = {};
|
|
39497
39549
|
filterGroups.forEach((group) => {
|
|
@@ -39501,8 +39553,37 @@ function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appe
|
|
|
39501
39553
|
return (option === null || option === void 0 ? void 0 : option.label) || optionId;
|
|
39502
39554
|
});
|
|
39503
39555
|
});
|
|
39504
|
-
|
|
39505
|
-
|
|
39556
|
+
// Call API to update widget config with filters
|
|
39557
|
+
if (widgetBackendUrl && widgetId) {
|
|
39558
|
+
setIsSubmitting(true);
|
|
39559
|
+
try {
|
|
39560
|
+
const response = await fetch(`${widgetBackendUrl}/api/widgets/${widgetId}/config`, {
|
|
39561
|
+
method: 'PATCH',
|
|
39562
|
+
headers: {
|
|
39563
|
+
'Content-Type': 'application/json',
|
|
39564
|
+
},
|
|
39565
|
+
body: JSON.stringify({
|
|
39566
|
+
config: Object.assign(Object.assign({}, widget.config), { filters: filtersWithLabels }),
|
|
39567
|
+
}),
|
|
39568
|
+
});
|
|
39569
|
+
if (!response.ok) {
|
|
39570
|
+
throw new Error('Failed to update widget config');
|
|
39571
|
+
}
|
|
39572
|
+
// Call the onApplyFilters callback after successful API call
|
|
39573
|
+
onApplyFilters === null || onApplyFilters === void 0 ? void 0 : onApplyFilters(filtersWithLabels);
|
|
39574
|
+
}
|
|
39575
|
+
catch (error) {
|
|
39576
|
+
console.error('Error updating widget config:', error);
|
|
39577
|
+
}
|
|
39578
|
+
finally {
|
|
39579
|
+
setIsSubmitting(false);
|
|
39580
|
+
}
|
|
39581
|
+
}
|
|
39582
|
+
else {
|
|
39583
|
+
// Fallback if no backend URL - just call the callback
|
|
39584
|
+
onApplyFilters === null || onApplyFilters === void 0 ? void 0 : onApplyFilters(filtersWithLabels);
|
|
39585
|
+
}
|
|
39586
|
+
}, disabled: isEditing || isSubmitting, className: `${isEditing || isSubmitting ? 'bg-gray-400 cursor-not-allowed' : 'bg-primary-600 hover:bg-primary-700'} text-white`, title: isEditing ? 'Save the layout first to apply filters' : '', children: isSubmitting ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Applying..."] })) : ('Apply Filters') })] }) })] }));
|
|
39506
39587
|
}
|
|
39507
39588
|
function CopilotKitFilters({ widget, showHeader, onFilterChange, onResetReady, widgetBackendUrl, datasetId, onApplyFilters, isEditing = false, }) {
|
|
39508
39589
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -41356,7 +41437,7 @@ const IconMap = {
|
|
|
41356
41437
|
'pie-chart': PieChart$1,
|
|
41357
41438
|
'chatbot': Bot,
|
|
41358
41439
|
};
|
|
41359
|
-
function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSelect, refreshKey, widgetBackendUrl, onSaveLayoutReady, openWidgetPallete = false, onCloseWidgetPallete, defaultAgentName = "adk-construction-project-agent", userId, onApplyFilters,
|
|
41440
|
+
function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSelect, refreshKey, widgetBackendUrl, onSaveLayoutReady, openWidgetPallete = false, onCloseWidgetPallete, defaultAgentName = "adk-construction-project-agent", userId, onApplyFilters, filterResults, isApplyingFilters = false }) {
|
|
41360
41441
|
const [widgets, setWidgets] = useState([]);
|
|
41361
41442
|
const [datasetId, setDatasetId] = useState('');
|
|
41362
41443
|
const [availableWidgets, setAvailableWidgets] = useState([]);
|
|
@@ -41371,6 +41452,31 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41371
41452
|
const [editInitialQuery, setEditInitialQuery] = useState("");
|
|
41372
41453
|
const [editingWidget, setEditingWidget] = useState(null);
|
|
41373
41454
|
const [widgetResetFunctions, setWidgetResetFunctions] = useState(new Map());
|
|
41455
|
+
// Helper to get filter status for a widget
|
|
41456
|
+
const getWidgetFilterStatus = useCallback((widgetId) => {
|
|
41457
|
+
if (!filterResults)
|
|
41458
|
+
return null;
|
|
41459
|
+
// Only show status for agent widgets
|
|
41460
|
+
const result = filterResults.results.find(r => r.widgetId === widgetId);
|
|
41461
|
+
if (!result)
|
|
41462
|
+
return null;
|
|
41463
|
+
return result;
|
|
41464
|
+
}, [filterResults]);
|
|
41465
|
+
// Helper to get badge variant based on filter status
|
|
41466
|
+
const getFilterStatusBadge = (status) => {
|
|
41467
|
+
switch (status) {
|
|
41468
|
+
case "updated":
|
|
41469
|
+
return { variant: "success", label: "Filtered", icon: "✓" };
|
|
41470
|
+
case "no_data":
|
|
41471
|
+
return { variant: "warning", label: "No Data", icon: "⚠" };
|
|
41472
|
+
case "skipped":
|
|
41473
|
+
return { variant: "muted", label: "Skipped", icon: "−" };
|
|
41474
|
+
case "failed":
|
|
41475
|
+
return { variant: "error", label: "Failed", icon: "✕" };
|
|
41476
|
+
default:
|
|
41477
|
+
return { variant: "muted", label: status, icon: "?" };
|
|
41478
|
+
}
|
|
41479
|
+
};
|
|
41374
41480
|
// Use external selectedWidget if provided, otherwise use internal state
|
|
41375
41481
|
const currentSelectedWidget = selectedWidget !== undefined ? selectedWidget : internalSelectedWidget;
|
|
41376
41482
|
const setSelectedWidget = onWidgetSelect || setInternalSelectedWidget;
|
|
@@ -41435,6 +41541,19 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41435
41541
|
}
|
|
41436
41542
|
});
|
|
41437
41543
|
window.dispatchEvent(event);
|
|
41544
|
+
// If filters have been applied (filter widget exists), regenerate filtered_sql_query for this widget
|
|
41545
|
+
// This handles the case where a widget's query is changed after filters have been applied
|
|
41546
|
+
const hasFilterWidget = widgets.some(w => w.type === 'filters');
|
|
41547
|
+
if (hasFilterWidget && editingWidget.type === 'agent' && widgetBackendUrl) {
|
|
41548
|
+
// Dispatch event to notify that filtered query needs regeneration for this widget
|
|
41549
|
+
const regenerateEvent = new CustomEvent('regenerateFilteredQuery', {
|
|
41550
|
+
detail: {
|
|
41551
|
+
widgetId: editingWidget.id,
|
|
41552
|
+
dashboardId: pageId
|
|
41553
|
+
}
|
|
41554
|
+
});
|
|
41555
|
+
window.dispatchEvent(regenerateEvent);
|
|
41556
|
+
}
|
|
41438
41557
|
}
|
|
41439
41558
|
};
|
|
41440
41559
|
const handleResetReady = useCallback((widgetId, resetFn) => {
|
|
@@ -41526,6 +41645,15 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41526
41645
|
};
|
|
41527
41646
|
loadWidgetTypes();
|
|
41528
41647
|
}, []);
|
|
41648
|
+
// Track original widget IDs from initial load
|
|
41649
|
+
const originalWidgetIdsRef = useRef(new Set());
|
|
41650
|
+
// Update original widget IDs when widgets are loaded from server
|
|
41651
|
+
useEffect(() => {
|
|
41652
|
+
if (pageData === null || pageData === void 0 ? void 0 : pageData.widgets) {
|
|
41653
|
+
const ids = new Set(pageData.widgets.map((w) => w.id));
|
|
41654
|
+
originalWidgetIdsRef.current = ids;
|
|
41655
|
+
}
|
|
41656
|
+
}, [pageData]);
|
|
41529
41657
|
// Use ref to store the latest save function without causing re-renders
|
|
41530
41658
|
const saveLayoutRef = useRef();
|
|
41531
41659
|
// Update the ref whenever dependencies change
|
|
@@ -41533,6 +41661,13 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41533
41661
|
if (!pageData) {
|
|
41534
41662
|
throw new Error("No page data available");
|
|
41535
41663
|
}
|
|
41664
|
+
// Identify new agent widgets (added since last load/save)
|
|
41665
|
+
const currentWidgetIds = new Set(widgets.map(w => w.id));
|
|
41666
|
+
const newAgentWidgetIds = widgets
|
|
41667
|
+
.filter(w => w.type === 'agent' && !originalWidgetIdsRef.current.has(w.id))
|
|
41668
|
+
.map(w => w.id);
|
|
41669
|
+
// Check if there's a filter widget on this dashboard
|
|
41670
|
+
const hasFilterWidget = widgets.some(w => w.type === 'filters');
|
|
41536
41671
|
try {
|
|
41537
41672
|
const response = await fetch(getApiUrl(`/api/pages/${pageId}`), {
|
|
41538
41673
|
method: "PUT",
|
|
@@ -41550,16 +41685,42 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41550
41685
|
throw new Error("Failed to save layout");
|
|
41551
41686
|
}
|
|
41552
41687
|
const savedData = await response.json();
|
|
41553
|
-
//
|
|
41554
|
-
|
|
41555
|
-
// setWidgets(prevWidgets => prevWidgets.map(widget => ({
|
|
41556
|
-
// ...widget,
|
|
41557
|
-
// config: {
|
|
41558
|
-
// ...widget.config,
|
|
41559
|
-
// isFirstLoad: false
|
|
41560
|
-
// }
|
|
41561
|
-
// })));
|
|
41688
|
+
// Update original widget IDs to include newly saved widgets
|
|
41689
|
+
originalWidgetIdsRef.current = currentWidgetIds;
|
|
41562
41690
|
console.log('Layout saved successfully');
|
|
41691
|
+
// If there are new agent widgets and a filter widget exists,
|
|
41692
|
+
// schedule generation of filtered_sql_query for new widgets
|
|
41693
|
+
// Note: This is done asynchronously after save to not block the save operation
|
|
41694
|
+
// The actual generation will happen after the widget agents have run and created sql_query
|
|
41695
|
+
if (newAgentWidgetIds.length > 0 && hasFilterWidget) {
|
|
41696
|
+
console.log(`[WidgetDashboard] New agent widgets detected: ${newAgentWidgetIds.join(', ')}`);
|
|
41697
|
+
console.log('[WidgetDashboard] Filter widget exists - filtered_sql_query will be generated when filters are applied');
|
|
41698
|
+
// Optionally, we could trigger generation after a delay to allow widget agents to initialize
|
|
41699
|
+
// For now, we rely on the auto-generation in /api/filters/apply when filters are applied
|
|
41700
|
+
// Uncomment below to proactively generate after a delay:
|
|
41701
|
+
/*
|
|
41702
|
+
setTimeout(async () => {
|
|
41703
|
+
try {
|
|
41704
|
+
console.log('[WidgetDashboard] Generating filtered_sql_query for new widgets...');
|
|
41705
|
+
const generateResponse = await fetch(getApiUrl('/api/filters/generate-queries'), {
|
|
41706
|
+
method: 'POST',
|
|
41707
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41708
|
+
body: JSON.stringify({
|
|
41709
|
+
dashboard_id: pageId,
|
|
41710
|
+
widget_ids: newAgentWidgetIds,
|
|
41711
|
+
regenerate: false,
|
|
41712
|
+
}),
|
|
41713
|
+
});
|
|
41714
|
+
if (generateResponse.ok) {
|
|
41715
|
+
const result = await generateResponse.json();
|
|
41716
|
+
console.log('[WidgetDashboard] Generate queries result:', result);
|
|
41717
|
+
}
|
|
41718
|
+
} catch (err) {
|
|
41719
|
+
console.warn('[WidgetDashboard] Could not generate filtered queries for new widgets:', err);
|
|
41720
|
+
}
|
|
41721
|
+
}, 5000); // 5 second delay to allow widget agents to initialize
|
|
41722
|
+
*/
|
|
41723
|
+
}
|
|
41563
41724
|
}
|
|
41564
41725
|
catch (err) {
|
|
41565
41726
|
console.error("Save error:", err);
|
|
@@ -41839,10 +42000,10 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41839
42000
|
onCloseWidgetPallete && onCloseWidgetPallete();
|
|
41840
42001
|
}, defaultAgentName: defaultAgentName, hasFiltersWidget: widgets.some(w => w.type === 'filters') }), jsxRuntimeExports.jsx(EditWidgetDialog, { editingWidget: editingWidget, setWidgets: setWidgets, initialText: editInitialQuery, isOpen: showEditModal, onClose: () => setShowEditModal(false), onSubmit: handleEditSubmit }), jsxRuntimeExports.jsx("div", { className: "min-h-full", onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, onClick: () => setSelectedWidget(null), children: isLoading ? (jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full", children: jsxRuntimeExports.jsx(Loader2, { className: "h-8 w-8 animate-spin" }) })) : (jsxRuntimeExports.jsx(RGL, { className: "layout m-0 p-0 gap-2", layouts: { lg: getLayoutFromWidgets() }, breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480 }, cols: { lg: 12, md: 8, sm: 6, xs: 2 }, rowHeight: 60, isDraggable: isEditing, isResizable: isEditing, draggableHandle: ".drag-icon", onLayoutChange: handleLayoutChange, compactType: "vertical", containerPadding: [0, 0], margin: [16, 16], children: widgets.map((w) => {
|
|
41841
42002
|
var _a, _b;
|
|
41842
|
-
const
|
|
41843
|
-
const
|
|
41844
|
-
return (jsxRuntimeExports.jsxs("div", { className: `${(w.type === "text" || w.type === "spacer") ? `${((_b = (_a = w === null || w === void 0 ? void 0 : w.config) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.divider) === "yes" && "border-b border-gray-300"} ${isEditing ? 'shadow-lg rounded-xl border border-primary-300' : 'flex items-center'}` : `shadow-lg rounded-xl border border-primary-300 p-4 ${isEditing ? 'pb-14' : 'pb-5'}`}`, children: [isEditing &&
|
|
41845
|
-
jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-end mb-4 relative ${(w.type === "text" || w.type === "spacer") ? "pl-4 pr-4 pt-4" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center drag-icon cursor-grab absolute left-1/2 -translate-x-1/2", children: [jsxRuntimeExports.jsx(GripHorizontal, { className: "" }), jsxRuntimeExports.jsx(GripHorizontal, { className: "-ml-[3px]" }), jsxRuntimeExports.jsx(GripHorizontal, { className: "-ml-[3px]" })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 cursor-pointer justify-end", children: [jsxRuntimeExports.jsx(Trash2, { onClick: () => removeWidget(w.id), className: "w-5 h-5 text-red-700" }), (w.type !== "spacer" && w.type !== "chatbot") && jsxRuntimeExports.jsx(Edit, { onClick: () => onClickSettings && onClickSettings(w), className: "w-5 h-5 text-gray-600" })] })] }),
|
|
42003
|
+
const filterStatus = w.type === 'agent' ? getWidgetFilterStatus(w.id) : null;
|
|
42004
|
+
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
42005
|
+
return (jsxRuntimeExports.jsxs("div", { className: `${(w.type === "text" || w.type === "spacer") ? `${((_b = (_a = w === null || w === void 0 ? void 0 : w.config) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.divider) === "yes" && "border-b border-gray-300"} ${isEditing ? 'shadow-lg rounded-xl border border-primary-300' : 'flex items-center'}` : `shadow-lg rounded-xl border border-primary-300 p-4 ${isEditing ? 'pb-14' : 'pb-5'}`} relative`, children: [w.type === 'agent' && badgeInfo && !isApplyingFilters && (jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 z-10", title: (filterStatus === null || filterStatus === void 0 ? void 0 : filterStatus.reason) || (filterStatus === null || filterStatus === void 0 ? void 0 : filterStatus.error) || '', children: jsxRuntimeExports.jsxs(Badge, { variant: badgeInfo.variant, className: "text-[10px] px-2 py-0.5 gap-1", children: [jsxRuntimeExports.jsx("span", { children: badgeInfo.icon }), jsxRuntimeExports.jsx("span", { children: badgeInfo.label })] }) })), w.type === 'agent' && isApplyingFilters && (jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 z-10", children: jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "text-[10px] px-2 py-0.5 gap-1 animate-pulse", children: [jsxRuntimeExports.jsx(Loader2, { className: "w-3 h-3 animate-spin" }), jsxRuntimeExports.jsx("span", { children: "Filtering..." })] }) })), isEditing &&
|
|
42006
|
+
jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-end mb-4 relative ${(w.type === "text" || w.type === "spacer") ? "pl-4 pr-4 pt-4" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center drag-icon cursor-grab absolute left-1/2 -translate-x-1/2", children: [jsxRuntimeExports.jsx(GripHorizontal, { className: "" }), jsxRuntimeExports.jsx(GripHorizontal, { className: "-ml-[3px]" }), jsxRuntimeExports.jsx(GripHorizontal, { className: "-ml-[3px]" })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 cursor-pointer justify-end", children: [jsxRuntimeExports.jsx(Trash2, { onClick: () => removeWidget(w.id), className: "w-5 h-5 text-red-700" }), (w.type !== "spacer" && w.type !== "chatbot") && jsxRuntimeExports.jsx(Edit, { onClick: () => onClickSettings && onClickSettings(w), className: "w-5 h-5 text-gray-600" })] })] }), jsxRuntimeExports.jsxs("div", { className: `${((w === null || w === void 0 ? void 0 : w.type) === 'text' || (w === null || w === void 0 ? void 0 : w.type) === 'spacer') ? `${isEditing ? 'px-4' : ''}` : "h-full"} w-full relative`, children: [(w === null || w === void 0 ? void 0 : w.type) === "chatbot" &&
|
|
41846
42007
|
jsxRuntimeExports.jsxs("div", { className: "relative z-50", children: [jsxRuntimeExports.jsx("div", { onClick: () => handleClearChat(w === null || w === void 0 ? void 0 : w.id), onMouseOver: () => setVisibleClearButton(w === null || w === void 0 ? void 0 : w.id), onMouseLeave: () => setVisibleClearButton(""), className: "absolute top-[12px] right-0 z-40 flex align-middle justify-center gap-2 text-sm px-4 py-2 border-primary-300 rounded-l-sm w-fit bg-primary-700 text-white cursor-pointer shadow-md transition-all", children: jsxRuntimeExports.jsx(MessageCircleX, { className: "w-5 h-5" }) }), jsxRuntimeExports.jsx("span", { className: `absolute top-[56px] right-[16px] z-50 w-max py-1 text-xs px-2 rounded-sm text-white bg-gray-950 ${visibleClearButton === (w === null || w === void 0 ? void 0 : w.id) ? "block" : "hidden"}`, children: "Clear Chat" })] }), jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl: widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter(widget => widget.type !== 'chatbot').map(widget => widget.id), datasetId: datasetId, pageId: pageId, onApplyFilters: onApplyFilters, isEditing: isEditing })] })] }, w.id));
|
|
41847
42008
|
}) })) })] }));
|
|
41848
42009
|
}
|
|
@@ -44740,7 +44901,6 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
44740
44901
|
const [pages, setPages] = useState([]);
|
|
44741
44902
|
const [isLoading, setIsLoading] = useState(true);
|
|
44742
44903
|
const [error, setError] = useState(null);
|
|
44743
|
-
const [activeFilters, setActiveFilters] = useState({});
|
|
44744
44904
|
// Helper function to get API URL
|
|
44745
44905
|
const getApiUrl = (endpoint) => {
|
|
44746
44906
|
const baseUrl = widgetBackendUrl || '';
|
|
@@ -44749,10 +44909,6 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
44749
44909
|
useEffect(() => {
|
|
44750
44910
|
loadPages();
|
|
44751
44911
|
}, []);
|
|
44752
|
-
const handleApplyFilters = (pageId) => (filters) => {
|
|
44753
|
-
console.log('Filters applied for page:', pageId, filters);
|
|
44754
|
-
setActiveFilters(prev => (Object.assign(Object.assign({}, prev), { [pageId]: filters })));
|
|
44755
|
-
};
|
|
44756
44912
|
const loadPages = async () => {
|
|
44757
44913
|
try {
|
|
44758
44914
|
setIsLoading(true);
|
|
@@ -44797,7 +44953,7 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
44797
44953
|
}
|
|
44798
44954
|
return (jsxRuntimeExports.jsxs("div", { className: "container mx-auto p-6 h-screen flex flex-col", children: [jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [jsxRuntimeExports.jsx("h1", { className: "text-2xl font-bold", children: "Dashboard Pages" }), jsxRuntimeExports.jsx("p", { className: "text-muted-foreground", children: "View all your saved pages in dashboard mode" })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: jsxRuntimeExports.jsxs(Tabs, { defaultValue: (_a = pages[0]) === null || _a === void 0 ? void 0 : _a.id, className: "h-full flex flex-col", children: [jsxRuntimeExports.jsx(TabsList, { className: "grid w-full grid-cols-auto gap-1 mb-4", style: {
|
|
44799
44955
|
gridTemplateColumns: `repeat(${pages.length}, minmax(120px, 1fr))`
|
|
44800
|
-
}, children: pages.map((page) => (jsxRuntimeExports.jsx(TabsTrigger, { value: page.id, className: "truncate px-3 py-2 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-lg border-2 data-[state=active]:border-primary data-[state=inactive]:border-transparent hover:bg-accent hover:text-accent-foreground transition-all duration-200", title: page.title, children: page.title }, page.id))) }), pages.map((page) => (jsxRuntimeExports.jsx(TabsContent, { value: page.id, className: "flex-1 overflow-hidden m-0", children: jsxRuntimeExports.jsx("div", { className: "h-full border rounded-lg overflow-hidden", children: jsxRuntimeExports.jsx(WidgetDashboard, { pageId: page.id, isEditing: false, widgetBackendUrl: widgetBackendUrl
|
|
44956
|
+
}, children: pages.map((page) => (jsxRuntimeExports.jsx(TabsTrigger, { value: page.id, className: "truncate px-3 py-2 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-lg border-2 data-[state=active]:border-primary data-[state=inactive]:border-transparent hover:bg-accent hover:text-accent-foreground transition-all duration-200", title: page.title, children: page.title }, page.id))) }), pages.map((page) => (jsxRuntimeExports.jsx(TabsContent, { value: page.id, className: "flex-1 overflow-hidden m-0", children: jsxRuntimeExports.jsx("div", { className: "h-full border rounded-lg overflow-hidden", children: jsxRuntimeExports.jsx(WidgetDashboard, { pageId: page.id, isEditing: false, widgetBackendUrl: widgetBackendUrl }) }) }, page.id)))] }) })] }));
|
|
44801
44957
|
}
|
|
44802
44958
|
|
|
44803
44959
|
export { Button, DashboardPages, Input, SavedPages, WidgetDashboard, WidgetPalette, WidgetSettingsPanel, cn };
|
package/dist/index.js
CHANGED
|
@@ -2013,6 +2013,29 @@ function WidgetPalette({ widgetBackendUrl } = {}) {
|
|
|
2013
2013
|
}, className: "cursor-move hover:bg-accent transition-colors", children: jsxRuntimeExports.jsx(CardContent, { className: "p-3", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [React.createElement(widget.icon, {}), jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("h4", { className: "font-medium text-sm", children: widget.name }), jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: widget.description })] })] }) }) }, widget.type))) }) })] }));
|
|
2014
2014
|
}
|
|
2015
2015
|
|
|
2016
|
+
const badgeVariants = classVarianceAuthority.cva("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
|
|
2017
|
+
variants: {
|
|
2018
|
+
variant: {
|
|
2019
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
2020
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
2021
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
2022
|
+
outline: "text-foreground",
|
|
2023
|
+
// Filter status variants
|
|
2024
|
+
success: "border-transparent bg-green-100 text-green-800 hover:bg-green-200",
|
|
2025
|
+
warning: "border-transparent bg-amber-100 text-amber-800 hover:bg-amber-200",
|
|
2026
|
+
muted: "border-transparent bg-gray-100 text-gray-600 hover:bg-gray-200",
|
|
2027
|
+
error: "border-transparent bg-red-100 text-red-800 hover:bg-red-200",
|
|
2028
|
+
},
|
|
2029
|
+
},
|
|
2030
|
+
defaultVariants: {
|
|
2031
|
+
variant: "default",
|
|
2032
|
+
},
|
|
2033
|
+
});
|
|
2034
|
+
function Badge(_a) {
|
|
2035
|
+
var { className, variant } = _a, props = __rest(_a, ["className", "variant"]);
|
|
2036
|
+
return (jsxRuntimeExports.jsx("div", Object.assign({ className: cn(badgeVariants({ variant }), className) }, props)));
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2016
2039
|
const borderRadiusMap$2 = {
|
|
2017
2040
|
none: "0px",
|
|
2018
2041
|
rounded: "0.375rem",
|
|
@@ -39354,6 +39377,10 @@ const parseAndUpdateFilterState = (apiResponse, setFilterState) => {
|
|
|
39354
39377
|
if (filterData.agent_message) {
|
|
39355
39378
|
newFilterState.agent_message = filterData.agent_message;
|
|
39356
39379
|
}
|
|
39380
|
+
// Handle error key as a fallback for agent_message
|
|
39381
|
+
if (filterData.error && !newFilterState.agent_message) {
|
|
39382
|
+
newFilterState.agent_message = filterData.error;
|
|
39383
|
+
}
|
|
39357
39384
|
// Handle confirmation state
|
|
39358
39385
|
if (filterData.status) {
|
|
39359
39386
|
newFilterState.status = filterData.status;
|
|
@@ -39409,15 +39436,17 @@ function TableSelectionConfirmation({ ambiguousColumns, resolvedColumns, message
|
|
|
39409
39436
|
onConfirm(selectedTables);
|
|
39410
39437
|
};
|
|
39411
39438
|
const allSelected = ambiguousColumns.every((col) => selectedTables[col.column]);
|
|
39412
|
-
return (jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full p-4 bg-white", children: [jsxRuntimeExports.jsxs("div", { className: "mb-4", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold text-gray-800 mb-2", children: "Table Selection Required" }), message && (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 mb-4 whitespace-pre-line", children: message }))] }), resolvedColumns && resolvedColumns.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "mb-4 p-3 bg-green-50 border border-green-200 rounded-lg", children: [jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-green-800 mb-2", children: "Already Resolved Columns:" }), jsxRuntimeExports.jsx("div", { className: "space-y-1", children: resolvedColumns.map((col) => (jsxRuntimeExports.jsxs("div", { className: "text-sm text-green-700", children: [jsxRuntimeExports.jsx("span", { className: "font-medium", children: col.column }), " \u2192 ", jsxRuntimeExports.jsx("span", { className: "text-green-600", children: col.table_name })] }, col.column))) })] })), jsxRuntimeExports.jsx(
|
|
39439
|
+
return (jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full p-4 bg-white overflow-hidden", children: [jsxRuntimeExports.jsxs("div", { className: "mb-4 flex-shrink-0", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold text-gray-800 mb-2", children: "Table Selection Required" }), message && (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 mb-4 whitespace-pre-line", children: message }))] }), resolvedColumns && resolvedColumns.length > 0 && (jsxRuntimeExports.jsxs("div", { className: "mb-4 p-3 bg-green-50 border border-green-200 rounded-lg flex-shrink-0", children: [jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-green-800 mb-2", children: "Already Resolved Columns:" }), jsxRuntimeExports.jsx("div", { className: "space-y-1", children: resolvedColumns.map((col) => (jsxRuntimeExports.jsxs("div", { className: "text-sm text-green-700", children: [jsxRuntimeExports.jsx("span", { className: "font-medium", children: col.column }), " \u2192 ", jsxRuntimeExports.jsx("span", { className: "text-green-600", children: col.table_name })] }, col.column))) })] })), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto mb-4 min-h-0 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent", children: jsxRuntimeExports.jsx("div", { className: "space-y-4", children: ambiguousColumns.map((col) => (jsxRuntimeExports.jsxs("div", { className: "border border-gray-200 rounded-lg p-3", children: [jsxRuntimeExports.jsx("label", { className: "block mb-2", children: jsxRuntimeExports.jsxs("span", { className: "text-sm font-medium text-gray-700", children: ["Column: ", jsxRuntimeExports.jsx("span", { className: "text-primary-600", children: col.column })] }) }), jsxRuntimeExports.jsxs("select", { value: selectedTables[col.column] || '', onChange: (e) => {
|
|
39413
39440
|
setSelectedTables((prev) => (Object.assign(Object.assign({}, prev), { [col.column]: e.target.value })));
|
|
39414
|
-
}, className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500", children: [jsxRuntimeExports.jsx("option", { value: "", children: "Select a table..." }), col.tables.map((table) => (jsxRuntimeExports.jsx("option", { value: table, children: table }, table)))] })] }, col.column))) }) }), jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-3 border-t border-gray-200", children: [jsxRuntimeExports.jsx(Button, { onClick: onCancel, variant: "outline", className: "flex-1", children: "Cancel" }), jsxRuntimeExports.jsx(Button, { onClick: handleSubmit, disabled: !allSelected, className: "flex-1 bg-primary-600 hover:bg-primary-700 text-white disabled:bg-gray-400", children: "Confirm Selection" })] })] }));
|
|
39441
|
+
}, className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500", children: [jsxRuntimeExports.jsx("option", { value: "", children: "Select a table..." }), col.tables.map((table) => (jsxRuntimeExports.jsx("option", { value: table, children: table }, table)))] })] }, col.column))) }) }), jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-3 border-t border-gray-200 flex-shrink-0", children: [jsxRuntimeExports.jsx(Button, { onClick: onCancel, variant: "outline", className: "flex-1", children: "Cancel" }), jsxRuntimeExports.jsx(Button, { onClick: handleSubmit, disabled: !allSelected, className: "flex-1 bg-primary-600 hover:bg-primary-700 text-white disabled:bg-gray-400", children: "Confirm Selection" })] })] }));
|
|
39415
39442
|
}
|
|
39416
39443
|
function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appendMessage, query, isFirstLoad, widgetBackendUrl, widgetId, startLoadingTimeout, clearLoadingTimeout, filterState, onApplyFilters, isEditing = false, }) {
|
|
39444
|
+
var _a;
|
|
39417
39445
|
const hasCalledRef = React.useRef(false);
|
|
39418
39446
|
const [expandedGroups, setExpandedGroups] = React.useState({});
|
|
39419
39447
|
const [selectedFilters, setSelectedFilters] = React.useState({});
|
|
39420
39448
|
const [searchQueries, setSearchQueries] = React.useState({});
|
|
39449
|
+
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
39421
39450
|
const isEmpty = filterGroups.length === 0;
|
|
39422
39451
|
const handleRefresh = async () => {
|
|
39423
39452
|
if (query) {
|
|
@@ -39455,6 +39484,29 @@ function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appe
|
|
|
39455
39484
|
});
|
|
39456
39485
|
setExpandedGroups(initialExpanded);
|
|
39457
39486
|
}, [filterGroups]);
|
|
39487
|
+
// Initialize selected filters from widget.config.filters
|
|
39488
|
+
React.useEffect(() => {
|
|
39489
|
+
var _a;
|
|
39490
|
+
if (((_a = widget.config) === null || _a === void 0 ? void 0 : _a.filters) && filterGroups.length > 0) {
|
|
39491
|
+
const initialSelectedFilters = {};
|
|
39492
|
+
Object.entries(widget.config.filters).forEach(([groupId, labels]) => {
|
|
39493
|
+
const group = filterGroups.find(g => g.id === groupId);
|
|
39494
|
+
if (group && Array.isArray(labels)) {
|
|
39495
|
+
// Convert labels back to option IDs
|
|
39496
|
+
const optionIds = labels
|
|
39497
|
+
.map(label => {
|
|
39498
|
+
const option = group.options.find(opt => opt.label === label);
|
|
39499
|
+
return option === null || option === void 0 ? void 0 : option.id;
|
|
39500
|
+
})
|
|
39501
|
+
.filter((id) => id !== undefined);
|
|
39502
|
+
if (optionIds.length > 0) {
|
|
39503
|
+
initialSelectedFilters[groupId] = optionIds;
|
|
39504
|
+
}
|
|
39505
|
+
}
|
|
39506
|
+
});
|
|
39507
|
+
setSelectedFilters(initialSelectedFilters);
|
|
39508
|
+
}
|
|
39509
|
+
}, [(_a = widget.config) === null || _a === void 0 ? void 0 : _a.filters, filterGroups]);
|
|
39458
39510
|
const toggleGroup = (groupId) => {
|
|
39459
39511
|
setExpandedGroups((prev) => (Object.assign(Object.assign({}, prev), { [groupId]: !prev[groupId] })));
|
|
39460
39512
|
};
|
|
@@ -39501,24 +39553,24 @@ function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appe
|
|
|
39501
39553
|
if (isEmpty) {
|
|
39502
39554
|
return createLoadingComponent$4();
|
|
39503
39555
|
}
|
|
39504
|
-
return (jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col bg-white rounded-lg", children: [showHeader && (jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntimeExports.jsx(lucideReact.Bot, { className: "h-4 w-4" }), jsxRuntimeExports.jsx("h3", { className: "font-semibold text-gray-800", children: "Filters" })] }) })), jsxRuntimeExports.jsx(
|
|
39556
|
+
return (jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col bg-white rounded-lg overflow-hidden", children: [showHeader && (jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-b border-gray-100 flex-shrink-0", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntimeExports.jsx(lucideReact.Bot, { className: "h-4 w-4" }), jsxRuntimeExports.jsx("h3", { className: "font-semibold text-gray-800", children: "Filters" })] }) })), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto min-h-0 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent", children: jsxRuntimeExports.jsx("div", { className: "p-2", children: filterGroups.map((group) => {
|
|
39505
39557
|
const isExpanded = expandedGroups[group.id];
|
|
39506
39558
|
const selectedCount = getSelectedCount(group.id);
|
|
39507
39559
|
const filteredOptions = getFilteredOptions(group);
|
|
39508
39560
|
return (jsxRuntimeExports.jsxs("div", { className: "mb-2 border border-gray-100 rounded-lg overflow-hidden", children: [jsxRuntimeExports.jsxs("button", { onClick: () => toggleGroup(group.id), className: cn("w-full flex items-center justify-between px-3 py-2.5", "bg-gray-50 hover:bg-gray-100 transition-colors", "focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-inset"), children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [isExpanded ? (jsxRuntimeExports.jsx(lucideReact.ChevronDown, { className: "w-4 h-4 text-primary-600" })) : (jsxRuntimeExports.jsx(lucideReact.ChevronRight, { className: "w-4 h-4 text-gray-500" })), jsxRuntimeExports.jsx("span", { className: "font-medium text-sm text-gray-700", children: group.name }), selectedCount > 0 && (jsxRuntimeExports.jsx("span", { className: "ml-1 px-1.5 py-0.5 text-xs font-medium bg-primary-100 text-primary-700 rounded-full", children: selectedCount }))] }), selectedCount > 0 && (jsxRuntimeExports.jsx("button", { onClick: (e) => {
|
|
39509
39561
|
e.stopPropagation();
|
|
39510
39562
|
clearGroupFilters(group.id);
|
|
39511
|
-
}, className: "text-xs text-primary-600 hover:text-primary-800 hover:underline", children: "Clear" }))] }), jsxRuntimeExports.jsx("div", { className: cn("overflow-hidden transition-all duration-200 ease-in-out", isExpanded ? "max-h-[
|
|
39563
|
+
}, className: "text-xs text-primary-600 hover:text-primary-800 hover:underline", children: "Clear" }))] }), jsxRuntimeExports.jsx("div", { className: cn("overflow-hidden transition-all duration-200 ease-in-out", isExpanded ? "max-h-[500px]" : "max-h-0"), children: jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 bg-white", children: [group.options.length > 5 && (jsxRuntimeExports.jsxs("div", { className: "relative mb-2", children: [jsxRuntimeExports.jsx(lucideReact.Search, { className: "absolute left-2.5 top-1/2 transform -translate-y-1/2 w-3.5 h-3.5 text-gray-400" }), jsxRuntimeExports.jsx(Input, { type: "text", placeholder: `Search ${group.name.toLowerCase()}...`, value: searchQueries[group.id] || "", onChange: (e) => handleSearchChange(group.id, e.target.value), className: "pl-8 h-8 text-sm border-gray-200 focus:border-primary-400 focus:ring-primary-400" })] })), jsxRuntimeExports.jsx("div", { className: "space-y-1 max-h-[350px] overflow-y-auto pr-1 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-transparent", children: filteredOptions.length === 0 ? (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500 py-2 text-center", children: "No options found" })) : (filteredOptions.map((option) => {
|
|
39512
39564
|
var _a;
|
|
39513
39565
|
const isChecked = ((_a = selectedFilters[group.id]) === null || _a === void 0 ? void 0 : _a.includes(option.id)) || false;
|
|
39514
39566
|
return (jsxRuntimeExports.jsxs("label", { className: cn("flex items-center gap-2.5 px-2 py-1.5 rounded-md cursor-pointer", "hover:bg-gray-50 transition-colors", isChecked && "bg-primary-50"), children: [jsxRuntimeExports.jsx(Checkbox, { checked: isChecked, onCheckedChange: (checked) => handleCheckboxChange(group.id, option.id, checked), className: cn("h-4 w-4 rounded border-gray-300", "data-[state=checked]:bg-primary-600 data-[state=checked]:border-primary-600") }), jsxRuntimeExports.jsx("span", { className: cn("text-sm flex-1 truncate", isChecked ? "text-primary-700 font-medium" : "text-gray-600"), title: option.label, children: option.label }), option.count !== undefined && (jsxRuntimeExports.jsxs("span", { className: "text-xs text-gray-400", children: ["(", option.count, ")"] }))] }, option.id));
|
|
39515
39567
|
})) })] }) })] }, group.id));
|
|
39516
|
-
}) }) }), jsxRuntimeExports.jsx("div", { className: "px-4 py-2 border-t border-gray-100 bg-gray-50", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [Object.values(selectedFilters).some((arr) => arr.length > 0) ? (jsxRuntimeExports.jsx("button", { onClick: () => {
|
|
39568
|
+
}) }) }), jsxRuntimeExports.jsx("div", { className: "px-4 py-2 border-t border-gray-100 bg-gray-50 flex-shrink-0", children: jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [Object.values(selectedFilters).some((arr) => arr.length > 0) ? (jsxRuntimeExports.jsx("button", { onClick: () => {
|
|
39517
39569
|
setSelectedFilters({});
|
|
39518
39570
|
if (onFilterChange) {
|
|
39519
39571
|
onFilterChange({});
|
|
39520
39572
|
}
|
|
39521
|
-
}, className: "py-1.5 text-sm font-medium text-primary-600 hover:text-primary-800 hover:bg-primary-50 rounded-md transition-colors px-2", children: "Clear All Filters" })) : (jsxRuntimeExports.jsx("div", {})), jsxRuntimeExports.jsx(Button, { onClick: () => {
|
|
39573
|
+
}, className: "py-1.5 text-sm font-medium text-primary-600 hover:text-primary-800 hover:bg-primary-50 rounded-md transition-colors px-2", children: "Clear All Filters" })) : (jsxRuntimeExports.jsx("div", {})), jsxRuntimeExports.jsx(Button, { onClick: async () => {
|
|
39522
39574
|
// Convert option IDs back to original label values
|
|
39523
39575
|
const filtersWithLabels = {};
|
|
39524
39576
|
filterGroups.forEach((group) => {
|
|
@@ -39528,8 +39580,37 @@ function FiltersContent({ filterGroups, showHeader, onFilterChange, widget, appe
|
|
|
39528
39580
|
return (option === null || option === void 0 ? void 0 : option.label) || optionId;
|
|
39529
39581
|
});
|
|
39530
39582
|
});
|
|
39531
|
-
|
|
39532
|
-
|
|
39583
|
+
// Call API to update widget config with filters
|
|
39584
|
+
if (widgetBackendUrl && widgetId) {
|
|
39585
|
+
setIsSubmitting(true);
|
|
39586
|
+
try {
|
|
39587
|
+
const response = await fetch(`${widgetBackendUrl}/api/widgets/${widgetId}/config`, {
|
|
39588
|
+
method: 'PATCH',
|
|
39589
|
+
headers: {
|
|
39590
|
+
'Content-Type': 'application/json',
|
|
39591
|
+
},
|
|
39592
|
+
body: JSON.stringify({
|
|
39593
|
+
config: Object.assign(Object.assign({}, widget.config), { filters: filtersWithLabels }),
|
|
39594
|
+
}),
|
|
39595
|
+
});
|
|
39596
|
+
if (!response.ok) {
|
|
39597
|
+
throw new Error('Failed to update widget config');
|
|
39598
|
+
}
|
|
39599
|
+
// Call the onApplyFilters callback after successful API call
|
|
39600
|
+
onApplyFilters === null || onApplyFilters === void 0 ? void 0 : onApplyFilters(filtersWithLabels);
|
|
39601
|
+
}
|
|
39602
|
+
catch (error) {
|
|
39603
|
+
console.error('Error updating widget config:', error);
|
|
39604
|
+
}
|
|
39605
|
+
finally {
|
|
39606
|
+
setIsSubmitting(false);
|
|
39607
|
+
}
|
|
39608
|
+
}
|
|
39609
|
+
else {
|
|
39610
|
+
// Fallback if no backend URL - just call the callback
|
|
39611
|
+
onApplyFilters === null || onApplyFilters === void 0 ? void 0 : onApplyFilters(filtersWithLabels);
|
|
39612
|
+
}
|
|
39613
|
+
}, disabled: isEditing || isSubmitting, className: `${isEditing || isSubmitting ? 'bg-gray-400 cursor-not-allowed' : 'bg-primary-600 hover:bg-primary-700'} text-white`, title: isEditing ? 'Save the layout first to apply filters' : '', children: isSubmitting ? (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(lucideReact.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Applying..."] })) : ('Apply Filters') })] }) })] }));
|
|
39533
39614
|
}
|
|
39534
39615
|
function CopilotKitFilters({ widget, showHeader, onFilterChange, onResetReady, widgetBackendUrl, datasetId, onApplyFilters, isEditing = false, }) {
|
|
39535
39616
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -41383,7 +41464,7 @@ const IconMap = {
|
|
|
41383
41464
|
'pie-chart': lucideReact.PieChart,
|
|
41384
41465
|
'chatbot': lucideReact.Bot,
|
|
41385
41466
|
};
|
|
41386
|
-
function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSelect, refreshKey, widgetBackendUrl, onSaveLayoutReady, openWidgetPallete = false, onCloseWidgetPallete, defaultAgentName = "adk-construction-project-agent", userId, onApplyFilters,
|
|
41467
|
+
function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSelect, refreshKey, widgetBackendUrl, onSaveLayoutReady, openWidgetPallete = false, onCloseWidgetPallete, defaultAgentName = "adk-construction-project-agent", userId, onApplyFilters, filterResults, isApplyingFilters = false }) {
|
|
41387
41468
|
const [widgets, setWidgets] = React.useState([]);
|
|
41388
41469
|
const [datasetId, setDatasetId] = React.useState('');
|
|
41389
41470
|
const [availableWidgets, setAvailableWidgets] = React.useState([]);
|
|
@@ -41398,6 +41479,31 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41398
41479
|
const [editInitialQuery, setEditInitialQuery] = React.useState("");
|
|
41399
41480
|
const [editingWidget, setEditingWidget] = React.useState(null);
|
|
41400
41481
|
const [widgetResetFunctions, setWidgetResetFunctions] = React.useState(new Map());
|
|
41482
|
+
// Helper to get filter status for a widget
|
|
41483
|
+
const getWidgetFilterStatus = React.useCallback((widgetId) => {
|
|
41484
|
+
if (!filterResults)
|
|
41485
|
+
return null;
|
|
41486
|
+
// Only show status for agent widgets
|
|
41487
|
+
const result = filterResults.results.find(r => r.widgetId === widgetId);
|
|
41488
|
+
if (!result)
|
|
41489
|
+
return null;
|
|
41490
|
+
return result;
|
|
41491
|
+
}, [filterResults]);
|
|
41492
|
+
// Helper to get badge variant based on filter status
|
|
41493
|
+
const getFilterStatusBadge = (status) => {
|
|
41494
|
+
switch (status) {
|
|
41495
|
+
case "updated":
|
|
41496
|
+
return { variant: "success", label: "Filtered", icon: "✓" };
|
|
41497
|
+
case "no_data":
|
|
41498
|
+
return { variant: "warning", label: "No Data", icon: "⚠" };
|
|
41499
|
+
case "skipped":
|
|
41500
|
+
return { variant: "muted", label: "Skipped", icon: "−" };
|
|
41501
|
+
case "failed":
|
|
41502
|
+
return { variant: "error", label: "Failed", icon: "✕" };
|
|
41503
|
+
default:
|
|
41504
|
+
return { variant: "muted", label: status, icon: "?" };
|
|
41505
|
+
}
|
|
41506
|
+
};
|
|
41401
41507
|
// Use external selectedWidget if provided, otherwise use internal state
|
|
41402
41508
|
const currentSelectedWidget = selectedWidget !== undefined ? selectedWidget : internalSelectedWidget;
|
|
41403
41509
|
const setSelectedWidget = onWidgetSelect || setInternalSelectedWidget;
|
|
@@ -41462,6 +41568,19 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41462
41568
|
}
|
|
41463
41569
|
});
|
|
41464
41570
|
window.dispatchEvent(event);
|
|
41571
|
+
// If filters have been applied (filter widget exists), regenerate filtered_sql_query for this widget
|
|
41572
|
+
// This handles the case where a widget's query is changed after filters have been applied
|
|
41573
|
+
const hasFilterWidget = widgets.some(w => w.type === 'filters');
|
|
41574
|
+
if (hasFilterWidget && editingWidget.type === 'agent' && widgetBackendUrl) {
|
|
41575
|
+
// Dispatch event to notify that filtered query needs regeneration for this widget
|
|
41576
|
+
const regenerateEvent = new CustomEvent('regenerateFilteredQuery', {
|
|
41577
|
+
detail: {
|
|
41578
|
+
widgetId: editingWidget.id,
|
|
41579
|
+
dashboardId: pageId
|
|
41580
|
+
}
|
|
41581
|
+
});
|
|
41582
|
+
window.dispatchEvent(regenerateEvent);
|
|
41583
|
+
}
|
|
41465
41584
|
}
|
|
41466
41585
|
};
|
|
41467
41586
|
const handleResetReady = React.useCallback((widgetId, resetFn) => {
|
|
@@ -41553,6 +41672,15 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41553
41672
|
};
|
|
41554
41673
|
loadWidgetTypes();
|
|
41555
41674
|
}, []);
|
|
41675
|
+
// Track original widget IDs from initial load
|
|
41676
|
+
const originalWidgetIdsRef = React.useRef(new Set());
|
|
41677
|
+
// Update original widget IDs when widgets are loaded from server
|
|
41678
|
+
React.useEffect(() => {
|
|
41679
|
+
if (pageData === null || pageData === void 0 ? void 0 : pageData.widgets) {
|
|
41680
|
+
const ids = new Set(pageData.widgets.map((w) => w.id));
|
|
41681
|
+
originalWidgetIdsRef.current = ids;
|
|
41682
|
+
}
|
|
41683
|
+
}, [pageData]);
|
|
41556
41684
|
// Use ref to store the latest save function without causing re-renders
|
|
41557
41685
|
const saveLayoutRef = React.useRef();
|
|
41558
41686
|
// Update the ref whenever dependencies change
|
|
@@ -41560,6 +41688,13 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41560
41688
|
if (!pageData) {
|
|
41561
41689
|
throw new Error("No page data available");
|
|
41562
41690
|
}
|
|
41691
|
+
// Identify new agent widgets (added since last load/save)
|
|
41692
|
+
const currentWidgetIds = new Set(widgets.map(w => w.id));
|
|
41693
|
+
const newAgentWidgetIds = widgets
|
|
41694
|
+
.filter(w => w.type === 'agent' && !originalWidgetIdsRef.current.has(w.id))
|
|
41695
|
+
.map(w => w.id);
|
|
41696
|
+
// Check if there's a filter widget on this dashboard
|
|
41697
|
+
const hasFilterWidget = widgets.some(w => w.type === 'filters');
|
|
41563
41698
|
try {
|
|
41564
41699
|
const response = await fetch(getApiUrl(`/api/pages/${pageId}`), {
|
|
41565
41700
|
method: "PUT",
|
|
@@ -41577,16 +41712,42 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41577
41712
|
throw new Error("Failed to save layout");
|
|
41578
41713
|
}
|
|
41579
41714
|
const savedData = await response.json();
|
|
41580
|
-
//
|
|
41581
|
-
|
|
41582
|
-
// setWidgets(prevWidgets => prevWidgets.map(widget => ({
|
|
41583
|
-
// ...widget,
|
|
41584
|
-
// config: {
|
|
41585
|
-
// ...widget.config,
|
|
41586
|
-
// isFirstLoad: false
|
|
41587
|
-
// }
|
|
41588
|
-
// })));
|
|
41715
|
+
// Update original widget IDs to include newly saved widgets
|
|
41716
|
+
originalWidgetIdsRef.current = currentWidgetIds;
|
|
41589
41717
|
console.log('Layout saved successfully');
|
|
41718
|
+
// If there are new agent widgets and a filter widget exists,
|
|
41719
|
+
// schedule generation of filtered_sql_query for new widgets
|
|
41720
|
+
// Note: This is done asynchronously after save to not block the save operation
|
|
41721
|
+
// The actual generation will happen after the widget agents have run and created sql_query
|
|
41722
|
+
if (newAgentWidgetIds.length > 0 && hasFilterWidget) {
|
|
41723
|
+
console.log(`[WidgetDashboard] New agent widgets detected: ${newAgentWidgetIds.join(', ')}`);
|
|
41724
|
+
console.log('[WidgetDashboard] Filter widget exists - filtered_sql_query will be generated when filters are applied');
|
|
41725
|
+
// Optionally, we could trigger generation after a delay to allow widget agents to initialize
|
|
41726
|
+
// For now, we rely on the auto-generation in /api/filters/apply when filters are applied
|
|
41727
|
+
// Uncomment below to proactively generate after a delay:
|
|
41728
|
+
/*
|
|
41729
|
+
setTimeout(async () => {
|
|
41730
|
+
try {
|
|
41731
|
+
console.log('[WidgetDashboard] Generating filtered_sql_query for new widgets...');
|
|
41732
|
+
const generateResponse = await fetch(getApiUrl('/api/filters/generate-queries'), {
|
|
41733
|
+
method: 'POST',
|
|
41734
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41735
|
+
body: JSON.stringify({
|
|
41736
|
+
dashboard_id: pageId,
|
|
41737
|
+
widget_ids: newAgentWidgetIds,
|
|
41738
|
+
regenerate: false,
|
|
41739
|
+
}),
|
|
41740
|
+
});
|
|
41741
|
+
if (generateResponse.ok) {
|
|
41742
|
+
const result = await generateResponse.json();
|
|
41743
|
+
console.log('[WidgetDashboard] Generate queries result:', result);
|
|
41744
|
+
}
|
|
41745
|
+
} catch (err) {
|
|
41746
|
+
console.warn('[WidgetDashboard] Could not generate filtered queries for new widgets:', err);
|
|
41747
|
+
}
|
|
41748
|
+
}, 5000); // 5 second delay to allow widget agents to initialize
|
|
41749
|
+
*/
|
|
41750
|
+
}
|
|
41590
41751
|
}
|
|
41591
41752
|
catch (err) {
|
|
41592
41753
|
console.error("Save error:", err);
|
|
@@ -41866,10 +42027,10 @@ function WidgetDashboard({ pageId, isEditing, selectedWidget = null, onWidgetSel
|
|
|
41866
42027
|
onCloseWidgetPallete && onCloseWidgetPallete();
|
|
41867
42028
|
}, defaultAgentName: defaultAgentName, hasFiltersWidget: widgets.some(w => w.type === 'filters') }), jsxRuntimeExports.jsx(EditWidgetDialog, { editingWidget: editingWidget, setWidgets: setWidgets, initialText: editInitialQuery, isOpen: showEditModal, onClose: () => setShowEditModal(false), onSubmit: handleEditSubmit }), jsxRuntimeExports.jsx("div", { className: "min-h-full", onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, onClick: () => setSelectedWidget(null), children: isLoading ? (jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full", children: jsxRuntimeExports.jsx(lucideReact.Loader2, { className: "h-8 w-8 animate-spin" }) })) : (jsxRuntimeExports.jsx(RGL, { className: "layout m-0 p-0 gap-2", layouts: { lg: getLayoutFromWidgets() }, breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480 }, cols: { lg: 12, md: 8, sm: 6, xs: 2 }, rowHeight: 60, isDraggable: isEditing, isResizable: isEditing, draggableHandle: ".drag-icon", onLayoutChange: handleLayoutChange, compactType: "vertical", containerPadding: [0, 0], margin: [16, 16], children: widgets.map((w) => {
|
|
41868
42029
|
var _a, _b;
|
|
41869
|
-
const
|
|
41870
|
-
const
|
|
41871
|
-
return (jsxRuntimeExports.jsxs("div", { className: `${(w.type === "text" || w.type === "spacer") ? `${((_b = (_a = w === null || w === void 0 ? void 0 : w.config) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.divider) === "yes" && "border-b border-gray-300"} ${isEditing ? 'shadow-lg rounded-xl border border-primary-300' : 'flex items-center'}` : `shadow-lg rounded-xl border border-primary-300 p-4 ${isEditing ? 'pb-14' : 'pb-5'}`}`, children: [isEditing &&
|
|
41872
|
-
jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-end mb-4 relative ${(w.type === "text" || w.type === "spacer") ? "pl-4 pr-4 pt-4" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center drag-icon cursor-grab absolute left-1/2 -translate-x-1/2", children: [jsxRuntimeExports.jsx(lucideReact.GripHorizontal, { className: "" }), jsxRuntimeExports.jsx(lucideReact.GripHorizontal, { className: "-ml-[3px]" }), jsxRuntimeExports.jsx(lucideReact.GripHorizontal, { className: "-ml-[3px]" })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 cursor-pointer justify-end", children: [jsxRuntimeExports.jsx(lucideReact.Trash2, { onClick: () => removeWidget(w.id), className: "w-5 h-5 text-red-700" }), (w.type !== "spacer" && w.type !== "chatbot") && jsxRuntimeExports.jsx(lucideReact.Edit, { onClick: () => onClickSettings && onClickSettings(w), className: "w-5 h-5 text-gray-600" })] })] }),
|
|
42030
|
+
const filterStatus = w.type === 'agent' ? getWidgetFilterStatus(w.id) : null;
|
|
42031
|
+
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
42032
|
+
return (jsxRuntimeExports.jsxs("div", { className: `${(w.type === "text" || w.type === "spacer") ? `${((_b = (_a = w === null || w === void 0 ? void 0 : w.config) === null || _a === void 0 ? void 0 : _a.content) === null || _b === void 0 ? void 0 : _b.divider) === "yes" && "border-b border-gray-300"} ${isEditing ? 'shadow-lg rounded-xl border border-primary-300' : 'flex items-center'}` : `shadow-lg rounded-xl border border-primary-300 p-4 ${isEditing ? 'pb-14' : 'pb-5'}`} relative`, children: [w.type === 'agent' && badgeInfo && !isApplyingFilters && (jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 z-10", title: (filterStatus === null || filterStatus === void 0 ? void 0 : filterStatus.reason) || (filterStatus === null || filterStatus === void 0 ? void 0 : filterStatus.error) || '', children: jsxRuntimeExports.jsxs(Badge, { variant: badgeInfo.variant, className: "text-[10px] px-2 py-0.5 gap-1", children: [jsxRuntimeExports.jsx("span", { children: badgeInfo.icon }), jsxRuntimeExports.jsx("span", { children: badgeInfo.label })] }) })), w.type === 'agent' && isApplyingFilters && (jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 z-10", children: jsxRuntimeExports.jsxs(Badge, { variant: "secondary", className: "text-[10px] px-2 py-0.5 gap-1 animate-pulse", children: [jsxRuntimeExports.jsx(lucideReact.Loader2, { className: "w-3 h-3 animate-spin" }), jsxRuntimeExports.jsx("span", { children: "Filtering..." })] }) })), isEditing &&
|
|
42033
|
+
jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-end mb-4 relative ${(w.type === "text" || w.type === "spacer") ? "pl-4 pr-4 pt-4" : ""}`, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center drag-icon cursor-grab absolute left-1/2 -translate-x-1/2", children: [jsxRuntimeExports.jsx(lucideReact.GripHorizontal, { className: "" }), jsxRuntimeExports.jsx(lucideReact.GripHorizontal, { className: "-ml-[3px]" }), jsxRuntimeExports.jsx(lucideReact.GripHorizontal, { className: "-ml-[3px]" })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 cursor-pointer justify-end", children: [jsxRuntimeExports.jsx(lucideReact.Trash2, { onClick: () => removeWidget(w.id), className: "w-5 h-5 text-red-700" }), (w.type !== "spacer" && w.type !== "chatbot") && jsxRuntimeExports.jsx(lucideReact.Edit, { onClick: () => onClickSettings && onClickSettings(w), className: "w-5 h-5 text-gray-600" })] })] }), jsxRuntimeExports.jsxs("div", { className: `${((w === null || w === void 0 ? void 0 : w.type) === 'text' || (w === null || w === void 0 ? void 0 : w.type) === 'spacer') ? `${isEditing ? 'px-4' : ''}` : "h-full"} w-full relative`, children: [(w === null || w === void 0 ? void 0 : w.type) === "chatbot" &&
|
|
41873
42034
|
jsxRuntimeExports.jsxs("div", { className: "relative z-50", children: [jsxRuntimeExports.jsx("div", { onClick: () => handleClearChat(w === null || w === void 0 ? void 0 : w.id), onMouseOver: () => setVisibleClearButton(w === null || w === void 0 ? void 0 : w.id), onMouseLeave: () => setVisibleClearButton(""), className: "absolute top-[12px] right-0 z-40 flex align-middle justify-center gap-2 text-sm px-4 py-2 border-primary-300 rounded-l-sm w-fit bg-primary-700 text-white cursor-pointer shadow-md transition-all", children: jsxRuntimeExports.jsx(lucideReact.MessageCircleX, { className: "w-5 h-5" }) }), jsxRuntimeExports.jsx("span", { className: `absolute top-[56px] right-[16px] z-50 w-max py-1 text-xs px-2 rounded-sm text-white bg-gray-950 ${visibleClearButton === (w === null || w === void 0 ? void 0 : w.id) ? "block" : "hidden"}`, children: "Clear Chat" })] }), jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl: widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter(widget => widget.type !== 'chatbot').map(widget => widget.id), datasetId: datasetId, pageId: pageId, onApplyFilters: onApplyFilters, isEditing: isEditing })] })] }, w.id));
|
|
41874
42035
|
}) })) })] }));
|
|
41875
42036
|
}
|
|
@@ -44767,7 +44928,6 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
44767
44928
|
const [pages, setPages] = React.useState([]);
|
|
44768
44929
|
const [isLoading, setIsLoading] = React.useState(true);
|
|
44769
44930
|
const [error, setError] = React.useState(null);
|
|
44770
|
-
const [activeFilters, setActiveFilters] = React.useState({});
|
|
44771
44931
|
// Helper function to get API URL
|
|
44772
44932
|
const getApiUrl = (endpoint) => {
|
|
44773
44933
|
const baseUrl = widgetBackendUrl || '';
|
|
@@ -44776,10 +44936,6 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
44776
44936
|
React.useEffect(() => {
|
|
44777
44937
|
loadPages();
|
|
44778
44938
|
}, []);
|
|
44779
|
-
const handleApplyFilters = (pageId) => (filters) => {
|
|
44780
|
-
console.log('Filters applied for page:', pageId, filters);
|
|
44781
|
-
setActiveFilters(prev => (Object.assign(Object.assign({}, prev), { [pageId]: filters })));
|
|
44782
|
-
};
|
|
44783
44939
|
const loadPages = async () => {
|
|
44784
44940
|
try {
|
|
44785
44941
|
setIsLoading(true);
|
|
@@ -44824,7 +44980,7 @@ function DashboardPages({ widgetBackendUrl }) {
|
|
|
44824
44980
|
}
|
|
44825
44981
|
return (jsxRuntimeExports.jsxs("div", { className: "container mx-auto p-6 h-screen flex flex-col", children: [jsxRuntimeExports.jsxs("div", { className: "mb-6", children: [jsxRuntimeExports.jsx("h1", { className: "text-2xl font-bold", children: "Dashboard Pages" }), jsxRuntimeExports.jsx("p", { className: "text-muted-foreground", children: "View all your saved pages in dashboard mode" })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: jsxRuntimeExports.jsxs(Tabs, { defaultValue: (_a = pages[0]) === null || _a === void 0 ? void 0 : _a.id, className: "h-full flex flex-col", children: [jsxRuntimeExports.jsx(TabsList, { className: "grid w-full grid-cols-auto gap-1 mb-4", style: {
|
|
44826
44982
|
gridTemplateColumns: `repeat(${pages.length}, minmax(120px, 1fr))`
|
|
44827
|
-
}, children: pages.map((page) => (jsxRuntimeExports.jsx(TabsTrigger, { value: page.id, className: "truncate px-3 py-2 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-lg border-2 data-[state=active]:border-primary data-[state=inactive]:border-transparent hover:bg-accent hover:text-accent-foreground transition-all duration-200", title: page.title, children: page.title }, page.id))) }), pages.map((page) => (jsxRuntimeExports.jsx(TabsContent, { value: page.id, className: "flex-1 overflow-hidden m-0", children: jsxRuntimeExports.jsx("div", { className: "h-full border rounded-lg overflow-hidden", children: jsxRuntimeExports.jsx(WidgetDashboard, { pageId: page.id, isEditing: false, widgetBackendUrl: widgetBackendUrl
|
|
44983
|
+
}, children: pages.map((page) => (jsxRuntimeExports.jsx(TabsTrigger, { value: page.id, className: "truncate px-3 py-2 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-lg border-2 data-[state=active]:border-primary data-[state=inactive]:border-transparent hover:bg-accent hover:text-accent-foreground transition-all duration-200", title: page.title, children: page.title }, page.id))) }), pages.map((page) => (jsxRuntimeExports.jsx(TabsContent, { value: page.id, className: "flex-1 overflow-hidden m-0", children: jsxRuntimeExports.jsx("div", { className: "h-full border rounded-lg overflow-hidden", children: jsxRuntimeExports.jsx(WidgetDashboard, { pageId: page.id, isEditing: false, widgetBackendUrl: widgetBackendUrl }) }) }, page.id)))] }) })] }));
|
|
44828
44984
|
}
|
|
44829
44985
|
|
|
44830
44986
|
exports.Button = Button;
|