mirror of
https://github.com/umami-software/umami.git
synced 2026-02-07 14:17:13 +01:00
Zen components conversion.
This commit is contained in:
parent
aac1a12e51
commit
5999bf6256
142 changed files with 1235 additions and 1454 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { useMemo } from 'react';
|
||||
import { StatusLight } from 'react-basics';
|
||||
import { StatusLight } from '@umami/react-zen';
|
||||
import { useApi } from '@/components/hooks';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import styles from './ActiveUsers.module.css';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import classNames from 'classnames';
|
||||
import { Icon, Icons } from 'react-basics';
|
||||
import { Icon, Icons } from '@umami/react-zen';
|
||||
import { ReactNode } from 'react';
|
||||
import styles from './ChangeLabel.module.css';
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ export function ChangeLabel({
|
|||
>
|
||||
{!neutral && (
|
||||
<Icon rotate={positive ? -90 : 90} size={size}>
|
||||
<Icons.ArrowRight />
|
||||
<Icons.Arrow />
|
||||
</Icon>
|
||||
)}
|
||||
{children || value}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useState } from 'react';
|
||||
import { Button, ButtonGroup, Calendar } from 'react-basics';
|
||||
import { Button, Row, Calendar } from '@umami/react-zen';
|
||||
import { isAfter, isBefore, isSameDay, startOfDay, endOfDay } from 'date-fns';
|
||||
import { useLocale } from '@/components/hooks';
|
||||
import { FILTER_DAY, FILTER_RANGE } from '@/lib/constants';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { parseDate } from '@internationalized/date';
|
||||
import styles from './DatePickerForm.module.css';
|
||||
|
||||
export function DatePickerForm({
|
||||
|
|
@ -17,10 +17,9 @@ export function DatePickerForm({
|
|||
const [selected, setSelected] = useState(
|
||||
isSameDay(defaultStartDate, defaultEndDate) ? FILTER_DAY : FILTER_RANGE,
|
||||
);
|
||||
const [singleDate, setSingleDate] = useState(defaultStartDate);
|
||||
const [startDate, setStartDate] = useState(defaultStartDate);
|
||||
const [endDate, setEndDate] = useState(defaultEndDate);
|
||||
const { dateLocale } = useLocale();
|
||||
const [singleDate, setSingleDate] = useState(defaultStartDate || new Date());
|
||||
const [startDate, setStartDate] = useState(defaultStartDate || new Date());
|
||||
const [endDate, setEndDate] = useState(defaultEndDate || new Date());
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
const disabled =
|
||||
|
|
@ -36,48 +35,41 @@ export function DatePickerForm({
|
|||
}
|
||||
};
|
||||
|
||||
console.log({ minDate, maxDate, singleDate, startDate, endDate, disabled });
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.filter}>
|
||||
<ButtonGroup selectedKey={selected} onSelect={key => setSelected(key as any)}>
|
||||
<Button key={FILTER_DAY}>{formatMessage(labels.singleDay)}</Button>
|
||||
<Button key={FILTER_RANGE}>{formatMessage(labels.dateRange)}</Button>
|
||||
</ButtonGroup>
|
||||
<Row>
|
||||
<Button key={FILTER_DAY} onPress={key => setSelected(key as any)}>
|
||||
{formatMessage(labels.singleDay)}
|
||||
</Button>
|
||||
<Button key={FILTER_RANGE} onPress={key => setSelected(key as any)}>
|
||||
{formatMessage(labels.dateRange)}
|
||||
</Button>
|
||||
</Row>
|
||||
</div>
|
||||
<div className={styles.calendars}>
|
||||
{selected === FILTER_DAY && (
|
||||
<Calendar
|
||||
date={singleDate}
|
||||
minDate={minDate}
|
||||
maxDate={maxDate}
|
||||
locale={dateLocale}
|
||||
onChange={setSingleDate}
|
||||
value={parseDate(singleDate.toISOString().split('T')[0])}
|
||||
onChange={d => setSingleDate(d.toDate('America/Los_Angeles'))}
|
||||
/>
|
||||
)}
|
||||
{selected === FILTER_RANGE && (
|
||||
<>
|
||||
<Calendar
|
||||
date={startDate}
|
||||
minDate={minDate}
|
||||
maxDate={endDate}
|
||||
locale={dateLocale}
|
||||
onChange={setStartDate}
|
||||
/>
|
||||
<Calendar
|
||||
date={endDate}
|
||||
minDate={startDate}
|
||||
maxDate={maxDate}
|
||||
locale={dateLocale}
|
||||
onChange={setEndDate}
|
||||
value={parseDate(startDate.toISOString().split('T')[0])}
|
||||
onChange={d => setStartDate(d.toDate('America/Los_Angeles'))}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.buttons}>
|
||||
<Button variant="primary" onClick={handleSave} disabled={disabled}>
|
||||
<Button variant="primary" onPress={handleSave} isDisabled={disabled}>
|
||||
{formatMessage(labels.save)}
|
||||
</Button>
|
||||
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { MouseEvent } from 'react';
|
||||
import { Button, Icon, Icons, Popup, PopupTrigger, Text } from 'react-basics';
|
||||
import { Button, Icon, Icons, Popover, MenuTrigger, Text, Row } from '@umami/react-zen';
|
||||
import {
|
||||
useDateRange,
|
||||
useFields,
|
||||
|
|
@ -8,7 +8,6 @@ import {
|
|||
useFormat,
|
||||
useFilters,
|
||||
} from '@/components/hooks';
|
||||
import { PopupForm } from '@/app/(main)/reports/[reportId]/PopupForm';
|
||||
import { FieldFilterEditForm } from '@/app/(main)/reports/[reportId]/FieldFilterEditForm';
|
||||
import { OPERATOR_PREFIXES } from '@/lib/constants';
|
||||
import { isSearchOperator, parseParameterValue } from '@/lib/params';
|
||||
|
|
@ -59,8 +58,17 @@ export function FilterTags({
|
|||
};
|
||||
|
||||
return (
|
||||
<div className={styles.filters}>
|
||||
<div className={styles.label}>{formatMessage(labels.filters)}</div>
|
||||
<Row
|
||||
gap="3"
|
||||
backgroundColor="1"
|
||||
alignItems="center"
|
||||
paddingX="3"
|
||||
paddingY="2"
|
||||
borderRadius="2"
|
||||
borderSize="1"
|
||||
marginBottom="6"
|
||||
>
|
||||
<Text weight="bold">{formatMessage(labels.filters)}</Text>
|
||||
{Object.keys(params).map(key => {
|
||||
if (!params[key]) {
|
||||
return null;
|
||||
|
|
@ -70,44 +78,44 @@ export function FilterTags({
|
|||
const paramValue = isSearchOperator(operator) ? value : formatValue(value, key);
|
||||
|
||||
return (
|
||||
<PopupTrigger key={key}>
|
||||
<div key={key} className={styles.tag}>
|
||||
<Text className={styles.name}>{label}</Text>
|
||||
<Text className={styles.operator}>{operatorLabels[operator]}</Text>
|
||||
<Text className={styles.value}>{paramValue}</Text>
|
||||
<Icon className={styles.icon} onClick={e => handleCloseFilter(key, e)}>
|
||||
<Icons.Close />
|
||||
</Icon>
|
||||
</div>
|
||||
<Popup alignment="start">
|
||||
{(close: () => void) => {
|
||||
<MenuTrigger key={key}>
|
||||
<Button variant="outline">
|
||||
<Row alignItems="center" gap="3">
|
||||
<Text weight="bold">{label}</Text>
|
||||
<Text>{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 (
|
||||
<PopupForm>
|
||||
<FieldFilterEditForm
|
||||
label={label}
|
||||
type="string"
|
||||
websiteId={websiteId}
|
||||
name={key}
|
||||
operator={operator}
|
||||
defaultValue={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={values => handleChangeFilter(values, close)}
|
||||
/>
|
||||
</PopupForm>
|
||||
<FieldFilterEditForm
|
||||
label={label}
|
||||
type="string"
|
||||
websiteId={websiteId}
|
||||
name={key}
|
||||
operator={operator}
|
||||
defaultValue={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={values => handleChangeFilter(values, close)}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Popup>
|
||||
</PopupTrigger>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
);
|
||||
})}
|
||||
<WebsiteFilterButton websiteId={websiteId} alignment="center" showText={false} />
|
||||
<Button className={styles.close} variant="quiet" onClick={handleResetFilter}>
|
||||
<Button className={styles.close} variant="quiet" onPress={handleResetFilter}>
|
||||
<Icon>
|
||||
<Icons.Close />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.clearAll)}</Text>
|
||||
</Button>
|
||||
</div>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { MetricsTable, MetricsTableProps } from './MetricsTable';
|
||||
import { FilterLink } from '@/components/common/FilterLink';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Flexbox } from 'react-basics';
|
||||
import { Flexbox } from '@umami/react-zen';
|
||||
|
||||
export function HostsTable(props: MetricsTableProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { StatusLight } from 'react-basics';
|
||||
import { StatusLight } from '@umami/react-zen';
|
||||
import { colord } from 'colord';
|
||||
import classNames from 'classnames';
|
||||
import { LegendItem } from 'chart.js/auto';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Loading, cloneChildren } from 'react-basics';
|
||||
import { Loading, Row } from '@umami/react-zen';
|
||||
import { cloneChildren } from '@/lib/react';
|
||||
import { ErrorMessage } from '@/components/common/ErrorMessage';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
import styles from './MetricsBar.module.css';
|
||||
|
||||
export interface MetricsBarProps {
|
||||
isLoading?: boolean;
|
||||
|
|
@ -15,15 +15,15 @@ export function MetricsBar({ children, isLoading, isFetched, error }: MetricsBar
|
|||
const formatFunc = n => (n >= 0 ? formatLongNumber(n) : `-${formatLongNumber(Math.abs(n))}`);
|
||||
|
||||
return (
|
||||
<div className={styles.bar}>
|
||||
<Row>
|
||||
{isLoading && !isFetched && <Loading icon="dots" />}
|
||||
{error && <ErrorMessage />}
|
||||
{!isLoading &&
|
||||
!error &&
|
||||
isFetched &&
|
||||
cloneChildren(children, child => {
|
||||
return { format: child.props.format || formatFunc };
|
||||
return { format: child.props['format'] || formatFunc };
|
||||
})}
|
||||
</div>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,11 @@
|
|||
import { ReactNode, useMemo, useState } from 'react';
|
||||
import { Loading, Icon, Text, SearchField } from 'react-basics';
|
||||
import { Loading, Icon, Text, SearchField } from '@umami/react-zen';
|
||||
import classNames from 'classnames';
|
||||
import { ErrorMessage } from '@/components/common/ErrorMessage';
|
||||
import { LinkButton } from '@/components/common/LinkButton';
|
||||
import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants';
|
||||
import { percentFilter } from '@/lib/filters';
|
||||
import {
|
||||
useNavigation,
|
||||
useWebsiteMetrics,
|
||||
useMessages,
|
||||
useLocale,
|
||||
useFormat,
|
||||
} from '@/components/hooks';
|
||||
import { useNavigation, useWebsiteMetrics, useMessages, useFormat } from '@/components/hooks';
|
||||
import { Icons } from '@/components/icons';
|
||||
import { ListTable, ListTableProps } from './ListTable';
|
||||
import styles from './MetricsTable.module.css';
|
||||
|
|
@ -51,7 +45,6 @@ export function MetricsTable({
|
|||
const { formatValue } = useFormat();
|
||||
const { renderUrl } = useNavigation();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { dir } = useLocale();
|
||||
|
||||
const { data, isLoading, isFetched, error } = useWebsiteMetrics(
|
||||
websiteId,
|
||||
|
|
@ -114,8 +107,8 @@ export function MetricsTable({
|
|||
{showMore && data && !error && limit && (
|
||||
<LinkButton href={renderUrl({ view: type })} variant="quiet">
|
||||
<Text>{formatMessage(labels.more)}</Text>
|
||||
<Icon size="sm" rotate={dir === 'rtl' ? 180 : 0}>
|
||||
<Icons.ArrowRight />
|
||||
<Icon size="sm">
|
||||
<Icons.Arrow />
|
||||
</Icon>
|
||||
</LinkButton>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { MetricsTable, MetricsTableProps } from './MetricsTable';
|
|||
import { FilterButtons } from '@/components/common/FilterButtons';
|
||||
import thenby from 'thenby';
|
||||
import { GROUPED_DOMAINS } from '@/lib/constants';
|
||||
import { Flexbox } from 'react-basics';
|
||||
import { Flexbox } from '@umami/react-zen';
|
||||
|
||||
export interface ReferrersTableProps extends MetricsTableProps {
|
||||
allowFilter?: boolean;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { MetricsTable, MetricsTableProps } from './MetricsTable';
|
||||
import { FilterLink } from '@/components/common/FilterLink';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Flexbox } from 'react-basics';
|
||||
import { Flexbox } from '@umami/react-zen';
|
||||
|
||||
export function TagsTable(props: MetricsTableProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue