diff --git a/CHANGELOG.md b/CHANGELOG.md index b5906cf567e..7c16f4f6e5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ * **Security**: Fix XSS vulnerabilities in dashboard links [#11813](https://github.com/grafana/grafana/pull/11813) * **Singlestat**: Fix "time of last point" shows local time when dashboard timezone set to UTC [#10338](https://github.com/grafana/grafana/issues/10338) * **Prometheus**: Add support for passing timeout parameter to Prometheus [#11788](https://github.com/grafana/grafana/pull/11788), thx [@mtanda](https://github.com/mtanda) +* **Login**: Add optional option sign out url for generic oauth [#9847](https://github.com/grafana/grafana/issues/9847), thx [@roidelapluie](https://github.com/roidelapluie) +* **Login**: Use proxy server from environment variable if available [#9703](https://github.com/grafana/grafana/issues/9703), thx [@iyeonok](https://github.com/iyeonok) +* **Invite users**: Friendlier error message when smtp is not configured [#12087](https://github.com/grafana/grafana/issues/12087), thx [@thurt](https://github.com/thurt) +* **Graphite**: Don't send distributed tracing headers when using direct/browser access mode [#11494](https://github.com/grafana/grafana/issues/11494) # 5.1.3 (2018-05-16) diff --git a/docker/blocks/elastic6/docker-compose.yaml b/docker/blocks/elastic6/docker-compose.yaml new file mode 100644 index 00000000000..dd2439f88e4 --- /dev/null +++ b/docker/blocks/elastic6/docker-compose.yaml @@ -0,0 +1,15 @@ +# You need to run 'sysctl -w vm.max_map_count=262144' on the host machine + + elasticsearch6: + image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.2.4 + command: elasticsearch + ports: + - "11200:9200" + - "11300:9300" + + fake-elastic6-data: + image: grafana/fake-data-gen + network_mode: bridge + environment: + FD_DATASOURCE: elasticsearch6 + FD_PORT: 11200 diff --git a/docker/blocks/elastic6/elasticsearch.yml b/docker/blocks/elastic6/elasticsearch.yml new file mode 100644 index 00000000000..c57b2c12908 --- /dev/null +++ b/docker/blocks/elastic6/elasticsearch.yml @@ -0,0 +1,2 @@ +script.inline: on +script.indexed: on diff --git a/docs/sources/features/panels/table_panel.md b/docs/sources/features/panels/table_panel.md index 32f7764e415..2cbb601820e 100644 --- a/docs/sources/features/panels/table_panel.md +++ b/docs/sources/features/panels/table_panel.md @@ -14,11 +14,53 @@ weight = 2 -The new table panel is very flexible, supporting both multiple modes for time series as well as for +The table panel is very flexible, supporting both multiple modes for time series as well as for table, annotation and raw JSON data. It also provides date formatting and value formatting and coloring options. To view table panels in action and test different configurations with sample data, check out the [Table Panel Showcase in the Grafana Playground](http://play.grafana.org/dashboard/db/table-panel-showcase). +## Querying Data + +The table panel displays the results of a query specified in the **Metrics** tab. +The result being displayed depends on the datasource and the query, but generally there is one row per datapoint, with extra columns for associated keys and values, as well as one column for the numeric value of the datapoint. +You can change the behavior in the section **Data to Table** below. + +### Merge Multiple Queries per Table + +> Only available in Grafana v5.0+. + +Sometimes it is useful to display the results of multiple queries in the same table on corresponding rows, e.g., when comparing capacity and actual usage of resources. +In this example usage and capacity are metrics that will have corresponding datapoints, while their associated keys and values can be used to match them. +(This matching is only available with the **Table Transform** set to **Table**.) + +In its simplest case, both queries return time-series data with a numeric value and a timestamp. +If the timestamps are the same, datapoints will be matched and rendered on the same row. +Some datasources return keys and values (labels, tags) associated with the datapoint. +These are being matched as well if they are present in both results and have the same value. +The following datapoints will end up on the same row with one time column, two label columns ("host" and "job") and two value columns: + +``` +Datapoint for query A: {time: 1, host: "node-2", job: "job-8", value: 3} +Datapoint for query B: {time: 1, host: "node-2", value: 4} +``` + +The following two results cannot be matched and will be rendered on separate rows: + +``` +Different time +Datapoint for query A: {time: 1, host: "node-2", job: "job-8", value: 3} +Datapoint for query B: {time: 2, host: "node-2", value: 4} + +Different label "host" +Datapoint for query A: {time: 1, host: "node-2", job: "job-8", value: 3} +Datapoint for query B: {time: 1, host: "node-9", value: 4} +``` + +You can still merge both of the above cases by changing the conflicting column's **Type** to **hidden** in the **Column Styles**. + +Note that if each datapoint of your query results have multiple value fields like max, min, mean, etc., they will likely have different values and therefore will not match and render on separate rows. +If you intend for rows to be merged but see them rendered on separate rows, check the query results in the **Query Inspector** for field values being identical across datapoints that should be merged into a row. + ## Options overview The table panel has many ways to manipulate your data for optimal presentation. diff --git a/package.json b/package.json index 84d404829eb..df3da5812c1 100644 --- a/package.json +++ b/package.json @@ -134,11 +134,11 @@ }, "license": "Apache-2.0", "dependencies": { - "angular": "^1.6.6", + "angular": "1.6.6", "angular-bindonce": "^0.3.1", "angular-native-dragdrop": "^1.2.2", - "angular-route": "^1.6.6", - "angular-sanitize": "^1.6.6", + "angular-route": "1.6.6", + "angular-sanitize": "1.6.6", "babel-polyfill": "^6.26.0", "baron": "^3.0.3", "brace": "^0.10.0", @@ -161,7 +161,7 @@ "prop-types": "^15.6.0", "react": "^16.2.0", "react-dom": "^16.2.0", - "react-grid-layout-grafana": "0.16.0", + "react-grid-layout": "0.16.6", "react-highlight-words": "^0.10.0", "react-popper": "^0.7.5", "react-select": "^1.1.0", @@ -180,4 +180,4 @@ "resolutions": { "caniuse-db": "1.0.30000772" } -} \ No newline at end of file +} diff --git a/pkg/api/login_oauth.go b/pkg/api/login_oauth.go index c4a5f8fdacf..fe4fa93b621 100644 --- a/pkg/api/login_oauth.go +++ b/pkg/api/login_oauth.go @@ -78,6 +78,7 @@ func OAuthLogin(ctx *m.ReqContext) { // handle call back tr := &http.Transport{ + Proxy: http.ProxyFromEnvironment, TLSClientConfig: &tls.Config{ InsecureSkipVerify: setting.OAuthService.OAuthInfos[name].TlsSkipVerify, }, diff --git a/pkg/api/org_invite.go b/pkg/api/org_invite.go index d6ab1c9d372..dfb2cf045ed 100644 --- a/pkg/api/org_invite.go +++ b/pkg/api/org_invite.go @@ -74,6 +74,9 @@ func AddOrgInvite(c *m.ReqContext, inviteDto dtos.AddInviteForm) Response { } if err := bus.Dispatch(&emailCmd); err != nil { + if err == m.ErrSmtpNotEnabled { + return Error(412, err.Error(), err) + } return Error(500, "Failed to send email invite", err) } diff --git a/pkg/tsdb/cloudwatch/metric_find_query.go b/pkg/tsdb/cloudwatch/metric_find_query.go index a7d33645b9b..136ee241c2e 100644 --- a/pkg/tsdb/cloudwatch/metric_find_query.go +++ b/pkg/tsdb/cloudwatch/metric_find_query.go @@ -230,8 +230,8 @@ func parseMultiSelectValue(input string) []string { // Please update the region list in public/app/plugins/datasource/cloudwatch/partials/config.html func (e *CloudWatchExecutor) handleGetRegions(ctx context.Context, parameters *simplejson.Json, queryContext *tsdb.TsdbQuery) ([]suggestData, error) { regions := []string{ - "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-south-1", "ca-central-1", "cn-north-1", - "eu-central-1", "eu-west-1", "eu-west-2", "sa-east-1", "us-east-1", "us-east-2", "us-gov-west-1", "us-west-1", "us-west-2", + "ap-northeast-1", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-south-1", "ca-central-1", "cn-north-1", "cn-northwest-1", + "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "sa-east-1", "us-east-1", "us-east-2", "us-gov-west-1", "us-west-1", "us-west-2", } result := make([]suggestData, 0) diff --git a/pkg/tsdb/sql_engine.go b/pkg/tsdb/sql_engine.go index 274e5b05dc1..82a9b8f0d88 100644 --- a/pkg/tsdb/sql_engine.go +++ b/pkg/tsdb/sql_engine.go @@ -144,10 +144,10 @@ func ConvertSqlTimeColumnToEpochMs(values RowValues, timeIndex int) { if timeIndex >= 0 { switch value := values[timeIndex].(type) { case time.Time: - values[timeIndex] = EpochPrecisionToMs(float64(value.UnixNano())) + values[timeIndex] = float64(value.UnixNano()) / float64(time.Millisecond) case *time.Time: if value != nil { - values[timeIndex] = EpochPrecisionToMs(float64((*value).UnixNano())) + values[timeIndex] = float64((*value).UnixNano()) / float64(time.Millisecond) } case int64: values[timeIndex] = int64(EpochPrecisionToMs(float64(value))) diff --git a/pkg/tsdb/sql_engine_test.go b/pkg/tsdb/sql_engine_test.go index ce1fb45de21..854734fac31 100644 --- a/pkg/tsdb/sql_engine_test.go +++ b/pkg/tsdb/sql_engine_test.go @@ -12,14 +12,17 @@ import ( func TestSqlEngine(t *testing.T) { Convey("SqlEngine", t, func() { dt := time.Date(2018, 3, 14, 21, 20, 6, int(527345*time.Microsecond), time.UTC) + earlyDt := time.Date(1970, 3, 14, 21, 20, 6, int(527345*time.Microsecond), time.UTC) Convey("Given row values with time.Time as time columns", func() { var nilPointer *time.Time - fixtures := make([]interface{}, 3) + fixtures := make([]interface{}, 5) fixtures[0] = dt fixtures[1] = &dt - fixtures[2] = nilPointer + fixtures[2] = earlyDt + fixtures[3] = &earlyDt + fixtures[4] = nilPointer for i := range fixtures { ConvertSqlTimeColumnToEpochMs(fixtures, i) @@ -27,9 +30,13 @@ func TestSqlEngine(t *testing.T) { Convey("When converting them should return epoch time with millisecond precision ", func() { expected := float64(dt.UnixNano()) / float64(time.Millisecond) + expectedEarly := float64(earlyDt.UnixNano()) / float64(time.Millisecond) + So(fixtures[0].(float64), ShouldEqual, expected) So(fixtures[1].(float64), ShouldEqual, expected) - So(fixtures[2], ShouldBeNil) + So(fixtures[2].(float64), ShouldEqual, expectedEarly) + So(fixtures[3].(float64), ShouldEqual, expectedEarly) + So(fixtures[4], ShouldBeNil) }) }) diff --git a/public/app/features/annotations/editor_ctrl.ts b/public/app/features/annotations/editor_ctrl.ts index 169e2e4c2bb..34b9635ec85 100644 --- a/public/app/features/annotations/editor_ctrl.ts +++ b/public/app/features/annotations/editor_ctrl.ts @@ -70,6 +70,10 @@ export class AnnotationsEditorCtrl { this.mode = 'list'; } + move(index, dir) { + _.move(this.annotations, index, index + dir); + } + add() { this.annotations.push(this.currentAnnotation); this.reset(); diff --git a/public/app/features/annotations/partials/editor.html b/public/app/features/annotations/partials/editor.html index 289f368ad0e..65ee7e52bd0 100644 --- a/public/app/features/annotations/partials/editor.html +++ b/public/app/features/annotations/partials/editor.html @@ -21,7 +21,7 @@ - +   {{annotation.name}} @@ -33,8 +33,8 @@ {{annotation.datasource || 'Default'}} - - + + diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index 03bf65afc6e..290e587eace 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactGridLayout from 'react-grid-layout-grafana'; +import ReactGridLayout from 'react-grid-layout'; import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants'; import { DashboardPanel } from './DashboardPanel'; import { DashboardModel } from '../dashboard_model'; diff --git a/public/app/features/dashboard/save_provisioned_modal.ts b/public/app/features/dashboard/save_provisioned_modal.ts index ba96ce0b0b9..3f2dcd0f57b 100644 --- a/public/app/features/dashboard/save_provisioned_modal.ts +++ b/public/app/features/dashboard/save_provisioned_modal.ts @@ -48,7 +48,7 @@ export class SaveProvisionedDashboardModalCtrl { constructor(dashboardSrv) { this.dash = dashboardSrv.getCurrent().getSaveModelClone(); delete this.dash.id; - this.dashboardJson = JSON.stringify(this.dash, null, 2); + this.dashboardJson = angular.toJson(this.dash, true); } save() { diff --git a/public/app/features/dashboard/settings/settings.ts b/public/app/features/dashboard/settings/settings.ts index 5acbbcf29c5..457cac5af72 100755 --- a/public/app/features/dashboard/settings/settings.ts +++ b/public/app/features/dashboard/settings/settings.ts @@ -2,6 +2,7 @@ import { coreModule, appEvents, contextSrv } from 'app/core/core'; import { DashboardModel } from '../dashboard_model'; import $ from 'jquery'; import _ from 'lodash'; +import angular from 'angular'; import config from 'app/core/config'; export class SettingsCtrl { @@ -118,7 +119,7 @@ export class SettingsCtrl { this.viewId = this.$location.search().editview; if (this.viewId) { - this.json = JSON.stringify(this.dashboard.getSaveModelClone(), null, 2); + this.json = angular.toJson(this.dashboard.getSaveModelClone(), true); } if (this.viewId === 'settings' && this.dashboard.meta.canMakeEditable) { diff --git a/public/app/plugins/datasource/graphite/datasource.ts b/public/app/plugins/datasource/graphite/datasource.ts index 0b79673a14c..bc1c5722c3f 100644 --- a/public/app/plugins/datasource/graphite/datasource.ts +++ b/public/app/plugins/datasource/graphite/datasource.ts @@ -50,11 +50,11 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv data: params.join('&'), headers: { 'Content-Type': 'application/x-www-form-urlencoded', - 'X-Dashboard-Id': options.dashboardId, // enables distributed tracing in ds_proxy - 'X-Panel-Id': options.panelId, // enables distributed tracing in ds_proxy }, }; + this.addTracingHeaders(httpOptions, options); + if (options.panelId) { httpOptions.requestId = this.name + '.panelId.' + options.panelId; } @@ -62,6 +62,14 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv return this.doGraphiteRequest(httpOptions).then(this.convertDataPointsToMs); }; + this.addTracingHeaders = function(httpOptions, options) { + var proxyMode = !this.url.match(/^http/); + if (proxyMode) { + httpOptions.headers['X-Dashboard-Id'] = options.dashboardId; + httpOptions.headers['X-Panel-Id'] = options.panelId; + } + }; + this.convertDataPointsToMs = function(result) { if (!result || !result.data) { return []; diff --git a/public/app/plugins/datasource/graphite/specs/datasource.jest.ts b/public/app/plugins/datasource/graphite/specs/datasource.jest.ts index dac6c2252d8..f94378c57a6 100644 --- a/public/app/plugins/datasource/graphite/specs/datasource.jest.ts +++ b/public/app/plugins/datasource/graphite/specs/datasource.jest.ts @@ -9,16 +9,18 @@ describe('graphiteDatasource', () => { backendSrv: {}, $q: $q, templateSrv: new TemplateSrvStub(), + instanceSettings: { url: 'url', name: 'graphiteProd', jsonData: {} }, }; beforeEach(function() { - ctx.instanceSettings = { url: [''], name: 'graphiteProd', jsonData: {} }; + ctx.instanceSettings.url = '/api/datasources/proxy/1'; ctx.ds = new GraphiteDatasource(ctx.instanceSettings, ctx.$q, ctx.backendSrv, ctx.templateSrv); }); describe('When querying graphite with one target using query editor target spec', function() { let query = { panelId: 3, + dashboardId: 5, rangeRaw: { from: 'now-1h', to: 'now' }, targets: [{ target: 'prod1.count' }, { target: 'prod2.count' }], maxDataPoints: 500, @@ -40,8 +42,13 @@ describe('graphiteDatasource', () => { }); }); + it('X-Dashboard and X-Panel headers to be set!', () => { + expect(requestOptions.headers['X-Dashboard-Id']).toBe(5); + expect(requestOptions.headers['X-Panel-Id']).toBe(3); + }); + it('should generate the correct query', function() { - expect(requestOptions.url).toBe('/render'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/render'); }); it('should set unique requestId', function() { @@ -228,7 +235,7 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/tags'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/tags'); expect(requestOptions.params.expr).toEqual([]); expect(results).not.toBe(null); }); @@ -238,7 +245,7 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/tags'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/tags'); expect(requestOptions.params.expr).toEqual(['server=backend_01']); expect(results).not.toBe(null); }); @@ -248,7 +255,7 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/tags'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/tags'); expect(requestOptions.params.expr).toEqual(['server=backend_01']); expect(results).not.toBe(null); }); @@ -258,7 +265,7 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/values'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual([]); expect(results).not.toBe(null); @@ -269,7 +276,7 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/values'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual(['server=~backend*']); expect(results).not.toBe(null); @@ -280,7 +287,7 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/values'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual([]); expect(results).not.toBe(null); @@ -291,10 +298,46 @@ describe('graphiteDatasource', () => { results = data; }); - expect(requestOptions.url).toBe('/tags/autoComplete/values'); + expect(requestOptions.url).toBe('/api/datasources/proxy/1/tags/autoComplete/values'); expect(requestOptions.params.tag).toBe('server'); expect(requestOptions.params.expr).toEqual(['server=~backend*']); expect(results).not.toBe(null); }); }); }); + +function accessScenario(name, url, fn) { + describe('access scenario ' + name, function() { + let ctx: any = { + backendSrv: {}, + $q: $q, + templateSrv: new TemplateSrvStub(), + instanceSettings: { url: 'url', name: 'graphiteProd', jsonData: {} }, + }; + + let httpOptions = { + headers: {}, + }; + + describe('when using proxy mode', () => { + let options = { dashboardId: 1, panelId: 2 }; + + it('tracing headers should be added', () => { + ctx.instanceSettings.url = url; + var ds = new GraphiteDatasource(ctx.instanceSettings, ctx.$q, ctx.backendSrv, ctx.templateSrv); + ds.addTracingHeaders(httpOptions, options); + fn(httpOptions); + }); + }); + }); +} + +accessScenario('with proxy access', '/api/datasources/proxy/1', function(httpOptions) { + expect(httpOptions.headers['X-Dashboard-Id']).toBe(1); + expect(httpOptions.headers['X-Panel-Id']).toBe(2); +}); + +accessScenario('with direct access', 'http://localhost:8080', function(httpOptions) { + expect(httpOptions.headers['X-Dashboard-Id']).toBe(undefined); + expect(httpOptions.headers['X-Panel-Id']).toBe(undefined); +}); diff --git a/public/img/resize-handle-white.svg b/public/img/resize-handle-white.svg deleted file mode 100644 index 110ff8edfbb..00000000000 --- a/public/img/resize-handle-white.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/public/sass/components/_dashboard_grid.scss b/public/sass/components/_dashboard_grid.scss index aec08d72258..0a27df75164 100644 --- a/public/sass/components/_dashboard_grid.scss +++ b/public/sass/components/_dashboard_grid.scss @@ -1,4 +1,4 @@ -@import '~react-grid-layout-grafana/css/styles.css'; +@import '~react-grid-layout/css/styles.css'; @import '~react-resizable/css/styles.css'; .panel-in-fullscreen { @@ -44,11 +44,6 @@ border-right: 2px solid $gray-1; border-bottom: 2px solid $gray-1; } - // temp fix since we use old commit of grid component - // this can be removed when we revert to non fork grid component - .react-grid-item > .react-resizable-handle { - background-image: url('../img/resize-handle-white.svg'); - } } .theme-light { diff --git a/public/sass/components/_panel_singlestat.scss b/public/sass/components/_panel_singlestat.scss index 33a956a0244..af11de3b835 100644 --- a/public/sass/components/_panel_singlestat.scss +++ b/public/sass/components/_panel_singlestat.scss @@ -7,13 +7,14 @@ .singlestat-panel-value-container { line-height: 1; - display: table-cell; - vertical-align: middle; - text-align: center; - position: relative; + position: absolute; z-index: 1; font-size: 3em; font-weight: bold; + margin: 0; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } .singlestat-panel-prefix { diff --git a/scripts/webpack/webpack.hot.js b/scripts/webpack/webpack.hot.js index e0f078b71fb..9a2845372ea 100644 --- a/scripts/webpack/webpack.hot.js +++ b/scripts/webpack/webpack.hot.js @@ -26,6 +26,8 @@ module.exports = merge(common, { extensions: ['.scss', '.ts', '.tsx', '.es6', '.js', '.json', '.svg', '.woff2', '.png'], }, + devtool: 'eval-source-map', + devServer: { publicPath: '/public/build/', hot: true, diff --git a/yarn.lock b/yarn.lock index cdd71528baa..f58731040c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -405,17 +405,17 @@ angular-native-dragdrop@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/angular-native-dragdrop/-/angular-native-dragdrop-1.2.2.tgz#d646c6b75b131c48073c3f6e36a225b2726d8bae" -angular-route@^1.6.6: - version "1.6.10" - resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.6.10.tgz#4247a32eab19495624623e96c1626dfba17ebf21" +angular-route@1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.6.6.tgz#8c11748aa195c717b1b615a7e746442bfc7c61f4" -angular-sanitize@^1.6.6: - version "1.6.10" - resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.6.10.tgz#635a362afb2dd040179f17d3a5455962b2c1918f" +angular-sanitize@1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.6.6.tgz#0fd065a19931517fbece66596d325d72b6e06041" -angular@^1.6.6: - version "1.6.10" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.10.tgz#eed3080a34d29d0f681ff119b18ce294e3f74826" +angular@1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.6.6.tgz#fd5a3cfb437ce382d854ee01120797978527cb64" ansi-align@^2.0.0: version "2.0.0" @@ -8898,22 +8898,22 @@ react-dom@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" -"react-draggable@^2.2.6 || ^3.0.3", react-draggable@^3.0.3: +react-draggable@3.x, "react-draggable@^2.2.6 || ^3.0.3": version "3.0.5" resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.0.5.tgz#c031e0ed4313531f9409d6cd84c8ebcec0ddfe2d" dependencies: classnames "^2.2.5" prop-types "^15.6.0" -react-grid-layout-grafana@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/react-grid-layout-grafana/-/react-grid-layout-grafana-0.16.0.tgz#12242153fcd0bb80a26af8e41694bc2fde788b3a" +react-grid-layout@0.16.6: + version "0.16.6" + resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-0.16.6.tgz#9b2407a2b946c2260ebaf66f13b556e1da4efeb2" dependencies: classnames "2.x" lodash.isequal "^4.0.0" prop-types "15.x" - react-draggable "^3.0.3" - react-resizable "^1.7.5" + react-draggable "3.x" + react-resizable "1.x" react-highlight-words@^0.10.0: version "0.10.0" @@ -8973,7 +8973,7 @@ react-reconciler@^0.7.0: object-assign "^4.1.1" prop-types "^15.6.0" -react-resizable@^1.7.5: +react-resizable@1.x: version "1.7.5" resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-1.7.5.tgz#83eb75bb3684da6989bbbf4f826e1470f0af902e" dependencies: