diff --git a/package.json b/package.json index 307ee191590..cff21752173 100644 --- a/package.json +++ b/package.json @@ -177,6 +177,7 @@ "@types/enzyme-adapter-react-16": "1.0.5", "@types/file-saver": "2.0.1", "@types/marked": "0.6.5", + "@types/mousetrap": "1.6.3", "@types/prismjs": "1.16.0", "@types/react-redux": "7.0.8", "@types/react-table": "6.8.5", diff --git a/packages/grafana-data/src/types/data.ts b/packages/grafana-data/src/types/data.ts index fe7bd106369..62286e770af 100644 --- a/packages/grafana-data/src/types/data.ts +++ b/packages/grafana-data/src/types/data.ts @@ -106,6 +106,7 @@ export interface AnnotationEvent { dashboardId?: number; panelId?: number; userId?: number; + regionId?: number; login?: string; email?: string; avatarUrl?: string; diff --git a/packages/grafana-ui/src/components/Graph/Graph.tsx b/packages/grafana-ui/src/components/Graph/Graph.tsx index 8c3bac26113..dd803792e8f 100644 --- a/packages/grafana-ui/src/components/Graph/Graph.tsx +++ b/packages/grafana-ui/src/components/Graph/Graph.tsx @@ -58,7 +58,7 @@ export class Graph extends PureComponent { }), yAxisConfig => yAxisConfig.index ); - const flotOptions = { + const flotOptions: any = { legend: { show: false, }, diff --git a/packages/grafana-ui/src/components/Input/Input.tsx b/packages/grafana-ui/src/components/Input/Input.tsx index b8165c48dca..95cc342c479 100644 --- a/packages/grafana-ui/src/components/Input/Input.tsx +++ b/packages/grafana-ui/src/components/Input/Input.tsx @@ -27,7 +27,7 @@ export class Input extends PureComponent { className: '', }; - state = { + state: State = { error: null, }; diff --git a/packages/grafana-ui/src/components/SetInterval/SetInterval.tsx b/packages/grafana-ui/src/components/SetInterval/SetInterval.tsx index 8a327f0126b..d239130c96d 100644 --- a/packages/grafana-ui/src/components/SetInterval/SetInterval.tsx +++ b/packages/grafana-ui/src/components/SetInterval/SetInterval.tsx @@ -76,7 +76,7 @@ export class SetInterval extends PureComponent { this.propsSubject.unsubscribe(); } - render() { + render(): null { return null; } } diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index 40ecb63d377..fa03a711134 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -210,7 +210,7 @@ export abstract class DataSourceApi< /** * Get tag keys for adhoc filters */ - getTagKeys?(options: any): Promise; + getTagKeys?(options?: any): Promise; /** * Get tag values for adhoc filters diff --git a/public/app/core/controllers/signup_ctrl.ts b/public/app/core/controllers/signup_ctrl.ts index 5a85e1605b7..7d3a3378fa8 100644 --- a/public/app/core/controllers/signup_ctrl.ts +++ b/public/app/core/controllers/signup_ctrl.ts @@ -34,7 +34,7 @@ export class SignUpCtrl { }, }; - backendSrv.get('/api/user/signup/options').then(options => { + backendSrv.get('/api/user/signup/options').then((options: any) => { $scope.verifyEmailEnabled = options.verifyEmailEnabled; $scope.autoAssignOrg = options.autoAssignOrg; }); @@ -45,7 +45,7 @@ export class SignUpCtrl { return; } - this.backendSrv.post('/api/user/signup/step2', this.$scope.formModel).then(rsp => { + this.backendSrv.post('/api/user/signup/step2', this.$scope.formModel).then((rsp: any) => { if (rsp.code === 'redirect-to-select-org') { window.location.href = config.appSubUrl + '/profile/select-org?signup=1'; } else { diff --git a/public/app/core/services/ng_react.ts b/public/app/core/services/ng_react.ts index ed51dd81a92..3307eefc2e1 100644 --- a/public/app/core/services/ng_react.ts +++ b/public/app/core/services/ng_react.ts @@ -12,11 +12,11 @@ import { kebabCase } from 'lodash'; import React from 'react'; import ReactDOM from 'react-dom'; -import angular from 'angular'; +import angular, { auto } from 'angular'; // get a react component from name (components can be an angular injectable e.g. value, factory or // available on window -function getReactComponent(name, $injector) { +function getReactComponent(name: string, $injector: auto.IInjectorService) { // if name is a function assume it is component and return it if (angular.isFunction(name)) { return name; @@ -36,6 +36,7 @@ function getReactComponent(name, $injector) { if (!reactComponent) { try { reactComponent = name.split('.').reduce((current, namePart) => { + // @ts-ignore return current[namePart]; }, window); } catch (e) {} @@ -49,7 +50,7 @@ function getReactComponent(name, $injector) { } // wraps a function with scope.$apply, if already applied just return -function applied(fn, scope) { +function applied(fn: any, scope: any) { if (fn.wrappedInApply) { return fn; } @@ -81,7 +82,7 @@ function applied(fn, scope) { * @param propsConfig configuration object for all properties * @returns {Object} props with the functions wrapped in scope.$apply */ -function applyFunctions(obj, scope, propsConfig?) { +function applyFunctions(obj: any, scope: any, propsConfig?: any): object { return Object.keys(obj || {}).reduce((prev, key) => { const value = obj[key]; const config = (propsConfig || {})[key] || {}; @@ -90,6 +91,7 @@ function applyFunctions(obj, scope, propsConfig?) { * ensures that when function is called from a React component * the Angular digest cycle is run */ + // @ts-ignore prev[key] = angular.isFunction(value) && config.wrapApply !== false ? applied(value, scope) : value; return prev; @@ -104,7 +106,7 @@ function applyFunctions(obj, scope, propsConfig?) { * Uses the watchDepth attribute to determine how to watch props on scope. * If watchDepth attribute is NOT reference or collection, watchDepth defaults to deep watching by value */ -function watchProps(watchDepth, scope, watchExpressions, listener) { +function watchProps(watchDepth: string, scope: any, watchExpressions: any[], listener: any) { const supportsWatchCollection = angular.isFunction(scope.$watchCollection); const supportsWatchGroup = angular.isFunction(scope.$watchGroup); @@ -138,24 +140,24 @@ function watchProps(watchDepth, scope, watchExpressions, listener) { } // render React component, with scope[attrs.props] being passed in as the component props -function renderComponent(component, props, scope, elem) { +function renderComponent(component: any, props: object, scope: any, elem: Element[]) { scope.$evalAsync(() => { ReactDOM.render(React.createElement(component, props), elem[0]); }); } // get prop name from prop (string or array) -function getPropName(prop) { +function getPropName(prop: any) { return Array.isArray(prop) ? prop[0] : prop; } // get prop name from prop (string or array) -function getPropConfig(prop) { +function getPropConfig(prop: any) { return Array.isArray(prop) ? prop[1] : {}; } // get prop expression from prop (string or array) -function getPropExpression(prop) { +function getPropExpression(prop: any) { return Array.isArray(prop) ? prop[0] : prop; } @@ -170,11 +172,12 @@ function findAttribute(attrs: string, propName: string): string { const index = Object.keys(attrs).find(attr => { return attr.toLowerCase() === propName.toLowerCase() || attr.toLowerCase() === kebabCase(propName); }); + // @ts-ignore return attrs[index]; } // get watch depth of prop (string or array) -function getPropWatchDepth(defaultWatch, prop) { +function getPropWatchDepth(defaultWatch: string, prop: string | any[]) { const customWatchDepth = Array.isArray(prop) && angular.isObject(prop[1]) && prop[1].watchDepth; return customWatchDepth || defaultWatch; } @@ -197,11 +200,11 @@ function getPropWatchDepth(defaultWatch, prop) { // } // })); // -const reactComponent = $injector => { +const reactComponent = ($injector: any): any => { return { restrict: 'E', replace: true, - link: function(scope, elem, attrs) { + link: function(scope: any, elem: Element[], attrs: any) { const reactComponent = getReactComponent(attrs.name, $injector); const renderMyComponent = () => { @@ -254,12 +257,12 @@ const reactComponent = $injector => { // // // -const reactDirective = $injector => { - return (reactComponentName, props, conf, injectableProps) => { +const reactDirective = ($injector: auto.IInjectorService) => { + return (reactComponentName: string, props: string[], conf: any, injectableProps: any) => { const directive = { restrict: 'E', replace: true, - link: function(scope, elem, attrs) { + link: function(scope: any, elem: Element[], attrs: any) { const reactComponent = getReactComponent(reactComponentName, $injector); // if props is not defined, fall back to use the React component's propTypes if present @@ -267,8 +270,8 @@ const reactDirective = $injector => { // for each of the properties, get their scope value and set it to scope.props const renderMyComponent = () => { - let scopeProps = {}; - const config = {}; + let scopeProps: any = {}; + const config: any = {}; props.forEach(prop => { const propName = getPropName(prop); diff --git a/public/app/core/services/popover_srv.ts b/public/app/core/services/popover_srv.ts index 3a00589c251..3442415cbb2 100644 --- a/public/app/core/services/popover_srv.ts +++ b/public/app/core/services/popover_srv.ts @@ -1,10 +1,11 @@ import _ from 'lodash'; import coreModule from 'app/core/core_module'; +// @ts-ignore import Drop from 'tether-drop'; /** @ngInject */ -function popoverSrv(this: any, $compile, $rootScope, $timeout) { - let openDrop = null; +function popoverSrv(this: any, $compile: any, $rootScope: any, $timeout: any) { + let openDrop: any = null; this.close = () => { if (openDrop) { @@ -12,14 +13,14 @@ function popoverSrv(this: any, $compile, $rootScope, $timeout) { } }; - this.show = options => { + this.show = (options: any) => { if (openDrop) { openDrop.close(); openDrop = null; } const scope = _.extend($rootScope.$new(true), options.model); - let drop; + let drop: any; const cleanUp = () => { setTimeout(() => { diff --git a/public/app/core/services/util_srv.ts b/public/app/core/services/util_srv.ts index c543c8c9b38..75d707275d4 100644 --- a/public/app/core/services/util_srv.ts +++ b/public/app/core/services/util_srv.ts @@ -5,7 +5,7 @@ export class UtilSrv { modalScope: any; /** @ngInject */ - constructor(private $rootScope, private $modal) {} + constructor(private $rootScope: any, private $modal: any) {} init() { appEvents.on('show-modal', this.showModal.bind(this), this.$rootScope); @@ -19,7 +19,7 @@ export class UtilSrv { } } - showModal(options) { + showModal(options: any) { if (this.modalScope && this.modalScope.dismiss) { this.modalScope.dismiss(); } @@ -49,10 +49,10 @@ export class UtilSrv { }); } - showConfirmModal(payload) { + showConfirmModal(payload: any) { const scope = this.$rootScope.$new(); - scope.updateConfirmText = value => { + scope.updateConfirmText = (value: any) => { scope.confirmTextValid = payload.confirmText.toLowerCase() === value.toLowerCase(); }; diff --git a/public/app/core/specs/backend_srv.test.ts b/public/app/core/specs/backend_srv.test.ts index f7af6c89e32..28802fb013b 100644 --- a/public/app/core/specs/backend_srv.test.ts +++ b/public/app/core/specs/backend_srv.test.ts @@ -4,7 +4,7 @@ import { ContextSrv } from '../services/context_srv'; jest.mock('app/core/store'); describe('backend_srv', () => { - const _httpBackend = options => { + const _httpBackend = (options: any) => { if (options.url === 'gateway-error') { return Promise.reject({ status: 502 }); } diff --git a/public/app/core/specs/file_export.test.ts b/public/app/core/specs/file_export.test.ts index 49a7b9caf6d..fb2774618fb 100644 --- a/public/app/core/specs/file_export.test.ts +++ b/public/app/core/specs/file_export.test.ts @@ -1,5 +1,6 @@ import * as fileExport from '../utils/file_export'; import { beforeEach, expect } from 'test/lib/common'; +import { TableData } from '@grafana/data'; describe('file_export', () => { const ctx: any = {}; @@ -74,7 +75,7 @@ describe('file_export', () => { describe('when exporting table data to csv', () => { it('should properly escape special characters and quote all string values', () => { - const inputTable = { + const inputTable: any = { columns: [ { title: 'integer_value' }, { text: 'string_value' }, @@ -116,7 +117,7 @@ describe('file_export', () => { }); it('should decode HTML encoded characters', () => { - const inputTable = { + const inputTable: TableData = { columns: [{ text: 'string_value' }], rows: [ ['"&ä'], diff --git a/public/app/core/specs/logs_model.test.ts b/public/app/core/specs/logs_model.test.ts index 49b75d8a8cf..36d05c1ec4c 100644 --- a/public/app/core/specs/logs_model.test.ts +++ b/public/app/core/specs/logs_model.test.ts @@ -330,7 +330,7 @@ describe('LogsParsers', () => { }); }); -const emptyLogsModel = { +const emptyLogsModel: any = { hasUniqueLabels: false, rows: [], meta: [], diff --git a/public/app/core/specs/org_switcher.test.ts b/public/app/core/specs/org_switcher.test.ts index 230da81f191..4f23738860a 100644 --- a/public/app/core/specs/org_switcher.test.ts +++ b/public/app/core/specs/org_switcher.test.ts @@ -1,4 +1,5 @@ import { OrgSwitchCtrl } from '../components/org_switcher'; +// @ts-ignore import q from 'q'; jest.mock('app/core/services/context_srv', () => ({ @@ -15,15 +16,15 @@ jest.mock('app/core/config', () => { describe('OrgSwitcher', () => { describe('when switching org', () => { - let expectedHref; - let expectedUsingUrl; + let expectedHref: string; + let expectedUsingUrl: string; beforeEach(() => { const backendSrvStub: any = { - get: url => { + get: (url: string) => { return q.resolve([]); }, - post: url => { + post: (url: string) => { expectedUsingUrl = url; return q.resolve({}); }, diff --git a/public/app/core/specs/search.test.ts b/public/app/core/specs/search.test.ts index fa60d373e2f..7dd99c1f415 100644 --- a/public/app/core/specs/search.test.ts +++ b/public/app/core/specs/search.test.ts @@ -51,7 +51,7 @@ describe('SearchCtrl', () => { items: [], selected: true, expanded: false, - toggle: i => (i.expanded = !i.expanded), + toggle: (i: any) => (i.expanded = !i.expanded), }, { id: 0, @@ -59,7 +59,7 @@ describe('SearchCtrl', () => { items: [{ id: 3, selected: false }, { id: 5, selected: false }], selected: false, expanded: true, - toggle: i => (i.expanded = !i.expanded), + toggle: (i: any) => (i.expanded = !i.expanded), }, ]; }); @@ -148,7 +148,7 @@ describe('SearchCtrl', () => { items: [{ id: 2, selected: false }, { id: 4, selected: false }], selected: true, expanded: false, - toggle: i => (i.expanded = !i.expanded), + toggle: (i: any) => (i.expanded = !i.expanded), }, { id: 0, @@ -156,7 +156,7 @@ describe('SearchCtrl', () => { items: [{ id: 3, selected: false }, { id: 5, selected: false }], selected: false, expanded: true, - toggle: i => (i.expanded = !i.expanded), + toggle: (i: any) => (i.expanded = !i.expanded), }, ]; }); @@ -252,7 +252,7 @@ describe('SearchCtrl', () => { items: [{ id: 3, selected: true }, { id: 5, selected: false }], selected: false, expanded: true, - toggle: i => (i.expanded = !i.expanded), + toggle: (i: any) => (i.expanded = !i.expanded), }, ]; }); diff --git a/public/app/core/specs/search_results.test.ts b/public/app/core/specs/search_results.test.ts index af0b9d19873..5893f99bbc7 100644 --- a/public/app/core/specs/search_results.test.ts +++ b/public/app/core/specs/search_results.test.ts @@ -9,7 +9,7 @@ jest.mock('app/core/app_events', () => { }); describe('SearchResultsCtrl', () => { - let ctrl; + let ctrl: any; describe('when checking an item that is not checked', () => { const item = { checked: false }; @@ -50,11 +50,11 @@ describe('SearchResultsCtrl', () => { }); describe('when selecting a tag', () => { - let selectedTag = null; + let selectedTag: any = null; beforeEach(() => { ctrl = new SearchResultsCtrl({}); - ctrl.onTagSelected = tag => (selectedTag = tag); + ctrl.onTagSelected = (tag: any) => (selectedTag = tag); ctrl.selectTag('tag-test'); }); diff --git a/public/app/core/specs/table_model.test.ts b/public/app/core/specs/table_model.test.ts index 19b2a7543fb..cc5e01fbf15 100644 --- a/public/app/core/specs/table_model.test.ts +++ b/public/app/core/specs/table_model.test.ts @@ -1,13 +1,14 @@ import TableModel, { mergeTablesIntoModel } from 'app/core/table_model'; describe('when sorting table desc', () => { - let table; + let table: TableModel; const panel = { sort: { col: 0, desc: true }, }; beforeEach(() => { table = new TableModel(); + // @ts-ignore table.columns = [{}, {}]; table.rows = [[100, 12], [105, 10], [103, 11]]; table.sort(panel.sort); @@ -26,13 +27,14 @@ describe('when sorting table desc', () => { }); describe('when sorting table asc', () => { - let table; + let table: TableModel; const panel = { sort: { col: 1, desc: false }, }; beforeEach(() => { table = new TableModel(); + // @ts-ignore table.columns = [{}, {}]; table.rows = [[100, 11], [105, 15], [103, 10]]; table.sort(panel.sort); @@ -46,11 +48,12 @@ describe('when sorting table asc', () => { }); describe('when sorting with nulls', () => { - let table; + let table: TableModel; let values; beforeEach(() => { table = new TableModel(); + // @ts-ignore table.columns = [{}, {}]; table.rows = [[42, ''], [19, 'a'], [null, 'b'], [0, 'd'], [null, null], [2, 'c'], [0, null], [-8, '']]; }); diff --git a/public/app/core/specs/time_series.test.ts b/public/app/core/specs/time_series.test.ts index 6cf7399c059..e2f91f27c44 100644 --- a/public/app/core/specs/time_series.test.ts +++ b/public/app/core/specs/time_series.test.ts @@ -2,9 +2,9 @@ import TimeSeries from 'app/core/time_series2'; import { updateLegendValues } from 'app/core/time_series2'; describe('TimeSeries', () => { - let points, series; + let points, series: any; const yAxisFormats = ['short', 'ms']; - let testData; + let testData: { alias?: string; datapoints: any }; beforeEach(() => { testData = { @@ -174,7 +174,7 @@ describe('TimeSeries', () => { }); describe('can detect if series contains ms precision', () => { - let fakedata; + let fakedata: any; beforeEach(() => { fakedata = testData; @@ -194,7 +194,7 @@ describe('TimeSeries', () => { }); describe('series overrides', () => { - let series; + let series: any; beforeEach(() => { series = new TimeSeries(testData); }); @@ -313,7 +313,7 @@ describe('TimeSeries', () => { }); describe('value formatter', () => { - let series; + let series: any; beforeEach(() => { series = new TimeSeries(testData); }); @@ -328,7 +328,7 @@ describe('TimeSeries', () => { }); describe('legend decimals', () => { - let series, panel; + let series: any, panel: any; const height = 200; beforeEach(() => { testData = { diff --git a/public/app/core/specs/value_select_dropdown.test.ts b/public/app/core/specs/value_select_dropdown.test.ts index 024774250b8..98f2467306b 100644 --- a/public/app/core/specs/value_select_dropdown.test.ts +++ b/public/app/core/specs/value_select_dropdown.test.ts @@ -1,19 +1,20 @@ import 'app/core/directives/value_select_dropdown'; import { ValueSelectDropdownCtrl } from '../directives/value_select_dropdown'; +// @ts-ignore import q from 'q'; describe('SelectDropdownCtrl', () => { const tagValuesMap: any = {}; ValueSelectDropdownCtrl.prototype.onUpdated = jest.fn(); - let ctrl; + let ctrl: ValueSelectDropdownCtrl; describe('Given simple variable', () => { beforeEach(() => { ctrl = new ValueSelectDropdownCtrl(q); ctrl.variable = { current: { text: 'hej', value: 'hej' }, - getValuesForTag: key => { + getValuesForTag: (key: string) => { return Promise.resolve(tagValuesMap[key]); }, }; @@ -36,7 +37,7 @@ describe('SelectDropdownCtrl', () => { { text: 'server-3', value: 'server-3' }, ], tags: ['key1', 'key2', 'key3'], - getValuesForTag: key => { + getValuesForTag: (key: string) => { return Promise.resolve(tagValuesMap[key]); }, multi: true, @@ -143,7 +144,7 @@ describe('SelectDropdownCtrl', () => { { text: 'server-3', value: 'server-3' }, ], tags: ['key1', 'key2', 'key3'], - getValuesForTag: key => { + getValuesForTag: (key: any) => { return Promise.resolve(tagValuesMap[key]); }, multi: true, diff --git a/public/app/core/utils/connectWithReduxStore.tsx b/public/app/core/utils/connectWithReduxStore.tsx index 19493681c0d..2140b294829 100644 --- a/public/app/core/utils/connectWithReduxStore.tsx +++ b/public/app/core/utils/connectWithReduxStore.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { connect } from 'react-redux'; import { store } from '../../store/store'; -export function connectWithStore(WrappedComponent, ...args) { +export function connectWithStore(WrappedComponent: any, ...args: any[]) { const ConnectedWrappedComponent = (connect as any)(...args)(WrappedComponent); - return props => { + return (props: any) => { return ; }; } diff --git a/public/app/core/utils/css_loader.ts b/public/app/core/utils/css_loader.ts index b4c26293bb8..31f34b91261 100644 --- a/public/app/core/utils/css_loader.ts +++ b/public/app/core/utils/css_loader.ts @@ -3,13 +3,13 @@ const head = document.getElementsByTagName('head')[0]; // get all link tags in the page const links = document.getElementsByTagName('link'); -const linkHrefs = []; +const linkHrefs: string[] = []; for (let i = 0; i < links.length; i++) { linkHrefs.push(links[i].href); } const isWebkit = !!window.navigator.userAgent.match(/AppleWebKit\/([^ ;]*)/); -const webkitLoadCheck = (link, callback) => { +const webkitLoadCheck = (link: HTMLLinkElement, callback: Function) => { setTimeout(() => { for (let i = 0; i < document.styleSheets.length; i++) { const sheet = document.styleSheets[i]; @@ -23,14 +23,14 @@ const webkitLoadCheck = (link, callback) => { const noop = () => {}; -const loadCSS = url => { +const loadCSS = (url: string) => { return new Promise((resolve, reject) => { const link = document.createElement('link'); const timeout = setTimeout(() => { reject('Unable to load CSS'); }, waitSeconds * 1000); - const _callback = error => { + const _callback = (error: any) => { clearTimeout(timeout); link.onload = link.onerror = noop; setTimeout(() => { @@ -62,7 +62,7 @@ const loadCSS = url => { }); }; -export function fetch(load): any { +export function fetch(load: any): any { if (typeof window === 'undefined') { return ''; } diff --git a/public/app/core/utils/dag.ts b/public/app/core/utils/dag.ts index 48c00a4c8c3..c222077ac9a 100644 --- a/public/app/core/utils/dag.ts +++ b/public/app/core/utils/dag.ts @@ -2,7 +2,7 @@ export class Edge { inputNode: Node; outputNode: Node; - _linkTo(node, direction) { + _linkTo(node: Node, direction: number) { if (direction <= 0) { node.inputEdges.push(this); } @@ -104,7 +104,7 @@ export class Node { } getOptimizedInputEdges(): Edge[] { - const toBeRemoved = []; + const toBeRemoved: any[] = []; this.inputEdges.forEach(e => { const inputEdgesNodes = e.inputNode.inputEdges.map(e => e.inputNode); @@ -121,7 +121,7 @@ export class Node { } export class Graph { - nodes = {}; + nodes: any = {}; constructor() {} @@ -132,7 +132,7 @@ export class Graph { } createNodes(names: string[]): Node[] { - const nodes = []; + const nodes: Node[] = []; names.forEach(name => { nodes.push(this.createNode(name)); }); @@ -142,8 +142,8 @@ export class Graph { link(input: string | string[] | Node | Node[], output: string | string[] | Node | Node[]): Edge[] { let inputArr = []; let outputArr = []; - const inputNodes = []; - const outputNodes = []; + const inputNodes: Node[] = []; + const outputNodes: Node[] = []; if (input instanceof Array) { inputArr = input; @@ -183,7 +183,7 @@ export class Graph { } } - const edges = []; + const edges: Edge[] = []; inputNodes.forEach(input => { outputNodes.forEach(output => { edges.push(this.createEdge().link(input, output)); @@ -204,11 +204,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 => e.outputNode.name).join(', '); + let outputEdges = n.outputEdges.map((e: Edge) => e.outputNode.name).join(', '); if (!outputEdges) { outputEdges = ''; } - let inputEdges = n.inputEdges.map(e => 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/emitter.ts b/public/app/core/utils/emitter.ts index 95258e7552e..9495900b4ce 100644 --- a/public/app/core/utils/emitter.ts +++ b/public/app/core/utils/emitter.ts @@ -7,11 +7,11 @@ export class Emitter { this.emitter = new EventEmitter(); } - emit(name, data?) { + emit(name: string, data?: any) { this.emitter.emit(name, data); } - on(name, handler, scope?) { + on(name: string, handler: (payload?: any) => void, scope?: any) { this.emitter.on(name, handler); if (scope) { @@ -22,11 +22,11 @@ export class Emitter { } } - removeAllListeners(evt?) { + removeAllListeners(evt?: string) { this.emitter.removeAllListeners(evt); } - off(name, handler) { + off(name: string, handler: (payload?: any) => void) { this.emitter.off(name, handler); } diff --git a/public/app/core/utils/errors.test.ts b/public/app/core/utils/errors.test.ts index a5783fe7204..b46841aefc0 100644 --- a/public/app/core/utils/errors.test.ts +++ b/public/app/core/utils/errors.test.ts @@ -1,7 +1,7 @@ import { getMessageFromError } from 'app/core/utils/errors'; describe('errors functions', () => { - let message; + let message: string; describe('when getMessageFromError gets an error string', () => { beforeEach(() => { diff --git a/public/app/core/utils/explore.test.ts b/public/app/core/utils/explore.test.ts index bb93b2a8815..528a464131c 100644 --- a/public/app/core/utils/explore.test.ts +++ b/public/app/core/utils/explore.test.ts @@ -223,7 +223,7 @@ describe('instanceOfDataQueryError', () => { describe('hasRefId', () => { describe('when called with a null value', () => { it('then it should return null', () => { - const input = null; + const input: any = null; const result = getValueWithRefId(input); expect(result).toBeNull(); @@ -304,7 +304,7 @@ describe('getFirstQueryErrorWithoutRefId', () => { describe('getRefIds', () => { describe('when called with a null value', () => { it('then it should return empty array', () => { - const input = null; + const input: any = null; const result = getRefIds(input); expect(result).toEqual([]); diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 627a9e3d844..408eeac4c1d 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -80,7 +80,7 @@ export async function getExploreUrl( // Mixed datasources need to choose only one datasource if (panelDatasource.meta.id === 'mixed' && panelTargets) { // Find first explore datasource among targets - let mixedExploreDatasource; + let mixedExploreDatasource: any; for (const t of panel.targets) { const datasource = await datasourceSrv.get(t.datasource); if (datasource && datasource.meta.explore) { @@ -210,7 +210,7 @@ export const safeStringifyValue = (value: any, space?: number) => { export function parseUrlState(initial: string | undefined): ExploreUrlState { const parsed = safeParseJson(initial); - const errorResult = { + const errorResult: any = { datasource: null, queries: [], range: DEFAULT_RANGE, @@ -323,7 +323,7 @@ const validKeys = ['refId', 'key', 'context']; export function hasNonEmptyQuery(queries: TQuery[]): boolean { return ( queries && - queries.some(query => { + queries.some((query: any) => { const keys = Object.keys(query) .filter(key => validKeys.indexOf(key) === -1) .map(k => query[k]) @@ -386,7 +386,7 @@ export const getTimeRange = (timeZone: TimeZone, rawRange: RawTimeRange): TimeRa }; }; -const parseRawTime = (value): TimeFragment => { +const parseRawTime = (value: any): TimeFragment => { if (value === null) { return null; } diff --git a/public/app/core/utils/file_export.ts b/public/app/core/utils/file_export.ts index 14fc10cfbb6..6ffdc8b40be 100644 --- a/public/app/core/utils/file_export.ts +++ b/public/app/core/utils/file_export.ts @@ -1,7 +1,7 @@ import { isBoolean, isNumber, sortedUniq, sortedIndexOf, unescape as htmlUnescaped } from 'lodash'; import { saveAs } from 'file-saver'; import { isNullOrUndefined } from 'util'; -import { dateTime, TimeZone } from '@grafana/data'; +import { dateTime, TimeZone, TableData } from '@grafana/data'; const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ'; const POINT_TIME_INDEX = 1; @@ -18,6 +18,11 @@ interface SeriesListToCsvColumnsOptions { timezone: TimeZone; } +type SeriesList = Array<{ + datapoints: any; + alias: any; +}>; + const defaultOptions: SeriesListToCsvColumnsOptions = { dateTimeFormat: DEFAULT_DATETIME_FORMAT, excel: false, @@ -50,11 +55,11 @@ function htmlDecoded(text: string) { return text.replace(regexp, htmlDecoded).replace(regexp, htmlDecoded); } -function formatSpecialHeader(useExcelHeader) { +function formatSpecialHeader(useExcelHeader: boolean) { return useExcelHeader ? `sep=${END_COLUMN}${END_ROW}` : ''; } -function formatRow(row, addEndRowDelimiter = true) { +function formatRow(row: any[], addEndRowDelimiter = true) { let text = ''; for (let i = 0; i < row.length; i += 1) { if (isBoolean(row[i]) || isNumber(row[i]) || isNullOrUndefined(row[i])) { @@ -70,7 +75,7 @@ function formatRow(row, addEndRowDelimiter = true) { return addEndRowDelimiter ? text + END_ROW : text; } -export function convertSeriesListToCsv(seriesList, options: Partial) { +export function convertSeriesListToCsv(seriesList: SeriesList, options: Partial) { const { dateTimeFormat, excel, timezone } = { ...defaultOptions, ...options }; let text = formatSpecialHeader(excel) + formatRow(['Series', 'Time', 'Value']); for (let seriesIndex = 0; seriesIndex < seriesList.length; seriesIndex += 1) { @@ -92,12 +97,12 @@ export function convertSeriesListToCsv(seriesList, options: Partial) { +export function exportSeriesListToCsv(seriesList: SeriesList, options: Partial) { const text = convertSeriesListToCsv(seriesList, options); saveSaveBlob(text, EXPORT_FILENAME); } -export function convertSeriesListToCsvColumns(seriesList, options: Partial) { +export function convertSeriesListToCsvColumns(seriesList: SeriesList, options: Partial) { const { dateTimeFormat, excel, timezone } = { ...defaultOptions, ...options }; // add header let text = @@ -138,7 +143,7 @@ export function convertSeriesListToCsvColumns(seriesList, options: Partial p[POINT_TIME_INDEX]); + const seriesTimestamps = seriesPoints.map((p: any) => p[POINT_TIME_INDEX]); const extendedDatapoints = []; for (let j = 0; j < timestamps.length; j++) { const timestamp = timestamps[j]; @@ -167,15 +172,15 @@ function mergeSeriesByTime(seriesList) { return result; } -export function exportSeriesListToCsvColumns(seriesList, options: Partial) { +export function exportSeriesListToCsvColumns(seriesList: SeriesList, options: Partial) { const text = convertSeriesListToCsvColumns(seriesList, options); saveSaveBlob(text, EXPORT_FILENAME); } -export function convertTableDataToCsv(table, excel = false) { +export function convertTableDataToCsv(table: TableData, excel = false) { let text = formatSpecialHeader(excel); // add headline - text += formatRow(table.columns.map(val => val.title || val.text)); + text += formatRow(table.columns.map((val: any) => val.title || val.text)); // process data for (let i = 0; i < table.rows.length; i += 1) { text += formatRow(table.rows[i], i < table.rows.length - 1); @@ -183,12 +188,12 @@ export function convertTableDataToCsv(table, excel = false) { return text; } -export function exportTableDataToCsv(table, excel = false) { +export function exportTableDataToCsv(table: TableData, excel = false) { const text = convertTableDataToCsv(table, excel); saveSaveBlob(text, EXPORT_FILENAME); } -export function saveSaveBlob(payload, fname) { +export function saveSaveBlob(payload: any, fname: string) { const blob = new Blob([payload], { type: 'text/csv;charset=utf-8;header=present;' }); saveAs(blob, fname); } diff --git a/public/app/core/utils/flatten.ts b/public/app/core/utils/flatten.ts index 38601f463aa..c042223eb5d 100644 --- a/public/app/core/utils/flatten.ts +++ b/public/app/core/utils/flatten.ts @@ -1,15 +1,15 @@ // Copyright (c) 2014, Hugh Kennedy // Based on code from https://github.com/hughsk/flat/blob/master/index.js // -export default function flatten(target, opts): any { +export default function flatten(target: object, opts: { delimiter?: any; maxDepth?: any; safe?: any }): any { opts = opts || {}; const delimiter = opts.delimiter || '.'; let maxDepth = opts.maxDepth || 3; let currentDepth = 1; - const output = {}; + const output: any = {}; - function step(object, prev) { + function step(object: any, prev: string) { Object.keys(object).forEach(key => { const value = object[key]; const isarray = opts.safe && Array.isArray(value); diff --git a/public/app/core/utils/kbn.ts b/public/app/core/utils/kbn.ts index 02807d21720..6a0e9e21773 100644 --- a/public/app/core/utils/kbn.ts +++ b/public/app/core/utils/kbn.ts @@ -1,18 +1,18 @@ import { has } from 'lodash'; import { getValueFormat, getValueFormatterIndex, getValueFormats, deprecationWarning } from '@grafana/ui'; -import { stringToJsRegex } from '@grafana/data'; +import { stringToJsRegex, TimeRange } from '@grafana/data'; const kbn: any = {}; kbn.valueFormats = {}; -kbn.regexEscape = value => { +kbn.regexEscape = (value: string) => { return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&'); }; ///// HELPER FUNCTIONS ///// -kbn.round_interval = interval => { +kbn.round_interval = (interval: number) => { switch (true) { // 0.015s case interval < 15: @@ -103,7 +103,7 @@ kbn.round_interval = interval => { } }; -kbn.secondsToHms = seconds => { +kbn.secondsToHms = (seconds: number) => { const numyears = Math.floor(seconds / 31536000); if (numyears) { return numyears + 'y'; @@ -132,7 +132,7 @@ kbn.secondsToHms = seconds => { return 'less than a millisecond'; //'just now' //or other string you like; }; -kbn.secondsToHhmmss = seconds => { +kbn.secondsToHhmmss = (seconds: number) => { const strings: string[] = []; const numhours = Math.floor(seconds / 3600); const numminutes = Math.floor((seconds % 3600) / 60); @@ -143,11 +143,11 @@ kbn.secondsToHhmmss = seconds => { return strings.join(':'); }; -kbn.to_percent = (nr, outof) => { +kbn.to_percent = (nr: number, outof: number) => { return Math.floor((nr / outof) * 10000) / 100 + '%'; }; -kbn.addslashes = str => { +kbn.addslashes = (str: string) => { str = str.replace(/\\/g, '\\\\'); str = str.replace(/\'/g, "\\'"); str = str.replace(/\"/g, '\\"'); @@ -169,7 +169,7 @@ kbn.intervals_in_seconds = { ms: 0.001, }; -kbn.calculateInterval = (range, resolution, lowLimitInterval) => { +kbn.calculateInterval = (range: TimeRange, resolution: number, lowLimitInterval: string[]) => { let lowLimitMs = 1; // 1 millisecond default low limit let intervalMs; @@ -191,7 +191,7 @@ kbn.calculateInterval = (range, resolution, lowLimitInterval) => { }; }; -kbn.describe_interval = str => { +kbn.describe_interval = (str: string) => { const matches = str.match(kbn.interval_regex); if (!matches || !has(kbn.intervals_in_seconds, matches[2])) { throw new Error('Invalid interval string, expecting a number followed by one of "Mwdhmsy"'); @@ -204,17 +204,17 @@ kbn.describe_interval = str => { } }; -kbn.interval_to_ms = str => { +kbn.interval_to_ms = (str: string) => { const info = kbn.describe_interval(str); return info.sec * 1000 * info.count; }; -kbn.interval_to_seconds = str => { +kbn.interval_to_seconds = (str: string) => { const info = kbn.describe_interval(str); return info.sec * info.count; }; -kbn.query_color_dot = (color, diameter) => { +kbn.query_color_dot = (color: string, diameter: string) => { return ( '