mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 04:37:11 +01:00
More conversions.
This commit is contained in:
parent
5999bf6256
commit
b4be6cb221
14 changed files with 240 additions and 262 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
import { Button, Dropdown, Item, Flexbox } from '@umami/react-zen';
|
||||
import { Button, Select, ListItem, Flexbox } from '@umami/react-zen';
|
||||
import { useLocale, useMessages } from '@/components/hooks';
|
||||
import { DEFAULT_LOCALE } from '@/lib/constants';
|
||||
import { languages } from '@/lib/lang';
|
||||
|
|
@ -20,22 +20,19 @@ export function LanguageSetting() {
|
|||
|
||||
const handleReset = () => saveLocale(DEFAULT_LOCALE);
|
||||
|
||||
const renderValue = (value: string | number) => languages?.[value]?.label;
|
||||
|
||||
return (
|
||||
<Flexbox gap={10}>
|
||||
<Dropdown
|
||||
<Select
|
||||
items={options}
|
||||
value={locale}
|
||||
renderValue={renderValue}
|
||||
onChange={val => saveLocale(val as string)}
|
||||
allowSearch={true}
|
||||
onSearch={setSearch}
|
||||
menuProps={{ className: styles.menu }}
|
||||
>
|
||||
{item => <Item key={item}>{languages[item].label}</Item>}
|
||||
</Dropdown>
|
||||
<Button onClick={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||
{item => <ListItem key={item}>{languages[item].label}</ListItem>}
|
||||
</Select>
|
||||
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||
</Flexbox>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
import { Dropdown, Item, Button, Flexbox } from '@umami/react-zen';
|
||||
import { Row, Select, ListItem, Button } from '@umami/react-zen';
|
||||
import { useTimezone, useMessages } from '@/components/hooks';
|
||||
import { getTimezone } from '@/lib/date';
|
||||
import styles from './TimezoneSetting.module.css';
|
||||
|
|
@ -17,19 +17,22 @@ export function TimezoneSetting() {
|
|||
const handleReset = () => saveTimezone(getTimezone());
|
||||
|
||||
return (
|
||||
<Flexbox gap={10}>
|
||||
<Dropdown
|
||||
<Row gap="3">
|
||||
<Select
|
||||
className={styles.dropdown}
|
||||
items={options}
|
||||
value={timezone}
|
||||
onChange={(value: any) => saveTimezone(value)}
|
||||
menuProps={{ className: styles.menu }}
|
||||
allowSearch={true}
|
||||
onSearch={setSearch}
|
||||
>
|
||||
{item => <Item key={item}>{item}</Item>}
|
||||
</Dropdown>
|
||||
<Button onClick={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||
</Flexbox>
|
||||
{item => (
|
||||
<ListItem key={item} id={item}>
|
||||
{item}
|
||||
</ListItem>
|
||||
)}
|
||||
</Select>
|
||||
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useFields, useMessages } from '@/components/hooks';
|
||||
import { Icons } from '@/components/icons';
|
||||
import { useContext } from 'react';
|
||||
import { Button, FormRow, Icon, Popup, PopupTrigger } from '@umami/react-zen';
|
||||
import { Button, Row, Label, Icon, Popover, MenuTrigger } from '@umami/react-zen';
|
||||
import { FieldSelectForm } from '../[reportId]/FieldSelectForm';
|
||||
import { ParameterList } from '../[reportId]/ParameterList';
|
||||
import { PopupForm } from '../[reportId]/PopupForm';
|
||||
|
|
@ -26,27 +26,26 @@ export function FieldParameters() {
|
|||
|
||||
const AddButton = () => {
|
||||
return (
|
||||
<PopupTrigger>
|
||||
<MenuTrigger>
|
||||
<Button size="sm">
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Popup position="bottom" alignment="start">
|
||||
<PopupForm>
|
||||
<FieldSelectForm
|
||||
fields={fieldOptions.filter(({ name }) => !fields.find(f => f.name === name))}
|
||||
onSelect={handleAdd}
|
||||
showType={false}
|
||||
/>
|
||||
</PopupForm>
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
<Popover placement="start">
|
||||
<FieldSelectForm
|
||||
fields={fieldOptions.filter(({ name }) => !fields.find(f => f.name === name))}
|
||||
onSelect={handleAdd}
|
||||
showType={false}
|
||||
/>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormRow label={formatMessage(labels.fields)} action={<AddButton />}>
|
||||
<Row>
|
||||
<Label>{formatMessage(labels.fields)}</Label>
|
||||
<ParameterList>
|
||||
{fields.map(({ name }) => {
|
||||
return (
|
||||
|
|
@ -56,6 +55,7 @@ export function FieldParameters() {
|
|||
);
|
||||
})}
|
||||
</ParameterList>
|
||||
</FormRow>
|
||||
<AddButton />
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useContext } from 'react';
|
||||
import { useMessages, useFormat, useFilters, useFields } from '@/components/hooks';
|
||||
import { Icons } from '@/components/icons';
|
||||
import { Button, FormRow, Icon, Popup, PopupTrigger } from '@umami/react-zen';
|
||||
import { Button, Text, Row, Label, Icon, Popover, MenuTrigger } from '@umami/react-zen';
|
||||
import { FilterSelectForm } from '../[reportId]/FilterSelectForm';
|
||||
import { ParameterList } from '../[reportId]/ParameterList';
|
||||
import { PopupForm } from '../[reportId]/PopupForm';
|
||||
|
|
@ -44,13 +44,13 @@ export function FilterParameters() {
|
|||
|
||||
const AddButton = () => {
|
||||
return (
|
||||
<PopupTrigger>
|
||||
<MenuTrigger>
|
||||
<Button size="sm">
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Popup position="bottom" alignment="start">
|
||||
<Popover placement="bottom start">
|
||||
<PopupForm>
|
||||
<FilterSelectForm
|
||||
websiteId={websiteId}
|
||||
|
|
@ -60,13 +60,17 @@ export function FilterParameters() {
|
|||
onChange={handleAdd}
|
||||
/>
|
||||
</PopupForm>
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormRow label={formatMessage(labels.filters)} action={<AddButton />}>
|
||||
<>
|
||||
<Row justifyContent="space-between">
|
||||
<Label>{formatMessage(labels.filters)}</Label>
|
||||
<AddButton />
|
||||
</Row>
|
||||
<ParameterList>
|
||||
{filters.map(
|
||||
({ name, operator, value }: { name: string; operator: string; value: string }) => {
|
||||
|
|
@ -90,7 +94,7 @@ export function FilterParameters() {
|
|||
},
|
||||
)}
|
||||
</ParameterList>
|
||||
</FormRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -108,29 +112,27 @@ const FilterParameter = ({
|
|||
const { operatorLabels } = useFilters();
|
||||
|
||||
return (
|
||||
<PopupTrigger>
|
||||
<MenuTrigger>
|
||||
<div className={styles.item}>
|
||||
<div className={styles.label}>{label}</div>
|
||||
<div className={styles.op}>{operatorLabels[operator]}</div>
|
||||
<div className={styles.value}>{value}</div>
|
||||
</div>
|
||||
<Popup className={styles.edit} alignment="start">
|
||||
<Popover className={styles.edit} placement="right top">
|
||||
{(close: any) => (
|
||||
<PopupForm>
|
||||
<FieldFilterEditForm
|
||||
websiteId={websiteId}
|
||||
name={name}
|
||||
label={label}
|
||||
type={type}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
operator={operator}
|
||||
defaultValue={value}
|
||||
onChange={onChange.bind(null, close)}
|
||||
/>
|
||||
</PopupForm>
|
||||
<FieldFilterEditForm
|
||||
websiteId={websiteId}
|
||||
name={name}
|
||||
label={label}
|
||||
type={type}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
operator={operator}
|
||||
defaultValue={value}
|
||||
onChange={onChange.bind(null, close)}
|
||||
/>
|
||||
)}
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useContext, useState } from 'react';
|
||||
import { ReportContext } from './Report';
|
||||
import styles from './ReportMenu.module.css';
|
||||
import { Icon, Icons } from '@umami/react-zen';
|
||||
import classNames from 'classnames';
|
||||
import { ReportContext } from './Report';
|
||||
import styles from './ReportMenu.module.css';
|
||||
|
||||
export function ReportMenu({ children }) {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
|
@ -16,7 +16,7 @@ export function ReportMenu({ children }) {
|
|||
<div className={classNames(styles.menu, collapsed && styles.collapsed)}>
|
||||
<div className={styles.button} onClick={() => setCollapsed(!collapsed)}>
|
||||
<Icon rotate={collapsed ? -90 : 90}>
|
||||
<Icons.ChevronDown />
|
||||
<Icons.Chevron />
|
||||
</Icon>
|
||||
</div>
|
||||
{!collapsed && children}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
import { useState } from 'react';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Button, FormRow, TextField, Flexbox, Dropdown, Item } from '@umami/react-zen';
|
||||
import {
|
||||
Button,
|
||||
Column,
|
||||
Row,
|
||||
TextField,
|
||||
Label,
|
||||
Select,
|
||||
ListItem,
|
||||
FormButtons,
|
||||
} from '@umami/react-zen';
|
||||
import styles from './FunnelStepAddForm.module.css';
|
||||
|
||||
export interface FunnelStepAddFormProps {
|
||||
|
|
@ -39,40 +48,34 @@ export function FunnelStepAddForm({
|
|||
}
|
||||
};
|
||||
|
||||
const renderTypeValue = (value: any) => {
|
||||
return items.find(item => item.value === value)?.label;
|
||||
};
|
||||
|
||||
return (
|
||||
<Flexbox direction="column" gap={10}>
|
||||
<FormRow label={formatMessage(defaultValue ? labels.update : labels.add)}>
|
||||
<Flexbox gap={10}>
|
||||
<Dropdown
|
||||
className={styles.dropdown}
|
||||
items={items}
|
||||
value={type}
|
||||
renderValue={renderTypeValue}
|
||||
onChange={(value: any) => setType(value)}
|
||||
>
|
||||
{({ value, label }) => {
|
||||
return <Item key={value}>{label}</Item>;
|
||||
}}
|
||||
</Dropdown>
|
||||
<TextField
|
||||
className={styles.input}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
autoFocus={true}
|
||||
autoComplete="off"
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Flexbox>
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
<Button variant="primary" onClick={handleSave} disabled={isDisabled}>
|
||||
<Column gap="3">
|
||||
<Label>{formatMessage(defaultValue ? labels.update : labels.add)}</Label>
|
||||
<Row gap="3">
|
||||
<Select
|
||||
className={styles.dropdown}
|
||||
items={items}
|
||||
value={type}
|
||||
onChange={(value: any) => setType(value)}
|
||||
>
|
||||
{({ value, label }: any) => {
|
||||
return <ListItem key={value}>{label}</ListItem>;
|
||||
}}
|
||||
</Select>
|
||||
<TextField
|
||||
className={styles.input}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
autoFocus={true}
|
||||
autoComplete="off"
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Row>
|
||||
<FormButtons>
|
||||
<Button variant="primary" onPress={handleSave} isDisabled={isDisabled}>
|
||||
{formatMessage(defaultValue ? labels.update : labels.add)}
|
||||
</Button>
|
||||
</FormRow>
|
||||
</Flexbox>
|
||||
</FormButtons>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
import { useMessages } from '@/components/hooks';
|
||||
import { useState } from 'react';
|
||||
import { Button, Dropdown, Flexbox, FormRow, Item, TextField } from '@umami/react-zen';
|
||||
import {
|
||||
Button,
|
||||
Row,
|
||||
Column,
|
||||
Select,
|
||||
Label,
|
||||
ListItem,
|
||||
TextField,
|
||||
FormButtons,
|
||||
} from '@umami/react-zen';
|
||||
import styles from './GoalsAddForm.module.css';
|
||||
|
||||
export function GoalsAddForm({
|
||||
|
|
@ -71,44 +80,43 @@ export function GoalsAddForm({
|
|||
};
|
||||
|
||||
return (
|
||||
<Flexbox direction="column" gap={10}>
|
||||
<FormRow label={formatMessage(defaultValue ? labels.update : labels.add)}>
|
||||
<Flexbox gap={10}>
|
||||
<Dropdown
|
||||
className={styles.dropdown}
|
||||
items={items}
|
||||
value={type}
|
||||
renderValue={renderTypeValue}
|
||||
onChange={(value: any) => setType(value)}
|
||||
>
|
||||
{({ value, label }) => {
|
||||
return <Item key={value}>{label}</Item>;
|
||||
}}
|
||||
</Dropdown>
|
||||
<TextField
|
||||
className={styles.input}
|
||||
value={value}
|
||||
onChange={e => handleChange(e, setValue)}
|
||||
autoFocus={true}
|
||||
autoComplete="off"
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Flexbox>
|
||||
</FormRow>
|
||||
<Column gap="3">
|
||||
<Label>{formatMessage(defaultValue ? labels.update : labels.add)}</Label>
|
||||
<Row gap="3">
|
||||
<Select
|
||||
className={styles.dropdown}
|
||||
items={items}
|
||||
value={type}
|
||||
renderValue={renderTypeValue}
|
||||
onChange={(value: any) => setType(value)}
|
||||
>
|
||||
{({ value, label }: any) => {
|
||||
return <ListItem key={value}>{label}</ListItem>;
|
||||
}}
|
||||
</Select>
|
||||
<TextField
|
||||
className={styles.input}
|
||||
value={value}
|
||||
onChange={e => handleChange(e, setValue)}
|
||||
autoFocus={true}
|
||||
autoComplete="off"
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Row>
|
||||
{type === 'event-data' && (
|
||||
<FormRow label={formatMessage(labels.property)}>
|
||||
<Flexbox gap={10}>
|
||||
<Dropdown
|
||||
<Column>
|
||||
<Label>label={formatMessage(labels.property)}</Label>
|
||||
<Row gap="3">
|
||||
<Select
|
||||
className={styles.dropdown}
|
||||
items={operators}
|
||||
value={operator}
|
||||
renderValue={renderoperatorValue}
|
||||
onChange={(value: any) => setOperator(value)}
|
||||
>
|
||||
{({ value, label }) => {
|
||||
return <Item key={value}>{label}</Item>;
|
||||
{({ value, label }: any) => {
|
||||
return <ListItem key={value}>{label}</ListItem>;
|
||||
}}
|
||||
</Dropdown>
|
||||
</Select>
|
||||
<TextField
|
||||
className={styles.input}
|
||||
value={property}
|
||||
|
|
@ -117,11 +125,12 @@ export function GoalsAddForm({
|
|||
autoComplete="off"
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Flexbox>
|
||||
</FormRow>
|
||||
</Row>
|
||||
</Column>
|
||||
)}
|
||||
<FormRow label={formatMessage(labels.goal)}>
|
||||
<Flexbox gap={10}>
|
||||
<Column>
|
||||
<Label>{formatMessage(labels.goal)}</Label>
|
||||
<Row gap="3">
|
||||
<TextField
|
||||
className={styles.input}
|
||||
value={goal?.toString()}
|
||||
|
|
@ -129,13 +138,13 @@ export function GoalsAddForm({
|
|||
autoComplete="off"
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</Flexbox>
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
<Button variant="primary" onClick={handleSave} disabled={isDisabled}>
|
||||
</Row>
|
||||
</Column>
|
||||
<FormButtons>
|
||||
<Button variant="primary" onPress={handleSave} isDisabled={isDisabled}>
|
||||
{formatMessage(defaultValue ? labels.update : labels.add)}
|
||||
</Button>
|
||||
</FormRow>
|
||||
</Flexbox>
|
||||
</FormButtons>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,17 @@ import { formatNumber } from '@/lib/format';
|
|||
import { useContext } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Flexbox,
|
||||
Form,
|
||||
FormButtons,
|
||||
FormRow,
|
||||
FormField,
|
||||
Icon,
|
||||
Popup,
|
||||
PopupTrigger,
|
||||
SubmitButton,
|
||||
Popover,
|
||||
MenuTrigger,
|
||||
FormSubmitButton,
|
||||
Column,
|
||||
} from '@umami/react-zen';
|
||||
import { BaseParameters } from '../[reportId]/BaseParameters';
|
||||
import { ParameterList } from '../[reportId]/ParameterList';
|
||||
import { PopupForm } from '../[reportId]/PopupForm';
|
||||
import { ReportContext } from '../[reportId]/Report';
|
||||
import { GoalsAddForm } from './GoalsAddForm';
|
||||
import styles from './GoalsParameters.module.css';
|
||||
|
|
@ -60,25 +59,24 @@ export function GoalsParameters() {
|
|||
|
||||
const AddGoalsButton = () => {
|
||||
return (
|
||||
<PopupTrigger>
|
||||
<MenuTrigger>
|
||||
<Button>
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Popup alignment="start">
|
||||
<PopupForm>
|
||||
<GoalsAddForm onChange={handleAddGoals} />
|
||||
</PopupForm>
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
<Popover placement="start">
|
||||
<GoalsAddForm onChange={handleAddGoals} />
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
|
||||
<BaseParameters allowWebsiteSelect={!id} />
|
||||
<FormRow label={formatMessage(labels.goals)} action={<AddGoalsButton />}>
|
||||
<AddGoalsButton />
|
||||
<FormField label={formatMessage(labels.goals)}>
|
||||
<ParameterList>
|
||||
{goals.map(
|
||||
(
|
||||
|
|
@ -92,12 +90,12 @@ export function GoalsParameters() {
|
|||
index: number,
|
||||
) => {
|
||||
return (
|
||||
<PopupTrigger key={index}>
|
||||
<MenuTrigger key={index}>
|
||||
<ParameterList.Item
|
||||
icon={goal.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />}
|
||||
onRemove={() => handleRemoveGoals(index)}
|
||||
>
|
||||
<Flexbox direction="column" gap={5}>
|
||||
<Column>
|
||||
<div className={styles.value}>{goal.value}</div>
|
||||
{goal.type === 'event-data' && (
|
||||
<div className={styles.eventData}>
|
||||
|
|
@ -107,32 +105,28 @@ export function GoalsParameters() {
|
|||
<div className={styles.goal}>
|
||||
{formatMessage(labels.goal)}: {formatNumber(goal.goal)}
|
||||
</div>
|
||||
</Flexbox>
|
||||
</Column>
|
||||
</ParameterList.Item>
|
||||
<Popup alignment="start">
|
||||
{(close: () => void) => (
|
||||
<PopupForm>
|
||||
<GoalsAddForm
|
||||
type={goal.type}
|
||||
value={goal.value}
|
||||
goal={goal.goal}
|
||||
operator={goal.operator}
|
||||
property={goal.property}
|
||||
onChange={handleUpdateGoals.bind(null, close, index)}
|
||||
/>
|
||||
</PopupForm>
|
||||
)}
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
<Popover placement="start">
|
||||
<GoalsAddForm
|
||||
type={goal.type}
|
||||
value={goal.value}
|
||||
goal={goal.goal}
|
||||
operator={goal.operator}
|
||||
property={goal.property}
|
||||
onChange={handleUpdateGoals.bind(null, () => {}, index)}
|
||||
/>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</ParameterList>
|
||||
</FormRow>
|
||||
</FormField>
|
||||
<FormButtons>
|
||||
<SubmitButton variant="primary" disabled={queryDisabled} isLoading={isRunning}>
|
||||
<FormSubmitButton variant="primary" isDisabled={queryDisabled} isLoading={isRunning}>
|
||||
{formatMessage(labels.runQuery)}
|
||||
</SubmitButton>
|
||||
</FormSubmitButton>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useMessages } from '@/components/hooks';
|
||||
import { useContext } from 'react';
|
||||
import { Form, FormButtons, SubmitButton } from '@umami/react-zen';
|
||||
import { Form, FormButtons, FormSubmitButton } from '@umami/react-zen';
|
||||
import { BaseParameters } from '../[reportId]/BaseParameters';
|
||||
import { ReportContext } from '../[reportId]/Report';
|
||||
import { FieldParameters } from '../[reportId]/FieldParameters';
|
||||
|
|
@ -25,9 +25,9 @@ export function InsightsParameters() {
|
|||
{parametersSelected && <FieldParameters />}
|
||||
{parametersSelected && <FilterParameters />}
|
||||
<FormButtons>
|
||||
<SubmitButton variant="primary" disabled={!queryEnabled} isLoading={isRunning}>
|
||||
<FormSubmitButton variant="primary" isDisabled={!queryEnabled} isLoading={isRunning}>
|
||||
{formatMessage(labels.runQuery)}
|
||||
</SubmitButton>
|
||||
</FormSubmitButton>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useContext, useEffect, useState } from 'react';
|
||||
import { GridTable, GridColumn } from '@umami/react-zen';
|
||||
import { DataTable, DataColumn } from '@umami/react-zen';
|
||||
import { useFormat, useMessages } from '@/components/hooks';
|
||||
import { ReportContext } from '../[reportId]/Report';
|
||||
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
|
||||
|
|
@ -24,50 +24,35 @@ export function InsightsTable() {
|
|||
}
|
||||
|
||||
return (
|
||||
<GridTable data={report?.data || []}>
|
||||
<DataTable data={report?.data || []}>
|
||||
{fields.map(({ name, label }) => {
|
||||
return (
|
||||
<GridColumn key={name} name={name} label={label}>
|
||||
<DataColumn key={name} id={name} label={label}>
|
||||
{row => formatValue(row[name], name)}
|
||||
</GridColumn>
|
||||
</DataColumn>
|
||||
);
|
||||
})}
|
||||
<GridColumn name="views" label={formatMessage(labels.views)} width="100px" alignment="end">
|
||||
{row => row?.views?.toLocaleString()}
|
||||
</GridColumn>
|
||||
<GridColumn name="visits" label={formatMessage(labels.visits)} width="100px" alignment="end">
|
||||
{row => row?.visits?.toLocaleString()}
|
||||
</GridColumn>
|
||||
<GridColumn
|
||||
name="visitors"
|
||||
label={formatMessage(labels.visitors)}
|
||||
width="100px"
|
||||
alignment="end"
|
||||
>
|
||||
{row => row?.visitors?.toLocaleString()}
|
||||
</GridColumn>
|
||||
<GridColumn
|
||||
name="bounceRate"
|
||||
label={formatMessage(labels.bounceRate)}
|
||||
width="100px"
|
||||
alignment="end"
|
||||
>
|
||||
{row => {
|
||||
<DataColumn id="views" label={formatMessage(labels.views)} align="end">
|
||||
{(row: any) => row?.views?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="visits" label={formatMessage(labels.visits)} align="end">
|
||||
{(row: any) => row?.visits?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="visitors" label={formatMessage(labels.visitors)} align="end">
|
||||
{(row: any) => row?.visitors?.toLocaleString()}
|
||||
</DataColumn>
|
||||
<DataColumn id="bounceRate" label={formatMessage(labels.bounceRate)} align="end">
|
||||
{(row: any) => {
|
||||
const n = (Math.min(row?.visits, row?.bounces) / row?.visits) * 100;
|
||||
return Math.round(+n) + '%';
|
||||
}}
|
||||
</GridColumn>
|
||||
<GridColumn
|
||||
name="visitDuration"
|
||||
label={formatMessage(labels.visitDuration)}
|
||||
width="100px"
|
||||
alignment="end"
|
||||
>
|
||||
{row => {
|
||||
</DataColumn>
|
||||
<DataColumn id="visitDuration" label={formatMessage(labels.visitDuration)} align="end">
|
||||
{(row: any) => {
|
||||
const n = row?.totaltime / row?.visits;
|
||||
return `${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`;
|
||||
}}
|
||||
</GridColumn>
|
||||
</GridTable>
|
||||
</DataColumn>
|
||||
</DataTable>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import { useContext } from 'react';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import {
|
||||
Dropdown,
|
||||
Select,
|
||||
Form,
|
||||
FormButtons,
|
||||
FormInput,
|
||||
FormRow,
|
||||
Item,
|
||||
SubmitButton,
|
||||
FormField,
|
||||
ListItem,
|
||||
FormSubmitButton,
|
||||
TextField,
|
||||
} from '@umami/react-zen';
|
||||
import { ReportContext } from '../[reportId]/Report';
|
||||
|
|
@ -33,28 +32,29 @@ export function JourneyParameters() {
|
|||
return (
|
||||
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
|
||||
<BaseParameters showDateSelect={true} allowWebsiteSelect={!id} />
|
||||
<FormRow label={formatMessage(labels.steps)}>
|
||||
<FormInput
|
||||
name="steps"
|
||||
rules={{ required: formatMessage(labels.required), pattern: /[0-9]+/, min: 3, max: 7 }}
|
||||
>
|
||||
<Dropdown items={[3, 4, 5, 6, 7]}>{item => <Item key={item}>{item}</Item>}</Dropdown>
|
||||
</FormInput>
|
||||
</FormRow>
|
||||
<FormRow label={formatMessage(labels.startStep)}>
|
||||
<FormInput name="startStep">
|
||||
<TextField autoComplete="off" />
|
||||
</FormInput>
|
||||
</FormRow>
|
||||
<FormRow label={formatMessage(labels.endStep)}>
|
||||
<FormInput name="endStep">
|
||||
<TextField autoComplete="off" />
|
||||
</FormInput>
|
||||
</FormRow>
|
||||
<FormField
|
||||
label={formatMessage(labels.steps)}
|
||||
name="steps"
|
||||
rules={{ required: formatMessage(labels.required), pattern: /[0-9]+/, min: 3, max: 7 }}
|
||||
>
|
||||
<Select items={[3, 4, 5, 6, 7]}>
|
||||
{(item: any) => (
|
||||
<ListItem key={item.toString()} id={item.toString()}>
|
||||
{item}
|
||||
</ListItem>
|
||||
)}
|
||||
</Select>
|
||||
</FormField>
|
||||
<FormField label={formatMessage(labels.startStep)} name="startStep">
|
||||
<TextField autoComplete="off" />
|
||||
</FormField>
|
||||
<FormField label={formatMessage(labels.endStep)} name="endStep">
|
||||
<TextField autoComplete="off" />
|
||||
</FormField>
|
||||
<FormButtons>
|
||||
<SubmitButton variant="primary" disabled={queryDisabled} isLoading={isRunning}>
|
||||
<FormSubmitButton variant="primary" isDisabled={queryDisabled} isLoading={isRunning}>
|
||||
{formatMessage(labels.runQuery)}
|
||||
</SubmitButton>
|
||||
</FormSubmitButton>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ export function RetentionParameters() {
|
|||
|
||||
const { id, parameters } = report || {};
|
||||
const { websiteId, dateRange } = parameters || {};
|
||||
const { startDate } = dateRange || {};
|
||||
const queryDisabled = !websiteId || !dateRange;
|
||||
|
||||
const handleSubmit = (data: any, e: any) => {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,7 @@
|
|||
import { useMessages } from '@/components/hooks';
|
||||
import { useRevenueValues } from '@/components/hooks/queries/useRevenueValues';
|
||||
import { useContext } from 'react';
|
||||
import {
|
||||
Dropdown,
|
||||
Form,
|
||||
FormButtons,
|
||||
FormInput,
|
||||
FormRow,
|
||||
Item,
|
||||
SubmitButton,
|
||||
} from '@umami/react-zen';
|
||||
import { Select, Form, FormButtons, FormField, ListItem, FormSubmitButton } from '@umami/react-zen';
|
||||
import { BaseParameters } from '../[reportId]/BaseParameters';
|
||||
import { ReportContext } from '../[reportId]/Report';
|
||||
|
||||
|
|
@ -35,17 +27,20 @@ export function RevenueParameters() {
|
|||
return (
|
||||
<Form values={parameters} onSubmit={handleSubmit} preventSubmit={true}>
|
||||
<BaseParameters showDateSelect={true} allowWebsiteSelect={!id} />
|
||||
<FormRow label={formatMessage(labels.currency)}>
|
||||
<FormInput name="currency" rules={{ required: formatMessage(labels.required) }}>
|
||||
<Dropdown items={values.map(item => item.currency)}>
|
||||
{item => <Item key={item}>{item}</Item>}
|
||||
</Dropdown>
|
||||
</FormInput>
|
||||
</FormRow>
|
||||
|
||||
<FormField
|
||||
label={formatMessage(labels.currency)}
|
||||
name="currency"
|
||||
rules={{ required: formatMessage(labels.required) }}
|
||||
>
|
||||
<Select items={values.map(item => item.currency)}>
|
||||
{item => <ListItem key={item}>{item}</ListItem>}
|
||||
</Select>
|
||||
</FormField>
|
||||
<FormButtons>
|
||||
<SubmitButton variant="primary" disabled={!queryEnabled} isLoading={isRunning}>
|
||||
<FormSubmitButton variant="primary" isDisabled={!queryEnabled} isLoading={isRunning}>
|
||||
{formatMessage(labels.runQuery)}
|
||||
</SubmitButton>
|
||||
</FormSubmitButton>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { useState, Key } from 'react';
|
||||
import { Dropdown, Item } from '@umami/react-zen';
|
||||
import { Select, ListItem } from '@umami/react-zen';
|
||||
import { useWebsite, useWebsites, useMessages } from '@/components/hooks';
|
||||
import { Empty } from '@/components/common/Empty';
|
||||
import styles from './WebsiteSelect.module.css';
|
||||
|
||||
export function WebsiteSelect({
|
||||
websiteId,
|
||||
|
|
@ -21,10 +20,6 @@ export function WebsiteSelect({
|
|||
|
||||
const queryResult = useWebsites({ teamId }, { search, pageSize: 5 });
|
||||
|
||||
const renderValue = () => {
|
||||
return website?.name;
|
||||
};
|
||||
|
||||
const renderEmpty = () => {
|
||||
return <Empty message={formatMessage(messages.noResultsFound)} />;
|
||||
};
|
||||
|
|
@ -39,20 +34,16 @@ export function WebsiteSelect({
|
|||
};
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
menuProps={{ className: styles.dropdown }}
|
||||
<Select
|
||||
items={queryResult?.result?.data as any[]}
|
||||
value={selectedId as string}
|
||||
renderValue={renderValue}
|
||||
renderEmpty={renderEmpty}
|
||||
onChange={handleSelect}
|
||||
alignment="end"
|
||||
placeholder={formatMessage(labels.selectWebsite)}
|
||||
allowSearch={true}
|
||||
onSearch={handleSearch}
|
||||
isLoading={queryResult.query.isLoading}
|
||||
>
|
||||
{({ id, name }) => <Item key={id}>{name}</Item>}
|
||||
</Dropdown>
|
||||
{({ id, name }: any) => <ListItem key={id}>{name}</ListItem>}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue