Skip to content

Commit

Permalink
Merge branch 'dev' into bug/um-362-relational-funnels-query
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscao633 committed Jul 27, 2023
2 parents 70367ff + f4aa8f9 commit a03574e
Show file tree
Hide file tree
Showing 78 changed files with 1,098 additions and 840 deletions.
19 changes: 0 additions & 19 deletions .github/stale.yml

This file was deleted.

22 changes: 22 additions & 0 deletions .github/workflows/stale-issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Close stale issues
on:
schedule:
- cron: '30 1 * * *'

jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v8
with:
days-before-issue-stale: 60
days-before-issue-close: 7
stale-issue-label: 'stale'
stale-issue-message: 'This issue is stale because it has been open for 60 days with no activity.'
close-issue-message: 'This issue was closed because it has been inactive for 7 days since being marked as stale.'
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}
6 changes: 1 addition & 5 deletions components/input/RefreshButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ export function RefreshButton({ websiteId, isLoading }) {

function handleClick() {
if (!isLoading && dateRange) {
if (/^\d+/.test(dateRange.value)) {
setWebsiteDateRange(websiteId, dateRange.value);
} else {
setWebsiteDateRange(websiteId, dateRange);
}
setWebsiteDateRange(websiteId, dateRange);
}
}

Expand Down
14 changes: 1 addition & 13 deletions components/input/WebsiteDateFilter.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import useApi from 'hooks/useApi';
import useDateRange from 'hooks/useDateRange';
import DateFilter from './DateFilter';
import styles from './WebsiteDateFilter.module.css';

export default function WebsiteDateFilter({ websiteId }) {
const { get } = useApi();
const [dateRange, setDateRange] = useDateRange(websiteId);
const { value, startDate, endDate } = dateRange;

const handleChange = async value => {
if (value === 'all' && websiteId) {
const data = await get(`/websites/${websiteId}`);

if (data) {
const start = new Date(data.createdAt).getTime();
const end = Date.now();
setDateRange(`range:${start}:${end}`);
}
} else if (value !== 'all') {
setDateRange(value);
}
setDateRange(value);
};

return (
Expand Down
2 changes: 1 addition & 1 deletion components/metrics/ActiveUsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function ActiveUsers({ websiteId, value, refetchInterval = 60000 }) {
}

return (
<StatusLight variant="success">
<StatusLight className={styles.container} variant="success">
<div className={styles.text}>{formatMessage(messages.activeUsers, { x: count })}</div>
</StatusLight>
);
Expand Down
4 changes: 4 additions & 0 deletions components/metrics/ActiveUsers.module.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
.container {
display: flex;
align-items: center;
margin-left: 20px;
}

.text {
display: flex;
white-space: nowrap;
font-size: var(--font-size-md);
font-weight: 400;
}

.value {
Expand Down
16 changes: 6 additions & 10 deletions components/pages/event-data/EventDataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,21 @@ export function EventDataTable({ data = [] }) {
const { formatMessage, labels } = useMessages();
const { resolveUrl } = usePageQuery();

function linkToView(row, cell) {
return (
<Link href={resolveUrl({ view: row.field, event: row.event })} shallow={true}>
{cell}
</Link>
);
}

if (data.length === 0) {
return <Empty />;
}

return (
<GridTable data={data}>
<GridColumn name="event" label={formatMessage(labels.event)}>
{row => linkToView(row, row.event)}
{row => (
<Link href={resolveUrl({ event: row.event })} shallow={true}>
{row.event}
</Link>
)}
</GridColumn>
<GridColumn name="field" label={formatMessage(labels.field)}>
{row => linkToView(row, row.field)}
{row => row.field}
</GridColumn>
<GridColumn name="total" label={formatMessage(labels.totalRecords)}>
{({ total }) => total.toLocaleString()}
Expand Down
11 changes: 5 additions & 6 deletions components/pages/event-data/EventDataValueTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,22 @@ import Icons from 'components/icons';
import PageHeader from 'components/layout/PageHeader';
import Empty from 'components/common/Empty';

export function EventDataTable({ data = [], field, event }) {
export function EventDataValueTable({ data = [], event }) {
const { formatMessage, labels } = useMessages();
const { resolveUrl } = usePageQuery();

const Title = () => {
return (
<>
<Link href={resolveUrl({ view: undefined })}>
<Link href={resolveUrl({ event: undefined })}>
<Button>
<Icon rotate={180}>
<Icons.ArrowRight />
</Icon>
<Text>{formatMessage(labels.back)}</Text>
</Button>
</Link>
<Text>
{event} - {field}
</Text>
<Text>{event}</Text>
</>
);
};
Expand All @@ -33,6 +31,7 @@ export function EventDataTable({ data = [], field, event }) {
{data.length <= 0 && <Empty />}
{data.length > 0 && (
<GridTable data={data}>
<GridColumn name="field" label={formatMessage(labels.field)} />
<GridColumn name="value" label={formatMessage(labels.value)} />
<GridColumn name="total" label={formatMessage(labels.totalRecords)} width="200px">
{({ total }) => total.toLocaleString()}
Expand All @@ -43,4 +42,4 @@ export function EventDataTable({ data = [], field, event }) {
);
}

export default EventDataTable;
export default EventDataValueTable;
2 changes: 1 addition & 1 deletion components/pages/realtime/RealtimePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export function RealtimePage({ websiteId }) {
<WebsiteHeader websiteId={websiteId} />
<RealtimeHeader websiteId={websiteId} data={currentData} />
<div className={styles.chart}>
<RealtimeChart data={realtimeData} unit="minute" records={REALTIME_RANGE} />
<RealtimeChart data={realtimeData} unit="minute" />
</div>
<GridRow>
<GridColumn xs={12} sm={12} md={12} lg={4} xl={4}>
Expand Down
14 changes: 3 additions & 11 deletions components/pages/websites/WebsiteChart.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from 'react';
import PageviewsChart from 'components/metrics/PageviewsChart';
import { useApi, useDateRange, useTimezone, usePageQuery } from 'hooks';
import { getDateArray, getDateLength } from 'lib/date';
import { getDateArray } from 'lib/date';

export function WebsiteChart({ websiteId }) {
const [dateRange] = useDateRange(websiteId);
Expand Down Expand Up @@ -43,17 +43,9 @@ export function WebsiteChart({ websiteId }) {
};
}
return { pageviews: [], sessions: [] };
}, [data, startDate, endDate, unit, modified]);
}, [data, startDate, endDate, unit]);

return (
<PageviewsChart
websiteId={websiteId}
data={chartData}
unit={unit}
records={getDateLength(startDate, endDate, unit)}
loading={isLoading}
/>
);
return <PageviewsChart websiteId={websiteId} data={chartData} unit={unit} loading={isLoading} />;
}

export default WebsiteChart;
16 changes: 7 additions & 9 deletions components/pages/websites/WebsiteEventData.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@ import { EventDataMetricsBar } from 'components/pages/event-data/EventDataMetric
import { useDateRange, useApi, usePageQuery } from 'hooks';
import styles from './WebsiteEventData.module.css';

function useFields(websiteId, field, event) {
function useData(websiteId, event) {
const [dateRange] = useDateRange(websiteId);
const { startDate, endDate } = dateRange;
const { get, useQuery } = useApi();
const { data, error, isLoading } = useQuery(
['event-data:fields', { websiteId, startDate, endDate, field }],
['event-data:events', { websiteId, startDate, endDate, event }],
() =>
get('/event-data/fields', {
get('/event-data/events', {
websiteId,
startAt: +startDate,
endAt: +endDate,
field,
event,
withEventNames: true,
}),
{ enabled: !!(websiteId && startDate && endDate) },
);
Expand All @@ -28,15 +26,15 @@ function useFields(websiteId, field, event) {

export default function WebsiteEventData({ websiteId }) {
const {
query: { view, event },
query: { event },
} = usePageQuery();
const { data } = useFields(websiteId, view, event);
const { data } = useData(websiteId, event);

return (
<Flexbox className={styles.container} direction="column" gap={20}>
<EventDataMetricsBar websiteId={websiteId} />
{!view && <EventDataTable data={data} />}
{view && <EventDataValueTable field={view} event={event} data={data} />}
{!event && <EventDataTable data={data} />}
{event && <EventDataValueTable event={event} data={data} />}
</Flexbox>
);
}
2 changes: 1 addition & 1 deletion components/pages/websites/WebsiteHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ export function WebsiteHeader({ websiteId, showLinks = true, children }) {
<Column className={styles.title} variant="two">
<Favicon domain={domain} />
<Text>{name}</Text>
<ActiveUsers websiteId={websiteId} />
</Column>
<Column className={styles.actions} variant="two">
<ActiveUsers websiteId={websiteId} />
{showLinks && (
<Flexbox alignItems="center">
{links.map(({ label, icon, path }) => {
Expand Down
14 changes: 7 additions & 7 deletions db/clickhouse/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CREATE TABLE umami.website_event
website_id UUID,
session_id UUID,
event_id UUID,
--session
--sessions
hostname LowCardinality(String),
browser LowCardinality(String),
os LowCardinality(String),
Expand All @@ -17,14 +17,14 @@ CREATE TABLE umami.website_event
subdivision1 LowCardinality(String),
subdivision2 LowCardinality(String),
city String,
--pageview
--pageviews
url_path String,
url_query String,
referrer_path String,
referrer_query String,
referrer_domain String,
page_title String,
--event
--events
event_type UInt32,
event_name String,
created_at DateTime('UTC'),
Expand All @@ -38,7 +38,7 @@ CREATE TABLE umami.website_event_queue (
website_id UUID,
session_id UUID,
event_id UUID,
--session
--sessions
hostname LowCardinality(String),
browser LowCardinality(String),
os LowCardinality(String),
Expand All @@ -49,14 +49,14 @@ CREATE TABLE umami.website_event_queue (
subdivision1 LowCardinality(String),
subdivision2 LowCardinality(String),
city String,
--pageview
--pageviews
url_path String,
url_query String,
referrer_path String,
referrer_query String,
referrer_domain String,
page_title String,
--event
--events
event_type UInt32,
event_name String,
created_at DateTime('UTC'),
Expand All @@ -66,7 +66,7 @@ CREATE TABLE umami.website_event_queue (
)
ENGINE = Kafka
SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input broker list
kafka_topic_list = 'event',
kafka_topic_list = 'events',
kafka_group_name = 'event_consumer_group',
kafka_format = 'JSONEachRow',
kafka_max_block_size = 1048576,
Expand Down
29 changes: 26 additions & 3 deletions hooks/useDateRange.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,43 @@
import { parseDateRange } from 'lib/date';
import { getMinimumUnit, parseDateRange } from 'lib/date';
import { setItem } from 'next-basics';
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE } from 'lib/constants';
import useLocale from './useLocale';
import websiteStore, { setWebsiteDateRange } from 'store/websites';
import appStore, { setDateRange } from 'store/app';
import useApi from './useApi';

export function useDateRange(websiteId) {
const { get } = useApi();
const { locale } = useLocale();
const websiteConfig = websiteStore(state => state[websiteId]?.dateRange);
const defaultConfig = DEFAULT_DATE_RANGE;
const globalConfig = appStore(state => state.dateRange);
const dateRange = parseDateRange(websiteConfig || globalConfig || defaultConfig, locale);

const saveDateRange = value => {
const saveDateRange = async value => {
if (websiteId) {
setWebsiteDateRange(websiteId, value);
let dateRange = value;

if (typeof value === 'string') {
if (value === 'all') {
const result = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;

const startDate = new Date(mindate);
const endDate = new Date(maxdate);

dateRange = {
startDate,
endDate,
unit: getMinimumUnit(startDate, endDate),
value,
};
} else {
dateRange = parseDateRange(value, locale);
}
}

setWebsiteDateRange(websiteId, dateRange);
} else {
setItem(DATE_RANGE_CONFIG, value);
setDateRange(value);
Expand Down
2 changes: 1 addition & 1 deletion lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { getTeamUser } from 'queries';
import { getTeamWebsite, getTeamWebsiteByTeamMemberId } from 'queries/admin/teamWebsite';
import { validate } from 'uuid';
import { loadWebsite } from './query';
import { loadWebsite } from './load';
import { Auth } from './types';

const log = debug('umami:auth');
Expand Down
Loading

0 comments on commit a03574e

Please sign in to comment.