mirror of https://github.com/buster-so/buster.git
update some grid layout stuff
This commit is contained in:
parent
8c43ca0403
commit
f7b8d87c01
|
@ -62,7 +62,7 @@
|
|||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"react": "^18",
|
||||
"react-color": "^2.19.3",
|
||||
"react-data-grid": "^7.0.0-beta.48",
|
||||
"react-data-grid": "^7.0.0-beta.47",
|
||||
"react-day-picker": "^9.6.1",
|
||||
"react-dom": "^18",
|
||||
"react-hotkeys-hook": "^4.6.1",
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"react": "^18",
|
||||
"react-color": "^2.19.3",
|
||||
"react-data-grid": "^7.0.0-beta.48",
|
||||
"react-data-grid": "^7.0.0-beta.47",
|
||||
"react-day-picker": "^9.6.1",
|
||||
"react-dom": "^18",
|
||||
"react-hotkeys-hook": "^4.6.1",
|
||||
|
|
|
@ -14,24 +14,34 @@ import type { GetMetricParams, ListMetricsParams } from './interfaces';
|
|||
import { upgradeMetricToIMetric } from '@/lib/chat';
|
||||
import { queryKeys } from '@/api/query_keys';
|
||||
import { useMemo } from 'react';
|
||||
import { useBusterAssetsContextSelector } from '@/context/Assets/BusterAssetsProvider';
|
||||
|
||||
export const useGetMetric = (params: GetMetricParams) => {
|
||||
const queryClient = useQueryClient();
|
||||
const setAssetPasswordError = useBusterAssetsContextSelector(
|
||||
(state) => state.setAssetPasswordError
|
||||
);
|
||||
|
||||
const queryFn = useMemoizedFn(async () => {
|
||||
const result = await getMetric(params);
|
||||
return upgradeMetricToIMetric(result, null);
|
||||
const oldMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(params.id).queryKey);
|
||||
return upgradeMetricToIMetric(result, oldMetric || null);
|
||||
});
|
||||
|
||||
return useQuery({
|
||||
...queryKeys.useMetricsGetMetric(params.id),
|
||||
queryFn,
|
||||
enabled: false //this is handle via a socket query? maybe it should not be?
|
||||
...queryKeys.metricsGetMetric(params.id),
|
||||
throwOnError: (error, query) => {
|
||||
setAssetPasswordError(params.id, error.message || 'An error occurred');
|
||||
return false;
|
||||
},
|
||||
queryFn
|
||||
});
|
||||
};
|
||||
|
||||
export const prefetchGetMetric = async (params: GetMetricParams, queryClientProp?: QueryClient) => {
|
||||
const queryClient = queryClientProp || new QueryClient();
|
||||
await queryClient.prefetchQuery({
|
||||
...queryKeys.useMetricsGetMetric(params.id),
|
||||
...queryKeys.metricsGetMetric(params.id),
|
||||
queryFn: async () => {
|
||||
const result = await getMetric_server(params);
|
||||
return upgradeMetricToIMetric(result, null);
|
||||
|
|
|
@ -9,18 +9,22 @@ import type {
|
|||
|
||||
export const getMetric = async ({ id, password }: GetMetricParams) => {
|
||||
return mainApi
|
||||
.get<BusterMetric>(`/metrics/get`, {
|
||||
.get<BusterMetric>(`/metrics/${id}`, {
|
||||
params: { id, ...(password && { password }) }
|
||||
})
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const getMetric_server = async ({ id, password }: GetMetricParams) => {
|
||||
return await serverFetch<BusterMetric>(`/metrics/get`, {
|
||||
params: { id, ...(password && { password }) }
|
||||
return await serverFetch<BusterMetric>(`/metrics/${id}`, {
|
||||
params: { ...(password && { password }) }
|
||||
});
|
||||
};
|
||||
|
||||
export const getMetricData = async ({ id }: { id: string }) => {
|
||||
return mainApi.get<BusterMetricData>(`/metrics/${id}/data`).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const listMetrics = async (params: ListMetricsParams) => {
|
||||
return mainApi.get<BusterMetricListItem[]>('/metrics/list', { params }).then((res) => res.data);
|
||||
};
|
||||
|
@ -29,10 +33,6 @@ export const listMetrics_server = async (params: ListMetricsParams) => {
|
|||
return await serverFetch<BusterMetricListItem[]>('/metrics/list', { params });
|
||||
};
|
||||
|
||||
export const getMetricData = async ({ id }: { id: string }) => {
|
||||
return mainApi.get<BusterMetricData>(`/metrics/${id}/data`).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const updateMetric = async (params: UpdateMetricParams) => {
|
||||
return mainApi
|
||||
.put<BusterMetric>(`/metrics/update/${params.id}`, { params })
|
||||
|
|
|
@ -36,7 +36,7 @@ const chatsBlackBoxMessages = (messageId: string) =>
|
|||
queryOptions<string | null>({
|
||||
queryKey: ['chats', 'messages', messageId, 'black-box'] as const,
|
||||
staleTime: Infinity,
|
||||
enabled: false,
|
||||
enabled: false, //this is local
|
||||
queryFn: () => Promise.resolve(null)
|
||||
});
|
||||
|
||||
|
|
|
@ -2,32 +2,16 @@
|
|||
|
||||
import { queryOptions } from '@tanstack/react-query';
|
||||
import type {
|
||||
BusterMetricData,
|
||||
BusterMetricListItem,
|
||||
IBusterMetric,
|
||||
IBusterMetricData
|
||||
} from '@/api/asset_interfaces/metric';
|
||||
import { useBusterAssetsContextSelector } from '@/context/Assets/BusterAssetsProvider';
|
||||
import { ListMetricsParams } from '../buster_rest/metrics';
|
||||
|
||||
export const metricsGetMetric = (metricId: string) => {
|
||||
return queryOptions<IBusterMetric>({
|
||||
queryKey: ['metrics', 'get', metricId] as const,
|
||||
staleTime: 30 * 60 * 1000,
|
||||
enabled: false
|
||||
});
|
||||
};
|
||||
|
||||
export const useMetricsGetMetric = (metricId: string) => {
|
||||
const setAssetPasswordError = useBusterAssetsContextSelector(
|
||||
(state) => state.setAssetPasswordError
|
||||
);
|
||||
return queryOptions<IBusterMetric>({
|
||||
...metricsGetMetric(metricId),
|
||||
throwOnError: (error, query) => {
|
||||
setAssetPasswordError(metricId, error.message || 'An error occurred');
|
||||
return false;
|
||||
}
|
||||
staleTime: 30 * 60 * 1000
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -45,7 +29,6 @@ export const metricsGetData = (id: string) =>
|
|||
|
||||
export const metricsQueryKeys = {
|
||||
metricsGetMetric,
|
||||
useMetricsGetMetric,
|
||||
metricsGetList,
|
||||
metricsGetData
|
||||
};
|
||||
|
|
|
@ -8,9 +8,6 @@ export default async function Page(props: {
|
|||
|
||||
const { chatId, metricId } = params;
|
||||
|
||||
console.log('chatId', chatId);
|
||||
console.log('metricId', metricId);
|
||||
|
||||
return (
|
||||
<AppAssetCheckLayout metricId={metricId} type="metric">
|
||||
<MetricController metricId={metricId} />
|
||||
|
|
|
@ -13,10 +13,11 @@ export default function Page(params: { params: { chatId: string } }) {
|
|||
}
|
||||
|
||||
return (
|
||||
<StatusCard
|
||||
className="text-red-500"
|
||||
title="Error"
|
||||
message="If you are seeing this, tell Nate and screenshot this whole page including the URL and logs..."
|
||||
/>
|
||||
<div className="p-5">
|
||||
<StatusCard
|
||||
title="Error"
|
||||
message="If you are seeing this, tell Nate and screenshot this whole page including the URL and logs..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ export const NewUserController = () => {
|
|||
});
|
||||
|
||||
onChangePage({
|
||||
route: BusterRoutes.APP_METRIC
|
||||
route: BusterRoutes.APP_HOME
|
||||
});
|
||||
} catch (error) {
|
||||
//
|
||||
|
@ -81,7 +81,6 @@ export const NewUserController = () => {
|
|||
placeholder="What is your full name"
|
||||
className="w-full"
|
||||
value={name || ''}
|
||||
defaultValue={user?.name || ''}
|
||||
name="name"
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
|
|
|
@ -38,6 +38,7 @@ export const SidebarUserFooterComponent: React.FC<{
|
|||
email: string;
|
||||
signOut: () => Promise<{ error: string }>;
|
||||
}> = React.memo(({ name, avatarUrl, email, signOut }) => {
|
||||
if (!name || !email) return null;
|
||||
return (
|
||||
<SidebarUserDropdown signOut={signOut}>
|
||||
<div className="flex w-full">
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { AppDataGrid } from './AppDataGrid';
|
||||
|
||||
const meta: Meta<typeof AppDataGrid> = {
|
||||
title: 'UI/table/AppDataGrid',
|
||||
component: AppDataGrid,
|
||||
parameters: {
|
||||
layout: 'centered'
|
||||
},
|
||||
tags: ['autodocs']
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof AppDataGrid>;
|
||||
|
||||
const sampleData = [
|
||||
{ id: 1, name: 'John Doe', age: 30, email: 'john@example.com', joinDate: new Date('2023-01-15') },
|
||||
{
|
||||
id: 2,
|
||||
name: 'Jane Smith',
|
||||
age: 25,
|
||||
email: 'jane@example.com',
|
||||
joinDate: new Date('2023-02-20')
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Bob Johnson',
|
||||
age: 35,
|
||||
email: 'bob@example.com',
|
||||
joinDate: new Date('2023-03-10')
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Alice Brown',
|
||||
age: 28,
|
||||
email: 'alice@example.com',
|
||||
joinDate: new Date('2023-04-05')
|
||||
}
|
||||
];
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
animate: true,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
export const NonResizable: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
resizable: false,
|
||||
draggable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
export const NonDraggable: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
resizable: true,
|
||||
draggable: false,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
export const NonSortable: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
sortable: false
|
||||
}
|
||||
};
|
||||
|
||||
export const CustomColumnOrder: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
columnOrder: ['name', 'email', 'age', 'id', 'joinDate'],
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
export const CustomFormatting: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
headerFormat: (value, columnName) => columnName.toUpperCase(),
|
||||
cellFormat: (value, columnName) => {
|
||||
if (columnName === 'joinDate' && value instanceof Date) {
|
||||
return value.toLocaleDateString();
|
||||
}
|
||||
return String(value);
|
||||
},
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
export const WithInitialWidth: Story = {
|
||||
args: {
|
||||
rows: sampleData,
|
||||
initialWidth: 800,
|
||||
resizable: true,
|
||||
draggable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
|
@ -35,7 +35,6 @@ import {
|
|||
defaultHeaderFormat,
|
||||
MIN_WIDTH
|
||||
} from './helpers';
|
||||
import styles from './AppDataGrid.module.css';
|
||||
|
||||
type Row = Record<string, string | number | null | Date>;
|
||||
|
||||
|
@ -339,6 +338,19 @@ export const AppDataGrid: React.FC<AppDataGridProps> = React.memo(
|
|||
});
|
||||
});
|
||||
|
||||
const columnsX = [
|
||||
{ key: 'id', name: 'ID' },
|
||||
{ key: 'title', name: 'Title' }
|
||||
];
|
||||
|
||||
const rowsX = [
|
||||
{ id: 0, title: 'Example' },
|
||||
{ id: 1, title: 'Demo' }
|
||||
];
|
||||
|
||||
console.log('columnsX', columnsX);
|
||||
console.log('rowsX', rowsX);
|
||||
|
||||
return (
|
||||
<React.Fragment key={forceRenderId}>
|
||||
<ErrorBoundary onError={handleErrorBoundary}>
|
||||
|
@ -348,7 +360,9 @@ export const AppDataGrid: React.FC<AppDataGridProps> = React.memo(
|
|||
style={{
|
||||
transition: animate ? 'opacity 0.25s' : undefined
|
||||
}}>
|
||||
<DataGrid
|
||||
<DataGrid columns={columnsX} rows={rowsX} />
|
||||
|
||||
{/* <DataGrid
|
||||
className={styles.dataGrid}
|
||||
columns={reorderedColumns}
|
||||
rows={sortedRows}
|
||||
|
@ -363,7 +377,7 @@ export const AppDataGrid: React.FC<AppDataGridProps> = React.memo(
|
|||
onColumnsReorder={onColumnsReorder}
|
||||
defaultColumnOptions={DEFAULT_COLUMN_WIDTH}
|
||||
direction={'ltr'}
|
||||
/>
|
||||
/> */}
|
||||
<div style={{ width: '100%' }}></div>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
|
|
|
@ -20,7 +20,7 @@ export const AppNoPageAccess: React.FC<{
|
|||
<div className="flex h-[85vh] w-full flex-col items-center justify-center space-y-6">
|
||||
<BusterLogo className="h-16 w-16" />
|
||||
|
||||
<div className="max-w-[340px] text-center">
|
||||
<div className="max-w-[440px] text-center">
|
||||
<Title
|
||||
as="h2"
|
||||
className="text-center">{`It looks like you don’t have access to this file...`}</Title>
|
||||
|
|
|
@ -63,7 +63,7 @@ const AppPasswordInputComponent: React.FC<{
|
|||
style={{
|
||||
marginTop: '25vh'
|
||||
}}>
|
||||
<div className="flex max-w-[340px] flex-col items-center space-y-6">
|
||||
<div className="flex max-w-[440px] flex-col items-center space-y-6">
|
||||
<BusterLogo className="h-16 w-16" />
|
||||
|
||||
<div className="text-center">
|
||||
|
|
|
@ -53,7 +53,7 @@ export const MetricTitle: React.FC<{
|
|||
<Title
|
||||
{...titleConfig}
|
||||
as="h4"
|
||||
className="text-md! max-w-[calc(100%_-_22px)]"
|
||||
className="text-md! max-w-[calc(100%_-_22px)] whitespace-nowrap"
|
||||
style={{ fontSize: '14px' }}>
|
||||
{`${title}`}
|
||||
</Title>
|
||||
|
@ -96,11 +96,7 @@ const ThreeDotPlaceholder: React.FC<{
|
|||
}> = React.memo(({ className }) => {
|
||||
return (
|
||||
<div className={`relative h-[24px] w-[24px] ${className}`}>
|
||||
{/* <Button
|
||||
className="absolute top-[-2px] hidden"
|
||||
type="text"
|
||||
icon={<AppMaterialIcons icon="more_vert" />}
|
||||
/> */}
|
||||
<Button variant="link" prefix={<DotsVertical />} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ export const MetricViewChartHeader: React.FC<{
|
|||
<EditableTitle level={4} className="mb-0" inputClassName="text-md!" onChange={onSetTitle}>
|
||||
{title}
|
||||
</EditableTitle>
|
||||
<div className="flex items-center space-x-1">
|
||||
<div className="flex items-center space-x-1 whitespace-nowrap">
|
||||
{!!timeFrame && (
|
||||
<>
|
||||
<Text size={'sm'} variant="secondary">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import { createContext, useContextSelector } from 'use-context-selector';
|
||||
import React, { PropsWithChildren, useTransition } from 'react';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import type { AppSplitterRef } from '@/components/ui/layouts';
|
||||
import { DEFAULT_CHAT_OPTION_SIDEBAR_SIZE } from './config';
|
||||
|
@ -38,9 +38,7 @@ export const useChatLayout = ({ appSplitterRef }: UseChatSplitterProps) => {
|
|||
renderViewLayoutKey
|
||||
} = useSelectedFileAndLayout({ animateOpenSplitter });
|
||||
|
||||
const { collapseDirection, isCollapseOpen, onCollapseFileClick } = useLayoutCollapse({
|
||||
selectedFile,
|
||||
selectedLayout,
|
||||
const { onCollapseFileClick } = useLayoutCollapse({
|
||||
animateOpenSplitter
|
||||
});
|
||||
|
||||
|
@ -56,8 +54,6 @@ export const useChatLayout = ({ appSplitterRef }: UseChatSplitterProps) => {
|
|||
renderViewLayoutKey,
|
||||
selectedFileType: selectedFile?.type,
|
||||
selectedFile,
|
||||
collapseDirection,
|
||||
isCollapseOpen,
|
||||
onCollapseFileClick,
|
||||
onSetSelectedFile,
|
||||
animateOpenSplitter
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { DoubleChevronRight, DoubleChevronLeft } from '@/components/ui/icons';
|
||||
import { DoubleChevronRight } from '@/components/ui/icons';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import React, { useMemo } from 'react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
|
@ -6,30 +6,21 @@ import { useMemoizedFn } from '@/hooks';
|
|||
|
||||
export const CollapseFileButton: React.FC<{
|
||||
showCollapseButton: boolean;
|
||||
isOpen: boolean;
|
||||
collapseDirection: 'left' | 'right';
|
||||
onCollapseFileClick: (value?: boolean) => void;
|
||||
}> = React.memo(({ showCollapseButton, isOpen, collapseDirection, onCollapseFileClick }) => {
|
||||
const icon = useMemo(() => {
|
||||
if (collapseDirection === 'left') {
|
||||
return isOpen ? <DoubleChevronLeft /> : <DoubleChevronRight />;
|
||||
}
|
||||
return isOpen ? <DoubleChevronRight /> : <DoubleChevronLeft />;
|
||||
}, [isOpen, collapseDirection]);
|
||||
}> = React.memo(({ showCollapseButton, onCollapseFileClick }) => {
|
||||
const icon = <DoubleChevronRight />;
|
||||
|
||||
const onClick = useMemoizedFn(() => {
|
||||
onCollapseFileClick();
|
||||
});
|
||||
|
||||
const animation = useMemo(() => {
|
||||
const baseAnimation = {
|
||||
return {
|
||||
initial: { opacity: 0 },
|
||||
animate: { opacity: 1 },
|
||||
exit: { opacity: 0 }
|
||||
};
|
||||
|
||||
return baseAnimation;
|
||||
}, [collapseDirection, isOpen]);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AnimatePresence mode="wait" initial={false}>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { CollapseFileButton } from './CollapseFileButton';
|
||||
import type { FileType } from '@/api/asset_interfaces';
|
||||
import type { FileType } from '@/api/asset_interfaces/chat';
|
||||
import { FileContainerSegmentProps, FileContainerButtonsProps } from './interfaces';
|
||||
import { DashboardContainerHeaderButtons } from './DashboardContainerHeaderButtons';
|
||||
import { DashboardContainerHeaderSegment } from './DashboardContainerHeaderSegment';
|
||||
|
@ -15,8 +15,6 @@ export const FileContainerHeader: React.FC = React.memo(() => {
|
|||
const selectedFileType = useChatLayoutContextSelector((x) => x.selectedFileType);
|
||||
const selectedFileView = useChatLayoutContextSelector((x) => x.selectedFileView);
|
||||
const onCollapseFileClick = useChatLayoutContextSelector((state) => state.onCollapseFileClick);
|
||||
const collapseDirection = useChatLayoutContextSelector((state) => state.collapseDirection);
|
||||
const isCollapseOpen = useChatLayoutContextSelector((state) => state.isCollapseOpen);
|
||||
const renderViewLayoutKey = useChatLayoutContextSelector((state) => state.renderViewLayoutKey);
|
||||
|
||||
const showCollapseButton = renderViewLayoutKey !== 'file';
|
||||
|
@ -33,7 +31,7 @@ export const FileContainerHeader: React.FC = React.memo(() => {
|
|||
() =>
|
||||
selectedFileType && SelectedFileButtonsRecord[selectedFileType]
|
||||
? SelectedFileButtonsRecord[selectedFileType]
|
||||
: () => <>no buttons</>,
|
||||
: () => null,
|
||||
[selectedFileType]
|
||||
);
|
||||
|
||||
|
@ -41,9 +39,7 @@ export const FileContainerHeader: React.FC = React.memo(() => {
|
|||
<>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<CollapseFileButton
|
||||
collapseDirection={collapseDirection}
|
||||
showCollapseButton={showCollapseButton}
|
||||
isOpen={isCollapseOpen}
|
||||
onCollapseFileClick={onCollapseFileClick}
|
||||
/>
|
||||
{selectedFileView && <SelectedFileSegment selectedFileView={selectedFileView} />}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { useMetricIndividual } from '@/context/Metrics';
|
|||
import { SaveMetricToCollectionButton } from '../../../../components/features/buttons/SaveMetricToCollectionButton';
|
||||
import { SaveMetricToDashboardButton } from '../../../../components/features/buttons/SaveMetricToDashboardButton';
|
||||
import { ShareMetricButton } from '../../../../components/features/buttons/ShareMetricButton';
|
||||
import { Code3, SquareChartPen } from '@/components/ui/icons';
|
||||
|
||||
export const MetricContainerHeaderButtons: React.FC<FileContainerButtonsProps> = React.memo(() => {
|
||||
const renderViewLayoutKey = useChatLayoutContextSelector((x) => x.renderViewLayoutKey);
|
||||
|
@ -52,7 +53,7 @@ const EditChartButton = React.memo(() => {
|
|||
return (
|
||||
<SelectableButton
|
||||
tooltipText="Edit chart"
|
||||
icon="chart_edit"
|
||||
icon={<SquareChartPen />}
|
||||
onClick={onClickButton}
|
||||
selected={isSelectedView}
|
||||
/>
|
||||
|
@ -76,7 +77,7 @@ const EditSQLButton = React.memo(() => {
|
|||
return (
|
||||
<SelectableButton
|
||||
tooltipText="Edit SQL"
|
||||
icon="code_blocks"
|
||||
icon={<Code3 />}
|
||||
onClick={onClickButton}
|
||||
selected={isSelectedView}
|
||||
/>
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { AppTooltip } from '@/components/ui/tooltip';
|
||||
import {} from '@/components/ui/icons';
|
||||
|
||||
export const SelectableButton = React.memo<{
|
||||
tooltipText: string;
|
||||
|
|
|
@ -6,50 +6,25 @@ import { SelectedFileParams } from './useSelectedFileAndLayout';
|
|||
import { ChatLayoutView } from '../interfaces';
|
||||
|
||||
export const useLayoutCollapse = ({
|
||||
selectedFile,
|
||||
animateOpenSplitter,
|
||||
selectedLayout
|
||||
animateOpenSplitter
|
||||
}: {
|
||||
selectedFile: SelectedFileParams['selectedFile'];
|
||||
selectedLayout: ChatLayoutView;
|
||||
animateOpenSplitter: (side: 'left' | 'right' | 'both') => void;
|
||||
}) => {
|
||||
const isReasoningFile = selectedFile?.type === 'reasoning';
|
||||
|
||||
const [isCollapseOpen, setIsCollapseOpen] = useState(isReasoningFile ? true : false);
|
||||
|
||||
const collapseDirection: 'left' | 'right' = useMemo(() => {
|
||||
if (selectedFile?.type === 'reasoning') return 'right';
|
||||
|
||||
return selectedLayout === 'file' ? 'left' : 'right';
|
||||
}, [selectedLayout, selectedFile?.type]);
|
||||
|
||||
const onCollapseFileClick = useMemoizedFn((close?: boolean) => {
|
||||
const isCloseAction = close ?? isCollapseOpen;
|
||||
const isFileLayout = selectedLayout === 'file';
|
||||
// if (selectedFile && selectedFile.type === 'reasoning') {
|
||||
// animateOpenSplitter(!isCloseAction ? 'both' : 'left');
|
||||
// } else if (isFileLayout) {
|
||||
// // For file layout, toggle between 'both' and 'right'
|
||||
// animateOpenSplitter(!isCloseAction && selectedFile ? 'both' : 'right');
|
||||
// } else {
|
||||
// // For other layouts, toggle between 'right' and 'both'
|
||||
// animateOpenSplitter(isCloseAction ? 'left' : 'both');
|
||||
// }
|
||||
|
||||
setIsCollapseOpen(!isCloseAction);
|
||||
|
||||
if (selectedFile && selectedFile.type === 'reasoning') {
|
||||
animateOpenSplitter(!isCloseAction ? 'both' : 'left');
|
||||
} else if (isFileLayout) {
|
||||
// For file layout, toggle between 'both' and 'right'
|
||||
animateOpenSplitter(!isCloseAction && selectedFile ? 'both' : 'right');
|
||||
} else {
|
||||
// For other layouts, toggle between 'right' and 'both'
|
||||
animateOpenSplitter(isCloseAction ? 'left' : 'both');
|
||||
}
|
||||
animateOpenSplitter('left');
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isReasoningFile && !isCollapseOpen) {
|
||||
setIsCollapseOpen(true);
|
||||
}
|
||||
}, [isReasoningFile]);
|
||||
|
||||
return {
|
||||
collapseDirection,
|
||||
isCollapseOpen,
|
||||
onCollapseFileClick
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue