mirror of https://github.com/buster-so/buster.git
update dashboard links
This commit is contained in:
parent
48678dd226
commit
9d5850cc07
|
@ -6,5 +6,8 @@
|
|||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@electric-sql/client": "^1.0.6",
|
||||
"@electric-sql/react": "^1.0.5",
|
||||
"@electric-sql/react": "^1.0.6",
|
||||
"@faker-js/faker": "^9.9.0",
|
||||
"@llm-ui/code": "^0.13.3",
|
||||
"@llm-ui/markdown": "^0.13.3",
|
||||
|
|
|
@ -46,14 +46,14 @@ const topItems = (
|
|||
{
|
||||
label: 'Home',
|
||||
icon: <House4 />,
|
||||
route: BusterRoutes.APP_HOME,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_HOME }),
|
||||
id: BusterRoutes.APP_HOME,
|
||||
active: currentParentRoute === BusterRoutes.APP_HOME
|
||||
},
|
||||
{
|
||||
label: 'Chat history',
|
||||
icon: <ASSET_ICONS.chats />,
|
||||
route: BusterRoutes.APP_CHAT,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_CHAT }),
|
||||
id: BusterRoutes.APP_CHAT,
|
||||
active: isActiveCheck('chat', BusterRoutes.APP_CHAT)
|
||||
}
|
||||
|
@ -75,21 +75,21 @@ const yourStuff = (
|
|||
{
|
||||
label: 'Metrics',
|
||||
icon: <ASSET_ICONS.metrics />,
|
||||
route: BusterRoutes.APP_METRIC,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_METRIC }),
|
||||
id: BusterRoutes.APP_METRIC,
|
||||
active: isActiveCheck('metric', BusterRoutes.APP_METRIC)
|
||||
},
|
||||
{
|
||||
label: 'Dashboards',
|
||||
icon: <ASSET_ICONS.dashboards />,
|
||||
route: BusterRoutes.APP_DASHBOARDS,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_DASHBOARDS }),
|
||||
id: BusterRoutes.APP_DASHBOARDS,
|
||||
active: isActiveCheck('dashboard', BusterRoutes.APP_DASHBOARDS)
|
||||
},
|
||||
{
|
||||
label: 'Collections',
|
||||
icon: <ASSET_ICONS.collections />,
|
||||
route: BusterRoutes.APP_COLLECTIONS,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_COLLECTIONS }),
|
||||
id: BusterRoutes.APP_COLLECTIONS,
|
||||
active: isActiveCheck('collection', BusterRoutes.APP_COLLECTIONS)
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ const adminTools = (currentParentRoute: BusterRoutes): ISidebarGroup => ({
|
|||
{
|
||||
label: 'Logs',
|
||||
icon: <UnorderedList2 />,
|
||||
route: BusterRoutes.APP_LOGS,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_LOGS }),
|
||||
id: BusterRoutes.APP_LOGS,
|
||||
collapsedTooltip: 'Logs'
|
||||
},
|
||||
|
@ -117,7 +117,7 @@ const adminTools = (currentParentRoute: BusterRoutes): ISidebarGroup => ({
|
|||
{
|
||||
label: 'Datasets',
|
||||
icon: <Table />,
|
||||
route: BusterRoutes.APP_DATASETS,
|
||||
route: createBusterRoute({ route: BusterRoutes.APP_DATASETS }),
|
||||
id: BusterRoutes.APP_DATASETS,
|
||||
collapsedTooltip: 'Datasets'
|
||||
}
|
||||
|
|
|
@ -40,10 +40,11 @@ export const DashboardContentController: React.FC<{
|
|||
metrics = DEFAULT_EMPTY_METRICS,
|
||||
onUpdateDashboardConfig
|
||||
}) => {
|
||||
const [draggingId, setDraggingId] = useState<string | null>(null);
|
||||
const dashboardVersionNumber = dashboard?.version_number;
|
||||
const dashboardConfig = dashboard?.config || DEFAULT_EMPTY_CONFIG;
|
||||
const configRows = dashboardConfig?.rows || DEFAULT_EMPTY_ROWS;
|
||||
const hasMetrics = !isEmpty(metrics);
|
||||
const [draggingId, setDraggingId] = useState<string | null>(null);
|
||||
const numberOfMetrics = Object.values(metrics).length;
|
||||
|
||||
const remapMetrics = useMemo(() => {
|
||||
|
@ -65,7 +66,8 @@ export const DashboardContentController: React.FC<{
|
|||
isDragOverlay
|
||||
numberOfMetrics={numberOfMetrics}
|
||||
chatId={undefined}
|
||||
versionNumber={metrics[draggingId]?.version_number}
|
||||
dashboardVersionNumber={dashboardVersionNumber}
|
||||
metricVersionNumber={metrics[draggingId]?.version_number}
|
||||
/>
|
||||
)
|
||||
);
|
||||
|
@ -79,7 +81,7 @@ export const DashboardContentController: React.FC<{
|
|||
...row,
|
||||
items: row.items.map((item) => {
|
||||
const selectedMetric = metrics[item.id];
|
||||
const versionNumber = selectedMetric.version_number;
|
||||
const metricVersionNumber = selectedMetric.version_number;
|
||||
|
||||
return {
|
||||
...item,
|
||||
|
@ -91,7 +93,8 @@ export const DashboardContentController: React.FC<{
|
|||
readOnly={readOnly}
|
||||
chatId={chatId}
|
||||
numberOfMetrics={numberOfMetrics}
|
||||
versionNumber={versionNumber}
|
||||
metricVersionNumber={metricVersionNumber}
|
||||
dashboardVersionNumber={dashboardVersionNumber}
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
|
|
@ -5,14 +5,14 @@ import { Card, CardHeader } from '@/components/ui/card/CardBase';
|
|||
import { BusterChart } from '@/components/ui/charts/BusterChart';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||
import { MetricTitle } from './MetricTitle';
|
||||
import { useDashboardMetric } from './useDashboardMetric';
|
||||
import { assetParamsToRoute } from '@/lib/assets';
|
||||
|
||||
const DashboardMetricItemBase: React.FC<{
|
||||
metricId: string;
|
||||
versionNumber: number | undefined;
|
||||
metricVersionNumber: number | undefined;
|
||||
dashboardVersionNumber: number | undefined;
|
||||
chatId: string | undefined;
|
||||
dashboardId: string;
|
||||
numberOfMetrics: number;
|
||||
|
@ -22,12 +22,13 @@ const DashboardMetricItemBase: React.FC<{
|
|||
}> = ({
|
||||
readOnly,
|
||||
dashboardId,
|
||||
versionNumber,
|
||||
metricVersionNumber,
|
||||
className = '',
|
||||
metricId,
|
||||
isDragOverlay = false,
|
||||
numberOfMetrics,
|
||||
chatId
|
||||
chatId,
|
||||
dashboardVersionNumber
|
||||
}) => {
|
||||
const {
|
||||
conatinerRef,
|
||||
|
@ -39,7 +40,7 @@ const DashboardMetricItemBase: React.FC<{
|
|||
isFetchedMetricData,
|
||||
metricError,
|
||||
metricDataError
|
||||
} = useDashboardMetric({ metricId, versionNumber });
|
||||
} = useDashboardMetric({ metricId, versionNumber: metricVersionNumber });
|
||||
|
||||
const loadingMetricData = !!metric && !isFetchedMetricData;
|
||||
const chartOptions = metric?.chart_config;
|
||||
|
@ -61,9 +62,10 @@ const DashboardMetricItemBase: React.FC<{
|
|||
assetId: metricId,
|
||||
chatId,
|
||||
dashboardId,
|
||||
page: 'chart'
|
||||
page: 'chart',
|
||||
metricVersionNumber
|
||||
});
|
||||
}, [metricId, chatId, dashboardId]);
|
||||
}, [metricId, chatId, dashboardId, metricVersionNumber]);
|
||||
|
||||
const onInitialAnimationEndPreflight = useMemoizedFn(() => {
|
||||
setInitialAnimationEnded(metricId);
|
||||
|
|
|
@ -71,10 +71,8 @@ export const ThreeDotMenuButton = React.memo(
|
|||
versionNumber: number | undefined;
|
||||
}) => {
|
||||
const chatId = useChatIndividualContextSelector((x) => x.chatId);
|
||||
const { openSuccessMessage } = useBusterNotifications();
|
||||
const { data: permission } = useGetMetric({ id: metricId }, { select: (x) => x.permission });
|
||||
const openFullScreenMetric = useOpenFullScreenMetric({ metricId, versionNumber });
|
||||
const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile);
|
||||
const dashboardSelectMenu = useDashboardSelectMenu({ metricId });
|
||||
const versionHistoryItems = useVersionHistorySelectMenu({ metricId });
|
||||
const collectionSelectMenu = useCollectionSelectMenu({ metricId });
|
||||
|
@ -89,6 +87,8 @@ export const ThreeDotMenuButton = React.memo(
|
|||
const renameMetricMenu = useRenameMetricSelectMenu({ metricId });
|
||||
const shareMenu = useShareMenuSelectMenu({ metricId });
|
||||
|
||||
console.log(permission);
|
||||
|
||||
const isEditor = canEdit(permission);
|
||||
const isOwnerEffective = getIsEffectiveOwner(permission);
|
||||
const isOwner = getIsOwner(permission);
|
||||
|
|
|
@ -32,6 +32,8 @@ const MetricSegments: React.FC<FileContainerSegmentProps> = React.memo(
|
|||
({ selectedFileView, chatId }) => {
|
||||
const metricId = useChatLayoutContextSelector((x) => x.metricId) || '';
|
||||
const dashboardId = useChatLayoutContextSelector((x) => x.dashboardId) || '';
|
||||
const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber);
|
||||
const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber);
|
||||
const { error } = useGetMetric({ id: metricId });
|
||||
|
||||
const segmentOptions: SegmentedItem<FileView>[] = React.useMemo(() => {
|
||||
|
@ -44,6 +46,8 @@ const MetricSegments: React.FC<FileContainerSegmentProps> = React.memo(
|
|||
chatId,
|
||||
dashboardId,
|
||||
assetId: metricId,
|
||||
metricVersionNumber: metricVersionNumber,
|
||||
dashboardVersionNumber,
|
||||
type: 'metric'
|
||||
})
|
||||
},
|
||||
|
@ -55,6 +59,8 @@ const MetricSegments: React.FC<FileContainerSegmentProps> = React.memo(
|
|||
chatId,
|
||||
dashboardId,
|
||||
assetId: metricId,
|
||||
metricVersionNumber,
|
||||
dashboardVersionNumber,
|
||||
type: 'metric'
|
||||
})
|
||||
},
|
||||
|
@ -66,11 +72,13 @@ const MetricSegments: React.FC<FileContainerSegmentProps> = React.memo(
|
|||
chatId,
|
||||
dashboardId,
|
||||
assetId: metricId,
|
||||
metricVersionNumber,
|
||||
dashboardVersionNumber,
|
||||
type: 'metric'
|
||||
})
|
||||
}
|
||||
];
|
||||
}, [chatId, error, metricId, dashboardId]);
|
||||
}, [chatId, error, metricId, dashboardId, metricVersionNumber, dashboardVersionNumber]);
|
||||
|
||||
return <AppSegmented type="button" options={segmentOptions} value={selectedFileView} />;
|
||||
}
|
||||
|
|
|
@ -6,15 +6,13 @@ import { createDashboardRoute } from './createDashboardRoute';
|
|||
import { createReasoningRoute } from './createReasoningRoute';
|
||||
import { createDatasetRoute } from './createDatasetRoute';
|
||||
|
||||
// Mock all the route creation functions
|
||||
vi.mock('@/routes/busterRoutes', () => ({
|
||||
BusterRoutes: {
|
||||
APP_CHAT_ID: '/app/chats/:chatId',
|
||||
APP_COLLECTIONS_ID: '/app/collections/:collectionId',
|
||||
APP_TERMS_ID: '/app/terms/:termId'
|
||||
},
|
||||
createBusterRoute: vi.fn()
|
||||
}));
|
||||
vi.mock('@/routes/busterRoutes', async () => {
|
||||
const actual = await vi.importActual('@/routes/busterRoutes');
|
||||
return {
|
||||
...actual,
|
||||
createBusterRoute: vi.fn()
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('./createMetricRoute', () => ({
|
||||
createMetricRoute: vi.fn()
|
||||
|
@ -92,7 +90,7 @@ describe('assetParamsToRoute', () => {
|
|||
assetId: 'metric-123',
|
||||
chatId: 'chat-456',
|
||||
secondaryView: 'chart-edit',
|
||||
versionNumber: 2,
|
||||
metricVersionNumber: 2,
|
||||
page: 'chart'
|
||||
});
|
||||
expect(result).toBe('/mock/metric/route');
|
||||
|
@ -122,7 +120,7 @@ describe('assetParamsToRoute', () => {
|
|||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
type: 'dashboard',
|
||||
versionNumber: 3,
|
||||
dashboardVersionNumber: 3,
|
||||
page: 'file',
|
||||
secondaryView: 'version-history'
|
||||
});
|
||||
|
@ -130,7 +128,7 @@ describe('assetParamsToRoute', () => {
|
|||
expect(mockCreateDashboardRoute).toHaveBeenCalledWith({
|
||||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
versionNumber: 3,
|
||||
dashboardVersionNumber: 3,
|
||||
page: 'file',
|
||||
secondaryView: 'version-history'
|
||||
});
|
||||
|
|
|
@ -13,9 +13,13 @@ import { createDatasetRoute } from './createDatasetRoute';
|
|||
type UnionOfFileTypes = FileType | ReasoningFileType | ReasoingMessage_ThoughtFileType;
|
||||
|
||||
type OtherRouteParams = {
|
||||
assetId: string | undefined;
|
||||
chatId: string | undefined;
|
||||
versionNumber?: number;
|
||||
assetId: string | undefined; //will first try and use metricId assuming it is a metric, then dashboardId assuming it is a dashboard, then assetId
|
||||
metricId?: string; //if this is provided, it will be used instead of assetId
|
||||
dashboardId?: string; //if this is provided, it will be used instead of assetId
|
||||
versionNumber?: number; //will first try and use metricVersionNumber assuming it is a metric, then dashboardVersionNumber assuming it is a dashboard, then versionNumber
|
||||
metricVersionNumber?: number; //if this is provided, it will be used instead of versionNumber
|
||||
dashboardVersionNumber?: number; //if this is provided, it will be used instead of versionNumber
|
||||
page?: undefined;
|
||||
secondaryView?: undefined | null | string;
|
||||
type: Exclude<UnionOfFileTypes, 'metric' | 'dashboard'>;
|
||||
|
@ -27,10 +31,14 @@ export const assetParamsToRoute = ({
|
|||
chatId,
|
||||
assetId,
|
||||
type,
|
||||
versionNumber,
|
||||
page,
|
||||
secondaryView
|
||||
secondaryView,
|
||||
...rest
|
||||
}: BaseParams): string => {
|
||||
const { versionNumber } = rest as OtherRouteParams;
|
||||
const { metricVersionNumber, dashboardVersionNumber } = rest as MetricRouteParams;
|
||||
const { metricId, dashboardId } = rest as OtherRouteParams;
|
||||
|
||||
if (!assetId && chatId) {
|
||||
return createBusterRoute({
|
||||
route: BusterRoutes.APP_CHAT_ID,
|
||||
|
@ -44,19 +52,22 @@ export const assetParamsToRoute = ({
|
|||
|
||||
if (type === 'metric') {
|
||||
return createMetricRoute({
|
||||
assetId,
|
||||
assetId: metricId || assetId,
|
||||
metricVersionNumber: metricVersionNumber || versionNumber,
|
||||
chatId,
|
||||
secondaryView: secondaryView as MetricFileViewSecondary,
|
||||
versionNumber,
|
||||
dashboardVersionNumber,
|
||||
dashboardId,
|
||||
page: page as MetricRouteParams['page']
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'dashboard') {
|
||||
return createDashboardRoute({
|
||||
assetId,
|
||||
assetId: dashboardId || assetId,
|
||||
dashboardVersionNumber: dashboardVersionNumber || versionNumber,
|
||||
metricVersionNumber,
|
||||
chatId,
|
||||
versionNumber,
|
||||
page,
|
||||
secondaryView: secondaryView as DashboardFileViewSecondary
|
||||
});
|
||||
|
|
|
@ -6,16 +6,7 @@ import { BusterRoutes } from '@/routes/busterRoutes';
|
|||
vi.mock('@/routes/busterRoutes', async () => {
|
||||
const actual = await vi.importActual('@/routes/busterRoutes');
|
||||
return {
|
||||
...actual,
|
||||
createBusterRoute: vi.fn((params) => {
|
||||
// Simple mock implementation that returns a string representation
|
||||
const { route, ...args } = params;
|
||||
const queryParams = Object.entries(args)
|
||||
.filter(([_, value]) => value !== undefined)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join('&');
|
||||
return queryParams ? `${route}?${queryParams}` : route;
|
||||
})
|
||||
...actual
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -30,29 +21,28 @@ describe('createDashboardRoute', () => {
|
|||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
secondaryView: 'version-history',
|
||||
versionNumber: 5,
|
||||
dashboardVersionNumber: 5,
|
||||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=5');
|
||||
expect(result).toContain('secondaryView=version-history');
|
||||
console.log('result', result);
|
||||
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?secondary_view=version-history&dashboard_version_number=5'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create chat dashboard route with version number only', () => {
|
||||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
versionNumber: 3,
|
||||
dashboardVersionNumber: 3,
|
||||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=3');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?dashboard_version_number=3'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create chat dashboard route with version-history secondary view', () => {
|
||||
|
@ -63,10 +53,9 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('secondaryView=version-history');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?secondary_view=version-history'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create chat dashboard route with minimal parameters', () => {
|
||||
|
@ -76,21 +65,17 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/chats/chat-456/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should create non-chat dashboard route with version number', () => {
|
||||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
versionNumber: 7,
|
||||
dashboardVersionNumber: 7,
|
||||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=7');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123?dashboard_version_number=7');
|
||||
});
|
||||
|
||||
it('should create non-chat dashboard route with version-history secondary view', () => {
|
||||
|
@ -100,9 +85,7 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('secondaryView=version-history');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123?secondary_view=version-history');
|
||||
});
|
||||
|
||||
it('should create non-chat dashboard route with minimal parameters', () => {
|
||||
|
@ -111,8 +94,7 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -121,14 +103,13 @@ describe('createDashboardRoute', () => {
|
|||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
versionNumber: 2,
|
||||
dashboardVersionNumber: 2,
|
||||
page: 'file'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=2');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?dashboard_version_number=2'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create chat dashboard file route with version-history secondary view', () => {
|
||||
|
@ -139,10 +120,9 @@ describe('createDashboardRoute', () => {
|
|||
page: 'file'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('secondaryView=version-history');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?secondary_view=version-history'
|
||||
);
|
||||
});
|
||||
|
||||
it('should create chat dashboard file route without version number', () => {
|
||||
|
@ -152,21 +132,17 @@ describe('createDashboardRoute', () => {
|
|||
page: 'file'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/chats/chat-456/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should create non-chat dashboard file route with version number', () => {
|
||||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
versionNumber: 8,
|
||||
dashboardVersionNumber: 8,
|
||||
page: 'file'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=8');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123?dashboard_version_number=8');
|
||||
});
|
||||
|
||||
it('should create non-chat dashboard file route without version number', () => {
|
||||
|
@ -175,8 +151,7 @@ describe('createDashboardRoute', () => {
|
|||
page: 'file'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -188,9 +163,7 @@ describe('createDashboardRoute', () => {
|
|||
page: undefined
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/chats/chat-456/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should handle undefined secondary view in chat context', () => {
|
||||
|
@ -201,9 +174,7 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/chats/chat-456/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should handle undefined secondary view in non-chat context', () => {
|
||||
|
@ -213,8 +184,7 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should handle undefined page value', () => {
|
||||
|
@ -224,9 +194,7 @@ describe('createDashboardRoute', () => {
|
|||
page: undefined
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/chats/chat-456/dashboards/dashboard-123');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -238,52 +206,46 @@ describe('createDashboardRoute', () => {
|
|||
secondaryView: undefined,
|
||||
versionNumber: undefined,
|
||||
page: 'dashboard'
|
||||
});
|
||||
} as any);
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_DASHBOARD_ID);
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe('/app/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should handle version number 1', () => {
|
||||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
versionNumber: 1,
|
||||
dashboardVersionNumber: 1,
|
||||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=1');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?dashboard_version_number=1'
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle zero version number', () => {
|
||||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
versionNumber: 0,
|
||||
dashboardVersionNumber: 0,
|
||||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=0');
|
||||
expect(result).toBe('/app/chats/chat-456/dashboards/dashboard-123');
|
||||
});
|
||||
|
||||
it('should handle large version numbers', () => {
|
||||
const result = createDashboardRoute({
|
||||
assetId: 'dashboard-123',
|
||||
chatId: 'chat-456',
|
||||
versionNumber: 999999,
|
||||
dashboardVersionNumber: 999999,
|
||||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toContain('dashboardVersionNumber=999999');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-123?dashboard_version_number=999999'
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle complex dashboard IDs', () => {
|
||||
|
@ -293,9 +255,9 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-456');
|
||||
expect(result).toContain('dashboardId=dashboard-with-special-chars-123_456-789');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-456/dashboards/dashboard-with-special-chars-123_456-789'
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle complex chat IDs', () => {
|
||||
|
@ -305,9 +267,9 @@ describe('createDashboardRoute', () => {
|
|||
page: 'dashboard'
|
||||
});
|
||||
|
||||
expect(result).toContain(BusterRoutes.APP_CHAT_ID_DASHBOARD_ID);
|
||||
expect(result).toContain('chatId=chat-with-special-chars-456_789-012');
|
||||
expect(result).toContain('dashboardId=dashboard-123');
|
||||
expect(result).toBe(
|
||||
'/app/chats/chat-with-special-chars-456_789-012/dashboards/dashboard-123'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,8 +4,10 @@ import type { DashboardFileViewSecondary } from '../../layouts/ChatLayout/ChatLa
|
|||
export type DashboardRouteParams = {
|
||||
assetId: string;
|
||||
chatId?: string;
|
||||
secondaryView?: DashboardFileViewSecondary;
|
||||
versionNumber?: number;
|
||||
secondaryView?: DashboardFileViewSecondary;
|
||||
dashboardVersionNumber?: number;
|
||||
metricVersionNumber?: number;
|
||||
type: 'dashboard';
|
||||
page?: 'file' | 'dashboard' | undefined;
|
||||
};
|
||||
|
@ -14,10 +16,13 @@ export const createDashboardRoute = ({
|
|||
assetId: dashboardId,
|
||||
chatId,
|
||||
secondaryView,
|
||||
versionNumber: dashboardVersionNumber,
|
||||
dashboardVersionNumber: _dashboardVersionNumber,
|
||||
metricVersionNumber,
|
||||
versionNumber,
|
||||
page = 'dashboard'
|
||||
}: Omit<DashboardRouteParams, 'type'>) => {
|
||||
const baseParams = { dashboardVersionNumber, dashboardId, secondaryView };
|
||||
const dashboardVersionNumber = _dashboardVersionNumber || versionNumber;
|
||||
const baseParams = { dashboardVersionNumber, dashboardId, secondaryView, metricVersionNumber };
|
||||
|
||||
if (page === 'dashboard') {
|
||||
if (chatId) {
|
||||
|
|
|
@ -6,9 +6,11 @@ export type MetricRouteParams = {
|
|||
dashboardId?: string;
|
||||
chatId?: string;
|
||||
secondaryView?: MetricFileViewSecondary;
|
||||
versionNumber?: number;
|
||||
metricVersionNumber?: number;
|
||||
dashboardVersionNumber?: number;
|
||||
type: 'metric';
|
||||
page?: 'chart' | 'results' | 'sql' | undefined;
|
||||
versionNumber?: number; //will first try and use metricVersionNumber assuming it is a metric, then dashboardVersionNumber assuming it is a dashboard, then versionNumber
|
||||
};
|
||||
|
||||
export const createMetricRoute = ({
|
||||
|
@ -16,10 +18,13 @@ export const createMetricRoute = ({
|
|||
chatId,
|
||||
secondaryView,
|
||||
dashboardId,
|
||||
versionNumber: metricVersionNumber,
|
||||
metricVersionNumber: _metricVersionNumber,
|
||||
dashboardVersionNumber,
|
||||
versionNumber,
|
||||
page = 'chart'
|
||||
}: Omit<MetricRouteParams, 'type'>) => {
|
||||
const baseParams = { metricVersionNumber, metricId, secondaryView };
|
||||
const metricVersionNumber = _metricVersionNumber || versionNumber;
|
||||
const baseParams = { metricVersionNumber, dashboardVersionNumber, metricId, secondaryView };
|
||||
|
||||
if (page === 'chart') {
|
||||
// Check for dashboardId first (requires chatId as well)
|
||||
|
|
|
@ -4,11 +4,11 @@ export enum BusterAppRoutes {
|
|||
APP_HOME = '/app/home',
|
||||
APP_COLLECTIONS = '/app/collections',
|
||||
APP_COLLECTIONS_ID = '/app/collections/:collectionId',
|
||||
APP_METRIC = '/app/metrics?metric_version_number=:metricVersionNumber',
|
||||
APP_METRIC = '/app/metrics',
|
||||
APP_METRIC_ID_CHART = '/app/metrics/:metricId/chart?secondary_view=:secondaryView&metric_version_number=:metricVersionNumber',
|
||||
APP_METRIC_ID_RESULTS = '/app/metrics/:metricId/results?secondary_view=:secondaryView&metric_version_number=:metricVersionNumber',
|
||||
APP_METRIC_ID_SQL = '/app/metrics/:metricId/sql?metric_version_number=:metricVersionNumber',
|
||||
APP_DASHBOARDS = '/app/dashboards?dashboard_version_number=:dashboardVersionNumber',
|
||||
APP_DASHBOARDS = '/app/dashboards',
|
||||
APP_DASHBOARD_ID = '/app/dashboards/:dashboardId?secondary_view=:secondaryView&dashboard_version_number=:dashboardVersionNumber',
|
||||
APP_DASHBOARD_ID_FILE = '/app/dashboards/:dashboardId/file?dashboard_version_number=:dashboardVersionNumber&secondary_view=:secondaryView',
|
||||
APP_LOGS = '/app/logs',
|
||||
|
@ -54,7 +54,6 @@ export type BusterAppRoutesWithArgs = {
|
|||
};
|
||||
[BusterAppRoutes.APP_METRIC]: {
|
||||
route: BusterAppRoutes.APP_METRIC;
|
||||
metricVersionNumber?: number;
|
||||
};
|
||||
[BusterAppRoutes.APP_METRIC_ID_CHART]: {
|
||||
route: BusterAppRoutes.APP_METRIC_ID_CHART;
|
||||
|
@ -75,7 +74,6 @@ export type BusterAppRoutesWithArgs = {
|
|||
};
|
||||
[BusterAppRoutes.APP_DASHBOARDS]: {
|
||||
route: BusterAppRoutes.APP_DASHBOARDS;
|
||||
dashboardVersionNumber?: number;
|
||||
};
|
||||
[BusterAppRoutes.APP_DASHBOARD_ID]: {
|
||||
route: BusterAppRoutes.APP_DASHBOARD_ID;
|
||||
|
|
|
@ -207,8 +207,8 @@ importers:
|
|||
specifier: ^1.0.6
|
||||
version: 1.0.6
|
||||
'@electric-sql/react':
|
||||
specifier: ^1.0.5
|
||||
version: 1.0.5(react@18.3.1)
|
||||
specifier: ^1.0.6
|
||||
version: 1.0.6(react@18.3.1)
|
||||
'@faker-js/faker':
|
||||
specifier: ^9.9.0
|
||||
version: 9.9.0
|
||||
|
@ -2005,14 +2005,11 @@ packages:
|
|||
'@electric-sql/client@1.0.0-beta.1':
|
||||
resolution: {integrity: sha512-Ei9jN3pDoGzc+a/bGqnB5ajb52IvSv7/n2btuyzUlcOHIR2kM9fqtYTJXPwZYKLkGZlHWlpHgWyRtrinkP2nHg==}
|
||||
|
||||
'@electric-sql/client@1.0.5':
|
||||
resolution: {integrity: sha512-DO7dvfCbZU6k33vr3ymBCXER6kPpoBODoRBru7oI16B4/ZXlxhMBpsmzmd8p9dQrPICCpQm6bBkNI6qI3oUAIQ==}
|
||||
|
||||
'@electric-sql/client@1.0.6':
|
||||
resolution: {integrity: sha512-W3vrQhpKeMrOwErnrurC+aXJI8o6g4hSvHdFv10vES4Y+u3zBQoee88otr25GYX8cdleTXlczvh7XQhn4ywRBA==}
|
||||
|
||||
'@electric-sql/react@1.0.5':
|
||||
resolution: {integrity: sha512-mNabbjw0BGV8nw6JUQF6OecQU5IQW8RbJ4SiwQ4LGJ2G0jRIT6cnQsNdXU4amoMnbchRhXFDGb8FJxnEVczn3Q==}
|
||||
'@electric-sql/react@1.0.6':
|
||||
resolution: {integrity: sha512-r+45jTP0o4urpn5LF94vIgqcvnBD6MJFi7QwYUjQLVU46gu+43Sudl503Klier10j473emZHIdvrI6FxRWH/Zw==}
|
||||
peerDependencies:
|
||||
react: '>=18.3.1 <20.0.0'
|
||||
peerDependenciesMeta:
|
||||
|
@ -13493,21 +13490,15 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@rollup/rollup-darwin-arm64': 4.44.2
|
||||
|
||||
'@electric-sql/client@1.0.5':
|
||||
dependencies:
|
||||
'@microsoft/fetch-event-source': 2.0.1
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-darwin-arm64': 4.44.2
|
||||
|
||||
'@electric-sql/client@1.0.6':
|
||||
dependencies:
|
||||
'@microsoft/fetch-event-source': 2.0.1
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-darwin-arm64': 4.44.2
|
||||
|
||||
'@electric-sql/react@1.0.5(react@18.3.1)':
|
||||
'@electric-sql/react@1.0.6(react@18.3.1)':
|
||||
dependencies:
|
||||
'@electric-sql/client': 1.0.5
|
||||
'@electric-sql/client': 1.0.6
|
||||
use-sync-external-store: 1.5.0(react@18.3.1)
|
||||
optionalDependencies:
|
||||
react: 18.3.1
|
||||
|
|
Loading…
Reference in New Issue