mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 20:57:17 +01:00
New settings layouts. Segment management screen.
This commit is contained in:
parent
2dbcf63eeb
commit
eb7b6978d3
70 changed files with 762 additions and 499 deletions
|
|
@ -1,33 +0,0 @@
|
|||
import { useState } from 'react';
|
||||
import { ToggleGroup, ToggleGroupItem, Box } from '@umami/react-zen';
|
||||
|
||||
export interface FilterButtonsProps {
|
||||
items: { id: string; label: string }[];
|
||||
value: string;
|
||||
onChange?: (value: string) => void;
|
||||
}
|
||||
|
||||
export function FilterButtons({ items, value, onChange }: FilterButtonsProps) {
|
||||
const [selected, setSelected] = useState(value);
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
setSelected(value);
|
||||
onChange?.(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<ToggleGroup
|
||||
value={[selected]}
|
||||
onChange={e => handleChange(e[0])}
|
||||
disallowEmptySelection={true}
|
||||
>
|
||||
{items.map(({ id, label }) => (
|
||||
<ToggleGroupItem key={id} id={id}>
|
||||
{label}
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
</ToggleGroup>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
import { useState } from 'react';
|
||||
import { Column, Tabs, TabList, Tab, TabPanel, Row, Button } from '@umami/react-zen';
|
||||
import { useDateRange, useMessages } from '@/components/hooks';
|
||||
import { FieldFilters } from '@/components/input/FieldFilters';
|
||||
import { SegmentFilters } from '@/components/input/SegmentFilters';
|
||||
|
||||
export interface FilterEditFormProps {
|
||||
websiteId?: string;
|
||||
filters: any[];
|
||||
segmentId?: string;
|
||||
onChange?: (params: { filters: any[]; segment: any }) => void;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export function FilterEditForm({
|
||||
websiteId,
|
||||
filters = [],
|
||||
segmentId,
|
||||
onChange,
|
||||
onClose,
|
||||
}: FilterEditFormProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const [currentFilters, setCurrentFilters] = useState(filters);
|
||||
const [currentSegment, setCurrentSegment] = useState(segmentId);
|
||||
|
||||
const {
|
||||
dateRange: { startDate, endDate },
|
||||
} = useDateRange(websiteId);
|
||||
|
||||
const handleReset = () => {
|
||||
setCurrentFilters([]);
|
||||
setCurrentSegment(null);
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
onChange?.({ filters: currentFilters.filter(f => f.value), segment: currentSegment });
|
||||
onClose?.();
|
||||
};
|
||||
|
||||
const handleSegmentChange = (id: string) => {
|
||||
setCurrentSegment(id);
|
||||
};
|
||||
|
||||
return (
|
||||
<Column>
|
||||
<Tabs>
|
||||
<TabList>
|
||||
<Tab id="fields">{formatMessage(labels.fields)}</Tab>
|
||||
<Tab id="segments">{formatMessage(labels.segments)}</Tab>
|
||||
</TabList>
|
||||
<TabPanel id="fields">
|
||||
<FieldFilters
|
||||
websiteId={websiteId}
|
||||
filters={currentFilters}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onSave={setCurrentFilters}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel id="segments">
|
||||
<SegmentFilters
|
||||
websiteId={websiteId}
|
||||
segmentId={currentSegment}
|
||||
onSave={handleSegmentChange}
|
||||
/>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
<Row alignItems="center" justifyContent="space-between" gridColumn="span 2" gap>
|
||||
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
|
||||
<Row alignItems="center" justifyContent="flex-end" gridColumn="span 2" gap>
|
||||
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
<Button variant="primary" onPress={handleSave}>
|
||||
{formatMessage(labels.apply)}
|
||||
</Button>
|
||||
</Row>
|
||||
</Row>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ export function PageHeader({
|
|||
{...props}
|
||||
>
|
||||
<Row alignItems="center" gap="3">
|
||||
{icon && <Icon>{icon}</Icon>}
|
||||
{icon && <Icon size="md">{icon}</Icon>}
|
||||
{title && <Heading size="4">{title}</Heading>}
|
||||
{description && <Text color="muted">{description}</Text>}
|
||||
</Row>
|
||||
|
|
|
|||
|
|
@ -1,27 +1,68 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Text, NavMenu, NavMenuItem, Icon, Row } from '@umami/react-zen';
|
||||
import {
|
||||
Text,
|
||||
Heading,
|
||||
NavMenu,
|
||||
NavMenuItem,
|
||||
Icon,
|
||||
Row,
|
||||
Column,
|
||||
NavMenuGroup,
|
||||
} from '@umami/react-zen';
|
||||
import Link from 'next/link';
|
||||
|
||||
export interface SideMenuProps {
|
||||
items: { id: string; label: string; url: string; icon?: ReactNode }[];
|
||||
items: { label: string; items: { id: string; label: string; icon?: any; path: string }[] }[];
|
||||
title?: string;
|
||||
selectedKey?: string;
|
||||
allowMinimize?: boolean;
|
||||
}
|
||||
|
||||
export function SideMenu({ items, selectedKey }: SideMenuProps) {
|
||||
export function SideMenu({ items, title, selectedKey, allowMinimize, children }: SideMenuProps) {
|
||||
return (
|
||||
<NavMenu highlightColor="3">
|
||||
{items.map(({ id, label, url, icon }) => {
|
||||
return (
|
||||
<Link key={id} href={url}>
|
||||
<NavMenuItem isSelected={id === selectedKey}>
|
||||
<Row alignItems="center" gap>
|
||||
{icon && <Icon>{icon}</Icon>}
|
||||
<Text>{label}</Text>
|
||||
</Row>
|
||||
</NavMenuItem>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</NavMenu>
|
||||
<Column
|
||||
gap
|
||||
padding
|
||||
width="240px"
|
||||
overflowY="auto"
|
||||
justifyContent="space-between"
|
||||
position="sticky"
|
||||
top="0"
|
||||
backgroundColor
|
||||
>
|
||||
{children}
|
||||
{title && (
|
||||
<Row padding>
|
||||
<Heading size="1">{title}</Heading>
|
||||
</Row>
|
||||
)}
|
||||
<NavMenu muteItems={false} gap="6">
|
||||
{items.map(({ label, items }) => {
|
||||
return (
|
||||
<NavMenuGroup
|
||||
title={label}
|
||||
key={label}
|
||||
gap="1"
|
||||
allowMinimize={allowMinimize}
|
||||
marginBottom="3"
|
||||
>
|
||||
{items.map(({ id, label, icon, path }) => {
|
||||
const isSelected = selectedKey === id;
|
||||
|
||||
return (
|
||||
<Link key={id} href={path}>
|
||||
<NavMenuItem isSelected={isSelected}>
|
||||
<Row alignItems="center" gap>
|
||||
<Icon>{icon}</Icon>
|
||||
<Text>{label}</Text>
|
||||
</Row>
|
||||
</NavMenuItem>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</NavMenuGroup>
|
||||
);
|
||||
})}
|
||||
</NavMenu>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue