mirror of
https://github.com/kremalicious/umami.git
synced 2025-01-04 19:15:09 +01:00
Added grid layout components.
This commit is contained in:
parent
e30f2dfb44
commit
910481e629
31
components/layout/GridLayout.js
Normal file
31
components/layout/GridLayout.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styles from './GridLayout.module.css';
|
||||
|
||||
export default function GridLayout({ className, children }) {
|
||||
return <div className={classNames(styles.grid, className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export const GridRow = ({ className, children }) => {
|
||||
return <div className={classNames(styles.row, className, 'row')}>{children}</div>;
|
||||
};
|
||||
|
||||
export const GridColumn = ({ xs, sm, md, lg, xl, className, children }) => {
|
||||
const classes = [];
|
||||
|
||||
classes.push(xs ? `col-${xs}` : 'col');
|
||||
|
||||
if (sm) {
|
||||
classes.push(`col-sm-${sm}`);
|
||||
}
|
||||
if (md) {
|
||||
classes.push(`col-md-${md}`);
|
||||
}
|
||||
if (lg) {
|
||||
classes.push(`col-lg-${lg}`);
|
||||
}
|
||||
if (xl) {
|
||||
classes.push(`col-lg-${xl}`);
|
||||
}
|
||||
return <div className={classNames(styles.col, classes, className)}>{children}</div>;
|
||||
};
|
40
components/layout/GridLayout.module.css
Normal file
40
components/layout/GridLayout.module.css
Normal file
@ -0,0 +1,40 @@
|
||||
.grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.row {
|
||||
border-top: 1px solid var(--gray300);
|
||||
min-height: 430px;
|
||||
}
|
||||
|
||||
.row > .col {
|
||||
border-left: 1px solid var(--gray300);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.row > .col:first-child {
|
||||
border-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.row > .col:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
.row {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.row > .col {
|
||||
border-top: 1px solid var(--gray300);
|
||||
border-left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import useTimezone from 'hooks/useTimezone';
|
||||
import usePageQuery from 'hooks/usePageQuery';
|
||||
import { EVENT_COLORS } from 'lib/constants';
|
||||
|
||||
export default function EventsChart({ websiteId, token }) {
|
||||
export default function EventsChart({ websiteId, className, token }) {
|
||||
const [dateRange] = useDateRange(websiteId);
|
||||
const { startDate, endDate, unit, modified } = dateRange;
|
||||
const [timezone] = useTimezone();
|
||||
@ -79,6 +79,7 @@ export default function EventsChart({ websiteId, token }) {
|
||||
return (
|
||||
<BarChart
|
||||
chartId={`events-${websiteId}`}
|
||||
className={className}
|
||||
datasets={datasets}
|
||||
unit={unit}
|
||||
records={getDateLength(startDate, endDate, unit)}
|
||||
|
@ -119,6 +119,9 @@ export default function RealtimeLog({ data, websites }) {
|
||||
|
||||
return (
|
||||
<div className={styles.log}>
|
||||
<div className={styles.header}>
|
||||
<FormattedMessage id="label.realtime-logs" defaultMessage="Realtime logs" />
|
||||
</div>
|
||||
<Table
|
||||
className={styles.table}
|
||||
bodyClassName={styles.body}
|
||||
@ -126,7 +129,7 @@ export default function RealtimeLog({ data, websites }) {
|
||||
rows={logs}
|
||||
showHeader={false}
|
||||
>
|
||||
<FixedSizeList height={300} itemCount={logs.length} itemSize={46}>
|
||||
<FixedSizeList height={400} itemCount={logs.length} itemSize={46}>
|
||||
{Row}
|
||||
</FixedSizeList>
|
||||
</Table>
|
||||
|
@ -2,13 +2,20 @@
|
||||
font-size: var(--font-size-xsmall);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
line-height: 40px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--gray300);
|
||||
}
|
||||
|
||||
.body {
|
||||
height: 600px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { subMinutes, startOfMinute } from 'date-fns';
|
||||
import Page from 'components/layout/Page';
|
||||
import useFetch from 'hooks/useFetch';
|
||||
import GridLayout, { GridRow, GridColumn } from 'components/layout/GridLayout';
|
||||
import RealtimeChart from '../metrics/RealtimeChart';
|
||||
import RealtimeLog from '../metrics/RealtimeLog';
|
||||
import styles from './RealtimeDashboard.module.css';
|
||||
import RealtimeHeader from '../metrics/RealtimeHeader';
|
||||
import useFetch from 'hooks/useFetch';
|
||||
|
||||
const REALTIME_RANGE = 30;
|
||||
const REALTIME_INTERVAL = 5000;
|
||||
@ -36,10 +36,22 @@ export default function RealtimeDashboard() {
|
||||
const realtimeData = useMemo(() => {
|
||||
if (websiteId) {
|
||||
const { pageviews, sessions, events, ...props } = data;
|
||||
const countries = sessions.reduce((obj, { country }) => {
|
||||
if (country) {
|
||||
if (!obj[country]) {
|
||||
obj[country] = 1;
|
||||
} else {
|
||||
obj[country] += 1;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
pageviews: filterWebsite(pageviews, websiteId),
|
||||
sessions: filterWebsite(sessions, websiteId),
|
||||
events: filterWebsite(events, websiteId),
|
||||
countries,
|
||||
...props,
|
||||
};
|
||||
}
|
||||
@ -83,12 +95,24 @@ export default function RealtimeDashboard() {
|
||||
records={REALTIME_RANGE}
|
||||
/>
|
||||
</div>
|
||||
<div className={classNames(styles.tables, 'row')}>
|
||||
<div className="col-12 col-lg-8">
|
||||
<RealtimeLog data={realtimeData} websites={websites} />
|
||||
</div>
|
||||
<div className="col-12 col-lg-4">hi.</div>
|
||||
</div>
|
||||
<GridLayout>
|
||||
<GridRow>
|
||||
<GridColumn xs={12} lg={8}>
|
||||
<RealtimeLog data={realtimeData} websites={websites} />
|
||||
</GridColumn>
|
||||
<GridColumn xs={12} lg={4}>
|
||||
x
|
||||
</GridColumn>
|
||||
</GridRow>
|
||||
<GridRow>
|
||||
<GridColumn xs={12} lg={4}>
|
||||
x
|
||||
</GridColumn>
|
||||
<GridColumn xs={12} lg={8}>
|
||||
x
|
||||
</GridColumn>
|
||||
</GridRow>
|
||||
</GridLayout>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import classNames from 'classnames';
|
||||
import WebsiteChart from 'components/metrics/WebsiteChart';
|
||||
import WorldMap from 'components/common/WorldMap';
|
||||
import Page from 'components/layout/Page';
|
||||
import GridLayout, { GridRow, GridColumn } from 'components/layout/GridLayout';
|
||||
import MenuLayout from 'components/layout/MenuLayout';
|
||||
import Link from 'components/common/Link';
|
||||
import Loading from 'components/common/Loading';
|
||||
@ -19,6 +20,7 @@ import EventsTable from '../metrics/EventsTable';
|
||||
import EventsChart from '../metrics/EventsChart';
|
||||
import useFetch from 'hooks/useFetch';
|
||||
import usePageQuery from 'hooks/usePageQuery';
|
||||
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
|
||||
|
||||
const views = {
|
||||
url: PagesTable,
|
||||
@ -100,7 +102,7 @@ export default function WebsiteDetails({ websiteId, token }) {
|
||||
|
||||
function handleDataLoad() {
|
||||
if (!chartLoaded) {
|
||||
setTimeout(() => setChartLoaded(true), 300);
|
||||
setTimeout(() => setChartLoaded(true), DEFAULT_ANIMATION_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,45 +126,43 @@ export default function WebsiteDetails({ websiteId, token }) {
|
||||
</div>
|
||||
{!chartLoaded && <Loading />}
|
||||
{chartLoaded && !view && (
|
||||
<>
|
||||
<div className={classNames(styles.row, 'row')}>
|
||||
<div className="col-md-12 col-lg-6">
|
||||
<GridLayout>
|
||||
<GridRow>
|
||||
<GridColumn md={12} lg={6}>
|
||||
<PagesTable {...tableProps} />
|
||||
</div>
|
||||
<div className="col-md-12 col-lg-6">
|
||||
</GridColumn>
|
||||
<GridColumn md={12} lg={6}>
|
||||
<ReferrersTable {...tableProps} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={classNames(styles.row, 'row')}>
|
||||
<div className="col-md-12 col-lg-4">
|
||||
</GridColumn>
|
||||
</GridRow>
|
||||
<GridRow>
|
||||
<GridColumn md={12} lg={4}>
|
||||
<BrowsersTable {...tableProps} />
|
||||
</div>
|
||||
<div className="col-md-12 col-lg-4">
|
||||
</GridColumn>
|
||||
<GridColumn md={12} lg={4}>
|
||||
<OSTable {...tableProps} />
|
||||
</div>
|
||||
<div className="col-md-12 col-lg-4">
|
||||
</GridColumn>
|
||||
<GridColumn md={12} lg={4}>
|
||||
<DevicesTable {...tableProps} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={classNames(styles.row, 'row')}>
|
||||
<div className="col-12 col-md-12 col-lg-8">
|
||||
</GridColumn>
|
||||
</GridRow>
|
||||
<GridRow>
|
||||
<GridColumn xs={12} md={12} lg={8}>
|
||||
<WorldMap data={countryData} />
|
||||
</div>
|
||||
<div className="col-12 col-md-12 col-lg-4">
|
||||
</GridColumn>
|
||||
<GridColumn xs={12} md={12} lg={4}>
|
||||
<CountriesTable {...tableProps} onDataLoad={setCountryData} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.row, 'row', { [styles.hidden]: !eventsData?.length > 0 })}
|
||||
>
|
||||
<div className="col-12 col-md-12 col-lg-4">
|
||||
</GridColumn>
|
||||
</GridRow>
|
||||
<GridRow className={classNames({ [styles.hidden]: !eventsData?.length > 0 })}>
|
||||
<GridColumn xs={12} md={12} lg={4}>
|
||||
<EventsTable {...tableProps} onDataLoad={setEventsData} />
|
||||
</div>
|
||||
<div className="col-12 col-md-12 col-lg-8 pt-5 pb-5">
|
||||
<EventsChart websiteId={websiteId} token={token} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</GridColumn>
|
||||
<GridColumn xs={12} md={12} lg={8}>
|
||||
<EventsChart className={styles.eventschart} websiteId={websiteId} token={token} />
|
||||
</GridColumn>
|
||||
</GridRow>
|
||||
</GridLayout>
|
||||
)}
|
||||
{view && (
|
||||
<MenuLayout
|
||||
|
@ -26,37 +26,10 @@
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.row {
|
||||
border-top: 1px solid var(--gray300);
|
||||
min-height: 430px;
|
||||
}
|
||||
|
||||
.row > [class*='col-'] {
|
||||
border-left: 1px solid var(--gray300);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.row > [class*='col-']:first-child {
|
||||
border-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.row > [class*='col-']:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 992px) {
|
||||
.row {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.row > [class*='col-'] {
|
||||
border-top: 1px solid var(--gray300);
|
||||
border-left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.eventschart {
|
||||
padding: 30px 0;
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 400;
|
||||
line-height: 30px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button,
|
||||
|
Loading…
Reference in New Issue
Block a user