From a63ff8ae1223f843c05f81df1627ac486f34b8b5 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 23 Jun 2022 18:59:21 +0200 Subject: [PATCH] fix(ui) - widget change detection on route change --- .../components/FilterSeries/FilterSeries.tsx | 7 ++++--- .../Dashboard/components/WidgetForm/WidgetForm.tsx | 4 ++-- .../Dashboard/components/WidgetView/WidgetView.tsx | 13 ++++++++++++- frontend/app/mstore/metricStore.ts | 9 ++++----- frontend/app/mstore/types/widget.ts | 8 ++++---- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index 67e39ed49..ccb269cbd 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -36,22 +36,24 @@ function FilterSeries(props: Props) { const [expanded, setExpanded] = useState(true) const { series, seriesIndex } = props; - useEffect(observeChanges, [series.filter]); - const onAddFilter = (filter: any) => { series.filter.addFilter(filter) + observeChanges() } const onUpdateFilter = (filterIndex: any, filter: any) => { series.filter.updateFilter(filterIndex, filter) + observeChanges() } const onChangeEventsOrder = (e, { name, value }: any) => { series.filter.updateKey(name, value) + observeChanges() } const onRemoveFilter = (filterIndex: any) => { series.filter.removeFilter(filterIndex) + observeChanges() } return ( @@ -80,7 +82,6 @@ function FilterSeries(props: Props) { onUpdateFilter={onUpdateFilter} onRemoveFilter={onRemoveFilter} onChangeEventsOrder={onChangeEventsOrder} - observeChanges={observeChanges} /> ): (
{emptyMessage}
diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx index 31f78c8e7..dd018f16b 100644 --- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx +++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { metricTypes, metricOf, issueOptions } from 'App/constants/filterOptions'; import { FilterKey } from 'Types/filter/filterType'; import { useStore } from 'App/mstore'; @@ -31,7 +31,6 @@ function WidgetForm(props: Props) { const canAddToDashboard = metric.exists() && dashboards.length > 0; const canAddSeries = metric.series.length < 3; - // const write = ({ target: { value, name } }) => metricStore.merge({ [ name ]: value }); const writeOption = ({ value, name }: any) => { value = Array.isArray(value) ? value : value.value const obj: any = { [ name ]: value }; @@ -170,6 +169,7 @@ function WidgetForm(props: Props) { {metric.series.length > 0 && metric.series.slice(0, (isTable || isFunnel) ? 1 : metric.series.length).map((series: any, index: number) => (
metric.updateKey('hasChanged', true)} hideHeader={ isTable } seriesIndex={index} series={series} diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx index 807f0f8ff..b4d55cbc4 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetView.tsx @@ -11,6 +11,7 @@ import { withSiteId } from 'App/routes'; import FunnelIssues from '../Funnels/FunnelIssues/FunnelIssues'; import Breadcrumb from 'Shared/Breadcrumb'; import { FilterKey } from 'Types/filter/filterType'; +import { Prompt } from 'react-router' interface Props { history: any; @@ -23,12 +24,13 @@ function WidgetView(props: Props) { const widget = useObserver(() => metricStore.instance); const loading = useObserver(() => metricStore.isLoading); const [expanded, setExpanded] = useState(!metricId || metricId === 'create'); + const hasChanged = useObserver(() => widget.hasChanged) + console.log('hasChanged', hasChanged) const dashboards = useObserver(() => dashboardStore.dashboards); const dashboard = useObserver(() => dashboards.find((d: any) => d.dashboardId == dashboardId)); const dashboardName = dashboard ? dashboard.name : null; - React.useEffect(() => { if (metricId && metricId !== 'create') { metricStore.fetch(metricId, dashboardStore.period); @@ -48,6 +50,15 @@ function WidgetView(props: Props) { return useObserver(() => ( + { + if (location.pathname.includes('/metrics/') || location.pathname.includes('/metric/')) { + return true; + } + return 'You have unsaved changes. Are you sure you want to leave?'; + }} + />
fetchList(): void - fetch(metricId: string) - delete(metric: IWidget) + fetch(metricId: string, period?: any): Promise + delete(metric: IWidget): Promise } export default class MetricStore implements IMetricStore { @@ -98,6 +98,7 @@ export default class MetricStore implements IMetricStore { merge(object: any) { Object.assign(this.instance, object) + this.instance.updateKey('hasChanged', true) } reset(id: string) { @@ -153,6 +154,7 @@ export default class MetricStore implements IMetricStore { toast.error('Error saving metric') reject() }).finally(() => { + this.instance.updateKey('hasChanged', false) this.isSaving = false }) }) @@ -172,9 +174,6 @@ export default class MetricStore implements IMetricStore { this.isLoading = true return metricService.getMetric(id) .then((metric: any) => { - // if (period) { - // metric.period = period - // } return this.instance = new Widget().fromJson(metric, period) }).finally(() => { this.isLoading = false diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts index fe0ecb0c5..24356c4be 100644 --- a/frontend/app/mstore/types/widget.ts +++ b/frontend/app/mstore/types/widget.ts @@ -40,13 +40,13 @@ export interface IWidget { limit: number params: any period: any - hasChanges: boolean + hasChanged: boolean updateKey(key: string, value: any): void removeSeries(index: number): void addSeries(): void fromJson(json: any): void - toJsonDrilldown(json: any): void + toJsonDrilldown(): void toJson(): any validate(): void update(data: any): void @@ -54,7 +54,7 @@ export interface IWidget { toWidget(): any setData(data: any): void fetchSessions(metricId: any, filter: any): Promise - setPeriod(period: Period): void + setPeriod(period: any): void } export default class Widget implements IWidget { public static get ID_KEY():string { return "metricId" } @@ -80,7 +80,7 @@ export default class Widget implements IWidget { params: any = { density: 70 } period: any = Period({ rangeName: LAST_24_HOURS }) // temp value in detail view - hasChanges: boolean = false + hasChanged: boolean = false sessionsLoading: boolean = false