mirror of
https://github.com/umami-software/umami.git
synced 2026-02-09 07:07:17 +01:00
Updated reports components.
This commit is contained in:
parent
f5bc3dc6c2
commit
0f6cdf8b80
95 changed files with 580 additions and 698 deletions
|
|
@ -9,18 +9,12 @@ import {
|
|||
useFilters,
|
||||
} from '@/components/hooks';
|
||||
import { FieldFilterEditForm } from '@/app/(main)/reports/[reportId]/FieldFilterEditForm';
|
||||
import { OPERATOR_PREFIXES } from '@/lib/constants';
|
||||
import { FILTER_COLUMNS, OPERATOR_PREFIXES } from '@/lib/constants';
|
||||
import { isSearchOperator, parseParameterValue } from '@/lib/params';
|
||||
import styles from './FilterTags.module.css';
|
||||
import { WebsiteFilterButton } from '@/app/(main)/websites/[websiteId]/WebsiteFilterButton';
|
||||
|
||||
export function FilterTags({
|
||||
websiteId,
|
||||
params,
|
||||
}: {
|
||||
websiteId: string;
|
||||
params: { [key: string]: string };
|
||||
}) {
|
||||
export function FilterTags({ websiteId }: { websiteId: string }) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { formatValue } = useFormat();
|
||||
const { dateRange } = useDateRange(websiteId);
|
||||
|
|
@ -32,6 +26,14 @@ export function FilterTags({
|
|||
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;
|
||||
|
|
@ -60,13 +62,13 @@ export function FilterTags({
|
|||
return (
|
||||
<Row
|
||||
gap="3"
|
||||
backgroundColor="1"
|
||||
backgroundColor="2"
|
||||
alignItems="center"
|
||||
paddingX="3"
|
||||
paddingY="2"
|
||||
paddingX="5"
|
||||
paddingY="3"
|
||||
border
|
||||
borderRadius="2"
|
||||
borderSize="1"
|
||||
marginBottom="6"
|
||||
wrap="wrap"
|
||||
>
|
||||
<Text weight="bold">{formatMessage(labels.filters)}</Text>
|
||||
{Object.keys(params).map(key => {
|
||||
|
|
|
|||
|
|
@ -1,37 +1,8 @@
|
|||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.card.compare .change {
|
||||
font-size: 16px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.card:first-child {
|
||||
padding-left: 0;
|
||||
border-right: 1px solid var(--border-color);
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.card:last-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 36px;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
color: var(--base900);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.value.prev {
|
||||
color: var(--base800);
|
||||
}
|
||||
|
||||
.label {
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
color: var(--base800);
|
||||
border-right: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import classNames from 'classnames';
|
||||
import { Text, Column } from '@umami/react-zen';
|
||||
import { useSpring } from '@react-spring/web';
|
||||
import { formatNumber } from '@/lib/format';
|
||||
import { AnimatedDiv } from '@/components/common/AnimatedDiv';
|
||||
|
|
@ -15,7 +15,6 @@ export interface MetricCardProps {
|
|||
showLabel?: boolean;
|
||||
showChange?: boolean;
|
||||
showPrevious?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const MetricCard = ({
|
||||
|
|
@ -27,7 +26,6 @@ export const MetricCard = ({
|
|||
showLabel = true,
|
||||
showChange = false,
|
||||
showPrevious = false,
|
||||
className,
|
||||
}: MetricCardProps) => {
|
||||
const diff = value - change;
|
||||
const pct = ((value - diff) / diff) * 100;
|
||||
|
|
@ -36,26 +34,19 @@ export const MetricCard = ({
|
|||
const prevProps = useSpring({ x: Number(diff) || 0, from: { x: 0 } });
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.card, className, showPrevious && styles.compare)}>
|
||||
{showLabel && <div className={styles.label}>{label}</div>}
|
||||
<AnimatedDiv className={styles.value} title={value?.toString()}>
|
||||
{props?.x?.to(x => formatValue(x))}
|
||||
</AnimatedDiv>
|
||||
<Column className={styles.card} justifyContent="center">
|
||||
{showLabel && <Text weight="bold">{label}</Text>}
|
||||
<Text size="8" weight="bold" wrap="nowrap">
|
||||
<AnimatedDiv title={value?.toString()}>{props?.x?.to(x => formatValue(x))}</AnimatedDiv>
|
||||
</Text>
|
||||
{showChange && (
|
||||
<ChangeLabel
|
||||
className={styles.change}
|
||||
value={change}
|
||||
title={formatValue(change)}
|
||||
reverseColors={reverseColors}
|
||||
>
|
||||
<ChangeLabel value={change} title={formatValue(change)} reverseColors={reverseColors}>
|
||||
<AnimatedDiv>{changeProps?.x?.to(x => `${Math.abs(~~x)}%`)}</AnimatedDiv>
|
||||
</ChangeLabel>
|
||||
)}
|
||||
{showPrevious && (
|
||||
<AnimatedDiv className={classNames(styles.value, styles.prev)} title={diff.toString()}>
|
||||
{prevProps?.x?.to(x => formatValue(x))}
|
||||
</AnimatedDiv>
|
||||
<AnimatedDiv title={diff.toString()}>{prevProps?.x?.to(x => formatValue(x))}</AnimatedDiv>
|
||||
)}
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
.bar {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
|
||||
gap: 20px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.bar {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Loading, Row } from '@umami/react-zen';
|
||||
import { cloneChildren } from '@/lib/react';
|
||||
import { Grid, Loading } from '@umami/react-zen';
|
||||
import { ErrorMessage } from '@/components/common/ErrorMessage';
|
||||
import { formatLongNumber } from '@/lib/format';
|
||||
|
||||
export interface MetricsBarProps {
|
||||
isLoading?: boolean;
|
||||
|
|
@ -12,18 +10,15 @@ export interface MetricsBarProps {
|
|||
}
|
||||
|
||||
export function MetricsBar({ children, isLoading, isFetched, error }: MetricsBarProps) {
|
||||
const formatFunc = n => (n >= 0 ? formatLongNumber(n) : `-${formatLongNumber(Math.abs(n))}`);
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<>
|
||||
{isLoading && !isFetched && <Loading icon="dots" />}
|
||||
{error && <ErrorMessage />}
|
||||
{!isLoading &&
|
||||
!error &&
|
||||
isFetched &&
|
||||
cloneChildren(children, child => {
|
||||
return { format: child?.props['format'] || formatFunc };
|
||||
})}
|
||||
</Row>
|
||||
{!isLoading && !error && isFetched && (
|
||||
<Grid columns="repeat(auto-fill, minmax(200px, 1fr))" width="100%" gapY="3">
|
||||
{children}
|
||||
</Grid>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue