// CHAKRA COMPONENTS
import {
Button,
Stack,
Flex,
Field,
NativeSelect,
Input,
HoverCard,
Text,
NumberInput,
Box,
useSlotRecipe,
Combobox,
Portal,
useFilter,
useListCollection
} from "@chakra-ui/react";
// ICONS
import {
Plus,
CircleMinus,
Files,
ClipboardPaste,
Trash
} from 'lucide-react';
// OTHER
import { useState } from 'react';
import useDataFilterStore from '../../store/useDataFilterStore.jsx';
// ============================================================================
// 1. MAIN QUERY BUILDER (The Engine Wrapper)
// ============================================================================
export default function MyQueryBuilder({ url, setUrl, allColumns, getColumns, pullTable, isLoading, isReadyRef }) {
// STYLING
const dataExplorerRecipe = useSlotRecipe({ key: "dataExplorer" });
const dataExplorerStyle = dataExplorerRecipe();
// THE SELECT DROPDOWN MENU
const { contains } = useFilter({ sensitivity: "base" })
const { collection, filter } = useListCollection({
initialItems: tables,
filter: contains,
})
// STATE MANAGEMENT
const [value, setValue] = useState([]);
const addNewGroup = useDataFilterStore(state => state.addNewGroup);
const filterGroups = useDataFilterStore(state => state.filterGroups);
console.log("filter groups", filterGroups);
return (
{/* Top Controls: Source & Execute */}
filter(e.inputValue)}
value={value}
onValueChange={(e) => {
setValue(e.value);
const selectedView = e.value;
setUrl(prev => ({ ...prev, source: selectedView }));
// need to get all columns as default in param building
const endpoint = "/api/v3/view_dash_event_search_columns";
getColumns(endpoint);
}}
width="320px"
>
Select Table
No items found
{collection.items.map((item) => (
{item.label}
))}
{/* Filter Builder Engine */}
{url.source && allColumns?.types && (
Filters
{filterGroups.map((group) => (
))}
)}
);
}
// LIST OF TABLES USER CAN EXPLORE
const tables = [
{ label: "Events Table", value: "ViewDashEventSearch" },
];
// ============================================================================
// 2. FILTERS GROUPS (The AND logic groups)
// ============================================================================
function FilterGroup({ groupID, filters, columns }) {
const removeGroup = useDataFilterStore(state => state.removeGroup);
const addFilter = useDataFilterStore(state => state.addFilter);
console.log("in filter group. GroupID: ", groupID, "filters: ", filters);
return (
{filters?.map((filter) => (
))}
);
};
// ============================================================================
// 3. FILTER ROW (The individual criteria inputs)
// ============================================================================
function FilterRow({ groupID, filterID, filter, columns }) {
// STATE MANAGEMENT
const removeFilter = useDataFilterStore(state => state.removeFilter);
const updateFilterColumn = useDataFilterStore(state => state.updateFilterColumn);
const updateFilterOp = useDataFilterStore(state => state.updateFilterOps);
const updateFilterValue = useDataFilterStore(state => state.updateFilterValue);
const copyFilter = useDataFilterStore(state => state.copyFilter);
const pasteFilter = useDataFilterStore(state => state.pasteFilter);
// CONSTANTS
const types = {
AutoField: ["=", "<", ">", "<=", ">="],
IntegerField: ["=", "<", ">", "<=", ">="],
CharField: ["=", "contains"],
DateTimeField: ["range"],
};
return (
{/* Remove button */}
Remove Filter
{/* Copy Button */}
Copy Filter
{/* paste button */}
Paste Filter
{/* Column selector */}
updateFilterColumn(groupID, filterID, e.target.value, columns[e.target.value], null, null)} // e.target.value is the new column
>
{Object.keys(columns).map((colName) => (
))}
{/* Operator selector or start date for range */}
{filter?.type === "DateTimeField" ? (
updateFilterValue(groupID, filterID, e.target.value, "s")} />
) : (
updateFilterOp(groupID, filterID, e.target.value)}>
{filter?.type && types[filter?.type].map((op) => )} {/* maps over the 'filter.type' corresponding ops from the types dictionary */}
)}
{/* Value input or end date for range */}
{filter?.type === "DateTimeField" ? (
updateFilterValue(groupID, filterID, e.target.value, "e")} />
) : filter?.type === "IntegerField" || filter?.type === "AutoField" ? (
updateFilterValue(groupID, filterID, e.value)}>
) : (
updateFilterValue(groupID, filterID, e.target.value)} />
)}
);
};