change(ui): apply session url series by default when switching on clickmap

This commit is contained in:
sylenien 2022-12-16 14:58:58 +01:00 committed by Shekar Siri
parent 7995e665cd
commit 41b8915bb3
3 changed files with 188 additions and 207 deletions

View file

@ -3,126 +3,128 @@ import { metricOf, issueOptions } from 'App/constants/filterOptions';
import { FilterKey } from 'Types/filter/filterType';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { Button, Icon } from 'UI'
import { Button, Icon } from 'UI';
import FilterSeries from '../FilterSeries';
import { confirm, Tooltip, Input } from 'UI';
import Select from 'Shared/Select'
import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes'
import Select from 'Shared/Select';
import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes';
import MetricTypeDropdown from './components/MetricTypeDropdown';
import MetricSubtypeDropdown from './components/MetricSubtypeDropdown';
import { TIMESERIES, TABLE, CLICKMAP } from 'App/constants/card'
import { pageUrlOperators } from 'App/constants/filterOptions'
import { TIMESERIES, TABLE, CLICKMAP } from 'App/constants/card';
import { pageUrlOperators } from 'App/constants/filterOptions';
import FilterAutoComplete from 'Shared/Filters/FilterAutoComplete';
import { clickmapFilter } from 'App/types/filter/newFilter';
import { toJS } from 'mobx'
import { toJS } from 'mobx';
import { List } from 'immutable';
interface Props {
history: any;
match: any;
onDelete: () => void;
history: any;
match: any;
onDelete: () => void;
}
const metricIcons = {
timeseries: 'graph-up',
table: 'table',
funnel: 'funnel',
}
timeseries: 'graph-up',
table: 'table',
funnel: 'funnel',
};
function WidgetForm(props: Props) {
const {
history,
match: {
params: { siteId, dashboardId },
},
} = props;
const { metricStore, dashboardStore } = useStore();
const isSaving = metricStore.isSaving;
const metric: any = metricStore.instance;
const { history, match: { params: { siteId, dashboardId } } } = props;
const { metricStore, dashboardStore } = useStore();
const isSaving = metricStore.isSaving;
const metric: any = 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 canAddSeries = metric.series.length < 3;
const eventsLength = metric.series[0].filter.filters.filter((i: any) => i.isEvent).length;
const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1);
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 canAddSeries = metric.series.length < 3;
const eventsLength = metric.series[0].filter.filters.filter((i: any) => i.isEvent).length
const cannotSaveFunnel = isFunnel && (!metric.series[0] || eventsLength <= 1);
const writeOption = ({ value, name }: any) => {
value = Array.isArray(value) ? value : value.value;
const obj: any = { [name]: value };
const writeOption = ({ value, name }: any) => {
value = Array.isArray(value) ? value : value.value
const obj: any = { [ name ]: value };
if (name === 'metricValue') {
obj['metricValue'] = value;
if (name === 'metricValue') {
obj['metricValue'] = value;
// handle issues (remove all when other option is selected)
if (Array.isArray(obj['metricValue']) && obj['metricValue'].length > 1) {
obj['metricValue'] = obj['metricValue'].filter(i => i.value !== 'all');
}
}
if (name === 'metricOf') {
// if (value === FilterKey.ISSUE) {
// obj['metricValue'] = [{ value: 'all', label: 'All' }];
// }
}
if (name === 'metricType') {
if (value === TIMESERIES) {
obj['metricOf'] = timeseriesOptions[0].value;
obj['viewType'] = 'lineChart';
} else if (value === TABLE) {
obj['metricOf'] = tableOptions[0].value;
obj['viewType'] = 'table';
}
if (value === CLICKMAP) {
obj['viewType'] = 'chart'
}
}
metricStore.merge(obj);
};
const onSelect = (_: any, option: Record<string, any>) => writeOption({ value: { value: option.value }, name: option.name})
const onSave = () => {
const wasCreating = !metric.exists()
metricStore.save(metric, dashboardId)
.then((metric: any) => {
if (wasCreating) {
if (parseInt(dashboardId) > 0) {
history.replace(withSiteId(dashboardMetricDetails(dashboardId, metric.metricId), siteId));
const dashboard = dashboardStore.getDashboard(parseInt(dashboardId))
dashboardStore.addWidgetToDashboard(dashboard, [metric.metricId])
} else {
history.replace(withSiteId(metricDetails(metric.metricId), siteId));
}
}
});
// handle issues (remove all when other option is selected)
if (Array.isArray(obj['metricValue']) && obj['metricValue'].length > 1) {
obj['metricValue'] = obj['metricValue'].filter((i) => i.value !== 'all');
}
}
const onDelete = async () => {
if (await confirm({
header: 'Confirm',
confirmButton: 'Yes, delete',
confirmation: `Are you sure you want to permanently delete this metric?`
})) {
metricStore.delete(metric).then(props.onDelete);
}
if (name === 'metricOf') {
// if (value === FilterKey.ISSUE) {
// obj['metricValue'] = [{ value: 'all', label: 'All' }];
// }
}
const updateClickMapURL = (_, item) => {
console.log('updating filter', item)
const newValues = {
value: item
}
metric.series[0].filter.updateFilter(0, newValues)
console.log(toJS(metric.series))
}
console.log(metric.series, metric.series[0].filter)
return (
<div className="p-6">
<div className="form-group">
<label className="font-medium">Metric Type</label>
<div className="flex items-center">
<MetricTypeDropdown onSelect={writeOption} />
<MetricSubtypeDropdown onSelect={writeOption} />
{/* {metric.metricType === 'timeseries' && (
if (name === 'metricType') {
if (value === TIMESERIES) {
obj['metricOf'] = timeseriesOptions[0].value;
obj['viewType'] = 'lineChart';
} else if (value === TABLE) {
obj['metricOf'] = tableOptions[0].value;
obj['viewType'] = 'table';
}
if (value === CLICKMAP) {
obj['viewType'] = 'chart';
if (metric.series[0].filter.filters.length < 1) {
metric.series[0].filter.addFilter({
...clickmapFilter,
value: [''],
},)
}
}
}
metricStore.merge(obj);
};
const onSave = () => {
const wasCreating = !metric.exists();
metricStore.save(metric, dashboardId).then((metric: any) => {
if (wasCreating) {
if (parseInt(dashboardId) > 0) {
history.replace(withSiteId(dashboardMetricDetails(dashboardId, metric.metricId), siteId));
const dashboard = dashboardStore.getDashboard(parseInt(dashboardId));
dashboardStore.addWidgetToDashboard(dashboard, [metric.metricId]);
} else {
history.replace(withSiteId(metricDetails(metric.metricId), siteId));
}
}
});
};
const onDelete = async () => {
if (
await confirm({
header: 'Confirm',
confirmButton: 'Yes, delete',
confirmation: `Are you sure you want to permanently delete this metric?`,
})
) {
metricStore.delete(metric).then(props.onDelete);
}
};
console.log(toJS(metric));
return (
<div className="p-6">
<div className="form-group">
<label className="font-medium">Metric Type</label>
<div className="flex items-center">
<MetricTypeDropdown onSelect={writeOption} />
<MetricSubtypeDropdown onSelect={writeOption} />
{/* {metric.metricType === 'timeseries' && (
<>
<span className="mx-3">of</span>
<Select
@ -134,7 +136,7 @@ function WidgetForm(props: Props) {
</>
)} */}
{/* {metric.metricType === 'table' && (
{/* {metric.metricType === 'table' && (
<>
<span className="mx-3">of</span>
<Select
@ -146,113 +148,92 @@ function WidgetForm(props: Props) {
</>
)} */}
{metric.metricOf === FilterKey.ISSUE && (
<>
<span className="mx-3">issue type</span>
<Select
name="metricValue"
options={issueOptions}
value={metric.metricValue}
onChange={ writeOption }
isMulti={true}
placeholder="All Issues"
/>
</>
)}
{metric.metricOf === FilterKey.ISSUE && (
<>
<span className="mx-3">issue type</span>
<Select
name="metricValue"
options={issueOptions}
value={metric.metricValue}
onChange={writeOption}
isMulti={true}
placeholder="All Issues"
/>
</>
)}
{metric.metricType === 'table' && !(metric.metricOf === FilterKey.ERRORS || metric.metricOf === FilterKey.SESSIONS) && (
<>
<span className="mx-3">showing</span>
<Select
name="metricFormat"
options={[
{ value: 'sessionCount', label: 'Session Count' },
]}
defaultValue={ metric.metricFormat }
onChange={ writeOption }
/>
</>
)}
</div>
{metric.metricType === CLICKMAP && (
<div className='flex items-center'>
<div className="mx-3">Where Visited URL</div>
<Select name="clickMapUrl"
options={pageUrlOperators.reverse()}
defaultValue={pageUrlOperators.reverse()[0].value}
onChange={ () => null }
/>
{/* <Input placeholder="Enter URL or path to select"
/> */}
<FilterAutoComplete
value={metric.series[0].filter.filters[0]?.value || ''} // ?
endpoint="/events/search"
params={{ type: clickmapFilter.key }}
headerText={''}
placeholder={clickmapFilter.placeholder}
onSelect={updateClickMapURL}
icon={clickmapFilter.icon}
hideOrText
/>
</div>
)}
</div>
<div className="form-group">
<div className="flex items-center font-medium py-2">
{`${(isTable || isFunnel) ? 'Filter by' : 'Chart Series'}`}
{!isTable && !isFunnel && (
<Button
className="ml-2"
variant="text-primary"
onClick={() => metric.addSeries()}
disabled={!canAddSeries}
>ADD</Button>
)}
</div>
{metric.series.length > 0 && metric.series.slice(0, (isTable || isFunnel) ? 1 : metric.series.length).map((series: any, index: number) => (
<div className="mb-2" key={series.name}>
<FilterSeries
observeChanges={() => metric.updateKey('hasChanged', true)}
hideHeader={ isTable }
seriesIndex={index}
series={series}
onRemoveSeries={() => metric.removeSeries(index)}
canDelete={metric.series.length > 1}
emptyMessage={isTable ?
'Filter data using any event or attribute. Use Add Step button below to do so.' :
'Add user event or filter to define the series by clicking Add Step.'
}
/>
</div>
))}
</div>
<div className="form-groups flex items-center justify-between">
<Tooltip
title="Cannot save funnel metric without at least 2 events"
disabled={!cannotSaveFunnel}
>
<Button
variant="primary"
onClick={onSave}
disabled={isSaving || cannotSaveFunnel}
>
{metric.exists() ? 'Update' : 'Create'}
</Button>
</Tooltip>
<div className="flex items-center">
{metric.exists() && (
<Button variant="text-primary" onClick={onDelete}>
<Icon name="trash" size="14" className="mr-2" color="teal"/>
Delete
</Button>
)}
</div>
</div>
{metric.metricType === 'table' &&
!(metric.metricOf === FilterKey.ERRORS || metric.metricOf === FilterKey.SESSIONS) && (
<>
<span className="mx-3">showing</span>
<Select
name="metricFormat"
options={[{ value: 'sessionCount', label: 'Session Count' }]}
defaultValue={metric.metricFormat}
onChange={writeOption}
/>
</>
)}
</div>
);
</div>
<div className="form-group">
<div className="flex items-center font-medium py-2">
{`${isTable || isFunnel ? 'Filter by' : 'Chart Series'}`}
{!isTable && !isFunnel && (
<Button
className="ml-2"
variant="text-primary"
onClick={() => metric.addSeries()}
disabled={!canAddSeries}
>
ADD
</Button>
)}
</div>
{metric.series.length > 0 &&
metric.series
.slice(0, isTable || isFunnel ? 1 : metric.series.length)
.map((series: any, index: number) => (
<div className="mb-2" key={series.name}>
<FilterSeries
observeChanges={() => metric.updateKey('hasChanged', true)}
hideHeader={isTable}
seriesIndex={index}
series={series}
onRemoveSeries={() => metric.removeSeries(index)}
canDelete={metric.series.length > 1}
emptyMessage={
isTable
? 'Filter data using any event or attribute. Use Add Step button below to do so.'
: 'Add user event or filter to define the series by clicking Add Step.'
}
/>
</div>
))}
</div>
<div className="form-groups flex items-center justify-between">
<Tooltip
title="Cannot save funnel metric without at least 2 events"
disabled={!cannotSaveFunnel}
>
<Button variant="primary" onClick={onSave} disabled={isSaving || cannotSaveFunnel}>
{metric.exists() ? 'Update' : 'Create'}
</Button>
</Tooltip>
<div className="flex items-center">
{metric.exists() && (
<Button variant="text-primary" onClick={onDelete}>
<Icon name="trash" size="14" className="mr-2" color="teal" />
Delete
</Button>
)}
</div>
</div>
</div>
);
}
export default observer(WidgetForm);

View file

@ -275,5 +275,5 @@ export enum FilterKey {
RESOURCE_FETCH_TIME = 'resourceFetchTime',
SLOWEST_RESOURCES = 'slowestResources',
CLICKMAP_URL = 'clickmapUrl'
CLICKMAP_URL = 'clickMapUrl'
}

View file

@ -57,7 +57,7 @@ export const clickmapFilter = {
key: FilterKey.LOCATION,
type: FilterType.MULTIPLE,
category: FilterCategory.INTERACTIONS,
label: '', placeholder: 'Enter URL or path to select', operator: 'is', operatorOptions: filterOptions.pageUrlOperators, icon: 'filters/location', isEvent: true }
label: 'Visited URL', placeholder: 'Enter URL or path to select', operator: filterOptions.pageUrlOperators[0].value, operatorOptions: filterOptions.pageUrlOperators, icon: 'filters/location', isEvent: true }
const mapFilters = (list) => {
return list.reduce((acc, filter) => {