fix(ui) - data reload on change
This commit is contained in:
parent
fabbe92086
commit
3c0d8f81fc
9 changed files with 68 additions and 52 deletions
|
|
@ -13,8 +13,7 @@ import { IconButton, Icon } from 'UI';
|
|||
import FilterSelection from 'Shared/Filters/FilterSelection';
|
||||
import SeriesName from './SeriesName';
|
||||
import cn from 'classnames';
|
||||
import { useDashboardStore } from '../../store/store';
|
||||
import { observer, useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
interface Props {
|
||||
seriesIndex: number;
|
||||
|
|
@ -37,7 +36,7 @@ function FilterSeries(props: Props) {
|
|||
const [expanded, setExpanded] = useState(true)
|
||||
const { series, seriesIndex } = props;
|
||||
|
||||
useEffect(observeChanges, [series])
|
||||
useEffect(observeChanges, [series.filter]);
|
||||
|
||||
const onAddFilter = (filter) => {
|
||||
series.filter.addFilter(filter)
|
||||
|
|
@ -49,12 +48,10 @@ function FilterSeries(props: Props) {
|
|||
|
||||
const onChangeEventsOrder = (e, { name, value }) => {
|
||||
series.filter.updateKey(name, value)
|
||||
// props.editSeriesFilter(seriesIndex, { eventsOrder: value });
|
||||
}
|
||||
|
||||
const onRemoveFilter = (filterIndex) => {
|
||||
series.filter.removeFilter(filterIndex)
|
||||
// props.removeSeriesFilterFilter(seriesIndex, filterIndex);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -4,29 +4,32 @@ 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 { useObserver } from 'mobx-react-lite';
|
||||
import { observer, useObserver } from 'mobx-react-lite';
|
||||
import { Loader } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import WidgetPredefinedChart from '../WidgetPredefinedChart';
|
||||
import CustomMetricOverviewChart from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricOverviewChart';
|
||||
import { getStartAndEndTimestampsByDensity } from 'Types/dashboard/helper';
|
||||
import { debounce } from 'App/utils';
|
||||
interface Props {
|
||||
metric: any;
|
||||
isWidget?: boolean
|
||||
}
|
||||
function WidgetChart(props: Props) {
|
||||
const { isWidget = false, metric } = props;
|
||||
const { dashboardStore } = useStore();
|
||||
const { dashboardStore, metricStore } = useStore();
|
||||
const _metric: any = useObserver(() => metricStore.instance);
|
||||
const period = useObserver(() => dashboardStore.period);
|
||||
const drillDownFilter = useObserver(() => dashboardStore.drillDownFilter);
|
||||
const colors = Styles.customMetricColors;
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const isOverviewWidget = metric.metricType === 'predefined' && metric.viewType === 'overview';
|
||||
const params = { density: isOverviewWidget ? 7 : 70 }
|
||||
const metricParams = { ...params }
|
||||
const prevMetricRef = useRef<any>();
|
||||
const [data, setData] = useState<any>(metric.data);
|
||||
|
||||
|
||||
const isTableWidget = metric.metricType === 'table' && metric.viewType === 'table';
|
||||
const isPieChart = metric.metricType === 'table' && metric.viewType === 'pieChart';
|
||||
|
||||
|
|
@ -52,21 +55,28 @@ function WidgetChart(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
const depsString = JSON.stringify(_metric.series);
|
||||
|
||||
|
||||
const fetchMetricChartData = (metric, payload, isWidget) => {
|
||||
setLoading(true)
|
||||
dashboardStore.fetchMetricChartData(metric, payload, isWidget).then((res: any) => {
|
||||
setData(res);
|
||||
}).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
const debounceRequest: any = React.useCallback(debounce(fetchMetricChartData, 500), []);
|
||||
useEffect(() => {
|
||||
if (prevMetricRef.current && prevMetricRef.current.name !== metric.name) {
|
||||
prevMetricRef.current = metric;
|
||||
return
|
||||
};
|
||||
prevMetricRef.current = metric;
|
||||
|
||||
setLoading(true);
|
||||
const payload = isWidget ? { ...params } : { ...metricParams, ...metric.toJson() };
|
||||
dashboardStore.fetchMetricChartData(metric, payload, isWidget).then((res: any) => {
|
||||
setData(res);
|
||||
}).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, [period]);
|
||||
debounceRequest(metric, payload, isWidget);
|
||||
}, [period, depsString]);
|
||||
|
||||
const renderChart = () => {
|
||||
const { metricType, viewType } = metric;
|
||||
|
|
@ -121,10 +131,10 @@ function WidgetChart(props: Props) {
|
|||
return <div>Unknown</div>;
|
||||
}
|
||||
return useObserver(() => (
|
||||
<Loader loading={loading}>
|
||||
<Loader loading={loading} size="small" style={{ height: `${isOverviewWidget ? 100 : 240}px` }}>
|
||||
{renderChart()}
|
||||
</Loader>
|
||||
));
|
||||
}
|
||||
|
||||
export default WidgetChart;
|
||||
export default observer(WidgetChart);
|
||||
|
|
@ -4,9 +4,8 @@ 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 { HelpText, Button, Icon } from 'UI'
|
||||
import { Button, Icon } from 'UI'
|
||||
import FilterSeries from '../FilterSeries';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { confirm } from 'UI/Confirmation';
|
||||
import { withSiteId, dashboardMetricDetails, metricDetails } from 'App/routes'
|
||||
import DashboardSelectionModal from '../DashboardSelectionModal/DashboardSelectionModal';
|
||||
|
|
@ -28,31 +27,34 @@ function WidgetForm(props: Props) {
|
|||
const timeseriesOptions = metricOf.filter(i => i.type === 'timeseries');
|
||||
const tableOptions = metricOf.filter(i => i.type === 'table');
|
||||
const isTable = metric.metricType === 'table';
|
||||
const isTimeSeries = metric.metricType === 'timeseries';
|
||||
const _issueOptions = [{ text: 'All', value: 'all' }].concat(issueOptions);
|
||||
const canAddToDashboard = metric.exists() && dashboards.length > 0;
|
||||
|
||||
const write = ({ target: { value, name } }) => metricStore.merge({ [ name ]: value });
|
||||
const writeOption = (e, { value, name }) => {
|
||||
metricStore.merge({ [ name ]: value });
|
||||
const obj = { [ name ]: value };
|
||||
|
||||
if (name === 'metricValue') {
|
||||
metricStore.merge({ metricValue: [value] });
|
||||
obj['metricValue'] = [value];
|
||||
}
|
||||
|
||||
if (name === 'metricOf') {
|
||||
if (value === FilterKey.ISSUE) {
|
||||
metricStore.merge({ metricValue: ['all'] });
|
||||
obj['metricValue'] = ['all'];
|
||||
}
|
||||
}
|
||||
|
||||
if (name === 'metricType') {
|
||||
if (value === 'timeseries') {
|
||||
metricStore.merge({ metricOf: timeseriesOptions[0].value, viewType: 'lineChart' });
|
||||
obj['metricOf'] = timeseriesOptions[0].value;
|
||||
obj['viewType'] = 'lineChart';
|
||||
} else if (value === 'table') {
|
||||
metricStore.merge({ metricOf: tableOptions[0].value, viewType: 'table' });
|
||||
obj['metricOf'] = tableOptions[0].value;
|
||||
obj['viewType'] = 'table';
|
||||
}
|
||||
}
|
||||
|
||||
metricStore.merge(obj);
|
||||
};
|
||||
|
||||
const onSave = () => {
|
||||
|
|
@ -172,7 +174,7 @@ function WidgetForm(props: Props) {
|
|||
'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.'
|
||||
}
|
||||
observeChanges={onObserveChanges}
|
||||
// observeChanges={onObserveChanges}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ import { useStore } from 'App/mstore';
|
|||
import SessionItem from 'Shared/SessionItem';
|
||||
import { observer, useObserver } from 'mobx-react-lite';
|
||||
import { DateTime } from 'luxon';
|
||||
import { debounce } from 'App/utils';
|
||||
interface Props {
|
||||
className?: string;
|
||||
}
|
||||
function WidgetSessions(props: Props) {
|
||||
const { className = '' } = props;
|
||||
const [data, setData] = useState<any>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [seriesOptions, setSeriesOptions] = useState([
|
||||
{ text: 'All', value: 'all' },
|
||||
]);
|
||||
|
|
@ -30,18 +32,27 @@ function WidgetSessions(props: Props) {
|
|||
]);
|
||||
}, [data]);
|
||||
|
||||
const fetchSessions = (metricId, filter) => {
|
||||
setLoading(true)
|
||||
widget.fetchSessions(metricId, filter).then(res => {
|
||||
setData(res)
|
||||
}).finally(() => {
|
||||
setLoading(false)
|
||||
});
|
||||
}
|
||||
|
||||
const filteredSessions = getListSessionsBySeries(data, activeSeries);
|
||||
const { dashboardStore, metricStore } = useStore();
|
||||
const filter = useObserver(() => dashboardStore.drillDownFilter);
|
||||
const widget: any = useObserver(() => metricStore.instance);
|
||||
const startTime = DateTime.fromMillis(filter.startTimestamp).toFormat('LLL dd, yyyy HH:mm a');
|
||||
const endTime = DateTime.fromMillis(filter.endTimestamp).toFormat('LLL dd, yyyy HH:mm a');
|
||||
const debounceRequest: any = React.useCallback(debounce(fetchSessions, 1000), []);
|
||||
|
||||
const depsString = JSON.stringify(widget.series);
|
||||
useEffect(() => {
|
||||
widget.fetchSessions({ ...filter, series: widget.toJsonDrilldown() }).then(res => {
|
||||
setData(res);
|
||||
});
|
||||
}, [filter.startTimestamp, filter.endTimestamp, filter.filters]);
|
||||
debounceRequest(widget.metricId, { ...filter, series: widget.toJsonDrilldown() });
|
||||
}, [filter.startTimestamp, filter.endTimestamp, filter.filters, depsString]);
|
||||
|
||||
return useObserver(() => (
|
||||
<div className={cn(className)}>
|
||||
|
|
@ -71,7 +82,7 @@ function WidgetSessions(props: Props) {
|
|||
</div>
|
||||
|
||||
<div className="mt-3">
|
||||
<Loader loading={widget.sessionsLoading}>
|
||||
<Loader loading={loading}>
|
||||
<NoContent
|
||||
title="No recordings found"
|
||||
show={filteredSessions.length === 0}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import React, { useState } from 'react';
|
||||
import { useStore } from 'App/mstore';
|
||||
import WidgetForm from '../WidgetForm';
|
||||
import WidgetPreview from '../WidgetPreview';
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ function WidgetWrapper(props: Props) {
|
|||
const widget: any = useObserver(() => props.widget);
|
||||
const isPredefined = widget.metricType === 'predefined';
|
||||
const dashboard = useObserver(() => dashboardStore.selectedDashboard);
|
||||
const isOverviewWidget = widget.widgetType === 'predefined' && widget.viewType === 'overview';
|
||||
|
||||
const [{ opacity, isDragging }, dragRef] = useDrag({
|
||||
type: 'item',
|
||||
|
|
@ -117,7 +118,7 @@ function WidgetWrapper(props: Props) {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<LazyLoad height={100} offset={120} >
|
||||
<LazyLoad height={!isTemplate ? 300 : 10} offset={!isTemplate ? 100 : 10} >
|
||||
<div className="px-4" onClick={onChartClick}>
|
||||
<WidgetChart metric={widget} isWidget={isWidget} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -73,13 +73,13 @@ export default class MetricStore implements IMetricStore {
|
|||
paginatedList: computed,
|
||||
})
|
||||
|
||||
reaction(
|
||||
() => this.metricsSearch,
|
||||
(metricsSearch) => { // TODO filter the list for View
|
||||
this.page = 1
|
||||
this.paginatedList
|
||||
}
|
||||
)
|
||||
// reaction(
|
||||
// () => this.metricsSearch,
|
||||
// (metricsSearch) => { // TODO filter the list for View
|
||||
// this.page = 1
|
||||
// this.paginatedList
|
||||
// }
|
||||
// )
|
||||
}
|
||||
|
||||
// State Actions
|
||||
|
|
@ -92,7 +92,7 @@ export default class MetricStore implements IMetricStore {
|
|||
}
|
||||
|
||||
merge(object: any) {
|
||||
this.instance = Object.assign(this.instance, object)
|
||||
Object.assign(this.instance, object)
|
||||
}
|
||||
|
||||
reset(id: string) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx"
|
||||
import { FilterKey, FilterType } from 'Types/filter/filterType'
|
||||
import { filtersMap } from 'Types/filter/newFilter'
|
||||
import { makeAutoObservable, runInAction, observable, action } from "mobx"
|
||||
import FilterItem from "./filterItem"
|
||||
|
||||
export interface IFilter {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { DateTime } from 'luxon';
|
|||
import { IFilter } from "./filter";
|
||||
import { metricService } from "App/services";
|
||||
import Session, { ISession } from "App/mstore/types/session";
|
||||
|
||||
export interface IWidget {
|
||||
metricId: any
|
||||
widgetId: any
|
||||
|
|
@ -45,7 +46,7 @@ export interface IWidget {
|
|||
exists(): boolean
|
||||
toWidget(): any
|
||||
setData(data: any): void
|
||||
fetchSessions(filter: any): Promise<any>
|
||||
fetchSessions(metricId: any, filter: any): Promise<any>
|
||||
}
|
||||
export default class Widget implements IWidget {
|
||||
public static get ID_KEY():string { return "metricId" }
|
||||
|
|
@ -195,18 +196,15 @@ export default class Widget implements IWidget {
|
|||
})
|
||||
}
|
||||
|
||||
fetchSessions(filter: any): Promise<any> {
|
||||
this.sessionsLoading = true
|
||||
fetchSessions(metricId: any, filter: any): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
metricService.fetchSessions(this.metricId, filter).then(response => {
|
||||
metricService.fetchSessions(metricId, filter).then(response => {
|
||||
resolve(response.map(cat => {
|
||||
return {
|
||||
...cat,
|
||||
sessions: cat.sessions.map(s => new Session().fromJson(s))
|
||||
}
|
||||
}))
|
||||
}).finally(() => {
|
||||
this.sessionsLoading = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue