From a8814979081a3a7fa94d349116f96e0d4ffe59c0 Mon Sep 17 00:00:00 2001 From: Pierre GIRAUD Date: Mon, 20 Aug 2018 15:33:49 +0200 Subject: [PATCH 01/37] Max number of repeated panels per row Instead of min width --- docs/sources/reference/dashboard.md | 2 +- docs/sources/reference/templating.md | 6 ++++-- pkg/models/dashboards.go | 2 +- .../features/dashboard/dashboard_migration.ts | 11 +++++++++- .../app/features/dashboard/dashboard_model.ts | 4 ++-- public/app/features/dashboard/panel_model.ts | 2 +- .../specs/dashboard_migration.test.ts | 20 ++++++++++--------- .../features/panel/partials/general_tab.html | 4 ++-- public/dashboards/home.json | 2 +- 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/docs/sources/reference/dashboard.md b/docs/sources/reference/dashboard.md index 6be12600da5..3d96923bc72 100644 --- a/docs/sources/reference/dashboard.md +++ b/docs/sources/reference/dashboard.md @@ -51,7 +51,7 @@ When a user creates a new dashboard, a new dashboard JSON object is initialized "list": [] }, "refresh": "5s", - "schemaVersion": 16, + "schemaVersion": 17, "version": 0, "links": [] } diff --git a/docs/sources/reference/templating.md b/docs/sources/reference/templating.md index f20cc0ccfc9..71ce6bdd2ae 100644 --- a/docs/sources/reference/templating.md +++ b/docs/sources/reference/templating.md @@ -292,9 +292,11 @@ The `direction` controls how the panels will be arranged. By choosing `horizontal` the panels will be arranged side-by-side. Grafana will automatically adjust the width of each repeated panel so that the whole row is filled. Currently, you cannot mix other panels on a row with a repeated -panel. Each panel will never be smaller that the provided `Min width` if you have many selected values. +panel. -By choosing `vertical` the panels will be arranged from top to bottom in a column. The `Min width` doesn't have any effect in this case. The width of the repeated panels will be the same as of the first panel (the original template) being repeated. +Set `Max per row` to tell grafana how many panels per row you want at most. It defaults to *4* if you don't set anything. + +By choosing `vertical` the panels will be arranged from top to bottom in a column. The width of the repeated panels will be the same as of the first panel (the original template) being repeated. Only make changes to the first panel (the original template). To have the changes take effect on all panels you need to trigger a dynamic dashboard re-build. You can do this by either changing the variable value (that is the basis for the repeat) or reload the dashboard. diff --git a/pkg/models/dashboards.go b/pkg/models/dashboards.go index 3a8010e797b..0f3f56175fe 100644 --- a/pkg/models/dashboards.go +++ b/pkg/models/dashboards.go @@ -112,7 +112,7 @@ func NewDashboard(title string) *Dashboard { func NewDashboardFolder(title string) *Dashboard { folder := NewDashboard(title) folder.IsFolder = true - folder.Data.Set("schemaVersion", 16) + folder.Data.Set("schemaVersion", 17) folder.Data.Set("version", 0) folder.IsFolder = true return folder diff --git a/public/app/features/dashboard/dashboard_migration.ts b/public/app/features/dashboard/dashboard_migration.ts index abd12ab4b13..4196456907f 100644 --- a/public/app/features/dashboard/dashboard_migration.ts +++ b/public/app/features/dashboard/dashboard_migration.ts @@ -21,7 +21,7 @@ export class DashboardMigrator { let i, j, k, n; const oldVersion = this.dashboard.schemaVersion; const panelUpgrades = []; - this.dashboard.schemaVersion = 16; + this.dashboard.schemaVersion = 17; if (oldVersion === this.dashboard.schemaVersion) { return; @@ -368,6 +368,15 @@ export class DashboardMigrator { this.upgradeToGridLayout(old); } + if (oldVersion < 17) { + panelUpgrades.push(panel => { + if (panel.minSpan) { + panel.maxPerRow = GRID_COLUMN_COUNT / panel.minSpan; + } + delete panel.minSpan; + }); + } + if (panelUpgrades.length === 0) { return; } diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index 6f98bc5a17a..33529abdd15 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -442,7 +442,7 @@ export class DashboardModel { } const selectedOptions = this.getSelectedVariableOptions(variable); - const minWidth = panel.minSpan || 6; + const maxPerRow = panel.maxPerRow || 4; let xPos = 0; let yPos = panel.gridPos.y; @@ -462,7 +462,7 @@ export class DashboardModel { } else { // set width based on how many are selected // assumed the repeated panels should take up full row width - copy.gridPos.w = Math.max(GRID_COLUMN_COUNT / selectedOptions.length, minWidth); + copy.gridPos.w = Math.max(GRID_COLUMN_COUNT / selectedOptions.length, GRID_COLUMN_COUNT / maxPerRow); copy.gridPos.x = xPos; copy.gridPos.y = yPos; diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index 2d5a70b47dd..2fec8e379dd 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -77,7 +77,7 @@ export class PanelModel { repeatPanelId?: number; repeatDirection?: string; repeatedByRow?: boolean; - minSpan?: number; + maxPerRow?: number; collapsed?: boolean; panels?: any; soloMode?: boolean; diff --git a/public/app/features/dashboard/specs/dashboard_migration.test.ts b/public/app/features/dashboard/specs/dashboard_migration.test.ts index 5f693c9f6d9..e15bd65d5a5 100644 --- a/public/app/features/dashboard/specs/dashboard_migration.test.ts +++ b/public/app/features/dashboard/specs/dashboard_migration.test.ts @@ -127,7 +127,7 @@ describe('DashboardModel', () => { }); it('dashboard schema version should be set to latest', () => { - expect(model.schemaVersion).toBe(16); + expect(model.schemaVersion).toBe(17); }); it('graph thresholds should be migrated', () => { @@ -364,14 +364,6 @@ describe('DashboardModel', () => { expect(dashboard.panels.length).toBe(2); }); - it('minSpan should be twice', () => { - model.rows = [createRow({ height: 8 }, [[6]])]; - model.rows[0].panels[0] = { minSpan: 12 }; - - const dashboard = new DashboardModel(model); - expect(dashboard.panels[0].minSpan).toBe(24); - }); - it('should assign id', () => { model.rows = [createRow({ collapse: true, height: 8 }, [[6], [6]])]; model.rows[0].panels[0] = {}; @@ -380,6 +372,16 @@ describe('DashboardModel', () => { expect(dashboard.panels[0].id).toBe(1); }); }); + + describe('when migrating from minSpan to maxPerRow', () => { + it('maxPerRow should be correct', () => { + const model = { + panels: [{ minSpan: 8 }], + }; + const dashboard = new DashboardModel(model); + expect(dashboard.panels[0].maxPerRow).toBe(3); + }); + }); }); function createRow(options, panelDescriptions: any[]) { diff --git a/public/app/features/panel/partials/general_tab.html b/public/app/features/panel/partials/general_tab.html index d6c2d4804a0..76c38f73912 100644 --- a/public/app/features/panel/partials/general_tab.html +++ b/public/app/features/panel/partials/general_tab.html @@ -32,8 +32,8 @@
- Min width -
diff --git a/public/dashboards/home.json b/public/dashboards/home.json index 55cf7242aa6..f2c441053bb 100644 --- a/public/dashboards/home.json +++ b/public/dashboards/home.json @@ -65,7 +65,7 @@ } ], "rows": [], - "schemaVersion": 16, + "schemaVersion": 17, "style": "dark", "tags": [], "templating": { From 97b087f5a561019392bb21053a64e07c91bbbba2 Mon Sep 17 00:00:00 2001 From: Pierre GIRAUD Date: Tue, 21 Aug 2018 09:22:41 +0200 Subject: [PATCH 02/37] Use factors for max repeated panels per row --- public/app/core/specs/factors.test.ts | 8 ++++++++ public/app/core/utils/factors.ts | 5 +++++ public/app/features/dashboard/dashboard_migration.ts | 12 +++++++++++- public/app/features/panel/panel_ctrl.ts | 5 ++++- 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 public/app/core/specs/factors.test.ts create mode 100644 public/app/core/utils/factors.ts diff --git a/public/app/core/specs/factors.test.ts b/public/app/core/specs/factors.test.ts new file mode 100644 index 00000000000..aed59b5be8b --- /dev/null +++ b/public/app/core/specs/factors.test.ts @@ -0,0 +1,8 @@ +import getFactors from 'app/core/utils/factors'; + +describe('factors', () => { + it('should return factors for 12', () => { + const factors = getFactors(12); + expect(factors).toEqual([1, 2, 3, 4, 6, 12]); + }); +}); diff --git a/public/app/core/utils/factors.ts b/public/app/core/utils/factors.ts new file mode 100644 index 00000000000..e9ce327a631 --- /dev/null +++ b/public/app/core/utils/factors.ts @@ -0,0 +1,5 @@ +// Returns the factors of a number +// Example getFactors(12) -> [1, 2, 3, 4, 6, 12] +export default function getFactors(num: number): number[] { + return Array.from(new Array(num + 1), (_, i) => i).filter(i => num % i === 0); +} diff --git a/public/app/features/dashboard/dashboard_migration.ts b/public/app/features/dashboard/dashboard_migration.ts index 4196456907f..2dbeb6c6e80 100644 --- a/public/app/features/dashboard/dashboard_migration.ts +++ b/public/app/features/dashboard/dashboard_migration.ts @@ -9,6 +9,7 @@ import { } from 'app/core/constants'; import { PanelModel } from './panel_model'; import { DashboardModel } from './dashboard_model'; +import getFactors from 'app/core/utils/factors'; export class DashboardMigrator { dashboard: DashboardModel; @@ -371,7 +372,16 @@ export class DashboardMigrator { if (oldVersion < 17) { panelUpgrades.push(panel => { if (panel.minSpan) { - panel.maxPerRow = GRID_COLUMN_COUNT / panel.minSpan; + const max = GRID_COLUMN_COUNT / panel.minSpan; + const factors = getFactors(GRID_COLUMN_COUNT); + // find the best match compared to factors + // (ie. [1,2,3,4,6,12,24] for 24 columns) + panel.maxPerRow = + factors[ + _.findIndex(factors, o => { + return o > max; + }) - 1 + ]; } delete panel.minSpan; }); diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index 432d22fecdf..f68423315d7 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -5,6 +5,7 @@ import Remarkable from 'remarkable'; import config from 'app/core/config'; import { profiler } from 'app/core/core'; import { Emitter } from 'app/core/core'; +import getFactors from 'app/core/utils/factors'; import { duplicatePanel, copyPanel as copyPanelUtil, @@ -12,7 +13,7 @@ import { sharePanel as sharePanelUtil, } from 'app/features/dashboard/utils/panel'; -import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, PANEL_HEADER_HEIGHT, PANEL_BORDER } from 'app/core/constants'; +import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT, PANEL_HEADER_HEIGHT, PANEL_BORDER } from 'app/core/constants'; export class PanelCtrl { panel: any; @@ -32,6 +33,7 @@ export class PanelCtrl { events: Emitter; timing: any; loading: boolean; + maxPanelsPerRowOptions: number[]; constructor($scope, $injector) { this.$injector = $injector; @@ -92,6 +94,7 @@ export class PanelCtrl { if (!this.editModeInitiated) { this.editModeInitiated = true; this.events.emit('init-edit-mode', null); + this.maxPanelsPerRowOptions = getFactors(GRID_COLUMN_COUNT); } } From 0571ad5ad7db0d9facf2f8c3e5d5b62f3ba2fa25 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Wed, 9 Jan 2019 11:33:08 +0100 Subject: [PATCH 03/37] Removes unnecessary warnings from webpack output about missing exports This should not break anything as ForkTsCheckerWebpackPlugin takes care of that --- scripts/webpack/IgnoreNotFoundExportPlugin.js | 22 +++++++++++++++++++ scripts/webpack/webpack.hot.js | 2 ++ 2 files changed, 24 insertions(+) create mode 100644 scripts/webpack/IgnoreNotFoundExportPlugin.js diff --git a/scripts/webpack/IgnoreNotFoundExportPlugin.js b/scripts/webpack/IgnoreNotFoundExportPlugin.js new file mode 100644 index 00000000000..37bf1f7200e --- /dev/null +++ b/scripts/webpack/IgnoreNotFoundExportPlugin.js @@ -0,0 +1,22 @@ +// https://github.com/TypeStrong/ts-loader/issues/653#issuecomment-390889335 + +const ModuleDependencyWarning = require("webpack/lib/ModuleDependencyWarning") + +module.exports = class IgnoreNotFoundExportPlugin { + apply(compiler) { + const messageRegExp = /export '.*'( \(reexported as '.*'\))? was not found in/ + function doneHook(stats) { + stats.compilation.warnings = stats.compilation.warnings.filter(function(warn) { + if (warn instanceof ModuleDependencyWarning && messageRegExp.test(warn.message)) { + return false + } + return true; + }) + } + if (compiler.hooks) { + compiler.hooks.done.tap("IgnoreNotFoundExportPlugin", doneHook) + } else { + compiler.plugin("done", doneHook) + } + } +} diff --git a/scripts/webpack/webpack.hot.js b/scripts/webpack/webpack.hot.js index ca08ff1e726..b37e4c08592 100644 --- a/scripts/webpack/webpack.hot.js +++ b/scripts/webpack/webpack.hot.js @@ -7,6 +7,7 @@ const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); +const IgnoreNotFoundExportPlugin = require("./IgnoreNotFoundExportPlugin.js"); module.exports = merge(common, { entry: { @@ -111,5 +112,6 @@ module.exports = merge(common, { NODE_ENV: JSON.stringify('development'), }, }), + new IgnoreNotFoundExportPlugin(), ], }); From f374da032e5cc9a12646c596298a1d8d38200206 Mon Sep 17 00:00:00 2001 From: Pierre GIRAUD Date: Wed, 9 Jan 2019 11:34:13 +0100 Subject: [PATCH 04/37] Hint for user on when the repeat is applied --- public/app/features/panel/partials/general_tab.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/app/features/panel/partials/general_tab.html b/public/app/features/panel/partials/general_tab.html index 76c38f73912..8881d2c28a4 100644 --- a/public/app/features/panel/partials/general_tab.html +++ b/public/app/features/panel/partials/general_tab.html @@ -37,7 +37,12 @@ +
+
+ Note: You may need to change the variable selection to see this in action. +
+ From e2fe663dba0922810bc56165023db4846024289f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 9 Jan 2019 11:34:22 +0100 Subject: [PATCH 05/37] Added TestRuleButton --- public/app/features/alerting/AlertTab.tsx | 29 +++++++++-- .../app/features/alerting/TestRuleButton.tsx | 48 +++++++++++++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 public/app/features/alerting/TestRuleButton.tsx diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index a5afbc198fc..5623fac95c1 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -1,5 +1,5 @@ // Libraries -import React, { PureComponent } from 'react'; +import React, { PureComponent, SFC } from 'react'; // Services & Utils import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader'; @@ -14,6 +14,7 @@ import 'app/features/alerting/AlertTabCtrl'; // Types import { DashboardModel } from '../dashboard/dashboard_model'; import { PanelModel } from '../dashboard/panel_model'; +import { TestRuleButton } from './TestRuleButton'; interface Props { angularPanel?: AngularComponent; @@ -21,6 +22,16 @@ interface Props { panel: PanelModel; } +interface LoadingPlaceholderProps { + text: string; +} + +const LoadingPlaceholder: SFC = ({ text }) => ( +
+ {text} +
+); + export class AlertTab extends PureComponent { element: any; component: AngularComponent; @@ -65,9 +76,7 @@ export class AlertTab extends PureComponent { const loader = getAngularLoader(); const template = ''; - const scopeProps = { - ctrl: this.panelCtrl, - }; + const scopeProps = { ctrl: this.panelCtrl }; this.component = loader.load(this.element, scopeProps, template); } @@ -111,6 +120,16 @@ export class AlertTab extends PureComponent { }; }; + renderTestRuleButton = () => { + const { panel, dashboard } = this.props; + return ; + }; + + testRule = (): EditorToolbarView => ({ + title: 'Test Rule', + render: () => this.renderTestRuleButton(), + }); + onAddAlert = () => { this.panelCtrl._enableAlert(); this.component.digest(); @@ -120,7 +139,7 @@ export class AlertTab extends PureComponent { render() { const { alert } = this.props.panel; - const toolbarItems = alert ? [this.stateHistory(), this.deleteAlert()] : []; + const toolbarItems = alert ? [this.stateHistory(), this.testRule(), this.deleteAlert()] : []; const model = { title: 'Panel has no alert rule defined', diff --git a/public/app/features/alerting/TestRuleButton.tsx b/public/app/features/alerting/TestRuleButton.tsx new file mode 100644 index 00000000000..032d7c7e4f8 --- /dev/null +++ b/public/app/features/alerting/TestRuleButton.tsx @@ -0,0 +1,48 @@ +import React, { PureComponent } from 'react'; +import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter'; +import { getBackendSrv } from 'app/core/services/backend_srv'; +import { DashboardModel } from '../dashboard/dashboard_model'; + +export interface Props { + panelId: number; + dashboard: DashboardModel; + LoadingPlaceholder: any; +} + +interface State { + isLoading: boolean; + testRuleResponse: {}; +} + +export class TestRuleButton extends PureComponent { + constructor(props) { + super(props); + this.state = { isLoading: false, testRuleResponse: {} }; + } + + componentDidMount() { + this.testRule(); + } + + async testRule() { + const { panelId, dashboard } = this.props; + const payload = { dashboard: dashboard.getSaveModelClone(), panelId }; + const testRuleResponse = await getBackendSrv().post(`/api/alerts/test`, payload); + this.setState(prevState => ({ ...prevState, isLoading: false, testRuleResponse })); + } + + render() { + const { testRuleResponse, isLoading } = this.state; + const { LoadingPlaceholder } = this.props; + + if (isLoading === true) { + return ; + } + + return ( + <> + + + ); + } +} From 8b8af6436c3b392dcf56b103db950c814251f743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 9 Jan 2019 11:38:10 +0100 Subject: [PATCH 06/37] Removed Test Rule button from Angular and view --- public/app/features/alerting/AlertTabCtrl.ts | 17 ----------------- .../features/alerting/partials/alert_tab.html | 14 -------------- 2 files changed, 31 deletions(-) diff --git a/public/app/features/alerting/AlertTabCtrl.ts b/public/app/features/alerting/AlertTabCtrl.ts index 2be25e9df6a..af00e79b085 100644 --- a/public/app/features/alerting/AlertTabCtrl.ts +++ b/public/app/features/alerting/AlertTabCtrl.ts @@ -9,8 +9,6 @@ import appEvents from 'app/core/app_events'; export class AlertTabCtrl { panel: any; panelCtrl: any; - testing: boolean; - testResult: any; subTabIndex: number; conditionTypes: any; alert: any; @@ -406,21 +404,6 @@ export class AlertTabCtrl { }, }); } - - test() { - this.testing = true; - this.testResult = false; - - const payload = { - dashboard: this.dashboardSrv.getCurrent().getSaveModelClone(), - panelId: this.panelCtrl.panel.id, - }; - - return this.backendSrv.post('/api/alerts/test', payload).then(res => { - this.testResult = res; - this.testing = false; - }); - } } /** @ngInject */ diff --git a/public/app/features/alerting/partials/alert_tab.html b/public/app/features/alerting/partials/alert_tab.html index da862203da6..90e0c7bbac2 100644 --- a/public/app/features/alerting/partials/alert_tab.html +++ b/public/app/features/alerting/partials/alert_tab.html @@ -121,20 +121,6 @@ - -
- -
- - -
- Evaluating rule -
- -
-
From 9b8a5333cb8cf3bcf41ec39c9f07d9270febad3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 9 Jan 2019 11:39:56 +0100 Subject: [PATCH 07/37] Added tests for TestRuleButton --- .../features/alerting/TestRuleButton.test.tsx | 44 +++++++++++++++++++ .../TestRuleButton.test.tsx.snap | 15 +++++++ 2 files changed, 59 insertions(+) create mode 100644 public/app/features/alerting/TestRuleButton.test.tsx create mode 100644 public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap diff --git a/public/app/features/alerting/TestRuleButton.test.tsx b/public/app/features/alerting/TestRuleButton.test.tsx new file mode 100644 index 00000000000..ae3b570cf43 --- /dev/null +++ b/public/app/features/alerting/TestRuleButton.test.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import { DashboardModel } from '../dashboard/dashboard_model'; +import { Props, TestRuleButton } from './TestRuleButton'; + +jest.mock('app/core/services/backend_srv', () => ({ + getBackendSrv: () => ({ + post: jest.fn(), + }), +})); + +const setup = (propOverrides?: object) => { + const props: Props = { + panelId: 1, + dashboard: new DashboardModel({ panels: [{ id: 1 }] }), + LoadingPlaceholder: {}, + }; + + Object.assign(props, propOverrides); + + const wrapper = shallow(); + + return { wrapper, instance: wrapper.instance() as TestRuleButton }; +}; + +describe('Render', () => { + it('should render component', () => { + const { wrapper } = setup(); + + expect(wrapper).toMatchSnapshot(); + }); +}); + +describe('Life cycle', () => { + describe('component did mount', () => { + it('should call testRule', () => { + const { instance } = setup(); + instance.testRule = jest.fn(); + instance.componentDidMount(); + + expect(instance.testRule).toHaveBeenCalled(); + }); + }); +}); diff --git a/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap b/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap new file mode 100644 index 00000000000..0e1c95d7233 --- /dev/null +++ b/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` + + + +`; From 67e8958aec04fed841c8ac0b7f3a6bb0bc4e4af3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 9 Jan 2019 11:49:17 +0100 Subject: [PATCH 08/37] Fixed a small bug when toggling items in toolbar --- public/app/features/dashboard/dashgrid/EditorTabBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx index b7da81a23f8..95397b884c8 100644 --- a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx +++ b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx @@ -52,7 +52,7 @@ export class EditorTabBody extends PureComponent { onToggleToolBarView = (item: EditorToolbarView) => { this.setState({ openView: item, - isOpen: !this.state.isOpen, + isOpen: this.state.openView !== item ? true : !this.state.isOpen, }); }; From 236d7b12138928eee17560cb3071e2414651f3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 9 Jan 2019 13:20:50 +0100 Subject: [PATCH 09/37] Changes after PR comments --- .../app/features/alerting/TestRuleButton.tsx | 14 +++++--------- .../__snapshots__/TestRuleButton.test.tsx.snap | 18 ++++++++---------- .../dashboard/dashgrid/EditorTabBody.tsx | 2 +- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/public/app/features/alerting/TestRuleButton.tsx b/public/app/features/alerting/TestRuleButton.tsx index 032d7c7e4f8..f9927b1a182 100644 --- a/public/app/features/alerting/TestRuleButton.tsx +++ b/public/app/features/alerting/TestRuleButton.tsx @@ -15,10 +15,10 @@ interface State { } export class TestRuleButton extends PureComponent { - constructor(props) { - super(props); - this.state = { isLoading: false, testRuleResponse: {} }; - } + readonly state: State = { + isLoading: false, + testRuleResponse: {}, + }; componentDidMount() { this.testRule(); @@ -39,10 +39,6 @@ export class TestRuleButton extends PureComponent { return ; } - return ( - <> - - - ); + return ; } } diff --git a/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap b/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap index 0e1c95d7233..d1ed3e64e99 100644 --- a/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap +++ b/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap @@ -1,15 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render component 1`] = ` - - - + } + json={Object {}} + open={3} +/> `; diff --git a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx index 95397b884c8..ebf57613699 100644 --- a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx +++ b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx @@ -52,7 +52,7 @@ export class EditorTabBody extends PureComponent { onToggleToolBarView = (item: EditorToolbarView) => { this.setState({ openView: item, - isOpen: this.state.openView !== item ? true : !this.state.isOpen, + isOpen: this.state.openView !== item || !this.state.isOpen, }); }; From e1f6870fce9a7d564c54c61152a561d138fa2d73 Mon Sep 17 00:00:00 2001 From: SamuelToh Date: Wed, 9 Jan 2019 16:46:20 +1000 Subject: [PATCH 10/37] 4075: Interpolate tempvar on alias --- .../datasource/elasticsearch/datasource.ts | 4 ++++ .../elasticsearch/specs/datasource.test.ts | 21 +++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/datasource/elasticsearch/datasource.ts b/public/app/plugins/datasource/elasticsearch/datasource.ts index c2f2364d49d..3781a9048a6 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.ts +++ b/public/app/plugins/datasource/elasticsearch/datasource.ts @@ -254,6 +254,10 @@ export class ElasticDatasource { continue; } + if (target.alias) { + target.alias = this.templateSrv.replace(target.alias, options.scopedVars, 'lucene'); + } + const queryString = this.templateSrv.replace(target.query || '*', options.scopedVars, 'lucene'); const queryObj = this.queryBuilder.build(target, adhocFilters, queryString); const esQuery = angular.toJson(queryObj); diff --git a/public/app/plugins/datasource/elasticsearch/specs/datasource.test.ts b/public/app/plugins/datasource/elasticsearch/specs/datasource.test.ts index 4be0c35852c..0480fcb52e8 100644 --- a/public/app/plugins/datasource/elasticsearch/specs/datasource.test.ts +++ b/public/app/plugins/datasource/elasticsearch/specs/datasource.test.ts @@ -16,7 +16,13 @@ describe('ElasticDatasource', function(this: any) { }; const templateSrv = { - replace: jest.fn(text => text), + replace: jest.fn(text => { + if (text.startsWith("$")) { + return `resolvedVariable`; + } else { + return text; + } + }), getAdhocFilters: jest.fn(() => []), }; @@ -67,7 +73,7 @@ describe('ElasticDatasource', function(this: any) { }); describe('When issuing metric query with interval pattern', () => { - let requestOptions, parts, header; + let requestOptions, parts, header, query; beforeEach(() => { createDatasource({ @@ -81,19 +87,22 @@ describe('ElasticDatasource', function(this: any) { return Promise.resolve({ data: { responses: [] } }); }); - ctx.ds.query({ + query = { range: { from: moment.utc([2015, 4, 30, 10]), to: moment.utc([2015, 5, 1, 10]), }, targets: [ { + alias: "$varAlias", bucketAggs: [], metrics: [{ type: 'raw_document' }], query: 'escape\\:test', }, ], - }); + }; + + ctx.ds.query(query); parts = requestOptions.data.split('\n'); header = angular.fromJson(parts[0]); @@ -103,6 +112,10 @@ describe('ElasticDatasource', function(this: any) { expect(header.index).toEqual(['asd-2015.05.30', 'asd-2015.05.31', 'asd-2015.06.01']); }); + it('should resolve the alias variable', () => { + expect(query.targets[0].alias).toEqual('resolvedVariable'); + }); + it('should json escape lucene query', () => { const body = angular.fromJson(parts[1]); expect(body.query.bool.filter[1].query_string.query).toBe('escape\\:test'); From 9e3ab71e403298b9ffa7710e84a8e6b47b336dcc Mon Sep 17 00:00:00 2001 From: SamuelToh Date: Thu, 10 Jan 2019 10:47:22 +1000 Subject: [PATCH 11/37] 11503: escape measurement filter regex value --- public/app/plugins/datasource/influxdb/query_builder.ts | 3 ++- .../plugins/datasource/influxdb/specs/query_builder.test.ts | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/public/app/plugins/datasource/influxdb/query_builder.ts b/public/app/plugins/datasource/influxdb/query_builder.ts index a61216787d3..0b3e6f01e74 100644 --- a/public/app/plugins/datasource/influxdb/query_builder.ts +++ b/public/app/plugins/datasource/influxdb/query_builder.ts @@ -1,4 +1,5 @@ import _ from 'lodash'; +import kbn from 'app/core/utils/kbn'; function renderTagCondition(tag, index) { let str = ''; @@ -43,7 +44,7 @@ export class InfluxQueryBuilder { } else if (type === 'MEASUREMENTS') { query = 'SHOW MEASUREMENTS'; if (withMeasurementFilter) { - query += ' WITH MEASUREMENT =~ /' + withMeasurementFilter + '/'; + query += ' WITH MEASUREMENT =~ /' + kbn.regexEscape(withMeasurementFilter) + '/'; } } else if (type === 'FIELDS') { measurement = this.target.measurement; diff --git a/public/app/plugins/datasource/influxdb/specs/query_builder.test.ts b/public/app/plugins/datasource/influxdb/specs/query_builder.test.ts index e21b95ac374..ee617e7e774 100644 --- a/public/app/plugins/datasource/influxdb/specs/query_builder.test.ts +++ b/public/app/plugins/datasource/influxdb/specs/query_builder.test.ts @@ -50,6 +50,12 @@ describe('InfluxQueryBuilder', () => { expect(query).toBe('SHOW MEASUREMENTS WITH MEASUREMENT =~ /something/ LIMIT 100'); }); + it('should escape the regex value in measurement query', () => { + const builder = new InfluxQueryBuilder({ measurement: '', tags: [] }); + const query = builder.buildExploreQuery('MEASUREMENTS', undefined, 'abc/edf/'); + expect(query).toBe('SHOW MEASUREMENTS WITH MEASUREMENT =~ /abc\\/edf\\// LIMIT 100'); + }); + it('should have WITH MEASUREMENT WHERE in measurement query for non-empty query with tags', () => { const builder = new InfluxQueryBuilder({ measurement: '', From 1dc1af7e00823e1107fc683b1e40ad5f86ba1743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 10 Jan 2019 08:37:40 +0100 Subject: [PATCH 12/37] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ce4ffbe109..ff5da04f209 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,9 @@ GRAFANA_TEST_DB=postgres go test ./pkg/... If you have any idea for an improvement or found a bug, do not hesitate to open an issue. And if you have time clone this repo and submit a pull request and help me make Grafana -the kickass metrics & devops dashboard we all dream about! +the kickass metrics & devops dashboard we all dream about! + +Read the [contributing](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guide then check the [`beginner friendly`](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) label to find issues that are easy and that we would like help with. ## Plugin development From 5fc07663410722713c54a457fa0ae1a9c7c871e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 10 Jan 2019 09:37:32 +0100 Subject: [PATCH 13/37] Moved Thresholds and styles to grafana/ui/components --- packages/grafana-ui/package.json | 3 ++- .../src/components/Thresholds}/Threshold.test.tsx | 8 ++++---- .../grafana-ui/src/components/Thresholds}/Thresholds.tsx | 8 ++++---- .../grafana-ui/src/components/Thresholds/_Thresholds.scss | 0 packages/grafana-ui/src/components/index.scss | 1 + packages/grafana-ui/src/components/index.ts | 1 + packages/grafana-ui/src/types/panel.ts | 6 ++++++ public/app/plugins/panel/gauge/GaugePanelOptions.tsx | 3 +-- public/app/types/index.ts | 3 ++- public/app/types/panel.ts | 6 ------ public/sass/_grafana.scss | 1 - 11 files changed, 21 insertions(+), 19 deletions(-) rename {public/app/plugins/panel/gauge => packages/grafana-ui/src/components/Thresholds}/Threshold.test.tsx (91%) rename {public/app/plugins/panel/gauge => packages/grafana-ui/src/components/Thresholds}/Thresholds.tsx (96%) rename public/sass/components/_thresholds.scss => packages/grafana-ui/src/components/Thresholds/_Thresholds.scss (100%) diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 6548f75e91f..724c3334643 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -23,7 +23,8 @@ "react-highlight-words": "0.11.0", "react-popper": "^1.3.0", "react-transition-group": "^2.2.1", - "react-virtualized": "^9.21.0" + "react-virtualized": "^9.21.0", + "tinycolor2": "^1.4.1" }, "devDependencies": { "@types/classnames": "^2.2.6", diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx similarity index 91% rename from public/app/plugins/panel/gauge/Threshold.test.tsx rename to packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx index 852b9f4c104..eac82e1b0f4 100644 --- a/public/app/plugins/panel/gauge/Threshold.test.tsx +++ b/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { shallow } from 'enzyme'; -import Thresholds from './Thresholds'; -import { defaultProps } from './GaugePanelOptions'; -import { BasicGaugeColor } from 'app/types'; import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; +import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; +import { Options } from 'app/plugins/panel/gauge/types'; +import { BasicGaugeColor } from 'app/types'; +import { Thresholds } from './Thresholds'; const setup = (propOverrides?: object) => { const props: PanelOptionsProps = { diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx similarity index 96% rename from public/app/plugins/panel/gauge/Thresholds.tsx rename to packages/grafana-ui/src/components/Thresholds/Thresholds.tsx index b4d4930e11d..802891998e9 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx @@ -1,16 +1,16 @@ import React, { PureComponent } from 'react'; import tinycolor from 'tinycolor2'; import { ColorPicker } from 'app/core/components/colorpicker/ColorPicker'; -import { BasicGaugeColor, Threshold } from 'app/types'; -import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; +import { BasicGaugeColor } from 'app/types'; +import { PanelOptionsProps, Threshold } from '@grafana/ui'; +import { Options } from 'app/plugins/panel/gauge/types'; interface State { thresholds: Threshold[]; baseColor: string; } -export default class Thresholds extends PureComponent, State> { +export class Thresholds extends PureComponent, State> { constructor(props) { super(props); diff --git a/public/sass/components/_thresholds.scss b/packages/grafana-ui/src/components/Thresholds/_Thresholds.scss similarity index 100% rename from public/sass/components/_thresholds.scss rename to packages/grafana-ui/src/components/Thresholds/_Thresholds.scss diff --git a/packages/grafana-ui/src/components/index.scss b/packages/grafana-ui/src/components/index.scss index e1d1474bb16..d0a81675490 100644 --- a/packages/grafana-ui/src/components/index.scss +++ b/packages/grafana-ui/src/components/index.scss @@ -1,3 +1,4 @@ @import 'CustomScrollbar/CustomScrollbar'; @import 'DeleteButton/DeleteButton'; +@import 'Thresholds/Thresholds'; @import 'Tooltip/Tooltip'; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index abb1cf1b34c..5293cb7bc66 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -2,3 +2,4 @@ export { DeleteButton } from './DeleteButton/DeleteButton'; export { Tooltip } from './Tooltip/Tooltip'; export { Portal } from './Portal/Portal'; export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; +export { Thresholds } from './Thresholds/Thresholds'; diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index 44336555a81..46fe84a211c 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -29,3 +29,9 @@ export interface PanelMenuItem { shortcut?: string; subMenu?: PanelMenuItem[]; } + +export interface Threshold { + index: number; + value: number; + color?: string; +} diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 2b16ef5a1fe..7b627a09592 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,8 +1,7 @@ import React, { PureComponent } from 'react'; import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; -import Thresholds from 'app/plugins/panel/gauge/Thresholds'; import { BasicGaugeColor } from 'app/types'; -import { PanelOptionsProps } from '@grafana/ui'; +import { PanelOptionsProps, Thresholds } from '@grafana/ui'; import ValueMappings from 'app/plugins/panel/gauge/ValueMappings'; import { Options } from './types'; import GaugeOptions from './GaugeOptions'; diff --git a/public/app/types/index.ts b/public/app/types/index.ts index ab52b03ab17..52b2b996542 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -9,7 +9,7 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys'; import { Invitee, OrgUser, User, UsersState, UserState } from './user'; import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources'; import { DataQuery, DataQueryResponse, DataQueryOptions } from './series'; -import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from './panel'; +import { BasicGaugeColor, MappingType, RangeMap, ValueMap } from './panel'; import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins'; import { Organization, OrganizationState } from './organization'; import { @@ -20,6 +20,7 @@ import { } from './appNotifications'; import { DashboardSearchHit } from './search'; import { ValidationEvents, ValidationRule } from './form'; +import { Threshold } from '@grafana/ui'; export { Team, TeamsState, diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 31674d20304..1f5a2307733 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -1,9 +1,3 @@ -export interface Threshold { - index: number; - value: number; - color?: string; -} - export enum MappingType { ValueToText = 1, RangeToText = 2, diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 10cc7335bdf..a3dd204eb63 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -102,7 +102,6 @@ @import 'components/toolbar'; @import 'components/add_data_source.scss'; @import 'components/page_loader'; -@import 'components/thresholds'; @import 'components/toggle_button_group'; @import 'components/value-mappings'; @import 'components/popover-box'; From 96759e39a63a2934a6cbbe34434a33d9767ceb53 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 10 Jan 2019 09:47:39 +0100 Subject: [PATCH 14/37] docker: enable flux in influxdb docker block --- devenv/docker/blocks/influxdb/influxdb.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/devenv/docker/blocks/influxdb/influxdb.conf b/devenv/docker/blocks/influxdb/influxdb.conf index c0331ce7449..120739dd896 100644 --- a/devenv/docker/blocks/influxdb/influxdb.conf +++ b/devenv/docker/blocks/influxdb/influxdb.conf @@ -69,6 +69,7 @@ reporting-disabled = false unix-socket-enabled = false # enable http service over unix domain socket # bind-socket = "/var/run/influxdb.sock" + flux-enabled = true [subscriber] enabled = true From 7819529d459c6c20aab524c26528212f754b72fb Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Thu, 10 Jan 2019 13:29:53 +0100 Subject: [PATCH 15/37] Migrate Select components to @grafana/ui --- .../components/Select/IndicatorsContainer.tsx | 2 +- .../components/Select/NoOptionsMessage.tsx | 0 .../src}/components/Select/OptionGroup.tsx | 2 +- .../components/Select/PickerOption.test.tsx | 34 +++++++++++++------ .../src}/components/Select/PickerOption.tsx | 2 +- .../src}/components/Select/Select.tsx | 8 ++--- .../components/Select/resetSelectStyles.ts | 27 +++++++++++++++ packages/grafana-ui/src/components/index.ts | 6 ++++ .../PermissionList/AddPermission.tsx | 2 +- .../DisabledPermissionListItem.tsx | 2 +- .../PermissionList/PermissionListItem.tsx | 2 +- .../components/Select/DataSourcePicker.tsx | 2 +- .../core/components/Select/ResetStyles.tsx | 25 -------------- .../app/core/components/Select/TeamPicker.tsx | 2 +- .../app/core/components/Select/UnitPicker.tsx | 2 +- .../app/core/components/Select/UserPicker.tsx | 2 +- .../SharedPreferences/SharedPreferences.tsx | 2 +- .../core/components/TagFilter/TagFilter.tsx | 6 ++-- public/app/plugins/panel/gauge/MappingRow.tsx | 2 +- .../app/plugins/panel/gauge/ValueOptions.tsx | 2 +- yarn.lock | 6 ++-- 21 files changed, 78 insertions(+), 60 deletions(-) rename {public/app/core => packages/grafana-ui/src}/components/Select/IndicatorsContainer.tsx (88%) rename {public/app/core => packages/grafana-ui/src}/components/Select/NoOptionsMessage.tsx (100%) rename {public/app/core => packages/grafana-ui/src}/components/Select/OptionGroup.tsx (96%) rename {public/app/core => packages/grafana-ui/src}/components/Select/PickerOption.test.tsx (55%) rename {public/app/core => packages/grafana-ui/src}/components/Select/PickerOption.tsx (96%) rename {public/app/core => packages/grafana-ui/src}/components/Select/Select.tsx (97%) create mode 100644 packages/grafana-ui/src/components/Select/resetSelectStyles.ts delete mode 100644 public/app/core/components/Select/ResetStyles.tsx diff --git a/public/app/core/components/Select/IndicatorsContainer.tsx b/packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx similarity index 88% rename from public/app/core/components/Select/IndicatorsContainer.tsx rename to packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx index d4de51a2cef..8fc8e0b08d3 100644 --- a/public/app/core/components/Select/IndicatorsContainer.tsx +++ b/packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { components } from '@torkelo/react-select'; -export const IndicatorsContainer = props => { +export const IndicatorsContainer = (props: any) => { const isOpen = props.selectProps.menuIsOpen; return ( diff --git a/public/app/core/components/Select/NoOptionsMessage.tsx b/packages/grafana-ui/src/components/Select/NoOptionsMessage.tsx similarity index 100% rename from public/app/core/components/Select/NoOptionsMessage.tsx rename to packages/grafana-ui/src/components/Select/NoOptionsMessage.tsx diff --git a/public/app/core/components/Select/OptionGroup.tsx b/packages/grafana-ui/src/components/Select/OptionGroup.tsx similarity index 96% rename from public/app/core/components/Select/OptionGroup.tsx rename to packages/grafana-ui/src/components/Select/OptionGroup.tsx index a001f58c681..ed2b72a537c 100644 --- a/public/app/core/components/Select/OptionGroup.tsx +++ b/packages/grafana-ui/src/components/Select/OptionGroup.tsx @@ -24,7 +24,7 @@ export default class OptionGroup extends PureComponent = { cx: jest.fn(), clearValue: jest.fn(), - onSelect: jest.fn(), getStyles: jest.fn(), getValue: jest.fn(), hasValue: true, @@ -18,21 +18,33 @@ const model = { isFocused: false, isSelected: false, innerRef: null, - innerProps: null, - label: 'Option label', - type: null, - children: 'Model title', - data: { - title: 'Model title', - imgUrl: 'url/to/avatar', - label: 'User picker label', + innerProps: { + id: '', + key: '', + onClick: jest.fn(), + onMouseOver: jest.fn(), + tabIndex: 1, }, + label: 'Option label', + type: 'option', + children: 'Model title', className: 'class-for-user-picker', }; describe('PickerOption', () => { it('renders correctly', () => { - const tree = renderer.create().toJSON(); + const tree = renderer + .create( + + ) + .toJSON(); expect(tree).toMatchSnapshot(); }); }); diff --git a/public/app/core/components/Select/PickerOption.tsx b/packages/grafana-ui/src/components/Select/PickerOption.tsx similarity index 96% rename from public/app/core/components/Select/PickerOption.tsx rename to packages/grafana-ui/src/components/Select/PickerOption.tsx index d263f6f832b..ac6a5c62783 100644 --- a/public/app/core/components/Select/PickerOption.tsx +++ b/packages/grafana-ui/src/components/Select/PickerOption.tsx @@ -28,7 +28,7 @@ export const Option = (props: ExtendedOptionProps) => { }; // was not able to type this without typescript error -export const SingleValue = props => { +export const SingleValue = (props: any) => { const { children, data } = props; return ( diff --git a/public/app/core/components/Select/Select.tsx b/packages/grafana-ui/src/components/Select/Select.tsx similarity index 97% rename from public/app/core/components/Select/Select.tsx rename to packages/grafana-ui/src/components/Select/Select.tsx index f66e07c9ed6..c456de1c94d 100644 --- a/public/app/core/components/Select/Select.tsx +++ b/packages/grafana-ui/src/components/Select/Select.tsx @@ -10,7 +10,7 @@ import { Option, SingleValue } from './PickerOption'; import OptionGroup from './OptionGroup'; import IndicatorsContainer from './IndicatorsContainer'; import NoOptionsMessage from './NoOptionsMessage'; -import ResetStyles from './ResetStyles'; +import resetSelectStyles from './resetSelectStyles'; import { CustomScrollbar } from '@grafana/ui'; export interface SelectOptionItem { @@ -53,7 +53,7 @@ interface AsyncProps { loadingMessage?: () => string; } -export const MenuList = props => { +export const MenuList = (props: any) => { return ( {props.children} @@ -127,7 +127,7 @@ export class Select extends PureComponent { onChange={onChange} options={options} placeholder={placeholder || 'Choose'} - styles={ResetStyles} + styles={resetSelectStyles()} isDisabled={isDisabled} isLoading={isLoading} isClearable={isClearable} @@ -212,7 +212,7 @@ export class AsyncSelect extends PureComponent { isLoading={isLoading} defaultOptions={defaultOptions} placeholder={placeholder || 'Choose'} - styles={ResetStyles} + styles={resetSelectStyles()} loadingMessage={loadingMessage} noOptionsMessage={noOptionsMessage} isDisabled={isDisabled} diff --git a/packages/grafana-ui/src/components/Select/resetSelectStyles.ts b/packages/grafana-ui/src/components/Select/resetSelectStyles.ts new file mode 100644 index 00000000000..a980741c17c --- /dev/null +++ b/packages/grafana-ui/src/components/Select/resetSelectStyles.ts @@ -0,0 +1,27 @@ +export default function resetSelectStyles() { + return { + clearIndicator: () => ({}), + container: () => ({}), + control: () => ({}), + dropdownIndicator: () => ({}), + group: () => ({}), + groupHeading: () => ({}), + indicatorsContainer: () => ({}), + indicatorSeparator: () => ({}), + input: () => ({}), + loadingIndicator: () => ({}), + loadingMessage: () => ({}), + menu: () => ({}), + menuList: ({ maxHeight }: { maxHeight: number }) => ({ + maxHeight, + }), + multiValue: () => ({}), + multiValueLabel: () => ({}), + multiValueRemove: () => ({}), + noOptionsMessage: () => ({}), + option: () => ({}), + placeholder: () => ({}), + singleValue: () => ({}), + valueContainer: () => ({}), + }; +} diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index abb1cf1b34c..9780b841959 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -2,3 +2,9 @@ export { DeleteButton } from './DeleteButton/DeleteButton'; export { Tooltip } from './Tooltip/Tooltip'; export { Portal } from './Portal/Portal'; export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; + +// Select +export { Select, AsyncSelect, SelectOptionItem } from './Select/Select'; +export { IndicatorsContainer } from './Select/IndicatorsContainer'; +export { NoOptionsMessage } from './Select/NoOptionsMessage'; +export { default as resetSelectStyles } from './Select/resetSelectStyles'; diff --git a/public/app/core/components/PermissionList/AddPermission.tsx b/public/app/core/components/PermissionList/AddPermission.tsx index 749bef680bf..30219371257 100644 --- a/public/app/core/components/PermissionList/AddPermission.tsx +++ b/public/app/core/components/PermissionList/AddPermission.tsx @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { UserPicker } from 'app/core/components/Select/UserPicker'; import { TeamPicker, Team } from 'app/core/components/Select/TeamPicker'; -import { Select, SelectOptionItem } from 'app/core/components/Select/Select'; +import { Select, SelectOptionItem } from '@grafana/ui'; import { User } from 'app/types'; import { dashboardPermissionLevels, diff --git a/public/app/core/components/PermissionList/DisabledPermissionListItem.tsx b/public/app/core/components/PermissionList/DisabledPermissionListItem.tsx index d3f9ddbb1fb..ebf3cbad1bc 100644 --- a/public/app/core/components/PermissionList/DisabledPermissionListItem.tsx +++ b/public/app/core/components/PermissionList/DisabledPermissionListItem.tsx @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import Select from 'app/core/components/Select/Select'; +import { Select } from '@grafana/ui'; import { dashboardPermissionLevels } from 'app/types/acl'; export interface Props { diff --git a/public/app/core/components/PermissionList/PermissionListItem.tsx b/public/app/core/components/PermissionList/PermissionListItem.tsx index e726667cfbb..c33b564154a 100644 --- a/public/app/core/components/PermissionList/PermissionListItem.tsx +++ b/public/app/core/components/PermissionList/PermissionListItem.tsx @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import { Select } from 'app/core/components/Select/Select'; +import { Select } from '@grafana/ui'; import { dashboardPermissionLevels, DashboardAcl, PermissionLevel } from 'app/types/acl'; import { FolderInfo } from 'app/types'; diff --git a/public/app/core/components/Select/DataSourcePicker.tsx b/public/app/core/components/Select/DataSourcePicker.tsx index 1a9081038c0..372c4cd4013 100644 --- a/public/app/core/components/Select/DataSourcePicker.tsx +++ b/public/app/core/components/Select/DataSourcePicker.tsx @@ -3,7 +3,7 @@ import React, { PureComponent } from 'react'; import _ from 'lodash'; // Components -import Select from './Select'; +import { Select } from '@grafana/ui'; // Types import { DataSourceSelectItem } from 'app/types'; diff --git a/public/app/core/components/Select/ResetStyles.tsx b/public/app/core/components/Select/ResetStyles.tsx deleted file mode 100644 index c34abb544ab..00000000000 --- a/public/app/core/components/Select/ResetStyles.tsx +++ /dev/null @@ -1,25 +0,0 @@ -export default { - clearIndicator: () => ({}), - container: () => ({}), - control: () => ({}), - dropdownIndicator: () => ({}), - group: () => ({}), - groupHeading: () => ({}), - indicatorsContainer: () => ({}), - indicatorSeparator: () => ({}), - input: () => ({}), - loadingIndicator: () => ({}), - loadingMessage: () => ({}), - menu: () => ({}), - menuList: ({ maxHeight }: { maxHeight: number }) => ({ - maxHeight, - }), - multiValue: () => ({}), - multiValueLabel: () => ({}), - multiValueRemove: () => ({}), - noOptionsMessage: () => ({}), - option: () => ({}), - placeholder: () => ({}), - singleValue: () => ({}), - valueContainer: () => ({}), -}; diff --git a/public/app/core/components/Select/TeamPicker.tsx b/public/app/core/components/Select/TeamPicker.tsx index bc608318806..8d9e1d48d81 100644 --- a/public/app/core/components/Select/TeamPicker.tsx +++ b/public/app/core/components/Select/TeamPicker.tsx @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import _ from 'lodash'; -import { AsyncSelect } from './Select'; +import { AsyncSelect } from '@grafana/ui'; import { debounce } from 'lodash'; import { getBackendSrv } from 'app/core/services/backend_srv'; diff --git a/public/app/core/components/Select/UnitPicker.tsx b/public/app/core/components/Select/UnitPicker.tsx index 75885cbbb84..54b064df7dc 100644 --- a/public/app/core/components/Select/UnitPicker.tsx +++ b/public/app/core/components/Select/UnitPicker.tsx @@ -1,5 +1,5 @@ import React, { PureComponent } from 'react'; -import Select from './Select'; +import { Select } from '@grafana/ui'; import kbn from 'app/core/utils/kbn'; interface Props { diff --git a/public/app/core/components/Select/UserPicker.tsx b/public/app/core/components/Select/UserPicker.tsx index 8496d707105..ff4ae32f068 100644 --- a/public/app/core/components/Select/UserPicker.tsx +++ b/public/app/core/components/Select/UserPicker.tsx @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import _ from 'lodash'; // Components -import { AsyncSelect } from './Select'; +import { AsyncSelect } from '@grafana/ui'; // Utils & Services import { debounce } from 'lodash'; diff --git a/public/app/core/components/SharedPreferences/SharedPreferences.tsx b/public/app/core/components/SharedPreferences/SharedPreferences.tsx index d41626d9a2f..b13393ab2e1 100644 --- a/public/app/core/components/SharedPreferences/SharedPreferences.tsx +++ b/public/app/core/components/SharedPreferences/SharedPreferences.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import { Label } from 'app/core/components/Label/Label'; -import Select from 'app/core/components/Select/Select'; +import { Select } from '@grafana/ui'; import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv'; import { DashboardSearchHit } from 'app/types'; diff --git a/public/app/core/components/TagFilter/TagFilter.tsx b/public/app/core/components/TagFilter/TagFilter.tsx index 4b2de6b1b16..7e8bc9c6fd2 100644 --- a/public/app/core/components/TagFilter/TagFilter.tsx +++ b/public/app/core/components/TagFilter/TagFilter.tsx @@ -1,12 +1,10 @@ import React from 'react'; +import { NoOptionsMessage, IndicatorsContainer, resetSelectStyles } from '@grafana/ui'; import AsyncSelect from '@torkelo/react-select/lib/Async'; import { TagOption } from './TagOption'; import { TagBadge } from './TagBadge'; -import IndicatorsContainer from 'app/core/components/Select/IndicatorsContainer'; -import NoOptionsMessage from 'app/core/components/Select/NoOptionsMessage'; import { components } from '@torkelo/react-select'; -import ResetStyles from 'app/core/components/Select/ResetStyles'; export interface Props { tags: string[]; @@ -51,7 +49,7 @@ export class TagFilter extends React.Component { getOptionValue: i => i.value, getOptionLabel: i => i.label, value: tags, - styles: ResetStyles, + styles: resetSelectStyles(), filterOption: (option, searchQuery) => { const regex = RegExp(searchQuery, 'i'); return regex.test(option.value); diff --git a/public/app/plugins/panel/gauge/MappingRow.tsx b/public/app/plugins/panel/gauge/MappingRow.tsx index 35d0b2e638c..277afb4fd5c 100644 --- a/public/app/plugins/panel/gauge/MappingRow.tsx +++ b/public/app/plugins/panel/gauge/MappingRow.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { Label } from 'app/core/components/Label/Label'; -import { Select } from 'app/core/components/Select/Select'; +import { Select } from '@grafana/ui'; import { MappingType, RangeMap, ValueMap } from 'app/types'; interface Props { diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/ValueOptions.tsx index 4aafc0b0457..e8af6bc2fe1 100644 --- a/public/app/plugins/panel/gauge/ValueOptions.tsx +++ b/public/app/plugins/panel/gauge/ValueOptions.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { Label } from 'app/core/components/Label/Label'; -import Select from 'app/core/components/Select/Select'; +import { Select} from '@grafana/ui'; import UnitPicker from 'app/core/components/Select/UnitPicker'; import { PanelOptionsProps } from '@grafana/ui'; import { Options } from './types'; diff --git a/yarn.lock b/yarn.lock index 8eff64ca822..c5734ffcad3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1098,14 +1098,14 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^2.0.15": +"@types/react-transition-group@*", "@types/react-transition-group@^2.0.15": version "2.0.15" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.15.tgz#e5ee3fe558832e141cc6041bdd54caea7b787af8" integrity sha512-S0QnNzbHoWXDbKBl/xk5dxA4FT+BNlBcI3hku991cl8Cz3ytOkUMcCRtzdX11eb86E131bSsQqy5WrPCdJYblw== dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.1.0", "@types/react@^16.7.6": +"@types/react@*", "@types/react@16.7.6", "@types/react@^16.1.0", "@types/react@^16.7.6": version "16.7.6" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.6.tgz#80e4bab0d0731ad3ae51f320c4b08bdca5f03040" integrity sha512-QBUfzftr/8eg/q3ZRgf/GaDP6rTYc7ZNem+g4oZM38C9vXyV8AWRWaTQuW5yCoZTsfHrN7b3DeEiUnqH9SrnpA== @@ -3168,7 +3168,7 @@ caniuse-api@^1.5.2: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: +caniuse-db@1.0.30000772, caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: version "1.0.30000772" resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000772.tgz#51aae891768286eade4a3d8319ea76d6a01b512b" integrity sha1-UarokXaChureSj2DGep21qAbUSs= From fbb3ad5fc45a93e040d1ab90092741612d990696 Mon Sep 17 00:00:00 2001 From: bergquist Date: Thu, 10 Jan 2019 09:35:48 +0100 Subject: [PATCH 16/37] make sure frequency cannot be zero frequency set to zero causes division by zero panics in the alert schedular. closes #14810 --- pkg/services/alerting/extractor.go | 2 +- pkg/services/alerting/rule.go | 21 ++++++-- pkg/services/alerting/rule_test.go | 80 ++++++++++++++++++++++-------- 3 files changed, 79 insertions(+), 24 deletions(-) diff --git a/pkg/services/alerting/extractor.go b/pkg/services/alerting/extractor.go index e33e3dc2af3..5b911c5a9ad 100644 --- a/pkg/services/alerting/extractor.go +++ b/pkg/services/alerting/extractor.go @@ -112,7 +112,7 @@ func (e *DashAlertExtractor) getAlertFromPanels(jsonWithPanels *simplejson.Json, frequency, err := getTimeDurationStringToSeconds(jsonAlert.Get("frequency").MustString()) if err != nil { - return nil, ValidationError{Reason: "Could not parse frequency"} + return nil, ValidationError{Reason: err.Error()} } rawFor := jsonAlert.Get("for").MustString() diff --git a/pkg/services/alerting/rule.go b/pkg/services/alerting/rule.go index d2a505145ac..4423046d600 100644 --- a/pkg/services/alerting/rule.go +++ b/pkg/services/alerting/rule.go @@ -1,16 +1,21 @@ package alerting import ( + "errors" "fmt" "regexp" "strconv" "time" "github.com/grafana/grafana/pkg/components/simplejson" - m "github.com/grafana/grafana/pkg/models" ) +var ( + ErrFrequencyCannotBeZeroOrLess = errors.New(`"evaluate every" cannot be zero or below`) + ErrFrequencyCouldNotBeParsed = errors.New(`"evaluate every" field could not be parsed`) +) + type Rule struct { Id int64 OrgId int64 @@ -76,7 +81,7 @@ func getTimeDurationStringToSeconds(str string) (int64, error) { matches := ValueFormatRegex.FindAllString(str, 1) if len(matches) <= 0 { - return 0, fmt.Errorf("Frequency could not be parsed") + return 0, ErrFrequencyCouldNotBeParsed } value, err := strconv.Atoi(matches[0]) @@ -84,6 +89,10 @@ func getTimeDurationStringToSeconds(str string) (int64, error) { return 0, err } + if value == 0 { + return 0, ErrFrequencyCannotBeZeroOrLess + } + unit := UnitFormatRegex.FindAllString(str, 1)[0] if val, ok := unitMultiplier[unit]; ok { @@ -101,7 +110,6 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) { model.PanelId = ruleDef.PanelId model.Name = ruleDef.Name model.Message = ruleDef.Message - model.Frequency = ruleDef.Frequency model.State = ruleDef.State model.LastStateChange = ruleDef.NewStateDate model.For = ruleDef.For @@ -109,6 +117,13 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) { model.ExecutionErrorState = m.ExecutionErrorOption(ruleDef.Settings.Get("executionErrorState").MustString("alerting")) model.StateChanges = ruleDef.StateChanges + model.Frequency = ruleDef.Frequency + // frequency cannot be zero since that would not execute the alert rule. + // so we fallback to 60 seconds if `Freqency` is missing + if model.Frequency == 0 { + model.Frequency = 60 + } + for _, v := range ruleDef.Settings.Get("notifications").MustArray() { jsonModel := simplejson.NewFromAny(v) id, err := jsonModel.Get("id").Int64() diff --git a/pkg/services/alerting/rule_test.go b/pkg/services/alerting/rule_test.go index 2a9e95e5723..cf25cc118f4 100644 --- a/pkg/services/alerting/rule_test.go +++ b/pkg/services/alerting/rule_test.go @@ -14,6 +14,36 @@ func (f *FakeCondition) Eval(context *EvalContext) (*ConditionResult, error) { return &ConditionResult{}, nil } +func TestAlertRuleFrequencyParsing(t *testing.T) { + tcs := []struct { + input string + err error + result int64 + }{ + {input: "10s", result: 10}, + {input: "10m", result: 600}, + {input: "1h", result: 3600}, + {input: "1o", result: 1}, + {input: "0s", err: ErrFrequencyCannotBeZeroOrLess}, + {input: "0m", err: ErrFrequencyCannotBeZeroOrLess}, + {input: "0h", err: ErrFrequencyCannotBeZeroOrLess}, + {input: "0", err: ErrFrequencyCannotBeZeroOrLess}, + {input: "-1s", err: ErrFrequencyCouldNotBeParsed}, + } + + for _, tc := range tcs { + r, err := getTimeDurationStringToSeconds(tc.input) + if err != tc.err { + t.Errorf("expected error: '%v' got: '%v'", tc.err, err) + return + } + + if r != tc.result { + t.Errorf("expected result: %d got %d", tc.result, r) + } + } +} + func TestAlertRuleModel(t *testing.T) { Convey("Testing alert rule", t, func() { @@ -21,26 +51,6 @@ func TestAlertRuleModel(t *testing.T) { return &FakeCondition{}, nil }) - Convey("Can parse seconds", func() { - seconds, _ := getTimeDurationStringToSeconds("10s") - So(seconds, ShouldEqual, 10) - }) - - Convey("Can parse minutes", func() { - seconds, _ := getTimeDurationStringToSeconds("10m") - So(seconds, ShouldEqual, 600) - }) - - Convey("Can parse hours", func() { - seconds, _ := getTimeDurationStringToSeconds("1h") - So(seconds, ShouldEqual, 3600) - }) - - Convey("defaults to seconds", func() { - seconds, _ := getTimeDurationStringToSeconds("1o") - So(seconds, ShouldEqual, 1) - }) - Convey("should return err for empty string", func() { _, err := getTimeDurationStringToSeconds("") So(err, ShouldNotBeNil) @@ -89,5 +99,35 @@ func TestAlertRuleModel(t *testing.T) { So(len(alertRule.Notifications), ShouldEqual, 2) }) }) + + Convey("can construct alert rule model with invalid frequency", func() { + json := ` + { + "name": "name2", + "description": "desc2", + "noDataMode": "critical", + "enabled": true, + "frequency": "0s", + "conditions": [ { "type": "test", "prop": 123 } ], + "notifications": [] + }` + + alertJSON, jsonErr := simplejson.NewJson([]byte(json)) + So(jsonErr, ShouldBeNil) + + alert := &m.Alert{ + Id: 1, + OrgId: 1, + DashboardId: 1, + PanelId: 1, + Frequency: 0, + + Settings: alertJSON, + } + + alertRule, err := NewRuleFromDBAlert(alert) + So(err, ShouldBeNil) + So(alertRule.Frequency, ShouldEqual, 60) + }) }) } From 53f0f08efab58384aac5f73c76c5de381f9f36db Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Thu, 10 Jan 2019 14:24:24 +0100 Subject: [PATCH 17/37] Fixing TS and updating snapshot --- .../src/components/Select/IndicatorsContainer.tsx | 3 +++ .../grafana-ui/src/components/Select/NoOptionsMessage.tsx | 4 ++++ .../grafana-ui/src/components/Select/PickerOption.test.tsx | 2 -- packages/grafana-ui/src/components/Select/PickerOption.tsx | 3 +++ packages/grafana-ui/src/components/Select/Select.tsx | 5 +++++ .../Select/__snapshots__/PickerOption.test.tsx.snap | 7 ++++++- 6 files changed, 21 insertions(+), 3 deletions(-) rename {public/app/core => packages/grafana-ui/src}/components/Select/__snapshots__/PickerOption.test.tsx.snap (81%) diff --git a/packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx b/packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx index 8fc8e0b08d3..260fe6ebbdf 100644 --- a/packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx +++ b/packages/grafana-ui/src/components/Select/IndicatorsContainer.tsx @@ -1,4 +1,7 @@ import React from 'react'; + +// Ignoring because I couldn't get @types/react-select work wih Torkel's fork +// @ts-ignore import { components } from '@torkelo/react-select'; export const IndicatorsContainer = (props: any) => { diff --git a/packages/grafana-ui/src/components/Select/NoOptionsMessage.tsx b/packages/grafana-ui/src/components/Select/NoOptionsMessage.tsx index 5fe229340a4..1cec06a5301 100644 --- a/packages/grafana-ui/src/components/Select/NoOptionsMessage.tsx +++ b/packages/grafana-ui/src/components/Select/NoOptionsMessage.tsx @@ -1,5 +1,9 @@ import React from 'react'; + +// Ignoring because I couldn't get @types/react-select work wih Torkel's fork +// @ts-ignore import { components } from '@torkelo/react-select'; +// @ts-ignore import { OptionProps } from '@torkelo/react-select/lib/components/Option'; export interface Props { diff --git a/packages/grafana-ui/src/components/Select/PickerOption.test.tsx b/packages/grafana-ui/src/components/Select/PickerOption.test.tsx index 96a4ff9cf2a..20187734c1a 100644 --- a/packages/grafana-ui/src/components/Select/PickerOption.test.tsx +++ b/packages/grafana-ui/src/components/Select/PickerOption.test.tsx @@ -38,9 +38,7 @@ describe('PickerOption', () => { ) diff --git a/packages/grafana-ui/src/components/Select/PickerOption.tsx b/packages/grafana-ui/src/components/Select/PickerOption.tsx index ac6a5c62783..4bbcb74a563 100644 --- a/packages/grafana-ui/src/components/Select/PickerOption.tsx +++ b/packages/grafana-ui/src/components/Select/PickerOption.tsx @@ -1,4 +1,7 @@ import React from 'react'; + +// Ignoring because I couldn't get @types/react-select work wih Torkel's fork +// @ts-ignore import { components } from '@torkelo/react-select'; import { OptionProps } from 'react-select/lib/components/Option'; diff --git a/packages/grafana-ui/src/components/Select/Select.tsx b/packages/grafana-ui/src/components/Select/Select.tsx index c456de1c94d..a2584ce8124 100644 --- a/packages/grafana-ui/src/components/Select/Select.tsx +++ b/packages/grafana-ui/src/components/Select/Select.tsx @@ -1,8 +1,13 @@ // Libraries import classNames from 'classnames'; import React, { PureComponent } from 'react'; + +// Ignoring because I couldn't get @types/react-select work wih Torkel's fork +// @ts-ignore import { default as ReactSelect } from '@torkelo/react-select'; +// @ts-ignore import { default as ReactAsyncSelect } from '@torkelo/react-select/lib/Async'; +// @ts-ignore import { components } from '@torkelo/react-select'; // Components diff --git a/public/app/core/components/Select/__snapshots__/PickerOption.test.tsx.snap b/packages/grafana-ui/src/components/Select/__snapshots__/PickerOption.test.tsx.snap similarity index 81% rename from public/app/core/components/Select/__snapshots__/PickerOption.test.tsx.snap rename to packages/grafana-ui/src/components/Select/__snapshots__/PickerOption.test.tsx.snap index 2136c22b1c6..c4185025a5d 100644 --- a/public/app/core/components/Select/__snapshots__/PickerOption.test.tsx.snap +++ b/packages/grafana-ui/src/components/Select/__snapshots__/PickerOption.test.tsx.snap @@ -1,7 +1,12 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PickerOption renders correctly 1`] = ` -
+
From 702d4490018dcd41f763f81b7631fef17a873429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20W=C3=BCrbach?= Date: Thu, 20 Dec 2018 22:48:53 +0100 Subject: [PATCH 18/37] Docker image for ARM --- .circleci/config.yml | 44 +++++++++++++------------- build.go | 2 ++ packaging/docker/Dockerfile | 6 ++-- packaging/docker/build.sh | 40 ++++++++++++++++++----- packaging/docker/push_to_docker_hub.sh | 36 +++++++++++++++++---- scripts/build/build.sh | 7 ++++ 6 files changed, 96 insertions(+), 39 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 236d5aec398..3d66a8ef13b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -200,47 +200,47 @@ jobs: - dist/grafana* grafana-docker-master: - docker: - - image: docker:stable-git + machine: + image: circleci/classic:201808-01 steps: - checkout - attach_workspace: at: . - - setup_remote_docker - run: docker info - - run: cp dist/grafana-latest.linux-x64.tar.gz packaging/docker + - run: docker run --privileged linuxkit/binfmt:v0.6 + - run: cp dist/grafana-latest.linux-*.tar.gz packaging/docker - run: cd packaging/docker && ./build-deploy.sh "master-${CIRCLE_SHA1}" - - run: rm packaging/docker/grafana-latest.linux-x64.tar.gz + - run: rm packaging/docker/grafana-latest.linux-*.tar.gz - run: cp enterprise-dist/grafana-enterprise-*.linux-amd64.tar.gz packaging/docker/grafana-latest.linux-x64.tar.gz - run: cd packaging/docker && ./build-enterprise.sh "master" grafana-docker-pr: - docker: - - image: docker:stable-git + machine: + image: circleci/classic:201808-01 steps: - checkout - attach_workspace: at: . - - setup_remote_docker - run: docker info - - run: cp dist/grafana-latest.linux-x64.tar.gz packaging/docker + - run: docker run --privileged linuxkit/binfmt:v0.6 + - run: cp dist/grafana-latest.linux-*.tar.gz packaging/docker - run: cd packaging/docker && ./build.sh "${CIRCLE_SHA1}" grafana-docker-release: - docker: - - image: docker:stable-git - steps: - - checkout - - attach_workspace: - at: . - - setup_remote_docker - - run: docker info - - run: cp dist/grafana-latest.linux-x64.tar.gz packaging/docker - - run: cd packaging/docker && ./build-deploy.sh "${CIRCLE_TAG}" - - run: rm packaging/docker/grafana-latest.linux-x64.tar.gz - - run: cp enterprise-dist/grafana-enterprise-*.linux-amd64.tar.gz packaging/docker/grafana-latest.linux-x64.tar.gz - - run: cd packaging/docker && ./build-enterprise.sh "${CIRCLE_TAG}" + machine: + image: circleci/classic:201808-01 + steps: + - checkout + - attach_workspace: + at: . + - run: docker info + - run: docker run --privileged linuxkit/binfmt:v0.6 + - run: cp dist/grafana-latest.linux-*.tar.gz packaging/docker + - run: cd packaging/docker && ./build-deploy.sh "${CIRCLE_TAG}" + - run: rm packaging/docker/grafana-latest.linux-*.tar.gz + - run: cp enterprise-dist/grafana-enterprise-*.linux-amd64.tar.gz packaging/docker/grafana-latest.linux-x64.tar.gz + - run: cd packaging/docker && ./build-enterprise.sh "${CIRCLE_TAG}" build-enterprise: docker: diff --git a/build.go b/build.go index 9d5216de1d0..4486cd3deb9 100644 --- a/build.go +++ b/build.go @@ -164,6 +164,8 @@ func makeLatestDistCopies() { "_amd64.deb": "dist/grafana_latest_amd64.deb", ".x86_64.rpm": "dist/grafana-latest-1.x86_64.rpm", ".linux-amd64.tar.gz": "dist/grafana-latest.linux-x64.tar.gz", + ".linux-armv7.tar.gz": "dist/grafana-latest.linux-armv7.tar.gz", + ".linux-arm64.tar.gz": "dist/grafana-latest.linux-arm64.tar.gz", } for _, file := range files { diff --git a/packaging/docker/Dockerfile b/packaging/docker/Dockerfile index 4d4f6539972..d4f2f2aa7a3 100644 --- a/packaging/docker/Dockerfile +++ b/packaging/docker/Dockerfile @@ -1,4 +1,5 @@ -FROM debian:stretch-slim +ARG BASE_IMAGE=debian:stretch-slim +FROM ${BASE_IMAGE} ARG GRAFANA_TGZ="grafana-latest.linux-x64.tar.gz" @@ -10,7 +11,8 @@ COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz RUN mkdir /tmp/grafana && tar xfvz /tmp/grafana.tar.gz --strip-components=1 -C /tmp/grafana -FROM debian:stretch-slim +ARG BASE_IMAGE=debian:stretch-slim +FROM ${BASE_IMAGE} ARG GF_UID="472" ARG GF_GID="472" diff --git a/packaging/docker/build.sh b/packaging/docker/build.sh index c303c71cd5f..1bad2980d34 100755 --- a/packaging/docker/build.sh +++ b/packaging/docker/build.sh @@ -1,25 +1,49 @@ #!/bin/sh -_grafana_tag=$1 +_grafana_tag=${1:-} +_docker_repo=${2:-grafana/grafana} # If the tag starts with v, treat this as a official release if echo "$_grafana_tag" | grep -q "^v"; then _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) - _docker_repo=${2:-grafana/grafana} else _grafana_version=$_grafana_tag - _docker_repo=${2:-grafana/grafana-dev} fi echo "Building ${_docker_repo}:${_grafana_version}" -docker build \ - --tag "${_docker_repo}:${_grafana_version}" \ - --no-cache=true . +export DOCKER_CLI_EXPERIMENTAL=enabled + +# Build grafana image for a specific arch +docker_build () { + base_image=$1 + grafana_tgz=$2 + tag=$3 + + docker build \ + --build-arg BASE_IMAGE=${base_image} \ + --build-arg GRAFANA_TGZ=${grafana_tgz} \ + --tag "${tag}" \ + --no-cache=true . +} + +# Tag docker images of all architectures +docker_tag_all () { + repo=$1 + tag=$2 + docker tag "${_docker_repo}:${_grafana_version}" "${repo}:${tag}" + docker tag "${_docker_repo}-arm32v7-linux:${_grafana_version}" "${repo}-arm32v7-linux:${tag}" + docker tag "${_docker_repo}-arm64v8-linux:${_grafana_version}" "${repo}-arm64v8-linux:${tag}" +} + +docker_build "debian:stretch-slim" "grafana-latest.linux-x64.tar.gz" "${_docker_repo}:${_grafana_version}" +docker_build "arm32v7/debian:stretch-slim" "grafana-latest.linux-armv7.tar.gz" "${_docker_repo}-arm32v7-linux:${_grafana_version}" +docker_build "arm64v8/debian:stretch-slim" "grafana-latest.linux-arm64.tar.gz" "${_docker_repo}-arm64v8-linux:${_grafana_version}" # Tag as 'latest' for official release; otherwise tag as grafana/grafana:master if echo "$_grafana_tag" | grep -q "^v"; then - docker tag "${_docker_repo}:${_grafana_version}" "${_docker_repo}:latest" + docker_tag_all "${_docker_repo}" "latest" else - docker tag "${_docker_repo}:${_grafana_version}" "grafana/grafana:master" + docker_tag_all "${_docker_repo}" "master" + docker tag "${_docker_repo}:${_grafana_version} grafana/grafana-dev:${_grafana_version}" fi diff --git a/packaging/docker/push_to_docker_hub.sh b/packaging/docker/push_to_docker_hub.sh index 526c216f8fa..cef6d596851 100755 --- a/packaging/docker/push_to_docker_hub.sh +++ b/packaging/docker/push_to_docker_hub.sh @@ -1,24 +1,46 @@ #!/bin/sh set -e -_grafana_tag=$1 +_grafana_tag=${1:-} +_docker_repo=${2:-grafana/grafana} # If the tag starts with v, treat this as a official release if echo "$_grafana_tag" | grep -q "^v"; then _grafana_version=$(echo "${_grafana_tag}" | cut -d "v" -f 2) - _docker_repo=${2:-grafana/grafana} else _grafana_version=$_grafana_tag - _docker_repo=${2:-grafana/grafana-dev} fi +export DOCKER_CLI_EXPERIMENTAL=enabled + echo "pushing ${_docker_repo}:${_grafana_version}" -docker push "${_docker_repo}:${_grafana_version}" + + +docker_push_all () { + repo=$1 + tag=$2 + + # Push each image individually + docker push "${repo}:${tag}" + docker push "${repo}-arm32v7-linux:${tag}" + docker push "${repo}-arm64v8-linux:${tag}" + + # Create and push a multi-arch manifest + docker manifest create "${repo}:${tag}" \ + "${repo}:${tag}" \ + "${repo}-arm32v7-linux:${tag}" \ + "${repo}-arm64v8-linux:${tag}" + + docker manifest push "${repo}:${tag}" +} if echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -vq "beta"; then echo "pushing ${_docker_repo}:latest" - docker push "${_docker_repo}:latest" + docker_push_all "${_docker_repo}" "latest" + docker_push_all "${_docker_repo}" "${_grafana_version}" +elif echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -q "beta"; then + docker_push_all "${_docker_repo}" "${_grafana_version}" elif echo "$_grafana_tag" | grep -q "master"; then - echo "pushing grafana/grafana:master" - docker push grafana/grafana:master + docker_push_all "grafana/grafana" "master" + docker push "grafana/grafana-dev:${_grafana_version}" fi diff --git a/scripts/build/build.sh b/scripts/build/build.sh index 8362942c6cd..1222053f1c8 100755 --- a/scripts/build/build.sh +++ b/scripts/build/build.sh @@ -8,6 +8,8 @@ set -e EXTRA_OPTS="$@" +CCARMV7=arm-linux-gnueabihf-gcc +CCARM64=aarch64-linux-gnu-gcc CCX64=/tmp/x86_64-centos6-linux-gnu/bin/x86_64-centos6-linux-gnu-gcc GOPATH=/go @@ -26,6 +28,9 @@ fi echo "Build arguments: $OPT" +go run build.go -goarch armv7 -cc ${CCARMV7} ${OPT} build +go run build.go -goarch arm64 -cc ${CCARM64} ${OPT} build + CC=${CCX64} go run build.go ${OPT} build yarn install --pure-lockfile --no-progress @@ -44,3 +49,5 @@ source /etc/profile.d/rvm.sh echo "Packaging" go run build.go -goos linux -pkg-arch amd64 ${OPT} package-only latest +go run build.go -goos linux -pkg-arch armv7 ${OPT} package-only latest +go run build.go -goos linux -pkg-arch arm64 ${OPT} package-only latest From a82f0ed393ef14007b4333bcb83b01f8a58c8aeb Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Thu, 10 Jan 2019 13:46:03 +0100 Subject: [PATCH 19/37] build: tags arm as well as amd64 as latest. --- packaging/docker/build.sh | 2 +- packaging/docker/push_to_docker_hub.sh | 2 +- scripts/build/build-all.sh | 3 ++- scripts/build/build.sh | 8 +++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packaging/docker/build.sh b/packaging/docker/build.sh index 1bad2980d34..a522363089b 100755 --- a/packaging/docker/build.sh +++ b/packaging/docker/build.sh @@ -45,5 +45,5 @@ if echo "$_grafana_tag" | grep -q "^v"; then docker_tag_all "${_docker_repo}" "latest" else docker_tag_all "${_docker_repo}" "master" - docker tag "${_docker_repo}:${_grafana_version} grafana/grafana-dev:${_grafana_version}" + docker tag "${_docker_repo}:${_grafana_version}" "grafana/grafana-dev:${_grafana_version}" fi diff --git a/packaging/docker/push_to_docker_hub.sh b/packaging/docker/push_to_docker_hub.sh index cef6d596851..37b5ae0095c 100755 --- a/packaging/docker/push_to_docker_hub.sh +++ b/packaging/docker/push_to_docker_hub.sh @@ -41,6 +41,6 @@ if echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -vq "beta" elif echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -q "beta"; then docker_push_all "${_docker_repo}" "${_grafana_version}" elif echo "$_grafana_tag" | grep -q "master"; then - docker_push_all "grafana/grafana" "master" + docker_push_all "${_docker_repo}" "master" docker push "grafana/grafana-dev:${_grafana_version}" fi diff --git a/scripts/build/build-all.sh b/scripts/build/build-all.sh index 3013452a279..980ef5cc4c2 100755 --- a/scripts/build/build-all.sh +++ b/scripts/build/build-all.sh @@ -59,7 +59,7 @@ go run build.go ${OPT} build-frontend source /etc/profile.d/rvm.sh echo "Packaging" -go run build.go -goos linux -pkg-arch amd64 ${OPT} package-only latest +go run build.go -goos linux -pkg-arch amd64 ${OPT} package-only #removing amd64 phantomjs bin for armv7/arm64 packages rm tools/phantomjs/phantomjs go run build.go -goos linux -pkg-arch armv7 ${OPT} package-only @@ -80,3 +80,4 @@ else fi go run build.go -goos windows -pkg-arch amd64 ${OPT} package-only +go run build.go latest \ No newline at end of file diff --git a/scripts/build/build.sh b/scripts/build/build.sh index 1222053f1c8..ac6aab0b867 100755 --- a/scripts/build/build.sh +++ b/scripts/build/build.sh @@ -48,6 +48,8 @@ go run build.go ${OPT} build-frontend source /etc/profile.d/rvm.sh echo "Packaging" -go run build.go -goos linux -pkg-arch amd64 ${OPT} package-only latest -go run build.go -goos linux -pkg-arch armv7 ${OPT} package-only latest -go run build.go -goos linux -pkg-arch arm64 ${OPT} package-only latest +go run build.go -goos linux -pkg-arch amd64 ${OPT} package-only +go run build.go -goos linux -pkg-arch armv7 ${OPT} package-only +go run build.go -goos linux -pkg-arch arm64 ${OPT} package-only + +go run build.go latest From c22ef628f32d5d7d29e44db634a48868d48d740b Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Thu, 10 Jan 2019 15:11:51 +0100 Subject: [PATCH 20/37] build: removes curl install from build. --- packaging/docker/build-deploy.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/packaging/docker/build-deploy.sh b/packaging/docker/build-deploy.sh index ac3226a4a61..22655bead8c 100755 --- a/packaging/docker/build-deploy.sh +++ b/packaging/docker/build-deploy.sh @@ -8,6 +8,5 @@ docker login -u "$DOCKER_USER" -p "$DOCKER_PASS" ./push_to_docker_hub.sh "$_grafana_version" if echo "$_grafana_version" | grep -q "^master-"; then - apk add --no-cache curl ./deploy_to_k8s.sh "grafana/grafana-dev:$_grafana_version" fi From d322717f3ee8551fffe11d883aff8446241a1ff6 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Thu, 10 Jan 2019 15:21:11 +0100 Subject: [PATCH 21/37] Renamed Select related components: Picker* to Select*, Option* to SelectOption* --- packages/grafana-ui/src/components/Select/Select.tsx | 8 ++++---- .../{PickerOption.test.tsx => SelectOption.test.tsx} | 6 +++--- .../Select/{PickerOption.tsx => SelectOption.tsx} | 4 ++-- .../Select/{OptionGroup.tsx => SelectOptionGroup.tsx} | 2 +- ...kerOption.test.tsx.snap => SelectOption.test.tsx.snap} | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) rename packages/grafana-ui/src/components/Select/{PickerOption.test.tsx => SelectOption.test.tsx} (90%) rename packages/grafana-ui/src/components/Select/{PickerOption.tsx => SelectOption.tsx} (93%) rename packages/grafana-ui/src/components/Select/{OptionGroup.tsx => SelectOptionGroup.tsx} (93%) rename packages/grafana-ui/src/components/Select/__snapshots__/{PickerOption.test.tsx.snap => SelectOption.test.tsx.snap} (90%) diff --git a/packages/grafana-ui/src/components/Select/Select.tsx b/packages/grafana-ui/src/components/Select/Select.tsx index a2584ce8124..b3b0c8efbbb 100644 --- a/packages/grafana-ui/src/components/Select/Select.tsx +++ b/packages/grafana-ui/src/components/Select/Select.tsx @@ -11,8 +11,8 @@ import { default as ReactAsyncSelect } from '@torkelo/react-select/lib/Async'; import { components } from '@torkelo/react-select'; // Components -import { Option, SingleValue } from './PickerOption'; -import OptionGroup from './OptionGroup'; +import { SelectOption, SingleValue } from './SelectOption'; +import SelectOptionGroup from './SelectOptionGroup'; import IndicatorsContainer from './IndicatorsContainer'; import NoOptionsMessage from './NoOptionsMessage'; import resetSelectStyles from './resetSelectStyles'; @@ -117,11 +117,11 @@ export class Select extends PureComponent { classNamePrefix="gf-form-select-box" className={selectClassNames} components={{ - Option, + Option: SelectOption, SingleValue, IndicatorsContainer, MenuList, - Group: OptionGroup, + Group: SelectOptionGroup, }} defaultValue={defaultValue} value={value} diff --git a/packages/grafana-ui/src/components/Select/PickerOption.test.tsx b/packages/grafana-ui/src/components/Select/SelectOption.test.tsx similarity index 90% rename from packages/grafana-ui/src/components/Select/PickerOption.test.tsx rename to packages/grafana-ui/src/components/Select/SelectOption.test.tsx index 20187734c1a..a7326b3f4db 100644 --- a/packages/grafana-ui/src/components/Select/PickerOption.test.tsx +++ b/packages/grafana-ui/src/components/Select/SelectOption.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; -import PickerOption from './PickerOption'; +import SelectOption from './SelectOption'; import { OptionProps } from 'react-select/lib/components/Option'; const model: OptionProps = { @@ -31,11 +31,11 @@ const model: OptionProps = { className: 'class-for-user-picker', }; -describe('PickerOption', () => { +describe('SelectOption', () => { it('renders correctly', () => { const tree = renderer .create( - { }; } -export const Option = (props: ExtendedOptionProps) => { +export const SelectOption = (props: ExtendedOptionProps) => { const { children, isSelected, data } = props; return ( @@ -44,4 +44,4 @@ export const SingleValue = (props: any) => { ); }; -export default Option; +export default SelectOption; diff --git a/packages/grafana-ui/src/components/Select/OptionGroup.tsx b/packages/grafana-ui/src/components/Select/SelectOptionGroup.tsx similarity index 93% rename from packages/grafana-ui/src/components/Select/OptionGroup.tsx rename to packages/grafana-ui/src/components/Select/SelectOptionGroup.tsx index ed2b72a537c..30842f02e29 100644 --- a/packages/grafana-ui/src/components/Select/OptionGroup.tsx +++ b/packages/grafana-ui/src/components/Select/SelectOptionGroup.tsx @@ -9,7 +9,7 @@ interface State { expanded: boolean; } -export default class OptionGroup extends PureComponent { +export default class SelectOptionGroup extends PureComponent { state = { expanded: false, }; diff --git a/packages/grafana-ui/src/components/Select/__snapshots__/PickerOption.test.tsx.snap b/packages/grafana-ui/src/components/Select/__snapshots__/SelectOption.test.tsx.snap similarity index 90% rename from packages/grafana-ui/src/components/Select/__snapshots__/PickerOption.test.tsx.snap rename to packages/grafana-ui/src/components/Select/__snapshots__/SelectOption.test.tsx.snap index c4185025a5d..c52be902edd 100644 --- a/packages/grafana-ui/src/components/Select/__snapshots__/PickerOption.test.tsx.snap +++ b/packages/grafana-ui/src/components/Select/__snapshots__/SelectOption.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PickerOption renders correctly 1`] = ` +exports[`SelectOption renders correctly 1`] = `
Date: Thu, 10 Jan 2019 16:50:36 +0100 Subject: [PATCH 22/37] changelog: docker images for arm. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 671740f7225..46b7381cba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * **OAuth**: Support OAuth providers that are not RFC6749 compliant [#14562](https://github.com/grafana/grafana/issues/14562), thx [@tdabasinskas](https://github.com/tdabasinskas) * **Units**: Add blood glucose level units mg/dL and mmol/L [#14519](https://github.com/grafana/grafana/issues/14519), thx [@kjedamzik](https://github.com/kjedamzik) * **Stackdriver**: Aggregating series returns more than one series [#14581](https://github.com/grafana/grafana/issues/14581) and [#13914](https://github.com/grafana/grafana/issues/13914), thx [@kinok](https://github.com/kinok) +* **Docker**: Build and publish docker images for armv7 and arm64 [#14617](https://github.com/grafana/grafana/pull/14617), thx [@johanneswuerbach](https://github.com/johanneswuerbach) ### Bug fixes * **Search**: Fix for issue with scrolling the "tags filter" dropdown, fixes [#14486](https://github.com/grafana/grafana/issues/14486) From 0f82fffed65449299394c109903f1ccac6d268d7 Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Thu, 10 Jan 2019 15:22:30 +0100 Subject: [PATCH 23/37] build: makes sure all builds use the latest container. --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3d66a8ef13b..7f9c40bd968 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -127,7 +127,7 @@ jobs: build-all: docker: - - image: grafana/build-container:1.2.1 + - image: grafana/build-container:1.2.2 working_directory: /go/src/github.com/grafana/grafana steps: - checkout @@ -244,7 +244,7 @@ jobs: build-enterprise: docker: - - image: grafana/build-container:1.2.1 + - image: grafana/build-container:1.2.2 working_directory: /go/src/github.com/grafana/grafana steps: - checkout @@ -276,7 +276,7 @@ jobs: build-all-enterprise: docker: - - image: grafana/build-container:1.2.1 + - image: grafana/build-container:1.2.2 working_directory: /go/src/github.com/grafana/grafana steps: - checkout From 60fadcf1e583b1243a2a0334389210a9b7a2807a Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Thu, 10 Jan 2019 20:15:03 +0100 Subject: [PATCH 24/37] Fix panel time overrides not being applied fully When both relative and time shift were applied, only time shift was taken into consideration --- public/app/features/dashboard/utils/panel.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index f7ed0efd910..cf00a31c71e 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -143,12 +143,9 @@ export function applyPanelTimeOverrides(panel: PanelModel, timeRange: TimeRange) const timeShift = '-' + timeShiftInterpolated; newTimeData.timeInfo += ' timeshift ' + timeShift; newTimeData.timeRange = { - from: dateMath.parseDateMath(timeShift, timeRange.from, false), - to: dateMath.parseDateMath(timeShift, timeRange.to, true), - raw: { - from: timeRange.from, - to: timeRange.to, - }, + from: dateMath.parseDateMath(timeShift, newTimeData.timeRange.from, false), + to: dateMath.parseDateMath(timeShift, newTimeData.timeRange.to, true), + raw: newTimeData.timeRange.raw, }; } From 08ac2959a4d17a58aaf1f64738d1e442c6de93eb Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 10 Jan 2019 21:47:09 +0000 Subject: [PATCH 25/37] Moving to grafana ui, fix issue with TestRuleResult --- .../LoadingPlaceholder/LoadingPlaceholder.tsx | 11 ++++++++++ packages/grafana-ui/src/components/index.ts | 1 + public/app/features/alerting/AlertTab.tsx | 21 ++++++------------- .../features/alerting/TestRuleButton.test.tsx | 6 +++--- ...{TestRuleButton.tsx => TestRuleResult.tsx} | 6 ++++-- .../dashboard/dashgrid/QueriesTab.tsx | 11 +++------- 6 files changed, 28 insertions(+), 28 deletions(-) create mode 100644 packages/grafana-ui/src/components/LoadingPlaceholder/LoadingPlaceholder.tsx rename public/app/features/alerting/{TestRuleButton.tsx => TestRuleResult.tsx} (86%) diff --git a/packages/grafana-ui/src/components/LoadingPlaceholder/LoadingPlaceholder.tsx b/packages/grafana-ui/src/components/LoadingPlaceholder/LoadingPlaceholder.tsx new file mode 100644 index 00000000000..01048014f8a --- /dev/null +++ b/packages/grafana-ui/src/components/LoadingPlaceholder/LoadingPlaceholder.tsx @@ -0,0 +1,11 @@ +import React, { SFC } from 'react'; + +interface LoadingPlaceholderProps { + text: string; +} + +export const LoadingPlaceholder: SFC = ({ text }) => ( +
+ {text} +
+); diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index abb1cf1b34c..6fa7de62572 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -2,3 +2,4 @@ export { DeleteButton } from './DeleteButton/DeleteButton'; export { Tooltip } from './Tooltip/Tooltip'; export { Portal } from './Portal/Portal'; export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; +export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder'; diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index 5623fac95c1..0520cd5e6e8 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -1,11 +1,12 @@ // Libraries -import React, { PureComponent, SFC } from 'react'; +import React, { PureComponent } from 'react'; // Services & Utils import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader'; import appEvents from 'app/core/app_events'; // Components +import { LoadingPlaceholder } from '@grafana/ui'; import { EditorTabBody, EditorToolbarView } from '../dashboard/dashgrid/EditorTabBody'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import StateHistory from './StateHistory'; @@ -14,7 +15,7 @@ import 'app/features/alerting/AlertTabCtrl'; // Types import { DashboardModel } from '../dashboard/dashboard_model'; import { PanelModel } from '../dashboard/panel_model'; -import { TestRuleButton } from './TestRuleButton'; +import { TestRuleResult } from './TestRuleResult'; interface Props { angularPanel?: AngularComponent; @@ -22,16 +23,6 @@ interface Props { panel: PanelModel; } -interface LoadingPlaceholderProps { - text: string; -} - -const LoadingPlaceholder: SFC = ({ text }) => ( -
- {text} -
-); - export class AlertTab extends PureComponent { element: any; component: AngularComponent; @@ -120,14 +111,14 @@ export class AlertTab extends PureComponent { }; }; - renderTestRuleButton = () => { + renderTestRuleResult = () => { const { panel, dashboard } = this.props; - return ; + return ; }; testRule = (): EditorToolbarView => ({ title: 'Test Rule', - render: () => this.renderTestRuleButton(), + render: () => this.renderTestRuleResult(), }); onAddAlert = () => { diff --git a/public/app/features/alerting/TestRuleButton.test.tsx b/public/app/features/alerting/TestRuleButton.test.tsx index ae3b570cf43..b762ebf2579 100644 --- a/public/app/features/alerting/TestRuleButton.test.tsx +++ b/public/app/features/alerting/TestRuleButton.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { DashboardModel } from '../dashboard/dashboard_model'; -import { Props, TestRuleButton } from './TestRuleButton'; +import { Props, TestRuleResult } from './TestRuleResult'; jest.mock('app/core/services/backend_srv', () => ({ getBackendSrv: () => ({ @@ -18,9 +18,9 @@ const setup = (propOverrides?: object) => { Object.assign(props, propOverrides); - const wrapper = shallow(); + const wrapper = shallow(); - return { wrapper, instance: wrapper.instance() as TestRuleButton }; + return { wrapper, instance: wrapper.instance() as TestRuleResult }; }; describe('Render', () => { diff --git a/public/app/features/alerting/TestRuleButton.tsx b/public/app/features/alerting/TestRuleResult.tsx similarity index 86% rename from public/app/features/alerting/TestRuleButton.tsx rename to public/app/features/alerting/TestRuleResult.tsx index f9927b1a182..e55dd6aae51 100644 --- a/public/app/features/alerting/TestRuleButton.tsx +++ b/public/app/features/alerting/TestRuleResult.tsx @@ -14,7 +14,7 @@ interface State { testRuleResponse: {}; } -export class TestRuleButton extends PureComponent { +export class TestRuleResult extends PureComponent { readonly state: State = { isLoading: false, testRuleResponse: {}, @@ -27,8 +27,10 @@ export class TestRuleButton extends PureComponent { async testRule() { const { panelId, dashboard } = this.props; const payload = { dashboard: dashboard.getSaveModelClone(), panelId }; + + this.setState({ isLoading: true }); const testRuleResponse = await getBackendSrv().post(`/api/alerts/test`, payload); - this.setState(prevState => ({ ...prevState, isLoading: false, testRuleResponse })); + this.setState({ isLoading: false, testRuleResponse }); } render() { diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index 77ab64b1dba..eab7a95d471 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -1,15 +1,16 @@ // Libraries -import React, { PureComponent, SFC } from 'react'; +import React, { PureComponent } from 'react'; import _ from 'lodash'; // Components import 'app/features/panel/metrics_tab'; -import { EditorTabBody, EditorToolbarView} from './EditorTabBody'; +import { EditorTabBody, EditorToolbarView } from './EditorTabBody'; import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker'; import { QueryInspector } from './QueryInspector'; import { QueryOptions } from './QueryOptions'; import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab'; import { PanelOptionSection } from './PanelOptionSection'; +import { LoadingPlaceholder } from '@grafana/ui'; // Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; @@ -36,12 +37,6 @@ interface State { isAddingMixed: boolean; } -interface LoadingPlaceholderProps { - text: string; -} - -const LoadingPlaceholder: SFC = ({ text }) =>

{text}

; - export class QueriesTab extends PureComponent { element: HTMLElement; component: AngularComponent; From 2f0ab99ae5e63bc58984b6cc126228962ea38b21 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Thu, 10 Jan 2019 22:15:37 +0000 Subject: [PATCH 26/37] Fixing test and small refactor --- public/app/features/alerting/AlertTab.tsx | 3 +-- ...tRuleButton.test.tsx => TestRuleResult.test.tsx} | 1 - public/app/features/alerting/TestRuleResult.tsx | 3 +-- .../__snapshots__/TestRuleButton.test.tsx.snap | 13 ------------- .../__snapshots__/TestRuleResult.test.tsx.snap | 7 +++++++ .../app/features/dashboard/dashgrid/QueriesTab.tsx | 3 +-- .../features/dashboard/dashgrid/QueryInspector.tsx | 3 +-- 7 files changed, 11 insertions(+), 22 deletions(-) rename public/app/features/alerting/{TestRuleButton.test.tsx => TestRuleResult.test.tsx} (97%) delete mode 100644 public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap create mode 100644 public/app/features/alerting/__snapshots__/TestRuleResult.test.tsx.snap diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index 0520cd5e6e8..2a1b3d12ecf 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -6,7 +6,6 @@ import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoa import appEvents from 'app/core/app_events'; // Components -import { LoadingPlaceholder } from '@grafana/ui'; import { EditorTabBody, EditorToolbarView } from '../dashboard/dashgrid/EditorTabBody'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import StateHistory from './StateHistory'; @@ -113,7 +112,7 @@ export class AlertTab extends PureComponent { renderTestRuleResult = () => { const { panel, dashboard } = this.props; - return ; + return ; }; testRule = (): EditorToolbarView => ({ diff --git a/public/app/features/alerting/TestRuleButton.test.tsx b/public/app/features/alerting/TestRuleResult.test.tsx similarity index 97% rename from public/app/features/alerting/TestRuleButton.test.tsx rename to public/app/features/alerting/TestRuleResult.test.tsx index b762ebf2579..9beb5ade632 100644 --- a/public/app/features/alerting/TestRuleButton.test.tsx +++ b/public/app/features/alerting/TestRuleResult.test.tsx @@ -13,7 +13,6 @@ const setup = (propOverrides?: object) => { const props: Props = { panelId: 1, dashboard: new DashboardModel({ panels: [{ id: 1 }] }), - LoadingPlaceholder: {}, }; Object.assign(props, propOverrides); diff --git a/public/app/features/alerting/TestRuleResult.tsx b/public/app/features/alerting/TestRuleResult.tsx index e55dd6aae51..4014e529597 100644 --- a/public/app/features/alerting/TestRuleResult.tsx +++ b/public/app/features/alerting/TestRuleResult.tsx @@ -2,11 +2,11 @@ import React, { PureComponent } from 'react'; import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { DashboardModel } from '../dashboard/dashboard_model'; +import { LoadingPlaceholder } from '@grafana/ui/src'; export interface Props { panelId: number; dashboard: DashboardModel; - LoadingPlaceholder: any; } interface State { @@ -35,7 +35,6 @@ export class TestRuleResult extends PureComponent { render() { const { testRuleResponse, isLoading } = this.state; - const { LoadingPlaceholder } = this.props; if (isLoading === true) { return ; diff --git a/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap b/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap deleted file mode 100644 index d1ed3e64e99..00000000000 --- a/public/app/features/alerting/__snapshots__/TestRuleButton.test.tsx.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render should render component 1`] = ` - -`; diff --git a/public/app/features/alerting/__snapshots__/TestRuleResult.test.tsx.snap b/public/app/features/alerting/__snapshots__/TestRuleResult.test.tsx.snap new file mode 100644 index 00000000000..73f85f12354 --- /dev/null +++ b/public/app/features/alerting/__snapshots__/TestRuleResult.test.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` + +`; diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index eab7a95d471..a20f8627fba 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -10,7 +10,6 @@ import { QueryInspector } from './QueryInspector'; import { QueryOptions } from './QueryOptions'; import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab'; import { PanelOptionSection } from './PanelOptionSection'; -import { LoadingPlaceholder } from '@grafana/ui'; // Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; @@ -129,7 +128,7 @@ export class QueriesTab extends PureComponent { renderQueryInspector = () => { const { panel } = this.props; - return ; + return ; }; renderHelp = () => { diff --git a/public/app/features/dashboard/dashgrid/QueryInspector.tsx b/public/app/features/dashboard/dashgrid/QueryInspector.tsx index 090bc220bc0..8e490f6b622 100644 --- a/public/app/features/dashboard/dashgrid/QueryInspector.tsx +++ b/public/app/features/dashboard/dashgrid/QueryInspector.tsx @@ -2,6 +2,7 @@ import React, { PureComponent } from 'react'; import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter'; import appEvents from 'app/core/app_events'; import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard'; +import { LoadingPlaceholder } from '@grafana/ui'; interface DsQuery { isLoading: boolean; @@ -10,7 +11,6 @@ interface DsQuery { interface Props { panel: any; - LoadingPlaceholder: any; } interface State { @@ -177,7 +177,6 @@ export class QueryInspector extends PureComponent { render() { const { response, isLoading } = this.state.dsQuery; - const { LoadingPlaceholder } = this.props; const { isMocking } = this.state; const openNodes = this.getNrOfOpenNodes(); From d376fae393b099811af036e799738880a2e542ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 10 Jan 2019 13:34:23 +0100 Subject: [PATCH 27/37] Moved colorpicker to ui/components --- packages/grafana-ui/package.json | 4 +- .../ColorPicker}/ColorPalette.test.tsx | 2 +- .../components/ColorPicker}/ColorPalette.tsx | 6 +- .../components/ColorPicker}/ColorPicker.tsx | 10 +- .../ColorPicker}/ColorPickerPopover.tsx | 33 +++---- .../ColorPicker}/SeriesColorPicker.tsx | 4 +- .../ColorPicker}/SeriesColorPickerPopover.tsx | 11 +-- .../ColorPicker}/SpectrumPicker.tsx | 8 +- .../__snapshots__/ColorPalette.test.tsx.snap | 0 packages/grafana-ui/src/components/index.ts | 3 + packages/grafana-ui/src/index.ts | 1 + packages/grafana-ui/src/utils/colors.ts | 94 +++++++++++++++++++ packages/grafana-ui/src/utils/index.ts | 2 + public/app/core/angular_wrappers.ts | 10 ++ public/app/core/core.ts | 4 +- public/app/core/logs_model.ts | 4 +- public/app/core/utils/colors.ts | 94 ------------------- public/app/core/utils/explore.ts | 2 +- .../app/features/annotations/event_manager.ts | 7 +- .../app/features/dashboard/dashboard_model.ts | 2 +- public/app/plugins/panel/gauge/Thresholds.tsx | 2 +- .../panel/graph/Legend/LegendSeriesItem.tsx | 2 +- .../app/plugins/panel/graph/data_processor.ts | 3 +- .../app/plugins/panel/graph2/GraphPanel.tsx | 2 +- public/app/routes/GrafanaCtrl.ts | 4 +- public/app/viz/state/timeSeries.ts | 2 +- 26 files changed, 157 insertions(+), 159 deletions(-) rename {public/app/core/specs => packages/grafana-ui/src/components/ColorPicker}/ColorPalette.test.tsx (80%) rename {public/app/core/components/colorpicker => packages/grafana-ui/src/components/ColorPicker}/ColorPalette.tsx (90%) rename {public/app/core/components/colorpicker => packages/grafana-ui/src/components/ColorPicker}/ColorPicker.tsx (85%) rename {public/app/core/components/colorpicker => packages/grafana-ui/src/components/ColorPicker}/ColorPickerPopover.tsx (83%) rename {public/app/core/components/colorpicker => packages/grafana-ui/src/components/ColorPicker}/SeriesColorPicker.tsx (96%) rename {public/app/core/components/colorpicker => packages/grafana-ui/src/components/ColorPicker}/SeriesColorPickerPopover.tsx (86%) rename {public/app/core/components/colorpicker => packages/grafana-ui/src/components/ColorPicker}/SpectrumPicker.tsx (92%) rename {public/app/core/specs => packages/grafana-ui/src/components/ColorPicker}/__snapshots__/ColorPalette.test.tsx.snap (100%) create mode 100644 packages/grafana-ui/src/utils/colors.ts diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 6548f75e91f..5221e1ba02f 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -23,7 +23,9 @@ "react-highlight-words": "0.11.0", "react-popper": "^1.3.0", "react-transition-group": "^2.2.1", - "react-virtualized": "^9.21.0" + "react-virtualized": "^9.21.0", + "tether-drop": "https://github.com/torkelo/drop/tarball/master", + "tinycolor2": "^1.4.1" }, "devDependencies": { "@types/classnames": "^2.2.6", diff --git a/public/app/core/specs/ColorPalette.test.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPalette.test.tsx similarity index 80% rename from public/app/core/specs/ColorPalette.test.tsx rename to packages/grafana-ui/src/components/ColorPicker/ColorPalette.test.tsx index fb1124aa975..0714180de54 100644 --- a/public/app/core/specs/ColorPalette.test.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPalette.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; -import { ColorPalette } from '../components/colorpicker/ColorPalette'; +import { ColorPalette } from './ColorPalette'; describe('CollorPalette', () => { it('renders correctly', () => { diff --git a/public/app/core/components/colorpicker/ColorPalette.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPalette.tsx similarity index 90% rename from public/app/core/components/colorpicker/ColorPalette.tsx rename to packages/grafana-ui/src/components/ColorPicker/ColorPalette.tsx index edb2629d16d..03ed9949361 100644 --- a/public/app/core/components/colorpicker/ColorPalette.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPalette.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { sortedColors } from 'app/core/utils/colors'; +import { sortedColors } from '../../utils'; export interface Props { color: string; @@ -9,13 +9,13 @@ export interface Props { export class ColorPalette extends React.Component { paletteColors: string[]; - constructor(props) { + constructor(props: Props) { super(props); this.paletteColors = sortedColors; this.onColorSelect = this.onColorSelect.bind(this); } - onColorSelect(color) { + onColorSelect(color: string) { return () => { this.props.onColorSelect(color); }; diff --git a/public/app/core/components/colorpicker/ColorPicker.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx similarity index 85% rename from public/app/core/components/colorpicker/ColorPicker.tsx rename to packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx index 9541001b0a8..fbe14d4eb8c 100644 --- a/public/app/core/components/colorpicker/ColorPicker.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx @@ -2,7 +2,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import Drop from 'tether-drop'; import { ColorPickerPopover } from './ColorPickerPopover'; -import { react2AngularDirective } from 'app/core/utils/react2angular'; export interface Props { color: string; @@ -10,7 +9,7 @@ export interface Props { } export class ColorPicker extends React.Component { - pickerElem: HTMLElement; + pickerElem: HTMLElement | null; colorPickerDrop: any; openColorPicker = () => { @@ -45,7 +44,7 @@ export class ColorPicker extends React.Component { }, 100); }; - onColorSelect = color => { + onColorSelect = (color: string) => { this.props.onChange(color); }; @@ -59,8 +58,3 @@ export class ColorPicker extends React.Component { ); } } - -react2AngularDirective('colorPicker', ColorPicker, [ - 'color', - ['onChange', { watchDepth: 'reference', wrapApply: true }], -]); diff --git a/public/app/core/components/colorpicker/ColorPickerPopover.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx similarity index 83% rename from public/app/core/components/colorpicker/ColorPickerPopover.tsx rename to packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx index c42bcfa1d06..e8305c99319 100644 --- a/public/app/core/components/colorpicker/ColorPickerPopover.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx @@ -14,7 +14,7 @@ export interface Props { export class ColorPickerPopover extends React.Component { pickerNavElem: any; - constructor(props) { + constructor(props: Props) { super(props); this.state = { tab: 'palette', @@ -23,60 +23,51 @@ export class ColorPickerPopover extends React.Component { }; } - setPickerNavElem(elem) { + setPickerNavElem(elem: any) { this.pickerNavElem = $(elem); } - setColor(color) { + setColor(color: string) { const newColor = tinycolor(color); if (newColor.isValid()) { - this.setState({ - color: newColor.toString(), - colorString: newColor.toString(), - }); + this.setState({ color: newColor.toString(), colorString: newColor.toString() }); this.props.onColorSelect(color); } } - sampleColorSelected(color) { + sampleColorSelected(color: string) { this.setColor(color); } - spectrumColorSelected(color) { + spectrumColorSelected(color: any) { const rgbColor = color.toRgbString(); this.setColor(rgbColor); } - onColorStringChange(e) { + onColorStringChange(e: any) { const colorString = e.target.value; - this.setState({ - colorString: colorString, - }); + this.setState({ colorString: colorString }); const newColor = tinycolor(colorString); if (newColor.isValid()) { // Update only color state const newColorString = newColor.toString(); - this.setState({ - color: newColorString, - }); + this.setState({ color: newColorString }); this.props.onColorSelect(newColorString); } } - onColorStringBlur(e) { + onColorStringBlur(e: any) { const colorString = e.target.value; this.setColor(colorString); } componentDidMount() { this.pickerNavElem.find('li:first').addClass('active'); - this.pickerNavElem.on('show', e => { + this.pickerNavElem.on('show', (e: any) => { // use href attr (#name => name) const tab = e.target.hash.slice(1); - this.setState({ - tab: tab, - }); + this.setState({ tab: tab }); }); } diff --git a/public/app/core/components/colorpicker/SeriesColorPicker.tsx b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx similarity index 96% rename from public/app/core/components/colorpicker/SeriesColorPicker.tsx rename to packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx index 32b7554e38d..b8ba03b7feb 100644 --- a/public/app/core/components/colorpicker/SeriesColorPicker.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx @@ -8,7 +8,7 @@ export interface SeriesColorPickerProps { yaxis?: number; optionalClass?: string; onColorChange: (newColor: string) => void; - onToggleAxis?: () => void; + onToggleAxis: () => void; } export class SeriesColorPicker extends React.Component { @@ -21,7 +21,7 @@ export class SeriesColorPicker extends React.Component { onToggleAxis: () => {}, }; - constructor(props) { + constructor(props: SeriesColorPickerProps) { super(props); } diff --git a/public/app/core/components/colorpicker/SeriesColorPickerPopover.tsx b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx similarity index 86% rename from public/app/core/components/colorpicker/SeriesColorPickerPopover.tsx rename to packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx index 085d554300d..9036a1a2ffd 100644 --- a/public/app/core/components/colorpicker/SeriesColorPickerPopover.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx @@ -1,12 +1,11 @@ import React from 'react'; import { ColorPickerPopover } from './ColorPickerPopover'; -import { react2AngularDirective } from 'app/core/utils/react2angular'; export interface SeriesColorPickerPopoverProps { color: string; yaxis?: number; onColorChange: (color: string) => void; - onToggleAxis?: () => void; + onToggleAxis: () => void; } export class SeriesColorPickerPopover extends React.PureComponent { @@ -30,7 +29,7 @@ interface AxisSelectorState { } export class AxisSelector extends React.PureComponent { - constructor(props) { + constructor(props: AxisSelectorProps) { super(props); this.state = { yaxis: this.props.yaxis, @@ -62,9 +61,3 @@ export class AxisSelector extends React.PureComponent { elem: any; isMoving: boolean; - constructor(props) { + constructor(props: Props) { super(props); this.onSpectrumMove = this.onSpectrumMove.bind(this); this.setComponentElem = this.setComponentElem.bind(this); } - setComponentElem(elem) { + setComponentElem(elem: any) { this.elem = $(elem); } - onSpectrumMove(color) { + onSpectrumMove(color: any) { this.isMoving = true; this.props.onColorSelect(color); } @@ -46,7 +46,7 @@ export class SpectrumPicker extends React.Component { this.elem.spectrum('set', this.props.color); } - componentWillUpdate(nextProps) { + componentWillUpdate(nextProps: any) { // If user move pointer over spectrum field this produce 'move' event and component // may update props.color. We don't want to update spectrum color in this case, so we can use // isMoving flag for tracking moving state. Flag should be cleared in componentDidUpdate() which diff --git a/public/app/core/specs/__snapshots__/ColorPalette.test.tsx.snap b/packages/grafana-ui/src/components/ColorPicker/__snapshots__/ColorPalette.test.tsx.snap similarity index 100% rename from public/app/core/specs/__snapshots__/ColorPalette.test.tsx.snap rename to packages/grafana-ui/src/components/ColorPicker/__snapshots__/ColorPalette.test.tsx.snap diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index abb1cf1b34c..b2b607415b8 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -2,3 +2,6 @@ export { DeleteButton } from './DeleteButton/DeleteButton'; export { Tooltip } from './Tooltip/Tooltip'; export { Portal } from './Portal/Portal'; export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; +export { ColorPicker } from './ColorPicker/ColorPicker'; +export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover'; +export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker'; diff --git a/packages/grafana-ui/src/index.ts b/packages/grafana-ui/src/index.ts index b22152497b9..4072052a07d 100644 --- a/packages/grafana-ui/src/index.ts +++ b/packages/grafana-ui/src/index.ts @@ -2,4 +2,5 @@ export * from './components'; export * from './visualizations'; export * from './types'; export * from './utils'; +export { default } from './utils'; export * from './forms'; diff --git a/packages/grafana-ui/src/utils/colors.ts b/packages/grafana-ui/src/utils/colors.ts new file mode 100644 index 00000000000..673b0109f11 --- /dev/null +++ b/packages/grafana-ui/src/utils/colors.ts @@ -0,0 +1,94 @@ +import _ from 'lodash'; +import tinycolor from 'tinycolor2'; + +export const PALETTE_ROWS = 4; +export const PALETTE_COLUMNS = 14; +export const DEFAULT_ANNOTATION_COLOR = 'rgba(0, 211, 255, 1)'; +export const OK_COLOR = 'rgba(11, 237, 50, 1)'; +export const ALERTING_COLOR = 'rgba(237, 46, 24, 1)'; +export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)'; +export const PENDING_COLOR = 'rgba(247, 149, 32, 1)'; +export const REGION_FILL_ALPHA = 0.09; + +const colors = [ + '#7EB26D', // 0: pale green + '#EAB839', // 1: mustard + '#6ED0E0', // 2: light blue + '#EF843C', // 3: orange + '#E24D42', // 4: red + '#1F78C1', // 5: ocean + '#BA43A9', // 6: purple + '#705DA0', // 7: violet + '#508642', // 8: dark green + '#CCA300', // 9: dark sand + '#447EBC', + '#C15C17', + '#890F02', + '#0A437C', + '#6D1F62', + '#584477', + '#B7DBAB', + '#F4D598', + '#70DBED', + '#F9BA8F', + '#F29191', + '#82B5D8', + '#E5A8E2', + '#AEA2E0', + '#629E51', + '#E5AC0E', + '#64B0C8', + '#E0752D', + '#BF1B00', + '#0A50A1', + '#962D82', + '#614D93', + '#9AC48A', + '#F2C96D', + '#65C5DB', + '#F9934E', + '#EA6460', + '#5195CE', + '#D683CE', + '#806EB7', + '#3F6833', + '#967302', + '#2F575E', + '#99440A', + '#58140C', + '#052B51', + '#511749', + '#3F2B5B', + '#E0F9D7', + '#FCEACA', + '#CFFAFF', + '#F9E2D2', + '#FCE2DE', + '#BADFF4', + '#F9D9F9', + '#DEDAF7', +]; + +function sortColorsByHue(hexColors: string[]) { + const hslColors = _.map(hexColors, hexToHsl); + + let sortedHSLColors = _.sortBy(hslColors, ['h']); + sortedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS); + sortedHSLColors = _.map(sortedHSLColors, chunk => { + return _.sortBy(chunk, 'l'); + }); + sortedHSLColors = _.flattenDeep(_.zip(...sortedHSLColors)); + + return _.map(sortedHSLColors, hslToHex); +} + +function hexToHsl(color: string) { + return tinycolor(color).toHsl(); +} + +function hslToHex(color: string) { + return tinycolor(color).toHexString(); +} + +export let sortedColors = sortColorsByHue(colors); +export default colors; diff --git a/packages/grafana-ui/src/utils/index.ts b/packages/grafana-ui/src/utils/index.ts index 4d9b9a4b948..1a677b1f033 100644 --- a/packages/grafana-ui/src/utils/index.ts +++ b/packages/grafana-ui/src/utils/index.ts @@ -1 +1,3 @@ export * from './processTimeSeries'; +export * from './colors'; +export { default } from './colors'; diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index 5609c058a27..d6fc68293c3 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -6,6 +6,7 @@ import { SearchResult } from './components/search/SearchResult'; import { TagFilter } from './components/TagFilter/TagFilter'; import { SideMenu } from './components/sidemenu/SideMenu'; import AppNotificationList from './components/AppNotifications/AppNotificationList'; +import { ColorPicker, SeriesColorPickerPopover } from '@grafana/ui'; export function registerAngularDirectives() { react2AngularDirective('passwordStrength', PasswordStrength, ['password']); @@ -19,4 +20,13 @@ export function registerAngularDirectives() { ['onChange', { watchDepth: 'reference' }], ['tagOptions', { watchDepth: 'reference' }], ]); + react2AngularDirective('colorPicker', ColorPicker, [ + 'color', + ['onChange', { watchDepth: 'reference', wrapApply: true }], + ]); + react2AngularDirective('seriesColorPickerPopover', SeriesColorPickerPopover, [ + 'series', + 'onColorChange', + 'onToggleAxis', + ]); } diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 257a2077c97..19e9a473e35 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -13,8 +13,6 @@ import './partials'; import './components/jsontree/jsontree'; import './components/code_editor/code_editor'; import './utils/outline'; -import './components/colorpicker/ColorPicker'; -import './components/colorpicker/SeriesColorPickerPopover'; import './components/colorpicker/spectrum_picker'; import './services/search_srv'; import './services/ng_react'; @@ -36,7 +34,7 @@ import 'app/core/services/all'; import './filters/filters'; import coreModule from './core_module'; import appEvents from './app_events'; -import colors from './utils/colors'; +import colors from '@grafana/ui/'; import { assignModelProperties } from './utils/model_utils'; import { contextSrv } from './services/context_srv'; import { KeybindingSrv } from './services/keybindingSrv'; diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index 4e8c6207959..8eb8433cd53 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -1,6 +1,8 @@ import _ from 'lodash'; +import colors from '@grafana/ui'; + import { TimeSeries } from 'app/core/core'; -import colors, { getThemeColor } from 'app/core/utils/colors'; +import { getThemeColor } from 'app/core/utils/colors'; /** * Mapping of log level abbreviation to canonical log level. diff --git a/public/app/core/utils/colors.ts b/public/app/core/utils/colors.ts index 34508e94a9f..6d73ab9fbd8 100644 --- a/public/app/core/utils/colors.ts +++ b/public/app/core/utils/colors.ts @@ -1,99 +1,5 @@ -import _ from 'lodash'; -import tinycolor from 'tinycolor2'; import config from 'app/core/config'; -export const PALETTE_ROWS = 4; -export const PALETTE_COLUMNS = 14; -export const DEFAULT_ANNOTATION_COLOR = 'rgba(0, 211, 255, 1)'; -export const OK_COLOR = 'rgba(11, 237, 50, 1)'; -export const ALERTING_COLOR = 'rgba(237, 46, 24, 1)'; -export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)'; -export const PENDING_COLOR = 'rgba(247, 149, 32, 1)'; -export const REGION_FILL_ALPHA = 0.09; - -const colors = [ - '#7EB26D', // 0: pale green - '#EAB839', // 1: mustard - '#6ED0E0', // 2: light blue - '#EF843C', // 3: orange - '#E24D42', // 4: red - '#1F78C1', // 5: ocean - '#BA43A9', // 6: purple - '#705DA0', // 7: violet - '#508642', // 8: dark green - '#CCA300', // 9: dark sand - '#447EBC', - '#C15C17', - '#890F02', - '#0A437C', - '#6D1F62', - '#584477', - '#B7DBAB', - '#F4D598', - '#70DBED', - '#F9BA8F', - '#F29191', - '#82B5D8', - '#E5A8E2', - '#AEA2E0', - '#629E51', - '#E5AC0E', - '#64B0C8', - '#E0752D', - '#BF1B00', - '#0A50A1', - '#962D82', - '#614D93', - '#9AC48A', - '#F2C96D', - '#65C5DB', - '#F9934E', - '#EA6460', - '#5195CE', - '#D683CE', - '#806EB7', - '#3F6833', - '#967302', - '#2F575E', - '#99440A', - '#58140C', - '#052B51', - '#511749', - '#3F2B5B', - '#E0F9D7', - '#FCEACA', - '#CFFAFF', - '#F9E2D2', - '#FCE2DE', - '#BADFF4', - '#F9D9F9', - '#DEDAF7', -]; - -export function sortColorsByHue(hexColors) { - const hslColors = _.map(hexColors, hexToHsl); - - let sortedHSLColors = _.sortBy(hslColors, ['h']); - sortedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS); - sortedHSLColors = _.map(sortedHSLColors, chunk => { - return _.sortBy(chunk, 'l'); - }); - sortedHSLColors = _.flattenDeep(_.zip(...sortedHSLColors)); - - return _.map(sortedHSLColors, hslToHex); -} - -export function hexToHsl(color) { - return tinycolor(color).toHsl(); -} - -export function hslToHex(color) { - return tinycolor(color).toHexString(); -} - export function getThemeColor(dark: string, light: string): string { return config.bootData.user.lightTheme ? light : dark; } - -export let sortedColors = sortColorsByHue(colors); -export default colors; diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index bea166075dc..2cca33620b7 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -1,9 +1,9 @@ import _ from 'lodash'; +import colors from '@grafana/ui'; import { renderUrl } from 'app/core/utils/url'; import kbn from 'app/core/utils/kbn'; import store from 'app/core/store'; -import colors from 'app/core/utils/colors'; import { parse as parseDate } from 'app/core/utils/datemath'; import TimeSeries from 'app/core/time_series2'; diff --git a/public/app/features/annotations/event_manager.ts b/public/app/features/annotations/event_manager.ts index db748e639a1..6966d3cdc82 100644 --- a/public/app/features/annotations/event_manager.ts +++ b/public/app/features/annotations/event_manager.ts @@ -1,8 +1,6 @@ import _ from 'lodash'; import moment from 'moment'; import tinycolor from 'tinycolor2'; -import { MetricsPanelCtrl } from 'app/plugins/sdk'; -import { AnnotationEvent } from './event'; import { OK_COLOR, ALERTING_COLOR, @@ -10,7 +8,10 @@ import { PENDING_COLOR, DEFAULT_ANNOTATION_COLOR, REGION_FILL_ALPHA, -} from 'app/core/utils/colors'; +} from '@grafana/ui'; + +import { MetricsPanelCtrl } from 'app/plugins/sdk'; +import { AnnotationEvent } from './event'; export class EventManager { event: AnnotationEvent; diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index 6f98bc5a17a..747ea9fecaa 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -1,8 +1,8 @@ import moment from 'moment'; import _ from 'lodash'; +import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui'; import { GRID_COLUMN_COUNT, REPEAT_DIR_VERTICAL, GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants'; -import { DEFAULT_ANNOTATION_COLOR } from 'app/core/utils/colors'; import { Emitter } from 'app/core/utils/emitter'; import { contextSrv } from 'app/core/services/context_srv'; import sortByKeys from 'app/core/utils/sort_by_keys'; diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/public/app/plugins/panel/gauge/Thresholds.tsx index b4d4930e11d..7699a499146 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/public/app/plugins/panel/gauge/Thresholds.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import tinycolor from 'tinycolor2'; -import { ColorPicker } from 'app/core/components/colorpicker/ColorPicker'; +import { ColorPicker } from '@grafana/ui'; import { BasicGaugeColor, Threshold } from 'app/types'; import { PanelOptionsProps } from '@grafana/ui'; import { Options } from './types'; diff --git a/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx b/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx index 2105687d8e1..d6df17d9699 100644 --- a/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx +++ b/public/app/plugins/panel/graph/Legend/LegendSeriesItem.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import classNames from 'classnames'; import { TimeSeries } from 'app/core/core'; -import { SeriesColorPicker } from 'app/core/components/colorpicker/SeriesColorPicker'; +import { SeriesColorPicker } from '@grafana/ui'; export const LEGEND_STATS = ['min', 'max', 'avg', 'current', 'total']; diff --git a/public/app/plugins/panel/graph/data_processor.ts b/public/app/plugins/panel/graph/data_processor.ts index 4ea1efe1502..ef4ad872753 100644 --- a/public/app/plugins/panel/graph/data_processor.ts +++ b/public/app/plugins/panel/graph/data_processor.ts @@ -1,6 +1,7 @@ import _ from 'lodash'; +import colors from '@grafana/ui'; + import TimeSeries from 'app/core/time_series2'; -import colors from 'app/core/utils/colors'; export class DataProcessor { constructor(private panel) {} diff --git a/public/app/plugins/panel/graph2/GraphPanel.tsx b/public/app/plugins/panel/graph2/GraphPanel.tsx index 020c33f7d38..11be172aaeb 100644 --- a/public/app/plugins/panel/graph2/GraphPanel.tsx +++ b/public/app/plugins/panel/graph2/GraphPanel.tsx @@ -1,7 +1,7 @@ // Libraries import _ from 'lodash'; import React, { PureComponent } from 'react'; -import colors from 'app/core/utils/colors'; +import colors from '@grafana/ui'; // Components & Types import { Graph, PanelProps, NullValueMode, processTimeSeries } from '@grafana/ui'; diff --git a/public/app/routes/GrafanaCtrl.ts b/public/app/routes/GrafanaCtrl.ts index 75a34ac01c0..434a112692e 100644 --- a/public/app/routes/GrafanaCtrl.ts +++ b/public/app/routes/GrafanaCtrl.ts @@ -1,12 +1,12 @@ import config from 'app/core/config'; import _ from 'lodash'; import $ from 'jquery'; +import Drop from 'tether-drop'; +import colors from '@grafana/ui'; import coreModule from 'app/core/core_module'; import { profiler } from 'app/core/profiler'; import appEvents from 'app/core/app_events'; -import Drop from 'tether-drop'; -import colors from 'app/core/utils/colors'; import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv'; import { TimeSrv, setTimeSrv } from 'app/features/dashboard/time_srv'; import { DatasourceSrv, setDatasourceSrv } from 'app/features/plugins/datasource_srv'; diff --git a/public/app/viz/state/timeSeries.ts b/public/app/viz/state/timeSeries.ts index 782383957bc..2329d6f41af 100644 --- a/public/app/viz/state/timeSeries.ts +++ b/public/app/viz/state/timeSeries.ts @@ -2,7 +2,7 @@ import _ from 'lodash'; // Utils -import colors from 'app/core/utils/colors'; +import colors from '@grafana/ui'; // Types import { TimeSeries, TimeSeriesVMs, NullValueMode } from '@grafana/ui'; From 37dae043d703c9586a9573ae3de1d463d150e4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 10 Jan 2019 13:38:55 +0100 Subject: [PATCH 28/37] Small change in SeriesColorPickerPopoverProps --- .../src/components/ColorPicker/SeriesColorPicker.tsx | 2 +- .../components/ColorPicker/SeriesColorPickerPopover.tsx | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx index b8ba03b7feb..09a53a8fe60 100644 --- a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx @@ -8,7 +8,7 @@ export interface SeriesColorPickerProps { yaxis?: number; optionalClass?: string; onColorChange: (newColor: string) => void; - onToggleAxis: () => void; + onToggleAxis?: () => void; } export class SeriesColorPicker extends React.Component { diff --git a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx index 9036a1a2ffd..541a77ddabc 100644 --- a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx @@ -5,7 +5,7 @@ export interface SeriesColorPickerPopoverProps { color: string; yaxis?: number; onColorChange: (color: string) => void; - onToggleAxis: () => void; + onToggleAxis?: () => void; } export class SeriesColorPickerPopover extends React.PureComponent { @@ -21,7 +21,7 @@ export class SeriesColorPickerPopover extends React.PureComponent void; + onToggleAxis?: () => void; } interface AxisSelectorState { @@ -41,7 +41,10 @@ export class AxisSelector extends React.PureComponent Date: Thu, 10 Jan 2019 16:52:08 +0100 Subject: [PATCH 29/37] Fixed typings --- packages/grafana-ui/package.json | 3 +++ .../components/ColorPicker/ColorPicker.tsx | 3 ++- .../ColorPicker/SeriesColorPicker.tsx | 1 + packages/grafana-ui/src/utils/colors.ts | 12 ++++++------ yarn.lock | 19 ++++++++++++++++++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 5221e1ba02f..91695dc5647 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -24,6 +24,7 @@ "react-popper": "^1.3.0", "react-transition-group": "^2.2.1", "react-virtualized": "^9.21.0", + "tether": "^1.4.0", "tether-drop": "https://github.com/torkelo/drop/tarball/master", "tinycolor2": "^1.4.1" }, @@ -35,6 +36,8 @@ "@types/react": "^16.7.6", "@types/react-custom-scrollbars": "^4.0.5", "@types/react-test-renderer": "^16.0.3", + "@types/tether-drop": "^1.4.8", + "@types/tinycolor2": "^1.4.1", "react-test-renderer": "^16.7.0", "typescript": "^3.2.2" } diff --git a/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx b/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx index fbe14d4eb8c..485aa5f03d3 100644 --- a/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx @@ -19,7 +19,7 @@ export class ColorPicker extends React.Component { ReactDOM.render(dropContent, dropContentElem); const drop = new Drop({ - target: this.pickerElem, + target: this.pickerElem as Element, content: dropContentElem, position: 'top center', classes: 'drop-popover', @@ -27,6 +27,7 @@ export class ColorPicker extends React.Component { hoverCloseDelay: 200, tetherOptions: { constraints: [{ to: 'scrollParent', attachment: 'none both' }], + attachment: 'bottom center', }, }); diff --git a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx index 09a53a8fe60..7c3848f6868 100644 --- a/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.tsx @@ -51,6 +51,7 @@ export class SeriesColorPicker extends React.Component { remove: true, tetherOptions: { constraints: [{ to: 'scrollParent', attachment: 'none both' }], + attachment: 'bottom center', }, }); diff --git a/packages/grafana-ui/src/utils/colors.ts b/packages/grafana-ui/src/utils/colors.ts index 673b0109f11..0b22cd7f81d 100644 --- a/packages/grafana-ui/src/utils/colors.ts +++ b/packages/grafana-ui/src/utils/colors.ts @@ -72,21 +72,21 @@ const colors = [ function sortColorsByHue(hexColors: string[]) { const hslColors = _.map(hexColors, hexToHsl); - let sortedHSLColors = _.sortBy(hslColors, ['h']); - sortedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS); - sortedHSLColors = _.map(sortedHSLColors, chunk => { + const sortedHSLColors = _.sortBy(hslColors, ['h']); + const chunkedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS); + const sortedChunkedHSLColors = _.map(chunkedHSLColors, chunk => { return _.sortBy(chunk, 'l'); }); - sortedHSLColors = _.flattenDeep(_.zip(...sortedHSLColors)); + const flattenedZippedSortedChunkedHSLColors = _.flattenDeep(_.zip(...sortedChunkedHSLColors)); - return _.map(sortedHSLColors, hslToHex); + return _.map(flattenedZippedSortedChunkedHSLColors, hslToHex); } function hexToHsl(color: string) { return tinycolor(color).toHsl(); } -function hslToHex(color: string) { +function hslToHex(color: any) { return tinycolor(color).toHexString(); } diff --git a/yarn.lock b/yarn.lock index 8eff64ca822..d6342e8dc26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1098,7 +1098,7 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^2.0.15": +"@types/react-transition-group@*", "@types/react-transition-group@^2.0.15": version "2.0.15" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.15.tgz#e5ee3fe558832e141cc6041bdd54caea7b787af8" integrity sha512-S0QnNzbHoWXDbKBl/xk5dxA4FT+BNlBcI3hku991cl8Cz3ytOkUMcCRtzdX11eb86E131bSsQqy5WrPCdJYblw== @@ -1118,6 +1118,23 @@ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-0.2.5.tgz#2443fc12da514c81346b1a665675559cee21fa75" integrity sha512-dEoVvo/I9QFomyhY+4Q6Qk+I+dhG59TYceZgC6Q0mCifVPErx6Y83PNTKGDS5e9h9Eti6q0S2mm16BU6iQK+3w== +"@types/tether-drop@^1.4.8": + version "1.4.8" + resolved "https://registry.yarnpkg.com/@types/tether-drop/-/tether-drop-1.4.8.tgz#8d64288e673259d1bc28518250b80b5ef43af0bc" + integrity sha512-QzrJDUxnLoqACUm7opxGOwa9mgMBlkyb7hHYWApMLM3ywWif4pWraTiotooiG3ePZmnTe8wQj2nx7GWMX4pb+w== + dependencies: + "@types/tether" "*" + +"@types/tether@*": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@types/tether/-/tether-1.4.4.tgz#0fde1ccbd2f1fad74f8f465fe6227ff3b7bff634" + integrity sha512-6qhsFJVMuMqaQRVyQVi3zUBLfKYyryktL0ZP0Z3zegzeQ7WKm0PZNCdl3JsaitJbzqaoQ9qsFKMfaj5MiMfcSQ== + +"@types/tinycolor2@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.1.tgz#2f5670c9d1d6e558897a810ed284b44918fc1253" + integrity sha512-25L/RL5tqZkquKXVHM1fM2bd23qjfbcPpAZ2N/H05Y45g3UEi+Hw8CbDV28shKY8gH1SHiLpZSxPI1lacqdpGg== + "@types/uglify-js@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.3.tgz#801a5ca1dc642861f47c46d14b700ed2d610840b" From dc9b83030f5ae162b005404abdb9da3d13d7b27f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Fri, 11 Jan 2019 06:48:17 +0100 Subject: [PATCH 30/37] Removed default export for colors --- packages/grafana-ui/src/index.ts | 1 - packages/grafana-ui/src/utils/colors.ts | 3 +-- packages/grafana-ui/src/utils/index.ts | 1 - public/app/core/core.ts | 2 +- public/app/core/logs_model.ts | 2 +- public/app/core/utils/explore.ts | 2 +- public/app/plugins/panel/graph/data_processor.ts | 2 +- public/app/plugins/panel/graph2/GraphPanel.tsx | 2 +- public/app/routes/GrafanaCtrl.ts | 2 +- public/app/viz/state/timeSeries.ts | 2 +- 10 files changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/grafana-ui/src/index.ts b/packages/grafana-ui/src/index.ts index 4072052a07d..b22152497b9 100644 --- a/packages/grafana-ui/src/index.ts +++ b/packages/grafana-ui/src/index.ts @@ -2,5 +2,4 @@ export * from './components'; export * from './visualizations'; export * from './types'; export * from './utils'; -export { default } from './utils'; export * from './forms'; diff --git a/packages/grafana-ui/src/utils/colors.ts b/packages/grafana-ui/src/utils/colors.ts index 0b22cd7f81d..263d128aec4 100644 --- a/packages/grafana-ui/src/utils/colors.ts +++ b/packages/grafana-ui/src/utils/colors.ts @@ -10,7 +10,7 @@ export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)'; export const PENDING_COLOR = 'rgba(247, 149, 32, 1)'; export const REGION_FILL_ALPHA = 0.09; -const colors = [ +export const colors = [ '#7EB26D', // 0: pale green '#EAB839', // 1: mustard '#6ED0E0', // 2: light blue @@ -91,4 +91,3 @@ function hslToHex(color: any) { } export let sortedColors = sortColorsByHue(colors); -export default colors; diff --git a/packages/grafana-ui/src/utils/index.ts b/packages/grafana-ui/src/utils/index.ts index 1a677b1f033..eb67a6f7256 100644 --- a/packages/grafana-ui/src/utils/index.ts +++ b/packages/grafana-ui/src/utils/index.ts @@ -1,3 +1,2 @@ export * from './processTimeSeries'; export * from './colors'; -export { default } from './colors'; diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 19e9a473e35..6713d8bcd14 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -16,6 +16,7 @@ import './utils/outline'; import './components/colorpicker/spectrum_picker'; import './services/search_srv'; import './services/ng_react'; +import { colors } from '@grafana/ui/'; import { searchDirective } from './components/search/search'; import { infoPopover } from './components/info_popover'; @@ -34,7 +35,6 @@ import 'app/core/services/all'; import './filters/filters'; import coreModule from './core_module'; import appEvents from './app_events'; -import colors from '@grafana/ui/'; import { assignModelProperties } from './utils/model_utils'; import { contextSrv } from './services/context_srv'; import { KeybindingSrv } from './services/keybindingSrv'; diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index 8eb8433cd53..4cf9a029a2a 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import colors from '@grafana/ui'; +import { colors } from '@grafana/ui'; import { TimeSeries } from 'app/core/core'; import { getThemeColor } from 'app/core/utils/colors'; diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index 2cca33620b7..f3273ffa16d 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import colors from '@grafana/ui'; +import { colors } from '@grafana/ui'; import { renderUrl } from 'app/core/utils/url'; import kbn from 'app/core/utils/kbn'; diff --git a/public/app/plugins/panel/graph/data_processor.ts b/public/app/plugins/panel/graph/data_processor.ts index ef4ad872753..4fe47b70129 100644 --- a/public/app/plugins/panel/graph/data_processor.ts +++ b/public/app/plugins/panel/graph/data_processor.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import colors from '@grafana/ui'; +import { colors } from '@grafana/ui'; import TimeSeries from 'app/core/time_series2'; diff --git a/public/app/plugins/panel/graph2/GraphPanel.tsx b/public/app/plugins/panel/graph2/GraphPanel.tsx index 11be172aaeb..4a3daf77333 100644 --- a/public/app/plugins/panel/graph2/GraphPanel.tsx +++ b/public/app/plugins/panel/graph2/GraphPanel.tsx @@ -1,7 +1,7 @@ // Libraries import _ from 'lodash'; import React, { PureComponent } from 'react'; -import colors from '@grafana/ui'; +import { colors } from '@grafana/ui'; // Components & Types import { Graph, PanelProps, NullValueMode, processTimeSeries } from '@grafana/ui'; diff --git a/public/app/routes/GrafanaCtrl.ts b/public/app/routes/GrafanaCtrl.ts index 434a112692e..4e4dd8121cf 100644 --- a/public/app/routes/GrafanaCtrl.ts +++ b/public/app/routes/GrafanaCtrl.ts @@ -2,7 +2,7 @@ import config from 'app/core/config'; import _ from 'lodash'; import $ from 'jquery'; import Drop from 'tether-drop'; -import colors from '@grafana/ui'; +import { colors } from '@grafana/ui'; import coreModule from 'app/core/core_module'; import { profiler } from 'app/core/profiler'; diff --git a/public/app/viz/state/timeSeries.ts b/public/app/viz/state/timeSeries.ts index 2329d6f41af..5f27974a33b 100644 --- a/public/app/viz/state/timeSeries.ts +++ b/public/app/viz/state/timeSeries.ts @@ -2,7 +2,7 @@ import _ from 'lodash'; // Utils -import colors from '@grafana/ui'; +import { colors } from '@grafana/ui'; // Types import { TimeSeries, TimeSeriesVMs, NullValueMode } from '@grafana/ui'; From 1581662a6cd55bc9002c6ae0618ecb57e0056b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 10 Jan 2019 09:37:32 +0100 Subject: [PATCH 31/37] Moved Thresholds and styles to grafana/ui/components --- .../src/components/Thresholds}/Threshold.test.tsx | 8 ++++---- .../grafana-ui/src/components/Thresholds}/Thresholds.tsx | 8 ++++---- .../grafana-ui/src/components/Thresholds/_Thresholds.scss | 0 packages/grafana-ui/src/components/index.scss | 1 + packages/grafana-ui/src/components/index.ts | 1 + packages/grafana-ui/src/types/panel.ts | 6 ++++++ public/app/plugins/panel/gauge/GaugePanelOptions.tsx | 3 +-- public/app/types/index.ts | 3 ++- public/app/types/panel.ts | 6 ------ public/sass/_grafana.scss | 1 - 10 files changed, 19 insertions(+), 18 deletions(-) rename {public/app/plugins/panel/gauge => packages/grafana-ui/src/components/Thresholds}/Threshold.test.tsx (91%) rename {public/app/plugins/panel/gauge => packages/grafana-ui/src/components/Thresholds}/Thresholds.tsx (96%) rename public/sass/components/_thresholds.scss => packages/grafana-ui/src/components/Thresholds/_Thresholds.scss (100%) diff --git a/public/app/plugins/panel/gauge/Threshold.test.tsx b/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx similarity index 91% rename from public/app/plugins/panel/gauge/Threshold.test.tsx rename to packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx index 852b9f4c104..eac82e1b0f4 100644 --- a/public/app/plugins/panel/gauge/Threshold.test.tsx +++ b/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { shallow } from 'enzyme'; -import Thresholds from './Thresholds'; -import { defaultProps } from './GaugePanelOptions'; -import { BasicGaugeColor } from 'app/types'; import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; +import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; +import { Options } from 'app/plugins/panel/gauge/types'; +import { BasicGaugeColor } from 'app/types'; +import { Thresholds } from './Thresholds'; const setup = (propOverrides?: object) => { const props: PanelOptionsProps = { diff --git a/public/app/plugins/panel/gauge/Thresholds.tsx b/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx similarity index 96% rename from public/app/plugins/panel/gauge/Thresholds.tsx rename to packages/grafana-ui/src/components/Thresholds/Thresholds.tsx index 7699a499146..b5885e4efe8 100644 --- a/public/app/plugins/panel/gauge/Thresholds.tsx +++ b/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx @@ -1,16 +1,16 @@ import React, { PureComponent } from 'react'; import tinycolor from 'tinycolor2'; import { ColorPicker } from '@grafana/ui'; -import { BasicGaugeColor, Threshold } from 'app/types'; -import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; +import { BasicGaugeColor } from 'app/types'; +import { PanelOptionsProps, Threshold } from '@grafana/ui'; +import { Options } from 'app/plugins/panel/gauge/types'; interface State { thresholds: Threshold[]; baseColor: string; } -export default class Thresholds extends PureComponent, State> { +export class Thresholds extends PureComponent, State> { constructor(props) { super(props); diff --git a/public/sass/components/_thresholds.scss b/packages/grafana-ui/src/components/Thresholds/_Thresholds.scss similarity index 100% rename from public/sass/components/_thresholds.scss rename to packages/grafana-ui/src/components/Thresholds/_Thresholds.scss diff --git a/packages/grafana-ui/src/components/index.scss b/packages/grafana-ui/src/components/index.scss index e1d1474bb16..d0a81675490 100644 --- a/packages/grafana-ui/src/components/index.scss +++ b/packages/grafana-ui/src/components/index.scss @@ -1,3 +1,4 @@ @import 'CustomScrollbar/CustomScrollbar'; @import 'DeleteButton/DeleteButton'; +@import 'Thresholds/Thresholds'; @import 'Tooltip/Tooltip'; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index b2b607415b8..fef3f6604c9 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -5,3 +5,4 @@ export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; export { ColorPicker } from './ColorPicker/ColorPicker'; export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover'; export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker'; +export { Thresholds } from './Thresholds/Thresholds'; diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index 44336555a81..46fe84a211c 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -29,3 +29,9 @@ export interface PanelMenuItem { shortcut?: string; subMenu?: PanelMenuItem[]; } + +export interface Threshold { + index: number; + value: number; + color?: string; +} diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 2b16ef5a1fe..7b627a09592 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,8 +1,7 @@ import React, { PureComponent } from 'react'; import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; -import Thresholds from 'app/plugins/panel/gauge/Thresholds'; import { BasicGaugeColor } from 'app/types'; -import { PanelOptionsProps } from '@grafana/ui'; +import { PanelOptionsProps, Thresholds } from '@grafana/ui'; import ValueMappings from 'app/plugins/panel/gauge/ValueMappings'; import { Options } from './types'; import GaugeOptions from './GaugeOptions'; diff --git a/public/app/types/index.ts b/public/app/types/index.ts index ab52b03ab17..52b2b996542 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -9,7 +9,7 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys'; import { Invitee, OrgUser, User, UsersState, UserState } from './user'; import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources'; import { DataQuery, DataQueryResponse, DataQueryOptions } from './series'; -import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from './panel'; +import { BasicGaugeColor, MappingType, RangeMap, ValueMap } from './panel'; import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins'; import { Organization, OrganizationState } from './organization'; import { @@ -20,6 +20,7 @@ import { } from './appNotifications'; import { DashboardSearchHit } from './search'; import { ValidationEvents, ValidationRule } from './form'; +import { Threshold } from '@grafana/ui'; export { Team, TeamsState, diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts index 31674d20304..1f5a2307733 100644 --- a/public/app/types/panel.ts +++ b/public/app/types/panel.ts @@ -1,9 +1,3 @@ -export interface Threshold { - index: number; - value: number; - color?: string; -} - export enum MappingType { ValueToText = 1, RangeToText = 2, diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 10cc7335bdf..a3dd204eb63 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -102,7 +102,6 @@ @import 'components/toolbar'; @import 'components/add_data_source.scss'; @import 'components/page_loader'; -@import 'components/thresholds'; @import 'components/toggle_button_group'; @import 'components/value-mappings'; @import 'components/popover-box'; From 0b6e21e9acb529bd12ae0141977782d18e785d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 10 Jan 2019 10:43:18 +0100 Subject: [PATCH 32/37] Renamed Thresholds to ThresholdsEditor --- .../grafana-ui/src/components/Thresholds/Threshold.test.tsx | 4 ++-- packages/grafana-ui/src/components/Thresholds/Thresholds.tsx | 2 +- packages/grafana-ui/src/components/index.ts | 2 +- public/app/plugins/panel/gauge/GaugePanelOptions.tsx | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx b/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx index eac82e1b0f4..90ce6687985 100644 --- a/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx +++ b/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx @@ -4,7 +4,7 @@ import { PanelOptionsProps } from '@grafana/ui'; import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; import { Options } from 'app/plugins/panel/gauge/types'; import { BasicGaugeColor } from 'app/types'; -import { Thresholds } from './Thresholds'; +import { ThresholdsEditor } from './Thresholds'; const setup = (propOverrides?: object) => { const props: PanelOptionsProps = { @@ -17,7 +17,7 @@ const setup = (propOverrides?: object) => { Object.assign(props, propOverrides); - return shallow().instance() as Thresholds; + return shallow().instance() as ThresholdsEditor; }; describe('Add threshold', () => { diff --git a/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx b/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx index b5885e4efe8..d5af07e4a49 100644 --- a/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx +++ b/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx @@ -10,7 +10,7 @@ interface State { baseColor: string; } -export class Thresholds extends PureComponent, State> { +export class ThresholdsEditor extends PureComponent, State> { constructor(props) { super(props); diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index fef3f6604c9..79764ac8fa4 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -5,4 +5,4 @@ export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; export { ColorPicker } from './ColorPicker/ColorPicker'; export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover'; export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker'; -export { Thresholds } from './Thresholds/Thresholds'; +export { ThresholdsEditor } from './Thresholds/Thresholds'; diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 7b627a09592..2030b3c4cde 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; import { BasicGaugeColor } from 'app/types'; -import { PanelOptionsProps, Thresholds } from '@grafana/ui'; +import { PanelOptionsProps, ThresholdsEditor } from '@grafana/ui'; import ValueMappings from 'app/plugins/panel/gauge/ValueMappings'; import { Options } from './types'; import GaugeOptions from './GaugeOptions'; @@ -33,7 +33,7 @@ export default class GaugePanelOptions extends PureComponent - +
From c05b92c2e0c9043a2e3933dd70cf700adf0e8970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Thu, 10 Jan 2019 10:47:49 +0100 Subject: [PATCH 33/37] Renamed Threshold files --- .../ThresholdsEditor.test.tsx} | 2 +- .../Thresholds.tsx => ThresholdsEditor/ThresholdsEditor.tsx} | 0 .../_ThresholdsEditor.scss} | 0 packages/grafana-ui/src/components/index.scss | 2 +- packages/grafana-ui/src/components/index.ts | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename packages/grafana-ui/src/components/{Thresholds/Threshold.test.tsx => ThresholdsEditor/ThresholdsEditor.test.tsx} (97%) rename packages/grafana-ui/src/components/{Thresholds/Thresholds.tsx => ThresholdsEditor/ThresholdsEditor.tsx} (100%) rename packages/grafana-ui/src/components/{Thresholds/_Thresholds.scss => ThresholdsEditor/_ThresholdsEditor.scss} (100%) diff --git a/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx similarity index 97% rename from packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx rename to packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx index 90ce6687985..6d6449aaa60 100644 --- a/packages/grafana-ui/src/components/Thresholds/Threshold.test.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx @@ -4,7 +4,7 @@ import { PanelOptionsProps } from '@grafana/ui'; import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; import { Options } from 'app/plugins/panel/gauge/types'; import { BasicGaugeColor } from 'app/types'; -import { ThresholdsEditor } from './Thresholds'; +import { ThresholdsEditor } from './ThresholdsEditor'; const setup = (propOverrides?: object) => { const props: PanelOptionsProps = { diff --git a/packages/grafana-ui/src/components/Thresholds/Thresholds.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx similarity index 100% rename from packages/grafana-ui/src/components/Thresholds/Thresholds.tsx rename to packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx diff --git a/packages/grafana-ui/src/components/Thresholds/_Thresholds.scss b/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss similarity index 100% rename from packages/grafana-ui/src/components/Thresholds/_Thresholds.scss rename to packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss diff --git a/packages/grafana-ui/src/components/index.scss b/packages/grafana-ui/src/components/index.scss index d0a81675490..cc5979c8444 100644 --- a/packages/grafana-ui/src/components/index.scss +++ b/packages/grafana-ui/src/components/index.scss @@ -1,4 +1,4 @@ @import 'CustomScrollbar/CustomScrollbar'; @import 'DeleteButton/DeleteButton'; -@import 'Thresholds/Thresholds'; +@import 'ThresholdsEditor/ThresholdsEditor'; @import 'Tooltip/Tooltip'; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 79764ac8fa4..4b60557be7e 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -5,4 +5,4 @@ export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar'; export { ColorPicker } from './ColorPicker/ColorPicker'; export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover'; export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker'; -export { ThresholdsEditor } from './Thresholds/Thresholds'; +export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor'; From c54ec5f52f3bdac684a396ad9699306af29bcd94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Fri, 11 Jan 2019 08:30:30 +0100 Subject: [PATCH 34/37] Moved the rest of Threshold dependencies to ui/components --- .../ThresholdsEditor.test.tsx | 7 +-- .../ThresholdsEditor/ThresholdsEditor.tsx | 60 ++++++------------- .../grafana-ui/src/types/gauge.ts | 4 +- packages/grafana-ui/src/types/index.ts | 1 + packages/grafana-ui/src/types/panel.ts | 26 ++++++++ ...augeOptions.tsx => GaugeOptionsEditor.tsx} | 6 +- public/app/plugins/panel/gauge/GaugePanel.tsx | 6 +- .../plugins/panel/gauge/GaugePanelOptions.tsx | 11 ++-- public/app/plugins/panel/gauge/MappingRow.tsx | 3 +- .../panel/gauge/ValueMappings.test.tsx | 7 +-- .../app/plugins/panel/gauge/ValueMappings.tsx | 7 +-- .../app/plugins/panel/gauge/ValueOptions.tsx | 6 +- public/app/types/index.ts | 7 --- public/app/types/panel.ts | 25 -------- public/app/viz/Gauge.test.tsx | 4 +- public/app/viz/Gauge.tsx | 4 +- 16 files changed, 76 insertions(+), 108 deletions(-) rename public/app/plugins/panel/gauge/types.ts => packages/grafana-ui/src/types/gauge.ts (75%) rename public/app/plugins/panel/gauge/{GaugeOptions.tsx => GaugeOptionsEditor.tsx} (91%) delete mode 100644 public/app/types/panel.ts diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx index 6d6449aaa60..8c0c131e1f8 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx @@ -1,13 +1,12 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { PanelOptionsProps } from '@grafana/ui'; +import { BasicGaugeColor, GaugeOptions, PanelOptionsProps } from '@grafana/ui'; + import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; -import { Options } from 'app/plugins/panel/gauge/types'; -import { BasicGaugeColor } from 'app/types'; import { ThresholdsEditor } from './ThresholdsEditor'; const setup = (propOverrides?: object) => { - const props: PanelOptionsProps = { + const props: PanelOptionsProps = { onChange: jest.fn(), options: { ...defaultProps.options, diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx index d5af07e4a49..df999de6c25 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx @@ -1,26 +1,20 @@ import React, { PureComponent } from 'react'; -import tinycolor from 'tinycolor2'; -import { ColorPicker } from '@grafana/ui'; -import { BasicGaugeColor } from 'app/types'; -import { PanelOptionsProps, Threshold } from '@grafana/ui'; -import { Options } from 'app/plugins/panel/gauge/types'; +import tinycolor, { ColorInput } from 'tinycolor2'; +import { BasicGaugeColor, ColorPicker, GaugeOptions, PanelOptionsProps, Threshold } from '@grafana/ui'; interface State { thresholds: Threshold[]; baseColor: string; } -export class ThresholdsEditor extends PureComponent, State> { - constructor(props) { +export class ThresholdsEditor extends PureComponent, State> { + constructor(props: PanelOptionsProps) { super(props); - this.state = { - thresholds: props.options.thresholds, - baseColor: props.options.baseColor, - }; + this.state = { thresholds: props.options.thresholds, baseColor: props.options.baseColor }; } - onAddThreshold = index => { + onAddThreshold = (index: number) => { const { maxValue, minValue } = this.props.options; const { thresholds } = this.state; @@ -48,27 +42,25 @@ export class ThresholdsEditor extends PureComponent, if (index === 0 && thresholds.length === 0) { color = tinycolor.mix(BasicGaugeColor.Green, BasicGaugeColor.Red, 50).toRgbString(); } else { - color = tinycolor.mix(thresholds[index - 1].color, BasicGaugeColor.Red, 50).toRgbString(); + color = tinycolor.mix(thresholds[index - 1].color as ColorInput, BasicGaugeColor.Red, 50).toRgbString(); } this.setState( { - thresholds: this.sortThresholds([...newThresholds, { index: index, value: value, color: color }]), + thresholds: this.sortThresholds([...newThresholds, { index, value: value as number, color }]), }, () => this.updateGauge() ); }; - onRemoveThreshold = threshold => { + onRemoveThreshold = (threshold: Threshold) => { this.setState( - prevState => ({ - thresholds: prevState.thresholds.filter(t => t !== threshold), - }), + prevState => ({ thresholds: prevState.thresholds.filter(t => t !== threshold) }), () => this.updateGauge() ); }; - onChangeThresholdValue = (event, threshold) => { + onChangeThresholdValue = (event: any, threshold: Threshold) => { const { thresholds } = this.state; const newThresholds = thresholds.map(t => { @@ -79,12 +71,10 @@ export class ThresholdsEditor extends PureComponent, return t; }); - this.setState({ - thresholds: newThresholds, - }); + this.setState({ thresholds: newThresholds }); }; - onChangeThresholdColor = (threshold, color) => { + onChangeThresholdColor = (threshold: Threshold, color: string) => { const { thresholds } = this.state; const newThresholds = thresholds.map(t => { @@ -103,11 +93,9 @@ export class ThresholdsEditor extends PureComponent, ); }; - onChangeBaseColor = color => this.props.onChange({ ...this.props.options, baseColor: color }); + onChangeBaseColor = (color: string) => this.props.onChange({ ...this.props.options, baseColor: color }); onBlur = () => { - this.setState(prevState => ({ - thresholds: this.sortThresholds(prevState.thresholds), - })); + this.setState(prevState => ({ thresholds: this.sortThresholds(prevState.thresholds) })); this.updateGauge(); }; @@ -116,7 +104,7 @@ export class ThresholdsEditor extends PureComponent, this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds }); }; - sortThresholds = thresholds => { + sortThresholds = (thresholds: Threshold[]) => { return thresholds.sort((t1, t2) => { return t2.value - t1.value; }); @@ -161,20 +149,8 @@ export class ThresholdsEditor extends PureComponent, return thresholds.map((t, i) => { return (
-
this.onAddThreshold(t.index + 1)} - style={{ - height: '50%', - backgroundColor: t.color, - }} - /> -
this.onAddThreshold(t.index)} - style={{ - height: '50%', - backgroundColor: t.color, - }} - /> +
this.onAddThreshold(t.index + 1)} style={{ height: '50%', backgroundColor: t.color }} /> +
this.onAddThreshold(t.index)} style={{ height: '50%', backgroundColor: t.color }} />
); }); diff --git a/public/app/plugins/panel/gauge/types.ts b/packages/grafana-ui/src/types/gauge.ts similarity index 75% rename from public/app/plugins/panel/gauge/types.ts rename to packages/grafana-ui/src/types/gauge.ts index 60c4fd1581d..de9c7f07328 100644 --- a/public/app/plugins/panel/gauge/types.ts +++ b/packages/grafana-ui/src/types/gauge.ts @@ -1,6 +1,6 @@ -import { RangeMap, ValueMap, Threshold } from 'app/types'; +import { RangeMap, Threshold, ValueMap } from '@grafana/ui'; -export interface Options { +export interface GaugeOptions { baseColor: string; decimals: number; mappings: Array; diff --git a/packages/grafana-ui/src/types/index.ts b/packages/grafana-ui/src/types/index.ts index f618ce6db34..814ab0478db 100644 --- a/packages/grafana-ui/src/types/index.ts +++ b/packages/grafana-ui/src/types/index.ts @@ -1,3 +1,4 @@ export * from './series'; export * from './time'; export * from './panel'; +export * from './gauge'; diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index 46fe84a211c..0b995f932f0 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -35,3 +35,29 @@ export interface Threshold { value: number; color?: string; } + +export enum BasicGaugeColor { + Green = '#299c46', + Red = '#d44a3a', +} + +export enum MappingType { + ValueToText = 1, + RangeToText = 2, +} + +interface BaseMap { + id: number; + operator: string; + text: string; + type: MappingType; +} + +export interface ValueMap extends BaseMap { + value: string; +} + +export interface RangeMap extends BaseMap { + from: string; + to: string; +} diff --git a/public/app/plugins/panel/gauge/GaugeOptions.tsx b/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx similarity index 91% rename from public/app/plugins/panel/gauge/GaugeOptions.tsx rename to public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx index 7607374b1b7..cb436180b49 100644 --- a/public/app/plugins/panel/gauge/GaugeOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx @@ -1,10 +1,10 @@ import React, { PureComponent } from 'react'; +import { GaugeOptions, PanelOptionsProps } from '@grafana/ui'; + import { Switch } from 'app/core/components/Switch/Switch'; import { Label } from '../../../core/components/Label/Label'; -import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; -export default class GaugeOptions extends PureComponent> { +export default class GaugeOptionsEditor extends PureComponent> { onToggleThresholdLabels = () => this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels }); diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index 5f1a438863f..79220daf37a 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -1,10 +1,10 @@ import React, { PureComponent } from 'react'; -import { PanelProps, NullValueMode } from '@grafana/ui'; +import { GaugeOptions, PanelProps, NullValueMode } from '@grafana/ui'; + import { getTimeSeriesVMs } from 'app/viz/state/timeSeries'; import Gauge from 'app/viz/Gauge'; -import { Options } from './types'; -interface Props extends PanelProps {} +interface Props extends PanelProps {} export class GaugePanel extends PureComponent { render() { diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 2030b3c4cde..951a310d29a 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,10 +1,9 @@ import React, { PureComponent } from 'react'; +import { BasicGaugeColor, GaugeOptions, PanelOptionsProps, ThresholdsEditor } from '@grafana/ui'; + import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; -import { BasicGaugeColor } from 'app/types'; -import { PanelOptionsProps, ThresholdsEditor } from '@grafana/ui'; import ValueMappings from 'app/plugins/panel/gauge/ValueMappings'; -import { Options } from './types'; -import GaugeOptions from './GaugeOptions'; +import GaugeOptionsEditor from './GaugeOptionsEditor'; export const defaultProps = { options: { @@ -23,7 +22,7 @@ export const defaultProps = { }, }; -export default class GaugePanelOptions extends PureComponent> { +export default class GaugePanelOptions extends PureComponent> { static defaultProps = defaultProps; render() { @@ -32,7 +31,7 @@ export default class GaugePanelOptions extends PureComponent
- +
diff --git a/public/app/plugins/panel/gauge/MappingRow.tsx b/public/app/plugins/panel/gauge/MappingRow.tsx index 35d0b2e638c..5bf3b4ab907 100644 --- a/public/app/plugins/panel/gauge/MappingRow.tsx +++ b/public/app/plugins/panel/gauge/MappingRow.tsx @@ -1,7 +1,8 @@ import React, { PureComponent } from 'react'; +import { MappingType, RangeMap, ValueMap } from '@grafana/ui'; + import { Label } from 'app/core/components/Label/Label'; import { Select } from 'app/core/components/Select/Select'; -import { MappingType, RangeMap, ValueMap } from 'app/types'; interface Props { mapping: ValueMap | RangeMap; diff --git a/public/app/plugins/panel/gauge/ValueMappings.test.tsx b/public/app/plugins/panel/gauge/ValueMappings.test.tsx index 3e59cc76742..503e3e53617 100644 --- a/public/app/plugins/panel/gauge/ValueMappings.test.tsx +++ b/public/app/plugins/panel/gauge/ValueMappings.test.tsx @@ -1,13 +1,12 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { GaugeOptions, MappingType, PanelOptionsProps } from '@grafana/ui'; + import ValueMappings from './ValueMappings'; -import { MappingType } from 'app/types'; -import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; const setup = (propOverrides?: object) => { - const props: PanelOptionsProps = { + const props: PanelOptionsProps = { onChange: jest.fn(), options: { ...defaultProps.options, diff --git a/public/app/plugins/panel/gauge/ValueMappings.tsx b/public/app/plugins/panel/gauge/ValueMappings.tsx index be800cf2412..4ce0d37b53c 100644 --- a/public/app/plugins/panel/gauge/ValueMappings.tsx +++ b/public/app/plugins/panel/gauge/ValueMappings.tsx @@ -1,15 +1,14 @@ import React, { PureComponent } from 'react'; +import { GaugeOptions, PanelOptionsProps, MappingType, RangeMap, ValueMap } from '@grafana/ui'; + import MappingRow from './MappingRow'; -import { MappingType, RangeMap, ValueMap } from 'app/types'; -import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; interface State { mappings: Array; nextIdToAdd: number; } -export default class ValueMappings extends PureComponent, State> { +export default class ValueMappings extends PureComponent, State> { constructor(props) { super(props); diff --git a/public/app/plugins/panel/gauge/ValueOptions.tsx b/public/app/plugins/panel/gauge/ValueOptions.tsx index 4aafc0b0457..0d8771ec326 100644 --- a/public/app/plugins/panel/gauge/ValueOptions.tsx +++ b/public/app/plugins/panel/gauge/ValueOptions.tsx @@ -1,9 +1,9 @@ import React, { PureComponent } from 'react'; +import { GaugeOptions, PanelOptionsProps } from '@grafana/ui'; + import { Label } from 'app/core/components/Label/Label'; import Select from 'app/core/components/Select/Select'; import UnitPicker from 'app/core/components/Select/UnitPicker'; -import { PanelOptionsProps } from '@grafana/ui'; -import { Options } from './types'; const statOptions = [ { value: 'min', label: 'Min' }, @@ -21,7 +21,7 @@ const statOptions = [ const labelWidth = 6; -export default class ValueOptions extends PureComponent> { +export default class ValueOptions extends PureComponent> { onUnitChange = unit => this.props.onChange({ ...this.props.options, unit: unit.value }); onStatChange = stat => this.props.onChange({ ...this.props.options, stat: stat.value }); diff --git a/public/app/types/index.ts b/public/app/types/index.ts index 52b2b996542..72da1c76ea8 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -9,7 +9,6 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys'; import { Invitee, OrgUser, User, UsersState, UserState } from './user'; import { DataSource, DataSourceSelectItem, DataSourcesState } from './datasources'; import { DataQuery, DataQueryResponse, DataQueryOptions } from './series'; -import { BasicGaugeColor, MappingType, RangeMap, ValueMap } from './panel'; import { PluginDashboard, PluginMeta, Plugin, PanelPlugin, PluginsState } from './plugins'; import { Organization, OrganizationState } from './organization'; import { @@ -20,7 +19,6 @@ import { } from './appNotifications'; import { DashboardSearchHit } from './search'; import { ValidationEvents, ValidationRule } from './form'; -import { Threshold } from '@grafana/ui'; export { Team, TeamsState, @@ -70,13 +68,8 @@ export { AppNotificationTimeout, DashboardSearchHit, UserState, - Threshold, ValidationEvents, ValidationRule, - ValueMap, - RangeMap, - MappingType, - BasicGaugeColor, }; export interface StoreState { diff --git a/public/app/types/panel.ts b/public/app/types/panel.ts deleted file mode 100644 index 1f5a2307733..00000000000 --- a/public/app/types/panel.ts +++ /dev/null @@ -1,25 +0,0 @@ -export enum MappingType { - ValueToText = 1, - RangeToText = 2, -} - -export enum BasicGaugeColor { - Green = '#299c46', - Red = '#d44a3a', -} - -interface BaseMap { - id: number; - operator: string; - text: string; - type: MappingType; -} - -export interface ValueMap extends BaseMap { - value: string; -} - -export interface RangeMap extends BaseMap { - from: string; - to: string; -} diff --git a/public/app/viz/Gauge.test.tsx b/public/app/viz/Gauge.test.tsx index 91107a563e5..f0c4a874649 100644 --- a/public/app/viz/Gauge.test.tsx +++ b/public/app/viz/Gauge.test.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { BasicGaugeColor, TimeSeriesVMs } from '@grafana/ui'; + import { Gauge, Props } from './Gauge'; -import { BasicGaugeColor } from '../types'; -import { TimeSeriesVMs } from '@grafana/ui'; jest.mock('jquery', () => ({ plot: jest.fn(), diff --git a/public/app/viz/Gauge.tsx b/public/app/viz/Gauge.tsx index defeaf8cc8f..5112ff9aa1b 100644 --- a/public/app/viz/Gauge.tsx +++ b/public/app/viz/Gauge.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import $ from 'jquery'; -import { BasicGaugeColor, MappingType, RangeMap, Threshold, ValueMap } from 'app/types'; -import { TimeSeriesVMs } from '@grafana/ui'; +import { BasicGaugeColor, Threshold, TimeSeriesVMs, RangeMap, ValueMap, MappingType } from '@grafana/ui'; + import config from '../core/config'; import kbn from '../core/utils/kbn'; From 5ceedc4ac4aca6f33d86d93fd3ac84b6381350ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Fri, 11 Jan 2019 09:16:53 +0100 Subject: [PATCH 35/37] Moved defaultProps to ui/components --- .../ThresholdsEditor.test.tsx | 2 +- .../ThresholdsEditor/ThresholdsEditor.tsx | 4 +++- packages/grafana-ui/src/types/gauge.ts | 19 ++++++++++++++++- .../plugins/panel/gauge/GaugePanelOptions.tsx | 21 ++----------------- .../panel/gauge/ValueMappings.test.tsx | 6 +++--- public/app/plugins/panel/gauge/module.tsx | 6 ++++-- 6 files changed, 31 insertions(+), 27 deletions(-) diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx index 074d3bc267b..40e6bb47f1f 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { BasicGaugeColor, GaugeOptions, PanelOptionsProps } from '@grafana/ui'; import { ThresholdsEditor } from './ThresholdsEditor'; +import { BasicGaugeColor, PanelOptionsProps, GaugeOptions } from '../../types'; const defaultProps = { options: { diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx index df999de6c25..ed6778f7c43 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx @@ -1,6 +1,8 @@ import React, { PureComponent } from 'react'; import tinycolor, { ColorInput } from 'tinycolor2'; -import { BasicGaugeColor, ColorPicker, GaugeOptions, PanelOptionsProps, Threshold } from '@grafana/ui'; + +import { Threshold, PanelOptionsProps, GaugeOptions, BasicGaugeColor } from '../../types'; +import { ColorPicker } from '../ColorPicker/ColorPicker'; interface State { thresholds: Threshold[]; diff --git a/packages/grafana-ui/src/types/gauge.ts b/packages/grafana-ui/src/types/gauge.ts index de9c7f07328..fe422386d92 100644 --- a/packages/grafana-ui/src/types/gauge.ts +++ b/packages/grafana-ui/src/types/gauge.ts @@ -1,4 +1,4 @@ -import { RangeMap, Threshold, ValueMap } from '@grafana/ui'; +import { BasicGaugeColor, RangeMap, Threshold, ValueMap } from './panel'; export interface GaugeOptions { baseColor: string; @@ -14,3 +14,20 @@ export interface GaugeOptions { thresholds: Threshold[]; unit: string; } + +export const GaugePanelOptionsDefaultProps = { + options: { + baseColor: BasicGaugeColor.Green, + minValue: 0, + maxValue: 100, + prefix: '', + showThresholdMarkers: true, + showThresholdLabels: false, + suffix: '', + decimals: 0, + stat: 'avg', + unit: 'none', + mappings: [], + thresholds: [], + }, +}; diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 951a310d29a..99bff41a0d3 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,29 +1,12 @@ import React, { PureComponent } from 'react'; -import { BasicGaugeColor, GaugeOptions, PanelOptionsProps, ThresholdsEditor } from '@grafana/ui'; +import { GaugeOptions, GaugePanelOptionsDefaultProps, PanelOptionsProps, ThresholdsEditor } from '@grafana/ui'; import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; import ValueMappings from 'app/plugins/panel/gauge/ValueMappings'; import GaugeOptionsEditor from './GaugeOptionsEditor'; -export const defaultProps = { - options: { - baseColor: BasicGaugeColor.Green, - minValue: 0, - maxValue: 100, - prefix: '', - showThresholdMarkers: true, - showThresholdLabels: false, - suffix: '', - decimals: 0, - stat: 'avg', - unit: 'none', - mappings: [], - thresholds: [], - }, -}; - export default class GaugePanelOptions extends PureComponent> { - static defaultProps = defaultProps; + static defaultProps = GaugePanelOptionsDefaultProps; render() { const { onChange, options } = this.props; diff --git a/public/app/plugins/panel/gauge/ValueMappings.test.tsx b/public/app/plugins/panel/gauge/ValueMappings.test.tsx index 503e3e53617..0cf08d6d3b7 100644 --- a/public/app/plugins/panel/gauge/ValueMappings.test.tsx +++ b/public/app/plugins/panel/gauge/ValueMappings.test.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { shallow } from 'enzyme'; import { GaugeOptions, MappingType, PanelOptionsProps } from '@grafana/ui'; +import { GaugePanelOptionsDefaultProps } from '@grafana/ui/src/types/gauge'; import ValueMappings from './ValueMappings'; -import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; const setup = (propOverrides?: object) => { const props: PanelOptionsProps = { onChange: jest.fn(), options: { - ...defaultProps.options, + ...GaugePanelOptionsDefaultProps.options, mappings: [ { id: 1, operator: '', type: MappingType.ValueToText, value: '20', text: 'Ok' }, { id: 2, operator: '', type: MappingType.RangeToText, from: '21', to: '30', text: 'Meh' }, @@ -67,7 +67,7 @@ describe('Next id to add', () => { }); it('should default to 1', () => { - const { instance } = setup({ options: { ...defaultProps.options } }); + const { instance } = setup({ options: { ...GaugePanelOptionsDefaultProps.options } }); expect(instance.state.nextIdToAdd).toEqual(1); }); diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 783e4825657..72230eb4ba3 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,4 +1,6 @@ -import GaugePanelOptions, { defaultProps } from './GaugePanelOptions'; +import { GaugePanelOptionsDefaultProps } from '@grafana/ui'; + +import GaugePanelOptions from './GaugePanelOptions'; import { GaugePanel } from './GaugePanel'; -export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, defaultProps as PanelDefaults }; +export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, GaugePanelOptionsDefaultProps as PanelDefaults }; From 537e2534a64b08fdb7e633c2bc7cd5161c969986 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Fri, 11 Jan 2019 09:50:05 +0100 Subject: [PATCH 36/37] Move Select styles to grafana/ui --- .../grafana-ui/src/components/Select/_Select.scss | 0 packages/grafana-ui/src/components/index.scss | 1 + public/sass/_grafana.scss | 9 ++++----- 3 files changed, 5 insertions(+), 5 deletions(-) rename public/sass/components/_form_select_box.scss => packages/grafana-ui/src/components/Select/_Select.scss (100%) diff --git a/public/sass/components/_form_select_box.scss b/packages/grafana-ui/src/components/Select/_Select.scss similarity index 100% rename from public/sass/components/_form_select_box.scss rename to packages/grafana-ui/src/components/Select/_Select.scss diff --git a/packages/grafana-ui/src/components/index.scss b/packages/grafana-ui/src/components/index.scss index e1d1474bb16..77a2caa9c5c 100644 --- a/packages/grafana-ui/src/components/index.scss +++ b/packages/grafana-ui/src/components/index.scss @@ -1,3 +1,4 @@ @import 'CustomScrollbar/CustomScrollbar'; @import 'DeleteButton/DeleteButton'; @import 'Tooltip/Tooltip'; +@import 'Select/Select'; diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 10cc7335bdf..c8ad1ce8edc 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -1,4 +1,4 @@ -// DEPENDENCIES + // DEPENDENCIES @import '../../node_modules/react-table/react-table.css'; // VENDOR @@ -38,9 +38,6 @@ @import 'layout/lists'; @import 'layout/page'; -// LOAD @grafana/ui components -@import '../../packages/grafana-ui/src/index'; - // COMPONENTS @import 'components/scrollbar'; @import 'components/cards'; @@ -97,7 +94,6 @@ @import 'components/page_header'; @import 'components/dashboard_settings'; @import 'components/empty_list_cta'; -@import 'components/form_select_box'; @import 'components/panel_editor'; @import 'components/toolbar'; @import 'components/add_data_source.scss'; @@ -107,6 +103,9 @@ @import 'components/value-mappings'; @import 'components/popover-box'; +// LOAD @grafana/ui components +@import '../../packages/grafana-ui/src/index'; + // PAGES @import 'pages/login'; @import 'pages/dashboard'; From d2b71cff3716f19456ea0e0d261f6924f5f9f245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Fri, 11 Jan 2019 11:25:49 +0100 Subject: [PATCH 37/37] Reverted move of defaults for GaugePanelOptions --- .../ThresholdsEditor.test.tsx | 33 +++------------- .../ThresholdsEditor/ThresholdsEditor.tsx | 38 +++++++++++++------ packages/grafana-ui/src/types/gauge.ts | 19 +--------- .../plugins/panel/gauge/GaugePanelOptions.tsx | 25 ++++++++++-- .../panel/gauge/ValueMappings.test.tsx | 6 +-- public/app/plugins/panel/gauge/module.tsx | 6 +-- 6 files changed, 60 insertions(+), 67 deletions(-) diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx index 40e6bb47f1f..14f84e00f80 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.test.tsx @@ -1,33 +1,13 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { ThresholdsEditor } from './ThresholdsEditor'; -import { BasicGaugeColor, PanelOptionsProps, GaugeOptions } from '../../types'; - -const defaultProps = { - options: { - baseColor: BasicGaugeColor.Green, - minValue: 0, - maxValue: 100, - prefix: '', - showThresholdMarkers: true, - showThresholdLabels: false, - suffix: '', - decimals: 0, - stat: 'avg', - unit: 'none', - mappings: [], - thresholds: [], - }, -}; +import { ThresholdsEditor, Props } from './ThresholdsEditor'; +import { BasicGaugeColor } from '../../types'; const setup = (propOverrides?: object) => { - const props: PanelOptionsProps = { + const props: Props = { onChange: jest.fn(), - options: { - ...defaultProps.options, - thresholds: [], - }, + thresholds: [], }; Object.assign(props, propOverrides); @@ -46,10 +26,7 @@ describe('Add threshold', () => { it('should add another threshold above a first', () => { const instance = setup({ - options: { - ...defaultProps.options, - thresholds: [{ index: 0, value: 50, color: 'rgb(127, 115, 64)' }], - }, + thresholds: [{ index: 0, value: 50, color: 'rgb(127, 115, 64)' }], }); instance.onAddThreshold(1); diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx index ed6778f7c43..54165dfadb5 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx +++ b/packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx @@ -1,28 +1,37 @@ import React, { PureComponent } from 'react'; import tinycolor, { ColorInput } from 'tinycolor2'; -import { Threshold, PanelOptionsProps, GaugeOptions, BasicGaugeColor } from '../../types'; +import { Threshold, BasicGaugeColor } from '../../types'; import { ColorPicker } from '../ColorPicker/ColorPicker'; +export interface Props { + thresholds: Threshold[]; + onChange: (thresholds: Threshold[]) => void; +} + interface State { thresholds: Threshold[]; baseColor: string; } -export class ThresholdsEditor extends PureComponent, State> { - constructor(props: PanelOptionsProps) { +export class ThresholdsEditor extends PureComponent { + constructor(props: Props) { super(props); - this.state = { thresholds: props.options.thresholds, baseColor: props.options.baseColor }; + this.state = { thresholds: props.thresholds, baseColor: BasicGaugeColor.Green }; } onAddThreshold = (index: number) => { - const { maxValue, minValue } = this.props.options; + const maxValue = 100; // hardcoded for now before we add the base threshold + const minValue = 0; // hardcoded for now before we add the base threshold const { thresholds } = this.state; const newThresholds = thresholds.map(threshold => { if (threshold.index >= index) { - threshold = { ...threshold, index: threshold.index + 1 }; + threshold = { + ...threshold, + index: threshold.index + 1, + }; } return threshold; @@ -49,7 +58,14 @@ export class ThresholdsEditor extends PureComponent this.updateGauge() ); @@ -95,7 +111,7 @@ export class ThresholdsEditor extends PureComponent this.props.onChange({ ...this.props.options, baseColor: color }); + onChangeBaseColor = (color: string) => this.props.onChange(this.state.thresholds); onBlur = () => { this.setState(prevState => ({ thresholds: this.sortThresholds(prevState.thresholds) })); @@ -103,7 +119,7 @@ export class ThresholdsEditor extends PureComponent { - this.props.onChange({ ...this.props.options, thresholds: this.state.thresholds }); + this.props.onChange(this.state.thresholds); }; sortThresholds = (thresholds: Threshold[]) => { @@ -163,14 +179,14 @@ export class ThresholdsEditor extends PureComponent
this.onAddThreshold(0)} - style={{ height: '100%', backgroundColor: this.props.options.baseColor }} + style={{ height: '100%', backgroundColor: BasicGaugeColor.Green }} />
); } renderBase() { - const { baseColor } = this.props.options; + const baseColor = BasicGaugeColor.Green; return (
diff --git a/packages/grafana-ui/src/types/gauge.ts b/packages/grafana-ui/src/types/gauge.ts index fe422386d92..e05849448f7 100644 --- a/packages/grafana-ui/src/types/gauge.ts +++ b/packages/grafana-ui/src/types/gauge.ts @@ -1,4 +1,4 @@ -import { BasicGaugeColor, RangeMap, Threshold, ValueMap } from './panel'; +import { RangeMap, Threshold, ValueMap } from './panel'; export interface GaugeOptions { baseColor: string; @@ -14,20 +14,3 @@ export interface GaugeOptions { thresholds: Threshold[]; unit: string; } - -export const GaugePanelOptionsDefaultProps = { - options: { - baseColor: BasicGaugeColor.Green, - minValue: 0, - maxValue: 100, - prefix: '', - showThresholdMarkers: true, - showThresholdLabels: false, - suffix: '', - decimals: 0, - stat: 'avg', - unit: 'none', - mappings: [], - thresholds: [], - }, -}; diff --git a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx index 99bff41a0d3..e43abad61a3 100644 --- a/public/app/plugins/panel/gauge/GaugePanelOptions.tsx +++ b/public/app/plugins/panel/gauge/GaugePanelOptions.tsx @@ -1,12 +1,31 @@ import React, { PureComponent } from 'react'; -import { GaugeOptions, GaugePanelOptionsDefaultProps, PanelOptionsProps, ThresholdsEditor } from '@grafana/ui'; +import { BasicGaugeColor, GaugeOptions, PanelOptionsProps, ThresholdsEditor, Threshold } from '@grafana/ui'; import ValueOptions from 'app/plugins/panel/gauge/ValueOptions'; import ValueMappings from 'app/plugins/panel/gauge/ValueMappings'; import GaugeOptionsEditor from './GaugeOptionsEditor'; +export const defaultProps = { + options: { + baseColor: BasicGaugeColor.Green, + minValue: 0, + maxValue: 100, + prefix: '', + showThresholdMarkers: true, + showThresholdLabels: false, + suffix: '', + decimals: 0, + stat: 'avg', + unit: 'none', + mappings: [], + thresholds: [], + }, +}; + export default class GaugePanelOptions extends PureComponent> { - static defaultProps = GaugePanelOptionsDefaultProps; + static defaultProps = defaultProps; + + onThresholdsChanged = (thresholds: Threshold[]) => this.props.onChange({ ...this.props.options, thresholds }); render() { const { onChange, options } = this.props; @@ -15,7 +34,7 @@ export default class GaugePanelOptions extends PureComponent - +
diff --git a/public/app/plugins/panel/gauge/ValueMappings.test.tsx b/public/app/plugins/panel/gauge/ValueMappings.test.tsx index 0cf08d6d3b7..07db4028c68 100644 --- a/public/app/plugins/panel/gauge/ValueMappings.test.tsx +++ b/public/app/plugins/panel/gauge/ValueMappings.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { GaugeOptions, MappingType, PanelOptionsProps } from '@grafana/ui'; -import { GaugePanelOptionsDefaultProps } from '@grafana/ui/src/types/gauge'; +import { defaultProps } from 'app/plugins/panel/gauge/GaugePanelOptions'; import ValueMappings from './ValueMappings'; @@ -9,7 +9,7 @@ const setup = (propOverrides?: object) => { const props: PanelOptionsProps = { onChange: jest.fn(), options: { - ...GaugePanelOptionsDefaultProps.options, + ...defaultProps.options, mappings: [ { id: 1, operator: '', type: MappingType.ValueToText, value: '20', text: 'Ok' }, { id: 2, operator: '', type: MappingType.RangeToText, from: '21', to: '30', text: 'Meh' }, @@ -67,7 +67,7 @@ describe('Next id to add', () => { }); it('should default to 1', () => { - const { instance } = setup({ options: { ...GaugePanelOptionsDefaultProps.options } }); + const { instance } = setup({ options: { ...defaultProps.options } }); expect(instance.state.nextIdToAdd).toEqual(1); }); diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 72230eb4ba3..783e4825657 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -1,6 +1,4 @@ -import { GaugePanelOptionsDefaultProps } from '@grafana/ui'; - -import GaugePanelOptions from './GaugePanelOptions'; +import GaugePanelOptions, { defaultProps } from './GaugePanelOptions'; import { GaugePanel } from './GaugePanel'; -export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, GaugePanelOptionsDefaultProps as PanelDefaults }; +export { GaugePanel as Panel, GaugePanelOptions as PanelOptions, defaultProps as PanelDefaults };