refactor: now using MyQueryBuilder (temp name) in Data Explorer pg as it implements zustand state management to aid the transition from retriggering an api call on every new filter added
This commit is contained in:
@@ -1,8 +1,24 @@
|
||||
import React, { useRef } from "react";
|
||||
import { Button, Stack, Flex, Field, NativeSelect, Input, HoverCard, Text, NumberInput, Box } from "@chakra-ui/react";
|
||||
import {
|
||||
Button,
|
||||
Stack,
|
||||
Flex,
|
||||
Field,
|
||||
NativeSelect,
|
||||
Input,
|
||||
HoverCard,
|
||||
Text,
|
||||
NumberInput,
|
||||
Box,
|
||||
useSlotRecipe,
|
||||
Combobox,
|
||||
Portal,
|
||||
useFilter,
|
||||
useListCollection
|
||||
} from "@chakra-ui/react";
|
||||
import { Plus, CircleMinus, Files, ClipboardPaste, Trash } from 'lucide-react';
|
||||
// import { GrAdd, GrSubtractCircle } from "react-icons/gr";
|
||||
// import { FaCopy, FaPaste, FaTrash } from "react-icons/fa";
|
||||
import { useState } from 'react';
|
||||
import useDataFilterStore from '../../store/useDataFilterStore.jsx';
|
||||
|
||||
// ============================================================================
|
||||
// 1. FILTER ROW (The individual criteria inputs)
|
||||
@@ -80,7 +96,7 @@ const FilterRow = React.memo(({ filter, columns, setUrl, bundleId, copiedFilter
|
||||
</Button>
|
||||
</HoverCard.Trigger>
|
||||
<HoverCard.Positioner>
|
||||
<HoverCard.Content p="2" bg="widgetItemExpandedBg"><Text fontSize="sm">Remove Filter</Text></HoverCard.Content>
|
||||
<HoverCard.Content p="2" bg="white"><Text fontSize="sm">Remove Filter</Text></HoverCard.Content>
|
||||
</HoverCard.Positioner>
|
||||
</HoverCard.Root>
|
||||
|
||||
@@ -92,7 +108,7 @@ const FilterRow = React.memo(({ filter, columns, setUrl, bundleId, copiedFilter
|
||||
</Button>
|
||||
</HoverCard.Trigger>
|
||||
<HoverCard.Positioner>
|
||||
<HoverCard.Content p="2" bg="widgetItemExpandedBg"><Text fontSize="sm">Copy Filter</Text></HoverCard.Content>
|
||||
<HoverCard.Content p="2" bg="white"><Text fontSize="sm">Copy Filter</Text></HoverCard.Content>
|
||||
</HoverCard.Positioner>
|
||||
</HoverCard.Root>
|
||||
|
||||
@@ -124,7 +140,7 @@ const FilterRow = React.memo(({ filter, columns, setUrl, bundleId, copiedFilter
|
||||
</Button>
|
||||
</HoverCard.Trigger>
|
||||
<HoverCard.Positioner>
|
||||
<HoverCard.Content p="2" bg="widgetItemExpandedBg"><Text fontSize="sm">Paste Filter</Text></HoverCard.Content>
|
||||
<HoverCard.Content p="2" bg="white"><Text fontSize="sm">Paste Filter</Text></HoverCard.Content>
|
||||
</HoverCard.Positioner>
|
||||
</HoverCard.Root>
|
||||
|
||||
@@ -207,6 +223,8 @@ const FilterBundle = ({ bundle, columns, url, setUrl, copiedFilter }) => {
|
||||
}) : (b)
|
||||
),
|
||||
}));
|
||||
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -234,8 +252,25 @@ const FilterBundle = ({ bundle, columns, url, setUrl, copiedFilter }) => {
|
||||
// 3. MAIN QUERY BUILDER (The Engine Wrapper)
|
||||
// ============================================================================
|
||||
export default function QueryBuilder({ url, setUrl, allColumns, getColumns, pullTable, isLoading, isReadyRef }) {
|
||||
const copiedFilter = useRef(null);
|
||||
// STYLING
|
||||
const dataExplorerRecipe = useSlotRecipe({ key: "dataExplorer" });
|
||||
const dataExplorerStyle = dataExplorerRecipe();
|
||||
|
||||
// SELECT DROPDOWN MENU
|
||||
const { contains } = useFilter({ sensitivity: "base" })
|
||||
|
||||
const { collection, filter } = useListCollection({
|
||||
initialItems: tables,
|
||||
filter: contains,
|
||||
})
|
||||
|
||||
// STATE MANAGEMENT
|
||||
const copiedFilter = useRef(null);
|
||||
const [value, setValue] = useState([]);
|
||||
const addNewGroup = useDataFilterStore(state => state.addNewGroup);
|
||||
const filterGroups = useDataFilterStore(state => state.filterGroups);
|
||||
|
||||
// FUNCTIONS
|
||||
const handleAddBundle = () => {
|
||||
setUrl(prev => ({
|
||||
...prev,
|
||||
@@ -253,39 +288,56 @@ export default function QueryBuilder({ url, setUrl, allColumns, getColumns, pull
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
// adding zustand state management as a test here
|
||||
addNewGroup();
|
||||
};
|
||||
|
||||
console.log("filter groups", filterGroups);
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="4" w="100%" p="4" bg="transparent">
|
||||
<Flex direction="column" gap={2} w="100%" bg="transparent" css={dataExplorerStyle.query_builder}>
|
||||
{/* Top Controls: Source & Execute */}
|
||||
<Flex gap="4" align="flex-end">
|
||||
<Field.Root maxW="300px">
|
||||
<Field.Label color="text">Data Source</Field.Label>
|
||||
<NativeSelect.Root>
|
||||
<NativeSelect.Field
|
||||
bg="widgetItemBg"
|
||||
color="text"
|
||||
value={url.source || ""}
|
||||
onChange={(e) => {
|
||||
const selectedView = e.target.value;
|
||||
setUrl(prev => ({ ...prev, source: selectedView }));
|
||||
// 🚨 FIXED: Now uses relative pathing for the production API
|
||||
const endpoint = "/api/v3/view_dash_event_search_columns";
|
||||
getColumns(endpoint);
|
||||
}}
|
||||
>
|
||||
<option value="" disabled hidden>Select View</option>
|
||||
<option value="main">Main View</option>
|
||||
{/*<option value="test">Test View</option>*/}
|
||||
</NativeSelect.Field>
|
||||
<NativeSelect.Indicator />
|
||||
</NativeSelect.Root>
|
||||
</Field.Root>
|
||||
<Flex gap={2} align="flex-end">
|
||||
<Combobox.Root
|
||||
collection={collection}
|
||||
onInputValueChange={(e) => 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"
|
||||
>
|
||||
<Combobox.Label>Select Table</Combobox.Label>
|
||||
<Combobox.Control>
|
||||
<Combobox.Input placeholder="Type to search" />
|
||||
<Combobox.IndicatorGroup>
|
||||
<Combobox.ClearTrigger />
|
||||
<Combobox.Trigger />
|
||||
</Combobox.IndicatorGroup>
|
||||
</Combobox.Control>
|
||||
<Portal>
|
||||
<Combobox.Positioner>
|
||||
<Combobox.Content>
|
||||
<Combobox.Empty>No items found</Combobox.Empty>
|
||||
{collection.items.map((item) => (
|
||||
<Combobox.Item item={item} key={item.value}>
|
||||
{item.label}
|
||||
<Combobox.ItemIndicator />
|
||||
</Combobox.Item>
|
||||
))}
|
||||
</Combobox.Content>
|
||||
</Combobox.Positioner>
|
||||
</Portal>
|
||||
</Combobox.Root>
|
||||
{/*</Field.Root>*/}
|
||||
|
||||
<Button
|
||||
bg="blue.600"
|
||||
color="white"
|
||||
_hover={{ bg: "blue.500" }}
|
||||
loading={isLoading}
|
||||
onClick={() => {
|
||||
isReadyRef.current = true;
|
||||
@@ -298,11 +350,11 @@ export default function QueryBuilder({ url, setUrl, allColumns, getColumns, pull
|
||||
|
||||
{/* Filter Builder Engine */}
|
||||
{url.source && allColumns?.types && (
|
||||
<Stack w="100%" gap="4">
|
||||
<Text fontSize="lg" fontWeight="bold" color="text">Filters</Text>
|
||||
<Stack w="100%" gap="2">
|
||||
<Text fontSize="sm" fontWeight="bold" color="text">Filters</Text>
|
||||
|
||||
<Box w="100%" maxH="400px" overflow="auto">
|
||||
<Stack w="100%" gap="4" pr="4">
|
||||
<Stack w="100%" gap="2" pr="4">
|
||||
{url.bundles.map((bundle) => (
|
||||
<FilterBundle key={bundle.id} bundle={bundle} columns={allColumns.types} url={url} setUrl={setUrl} copiedFilter={copiedFilter} />
|
||||
))}
|
||||
@@ -315,4 +367,9 @@ export default function QueryBuilder({ url, setUrl, allColumns, getColumns, pull
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// LIST OF TABLES USER CAN EXPLORE
|
||||
const tables = [
|
||||
{ label: "Events Table", value: "ViewDashEventSearch" },
|
||||
]
|
||||
Reference in New Issue
Block a user