From 01b57f412f005c58d9739f580c671df183df65cb Mon Sep 17 00:00:00 2001 From: Oscar Kilhed Date: Mon, 24 Feb 2025 11:35:55 +0100 Subject: [PATCH] =?UTF-8?q?Dashboards:=20WeekStart=20is=20now=20of=20type?= =?UTF-8?q?=20WeekStart=20|=C2=A0undefined=20instead=20of=20string=20(#101?= =?UTF-8?q?123)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * change weektype from string to WeekStart | undefined * Change to WeekStart in more places, fix lint * change in more places * More weekstart changes * fix snapshot, update betterer * keep weekstart as '' in test dashboards to make sure it doesn't break old dashboards --- .betterer.results | 8 ++------ e2e/dashboards-suite/utils/makeDashboard.ts | 2 +- .../components/DateTimePickers/WeekStartPicker.tsx | 12 ++++++------ packages/grafana-ui/src/components/index.ts | 2 +- .../SharedPreferences/SharedPreferences.tsx | 9 +++++---- .../transformSceneToSaveModel.test.ts.snap | 1 - .../serialization/transformSaveModelToScene.ts | 3 ++- .../settings/GeneralSettingsEditView.tsx | 4 ++-- .../features/dashboard/api/ResponseTransformers.ts | 12 +++++++++--- .../components/DashNav/DashNavTimeControls.tsx | 4 ++-- .../components/DashboardSettings/GeneralSettings.tsx | 3 ++- .../DashboardSettings/TimePickerSettings.tsx | 6 +++--- public/app/features/dashboard/state/actions.ts | 3 ++- public/app/features/dashboard/state/initDashboard.ts | 2 +- public/app/features/profile/state/reducers.ts | 7 ++++--- 15 files changed, 42 insertions(+), 36 deletions(-) diff --git a/.betterer.results b/.betterer.results index 4197643351c..b4f67dde103 100644 --- a/.betterer.results +++ b/.betterer.results @@ -635,9 +635,6 @@ exports[`better eslint`] = { [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"] ], - "packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"] - ], "packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] ], @@ -3661,10 +3658,9 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "2"], [0, 0, 0, "Do not use any type assertions.", "3"], - [0, 0, 0, "Do not use any type assertions.", "4"], + [0, 0, 0, "Unexpected any. Specify a different type.", "4"], [0, 0, 0, "Unexpected any. Specify a different type.", "5"], - [0, 0, 0, "Unexpected any. Specify a different type.", "6"], - [0, 0, 0, "Unexpected any. Specify a different type.", "7"] + [0, 0, 0, "Unexpected any. Specify a different type.", "6"] ], "public/app/features/dashboard/api/v1.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] diff --git a/e2e/dashboards-suite/utils/makeDashboard.ts b/e2e/dashboards-suite/utils/makeDashboard.ts index 4deaaa773ce..2ada48db7a9 100644 --- a/e2e/dashboards-suite/utils/makeDashboard.ts +++ b/e2e/dashboards-suite/utils/makeDashboard.ts @@ -48,8 +48,8 @@ export function makeNewDashboardRequestBody(dashboardName: string, folderUid?: s timezone: '', title: dashboardName, version: 0, - weekStart: '', uid: '', + weekStart: '', }, message: '', overwrite: false, diff --git a/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx index aebcc7075d2..139a03713bd 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx @@ -7,8 +7,8 @@ import { Combobox } from '../Combobox/Combobox'; import { ComboboxOption } from '../Combobox/types'; export interface Props { - onChange: (weekStart: WeekStart) => void; - value: string; + onChange: (weekStart?: WeekStart) => void; + value?: WeekStart; width?: number; autoFocus?: boolean; onBlur?: () => void; @@ -24,9 +24,9 @@ const weekStarts: ComboboxOption[] = [ { value: 'monday', label: 'Monday' }, ]; -const isWeekStart = (value: string): value is WeekStart => { +export function isWeekStart(value: string): value is WeekStart { return ['saturday', 'sunday', 'monday'].includes(value); -}; +} declare global { interface Window { @@ -57,13 +57,13 @@ export const WeekStartPicker = (props: Props) => { const onChangeWeekStart = useCallback( (selectable: ComboboxOption | null) => { if (selectable && selectable.value !== undefined) { - onChange(selectable.value as WeekStart); + onChange(isWeekStart(selectable.value) ? selectable.value : undefined); } }, [onChange] ); - const selected = useMemo(() => weekStarts.find((item) => item.value === value)?.value ?? null, [value]); + const selected = useMemo(() => weekStarts.find((item) => item.value === value)?.value ?? '', [value]); return ( { this.setState({ timezone: timezone }); }; - onWeekStartChanged = (weekStart: string) => { - this.setState({ weekStart: weekStart }); + onWeekStartChanged = (weekStart?: WeekStart) => { + this.setState({ weekStart: weekStart ?? '' }); }; onHomeDashboardChanged = (dashboardUID: string) => { @@ -249,7 +250,7 @@ export class SharedPreferences extends PureComponent { data-testid={selectors.components.WeekStartPicker.containerV2} > diff --git a/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModel.test.ts.snap b/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModel.test.ts.snap index 8146499446c..585b51daf4e 100644 --- a/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModel.test.ts.snap +++ b/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModel.test.ts.snap @@ -334,7 +334,6 @@ exports[`transformSceneToSaveModel Given a scene with rows Should transform back "title": "Repeating rows", "uid": "Repeating-rows-uid", "version": 1, - "weekStart": "", } `; diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index b5ca18ea717..b271697a87e 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -22,6 +22,7 @@ import { SceneInteractionProfileEvent, SceneObjectState, } from '@grafana/scenes'; +import { isWeekStart } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; @@ -274,7 +275,7 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel, to: oldModel.time.to, fiscalYearStartMonth: oldModel.fiscalYearStartMonth, timeZone: oldModel.timezone, - weekStart: oldModel.weekStart, + weekStart: isWeekStart(oldModel.weekStart) ? oldModel.weekStart : undefined, UNSAFE_nowDelay: oldModel.timepicker?.nowDelay, }), $variables: variables, diff --git a/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx b/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx index ef7ae0489e6..d688616afc0 100644 --- a/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx +++ b/public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx @@ -123,7 +123,7 @@ export class GeneralSettingsEditView }); }; - public onWeekStartChange = (value: WeekStart) => { + public onWeekStartChange = (value?: WeekStart) => { this.getTimeRange().setState({ weekStart: value }); }; @@ -258,7 +258,7 @@ export class GeneralSettingsEditView nowDelay={nowDelay || ''} liveNow={liveNow} timezone={timeZone || ''} - weekStart={weekStart || ''} + weekStart={weekStart} /> {/* @todo: Update "Graph tooltip" description to remove prompt about reloading when resolving #46581 */} diff --git a/public/app/features/dashboard/api/ResponseTransformers.ts b/public/app/features/dashboard/api/ResponseTransformers.ts index b57465de211..5ad1d7836d6 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.ts @@ -41,7 +41,7 @@ import { GridLayoutItemKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0'; import { DashboardLink, DataTransformerConfig } from '@grafana/schema/src/raw/dashboard/x/dashboard_types.gen'; -import { WeekStart } from '@grafana/ui'; +import { isWeekStart, WeekStart } from '@grafana/ui'; import { AnnoKeyCreatedBy, AnnoKeyDashboardGnetId, @@ -161,8 +161,7 @@ export function ensureV2Response( fiscalYearStartMonth: dashboard.fiscalYearStartMonth || timeSettingsDefaults.fiscalYearStartMonth, hideTimepicker: dashboard.timepicker?.hidden || timeSettingsDefaults.hideTimepicker, quickRanges: dashboard.timepicker?.quick_ranges, - // casting WeekStart here to avoid editing old schema - weekStart: (dashboard.weekStart as WeekStart) || timeSettingsDefaults.weekStart, + weekStart: getWeekStart(dashboard.weekStart, timeSettingsDefaults.weekStart), nowDelay: dashboard.timepicker?.nowDelay || timeSettingsDefaults.nowDelay, }, links: dashboard.links || [], @@ -332,6 +331,13 @@ function isRowPanel(panel: Panel | RowPanel): panel is RowPanel { return panel.type === 'row'; } +function getWeekStart(weekStart?: string, defaultWeekStart?: WeekStart): WeekStart | undefined { + if (!weekStart || !isWeekStart(weekStart)) { + return defaultWeekStart; + } + return weekStart; +} + function buildRowKind(p: RowPanel, elements: GridLayoutItemKind[]): GridLayoutRowKind { return { kind: 'GridLayoutRow', diff --git a/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx b/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx index 7be88761ec9..6c66c66dc82 100644 --- a/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx @@ -3,7 +3,7 @@ import { Unsubscribable } from 'rxjs'; import { dateMath, TimeRange, TimeZone } from '@grafana/data'; import { TimeRangeUpdatedEvent } from '@grafana/runtime'; -import { defaultIntervals, RefreshPicker } from '@grafana/ui'; +import { defaultIntervals, isWeekStart, RefreshPicker } from '@grafana/ui'; import { TimePickerWithHistory } from 'app/core/components/TimePicker/TimePickerWithHistory'; import { appEvents } from 'app/core/core'; import { t } from 'app/core/internationalization'; @@ -121,7 +121,7 @@ export class DashNavTimeControls extends Component { onChangeFiscalYearStartMonth={this.onChangeFiscalYearStartMonth} isOnCanvas={isOnCanvas} onToolbarTimePickerClick={this.props.onToolbarTimePickerClick} - weekStart={weekStart} + weekStart={isWeekStart(weekStart) ? weekStart : undefined} quickRanges={quick_ranges} /> { + const onWeekStartChange = (weekStart?: WeekStart) => { dashboard.weekStart = weekStart; setRenderCounter(renderCounter + 1); updateWeekStart(weekStart); diff --git a/public/app/features/dashboard/components/DashboardSettings/TimePickerSettings.tsx b/public/app/features/dashboard/components/DashboardSettings/TimePickerSettings.tsx index d88e3deaa64..1b31c3ee035 100644 --- a/public/app/features/dashboard/components/DashboardSettings/TimePickerSettings.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/TimePickerSettings.tsx @@ -10,7 +10,7 @@ import { t } from 'app/core/internationalization'; import { AutoRefreshIntervals } from './AutoRefreshIntervals'; interface Props { - onWeekStartChange: (weekStart: WeekStart) => void; + onWeekStartChange: (weekStart?: WeekStart) => void; onTimeZoneChange: (timeZone: TimeZone) => void; onRefreshIntervalChange: (interval: string[]) => void; onNowDelayChange: (nowDelay: string) => void; @@ -20,7 +20,7 @@ interface Props { timePickerHidden?: boolean; nowDelay?: string; timezone: TimeZone; - weekStart: string; + weekStart?: WeekStart; liveNow?: boolean; } @@ -62,7 +62,7 @@ export class TimePickerSettings extends PureComponent { this.props.onTimeZoneChange(timeZone); }; - onWeekStartChange = (weekStart: WeekStart) => { + onWeekStartChange = (weekStart?: WeekStart) => { this.props.onWeekStartChange(weekStart); }; diff --git a/public/app/features/dashboard/state/actions.ts b/public/app/features/dashboard/state/actions.ts index 3f9b8d529f8..ed28663f745 100644 --- a/public/app/features/dashboard/state/actions.ts +++ b/public/app/features/dashboard/state/actions.ts @@ -1,5 +1,6 @@ import { TimeZone } from '@grafana/data'; import { getBackendSrv } from '@grafana/runtime'; +import { WeekStart } from '@grafana/ui'; import { notifyApp } from 'app/core/actions'; import { createSuccessNotification } from 'app/core/copy/appNotification'; import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; @@ -56,7 +57,7 @@ export const updateTimeZoneDashboard = }; export const updateWeekStartDashboard = - (weekStart: string): ThunkResult => + (weekStart?: WeekStart): ThunkResult => (dispatch) => { dispatch(updateWeekStartForSession(weekStart)); getTimeSrv().refreshTimeModel(); diff --git a/public/app/features/dashboard/state/initDashboard.ts b/public/app/features/dashboard/state/initDashboard.ts index 23b36244519..71c5cbf79eb 100644 --- a/public/app/features/dashboard/state/initDashboard.ts +++ b/public/app/features/dashboard/state/initDashboard.ts @@ -273,7 +273,7 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult { } // set week start - if (dashboard.weekStart !== '') { + if (dashboard.weekStart !== '' && dashboard.weekStart !== undefined) { setWeekStart(dashboard.weekStart); } else { setWeekStart(config.bootData.user.weekStart); diff --git a/public/app/features/profile/state/reducers.ts b/public/app/features/profile/state/reducers.ts index 5098fa3670d..f4de9c34f0b 100644 --- a/public/app/features/profile/state/reducers.ts +++ b/public/app/features/profile/state/reducers.ts @@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { isEmpty, isString, set } from 'lodash'; import { dateTimeFormatTimeAgo, setWeekStart, TimeZone } from '@grafana/data'; +import { getWeekStart, WeekStart } from '@grafana/ui'; import config from 'app/core/config'; import { contextSrv } from 'app/core/core'; import { Team, ThunkResult, UserDTO, UserOrg, UserSession } from 'app/types'; @@ -116,10 +117,10 @@ export const updateTimeZoneForSession = (timeZone: TimeZone): ThunkResult }; }; -export const updateWeekStartForSession = (weekStart: string): ThunkResult => { +export const updateWeekStartForSession = (weekStart?: WeekStart): ThunkResult => { return async (dispatch) => { - if (!isString(weekStart) || isEmpty(weekStart)) { - weekStart = config?.bootData?.user?.weekStart; + if (!weekStart) { + weekStart = getWeekStart(); } set(contextSrv, 'user.weekStart', weekStart);