feat: report editor

commit bfcf271a64c33a60f61f511cec2198d9c8a9c51a
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Wed Nov 26 12:32:40 2025 +0100

    wip

commit 8cd3b89fa3
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Tue Nov 25 22:33:58 2025 +0100

    funnel

commit 95af86dc44
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Tue Nov 25 22:23:25 2025 +0100

    wip

commit 727a218e6b
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Tue Nov 25 10:18:26 2025 +0100

    conversion wip

commit 958ba535d6
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Tue Nov 25 10:18:20 2025 +0100

    wip

commit 3bbeb927cc
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Tue Nov 25 09:18:48 2025 +0100

    wip

commit d99335e2f4
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Mon Nov 24 18:08:10 2025 +0100

    wip

commit 1fa61b1ae9
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Mon Nov 24 15:50:28 2025 +0100

    ts

commit 548747d826
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Mon Nov 24 13:17:01 2025 +0100

    fix typecheck events -> series

commit 7b18544085
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Mon Nov 24 13:06:46 2025 +0100

    fix report table

commit 57697a5a39
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Sat Nov 22 00:05:13 2025 +0100

    wip

commit 06fb6c4f3c
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Fri Nov 21 11:21:17 2025 +0100

    wip

commit dd71fd4e11
Author: Carl-Gerhard Lindesvärd <lindesvard@gmail.com>
Date:   Thu Nov 20 13:56:58 2025 +0100

    formulas
This commit is contained in:
Carl-Gerhard Lindesvärd
2025-11-26 12:33:41 +01:00
parent 828c8c4f91
commit b421474616
70 changed files with 6867 additions and 1918 deletions

View File

@@ -11,12 +11,14 @@ import {
} from '@openpanel/constants';
import type {
IChartBreakdown,
IChartEvent,
IChartEventItem,
IChartFormula,
IChartLineType,
IChartProps,
IChartRange,
IChartType,
IInterval,
UnionOmit,
zCriteria,
} from '@openpanel/validation';
import type { z } from 'zod';
@@ -39,7 +41,7 @@ const initialState: InitialState = {
lineType: 'monotone',
interval: 'day',
breakdowns: [],
events: [],
series: [],
range: '30d',
startDate: null,
endDate: null,
@@ -86,24 +88,34 @@ export const reportSlice = createSlice({
state.dirty = true;
state.name = action.payload;
},
// Events
addEvent: (state, action: PayloadAction<Omit<IChartEvent, 'id'>>) => {
// Series (Events and Formulas)
addSerie: (
state,
action: PayloadAction<UnionOmit<IChartEventItem, 'id'>>,
) => {
state.dirty = true;
state.events.push({
state.series.push({
id: shortId(),
...action.payload,
});
},
duplicateEvent: (state, action: PayloadAction<Omit<IChartEvent, 'id'>>) => {
duplicateEvent: (state, action: PayloadAction<IChartEventItem>) => {
state.dirty = true;
state.events.push({
...action.payload,
filters: action.payload.filters.map((filter) => ({
...filter,
if (action.payload.type === 'event') {
state.series.push({
...action.payload,
filters: action.payload.filters.map((filter) => ({
...filter,
id: shortId(),
})),
id: shortId(),
})),
id: shortId(),
});
} as IChartEventItem);
} else {
state.series.push({
...action.payload,
id: shortId(),
} as IChartEventItem);
}
},
removeEvent: (
state,
@@ -112,13 +124,13 @@ export const reportSlice = createSlice({
}>,
) => {
state.dirty = true;
state.events = state.events.filter(
(event) => event.id !== action.payload.id,
);
state.series = state.series.filter((event) => {
return event.id !== action.payload.id;
});
},
changeEvent: (state, action: PayloadAction<IChartEvent>) => {
changeEvent: (state, action: PayloadAction<IChartEventItem>) => {
state.dirty = true;
state.events = state.events.map((event) => {
state.series = state.series.map((event) => {
if (event.id === action.payload.id) {
return action.payload;
}
@@ -265,9 +277,9 @@ export const reportSlice = createSlice({
) {
state.dirty = true;
const { fromIndex, toIndex } = action.payload;
const [movedEvent] = state.events.splice(fromIndex, 1);
const [movedEvent] = state.series.splice(fromIndex, 1);
if (movedEvent) {
state.events.splice(toIndex, 0, movedEvent);
state.series.splice(toIndex, 0, movedEvent);
}
},
},
@@ -279,7 +291,7 @@ export const {
ready,
setReport,
setName,
addEvent,
addSerie,
removeEvent,
duplicateEvent,
changeEvent,