mirror of
https://github.com/umami-software/umami.git
synced 2026-02-06 21:57:16 +01:00
New filter bar and filter edit form.
This commit is contained in:
parent
47e89afcb4
commit
bfdd3f9525
19 changed files with 300 additions and 150 deletions
|
|
@ -28,7 +28,7 @@ export function LanguageSetting() {
|
|||
return (
|
||||
<Row gap="3">
|
||||
<Select
|
||||
value={locale}
|
||||
selectedKey={locale}
|
||||
onChange={val => saveLocale(val as string)}
|
||||
allowSearch
|
||||
onSearch={setSearch}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function TimezoneSetting() {
|
|||
<Row gap="3">
|
||||
<Select
|
||||
className={styles.dropdown}
|
||||
value={timezone}
|
||||
selectedKey={timezone}
|
||||
onChange={(value: any) => saveTimezone(value)}
|
||||
allowSearch={true}
|
||||
onSearch={setSearch}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {
|
|||
Column,
|
||||
Row,
|
||||
Select,
|
||||
Flexbox,
|
||||
Icon,
|
||||
Icons,
|
||||
Loading,
|
||||
|
|
@ -130,15 +129,17 @@ export function FieldFilterEditForm({
|
|||
window.setTimeout(() => setShowMenu(false), 500);
|
||||
};
|
||||
|
||||
const items = filterDropdownItems(name);
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<Row className={styles.filter}>
|
||||
<Label>{label}</Label>
|
||||
<Flexbox gap="3">
|
||||
<Row gap="3">
|
||||
{allowFilterSelect && (
|
||||
<Select
|
||||
className={styles.dropdown}
|
||||
items={filterDropdownItems(name)}
|
||||
items={items}
|
||||
value={operator}
|
||||
onChange={handleOperatorChange}
|
||||
>
|
||||
|
|
@ -183,7 +184,7 @@ export function FieldFilterEditForm({
|
|||
onChange={e => setValue(e.target.value)}
|
||||
/>
|
||||
)}
|
||||
</Flexbox>
|
||||
</Row>
|
||||
<Button variant="primary" onPress={handleAdd} isDisabled={isDisabled}>
|
||||
{formatMessage(isNew ? labels.add : labels.update)}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ export function FieldSelectForm({ fields = [], onSelect, showType = true }: Fiel
|
|||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
<MenuSection title={formatMessage(labels.fields)}>
|
||||
<Menu onAction={value => onSelect?.(value)}>
|
||||
<MenuSection title={formatMessage(labels.fields)} selectionMode="multiple">
|
||||
{fields.map(({ name, label, type }) => {
|
||||
return (
|
||||
<MenuItem key={name} id={name} onAction={() => onSelect(name)}>
|
||||
<MenuItem key={name} id={name}>
|
||||
<Row alignItems="center" justifyContent="space-between">
|
||||
<Text>{label || name}</Text>
|
||||
{showType && type && <Text color="muted">{type}</Text>}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export function FilterSelectForm({
|
|||
return (
|
||||
<FieldFilterEditForm
|
||||
websiteId={websiteId}
|
||||
name={name}
|
||||
name={name || 'url'}
|
||||
label={label}
|
||||
type={type}
|
||||
startDate={startDate}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Button, Icon, Icons, MenuTrigger, Popover, Text } from '@umami/react-zen';
|
||||
import { FilterSelectForm } from '@/app/(main)/reports/[reportId]/FilterSelectForm';
|
||||
import { useFields, useMessages, useNavigation, useDateRange } from '@/components/hooks';
|
||||
import { OPERATOR_PREFIXES } from '@/lib/constants';
|
||||
import { Button, Icon, Icons, DialogTrigger, Dialog, Modal, Text } from '@umami/react-zen';
|
||||
import { FilterEditForm } from '@/components/common/FilterEditForm';
|
||||
import { useMessages, useNavigation, useFilters } from '@/components/hooks';
|
||||
import { OPERATORS } from '@/lib/constants';
|
||||
|
||||
export function WebsiteFilterButton({
|
||||
websiteId,
|
||||
|
|
@ -14,41 +14,44 @@ export function WebsiteFilterButton({
|
|||
}) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { renderUrl, router } = useNavigation();
|
||||
const { fields } = useFields();
|
||||
const {
|
||||
dateRange: { startDate, endDate },
|
||||
} = useDateRange(websiteId);
|
||||
const { filters } = useFilters();
|
||||
|
||||
const handleAddFilter = ({ name, operator, value }) => {
|
||||
const prefix = OPERATOR_PREFIXES[operator];
|
||||
const handleChange = (filters: any[]) => {
|
||||
const params = filters.reduce((obj, filter) => {
|
||||
const { name, operator, value } = filter;
|
||||
|
||||
router.push(renderUrl({ [name]: prefix + value }));
|
||||
obj[name] = operator === OPERATORS.equals ? value : `${operator}~${value}`;
|
||||
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
const url = renderUrl(params);
|
||||
|
||||
router.push(url);
|
||||
};
|
||||
|
||||
return (
|
||||
<MenuTrigger>
|
||||
<DialogTrigger>
|
||||
<Button variant="quiet">
|
||||
<Icon>
|
||||
<Icons.Plus />
|
||||
</Icon>
|
||||
{showText && <Text>{formatMessage(labels.filter)}</Text>}
|
||||
</Button>
|
||||
<Popover placement="bottom start">
|
||||
{({ close }: any) => {
|
||||
return (
|
||||
<FilterSelectForm
|
||||
websiteId={websiteId}
|
||||
fields={fields}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={value => {
|
||||
handleAddFilter(value);
|
||||
close();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
<Modal>
|
||||
<Dialog>
|
||||
{({ close }) => {
|
||||
return (
|
||||
<FilterEditForm
|
||||
websiteId={websiteId}
|
||||
data={filters}
|
||||
onChange={handleChange}
|
||||
onClose={close}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</DialogTrigger>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function EventsPage({ websiteId }) {
|
|||
<EventsMetricsBar websiteId={websiteId} />
|
||||
</Panel>
|
||||
<GridRow layout="two-one">
|
||||
<Panel>
|
||||
<Panel gridColumn="span 2">
|
||||
<EventsChart websiteId={websiteId} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function SessionsPage({ websiteId }) {
|
|||
<SessionsMetricsBar websiteId={websiteId} />
|
||||
</Panel>
|
||||
<GridRow layout="two-one">
|
||||
<Panel padding="0">
|
||||
<Panel padding="0" gridColumn="span 2">
|
||||
<WorldMap websiteId={websiteId} />
|
||||
</Panel>
|
||||
<Panel>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue