Browse Source

Chore: noImplicitAny Sub 500 errors (#18287)

Tobias Skarhed 6 years ago
parent
commit
7891233812
74 changed files with 351 additions and 254 deletions
  1. 4 1
      package.json
  2. 11 9
      public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts
  3. 13 9
      public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.test.ts
  4. 6 4
      public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.ts
  5. 4 4
      public/app/features/dashboard/components/SaveModals/SaveDashboardModalCtrl.test.ts
  6. 6 5
      public/app/features/dashboard/components/SaveModals/SaveDashboardModalCtrl.ts
  7. 1 1
      public/app/features/dashboard/components/SaveModals/SaveProvisionedDashboardModalCtrl.test.ts
  8. 2 1
      public/app/features/dashboard/components/SaveModals/SaveProvisionedDashboardModalCtrl.ts
  9. 2 2
      public/app/features/dashboard/components/ShareModal/ShareModalCtrl.test.ts
  10. 13 2
      public/app/features/dashboard/components/ShareModal/ShareModalCtrl.ts
  11. 19 8
      public/app/features/dashboard/components/ShareModal/ShareSnapshotCtrl.ts
  12. 5 4
      public/app/features/dashboard/components/SubMenu/SubMenuCtrl.ts
  13. 1 1
      public/app/features/dashboard/components/UnsavedChangesModal/UnsavedChangesModalCtrl.ts
  14. 12 11
      public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.test.ts
  15. 16 13
      public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.ts
  16. 5 5
      public/app/features/dashboard/components/VersionHistory/HistorySrv.test.ts
  17. 2 1
      public/app/features/dashboard/components/VersionHistory/HistorySrv.ts
  18. 2 2
      public/app/features/dashboard/components/VersionHistory/__mocks__/history.ts
  19. 1 1
      public/app/features/dashboard/containers/DashboardPage.test.tsx
  20. 1 1
      public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx
  21. 1 0
      public/app/features/dashboard/dashgrid/DashboardGrid.tsx
  22. 1 1
      public/app/features/dashboard/dashgrid/DashboardPanel.tsx
  23. 1 1
      public/app/features/dashboard/dashgrid/PanelResizer.tsx
  24. 4 4
      public/app/features/dashboard/panel_editor/EditorTabBody.tsx
  25. 1 1
      public/app/features/dashboard/panel_editor/GeneralTab.tsx
  26. 3 3
      public/app/features/dashboard/panel_editor/QueriesTab.tsx
  27. 4 4
      public/app/features/dashboard/panel_editor/QueryInspector.tsx
  28. 6 4
      public/app/features/dashboard/panel_editor/QueryOptions.tsx
  29. 2 2
      public/app/features/dashboard/services/ChangeTracker.test.ts
  30. 12 11
      public/app/features/dashboard/services/ChangeTracker.ts
  31. 24 20
      public/app/features/dashboard/services/DashboardLoaderSrv.ts
  32. 14 8
      public/app/features/dashboard/services/DashboardSrv.ts
  33. 1 1
      public/app/features/dashboard/services/TimeSrv.test.ts
  34. 14 3
      public/app/features/dashboard/services/UnsavedChangesSrv.ts
  35. 9 8
      public/app/features/dashboard/state/DashboardMigrator.test.ts
  36. 17 17
      public/app/features/dashboard/state/DashboardMigrator.ts
  37. 6 6
      public/app/features/dashboard/state/DashboardModel.repeat.test.ts
  38. 2 2
      public/app/features/dashboard/state/PanelModel.test.ts
  39. 1 1
      public/app/features/dashboard/state/PanelQueryState.test.ts
  40. 1 1
      public/app/features/dashboard/state/PanelQueryState.ts
  41. 1 1
      public/app/features/dashboard/state/actions.ts
  42. 1 1
      public/app/features/dashboard/state/initDashboard.test.ts
  43. 2 2
      public/app/features/datasources/DataSourceDashboards.tsx
  44. 2 2
      public/app/features/datasources/__mocks__/dataSourcesMocks.ts
  45. 12 10
      public/app/features/datasources/state/selectors.ts
  46. 1 1
      public/app/features/explore/AdHocFilterField.tsx
  47. 4 4
      public/app/features/explore/ErrorBoundary.tsx
  48. 1 1
      public/app/features/explore/ExploreToolbar.tsx
  49. 5 5
      public/app/features/explore/Graph.tsx
  50. 2 1
      public/app/features/explore/GraphContainer.tsx
  51. 1 1
      public/app/features/explore/JSONViewer.tsx
  52. 1 1
      public/app/features/explore/LogLabel.tsx
  53. 2 1
      public/app/features/explore/LogMessageAnsi.tsx
  54. 3 2
      public/app/features/explore/Logs.tsx
  55. 3 2
      public/app/features/explore/LogsContainer.tsx
  56. 1 0
      public/app/features/explore/QueryRow.tsx
  57. 1 1
      public/app/features/explore/QueryStatus.tsx
  58. 4 4
      public/app/features/explore/Table.tsx
  59. 2 1
      public/app/features/explore/TableContainer.tsx
  60. 1 0
      public/app/features/explore/slate-plugins/braces.test.ts
  61. 2 2
      public/app/features/explore/slate-plugins/braces.ts
  62. 1 0
      public/app/features/explore/slate-plugins/clear.test.ts
  63. 1 1
      public/app/features/explore/slate-plugins/clear.ts
  64. 2 2
      public/app/features/explore/slate-plugins/newline.ts
  65. 6 6
      public/app/features/explore/slate-plugins/prism/index.tsx
  66. 2 2
      public/app/features/explore/slate-plugins/runner.ts
  67. 6 6
      public/app/features/explore/state/epics/processQueryResultsEpic.test.ts
  68. 4 4
      public/app/features/explore/state/epics/runQueriesBatchEpic.test.ts
  69. 1 1
      public/app/features/explore/state/epics/runQueriesEpic.test.ts
  70. 1 1
      public/app/features/explore/state/epics/timeEpic.ts
  71. 2 2
      public/app/features/explore/state/reducers.test.ts
  72. 1 1
      public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts
  73. 1 1
      scripts/ci-frontend-metrics.sh
  74. 21 1
      yarn.lock

+ 4 - 1
package.json

@@ -175,11 +175,14 @@
     "@types/angular-route": "1.7.0",
     "@types/angular-route": "1.7.0",
     "@types/d3-scale-chromatic": "1.3.1",
     "@types/d3-scale-chromatic": "1.3.1",
     "@types/enzyme-adapter-react-16": "1.0.5",
     "@types/enzyme-adapter-react-16": "1.0.5",
+    "@types/file-saver": "2.0.1",
     "@types/marked": "0.6.5",
     "@types/marked": "0.6.5",
     "@types/prismjs": "1.16.0",
     "@types/prismjs": "1.16.0",
-    "@types/react-redux": "^7.0.8",
+    "@types/react-redux": "7.0.8",
+    "@types/react-table": "6.8.5",
     "@types/react-test-renderer": "16.8.2",
     "@types/react-test-renderer": "16.8.2",
     "@types/redux-logger": "3.0.7",
     "@types/redux-logger": "3.0.7",
+    "@types/redux-mock-store": "1.0.1",
     "@types/reselect": "2.2.0",
     "@types/reselect": "2.2.0",
     "@types/slate": "0.44.11",
     "@types/slate": "0.44.11",
     "@types/tinycolor2": "1.4.2",
     "@types/tinycolor2": "1.4.2",

+ 11 - 9
public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts

@@ -2,8 +2,10 @@ import { coreModule, appEvents, contextSrv } from 'app/core/core';
 import { DashboardModel } from '../../state/DashboardModel';
 import { DashboardModel } from '../../state/DashboardModel';
 import $ from 'jquery';
 import $ from 'jquery';
 import _ from 'lodash';
 import _ from 'lodash';
-import angular from 'angular';
+import angular, { ILocationService } from 'angular';
 import config from 'app/core/config';
 import config from 'app/core/config';
+import { BackendSrv } from 'app/core/services/backend_srv';
+import { DashboardSrv } from '../../services/DashboardSrv';
 
 
 export class SettingsCtrl {
 export class SettingsCtrl {
   dashboard: DashboardModel;
   dashboard: DashboardModel;
@@ -19,12 +21,12 @@ export class SettingsCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(
   constructor(
-    private $scope,
-    private $route,
-    private $location,
-    private $rootScope,
-    private backendSrv,
-    private dashboardSrv
+    private $scope: any,
+    private $route: any,
+    private $location: ILocationService,
+    private $rootScope: any,
+    private backendSrv: BackendSrv,
+    private dashboardSrv: DashboardSrv
   ) {
   ) {
     // temp hack for annotations and variables editors
     // temp hack for annotations and variables editors
     // that rely on inherited scope
     // that rely on inherited scope
@@ -226,13 +228,13 @@ export class SettingsCtrl {
   }
   }
 
 
   deleteDashboardConfirmed() {
   deleteDashboardConfirmed() {
-    this.backendSrv.deleteDashboard(this.dashboard.uid).then(() => {
+    this.backendSrv.deleteDashboard(this.dashboard.uid, false).then(() => {
       appEvents.emit('alert-success', ['Dashboard Deleted', this.dashboard.title + ' has been deleted']);
       appEvents.emit('alert-success', ['Dashboard Deleted', this.dashboard.title + ' has been deleted']);
       this.$location.url('/');
       this.$location.url('/');
     });
     });
   }
   }
 
 
-  onFolderChange(folder) {
+  onFolderChange(folder: { id: number; title: string }) {
     this.dashboard.meta.folderId = folder.id;
     this.dashboard.meta.folderId = folder.id;
     this.dashboard.meta.folderTitle = folder.title;
     this.dashboard.meta.folderTitle = folder.title;
     this.hasUnsavedFolderChange = true;
     this.hasUnsavedFolderChange = true;

+ 13 - 9
public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.test.ts

@@ -2,14 +2,14 @@ import { SaveDashboardAsModalCtrl } from './SaveDashboardAsModalCtrl';
 import { describe, it, expect } from 'test/lib/common';
 import { describe, it, expect } from 'test/lib/common';
 
 
 describe('saving dashboard as', () => {
 describe('saving dashboard as', () => {
-  function scenario(name, panel, verify) {
+  function scenario(name: string, panel: any, verify: Function) {
     describe(name, () => {
     describe(name, () => {
       const json = {
       const json = {
         title: 'name',
         title: 'name',
         panels: [panel],
         panels: [panel],
       };
       };
 
 
-      const mockDashboardSrv = {
+      const mockDashboardSrv: any = {
         getCurrent: () => {
         getCurrent: () => {
           return {
           return {
             id: 5,
             id: 5,
@@ -34,7 +34,7 @@ describe('saving dashboard as', () => {
     });
     });
   }
   }
 
 
-  scenario('default values', {}, ctx => {
+  scenario('default values', {}, (ctx: any) => {
     const clone = ctx.clone;
     const clone = ctx.clone;
     expect(clone.id).toBe(null);
     expect(clone.id).toBe(null);
     expect(clone.title).toBe('name Copy');
     expect(clone.title).toBe('name Copy');
@@ -49,19 +49,23 @@ describe('saving dashboard as', () => {
     thresholds: { value: 3000 },
     thresholds: { value: 3000 },
   };
   };
 
 
-  scenario('should remove alert from graph panel', graphPanel, ctx => {
+  scenario('should remove alert from graph panel', graphPanel, (ctx: any) => {
     expect(ctx.panel.alert).toBe(undefined);
     expect(ctx.panel.alert).toBe(undefined);
   });
   });
 
 
-  scenario('should remove threshold from graph panel', graphPanel, ctx => {
+  scenario('should remove threshold from graph panel', graphPanel, (ctx: any) => {
     expect(ctx.panel.thresholds).toBe(undefined);
     expect(ctx.panel.thresholds).toBe(undefined);
   });
   });
 
 
-  scenario('singlestat should keep threshold', { id: 1, type: 'singlestat', thresholds: { value: 3000 } }, ctx => {
-    expect(ctx.panel.thresholds).not.toBe(undefined);
-  });
+  scenario(
+    'singlestat should keep threshold',
+    { id: 1, type: 'singlestat', thresholds: { value: 3000 } },
+    (ctx: any) => {
+      expect(ctx.panel.thresholds).not.toBe(undefined);
+    }
+  );
 
 
-  scenario('table should keep threshold', { id: 1, type: 'table', thresholds: { value: 3000 } }, ctx => {
+  scenario('table should keep threshold', { id: 1, type: 'table', thresholds: { value: 3000 } }, (ctx: any) => {
     expect(ctx.panel.thresholds).not.toBe(undefined);
     expect(ctx.panel.thresholds).not.toBe(undefined);
   });
   });
 });
 });

+ 6 - 4
public/app/features/dashboard/components/SaveModals/SaveDashboardAsModalCtrl.ts

@@ -1,4 +1,6 @@
 import coreModule from 'app/core/core_module';
 import coreModule from 'app/core/core_module';
+import { DashboardSrv } from '../../services/DashboardSrv';
+import { PanelModel } from '../../state/PanelModel';
 
 
 const template = `
 const template = `
 <div class="modal-body">
 <div class="modal-body">
@@ -56,7 +58,7 @@ export class SaveDashboardAsModalCtrl {
   copyTags: boolean;
   copyTags: boolean;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private dashboardSrv) {
+  constructor(private dashboardSrv: DashboardSrv) {
     const dashboard = this.dashboardSrv.getCurrent();
     const dashboard = this.dashboardSrv.getCurrent();
     this.clone = dashboard.getSaveModelClone();
     this.clone = dashboard.getSaveModelClone();
     this.clone.id = null;
     this.clone.id = null;
@@ -70,7 +72,7 @@ export class SaveDashboardAsModalCtrl {
     // remove alerts if source dashboard is already persisted
     // remove alerts if source dashboard is already persisted
     // do not want to create alert dupes
     // do not want to create alert dupes
     if (dashboard.id > 0) {
     if (dashboard.id > 0) {
-      this.clone.panels.forEach(panel => {
+      this.clone.panels.forEach((panel: PanelModel) => {
         if (panel.type === 'graph' && panel.alert) {
         if (panel.type === 'graph' && panel.alert) {
           delete panel.thresholds;
           delete panel.thresholds;
         }
         }
@@ -89,13 +91,13 @@ export class SaveDashboardAsModalCtrl {
     return this.dashboardSrv.save(this.clone, { folderId: this.folderId }).then(this.dismiss);
     return this.dashboardSrv.save(this.clone, { folderId: this.folderId }).then(this.dismiss);
   }
   }
 
 
-  keyDown(evt) {
+  keyDown(evt: KeyboardEvent) {
     if (evt.keyCode === 13) {
     if (evt.keyCode === 13) {
       this.save();
       this.save();
     }
     }
   }
   }
 
 
-  onFolderChange(folder) {
+  onFolderChange(folder: { id: any }) {
     this.folderId = folder.id;
     this.folderId = folder.id;
   }
   }
 
 

+ 4 - 4
public/app/features/dashboard/components/SaveModals/SaveDashboardModalCtrl.test.ts

@@ -1,6 +1,6 @@
 import { SaveDashboardModalCtrl } from './SaveDashboardModalCtrl';
 import { SaveDashboardModalCtrl } from './SaveDashboardModalCtrl';
 
 
-const setup = (timeChanged, variableValuesChanged, cb) => {
+const setup = (timeChanged: boolean, variableValuesChanged: boolean, cb: Function) => {
   const dash = {
   const dash = {
     hasTimeChanged: jest.fn().mockReturnValue(timeChanged),
     hasTimeChanged: jest.fn().mockReturnValue(timeChanged),
     hasVariableValuesChanged: jest.fn().mockReturnValue(variableValuesChanged),
     hasVariableValuesChanged: jest.fn().mockReturnValue(variableValuesChanged),
@@ -8,7 +8,7 @@ const setup = (timeChanged, variableValuesChanged, cb) => {
     resetOriginalVariables: jest.fn(),
     resetOriginalVariables: jest.fn(),
     getSaveModelClone: jest.fn().mockReturnValue({}),
     getSaveModelClone: jest.fn().mockReturnValue({}),
   };
   };
-  const dashboardSrvMock = {
+  const dashboardSrvMock: any = {
     getCurrent: jest.fn().mockReturnValue(dash),
     getCurrent: jest.fn().mockReturnValue(dash),
     save: jest.fn().mockReturnValue(Promise.resolve()),
     save: jest.fn().mockReturnValue(Promise.resolve()),
   };
   };
@@ -22,7 +22,7 @@ const setup = (timeChanged, variableValuesChanged, cb) => {
 
 
 describe('SaveDashboardModal', () => {
 describe('SaveDashboardModal', () => {
   describe('Given time and template variable values have not changed', () => {
   describe('Given time and template variable values have not changed', () => {
-    setup(false, false, (dash, ctrl: SaveDashboardModalCtrl) => {
+    setup(false, false, (dash: any, ctrl: SaveDashboardModalCtrl) => {
       it('When creating ctrl should set time and template variable values changed', () => {
       it('When creating ctrl should set time and template variable values changed', () => {
         expect(ctrl.timeChange).toBeFalsy();
         expect(ctrl.timeChange).toBeFalsy();
         expect(ctrl.variableValueChange).toBeFalsy();
         expect(ctrl.variableValueChange).toBeFalsy();
@@ -31,7 +31,7 @@ describe('SaveDashboardModal', () => {
   });
   });
 
 
   describe('Given time and template variable values have changed', () => {
   describe('Given time and template variable values have changed', () => {
-    setup(true, true, (dash, ctrl: SaveDashboardModalCtrl) => {
+    setup(true, true, (dash: any, ctrl: SaveDashboardModalCtrl) => {
       it('When creating ctrl should set time and template variable values changed', () => {
       it('When creating ctrl should set time and template variable values changed', () => {
         expect(ctrl.timeChange).toBeTruthy();
         expect(ctrl.timeChange).toBeTruthy();
         expect(ctrl.variableValueChange).toBeTruthy();
         expect(ctrl.variableValueChange).toBeTruthy();

+ 6 - 5
public/app/features/dashboard/components/SaveModals/SaveDashboardModalCtrl.ts

@@ -1,4 +1,5 @@
 import coreModule from 'app/core/core_module';
 import coreModule from 'app/core/core_module';
+import { DashboardSrv } from '../../services/DashboardSrv';
 
 
 const template = `
 const template = `
 <div class="modal-body">
 <div class="modal-body">
@@ -71,8 +72,8 @@ export class SaveDashboardModalCtrl {
   saveTimerange = false;
   saveTimerange = false;
   time: any;
   time: any;
   originalTime: any;
   originalTime: any;
-  current = [];
-  originalCurrent = [];
+  current: any[] = [];
+  originalCurrent: any[] = [];
   max: number;
   max: number;
   saveForm: any;
   saveForm: any;
   isSaving: boolean;
   isSaving: boolean;
@@ -81,7 +82,7 @@ export class SaveDashboardModalCtrl {
   variableValueChange = false;
   variableValueChange = false;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private dashboardSrv) {
+  constructor(private dashboardSrv: DashboardSrv) {
     this.message = '';
     this.message = '';
     this.max = 64;
     this.max = 64;
     this.isSaving = false;
     this.isSaving = false;
@@ -94,7 +95,7 @@ export class SaveDashboardModalCtrl {
       return;
       return;
     }
     }
 
 
-    const options = {
+    const options: any = {
       saveVariables: this.saveVariables,
       saveVariables: this.saveVariables,
       saveTimerange: this.saveTimerange,
       saveTimerange: this.saveTimerange,
       message: this.message,
       message: this.message,
@@ -108,7 +109,7 @@ export class SaveDashboardModalCtrl {
     return this.dashboardSrv.save(saveModel, options).then(this.postSave.bind(this, options));
     return this.dashboardSrv.save(saveModel, options).then(this.postSave.bind(this, options));
   }
   }
 
 
-  postSave(options) {
+  postSave(options: any) {
     if (options.saveVariables) {
     if (options.saveVariables) {
       this.dashboardSrv.getCurrent().resetOriginalVariables();
       this.dashboardSrv.getCurrent().resetOriginalVariables();
     }
     }

+ 1 - 1
public/app/features/dashboard/components/SaveModals/SaveProvisionedDashboardModalCtrl.test.ts

@@ -6,7 +6,7 @@ describe('SaveProvisionedDashboardModalCtrl', () => {
     id: 5,
     id: 5,
   };
   };
 
 
-  const mockDashboardSrv = {
+  const mockDashboardSrv: any = {
     getCurrent: () => {
     getCurrent: () => {
       return {
       return {
         id: 5,
         id: 5,

+ 2 - 1
public/app/features/dashboard/components/SaveModals/SaveProvisionedDashboardModalCtrl.ts

@@ -2,6 +2,7 @@ import angular from 'angular';
 import { saveAs } from 'file-saver';
 import { saveAs } from 'file-saver';
 import coreModule from 'app/core/core_module';
 import coreModule from 'app/core/core_module';
 import { DashboardModel } from '../../state';
 import { DashboardModel } from '../../state';
+import { DashboardSrv } from '../../services/DashboardSrv';
 
 
 const template = `
 const template = `
 <div class="modal-body">
 <div class="modal-body">
@@ -50,7 +51,7 @@ export class SaveProvisionedDashboardModalCtrl {
   dismiss: () => void;
   dismiss: () => void;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(dashboardSrv) {
+  constructor(dashboardSrv: DashboardSrv) {
     this.dashboardModel = dashboardSrv.getCurrent();
     this.dashboardModel = dashboardSrv.getCurrent();
     this.dash = this.dashboardModel.getSaveModelClone();
     this.dash = this.dashboardModel.getSaveModelClone();
     delete this.dash.id;
     delete this.dash.id;

+ 2 - 2
public/app/features/dashboard/components/ShareModal/ShareModalCtrl.test.ts

@@ -42,7 +42,7 @@ describe('ShareModalCtrl', () => {
         orgId: 1,
         orgId: 1,
       },
       },
     };
     };
-
+    // @ts-ignore
     ctx.ctrl = new ShareModalCtrl(
     ctx.ctrl = new ShareModalCtrl(
       ctx.scope,
       ctx.scope,
       {},
       {},
@@ -136,7 +136,7 @@ describe('ShareModalCtrl', () => {
       ctx.$location.absUrl = () => 'http://server/#!/test';
       ctx.$location.absUrl = () => 'http://server/#!/test';
       ctx.scope.options.includeTemplateVars = true;
       ctx.scope.options.includeTemplateVars = true;
 
 
-      ctx.templateSrv.fillVariableValuesForUrl = params => {
+      ctx.templateSrv.fillVariableValuesForUrl = (params: any) => {
         params['var-app'] = 'mupp';
         params['var-app'] = 'mupp';
         params['var-server'] = 'srv-01';
         params['var-server'] = 'srv-01';
       };
       };

+ 13 - 2
public/app/features/dashboard/components/ShareModal/ShareModalCtrl.ts

@@ -1,10 +1,21 @@
-import angular from 'angular';
+import angular, { ILocationService } from 'angular';
 import config from 'app/core/config';
 import config from 'app/core/config';
 import { dateTime } from '@grafana/data';
 import { dateTime } from '@grafana/data';
 import { appendQueryToUrl, toUrlParams } from 'app/core/utils/url';
 import { appendQueryToUrl, toUrlParams } from 'app/core/utils/url';
+import { TimeSrv } from '../../services/TimeSrv';
+import { TemplateSrv } from 'app/features/templating/template_srv';
+import { LinkSrv } from 'app/features/panel/panellinks/link_srv';
 
 
 /** @ngInject */
 /** @ngInject */
-export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv, templateSrv, linkSrv) {
+export function ShareModalCtrl(
+  $scope: any,
+  $rootScope: any,
+  $location: ILocationService,
+  $timeout: any,
+  timeSrv: TimeSrv,
+  templateSrv: TemplateSrv,
+  linkSrv: LinkSrv
+) {
   $scope.options = {
   $scope.options = {
     forCurrent: true,
     forCurrent: true,
     includeTemplateVars: true,
     includeTemplateVars: true,

+ 19 - 8
public/app/features/dashboard/components/ShareModal/ShareSnapshotCtrl.ts

@@ -1,9 +1,20 @@
-import angular from 'angular';
+import angular, { ILocationService } from 'angular';
 import _ from 'lodash';
 import _ from 'lodash';
+import { BackendSrv } from 'app/core/services/backend_srv';
+import { TimeSrv } from '../../services/TimeSrv';
+import { DashboardModel } from '../../state/DashboardModel';
+import { PanelModel } from '../../state/PanelModel';
 
 
 export class ShareSnapshotCtrl {
 export class ShareSnapshotCtrl {
   /** @ngInject */
   /** @ngInject */
-  constructor($scope, $rootScope, $location, backendSrv, $timeout, timeSrv) {
+  constructor(
+    $scope: any,
+    $rootScope: any,
+    $location: ILocationService,
+    backendSrv: BackendSrv,
+    $timeout: any,
+    timeSrv: TimeSrv
+  ) {
     $scope.snapshot = {
     $scope.snapshot = {
       name: $scope.dashboard.title,
       name: $scope.dashboard.title,
       expires: 0,
       expires: 0,
@@ -26,7 +37,7 @@ export class ShareSnapshotCtrl {
     ];
     ];
 
 
     $scope.init = () => {
     $scope.init = () => {
-      backendSrv.get('/api/snapshot/shared-options').then(options => {
+      backendSrv.get('/api/snapshot/shared-options').then((options: { [x: string]: any }) => {
         $scope.sharingButtonText = options['externalSnapshotName'];
         $scope.sharingButtonText = options['externalSnapshotName'];
         $scope.externalEnabled = options['externalEnabled'];
         $scope.externalEnabled = options['externalEnabled'];
       });
       });
@@ -34,7 +45,7 @@ export class ShareSnapshotCtrl {
 
 
     $scope.apiUrl = '/api/snapshots';
     $scope.apiUrl = '/api/snapshots';
 
 
-    $scope.createSnapshot = external => {
+    $scope.createSnapshot = (external: any) => {
       $scope.dashboard.snapshot = {
       $scope.dashboard.snapshot = {
         timestamp: new Date(),
         timestamp: new Date(),
       };
       };
@@ -52,7 +63,7 @@ export class ShareSnapshotCtrl {
       }, $scope.snapshot.timeoutSeconds * 1000);
       }, $scope.snapshot.timeoutSeconds * 1000);
     };
     };
 
 
-    $scope.saveSnapshot = external => {
+    $scope.saveSnapshot = (external: any) => {
       const dash = $scope.dashboard.getSaveModelClone();
       const dash = $scope.dashboard.getSaveModelClone();
       $scope.scrubDashboard(dash);
       $scope.scrubDashboard(dash);
 
 
@@ -64,7 +75,7 @@ export class ShareSnapshotCtrl {
       };
       };
 
 
       backendSrv.post($scope.apiUrl, cmdData).then(
       backendSrv.post($scope.apiUrl, cmdData).then(
-        results => {
+        (results: { deleteUrl: any; url: any }) => {
           $scope.loading = false;
           $scope.loading = false;
           $scope.deleteUrl = results.deleteUrl;
           $scope.deleteUrl = results.deleteUrl;
           $scope.snapshotUrl = results.url;
           $scope.snapshotUrl = results.url;
@@ -80,7 +91,7 @@ export class ShareSnapshotCtrl {
       return $scope.snapshotUrl;
       return $scope.snapshotUrl;
     };
     };
 
 
-    $scope.scrubDashboard = dash => {
+    $scope.scrubDashboard = (dash: DashboardModel) => {
       // change title
       // change title
       dash.title = $scope.snapshot.name;
       dash.title = $scope.snapshot.name;
 
 
@@ -131,7 +142,7 @@ export class ShareSnapshotCtrl {
 
 
       // cleanup snapshotData
       // cleanup snapshotData
       delete $scope.dashboard.snapshot;
       delete $scope.dashboard.snapshot;
-      $scope.dashboard.forEachPanel(panel => {
+      $scope.dashboard.forEachPanel((panel: PanelModel) => {
         delete panel.snapshotData;
         delete panel.snapshotData;
       });
       });
       _.each($scope.dashboard.annotations.list, annotation => {
       _.each($scope.dashboard.annotations.list, annotation => {

+ 5 - 4
public/app/features/dashboard/components/SubMenu/SubMenuCtrl.ts

@@ -1,5 +1,6 @@
-import angular from 'angular';
+import angular, { ILocationService } from 'angular';
 import _ from 'lodash';
 import _ from 'lodash';
+import { VariableSrv } from 'app/features/templating/all';
 
 
 export class SubMenuCtrl {
 export class SubMenuCtrl {
   annotations: any;
   annotations: any;
@@ -7,7 +8,7 @@ export class SubMenuCtrl {
   dashboard: any;
   dashboard: any;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private variableSrv, private $location) {
+  constructor(private variableSrv: VariableSrv, private $location: ILocationService) {
     this.annotations = this.dashboard.templating.list;
     this.annotations = this.dashboard.templating.list;
     this.variables = this.variableSrv.variables;
     this.variables = this.variableSrv.variables;
   }
   }
@@ -16,11 +17,11 @@ export class SubMenuCtrl {
     this.dashboard.startRefresh();
     this.dashboard.startRefresh();
   }
   }
 
 
-  variableUpdated(variable) {
+  variableUpdated(variable: any) {
     this.variableSrv.variableUpdated(variable, true);
     this.variableSrv.variableUpdated(variable, true);
   }
   }
 
 
-  openEditView(editview) {
+  openEditView(editview: any) {
     const search = _.extend(this.$location.search(), { editview: editview });
     const search = _.extend(this.$location.search(), { editview: editview });
     this.$location.search(search);
     this.$location.search(search);
   }
   }

+ 1 - 1
public/app/features/dashboard/components/UnsavedChangesModal/UnsavedChangesModalCtrl.ts

@@ -33,7 +33,7 @@ export class UnsavedChangesModalCtrl {
   dismiss: () => void;
   dismiss: () => void;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private unsavedChangesSrv) {}
+  constructor(private unsavedChangesSrv: any) {}
 
 
   discard() {
   discard() {
     this.dismiss();
     this.dismiss();

+ 12 - 11
public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.test.ts

@@ -1,6 +1,7 @@
 import _ from 'lodash';
 import _ from 'lodash';
 import { HistoryListCtrl } from './HistoryListCtrl';
 import { HistoryListCtrl } from './HistoryListCtrl';
 import { versions, compare, restore } from './__mocks__/history';
 import { versions, compare, restore } from './__mocks__/history';
+// @ts-ignore
 import $q from 'q';
 import $q from 'q';
 
 
 describe('HistoryListCtrl', () => {
 describe('HistoryListCtrl', () => {
@@ -10,9 +11,9 @@ describe('HistoryListCtrl', () => {
 
 
   restore(7, RESTORE_ID);
   restore(7, RESTORE_ID);
 
 
-  let historySrv;
-  let $rootScope;
-  let historyListCtrl;
+  let historySrv: any;
+  let $rootScope: any;
+  let historyListCtrl: any;
   beforeEach(() => {
   beforeEach(() => {
     historySrv = {
     historySrv = {
       calculateDiff: jest.fn(),
       calculateDiff: jest.fn(),
@@ -25,13 +26,13 @@ describe('HistoryListCtrl', () => {
   });
   });
 
 
   describe('when the history list component is loaded', () => {
   describe('when the history list component is loaded', () => {
-    let deferred;
+    let deferred: any;
 
 
     beforeEach(() => {
     beforeEach(() => {
       deferred = $q.defer({});
       deferred = $q.defer({});
       historySrv.getHistoryList = jest.fn(() => deferred.promise);
       historySrv.getHistoryList = jest.fn(() => deferred.promise);
 
 
-      historyListCtrl = new HistoryListCtrl({}, $rootScope, {}, $q, historySrv, {});
+      historyListCtrl = new HistoryListCtrl({}, $rootScope, {} as any, $q, historySrv, {});
 
 
       historyListCtrl.dashboard = {
       historyListCtrl.dashboard = {
         id: 2,
         id: 2,
@@ -89,7 +90,7 @@ describe('HistoryListCtrl', () => {
 
 
         historySrv.getHistoryList = jest.fn(() => deferred.promise);
         historySrv.getHistoryList = jest.fn(() => deferred.promise);
 
 
-        historyListCtrl = new HistoryListCtrl({}, $rootScope, {}, $q, historySrv, {});
+        historyListCtrl = new HistoryListCtrl({}, $rootScope, {} as any, $q, historySrv, {});
 
 
         deferred.reject(new Error('HistoryListError'));
         deferred.reject(new Error('HistoryListError'));
 
 
@@ -130,14 +131,14 @@ describe('HistoryListCtrl', () => {
   });
   });
 
 
   describe('when the user wants to compare two revisions', () => {
   describe('when the user wants to compare two revisions', () => {
-    let deferred;
+    let deferred: any;
 
 
     beforeEach(async () => {
     beforeEach(async () => {
       deferred = $q.defer({});
       deferred = $q.defer({});
       historySrv.getHistoryList = jest.fn(() => $q.when(versionsResponse));
       historySrv.getHistoryList = jest.fn(() => $q.when(versionsResponse));
       historySrv.calculateDiff = jest.fn(() => deferred.promise);
       historySrv.calculateDiff = jest.fn(() => deferred.promise);
 
 
-      historyListCtrl = new HistoryListCtrl({}, $rootScope, {}, $q, historySrv, {});
+      historyListCtrl = new HistoryListCtrl({}, $rootScope, {} as any, $q, historySrv, {});
 
 
       historyListCtrl.dashboard = {
       historyListCtrl.dashboard = {
         id: 2,
         id: 2,
@@ -272,14 +273,14 @@ describe('HistoryListCtrl', () => {
   });
   });
 
 
   describe('when the user wants to restore a revision', () => {
   describe('when the user wants to restore a revision', () => {
-    let deferred;
+    let deferred: any;
 
 
     beforeEach(async () => {
     beforeEach(async () => {
       deferred = $q.defer();
       deferred = $q.defer();
       historySrv.getHistoryList = jest.fn(() => $q.when(versionsResponse));
       historySrv.getHistoryList = jest.fn(() => $q.when(versionsResponse));
       historySrv.restoreDashboard = jest.fn(() => deferred.promise);
       historySrv.restoreDashboard = jest.fn(() => deferred.promise);
 
 
-      historyListCtrl = new HistoryListCtrl({}, $rootScope, {}, $q, historySrv, {});
+      historyListCtrl = new HistoryListCtrl({}, $rootScope, {} as any, $q, historySrv, {});
 
 
       historyListCtrl.dashboard = {
       historyListCtrl.dashboard = {
         id: 1,
         id: 1,
@@ -299,7 +300,7 @@ describe('HistoryListCtrl', () => {
         deferred = $q.defer();
         deferred = $q.defer();
         historySrv.getHistoryList = jest.fn(() => $q.when(versionsResponse));
         historySrv.getHistoryList = jest.fn(() => $q.when(versionsResponse));
         historySrv.restoreDashboard = jest.fn(() => deferred.promise);
         historySrv.restoreDashboard = jest.fn(() => deferred.promise);
-        historyListCtrl = new HistoryListCtrl({}, $rootScope, {}, $q, historySrv, {});
+        historyListCtrl = new HistoryListCtrl({}, $rootScope, {} as any, $q, historySrv, {});
         deferred.reject(new Error('RestoreError'));
         deferred.reject(new Error('RestoreError'));
         historyListCtrl.restoreConfirm(RESTORE_ID);
         historyListCtrl.restoreConfirm(RESTORE_ID);
         await historyListCtrl.getLog();
         await historyListCtrl.getLog();

+ 16 - 13
public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.ts

@@ -1,10 +1,10 @@
 import _ from 'lodash';
 import _ from 'lodash';
-import angular from 'angular';
+import angular, { ILocationService, IQService } from 'angular';
 
 
 import locationUtil from 'app/core/utils/location_util';
 import locationUtil from 'app/core/utils/location_util';
 import { DashboardModel } from '../../state/DashboardModel';
 import { DashboardModel } from '../../state/DashboardModel';
 import { HistoryListOpts, RevisionsModel, CalculateDiffOptions, HistorySrv } from './HistorySrv';
 import { HistoryListOpts, RevisionsModel, CalculateDiffOptions, HistorySrv } from './HistorySrv';
-import { dateTime, toUtc } from '@grafana/data';
+import { dateTime, toUtc, DateTimeInput } from '@grafana/data';
 
 
 export class HistoryListCtrl {
 export class HistoryListCtrl {
   appending: boolean;
   appending: boolean;
@@ -24,12 +24,12 @@ export class HistoryListCtrl {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(
   constructor(
-    private $route,
-    private $rootScope,
-    private $location,
-    private $q,
+    private $route: any,
+    private $rootScope: any,
+    private $location: ILocationService,
+    private $q: IQService,
     private historySrv: HistorySrv,
     private historySrv: HistorySrv,
-    public $scope
+    public $scope: any
   ) {
   ) {
     this.appending = false;
     this.appending = false;
     this.diff = 'basic';
     this.diff = 'basic';
@@ -69,11 +69,11 @@ export class HistoryListCtrl {
     this.canCompare = selected === 2;
     this.canCompare = selected === 2;
   }
   }
 
 
-  formatDate(date) {
+  formatDate(date: DateTimeInput) {
     return this.dashboard.formatDate(date);
     return this.dashboard.formatDate(date);
   }
   }
 
 
-  formatBasicDate(date) {
+  formatBasicDate(date: DateTimeInput) {
     const now = this.dashboard.timezone === 'browser' ? dateTime() : toUtc();
     const now = this.dashboard.timezone === 'browser' ? dateTime() : toUtc();
     const then = this.dashboard.timezone === 'browser' ? dateTime(date) : toUtc(date);
     const then = this.dashboard.timezone === 'browser' ? dateTime(date) : toUtc(date);
     return then.from(now);
     return then.from(now);
@@ -84,7 +84,9 @@ export class HistoryListCtrl {
     this.mode = 'compare';
     this.mode = 'compare';
 
 
     // have it already been fetched?
     // have it already been fetched?
+    // @ts-ignore
     if (this.delta[this.diff]) {
     if (this.delta[this.diff]) {
+      // @ts-ignore
       return this.$q.when(this.delta[this.diff]);
       return this.$q.when(this.delta[this.diff]);
     }
     }
 
 
@@ -109,7 +111,8 @@ export class HistoryListCtrl {
 
 
     return this.historySrv
     return this.historySrv
       .calculateDiff(options)
       .calculateDiff(options)
-      .then(response => {
+      .then((response: any) => {
+        // @ts-ignore
         this.delta[this.diff] = response;
         this.delta[this.diff] = response;
       })
       })
       .catch(() => {
       .catch(() => {
@@ -130,7 +133,7 @@ export class HistoryListCtrl {
 
 
     return this.historySrv
     return this.historySrv
       .getHistoryList(this.dashboard, options)
       .getHistoryList(this.dashboard, options)
-      .then(revisions => {
+      .then((revisions: any) => {
         // set formatted dates & default values
         // set formatted dates & default values
         for (const rev of revisions) {
         for (const rev of revisions) {
           rev.createdDateString = this.formatDate(rev.created);
           rev.createdDateString = this.formatDate(rev.created);
@@ -140,7 +143,7 @@ export class HistoryListCtrl {
 
 
         this.revisions = append ? this.revisions.concat(revisions) : revisions;
         this.revisions = append ? this.revisions.concat(revisions) : revisions;
       })
       })
-      .catch(err => {
+      .catch((err: any) => {
         this.loading = false;
         this.loading = false;
       })
       })
       .finally(() => {
       .finally(() => {
@@ -183,7 +186,7 @@ export class HistoryListCtrl {
     this.loading = true;
     this.loading = true;
     return this.historySrv
     return this.historySrv
       .restoreDashboard(this.dashboard, version)
       .restoreDashboard(this.dashboard, version)
-      .then(response => {
+      .then((response: any) => {
         this.$location.url(locationUtil.stripBaseFromUrl(response.url)).replace();
         this.$location.url(locationUtil.stripBaseFromUrl(response.url)).replace();
         this.$route.reload();
         this.$route.reload();
         this.$rootScope.appEvent('alert-success', ['Dashboard restored', 'Restored from version ' + version]);
         this.$rootScope.appEvent('alert-success', ['Dashboard restored', 'Restored from version ' + version]);

+ 5 - 5
public/app/features/dashboard/components/VersionHistory/HistorySrv.test.ts

@@ -7,7 +7,7 @@ describe('historySrv', () => {
   const versionsResponse = versions();
   const versionsResponse = versions();
   const restoreResponse = restore;
   const restoreResponse = restore;
 
 
-  const backendSrv = {
+  const backendSrv: any = {
     get: jest.fn(() => Promise.resolve({})),
     get: jest.fn(() => Promise.resolve({})),
     post: jest.fn(() => Promise.resolve({})),
     post: jest.fn(() => Promise.resolve({})),
   };
   };
@@ -23,19 +23,19 @@ describe('historySrv', () => {
       backendSrv.get = jest.fn(() => Promise.resolve(versionsResponse));
       backendSrv.get = jest.fn(() => Promise.resolve(versionsResponse));
       historySrv = new HistorySrv(backendSrv);
       historySrv = new HistorySrv(backendSrv);
 
 
-      return historySrv.getHistoryList(dash, historyListOpts).then(versions => {
+      return historySrv.getHistoryList(dash, historyListOpts).then((versions: any) => {
         expect(versions).toEqual(versionsResponse);
         expect(versions).toEqual(versionsResponse);
       });
       });
     });
     });
 
 
     it('should return an empty array when not given an id', () => {
     it('should return an empty array when not given an id', () => {
-      return historySrv.getHistoryList(emptyDash, historyListOpts).then(versions => {
+      return historySrv.getHistoryList(emptyDash, historyListOpts).then((versions: any) => {
         expect(versions).toEqual([]);
         expect(versions).toEqual([]);
       });
       });
     });
     });
 
 
     it('should return an empty array when not given a dashboard', () => {
     it('should return an empty array when not given a dashboard', () => {
-      return historySrv.getHistoryList(null, historyListOpts).then(versions => {
+      return historySrv.getHistoryList(null, historyListOpts).then((versions: any) => {
         expect(versions).toEqual([]);
         expect(versions).toEqual([]);
       });
       });
     });
     });
@@ -46,7 +46,7 @@ describe('historySrv', () => {
       const version = 6;
       const version = 6;
       backendSrv.post = jest.fn(() => Promise.resolve(restoreResponse(version)));
       backendSrv.post = jest.fn(() => Promise.resolve(restoreResponse(version)));
       historySrv = new HistorySrv(backendSrv);
       historySrv = new HistorySrv(backendSrv);
-      return historySrv.restoreDashboard(dash, version).then(response => {
+      return historySrv.restoreDashboard(dash, version).then((response: any) => {
         expect(response).toEqual(restoreResponse(version));
         expect(response).toEqual(restoreResponse(version));
       });
       });
     });
     });

+ 2 - 1
public/app/features/dashboard/components/VersionHistory/HistorySrv.ts

@@ -1,6 +1,7 @@
 import _ from 'lodash';
 import _ from 'lodash';
 import coreModule from 'app/core/core_module';
 import coreModule from 'app/core/core_module';
 import { DashboardModel } from '../../state/DashboardModel';
 import { DashboardModel } from '../../state/DashboardModel';
+import { BackendSrv } from 'app/core/services/backend_srv';
 
 
 export interface HistoryListOpts {
 export interface HistoryListOpts {
   limit: number;
   limit: number;
@@ -32,7 +33,7 @@ export interface DiffTarget {
 
 
 export class HistorySrv {
 export class HistorySrv {
   /** @ngInject */
   /** @ngInject */
-  constructor(private backendSrv) {}
+  constructor(private backendSrv: BackendSrv) {}
 
 
   getHistoryList(dashboard: DashboardModel, options: HistoryListOpts) {
   getHistoryList(dashboard: DashboardModel, options: HistoryListOpts) {
     const id = dashboard && dashboard.id ? dashboard.id : void 0;
     const id = dashboard && dashboard.id ? dashboard.id : void 0;

+ 2 - 2
public/app/features/dashboard/components/VersionHistory/__mocks__/history.ts

@@ -44,11 +44,11 @@ export function versions() {
   ];
   ];
 }
 }
 
 
-export function compare(type) {
+export function compare(type: any) {
   return type === 'basic' ? '<div></div>' : '<pre><code></code></pre>';
   return type === 'basic' ? '<div></div>' : '<pre><code></code></pre>';
 }
 }
 
 
-export function restore(version, restoredFrom?) {
+export function restore(version: any, restoredFrom?: any): any {
   return {
   return {
     dashboard: {
     dashboard: {
       meta: {
       meta: {

+ 1 - 1
public/app/features/dashboard/containers/DashboardPage.test.tsx

@@ -38,7 +38,7 @@ function getTestDashboard(overrides?: any, metaOverrides?: any): DashboardModel
   return new DashboardModel(data, meta);
   return new DashboardModel(data, meta);
 }
 }
 
 
-function dashboardPageScenario(description, scenarioFn: (ctx: ScenarioContext) => void) {
+function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioContext) => void) {
   describe(description, () => {
   describe(description, () => {
     let setupFn: () => void;
     let setupFn: () => void;
 
 

+ 1 - 1
public/app/features/dashboard/dashgrid/DashboardGrid.test.tsx

@@ -48,7 +48,7 @@ function getTestDashboard(overrides?: any, metaOverrides?: any): DashboardModel
   return new DashboardModel(data, meta);
   return new DashboardModel(data, meta);
 }
 }
 
 
-function dashboardGridScenario(description, scenarioFn: (ctx: ScenarioContext) => void) {
+function dashboardGridScenario(description: string, scenarioFn: (ctx: ScenarioContext) => void) {
   describe(description, () => {
   describe(description, () => {
     let setupFn: () => void;
     let setupFn: () => void;
 
 

+ 1 - 0
public/app/features/dashboard/dashgrid/DashboardGrid.tsx

@@ -3,6 +3,7 @@ import React, { PureComponent } from 'react';
 import { hot } from 'react-hot-loader';
 import { hot } from 'react-hot-loader';
 import ReactGridLayout, { ItemCallback } from 'react-grid-layout';
 import ReactGridLayout, { ItemCallback } from 'react-grid-layout';
 import classNames from 'classnames';
 import classNames from 'classnames';
+// @ts-ignore
 import sizeMe from 'react-sizeme';
 import sizeMe from 'react-sizeme';
 
 
 // Types
 // Types

+ 1 - 1
public/app/features/dashboard/dashgrid/DashboardPanel.tsx

@@ -34,7 +34,7 @@ export interface State {
 
 
 export class DashboardPanel extends PureComponent<Props, State> {
 export class DashboardPanel extends PureComponent<Props, State> {
   element: HTMLElement;
   element: HTMLElement;
-  specialPanels = {};
+  specialPanels: { [key: string]: Function } = {};
 
 
   constructor(props: Props) {
   constructor(props: Props) {
     super(props);
     super(props);

+ 1 - 1
public/app/features/dashboard/dashgrid/PanelResizer.tsx

@@ -21,7 +21,7 @@ export class PanelResizer extends PureComponent<Props, State> {
   throttledResizeDone: () => void;
   throttledResizeDone: () => void;
   noStyles: object = {};
   noStyles: object = {};
 
 
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     super(props);
     const { panel } = this.props;
     const { panel } = this.props;
 
 

+ 4 - 4
public/app/features/dashboard/panel_editor/EditorTabBody.tsx

@@ -32,11 +32,11 @@ interface State {
 }
 }
 
 
 export class EditorTabBody extends PureComponent<Props, State> {
 export class EditorTabBody extends PureComponent<Props, State> {
-  static defaultProps = {
+  static defaultProps: Partial<Props> = {
     toolbarItems: [],
     toolbarItems: [],
   };
   };
 
 
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     super(props);
 
 
     this.state = {
     this.state = {
@@ -61,10 +61,10 @@ export class EditorTabBody extends PureComponent<Props, State> {
     this.setState({ isOpen: false });
     this.setState({ isOpen: false });
   };
   };
 
 
-  static getDerivedStateFromProps(props, state) {
+  static getDerivedStateFromProps(props: Props, state: State) {
     if (state.openView) {
     if (state.openView) {
       const activeToolbarItem = props.toolbarItems.find(
       const activeToolbarItem = props.toolbarItems.find(
-        item => item.title === state.openView.title && item.icon === state.openView.icon
+        (item: any) => item.title === state.openView.title && item.icon === state.openView.icon
       );
       );
       if (activeToolbarItem) {
       if (activeToolbarItem) {
         return {
         return {

+ 1 - 1
public/app/features/dashboard/panel_editor/GeneralTab.tsx

@@ -20,7 +20,7 @@ export class GeneralTab extends PureComponent<Props> {
   element: any;
   element: any;
   component: AngularComponent;
   component: AngularComponent;
 
 
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     super(props);
   }
   }
 
 

+ 3 - 3
public/app/features/dashboard/panel_editor/QueriesTab.tsx

@@ -89,7 +89,7 @@ export class QueriesTab extends PureComponent<Props, State> {
     return this.datasources.find(datasource => datasource.value === panel.datasource) || this.datasources[0];
     return this.datasources.find(datasource => datasource.value === panel.datasource) || this.datasources[0];
   }
   }
 
 
-  onChangeDataSource = datasource => {
+  onChangeDataSource = (datasource: any) => {
     const { panel } = this.props;
     const { panel } = this.props;
     const { currentDS } = this.state;
     const { currentDS } = this.state;
 
 
@@ -194,7 +194,7 @@ export class QueriesTab extends PureComponent<Props, State> {
     );
     );
   };
   };
 
 
-  onAddMixedQuery = datasource => {
+  onAddMixedQuery = (datasource: any) => {
     this.onAddQuery({ datasource: datasource.name });
     this.onAddQuery({ datasource: datasource.name });
     this.setState({ isAddingMixed: false, scrollTop: this.state.scrollTop + 10000 });
     this.setState({ isAddingMixed: false, scrollTop: this.state.scrollTop + 10000 });
   };
   };
@@ -203,7 +203,7 @@ export class QueriesTab extends PureComponent<Props, State> {
     this.setState({ isAddingMixed: false });
     this.setState({ isAddingMixed: false });
   };
   };
 
 
-  onQueryChange = (query: DataQuery, index) => {
+  onQueryChange = (query: DataQuery, index: number) => {
     this.props.panel.changeQuery(query, index);
     this.props.panel.changeQuery(query, index);
     this.forceUpdate();
     this.forceUpdate();
   };
   };

+ 4 - 4
public/app/features/dashboard/panel_editor/QueryInspector.tsx

@@ -24,7 +24,7 @@ export class QueryInspector extends PureComponent<Props, State> {
   formattedJson: any;
   formattedJson: any;
   clipboard: any;
   clipboard: any;
 
 
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     super(props);
     this.state = {
     this.state = {
       allNodesExpanded: null,
       allNodesExpanded: null,
@@ -56,7 +56,7 @@ export class QueryInspector extends PureComponent<Props, State> {
     panel.events.off('refresh', this.onPanelRefresh);
     panel.events.off('refresh', this.onPanelRefresh);
   }
   }
 
 
-  handleMocking(response) {
+  handleMocking(response: any) {
     const { mockedResponse } = this.state;
     const { mockedResponse } = this.state;
     let mockedData;
     let mockedData;
     try {
     try {
@@ -126,7 +126,7 @@ export class QueryInspector extends PureComponent<Props, State> {
     }));
     }));
   };
   };
 
 
-  setFormattedJson = formattedJson => {
+  setFormattedJson = (formattedJson: any) => {
     this.formattedJson = formattedJson;
     this.formattedJson = formattedJson;
   };
   };
 
 
@@ -161,7 +161,7 @@ export class QueryInspector extends PureComponent<Props, State> {
     return 1;
     return 1;
   };
   };
 
 
-  setMockedResponse = evt => {
+  setMockedResponse = (evt: any) => {
     const mockedResponse = evt.target.value;
     const mockedResponse = evt.target.value;
     this.setState(prevState => ({
     this.setState(prevState => ({
       ...prevState,
       ...prevState,

+ 6 - 4
public/app/features/dashboard/panel_editor/QueryOptions.tsx

@@ -1,5 +1,5 @@
 // Libraries
 // Libraries
-import React, { PureComponent, ChangeEvent, FocusEvent } from 'react';
+import React, { PureComponent, ChangeEvent, FocusEvent, ReactText } from 'react';
 
 
 // Utils
 // Utils
 import { rangeUtil } from '@grafana/data';
 import { rangeUtil } from '@grafana/data';
@@ -46,13 +46,13 @@ interface State {
   relativeTime: string;
   relativeTime: string;
   timeShift: string;
   timeShift: string;
   cacheTimeout: string;
   cacheTimeout: string;
-  maxDataPoints: string;
+  maxDataPoints: string | ReactText;
   interval: string;
   interval: string;
   hideTimeOverride: boolean;
   hideTimeOverride: boolean;
 }
 }
 
 
 export class QueryOptions extends PureComponent<Props, State> {
 export class QueryOptions extends PureComponent<Props, State> {
-  allOptions = {
+  allOptions: any = {
     cacheTimeout: {
     cacheTimeout: {
       label: 'Cache timeout',
       label: 'Cache timeout',
       placeholder: '60',
       placeholder: '60',
@@ -91,7 +91,7 @@ export class QueryOptions extends PureComponent<Props, State> {
     },
     },
   };
   };
 
 
-  constructor(props) {
+  constructor(props: Props) {
     super(props);
     super(props);
 
 
     this.state = {
     this.state = {
@@ -147,6 +147,7 @@ export class QueryOptions extends PureComponent<Props, State> {
   onDataSourceOptionBlur = (panelKey: string) => () => {
   onDataSourceOptionBlur = (panelKey: string) => () => {
     const { panel } = this.props;
     const { panel } = this.props;
 
 
+    // @ts-ignore
     panel[panelKey] = this.state[panelKey];
     panel[panelKey] = this.state[panelKey];
     panel.refresh();
     panel.refresh();
   };
   };
@@ -172,6 +173,7 @@ export class QueryOptions extends PureComponent<Props, State> {
           {...options}
           {...options}
           onChange={this.onDataSourceOptionChange(panelKey)}
           onChange={this.onDataSourceOptionChange(panelKey)}
           onBlur={this.onDataSourceOptionBlur(panelKey)}
           onBlur={this.onDataSourceOptionBlur(panelKey)}
+          // @ts-ignore
           value={this.state[panelKey]}
           value={this.state[panelKey]}
         />
         />
       );
       );

+ 2 - 2
public/app/features/dashboard/services/ChangeTracker.test.ts

@@ -14,7 +14,7 @@ describe('ChangeTracker', () => {
   let location;
   let location;
   const timeout = () => {};
   const timeout = () => {};
   let tracker: ChangeTracker;
   let tracker: ChangeTracker;
-  let dash;
+  let dash: any;
   let scope;
   let scope;
 
 
   beforeEach(() => {
   beforeEach(() => {
@@ -57,7 +57,7 @@ describe('ChangeTracker', () => {
       path: jest.fn(),
       path: jest.fn(),
     };
     };
 
 
-    tracker = new ChangeTracker(dash, scope, undefined, location, window, timeout, contextSrv, rootScope);
+    tracker = new ChangeTracker(dash, scope, undefined, location as any, window, timeout, contextSrv, rootScope);
   });
   });
 
 
   it('No changes should not have changes', () => {
   it('No changes should not have changes', () => {

+ 12 - 11
public/app/features/dashboard/services/ChangeTracker.ts

@@ -1,6 +1,7 @@
-import angular from 'angular';
+import angular, { ILocationService } from 'angular';
 import _ from 'lodash';
 import _ from 'lodash';
 import { DashboardModel } from '../state/DashboardModel';
 import { DashboardModel } from '../state/DashboardModel';
+import { ContextSrv } from 'app/core/services/context_srv';
 
 
 export class ChangeTracker {
 export class ChangeTracker {
   current: any;
   current: any;
@@ -12,14 +13,14 @@ export class ChangeTracker {
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(
   constructor(
-    dashboard,
-    scope,
-    originalCopyDelay,
-    private $location,
-    $window,
-    private $timeout,
-    private contextSrv,
-    private $rootScope
+    dashboard: DashboardModel,
+    scope: any,
+    originalCopyDelay: any,
+    private $location: ILocationService,
+    $window: any,
+    private $timeout: any,
+    private contextSrv: ContextSrv,
+    private $rootScope: any
   ) {
   ) {
     this.$location = $location;
     this.$location = $location;
     this.$window = $window;
     this.$window = $window;
@@ -44,7 +45,7 @@ export class ChangeTracker {
       return undefined;
       return undefined;
     };
     };
 
 
-    scope.$on('$locationChangeStart', (event, next) => {
+    scope.$on('$locationChangeStart', (event: any, next: any) => {
       // check if we should look for changes
       // check if we should look for changes
       if (this.originalPath === $location.path()) {
       if (this.originalPath === $location.path()) {
         return true;
         return true;
@@ -92,7 +93,7 @@ export class ChangeTracker {
   }
   }
 
 
   // remove stuff that should not count in diff
   // remove stuff that should not count in diff
-  cleanDashboardFromIgnoredChanges(dashData) {
+  cleanDashboardFromIgnoredChanges(dashData: any) {
     // need to new up the domain model class to get access to expand / collapse row logic
     // need to new up the domain model class to get access to expand / collapse row logic
     const model = new DashboardModel(dashData);
     const model = new DashboardModel(dashData);
 
 

+ 24 - 20
public/app/features/dashboard/services/DashboardLoaderSrv.ts

@@ -1,27 +1,31 @@
 /* tslint:disable:import-blacklist */
 /* tslint:disable:import-blacklist */
-import angular from 'angular';
+import angular, { IQService } from 'angular';
 import moment from 'moment';
 import moment from 'moment';
 import _ from 'lodash';
 import _ from 'lodash';
 import $ from 'jquery';
 import $ from 'jquery';
 import kbn from 'app/core/utils/kbn';
 import kbn from 'app/core/utils/kbn';
 import { dateMath } from '@grafana/data';
 import { dateMath } from '@grafana/data';
 import impressionSrv from 'app/core/services/impression_srv';
 import impressionSrv from 'app/core/services/impression_srv';
+import { BackendSrv } from 'app/core/services/backend_srv';
+import { DashboardSrv } from './DashboardSrv';
+import DatasourceSrv from 'app/features/plugins/datasource_srv';
+import { UrlQueryValue } from '@grafana/runtime';
 
 
 export class DashboardLoaderSrv {
 export class DashboardLoaderSrv {
   /** @ngInject */
   /** @ngInject */
   constructor(
   constructor(
-    private backendSrv,
-    private dashboardSrv,
-    private datasourceSrv,
-    private $http,
-    private $q,
-    private $timeout,
-    contextSrv,
-    private $routeParams,
-    private $rootScope
+    private backendSrv: BackendSrv,
+    private dashboardSrv: DashboardSrv,
+    private datasourceSrv: DatasourceSrv,
+    private $http: any,
+    private $q: IQService,
+    private $timeout: any,
+    contextSrv: any,
+    private $routeParams: any,
+    private $rootScope: any
   ) {}
   ) {}
 
 
-  _dashboardLoadFailed(title, snapshot?) {
+  _dashboardLoadFailed(title: string, snapshot?: boolean) {
     snapshot = snapshot || false;
     snapshot = snapshot || false;
     return {
     return {
       meta: {
       meta: {
@@ -32,11 +36,11 @@ export class DashboardLoaderSrv {
         canEdit: false,
         canEdit: false,
         dashboardNotFound: true,
         dashboardNotFound: true,
       },
       },
-      dashboard: { title: title },
+      dashboard: { title },
     };
     };
   }
   }
 
 
-  loadDashboard(type, slug, uid) {
+  loadDashboard(type: UrlQueryValue, slug: any, uid: any) {
     let promise;
     let promise;
 
 
     if (type === 'script') {
     if (type === 'script') {
@@ -48,7 +52,7 @@ export class DashboardLoaderSrv {
     } else {
     } else {
       promise = this.backendSrv
       promise = this.backendSrv
         .getDashboardByUid(uid)
         .getDashboardByUid(uid)
-        .then(result => {
+        .then((result: any) => {
           if (result.meta.isFolder) {
           if (result.meta.isFolder) {
             this.$rootScope.appEvent('alert-error', ['Dashboard not found']);
             this.$rootScope.appEvent('alert-error', ['Dashboard not found']);
             throw new Error('Dashboard not found');
             throw new Error('Dashboard not found');
@@ -60,7 +64,7 @@ export class DashboardLoaderSrv {
         });
         });
     }
     }
 
 
-    promise.then(result => {
+    promise.then((result: any) => {
       if (result.meta.dashboardNotFound !== true) {
       if (result.meta.dashboardNotFound !== true) {
         impressionSrv.addDashboardImpression(result.dashboard.id);
         impressionSrv.addDashboardImpression(result.dashboard.id);
       }
       }
@@ -71,13 +75,13 @@ export class DashboardLoaderSrv {
     return promise;
     return promise;
   }
   }
 
 
-  _loadScriptedDashboard(file) {
+  _loadScriptedDashboard(file: string) {
     const url = 'public/dashboards/' + file.replace(/\.(?!js)/, '/') + '?' + new Date().getTime();
     const url = 'public/dashboards/' + file.replace(/\.(?!js)/, '/') + '?' + new Date().getTime();
 
 
     return this.$http({ url: url, method: 'GET' })
     return this.$http({ url: url, method: 'GET' })
       .then(this._executeScript.bind(this))
       .then(this._executeScript.bind(this))
       .then(
       .then(
-        result => {
+        (result: any) => {
           return {
           return {
             meta: {
             meta: {
               fromScript: true,
               fromScript: true,
@@ -88,7 +92,7 @@ export class DashboardLoaderSrv {
             dashboard: result.data,
             dashboard: result.data,
           };
           };
         },
         },
-        err => {
+        (err: any) => {
           console.log('Script dashboard error ' + err);
           console.log('Script dashboard error ' + err);
           this.$rootScope.appEvent('alert-error', [
           this.$rootScope.appEvent('alert-error', [
             'Script Error',
             'Script Error',
@@ -99,7 +103,7 @@ export class DashboardLoaderSrv {
       );
       );
   }
   }
 
 
-  _executeScript(result) {
+  _executeScript(result: any) {
     const services = {
     const services = {
       dashboardSrv: this.dashboardSrv,
       dashboardSrv: this.dashboardSrv,
       datasourceSrv: this.datasourceSrv,
       datasourceSrv: this.datasourceSrv,
@@ -125,7 +129,7 @@ export class DashboardLoaderSrv {
     // Handle async dashboard scripts
     // Handle async dashboard scripts
     if (_.isFunction(scriptResult)) {
     if (_.isFunction(scriptResult)) {
       const deferred = this.$q.defer();
       const deferred = this.$q.defer();
-      scriptResult(dashboard => {
+      scriptResult((dashboard: any) => {
         this.$timeout(() => {
         this.$timeout(() => {
           deferred.resolve({ data: dashboard });
           deferred.resolve({ data: dashboard });
         });
         });

+ 14 - 8
public/app/features/dashboard/services/DashboardSrv.ts

@@ -4,12 +4,14 @@ import locationUtil from 'app/core/utils/location_util';
 import { DashboardModel } from '../state/DashboardModel';
 import { DashboardModel } from '../state/DashboardModel';
 import { removePanel } from '../utils/panel';
 import { removePanel } from '../utils/panel';
 import { DashboardMeta } from 'app/types';
 import { DashboardMeta } from 'app/types';
+import { BackendSrv } from 'app/core/services/backend_srv';
+import { ILocationService } from 'angular';
 
 
 export class DashboardSrv {
 export class DashboardSrv {
   dashboard: DashboardModel;
   dashboard: DashboardModel;
 
 
   /** @ngInject */
   /** @ngInject */
-  constructor(private backendSrv, private $rootScope, private $location) {
+  constructor(private backendSrv: BackendSrv, private $rootScope: any, private $location: ILocationService) {
     appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
     appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
     appEvents.on('panel-change-view', this.onPanelChangeView);
     appEvents.on('panel-change-view', this.onPanelChangeView);
     appEvents.on('remove-panel', this.onRemovePanel);
     appEvents.on('remove-panel', this.onRemovePanel);
@@ -35,7 +37,7 @@ export class DashboardSrv {
     removePanel(dashboard, dashboard.getPanelById(panelId), true);
     removePanel(dashboard, dashboard.getPanelById(panelId), true);
   };
   };
 
 
-  onPanelChangeView = options => {
+  onPanelChangeView = (options: any) => {
     const urlParams = this.$location.search();
     const urlParams = this.$location.search();
 
 
     // handle toggle logic
     // handle toggle logic
@@ -75,7 +77,11 @@ export class DashboardSrv {
     this.$location.search(urlParams);
     this.$location.search(urlParams);
   };
   };
 
 
-  handleSaveDashboardError(clone, options, err) {
+  handleSaveDashboardError(
+    clone: any,
+    options: { overwrite?: any },
+    err: { data: { status: string; message: any }; isHandled: boolean }
+  ) {
     options = options || {};
     options = options || {};
     options.overwrite = true;
     options.overwrite = true;
 
 
@@ -129,7 +135,7 @@ export class DashboardSrv {
     }
     }
   }
   }
 
 
-  postSave(clone, data) {
+  postSave(clone: DashboardModel, data: { version: number; url: string }) {
     this.dashboard.version = data.version;
     this.dashboard.version = data.version;
 
 
     // important that these happens before location redirect below
     // important that these happens before location redirect below
@@ -146,7 +152,7 @@ export class DashboardSrv {
     return this.dashboard;
     return this.dashboard;
   }
   }
 
 
-  save(clone, options) {
+  save(clone: any, options: { overwrite?: any; folderId?: any }) {
     options = options || {};
     options = options || {};
     options.folderId = options.folderId >= 0 ? options.folderId : this.dashboard.meta.folderId || clone.folderId;
     options.folderId = options.folderId >= 0 ? options.folderId : this.dashboard.meta.folderId || clone.folderId;
 
 
@@ -156,7 +162,7 @@ export class DashboardSrv {
       .catch(this.handleSaveDashboardError.bind(this, clone, options));
       .catch(this.handleSaveDashboardError.bind(this, clone, options));
   }
   }
 
 
-  saveDashboard(options?, clone?) {
+  saveDashboard(options?: { overwrite?: any; folderId?: any; makeEditable?: any }, clone?: DashboardModel) {
     if (clone) {
     if (clone) {
       this.setCurrent(this.create(clone, this.dashboard.meta));
       this.setCurrent(this.create(clone, this.dashboard.meta));
     }
     }
@@ -204,7 +210,7 @@ export class DashboardSrv {
     });
     });
   }
   }
 
 
-  starDashboard(dashboardId, isStarred) {
+  starDashboard(dashboardId: string, isStarred: any) {
     let promise;
     let promise;
 
 
     if (isStarred) {
     if (isStarred) {
@@ -217,7 +223,7 @@ export class DashboardSrv {
       });
       });
     }
     }
 
 
-    return promise.then(res => {
+    return promise.then((res: boolean) => {
       if (this.dashboard && this.dashboard.id === dashboardId) {
       if (this.dashboard && this.dashboard.id === dashboardId) {
         this.dashboard.meta.isStarred = res;
         this.dashboard.meta.isStarred = res;
       }
       }

+ 1 - 1
public/app/features/dashboard/services/TimeSrv.test.ts

@@ -19,7 +19,7 @@ describe('timeSrv', () => {
     search: jest.fn(() => ({})),
     search: jest.fn(() => ({})),
   };
   };
 
 
-  let timeSrv;
+  let timeSrv: TimeSrv;
 
 
   const _dashboard: any = {
   const _dashboard: any = {
     time: { from: 'now-6h', to: 'now' },
     time: { from: 'now-6h', to: 'now' },

+ 14 - 3
public/app/features/dashboard/services/UnsavedChangesSrv.ts

@@ -1,9 +1,20 @@
-import angular from 'angular';
+import angular, { IQService, ILocationService } from 'angular';
 import { ChangeTracker } from './ChangeTracker';
 import { ChangeTracker } from './ChangeTracker';
+import { ContextSrv } from 'app/core/services/context_srv';
+import { DashboardSrv } from './DashboardSrv';
 
 
 /** @ngInject */
 /** @ngInject */
-export function unsavedChangesSrv(this: any, $rootScope, $q, $location, $timeout, contextSrv, dashboardSrv, $window) {
-  this.init = function(dashboard, scope) {
+export function unsavedChangesSrv(
+  this: any,
+  $rootScope: any,
+  $q: IQService,
+  $location: ILocationService,
+  $timeout: any,
+  contextSrv: ContextSrv,
+  dashboardSrv: DashboardSrv,
+  $window: any
+) {
+  this.init = function(dashboard: any, scope: any) {
     this.tracker = new ChangeTracker(dashboard, scope, 1000, $location, $window, $timeout, contextSrv, $rootScope);
     this.tracker = new ChangeTracker(dashboard, scope, 1000, $location, $window, $timeout, contextSrv, $rootScope);
     return this.tracker;
     return this.tracker;
   };
   };

+ 9 - 8
public/app/features/dashboard/state/DashboardMigrator.test.ts

@@ -9,10 +9,10 @@ jest.mock('app/core/services/context_srv', () => ({}));
 
 
 describe('DashboardModel', () => {
 describe('DashboardModel', () => {
   describe('when creating dashboard with old schema', () => {
   describe('when creating dashboard with old schema', () => {
-    let model;
-    let graph;
-    let singlestat;
-    let table;
+    let model: any;
+    let graph: any;
+    let singlestat: any;
+    let table: any;
 
 
     beforeEach(() => {
     beforeEach(() => {
       model = new DashboardModel({
       model = new DashboardModel({
@@ -142,7 +142,7 @@ describe('DashboardModel', () => {
   });
   });
 
 
   describe('when migrating to the grid layout', () => {
   describe('when migrating to the grid layout', () => {
-    let model;
+    let model: any;
 
 
     beforeEach(() => {
     beforeEach(() => {
       model = {
       model = {
@@ -385,7 +385,7 @@ describe('DashboardModel', () => {
   });
   });
 
 
   describe('when migrating panel links', () => {
   describe('when migrating panel links', () => {
-    let model;
+    let model: any;
 
 
     beforeEach(() => {
     beforeEach(() => {
       model = new DashboardModel({
       model = new DashboardModel({
@@ -439,15 +439,16 @@ describe('DashboardModel', () => {
   });
   });
 });
 });
 
 
-function createRow(options, panelDescriptions: any[]) {
+function createRow(options: any, panelDescriptions: any[]) {
   const PANEL_HEIGHT_STEP = GRID_CELL_HEIGHT + GRID_CELL_VMARGIN;
   const PANEL_HEIGHT_STEP = GRID_CELL_HEIGHT + GRID_CELL_VMARGIN;
   const { collapse, showTitle, title, repeat, repeatIteration } = options;
   const { collapse, showTitle, title, repeat, repeatIteration } = options;
   let { height } = options;
   let { height } = options;
   height = height * PANEL_HEIGHT_STEP;
   height = height * PANEL_HEIGHT_STEP;
-  const panels = [];
+  const panels: any[] = [];
   _.each(panelDescriptions, panelDesc => {
   _.each(panelDescriptions, panelDesc => {
     const panel = { span: panelDesc[0] };
     const panel = { span: panelDesc[0] };
     if (panelDesc.length > 1) {
     if (panelDesc.length > 1) {
+      //@ts-ignore
       panel['height'] = panelDesc[1] * PANEL_HEIGHT_STEP;
       panel['height'] = panelDesc[1] * PANEL_HEIGHT_STEP;
     }
     }
     panels.push(panel);
     panels.push(panel);

+ 17 - 17
public/app/features/dashboard/state/DashboardMigrator.ts

@@ -48,7 +48,7 @@ export class DashboardMigrator {
         }
         }
       }
       }
 
 
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         // rename panel type
         // rename panel type
         if (panel.type === 'graphite') {
         if (panel.type === 'graphite') {
           panel.type = 'graph';
           panel.type = 'graph';
@@ -95,7 +95,7 @@ export class DashboardMigrator {
     if (oldVersion < 3) {
     if (oldVersion < 3) {
       // ensure panel ids
       // ensure panel ids
       let maxId = this.dashboard.getNextPanelId();
       let maxId = this.dashboard.getNextPanelId();
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (!panel.id) {
         if (!panel.id) {
           panel.id = maxId;
           panel.id = maxId;
           maxId += 1;
           maxId += 1;
@@ -106,7 +106,7 @@ export class DashboardMigrator {
     // schema version 4 changes
     // schema version 4 changes
     if (oldVersion < 4) {
     if (oldVersion < 4) {
       // move aliasYAxis changes
       // move aliasYAxis changes
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.type !== 'graph') {
         if (panel.type !== 'graph') {
           return;
           return;
         }
         }
@@ -151,7 +151,7 @@ export class DashboardMigrator {
       }
       }
 
 
       // ensure query refIds
       // ensure query refIds
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         _.each(panel.targets, target => {
         _.each(panel.targets, target => {
           if (!target.refId) {
           if (!target.refId) {
             target.refId = panel.getNextQueryLetter && panel.getNextQueryLetter();
             target.refId = panel.getNextQueryLetter && panel.getNextQueryLetter();
@@ -161,7 +161,7 @@ export class DashboardMigrator {
     }
     }
 
 
     if (oldVersion < 8) {
     if (oldVersion < 8) {
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         _.each(panel.targets, target => {
         _.each(panel.targets, target => {
           // update old influxdb query schema
           // update old influxdb query schema
           if (target.fields && target.tags && target.groupBy) {
           if (target.fields && target.tags && target.groupBy) {
@@ -206,7 +206,7 @@ export class DashboardMigrator {
     // schema version 9 changes
     // schema version 9 changes
     if (oldVersion < 9) {
     if (oldVersion < 9) {
       // move aliasYAxis changes
       // move aliasYAxis changes
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.type !== 'singlestat' && panel.thresholds !== '') {
         if (panel.type !== 'singlestat' && panel.thresholds !== '') {
           return;
           return;
         }
         }
@@ -225,7 +225,7 @@ export class DashboardMigrator {
     // schema version 10 changes
     // schema version 10 changes
     if (oldVersion < 10) {
     if (oldVersion < 10) {
       // move aliasYAxis changes
       // move aliasYAxis changes
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.type !== 'table') {
         if (panel.type !== 'table') {
           return;
           return;
         }
         }
@@ -259,7 +259,7 @@ export class DashboardMigrator {
 
 
     if (oldVersion < 12) {
     if (oldVersion < 12) {
       // update graph yaxes changes
       // update graph yaxes changes
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.type !== 'graph') {
         if (panel.type !== 'graph') {
           return;
           return;
         }
         }
@@ -308,7 +308,7 @@ export class DashboardMigrator {
 
 
     if (oldVersion < 13) {
     if (oldVersion < 13) {
       // update graph yaxes changes
       // update graph yaxes changes
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.type !== 'graph') {
         if (panel.type !== 'graph') {
           return;
           return;
         }
         }
@@ -380,7 +380,7 @@ export class DashboardMigrator {
     }
     }
 
 
     if (oldVersion < 17) {
     if (oldVersion < 17) {
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.minSpan) {
         if (panel.minSpan) {
           const max = GRID_COLUMN_COUNT / panel.minSpan;
           const max = GRID_COLUMN_COUNT / panel.minSpan;
           const factors = getFactors(GRID_COLUMN_COUNT);
           const factors = getFactors(GRID_COLUMN_COUNT);
@@ -399,7 +399,7 @@ export class DashboardMigrator {
 
 
     if (oldVersion < 18) {
     if (oldVersion < 18) {
       // migrate change to gauge options
       // migrate change to gauge options
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel['options-gauge']) {
         if (panel['options-gauge']) {
           panel.options = panel['options-gauge'];
           panel.options = panel['options-gauge'];
           panel.options.valueOptions = {
           panel.options.valueOptions = {
@@ -429,7 +429,7 @@ export class DashboardMigrator {
 
 
     if (oldVersion < 19) {
     if (oldVersion < 19) {
       // migrate change to gauge options
       // migrate change to gauge options
-      panelUpgrades.push(panel => {
+      panelUpgrades.push((panel: any) => {
         if (panel.links && _.isArray(panel.links)) {
         if (panel.links && _.isArray(panel.links)) {
           panel.links = panel.links.map(upgradePanelLink);
           panel.links = panel.links.map(upgradePanelLink);
         }
         }
@@ -452,7 +452,7 @@ export class DashboardMigrator {
     }
     }
   }
   }
 
 
-  upgradeToGridLayout(old) {
+  upgradeToGridLayout(old: any) {
     let yPos = 0;
     let yPos = 0;
     const widthFactor = GRID_COLUMN_COUNT / 12;
     const widthFactor = GRID_COLUMN_COUNT / 12;
 
 
@@ -541,7 +541,7 @@ export class DashboardMigrator {
   }
   }
 }
 }
 
 
-function getGridHeight(height) {
+function getGridHeight(height: number | string) {
   if (_.isString(height)) {
   if (_.isString(height)) {
     height = parseInt(height.replace('px', ''), 10);
     height = parseInt(height.replace('px', ''), 10);
   }
   }
@@ -569,7 +569,7 @@ class RowArea {
   yPos: number;
   yPos: number;
   height: number;
   height: number;
 
 
-  constructor(height, width = GRID_COLUMN_COUNT, rowYPos = 0) {
+  constructor(height: number, width = GRID_COLUMN_COUNT, rowYPos = 0) {
     this.area = new Array(width).fill(0);
     this.area = new Array(width).fill(0);
     this.yPos = rowYPos;
     this.yPos = rowYPos;
     this.height = height;
     this.height = height;
@@ -582,7 +582,7 @@ class RowArea {
   /**
   /**
    * Update area after adding the panel.
    * Update area after adding the panel.
    */
    */
-  addPanel(gridPos) {
+  addPanel(gridPos: any) {
     for (let i = gridPos.x; i < gridPos.x + gridPos.w; i++) {
     for (let i = gridPos.x; i < gridPos.x + gridPos.w; i++) {
       if (!this.area[i] || gridPos.y + gridPos.h - this.yPos > this.area[i]) {
       if (!this.area[i] || gridPos.y + gridPos.h - this.yPos > this.area[i]) {
         this.area[i] = gridPos.y + gridPos.h - this.yPos;
         this.area[i] = gridPos.y + gridPos.h - this.yPos;
@@ -594,7 +594,7 @@ class RowArea {
   /**
   /**
    * Calculate position for the new panel in the row.
    * Calculate position for the new panel in the row.
    */
    */
-  getPanelPosition(panelHeight, panelWidth, callOnce = false) {
+  getPanelPosition(panelHeight: number, panelWidth: number, callOnce = false): any {
     let startPlace, endPlace;
     let startPlace, endPlace;
     let place;
     let place;
     for (let i = this.area.length - 1; i >= 0; i--) {
     for (let i = this.area.length - 1; i >= 0; i--) {

+ 6 - 6
public/app/features/dashboard/state/DashboardModel.repeat.test.ts

@@ -5,7 +5,7 @@ import { expect } from 'test/lib/common';
 jest.mock('app/core/services/context_srv', () => ({}));
 jest.mock('app/core/services/context_srv', () => ({}));
 
 
 describe('given dashboard with panel repeat', () => {
 describe('given dashboard with panel repeat', () => {
-  let dashboard;
+  let dashboard: DashboardModel;
 
 
   beforeEach(() => {
   beforeEach(() => {
     const dashboardJSON = {
     const dashboardJSON = {
@@ -56,7 +56,7 @@ describe('given dashboard with panel repeat', () => {
 });
 });
 
 
 describe('given dashboard with panel repeat in horizontal direction', () => {
 describe('given dashboard with panel repeat in horizontal direction', () => {
-  let dashboard;
+  let dashboard: any;
 
 
   beforeEach(() => {
   beforeEach(() => {
     dashboard = new DashboardModel({
     dashboard = new DashboardModel({
@@ -188,7 +188,7 @@ describe('given dashboard with panel repeat in horizontal direction', () => {
 });
 });
 
 
 describe('given dashboard with panel repeat in vertical direction', () => {
 describe('given dashboard with panel repeat in vertical direction', () => {
-  let dashboard;
+  let dashboard: any;
 
 
   beforeEach(() => {
   beforeEach(() => {
     dashboard = new DashboardModel({
     dashboard = new DashboardModel({
@@ -230,7 +230,7 @@ describe('given dashboard with panel repeat in vertical direction', () => {
 });
 });
 
 
 describe('given dashboard with row repeat and panel repeat in horizontal direction', () => {
 describe('given dashboard with row repeat and panel repeat in horizontal direction', () => {
-  let dashboard, dashboardJSON;
+  let dashboard: any, dashboardJSON;
 
 
   beforeEach(() => {
   beforeEach(() => {
     dashboardJSON = {
     dashboardJSON = {
@@ -312,7 +312,7 @@ describe('given dashboard with row repeat and panel repeat in horizontal directi
 });
 });
 
 
 describe('given dashboard with row repeat', () => {
 describe('given dashboard with row repeat', () => {
-  let dashboard, dashboardJSON;
+  let dashboard: any, dashboardJSON: any;
 
 
   beforeEach(() => {
   beforeEach(() => {
     dashboardJSON = {
     dashboardJSON = {
@@ -519,7 +519,7 @@ describe('given dashboard with row repeat', () => {
 });
 });
 
 
 describe('given dashboard with row and panel repeat', () => {
 describe('given dashboard with row and panel repeat', () => {
-  let dashboard, dashboardJSON;
+  let dashboard: any, dashboardJSON: any;
 
 
   beforeEach(() => {
   beforeEach(() => {
     dashboardJSON = {
     dashboardJSON = {

+ 2 - 2
public/app/features/dashboard/state/PanelModel.test.ts

@@ -5,8 +5,8 @@ class TablePanelCtrl {}
 
 
 describe('PanelModel', () => {
 describe('PanelModel', () => {
   describe('when creating new panel model', () => {
   describe('when creating new panel model', () => {
-    let model;
-    let modelJson;
+    let model: any;
+    let modelJson: any;
     let persistedOptionsMock;
     let persistedOptionsMock;
     const defaultOptionsMock = {
     const defaultOptionsMock = {
       fieldOptions: {
       fieldOptions: {

+ 1 - 1
public/app/features/dashboard/state/PanelQueryState.test.ts

@@ -95,7 +95,7 @@ function makeSeriesStub(refId: string) {
     fields: [{ name: 'a' }],
     fields: [{ name: 'a' }],
     rows: [],
     rows: [],
     refId,
     refId,
-  };
+  } as any;
 }
 }
 
 
 describe('stream handling', () => {
 describe('stream handling', () => {

+ 1 - 1
public/app/features/dashboard/state/PanelQueryState.ts

@@ -336,7 +336,7 @@ export function toDataQueryError(err: any): DataQueryError {
 }
 }
 
 
 function translateToLegacyData(data: DataQueryResponseData) {
 function translateToLegacyData(data: DataQueryResponseData) {
-  return data.map(v => {
+  return data.map((v: any) => {
     if (isDataFrame(v)) {
     if (isDataFrame(v)) {
       return toLegacyResponseData(v);
       return toLegacyResponseData(v);
     }
     }

+ 1 - 1
public/app/features/dashboard/state/actions.ts

@@ -125,7 +125,7 @@ export function addDashboardPermission(dashboardId: number, newItem: NewDashboar
   };
   };
 }
 }
 
 
-export function importDashboard(data, dashboardTitle: string): ThunkResult<void> {
+export function importDashboard(data: any, dashboardTitle: string): ThunkResult<void> {
   return async dispatch => {
   return async dispatch => {
     await getBackendSrv().post('/api/dashboards/import', data);
     await getBackendSrv().post('/api/dashboards/import', data);
     dispatch(notifyApp(createSuccessNotification('Dashboard Imported', dashboardTitle)));
     dispatch(notifyApp(createSuccessNotification('Dashboard Imported', dashboardTitle)));

+ 1 - 1
public/app/features/dashboard/state/initDashboard.test.ts

@@ -87,7 +87,7 @@ function describeInitScenario(description: string, scenarioFn: ScenarioFn) {
       setupFn();
       setupFn();
 
 
       const store = mockStore(ctx.storeState);
       const store = mockStore(ctx.storeState);
-
+      // @ts-ignore
       await store.dispatch(initDashboard(ctx.args));
       await store.dispatch(initDashboard(ctx.args));
 
 
       ctx.actions = store.getActions();
       ctx.actions = store.getActions();

+ 2 - 2
public/app/features/datasources/DataSourceDashboards.tsx

@@ -42,10 +42,10 @@ export class DataSourceDashboards extends PureComponent<Props> {
 
 
   onImport = (dashboard: PluginDashboard, overwrite: boolean) => {
   onImport = (dashboard: PluginDashboard, overwrite: boolean) => {
     const { dataSource, importDashboard } = this.props;
     const { dataSource, importDashboard } = this.props;
-    const data = {
+    const data: any = {
       pluginId: dashboard.pluginId,
       pluginId: dashboard.pluginId,
       path: dashboard.path,
       path: dashboard.path,
-      overwrite: overwrite,
+      overwrite,
       inputs: [],
       inputs: [],
     };
     };
 
 

+ 2 - 2
public/app/features/datasources/__mocks__/dataSourcesMocks.ts

@@ -1,6 +1,6 @@
 import { DataSourceSettings } from '@grafana/ui';
 import { DataSourceSettings } from '@grafana/ui';
 
 
-export const getMockDataSources = (amount: number): DataSourceSettings[] => {
+export const getMockDataSources = (amount: number) => {
   const dataSources = [];
   const dataSources = [];
 
 
   for (let i = 0; i <= amount; i++) {
   for (let i = 0; i <= amount; i++) {
@@ -22,7 +22,7 @@ export const getMockDataSources = (amount: number): DataSourceSettings[] => {
     });
     });
   }
   }
 
 
-  return dataSources;
+  return dataSources as DataSourceSettings[];
 };
 };
 
 
 export const getMockDataSource = (): DataSourceSettings => {
 export const getMockDataSource = (): DataSourceSettings => {

+ 12 - 10
public/app/features/datasources/state/selectors.ts

@@ -1,29 +1,31 @@
 import { DataSourceSettings, DataSourcePluginMeta } from '@grafana/ui';
 import { DataSourceSettings, DataSourcePluginMeta } from '@grafana/ui';
+import { DataSourcesState } from '../../../types/datasources';
+import { UrlQueryValue } from '@grafana/runtime';
 
 
-export const getDataSources = state => {
+export const getDataSources = (state: DataSourcesState) => {
   const regex = new RegExp(state.searchQuery, 'i');
   const regex = new RegExp(state.searchQuery, 'i');
 
 
-  return state.dataSources.filter(dataSource => {
+  return state.dataSources.filter((dataSource: DataSourceSettings) => {
     return regex.test(dataSource.name) || regex.test(dataSource.database);
     return regex.test(dataSource.name) || regex.test(dataSource.database);
   });
   });
 };
 };
 
 
-export const getDataSourceTypes = state => {
+export const getDataSourceTypes = (state: DataSourcesState) => {
   const regex = new RegExp(state.dataSourceTypeSearchQuery, 'i');
   const regex = new RegExp(state.dataSourceTypeSearchQuery, 'i');
 
 
-  return state.dataSourceTypes.filter(type => {
+  return state.dataSourceTypes.filter((type: DataSourcePluginMeta) => {
     return regex.test(type.name);
     return regex.test(type.name);
   });
   });
 };
 };
 
 
-export const getDataSource = (state, dataSourceId): DataSourceSettings | null => {
-  if (state.dataSource.id === parseInt(dataSourceId, 10)) {
+export const getDataSource = (state: DataSourcesState, dataSourceId: UrlQueryValue): DataSourceSettings | null => {
+  if (state.dataSource.id === parseInt(dataSourceId as string, 10)) {
     return state.dataSource;
     return state.dataSource;
   }
   }
   return {} as DataSourceSettings;
   return {} as DataSourceSettings;
 };
 };
 
 
-export const getDataSourceMeta = (state, type): DataSourcePluginMeta => {
+export const getDataSourceMeta = (state: DataSourcesState, type: string): DataSourcePluginMeta => {
   if (state.dataSourceMeta.id === type) {
   if (state.dataSourceMeta.id === type) {
     return state.dataSourceMeta;
     return state.dataSourceMeta;
   }
   }
@@ -31,6 +33,6 @@ export const getDataSourceMeta = (state, type): DataSourcePluginMeta => {
   return {} as DataSourcePluginMeta;
   return {} as DataSourcePluginMeta;
 };
 };
 
 
-export const getDataSourcesSearchQuery = state => state.searchQuery;
-export const getDataSourcesLayoutMode = state => state.layoutMode;
-export const getDataSourcesCount = state => state.dataSourcesCount;
+export const getDataSourcesSearchQuery = (state: DataSourcesState) => state.searchQuery;
+export const getDataSourcesLayoutMode = (state: DataSourcesState) => state.layoutMode;
+export const getDataSourcesCount = (state: DataSourcesState) => state.dataSourcesCount;

+ 1 - 1
public/app/features/explore/AdHocFilterField.tsx

@@ -36,7 +36,7 @@ export class AdHocFilterField<
 
 
   componentDidUpdate(prevProps: Props) {
   componentDidUpdate(prevProps: Props) {
     if (_.isEqual(prevProps.extendedOptions, this.props.extendedOptions) === false) {
     if (_.isEqual(prevProps.extendedOptions, this.props.extendedOptions) === false) {
-      const pairs = [];
+      const pairs: any[] = [];
 
 
       this.setState({ pairs }, () => this.props.onPairsChanged(pairs));
       this.setState({ pairs }, () => this.props.onPairsChanged(pairs));
     }
     }

+ 4 - 4
public/app/features/explore/ErrorBoundary.tsx

@@ -1,16 +1,16 @@
 import React, { Component } from 'react';
 import React, { Component } from 'react';
 
 
 export default class ErrorBoundary extends Component<{}, any> {
 export default class ErrorBoundary extends Component<{}, any> {
-  constructor(props) {
+  constructor(props: {}) {
     super(props);
     super(props);
     this.state = { error: null, errorInfo: null };
     this.state = { error: null, errorInfo: null };
   }
   }
 
 
-  componentDidCatch(error, errorInfo) {
+  componentDidCatch(error: any, errorInfo: any) {
     // Catch errors in any components below and re-render with error message
     // Catch errors in any components below and re-render with error message
     this.setState({
     this.setState({
-      error: error,
-      errorInfo: errorInfo,
+      error,
+      errorInfo,
     });
     });
   }
   }
 
 

+ 1 - 1
public/app/features/explore/ExploreToolbar.tsx

@@ -90,7 +90,7 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
     super(props);
     super(props);
   }
   }
 
 
-  onChangeDatasource = async option => {
+  onChangeDatasource = async (option: { value: any }) => {
     this.props.changeDatasource(this.props.exploreId, option.value);
     this.props.changeDatasource(this.props.exploreId, option.value);
   };
   };
 
 

+ 5 - 5
public/app/features/explore/Graph.tsx

@@ -14,7 +14,7 @@ import TimeSeries from 'app/core/time_series2';
 const MAX_NUMBER_OF_TIME_SERIES = 20;
 const MAX_NUMBER_OF_TIME_SERIES = 20;
 
 
 // Copied from graph.ts
 // Copied from graph.ts
-function time_format(ticks, min, max) {
+function time_format(ticks: number, min: number, max: number) {
   if (min && max && ticks) {
   if (min && max && ticks) {
     const range = max - min;
     const range = max - min;
     const secPerTick = range / ticks / 1000;
     const secPerTick = range / ticks / 1000;
@@ -39,7 +39,7 @@ function time_format(ticks, min, max) {
   return '%H:%M';
   return '%H:%M';
 }
 }
 
 
-const FLOT_OPTIONS = {
+const FLOT_OPTIONS: any = {
   legend: {
   legend: {
     show: false,
     show: false,
   },
   },
@@ -94,9 +94,9 @@ interface GraphState {
 
 
 export class Graph extends PureComponent<GraphProps, GraphState> {
 export class Graph extends PureComponent<GraphProps, GraphState> {
   $el: any;
   $el: any;
-  dynamicOptions = null;
+  dynamicOptions: any = null;
 
 
-  state = {
+  state: GraphState = {
     hiddenSeries: [],
     hiddenSeries: [],
     showAllTimeSeries: false,
     showAllTimeSeries: false,
   };
   };
@@ -130,7 +130,7 @@ export class Graph extends PureComponent<GraphProps, GraphState> {
     this.$el.unbind('plotselected', this.onPlotSelected);
     this.$el.unbind('plotselected', this.onPlotSelected);
   }
   }
 
 
-  onPlotSelected = (event: JQueryEventObject, ranges) => {
+  onPlotSelected = (event: JQueryEventObject, ranges: { xaxis: { from: number; to: number } }) => {
     const { onChangeTime } = this.props;
     const { onChangeTime } = this.props;
     if (onChangeTime) {
     if (onChangeTime) {
       this.props.onChangeTime({
       this.props.onChangeTime({

+ 2 - 1
public/app/features/explore/GraphContainer.tsx

@@ -69,9 +69,10 @@ export class GraphContainer extends PureComponent<GraphContainerProps> {
   }
   }
 }
 }
 
 
-function mapStateToProps(state: StoreState, { exploreId }) {
+function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }) {
   const explore = state.explore;
   const explore = state.explore;
   const { split } = explore;
   const { split } = explore;
+  // @ts-ignore
   const item: ExploreItemState = explore[exploreId];
   const item: ExploreItemState = explore[exploreId];
   const { graphResult, loadingState, showingGraph, showingTable, absoluteRange } = item;
   const { graphResult, loadingState, showingGraph, showingTable, absoluteRange } = item;
   const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
   const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;

+ 1 - 1
public/app/features/explore/JSONViewer.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import React from 'react';
 
 
-export default function({ value }) {
+export default function({ value }: any) {
   return (
   return (
     <div>
     <div>
       <pre>{JSON.stringify(value, undefined, 2)}</pre>
       <pre>{JSON.stringify(value, undefined, 2)}</pre>

+ 1 - 1
public/app/features/explore/LogLabel.tsx

@@ -18,7 +18,7 @@ interface State {
 }
 }
 
 
 export class LogLabel extends PureComponent<Props, State> {
 export class LogLabel extends PureComponent<Props, State> {
-  state = {
+  state: State = {
     stats: null,
     stats: null,
     showStats: false,
     showStats: false,
   };
   };

+ 2 - 1
public/app/features/explore/LogMessageAnsi.tsx

@@ -16,6 +16,7 @@ function convertCSSToStyle(css: string): Style {
 
 
     if (match && match[1] && match[2]) {
     if (match && match[1] && match[2]) {
       const key = match[1].replace(/-(a-z)/g, (_, character) => character.toUpperCase());
       const key = match[1].replace(/-(a-z)/g, (_, character) => character.toUpperCase());
+      // @ts-ignore
       accumulated[key] = match[2];
       accumulated[key] = match[2];
     }
     }
 
 
@@ -33,7 +34,7 @@ interface State {
 }
 }
 
 
 export class LogMessageAnsi extends PureComponent<Props, State> {
 export class LogMessageAnsi extends PureComponent<Props, State> {
-  state = {
+  state: State = {
     chunks: [],
     chunks: [],
     prevValue: '',
     prevValue: '',
   };
   };

+ 3 - 2
public/app/features/explore/Logs.tsx

@@ -136,7 +136,7 @@ export default class Logs extends PureComponent<Props, State> {
   };
   };
 
 
   onToggleLogLevel = (rawLevel: string, hiddenRawLevels: string[]) => {
   onToggleLogLevel = (rawLevel: string, hiddenRawLevels: string[]) => {
-    const hiddenLogLevels: LogLevel[] = hiddenRawLevels.map(level => LogLevel[level]);
+    const hiddenLogLevels: LogLevel[] = hiddenRawLevels.map((level: LogLevel) => LogLevel[level]);
     this.props.onToggleLogLevel(hiddenLogLevels);
     this.props.onToggleLogLevel(hiddenLogLevels);
   };
   };
 
 
@@ -217,12 +217,13 @@ export default class Logs extends PureComponent<Props, State> {
             <Switch label="Time" checked={showTime} onChange={this.onChangeTime} transparent />
             <Switch label="Time" checked={showTime} onChange={this.onChangeTime} transparent />
             <Switch label="Labels" checked={showLabels} onChange={this.onChangeLabels} transparent />
             <Switch label="Labels" checked={showLabels} onChange={this.onChangeLabels} transparent />
             <ToggleButtonGroup label="Dedup" transparent={true}>
             <ToggleButtonGroup label="Dedup" transparent={true}>
-              {Object.keys(LogsDedupStrategy).map((dedupType, i) => (
+              {Object.keys(LogsDedupStrategy).map((dedupType: string, i) => (
                 <ToggleButton
                 <ToggleButton
                   key={i}
                   key={i}
                   value={dedupType}
                   value={dedupType}
                   onChange={this.onChangeDedup}
                   onChange={this.onChangeDedup}
                   selected={dedupStrategy === dedupType}
                   selected={dedupStrategy === dedupType}
+                  // @ts-ignore
                   tooltip={LogsDedupDescription[dedupType]}
                   tooltip={LogsDedupDescription[dedupType]}
                 >
                 >
                   {dedupType}
                   {dedupType}

+ 3 - 2
public/app/features/explore/LogsContainer.tsx

@@ -77,7 +77,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
     });
     });
   };
   };
 
 
-  getLogRowContext = async (row: LogRowModel, options?: any) => {
+  getLogRowContext = async (row: LogRowModel, options?: any): Promise<any> => {
     const { datasourceInstance } = this.props;
     const { datasourceInstance } = this.props;
 
 
     if (datasourceInstance) {
     if (datasourceInstance) {
@@ -142,8 +142,9 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
   }
   }
 }
 }
 
 
-function mapStateToProps(state: StoreState, { exploreId }) {
+function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }) {
   const explore = state.explore;
   const explore = state.explore;
+  // @ts-ignore
   const item: ExploreItemState = explore[exploreId];
   const item: ExploreItemState = explore[exploreId];
   const {
   const {
     logsHighlighterExpressions,
     logsHighlighterExpressions,

+ 1 - 0
public/app/features/explore/QueryRow.tsx

@@ -140,6 +140,7 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
       <div className="query-row">
       <div className="query-row">
         <div className="query-row-field flex-shrink-1">
         <div className="query-row-field flex-shrink-1">
           {QueryField ? (
           {QueryField ? (
+            //@ts-ignore
             <QueryField
             <QueryField
               datasource={datasourceInstance}
               datasource={datasourceInstance}
               datasourceStatus={datasourceStatus}
               datasourceStatus={datasourceStatus}

+ 1 - 1
public/app/features/explore/QueryStatus.tsx

@@ -4,7 +4,7 @@ import ElapsedTime from './ElapsedTime';
 import { LoadingState } from '@grafana/data';
 import { LoadingState } from '@grafana/data';
 import { PanelData } from '@grafana/ui';
 import { PanelData } from '@grafana/ui';
 
 
-function formatLatency(value) {
+function formatLatency(value: number) {
   return `${(value / 1000).toFixed(1)}s`;
   return `${(value / 1000).toFixed(1)}s`;
 }
 }
 
 

+ 4 - 4
public/app/features/explore/Table.tsx

@@ -1,6 +1,6 @@
 import _ from 'lodash';
 import _ from 'lodash';
 import React, { PureComponent } from 'react';
 import React, { PureComponent } from 'react';
-import ReactTable from 'react-table';
+import ReactTable, { RowInfo } from 'react-table';
 
 
 import TableModel from 'app/core/table_model';
 import TableModel from 'app/core/table_model';
 
 
@@ -14,12 +14,12 @@ interface TableProps {
   onClickCell?: (columnKey: string, rowValue: string) => void;
   onClickCell?: (columnKey: string, rowValue: string) => void;
 }
 }
 
 
-function prepareRows(rows, columnNames) {
+function prepareRows(rows: any[], columnNames: string[]) {
   return rows.map(cells => _.zipObject(columnNames, cells));
   return rows.map(cells => _.zipObject(columnNames, cells));
 }
 }
 
 
 export default class Table extends PureComponent<TableProps> {
 export default class Table extends PureComponent<TableProps> {
-  getCellProps = (state, rowInfo, column) => {
+  getCellProps = (state: any, rowInfo: RowInfo, column: any) => {
     return {
     return {
       onClick: (e: React.SyntheticEvent) => {
       onClick: (e: React.SyntheticEvent) => {
         // Only handle click on link, not the cell
         // Only handle click on link, not the cell
@@ -44,7 +44,7 @@ export default class Table extends PureComponent<TableProps> {
       accessor: text,
       accessor: text,
       className: VALUE_REGEX.test(text) ? 'text-right' : '',
       className: VALUE_REGEX.test(text) ? 'text-right' : '',
       show: text !== 'Time',
       show: text !== 'Time',
-      Cell: row => (
+      Cell: (row: any) => (
         <span className={filterable ? 'link' : ''} title={text + ': ' + row.value}>
         <span className={filterable ? 'link' : ''} title={text + ': ' + row.value}>
           {row.value}
           {row.value}
         </span>
         </span>

+ 2 - 1
public/app/features/explore/TableContainer.tsx

@@ -36,8 +36,9 @@ export class TableContainer extends PureComponent<TableContainerProps> {
   }
   }
 }
 }
 
 
-function mapStateToProps(state: StoreState, { exploreId }) {
+function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }) {
   const explore = state.explore;
   const explore = state.explore;
+  // @ts-ignore
   const item: ExploreItemState = explore[exploreId];
   const item: ExploreItemState = explore[exploreId];
   const { loadingState, showingTable, tableResult } = item;
   const { loadingState, showingTable, tableResult } = item;
   const loading =
   const loading =

+ 1 - 0
public/app/features/explore/slate-plugins/braces.test.ts

@@ -1,3 +1,4 @@
+// @ts-ignore
 import Plain from 'slate-plain-serializer';
 import Plain from 'slate-plain-serializer';
 
 
 import BracesPlugin from './braces';
 import BracesPlugin from './braces';

+ 2 - 2
public/app/features/explore/slate-plugins/braces.ts

@@ -1,4 +1,4 @@
-const BRACES = {
+const BRACES: any = {
   '[': ']',
   '[': ']',
   '{': '}',
   '{': '}',
   '(': ')',
   '(': ')',
@@ -8,7 +8,7 @@ const NON_SELECTOR_SPACE_REGEXP = / (?![^}]+})/;
 
 
 export default function BracesPlugin() {
 export default function BracesPlugin() {
   return {
   return {
-    onKeyDown(event, change) {
+    onKeyDown(event: any, change: { value?: any; insertText?: any; deleteBackward?: any }) {
       const { value } = change;
       const { value } = change;
       if (!value.isCollapsed) {
       if (!value.isCollapsed) {
         return undefined;
         return undefined;

+ 1 - 0
public/app/features/explore/slate-plugins/clear.test.ts

@@ -1,3 +1,4 @@
+// @ts-ignore
 import Plain from 'slate-plain-serializer';
 import Plain from 'slate-plain-serializer';
 
 
 import ClearPlugin from './clear';
 import ClearPlugin from './clear';

+ 1 - 1
public/app/features/explore/slate-plugins/clear.ts

@@ -1,7 +1,7 @@
 // Clears the rest of the line after the caret
 // Clears the rest of the line after the caret
 export default function ClearPlugin() {
 export default function ClearPlugin() {
   return {
   return {
-    onKeyDown(event, change) {
+    onKeyDown(event: any, change: { value?: any; deleteForward?: any }) {
       const { value } = change;
       const { value } = change;
       if (!value.isCollapsed) {
       if (!value.isCollapsed) {
         return undefined;
         return undefined;

+ 2 - 2
public/app/features/explore/slate-plugins/newline.ts

@@ -1,4 +1,4 @@
-function getIndent(text) {
+function getIndent(text: any) {
   let offset = text.length - text.trimLeft().length;
   let offset = text.length - text.trimLeft().length;
   if (offset) {
   if (offset) {
     let indent = text[0];
     let indent = text[0];
@@ -12,7 +12,7 @@ function getIndent(text) {
 
 
 export default function NewlinePlugin() {
 export default function NewlinePlugin() {
   return {
   return {
-    onKeyDown(event, change) {
+    onKeyDown(event: any, change: { value?: any; splitBlock?: any }) {
       const { value } = change;
       const { value } = change;
       if (!value.isCollapsed) {
       if (!value.isCollapsed) {
         return undefined;
         return undefined;

+ 6 - 6
public/app/features/explore/slate-plugins/prism/index.tsx

@@ -3,7 +3,7 @@ import Prism from 'prismjs';
 
 
 const TOKEN_MARK = 'prism-token';
 const TOKEN_MARK = 'prism-token';
 
 
-export function setPrismTokens(language, field, values, alias = 'variable') {
+export function setPrismTokens(language: string, field: string | number, values: any, alias = 'variable') {
   Prism.languages[language][field] = {
   Prism.languages[language][field] = {
     alias,
     alias,
     pattern: new RegExp(`(?:^|\\s)(${values.join('|')})(?:$|\\s)`),
     pattern: new RegExp(`(?:^|\\s)(${values.join('|')})(?:$|\\s)`),
@@ -17,7 +17,7 @@ export function setPrismTokens(language, field, values, alias = 'variable') {
  * (Adapted to handle nested grammar definitions.)
  * (Adapted to handle nested grammar definitions.)
  */
  */
 
 
-export default function PrismPlugin({ definition, language }) {
+export default function PrismPlugin({ definition, language }: { definition: any; language: string }) {
   if (definition) {
   if (definition) {
     // Don't override exising modified definitions
     // Don't override exising modified definitions
     Prism.languages[language] = Prism.languages[language] || definition;
     Prism.languages[language] = Prism.languages[language] || definition;
@@ -31,7 +31,7 @@ export default function PrismPlugin({ definition, language }) {
      * @return {Element}
      * @return {Element}
      */
      */
 
 
-    renderMark(props) {
+    renderMark(props: any): JSX.Element {
       const { children, mark } = props;
       const { children, mark } = props;
       // Only apply spans to marks identified by this plugin
       // Only apply spans to marks identified by this plugin
       if (mark.type !== TOKEN_MARK) {
       if (mark.type !== TOKEN_MARK) {
@@ -48,13 +48,13 @@ export default function PrismPlugin({ definition, language }) {
      * @return {Array}
      * @return {Array}
      */
      */
 
 
-    decorateNode(node) {
+    decorateNode(node: any): any[] {
       if (node.type !== 'paragraph') {
       if (node.type !== 'paragraph') {
         return [];
         return [];
       }
       }
 
 
       const texts = node.getTexts().toArray();
       const texts = node.getTexts().toArray();
-      const tstring = texts.map(t => t.text).join('\n');
+      const tstring = texts.map((t: { text: any }) => t.text).join('\n');
       const grammar = Prism.languages[language];
       const grammar = Prism.languages[language];
       const tokens = Prism.tokenize(tstring, grammar);
       const tokens = Prism.tokenize(tstring, grammar);
       const decorations: any[] = [];
       const decorations: any[] = [];
@@ -64,7 +64,7 @@ export default function PrismPlugin({ definition, language }) {
       let endOffset = 0;
       let endOffset = 0;
       let start = 0;
       let start = 0;
 
 
-      function processToken(token, acc?) {
+      function processToken(token: any, acc?: string) {
         // Accumulate token types down the tree
         // Accumulate token types down the tree
         const types = `${acc || ''} ${token.type || ''} ${token.alias || ''}`;
         const types = `${acc || ''} ${token.type || ''} ${token.alias || ''}`;
 
 

+ 2 - 2
public/app/features/explore/slate-plugins/runner.ts

@@ -1,6 +1,6 @@
-export default function RunnerPlugin({ handler }) {
+export default function RunnerPlugin({ handler }: any) {
   return {
   return {
-    onKeyDown(event) {
+    onKeyDown(event: any) {
       // Handle enter
       // Handle enter
       if (handler && event.key === 'Enter' && !event.shiftKey) {
       if (handler && event.key === 'Enter' && !event.shiftKey) {
         // Submit on Enter
         // Submit on Enter

+ 6 - 6
public/app/features/explore/state/epics/processQueryResultsEpic.test.ts

@@ -41,9 +41,9 @@ describe('processQueryResultsEpic', () => {
         it('then resetQueryErrorAction and querySuccessAction are dispatched and eventBridge emits correct message', () => {
         it('then resetQueryErrorAction and querySuccessAction are dispatched and eventBridge emits correct message', () => {
           const { datasourceId, exploreId, state, eventBridge } = mockExploreState();
           const { datasourceId, exploreId, state, eventBridge } = mockExploreState();
           const { latency, series, loadingState } = testContext();
           const { latency, series, loadingState } = testContext();
-          const graphResult = [];
+          const graphResult: any[] = [];
           const tableResult = new TableModel();
           const tableResult = new TableModel();
-          const logsResult = null;
+          const logsResult: any = null;
 
 
           epicTester(processQueryResultsEpic, state)
           epicTester(processQueryResultsEpic, state)
             .whenActionIsDispatched(
             .whenActionIsDispatched(
@@ -64,9 +64,9 @@ describe('processQueryResultsEpic', () => {
           it('then correct actions are dispatched', () => {
           it('then correct actions are dispatched', () => {
             const { datasourceId, exploreId, state } = mockExploreState({ scanning: true });
             const { datasourceId, exploreId, state } = mockExploreState({ scanning: true });
             const { latency, series, loadingState } = testContext();
             const { latency, series, loadingState } = testContext();
-            const graphResult = [];
+            const graphResult: any[] = [];
             const tableResult = new TableModel();
             const tableResult = new TableModel();
-            const logsResult = null;
+            const logsResult: any = null;
 
 
             epicTester(processQueryResultsEpic, state)
             epicTester(processQueryResultsEpic, state)
               .whenActionIsDispatched(
               .whenActionIsDispatched(
@@ -84,9 +84,9 @@ describe('processQueryResultsEpic', () => {
           it('then correct actions are dispatched', () => {
           it('then correct actions are dispatched', () => {
             const { datasourceId, exploreId, state } = mockExploreState({ scanning: true });
             const { datasourceId, exploreId, state } = mockExploreState({ scanning: true });
             const { latency, loadingState } = testContext();
             const { latency, loadingState } = testContext();
-            const graphResult = [];
+            const graphResult: any[] = [];
             const tableResult = new TableModel();
             const tableResult = new TableModel();
-            const logsResult = null;
+            const logsResult: any = null;
 
 
             epicTester(processQueryResultsEpic, state)
             epicTester(processQueryResultsEpic, state)
               .whenActionIsDispatched(
               .whenActionIsDispatched(

+ 4 - 4
public/app/features/explore/state/epics/runQueriesBatchEpic.test.ts

@@ -106,12 +106,12 @@ describe('runQueriesBatchEpic', () => {
         it('then correct actions are dispatched', () => {
         it('then correct actions are dispatched', () => {
           const { exploreId, state, datasourceId } = mockExploreState();
           const { exploreId, state, datasourceId } = mockExploreState();
           const unsubscribe = jest.fn();
           const unsubscribe = jest.fn();
-          const serieA = {
+          const serieA: any = {
             fields: [],
             fields: [],
             rows: [],
             rows: [],
             refId: 'A',
             refId: 'A',
           };
           };
-          const serieB = {
+          const serieB: any = {
             fields: [],
             fields: [],
             rows: [],
             rows: [],
             refId: 'B',
             refId: 'B',
@@ -171,12 +171,12 @@ describe('runQueriesBatchEpic', () => {
         it('then correct actions are dispatched', () => {
         it('then correct actions are dispatched', () => {
           const { exploreId, state, datasourceId, history } = mockExploreState();
           const { exploreId, state, datasourceId, history } = mockExploreState();
           const unsubscribe = jest.fn();
           const unsubscribe = jest.fn();
-          const serieA = {
+          const serieA: any = {
             fields: [],
             fields: [],
             rows: [],
             rows: [],
             refId: 'A',
             refId: 'A',
           };
           };
-          const serieB = {
+          const serieB: any = {
             fields: [],
             fields: [],
             rows: [],
             rows: [],
             refId: 'B',
             refId: 'B',

+ 1 - 1
public/app/features/explore/state/epics/runQueriesEpic.test.ts

@@ -46,7 +46,7 @@ describe('runQueriesEpic', () => {
 
 
       describe('and we have no queries', () => {
       describe('and we have no queries', () => {
         it('then clearQueriesAction and stateSaveAction are dispatched', () => {
         it('then clearQueriesAction and stateSaveAction are dispatched', () => {
-          const queries = [];
+          const queries: any[] = [];
           const { exploreId, state } = mockExploreState({ queries });
           const { exploreId, state } = mockExploreState({ queries });
 
 
           epicTester(runQueriesEpic, state)
           epicTester(runQueriesEpic, state)

+ 1 - 1
public/app/features/explore/state/epics/timeEpic.ts

@@ -37,7 +37,7 @@ export const timeEpic: Epic<ActionOf<any>, ActionOf<any>, StoreState> = (
         time: range.raw,
         time: range.raw,
         refresh: false,
         refresh: false,
         getTimezone: () => timeZone.raw,
         getTimezone: () => timeZone.raw,
-        timeRangeUpdated: () => undefined,
+        timeRangeUpdated: (): any => undefined,
       });
       });
 
 
       return changeRangeAction({ exploreId, range, absoluteRange });
       return changeRangeAction({ exploreId, range, absoluteRange });

+ 2 - 2
public/app/features/explore/state/reducers.test.ts

@@ -146,7 +146,7 @@ describe('Explore item reducer', () => {
             queries,
             queries,
             queryKeys,
             queryKeys,
           };
           };
-          const expectedState = {
+          const expectedState: any = {
             datasourceInstance,
             datasourceInstance,
             StartPage,
             StartPage,
             showingStartPage: true,
             showingStartPage: true,
@@ -175,7 +175,7 @@ describe('Explore item reducer', () => {
           showingStartPage: true,
           showingStartPage: true,
           range: null,
           range: null,
         };
         };
-        const expectedState = {
+        const expectedState: any = {
           queryIntervals: {
           queryIntervals: {
             interval: '1s',
             interval: '1s',
             intervalMs: 1000,
             intervalMs: 1000,

+ 1 - 1
public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts

@@ -332,7 +332,7 @@ export default class AzureMonitorDatasource {
       this.apiPreviewVersion
       this.apiPreviewVersion
     );
     );
 
 
-    return this.doRequest(url).then(result => {
+    return this.doRequest(url).then((result: any) => {
       return ResponseParser.parseResponseValues(result, 'name', 'properties.metricNamespaceName');
       return ResponseParser.parseResponseValues(result, 'name', 'properties.metricNamespaceName');
     });
     });
   }
   }

+ 1 - 1
scripts/ci-frontend-metrics.sh

@@ -3,7 +3,7 @@
 echo -e "Collecting code stats (typescript errors & more)"
 echo -e "Collecting code stats (typescript errors & more)"
 
 
 
 
-ERROR_COUNT_LIMIT=1670
+ERROR_COUNT_LIMIT=800
 DIRECTIVES_LIMIT=172
 DIRECTIVES_LIMIT=172
 CONTROLLERS_LIMIT=139
 CONTROLLERS_LIMIT=139
 
 

+ 21 - 1
yarn.lock

@@ -2974,6 +2974,11 @@
     "@types/express-serve-static-core" "*"
     "@types/express-serve-static-core" "*"
     "@types/serve-static" "*"
     "@types/serve-static" "*"
 
 
+"@types/file-saver@^2.0.1":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.1.tgz#e18eb8b069e442f7b956d313f4fadd3ef887354e"
+  integrity sha512-g1QUuhYVVAamfCifK7oB7G3aIl4BbOyzDOqVyUfEr4tfBKrXfeH+M+Tg7HKCXSrbzxYdhyCP7z9WbKo0R2hBCw==
+
 "@types/geojson@*":
 "@types/geojson@*":
   version "7946.0.7"
   version "7946.0.7"
   resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad"
   resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad"
@@ -3218,9 +3223,10 @@
   dependencies:
   dependencies:
     "@types/react" "*"
     "@types/react" "*"
 
 
-"@types/react-redux@^7.0.8":
+"@types/react-redux@7.0.8":
   version "7.0.8"
   version "7.0.8"
   resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.0.8.tgz#c928863058e334d41031c6bedd0f113bc514e234"
   resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.0.8.tgz#c928863058e334d41031c6bedd0f113bc514e234"
+  integrity sha512-vIBC15E84ehN6RzdGwRVa41whp9e4CkfPm+WfD0r6y6vqBf4tQPKZeKEBfLLM8k79uSwQC7rh3rH/MFaN1IESQ==
   dependencies:
   dependencies:
     "@types/hoist-non-react-statics" "^3.3.0"
     "@types/hoist-non-react-statics" "^3.3.0"
     "@types/react" "*"
     "@types/react" "*"
@@ -3234,6 +3240,13 @@
     "@types/react-dom" "*"
     "@types/react-dom" "*"
     "@types/react-transition-group" "*"
     "@types/react-transition-group" "*"
 
 
+"@types/react-table@6.8.5":
+  version "6.8.5"
+  resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-6.8.5.tgz#deb2bf2fcedcfb81e9020edbb7df0d8459ca348b"
+  integrity sha512-ueCsAadG1IwuuAZM+MWf2SoxbccSWweyQa9YG6xGN5cOVK3SayPOJW4MsUHGpY0V/Q+iZWgohpasliiao29O6g==
+  dependencies:
+    "@types/react" "*"
+
 "@types/react-test-renderer@16.8.1":
 "@types/react-test-renderer@16.8.1":
   version "16.8.1"
   version "16.8.1"
   resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.8.1.tgz#96f3ce45a3a41c94eca532a99103dd3042c9d055"
   resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.8.1.tgz#96f3ce45a3a41c94eca532a99103dd3042c9d055"
@@ -3286,6 +3299,13 @@
   dependencies:
   dependencies:
     redux "^3.6.0"
     redux "^3.6.0"
 
 
+"@types/redux-mock-store@1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.1.tgz#90ca701d640aef7c007f564a9a4f8dc03180b0f7"
+  integrity sha512-1egEnh2/+sRRKImnCo5EMVm0Uxu4fBHeLHk/inhSp/VpE93It8lk3gYeNfehUgXd6OzqP5LLA9kzO9x7o3WfwA==
+  dependencies:
+    redux "^4.0.0"
+
 "@types/relateurl@*":
 "@types/relateurl@*":
   version "0.2.28"
   version "0.2.28"
   resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"
   resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"