From 2e1e5e2616b0472761cf5523c9e7ca6c715dd3cf Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 18 Jul 2023 09:09:22 -0700 Subject: [PATCH] Insights report updates. --- components/messages.js | 1 + .../pages/reports/FieldAggregateForm.js | 4 + components/pages/reports/FieldSelectForm.js | 4 +- components/pages/reports/ReportTemplates.js | 25 ++-- .../reports/event-data/EventDataParameters.js | 8 +- .../reports/insights/InsightsParameters.js | 112 +++++++----------- hooks/useFilters.js | 1 + lib/constants.ts | 34 +++++- 8 files changed, 101 insertions(+), 88 deletions(-) diff --git a/components/messages.js b/components/messages.js index d41c4430..4dbebd3a 100644 --- a/components/messages.js +++ b/components/messages.js @@ -159,6 +159,7 @@ export const labels = defineMessages({ value: { id: 'labels.value', defaultMessage: 'Value' }, overview: { id: 'labels.overview', defaultMessage: 'Overview' }, totalRecords: { id: 'labels.total-records', defaultMessage: 'Total records' }, + insights: { id: 'label.insights', defaultMessage: 'Insights' }, }); export const messages = defineMessages({ diff --git a/components/pages/reports/FieldAggregateForm.js b/components/pages/reports/FieldAggregateForm.js index cdcbdacc..abd1dbd9 100644 --- a/components/pages/reports/FieldAggregateForm.js +++ b/components/pages/reports/FieldAggregateForm.js @@ -19,6 +19,10 @@ export default function FieldAggregateForm({ name, type, onSelect }) { { label: formatMessage(labels.total), value: 'total' }, { label: formatMessage(labels.unique), value: 'unique' }, ], + uuid: [ + { label: formatMessage(labels.total), value: 'total' }, + { label: formatMessage(labels.unique), value: 'unique' }, + ], }; const items = options[type]; diff --git a/components/pages/reports/FieldSelectForm.js b/components/pages/reports/FieldSelectForm.js index 1ff6412a..0e41ea1f 100644 --- a/components/pages/reports/FieldSelectForm.js +++ b/components/pages/reports/FieldSelectForm.js @@ -9,10 +9,10 @@ export default function FieldSelectForm({ fields, onSelect }) {
onSelect(fields[key])}> - {fields.map(({ name, type }, index) => { + {fields.map(({ label, name, type }, index) => { return ( -
{name}
+
{label || name}
{type}
); diff --git a/components/pages/reports/ReportTemplates.js b/components/pages/reports/ReportTemplates.js index 35ba6f01..c1e0acdf 100644 --- a/components/pages/reports/ReportTemplates.js +++ b/components/pages/reports/ReportTemplates.js @@ -3,20 +3,10 @@ import { Button, Icons, Text, Icon } from 'react-basics'; import Page from 'components/layout/Page'; import PageHeader from 'components/layout/PageHeader'; import Funnel from 'assets/funnel.svg'; -import Nodes from 'assets/nodes.svg'; import Lightbulb from 'assets/lightbulb.svg'; import styles from './ReportTemplates.module.css'; import { useMessages } from 'hooks'; -const reports = [ - { - title: 'Funnel', - description: 'Understand the conversion and drop-off rate of users.', - url: '/reports/funnel', - icon: , - }, -]; - function ReportItem({ title, description, url, icon }) { return (
@@ -42,6 +32,21 @@ function ReportItem({ title, description, url, icon }) { export function ReportTemplates() { const { formatMessage, labels } = useMessages(); + const reports = [ + { + title: formatMessage(labels.insights), + description: 'Dive deeper into your data by using segments and filters.', + url: '/reports/insights', + icon: , + }, + { + title: formatMessage(labels.funnel), + description: 'Understand the conversion and drop-off rate of users.', + url: '/reports/funnel', + icon: , + }, + ]; + return ( diff --git a/components/pages/reports/event-data/EventDataParameters.js b/components/pages/reports/event-data/EventDataParameters.js index 09358be2..8d4dbb62 100644 --- a/components/pages/reports/event-data/EventDataParameters.js +++ b/components/pages/reports/event-data/EventDataParameters.js @@ -5,7 +5,7 @@ import { ReportContext } from 'components/pages/reports/Report'; import Empty from 'components/common/Empty'; import { DATA_TYPES, REPORT_PARAMETERS } from 'lib/constants'; import Icons from 'components/icons'; -import FieldAddForm from './FieldAddForm'; +import FieldAddForm from '../FieldAddForm'; import BaseParameters from '../BaseParameters'; import ParameterList from '../ParameterList'; import styles from './EventDataParameters.module.css'; @@ -54,9 +54,11 @@ export function EventDataParameters() { }; const handleAdd = (group, value) => { - const data = parameterData[group].filter(({ name }) => name !== value.name); + const data = parameterData[group]; - updateReport({ parameters: { [group]: data.concat(value) } }); + if (!data.find(({ name }) => name === value.name)) { + updateReport({ parameters: { [group]: data.concat(value) } }); + } }; const handleRemove = (group, index) => { diff --git a/components/pages/reports/insights/InsightsParameters.js b/components/pages/reports/insights/InsightsParameters.js index 39bfc2e8..b87a566d 100644 --- a/components/pages/reports/insights/InsightsParameters.js +++ b/components/pages/reports/insights/InsightsParameters.js @@ -1,42 +1,22 @@ import { useContext, useRef } from 'react'; -import { useApi, useMessages } from 'hooks'; +import { useMessages } from 'hooks'; import { Form, FormRow, FormButtons, SubmitButton, PopupTrigger, Icon, Popup } from 'react-basics'; import { ReportContext } from 'components/pages/reports/Report'; -import Empty from 'components/common/Empty'; -import { DATA_TYPES, REPORT_PARAMETERS } from 'lib/constants'; +import { REPORT_PARAMETERS, WEBSITE_EVENT_FIELDS } from 'lib/constants'; import Icons from 'components/icons'; -import FieldAddForm from './FieldAddForm'; import BaseParameters from '../BaseParameters'; +import FieldAddForm from '../FieldAddForm'; import ParameterList from '../ParameterList'; import styles from './InsightsParameters.module.css'; -function useFields(websiteId, startDate, endDate) { - const { get, useQuery } = useApi(); - const { data, error, isLoading } = useQuery( - ['fields', websiteId, startDate, endDate], - () => - get('/reports/event-data', { - websiteId, - startAt: +startDate, - endAt: +endDate, - }), - { enabled: !!(websiteId && startDate && endDate) }, - ); - - return { data, error, isLoading }; -} - export function InsightsParameters() { const { report, runReport, updateReport, isRunning } = useContext(ReportContext); - const { formatMessage, labels, messages } = useMessages(); + const { formatMessage, labels } = useMessages(); const ref = useRef(null); const { parameters } = report || {}; const { websiteId, dateRange, fields, filters, groups } = parameters || {}; - const { startDate, endDate } = dateRange || {}; const queryEnabled = websiteId && dateRange && fields?.length; - const { data, error } = useFields(websiteId, startDate, endDate); - const parametersSelected = websiteId && startDate && endDate; - const hasData = data?.length !== 0; + const fieldOptions = Object.keys(WEBSITE_EVENT_FIELDS).map(key => WEBSITE_EVENT_FIELDS[key]); const parameterGroups = [ { label: formatMessage(labels.fields), group: REPORT_PARAMETERS.fields }, @@ -78,10 +58,7 @@ export function InsightsParameters() { {(close, element) => { return ( ({ - name: eventKey, - type: DATA_TYPES[InsightsType], - }))} + fields={fieldOptions} group={group} element={element} onAdd={handleAdd} @@ -95,50 +72,43 @@ export function InsightsParameters() { }; return ( - + - {!hasData && } - {parametersSelected && - hasData && - parameterGroups.map(({ label, group }) => { - return ( - } + {parameterGroups.map(({ label, group }) => { + return ( + }> + handleRemove(group, index)} > - handleRemove(group, index)} - > - {({ name, value }) => { - return ( -
- {group === REPORT_PARAMETERS.fields && ( - <> -
{name}
-
{value}
- - )} - {group === REPORT_PARAMETERS.filters && ( - <> -
{name}
-
{value[0]}
-
{value[1]}
- - )} - {group === REPORT_PARAMETERS.groups && ( - <> -
{name}
- - )} -
- ); - }} -
-
- ); - })} + {({ name, value }) => { + return ( +
+ {group === REPORT_PARAMETERS.fields && ( + <> +
{name}
+
{value}
+ + )} + {group === REPORT_PARAMETERS.filters && ( + <> +
{name}
+
{value[0]}
+
{value[1]}
+ + )} + {group === REPORT_PARAMETERS.groups && ( + <> +
{name}
+ + )} +
+ ); + }} + +
+ ); + })} {formatMessage(labels.runQuery)} diff --git a/hooks/useFilters.js b/hooks/useFilters.js index ae01aadb..51268382 100644 --- a/hooks/useFilters.js +++ b/hooks/useFilters.js @@ -24,6 +24,7 @@ export function useFilters() { boolean: ['t', 'f'], number: ['eq', 'neq', 'gt', 'lt', 'gte', 'lte'], date: ['be', 'af'], + uuid: ['eq'], }; return { filters, types }; diff --git a/lib/constants.ts b/lib/constants.ts index 209a97b6..493cb525 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -120,6 +120,37 @@ export const ROLE_PERMISSIONS = { [ROLES.teamMember]: [], } as const; +export const WEBSITE_EVENT_FIELDS = { + eventId: { name: 'event_id', type: 'uuid', label: 'Event ID' }, + websiteId: { name: 'website_id', type: 'uuid', label: 'Website ID' }, + sessionId: { name: 'session_id', type: 'uuid', label: 'Session ID' }, + createdAt: { name: 'created_at', type: 'date', label: 'Created date' }, + urlPath: { name: 'url_path', type: 'string', label: 'URL path' }, + urlQuery: { name: 'url_query', type: 'string', label: 'URL query' }, + referrerPath: { name: 'referrer_path', type: 'string', label: 'Referrer path' }, + referrerQuery: { name: 'referrer_query', type: 'string', label: 'Referrer query' }, + referrerDomain: { name: 'referrer_domain', type: 'string', label: 'Referrer domain' }, + pageTitle: { name: 'page_title', type: 'string', label: 'Page title' }, + eventType: { name: 'event_type', type: 'string', label: 'Event type' }, + eventName: { name: 'event_name', type: 'string', label: 'Event name' }, +}; + +export const SESSION_FIELDS = { + sessionId: { name: 'session_id', type: 'uuid' }, + websiteId: { name: 'website_id', type: 'uuid' }, + hostname: { name: 'hostname', type: 'string' }, + browser: { name: 'browser', type: 'string' }, + os: { name: 'os', type: 'string' }, + device: { name: 'device', type: 'string' }, + screen: { name: 'screen', type: 'string' }, + language: { name: 'language', type: 'string' }, + country: { name: 'country', type: 'string' }, + subdivision1: { name: 'subdivision1', type: 'string' }, + subdivision2: { name: 'subdivision2', type: 'string' }, + city: { name: 'city', type: 'string' }, + createdAt: { name: 'created_at', type: 'date' }, +}; + export const THEME_COLORS = { light: { primary: '#2680eb', @@ -166,10 +197,9 @@ export const EVENT_COLORS = [ '#ffec16', ]; -export const DOMAIN_REGEX = +export const DOMAIN_REGEX = /^(localhost(:[1-9]\d{0,4})?|((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9-]+(-[a-z0-9-]+)*\.)+(xn--)?[a-z0-9-]{2,63})$/; - export const SHARE_ID_REGEX = /^[a-zA-Z0-9]{16}$/; export const DESKTOP_SCREEN_WIDTH = 1920;