import React from 'react' import MetricValue from './metric-value' import { hasConversionGoalFilter } from '../../util/filters' // Class representation of a metric. // Metric instances can be created directly via the Metric constructor, // or using special creator functions like `createVisitors`, which just // fill out the known fields for that metric. // ### Required props // * `key` - the key under which to read values under in an API // * `formatter` - a function that takes a value of this metric, and // and returns the "rendered" version of it. Can be JSX or a string. // * `renderLabel` - a function rendering a label for this metric given a // query argument. Returns string. // ### Optional props // * `meta` - a map with extra context for this metric. E.g. `plot`, or // `hiddenOnMobile` define some special behaviours in the context where // it's used. export class Metric { constructor(props) { if (!props.key) { throw Error('Required field `key` is missing') } if (typeof props.renderLabel !== 'function') { throw Error('Required field `renderLabel` should be a function') } this.key = props.key this.meta = props.meta || {} this.sortable = props.sortable this.width = props.width ?? 'w-24' this.formatter = props.formatter this.renderLabel = props.renderLabel this.renderValue = this.renderValue.bind(this) } renderValue(listItem, meta, options = {}) { const { detailedView = false, isRowHovered = false } = options return ( ) } } // Creates a Metric class representing the `visitors` metric. // Optional props for conveniently generating the `renderLabel` function: // * `defaultLabel` - label when not realtime, and no goal filter applied // * `realtimeLabel` - label when realtime period // * `goalFilterLabel` - label when goal filter is applied export const createVisitors = (props) => { let renderLabel if (typeof props.renderLabel === 'function') { renderLabel = props.renderLabel } else { renderLabel = (query) => { const defaultLabel = props.defaultLabel || 'Visitors' const realtimeLabel = props.realtimeLabel || 'Current visitors' const goalFilterLabel = props.goalFilterLabel || 'Conversions' if (query.period === 'realtime') { return realtimeLabel } if (query && hasConversionGoalFilter(query)) { return goalFilterLabel } return defaultLabel } } return new Metric({ width: 'w-36', sortable: true, ...props, key: 'visitors', renderLabel }) } export const createConversionRate = (props) => { const renderLabel = (_query) => 'CR' return new Metric({ width: 'w-28 md:w-24', ...props, key: 'conversion_rate', renderLabel, sortable: true }) } export const createPercentage = (props) => { const renderLabel = (_query) => '%' return new Metric({ width: 'w-24', ...props, key: 'percentage', renderLabel, sortable: true }) } export const createEvents = (props) => { return new Metric({ width: 'w-28', ...props, key: 'events', sortable: true }) } export const createTotalRevenue = (props) => { const renderLabel = (_query) => 'Revenue' return new Metric({ width: 'w-32', ...props, key: 'total_revenue', renderLabel, sortable: true }) } export const createAverageRevenue = (props) => { const renderLabel = (_query) => 'Average' return new Metric({ width: 'w-28', ...props, key: 'average_revenue', renderLabel, sortable: true }) } export const createTotalVisitors = (props) => { const renderLabel = (_query) => 'Total visitors' return new Metric({ width: 'w-32', ...props, key: 'total_visitors', renderLabel, sortable: false }) } export const createVisits = (props) => { return new Metric({ width: 'w-24', sortable: true, ...props, key: 'visits' }) } export const createVisitDuration = (props) => { const renderLabel = (_query) => 'Visit duration' return new Metric({ width: 'w-28 md:w-24', ...props, key: 'visit_duration', renderLabel, sortable: true }) } export const createBounceRate = (props) => { const renderLabel = (_query) => 'Bounce rate' return new Metric({ width: 'w-28 md:w-24', ...props, key: 'bounce_rate', renderLabel, sortable: true }) } export const createPageviews = (props) => { const renderLabel = (_query) => 'Pageviews' return new Metric({ width: 'w-28', ...props, key: 'pageviews', renderLabel, sortable: true }) } export const createTimeOnPage = (props) => { const renderLabel = (_query) => 'Time on page' return new Metric({ width: 'w-28 md:w-24', ...props, key: 'time_on_page', renderLabel, sortable: true }) } export const createExitRate = (props) => { const renderLabel = (_query) => 'Exit rate' return new Metric({ width: 'w-28 md:w-24', ...props, key: 'exit_rate', renderLabel, sortable: true }) } export const createScrollDepth = (props) => { const renderLabel = (_query) => 'Scroll depth' return new Metric({ width: 'w-28 md:w-24', ...props, key: 'scroll_depth', renderLabel, sortable: true }) }