mirror of
https://github.com/umami-software/umami.git
synced 2026-02-15 10:05:36 +01:00
Remove report components from boards and sanitize saved layouts
This commit is contained in:
parent
57c4a6ed51
commit
b09694ddb6
2 changed files with 31 additions and 69 deletions
|
|
@ -5,6 +5,7 @@ import { v4 as uuid } from 'uuid';
|
|||
import { useApi, useMessages, useModified, useNavigation } from '@/components/hooks';
|
||||
import { useBoardQuery } from '@/components/hooks/queries/useBoardQuery';
|
||||
import type { Board, BoardParameters } from '@/lib/types';
|
||||
import { getComponentDefinition } from './boardComponentRegistry';
|
||||
|
||||
export type LayoutGetter = () => Partial<BoardParameters> | null;
|
||||
|
||||
|
|
@ -27,6 +28,29 @@ const createDefaultBoard = (): Partial<Board> => ({
|
|||
},
|
||||
});
|
||||
|
||||
function sanitizeBoardParameters(parameters?: BoardParameters): BoardParameters | undefined {
|
||||
if (!parameters?.rows) {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
return {
|
||||
...parameters,
|
||||
rows: parameters.rows.map(row => ({
|
||||
...row,
|
||||
columns: row.columns.map(column => {
|
||||
if (column.component && !getComponentDefinition(column.component.type)) {
|
||||
return {
|
||||
...column,
|
||||
component: null,
|
||||
};
|
||||
}
|
||||
|
||||
return column;
|
||||
}),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
export function BoardProvider({
|
||||
boardId,
|
||||
editing = false,
|
||||
|
|
@ -52,7 +76,10 @@ export function BoardProvider({
|
|||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setBoard(data);
|
||||
setBoard({
|
||||
...data,
|
||||
parameters: sanitizeBoardParameters(data.parameters),
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
|
|
@ -74,7 +101,9 @@ export function BoardProvider({
|
|||
|
||||
// Get current layout sizes from BoardBody if registered
|
||||
const layoutData = layoutGetterRef.current?.();
|
||||
const parameters = layoutData ? { ...board.parameters, ...layoutData } : board.parameters;
|
||||
const parameters = sanitizeBoardParameters(
|
||||
layoutData ? { ...board.parameters, ...layoutData } : board.parameters,
|
||||
);
|
||||
|
||||
const result = await mutateAsync({
|
||||
...board,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,4 @@
|
|||
import type { ComponentType } from 'react';
|
||||
import { Attribution } from '@/app/(main)/websites/[websiteId]/(reports)/attribution/Attribution';
|
||||
import { Breakdown } from '@/app/(main)/websites/[websiteId]/(reports)/breakdown/Breakdown';
|
||||
import { Funnel } from '@/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel';
|
||||
import { Goal } from '@/app/(main)/websites/[websiteId]/(reports)/goals/Goal';
|
||||
import { Journey } from '@/app/(main)/websites/[websiteId]/(reports)/journeys/Journey';
|
||||
import { Retention } from '@/app/(main)/websites/[websiteId]/(reports)/retention/Retention';
|
||||
import { Revenue } from '@/app/(main)/websites/[websiteId]/(reports)/revenue/Revenue';
|
||||
import { UTM } from '@/app/(main)/websites/[websiteId]/(reports)/utm/UTM';
|
||||
import { WebsiteChart } from '@/app/(main)/websites/[websiteId]/WebsiteChart';
|
||||
import { WebsiteMetricsBar } from '@/app/(main)/websites/[websiteId]/WebsiteMetricsBar';
|
||||
import { EventsChart } from '@/components/metrics/EventsChart';
|
||||
|
|
@ -36,7 +28,6 @@ export const CATEGORIES = [
|
|||
{ key: 'overview', name: 'Overview' },
|
||||
{ key: 'tables', name: 'Tables' },
|
||||
{ key: 'visualization', name: 'Visualization' },
|
||||
{ key: 'reports', name: 'Reports' },
|
||||
] as const;
|
||||
|
||||
const METRIC_TYPES = [
|
||||
|
|
@ -130,64 +121,6 @@ const componentDefinitions: ComponentDefinition[] = [
|
|||
category: 'visualization',
|
||||
component: EventsChart,
|
||||
},
|
||||
|
||||
// Reports
|
||||
{
|
||||
type: 'Retention',
|
||||
name: 'Retention',
|
||||
description: 'User retention cohort analysis',
|
||||
category: 'reports',
|
||||
component: Retention,
|
||||
},
|
||||
{
|
||||
type: 'Funnel',
|
||||
name: 'Funnel',
|
||||
description: 'Conversion funnel visualization',
|
||||
category: 'reports',
|
||||
component: Funnel,
|
||||
},
|
||||
{
|
||||
type: 'Goal',
|
||||
name: 'Goal',
|
||||
description: 'Goal tracking and progress',
|
||||
category: 'reports',
|
||||
component: Goal,
|
||||
},
|
||||
{
|
||||
type: 'Journey',
|
||||
name: 'Journey',
|
||||
description: 'User navigation flow',
|
||||
category: 'reports',
|
||||
component: Journey,
|
||||
},
|
||||
{
|
||||
type: 'UTM',
|
||||
name: 'UTM',
|
||||
description: 'UTM campaign performance',
|
||||
category: 'reports',
|
||||
component: UTM,
|
||||
},
|
||||
{
|
||||
type: 'Revenue',
|
||||
name: 'Revenue',
|
||||
description: 'Revenue analytics and trends',
|
||||
category: 'reports',
|
||||
component: Revenue,
|
||||
},
|
||||
{
|
||||
type: 'Attribution',
|
||||
name: 'Attribution',
|
||||
description: 'Traffic source attribution',
|
||||
category: 'reports',
|
||||
component: Attribution,
|
||||
},
|
||||
{
|
||||
type: 'Breakdown',
|
||||
name: 'Breakdown',
|
||||
description: 'Multi-dimensional data breakdown',
|
||||
category: 'reports',
|
||||
component: Breakdown,
|
||||
},
|
||||
];
|
||||
|
||||
const definitionMap = new Map(componentDefinitions.map(def => [def.type, def]));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue