feat(ui) - funnels - fitler dropdowns to select
This commit is contained in:
parent
97da3f5c1c
commit
baa6c916dc
5 changed files with 109 additions and 66 deletions
|
|
@ -7,6 +7,7 @@ import { useObserver } from 'mobx-react-lite';
|
|||
import { Button, Icon } from 'UI'
|
||||
import FilterSeries from '../FilterSeries';
|
||||
import { confirm } from 'UI/Confirmation';
|
||||
import Select from 'Shared/Select'
|
||||
import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes'
|
||||
import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelectionModal';
|
||||
|
||||
|
|
@ -22,18 +23,20 @@ function WidgetForm(props: Props) {
|
|||
const { metricStore, dashboardStore } = useStore();
|
||||
const dashboards = dashboardStore.dashboards;
|
||||
const isSaving = useObserver(() => metricStore.isSaving);
|
||||
const metric: any = useObserver(() => metricStore.instance);
|
||||
const metric: any = useObserver(() => metricStore.instance)
|
||||
|
||||
const timeseriesOptions = metricOf.filter(i => i.type === 'timeseries');
|
||||
const tableOptions = metricOf.filter(i => i.type === 'table');
|
||||
const isTable = metric.metricType === 'table';
|
||||
const isFunnel = metric.metricType === 'funnel';
|
||||
const _issueOptions = [{ text: 'All', value: 'all' }].concat(issueOptions);
|
||||
const isErrors = metric.metricType === 'errors';
|
||||
const isSessions = metric.metricType === 'sessions';
|
||||
const _issueOptions = [{ label: 'All', value: 'all' }].concat(issueOptions);
|
||||
const canAddToDashboard = metric.exists() && dashboards.length > 0;
|
||||
const canAddSeries = metric.series.length < 3;
|
||||
|
||||
const write = ({ target: { value, name } }) => metricStore.merge({ [ name ]: value });
|
||||
const writeOption = (e, { value, name }) => {
|
||||
// const write = ({ target: { value, name } }) => metricStore.merge({ [ name ]: value });
|
||||
const writeOption = ({ value: { value }, name }) => {
|
||||
const obj = { [ name ]: value };
|
||||
|
||||
if (name === 'metricValue') {
|
||||
|
|
@ -86,66 +89,98 @@ function WidgetForm(props: Props) {
|
|||
const onObserveChanges = () => {
|
||||
// metricStore.fetchMetricChartData(metric);
|
||||
}
|
||||
|
||||
|
||||
return useObserver(() => (
|
||||
<div className="p-6">
|
||||
<div className="form-group">
|
||||
<label className="font-medium">Metric Type</label>
|
||||
<div className="flex items-center">
|
||||
<DropdownPlain
|
||||
<Select
|
||||
name="metricType"
|
||||
options={metricTypes}
|
||||
value={metricTypes.find(i => i.value === metric.metricType) || metricTypes[0]}
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
{/* <DropdownPlain
|
||||
name="metricType"
|
||||
options={metricTypes}
|
||||
value={ metric.metricType }
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
/> */}
|
||||
|
||||
{metric.metricType === 'timeseries' && (
|
||||
<>
|
||||
<span className="mx-3">of</span>
|
||||
<DropdownPlain
|
||||
<Select
|
||||
name="metricOf"
|
||||
options={timeseriesOptions}
|
||||
defaultValue={metric.metricOf}
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
{/* <DropdownPlain
|
||||
name="metricOf"
|
||||
options={timeseriesOptions}
|
||||
value={ metric.metricOf }
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
|
||||
{metric.metricType === 'table' && (
|
||||
<>
|
||||
<span className="mx-3">of</span>
|
||||
<DropdownPlain
|
||||
<Select
|
||||
name="metricOf"
|
||||
options={tableOptions}
|
||||
defaultValue={metric.metricOf}
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
{/* <DropdownPlain
|
||||
name="metricOf"
|
||||
options={tableOptions}
|
||||
value={ metric.metricOf }
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
|
||||
{metric.metricOf === FilterKey.ISSUE && (
|
||||
<>
|
||||
<span className="mx-3">issue type</span>
|
||||
<DropdownPlain
|
||||
<Select
|
||||
name="metricValue"
|
||||
options={_issueOptions}
|
||||
defaultValue={metric.metricValue[0]}
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
{/* <DropdownPlain
|
||||
name="metricValue"
|
||||
options={_issueOptions}
|
||||
value={ metric.metricValue[0] }
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
|
||||
{metric.metricType === 'table' && (
|
||||
<>
|
||||
<span className="mx-3">showing</span>
|
||||
<DropdownPlain
|
||||
<Select
|
||||
name="metricFormat"
|
||||
options={[
|
||||
{ value: 'sessionCount', label: 'Session Count' },
|
||||
]}
|
||||
defaultValue={ metric.metricFormat }
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
{/* <DropdownPlain
|
||||
name="metricFormat"
|
||||
options={[
|
||||
{ value: 'sessionCount', text: 'Session Count' },
|
||||
]}
|
||||
value={ metric.metricFormat }
|
||||
onChange={ writeOption }
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ interface Props {
|
|||
plain?: boolean;
|
||||
components?: any;
|
||||
styles?: any;
|
||||
onChange: (value: any) => void;
|
||||
name?: string;
|
||||
[x:string]: any;
|
||||
}
|
||||
export default function({ styles= {}, alignRight = false, plain = false, options, isSearchable = false, components = {}, defaultValue = '', ...rest }: Props) {
|
||||
export default function({ name = '', onChange, styles= {}, alignRight = false, plain = false, options, isSearchable = false, components = {}, defaultValue = '', ...rest }: Props) {
|
||||
const defaultSelected = defaultValue ? options.find(x => x.value === defaultValue) : null;
|
||||
|
||||
const customStyles = {
|
||||
|
|
@ -54,6 +56,10 @@ export default function({ styles= {}, alignRight = false, plain = false, options
|
|||
border: 'solid thin #ddd',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.5s',
|
||||
['&:hover']: {
|
||||
backgroundColor: colors['gray-lightest'],
|
||||
transition: 'all 0.2s ease-in-out'
|
||||
}
|
||||
}
|
||||
if (plain) {
|
||||
obj['border'] = '1px solid transparent'
|
||||
|
|
@ -100,6 +106,7 @@ export default function({ styles= {}, alignRight = false, plain = false, options
|
|||
DropdownIndicator,
|
||||
...components,
|
||||
}}
|
||||
onChange={(value) => onChange({ name, value: value })}
|
||||
styles={{ ...customStyles, ...styles }}
|
||||
theme={(theme) => ({
|
||||
...theme,
|
||||
|
|
|
|||
|
|
@ -60,10 +60,11 @@ export const customOperators = [
|
|||
]
|
||||
|
||||
export const metricTypes = [
|
||||
{ text: 'Timeseries', value: 'timeseries' },
|
||||
{ text: 'Table', value: 'table' },
|
||||
{ text: 'Funnel', value: 'funnel' },
|
||||
{ text: 'Error', value: 'error' },
|
||||
{ label: 'Timeseries', value: 'timeseries' },
|
||||
{ label: 'Table', value: 'table' },
|
||||
{ label: 'Funnel', value: 'funnel' },
|
||||
{ label: 'Errors', value: 'errors' },
|
||||
{ label: 'Sessions', value: 'sessions' },
|
||||
];
|
||||
|
||||
export const tableColumnName = {
|
||||
|
|
@ -76,13 +77,13 @@ export const tableColumnName = {
|
|||
}
|
||||
|
||||
export const metricOf = [
|
||||
{ text: 'Session Count', value: 'sessionCount', type: 'timeseries' },
|
||||
{ text: 'Users', value: FilterKey.USERID, type: 'table' },
|
||||
{ text: 'Issues', value: FilterKey.ISSUE, type: 'table' },
|
||||
{ text: 'Browsers', value: FilterKey.USER_BROWSER, type: 'table' },
|
||||
{ text: 'Devices', value: FilterKey.USER_DEVICE, type: 'table' },
|
||||
{ text: 'Countries', value: FilterKey.USER_COUNTRY, type: 'table' },
|
||||
{ text: 'URLs', value: FilterKey.LOCATION, type: 'table' },
|
||||
{ label: 'Session Count', value: 'sessionCount', type: 'timeseries' },
|
||||
{ label: 'Users', value: FilterKey.USERID, type: 'table' },
|
||||
{ label: 'Issues', value: FilterKey.ISSUE, type: 'table' },
|
||||
{ label: 'Browsers', value: FilterKey.USER_BROWSER, type: 'table' },
|
||||
{ label: 'Devices', value: FilterKey.USER_DEVICE, type: 'table' },
|
||||
{ label: 'Countries', value: FilterKey.USER_COUNTRY, type: 'table' },
|
||||
{ label: 'URLs', value: FilterKey.LOCATION, type: 'table' },
|
||||
]
|
||||
|
||||
export const methodOptions = [
|
||||
|
|
@ -98,18 +99,18 @@ export const methodOptions = [
|
|||
]
|
||||
|
||||
export const issueOptions = [
|
||||
{ text: 'Click Rage', value: IssueType.CLICK_RAGE },
|
||||
{ text: 'Dead Click', value: IssueType.DEAD_CLICK },
|
||||
{ text: 'Excessive Scrolling', value: IssueType.EXCESSIVE_SCROLLING },
|
||||
{ text: 'Bad Request', value: IssueType.BAD_REQUEST },
|
||||
{ text: 'Missing Resource', value: IssueType.MISSING_RESOURCE },
|
||||
{ text: 'Memory', value: IssueType.MEMORY },
|
||||
{ text: 'CPU', value: IssueType.CPU },
|
||||
{ text: 'Slow Resource', value: IssueType.SLOW_RESOURCE },
|
||||
{ text: 'Slow Page Load', value: IssueType.SLOW_PAGE_LOAD },
|
||||
{ text: 'Crash', value: IssueType.CRASH },
|
||||
{ text: 'Custom', value: IssueType.CUSTOM },
|
||||
{ text: 'Error', value: IssueType.JS_EXCEPTION },
|
||||
{ label: 'Click Rage', value: IssueType.CLICK_RAGE },
|
||||
{ label: 'Dead Click', value: IssueType.DEAD_CLICK },
|
||||
{ label: 'Excessive Scrolling', value: IssueType.EXCESSIVE_SCROLLING },
|
||||
{ label: 'Bad Request', value: IssueType.BAD_REQUEST },
|
||||
{ label: 'Missing Resource', value: IssueType.MISSING_RESOURCE },
|
||||
{ label: 'Memory', value: IssueType.MEMORY },
|
||||
{ label: 'CPU', value: IssueType.CPU },
|
||||
{ label: 'Slow Resource', value: IssueType.SLOW_RESOURCE },
|
||||
{ label: 'Slow Page Load', value: IssueType.SLOW_PAGE_LOAD },
|
||||
{ label: 'Crash', value: IssueType.CRASH },
|
||||
{ label: 'Custom', value: IssueType.CUSTOM },
|
||||
{ label: 'Error', value: IssueType.JS_EXCEPTION },
|
||||
]
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default class MetricStore implements IMetricStore {
|
|||
|
||||
// State Actions
|
||||
init(metric?: IWidget|null) {
|
||||
const _metric = new Widget().fromJson(sampleJson)
|
||||
const _metric = new Widget().fromJson(sampleJsonErrors)
|
||||
this.instance.update(metric || _metric)
|
||||
|
||||
// this.instance.update(metric || new Widget())
|
||||
|
|
@ -191,7 +191,7 @@ export default class MetricStore implements IMetricStore {
|
|||
}
|
||||
}
|
||||
|
||||
const sampleJson = {
|
||||
const sampleJsonFunnel = {
|
||||
// metricId: 1,
|
||||
name: "Funnel Sample",
|
||||
metricType: 'funnel',
|
||||
|
|
@ -199,31 +199,31 @@ const sampleJson = {
|
|||
{
|
||||
name: 'Series 1',
|
||||
filter: {
|
||||
eventsOrder: 'then',
|
||||
filters: [
|
||||
{
|
||||
type: 'LOCATION',
|
||||
operator: 'is',
|
||||
value: ['/sessions', '/errors', '/users'],
|
||||
percent: 100,
|
||||
completed: 60,
|
||||
dropped: 40,
|
||||
},
|
||||
{
|
||||
type: 'LOCATION',
|
||||
operator: 'is',
|
||||
value: ['/sessions'],
|
||||
percent: 80,
|
||||
completed: 40,
|
||||
dropped: 60,
|
||||
},
|
||||
{
|
||||
type: 'CLICK',
|
||||
operator: 'on',
|
||||
value: ['DASHBOARDS'],
|
||||
percent: 80,
|
||||
completed: 10,
|
||||
dropped: 90,
|
||||
}
|
||||
{ type: 'LOCATION', operator: 'is', value: ['/sessions', '/errors', '/users'], percent: 100, completed: 60, dropped: 40, },
|
||||
{ type: 'LOCATION', operator: 'is', value: ['/sessions'], percent: 80, completed: 40, dropped: 60, },
|
||||
{ type: 'CLICK', operator: 'on', value: ['DASHBOARDS'], percent: 80, completed: 10, dropped: 90, }
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
const sampleJsonErrors = {
|
||||
// metricId: 1,
|
||||
name: "Errors Sample",
|
||||
metricType: 'errors',
|
||||
metricFormat: 'sessionCount',
|
||||
series: [
|
||||
{
|
||||
name: 'Series 1',
|
||||
filter: {
|
||||
eventsOrder: 'then',
|
||||
filters: [
|
||||
{ type: 'LOCATION', operator: 'is', value: ['/sessions', '/errors', '/users'], percent: 100, completed: 60, dropped: 40, },
|
||||
{ type: 'LOCATION', operator: 'is', value: ['/sessions'], percent: 80, completed: 40, dropped: 60, },
|
||||
{ type: 'CLICK', operator: 'on', value: ['DASHBOARDS'], percent: 80, completed: 10, dropped: 90, }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ export default class Widget implements IWidget {
|
|||
this.viewType = json.viewType
|
||||
this.name = json.name
|
||||
this.series = json.series ? json.series.map((series: any) => new FilterSeries().fromJson(series)) : [],
|
||||
this.dashboards = json.dashboards
|
||||
this.dashboards = json.dashboards || []
|
||||
this.owner = json.ownerEmail
|
||||
this.lastModified = json.editedAt || json.createdAt ? DateTime.fromMillis(json.editedAt || json.createdAt) : null
|
||||
this.config = json.config
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue