change(ui): add clickmap card type, add query effect for metric type dd
This commit is contained in:
parent
4a611a6d4a
commit
013db32b60
8 changed files with 66 additions and 34 deletions
|
|
@ -4,7 +4,7 @@ import CustomMetricPercentage from 'App/components/Dashboard/Widgets/CustomMetri
|
|||
import CustomMetricTable from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable';
|
||||
import CustomMetricPieChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart';
|
||||
import { Styles } from 'App/components/Dashboard/Widgets/common';
|
||||
import { observer, useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Loader } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import WidgetPredefinedChart from '../WidgetPredefinedChart';
|
||||
|
|
@ -13,23 +13,25 @@ import { getStartAndEndTimestampsByDensity } from 'Types/dashboard/helper';
|
|||
import { debounce } from 'App/utils';
|
||||
import useIsMounted from 'App/hooks/useIsMounted'
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
|
||||
import { CLICKMAP } from 'App/constants/card';
|
||||
import FunnelWidget from 'App/components/Funnels/FunnelWidget';
|
||||
import ErrorsWidget from '../Errors/ErrorsWidget';
|
||||
import SessionWidget from '../Sessions/SessionWidget';
|
||||
import CustomMetricTableSessions from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions';
|
||||
import CustomMetricTableErrors from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableErrors';
|
||||
|
||||
interface Props {
|
||||
metric: any;
|
||||
isWidget?: boolean;
|
||||
isTemplate?: boolean;
|
||||
}
|
||||
|
||||
function WidgetChart(props: Props) {
|
||||
const { isWidget = false, metric, isTemplate } = props;
|
||||
const { dashboardStore, metricStore } = useStore();
|
||||
const _metric: any = metricStore.instance;
|
||||
const period = useObserver(() => dashboardStore.period);
|
||||
const drillDownPeriod = useObserver(() => dashboardStore.drillDownPeriod);
|
||||
const period = dashboardStore.period;
|
||||
const drillDownPeriod = dashboardStore.drillDownPeriod;
|
||||
const drillDownFilter = dashboardStore.drillDownFilter;
|
||||
const colors = Styles.customMetricColors;
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
|
@ -175,6 +177,11 @@ function WidgetChart(props: Props) {
|
|||
)
|
||||
}
|
||||
}
|
||||
if (metricType === CLICKMAP) {
|
||||
return (
|
||||
<div>rendering clickmap</div>
|
||||
)
|
||||
}
|
||||
|
||||
return <div>Unknown</div>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { metricTypes, metricOf, issueOptions } from 'App/constants/filterOptions';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Button, Icon, SegmentSelection } from 'UI'
|
||||
import FilterSeries from '../FilterSeries';
|
||||
import { confirm, Tooltip } from 'UI';
|
||||
|
|
@ -28,8 +28,8 @@ function WidgetForm(props: Props) {
|
|||
const { history, match: { params: { siteId, dashboardId } } } = props;
|
||||
const { metricStore, dashboardStore } = useStore();
|
||||
const dashboards = dashboardStore.dashboards;
|
||||
const isSaving = useObserver(() => metricStore.isSaving);
|
||||
const metric: any = useObserver(() => metricStore.instance)
|
||||
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');
|
||||
|
|
@ -37,7 +37,7 @@ function WidgetForm(props: Props) {
|
|||
const isFunnel = metric.metricType === 'funnel';
|
||||
const canAddToDashboard = metric.exists() && dashboards.length > 0;
|
||||
const canAddSeries = metric.series.length < 3;
|
||||
const eventsLength = useObserver(() => metric.series[0].filter.filters.filter((i: any) => i.isEvent).length)
|
||||
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) => {
|
||||
|
|
@ -100,12 +100,12 @@ function WidgetForm(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
return useObserver(() => (
|
||||
return (
|
||||
<div className="p-6">
|
||||
<div className="form-group">
|
||||
<label className="font-medium">Metric Type</label>
|
||||
<div className="flex items-center">
|
||||
<MetricTypeDropdown onSelect={writeOption} />
|
||||
<MetricTypeDropdown />
|
||||
<MetricSubtypeDropdown onSelect={writeOption} />
|
||||
|
||||
{/* {metric.metricType === 'timeseries' && (
|
||||
|
|
@ -216,7 +216,7 @@ function WidgetForm(props: Props) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
export default WidgetForm;
|
||||
export default observer(WidgetForm);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { TYPES } from 'App/constants/card';
|
||||
import { MetricType } from 'App/components/Dashboard/components/MetricTypeItem/MetricTypeItem';
|
||||
import React from 'react';
|
||||
|
|
@ -12,8 +12,8 @@ interface Props {
|
|||
}
|
||||
function MetricSubtypeDropdown(props: Props) {
|
||||
const { metricStore } = useStore();
|
||||
const metric: any = useObserver(() => metricStore.instance);
|
||||
|
||||
const metric: any = metricStore.instance;
|
||||
|
||||
const options = React.useMemo(() => {
|
||||
const type = TYPES.find((i: MetricType) => i.slug === metric.metricType);
|
||||
if (type && type.subTypes) {
|
||||
|
|
@ -56,4 +56,4 @@ function MetricSubtypeDropdown(props: Props) {
|
|||
) : null;
|
||||
}
|
||||
|
||||
export default MetricSubtypeDropdown;
|
||||
export default observer(MetricSubtypeDropdown);
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ import Select from 'Shared/Select';
|
|||
import { MetricType } from 'App/components/Dashboard/components/MetricTypeItem/MetricTypeItem';
|
||||
import { components } from 'react-select';
|
||||
import CustomDropdownOption from 'Shared/CustomDropdownOption';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import withLocationHandlers from 'HOCs/withLocationHandlers';
|
||||
|
||||
interface Props {
|
||||
onSelect: any;
|
||||
query: Record<string, (key: string) => any>;
|
||||
}
|
||||
function MetricTypeDropdown(props: Props) {
|
||||
const { metricStore } = useStore();
|
||||
const metric: any = useObserver(() => metricStore.instance);
|
||||
const metric: any = metricStore.instance;
|
||||
const options: any = useMemo(() => {
|
||||
// TYPES.shift(); // remove "Add from library" item
|
||||
return TYPES.filter((i: MetricType) => i.slug !== LIBRARY).map((i: MetricType) => ({
|
||||
|
|
@ -23,16 +24,25 @@ function MetricTypeDropdown(props: Props) {
|
|||
}));
|
||||
}, []);
|
||||
|
||||
const onSelect = (_: any, option: Record<string, any>) =>
|
||||
props.onSelect({ value: { value: option.value }, name: option.name });
|
||||
React.useEffect(() => {
|
||||
const queryCardType = props.query.get('type')
|
||||
if (queryCardType && options.length > 0 && metric.metricType) {
|
||||
const type = options.find(i => i.value === queryCardType)
|
||||
setTimeout(() => onChange(type.value), 0)
|
||||
console.log('trying to change to ', type, metric.metricType)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const onChange = (type: string) => {
|
||||
metricStore.changeType(type)
|
||||
}
|
||||
return (
|
||||
<Select
|
||||
name="metricType"
|
||||
placeholder="Select Card Type"
|
||||
options={options}
|
||||
value={options.find((i: any) => i.value === metric.metricType) || options[0]}
|
||||
onChange={props.onSelect}
|
||||
onChange={(selected) => onChange(selected.value.value as string)}
|
||||
// onSelect={onSelect}
|
||||
components={{
|
||||
MenuList: ({ children, ...props }: any) => {
|
||||
|
|
@ -51,4 +61,4 @@ function MetricTypeDropdown(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default MetricTypeDropdown;
|
||||
export default withLocationHandlers()(observer(MetricTypeDropdown));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import cn from 'classnames';
|
|||
import WidgetWrapper from '../WidgetWrapper';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { SegmentSelection, Button, Icon } from 'UI';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import WidgetDateRange from '../WidgetDateRange/WidgetDateRange';
|
||||
// import Period, { LAST_24_HOURS, LAST_30_DAYS } from 'Types/app/period';
|
||||
|
|
@ -18,12 +18,12 @@ function WidgetPreview(props: Props) {
|
|||
const { className = '' } = props;
|
||||
const { metricStore, dashboardStore } = useStore();
|
||||
const dashboards = dashboardStore.dashboards;
|
||||
const metric: any = useObserver(() => metricStore.instance);
|
||||
const metric: any = metricStore.instance;
|
||||
const isTimeSeries = metric.metricType === 'timeseries';
|
||||
const isTable = metric.metricType === 'table';
|
||||
const drillDownFilter = useObserver(() => dashboardStore.drillDownFilter);
|
||||
const disableVisualization = useObserver(() => metric.metricOf === FilterKey.SESSIONS || metric.metricOf === FilterKey.ERRORS);
|
||||
// const period = useObserver(() => dashboardStore.drillDownPeriod);
|
||||
const drillDownFilter = dashboardStore.drillDownFilter;
|
||||
const disableVisualization = metric.metricOf === FilterKey.SESSIONS || metric.metricOf === FilterKey.ERRORS;
|
||||
// const period = dashboardStore.drillDownPeriod;
|
||||
|
||||
const chagneViewType = (e, { name, value }: any) => {
|
||||
metric.update({ [ name ]: value });
|
||||
|
|
@ -40,7 +40,7 @@ function WidgetPreview(props: Props) {
|
|||
|
||||
const canAddToDashboard = metric.exists() && dashboards.length > 0;
|
||||
|
||||
return useObserver(() => (
|
||||
return (
|
||||
<>
|
||||
<div className={cn(className, 'bg-white rounded border')}>
|
||||
<div className="flex items-center justify-between px-4 pt-2">
|
||||
|
|
@ -93,7 +93,7 @@ function WidgetPreview(props: Props) {
|
|||
className="ml-2 p-0"
|
||||
onClick={() => setShowDashboardSelectionModal(true)}
|
||||
disabled={!canAddToDashboard}
|
||||
>
|
||||
>
|
||||
<Icon name="columns-gap-filled" size="14" className="mr-2" color="teal"/>
|
||||
Add to Dashboard
|
||||
</Button>
|
||||
|
|
@ -112,7 +112,7 @@ function WidgetPreview(props: Props) {
|
|||
/>
|
||||
)}
|
||||
</>
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
export default WidgetPreview;
|
||||
export default observer(WidgetPreview);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export interface CardType {
|
|||
export const LIBRARY = 'library';
|
||||
export const TIMESERIES = 'timeseries';
|
||||
export const TABLE = 'table';
|
||||
export const CLICKMAP = 'clickmap'
|
||||
|
||||
export const TYPES: CardType[] = [
|
||||
{
|
||||
|
|
@ -20,6 +21,15 @@ export const TYPES: CardType[] = [
|
|||
description: 'Select a pre existing card from card library',
|
||||
slug: LIBRARY,
|
||||
},
|
||||
{
|
||||
title: 'Clickmap',
|
||||
icon: 'puzzle-piece',
|
||||
description: 'Track the features that are being used the most.',
|
||||
slug: CLICKMAP,
|
||||
subTypes: [
|
||||
{ title: 'Visited URL', slug: FilterKey.CLICKMAP_URL, description: "" },
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Timeseries',
|
||||
icon: 'graph-up',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { makeAutoObservable, computed } from 'mobx';
|
||||
import { makeAutoObservable } from 'mobx';
|
||||
import Widget from './types/widget';
|
||||
import { metricService, errorService } from 'App/services';
|
||||
import { toast } from 'react-toastify';
|
||||
|
|
@ -24,7 +24,6 @@ export default class MetricStore {
|
|||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
@computed
|
||||
get sortedWidgets() {
|
||||
return [...this.metrics].sort((a, b) => b.lastModified - a.lastModified);
|
||||
}
|
||||
|
|
@ -44,6 +43,10 @@ export default class MetricStore {
|
|||
this.instance.updateKey('hasChanged', true);
|
||||
}
|
||||
|
||||
changeType(value: string) {
|
||||
this.instance.update({ metricType: value})
|
||||
}
|
||||
|
||||
reset(id: string) {
|
||||
const metric = this.findById(id);
|
||||
if (metric) {
|
||||
|
|
|
|||
|
|
@ -274,4 +274,6 @@ export enum FilterKey {
|
|||
RESOURCE_TYPE_VS_RESPONSE_END = 'resourceTypeVsResponseEnd',
|
||||
RESOURCE_FETCH_TIME = 'resourceFetchTime',
|
||||
SLOWEST_RESOURCES = 'slowestResources',
|
||||
|
||||
CLICKMAP_URL = 'clickmapUrl'
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue