From 8f78b0e7bc37710b36fbd4dce521ca488d31c4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 10 Jul 2020 12:46:59 +0200 Subject: [PATCH] Chore: Fix all Typescript strict null errors (#26204) * Chore: Fix typescript strict null errors * Added new limit * Fixed ts issue * fixed tests * trying to fix type inference * Fixing more ts errors * Revert tsconfig option * Fix * Fixed code * More fixes * fix tests * Updated snapshot * Chore: More ts strict null fixes * More fixes in some really messed up azure config components * More fixes, current count: 441 * 419 * More fixes * Fixed invalid initial state in explore * Fixing tests * Fixed tests * Explore fix * More fixes * Progress * Sub 300 * Now at 218 * Progress * Update * Progress * Updated tests * at 159 * fixed tests * Progress * YAy blow 100! at 94 * 10,9,8,7,6,5,4,3,2,1... lift off * Fixed tests * Fixed more type errors Co-authored-by: Ryan McKinley --- .../grafana-data/src/panel/PanelPlugin.ts | 9 +++-- packages/grafana-data/src/types/panel.ts | 2 +- .../grafana-ui/src/components/Tabs/Tab.tsx | 2 +- .../QueryOperationAction.test.tsx | 2 +- .../QueryOperationAction.tsx | 2 +- .../QueryOperationRow/QueryOperationRow.tsx | 1 + .../core/components/Select/MetricSelect.tsx | 2 +- .../components/form_dropdown/form_dropdown.ts | 2 +- .../query_part/query_part_editor.ts | 2 +- .../components/sidemenu/BottomSection.tsx | 2 +- .../components/sql_part/sql_part_editor.ts | 2 +- public/app/core/directives/metric_segment.ts | 2 +- .../app/core/directives/rebuild_on_change.ts | 5 ++- public/app/core/jquery_extended.ts | 8 ++-- public/app/core/logs_model.ts | 40 +++++++++---------- public/app/core/nav_model_srv.ts | 2 +- public/app/core/reducers/navModel.ts | 6 +-- public/app/core/reducers/processsAclItems.ts | 7 ++-- public/app/core/services/backend_srv.ts | 1 + public/app/core/services/bridge_srv.test.ts | 2 +- public/app/core/services/keybindingSrv.ts | 34 ++++++++++------ public/app/core/time_series2.ts | 2 +- public/app/core/utils/acl.ts | 7 ++-- public/app/core/utils/browser.ts | 8 ++-- public/app/core/utils/dag.ts | 7 +--- public/app/core/utils/explore.ts | 1 + public/app/core/utils/richHistory.ts | 2 +- public/app/features/admin/UserCreatePage.tsx | 9 ++++- .../app/features/admin/UserLdapSyncInfo.tsx | 2 +- public/app/features/admin/UserOrgs.tsx | 8 ++-- public/app/features/admin/UserSyncInfo.tsx | 4 +- public/app/features/alerting/AlertTab.tsx | 2 +- public/app/features/alerting/AlertTabCtrl.ts | 4 +- .../app/features/alerting/TestRuleResult.tsx | 2 +- .../alerting/getAlertingValidationMessage.ts | 4 +- .../app/features/alerting/state/alertDef.ts | 2 +- .../app/features/alerting/state/selectors.ts | 2 +- .../app/features/annotations/event_editor.ts | 6 +-- .../app/features/annotations/event_manager.ts | 2 +- .../api-keys/__mocks__/apiKeysMock.ts | 5 ++- .../dashboard/components/DashNav/DashNav.tsx | 2 +- .../components/DashboardRow/DashboardRow.tsx | 2 +- .../DashboardSettings/DashboardSettings.tsx | 6 +-- .../DashboardSettings/SettingsCtrl.ts | 4 +- .../FolderPicker/FolderPickerCtrl.ts | 3 +- .../components/Inspector/InspectDataTab.tsx | 33 ++++++++++----- .../components/Inspector/InspectJSONTab.tsx | 16 ++++---- .../components/Inspector/PanelInspector.tsx | 8 ++-- .../components/Inspector/QueryInspector.tsx | 2 +- .../PanelEditor/AngularPanelOptions.tsx | 6 +-- .../PanelEditor/FieldConfigEditor.tsx | 4 +- .../PanelEditor/OptionsPaneContent.tsx | 10 ++--- .../components/PanelEditor/OverrideEditor.tsx | 2 +- .../PanelEditor/PanelEditorTabs.tsx | 2 +- .../PanelEditor/PanelOptionsTab.tsx | 4 +- .../PanelEditor/usePanelLatestData.ts | 2 +- .../RepeatRowSelect/RepeatRowSelect.tsx | 4 +- .../RowOptions/RowOptionsButton.tsx | 2 +- .../components/RowOptions/RowOptionsForm.tsx | 6 +-- .../forms/SaveDashboardAsForm.tsx | 4 ++ .../SaveDashboard/forms/SaveDashboardForm.tsx | 4 ++ .../SaveDashboard/useDashboardSave.tsx | 5 ++- .../components/ShareModal/ShareModal.tsx | 4 +- .../TransformationOperationRow.tsx | 3 +- .../features/explore/state/actions.test.ts | 2 +- .../features/explore/state/reducers.test.ts | 10 ++--- .../features/plugins/__mocks__/pluginMocks.ts | 12 +++--- .../datasource/cloudwatch/datasource.ts | 2 +- .../elasticsearch/datasource.test.ts | 9 +++-- .../elasticsearch/specs/index_pattern.test.ts | 2 +- .../datasource/loki/datasource.test.ts | 1 + tsconfig.json | 3 +- 72 files changed, 224 insertions(+), 169 deletions(-) diff --git a/packages/grafana-data/src/panel/PanelPlugin.ts b/packages/grafana-data/src/panel/PanelPlugin.ts index 08ac016b582..2ac441d72d1 100644 --- a/packages/grafana-data/src/panel/PanelPlugin.ts +++ b/packages/grafana-data/src/panel/PanelPlugin.ts @@ -158,11 +158,14 @@ export class PanelPlugin(); - this.registerOptionEditors(builder); this._optionEditors = builder.getRegistry(); + + if (this.registerOptionEditors) { + this.registerOptionEditors(builder); + } } return this._optionEditors; diff --git a/packages/grafana-data/src/types/panel.ts b/packages/grafana-data/src/types/panel.ts index a0a89a2ecd4..ad51625f04c 100644 --- a/packages/grafana-data/src/types/panel.ts +++ b/packages/grafana-data/src/types/panel.ts @@ -81,7 +81,7 @@ export interface PanelEditorProps { callback?: () => void ) => void; /** Result set of panel queries */ - data: PanelData; + data?: PanelData; } export interface PanelModel { diff --git a/packages/grafana-ui/src/components/Tabs/Tab.tsx b/packages/grafana-ui/src/components/Tabs/Tab.tsx index 00127d38261..9932b07f721 100644 --- a/packages/grafana-ui/src/components/Tabs/Tab.tsx +++ b/packages/grafana-ui/src/components/Tabs/Tab.tsx @@ -16,7 +16,7 @@ export interface TabProps extends HTMLProps { icon?: IconName; onChangeTab: (event?: React.MouseEvent) => void; /** A number rendered next to the text. Usually used to display the number of items in a tab's view. */ - counter?: number; + counter?: number | null; } export const Tab = React.forwardRef( diff --git a/public/app/core/components/QueryOperationRow/QueryOperationAction.test.tsx b/public/app/core/components/QueryOperationRow/QueryOperationAction.test.tsx index 5e2d0cfde0f..f61b06c0de6 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationAction.test.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationAction.test.tsx @@ -4,7 +4,7 @@ import { shallow } from 'enzyme'; describe('QueryOperationAction', () => { it('renders', () => { - expect(() => shallow( {}} />)).not.toThrow(); + expect(() => shallow( {}} />)).not.toThrow(); }); describe('when disabled', () => { it('does not call onClick handler', () => { diff --git a/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx b/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx index f109b3c0d7a..5a7c86a69df 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx @@ -6,7 +6,7 @@ import { selectors } from '@grafana/e2e-selectors'; interface QueryOperationActionProps { icon: IconName; - title?: string; + title: string; onClick: (e: React.MouseEvent) => void; disabled?: boolean; } diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx index c124a0d6f0b..d7a3128a1b7 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx @@ -28,6 +28,7 @@ export const QueryOperationRow: React.FC = ({ const [isContentVisible, setIsContentVisible] = useState(isOpen !== undefined ? isOpen : true); const theme = useTheme(); const styles = getQueryOperationRowStyles(theme); + useUpdateEffect(() => { if (isContentVisible) { if (onOpen) { diff --git a/public/app/core/components/Select/MetricSelect.tsx b/public/app/core/components/Select/MetricSelect.tsx index 37bee34db3b..a1c4bb26224 100644 --- a/public/app/core/components/Select/MetricSelect.tsx +++ b/public/app/core/components/Select/MetricSelect.tsx @@ -7,7 +7,7 @@ import { Variable } from 'app/types/templates'; const { Select } = LegacyForms; export interface Props { - onChange: (value: string) => void; + onChange: (value: string | undefined) => void; options: Array>; isSearchable: boolean; value: string; diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts index 9f999570024..55b99c5fde7 100644 --- a/public/app/core/components/form_dropdown/form_dropdown.ts +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -218,7 +218,7 @@ export class FormDropdownCtrl { } open() { - this.inputElement.css('width', Math.max(this.linkElement.width(), 80) + 16 + 'px'); + this.inputElement.css('width', Math.max(this.linkElement.width()!, 80) + 16 + 'px'); this.inputElement.show(); this.inputElement.focus(); diff --git a/public/app/core/components/query_part/query_part_editor.ts b/public/app/core/components/query_part/query_part_editor.ts index 372452a6adb..2d09a828cb6 100644 --- a/public/app/core/components/query_part/query_part_editor.ts +++ b/public/app/core/components/query_part/query_part_editor.ts @@ -39,7 +39,7 @@ export function queryPartEditorDirective(templateSrv: any) { const $input = $link.next(); $input.val(part.params[paramIndex]); - $input.css('width', $link.width() + 16 + 'px'); + $input.css('width', $link.width()! + 16 + 'px'); $link.hide(); $input.show(); diff --git a/public/app/core/components/sidemenu/BottomSection.tsx b/public/app/core/components/sidemenu/BottomSection.tsx index fb93f6f2202..6a453380cab 100644 --- a/public/app/core/components/sidemenu/BottomSection.tsx +++ b/public/app/core/components/sidemenu/BottomSection.tsx @@ -8,7 +8,7 @@ import { NavModelItem } from '@grafana/data'; export default function BottomSection() { const navTree: NavModelItem[] = _.cloneDeep(config.bootData.navTree); - const bottomNav: NavModelItem[] = _.filter(navTree, item => item.hideFromMenu); + const bottomNav: NavModelItem[] = navTree.filter(item => item.hideFromMenu); const isSignedIn = contextSrv.isSignedIn; const user = contextSrv.user; diff --git a/public/app/core/components/sql_part/sql_part_editor.ts b/public/app/core/components/sql_part/sql_part_editor.ts index 4ceaa50bcc4..b0f17a69520 100644 --- a/public/app/core/components/sql_part/sql_part_editor.ts +++ b/public/app/core/components/sql_part/sql_part_editor.ts @@ -39,7 +39,7 @@ export function sqlPartEditorDirective(templateSrv: any) { const $input = $link.next(); $input.val(part.params[paramIndex]); - $input.css('width', $link.width() + 16 + 'px'); + $input.css('width', $link.width()! + 16 + 'px'); $link.hide(); $input.show(); diff --git a/public/app/core/directives/metric_segment.ts b/public/app/core/directives/metric_segment.ts index cc49ccac92b..4542530f3f1 100644 --- a/public/app/core/directives/metric_segment.ts +++ b/public/app/core/directives/metric_segment.ts @@ -164,7 +164,7 @@ export function metricSegment($compile: any, $sce: any, templateSrv: TemplateSrv $button.click(() => { options = null; - $input.css('width', Math.max($button.width(), 80) + 16 + 'px'); + $input.css('width', Math.max($button.width()!, 80) + 16 + 'px'); $button.hide(); $input.show(); diff --git a/public/app/core/directives/rebuild_on_change.ts b/public/app/core/directives/rebuild_on_change.ts index 57b42ecaa63..a8be3ca70df 100644 --- a/public/app/core/directives/rebuild_on_change.ts +++ b/public/app/core/directives/rebuild_on_change.ts @@ -4,7 +4,7 @@ import coreModule from '../core_module'; function getBlockNodes(nodes: any[]) { let node = nodes[0]; const endNode = nodes[nodes.length - 1]; - let blockNodes: any[]; + let blockNodes: any[] | undefined; node = node.nextSibling; for (let i = 1; node !== endNode && node; i++) { @@ -12,7 +12,8 @@ function getBlockNodes(nodes: any[]) { if (!blockNodes) { blockNodes = $([].slice.call(nodes, 0, i)) as any; } - blockNodes.push(node); + + blockNodes!.push(node); } node = node.nextSibling; } diff --git a/public/app/core/jquery_extended.ts b/public/app/core/jquery_extended.ts index 36d6d44c0d3..0d11eece8dc 100644 --- a/public/app/core/jquery_extended.ts +++ b/public/app/core/jquery_extended.ts @@ -39,11 +39,11 @@ $.fn.place_tt = (() => { ]); } - width = $tooltip.outerWidth(true); - height = $tooltip.outerHeight(true); + width = $tooltip.outerWidth(true)!; + height = $tooltip.outerHeight(true)!; - const left = x + opts.offset + width > $win.width() ? x - opts.offset - width : x + opts.offset; - const top = y + opts.offset + height > $win.height() ? y - opts.offset - height : y + opts.offset; + const left = x + opts.offset + width > $win.width()! ? x - opts.offset - width : x + opts.offset; + const top = y + opts.offset + height > $win.height()! ? y - opts.offset - height : y + opts.offset; $tooltip.css('left', left > 0 ? left : 0); $tooltip.css('top', top > 0 ? top : 0); diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index c3ab257a78f..8e80f04d31d 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -141,24 +141,21 @@ export function makeSeriesForLogs(sortedRows: LogRowModel[], bucketSize: number, const data = toDataFrame(series); const fieldCache = new FieldCache(data); - const timeField = fieldCache.getFirstFieldOfType(FieldType.time); - if (timeField) { - timeField.display = getDisplayProcessor({ - field: timeField, - timeZone, - }); - } + const timeField = fieldCache.getFirstFieldOfType(FieldType.time)!; + timeField.display = getDisplayProcessor({ + field: timeField, + timeZone, + }); - const valueField = fieldCache.getFirstFieldOfType(FieldType.number); - if (valueField) { - valueField.config = { - ...valueField.config, - color: series.color, - }; - valueField.name = series.alias; - const fieldDisplayProcessor = getDisplayProcessor({ field: valueField, timeZone }); - valueField.display = (value: any) => ({ ...fieldDisplayProcessor(value), color: series.color }); - } + const valueField = fieldCache.getFirstFieldOfType(FieldType.number)!; + valueField.config = { + ...valueField.config, + color: series.color, + }; + + valueField.name = series.alias; + const fieldDisplayProcessor = getDisplayProcessor({ field: valueField, timeZone }); + valueField.display = (value: any) => ({ ...fieldDisplayProcessor(value), color: series.color }); const points = getFlotPairs({ xField: timeField, @@ -415,20 +412,23 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi // Hack to print loki stats in Explore. Should be using proper stats display via drawer in Explore (rework in 7.1) let totalBytes = 0; const queriesVisited: { [refId: string]: boolean } = {}; + for (const series of logSeries) { const totalBytesKey = series.meta?.custom?.lokiQueryStatKey; - // Stats are per query, keeping track by refId - const { refId } = series; + const { refId } = series; // Stats are per query, keeping track by refId + if (refId && !queriesVisited[refId]) { if (totalBytesKey && series.meta?.stats) { - const byteStat = series.meta?.stats.find(stat => stat.displayName === totalBytesKey); + const byteStat = series.meta.stats.find(stat => stat.displayName === totalBytesKey); if (byteStat) { totalBytes += byteStat.value; } } + queriesVisited[refId] = true; } } + if (totalBytes > 0) { const { text, suffix } = decimalSIPrefix('B')(totalBytes); meta.push({ diff --git a/public/app/core/nav_model_srv.ts b/public/app/core/nav_model_srv.ts index b869a1bea3a..22204565004 100644 --- a/public/app/core/nav_model_srv.ts +++ b/public/app/core/nav_model_srv.ts @@ -19,7 +19,7 @@ export class NavModelSrv { let children = this.navItems; const nav = { breadcrumbs: [], - } as NavModel; + } as any; for (const id of args) { // if its a number then it's the index to use for main diff --git a/public/app/core/reducers/navModel.ts b/public/app/core/reducers/navModel.ts index d974e82efc7..3af34c8fde9 100644 --- a/public/app/core/reducers/navModel.ts +++ b/public/app/core/reducers/navModel.ts @@ -12,7 +12,7 @@ export function buildInitialState(): NavIndex { function buildNavIndex(navIndex: NavIndex, children: NavModelItem[], parentItem?: NavModelItem) { for (const node of children) { - navIndex[node.id] = { + navIndex[node.id!] = { ...node, parentItem: parentItem, }; @@ -52,8 +52,8 @@ export const navIndexReducer = (state: NavIndex = initialState, action: AnyActio const newPages: NavIndex = {}; const payload = action.payload; - for (const node of payload.children) { - newPages[node.id] = { + for (const node of payload.children!) { + newPages[node.id!] = { ...node, parentItem: payload, }; diff --git a/public/app/core/reducers/processsAclItems.ts b/public/app/core/reducers/processsAclItems.ts index 57578d6b2d8..e8aeaa60fec 100644 --- a/public/app/core/reducers/processsAclItems.ts +++ b/public/app/core/reducers/processsAclItems.ts @@ -1,17 +1,18 @@ import { DashboardAcl, DashboardAclDTO } from 'app/types/acl'; export function processAclItems(items: DashboardAclDTO[]): DashboardAcl[] { - return items.map(processAclItem).sort((a, b) => b.sortRank - a.sortRank || a.name.localeCompare(b.name)); + return items.map(processAclItem).sort((a, b) => b.sortRank! - a.sortRank! || a.name!.localeCompare(b.name!)); } function processAclItem(dto: DashboardAclDTO): DashboardAcl { const item = dto as DashboardAcl; item.sortRank = 0; - if (item.userId > 0) { + + if (item.userId! > 0) { item.name = item.userLogin; item.sortRank = 10; - } else if (item.teamId > 0) { + } else if (item.teamId! > 0) { item.name = item.team; item.sortRank = 20; } else if (item.role) { diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index 6b3735fd58a..6518b37874c 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -113,6 +113,7 @@ export class BackendSrv implements BackendService { } if (this.noBackendCache) { + options.headers = options.headers ?? {}; options.headers['X-Grafana-NoCache'] = 'true'; } } diff --git a/public/app/core/services/bridge_srv.test.ts b/public/app/core/services/bridge_srv.test.ts index b6e7d1e6fea..06b42e30640 100644 --- a/public/app/core/services/bridge_srv.test.ts +++ b/public/app/core/services/bridge_srv.test.ts @@ -71,6 +71,6 @@ describe('when checking template variables', () => { 'var-test': 'asd', }; - expect(findTemplateVarChanges(a, b)['var-test']).toEqual(['test']); + expect(findTemplateVarChanges(a, b)!['var-test']).toEqual(['test']); }); }); diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts index e69a4bc5437..0ec85fc66ab 100644 --- a/public/app/core/services/keybindingSrv.ts +++ b/public/app/core/services/keybindingSrv.ts @@ -228,6 +228,10 @@ export class KeybindingSrv { // edit panel this.bind('e', () => { + if (!dashboard.meta.focusPanelId) { + return; + } + if (dashboard.canEditPanelById(dashboard.meta.focusPanelId)) { const search = _.extend(this.$location.search(), { editPanel: dashboard.meta.focusPanelId }); this.$location.search(search); @@ -253,7 +257,7 @@ export class KeybindingSrv { if (this.contextSrv.hasAccessToExplore()) { this.bind('x', async () => { if (dashboard.meta.focusPanelId) { - const panel = dashboard.getPanelById(dashboard.meta.focusPanelId); + const panel = dashboard.getPanelById(dashboard.meta.focusPanelId)!; const datasource = await this.datasourceSrv.get(panel.datasource); const url = await getExploreUrl({ panel, @@ -262,10 +266,12 @@ export class KeybindingSrv { datasourceSrv: this.datasourceSrv, timeSrv: this.timeSrv, }); - const urlWithoutBase = locationUtil.stripBaseFromUrl(url); - if (urlWithoutBase) { - this.$timeout(() => this.$location.url(urlWithoutBase)); + if (url) { + const urlWithoutBase = locationUtil.stripBaseFromUrl(url); + if (urlWithoutBase) { + this.$timeout(() => this.$location.url(urlWithoutBase)); + } } } }); @@ -273,16 +279,20 @@ export class KeybindingSrv { // delete panel this.bind('p r', () => { - if (dashboard.canEditPanelById(dashboard.meta.focusPanelId)) { - appEvents.emit(CoreEvents.removePanel, dashboard.meta.focusPanelId); + const panelId = dashboard.meta.focusPanelId; + + if (panelId && dashboard.canEditPanelById(panelId)) { + appEvents.emit(CoreEvents.removePanel, panelId); dashboard.meta.focusPanelId = 0; } }); // duplicate panel this.bind('p d', () => { - if (dashboard.canEditPanelById(dashboard.meta.focusPanelId)) { - const panelIndex = dashboard.getPanelInfoById(dashboard.meta.focusPanelId).index; + const panelId = dashboard.meta.focusPanelId; + + if (panelId && dashboard.canEditPanelById(panelId)) { + const panelIndex = dashboard.getPanelInfoById(panelId)!.index; dashboard.duplicatePanel(dashboard.panels[panelIndex]); } }); @@ -305,11 +315,11 @@ export class KeybindingSrv { // toggle panel legend this.bind('p l', () => { if (dashboard.meta.focusPanelId) { - const panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId); + const panelInfo = dashboard.getPanelInfoById(dashboard.meta.focusPanelId)!; + if (panelInfo.panel.legend) { - const panelRef = dashboard.getPanelById(dashboard.meta.focusPanelId); - panelRef.legend.show = !panelRef.legend.show; - panelRef.render(); + panelInfo.panel.legend.show = !panelInfo.panel.legend.show; + panelInfo.panel.render(); } } }); diff --git a/public/app/core/time_series2.ts b/public/app/core/time_series2.ts index 0c4b2415586..07fabac2d09 100644 --- a/public/app/core/time_series2.ts +++ b/public/app/core/time_series2.ts @@ -348,7 +348,7 @@ export default class TimeSeries { this.scaledDecimals = scaledDecimals; } - formatValue(value: number) { + formatValue(value: number | null) { if (!_.isFinite(value)) { value = null; // Prevent NaN formatting } diff --git a/public/app/core/utils/acl.ts b/public/app/core/utils/acl.ts index 57578d6b2d8..e8aeaa60fec 100644 --- a/public/app/core/utils/acl.ts +++ b/public/app/core/utils/acl.ts @@ -1,17 +1,18 @@ import { DashboardAcl, DashboardAclDTO } from 'app/types/acl'; export function processAclItems(items: DashboardAclDTO[]): DashboardAcl[] { - return items.map(processAclItem).sort((a, b) => b.sortRank - a.sortRank || a.name.localeCompare(b.name)); + return items.map(processAclItem).sort((a, b) => b.sortRank! - a.sortRank! || a.name!.localeCompare(b.name!)); } function processAclItem(dto: DashboardAclDTO): DashboardAcl { const item = dto as DashboardAcl; item.sortRank = 0; - if (item.userId > 0) { + + if (item.userId! > 0) { item.name = item.userLogin; item.sortRank = 10; - } else if (item.teamId > 0) { + } else if (item.teamId! > 0) { item.name = item.team; item.sortRank = 20; } else if (item.role) { diff --git a/public/app/core/utils/browser.ts b/public/app/core/utils/browser.ts index a89bd6122f3..9ed3c77f6e3 100644 --- a/public/app/core/utils/browser.ts +++ b/public/app/core/utils/browser.ts @@ -13,17 +13,17 @@ export function checkBrowserCompatibility() { */ const isEdgeVersion = /Edge\/([0-9.]+)/.exec(navigator.userAgent); - if (isIE && parseFloat(/Trident\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 7) { + if (isIE && parseFloat(/Trident\/([0-9.]+)/.exec(navigator.userAgent)![1]) <= 7) { return false; } else if ( isEdge && ((isEdgeVersion && parseFloat(isEdgeVersion[1]) <= 16) || - parseFloat(/Edg\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 16) + parseFloat(/Edg\/([0-9.]+)/.exec(navigator.userAgent)![1]) <= 16) ) { return false; - } else if (isFirefox && parseFloat(/Firefox\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 64) { + } else if (isFirefox && parseFloat(/Firefox\/([0-9.]+)/.exec(navigator.userAgent)![1]) <= 64) { return false; - } else if (isChrome && parseFloat(/Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 54) { + } else if (isChrome && parseFloat(/Chrome\/([0-9.]+)/.exec(navigator.userAgent)![1]) <= 54) { return false; } diff --git a/public/app/core/utils/dag.ts b/public/app/core/utils/dag.ts index c222077ac9a..6d1e690b090 100644 --- a/public/app/core/utils/dag.ts +++ b/public/app/core/utils/dag.ts @@ -60,9 +60,6 @@ export class Edge { if (pos > -1) { onode.inputEdges.splice(pos, 1); } - - this.inputNode = null; - this.outputNode = null; } } @@ -79,7 +76,7 @@ export class Node { this.outputEdges = []; } - getEdgeFrom(from: string | Node): Edge { + getEdgeFrom(from: string | Node): Edge | null | undefined { if (!from) { return null; } @@ -91,7 +88,7 @@ export class Node { return this.inputEdges.find(e => e.inputNode.name === from); } - getEdgeTo(to: string | Node): Edge { + getEdgeTo(to: string | Node): Edge | null | undefined { if (!to) { return null; } diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index cce634dfb17..5545fb0e465 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -113,6 +113,7 @@ export async function getExploreUrl(args: GetExploreUrlArguments): Promise { }; const serializedState = serializeStateToUrlParam(exploreState, true); - const baseUrl = /.*(?=\/explore)/.exec(`${window.location.href}`)[0]; + const baseUrl = /.*(?=\/explore)/.exec(`${window.location.href}`)![0]; const url = urlUtil.renderUrl(`${baseUrl}/explore`, { left: serializedState }); return url; }; diff --git a/public/app/features/admin/UserCreatePage.tsx b/public/app/features/admin/UserCreatePage.tsx index 95df6f4e911..62ff8805a52 100644 --- a/public/app/features/admin/UserCreatePage.tsx +++ b/public/app/features/admin/UserCreatePage.tsx @@ -36,7 +36,12 @@ const UserCreatePage: React.FC = ({ navModel, updateLocatio {({ register, errors }) => { return ( <> - + @@ -51,7 +56,7 @@ const UserCreatePage: React.FC = ({ navModel, updateLocatio label="Password" required invalid={!!errors.password} - error={!!errors.password && 'Password is required and must contain at least 4 characters'} + error={errors.password ? 'Password is required and must contain at least 4 characters' : undefined} > { const prevSyncSuccessful = ldapSyncInfo && ldapSyncInfo.prevSync; const nextSyncSuccessful = ldapSyncInfo && ldapSyncInfo.nextSync; const nextSyncTime = nextSyncSuccessful ? dateTimeFormat(ldapSyncInfo.nextSync, { format }) : ''; - const prevSyncTime = prevSyncSuccessful ? dateTimeFormat(ldapSyncInfo.prevSync.started, { format }) : ''; + const prevSyncTime = prevSyncSuccessful ? dateTimeFormat(ldapSyncInfo.prevSync!.started, { format }) : ''; const debugLDAPMappingURL = `${debugLDAPMappingBaseURL}?user=${user && user.login}`; return ( diff --git a/public/app/features/admin/UserOrgs.tsx b/public/app/features/admin/UserOrgs.tsx index 8534c46b14d..7eb5f0ac67f 100644 --- a/public/app/features/admin/UserOrgs.tsx +++ b/public/app/features/admin/UserOrgs.tsx @@ -189,7 +189,7 @@ interface AddToOrgModalProps { } interface AddToOrgModalState { - selectedOrg: Organization; + selectedOrg: Organization | null; role: OrgRole; } @@ -211,11 +211,13 @@ export class AddToOrgModal extends PureComponent { const { selectedOrg, role } = this.state; - this.props.onOrgAdd(selectedOrg.id, role); + this.props.onOrgAdd(selectedOrg!.id, role); }; onCancel = () => { - this.props.onDismiss(); + if (this.props.onDismiss) { + this.props.onDismiss(); + } }; render() { diff --git a/public/app/features/admin/UserSyncInfo.tsx b/public/app/features/admin/UserSyncInfo.tsx index 90238a5f998..5d76bf5c120 100644 --- a/public/app/features/admin/UserSyncInfo.tsx +++ b/public/app/features/admin/UserSyncInfo.tsx @@ -36,9 +36,9 @@ export class UserSyncInfo extends PureComponent { const { syncInfo, disableSync } = this.props; const { isSyncing } = this.state; const nextSyncSuccessful = syncInfo && syncInfo.nextSync; - const nextSyncTime = nextSyncSuccessful ? dateTimeFormat(syncInfo.nextSync, { format }) : ''; + const nextSyncTime = nextSyncSuccessful ? dateTimeFormat(syncInfo.nextSync!, { format }) : ''; const prevSyncSuccessful = syncInfo && syncInfo.prevSync; - const prevSyncTime = prevSyncSuccessful ? dateTimeFormat(syncInfo.prevSync, { format }) : ''; + const prevSyncTime = prevSyncSuccessful ? dateTimeFormat(syncInfo.prevSync!, { format }) : ''; const isDisabled = isSyncing || disableSync; return ( diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index fdfeb220fb9..9b9a7759e49 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -23,7 +23,7 @@ interface OwnProps { } interface ConnectedProps { - angularPanelComponent: AngularComponent; + angularPanelComponent?: AngularComponent | null; } interface DispatchProps { diff --git a/public/app/features/alerting/AlertTabCtrl.ts b/public/app/features/alerting/AlertTabCtrl.ts index 7df499dd2c0..5da5fae2f8f 100644 --- a/public/app/features/alerting/AlertTabCtrl.ts +++ b/public/app/features/alerting/AlertTabCtrl.ts @@ -214,7 +214,7 @@ export class AlertTabCtrl { memo.push(this.buildConditionModel(value)); return memo; }, - [] + [] as string[] ); ThresholdMapper.alertToGraphThresholds(this.panel); @@ -282,7 +282,7 @@ export class AlertTabCtrl { } let firstTarget; - let foundTarget: DataQuery = null; + let foundTarget: DataQuery | null = null; const promises: Array> = []; for (const condition of this.alert.conditions) { diff --git a/public/app/features/alerting/TestRuleResult.tsx b/public/app/features/alerting/TestRuleResult.tsx index 7a95a8a995c..e17c1b65571 100644 --- a/public/app/features/alerting/TestRuleResult.tsx +++ b/public/app/features/alerting/TestRuleResult.tsx @@ -14,7 +14,7 @@ export interface Props { interface State { isLoading: boolean; - allNodesExpanded: boolean; + allNodesExpanded: boolean | null; testRuleResponse: {}; } diff --git a/public/app/features/alerting/getAlertingValidationMessage.ts b/public/app/features/alerting/getAlertingValidationMessage.ts index 2d89e506040..a92f2e67e6d 100644 --- a/public/app/features/alerting/getAlertingValidationMessage.ts +++ b/public/app/features/alerting/getAlertingValidationMessage.ts @@ -11,10 +11,10 @@ export const getDefaultCondition = () => ({ }); export const getAlertingValidationMessage = async ( - transformations: DataTransformerConfig[], + transformations: DataTransformerConfig[] | undefined, targets: DataQuery[], datasourceSrv: DataSourceSrv, - datasourceName: string + datasourceName: string | null ): Promise => { if (targets.length === 0) { return 'Could not find any metric queries'; diff --git a/public/app/features/alerting/state/alertDef.ts b/public/app/features/alerting/state/alertDef.ts index 060c4df10b7..f41065365ee 100644 --- a/public/app/features/alerting/state/alertDef.ts +++ b/public/app/features/alerting/state/alertDef.ts @@ -134,7 +134,7 @@ function joinEvalMatches(matches: any, separator: string) { return res; }, - [] + [] as string[] ).join(separator); } diff --git a/public/app/features/alerting/state/selectors.ts b/public/app/features/alerting/state/selectors.ts index 0b03076b573..a1e2c646f1f 100644 --- a/public/app/features/alerting/state/selectors.ts +++ b/public/app/features/alerting/state/selectors.ts @@ -6,6 +6,6 @@ export const getAlertRuleItems = (state: AlertRulesState) => { const regex = new RegExp(state.searchQuery, 'i'); return state.items.filter(item => { - return regex.test(item.name) || regex.test(item.stateText) || regex.test(item.info); + return regex.test(item.name) || regex.test(item.stateText) || regex.test(item.info!); }); }; diff --git a/public/app/features/annotations/event_editor.ts b/public/app/features/annotations/event_editor.ts index b70a456a00d..f6a15935876 100644 --- a/public/app/features/annotations/event_editor.ts +++ b/public/app/features/annotations/event_editor.ts @@ -24,7 +24,7 @@ export class EventEditorCtrl { this.event.timeEnd = tryEpochToMoment(this.event.timeEnd); } - this.timeFormated = this.panelCtrl.dashboard.formatDate(this.event.time); + this.timeFormated = this.panelCtrl.dashboard.formatDate(this.event.time!); } save() { @@ -33,11 +33,11 @@ export class EventEditorCtrl { } const saveModel = _.cloneDeep(this.event); - saveModel.time = saveModel.time.valueOf(); + saveModel.time = saveModel.time!.valueOf(); saveModel.timeEnd = 0; if (saveModel.isRegion) { - saveModel.timeEnd = this.event.timeEnd.valueOf(); + saveModel.timeEnd = this.event.timeEnd!.valueOf(); if (saveModel.timeEnd < saveModel.time) { console.log('invalid time'); diff --git a/public/app/features/annotations/event_manager.ts b/public/app/features/annotations/event_manager.ts index 38faeef3f83..0eddda2ce46 100644 --- a/public/app/features/annotations/event_manager.ts +++ b/public/app/features/annotations/event_manager.ts @@ -13,7 +13,7 @@ import { MetricsPanelCtrl } from 'app/plugins/sdk'; import { AnnotationEvent } from '@grafana/data'; export class EventManager { - event: AnnotationEvent; + event: AnnotationEvent | null; editorOpen: boolean; constructor(private panelCtrl: MetricsPanelCtrl) {} diff --git a/public/app/features/api-keys/__mocks__/apiKeysMock.ts b/public/app/features/api-keys/__mocks__/apiKeysMock.ts index 099b4c92ec4..c244cb6af8f 100644 --- a/public/app/features/api-keys/__mocks__/apiKeysMock.ts +++ b/public/app/features/api-keys/__mocks__/apiKeysMock.ts @@ -2,12 +2,13 @@ export const getMultipleMockKeys = (numberOfKeys: number): ApiKey[] => { const keys: ApiKey[] = []; + for (let i = 1; i <= numberOfKeys; i++) { keys.push({ id: i, name: `test-${i}`, role: OrgRole.Viewer, - secondsToLive: null, + secondsToLive: 100, expiration: '2019-06-04', }); } @@ -20,7 +21,7 @@ export const getMockKey = (): ApiKey => { id: 1, name: 'test', role: OrgRole.Admin, - secondsToLive: null, + secondsToLive: 200, expiration: '2019-06-04', }; }; diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index 5d769e27b06..eeacb49458e 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -184,7 +184,7 @@ class DashNav extends PureComponent { `; const folderTitle = dashboard.meta.folderTitle; - const haveFolder = dashboard.meta.folderId > 0; + const haveFolder = (dashboard.meta.folderId ?? 0) > 0; return ( <> diff --git a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx index 04511859bbb..233b1f1ce92 100644 --- a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx +++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx @@ -40,7 +40,7 @@ export class DashboardRow extends React.Component { }); }; - onUpdate = (title: string | null, repeat: string | null) => { + onUpdate = (title: string, repeat: string | undefined) => { this.props.panel['title'] = title; this.props.panel['repeat'] = repeat; this.props.panel.render(); diff --git a/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx b/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx index 0d663c39b6b..8607b8d9341 100644 --- a/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx +++ b/public/app/features/dashboard/components/DashboardSettings/DashboardSettings.tsx @@ -11,12 +11,12 @@ import { updateLocation } from 'app/core/actions'; import { CustomScrollbar } from '@grafana/ui'; export interface Props { - dashboard: DashboardModel | null; + dashboard: DashboardModel; updateLocation: typeof updateLocation; } export class DashboardSettings extends PureComponent { - element: HTMLElement; + element?: HTMLElement | null; angularCmp: AngularComponent; componentDidMount() { @@ -44,7 +44,7 @@ export class DashboardSettings extends PureComponent { render() { const { dashboard } = this.props; const folderTitle = dashboard.meta.folderTitle; - const haveFolder = dashboard.meta.folderId > 0; + const haveFolder = (dashboard.meta.folderId ?? 0) > 0; return (
diff --git a/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts b/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts index da0090ed869..6df016efdb1 100644 --- a/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts +++ b/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts @@ -18,8 +18,8 @@ export class SettingsCtrl { json: string; alertCount: number; canSaveAs: boolean; - canSave: boolean; - canDelete: boolean; + canSave?: boolean; + canDelete?: boolean; sections: any[]; hasUnsavedFolderChange: boolean; selectors: typeof selectors.pages.Dashboard.Settings.General; diff --git a/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts b/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts index 40121de191c..2dce27c6e1e 100644 --- a/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts +++ b/public/app/features/dashboard/components/FolderPicker/FolderPickerCtrl.ts @@ -146,7 +146,8 @@ export class FolderPickerCtrl { const rootFolder: { text: string; value: any } = { text: this.rootName, value: 0 }; this.getOptions('').then((result: any[]) => { - let folder: { text: string; value: any }; + let folder: { text: string; value: any } | undefined; + if (this.initialFolderId) { // @ts-ignore folder = _.find(result, { value: this.initialFolderId }); diff --git a/public/app/features/dashboard/components/Inspector/InspectDataTab.tsx b/public/app/features/dashboard/components/Inspector/InspectDataTab.tsx index ecc6bc777e9..51f3aed37a6 100644 --- a/public/app/features/dashboard/components/Inspector/InspectDataTab.tsx +++ b/public/app/features/dashboard/components/Inspector/InspectDataTab.tsx @@ -62,9 +62,10 @@ export class InspectDataTab extends PureComponent { // Replace the time field with a formatted time const { timeIndex, timeField } = getTimeField(dataFrame); + if (timeField) { // Use the configurd date or standandard time display - let processor: DisplayProcessor = timeField.display; + let processor: DisplayProcessor | undefined = timeField.display; if (!processor) { processor = getDisplayProcessor({ field: timeField, @@ -78,7 +79,8 @@ export class InspectDataTab extends PureComponent { }; const fields = [...dataFrame.fields]; - fields[timeIndex] = formattedDateField; + fields[timeIndex!] = formattedDateField; + dataFrame = { ...dataFrame, fields, @@ -100,8 +102,9 @@ export class InspectDataTab extends PureComponent { transformId: item.value === DataTransformerID.seriesToColumns ? DataTransformerID.seriesToColumns : DataTransformerID.noop, dataFrameIndex: typeof item.value === 'number' ? item.value : 0, - selectedDataFrame: item.value, + selectedDataFrame: item.value!, }); + this.props.onOptionsChange({ ...this.props.options, }); @@ -127,6 +130,10 @@ export class InspectDataTab extends PureComponent { const { options } = this.props; let data = this.props.data; + if (!data) { + return []; + } + if (this.state.transformId !== DataTransformerID.noop) { data = this.getTransformedData(); } @@ -152,16 +159,21 @@ export class InspectDataTab extends PureComponent { }); } - getActiveString = () => { + getActiveString() { const { selectedDataFrame } = this.state; const { options, data } = this.props; - let activeString = ''; + + if (!data) { + return activeString; + } + if (selectedDataFrame === DataTransformerID.seriesToColumns) { activeString = 'series joined by time'; } else { activeString = getFrameDisplayName(data[selectedDataFrame as number]); } + if (options.withTransforms || options.withFieldConfig) { activeString += ' - applied '; if (options.withTransforms) { @@ -176,10 +188,11 @@ export class InspectDataTab extends PureComponent { activeString += 'field configuration'; } } + return activeString; - }; + } - renderDataOptions = (dataFrames: DataFrame[]) => { + renderDataOptions(dataFrames: DataFrame[]) { const { options, onOptionsChange, panel, data } = this.props; const { transformId, transformationOptions, selectedDataFrame } = this.state; @@ -193,7 +206,7 @@ export class InspectDataTab extends PureComponent { let dataSelect = dataFrames; if (selectedDataFrame === DataTransformerID.seriesToColumns) { - dataSelect = data; + dataSelect = data!; } const choices = dataSelect.map((frame, index) => { @@ -222,7 +235,7 @@ export class InspectDataTab extends PureComponent { className={css` margin-bottom: 0; `} - disabled={!(data.length > 1)} + disabled={data!.length < 2} >