mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 12:47:13 +01:00
Fixed funnel report saving invalid data.
Some checks are pending
Node.js CI / build (postgresql, 18.18) (push) Waiting to run
Some checks are pending
Node.js CI / build (postgresql, 18.18) (push) Waiting to run
This commit is contained in:
parent
bf16ade184
commit
980e4e6b41
11 changed files with 34 additions and 25 deletions
|
|
@ -82,7 +82,7 @@
|
|||
"@react-spring/web": "^10.0.1",
|
||||
"@svgr/cli": "^8.1.0",
|
||||
"@tanstack/react-query": "^5.85.5",
|
||||
"@umami/react-zen": "^0.183.0",
|
||||
"@umami/react-zen": "^0.184.0",
|
||||
"@umami/redis-client": "^0.29.0",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"chalk": "^5.6.0",
|
||||
|
|
|
|||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
|
|
@ -45,8 +45,8 @@ importers:
|
|||
specifier: ^5.85.5
|
||||
version: 5.85.5(react@19.1.1)
|
||||
'@umami/react-zen':
|
||||
specifier: ^0.183.0
|
||||
version: 0.183.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
|
||||
specifier: ^0.184.0
|
||||
version: 0.184.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
|
||||
'@umami/redis-client':
|
||||
specifier: ^0.29.0
|
||||
version: 0.29.0
|
||||
|
|
@ -2735,8 +2735,8 @@ packages:
|
|||
'@prisma/client': ^6.1.0
|
||||
'@prisma/extension-read-replicas': ^0.4.1
|
||||
|
||||
'@umami/react-zen@0.183.0':
|
||||
resolution: {integrity: sha512-snzfp87NElKbQn5lHUs3jTdCkXww4FHNJAGzyXVUcTv/5Bqv9mAmW+6htELychvQnO259t8GL/qJrcC5V/e4cg==}
|
||||
'@umami/react-zen@0.184.0':
|
||||
resolution: {integrity: sha512-XfxTiP4ljumflx02ymDMXLnhcJW+mOxxKCPEVEjuDrQfR6VUlbHg0EdH04S4gvCJZJC/WnP6guyO2eabhJL88Q==}
|
||||
|
||||
'@umami/redis-client@0.29.0':
|
||||
resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==}
|
||||
|
|
@ -10323,7 +10323,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@umami/react-zen@0.183.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
|
||||
'@umami/react-zen@0.184.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
|
||||
dependencies:
|
||||
'@fontsource/jetbrains-mono': 5.2.8
|
||||
'@internationalized/date': 3.9.0
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Grid, Column, Row, Text, Icon, ProgressBar, Dialog, Box } from '@umami/react-zen';
|
||||
import { useMessages, useResultQuery } from '@/components/hooks';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { File, Lightning, User } from '@/components/icons';
|
||||
import { File, LightningSvg, User } from '@/components/icons';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
import { ReportEditButton } from '@/components/input/ReportEditButton';
|
||||
import { FunnelEditForm } from './FunnelEditForm';
|
||||
|
|
@ -92,7 +92,7 @@ export function Funnel({ id, name, type, parameters, websiteId }) {
|
|||
</Row>
|
||||
<Row alignItems="center" justifyContent="space-between" gap>
|
||||
<Row alignItems="center" gap>
|
||||
<Icon>{type === 'path' ? <File /> : <Lightning />}</Icon>
|
||||
<Icon>{type === 'path' ? <File /> : <LightningSvg />}</Icon>
|
||||
<Text>{value}</Text>
|
||||
</Row>
|
||||
<Row alignItems="center" gap>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
Column,
|
||||
} from '@umami/react-zen';
|
||||
import { useMessages, useReportQuery, useUpdateQuery } from '@/components/hooks';
|
||||
import { Close, Plus } from '@/components/icons';
|
||||
import { X, Plus } from '@/components/icons';
|
||||
import { ActionSelect } from '@/components/input/ActionSelect';
|
||||
import { LookupField } from '@/components/input/LookupField';
|
||||
|
||||
|
|
@ -36,6 +36,8 @@ export function FunnelEditForm({
|
|||
const { mutate, error, isPending, touch } = useUpdateQuery(`/reports${id ? `/${id}` : ''}`);
|
||||
|
||||
const handleSubmit = async ({ name, ...parameters }) => {
|
||||
//
|
||||
|
||||
mutate(
|
||||
{ ...data, id, name, type: 'funnel', websiteId, parameters },
|
||||
{
|
||||
|
|
@ -75,7 +77,13 @@ export function FunnelEditForm({
|
|||
>
|
||||
<TextField />
|
||||
</FormField>
|
||||
<FormFieldArray name="steps" label={formatMessage(labels.steps)}>
|
||||
<FormFieldArray
|
||||
name="steps"
|
||||
label={formatMessage(labels.steps)}
|
||||
rules={{
|
||||
validate: value => value.length > 1 || 'At least two steps are required',
|
||||
}}
|
||||
>
|
||||
{({ fields, append, remove, getValues }) => {
|
||||
return (
|
||||
<Grid gap>
|
||||
|
|
@ -104,7 +112,7 @@ export function FunnelEditForm({
|
|||
</Column>
|
||||
<Button onPress={() => remove(index)}>
|
||||
<Icon size="sm">
|
||||
<Close />
|
||||
<X />
|
||||
</Icon>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { TooltipTrigger, Tooltip, Focusable, Icon, Text, Row, Column } from '@um
|
|||
import { firstBy } from 'thenby';
|
||||
import classNames from 'classnames';
|
||||
import { useEscapeKey, useMessages, useResultQuery } from '@/components/hooks';
|
||||
import { File, Lightning } from '@/components/icons';
|
||||
import { File, LightningSvg } from '@/components/icons';
|
||||
import { objectToArray } from '@/lib/data';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
|
|
@ -215,7 +215,7 @@ export function Journey({ websiteId, steps, startStep, endStep }: JourneyProps)
|
|||
onClick={() => handleClick(name, columnIndex, paths)}
|
||||
>
|
||||
<Row alignItems="center" className={styles.name} title={name} gap>
|
||||
<Icon>{name.startsWith('/') ? <File /> : <Lightning />}</Icon>
|
||||
<Icon>{name.startsWith('/') ? <File /> : <LightningSvg />}</Icon>
|
||||
<Text truncate>{name}</Text>
|
||||
</Row>
|
||||
<div className={styles.count} title={nodeCount}>
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import { useMessages, useNavigation } from '@/components/hooks';
|
|||
import { MetricsExpandedTable } from '@/components/metrics/MetricsExpandedTable';
|
||||
import { SideMenu } from '@/components/common/SideMenu';
|
||||
import {
|
||||
Link,
|
||||
LogOut,
|
||||
LogIn,
|
||||
Search,
|
||||
Type,
|
||||
ArrowRight,
|
||||
SquareSlash,
|
||||
SquareArrowRight,
|
||||
Megaphone,
|
||||
Earth,
|
||||
Globe,
|
||||
|
|
@ -45,7 +45,7 @@ export function WebsiteExpandedView({
|
|||
id: 'path',
|
||||
label: formatMessage(labels.path),
|
||||
path: updateParams({ view: 'path' }),
|
||||
icon: <Link />,
|
||||
icon: <SquareSlash />,
|
||||
},
|
||||
{
|
||||
id: 'entry',
|
||||
|
|
@ -80,7 +80,7 @@ export function WebsiteExpandedView({
|
|||
id: 'referrer',
|
||||
label: formatMessage(labels.referrer),
|
||||
path: updateParams({ view: 'referrer' }),
|
||||
icon: <ArrowRight />,
|
||||
icon: <SquareArrowRight />,
|
||||
},
|
||||
{
|
||||
id: 'channel',
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ import { z } from 'zod';
|
|||
import * as send from '@/app/api/send/route';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { json, serverError } from '@/lib/response';
|
||||
import { anyObjectParam } from '@/lib/schema';
|
||||
|
||||
const schema = z.array(z.object({}).passthrough());
|
||||
const schema = z.array(anyObjectParam);
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { canDeleteWebsite, canUpdateWebsite, canViewWebsite } from '@/permissions';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { json, notFound, ok, unauthorized } from '@/lib/response';
|
||||
import { segmentTypeParam } from '@/lib/schema';
|
||||
import { anyObjectParam, segmentTypeParam } from '@/lib/schema';
|
||||
import { deleteSegment, getSegment, updateSegment } from '@/queries';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ export async function POST(
|
|||
const schema = z.object({
|
||||
type: segmentTypeParam,
|
||||
name: z.string().max(200),
|
||||
parameters: z.object({}).passthrough(),
|
||||
parameters: anyObjectParam,
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { canUpdateWebsite, canViewWebsite } from '@/permissions';
|
|||
import { uuid } from '@/lib/crypto';
|
||||
import { getQueryFilters, parseRequest } from '@/lib/request';
|
||||
import { json, unauthorized } from '@/lib/response';
|
||||
import { segmentTypeParam, searchParams } from '@/lib/schema';
|
||||
import { segmentTypeParam, searchParams, anyObjectParam } from '@/lib/schema';
|
||||
import { createSegment, getWebsiteSegments } from '@/queries';
|
||||
import { z } from 'zod';
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ export async function POST(
|
|||
const schema = z.object({
|
||||
type: segmentTypeParam,
|
||||
name: z.string().max(200),
|
||||
parameters: z.object({}).passthrough(),
|
||||
parameters: anyObjectParam,
|
||||
});
|
||||
|
||||
const { auth, body, error } = await parseRequest(request, schema);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export function WebsiteDateFilter({
|
|||
</Button>
|
||||
</Row>
|
||||
)}
|
||||
<Row width="200px">
|
||||
<Row minWidth="200px">
|
||||
<DateFilter
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export const userRoleParam = z.enum(['admin', 'user', 'view-only']);
|
|||
|
||||
export const teamRoleParam = z.enum(['team-member', 'team-view-only', 'team-manager']);
|
||||
|
||||
export const anyObjectParam = z.object({}).passthrough();
|
||||
export const anyObjectParam = z.record(z.string(), z.any());
|
||||
|
||||
export const urlOrPathParam = z.string().refine(
|
||||
value => {
|
||||
|
|
@ -202,7 +202,7 @@ export const reportBaseSchema = z.object({
|
|||
type: reportTypeParam,
|
||||
name: z.string().max(200),
|
||||
description: z.string().max(500).optional(),
|
||||
parameters: z.object({}).passthrough(),
|
||||
parameters: anyObjectParam,
|
||||
});
|
||||
|
||||
export const reportTypeSchema = z.discriminatedUnion('type', [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue