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",
"use-context-selector": "^2.0.0",
"utility-types": "^3.11.0",
"virtua": "^0.40.3"
"virtua": "^0.40.3",
"zustand": "^5.0.3"
},
"devDependencies": {
"@chromatic-com/storybook": "^3.2.6",
@ -21661,6 +21662,35 @@
"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": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",

View File

@ -85,7 +85,8 @@
"ts-jest": "^29.2.6",
"use-context-selector": "^2.0.0",
"utility-types": "^3.11.0",
"virtua": "^0.40.3"
"virtua": "^0.40.3",
"zustand": "^5.0.3"
},
"devDependencies": {
"@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 { BusterReactQueryProvider } from './BusterReactQuery/BusterReactQueryAndApi';
import { AppLayoutProvider } from './BusterAppLayout';
import { BusterUserConfigProvider } from './Users/UserConfigProvider';
import { BusterUserConfigProvider } from './Users/BusterUserConfigProvider';
import { BusterAssetsProvider } from './Assets/BusterAssetsProvider';
import { BusterPosthogProvider } from './Posthog';
import { BusterChatProvider } from './Chats';
import { BusterNewChatProvider } from './Chats';
import { RoutePrefetcher } from './RoutePrefetcher';
import type { BusterUserResponse } from '@/api/asset_interfaces';
@ -30,12 +30,12 @@ export const AppProviders: React.FC<
<AppLayoutProvider>
<BusterUserConfigProvider userInfo={userInfo}>
<BusterAssetsProvider>
<BusterChatProvider>
<BusterNewChatProvider>
<BusterPosthogProvider>
{children}
<RoutePrefetcher />
</BusterPosthogProvider>
</BusterChatProvider>
</BusterNewChatProvider>
</BusterAssetsProvider>
</BusterUserConfigProvider>
</AppLayoutProvider>

View File

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

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 './BusterChatProvider';
export { useBusterNewChatContextSelector };
export * from './NewChatProvider';

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

View File

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