feat(ui) - custom metrics - wip
This commit is contained in:
parent
0791744de7
commit
82e572b9d1
21 changed files with 266 additions and 72 deletions
|
|
@ -0,0 +1,56 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Styles } from '../../common';
|
||||||
|
import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Area, Tooltip } from 'recharts';
|
||||||
|
import { LineChart, Line, Legend } from 'recharts';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: any;
|
||||||
|
params: any;
|
||||||
|
seriesMap: any;
|
||||||
|
colors: any;
|
||||||
|
}
|
||||||
|
function CustomMetriLineChart(props: Props) {
|
||||||
|
const { data, params, seriesMap, colors } = props;
|
||||||
|
return (
|
||||||
|
<ResponsiveContainer height={ 240 } width="100%">
|
||||||
|
<LineChart
|
||||||
|
data={ data }
|
||||||
|
margin={Styles.chartMargins}
|
||||||
|
// syncId={ showSync ? "domainsErrors_4xx" : undefined }
|
||||||
|
>
|
||||||
|
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
||||||
|
<XAxis
|
||||||
|
{...Styles.xaxis}
|
||||||
|
dataKey="time"
|
||||||
|
interval={params.density/7}
|
||||||
|
/>
|
||||||
|
<YAxis
|
||||||
|
{...Styles.yaxis}
|
||||||
|
allowDecimals={false}
|
||||||
|
label={{
|
||||||
|
...Styles.axisLabelLeft,
|
||||||
|
value: "Number of Sessions"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Legend />
|
||||||
|
<Tooltip {...Styles.tooltip} />
|
||||||
|
{ seriesMap.map((key, index) => (
|
||||||
|
<Line
|
||||||
|
key={key}
|
||||||
|
name={key}
|
||||||
|
type="monotone"
|
||||||
|
dataKey={key}
|
||||||
|
stroke={colors[index]}
|
||||||
|
fillOpacity={ 1 }
|
||||||
|
strokeWidth={ 2 }
|
||||||
|
strokeOpacity={ 0.6 }
|
||||||
|
// fill="url(#colorCount)"
|
||||||
|
dot={false}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</LineChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomMetriLineChart
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './CustomMetriLineChart';
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
function CustomMetriPercentage(props: Props) {
|
||||||
|
const { data } = props;
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center" style={{ height: '240px'}}>
|
||||||
|
<div className="text-6xl">0%</div>
|
||||||
|
<div className="text-lg mt-6">0 ( 0.0% ) from previous hour</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomMetriPercentage;
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './CustomMetriPercentage';
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
.wrapper {
|
||||||
|
background-color: white;
|
||||||
|
/* border: solid thin $gray-medium; */
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
function CustomMetricPieChart(props: Props) {
|
||||||
|
const { data } = props;
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center" style={{ height: '240px'}}>
|
||||||
|
<div className="text-6xl">0%</div>
|
||||||
|
<div className="text-lg mt-6">0 ( 0.0% ) from previous hour</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomMetricPieChart;
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './CustomMetricPieChart';
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
.wrapper {
|
||||||
|
background-color: white;
|
||||||
|
/* border: solid thin $gray-medium; */
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Table } from '../../common';
|
||||||
|
import { List } from 'immutable';
|
||||||
|
|
||||||
|
const cols = [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
title: 'Resource',
|
||||||
|
toText: name => name,
|
||||||
|
width: '70%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sessions',
|
||||||
|
title: 'Sessions',
|
||||||
|
toText: sessions => sessions,
|
||||||
|
width: '30%',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
function CustomMetriTable(props: Props) {
|
||||||
|
const { data } = props;
|
||||||
|
const rows = List([
|
||||||
|
{ name: 'one', sessions: 2 },
|
||||||
|
{ name: 'two', sessions: 3 },
|
||||||
|
{ name: 'three', sessions: 4 },
|
||||||
|
{ name: 'four', sessions: 1 },
|
||||||
|
{ name: 'five', sessions: 6 },
|
||||||
|
])
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center" style={{ height: '240px'}}>
|
||||||
|
<Table
|
||||||
|
small
|
||||||
|
cols={ cols }
|
||||||
|
rows={ rows }
|
||||||
|
rowClass="group"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CustomMetriTable;
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export { default } from './CustomMetricTable';
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useState, useRef } from 'react';
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Loader, NoContent, Icon } from 'UI';
|
import { Loader, NoContent, SegmentSelection, Icon } from 'UI';
|
||||||
import { Styles } from '../../common';
|
import { Styles } from '../../common';
|
||||||
import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line, Legend } from 'recharts';
|
import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line, Legend } from 'recharts';
|
||||||
import Period, { LAST_24_HOURS, LAST_30_MINUTES, YESTERDAY, LAST_7_DAYS } from 'Types/app/period';
|
import Period, { LAST_24_HOURS, LAST_30_MINUTES, YESTERDAY, LAST_7_DAYS } from 'Types/app/period';
|
||||||
|
|
@ -9,6 +9,9 @@ import { getChartFormatter } from 'Types/dashboard/helper';
|
||||||
import { remove } from 'Duck/customMetrics';
|
import { remove } from 'Duck/customMetrics';
|
||||||
import DateRange from 'Shared/DateRange';
|
import DateRange from 'Shared/DateRange';
|
||||||
import { edit } from 'Duck/customMetrics';
|
import { edit } from 'Duck/customMetrics';
|
||||||
|
import CustomMetriLineChart from '../CustomMetriLineChart';
|
||||||
|
import CustomMetriPercentage from '../CustomMetriPercentage';
|
||||||
|
import CustomMetricTable from '../CustomMetricTable';
|
||||||
|
|
||||||
import APIClient from 'App/api_client';
|
import APIClient from 'App/api_client';
|
||||||
|
|
||||||
|
|
@ -83,11 +86,28 @@ function CustomMetricWidget(props: Props) {
|
||||||
props.edit({ ...changedDates, rangeName: changedDates.rangeValue });
|
props.edit({ ...changedDates, rangeName: changedDates.rangeValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chagneViewType = (e, { name, value }) => {
|
||||||
|
props.edit({ [ name ]: value });
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-10">
|
<div className="mb-10">
|
||||||
<div className="flex items-center mb-4">
|
<div className="flex items-center mb-4">
|
||||||
<div className="mr-auto font-medium">Preview</div>
|
<div className="mr-auto font-medium">Preview</div>
|
||||||
<div>
|
<div className="flex items-center">
|
||||||
|
<SegmentSelection
|
||||||
|
name="viewType"
|
||||||
|
className="my-3"
|
||||||
|
size="extraSmall"
|
||||||
|
onSelect={ chagneViewType }
|
||||||
|
value={{ value: metric.viewType }}
|
||||||
|
list={ [
|
||||||
|
{ value: 'chart', icon: 'graph-up-arrow' },
|
||||||
|
{ value: 'percent', icon: 'hash' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<div className="mx-2" />
|
||||||
|
<span className="mr-1 color-gray-medium">Time Range</span>
|
||||||
<DateRange
|
<DateRange
|
||||||
rangeValue={metric.rangeName}
|
rangeValue={metric.rangeName}
|
||||||
startDate={metric.startDate}
|
startDate={metric.startDate}
|
||||||
|
|
@ -105,44 +125,27 @@ function CustomMetricWidget(props: Props) {
|
||||||
size="small"
|
size="small"
|
||||||
show={ data.length === 0 }
|
show={ data.length === 0 }
|
||||||
>
|
>
|
||||||
<ResponsiveContainer height={ 240 } width="100%">
|
{ metric.metricType === 'timeseries' && (
|
||||||
<LineChart
|
<>
|
||||||
|
{ metric.viewType === 'percent' && (
|
||||||
|
<CustomMetriPercentage data={data} />
|
||||||
|
)}
|
||||||
|
{ metric.viewType === 'chart' && (
|
||||||
|
<CustomMetriLineChart
|
||||||
data={data}
|
data={data}
|
||||||
margin={Styles.chartMargins}
|
seriesMap={seriesMap}
|
||||||
syncId={ showSync ? "domainsErrors_4xx" : undefined }
|
colors={colors}
|
||||||
>
|
params={params}
|
||||||
<CartesianGrid strokeDasharray="3 3" vertical={ false } stroke="#EEEEEE" />
|
|
||||||
<XAxis
|
|
||||||
{...Styles.xaxis}
|
|
||||||
dataKey="time"
|
|
||||||
interval={params.density/7}
|
|
||||||
/>
|
/>
|
||||||
<YAxis
|
)}
|
||||||
{...Styles.yaxis}
|
</>
|
||||||
allowDecimals={false}
|
)}
|
||||||
label={{
|
|
||||||
...Styles.axisLabelLeft,
|
{ metric.metricType === 'table' && (
|
||||||
value: "Number of Sessions"
|
<div className="p-3">
|
||||||
}}
|
<CustomMetricTable data={data} />
|
||||||
/>
|
</div>
|
||||||
<Legend />
|
)}
|
||||||
<Tooltip {...Styles.tooltip} />
|
|
||||||
{ seriesMap.map((key, index) => (
|
|
||||||
<Line
|
|
||||||
key={key}
|
|
||||||
name={key}
|
|
||||||
type="monotone"
|
|
||||||
dataKey={key}
|
|
||||||
stroke={colors[index]}
|
|
||||||
fillOpacity={ 1 }
|
|
||||||
strokeWidth={ 2 }
|
|
||||||
strokeOpacity={ 0.6 }
|
|
||||||
// fill="url(#colorCount)"
|
|
||||||
dot={false}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</LineChart>
|
|
||||||
</ResponsiveContainer>
|
|
||||||
</NoContent>
|
</NoContent>
|
||||||
</Loader>
|
</Loader>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ export default class Table extends React.PureComponent {
|
||||||
rowProps,
|
rowProps,
|
||||||
rowClass = '',
|
rowClass = '',
|
||||||
small = false,
|
small = false,
|
||||||
compare = false
|
compare = false,
|
||||||
|
maxHeight = 200,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { showAll } = this.state;
|
const { showAll } = this.state;
|
||||||
|
|
||||||
|
|
@ -30,7 +31,7 @@ export default class Table extends React.PureComponent {
|
||||||
<div key={ key } style={ { width } } className={ stl.header }>{ title }</div>)
|
<div key={ key } style={ { width } } className={ stl.header }>{ title }</div>)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className={ cn(stl.content, "thin-scrollbar") }>
|
<div className={ cn(stl.content, "thin-scrollbar") } style={{ maxHeight: maxHeight + 'px'}}>
|
||||||
{ rows.take(showAll ? 10 : (small ? 3 : 5)).map(row => (
|
{ rows.take(showAll ? 10 : (small ? 3 : 5)).map(row => (
|
||||||
<div className={ cn(rowClass, stl.row, { [stl.small]: small}) } key={ row.key }>
|
<div className={ cn(rowClass, stl.row, { [stl.small]: small}) } key={ row.key }>
|
||||||
{ cols.map(({ cellClass = '', className = '', Component, key, toText = t => t, width }) => (
|
{ cols.map(({ cellClass = '', className = '', Component, key, toText = t => t, width }) => (
|
||||||
|
|
@ -42,7 +43,7 @@ export default class Table extends React.PureComponent {
|
||||||
)) }
|
)) }
|
||||||
</div>
|
</div>
|
||||||
)) }
|
)) }
|
||||||
|
</div>
|
||||||
{ rows.size > (small ? 3 : 5) && !showAll &&
|
{ rows.size > (small ? 3 : 5) && !showAll &&
|
||||||
<div className="w-full flex justify-center mt-3">
|
<div className="w-full flex justify-center mt-3">
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -56,7 +57,6 @@ export default class Table extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ interface Props {
|
||||||
function CustomMetricForm(props: Props) {
|
function CustomMetricForm(props: Props) {
|
||||||
const { metric, loading } = props;
|
const { metric, loading } = props;
|
||||||
const metricOfOptions = metricOf.filter(i => i.key === metric.metricType);
|
const metricOfOptions = metricOf.filter(i => i.key === metric.metricType);
|
||||||
|
const timeseriesOptions = metricOf.filter(i => i.key === 'timeseries');
|
||||||
|
const tableOptions = metricOf.filter(i => i.key === 'table');
|
||||||
|
|
||||||
const addSeries = () => {
|
const addSeries = () => {
|
||||||
props.addSeries();
|
props.addSeries();
|
||||||
|
|
@ -34,7 +36,17 @@ function CustomMetricForm(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const write = ({ target: { value, name } }) => props.editMetric({ [ name ]: value }, false);
|
const write = ({ target: { value, name } }) => props.editMetric({ [ name ]: value }, false);
|
||||||
const writeOption = (e, { value, name }) => props.editMetric({ [ name ]: value }, false);
|
const writeOption = (e, { value, name }) => {
|
||||||
|
props.editMetric({ [ name ]: value }, false);
|
||||||
|
|
||||||
|
if (name === 'metricType') {
|
||||||
|
if (value === 'timeseries') {
|
||||||
|
props.editMetric({ metricOf: timeseriesOptions[0].value }, false);
|
||||||
|
} else if (value === 'table') {
|
||||||
|
props.editMetric({ metricOf: tableOptions[0].value }, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const changeConditionTab = (e, { name, value }) => {
|
const changeConditionTab = (e, { name, value }) => {
|
||||||
props.editMetric({[ 'viewType' ]: value });
|
props.editMetric({[ 'viewType' ]: value });
|
||||||
|
|
@ -89,22 +101,44 @@ function CustomMetricForm(props: Props) {
|
||||||
value={ metric.metricType }
|
value={ metric.metricType }
|
||||||
onChange={ writeOption }
|
onChange={ writeOption }
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{metric.metricType === 'timeseries' && (
|
||||||
|
<>
|
||||||
<span className="mx-3">of</span>
|
<span className="mx-3">of</span>
|
||||||
<DropdownPlain
|
<DropdownPlain
|
||||||
name="metricOf"
|
name="metricOf"
|
||||||
options={metricOfOptions}
|
options={timeseriesOptions}
|
||||||
value={ metric.metricOf }
|
value={ metric.metricOf }
|
||||||
onChange={ writeOption }
|
onChange={ writeOption }
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{metric.metricType === 'table' && (
|
||||||
|
<>
|
||||||
|
<span className="mx-3">of</span>
|
||||||
|
<DropdownPlain
|
||||||
|
name="metricOf"
|
||||||
|
options={tableOptions}
|
||||||
|
value={ metric.metricOf }
|
||||||
|
onChange={ writeOption }
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{metric.metricType === 'table' && (
|
||||||
|
<>
|
||||||
<span className="mx-3">showing</span>
|
<span className="mx-3">showing</span>
|
||||||
<DropdownPlain
|
<DropdownPlain
|
||||||
name="viewType"
|
name="viewType"
|
||||||
options={[
|
options={[
|
||||||
{ value: 'sessionCount', text: 'Session Count' },
|
{ value: 'sessionCount', text: 'Session Count' },
|
||||||
]}
|
]}
|
||||||
value={ metric.metricType }
|
value={ metric.viewType }
|
||||||
onChange={ writeOption }
|
onChange={ writeOption }
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="flex items-center">
|
{/* <div className="flex items-center">
|
||||||
<span className="bg-white p-1 px-2 border rounded" style={{ height: '30px'}}>Timeseries</span>
|
<span className="bg-white p-1 px-2 border rounded" style={{ height: '30px'}}>Timeseries</span>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: $gray-darkest;
|
color: $gray-darkest;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
background-color: white;
|
||||||
|
border: solid thin $gray-light;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $gray-light;
|
background-color: $gray-light;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DropdownPlain(props: Props) {
|
export default function DropdownPlain(props: Props) {
|
||||||
const { name = "sort", value, options, icon = "chevron-down", direction = "left" } = props;
|
const { name = "sort", value, options, icon = "chevron-down", direction = "right" } = props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
|
@ -22,7 +22,7 @@ export default function DropdownPlain(props: Props) {
|
||||||
direction={direction}
|
direction={direction}
|
||||||
options={ options }
|
options={ options }
|
||||||
onChange={ props.onChange }
|
onChange={ props.onChange }
|
||||||
floating
|
// floating
|
||||||
scrolling
|
scrolling
|
||||||
selectOnBlur={ false }
|
selectOnBlur={ false }
|
||||||
// defaultValue={ value }
|
// defaultValue={ value }
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class SegmentSelection extends React.Component {
|
||||||
<div className={ cn(styles.wrapper, {
|
<div className={ cn(styles.wrapper, {
|
||||||
[styles.primary] : primary,
|
[styles.primary] : primary,
|
||||||
[styles.small] : size === 'small' || small,
|
[styles.small] : size === 'small' || small,
|
||||||
[styles.extraSmall] : extraSmall,
|
[styles.extraSmall] : size === 'extraSmall' || extraSmall,
|
||||||
}, className) }
|
}, className) }
|
||||||
>
|
>
|
||||||
{ list.map(item => (
|
{ list.map(item => (
|
||||||
|
|
@ -27,7 +27,7 @@ class SegmentSelection extends React.Component {
|
||||||
data-active={ this.props.value && this.props.value.value === item.value }
|
data-active={ this.props.value && this.props.value.value === item.value }
|
||||||
onClick={ () => !item.disabled && this.setActiveItem(item) }
|
onClick={ () => !item.disabled && this.setActiveItem(item) }
|
||||||
>
|
>
|
||||||
{ item.icon && <Icon name={ item.icon } size="20" marginRight="10" /> }
|
{ item.icon && <Icon name={ item.icon } size={size === "extraSmall" ? 12 : 20} marginRight={ item.name ? "10" : "" } /> }
|
||||||
<div>{ item.name }</div>
|
<div>{ item.name }</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-right: solid thin $teal;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: $gray-lightest;
|
background-color: $gray-lightest;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
border-right: solid thin $gray-light;
|
||||||
|
|
||||||
& span svg {
|
& span svg {
|
||||||
fill: $gray-medium;
|
fill: $gray-medium;
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
& .item {
|
& .item {
|
||||||
color: $teal;
|
color: $teal;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
border-right: solid thin $teal;
|
||||||
&[data-active=true] {
|
&[data-active=true] {
|
||||||
background-color: $teal;
|
background-color: $teal;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
@ -65,6 +66,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.extraSmall .item {
|
.extraSmall .item {
|
||||||
padding: 0 4px;
|
padding: 6px !important;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +61,7 @@ export const metricTypes = [
|
||||||
|
|
||||||
export const metricOf = [
|
export const metricOf = [
|
||||||
{ text: 'Session Count', value: 'sessionCount', key: 'timeseries' },
|
{ text: 'Session Count', value: 'sessionCount', key: 'timeseries' },
|
||||||
{ text: 'Users', value: 'users', key: 'table' },
|
{ text: 'Users', value: 'USERID', key: 'table' },
|
||||||
{ text: 'Rage Click', value: 'rageClick', key: 'table' },
|
{ text: 'Rage Click', value: 'rageClick', key: 'table' },
|
||||||
{ text: 'Dead Click', value: 'deadClick', key: 'table' },
|
{ text: 'Dead Click', value: 'deadClick', key: 'table' },
|
||||||
{ text: 'Browser', value: 'browser', key: 'table' },
|
{ text: 'Browser', value: 'browser', key: 'table' },
|
||||||
|
|
|
||||||
3
frontend/app/svg/icons/graph-up-arrow.svg
Normal file
3
frontend/app/svg/icons/graph-up-arrow.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-graph-up-arrow" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M0 0h1v15h15v1H0V0Zm10 3.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-1 0V4.9l-3.613 4.417a.5.5 0 0 1-.74.037L7.06 6.767l-3.656 5.027a.5.5 0 0 1-.808-.588l4-5.5a.5.5 0 0 1 .758-.06l2.609 2.61L13.445 4H10.5a.5.5 0 0 1-.5-.5Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 402 B |
3
frontend/app/svg/icons/hash.svg
Normal file
3
frontend/app/svg/icons/hash.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-hash" viewBox="0 0 16 16">
|
||||||
|
<path d="M8.39 12.648a1.32 1.32 0 0 0-.015.18c0 .305.21.508.5.508.266 0 .492-.172.555-.477l.554-2.703h1.204c.421 0 .617-.234.617-.547 0-.312-.188-.53-.617-.53h-.985l.516-2.524h1.265c.43 0 .618-.227.618-.547 0-.313-.188-.524-.618-.524h-1.046l.476-2.304a1.06 1.06 0 0 0 .016-.164.51.51 0 0 0-.516-.516.54.54 0 0 0-.539.43l-.523 2.554H7.617l.477-2.304c.008-.04.015-.118.015-.164a.512.512 0 0 0-.523-.516.539.539 0 0 0-.531.43L6.53 5.484H5.414c-.43 0-.617.22-.617.532 0 .312.187.539.617.539h.906l-.515 2.523H4.609c-.421 0-.609.219-.609.531 0 .313.188.547.61.547h.976l-.516 2.492c-.008.04-.015.125-.015.18 0 .305.21.508.5.508.265 0 .492-.172.554-.477l.555-2.703h2.242l-.515 2.492zm-1-6.109h2.266l-.515 2.563H6.859l.532-2.563z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 855 B |
|
|
@ -27,9 +27,9 @@ export const FilterSeries = Record({
|
||||||
export default Record({
|
export default Record({
|
||||||
metricId: undefined,
|
metricId: undefined,
|
||||||
name: 'Series',
|
name: 'Series',
|
||||||
metricType: 'timeseries',
|
metricType: 'table',
|
||||||
metricOf: 'sessionCount',
|
metricOf: 'USERID',
|
||||||
viewType: 'sessionCount',
|
viewType: 'lineChart',
|
||||||
series: List(),
|
series: List(),
|
||||||
isPublic: true,
|
isPublic: true,
|
||||||
startDate: '',
|
startDate: '',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue