From 206c7d3a7403ac854062ed4bbed6ecd90484ded5 Mon Sep 17 00:00:00 2001 From: Julian Bez Date: Thu, 25 Apr 2024 14:19:54 +0200 Subject: [PATCH] Mark dashboard stale --- .../Cards/InsightCard/InsightCard.tsx | 8 +++- frontend/src/lib/lemon-ui/Spinner/Spinner.tsx | 8 ++-- frontend/src/scenes/dashboard/Dashboard.tsx | 3 +- .../src/scenes/dashboard/DashboardEditBar.tsx | 37 ++++++++++++++----- .../src/scenes/dashboard/DashboardItems.tsx | 2 + .../src/scenes/dashboard/dashboardLogic.tsx | 7 ++++ 6 files changed, 50 insertions(+), 15 deletions(-) diff --git a/frontend/src/lib/components/Cards/InsightCard/InsightCard.tsx b/frontend/src/lib/components/Cards/InsightCard/InsightCard.tsx index 084371830fa99..31dfdc820bc5a 100644 --- a/frontend/src/lib/components/Cards/InsightCard/InsightCard.tsx +++ b/frontend/src/lib/components/Cards/InsightCard/InsightCard.tsx @@ -133,6 +133,8 @@ export interface InsightCardProps extends Resizeable, React.HTMLAttributes { + extends Pick { insightProps: InsightLogicProps tooFewFunnelSteps?: boolean validationError?: string | null @@ -186,6 +188,7 @@ export function FilterBasedCardContent({ tooFewFunnelSteps, validationError, context, + stale, }: FilterBasedCardContentProps): JSX.Element { const displayedType = getDisplayedType(insight.filters) const VizComponent = displayMap[displayedType]?.element || VizComponentFallback @@ -211,6 +214,7 @@ export function FilterBasedCardContent({ : undefined } > + {stale && !loading && } {loading && } {tooFewFunnelSteps ? ( @@ -237,6 +241,7 @@ function InsightCardInternal( ribbonColor, loadingQueued, loading, + stale, apiErrored, timedOut, highlighted, @@ -338,6 +343,7 @@ function InsightCardInternal( insight={insight} insightProps={insightLogicProps} loading={loading} + stale={stale} apiErrored={apiErrored} timedOut={timedOut} empty={empty} diff --git a/frontend/src/lib/lemon-ui/Spinner/Spinner.tsx b/frontend/src/lib/lemon-ui/Spinner/Spinner.tsx index 619ffdf08bc80..c2e70d129022f 100644 --- a/frontend/src/lib/lemon-ui/Spinner/Spinner.tsx +++ b/frontend/src/lib/lemon-ui/Spinner/Spinner.tsx @@ -1,6 +1,6 @@ import './Spinner.scss' -import { IconClock } from '@posthog/icons' +import { IconPencil } from '@posthog/icons' import { twJoin, twMerge } from 'tailwind-merge' export interface SpinnerProps { @@ -38,12 +38,12 @@ export function SpinnerOverlay({ /** @default true */ visible?: boolean /** @default "spinning" */ - mode?: 'spinning' | 'waiting' + mode?: 'spinning' | 'editing' }): JSX.Element { return (
- {mode === 'waiting' ? ( - + {mode === 'editing' ? ( + ) : ( )} diff --git a/frontend/src/scenes/dashboard/Dashboard.tsx b/frontend/src/scenes/dashboard/Dashboard.tsx index 313a07ab552e4..f501bcd732e44 100644 --- a/frontend/src/scenes/dashboard/Dashboard.tsx +++ b/frontend/src/scenes/dashboard/Dashboard.tsx @@ -53,7 +53,7 @@ function DashboardScene(): JSX.Element { dashboardMode, receivedErrorsFromAPI, } = useValues(dashboardLogic) - const { setDashboardMode, setDates, reportDashboardViewed, setProperties, abortAnyRunningQuery } = + const { setDashboardMode, setDates, reportDashboardViewed, setProperties, abortAnyRunningQuery, setStale } = useActions(dashboardLogic) const { groupsTaxonomicTypes } = useValues(groupsModel) @@ -131,6 +131,7 @@ function DashboardScene(): JSX.Element { TaxonomicFilterGroupType.Elements, TaxonomicFilterGroupType.HogQLExpression, ]} + onPendingChanges={(stale: boolean) => setStale(stale)} />
)} diff --git a/frontend/src/scenes/dashboard/DashboardEditBar.tsx b/frontend/src/scenes/dashboard/DashboardEditBar.tsx index 6f79e9b3c1956..56d83e803afd3 100644 --- a/frontend/src/scenes/dashboard/DashboardEditBar.tsx +++ b/frontend/src/scenes/dashboard/DashboardEditBar.tsx @@ -3,7 +3,7 @@ import { LemonButton } from '@posthog/lemon-ui' import { DateFilter } from 'lib/components/DateFilter/DateFilter' import { PropertyFilters } from 'lib/components/PropertyFilters/PropertyFilters' import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { AnyPropertyFilter, DashboardType, FilterType } from '~/types' @@ -16,6 +16,7 @@ interface DashboardEditBarProps { setDates: (dateFrom: string | null, dateTo: string | null) => void setProperties: (properties: AnyPropertyFilter[]) => void groupsTaxonomicTypes: TaxonomicFilterGroupType[] + onPendingChanges?: (stale: boolean) => void } export function DashboardEditBar({ @@ -25,6 +26,7 @@ export function DashboardEditBar({ setDates, setProperties, groupsTaxonomicTypes, + onPendingChanges, }: DashboardEditBarProps): JSX.Element { const [editMode, setEditMode] = useState(false) const [tempDates, setTempDates] = useState({ @@ -35,14 +37,28 @@ export function DashboardEditBar({ dashboard?.filters.properties ?? undefined ) + useEffect(() => { + const hasPendingChanges = + tempDates.dateFrom !== dashboardFilters?.date_from || + tempDates.dateTo !== dashboardFilters?.date_to || + JSON.stringify(tempProperties) !== JSON.stringify(dashboard?.filters.properties) + if (onPendingChanges) { + onPendingChanges(hasPendingChanges) + } + }, [tempDates, tempProperties]) + const handleSave: () => void = () => { - if (canEditDashboard) { - setDates(tempDates.dateFrom ?? null, tempDates.dateTo ?? null) - if (tempProperties) { - setProperties(tempProperties) - } - setEditMode(false) + if (!canEditDashboard) { + return + } + setDates(tempDates.dateFrom ?? null, tempDates.dateTo ?? null) + if (tempProperties) { + setProperties(tempProperties) + } + if (onPendingChanges) { + onPendingChanges(false) } + setEditMode(false) } const handleCancel: () => void = () => { @@ -52,6 +68,9 @@ export function DashboardEditBar({ }) setTempProperties(dashboard?.filters.properties ?? undefined) setEditMode(false) + if (onPendingChanges) { + onPendingChanges(false) + } } return ( @@ -70,7 +89,7 @@ export function DashboardEditBar({ )} /> - {!editMode ? ( + {canEditDashboard && !editMode ? ( setEditMode(true)}> Edit filters diff --git a/frontend/src/scenes/dashboard/DashboardItems.tsx b/frontend/src/scenes/dashboard/DashboardItems.tsx index bee0d65f16c32..33137753a6c65 100644 --- a/frontend/src/scenes/dashboard/DashboardItems.tsx +++ b/frontend/src/scenes/dashboard/DashboardItems.tsx @@ -26,6 +26,7 @@ export function DashboardItems(): JSX.Element { highlightedInsightId, refreshStatus, canEditDashboard, + stale, } = useValues(dashboardLogic) const { updateLayouts, @@ -137,6 +138,7 @@ export function DashboardItems(): JSX.Element { ([ setInitialLoadResponseBytes: (responseBytes: number) => ({ responseBytes }), abortQuery: (payload: { dashboardQueryId: string; queryId: string; queryStartTime: number }) => payload, abortAnyRunningQuery: true, + setStale: (stale: boolean) => ({ stale }), }), loaders(({ actions, props, values }) => ({ @@ -522,6 +523,12 @@ export const dashboardLogic = kea([ setTextTileId: (_, { textTileId }) => textTileId, }, ], + stale: [ + false, + { + setStale: (_, { stale }) => stale, + }, + ], })), selectors(() => ({ asDashboardTemplate: [