Fix Goal/Funnel wildcard UI bug
This commit is contained in:
1 parent
2709d8e8ea
commit
26e236c95c
4 files changed
+81
-4
No files matched your search
@@ -61,6 +61,7 @@ function StepRow({
|
||||
<LookupField
|
||||
websiteId={websiteId}
|
||||
type={type}
|
||||
allowCustomValue
|
||||
{...field}
|
||||
onValueChange={(v: string) => {
|
||||
setEventName(v);
|
||||
|
||||
@@ -72,7 +72,7 @@ export function GoalEditForm({
|
||||
</FormField>
|
||||
<FormField name="parameters.value" rules={{ required: t(labels.required) }}>
|
||||
{({ field }) => {
|
||||
return <LookupField websiteId={websiteId} type={type} {...field} />;
|
||||
return <LookupField websiteId={websiteId} type={type} allowCustomValue {...field} />;
|
||||
}}
|
||||
</FormField>
|
||||
</Column>
|
||||
@@ -86,7 +86,7 @@ export function GoalEditForm({
|
||||
<Column style={{ minWidth: 0 }}>
|
||||
<FormField name="parameters.value" rules={{ required: t(labels.required) }}>
|
||||
{({ field }) => {
|
||||
return <LookupField websiteId={websiteId} type={type} {...field} />;
|
||||
return <LookupField websiteId={websiteId} type={type} allowCustomValue {...field} />;
|
||||
}}
|
||||
</FormField>
|
||||
</Column>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
import { LookupField } from './LookupField';
|
||||
|
||||
vi.mock('@umami/react-zen', () => ({
|
||||
ListItem: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||||
Loading: () => <div>Loading</div>,
|
||||
useDebounce: (value: string) => value,
|
||||
}));
|
||||
|
||||
vi.mock('@/components/common/ComboBox', () => ({
|
||||
ComboBox: ({
|
||||
'aria-label': ariaLabel,
|
||||
inputValue,
|
||||
onInputValueChange,
|
||||
items,
|
||||
}: {
|
||||
'aria-label'?: string;
|
||||
inputValue: string;
|
||||
onInputValueChange: (value: string) => void;
|
||||
items: string[];
|
||||
}) => (
|
||||
<div>
|
||||
<input
|
||||
aria-label={ariaLabel}
|
||||
value={inputValue}
|
||||
onChange={event => onInputValueChange(event.currentTarget.value)}
|
||||
/>
|
||||
{items.map(item => (
|
||||
<div key={item}>{item}</div>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock('@/components/hooks', () => ({
|
||||
useMessages: () => ({
|
||||
t: (value: string) => value,
|
||||
messages: { noResultsFound: 'No results found' },
|
||||
}),
|
||||
useWebsiteValuesQuery: () => ({ data: [], isLoading: false }),
|
||||
}));
|
||||
|
||||
function TestLookupField() {
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
return (
|
||||
<LookupField
|
||||
websiteId="website-1"
|
||||
type="path"
|
||||
value={value}
|
||||
allowCustomValue
|
||||
onChange={setValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
test('offers a manually entered funnel value as a selectable option', () => {
|
||||
render(<TestLookupField />);
|
||||
|
||||
fireEvent.change(screen.getByLabelText('LookupField'), { target: { value: '/blog/*' } });
|
||||
|
||||
expect(screen.getByText('/blog/*')).toBeInTheDocument();
|
||||
});
|
||||
@@ -9,6 +9,7 @@ export interface LookupFieldProps extends Omit<ComboBoxProps, 'onChange'> {
|
||||
websiteId: string;
|
||||
type: string;
|
||||
value: string;
|
||||
allowCustomValue?: boolean;
|
||||
onChange: (value: string) => void;
|
||||
onValueChange?: (value: string) => void;
|
||||
}
|
||||
@@ -17,6 +18,7 @@ export function LookupField({
|
||||
websiteId,
|
||||
type,
|
||||
value,
|
||||
allowCustomValue,
|
||||
onChange,
|
||||
onValueChange,
|
||||
...props
|
||||
@@ -39,6 +41,14 @@ export function LookupField({
|
||||
return data?.map(({ value }) => value) || [];
|
||||
}, [data]);
|
||||
|
||||
const options = useMemo(() => {
|
||||
if (allowCustomValue && value && !items.includes(value)) {
|
||||
return [value, ...items];
|
||||
}
|
||||
|
||||
return items;
|
||||
}, [allowCustomValue, items, value]);
|
||||
|
||||
const handleSearch = (value: SetStateAction<string>) => {
|
||||
setSearch(value);
|
||||
};
|
||||
@@ -47,7 +57,7 @@ export function LookupField({
|
||||
<ComboBox
|
||||
aria-label="LookupField"
|
||||
{...props}
|
||||
items={items}
|
||||
items={options}
|
||||
inputValue={value}
|
||||
onInputValueChange={value => {
|
||||
handleSearch(value);
|
||||
@@ -62,7 +72,7 @@ export function LookupField({
|
||||
)
|
||||
}
|
||||
>
|
||||
{items.map(item => (
|
||||
{options.map(item => (
|
||||
<ListItem key={item} id={item}>
|
||||
{item}
|
||||
</ListItem>
|
||||
|
||||
Reference in new issue
Block a user