From 34b4f7c717036449da5dafbca612c817f9332de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 15 Apr 2021 14:21:06 +0200 Subject: [PATCH] Chore: Reduces strict errors (#33012) * Chore: reduces strict error in OptionPicker tests * Chore: reduces strict errors in FormDropdownCtrl * Chore: reduces has no initializer and is not definitely assigned in the constructor errors * Chore: reduces has no initializer and is not definitely assigned in the constructor errors * Chore: lowers strict count limit * Tests: updates snapshots * Tests: updates snapshots * Chore: updates after PR comments * Refactor: removes throw and changes signature for DashboardSrv.getCurrent --- .../app/core/components/Select/OrgPicker.tsx | 2 +- .../components/form_dropdown/form_dropdown.ts | 5 +- .../core/components/query_part/query_part.ts | 1 + public/app/core/components/switch.ts | 2 +- public/app/core/profiler.ts | 10 +-- public/app/core/services/backend_srv.ts | 1 + public/app/core/services/context_srv.ts | 13 ++++ public/app/core/services/segment_srv.ts | 13 ++-- public/app/core/time_series2.ts | 12 ++-- public/app/core/utils/dag.ts | 22 +++--- public/app/core/utils/version.ts | 4 ++ public/app/features/admin/UserProfile.tsx | 8 +-- public/app/features/alerting/AlertTab.tsx | 28 +++++--- public/app/features/alerting/AlertTabCtrl.ts | 4 +- .../annotations/annotation_tooltip.ts | 4 +- .../StandardAnnotationQueryEditor.tsx | 13 ++-- .../app/features/annotations/event_editor.ts | 6 +- .../app/features/annotations/event_manager.ts | 10 +-- .../AngularEditorLoader.tsx | 2 +- .../FolderPicker/FolderPickerCtrl.ts | 14 ++-- .../__snapshots__/DashboardPage.test.tsx.snap | 28 ++++++++ .../dashboard/dashgrid/PanelResizer.tsx | 4 +- .../__snapshots__/DashboardGrid.test.tsx.snap | 68 +++++++++++++++++++ .../dashboard/services/DashboardSrv.ts | 13 ++-- .../features/dashboard/services/TimeSrv.ts | 19 ++++-- .../dashboard/state/DashboardModel.ts | 2 +- .../features/dashboard/state/PanelModel.ts | 22 +++--- .../datasources/settings/PluginSettings.tsx | 16 ++--- .../explore/ReturnToDashboardButton.tsx | 6 +- .../PanelLibraryOptionsGroup.tsx | 2 +- .../live/dashboard/dashboardWatcher.ts | 10 +-- .../services/ValidationSrv.ts | 4 +- public/app/features/search/utils.ts | 6 +- .../OptionsPicker/OptionPicker.test.tsx | 4 +- .../app/features/variables/state/actions.ts | 2 +- .../dashboard/DashboardQueryEditor.tsx | 6 +- .../datasource/dashboard/runSharedRequest.ts | 2 +- .../app/plugins/panel/alertlist/AlertList.tsx | 14 ++-- .../plugins/panel/annolist/AnnoListPanel.tsx | 7 +- .../panel/gettingstarted/GettingStarted.tsx | 4 +- public/app/plugins/panel/table/TablePanel.tsx | 2 +- scripts/ci-check-strict.sh | 2 +- 42 files changed, 286 insertions(+), 131 deletions(-) diff --git a/public/app/core/components/Select/OrgPicker.tsx b/public/app/core/components/Select/OrgPicker.tsx index c74de40e7c3..e5a0433c754 100644 --- a/public/app/core/components/Select/OrgPicker.tsx +++ b/public/app/core/components/Select/OrgPicker.tsx @@ -21,7 +21,7 @@ export interface State { } export class OrgPicker extends PureComponent { - orgs: Organization[]; + orgs: Organization[] = []; state: State = { isLoading: false, diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts index da97ea9d80e..b6f0b71cd60 100644 --- a/public/app/core/components/form_dropdown/form_dropdown.ts +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -36,7 +36,7 @@ export class FormDropdownCtrl { lookupText: boolean; placeholder: any; startOpen: any; - debounce: number; + debounce: boolean; /** @ngInject */ constructor(private $scope: any, $element: JQLite, private $sce: ISCEService, private templateSrv: any) { @@ -44,6 +44,9 @@ export class FormDropdownCtrl { this.linkElement = $element.find('a').first(); this.linkMode = true; this.cancelBlur = null; + this.labelMode = false; + this.lookupText = false; + this.debounce = false; // listen to model changes $scope.$watch('ctrl.model', this.modelChanged.bind(this)); diff --git a/public/app/core/components/query_part/query_part.ts b/public/app/core/components/query_part/query_part.ts index b2466977c22..7f3d52c366b 100644 --- a/public/app/core/components/query_part/query_part.ts +++ b/public/app/core/components/query_part/query_part.ts @@ -33,6 +33,7 @@ export class QueryPart { part.params = part.params || _.clone(this.def.defaultParams); this.params = part.params; + this.text = ''; this.updateText(); } diff --git a/public/app/core/components/switch.ts b/public/app/core/components/switch.ts index d6a66a1a362..3d213f6a6de 100644 --- a/public/app/core/components/switch.ts +++ b/public/app/core/components/switch.ts @@ -35,7 +35,7 @@ export class SwitchCtrl { checked: any; show: any; id: any; - label: string; + label?: string; /** @ngInject */ constructor($scope: any, private $timeout: any) { diff --git a/public/app/core/profiler.ts b/public/app/core/profiler.ts index 46db094883b..100b42d4171 100644 --- a/public/app/core/profiler.ts +++ b/public/app/core/profiler.ts @@ -1,10 +1,10 @@ import { GrafanaRootScope } from 'app/routes/GrafanaCtrl'; export class Profiler { - panelsRendered: number; - enabled: boolean; - $rootScope: GrafanaRootScope; - window: any; + panelsRendered = 0; + enabled?: boolean = undefined; + $rootScope?: GrafanaRootScope = undefined; + window?: any = undefined; init(config: any, $rootScope: GrafanaRootScope) { this.$rootScope = $rootScope; @@ -18,7 +18,7 @@ export class Profiler { renderingCompleted() { // add render counter to root scope // used by image renderer to know when panel has rendered - this.panelsRendered = (this.panelsRendered || 0) + 1; + this.panelsRendered += 1; // this window variable is used by backend rendering tools to know // all panels have completed rendering diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index defb2f6e8bc..84fa55b32ff 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -54,6 +54,7 @@ export class BackendSrv implements BackendService { }; } + this.noBackendCache = false; this.internalFetch = this.internalFetch.bind(this); this.fetchQueue = new FetchQueue(); this.responseQueue = new ResponseQueue(this.fetchQueue, this.internalFetch); diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts index ff98c016370..23532842c17 100644 --- a/public/app/core/services/context_srv.ts +++ b/public/app/core/services/context_srv.ts @@ -19,6 +19,19 @@ export class User { email?: string; constructor() { + this.id = 0; + this.isGrafanaAdmin = false; + this.isSignedIn = false; + this.orgRole = ''; + this.orgId = 0; + this.orgName = ''; + this.login = ''; + this.orgCount = 0; + this.timezone = ''; + this.helpFlags1 = 0; + this.lightTheme = false; + this.hasEditPermissionInFolders = false; + this.email = undefined; if (config.bootData.user) { _.extend(this, config.bootData.user); } diff --git a/public/app/core/services/segment_srv.ts b/public/app/core/services/segment_srv.ts index 333f5bac216..9b189a7d88c 100644 --- a/public/app/core/services/segment_srv.ts +++ b/public/app/core/services/segment_srv.ts @@ -9,12 +9,12 @@ export function uiSegmentSrv(this: any, $sce: any, templateSrv: any) { value: string; html: any; type: any; - expandable: boolean; - text: string; - cssClass: string; - fake: boolean; - custom: boolean; - selectMode: any; + expandable?: boolean; + text?: string; + cssClass?: string; + fake?: boolean; + custom?: boolean; + selectMode?: any; constructor(options: any) { if (options === '*' || options.value === '*') { @@ -40,7 +40,6 @@ export function uiSegmentSrv(this: any, $sce: any, templateSrv: any) { this.fake = options.fake; this.value = options.value; this.selectMode = options.selectMode; - this.type = options.type; this.expandable = options.expandable; this.html = options.html || $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value)); } diff --git a/public/app/core/time_series2.ts b/public/app/core/time_series2.ts index 5606ced6e66..4af5b130f59 100644 --- a/public/app/core/time_series2.ts +++ b/public/app/core/time_series2.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { getValueFormat, ValueFormatter, stringToJsRegex, DecimalCount, formattedValueToString } from '@grafana/data'; +import { DecimalCount, formattedValueToString, getValueFormat, stringToJsRegex, ValueFormatter } from '@grafana/data'; function matchSeriesOverride(aliasOrRegex: string, seriesAlias: string) { if (!aliasOrRegex) { @@ -72,15 +72,15 @@ export default class TimeSeries { valueFormater: any; stats: any; legend: boolean; - hideTooltip: boolean; - allIsNull: boolean; - allIsZero: boolean; + hideTooltip?: boolean; + allIsNull?: boolean; + allIsZero?: boolean; decimals: DecimalCount; hasMsResolution: boolean; - isOutsideRange: boolean; + isOutsideRange?: boolean; lines: any; - hiddenSeries: boolean; + hiddenSeries?: boolean; dashes: any; bars: any; points: any; diff --git a/public/app/core/utils/dag.ts b/public/app/core/utils/dag.ts index 8a9a146999d..94716be2855 100644 --- a/public/app/core/utils/dag.ts +++ b/public/app/core/utils/dag.ts @@ -1,6 +1,6 @@ export class Edge { - inputNode: Node; - outputNode: Node; + inputNode?: Node; + outputNode?: Node; _linkTo(node: Node, direction: number) { if (direction <= 0) { @@ -82,10 +82,10 @@ export class Node { } if (typeof from === 'object') { - return this.inputEdges.find((e) => e.inputNode.name === from.name); + return this.inputEdges.find((e) => e.inputNode?.name === from.name); } - return this.inputEdges.find((e) => e.inputNode.name === from); + return this.inputEdges.find((e) => e.inputNode?.name === from); } getEdgeTo(to: string | Node): Edge | null | undefined { @@ -94,19 +94,19 @@ export class Node { } if (typeof to === 'object') { - return this.outputEdges.find((e) => e.outputNode.name === to.name); + return this.outputEdges.find((e) => e.outputNode?.name === to.name); } - return this.outputEdges.find((e) => e.outputNode.name === to); + return this.outputEdges.find((e) => e.outputNode?.name === to); } getOptimizedInputEdges(): Edge[] { const toBeRemoved: any[] = []; this.inputEdges.forEach((e) => { - const inputEdgesNodes = e.inputNode.inputEdges.map((e) => e.inputNode); + const inputEdgesNodes = e.inputNode?.inputEdges.map((e) => e.inputNode); - inputEdgesNodes.forEach((n) => { - const edgeToRemove = n.getEdgeTo(this.name); + inputEdgesNodes?.forEach((n) => { + const edgeToRemove = n?.getEdgeTo(this.name); if (edgeToRemove) { toBeRemoved.push(edgeToRemove); } @@ -201,11 +201,11 @@ export class Graph { export const printGraph = (g: Graph) => { Object.keys(g.nodes).forEach((name) => { const n = g.nodes[name]; - let outputEdges = n.outputEdges.map((e: Edge) => e.outputNode.name).join(', '); + let outputEdges = n.outputEdges.map((e: Edge) => e.outputNode?.name).join(', '); if (!outputEdges) { outputEdges = ''; } - let inputEdges = n.inputEdges.map((e: Edge) => e.inputNode.name).join(', '); + let inputEdges = n.inputEdges.map((e: Edge) => e.inputNode?.name).join(', '); if (!inputEdges) { inputEdges = ''; } diff --git a/public/app/core/utils/version.ts b/public/app/core/utils/version.ts index 746de761fa3..8eeda370511 100644 --- a/public/app/core/utils/version.ts +++ b/public/app/core/utils/version.ts @@ -9,6 +9,10 @@ export class SemVersion { meta: string; constructor(version: string) { + this.major = 0; + this.minor = 0; + this.patch = 0; + this.meta = ''; const match = versionPattern.exec(version); if (match) { this.major = Number(match[1]); diff --git a/public/app/features/admin/UserProfile.tsx b/public/app/features/admin/UserProfile.tsx index 25672f879fe..58e10cd8065 100644 --- a/public/app/features/admin/UserProfile.tsx +++ b/public/app/features/admin/UserProfile.tsx @@ -1,9 +1,9 @@ -import React, { PureComponent, FC } from 'react'; +import React, { FC, PureComponent } from 'react'; import { UserDTO } from 'app/types'; -import { cx, css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import { config } from 'app/core/config'; import { GrafanaTheme } from '@grafana/data'; -import { ConfirmButton, ConfirmModal, LegacyInputStatus, Button, stylesFactory, Input } from '@grafana/ui'; +import { Button, ConfirmButton, ConfirmModal, Input, LegacyInputStatus, stylesFactory } from '@grafana/ui'; interface Props { user: UserDTO; @@ -187,7 +187,7 @@ interface UserProfileRowState { } export class UserProfileRow extends PureComponent { - inputElem: HTMLInputElement; + inputElem?: HTMLInputElement; static defaultProps: Partial = { value: '', diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index d596cc47053..9ecf2858ba3 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -14,6 +14,14 @@ import { PanelModel } from '../dashboard/state/PanelModel'; import { TestRuleResult } from './TestRuleResult'; import { AppNotificationSeverity, StoreState } from 'app/types'; import { PanelNotSupported } from '../dashboard/components/PanelEditor/PanelNotSupported'; +import { AlertState } from '../../plugins/datasource/alertmanager/types'; + +interface AngularPanelController { + _enableAlert: () => void; + alertState: AlertState | null; + render: () => void; + refresh: () => void; +} interface OwnProps { dashboard: DashboardModel; @@ -36,9 +44,9 @@ interface State { } class UnConnectedAlertTab extends PureComponent { - element: any; - component: AngularComponent; - panelCtrl: any; + element?: HTMLDivElement | null; + component?: AngularComponent; + panelCtrl?: AngularPanelController; state: State = { validationMessage: '', @@ -103,8 +111,8 @@ class UnConnectedAlertTab extends PureComponent { } onAddAlert = () => { - this.panelCtrl._enableAlert(); - this.component.digest(); + this.panelCtrl?._enableAlert(); + this.component?.digest(); this.forceUpdate(); }; @@ -153,9 +161,11 @@ class UnConnectedAlertTab extends PureComponent { onConfirm={() => { delete panel.alert; panel.thresholds = []; - this.panelCtrl.alertState = null; - this.panelCtrl.render(); - this.component.digest(); + if (this.panelCtrl) { + this.panelCtrl.alertState = null; + this.panelCtrl.render(); + } + this.component?.digest(); onDismiss(); }} /> @@ -175,7 +185,7 @@ class UnConnectedAlertTab extends PureComponent { this.panelCtrl.refresh()} + onRefresh={() => this.panelCtrl?.refresh()} /> ); diff --git a/public/app/features/alerting/AlertTabCtrl.ts b/public/app/features/alerting/AlertTabCtrl.ts index 4500758209e..d3c83be13bd 100644 --- a/public/app/features/alerting/AlertTabCtrl.ts +++ b/public/app/features/alerting/AlertTabCtrl.ts @@ -29,7 +29,7 @@ export class AlertTabCtrl { addNotificationSegment: any; notifications: any; alertNotifications: any; - error: string; + error?: string; appSubUrl: string; alertHistory: any; newAlertRuleTag: any; @@ -96,7 +96,7 @@ export class AlertTabCtrl { .get(`/api/annotations?dashboardId=${this.panelCtrl.dashboard.id}&panelId=${this.panel.id}&limit=50&type=alert`) .then((res: any) => { this.alertHistory = _.map(res, (ah) => { - ah.time = this.dashboardSrv.getCurrent().formatDate(ah.time, 'MMM D, YYYY HH:mm:ss'); + ah.time = this.dashboardSrv.getCurrent()?.formatDate(ah.time, 'MMM D, YYYY HH:mm:ss'); ah.stateModel = alertDef.getStateDisplayModel(ah.newState); ah.info = alertDef.getAlertAnnotationInfo(ah); return ah; diff --git a/public/app/features/annotations/annotation_tooltip.ts b/public/app/features/annotations/annotation_tooltip.ts index df6fb9e7d09..3e896e65077 100644 --- a/public/app/features/annotations/annotation_tooltip.ts +++ b/public/app/features/annotations/annotation_tooltip.ts @@ -55,11 +55,11 @@ export function annotationTooltipDirective( } header += ` ${sanitizeString(title)} - ${dashboard.formatDate(event.min)} + ${dashboard?.formatDate(event.min)} `; // Show edit icon only for users with at least Editor role - if (event.id && dashboard.canAddAnnotations()) { + if (event.id && dashboard?.canAddAnnotations()) { header += ` diff --git a/public/app/features/annotations/components/StandardAnnotationQueryEditor.tsx b/public/app/features/annotations/components/StandardAnnotationQueryEditor.tsx index 9f6d3e8f9d0..3a223a3185a 100644 --- a/public/app/features/annotations/components/StandardAnnotationQueryEditor.tsx +++ b/public/app/features/annotations/components/StandardAnnotationQueryEditor.tsx @@ -1,11 +1,11 @@ import React, { PureComponent } from 'react'; -import { AnnotationEventMappings, DataQuery, LoadingState, DataSourceApi, AnnotationQuery } from '@grafana/data'; -import { Spinner, Icon, IconName, Button } from '@grafana/ui'; +import { AnnotationEventMappings, AnnotationQuery, DataQuery, DataSourceApi, LoadingState } from '@grafana/data'; +import { Button, Icon, IconName, Spinner } from '@grafana/ui'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; -import { cx, css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import { standardAnnotationSupport } from '../standardAnnotationSupport'; import { executeAnnotationQuery } from '../annotations_srv'; import { PanelModel } from 'app/features/dashboard/state'; @@ -56,6 +56,11 @@ export default class StandardAnnotationQueryEditor extends PureComponent { const { datasource, annotation } = this.props; + const dashboard = getDashboardSrv().getCurrent(); + if (!dashboard) { + return; + } + this.setState({ running: true, }); @@ -63,7 +68,7 @@ export default class StandardAnnotationQueryEditor extends PureComponent { ref: HTMLDivElement | null = null; - angularComponent: AngularComponent; + angularComponent?: AngularComponent; componentWillUnmount() { if (this.angularComponent) { diff --git a/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts b/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts index 9e05489693d..a49f452eae4 100644 --- a/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts +++ b/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts @@ -11,7 +11,7 @@ import { promiseToDigest } from '../../../../core/utils/promiseToDigest'; import { createFolder } from 'app/features/manage-dashboards/state/actions'; export class FolderPickerCtrl { - initialTitle: string; + declare initialTitle: string; initialFolderId?: number; labelClass: string; onChange: any; @@ -19,14 +19,14 @@ export class FolderPickerCtrl { onCreateFolder: any; enterFolderCreation: any; exitFolderCreation: any; - enableCreateNew: boolean; - enableReset: boolean; + declare enableCreateNew: boolean; + declare enableReset: boolean; rootName = 'General'; folder: any; - createNewFolder: boolean; - newFolderName: string; - newFolderNameTouched: boolean; - hasValidationError: boolean; + createNewFolder?: boolean; + newFolderName?: string; + newFolderNameTouched?: boolean; + hasValidationError?: boolean; validationError: any; isEditor: boolean; dashboardId?: number; diff --git a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap index bff2981e711..fa86bdab46f 100644 --- a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap +++ b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap @@ -69,7 +69,11 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -197,7 +201,11 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -295,7 +303,11 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -415,7 +427,11 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -543,7 +559,11 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -641,7 +661,11 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -743,7 +767,11 @@ exports[`DashboardPage When dashboard has editview url state should render setti "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, + "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ diff --git a/public/app/features/dashboard/dashgrid/PanelResizer.tsx b/public/app/features/dashboard/dashgrid/PanelResizer.tsx index 6b169e2b1f8..3bd191300ff 100644 --- a/public/app/features/dashboard/dashgrid/PanelResizer.tsx +++ b/public/app/features/dashboard/dashgrid/PanelResizer.tsx @@ -16,9 +16,9 @@ interface State { export class PanelResizer extends PureComponent { initialHeight: number = Math.floor(document.documentElement.scrollHeight * 0.3); - prevEditorHeight: number; + prevEditorHeight?: number; throttledChangeHeight: (height: number) => void; - throttledResizeDone: () => void; + throttledResizeDone?: () => void; noStyles: object = {}; constructor(props: Props) { diff --git a/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap b/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap index 65d7987b01f..e7976d5171c 100644 --- a/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap +++ b/public/app/features/dashboard/dashgrid/__snapshots__/DashboardGrid.test.tsx.snap @@ -116,8 +116,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -144,8 +147,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, + "hasChanged": false, "id": 2, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -172,8 +178,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, + "hasChanged": false, "id": 3, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -200,8 +209,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, + "hasChanged": false, "id": 4, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -234,7 +246,9 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "version": 0, } } + isEditing={false} isInView={false} + isViewing={false} panel={ PanelModel { "cachedPluginOptions": Object {}, @@ -251,8 +265,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -340,8 +357,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -368,8 +388,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, + "hasChanged": false, "id": 2, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -396,8 +419,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, + "hasChanged": false, "id": 3, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -424,8 +450,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, + "hasChanged": false, "id": 4, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -458,7 +487,9 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "version": 0, } } + isEditing={false} isInView={false} + isViewing={false} panel={ PanelModel { "cachedPluginOptions": Object {}, @@ -475,8 +506,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, + "hasChanged": false, "id": 2, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -564,8 +598,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -592,8 +629,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, + "hasChanged": false, "id": 2, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -620,8 +660,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, + "hasChanged": false, "id": 3, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -648,8 +691,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, + "hasChanged": false, "id": 4, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -682,7 +728,9 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "version": 0, } } + isEditing={false} isInView={false} + isViewing={false} panel={ PanelModel { "cachedPluginOptions": Object {}, @@ -699,8 +747,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, + "hasChanged": false, "id": 3, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -788,8 +839,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 0, }, + "hasChanged": false, "id": 1, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -816,8 +870,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 10, }, + "hasChanged": false, "id": 2, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -844,8 +901,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 20, }, + "hasChanged": false, "id": 3, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -872,8 +932,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, + "hasChanged": false, "id": 4, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ @@ -906,7 +969,9 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "version": 0, } } + isEditing={false} isInView={false} + isViewing={false} panel={ PanelModel { "cachedPluginOptions": Object {}, @@ -923,8 +988,11 @@ exports[`DashboardGrid Can render dashboard grid Should render 1`] = ` "x": 0, "y": 120, }, + "hasChanged": false, "id": 4, + "isEditing": false, "isInView": false, + "isViewing": false, "options": Object {}, "replaceVariables": [Function], "targets": Array [ diff --git a/public/app/features/dashboard/services/DashboardSrv.ts b/public/app/features/dashboard/services/DashboardSrv.ts index 227287069bf..4f9c16b36a8 100644 --- a/public/app/features/dashboard/services/DashboardSrv.ts +++ b/public/app/features/dashboard/services/DashboardSrv.ts @@ -10,7 +10,7 @@ import { saveDashboard } from 'app/features/manage-dashboards/state/actions'; import { RemovePanelEvent } from '../../../types/events'; export class DashboardSrv { - dashboard: DashboardModel; + dashboard?: DashboardModel; /** @ngInject */ constructor(private $rootScope: GrafanaRootScope) { @@ -25,20 +25,25 @@ export class DashboardSrv { this.dashboard = dashboard; } - getCurrent(): DashboardModel { + getCurrent(): DashboardModel | undefined { + if (!this.dashboard) { + console.warn('Calling getDashboardSrv().getCurrent() without calling getDashboardSrv().setCurrent() first.'); + } return this.dashboard; } onRemovePanel = (panelId: number) => { const dashboard = this.getCurrent(); - removePanel(dashboard, dashboard.getPanelById(panelId)!, true); + if (dashboard) { + removePanel(dashboard, dashboard.getPanelById(panelId)!, true); + } }; saveJSONDashboard(json: string) { const parsedJson = JSON.parse(json); return saveDashboard({ dashboard: parsedJson, - folderId: this.dashboard.meta.folderId || parsedJson.folderId, + folderId: this.dashboard?.meta.folderId || parsedJson.folderId, }); } diff --git a/public/app/features/dashboard/services/TimeSrv.ts b/public/app/features/dashboard/services/TimeSrv.ts index e0c450bb9a2..4decac0a2ab 100644 --- a/public/app/features/dashboard/services/TimeSrv.ts +++ b/public/app/features/dashboard/services/TimeSrv.ts @@ -23,9 +23,9 @@ export class TimeSrv { refreshTimer: any; refresh: any; oldRefresh: string | null | undefined; - dashboard: DashboardModel; + dashboard?: DashboardModel; timeAtLoad: any; - private autoRefreshBlocked: boolean; + private autoRefreshBlocked?: boolean; constructor(private contextSrv: ContextSrv) { // default time @@ -141,7 +141,9 @@ export class TimeSrv { // if absolute ignore refresh option saved to dashboard if (params.get('to') && params.get('to')!.indexOf('now') === -1) { this.refresh = false; - this.dashboard.refresh = false; + if (this.dashboard) { + this.dashboard.refresh = false; + } } let paramsJSON: Record = {}; @@ -188,7 +190,10 @@ export class TimeSrv { } setAutoRefresh(interval: any) { - this.dashboard.refresh = interval; + if (this.dashboard) { + this.dashboard.refresh = interval; + } + this.stopAutoRefresh(); if (interval) { @@ -210,7 +215,7 @@ export class TimeSrv { } refreshDashboard() { - this.dashboard.timeRangeUpdated(this.timeRange()); + this.dashboard?.timeRangeUpdated(this.timeRange()); } private startNextRefreshTimer(afterMs: number) { @@ -233,9 +238,9 @@ export class TimeSrv { // disable refresh if zoom in or zoom out if (isDateTime(time.to)) { - this.oldRefresh = this.dashboard.refresh || this.oldRefresh; + this.oldRefresh = this.dashboard?.refresh || this.oldRefresh; this.setAutoRefresh(false); - } else if (this.oldRefresh && this.oldRefresh !== this.dashboard.refresh) { + } else if (this.oldRefresh && this.oldRefresh !== this.dashboard?.refresh) { this.setAutoRefresh(this.oldRefresh); this.oldRefresh = null; } diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index 04af1fd75a7..827518469a7 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -85,7 +85,7 @@ export class DashboardModel { // repeat process cycles iteration?: number; - meta: DashboardMeta; + declare meta: DashboardMeta; events: EventBusExtended; static nonPersistedProperties: { [str: string]: boolean } = { diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 7f910c48016..c266027e527 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -135,9 +135,9 @@ export class PanelModel implements DataConfigSource { collapsed?: boolean; panels?: any; - targets: DataQuery[]; + declare targets: DataQuery[]; transformations?: DataTransformerConfig[]; - datasource: string | null; + datasource: string | null = null; thresholds?: any; pluginVersion?: string; @@ -145,29 +145,29 @@ export class PanelModel implements DataConfigSource { timeFrom?: any; timeShift?: any; hideTimeOverride?: any; - options: { + declare options: { [key: string]: any; }; - fieldConfig: FieldConfigSource; + declare fieldConfig: FieldConfigSource; maxDataPoints?: number | null; interval?: string | null; description?: string; links?: DataLink[]; - transparent: boolean; + declare transparent: boolean; libraryPanel?: { uid: undefined; name: string } | PanelModelLibraryPanel; // non persisted - isViewing: boolean; - isEditing: boolean; - isInView: boolean; - hasChanged: boolean; + isViewing = false; + isEditing = false; + isInView = false; + hasChanged = false; - hasRefreshed: boolean; + hasRefreshed?: boolean; events: EventBus; cacheTimeout?: any; - cachedPluginOptions: Record; + declare cachedPluginOptions: Record; legend?: { show: boolean; sort?: string; sortDesc?: boolean }; plugin?: PanelPlugin; diff --git a/public/app/features/datasources/settings/PluginSettings.tsx b/public/app/features/datasources/settings/PluginSettings.tsx index b0f3375a040..fd99820a409 100644 --- a/public/app/features/datasources/settings/PluginSettings.tsx +++ b/public/app/features/datasources/settings/PluginSettings.tsx @@ -1,14 +1,14 @@ import React, { PureComponent } from 'react'; import _ from 'lodash'; import { - DataSourceSettings, + DataQuery, + DataSourceApi, + DataSourceJsonData, DataSourcePlugin, DataSourcePluginMeta, - DataSourceApi, - DataQuery, - DataSourceJsonData, + DataSourceSettings, } from '@grafana/data'; -import { getAngularLoader, AngularComponent } from '@grafana/runtime'; +import { AngularComponent, getAngularLoader } from '@grafana/runtime'; export type GenericDataSourcePlugin = DataSourcePlugin>; @@ -20,8 +20,8 @@ export interface Props { } export class PluginSettings extends PureComponent { - element: any; - component: AngularComponent; + element: HTMLDivElement | null = null; + component?: AngularComponent; scopeProps: { ctrl: { datasourceMeta: DataSourcePluginMeta; current: DataSourceSettings }; onModelChanged: (dataSource: DataSourceSettings) => void; @@ -59,7 +59,7 @@ export class PluginSettings extends PureComponent { if (!plugin.components.ConfigEditor && this.props.dataSource !== prevProps.dataSource) { this.scopeProps.ctrl.current = _.cloneDeep(this.props.dataSource); - this.component.digest(); + this.component?.digest(); } } diff --git a/public/app/features/explore/ReturnToDashboardButton.tsx b/public/app/features/explore/ReturnToDashboardButton.tsx index 7b80ef89243..23a11096c9c 100644 --- a/public/app/features/explore/ReturnToDashboardButton.tsx +++ b/public/app/features/explore/ReturnToDashboardButton.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react'; import { connect } from 'react-redux'; -import { Icon, Tooltip, ButtonSelect, ToolbarButton, ButtonGroup } from '@grafana/ui'; +import { ButtonGroup, ButtonSelect, Icon, ToolbarButton, Tooltip } from '@grafana/ui'; import { DataQuery, urlUtil } from '@grafana/data'; import kbn from '../../core/utils/kbn'; @@ -43,6 +43,10 @@ export const UnconnectedReturnToDashboardButton: FC = ({ const returnToPanel = async ({ withChanges = false } = {}) => { const dashboardSrv = getDashboardSrv(); const dash = dashboardSrv.getCurrent(); + if (!dash) { + return; + } + const titleSlug = kbn.slugifyForUrl(dash.title); if (withChanges) { diff --git a/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx b/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx index abb05f603c0..b2d918bd97d 100644 --- a/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx +++ b/public/app/features/library-panels/components/PanelLibraryOptionsGroup/PanelLibraryOptionsGroup.tsx @@ -84,7 +84,7 @@ export const PanelLibraryOptionsGroup: FC = ({ panel, searchQuery }) => { setShowingAddPanelModal(false)} - initialFolderId={dashboard.meta.folderId} + initialFolderId={dashboard?.meta.folderId} isOpen={showingAddPanelModal} /> )} diff --git a/public/app/features/live/dashboard/dashboardWatcher.ts b/public/app/features/live/dashboard/dashboardWatcher.ts index acc31452a88..2d27d6ee8d6 100644 --- a/public/app/features/live/dashboard/dashboardWatcher.ts +++ b/public/app/features/live/dashboard/dashboardWatcher.ts @@ -3,13 +3,13 @@ import { getDashboardSrv } from '../../dashboard/services/DashboardSrv'; import { appEvents } from 'app/core/core'; import { AppEvents, + isLiveChannelMessageEvent, + isLiveChannelStatusEvent, LiveChannel, - LiveChannelScope, - LiveChannelEvent, LiveChannelConfig, LiveChannelConnectionState, - isLiveChannelStatusEvent, - isLiveChannelMessageEvent, + LiveChannelEvent, + LiveChannelScope, } from '@grafana/data'; import { DashboardChangedModal } from './DashboardChangedModal'; import { DashboardEvent, DashboardEventAction } from './types'; @@ -111,7 +111,7 @@ class DashboardWatcher { } const dash = getDashboardSrv().getCurrent(); - if (dash.uid !== event.message.uid) { + if (dash?.uid !== event.message.uid) { console.log('dashboard event for different dashboard?', event, dash); return; } diff --git a/public/app/features/manage-dashboards/services/ValidationSrv.ts b/public/app/features/manage-dashboards/services/ValidationSrv.ts index 060a9b99729..ea0c572f0a6 100644 --- a/public/app/features/manage-dashboards/services/ValidationSrv.ts +++ b/public/app/features/manage-dashboards/services/ValidationSrv.ts @@ -13,11 +13,11 @@ export class ValidationSrv { return this.validate(folderId, name, 'A dashboard or a folder with the same name already exists'); } - validateNewFolderName(name: string) { + validateNewFolderName(name?: string) { return this.validate(0, name, 'A folder or dashboard in the general folder with the same name already exists'); } - private async validate(folderId: any, name: string, existingErrorMessage: string) { + private async validate(folderId: any, name: string | undefined, existingErrorMessage: string) { name = (name || '').trim(); const nameLowerCased = name.toLowerCase(); diff --git a/public/app/features/search/utils.ts b/public/app/features/search/utils.ts index 917194e9e1e..060798b5a7b 100644 --- a/public/app/features/search/utils.ts +++ b/public/app/features/search/utils.ts @@ -189,9 +189,9 @@ export const getParsedQuery = (query: DashboardQuery, queryParsing = false) => { if (parseQuery(query.query).folder === 'current') { try { - const { folderId } = getDashboardSrv().getCurrent()?.meta; - if (folderId) { - folderIds = [folderId]; + const dash = getDashboardSrv().getCurrent(); + if (dash?.meta.folderId) { + folderIds = [dash?.meta.folderId]; } } catch (e) { console.error(e); diff --git a/public/app/features/variables/pickers/OptionsPicker/OptionPicker.test.tsx b/public/app/features/variables/pickers/OptionsPicker/OptionPicker.test.tsx index afbfeb2d4e5..f697ed09932 100644 --- a/public/app/features/variables/pickers/OptionsPicker/OptionPicker.test.tsx +++ b/public/app/features/variables/pickers/OptionsPicker/OptionPicker.test.tsx @@ -6,7 +6,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { LoadingState } from '@grafana/data'; import { VariablePickerProps } from '../types'; -import { QueryVariableModel } from '../../types'; +import { QueryVariableModel, VariableWithMultiSupport, VariableWithOptions } from '../../types'; import { queryBuilder } from '../../shared/testing/builders'; import { optionPickerFactory } from './OptionsPicker'; import { initialState, OptionsPickerState } from './reducer'; @@ -30,7 +30,7 @@ function setupTestContext({ pickerState = {}, variable = {} }: Args = {}) { ...variable, }; const onVariableChange = jest.fn(); - const props: VariablePickerProps = { + const props: VariablePickerProps = { variable: v, onVariableChange, }; diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index d0b001f57c3..62e7a979b92 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -482,7 +482,7 @@ export const variableUpdated = ( let promises: Array> = []; if (node) { promises = node.getOptimizedInputEdges().map((e) => { - const variable = variables.find((v) => v.name === e.inputNode.name); + const variable = variables.find((v) => v.name === e.inputNode?.name); if (!variable) { return Promise.resolve(); } diff --git a/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx b/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx index 7e999fc131c..83058c9d787 100644 --- a/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx +++ b/public/app/plugins/datasource/dashboard/DashboardQueryEditor.tsx @@ -60,7 +60,7 @@ export class DashboardQueryEditor extends PureComponent { const query = queries[0] as DashboardQuery; const defaultDS = await getDatasourceSrv().get(); const dashboard = getDashboardSrv().getCurrent(); - const panel = dashboard.getPanelById(query.panelId ?? -124134); + const panel = dashboard?.getPanelById(query.panelId ?? -124134); if (!panel) { this.setState({ defaultDatasource: defaultDS.name }); @@ -126,6 +126,10 @@ export class DashboardQueryEditor extends PureComponent { render() { const dashboard = getDashboardSrv().getCurrent(); + if (!dashboard) { + return null; + } + const query = this.getQuery(); let selected: SelectableValue | undefined; diff --git a/public/app/plugins/datasource/dashboard/runSharedRequest.ts b/public/app/plugins/datasource/dashboard/runSharedRequest.ts index 8a0cec09a51..00897caa8e8 100644 --- a/public/app/plugins/datasource/dashboard/runSharedRequest.ts +++ b/public/app/plugins/datasource/dashboard/runSharedRequest.ts @@ -33,7 +33,7 @@ export function runSharedRequest(options: QueryRunnerOptions): Observable) { const params: any = { state: getStateFilter(props.options.stateFilter), }; - const panel = getDashboardSrv().getCurrent().getPanelById(props.id)!; + const panel = getDashboardSrv().getCurrent()?.getPanelById(props.id)!; if (props.options.alertName) { params.query = getTemplateSrv().replace(props.options.alertName, panel.scopedVars); @@ -36,7 +36,7 @@ export function AlertList(props: PanelProps) { } if (props.options.dashboardAlerts) { - params.dashboardId = getDashboardSrv().getCurrent().id; + params.dashboardId = getDashboardSrv().getCurrent()?.id; } if (props.options.tags) { @@ -93,11 +93,11 @@ export function AlertList(props: PanelProps) { const currentDashboard = getDashboardSrv().getCurrent(); if (props.options.dashboardAlerts) { - params.dashboardId = currentDashboard.id; + params.dashboardId = currentDashboard?.id; } - params.from = dateMath.parse(currentDashboard.time.from)!.unix() * 1000; - params.to = dateMath.parse(currentDashboard.time.to)!.unix() * 1000; + params.from = dateMath.parse(currentDashboard?.time.from)!.unix() * 1000; + params.to = dateMath.parse(currentDashboard?.time.to)!.unix() * 1000; const data: AnnotationItemDTO[] = await getBackendSrv().get( '/api/annotations', @@ -109,7 +109,7 @@ export function AlertList(props: PanelProps) { data.map((al) => { return { ...al, - time: currentDashboard.formatDate(al.time, 'MMM D, YYYY HH:mm:ss'), + time: currentDashboard?.formatDate(al.time, 'MMM D, YYYY HH:mm:ss'), stateModel: alertDef.getStateDisplayModel(al.newState), info: alertDef.getAlertAnnotationInfo(al), }; diff --git a/public/app/plugins/panel/annolist/AnnoListPanel.tsx b/public/app/plugins/panel/annolist/AnnoListPanel.tsx index 823ef3b83e7..7c974a7d15c 100644 --- a/public/app/plugins/panel/annolist/AnnoListPanel.tsx +++ b/public/app/plugins/panel/annolist/AnnoListPanel.tsx @@ -69,7 +69,7 @@ export class AnnoListPanel extends PureComponent { }; if (options.onlyFromThisDashboard) { - params.dashboardId = getDashboardSrv().getCurrent().id; + params.dashboardId = getDashboardSrv().getCurrent()?.id; } let timeInfo = ''; @@ -120,7 +120,7 @@ export class AnnoListPanel extends PureComponent { params.viewPanel = anno.panelId; } - if (current.id === anno.dashboardId) { + if (current?.id === anno.dashboardId) { getLocationSrv().update({ query: params, partial: true, @@ -188,6 +188,9 @@ export class AnnoListPanel extends PureComponent { renderItem = (anno: AnnotationEvent, index: number): JSX.Element => { const { options } = this.props; const dashboard = getDashboardSrv().getCurrent(); + if (!dashboard) { + return <>; + } return ( { dismiss = () => { const { id } = this.props; const dashboard = getDashboardSrv().getCurrent(); - const panel = dashboard.getPanelById(id); + const panel = dashboard?.getPanelById(id); - dashboard.removePanel(panel!); + dashboard?.removePanel(panel!); backendSrv .request({ diff --git a/public/app/plugins/panel/table/TablePanel.tsx b/public/app/plugins/panel/table/TablePanel.tsx index 9956d065aa1..6040f5b49df 100644 --- a/public/app/plugins/panel/table/TablePanel.tsx +++ b/public/app/plugins/panel/table/TablePanel.tsx @@ -67,7 +67,7 @@ export class TablePanel extends Component { onCellFilterAdded = (filter: FilterItem) => { const { key, value, operator } = filter; - const panelModel = getDashboardSrv().getCurrent().getPanelById(this.props.id); + const panelModel = getDashboardSrv().getCurrent()?.getPanelById(this.props.id); const datasource = panelModel?.datasource; if (!datasource) { diff --git a/scripts/ci-check-strict.sh b/scripts/ci-check-strict.sh index 4c718787def..6262376933a 100755 --- a/scripts/ci-check-strict.sh +++ b/scripts/ci-check-strict.sh @@ -3,7 +3,7 @@ set -e echo -e "Collecting code stats (typescript errors & more)" -ERROR_COUNT_LIMIT=340 +ERROR_COUNT_LIMIT=255 ERROR_COUNT="$(./node_modules/.bin/tsc --project tsconfig.json --noEmit --strict true | grep -oP 'Found \K(\d+)')" if [ "$ERROR_COUNT" -gt $ERROR_COUNT_LIMIT ]; then