From c2530be07dfb30c3743c88f20335712f16d645cb Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 26 Apr 2019 19:14:48 +0200 Subject: [PATCH 1/8] Build: Use isolated modules for ts-jest (#16786) --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index c5c6bcb9f5f1..09342e147207 100644 --- a/jest.config.js +++ b/jest.config.js @@ -23,4 +23,5 @@ module.exports = { "./public/test/jest-setup.ts" ], "snapshotSerializers": ["enzyme-to-json/serializer"], + "globals": { "ts-jest": { "isolatedModules": true } }, }; From e694fd8fb6e69eca1aa69bd5ae7a4fd84a760dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 26 Apr 2019 19:15:37 +0200 Subject: [PATCH 2/8] ThresholdEditor: Minor style fix for smaller screens (#16791) --- .../src/components/ThresholdsEditor/_ThresholdsEditor.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss b/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss index 0f2bb6669ca4..4662be0322f3 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss +++ b/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss @@ -31,6 +31,7 @@ display: flex; align-items: center; justify-content: center; + flex-shrink: 0; cursor: pointer; &:hover { @@ -40,6 +41,7 @@ .thresholds-row-color-indicator { width: 10px; + flex-shrink: 0; } .thresholds-row-input { From e38762665b7647297e80692ac185871db378dfb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 26 Apr 2019 19:16:03 +0200 Subject: [PATCH 3/8] UX: Improve Grafana usage for smaller screens (#16783) * Mobile: Switch to mobile view already at md or lower breakpoint * UX: Tweaked breakpoint so that media-breakpoint-up(md) will only apply to screens larger than normal ipad * Updated snapshots --- .../RefreshPicker/_RefreshPicker.scss | 2 +- .../ThresholdsEditor.test.tsx.snap | 4 +-- packages/grafana-ui/src/themes/default.ts | 2 +- .../app/features/explore/ExploreToolbar.tsx | 6 ++-- public/sass/_variables.generated.scss | 2 +- public/sass/components/_navbar.scss | 28 +++++++++++-------- public/sass/components/_search.scss | 2 +- public/sass/components/_sidemenu.scss | 13 +++++---- public/sass/pages/_explore.scss | 25 ++++------------- 9 files changed, 37 insertions(+), 47 deletions(-) diff --git a/packages/grafana-ui/src/components/RefreshPicker/_RefreshPicker.scss b/packages/grafana-ui/src/components/RefreshPicker/_RefreshPicker.scss index 7d922324dc5b..bfa67d87582c 100644 --- a/packages/grafana-ui/src/components/RefreshPicker/_RefreshPicker.scss +++ b/packages/grafana-ui/src/components/RefreshPicker/_RefreshPicker.scss @@ -30,7 +30,7 @@ } } - @include media-breakpoint-up(md) { + @include media-breakpoint-up(sm) { display: block; } } diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/__snapshots__/ThresholdsEditor.test.tsx.snap b/packages/grafana-ui/src/components/ThresholdsEditor/__snapshots__/ThresholdsEditor.test.tsx.snap index 09596e066dd6..faa59ddb0460 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/__snapshots__/ThresholdsEditor.test.tsx.snap +++ b/packages/grafana-ui/src/components/ThresholdsEditor/__snapshots__/ThresholdsEditor.test.tsx.snap @@ -109,7 +109,7 @@ exports[`Render should render with base threshold 1`] = ` }, "breakpoints": Object { "lg": "992px", - "md": "768px", + "md": "769px", "sm": "544px", "xl": "1200px", "xs": "0", @@ -272,7 +272,7 @@ exports[`Render should render with base threshold 1`] = ` }, "breakpoints": Object { "lg": "992px", - "md": "768px", + "md": "769px", "sm": "544px", "xl": "1200px", "xs": "0", diff --git a/packages/grafana-ui/src/themes/default.ts b/packages/grafana-ui/src/themes/default.ts index dadaa2769efb..4a0e42312b7b 100644 --- a/packages/grafana-ui/src/themes/default.ts +++ b/packages/grafana-ui/src/themes/default.ts @@ -42,7 +42,7 @@ const theme: GrafanaThemeCommons = { breakpoints: { xs: '0', sm: '544px', - md: '768px', + md: '769px', // 1 more than regular ipad in portrait lg: '992px', xl: '1200px', }, diff --git a/public/app/features/explore/ExploreToolbar.tsx b/public/app/features/explore/ExploreToolbar.tsx index 4222b000eb9c..0ee34958f4fe 100644 --- a/public/app/features/explore/ExploreToolbar.tsx +++ b/public/app/features/explore/ExploreToolbar.tsx @@ -38,9 +38,9 @@ const createResponsiveButton = (options: { return ( ); }; @@ -172,7 +172,7 @@ export class UnConnectedExploreToolbar extends PureComponent {
-
diff --git a/public/sass/_variables.generated.scss b/public/sass/_variables.generated.scss index 16277534f2bd..510e5649974e 100644 --- a/public/sass/_variables.generated.scss +++ b/public/sass/_variables.generated.scss @@ -67,7 +67,7 @@ $spacers: ( $grid-breakpoints: ( xs: 0, sm: 544px, - md: 768px, + md: 769px, lg: 992px, xl: 1200px, ) !default; diff --git a/public/sass/components/_navbar.scss b/public/sass/components/_navbar.scss index 0128defe1610..8c950f728590 100644 --- a/public/sass/components/_navbar.scss +++ b/public/sass/components/_navbar.scss @@ -9,6 +9,11 @@ transition-duration: 350ms; transition-timing-function: ease-in-out; transition-property: box-shadow, border-bottom; + + @include media-breakpoint-up(md) { + padding-left: $dashboard-padding; + margin-left: 0; + } } @mixin navbar-alt-look() { @@ -75,13 +80,18 @@ opacity: 0.75; margin-right: 10px; display: none; + + @include media-breakpoint-up(md) { + display: inline-block; + } } &--folder { color: $text-color-weak; + display: none; - @include media-breakpoint-down(md) { - display: none; + @include media-breakpoint-up(lg) { + display: inline-block; } } } @@ -170,17 +180,11 @@ &--secondary { @include buttonBackground($btn-secondary-bg, $btn-secondary-bg-hl); } -} -@include media-breakpoint-up(sm) { - .navbar { - padding-left: 20px; - margin-left: 0; - } - - .navbar-page-btn { - .gicon { - display: inline-block; + @include media-breakpoint-down(lg) { + .btn-title { + margin-left: $space-xs; + display: none; } } } diff --git a/public/sass/components/_search.scss b/public/sass/components/_search.scss index 0e8008926190..196075d20b50 100644 --- a/public/sass/components/_search.scss +++ b/public/sass/components/_search.scss @@ -262,7 +262,7 @@ background: $panel-bg; } -@include media-breakpoint-up(sm) { +@include media-breakpoint-up(md) { .search-container { left: $side-menu-width; } diff --git a/public/sass/components/_sidemenu.scss b/public/sass/components/_sidemenu.scss index 7e68ed8d3412..334378036c38 100644 --- a/public/sass/components/_sidemenu.scss +++ b/public/sass/components/_sidemenu.scss @@ -1,3 +1,5 @@ +$mobile-menu-breakpoint: md; + .sidemenu { position: fixed; display: flex; @@ -17,7 +19,7 @@ display: none; } - @include media-breakpoint-up(sm) { + @include media-breakpoint-up($mobile-menu-breakpoint) { background: $side-menu-bg; height: auto; box-shadow: $side-menu-shadow; @@ -46,7 +48,7 @@ .sidemenu__bottom { display: none; - @include media-breakpoint-up(sm) { + @include media-breakpoint-up($mobile-menu-breakpoint) { display: block; } } @@ -55,7 +57,7 @@ position: relative; @include left-brand-border(); - @include media-breakpoint-up(sm) { + @include media-breakpoint-up($mobile-menu-breakpoint) { &.active, &:hover { background-color: $side-menu-item-hover-bg; @@ -214,10 +216,10 @@ li.sidemenu-org-switcher { } } -@include media-breakpoint-down(xs) { +@include media-breakpoint-down(sm) { .sidemenu-open--xs { li { - font-size: $font-size-lg; + font-size: $font-size-md; } .sidemenu { @@ -283,7 +285,6 @@ li.sidemenu-org-switcher { position: unset; width: 100%; float: none; - margin-top: $space-sm; margin-bottom: $space-sm; > li > a { diff --git a/public/sass/pages/_explore.scss b/public/sass/pages/_explore.scss index c7bea01df4cf..fd0a14193abc 100644 --- a/public/sass/pages/_explore.scss +++ b/public/sass/pages/_explore.scss @@ -31,11 +31,15 @@ flex-flow: row wrap; justify-content: flex-start; height: auto; - padding: 0 $dashboard-padding; + padding: 0 $dashboard-padding 0 50px; border-bottom: 1px solid #0000; transition-duration: 0.35s; transition-timing-function: ease-in-out; transition-property: box-shadow, border-bottom; + + @include media-breakpoint-up(md) { + padding-left: $dashboard-padding; + } } .explore-toolbar-item { @@ -65,11 +69,6 @@ font-size: 18px; min-height: 55px; line-height: 55px; - justify-content: space-between; - margin-left: $space-xl; -} - -.explore-toolbar-header { justify-content: space-between; align-items: center; } @@ -126,12 +125,6 @@ } } -@media only screen and (max-width: 803px) { - .btn-title { - display: none; - } -} - @media only screen and (max-width: 702px) { .explore-toolbar-content-item:first-child { padding-left: 2px; @@ -139,14 +132,6 @@ } } -@media only screen and (max-width: 544px) { - .explore-toolbar-header-title { - .navbar-page-btn { - margin-left: $dashboard-padding; - } - } -} - .explore { flex: 1 1 auto; } From 060e97bea8863904dded52f44ff37a4a7a566cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 26 Apr 2019 19:16:38 +0200 Subject: [PATCH 4/8] Plugins: ReactPanelPlugin to VizPanelPlugin (#16779) * Plugins: ReactPanelPlugin renamed * Plugins: renamed PanelPlugin to PanelPluginMeta and VizPanelPlugin to PanelPlugin --- packages/grafana-ui/src/types/panel.ts | 2 +- public/app/core/config.ts | 4 ++-- .../DashExportModal/DashboardExporter.test.ts | 8 ++++---- .../DashExportModal/DashboardExporter.ts | 4 ++-- .../dashboard/dashgrid/DashboardPanel.tsx | 16 ++++++++-------- .../features/dashboard/dashgrid/PanelChrome.tsx | 8 ++++---- .../dashboard/dashgrid/PanelPluginNotFound.tsx | 8 ++++---- .../dashboard/panel_editor/PanelEditor.tsx | 6 +++--- .../dashboard/panel_editor/VisualizationTab.tsx | 14 +++++++------- .../dashboard/panel_editor/VizPickerSearch.tsx | 4 ++-- .../dashboard/panel_editor/VizTypePicker.tsx | 14 +++++++------- .../panel_editor/VizTypePickerPlugin.tsx | 4 ++-- .../features/dashboard/state/PanelModel.test.ts | 6 +++--- .../app/features/dashboard/state/PanelModel.ts | 16 ++++++++-------- .../features/plugins/__mocks__/pluginMocks.ts | 6 +++--- public/app/features/plugins/plugin_loader.ts | 8 ++++---- public/app/plugins/panel/bargauge/module.tsx | 4 ++-- public/app/plugins/panel/gauge/module.tsx | 4 ++-- public/app/plugins/panel/graph2/module.tsx | 4 ++-- public/app/plugins/panel/piechart/module.tsx | 4 ++-- public/app/plugins/panel/singlestat2/module.tsx | 4 ++-- public/app/plugins/panel/table2/module.tsx | 4 ++-- public/app/plugins/panel/text2/module.tsx | 4 ++-- public/app/types/plugins.ts | 8 +++----- public/test/specs/helpers.ts | 4 ++-- 25 files changed, 83 insertions(+), 85 deletions(-) diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index c06ea7acd42b..5354df29d1de 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -53,7 +53,7 @@ export type PanelTypeChangedHandler = ( prevOptions: any ) => Partial; -export class ReactPanelPlugin { +export class PanelPlugin { panel: ComponentType>; editor?: ComponentClass>; defaults?: TOptions; diff --git a/public/app/core/config.ts b/public/app/core/config.ts index 58aaedffa7cb..4d83cb8f5b17 100644 --- a/public/app/core/config.ts +++ b/public/app/core/config.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { PanelPlugin } from 'app/types/plugins'; +import { PanelPluginMeta } from 'app/types/plugins'; import { GrafanaTheme, getTheme, GrafanaThemeType, DataSourceInstanceSettings } from '@grafana/ui'; export interface BuildInfo { @@ -13,7 +13,7 @@ export interface BuildInfo { export class Settings { datasources: { [str: string]: DataSourceInstanceSettings }; - panels: { [key: string]: PanelPlugin }; + panels: { [key: string]: PanelPluginMeta }; appSubUrl: string; windowTitlePrefix: string; buildInfo: BuildInfo; diff --git a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts index 61e0ca93c38c..76151e26c158 100644 --- a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts +++ b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts @@ -9,7 +9,7 @@ import config from 'app/core/config'; import { DashboardExporter } from './DashboardExporter'; import { DashboardModel } from '../../state/DashboardModel'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { PanelPlugin } from 'app/types'; +import { PanelPluginMeta } from 'app/types'; describe('given dashboard with repeated panels', () => { let dash: any, exported: any; @@ -97,19 +97,19 @@ describe('given dashboard with repeated panels', () => { id: 'graph', name: 'Graph', info: { version: '1.1.0' }, - } as PanelPlugin; + } as PanelPluginMeta; config.panels['table'] = { id: 'table', name: 'Table', info: { version: '1.1.1' }, - } as PanelPlugin; + } as PanelPluginMeta; config.panels['heatmap'] = { id: 'heatmap', name: 'Heatmap', info: { version: '1.1.2' }, - } as PanelPlugin; + } as PanelPluginMeta; dash = new DashboardModel(dash, {}); const exporter = new DashboardExporter(datasourceSrvStub); diff --git a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts index 6be4dd2e2808..78d84350b572 100644 --- a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts +++ b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts @@ -4,7 +4,7 @@ import config from 'app/core/config'; import { DashboardModel } from '../../state/DashboardModel'; import DatasourceSrv from 'app/features/plugins/datasource_srv'; import { PanelModel } from 'app/features/dashboard/state'; -import { PanelPlugin } from 'app/types/plugins'; +import { PanelPluginMeta } from 'app/types/plugins'; interface Input { name: string; @@ -119,7 +119,7 @@ export class DashboardExporter { } } - const panelDef: PanelPlugin = config.panels[panel.type]; + const panelDef: PanelPluginMeta = config.panels[panel.type]; if (panelDef) { requires['panel' + panelDef.id] = { type: 'panel', diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index cac0c5739009..44ae626cc205 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -17,8 +17,8 @@ import { PanelResizer } from './PanelResizer'; // Types import { PanelModel, DashboardModel } from '../state'; -import { PanelPlugin } from 'app/types'; -import { AngularPanelPlugin, ReactPanelPlugin } from '@grafana/ui/src/types/panel'; +import { PanelPluginMeta } from 'app/types'; +import { AngularPanelPlugin, PanelPlugin } from '@grafana/ui/src/types/panel'; import { AutoSizer } from 'react-virtualized'; export interface Props { @@ -29,7 +29,7 @@ export interface Props { } export interface State { - plugin: PanelPlugin; + plugin: PanelPluginMeta; angularPanel: AngularComponent; } @@ -61,7 +61,7 @@ export class DashboardPanel extends PureComponent { return ; } - onPluginTypeChanged = (plugin: PanelPlugin) => { + onPluginTypeChanged = (plugin: PanelPluginMeta) => { this.loadPlugin(plugin.id); }; @@ -92,7 +92,7 @@ export class DashboardPanel extends PureComponent { } } - async importPanelPluginModule(plugin: PanelPlugin): Promise { + async importPanelPluginModule(plugin: PanelPluginMeta): Promise { if (plugin.hasBeenImported) { return plugin; } @@ -101,8 +101,8 @@ export class DashboardPanel extends PureComponent { const importedPlugin = await importPanelPlugin(plugin.module); if (importedPlugin instanceof AngularPanelPlugin) { plugin.angularPlugin = importedPlugin as AngularPanelPlugin; - } else if (importedPlugin instanceof ReactPanelPlugin) { - plugin.reactPlugin = importedPlugin as ReactPanelPlugin; + } else if (importedPlugin instanceof PanelPlugin) { + plugin.vizPlugin = importedPlugin as PanelPlugin; } } catch (e) { plugin = getPanelPluginNotFound(plugin.id); @@ -210,7 +210,7 @@ export class DashboardPanel extends PureComponent { onMouseLeave={this.onMouseLeave} style={styles} > - {plugin.reactPlugin && this.renderReactPanel()} + {plugin.vizPlugin && this.renderReactPanel()} {plugin.angularPlugin && this.renderAngularPanel()} )} diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index c69e7be0c4e6..148c559f6aac 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -16,7 +16,7 @@ import config from 'app/core/config'; // Types import { DashboardModel, PanelModel } from '../state'; -import { PanelPlugin } from 'app/types'; +import { PanelPluginMeta } from 'app/types'; import { LoadingState, PanelData } from '@grafana/ui'; import { ScopedVars } from '@grafana/ui'; @@ -30,7 +30,7 @@ const DEFAULT_PLUGIN_ERROR = 'Error in plugin'; export interface Props { panel: PanelModel; dashboard: DashboardModel; - plugin: PanelPlugin; + plugin: PanelPluginMeta; isFullscreen: boolean; width: number; height: number; @@ -216,7 +216,7 @@ export class PanelChrome extends PureComponent { renderPanel(width: number, height: number): JSX.Element { const { panel, plugin } = this.props; const { renderCounter, data, isFirstLoad } = this.state; - const PanelComponent = plugin.reactPlugin.panel; + const PanelComponent = plugin.vizPlugin.panel; // This is only done to increase a counter that is used by backend // image rendering (phantomjs/headless chrome) to know when to capture image @@ -237,7 +237,7 @@ export class PanelChrome extends PureComponent { { } } -export function getPanelPluginNotFound(id: string): PanelPlugin { +export function getPanelPluginNotFound(id: string): PanelPluginMeta { const NotFound = class NotFound extends PureComponent { render() { return ; @@ -63,7 +63,7 @@ export function getPanelPluginNotFound(id: string): PanelPlugin { updated: '', version: '', }, - reactPlugin: new ReactPanelPlugin(NotFound), + vizPlugin: new PanelPlugin(NotFound), angularPlugin: null, }; } diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index 1bc42a2fd88b..bc49207e5cc4 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -13,16 +13,16 @@ import { AngularComponent } from 'app/core/services/AngularLoader'; import { PanelModel } from '../state/PanelModel'; import { DashboardModel } from '../state/DashboardModel'; -import { PanelPlugin } from 'app/types/plugins'; +import { PanelPluginMeta } from 'app/types/plugins'; import { Tooltip } from '@grafana/ui'; interface PanelEditorProps { panel: PanelModel; dashboard: DashboardModel; - plugin: PanelPlugin; + plugin: PanelPluginMeta; angularPanel?: AngularComponent; - onTypeChanged: (newType: PanelPlugin) => void; + onTypeChanged: (newType: PanelPluginMeta) => void; } interface PanelEditorTab { diff --git a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx index a8f2c28c2c0b..3247cf631a76 100644 --- a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx +++ b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx @@ -16,16 +16,16 @@ import { FadeIn } from 'app/core/components/Animations/FadeIn'; // Types import { PanelModel } from '../state'; import { DashboardModel } from '../state'; -import { PanelPlugin } from 'app/types/plugins'; +import { PanelPluginMeta } from 'app/types/plugins'; import { VizPickerSearch } from './VizPickerSearch'; import PluginStateinfo from 'app/features/plugins/PluginStateInfo'; interface Props { panel: PanelModel; dashboard: DashboardModel; - plugin: PanelPlugin; + plugin: PanelPluginMeta; angularPanel?: AngularComponent; - onTypeChanged: (newType: PanelPlugin) => void; + onTypeChanged: (newType: PanelPluginMeta) => void; updateLocation: typeof updateLocation; urlOpenVizPicker: boolean; } @@ -54,7 +54,7 @@ export class VisualizationTab extends PureComponent { getReactPanelOptions = () => { const { panel, plugin } = this.props; - return panel.getOptions(plugin.reactPlugin.defaults); + return panel.getOptions(plugin.vizPlugin.defaults); }; renderPanelOptions() { @@ -64,8 +64,8 @@ export class VisualizationTab extends PureComponent { return
(this.element = element)} />; } - if (plugin.reactPlugin) { - const PanelEditor = plugin.reactPlugin.editor; + if (plugin.vizPlugin) { + const PanelEditor = plugin.vizPlugin.editor; if (PanelEditor) { return ; @@ -197,7 +197,7 @@ export class VisualizationTab extends PureComponent { } }; - onTypeChanged = (plugin: PanelPlugin) => { + onTypeChanged = (plugin: PanelPluginMeta) => { if (plugin.id === this.props.plugin.id) { this.setState({ isVizPickerOpen: false }); } else { diff --git a/public/app/features/dashboard/panel_editor/VizPickerSearch.tsx b/public/app/features/dashboard/panel_editor/VizPickerSearch.tsx index ddf9485dab90..beb9a8508f96 100644 --- a/public/app/features/dashboard/panel_editor/VizPickerSearch.tsx +++ b/public/app/features/dashboard/panel_editor/VizPickerSearch.tsx @@ -2,10 +2,10 @@ import React, { PureComponent } from 'react'; import { FilterInput } from 'app/core/components/FilterInput/FilterInput'; -import { PanelPlugin } from 'app/types'; +import { PanelPluginMeta } from 'app/types'; interface Props { - plugin: PanelPlugin; + plugin: PanelPluginMeta; searchQuery: string; onChange: (query: string) => void; onClose: () => void; diff --git a/public/app/features/dashboard/panel_editor/VizTypePicker.tsx b/public/app/features/dashboard/panel_editor/VizTypePicker.tsx index efbfed65a99d..71a02f9644ee 100644 --- a/public/app/features/dashboard/panel_editor/VizTypePicker.tsx +++ b/public/app/features/dashboard/panel_editor/VizTypePicker.tsx @@ -1,13 +1,13 @@ import React, { PureComponent } from 'react'; import config from 'app/core/config'; -import { PanelPlugin } from 'app/types/plugins'; +import { PanelPluginMeta } from 'app/types/plugins'; import VizTypePickerPlugin from './VizTypePickerPlugin'; import { EmptySearchResult } from '@grafana/ui'; export interface Props { - current: PanelPlugin; - onTypeChanged: (newType: PanelPlugin) => void; + current: PanelPluginMeta; + onTypeChanged: (newType: PanelPluginMeta) => void; searchQuery: string; onClose: () => void; } @@ -25,16 +25,16 @@ export class VizTypePicker extends PureComponent { return filteredPluginList.length - 1; } - get getPanelPlugins(): PanelPlugin[] { + get getPanelPlugins(): PanelPluginMeta[] { const allPanels = config.panels; return Object.keys(allPanels) .filter(key => allPanels[key]['hideFromList'] === false) .map(key => allPanels[key]) - .sort((a: PanelPlugin, b: PanelPlugin) => a.sort - b.sort); + .sort((a: PanelPluginMeta, b: PanelPluginMeta) => a.sort - b.sort); } - renderVizPlugin = (plugin: PanelPlugin, index: number) => { + renderVizPlugin = (plugin: PanelPluginMeta, index: number) => { const { onTypeChanged } = this.props; const isCurrent = plugin.id === this.props.current.id; @@ -48,7 +48,7 @@ export class VizTypePicker extends PureComponent { ); }; - getFilteredPluginList = (): PanelPlugin[] => { + getFilteredPluginList = (): PanelPluginMeta[] => { const { searchQuery } = this.props; const regex = new RegExp(searchQuery, 'i'); const pluginList = this.pluginList; diff --git a/public/app/features/dashboard/panel_editor/VizTypePickerPlugin.tsx b/public/app/features/dashboard/panel_editor/VizTypePickerPlugin.tsx index 430cf7c7ee39..a91917e918c6 100644 --- a/public/app/features/dashboard/panel_editor/VizTypePickerPlugin.tsx +++ b/public/app/features/dashboard/panel_editor/VizTypePickerPlugin.tsx @@ -1,10 +1,10 @@ import React from 'react'; import classNames from 'classnames'; -import { PanelPlugin } from 'app/types/plugins'; +import { PanelPluginMeta } from 'app/types/plugins'; interface Props { isCurrent: boolean; - plugin: PanelPlugin; + plugin: PanelPluginMeta; onClick: () => void; } diff --git a/public/app/features/dashboard/state/PanelModel.test.ts b/public/app/features/dashboard/state/PanelModel.test.ts index 366c933d58d6..6cde516d1af6 100644 --- a/public/app/features/dashboard/state/PanelModel.test.ts +++ b/public/app/features/dashboard/state/PanelModel.test.ts @@ -1,6 +1,6 @@ import { PanelModel } from './PanelModel'; import { getPanelPlugin } from '../../plugins/__mocks__/pluginMocks'; -import { ReactPanelPlugin, AngularPanelPlugin } from '@grafana/ui/src/types/panel'; +import { PanelPlugin, AngularPanelPlugin } from '@grafana/ui/src/types/panel'; class TablePanelCtrl {} @@ -123,13 +123,13 @@ describe('PanelModel', () => { describe('when changing to react panel', () => { const onPanelTypeChanged = jest.fn(); - const reactPlugin = new ReactPanelPlugin({} as any).setPanelChangeHandler(onPanelTypeChanged as any); + const reactPlugin = new PanelPlugin({} as any).setPanelChangeHandler(onPanelTypeChanged as any); beforeEach(() => { model.changePlugin( getPanelPlugin({ id: 'react', - reactPlugin: reactPlugin, + vizPlugin: reactPlugin, }) ); }); diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index d730b86b828f..e79d8df00acc 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -7,7 +7,7 @@ import { getNextRefIdChar } from 'app/core/utils/query'; // Types import { DataQuery, Threshold, ScopedVars, DataQueryResponseData } from '@grafana/ui'; -import { PanelPlugin } from 'app/types'; +import { PanelPluginMeta } from 'app/types'; import config from 'app/core/config'; import { PanelQueryRunner } from './PanelQueryRunner'; @@ -117,7 +117,7 @@ export class PanelModel { cacheTimeout?: any; cachedPluginOptions?: any; legend?: { show: boolean }; - plugin?: PanelPlugin; + plugin?: PanelPluginMeta; private queryRunner?: PanelQueryRunner; constructor(model: any) { @@ -249,23 +249,23 @@ export class PanelModel { }); } - private getPluginVersion(plugin: PanelPlugin): string { + private getPluginVersion(plugin: PanelPluginMeta): string { return this.plugin && this.plugin.info.version ? this.plugin.info.version : config.buildInfo.version; } - pluginLoaded(plugin: PanelPlugin) { + pluginLoaded(plugin: PanelPluginMeta) { this.plugin = plugin; - if (plugin.reactPlugin && plugin.reactPlugin.onPanelMigration) { + if (plugin.vizPlugin && plugin.vizPlugin.onPanelMigration) { const version = this.getPluginVersion(plugin); if (version !== this.pluginVersion) { - this.options = plugin.reactPlugin.onPanelMigration(this); + this.options = plugin.vizPlugin.onPanelMigration(this); this.pluginVersion = version; } } } - changePlugin(newPlugin: PanelPlugin) { + changePlugin(newPlugin: PanelPluginMeta) { const pluginId = newPlugin.id; const oldOptions: any = this.getOptionsToRemember(); const oldPluginId = this.type; @@ -292,7 +292,7 @@ export class PanelModel { this.plugin = newPlugin; // Let panel plugins inspect options from previous panel and keep any that it can use - const reactPanel = newPlugin.reactPlugin; + const reactPanel = newPlugin.vizPlugin; if (reactPanel) { if (reactPanel.onPanelTypeChanged) { diff --git a/public/app/features/plugins/__mocks__/pluginMocks.ts b/public/app/features/plugins/__mocks__/pluginMocks.ts index f56fb21de294..089a39ff4953 100644 --- a/public/app/features/plugins/__mocks__/pluginMocks.ts +++ b/public/app/features/plugins/__mocks__/pluginMocks.ts @@ -1,4 +1,4 @@ -import { Plugin, PanelPlugin, PanelDataFormat } from 'app/types'; +import { Plugin, PanelPluginMeta, PanelDataFormat } from 'app/types'; import { PluginType } from '@grafana/ui'; export const getMockPlugins = (amount: number): Plugin[] => { @@ -34,7 +34,7 @@ export const getMockPlugins = (amount: number): Plugin[] => { return plugins; }; -export const getPanelPlugin = (options: Partial): PanelPlugin => { +export const getPanelPlugin = (options: Partial): PanelPluginMeta => { return { id: options.id, type: PluginType.panel, @@ -58,7 +58,7 @@ export const getPanelPlugin = (options: Partial): PanelPlugin => { hideFromList: options.hideFromList === true, module: '', baseUrl: '', - reactPlugin: options.reactPlugin, + vizPlugin: options.vizPlugin, angularPlugin: options.angularPlugin, }; }; diff --git a/public/app/features/plugins/plugin_loader.ts b/public/app/features/plugins/plugin_loader.ts index 063c6f989db5..756724ace9d0 100644 --- a/public/app/features/plugins/plugin_loader.ts +++ b/public/app/features/plugins/plugin_loader.ts @@ -18,7 +18,7 @@ import config from 'app/core/config'; import TimeSeries from 'app/core/time_series2'; import TableModel from 'app/core/table_model'; import { coreModule, appEvents, contextSrv } from 'app/core/core'; -import { DataSourcePlugin, AppPlugin, ReactPanelPlugin, AngularPanelPlugin, PluginMeta } from '@grafana/ui/src/types'; +import { DataSourcePlugin, AppPlugin, PanelPlugin, AngularPanelPlugin, PluginMeta } from '@grafana/ui/src/types'; import * as datemath from 'app/core/utils/datemath'; import * as fileExport from 'app/core/utils/file_export'; import * as flatten from 'app/core/utils/flatten'; @@ -182,10 +182,10 @@ export function importAppPlugin(meta: PluginMeta): Promise { }); } -export function importPanelPlugin(path: string): Promise { +export function importPanelPlugin(path: string): Promise { return importPluginModule(path).then(pluginExports => { - if (pluginExports.reactPanel) { - return pluginExports.reactPanel as ReactPanelPlugin; + if (pluginExports.plugin) { + return pluginExports.plugin as PanelPlugin; } else { return new AngularPanelPlugin(pluginExports.PanelCtrl); } diff --git a/public/app/plugins/panel/bargauge/module.tsx b/public/app/plugins/panel/bargauge/module.tsx index 0d0312087e84..20c973aeaf5d 100644 --- a/public/app/plugins/panel/bargauge/module.tsx +++ b/public/app/plugins/panel/bargauge/module.tsx @@ -1,10 +1,10 @@ -import { ReactPanelPlugin, sharedSingleStatOptionsCheck } from '@grafana/ui'; +import { PanelPlugin, sharedSingleStatOptionsCheck } from '@grafana/ui'; import { BarGaugePanel } from './BarGaugePanel'; import { BarGaugePanelEditor } from './BarGaugePanelEditor'; import { BarGaugeOptions, defaults } from './types'; -export const reactPanel = new ReactPanelPlugin(BarGaugePanel) +export const plugin = new PanelPlugin(BarGaugePanel) .setDefaults(defaults) .setEditor(BarGaugePanelEditor) .setPanelChangeHandler(sharedSingleStatOptionsCheck); diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 7cf7841d225f..6272181e566a 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,9 +1,9 @@ -import { ReactPanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui'; +import { PanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui'; import { GaugePanelEditor } from './GaugePanelEditor'; import { GaugePanel } from './GaugePanel'; import { GaugeOptions, defaults } from './types'; -export const reactPanel = new ReactPanelPlugin(GaugePanel) +export const plugin = new PanelPlugin(GaugePanel) .setDefaults(defaults) .setEditor(GaugePanelEditor) .setPanelChangeHandler(sharedSingleStatOptionsCheck) diff --git a/public/app/plugins/panel/graph2/module.tsx b/public/app/plugins/panel/graph2/module.tsx index 8d27c36492f8..0daf85c3f912 100644 --- a/public/app/plugins/panel/graph2/module.tsx +++ b/public/app/plugins/panel/graph2/module.tsx @@ -1,6 +1,6 @@ -import { ReactPanelPlugin } from '@grafana/ui'; +import { PanelPlugin } from '@grafana/ui'; import { GraphPanelEditor } from './GraphPanelEditor'; import { GraphPanel } from './GraphPanel'; import { Options, defaults } from './types'; -export const reactPanel = new ReactPanelPlugin(GraphPanel).setDefaults(defaults).setEditor(GraphPanelEditor); +export const plugin = new PanelPlugin(GraphPanel).setDefaults(defaults).setEditor(GraphPanelEditor); diff --git a/public/app/plugins/panel/piechart/module.tsx b/public/app/plugins/panel/piechart/module.tsx index fd9c14a47609..83c7ddeb5c9e 100644 --- a/public/app/plugins/panel/piechart/module.tsx +++ b/public/app/plugins/panel/piechart/module.tsx @@ -1,8 +1,8 @@ -import { ReactPanelPlugin } from '@grafana/ui'; +import { PanelPlugin } from '@grafana/ui'; import { PieChartPanelEditor } from './PieChartPanelEditor'; import { PieChartPanel } from './PieChartPanel'; import { PieChartOptions, defaults } from './types'; -export const reactPanel = new ReactPanelPlugin(PieChartPanel) +export const plugin = new PanelPlugin(PieChartPanel) .setDefaults(defaults) .setEditor(PieChartPanelEditor); diff --git a/public/app/plugins/panel/singlestat2/module.tsx b/public/app/plugins/panel/singlestat2/module.tsx index 2be94666d5cc..abf794f02d3d 100644 --- a/public/app/plugins/panel/singlestat2/module.tsx +++ b/public/app/plugins/panel/singlestat2/module.tsx @@ -1,9 +1,9 @@ -import { ReactPanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui'; +import { PanelPlugin, sharedSingleStatMigrationCheck, sharedSingleStatOptionsCheck } from '@grafana/ui'; import { SingleStatOptions, defaults } from './types'; import { SingleStatPanel } from './SingleStatPanel'; import { SingleStatEditor } from './SingleStatEditor'; -export const reactPanel = new ReactPanelPlugin(SingleStatPanel) +export const plugin = new PanelPlugin(SingleStatPanel) .setDefaults(defaults) .setEditor(SingleStatEditor) .setPanelChangeHandler(sharedSingleStatOptionsCheck) diff --git a/public/app/plugins/panel/table2/module.tsx b/public/app/plugins/panel/table2/module.tsx index ed04e6867b56..297abee5e273 100644 --- a/public/app/plugins/panel/table2/module.tsx +++ b/public/app/plugins/panel/table2/module.tsx @@ -1,7 +1,7 @@ -import { ReactPanelPlugin } from '@grafana/ui'; +import { PanelPlugin } from '@grafana/ui'; import { TablePanelEditor } from './TablePanelEditor'; import { TablePanel } from './TablePanel'; import { Options, defaults } from './types'; -export const reactPanel = new ReactPanelPlugin(TablePanel).setDefaults(defaults).setEditor(TablePanelEditor); +export const plugin = new PanelPlugin(TablePanel).setDefaults(defaults).setEditor(TablePanelEditor); diff --git a/public/app/plugins/panel/text2/module.tsx b/public/app/plugins/panel/text2/module.tsx index 29d5167463e0..ca3f981a9464 100644 --- a/public/app/plugins/panel/text2/module.tsx +++ b/public/app/plugins/panel/text2/module.tsx @@ -1,10 +1,10 @@ -import { ReactPanelPlugin } from '@grafana/ui'; +import { PanelPlugin } from '@grafana/ui'; import { TextPanelEditor } from './TextPanelEditor'; import { TextPanel } from './TextPanel'; import { TextOptions, defaults } from './types'; -export const reactPanel = new ReactPanelPlugin(TextPanel) +export const plugin = new PanelPlugin(TextPanel) .setDefaults(defaults) .setEditor(TextPanelEditor) .setPanelChangeHandler((options: TextOptions, prevPluginId: string, prevOptions: any) => { diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index ce71bf0243a4..e1225a387421 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -1,12 +1,10 @@ -import { AngularPanelPlugin, ReactPanelPlugin, PluginMetaInfo, PluginMeta } from '@grafana/ui/src/types'; +import { AngularPanelPlugin, PanelPlugin, PluginMeta } from '@grafana/ui/src/types'; -export interface PanelPlugin extends PluginMeta { +export interface PanelPluginMeta extends PluginMeta { hideFromList?: boolean; - baseUrl: string; - info: PluginMetaInfo; sort: number; angularPlugin: AngularPanelPlugin | null; - reactPlugin: ReactPanelPlugin | null; + vizPlugin: PanelPlugin | null; hasBeenImported?: boolean; dataFormats: PanelDataFormat[]; } diff --git a/public/test/specs/helpers.ts b/public/test/specs/helpers.ts index 9b6036d0cfb5..5d28506d4be0 100644 --- a/public/test/specs/helpers.ts +++ b/public/test/specs/helpers.ts @@ -3,7 +3,7 @@ import config from 'app/core/config'; import * as dateMath from 'app/core/utils/datemath'; import { angularMocks, sinon } from '../lib/common'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { PanelPlugin } from 'app/types'; +import { PanelPluginMeta } from 'app/types'; import { RawTimeRange } from '@grafana/ui/src/types'; export function ControllerTestContext(this: any) { @@ -64,7 +64,7 @@ export function ControllerTestContext(this: any) { $rootScope.colors.push('#' + i); } - config.panels['test'] = { info: {} } as PanelPlugin; + config.panels['test'] = { info: {} } as PanelPluginMeta; self.ctrl = $controller( Ctrl, { $scope: self.scope }, From 66c9297c367894d4f84b2e2ba2227e0019b3b6ec Mon Sep 17 00:00:00 2001 From: Oleg Gaidarenko Date: Sat, 27 Apr 2019 09:03:59 +0300 Subject: [PATCH 5/8] Feature: introduce LdapActiveSyncEnabled setting (#16787) * Feature: introduce LdapActiveSyncEnabled setting We probably remove it after the active sync is done. But at the moment we do not want to affect the current users with not fully tested feature * Chore: move settings in more logical order --- conf/defaults.ini | 2 +- pkg/setting/setting.go | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/conf/defaults.ini b/conf/defaults.ini index 61bc6af6dd83..c550e5bfdee3 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -362,10 +362,10 @@ headers = enabled = false config_file = /etc/grafana/ldap.toml allow_sign_up = true -sync_cron = @hourly # LDAP backround sync (Enterprise only) sync_cron = @hourly +active_sync_enabled = false #################################### SMTP / Emailing ##################### [smtp] diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index d6a6ca5767dc..0ed02f7f0ed8 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -164,10 +164,11 @@ var ( GoogleTagManagerId string // LDAP - LdapEnabled bool - LdapConfigFile string - LdapSyncCron string - LdapAllowSignup = true + LdapEnabled bool + LdapConfigFile string + LdapSyncCron string + LdapAllowSignup bool + LdapActiveSyncEnabled bool // QUOTA Quota QuotaSettings @@ -971,10 +972,11 @@ type RemoteCacheOptions struct { func (cfg *Cfg) readLDAPConfig() { ldapSec := cfg.Raw.Section("auth.ldap") - LdapEnabled = ldapSec.Key("enabled").MustBool(false) LdapConfigFile = ldapSec.Key("config_file").String() - LdapAllowSignup = ldapSec.Key("allow_sign_up").MustBool(true) LdapSyncCron = ldapSec.Key("sync_cron").String() + LdapEnabled = ldapSec.Key("enabled").MustBool(false) + LdapActiveSyncEnabled = ldapSec.Key("active_sync_enabled").MustBool(false) + LdapAllowSignup = ldapSec.Key("allow_sign_up").MustBool(true) } func (cfg *Cfg) readSessionConfig() { From a4f5c5487107655da1a3a04f893631493c306ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sun, 28 Apr 2019 09:58:12 +0200 Subject: [PATCH 6/8] Chore: Fixed no implicit any Typescript errors (#16799) --- public/app/core/controllers/error_ctrl.ts | 2 +- public/app/core/controllers/invited_ctrl.ts | 4 +-- .../app/core/controllers/json_editor_ctrl.ts | 2 +- public/app/core/controllers/login_ctrl.ts | 11 +++---- .../core/controllers/reset_password_ctrl.ts | 4 +-- public/app/core/directives/array_join.ts | 6 ++-- .../app/core/directives/autofill_event_fix.ts | 2 +- public/app/core/directives/diff-view.ts | 8 ++--- .../app/core/directives/dropdown_typeahead.ts | 22 ++++++------- public/app/core/directives/give_focus.ts | 6 ++-- public/app/core/directives/metric_segment.ts | 29 ++++++++--------- public/app/core/directives/misc.ts | 30 +++++++++--------- .../app/core/directives/ng_model_on_blur.ts | 10 +++--- .../app/core/directives/rebuild_on_change.ts | 16 +++++----- public/app/core/directives/tags.ts | 10 +++--- .../core/directives/value_select_dropdown.ts | 24 +++++++------- public/app/core/filters/filters.ts | 30 +++++------------- public/app/core/live/live_srv.ts | 26 ++++++++-------- public/app/core/reducers/navModel.ts | 2 +- public/app/core/selectors/location.ts | 5 +-- public/app/core/services/AngularLoader.ts | 10 +++--- public/app/core/services/analytics.ts | 4 +-- public/app/core/services/bridge_srv.ts | 13 ++++++-- public/app/core/services/context_srv.ts | 2 +- .../core/services/dynamic_directive_srv.ts | 12 +++---- public/app/core/services/impression_srv.ts | 8 ++--- public/app/core/services/keybindingSrv.ts | 25 ++++++++------- public/app/core/services/timer.ts | 9 +++--- .../dashboard/services/TimeSrv.test.ts | 17 +++++----- .../features/dashboard/services/TimeSrv.ts | 31 ++++++++++++------- public/app/features/teams/TeamPages.tsx | 2 +- public/test/specs/helpers.ts | 2 ++ 32 files changed, 196 insertions(+), 188 deletions(-) diff --git a/public/app/core/controllers/error_ctrl.ts b/public/app/core/controllers/error_ctrl.ts index a47cae9fea39..7b834946f407 100644 --- a/public/app/core/controllers/error_ctrl.ts +++ b/public/app/core/controllers/error_ctrl.ts @@ -4,7 +4,7 @@ import appEvents from 'app/core/app_events'; export class ErrorCtrl { /** @ngInject */ - constructor($scope, contextSrv, navModelSrv) { + constructor($scope: any, contextSrv: any, navModelSrv: any) { $scope.navModel = navModelSrv.getNotFoundNav(); $scope.appSubUrl = config.appSubUrl; diff --git a/public/app/core/controllers/invited_ctrl.ts b/public/app/core/controllers/invited_ctrl.ts index 63f9d975c1fa..dba074dc8902 100644 --- a/public/app/core/controllers/invited_ctrl.ts +++ b/public/app/core/controllers/invited_ctrl.ts @@ -3,7 +3,7 @@ import config from 'app/core/config'; export class InvitedCtrl { /** @ngInject */ - constructor($scope, $routeParams, contextSrv, backendSrv) { + constructor($scope: any, $routeParams: any, contextSrv: any, backendSrv: any) { contextSrv.sidemenu = false; $scope.formModel = {}; @@ -17,7 +17,7 @@ export class InvitedCtrl { }; $scope.init = () => { - backendSrv.get('/api/user/invite/' + $routeParams.code).then(invite => { + backendSrv.get('/api/user/invite/' + $routeParams.code).then((invite: any) => { $scope.formModel.name = invite.name; $scope.formModel.email = invite.email; $scope.formModel.username = invite.email; diff --git a/public/app/core/controllers/json_editor_ctrl.ts b/public/app/core/controllers/json_editor_ctrl.ts index a0384aa8d364..0c33a0408e7f 100644 --- a/public/app/core/controllers/json_editor_ctrl.ts +++ b/public/app/core/controllers/json_editor_ctrl.ts @@ -3,7 +3,7 @@ import coreModule from '../core_module'; export class JsonEditorCtrl { /** @ngInject */ - constructor($scope) { + constructor($scope: any) { $scope.json = angular.toJson($scope.model.object, true); $scope.canUpdate = $scope.model.updateHandler !== void 0 && $scope.model.canUpdate; $scope.canCopy = $scope.model.enableCopy; diff --git a/public/app/core/controllers/login_ctrl.ts b/public/app/core/controllers/login_ctrl.ts index 3a72379aa81a..991ce1146a62 100644 --- a/public/app/core/controllers/login_ctrl.ts +++ b/public/app/core/controllers/login_ctrl.ts @@ -1,10 +1,11 @@ import _ from 'lodash'; import coreModule from '../core_module'; import config from 'app/core/config'; +import { BackendSrv } from '../services/backend_srv'; export class LoginCtrl { /** @ngInject */ - constructor($scope, backendSrv, contextSrv, $location) { + constructor($scope: any, backendSrv: BackendSrv, $location: any) { $scope.formModel = { user: '', email: '', @@ -15,8 +16,6 @@ export class LoginCtrl { $scope.result = ''; $scope.loggingIn = false; - contextSrv.sidemenu = false; - $scope.oauth = config.oauth; $scope.oauthEnabled = _.keys(config.oauth).length > 0; $scope.ldapEnabled = config.ldapEnabled; @@ -83,7 +82,7 @@ export class LoginCtrl { $scope.toGrafana(); }; - $scope.loginModeChanged = newValue => { + $scope.loginModeChanged = (newValue: boolean) => { $scope.submitBtnText = newValue ? 'Log in' : 'Sign up'; }; @@ -92,7 +91,7 @@ export class LoginCtrl { return; } - backendSrv.post('/api/user/signup', $scope.formModel).then(result => { + backendSrv.post('/api/user/signup', $scope.formModel).then((result: any) => { if (result.status === 'SignUpCreated') { $location.path('/signup').search({ email: $scope.formModel.email }); } else { @@ -111,7 +110,7 @@ export class LoginCtrl { backendSrv .post('/login', $scope.formModel) - .then(result => { + .then((result: any) => { $scope.result = result; if ($scope.formModel.password !== 'admin' || $scope.ldapEnabled || $scope.authProxyEnabled) { diff --git a/public/app/core/controllers/reset_password_ctrl.ts b/public/app/core/controllers/reset_password_ctrl.ts index 9ad6864ece23..86c0caf8b231 100644 --- a/public/app/core/controllers/reset_password_ctrl.ts +++ b/public/app/core/controllers/reset_password_ctrl.ts @@ -1,10 +1,10 @@ import coreModule from '../core_module'; import config from 'app/core/config'; +import { BackendSrv } from '../services/backend_srv'; export class ResetPasswordCtrl { /** @ngInject */ - constructor($scope, contextSrv, backendSrv, $location) { - contextSrv.sidemenu = false; + constructor($scope: any, backendSrv: BackendSrv, $location: any) { $scope.formModel = {}; $scope.mode = 'send'; $scope.ldapEnabled = config.ldapEnabled; diff --git a/public/app/core/directives/array_join.ts b/public/app/core/directives/array_join.ts index 137689ab7d28..f456911ce3fa 100644 --- a/public/app/core/directives/array_join.ts +++ b/public/app/core/directives/array_join.ts @@ -7,12 +7,12 @@ export function arrayJoin() { return { restrict: 'A', require: 'ngModel', - link: (scope, element, attr, ngModel) => { - function split_array(text) { + link: (scope: any, element: any, attr: any, ngModel: any) => { + function split_array(text: string) { return (text || '').split(','); } - function join_array(text) { + function join_array(text: string) { if (_.isArray(text)) { return ((text || '') as any).join(','); } else { diff --git a/public/app/core/directives/autofill_event_fix.ts b/public/app/core/directives/autofill_event_fix.ts index 4aaa63e276f1..d6bd4af55fa9 100644 --- a/public/app/core/directives/autofill_event_fix.ts +++ b/public/app/core/directives/autofill_event_fix.ts @@ -1,7 +1,7 @@ import coreModule from '../core_module'; /** @ngInject */ -export function autofillEventFix($compile) { +export function autofillEventFix($compile: any) { return { link: ($scope: any, elem: any) => { const input = elem[0]; diff --git a/public/app/core/directives/diff-view.ts b/public/app/core/directives/diff-view.ts index 84cb597e5430..b7c41e022c90 100644 --- a/public/app/core/directives/diff-view.ts +++ b/public/app/core/directives/diff-view.ts @@ -5,8 +5,8 @@ export class DeltaCtrl { observer: any; /** @ngInject */ - constructor(private $rootScope) { - const waitForCompile = mutations => { + constructor(private $rootScope: any) { + const waitForCompile = (mutations: any) => { if (mutations.length === 1) { this.$rootScope.appEvent('json-diff-ready'); } @@ -42,10 +42,10 @@ coreModule.directive('diffDelta', delta); // Link to JSON line number export class LinkJSONCtrl { /** @ngInject */ - constructor(private $scope, private $rootScope, private $anchorScroll) {} + constructor(private $scope: any, private $rootScope: any, private $anchorScroll: any) {} goToLine(line: number) { - let unbind; + let unbind: () => void; const scroll = () => { this.$anchorScroll(`l${line}`); diff --git a/public/app/core/directives/dropdown_typeahead.ts b/public/app/core/directives/dropdown_typeahead.ts index 7456df8de53d..05e2eb49ec56 100644 --- a/public/app/core/directives/dropdown_typeahead.ts +++ b/public/app/core/directives/dropdown_typeahead.ts @@ -3,7 +3,7 @@ import $ from 'jquery'; import coreModule from '../core_module'; /** @ngInject */ -export function dropdownTypeahead($compile) { +export function dropdownTypeahead($compile: any) { const inputTemplate = ' { + link: ($scope: any, elem: any, attrs: any) => { const $input = $(inputTemplate); const $button = $(buttonTemplate); $input.appendTo(elem); @@ -31,7 +31,7 @@ export function dropdownTypeahead($compile) { } if (attrs.ngModel) { - $scope.$watch('model', newValue => { + $scope.$watch('model', (newValue: any) => { _.each($scope.menuItems, item => { _.each(item.submenu, subItem => { if (subItem.value === newValue) { @@ -59,7 +59,7 @@ export function dropdownTypeahead($compile) { [] ); - $scope.menuItemSelected = (index, subIndex) => { + $scope.menuItemSelected = (index: number, subIndex: number) => { const menuItem = $scope.menuItems[index]; const payload: any = { $item: menuItem }; if (menuItem.submenu && subIndex !== void 0) { @@ -73,7 +73,7 @@ export function dropdownTypeahead($compile) { source: typeaheadValues, minLength: 1, items: 10, - updater: value => { + updater: (value: string) => { const result: any = {}; _.each($scope.menuItems, menuItem => { _.each(menuItem.submenu, submenuItem => { @@ -123,7 +123,7 @@ export function dropdownTypeahead($compile) { } /** @ngInject */ -export function dropdownTypeahead2($compile) { +export function dropdownTypeahead2($compile: any) { const inputTemplate = ''; @@ -139,7 +139,7 @@ export function dropdownTypeahead2($compile) { model: '=ngModel', buttonTemplateClass: '@', }, - link: ($scope, elem, attrs) => { + link: ($scope: any, elem: any, attrs: any) => { const $input = $(inputTemplate); if (!$scope.buttonTemplateClass) { @@ -148,7 +148,7 @@ export function dropdownTypeahead2($compile) { const $button = $(buttonTemplate); const timeoutId = { - blur: null, + blur: null as any, }; $input.appendTo(elem); $button.appendTo(elem); @@ -158,7 +158,7 @@ export function dropdownTypeahead2($compile) { } if (attrs.ngModel) { - $scope.$watch('model', newValue => { + $scope.$watch('model', (newValue: any) => { _.each($scope.menuItems, item => { _.each(item.submenu, subItem => { if (subItem.value === newValue) { @@ -194,7 +194,7 @@ export function dropdownTypeahead2($compile) { elem.removeClass('open'); }; - $scope.menuItemSelected = (index, subIndex) => { + $scope.menuItemSelected = (index: number, subIndex: number) => { const menuItem = $scope.menuItems[index]; const payload: any = { $item: menuItem }; if (menuItem.submenu && subIndex !== void 0) { @@ -209,7 +209,7 @@ export function dropdownTypeahead2($compile) { source: typeaheadValues, minLength: 1, items: 10, - updater: value => { + updater: (value: string) => { const result: any = {}; _.each($scope.menuItems, menuItem => { _.each(menuItem.submenu, submenuItem => { diff --git a/public/app/core/directives/give_focus.ts b/public/app/core/directives/give_focus.ts index 37549ad7229b..c10dbb9f9ac4 100644 --- a/public/app/core/directives/give_focus.ts +++ b/public/app/core/directives/give_focus.ts @@ -1,14 +1,14 @@ import coreModule from '../core_module'; coreModule.directive('giveFocus', () => { - return (scope, element, attrs) => { - element.click(e => { + return (scope: any, element: any, attrs: any) => { + element.click((e: any) => { e.stopPropagation(); }); scope.$watch( attrs.giveFocus, - newValue => { + (newValue: any) => { if (!newValue) { return; } diff --git a/public/app/core/directives/metric_segment.ts b/public/app/core/directives/metric_segment.ts index 03bb8209b54b..22bf6789b8e0 100644 --- a/public/app/core/directives/metric_segment.ts +++ b/public/app/core/directives/metric_segment.ts @@ -1,9 +1,10 @@ import _ from 'lodash'; import $ from 'jquery'; import coreModule from '../core_module'; +import { TemplateSrv } from 'app/features/templating/template_srv'; /** @ngInject */ -export function metricSegment($compile, $sce, templateSrv) { +export function metricSegment($compile: any, $sce: any, templateSrv: TemplateSrv) { const inputTemplate = ' { + link: ($scope: any, elem: any) => { const $input = $(inputTemplate); const segment = $scope.segment; const $button = $(segment.selectMode ? selectTemplate : linkTemplate); let options = null; - let cancelBlur = null; + let cancelBlur: any = null; let linkMode = true; const debounceLookup = $scope.debounce; $input.appendTo(elem); $button.appendTo(elem); - $scope.updateVariableValue = value => { + $scope.updateVariableValue = (value: string) => { if (value === '' || segment.value === value) { return; } @@ -63,7 +64,7 @@ export function metricSegment($compile, $sce, templateSrv) { }); }; - $scope.switchToLink = fromClick => { + $scope.switchToLink = (fromClick: boolean) => { if (linkMode && !fromClick) { return; } @@ -82,9 +83,9 @@ export function metricSegment($compile, $sce, templateSrv) { cancelBlur = setTimeout($scope.switchToLink, 200); }; - $scope.source = (query, callback) => { + $scope.source = (query: string, callback: any) => { $scope.$apply(() => { - $scope.getOptions({ $query: query }).then(altSegments => { + $scope.getOptions({ $query: query }).then((altSegments: any) => { $scope.altSegments = altSegments; options = _.map($scope.altSegments, alt => { return _.escape(alt.value); @@ -102,7 +103,7 @@ export function metricSegment($compile, $sce, templateSrv) { }); }; - $scope.updater = value => { + $scope.updater = (value: string) => { value = _.unescape(value); if (value === segment.value) { clearTimeout(cancelBlur); @@ -116,7 +117,7 @@ export function metricSegment($compile, $sce, templateSrv) { return value; }; - $scope.matcher = function(item) { + $scope.matcher = function(item: string) { if (linkMode) { return false; } @@ -186,7 +187,7 @@ export function metricSegment($compile, $sce, templateSrv) { } /** @ngInject */ -export function metricSegmentModel(uiSegmentSrv, $q) { +export function metricSegmentModel(uiSegmentSrv: any, $q: any) { return { template: '', @@ -198,10 +199,10 @@ export function metricSegmentModel(uiSegmentSrv, $q) { onChange: '&', }, link: { - pre: function postLink($scope, elem, attrs) { - let cachedOptions; + pre: function postLink($scope: any, elem: any, attrs: any) { + let cachedOptions: any; - $scope.valueToSegment = value => { + $scope.valueToSegment = (value: any) => { const option: any = _.find($scope.options, { value: value }); const segment = { cssClass: attrs.cssClass, @@ -222,7 +223,7 @@ export function metricSegmentModel(uiSegmentSrv, $q) { }) ); } else { - return $scope.getOptions().then(options => { + return $scope.getOptions().then((options: any) => { cachedOptions = options; return _.map(options, option => { if (option.html) { diff --git a/public/app/core/directives/misc.ts b/public/app/core/directives/misc.ts index 192e2df4167c..1fa0eacac4f2 100644 --- a/public/app/core/directives/misc.ts +++ b/public/app/core/directives/misc.ts @@ -5,10 +5,10 @@ import kbn from 'app/core/utils/kbn'; import { appEvents } from 'app/core/core'; /** @ngInject */ -function tip($compile) { +function tip($compile: any) { return { restrict: 'E', - link: (scope, elem, attrs) => { + link: (scope: any, elem: any, attrs: any) => { let _t = '' + attrs.tip + '' : ''; const showIf = attrs.showIf ? ' ng-show="' + attrs.showIf + '" ' : ''; @@ -115,10 +115,10 @@ function editorOptBool($compile) { } /** @ngInject */ -function editorCheckbox($compile, $interpolate) { +function editorCheckbox($compile: any, $interpolate: any) { return { restrict: 'E', - link: (scope, elem, attrs) => { + link: (scope: any, elem: any, attrs: any) => { const text = $interpolate(attrs.text)(scope); const model = $interpolate(attrs.model)(scope); const ngchange = attrs.change ? ' ng-change="' + attrs.change + '"' : ''; @@ -150,8 +150,8 @@ function editorCheckbox($compile, $interpolate) { } /** @ngInject */ -function gfDropdown($parse, $compile, $timeout) { - function buildTemplate(items, placement?) { +function gfDropdown($parse: any, $compile: any, $timeout: any) { + function buildTemplate(items: any, placement?: any) { const upclass = placement === 'top' ? 'dropup' : ''; const ul = ['']; @@ -191,7 +191,7 @@ function gfDropdown($parse, $compile, $timeout) { return { restrict: 'EA', scope: true, - link: function postLink(scope, iElement, iAttrs) { + link: function postLink(scope: any, iElement: any, iAttrs: any) { const getter = $parse(iAttrs.gfDropdown), items = getter(scope); $timeout(() => { diff --git a/public/app/core/directives/ng_model_on_blur.ts b/public/app/core/directives/ng_model_on_blur.ts index 7e903c1f8893..45991f99b551 100644 --- a/public/app/core/directives/ng_model_on_blur.ts +++ b/public/app/core/directives/ng_model_on_blur.ts @@ -6,7 +6,7 @@ function ngModelOnBlur() { restrict: 'A', priority: 1, require: 'ngModel', - link: (scope, elm, attr, ngModelCtrl) => { + link: (scope: any, elm: any, attr: any, ngModelCtrl: any) => { if (attr.type === 'radio' || attr.type === 'checkbox') { return; } @@ -25,8 +25,8 @@ function emptyToNull() { return { restrict: 'A', require: 'ngModel', - link: (scope, elm, attrs, ctrl) => { - ctrl.$parsers.push(viewValue => { + link: (scope: any, elm: any, attrs: any, ctrl: any) => { + ctrl.$parsers.push((viewValue: any) => { if (viewValue === '') { return null; } @@ -39,8 +39,8 @@ function emptyToNull() { function validTimeSpan() { return { require: 'ngModel', - link: (scope, elm, attrs, ctrl) => { - ctrl.$validators.integer = (modelValue, viewValue) => { + link: (scope: any, elm: any, attrs: any, ctrl: any) => { + ctrl.$validators.integer = (modelValue: any, viewValue: any) => { if (ctrl.$isEmpty(modelValue)) { return true; } diff --git a/public/app/core/directives/rebuild_on_change.ts b/public/app/core/directives/rebuild_on_change.ts index 43edf9d703f5..57b42ecaa63b 100644 --- a/public/app/core/directives/rebuild_on_change.ts +++ b/public/app/core/directives/rebuild_on_change.ts @@ -1,16 +1,16 @@ import $ from 'jquery'; import coreModule from '../core_module'; -function getBlockNodes(nodes) { +function getBlockNodes(nodes: any[]) { let node = nodes[0]; const endNode = nodes[nodes.length - 1]; - let blockNodes; + let blockNodes: any[]; node = node.nextSibling; for (let i = 1; node !== endNode && node; i++) { if (blockNodes || nodes[i] !== node) { if (!blockNodes) { - blockNodes = $([].slice.call(nodes, 0, i)); + blockNodes = $([].slice.call(nodes, 0, i)) as any; } blockNodes.push(node); } @@ -21,15 +21,15 @@ function getBlockNodes(nodes) { } /** @ngInject */ -function rebuildOnChange($animate) { +function rebuildOnChange($animate: any) { return { multiElement: true, terminal: true, transclude: true, priority: 600, restrict: 'E', - link: (scope, elem, attrs, ctrl, transclude) => { - let block, childScope, previousElements; + link: (scope: any, elem: any, attrs: any, ctrl: any, transclude: any) => { + let block: any, childScope: any, previousElements: any; function cleanUp() { if (previousElements) { @@ -49,13 +49,13 @@ function rebuildOnChange($animate) { } } - scope.$watch(attrs.property, function rebuildOnChangeAction(value, oldValue) { + scope.$watch(attrs.property, function rebuildOnChangeAction(value: any, oldValue: any) { if (childScope && value !== oldValue) { cleanUp(); } if (!childScope && (value || attrs.showNull)) { - transclude((clone, newScope) => { + transclude((clone: any, newScope: any) => { childScope = newScope; clone[clone.length++] = document.createComment(' end rebuild on change '); block = { clone: clone }; diff --git a/public/app/core/directives/tags.ts b/public/app/core/directives/tags.ts index 27bddfb18833..fb4420f4f2cc 100644 --- a/public/app/core/directives/tags.ts +++ b/public/app/core/directives/tags.ts @@ -4,7 +4,7 @@ import coreModule from '../core_module'; import tags from 'app/core/utils/tags'; import 'vendor/tagsinput/bootstrap-tagsinput.js'; -function setColor(name, element) { +function setColor(name: string, element: JQuery) { const { color, borderColor } = tags.getTagColorsFromName(name); element.css('background-color', color); element.css('border-color', borderColor); @@ -13,14 +13,14 @@ function setColor(name, element) { function tagColorFromName() { return { scope: { tagColorFromName: '=' }, - link: (scope, element) => { + link: (scope: any, element: any) => { setColor(scope.tagColorFromName, element); }, }; } function bootstrapTagsinput() { - function getItemProperty(scope, property) { + function getItemProperty(scope: any, property: any) { if (!property) { return undefined; } @@ -29,7 +29,7 @@ function bootstrapTagsinput() { return scope.$parent[property]; } - return item => { + return (item: any) => { return item[property]; }; } @@ -42,7 +42,7 @@ function bootstrapTagsinput() { }, template: '', replace: false, - link: function(scope, element, attrs) { + link: function(scope: any, element: any, attrs: any) { if (!angular.isArray(scope.model)) { scope.model = []; } diff --git a/public/app/core/directives/value_select_dropdown.ts b/public/app/core/directives/value_select_dropdown.ts index 0df1b2758be0..90a4ad64477b 100644 --- a/public/app/core/directives/value_select_dropdown.ts +++ b/public/app/core/directives/value_select_dropdown.ts @@ -18,7 +18,7 @@ export class ValueSelectDropdownCtrl { onUpdated: any; /** @ngInject */ - constructor(private $q) {} + constructor(private $q: any) {} show() { this.oldVariableText = this.variable.current.text; @@ -84,7 +84,7 @@ export class ValueSelectDropdownCtrl { this.selectionsChanged(false); } - selectTag(tag) { + selectTag(tag: any) { tag.selected = !tag.selected; let tagValuesPromise; if (!tag.values) { @@ -93,7 +93,7 @@ export class ValueSelectDropdownCtrl { tagValuesPromise = this.$q.when(tag.values); } - return tagValuesPromise.then(values => { + return tagValuesPromise.then((values: any) => { tag.values = values; tag.valuesText = values.join(' + '); _.each(this.options, option => { @@ -106,7 +106,7 @@ export class ValueSelectDropdownCtrl { }); } - keyDown(evt) { + keyDown(evt: any) { if (evt.keyCode === 27) { this.hide(); } @@ -128,11 +128,11 @@ export class ValueSelectDropdownCtrl { } } - moveHighlight(direction) { + moveHighlight(direction: number) { this.highlightIndex = (this.highlightIndex + direction) % this.search.options.length; } - selectValue(option, event, commitChange?, excludeOthers?) { + selectValue(option: any, event: any, commitChange?: boolean, excludeOthers?: boolean) { if (!option) { return; } @@ -142,7 +142,7 @@ export class ValueSelectDropdownCtrl { commitChange = commitChange || false; excludeOthers = excludeOthers || false; - const setAllExceptCurrentTo = newValue => { + const setAllExceptCurrentTo = (newValue: any) => { _.each(this.options, other => { if (option !== other) { other.selected = newValue; @@ -169,7 +169,7 @@ export class ValueSelectDropdownCtrl { this.selectionsChanged(commitChange); } - selectionsChanged(commitChange) { + selectionsChanged(commitChange: boolean) { this.selectedValues = _.filter(this.options, { selected: true }); if (this.selectedValues.length > 1) { @@ -238,14 +238,14 @@ export class ValueSelectDropdownCtrl { } /** @ngInject */ -export function valueSelectDropdown($compile, $window, $timeout, $rootScope) { +export function valueSelectDropdown($compile: any, $window: any, $timeout: any, $rootScope: any) { return { scope: { dashboard: '=', variable: '=', onUpdated: '&' }, templateUrl: 'public/app/partials/valueSelectDropdown.html', controller: 'ValueSelectDropdownCtrl', controllerAs: 'vm', bindToController: true, - link: (scope, elem) => { + link: (scope: any, elem: any) => { const bodyEl = angular.element($window.document.body); const linkEl = elem.find('.variable-value-link'); const inputEl = elem.find('input'); @@ -272,7 +272,7 @@ export function valueSelectDropdown($compile, $window, $timeout, $rootScope) { bodyEl.off('click', bodyOnClick); } - function bodyOnClick(e) { + function bodyOnClick(e: any) { if (elem.has(e.target).length === 0) { scope.$apply(() => { scope.vm.commitChanges(); @@ -280,7 +280,7 @@ export function valueSelectDropdown($compile, $window, $timeout, $rootScope) { } } - scope.$watch('vm.dropdownVisible', newValue => { + scope.$watch('vm.dropdownVisible', (newValue: any) => { if (newValue) { openDropdown(); } else { diff --git a/public/app/core/filters/filters.ts b/public/app/core/filters/filters.ts index c4dbf6b7535b..22e1f9a79837 100644 --- a/public/app/core/filters/filters.ts +++ b/public/app/core/filters/filters.ts @@ -2,23 +2,25 @@ import _ from 'lodash'; import angular from 'angular'; import moment from 'moment'; import coreModule from '../core_module'; +import { TemplateSrv } from 'app/features/templating/template_srv'; coreModule.filter('stringSort', () => { - return input => { + return (input: any) => { return input.sort(); }; }); coreModule.filter('slice', () => { - return (arr, start, end) => { + return (arr: any[], start: any, end: any) => { if (!_.isUndefined(arr)) { return arr.slice(start, end); } + return arr; }; }); coreModule.filter('stringify', () => { - return arr => { + return (arr: any[]) => { if (_.isObject(arr) && !_.isArray(arr)) { return angular.toJson(arr); } else { @@ -28,7 +30,7 @@ coreModule.filter('stringify', () => { }); coreModule.filter('moment', () => { - return (date, mode) => { + return (date: string, mode: string) => { switch (mode) { case 'ago': return moment(date).fromNow(); @@ -37,25 +39,9 @@ coreModule.filter('moment', () => { }; }); -coreModule.filter('noXml', () => { - const noXml = text => { - return _.isString(text) - ? text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/'/g, ''') - .replace(/"/g, '"') - : text; - }; - return text => { - return _.isArray(text) ? _.map(text, noXml) : noXml(text); - }; -}); - /** @ngInject */ -function interpolateTemplateVars(templateSrv) { - const filterFunc: any = (text, scope) => { +function interpolateTemplateVars(templateSrv: TemplateSrv) { + const filterFunc: any = (text: string, scope: any) => { let scopedVars; if (scope.ctrl) { scopedVars = (scope.ctrl.panel || scope.ctrl.row).scopedVars; diff --git a/public/app/core/live/live_srv.ts b/public/app/core/live/live_srv.ts index 3666fde3b91e..1c761f373b1b 100644 --- a/public/app/core/live/live_srv.ts +++ b/public/app/core/live/live_srv.ts @@ -30,7 +30,7 @@ export class LiveSrv { console.log('Live: connecting...'); this.conn = new WebSocket(this.getWebSocketUrl()); - this.conn.onclose = evt => { + this.conn.onclose = (evt: any) => { console.log('Live: websocket onclose', evt); reject({ message: 'Connection closed' }); @@ -38,17 +38,17 @@ export class LiveSrv { setTimeout(this.reconnect.bind(this), 2000); }; - this.conn.onmessage = evt => { + this.conn.onmessage = (evt: any) => { this.handleMessage(evt.data); }; - this.conn.onerror = evt => { + this.conn.onerror = (evt: any) => { this.initPromise = null; reject({ message: 'Connection error' }); console.log('Live: websocket error', evt); }; - this.conn.onopen = evt => { + this.conn.onopen = (evt: any) => { console.log('opened'); this.initPromise = null; resolve(this.conn); @@ -58,7 +58,7 @@ export class LiveSrv { return this.initPromise; } - handleMessage(message) { + handleMessage(message: any) { message = JSON.parse(message); if (!message.stream) { @@ -83,38 +83,38 @@ export class LiveSrv { console.log('LiveSrv: Reconnecting'); - this.getConnection().then(conn => { + this.getConnection().then((conn: any) => { _.each(this.observers, (value, key) => { this.send({ action: 'subscribe', stream: key }); }); }); } - send(data) { + send(data: any) { this.conn.send(JSON.stringify(data)); } - addObserver(stream, observer) { + addObserver(stream: any, observer: any) { this.observers[stream] = observer; - this.getConnection().then(conn => { + this.getConnection().then((conn: any) => { this.send({ action: 'subscribe', stream: stream }); }); } - removeObserver(stream, observer) { + removeObserver(stream: any, observer: any) { console.log('unsubscribe', stream); delete this.observers[stream]; - this.getConnection().then(conn => { + this.getConnection().then((conn: any) => { this.send({ action: 'unsubscribe', stream: stream }); }); } - subscribe(streamName) { + subscribe(streamName: string) { console.log('LiveSrv.subscribe: ' + streamName); - return Observable.create(observer => { + return Observable.create((observer: any) => { this.addObserver(streamName, observer); return () => { diff --git a/public/app/core/reducers/navModel.ts b/public/app/core/reducers/navModel.ts index ac0e51854e7f..942739e45e6f 100644 --- a/public/app/core/reducers/navModel.ts +++ b/public/app/core/reducers/navModel.ts @@ -27,7 +27,7 @@ export const initialState: NavIndex = buildInitialState(); export const navIndexReducer = (state = initialState, action: Action): NavIndex => { switch (action.type) { case ActionTypes.UpdateNavIndex: - const newPages = {}; + const newPages: NavIndex = {}; const payload = action.payload; for (const node of payload.children) { diff --git a/public/app/core/selectors/location.ts b/public/app/core/selectors/location.ts index adc31f47e89d..b49bdbe0513a 100644 --- a/public/app/core/selectors/location.ts +++ b/public/app/core/selectors/location.ts @@ -1,3 +1,4 @@ -export const getRouteParamsId = state => state.routeParams.id; +import { LocationState } from 'app/types'; -export const getRouteParamsPage = state => state.routeParams.page; +export const getRouteParamsId = (state: LocationState) => state.routeParams.id; +export const getRouteParamsPage = (state: LocationState) => state.routeParams.page; diff --git a/public/app/core/services/AngularLoader.ts b/public/app/core/services/AngularLoader.ts index d9b78e66cbab..817e9c9f3985 100644 --- a/public/app/core/services/AngularLoader.ts +++ b/public/app/core/services/AngularLoader.ts @@ -3,16 +3,16 @@ import coreModule from 'app/core/core_module'; import _ from 'lodash'; export interface AngularComponent { - destroy(); - digest(); - getScope(); + destroy(): void; + digest(): void; + getScope(): any; } export class AngularLoader { /** @ngInject */ - constructor(private $compile, private $rootScope) {} + constructor(private $compile: any, private $rootScope: any) {} - load(elem, scopeProps, template): AngularComponent { + load(elem: any, scopeProps: any, template: string): AngularComponent { const scope = this.$rootScope.$new(); _.assign(scope, scopeProps); diff --git a/public/app/core/services/analytics.ts b/public/app/core/services/analytics.ts index be4371adb26c..1bf143d00cf9 100644 --- a/public/app/core/services/analytics.ts +++ b/public/app/core/services/analytics.ts @@ -4,7 +4,7 @@ import config from 'app/core/config'; export class Analytics { /** @ngInject */ - constructor(private $rootScope, private $location) {} + constructor(private $rootScope: any, private $location: any) {} gaInit() { $.ajax({ @@ -35,7 +35,7 @@ export class Analytics { } /** @ngInject */ -function startAnalytics(googleAnalyticsSrv) { +function startAnalytics(googleAnalyticsSrv: Analytics) { if ((config as any).googleAnalyticsId) { googleAnalyticsSrv.init(); } diff --git a/public/app/core/services/bridge_srv.ts b/public/app/core/services/bridge_srv.ts index 8bb828310cf1..c5769a61c6b9 100644 --- a/public/app/core/services/bridge_srv.ts +++ b/public/app/core/services/bridge_srv.ts @@ -3,13 +3,20 @@ import appEvents from 'app/core/app_events'; import { store } from 'app/store/store'; import locationUtil from 'app/core/utils/location_util'; import { updateLocation } from 'app/core/actions'; +import { ITimeoutService, ILocationService, IWindowService, IRootScopeService } from 'angular'; // Services that handles angular -> redux store sync & other react <-> angular sync export class BridgeSrv { - private fullPageReloadRoutes; + private fullPageReloadRoutes: string[]; /** @ngInject */ - constructor(private $location, private $timeout, private $window, private $rootScope, private $route) { + constructor( + private $location: ILocationService, + private $timeout: ITimeoutService, + private $window: IWindowService, + private $rootScope: IRootScopeService, + private $route: any + ) { this.fullPageReloadRoutes = ['/logout']; } @@ -55,7 +62,7 @@ export class BridgeSrv { } }); - appEvents.on('location-change', payload => { + appEvents.on('location-change', (payload: any) => { const urlWithoutBase = locationUtil.stripBaseFromUrl(payload.href); if (this.fullPageReloadRoutes.indexOf(urlWithoutBase) > -1) { this.$window.location.href = payload.href; diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts index 214c7efb7826..bbb448863866 100644 --- a/public/app/core/services/context_srv.ts +++ b/public/app/core/services/context_srv.ts @@ -44,7 +44,7 @@ export class ContextSrv { this.hasEditPermissionInFolders = this.user.hasEditPermissionInFolders; } - hasRole(role) { + hasRole(role: string) { return this.user.orgRole === role; } diff --git a/public/app/core/services/dynamic_directive_srv.ts b/public/app/core/services/dynamic_directive_srv.ts index c27842ab54ff..30c4c8602406 100644 --- a/public/app/core/services/dynamic_directive_srv.ts +++ b/public/app/core/services/dynamic_directive_srv.ts @@ -3,9 +3,9 @@ import coreModule from '../core_module'; class DynamicDirectiveSrv { /** @ngInject */ - constructor(private $compile) {} + constructor(private $compile: angular.ICompileService) {} - addDirective(element, name, scope) { + addDirective(element: any, name: string, scope: any) { const child = angular.element(document.createElement(name)); this.$compile(child)(scope); @@ -13,7 +13,7 @@ class DynamicDirectiveSrv { element.append(child); } - link(scope, elem, attrs, options) { + link(scope: any, elem: JQLite, attrs: any, options: any) { const directiveInfo = options.directive(scope); if (!directiveInfo || !directiveInfo.fn) { elem.empty(); @@ -28,13 +28,13 @@ class DynamicDirectiveSrv { this.addDirective(elem, directiveInfo.name, scope); } - create(options) { + create(options: any) { const directiveDef = { restrict: 'E', scope: options.scope, - link: (scope, elem, attrs) => { + link: (scope: any, elem: JQLite, attrs: any) => { if (options.watchPath) { - let childScope = null; + let childScope: any = null; scope.$watch(options.watchPath, () => { if (childScope) { childScope.$destroy(); diff --git a/public/app/core/services/impression_srv.ts b/public/app/core/services/impression_srv.ts index 57464f773b33..8e8a58d664fa 100644 --- a/public/app/core/services/impression_srv.ts +++ b/public/app/core/services/impression_srv.ts @@ -5,8 +5,8 @@ import config from 'app/core/config'; export class ImpressionSrv { constructor() {} - addDashboardImpression(dashboardId) { - const impressionsKey = this.impressionKey(config); + addDashboardImpression(dashboardId: number) { + const impressionsKey = this.impressionKey(); let impressions = []; if (store.exists(impressionsKey)) { impressions = JSON.parse(store.get(impressionsKey)); @@ -28,7 +28,7 @@ export class ImpressionSrv { } getDashboardOpened() { - let impressions = store.get(this.impressionKey(config)) || '[]'; + let impressions = store.get(this.impressionKey()) || '[]'; impressions = JSON.parse(impressions); @@ -39,7 +39,7 @@ export class ImpressionSrv { return impressions; } - impressionKey(config) { + impressionKey() { return 'dashboard_impressions-' + config.bootData.user.orgId; } } diff --git a/public/app/core/services/keybindingSrv.ts b/public/app/core/services/keybindingSrv.ts index 2473c1b8e363..6fb50dd4ec29 100644 --- a/public/app/core/services/keybindingSrv.ts +++ b/public/app/core/services/keybindingSrv.ts @@ -9,6 +9,7 @@ import { store } from 'app/store/store'; import Mousetrap from 'mousetrap'; import 'mousetrap-global-bind'; import { ContextSrv } from './context_srv'; +import { ILocationService, ITimeoutService } from 'angular'; export class KeybindingSrv { helpModal: boolean; @@ -17,11 +18,11 @@ export class KeybindingSrv { /** @ngInject */ constructor( - private $rootScope, - private $location, - private $timeout, - private datasourceSrv, - private timeSrv, + private $rootScope: any, + private $location: ILocationService, + private $timeout: ITimeoutService, + private datasourceSrv: any, + private timeSrv: any, private contextSrv: ContextSrv ) { // clear out all shortcuts on route change @@ -114,10 +115,10 @@ export class KeybindingSrv { } } - bind(keyArg, fn) { + bind(keyArg: string | string[], fn: () => void) { Mousetrap.bind( keyArg, - evt => { + (evt: any) => { evt.preventDefault(); evt.stopPropagation(); evt.returnValue = false; @@ -127,10 +128,10 @@ export class KeybindingSrv { ); } - bindGlobal(keyArg, fn) { + bindGlobal(keyArg: string, fn: () => void) { Mousetrap.bindGlobal( keyArg, - evt => { + (evt: any) => { evt.preventDefault(); evt.stopPropagation(); evt.returnValue = false; @@ -149,14 +150,14 @@ export class KeybindingSrv { this.$location.search(search); } - setupDashboardBindings(scope, dashboard) { + setupDashboardBindings(scope: any, dashboard: any) { this.bind('mod+o', () => { dashboard.graphTooltip = (dashboard.graphTooltip + 1) % 3; appEvents.emit('graph-hover-clear'); dashboard.startRefresh(); }); - this.bind('mod+s', e => { + this.bind('mod+s', () => { scope.appEvent('save-dashboard'); }); @@ -272,7 +273,7 @@ export class KeybindingSrv { dashboard.expandRows(); }); - this.bind('d n', e => { + this.bind('d n', () => { this.$location.url('/dashboard/new'); }); diff --git a/public/app/core/services/timer.ts b/public/app/core/services/timer.ts index 8234b6288d4e..65303ed78e47 100644 --- a/public/app/core/services/timer.ts +++ b/public/app/core/services/timer.ts @@ -1,20 +1,21 @@ import _ from 'lodash'; import coreModule from 'app/core/core_module'; +import { ITimeoutService } from 'angular'; // This service really just tracks a list of $timeout promises to give us a // method for canceling them all when we need to export class Timer { - timers = []; + timers: Array> = []; /** @ngInject */ - constructor(private $timeout) {} + constructor(private $timeout: ITimeoutService) {} - register(promise) { + register(promise: angular.IPromise) { this.timers.push(promise); return promise; } - cancel(promise) { + cancel(promise: angular.IPromise) { this.timers = _.without(this.timers, promise); this.$timeout.cancel(promise); } diff --git a/public/app/features/dashboard/services/TimeSrv.test.ts b/public/app/features/dashboard/services/TimeSrv.test.ts index e5b4c2407854..8bb93fc3aec5 100644 --- a/public/app/features/dashboard/services/TimeSrv.test.ts +++ b/public/app/features/dashboard/services/TimeSrv.test.ts @@ -1,5 +1,6 @@ -import { TimeSrv } from './TimeSrv'; import moment from 'moment'; +import { TimeSrv } from './TimeSrv'; +import { ContextSrvStub } from 'test/specs/helpers'; describe('timeSrv', () => { const rootScope = { @@ -26,7 +27,7 @@ describe('timeSrv', () => { }; beforeEach(() => { - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); timeSrv.init(_dashboard); _dashboard.refresh = false; }); @@ -56,7 +57,7 @@ describe('timeSrv', () => { })), }; - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); timeSrv.init(_dashboard); const time = timeSrv.timeRange(); expect(time.raw.from).toBe('now-2d'); @@ -71,7 +72,7 @@ describe('timeSrv', () => { })), }; - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); timeSrv.init(_dashboard); const time = timeSrv.timeRange(); @@ -87,7 +88,7 @@ describe('timeSrv', () => { })), }; - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); // dashboard saved with refresh on _dashboard.refresh = true; @@ -104,7 +105,7 @@ describe('timeSrv', () => { })), }; - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); timeSrv.init(_dashboard); const time = timeSrv.timeRange(); @@ -120,7 +121,7 @@ describe('timeSrv', () => { })), }; - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); timeSrv.init(_dashboard); const time = timeSrv.timeRange(); @@ -136,7 +137,7 @@ describe('timeSrv', () => { })), }; - timeSrv = new TimeSrv(rootScope, jest.fn(), location, timer, { isGrafanaVisibile: jest.fn() }); + timeSrv = new TimeSrv(rootScope as any, jest.fn() as any, location as any, timer, new ContextSrvStub() as any); _dashboard.time.from = 'now-6h'; timeSrv.init(_dashboard); diff --git a/public/app/features/dashboard/services/TimeSrv.ts b/public/app/features/dashboard/services/TimeSrv.ts index e54dd212539f..5fa0c63c35e7 100644 --- a/public/app/features/dashboard/services/TimeSrv.ts +++ b/public/app/features/dashboard/services/TimeSrv.ts @@ -8,19 +8,28 @@ import coreModule from 'app/core/core_module'; import * as dateMath from 'app/core/utils/datemath'; // Types -import { TimeRange } from '@grafana/ui'; +import { TimeRange, RawTimeRange } from '@grafana/ui'; +import { ITimeoutService, ILocationService } from 'angular'; +import { ContextSrv } from 'app/core/services/context_srv'; +import { DashboardModel } from '../state/DashboardModel'; export class TimeSrv { time: any; refreshTimer: any; - refresh: boolean; + refresh: any; oldRefresh: boolean; - dashboard: any; + dashboard: Partial; timeAtLoad: any; private autoRefreshBlocked: boolean; /** @ngInject */ - constructor($rootScope, private $timeout, private $location, private timer, private contextSrv) { + constructor( + $rootScope: any, + private $timeout: ITimeoutService, + private $location: ILocationService, + private timer: any, + private contextSrv: ContextSrv + ) { // default time this.time = { from: '6h', to: 'now' }; @@ -35,7 +44,7 @@ export class TimeSrv { }); } - init(dashboard) { + init(dashboard: Partial) { this.timer.cancelAll(); this.dashboard = dashboard; @@ -63,7 +72,7 @@ export class TimeSrv { } } - private parseUrlParam(value) { + private parseUrlParam(value: any) { if (value.indexOf('now') !== -1) { return value; } @@ -121,7 +130,7 @@ export class TimeSrv { return this.timeAtLoad && (this.timeAtLoad.from !== this.time.from || this.timeAtLoad.to !== this.time.to); } - setAutoRefresh(interval) { + setAutoRefresh(interval: any) { this.dashboard.refresh = interval; this.cancelNextRefresh(); @@ -153,7 +162,7 @@ export class TimeSrv { this.dashboard.timeRangeUpdated(this.timeRange()); } - private startNextRefreshTimer(afterMs) { + private startNextRefreshTimer(afterMs: number) { this.cancelNextRefresh(); this.refreshTimer = this.timer.register( this.$timeout(() => { @@ -171,7 +180,7 @@ export class TimeSrv { this.timer.cancel(this.refreshTimer); } - setTime(time, fromRouteUpdate?) { + setTime(time: RawTimeRange, fromRouteUpdate?: boolean) { _.extend(this.time, time); // disable refresh if zoom in or zoom out @@ -224,7 +233,7 @@ export class TimeSrv { }; } - zoomOut(e, factor) { + zoomOut(e: any, factor: number) { const range = this.timeRange(); const timespan = range.to.valueOf() - range.from.valueOf(); @@ -237,7 +246,7 @@ export class TimeSrv { } } -let singleton; +let singleton: TimeSrv; export function setTimeSrv(srv: TimeSrv) { singleton = srv; diff --git a/public/app/features/teams/TeamPages.tsx b/public/app/features/teams/TeamPages.tsx index e6b70e7b33b4..ae346aaaa97f 100644 --- a/public/app/features/teams/TeamPages.tsx +++ b/public/app/features/teams/TeamPages.tsx @@ -126,7 +126,7 @@ export class TeamPages extends PureComponent { function mapStateToProps(state) { const teamId = getRouteParamsId(state.location); const pageName = getRouteParamsPage(state.location) || 'members'; - const teamLoadingNav = getTeamLoadingNav(pageName); + const teamLoadingNav = getTeamLoadingNav(pageName as string); const navModel = getNavModel(state.navIndex, `team-${pageName}-${teamId}`, teamLoadingNav); const team = getTeam(state.team, teamId); const members = getTeamMembers(state.team); diff --git a/public/test/specs/helpers.ts b/public/test/specs/helpers.ts index 5d28506d4be0..9c56c6528846 100644 --- a/public/test/specs/helpers.ts +++ b/public/test/specs/helpers.ts @@ -172,6 +172,8 @@ export class TimeSrvStub { } export class ContextSrvStub { + isGrafanaVisibile = jest.fn(); + hasRole() { return true; } From 928f9516de9e583ec34ee7386b5d1c927641fa90 Mon Sep 17 00:00:00 2001 From: Reiner Gerecke Date: Sun, 28 Apr 2019 11:49:36 +0200 Subject: [PATCH 7/8] docs: explain correct access control model of GCS buckets (#16792) --- docs/sources/installation/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/installation/configuration.md b/docs/sources/installation/configuration.md index 5b05daec8d96..6d58d200c980 100644 --- a/docs/sources/installation/configuration.md +++ b/docs/sources/installation/configuration.md @@ -571,7 +571,7 @@ basic auth password Path to JSON key file associated with a Google service account to authenticate and authorize. Service Account keys can be created and downloaded from https://console.developers.google.com/permissions/serviceaccounts. -Service Account should have "Storage Object Writer" role. +Service Account should have "Storage Object Writer" role. The access control model of the bucket needs to be "Set object-level and bucket-level permissions". Grafana itself will make the images public readable. ### bucket name Bucket Name on Google Cloud Storage. From decd65671c473d4bd8e4f582a7ce61d6682c8fc5 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Sun, 28 Apr 2019 12:28:01 +0200 Subject: [PATCH 8/8] build: restore postgres integration tests (#16801) This fixes the CI script for postgres integration tests so that all tests are run. --- scripts/circle-test-postgres.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/circle-test-postgres.sh b/scripts/circle-test-postgres.sh index df4897484ad4..7dc6232b1f2a 100755 --- a/scripts/circle-test-postgres.sh +++ b/scripts/circle-test-postgres.sh @@ -12,7 +12,6 @@ function exit_if_fail { export GRAFANA_TEST_DB=postgres -exit_if_fail go test -v -run="StatsDataAccess" -tags=integration ./pkg/services/sqlstore/... -#time for d in $(go list ./pkg/...); do -# exit_if_fail go test -tags=integration $d -#done \ No newline at end of file +time for d in $(go list ./pkg/...); do + exit_if_fail go test -tags=integration $d +done \ No newline at end of file