mirror of
https://github.com/umami-software/umami.git
synced 2026-02-07 22:27: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
|
|
@ -1,52 +1,14 @@
|
|||
import { MouseEvent } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
Icons,
|
||||
Popover,
|
||||
MenuTrigger,
|
||||
Text,
|
||||
Row,
|
||||
TooltipTrigger,
|
||||
Tooltip,
|
||||
} from '@umami/react-zen';
|
||||
import {
|
||||
useDateRange,
|
||||
useFields,
|
||||
useNavigation,
|
||||
useMessages,
|
||||
useFormat,
|
||||
useFilters,
|
||||
} from '@/components/hooks';
|
||||
import { FieldFilterEditForm } from '@/app/(main)/reports/[reportId]/FieldFilterEditForm';
|
||||
import { FILTER_COLUMNS, OPERATOR_PREFIXES } from '@/lib/constants';
|
||||
import { isSearchOperator, parseParameterValue } from '@/lib/params';
|
||||
import { Button, Icon, Icons, Text, Row, TooltipTrigger, Tooltip } from '@umami/react-zen';
|
||||
import { useNavigation, useMessages, useFormat, useFilters } from '@/components/hooks';
|
||||
import { isSearchOperator } from '@/lib/params';
|
||||
import { WebsiteFilterButton } from '@/app/(main)/websites/[websiteId]/WebsiteFilterButton';
|
||||
|
||||
export function FilterBar({ websiteId }: { websiteId: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { formatValue } = useFormat();
|
||||
const { dateRange } = useDateRange(websiteId);
|
||||
const {
|
||||
router,
|
||||
renderUrl,
|
||||
query: { view },
|
||||
} = useNavigation();
|
||||
const { fields } = useFields();
|
||||
const { operatorLabels } = useFilters();
|
||||
const { startDate, endDate } = dateRange;
|
||||
const { query } = useNavigation();
|
||||
|
||||
const params = Object.keys(query).reduce((obj, key) => {
|
||||
if (FILTER_COLUMNS[key]) {
|
||||
obj[key] = query[key];
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
if (Object.keys(params).filter(key => params[key]).length === 0) {
|
||||
return null;
|
||||
}
|
||||
const { router, renderUrl } = useNavigation();
|
||||
const { filters, operatorLabels } = useFilters();
|
||||
|
||||
const handleCloseFilter = (param: string, e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -54,25 +16,17 @@ export function FilterBar({ websiteId }: { websiteId: string }) {
|
|||
};
|
||||
|
||||
const handleResetFilter = () => {
|
||||
router.push(renderUrl({ view }, true));
|
||||
router.push(renderUrl(false));
|
||||
};
|
||||
|
||||
const handleChangeFilter = (
|
||||
values: { name: string; operator: string; value: string },
|
||||
close: () => void,
|
||||
) => {
|
||||
const { name, operator, value } = values;
|
||||
const prefix = OPERATOR_PREFIXES[operator];
|
||||
|
||||
router.push(renderUrl({ [name]: prefix + value }));
|
||||
close();
|
||||
};
|
||||
if (!filters.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Row
|
||||
className="dark-theme"
|
||||
gap="3"
|
||||
backgroundColor="3"
|
||||
backgroundColor="2"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
paddingY="3"
|
||||
|
|
@ -85,46 +39,26 @@ export function FilterBar({ websiteId }: { websiteId: string }) {
|
|||
<Text color="11" weight="bold">
|
||||
{formatMessage(labels.filters)}
|
||||
</Text>
|
||||
{Object.keys(params).map(key => {
|
||||
if (!params[key]) {
|
||||
return null;
|
||||
}
|
||||
const label = fields.find(f => f.name === key)?.label;
|
||||
const { operator, value } = parseParameterValue(params[key]);
|
||||
{Object.keys(filters).map(key => {
|
||||
const filter = filters[key];
|
||||
const { name, label, operator, value } = filter;
|
||||
const paramValue = isSearchOperator(operator) ? value : formatValue(value, key);
|
||||
|
||||
return (
|
||||
<MenuTrigger key={key}>
|
||||
<Button variant="outline">
|
||||
<Button key={name} variant="outline">
|
||||
<Row alignItems="center" gap="6">
|
||||
<Row alignItems="center" gap="2">
|
||||
<Text weight="bold">{label}</Text>
|
||||
<Text transform="uppercase" color="muted">
|
||||
<Text transform="uppercase" color="11" size="1">
|
||||
{operatorLabels[operator]}
|
||||
</Text>
|
||||
<Text weight="bold">{paramValue}</Text>
|
||||
<Icon onClick={e => handleCloseFilter(key, e)}>
|
||||
<Icons.Close />
|
||||
</Icon>
|
||||
</Row>
|
||||
</Button>
|
||||
<Popover placement="start">
|
||||
{({ close }: any) => {
|
||||
return (
|
||||
<FieldFilterEditForm
|
||||
label={label}
|
||||
type="string"
|
||||
websiteId={websiteId}
|
||||
name={key}
|
||||
operator={operator}
|
||||
defaultValue={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={values => handleChangeFilter(values, close)}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
<Icon onClick={e => handleCloseFilter(name, e)}>
|
||||
<Icons.Close />
|
||||
</Icon>
|
||||
</Row>
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
<WebsiteFilterButton websiteId={websiteId} alignment="center" showText={false} />
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export function PagesTable({ allowFilter, ...props }: PagesTableProps) {
|
|||
const { domain } = useContext(WebsiteContext);
|
||||
|
||||
const handleSelect = (key: any) => {
|
||||
router.push(renderUrl({ view: key }), { scroll: false });
|
||||
router.push(renderUrl({ view: key }));
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export function ReferrersTable({ allowFilter, ...props }: ReferrersTableProps) {
|
|||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
const handleSelect = (key: any) => {
|
||||
router.push(renderUrl({ view: key }), { scroll: false });
|
||||
router.push(renderUrl({ view: key }));
|
||||
};
|
||||
|
||||
const buttons = [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue