update chats controller

This commit is contained in:
Nate Kelley 2025-03-20 17:03:46 -06:00
parent 5d632413ec
commit c1ddd37ace
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
20 changed files with 145 additions and 36 deletions

32
web/package-lock.json generated
View File

@ -77,7 +77,8 @@
"ts-jest": "^29.2.6", "ts-jest": "^29.2.6",
"use-context-selector": "^2.0.0", "use-context-selector": "^2.0.0",
"utility-types": "^3.11.0", "utility-types": "^3.11.0",
"virtua": "^0.40.3" "virtua": "^0.40.3",
"zustand": "^5.0.3"
}, },
"devDependencies": { "devDependencies": {
"@chromatic-com/storybook": "^3.2.6", "@chromatic-com/storybook": "^3.2.6",
@ -21661,6 +21662,35 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/zustand": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz",
"integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
},
"peerDependencies": {
"@types/react": ">=18.0.0",
"immer": ">=9.0.6",
"react": ">=18.0.0",
"use-sync-external-store": ">=1.2.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"immer": {
"optional": true
},
"react": {
"optional": true
},
"use-sync-external-store": {
"optional": true
}
}
},
"node_modules/zwitch": { "node_modules/zwitch": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",

View File

@ -85,7 +85,8 @@
"ts-jest": "^29.2.6", "ts-jest": "^29.2.6",
"use-context-selector": "^2.0.0", "use-context-selector": "^2.0.0",
"utility-types": "^3.11.0", "utility-types": "^3.11.0",
"virtua": "^0.40.3" "virtua": "^0.40.3",
"zustand": "^5.0.3"
}, },
"devDependencies": { "devDependencies": {
"@chromatic-com/storybook": "^3.2.6", "@chromatic-com/storybook": "^3.2.6",

View File

@ -0,0 +1,86 @@
import { useGetMetricsList } from '@/api/buster_rest/metrics';
import { AppModal } from '@/components/ui/modal';
import { useDebounceSearch } from '@/hooks';
import React, { useState } from 'react';
import { BusterList } from '@/components/ui/list';
import { Input } from '@/components/ui/inputs';
export const AddToDashboardModal: React.FC<{
open: boolean;
onClose: () => void;
dashboardId: string;
}> = React.memo(({ open, onClose, dashboardId }) => {
const { data: metrics, isFetched: isFetchedMetrics } = useGetMetricsList({});
const [selectedMetrics, setSelectedMetrics] = useState<string[]>([]);
const { filteredItems, handleSearchChange } = useDebounceSearch({
items: metrics || [],
searchPredicate: (item, searchText) => {
return item.title.toLowerCase().includes(searchText.toLowerCase());
}
});
const columns = [
{
title: 'Metric',
dataIndex: 'title',
width: 300
}
];
const rows = filteredItems.map((metric) => ({
id: metric.id,
data: {
title: metric.title
}
}));
const handleAddMetrics = async () => {
// TODO: Implement the API call to add metrics to dashboard
console.log('Adding metrics:', selectedMetrics);
onClose();
};
return (
<AppModal
open={open}
onClose={onClose}
header={{
title: 'Add Metrics to Dashboard',
description: 'Select metrics to add to your dashboard'
}}
footer={{
primaryButton: {
text: 'Add Selected Metrics',
onClick: handleAddMetrics,
disabled: selectedMetrics.length === 0
},
secondaryButton: {
text: 'Cancel',
onClick: onClose
}
}}>
<div className="flex flex-col gap-4">
<Input
placeholder="Search metrics..."
onChange={(e) => handleSearchChange(e.target.value)}
/>
<div className="h-[400px]">
<BusterList
columns={columns}
rows={rows}
selectedRowKeys={selectedMetrics}
onSelectChange={setSelectedMetrics}
emptyState={
!isFetchedMetrics
? 'Loading metrics...'
: filteredItems.length === 0
? 'No metrics found'
: undefined
}
/>
</div>
</div>
</AppModal>
);
});

View File

@ -4,10 +4,10 @@ import { SupabaseContextProvider } from './Supabase/SupabaseContextProvider';
import { UseSupabaseContextType } from './Supabase/getSupabaseServerContext'; import { UseSupabaseContextType } from './Supabase/getSupabaseServerContext';
import { BusterReactQueryProvider } from './BusterReactQuery/BusterReactQueryAndApi'; import { BusterReactQueryProvider } from './BusterReactQuery/BusterReactQueryAndApi';
import { AppLayoutProvider } from './BusterAppLayout'; import { AppLayoutProvider } from './BusterAppLayout';
import { BusterUserConfigProvider } from './Users/UserConfigProvider'; import { BusterUserConfigProvider } from './Users/BusterUserConfigProvider';
import { BusterAssetsProvider } from './Assets/BusterAssetsProvider'; import { BusterAssetsProvider } from './Assets/BusterAssetsProvider';
import { BusterPosthogProvider } from './Posthog'; import { BusterPosthogProvider } from './Posthog';
import { BusterChatProvider } from './Chats'; import { BusterNewChatProvider } from './Chats';
import { RoutePrefetcher } from './RoutePrefetcher'; import { RoutePrefetcher } from './RoutePrefetcher';
import type { BusterUserResponse } from '@/api/asset_interfaces'; import type { BusterUserResponse } from '@/api/asset_interfaces';
@ -30,12 +30,12 @@ export const AppProviders: React.FC<
<AppLayoutProvider> <AppLayoutProvider>
<BusterUserConfigProvider userInfo={userInfo}> <BusterUserConfigProvider userInfo={userInfo}>
<BusterAssetsProvider> <BusterAssetsProvider>
<BusterChatProvider> <BusterNewChatProvider>
<BusterPosthogProvider> <BusterPosthogProvider>
{children} {children}
<RoutePrefetcher /> <RoutePrefetcher />
</BusterPosthogProvider> </BusterPosthogProvider>
</BusterChatProvider> </BusterNewChatProvider>
</BusterAssetsProvider> </BusterAssetsProvider>
</BusterUserConfigProvider> </BusterUserConfigProvider>
</AppLayoutProvider> </AppLayoutProvider>

View File

@ -57,8 +57,7 @@ export const useAppLayout = () => {
currentRoute, currentRoute,
onToggleInviteModal, onToggleInviteModal,
openInviteModal, openInviteModal,
onChangePage, onChangePage
pathname
}; };
}; };

View File

@ -1,8 +0,0 @@
import React from 'react';
import { BusterNewChatProvider } from './NewChatProvider';
export const BusterChatProvider = React.memo(({ children }: { children: React.ReactNode }) => {
return <BusterNewChatProvider>{children}</BusterNewChatProvider>;
});
BusterChatProvider.displayName = 'ChatProvider';

View File

@ -1 +0,0 @@
export * from './NewChatProvider';

View File

@ -1,5 +1 @@
import { useBusterNewChatContextSelector } from './NewChatProvider'; export * from './NewChatProvider';
export * from './BusterChatProvider';
export { useBusterNewChatContextSelector };

View File

@ -0,0 +1 @@
export * from './useDashboardContentStore';

View File

@ -0,0 +1,11 @@
import { create } from 'zustand';
export const useDashboardContentStore = create<{
openAddContentModal: boolean;
onCloseAddContentModal: () => void;
onOpenAddContentModal: () => void;
}>((set) => ({
openAddContentModal: false,
onCloseAddContentModal: () => set({ openAddContentModal: false }),
onOpenAddContentModal: () => set({ openAddContentModal: true })
}));

View File

@ -1 +1 @@
export * from './UserConfigProvider'; export * from './BusterUserConfigProvider';

View File

@ -1,21 +1,17 @@
'use client'; 'use client';
import React, { useState } from 'react'; import React from 'react';
import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader'; import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader';
import { DashboardFileView, useChatLayoutContextSelector } from '@/layouts/ChatLayout'; import { DashboardFileView, useChatLayoutContextSelector } from '@/layouts/ChatLayout';
import { DashboardViewComponents } from './config'; import { DashboardViewComponents } from './config';
import { AddTypeModal } from '@/components/features/modal/AddTypeModal'; import { AddTypeModal } from '@/components/features/modal/AddTypeModal';
import { useMemoizedFn } from '@/hooks';
import { useGetDashboard } from '@/api/buster_rest/dashboards'; import { useGetDashboard } from '@/api/buster_rest/dashboards';
import { useDashboardContentStore } from '@/context/Dashboards';
export const DashboardController: React.FC<{ dashboardId: string }> = ({ dashboardId }) => { export const DashboardController: React.FC<{ dashboardId: string }> = ({ dashboardId }) => {
const { data: dashboardResponse, isFetched: isFetchedDashboard } = useGetDashboard(dashboardId); const { data: dashboardResponse, isFetched: isFetchedDashboard } = useGetDashboard(dashboardId);
const selectedFileView = useChatLayoutContextSelector((x) => x.selectedFileView) || 'dashboard'; const selectedFileView = useChatLayoutContextSelector((x) => x.selectedFileView) || 'dashboard';
const [openAddTypeModal, setOpenAddTypeModal] = useState(false); const { openAddContentModal, onCloseAddContentModal } = useDashboardContentStore();
const onCloseModal = useMemoizedFn(() => {
setOpenAddTypeModal(false);
});
const Component = const Component =
selectedFileView && isFetchedDashboard selectedFileView && isFetchedDashboard
@ -28,8 +24,8 @@ export const DashboardController: React.FC<{ dashboardId: string }> = ({ dashboa
<Component dashboardId={dashboardId} /> <Component dashboardId={dashboardId} />
<AddTypeModal <AddTypeModal
open={openAddTypeModal} open={openAddContentModal}
onClose={onCloseModal} onClose={onCloseAddContentModal}
type="dashboard" type="dashboard"
dashboardResponse={dashboardResponse} dashboardResponse={dashboardResponse}
/> />

View File

@ -10,6 +10,7 @@ import {
useUpdateDashboard, useUpdateDashboard,
useUpdateDashboardConfig useUpdateDashboardConfig
} from '@/api/buster_rest/dashboards'; } from '@/api/buster_rest/dashboards';
import { useDashboardContentStore } from '@/context/Dashboards';
export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({ export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({
dashboardId, dashboardId,
@ -18,10 +19,7 @@ export const DashboardViewDashboardController: React.FC<DashboardViewProps> = ({
const { data: dashboardResponse } = useGetDashboard(dashboardId); const { data: dashboardResponse } = useGetDashboard(dashboardId);
const { mutateAsync: onUpdateDashboard } = useUpdateDashboard(); const { mutateAsync: onUpdateDashboard } = useUpdateDashboard();
const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig(); const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig();
const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal);
const onOpenAddContentModal = useMemoizedFn(() => {
console.log('open add content modal');
});
const metrics = dashboardResponse?.metrics; const metrics = dashboardResponse?.metrics;
const dashboard = dashboardResponse?.dashboard; const dashboard = dashboardResponse?.dashboard;