From ec0fe1193980c3aecddacece20d662731705e1b9 Mon Sep 17 00:00:00 2001 From: NighterMan Date: Sun, 13 Jan 2019 04:09:51 +0100 Subject: [PATCH 01/43] pushover: add support for attaching images (closes #10780) Use native pushover native attachment support to deliver images --- pkg/services/alerting/notifiers/pushover.go | 144 ++++++++++++++++---- 1 file changed, 120 insertions(+), 24 deletions(-) diff --git a/pkg/services/alerting/notifiers/pushover.go b/pkg/services/alerting/notifiers/pushover.go index 55dc02c5f4a..6581328b745 100644 --- a/pkg/services/alerting/notifiers/pushover.go +++ b/pkg/services/alerting/notifiers/pushover.go @@ -1,8 +1,11 @@ package notifiers import ( + "bytes" "fmt" - "net/url" + "io" + "mime/multipart" + "os" "strconv" "github.com/grafana/grafana/pkg/bus" @@ -91,6 +94,7 @@ func NewPushoverNotifier(model *m.AlertNotification) (alerting.Notifier, error) retry, _ := strconv.Atoi(model.Settings.Get("retry").MustString()) expire, _ := strconv.Atoi(model.Settings.Get("expire").MustString()) sound := model.Settings.Get("sound").MustString() + uploadImage := model.Settings.Get("uploadImage").MustBool(true) if userKey == "" { return nil, alerting.ValidationError{Reason: "User key not given"} @@ -107,6 +111,7 @@ func NewPushoverNotifier(model *m.AlertNotification) (alerting.Notifier, error) Expire: expire, Device: device, Sound: sound, + Upload: uploadImage, log: log.New("alerting.notifier.pushover"), }, nil } @@ -120,6 +125,7 @@ type PushoverNotifier struct { Expire int Device string Sound string + Upload bool log log.Logger } @@ -140,38 +146,22 @@ func (this *PushoverNotifier) Notify(evalContext *alerting.EvalContext) error { if evalContext.Error != nil { message += fmt.Sprintf("\nError message: %s", evalContext.Error.Error()) } - if evalContext.ImagePublicUrl != "" { - message += fmt.Sprintf("\nShow graph image", evalContext.ImagePublicUrl) - } + if message == "" { message = "Notification message missing (Set a notification message to replace this text.)" } - q := url.Values{} - q.Add("user", this.UserKey) - q.Add("token", this.ApiToken) - q.Add("priority", strconv.Itoa(this.Priority)) - if this.Priority == 2 { - q.Add("retry", strconv.Itoa(this.Retry)) - q.Add("expire", strconv.Itoa(this.Expire)) + headers, uploadBody, err := this.genPushoverBody(evalContext, message, ruleUrl) + if err != nil { + this.log.Error("Failed to generate body for pushover", "error", err) + return err } - if this.Device != "" { - q.Add("device", this.Device) - } - if this.Sound != "default" { - q.Add("sound", this.Sound) - } - q.Add("title", evalContext.GetNotificationTitle()) - q.Add("url", ruleUrl) - q.Add("url_title", "Show dashboard with alert") - q.Add("message", message) - q.Add("html", "1") cmd := &m.SendWebhookSync{ Url: PUSHOVER_ENDPOINT, HttpMethod: "POST", - HttpHeader: map[string]string{"Content-Type": "application/x-www-form-urlencoded"}, - Body: q.Encode(), + HttpHeader: headers, + Body: uploadBody.String(), } if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil { @@ -181,3 +171,109 @@ func (this *PushoverNotifier) Notify(evalContext *alerting.EvalContext) error { return nil } + +func (this *PushoverNotifier) genPushoverBody(evalContext *alerting.EvalContext, message string, ruleUrl string) (map[string]string, bytes.Buffer, error) { + var b bytes.Buffer + var err error + w := multipart.NewWriter(&b) + + // Add image only if requested and available + if this.Upload && evalContext.ImageOnDiskPath != "" { + f, err := os.Open(evalContext.ImageOnDiskPath) + if err != nil { + return nil, b, err + } + defer f.Close() + + fw, err := w.CreateFormFile("attachment", evalContext.ImageOnDiskPath) + if err != nil { + return nil, b, err + } + + _, err = io.Copy(fw, f) + if err != nil { + return nil, b, err + } + } + + // Add the user token + err = w.WriteField("user", this.UserKey) + if err != nil { + return nil, b, err + } + + // Add the api token + err = w.WriteField("token", this.ApiToken) + if err != nil { + return nil, b, err + } + + // Add priority + err = w.WriteField("priority", strconv.Itoa(this.Priority)) + if err != nil { + return nil, b, err + } + + if this.Priority == 2 { + err = w.WriteField("retry", strconv.Itoa(this.Retry)) + if err != nil { + return nil, b, err + } + + err = w.WriteField("expire", strconv.Itoa(this.Expire)) + if err != nil { + return nil, b, err + } + } + + // Add device + if this.Device != "" { + err = w.WriteField("device", this.Device) + if err != nil { + return nil, b, err + } + } + + // Add sound + if this.Sound != "default" { + err = w.WriteField("sound", this.Sound) + if err != nil { + return nil, b, err + } + } + + // Add title + err = w.WriteField("title", evalContext.GetNotificationTitle()) + if err != nil { + return nil, b, err + } + + // Add URL + err = w.WriteField("url", ruleUrl) + if err != nil { + return nil, b, err + } + // Add URL title + err = w.WriteField("url_title", "Show dashboard with alert") + if err != nil { + return nil, b, err + } + + // Add message + err = w.WriteField("message", message) + if err != nil { + return nil, b, err + } + + // Mark as html message + err = w.WriteField("html", "1") + if err != nil { + return nil, b, err + } + + w.Close() + headers := map[string]string{ + "Content-Type": w.FormDataContentType(), + } + return headers, b, nil +} From 010f902003685a652fc7b37a9e6e27d7792e6b41 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 29 Jan 2019 15:34:28 +0100 Subject: [PATCH 02/43] Import queries before datasource is changed --- .../app/features/explore/state/actionTypes.ts | 14 +++- public/app/features/explore/state/actions.ts | 84 ++++++++++++------- public/app/features/explore/state/reducers.ts | 12 ++- .../datasource/loki/language_provider.ts | 1 + 4 files changed, 77 insertions(+), 34 deletions(-) diff --git a/public/app/features/explore/state/actionTypes.ts b/public/app/features/explore/state/actionTypes.ts index 757f946f37a..3678aeebe7a 100644 --- a/public/app/features/explore/state/actionTypes.ts +++ b/public/app/features/explore/state/actionTypes.ts @@ -43,6 +43,7 @@ export enum ActionTypes { ToggleTable = 'explore/TOGGLE_TABLE', UpdateDatasourceInstance = 'explore/UPDATE_DATASOURCE_INSTANCE', ResetExplore = 'explore/RESET_EXPLORE', + SetInitialQueries = 'explore/SET_INITIAL_QUERIES', } export interface AddQueryRowAction { @@ -142,7 +143,7 @@ export interface LoadDatasourceSuccessAction { StartPage?: any; datasourceInstance: any; history: HistoryItem[]; - initialQueries: DataQuery[]; + // initialQueries: DataQuery[]; logsHighlighterExpressions?: any[]; showingStartPage: boolean; supportsGraph: boolean; @@ -283,6 +284,14 @@ export interface ResetExploreAction { payload: {}; } +export interface SetInitialQueriesAction { + type: ActionTypes.SetInitialQueries; + payload: { + exploreId: ExploreId; + queries: DataQuery[]; + }; +} + export type Action = | AddQueryRowAction | ChangeQueryAction @@ -312,4 +321,5 @@ export type Action = | ToggleLogsAction | ToggleTableAction | UpdateDatasourceInstanceAction - | ResetExploreAction; + | ResetExploreAction + | SetInitialQueriesAction; diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index 40a8f367672..2c1c2a060d6 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -53,6 +53,7 @@ import { QueryTransactionStartAction, ScanStopAction, UpdateDatasourceInstanceAction, + SetInitialQueriesAction, } from './actionTypes'; type ThunkResult = ThunkAction; @@ -69,10 +70,14 @@ export function addQueryRow(exploreId: ExploreId, index: number): AddQueryRowAct * Loads a new datasource identified by the given name. */ export function changeDatasource(exploreId: ExploreId, datasource: string): ThunkResult { - return async dispatch => { - const instance = await getDatasourceSrv().get(datasource); - dispatch(updateDatasourceInstance(exploreId, instance)); - dispatch(loadDatasource(exploreId, instance)); + return async (dispatch, getState) => { + const newDataSourceInstance = await getDatasourceSrv().get(datasource); + const currentDataSourceInstance = getState().explore[exploreId].datasourceInstance; + const modifiedQueries = getState().explore[exploreId].modifiedQueries; + + dispatch(importQueries(exploreId, modifiedQueries, currentDataSourceInstance, newDataSourceInstance)); + dispatch(updateDatasourceInstance(exploreId, newDataSourceInstance)); + dispatch(loadDatasource(exploreId, newDataSourceInstance)); }; } @@ -174,6 +179,7 @@ export function initializeExplore( if (exploreDatasources.length >= 1) { let instance; + if (datasourceName) { try { instance = await getDatasourceSrv().get(datasourceName); @@ -185,6 +191,7 @@ export function initializeExplore( if (!instance) { instance = await getDatasourceSrv().get(); } + dispatch(updateDatasourceInstance(exploreId, instance)); dispatch(loadDatasource(exploreId, instance)); } else { @@ -224,7 +231,10 @@ export const loadDatasourceMissing = (exploreId: ExploreId): LoadDatasourceMissi /** * Start the async process of loading a datasource to display a loading indicator */ -export const loadDatasourcePending = (exploreId: ExploreId, requestedDatasourceName: string): LoadDatasourcePendingAction => ({ +export const loadDatasourcePending = ( + exploreId: ExploreId, + requestedDatasourceName: string +): LoadDatasourcePendingAction => ({ type: ActionTypes.LoadDatasourcePending, payload: { exploreId, @@ -232,6 +242,16 @@ export const loadDatasourcePending = (exploreId: ExploreId, requestedDatasourceN }, }); +export const setInitialQueries = (exploreId: ExploreId, queries: DataQuery[]): SetInitialQueriesAction => { + return { + type: ActionTypes.SetInitialQueries, + payload: { + exploreId, + queries, + }, + }; +}; + /** * Datasource loading was successfully completed. The instance is stored in the state as well in case we need to * run datasource-specific code. Existing queries are imported to the new datasource if an importer exists, @@ -239,8 +259,8 @@ export const loadDatasourcePending = (exploreId: ExploreId, requestedDatasourceN */ export const loadDatasourceSuccess = ( exploreId: ExploreId, - instance: any, - queries: DataQuery[] + instance: any + // queries: DataQuery[] ): LoadDatasourceSuccessAction => { // Capabilities const supportsGraph = instance.meta.metrics; @@ -261,7 +281,7 @@ export const loadDatasourceSuccess = ( StartPage, datasourceInstance: instance, history, - initialQueries: queries, + // initialQueries: queries, showingStartPage: Boolean(StartPage), supportsGraph, supportsLogs, @@ -286,6 +306,29 @@ export function updateDatasourceInstance( }; } +export function importQueries( + exploreId: ExploreId, + queries: DataQuery[], + sourceDataSource: DataSourceApi, + targetDataSource: DataSourceApi +) { + return async dispatch => { + let importedQueries = queries; + // Check if queries can be imported from previously selected datasource + if (sourceDataSource.meta.id === targetDataSource.meta.id) { + // Keep same queries if same type of datasource + importedQueries = [...queries]; + } else if (targetDataSource.importQueries) { + // Datasource-specific importers + importedQueries = await targetDataSource.importQueries(queries, sourceDataSource.meta); + } else { + // Default is blank queries + importedQueries = ensureQueries(); + } + dispatch(setInitialQueries(exploreId, importedQueries)); + }; +} + /** * Main action to asynchronously load a datasource. Dispatches lots of smaller actions for feedback. */ @@ -319,21 +362,6 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi): T } // Check if queries can be imported from previously selected datasource - const queries = getState().explore[exploreId].modifiedQueries; - let importedQueries = queries; - const origin = getState().explore[exploreId].datasourceInstance; - if (origin) { - if (origin.meta.id === instance.meta.id) { - // Keep same queries if same type of datasource - importedQueries = [...queries]; - } else if (instance.importQueries) { - // Datasource-specific importers - importedQueries = await instance.importQueries(queries, origin.meta); - } else { - // Default is blank queries - importedQueries = ensureQueries(); - } - } if (datasourceName !== getState().explore[exploreId].requestedDatasourceName) { // User already changed datasource again, discard results @@ -341,12 +369,12 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi): T } // Reset edit state with new queries - const nextQueries = importedQueries.map((q, i) => ({ - ...importedQueries[i], - ...generateEmptyQuery(i), - })); + // const nextQueries = importedQueries.map((q, i) => ({ + // ...importedQueries[i], + // ...generateEmptyQuery(i), + // })); - dispatch(loadDatasourceSuccess(exploreId, instance, nextQueries)); + dispatch(loadDatasourceSuccess(exploreId, instance /*, nextQueries*/)); dispatch(runQueries(exploreId)); }; } diff --git a/public/app/features/explore/state/reducers.ts b/public/app/features/explore/state/reducers.ts index ad5ef8b5a71..c89307e4376 100644 --- a/public/app/features/explore/state/reducers.ts +++ b/public/app/features/explore/state/reducers.ts @@ -203,7 +203,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => { StartPage, datasourceInstance, history, - initialQueries, showingStartPage, supportsGraph, supportsLogs, @@ -217,7 +216,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => { StartPage, datasourceInstance, history, - initialQueries, showingStartPage, supportsGraph, supportsLogs, @@ -226,7 +224,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => { datasourceMissing: false, datasourceError: null, logsHighlighterExpressions: undefined, - modifiedQueries: initialQueries.slice(), queryTransactions: [], }; } @@ -295,7 +292,6 @@ export const itemReducer = (state, action: Action): ExploreItemState => { // Append new transaction const nextQueryTransactions: QueryTransaction[] = [...remainingTransactions, transaction]; - return { ...state, queryTransactions: nextQueryTransactions, @@ -417,6 +413,14 @@ export const itemReducer = (state, action: Action): ExploreItemState => { return { ...state, ...results, queryTransactions: nextQueryTransactions, showingTable }; } + + case ActionTypes.SetInitialQueries: { + return { + ...state, + initialQueries: action.payload.queries, + modifiedQueries: action.payload.queries.slice(), + }; + } } return state; diff --git a/public/app/plugins/datasource/loki/language_provider.ts b/public/app/plugins/datasource/loki/language_provider.ts index 631e61277b8..8b50eeaad53 100644 --- a/public/app/plugins/datasource/loki/language_provider.ts +++ b/public/app/plugins/datasource/loki/language_provider.ts @@ -177,6 +177,7 @@ export default class LokiLanguageProvider extends LanguageProvider { return queries.map(query => ({ refId: query.refId, expr: '', + key: query.key, })); } From 8ea72eeaf7c0de96dc9565bd1e49c6a2352b79c0 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 29 Jan 2019 15:35:32 +0100 Subject: [PATCH 03/43] Remove commented code --- public/app/features/explore/state/actionTypes.ts | 1 - public/app/features/explore/state/actions.ts | 12 ++---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/public/app/features/explore/state/actionTypes.ts b/public/app/features/explore/state/actionTypes.ts index 3678aeebe7a..7c7ab40756f 100644 --- a/public/app/features/explore/state/actionTypes.ts +++ b/public/app/features/explore/state/actionTypes.ts @@ -143,7 +143,6 @@ export interface LoadDatasourceSuccessAction { StartPage?: any; datasourceInstance: any; history: HistoryItem[]; - // initialQueries: DataQuery[]; logsHighlighterExpressions?: any[]; showingStartPage: boolean; supportsGraph: boolean; diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index 2c1c2a060d6..f9092fb4206 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -259,8 +259,7 @@ export const setInitialQueries = (exploreId: ExploreId, queries: DataQuery[]): S */ export const loadDatasourceSuccess = ( exploreId: ExploreId, - instance: any - // queries: DataQuery[] + instance: any, ): LoadDatasourceSuccessAction => { // Capabilities const supportsGraph = instance.meta.metrics; @@ -281,7 +280,6 @@ export const loadDatasourceSuccess = ( StartPage, datasourceInstance: instance, history, - // initialQueries: queries, showingStartPage: Boolean(StartPage), supportsGraph, supportsLogs, @@ -368,13 +366,7 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi): T return; } - // Reset edit state with new queries - // const nextQueries = importedQueries.map((q, i) => ({ - // ...importedQueries[i], - // ...generateEmptyQuery(i), - // })); - - dispatch(loadDatasourceSuccess(exploreId, instance /*, nextQueries*/)); + dispatch(loadDatasourceSuccess(exploreId, instance)); dispatch(runQueries(exploreId)); }; } From 9ddbfed730ced7d0825db71d96a311842a2d4faa Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Tue, 29 Jan 2019 15:52:36 +0100 Subject: [PATCH 04/43] Wait for queries to be imported before proceeding with datasource change --- public/app/features/explore/state/actions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index f9092fb4206..3d2896f38d3 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -75,7 +75,8 @@ export function changeDatasource(exploreId: ExploreId, datasource: string): Thun const currentDataSourceInstance = getState().explore[exploreId].datasourceInstance; const modifiedQueries = getState().explore[exploreId].modifiedQueries; - dispatch(importQueries(exploreId, modifiedQueries, currentDataSourceInstance, newDataSourceInstance)); + await dispatch(importQueries(exploreId, modifiedQueries, currentDataSourceInstance, newDataSourceInstance)); + dispatch(updateDatasourceInstance(exploreId, newDataSourceInstance)); dispatch(loadDatasource(exploreId, newDataSourceInstance)); }; From 13579b76d9a11a729629182eb621f00ec973a542 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 28 Jan 2019 18:43:41 +0100 Subject: [PATCH 05/43] docs: wip - what's new for 6.0 --- .../features/datasources/stackdriver.md | 4 +- docs/sources/features/explore/index.md | 17 ----- docs/sources/guides/whats-new-in-v5-3.md | 2 +- docs/sources/guides/whats-new-in-v6-0.md | 75 +++++++++++++++++++ 4 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 docs/sources/guides/whats-new-in-v6-0.md diff --git a/docs/sources/features/datasources/stackdriver.md b/docs/sources/features/datasources/stackdriver.md index 2c14d897d8e..d1cc1088276 100644 --- a/docs/sources/features/datasources/stackdriver.md +++ b/docs/sources/features/datasources/stackdriver.md @@ -12,8 +12,8 @@ weight = 11 # Using Google Stackdriver in Grafana -> Only available in Grafana v5.3+. -> The datasource is currently a beta feature and is subject to change. +> Available as a beta feature in Grafana v5.3.x and v5.4.x. +> Officially released in Grafana v6.0.0 Grafana ships with built-in support for Google Stackdriver. Just add it as a datasource and you are ready to build dashboards for your Stackdriver metrics. diff --git a/docs/sources/features/explore/index.md b/docs/sources/features/explore/index.md index 0ba3d2f7d44..6580bcf217f 100644 --- a/docs/sources/features/explore/index.md +++ b/docs/sources/features/explore/index.md @@ -27,23 +27,6 @@ For infrastructure monitoring and incident response, you no longer need to switc If you just want to explore your data and do not want to create a dashboard then Explore makes this much easier. Explore will show the results as both a graph and a table enabling you to see trends in the data and more detail at the same time (if the datasource supports both graph and table data). -## Turning the Explore Feature On - -Explore will be officially released in Grafana 6.0. It is however already in the latest nightly builds of Grafana and can be turned using a feature flag in the config file. Restart Grafana after making the config file change. - -```ini -[explore] -# Enable the Explore section -enabled = true -``` - -Or if using docker: - -```bash -docker pull grafana/grafana:master -docker run --name grafana -p 3000:3000 -e "GF_EXPLORE_ENABLED=true" grafana/grafana:master -``` - ## How to Start Exploring There is a new Explore icon on the menu bar to the left. This opens a new empty Explore tab. diff --git a/docs/sources/guides/whats-new-in-v5-3.md b/docs/sources/guides/whats-new-in-v5-3.md index 10592f51648..abd83e7e002 100644 --- a/docs/sources/guides/whats-new-in-v5-3.md +++ b/docs/sources/guides/whats-new-in-v5-3.md @@ -26,7 +26,7 @@ Grafana v5.3 brings new features, many enhancements and bug fixes. This article {{< docs-imagebox img="/img/docs/v53/stackdriver-with-heatmap.png" max-width= "600px" class="docs-image--no-shadow docs-image--right" >}} -Grafana v5.3 ships with built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) and enables you to visualize your Stackdriver metrics in Grafana. +Grafana v5.3 ships with built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) and enables you to visualize your Stackdriver metrics in Grafana. Getting started with the plugin is easy. Simply create a GCE Service account that has access to the Stackdriver API scope, download the Service Account key file from Google and upload it on the Stackdriver datasource config page in Grafana and you should have a secure server-to-server authentication setup. Like other core plugins, Stackdriver has built-in support for alerting. It also comes with support for heatmaps and basic variables. diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md new file mode 100644 index 00000000000..70117148dc9 --- /dev/null +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -0,0 +1,75 @@ ++++ +title = "What's New in Grafana v6.0" +description = "Feature & improvement highlights for Grafana v6.0" +keywords = ["grafana", "new", "documentation", "6.0"] +type = "docs" +[menu.docs] +name = "Version 6.0" +identifier = "v6.0" +parent = "whatsnew" +weight = -11 ++++ + +# What's New in Grafana v6.0 + +This update to Grafana introduces a new way of exploring your data, support for log data and tons of other features. + +The main highlights are: + +- The new query-focused [Explore]({{< relref "#explore" >}}) workflow for troubleshooting and/or for data exploration. +- [Support for Grafana Loki]({{< relref "#explore-and-grafana-loki" >}}) - a new open source log aggregation system from Grafana Labs. +- [Easily Switch Visualization with the Panel Edit UX Update]({{< relref "#easily-switch-visualization-with-panel-edit-ux-update" >}}) +- [Google Stackdriver Datasource]({{< relref "#google-stackdriver-datasource" >}}) is out of beta and is officially released. +- The [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource + +### Explore + +Grafana's dashboard UI is all about building dashboards for visualization. **Explore** strips away all the dashboard and panel options so that you can focus on the query. Iterate until you have a working query and then think about building a dashboard. + +For infrastructure monitoring and incident response, you no longer need to switch to other tools to debug what went wrong. **Explore** allows you to dig deeper into your metrics and logs to find the cause. Grafana's new logging datasource, [Loki](https://github.com/grafana/loki) is tightly integrated into Explore and allows you to correlate metrics and logs by viewing them side-by-side. + +{{< docs-imagebox img="/img/docs/v60/explore_split.png" class="docs-image--no-shadow" caption="Screenshot of the new Explore option in the panel menu" >}} + +**Explore** is a new paradigm for Grafana. It creates a new interactive debugging workflow that integrates two pillars of observability - metrics and logs. + +#### Explore and Prometheus + +The first version of Explore features a [custom querying experience for Prometheus](/features/explore/#prometheus-specific-features) and as well as an integration between Prometheus and Grafana Loki (see more about Loki below). + +### Explore and Grafana Loki + +The Explore feature allows you to combine metric queries and log queries. The first log integration is for the new open source log aggregation system from Grafana Labs called [Grafana Loki](https://github.com/grafana/loki). + +Loki a horizontally-scalable, highly-available, multi-tenant log aggregation system inspired by Prometheus. It is designed to be very cost effective, as it does not index the contents of the logs, but rather a set of labels for each log stream. The logs from Loki are queried in a similar way to querying with label selectors in Prometheus. It uses labels to group log streams which can be made to match up with your Prometheus labels. + +Read more about Grafana Loki [here](https://github.com/grafana/loki) or [Grafana Labs hosted Loki](https://grafana.com/loki). + +The Explore feature allows you to query logs and features a new log panel. + +{{< docs-imagebox img="/img/docs/v60/explore_loki.png" class="docs-image--no-shadow" caption="Explore Loki Log Streams" >}} + +In the near future, we will be adding support for other log sources to Explore and the next planned integration is ElasticSearch logs. + +### Easily Switch Visualization with Panel Edit UX Update + +The UX for editing a panel has gotten an update and the major feature is being able to easily switch visualization using the new Visualization option. This means you can quickly switch from a Graph visualization to a Table visualization or any other visualization without having to create a new panel. + +### Google Stackdriver Datasource + +Built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) is officially released in Grafana 6.0. Beta support was added in Grafana 5.3 and we have added lots of improvements since then. + +To get started read the guide: [Using Google Stackdriver in Grafana](/features/datasources/stackdriver/). + +### Azure Monitor Datasource + +One of the goals of the Grafana v6.0 release is to add support for the three major clouds. Amazon Cloudwatch has been a core datasource for years and Google Stackdriver is also now supported. We developed an external plugin for Azure Monitor last year and for this release the [plugin](https://grafana.com/plugins/grafana-azure-monitor-datasource) is being moved into Grafana to be one of the built-in datasources. For users of the external plugin, Grafana will automatically start using the built-in version. As a core datasource, the Azure Monitor datasource will get alerting support for the official 6.0 release. + +The Azure Monitor datasource integrates four Azure services with Grafana - Azure Monitor, Azure Log Analytics, Azure Application Insights and Azure Application Insights Analytics. + +#### Technical Work - moving from Angular to React + +The Grafana team is putting a huge amount of work into converting the frontend code in Grafana from Angular to React. Currently, all external plugins for Grafana are written in Angular but we are planning to also support plugins written in React very soon. + +## Changelog + +Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list of new features, changes, and bug fixes. From 368494bb16d7a3912eb698685b6b85446185c601 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Wed, 30 Jan 2019 00:25:32 +0100 Subject: [PATCH 06/43] docs: update to what's new --- docs/sources/guides/whats-new-in-v6-0.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 70117148dc9..57bd9055032 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -66,6 +66,14 @@ One of the goals of the Grafana v6.0 release is to add support for the three maj The Azure Monitor datasource integrates four Azure services with Grafana - Azure Monitor, Azure Log Analytics, Azure Application Insights and Azure Application Insights Analytics. +### Other features + +- The ElasticSearch datasource now supports [bucket script pipeline aggregations](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-bucket-script-aggregation.html). This gives the ability to do per bucket computations like the difference or ratio between two metrics. + +- The way session storage works has been refactored to be more secure and to be more performant by doing fewer writes to the database. + +- Support for Google Hangouts Chat alert notifications + #### Technical Work - moving from Angular to React The Grafana team is putting a huge amount of work into converting the frontend code in Grafana from Angular to React. Currently, all external plugins for Grafana are written in Angular but we are planning to also support plugins written in React very soon. From d746df485c54856480ab8ffa21ff49ada32ad9f2 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Wed, 30 Jan 2019 09:36:23 +0100 Subject: [PATCH 07/43] Add missing code --- public/app/features/explore/state/actions.ts | 10 +++++++--- .../app/plugins/datasource/loki/language_provider.ts | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index 3d2896f38d3..1b7461a41e1 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -324,7 +324,13 @@ export function importQueries( // Default is blank queries importedQueries = ensureQueries(); } - dispatch(setInitialQueries(exploreId, importedQueries)); + + const nextQueries = importedQueries.map((q, i) => ({ + ...importedQueries[i], + ...generateEmptyQuery(i), + })); + + dispatch(setInitialQueries(exploreId, nextQueries)); }; } @@ -360,8 +366,6 @@ export function loadDatasource(exploreId: ExploreId, instance: DataSourceApi): T instance.init(); } - // Check if queries can be imported from previously selected datasource - if (datasourceName !== getState().explore[exploreId].requestedDatasourceName) { // User already changed datasource again, discard results return; diff --git a/public/app/plugins/datasource/loki/language_provider.ts b/public/app/plugins/datasource/loki/language_provider.ts index 8b50eeaad53..631e61277b8 100644 --- a/public/app/plugins/datasource/loki/language_provider.ts +++ b/public/app/plugins/datasource/loki/language_provider.ts @@ -177,7 +177,6 @@ export default class LokiLanguageProvider extends LanguageProvider { return queries.map(query => ({ refId: query.refId, expr: '', - key: query.key, })); } From 661de1efe1ed15e09e5f92e1b4d67a1a4670673c Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Wed, 30 Jan 2019 09:50:28 +0100 Subject: [PATCH 08/43] Rename SetInitialQueries action to QueriesImported --- public/app/features/explore/state/actionTypes.ts | 8 ++++---- public/app/features/explore/state/actions.ts | 8 ++++---- public/app/features/explore/state/reducers.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/app/features/explore/state/actionTypes.ts b/public/app/features/explore/state/actionTypes.ts index 7c7ab40756f..be7d5754bbe 100644 --- a/public/app/features/explore/state/actionTypes.ts +++ b/public/app/features/explore/state/actionTypes.ts @@ -43,7 +43,7 @@ export enum ActionTypes { ToggleTable = 'explore/TOGGLE_TABLE', UpdateDatasourceInstance = 'explore/UPDATE_DATASOURCE_INSTANCE', ResetExplore = 'explore/RESET_EXPLORE', - SetInitialQueries = 'explore/SET_INITIAL_QUERIES', + QueriesImported = 'explore/QueriesImported', } export interface AddQueryRowAction { @@ -283,8 +283,8 @@ export interface ResetExploreAction { payload: {}; } -export interface SetInitialQueriesAction { - type: ActionTypes.SetInitialQueries; +export interface QueriesImported { + type: ActionTypes.QueriesImported; payload: { exploreId: ExploreId; queries: DataQuery[]; @@ -321,4 +321,4 @@ export type Action = | ToggleTableAction | UpdateDatasourceInstanceAction | ResetExploreAction - | SetInitialQueriesAction; + | QueriesImported; diff --git a/public/app/features/explore/state/actions.ts b/public/app/features/explore/state/actions.ts index 1b7461a41e1..1a11b7fcac9 100644 --- a/public/app/features/explore/state/actions.ts +++ b/public/app/features/explore/state/actions.ts @@ -53,7 +53,7 @@ import { QueryTransactionStartAction, ScanStopAction, UpdateDatasourceInstanceAction, - SetInitialQueriesAction, + QueriesImported, } from './actionTypes'; type ThunkResult = ThunkAction; @@ -243,9 +243,9 @@ export const loadDatasourcePending = ( }, }); -export const setInitialQueries = (exploreId: ExploreId, queries: DataQuery[]): SetInitialQueriesAction => { +export const queriesImported = (exploreId: ExploreId, queries: DataQuery[]): QueriesImported => { return { - type: ActionTypes.SetInitialQueries, + type: ActionTypes.QueriesImported, payload: { exploreId, queries, @@ -330,7 +330,7 @@ export function importQueries( ...generateEmptyQuery(i), })); - dispatch(setInitialQueries(exploreId, nextQueries)); + dispatch(queriesImported(exploreId, nextQueries)); }; } diff --git a/public/app/features/explore/state/reducers.ts b/public/app/features/explore/state/reducers.ts index c89307e4376..eb67beee3b3 100644 --- a/public/app/features/explore/state/reducers.ts +++ b/public/app/features/explore/state/reducers.ts @@ -414,7 +414,7 @@ export const itemReducer = (state, action: Action): ExploreItemState => { return { ...state, ...results, queryTransactions: nextQueryTransactions, showingTable }; } - case ActionTypes.SetInitialQueries: { + case ActionTypes.QueriesImported: { return { ...state, initialQueries: action.payload.queries, From dfd87c3b9342f93a25bc5dcfb7beb469896bfafa Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 30 Jan 2019 09:54:08 +0100 Subject: [PATCH 09/43] whats new: provisioning for alert notifiers --- docs/sources/guides/whats-new-in-v6-0.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 57bd9055032..890de9aedf3 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -66,6 +66,10 @@ One of the goals of the Grafana v6.0 release is to add support for the three maj The Azure Monitor datasource integrates four Azure services with Grafana - Azure Monitor, Azure Log Analytics, Azure Application Insights and Azure Application Insights Analytics. +### Provisioning support for alert notifiers + +Grafana now added support for provisioning alert notifiers from configuration files. Allowing operators to provision notifiers without using the UI or the API. A new field called `uid` has been introduced which is a string identifier that the administrator can set themselves. Same kind of identifier used for dashboards since v5.0. This feature makes it possible to use the same notifier configuration in multiple environments and refer to notifiers in dashboard json by a string identifier instead of the numeric id which depends on insert order and how many notifiers that exists in the instance. + ### Other features - The ElasticSearch datasource now supports [bucket script pipeline aggregations](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-bucket-script-aggregation.html). This gives the ability to do per bucket computations like the difference or ratio between two metrics. From ae0b9692be583a0f1563ede523b5c5abd79c8cef Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Wed, 30 Jan 2019 10:39:42 +0100 Subject: [PATCH 10/43] first implementation --- .../app/features/dashboard/dashboard_model.ts | 4 + .../features/dashboard/dashgrid/DataPanel.tsx | 24 ++++-- .../dashboard/dashgrid/PanelChrome.tsx | 75 ++++++++++++------- public/app/features/dashboard/panel_model.ts | 4 +- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index 2ae2df0124b..4ffcc034193 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -810,6 +810,10 @@ export class DashboardModel { return this.getTimezone() === 'utc'; } + isSnapshot() { + return this.snapshot !== undefined; + } + getTimezone() { return this.timezone ? this.timezone : contextSrv.user.timezone; } diff --git a/public/app/features/dashboard/dashgrid/DataPanel.tsx b/public/app/features/dashboard/dashgrid/DataPanel.tsx index a681428f4bd..e15ff8d4c0d 100644 --- a/public/app/features/dashboard/dashgrid/DataPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DataPanel.tsx @@ -3,15 +3,12 @@ import React, { Component } from 'react'; import { Tooltip } from '@grafana/ui'; import ErrorBoundary from 'app/core/components/ErrorBoundary/ErrorBoundary'; - // Services -import { getDatasourceSrv, DatasourceSrv } from 'app/features/plugins/datasource_srv'; - +import { DatasourceSrv, getDatasourceSrv } from 'app/features/plugins/datasource_srv'; // Utils import kbn from 'app/core/utils/kbn'; - // Types -import { TimeRange, TimeSeries, LoadingState, DataQueryResponse, DataQueryOptions } from '@grafana/ui/src/types'; +import { DataQueryOptions, DataQueryResponse, LoadingState, TimeRange, TimeSeries } from '@grafana/ui/src/types'; const DEFAULT_PLUGIN_ERROR = 'Error in plugin'; @@ -32,6 +29,7 @@ export interface Props { minInterval?: string; maxDataPoints?: number; children: (r: RenderProps) => JSX.Element; + onDataResponse?: (data: DataQueryResponse) => void; } export interface State { @@ -85,7 +83,17 @@ export class DataPanel extends Component { } private issueQueries = async () => { - const { isVisible, queries, datasource, panelId, dashboardId, timeRange, widthPixels, maxDataPoints } = this.props; + const { + isVisible, + queries, + datasource, + panelId, + dashboardId, + timeRange, + widthPixels, + maxDataPoints, + onDataResponse, + } = this.props; if (!isVisible) { return; @@ -127,6 +135,10 @@ export class DataPanel extends Component { return; } + if (onDataResponse) { + onDataResponse(resp); + } + this.setState({ loading: LoadingState.Done, response: resp, diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 6b4ef48c32e..853139db803 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -21,6 +21,7 @@ import { TimeRange } from '@grafana/ui'; import variables from 'sass/_variables.scss'; import templateSrv from 'app/features/templating/template_srv'; +import { DataQueryResponse } from '@grafana/ui/src'; export interface Props { panel: PanelModel; @@ -83,16 +84,42 @@ export class PanelChrome extends PureComponent { return templateSrv.replace(value, this.props.panel.scopedVars, format); }; + onDataResponse = (dataQueryResponse: DataQueryResponse) => { + if (this.props.dashboard.isSnapshot()) { + this.props.panel.snapshotData = dataQueryResponse; + } + }; + get isVisible() { return !this.props.dashboard.otherPanelInFullscreen(this.props.panel); } + renderPanel(loading, timeSeries, width, height): JSX.Element { + const { panel, plugin } = this.props; + const { timeRange, renderCounter } = this.state; + const PanelComponent = plugin.exports.Panel; + + return ( +
+ +
+ ); + } + render() { - const { panel, dashboard, plugin } = this.props; - const { refreshCounter, timeRange, timeInfo, renderCounter } = this.state; + const { panel, dashboard } = this.props; + const { refreshCounter, timeRange, timeInfo } = this.state; const { datasource, targets, transparent } = panel; - const PanelComponent = plugin.exports.Panel; const containerClassNames = `panel-container panel-container--absolute ${transparent ? 'panel-transparent' : ''}`; return ( @@ -113,31 +140,23 @@ export class PanelChrome extends PureComponent { links={panel.links} /> - - {({ loading, timeSeries }) => { - return ( -
- -
- ); - }} -
+ {panel.snapshotData ? ( + this.renderPanel(false, panel.snapshotData, width, height) + ) : ( + + {({ loading, timeSeries }) => { + return this.renderPanel(loading, timeSeries, width, height); + }} + + )} ); }} diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index 6aded0da1d7..469884517b3 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -4,7 +4,7 @@ import _ from 'lodash'; // Types import { Emitter } from 'app/core/utils/emitter'; import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants'; -import { DataQuery } from '@grafana/ui/src/types'; +import { DataQuery, DataQueryResponse } from '@grafana/ui/src/types'; export interface GridPos { x: number; @@ -87,7 +87,7 @@ export class PanelModel { datasource: string; thresholds?: any; - snapshotData?: any; + snapshotData?: DataQueryResponse; timeFrom?: any; timeShift?: any; hideTimeOverride?: any; From 445b427fb6124d2424202a14725c69b1687afb58 Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 30 Jan 2019 10:52:42 +0100 Subject: [PATCH 11/43] whats new: note about session storage --- docs/sources/guides/whats-new-in-v6-0.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 890de9aedf3..bfd34033912 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -70,6 +70,12 @@ The Azure Monitor datasource integrates four Azure services with Grafana - Azure Grafana now added support for provisioning alert notifiers from configuration files. Allowing operators to provision notifiers without using the UI or the API. A new field called `uid` has been introduced which is a string identifier that the administrator can set themselves. Same kind of identifier used for dashboards since v5.0. This feature makes it possible to use the same notifier configuration in multiple environments and refer to notifiers in dashboard json by a string identifier instead of the numeric id which depends on insert order and how many notifiers that exists in the instance. +### Auth and session token improvements +The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. +If you are using `Auth proxy` for authentication the session storage will still be used but our goal is to remove this ASAP as well. + +This release will force all users to log in again since their previous token is not valid anymore. + ### Other features - The ElasticSearch datasource now supports [bucket script pipeline aggregations](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-bucket-script-aggregation.html). This gives the ability to do per bucket computations like the difference or ratio between two metrics. From 0b971d48c296628722a7d9c5a80676ba33a9cb78 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Wed, 30 Jan 2019 11:09:45 +0100 Subject: [PATCH 12/43] docs: add video link to what's new --- docs/sources/guides/whats-new-in-v6-0.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index bfd34033912..db9a76dedc5 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -54,6 +54,13 @@ In the near future, we will be adding support for other log sources to Explore a The UX for editing a panel has gotten an update and the major feature is being able to easily switch visualization using the new Visualization option. This means you can quickly switch from a Graph visualization to a Table visualization or any other visualization without having to create a new panel. +
+ +
+ ### Google Stackdriver Datasource Built-in support for [Google Stackdriver](https://cloud.google.com/stackdriver/) is officially released in Grafana 6.0. Beta support was added in Grafana 5.3 and we have added lots of improvements since then. From ce617bc02e6938d02824996ff2a6b16faf591bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 11:12:07 +0100 Subject: [PATCH 13/43] Minor updates to text and image placements --- docs/sources/guides/whats-new-in-v6-0.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 890de9aedf3..5b6a8cfbf58 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -22,34 +22,41 @@ The main highlights are: - [Google Stackdriver Datasource]({{< relref "#google-stackdriver-datasource" >}}) is out of beta and is officially released. - The [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource -### Explore +## Explore -Grafana's dashboard UI is all about building dashboards for visualization. **Explore** strips away all the dashboard and panel options so that you can focus on the query. Iterate until you have a working query and then think about building a dashboard. +{{< docs-imagebox img="/img/docs/v60/explore_prometheus.png" max-width="800px" class="docs-image--right" caption="Screenshot of the new Explore option in the panel menu" >}} + +Grafana's dashboard UI is all about building dashboards for visualization. **Explore** strips away all the dashboard and panel options so that you can focus on the query & metric exploration. Iterate until you have a working query and then think about building a dashboard. You can also jump from a dashboard panel into **Explore** and from there do some ad-hoc query exporation with the panel queries as a starting point. For infrastructure monitoring and incident response, you no longer need to switch to other tools to debug what went wrong. **Explore** allows you to dig deeper into your metrics and logs to find the cause. Grafana's new logging datasource, [Loki](https://github.com/grafana/loki) is tightly integrated into Explore and allows you to correlate metrics and logs by viewing them side-by-side. -{{< docs-imagebox img="/img/docs/v60/explore_split.png" class="docs-image--no-shadow" caption="Screenshot of the new Explore option in the panel menu" >}} - **Explore** is a new paradigm for Grafana. It creates a new interactive debugging workflow that integrates two pillars of observability - metrics and logs. #### Explore and Prometheus The first version of Explore features a [custom querying experience for Prometheus](/features/explore/#prometheus-specific-features) and as well as an integration between Prometheus and Grafana Loki (see more about Loki below). +### Explore splits + +Explore supports splitting the view so you can compare different queries, different datasources and metrics & logs side by side! + +{{< docs-imagebox img="/img/docs/v60/explore_split.png" max-width="800px" caption="Screenshot of the new Explore option in the panel menu" >}} + ### Explore and Grafana Loki -The Explore feature allows you to combine metric queries and log queries. The first log integration is for the new open source log aggregation system from Grafana Labs called [Grafana Loki](https://github.com/grafana/loki). +The log exploration & visualization features in Explore are available to any data source but are currently only implemented by the new open source log +aggregation system from Grafana Lab called [Grafana Loki](https://github.com/grafana/loki). -Loki a horizontally-scalable, highly-available, multi-tenant log aggregation system inspired by Prometheus. It is designed to be very cost effective, as it does not index the contents of the logs, but rather a set of labels for each log stream. The logs from Loki are queried in a similar way to querying with label selectors in Prometheus. It uses labels to group log streams which can be made to match up with your Prometheus labels. +Loki is a horizontally-scalable, highly-available, multi-tenant log aggregation system inspired by Prometheus. It is designed to be very cost effective, as it does not index the contents of the logs, but rather a set of labels for each log stream. The logs from Loki are queried in a similar way to querying with label selectors in Prometheus. It uses labels to group log streams which can be made to match up with your Prometheus labels. Read more about Grafana Loki [here](https://github.com/grafana/loki) or [Grafana Labs hosted Loki](https://grafana.com/loki). The Explore feature allows you to query logs and features a new log panel. -{{< docs-imagebox img="/img/docs/v60/explore_loki.png" class="docs-image--no-shadow" caption="Explore Loki Log Streams" >}} - In the near future, we will be adding support for other log sources to Explore and the next planned integration is ElasticSearch logs. +{{< docs-imagebox img="/img/docs/v60/explore_loki.png" max-width="1200px" class="docs-image--left" caption="Explore Loki Log Streams" >}} + ### Easily Switch Visualization with Panel Edit UX Update The UX for editing a panel has gotten an update and the major feature is being able to easily switch visualization using the new Visualization option. This means you can quickly switch from a Graph visualization to a Table visualization or any other visualization without having to create a new panel. From 3bb5930c54bacae7f78f00eacd440130d3ba23be Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Wed, 30 Jan 2019 11:15:04 +0100 Subject: [PATCH 14/43] docs: whats new tweaks --- docs/sources/guides/whats-new-in-v6-0.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 7cc4a4e26a4..6c138aab31c 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -62,11 +62,11 @@ In the near future, we will be adding support for other log sources to Explore a The UX for editing a panel has gotten an update and the major feature is being able to easily switch visualization using the new Visualization option. This means you can quickly switch from a Graph visualization to a Table visualization or any other visualization without having to create a new panel.
-
+ ### Google Stackdriver Datasource @@ -85,6 +85,7 @@ The Azure Monitor datasource integrates four Azure services with Grafana - Azure Grafana now added support for provisioning alert notifiers from configuration files. Allowing operators to provision notifiers without using the UI or the API. A new field called `uid` has been introduced which is a string identifier that the administrator can set themselves. Same kind of identifier used for dashboards since v5.0. This feature makes it possible to use the same notifier configuration in multiple environments and refer to notifiers in dashboard json by a string identifier instead of the numeric id which depends on insert order and how many notifiers that exists in the instance. ### Auth and session token improvements + The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. If you are using `Auth proxy` for authentication the session storage will still be used but our goal is to remove this ASAP as well. @@ -94,8 +95,6 @@ This release will force all users to log in again since their previous token is - The ElasticSearch datasource now supports [bucket script pipeline aggregations](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-bucket-script-aggregation.html). This gives the ability to do per bucket computations like the difference or ratio between two metrics. -- The way session storage works has been refactored to be more secure and to be more performant by doing fewer writes to the database. - - Support for Google Hangouts Chat alert notifications #### Technical Work - moving from Angular to React From d784accdec132bad506fc4529236dec0519a34f9 Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Wed, 30 Jan 2019 12:54:24 +0100 Subject: [PATCH 15/43] Add storybook script to run it from root dir --- package.json | 3 ++- .../src/components/ColorPicker/SpectrumPalette.story.tsx | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b8cb9ab7faf..6a2f4c06cb5 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,8 @@ "typecheck": "tsc --noEmit", "jest": "jest --notify --watch", "api-tests": "jest --notify --watch --config=tests/api/jest.js", - "precommit": "grunt precommit" + "precommit": "grunt precommit", + "storybook": "cd packages/grafana-ui && yarn storybook" }, "husky": { "hooks": { diff --git a/packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.story.tsx b/packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.story.tsx index 407564cdfb2..b4fdaf69ed9 100644 --- a/packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.story.tsx +++ b/packages/grafana-ui/src/components/ColorPicker/SpectrumPalette.story.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { withKnobs } from '@storybook/addon-knobs'; - import SpectrumPalette from './SpectrumPalette'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { UseState } from '../../utils/storybook/UseState'; @@ -11,8 +10,9 @@ const SpectrumPaletteStories = storiesOf('UI/ColorPicker/Palettes/SpectrumPalett SpectrumPaletteStories.addDecorator(withCenteredStory).addDecorator(withKnobs); -SpectrumPaletteStories.add('Named colors swatch - support for named colors', () => { +SpectrumPaletteStories.add('default', () => { const selectedTheme = getThemeKnob(); + return ( {(selectedColor, updateSelectedColor) => { From 4b47e857f21a1bbc87d0219c89cc44366320cce6 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Wed, 30 Jan 2019 13:43:17 +0100 Subject: [PATCH 16/43] adjusting types to match --- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 2 +- public/app/features/dashboard/panel_model.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 853139db803..359965bc9ad 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -86,7 +86,7 @@ export class PanelChrome extends PureComponent { onDataResponse = (dataQueryResponse: DataQueryResponse) => { if (this.props.dashboard.isSnapshot()) { - this.props.panel.snapshotData = dataQueryResponse; + this.props.panel.snapshotData = dataQueryResponse.data; } }; diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index 469884517b3..6f85e7a7a3c 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -4,7 +4,7 @@ import _ from 'lodash'; // Types import { Emitter } from 'app/core/utils/emitter'; import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants'; -import { DataQuery, DataQueryResponse } from '@grafana/ui/src/types'; +import { DataQuery, TimeSeries } from '@grafana/ui'; export interface GridPos { x: number; @@ -87,7 +87,7 @@ export class PanelModel { datasource: string; thresholds?: any; - snapshotData?: DataQueryResponse; + snapshotData?: TimeSeries[]; timeFrom?: any; timeShift?: any; hideTimeOverride?: any; From 909acb08efcce81b647f4e59581cff3747f2ca6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 14:17:34 +0100 Subject: [PATCH 17/43] updated what's new article --- docs/sources/guides/whats-new-in-v6-0.md | 44 ++++++++++++++++++------ 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 7cc4a4e26a4..4fe5e14aa56 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -51,22 +51,46 @@ Loki is a horizontally-scalable, highly-available, multi-tenant log aggregation Read more about Grafana Loki [here](https://github.com/grafana/loki) or [Grafana Labs hosted Loki](https://grafana.com/loki). -The Explore feature allows you to query logs and features a new log panel. +The Explore feature allows you to query logs and features a new log panel. In the near future, we will be adding support +for other log sources to Explore and the next planned integration is Elasticsearch. -In the near future, we will be adding support for other log sources to Explore and the next planned integration is ElasticSearch logs. +{{< docs-imagebox img="/img/docs/v60/explore_loki.png" max-width="1200px" caption="Explore Loki Log Streams" >}} -{{< docs-imagebox img="/img/docs/v60/explore_loki.png" max-width="1200px" class="docs-image--left" caption="Explore Loki Log Streams" >}} +## New Panel Editor -### Easily Switch Visualization with Panel Edit UX Update - -The UX for editing a panel has gotten an update and the major feature is being able to easily switch visualization using the new Visualization option. This means you can quickly switch from a Graph visualization to a Table visualization or any other visualization without having to create a new panel. +Grafana v6.0 has a completely redesigned UX around editing panels. You can now resize the visualization area if you want +more space for queries & options and vice versa. You can now also change visualization (panel type) from within the new +panel edit mode. No need to add a new panel to try out different visualizations! Checkout the +video below to see the new Panel Editor in action.
-
+ + +
+ +### Gauge Panel + +We have created a new seperate Gauge panel as we felt having this visualization be a hidden option in the Singlestat panel +was not ideal. When it supports 100% of the Singlestat Gauge features we plan to add a migration so all +singlestats that use it become Gauge panels instead. This new panel contains a new **Threshold** editor that we will +continue to refine and start using in other panels. + +{{< docs-imagebox img="/img/docs/v60/gauge_panel.png" max-width="600px" caption="Gauge Panel" >}} + +
+ +### React Panels & Query Editors + +A major part of all the work that has gone into Grafana v6.0 has been on the migration to React. This investment +is part of the future proofing of Grafana and it's code base and ecosystem. Starting in v6.0 **Panels** and **Data +source** plugins can be written in React using our published `@grafana/ui` sdk library. More information on this +will be shared closer to or just after release. + +{{< docs-imagebox img="/img/docs/v60/react_panels.png" max-width="600px" caption="React Panel" >}} ### Google Stackdriver Datasource @@ -85,7 +109,7 @@ The Azure Monitor datasource integrates four Azure services with Grafana - Azure Grafana now added support for provisioning alert notifiers from configuration files. Allowing operators to provision notifiers without using the UI or the API. A new field called `uid` has been introduced which is a string identifier that the administrator can set themselves. Same kind of identifier used for dashboards since v5.0. This feature makes it possible to use the same notifier configuration in multiple environments and refer to notifiers in dashboard json by a string identifier instead of the numeric id which depends on insert order and how many notifiers that exists in the instance. ### Auth and session token improvements -The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. +The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. If you are using `Auth proxy` for authentication the session storage will still be used but our goal is to remove this ASAP as well. This release will force all users to log in again since their previous token is not valid anymore. From 2ca34376a0887442341759e0ea49e51a4d86466c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 14:33:49 +0100 Subject: [PATCH 18/43] fixe merge issue --- docs/sources/guides/whats-new-in-v6-0.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 7ab9698989b..77f6944b9af 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -64,19 +64,10 @@ panel edit mode. No need to add a new panel to try out different visualizations! video below to see the new Panel Editor in action.
-<<<<<<< HEAD

@@ -100,11 +91,6 @@ source** plugins can be written in React using our published `@grafana/ui` sdk l will be shared closer to or just after release. {{< docs-imagebox img="/img/docs/v60/react_panels.png" max-width="600px" caption="React Panel" >}} -||||||| merged common ancestors - -======= - ->>>>>>> 3bb5930c54bacae7f78f00eacd440130d3ba23be ### Google Stackdriver Datasource @@ -123,14 +109,8 @@ The Azure Monitor datasource integrates four Azure services with Grafana - Azure Grafana now added support for provisioning alert notifiers from configuration files. Allowing operators to provision notifiers without using the UI or the API. A new field called `uid` has been introduced which is a string identifier that the administrator can set themselves. Same kind of identifier used for dashboards since v5.0. This feature makes it possible to use the same notifier configuration in multiple environments and refer to notifiers in dashboard json by a string identifier instead of the numeric id which depends on insert order and how many notifiers that exists in the instance. ### Auth and session token improvements -<<<<<<< HEAD -The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. -||||||| merged common ancestors -The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. -======= The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. ->>>>>>> 3bb5930c54bacae7f78f00eacd440130d3ba23be If you are using `Auth proxy` for authentication the session storage will still be used but our goal is to remove this ASAP as well. This release will force all users to log in again since their previous token is not valid anymore. From 5fa8c53d2e4904332cddd4a10c0fb46f2511e6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 14:44:35 +0100 Subject: [PATCH 19/43] Updated explore section --- docs/sources/guides/whats-new-in-v6-0.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 77f6944b9af..40b5d2dcb1b 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -30,11 +30,17 @@ Grafana's dashboard UI is all about building dashboards for visualization. **Exp For infrastructure monitoring and incident response, you no longer need to switch to other tools to debug what went wrong. **Explore** allows you to dig deeper into your metrics and logs to find the cause. Grafana's new logging datasource, [Loki](https://github.com/grafana/loki) is tightly integrated into Explore and allows you to correlate metrics and logs by viewing them side-by-side. -**Explore** is a new paradigm for Grafana. It creates a new interactive debugging workflow that integrates two pillars of observability - metrics and logs. +**Explore** is a new paradigm for Grafana. It creates a new interactive debugging workflow that integrates two pillars +of observability - metrics and logs. Explore works with every datasource but for Prometheus we have customized the +query editor and the experiance to provide the best possible exploration UX. #### Explore and Prometheus -The first version of Explore features a [custom querying experience for Prometheus](/features/explore/#prometheus-specific-features) and as well as an integration between Prometheus and Grafana Loki (see more about Loki below). +The first version of Explore features our new [query editor for +Prometheus](/features/explore/#prometheus-specific-features). This new editor has improved autocomplete, metric tree selector, +integrations with the Explore table view for easy label filtering and useful query hints that can automatically apply +functions to your query. There is also integration between Prometheus and Grafana Loki (see more about Loki below) that +enabled jumping between metrics query and logs query with preserved label filters. ### Explore splits @@ -110,7 +116,7 @@ Grafana now added support for provisioning alert notifiers from configuration fi ### Auth and session token improvements -The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. +The previous session storage implementation in Grafana was causing problems in larger HA setups due to too many write requests to the database. The remember me token also have several security issues which is why we decided to rewrite auth middleware in Grafana and remove the session storage since most operations using the session storage could be rewritten to use cookies or data already made available earlier in the request. If you are using `Auth proxy` for authentication the session storage will still be used but our goal is to remove this ASAP as well. This release will force all users to log in again since their previous token is not valid anymore. From 8aed40164047ff65f5e5ceac695e66c2a4d3924b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 14:47:23 +0100 Subject: [PATCH 20/43] Updated explore section again --- docs/sources/guides/whats-new-in-v6-0.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 40b5d2dcb1b..4733a9b0e30 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -36,8 +36,7 @@ query editor and the experiance to provide the best possible exploration UX. #### Explore and Prometheus -The first version of Explore features our new [query editor for -Prometheus](/features/explore/#prometheus-specific-features). This new editor has improved autocomplete, metric tree selector, +Explore features a new [Prometheus query editor](/features/explore/#prometheus-specific-features). This new editor has improved autocomplete, metric tree selector, integrations with the Explore table view for easy label filtering and useful query hints that can automatically apply functions to your query. There is also integration between Prometheus and Grafana Loki (see more about Loki below) that enabled jumping between metrics query and logs query with preserved label filters. From 1230f3e48dc8064a5bd63c348869a775fcf727b3 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 30 Jan 2019 15:28:41 +0100 Subject: [PATCH 21/43] chore: Fix typings and remove bindings for arrow functions in DashboardGrid --- .../dashboard/dashgrid/DashboardGrid.tsx | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index a401505b787..c9c1dd0d7b0 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { hot } from 'react-hot-loader'; -import ReactGridLayout from 'react-grid-layout'; +import ReactGridLayout, { ItemCallback } 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'; @@ -11,6 +11,21 @@ import sizeMe from 'react-sizeme'; let lastGridWidth = 1200; let ignoreNextWidthChange = false; +interface GridWrapperProps { + size: { width: number; }; + layout: ReactGridLayout.Layout[]; + onLayoutChange: (layout: ReactGridLayout.Layout[]) => void; + children: JSX.Element | JSX.Element[]; + onDragStop: ItemCallback; + onResize: ItemCallback; + onResizeStop: ItemCallback; + onWidthChange: () => void; + className: string; + isResizable?: boolean; + isDraggable?: boolean; + isFullscreen?: boolean; +} + function GridWrapper({ size, layout, @@ -24,7 +39,7 @@ function GridWrapper({ isResizable, isDraggable, isFullscreen, -}) { +}: GridWrapperProps) { const width = size.width > 0 ? size.width : lastGridWidth; // logic to ignore width changes (optimization) @@ -43,7 +58,6 @@ function GridWrapper({ className={className} isDraggable={isDraggable} isResizable={isResizable} - measureBeforeMount={false} containerPadding={[0, 0]} useCSSTransforms={false} margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]} @@ -71,22 +85,17 @@ export class DashboardGrid extends React.Component { gridToPanelMap: any; panelMap: { [id: string]: PanelModel }; - constructor(props) { + constructor(props: DashboardGridProps) { super(props); - this.onLayoutChange = this.onLayoutChange.bind(this); - this.onResize = this.onResize.bind(this); - this.onResizeStop = this.onResizeStop.bind(this); - this.onDragStop = this.onDragStop.bind(this); - this.onWidthChange = this.onWidthChange.bind(this); // subscribe to dashboard events const dashboard = this.props.dashboard; - dashboard.on('panel-added', this.triggerForceUpdate.bind(this)); - dashboard.on('panel-removed', this.triggerForceUpdate.bind(this)); - dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this)); - dashboard.on('view-mode-changed', this.onViewModeChanged.bind(this)); - dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this)); - dashboard.on('row-expanded', this.triggerForceUpdate.bind(this)); + dashboard.on('panel-added', this.triggerForceUpdate); + dashboard.on('panel-removed', this.triggerForceUpdate); + dashboard.on('repeats-processed', this.triggerForceUpdate); + dashboard.on('view-mode-changed', this.onViewModeChanged); + dashboard.on('row-collapsed', this.triggerForceUpdate); + dashboard.on('row-expanded', this.triggerForceUpdate); } buildLayout() { @@ -123,7 +132,7 @@ export class DashboardGrid extends React.Component { return layout; } - onLayoutChange(newLayout) { + onLayoutChange = (newLayout: ReactGridLayout.Layout[]) => { for (const newPos of newLayout) { this.panelMap[newPos.i].updateGridPos(newPos); } @@ -131,22 +140,22 @@ export class DashboardGrid extends React.Component { this.props.dashboard.sortPanelsByGridPos(); } - triggerForceUpdate() { + triggerForceUpdate = () => { this.forceUpdate(); } - onWidthChange() { + onWidthChange = () => { for (const panel of this.props.dashboard.panels) { panel.resizeDone(); } } - onViewModeChanged(payload) { + onViewModeChanged = () => { ignoreNextWidthChange = true; this.forceUpdate(); } - updateGridPos(item, layout) { + updateGridPos = (item: ReactGridLayout.Layout, layout: ReactGridLayout.Layout[]) => { this.panelMap[item.i].updateGridPos(item); // react-grid-layout has a bug (#670), and onLayoutChange() is only called when the component is mounted. @@ -154,16 +163,17 @@ export class DashboardGrid extends React.Component { this.onLayoutChange(layout); } - onResize(layout, oldItem, newItem) { + onResize: ItemCallback = (layout, oldItem, newItem) => { + console.log(); this.panelMap[newItem.i].updateGridPos(newItem); } - onResizeStop(layout, oldItem, newItem) { + onResizeStop: ItemCallback = (layout, oldItem, newItem) => { this.updateGridPos(newItem, layout); this.panelMap[newItem.i].resizeDone(); } - onDragStop(layout, oldItem, newItem) { + onDragStop: ItemCallback = (layout, oldItem, newItem) => { this.updateGridPos(newItem, layout); } From ef4611eb56841b73f6154dab59f57a9dc79e0b36 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 30 Jan 2019 15:32:29 +0100 Subject: [PATCH 22/43] chore: Add missing typings in PanelResizer --- public/app/features/dashboard/dashgrid/PanelResizer.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelResizer.tsx b/public/app/features/dashboard/dashgrid/PanelResizer.tsx index ca8abd0d1e3..1ee5b3884a0 100644 --- a/public/app/features/dashboard/dashgrid/PanelResizer.tsx +++ b/public/app/features/dashboard/dashgrid/PanelResizer.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import { throttle } from 'lodash'; -import Draggable from 'react-draggable'; +import Draggable, { DraggableEventHandler } from 'react-draggable'; import { PanelModel } from '../panel_model'; @@ -42,7 +42,7 @@ export class PanelResizer extends PureComponent { return 100; } - changeHeight = height => { + changeHeight = (height: number) => { const sh = this.smallestHeight; const lh = this.largestHeight; height = height < sh ? sh : height; @@ -54,7 +54,7 @@ export class PanelResizer extends PureComponent { }); }; - onDrag = (evt, data) => { + onDrag: DraggableEventHandler = (evt, data) => { const newHeight = this.state.editorHeight + data.y; this.throttledChangeHeight(newHeight); this.throttledResizeDone(); From 1afc590c703731cd2026fb8286388e1db6afc09f Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 30 Jan 2019 15:38:59 +0100 Subject: [PATCH 23/43] fix: Don't open panel menu when dragging (react-)panel in dashboard #14946 --- .../dashgrid/PanelHeader/PanelHeader.tsx | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx index b5cd9258c08..6dd4af2dc03 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import classNames from 'classnames'; +import { isEqual } from 'lodash'; import PanelHeaderCorner from './PanelHeaderCorner'; import { PanelHeaderMenu } from './PanelHeaderMenu'; @@ -19,21 +20,45 @@ export interface Props { links?: []; } +interface ClickCoordinates { + x: number; + y: number; +} + interface State { panelMenuOpen: boolean; } export class PanelHeader extends Component { + clickCoordinates: ClickCoordinates = {x: 0, y: 0}; state = { panelMenuOpen: false, + clickCoordinates: {x: 0, y: 0} }; - onMenuToggle = event => { - event.stopPropagation(); + eventToClickCoordinates = (event: React.MouseEvent) => { + return { + x: event.clientX, + y: event.clientY + }; + } - this.setState(prevState => ({ - panelMenuOpen: !prevState.panelMenuOpen, - })); + onMouseDown = (event: React.MouseEvent) => { + this.clickCoordinates = this.eventToClickCoordinates(event); + }; + + isClick = (clickCoordinates: ClickCoordinates) => { + return isEqual(clickCoordinates, this.clickCoordinates); + } + + onMenuToggle = (event: React.MouseEvent) => { + if (this.isClick(this.eventToClickCoordinates(event))) { + event.stopPropagation(); + + this.setState(prevState => ({ + panelMenuOpen: !prevState.panelMenuOpen, + })); + } }; closeMenu = () => { @@ -64,7 +89,7 @@ export class PanelHeader extends Component { )} -
+
From 3165305377c05aaaf08fc86f7c352885d60a58c0 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 30 Jan 2019 15:44:34 +0100 Subject: [PATCH 24/43] chore: Add typings for react-grid-layout and react-virtualized --- package.json | 2 ++ yarn.lock | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/package.json b/package.json index b8cb9ab7faf..d2b7effbf68 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,9 @@ "@types/node": "^8.0.31", "@types/react": "^16.7.6", "@types/react-dom": "^16.0.9", + "@types/react-grid-layout": "^0.16.6", "@types/react-select": "^2.0.4", + "@types/react-virtualized": "^9.18.12", "angular-mocks": "1.6.6", "autoprefixer": "^6.4.0", "axios": "^0.17.1", diff --git a/yarn.lock b/yarn.lock index 41928daab5e..169abd40ee4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1773,6 +1773,13 @@ dependencies: "@types/react" "*" +"@types/react-grid-layout@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-0.16.6.tgz#9149efe128e05d59c54063c7781d18b8febe112c" + integrity sha512-Jp0VfCHJE4uxekPBPpRkADKOjoSHssF2ba1ZMMAfCEqkoSkE+K+3bhI39++fbd7MqGySaqADVHeOoxlBnA3p5g== + dependencies: + "@types/react" "*" + "@types/react-select@^2.0.4": version "2.0.11" resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-2.0.11.tgz#9b2b1fdb12b67a5a617c5f572e15617636cc65af" @@ -1796,6 +1803,14 @@ dependencies: "@types/react" "*" +"@types/react-virtualized@^9.18.12": + version "9.18.12" + resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.18.12.tgz#541e65c5e0b4629d6a1c6f339171c7943e016ecb" + integrity sha512-Msdpt9zvYlb5Ul4PA339QUkJ0/z2O+gaFxed1rG+2rZjbe6XdYo7jWfJe206KBnjj84DwPPIbPFQCtoGuNwNTQ== + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + "@types/react@*", "@types/react@16.7.6", "@types/react@^16.7.6": version "16.7.6" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.6.tgz#80e4bab0d0731ad3ae51f320c4b08bdca5f03040" From 26096c65a54705f7ed43d961eca90c29d56b9071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 16:15:56 +0100 Subject: [PATCH 25/43] spell fixes --- docs/sources/guides/whats-new-in-v6-0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 4733a9b0e30..d31ce48794e 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -32,7 +32,7 @@ For infrastructure monitoring and incident response, you no longer need to switc **Explore** is a new paradigm for Grafana. It creates a new interactive debugging workflow that integrates two pillars of observability - metrics and logs. Explore works with every datasource but for Prometheus we have customized the -query editor and the experiance to provide the best possible exploration UX. +query editor and the experience to provide the best possible exploration UX. #### Explore and Prometheus @@ -79,7 +79,7 @@ video below to see the new Panel Editor in action. ### Gauge Panel -We have created a new seperate Gauge panel as we felt having this visualization be a hidden option in the Singlestat panel +We have created a new separate Gauge panel as we felt having this visualization be a hidden option in the Singlestat panel was not ideal. When it supports 100% of the Singlestat Gauge features we plan to add a migration so all singlestats that use it become Gauge panels instead. This new panel contains a new **Threshold** editor that we will continue to refine and start using in other panels. From 70c35d646f716aae93692f71e04bc5f24123a6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 16:51:59 +0100 Subject: [PATCH 26/43] Added loki video --- docs/sources/guides/whats-new-in-v6-0.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index d31ce48794e..a2969b32197 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -59,7 +59,12 @@ Read more about Grafana Loki [here](https://github.com/grafana/loki) or [Grafana The Explore feature allows you to query logs and features a new log panel. In the near future, we will be adding support for other log sources to Explore and the next planned integration is Elasticsearch. -{{< docs-imagebox img="/img/docs/v60/explore_loki.png" max-width="1200px" caption="Explore Loki Log Streams" >}} +
+ +
## New Panel Editor From 3ad48ff7e5067e48fea9eee4e1d22ed254fc6752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 16:54:09 +0100 Subject: [PATCH 27/43] docs: Added version notice for time range variables --- docs/sources/reference/templating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/reference/templating.md b/docs/sources/reference/templating.md index 340384b62e5..7426877654b 100644 --- a/docs/sources/reference/templating.md +++ b/docs/sources/reference/templating.md @@ -248,7 +248,7 @@ Grafana has global built-in variables that can be used in expressions in the que ### Time range variables Grafana has two built in time range variables in `$__from` and `$__to`. They are currently always interpolated -as epoch milliseconds. +as epoch milliseconds. These variables are only available in Grafana v6.0 and above. ### The $__interval Variable From d7f81c47951bc832061c726060c75fd587fb136e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 17:14:42 +0100 Subject: [PATCH 28/43] Updated version and made some changes to changelog and what's new article --- CHANGELOG.md | 1 + docs/sources/guides/whats-new-in-v6-0.md | 10 ++++++---- package.json | 2 +- scripts/build/publish.sh | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 364a33cfb5b..54d22ae7b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * **Influxdb**: Add support for time zone (`tz`) clause [#10322](https://github.com/grafana/grafana/issues/10322), thx [@cykl](https://github.com/cykl) * **Snapshots**: Enable deletion of public snapshot [#14109](https://github.com/grafana/grafana/issues/14109) * **Provisioning**: Provisioning support for alert notifiers [#10487](https://github.com/grafana/grafana/issues/10487), thx [@pbakulev](https://github.com/pbakulev) +* **Explore**: A whole new way to do ad-hoc metric queries and exploration. Split view in half and compare metrics & logs and much much more. [Read more here](http://docs.grafana.org/features/explore/) ### Minor diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index a2969b32197..184e038fc88 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -16,11 +16,13 @@ This update to Grafana introduces a new way of exploring your data, support for The main highlights are: -- The new query-focused [Explore]({{< relref "#explore" >}}) workflow for troubleshooting and/or for data exploration. -- [Support for Grafana Loki]({{< relref "#explore-and-grafana-loki" >}}) - a new open source log aggregation system from Grafana Labs. -- [Easily Switch Visualization with the Panel Edit UX Update]({{< relref "#easily-switch-visualization-with-panel-edit-ux-update" >}}) +- [Explore]({{< relref "#explore" >}}) - A new query focused workflow for ad hoc data exploration and troubleshooting. +- [Grafana Loki]({{< relref "#explore-and-grafana-loki" >}}) - Integration with the new open source log aggregation system from Grafana Labs. +- [Gauge Panel]({{< relref "#gauge-panel" >}}) - A new standalone panel for gauges. +- [New Panel Editor UX]({{< relref "#easily-switch-visualization-with-panel-edit-ux-update" >}}) improves panel editing + and enables easy switch between different visualizations. - [Google Stackdriver Datasource]({{< relref "#google-stackdriver-datasource" >}}) is out of beta and is officially released. -- The [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource +- [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource ## Explore diff --git a/package.json b/package.json index d2b7effbf68..12c36e610b0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "company": "Grafana Labs" }, "name": "grafana", - "version": "6.0.0-pre1", + "version": "6.0.0-beta1", "repository": { "type": "git", "url": "http://github.com/grafana/grafana.git" diff --git a/scripts/build/publish.sh b/scripts/build/publish.sh index 264d930e51b..785f46f22a0 100755 --- a/scripts/build/publish.sh +++ b/scripts/build/publish.sh @@ -6,8 +6,8 @@ EXTRA_OPTS="$@" # Right now we hack this in into the publish script. # Eventually we might want to keep a list of all previous releases somewhere. -_releaseNoteUrl="https://community.grafana.com/t/release-notes-v5-4-x/12215" -_whatsNewUrl="http://docs.grafana.org/guides/whats-new-in-v5-4/" +_releaseNoteUrl="https://community.grafana.com/t/release-notes-v6-0-x/14010" +_whatsNewUrl="http://docs.grafana.org/guides/whats-new-in-v6-0/" ./scripts/build/release_publisher/release_publisher \ --wn ${_whatsNewUrl} \ From 6fd60c639fc8cbe2a09d3b547b321e9c47fb03b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 17:20:43 +0100 Subject: [PATCH 29/43] Updated version again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 12c36e610b0..b9271885edd 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "company": "Grafana Labs" }, "name": "grafana", - "version": "6.0.0-beta1", + "version": "6.0.0-prebeta2", "repository": { "type": "git", "url": "http://github.com/grafana/grafana.git" From b8427ba3790033d874faef8d6353b194cdd149ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 17:28:43 +0100 Subject: [PATCH 30/43] Updated docs --- docs/sources/features/explore/index.md | 9 ++++++++- docs/sources/guides/whats-new-in-v6-0.md | 15 ++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/sources/features/explore/index.md b/docs/sources/features/explore/index.md index 6580bcf217f..25af18c2a3d 100644 --- a/docs/sources/features/explore/index.md +++ b/docs/sources/features/explore/index.md @@ -99,7 +99,14 @@ The Logs Explorer (the `Log labels` button) next to the query field shows a list Once the result is returned, the log panel shows a list of log rows and a bar chart where the x-axis shows the time and the y-axis shows the frequency/count. -{{< docs-imagebox img="/img/docs/v60/explore_loki.png" class="docs-image--no-shadow" caption="Explore Loki Log Streams" >}} +
+ +
+ +
#### Log Stream Selector diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 184e038fc88..586277248bf 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -16,13 +16,14 @@ This update to Grafana introduces a new way of exploring your data, support for The main highlights are: -- [Explore]({{< relref "#explore" >}}) - A new query focused workflow for ad hoc data exploration and troubleshooting. +- [Explore]({{< relref "#explore" >}}) - A new query focused workflow for ad-hoc data exploration and troubleshooting. - [Grafana Loki]({{< relref "#explore-and-grafana-loki" >}}) - Integration with the new open source log aggregation system from Grafana Labs. - [Gauge Panel]({{< relref "#gauge-panel" >}}) - A new standalone panel for gauges. - [New Panel Editor UX]({{< relref "#easily-switch-visualization-with-panel-edit-ux-update" >}}) improves panel editing - and enables easy switch between different visualizations. + and enables easy switching between different visualizations. - [Google Stackdriver Datasource]({{< relref "#google-stackdriver-datasource" >}}) is out of beta and is officially released. - [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource +- [React Plugin]({{< relref "#react-panels-query-editors" >}}) support enables an easier way to build plugins. ## Explore @@ -36,7 +37,7 @@ For infrastructure monitoring and incident response, you no longer need to switc of observability - metrics and logs. Explore works with every datasource but for Prometheus we have customized the query editor and the experience to provide the best possible exploration UX. -#### Explore and Prometheus +### Explore and Prometheus Explore features a new [Prometheus query editor](/features/explore/#prometheus-specific-features). This new editor has improved autocomplete, metric tree selector, integrations with the Explore table view for easy label filtering and useful query hints that can automatically apply @@ -49,6 +50,8 @@ Explore supports splitting the view so you can compare different queries, differ {{< docs-imagebox img="/img/docs/v60/explore_split.png" max-width="800px" caption="Screenshot of the new Explore option in the panel menu" >}} +
+ ### Explore and Grafana Loki The log exploration & visualization features in Explore are available to any data source but are currently only implemented by the new open source log @@ -68,6 +71,8 @@ for other log sources to Explore and the next planned integration is Elasticsear
+
+ ## New Panel Editor Grafana v6.0 has a completely redesigned UX around editing panels. You can now resize the visualization area if you want @@ -133,10 +138,6 @@ This release will force all users to log in again since their previous token is - Support for Google Hangouts Chat alert notifications -#### Technical Work - moving from Angular to React - -The Grafana team is putting a huge amount of work into converting the frontend code in Grafana from Angular to React. Currently, all external plugins for Grafana are written in Angular but we are planning to also support plugins written in React very soon. - ## Changelog Checkout the [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md) file for a complete list of new features, changes, and bug fixes. From e3472f6d81554470725978537f4ae2eee565905c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 30 Jan 2019 17:53:41 +0100 Subject: [PATCH 31/43] Added download links to docs --- docs/sources/guides/whats-new-in-v6-0.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index 586277248bf..afc312c7b0a 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -14,6 +14,8 @@ weight = -11 This update to Grafana introduces a new way of exploring your data, support for log data and tons of other features. +Grafana v6.0 is out in **Beta**, [Download Now!](https://grafana.com/grafana/download/beta) + The main highlights are: - [Explore]({{< relref "#explore" >}}) - A new query focused workflow for ad-hoc data exploration and troubleshooting. From e83831904a0e5943df92be84360532468d5ee765 Mon Sep 17 00:00:00 2001 From: Thomas Rohlik Date: Wed, 30 Jan 2019 18:52:40 +0100 Subject: [PATCH 32/43] Fix anchor --- docs/sources/guides/whats-new-in-v6-0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index afc312c7b0a..f1bf91f88d1 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -21,7 +21,7 @@ The main highlights are: - [Explore]({{< relref "#explore" >}}) - A new query focused workflow for ad-hoc data exploration and troubleshooting. - [Grafana Loki]({{< relref "#explore-and-grafana-loki" >}}) - Integration with the new open source log aggregation system from Grafana Labs. - [Gauge Panel]({{< relref "#gauge-panel" >}}) - A new standalone panel for gauges. -- [New Panel Editor UX]({{< relref "#easily-switch-visualization-with-panel-edit-ux-update" >}}) improves panel editing +- [New Panel Editor UX]({{< relref "#new-panel-editor" >}}) improves panel editing and enables easy switching between different visualizations. - [Google Stackdriver Datasource]({{< relref "#google-stackdriver-datasource" >}}) is out of beta and is officially released. - [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource From f13018ce05b3c99b04e7d9711df03ae2106b6080 Mon Sep 17 00:00:00 2001 From: Jeff Hage Date: Wed, 30 Jan 2019 18:57:33 -0500 Subject: [PATCH 33/43] Replace usages of kbn.valueFormats with ui/getValueFormat --- public/app/core/time_series2.ts | 11 ++++++----- public/app/plugins/panel/graph/graph.ts | 9 +++++---- public/app/plugins/panel/heatmap/heatmap_tooltip.ts | 4 ++-- public/app/plugins/panel/heatmap/rendering.ts | 5 ++--- public/app/plugins/panel/singlestat/module.ts | 9 ++++----- public/app/plugins/panel/table/renderer.ts | 5 ++--- 6 files changed, 21 insertions(+), 22 deletions(-) diff --git a/public/app/core/time_series2.ts b/public/app/core/time_series2.ts index 9872c0bc912..23a0a0c19ea 100644 --- a/public/app/core/time_series2.ts +++ b/public/app/core/time_series2.ts @@ -1,6 +1,7 @@ import kbn from 'app/core/utils/kbn'; import { getFlotTickDecimals } from 'app/core/utils/ticks'; import _ from 'lodash'; +import { getValueFormat } from '@grafana/ui'; function matchSeriesOverride(aliasOrRegex, seriesAlias) { if (!aliasOrRegex) { @@ -31,13 +32,13 @@ export function updateLegendValues(data: TimeSeries[], panel, height) { const yaxes = panel.yaxes; const seriesYAxis = series.yaxis || 1; const axis = yaxes[seriesYAxis - 1]; - const formater = kbn.valueFormats[axis.format]; + const formatter = getValueFormat(axis.format); // decimal override if (_.isNumber(panel.decimals)) { - series.updateLegendValues(formater, panel.decimals, null); + series.updateLegendValues(formatter, panel.decimals, null); } else if (_.isNumber(axis.decimals)) { - series.updateLegendValues(formater, axis.decimals + 1, null); + series.updateLegendValues(formatter, axis.decimals + 1, null); } else { // auto decimals // legend and tooltip gets one more decimal precision @@ -45,7 +46,7 @@ export function updateLegendValues(data: TimeSeries[], panel, height) { const { datamin, datamax } = getDataMinMax(data); const { tickDecimals, scaledDecimals } = getFlotTickDecimals(datamin, datamax, axis, height); const tickDecimalsPlusOne = (tickDecimals || -1) + 1; - series.updateLegendValues(formater, tickDecimalsPlusOne, scaledDecimals + 2); + series.updateLegendValues(formatter, tickDecimalsPlusOne, scaledDecimals + 2); } } } @@ -105,7 +106,7 @@ export default class TimeSeries { this.aliasEscaped = _.escape(opts.alias); this.color = opts.color; this.bars = { fillColor: opts.color }; - this.valueFormater = kbn.valueFormats.none; + this.valueFormater = getValueFormat('none'); this.stats = {}; this.legend = true; this.unit = opts.unit; diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 78f9d09520b..aeb540551b8 100755 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -11,7 +11,6 @@ import './jquery.flot.events'; import $ from 'jquery'; import _ from 'lodash'; import moment from 'moment'; -import kbn from 'app/core/utils/kbn'; import { tickStep } from 'app/core/utils/ticks'; import { appEvents, coreModule, updateLegendValues } from 'app/core/core'; import GraphTooltip from './graph_tooltip'; @@ -26,7 +25,7 @@ import ReactDOM from 'react-dom'; import { Legend, GraphLegendProps } from './Legend/Legend'; import { GraphCtrl } from './module'; -import { GrafanaTheme } from '@grafana/ui'; +import { GrafanaTheme, getValueFormat } from '@grafana/ui'; class GraphElement { ctrl: GraphCtrl; @@ -730,10 +729,12 @@ class GraphElement { configureAxisMode(axis, format) { axis.tickFormatter = (val, axis) => { - if (!kbn.valueFormats[format]) { + const formatter = getValueFormat(format); + + if (!formatter) { throw new Error(`Unit '${format}' is not supported`); } - return kbn.valueFormats[format](val, axis.tickDecimals, axis.scaledDecimals); + return formatter(val, axis.tickDecimals, axis.scaledDecimals); }; } diff --git a/public/app/plugins/panel/heatmap/heatmap_tooltip.ts b/public/app/plugins/panel/heatmap/heatmap_tooltip.ts index 4ff0176d0bf..be9920b3edf 100644 --- a/public/app/plugins/panel/heatmap/heatmap_tooltip.ts +++ b/public/app/plugins/panel/heatmap/heatmap_tooltip.ts @@ -1,8 +1,8 @@ import * as d3 from 'd3'; import $ from 'jquery'; import _ from 'lodash'; -import kbn from 'app/core/utils/kbn'; import { getValueBucketBound } from './heatmap_data_converter'; +import { getValueFormat } from '@grafana/ui'; const TOOLTIP_PADDING_X = 30; const TOOLTIP_PADDING_Y = 5; @@ -268,7 +268,7 @@ export class HeatmapTooltip { countValueFormatter(decimals, scaledDecimals = null) { const format = 'short'; return value => { - return kbn.valueFormats[format](value, decimals, scaledDecimals); + return getValueFormat(format)(value, decimals, scaledDecimals); }; } } diff --git a/public/app/plugins/panel/heatmap/rendering.ts b/public/app/plugins/panel/heatmap/rendering.ts index 6333a985819..6489c9e9895 100644 --- a/public/app/plugins/panel/heatmap/rendering.ts +++ b/public/app/plugins/panel/heatmap/rendering.ts @@ -2,13 +2,12 @@ import _ from 'lodash'; import $ from 'jquery'; import moment from 'moment'; import * as d3 from 'd3'; -import kbn from 'app/core/utils/kbn'; import { appEvents, contextSrv } from 'app/core/core'; import * as ticksUtils from 'app/core/utils/ticks'; import { HeatmapTooltip } from './heatmap_tooltip'; import { mergeZeroBuckets } from './heatmap_data_converter'; import { getColorScale, getOpacityScale } from './color_scale'; -import { GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/ui'; +import { GrafanaTheme, getColorFromHexRgbOrName, getValueFormat } from '@grafana/ui'; const MIN_CARD_SIZE = 1, CARD_PADDING = 1, @@ -436,7 +435,7 @@ export class HeatmapRenderer { const format = this.panel.yAxis.format; return value => { try { - return format !== 'none' ? kbn.valueFormats[format](value, decimals, scaledDecimals) : value; + return format !== 'none' ? getValueFormat(format)(value, decimals, scaledDecimals) : value; } catch (err) { console.error(err.message || err); return value; diff --git a/public/app/plugins/panel/singlestat/module.ts b/public/app/plugins/panel/singlestat/module.ts index da9cf0de689..2768951d2ba 100644 --- a/public/app/plugins/panel/singlestat/module.ts +++ b/public/app/plugins/panel/singlestat/module.ts @@ -8,8 +8,7 @@ import kbn from 'app/core/utils/kbn'; import config from 'app/core/config'; import TimeSeries from 'app/core/time_series2'; import { MetricsPanelCtrl } from 'app/plugins/sdk'; -import { getColorFromHexRgbOrName } from '@grafana/ui'; -import { GrafanaTheme } from '@grafana/ui'; +import { GrafanaTheme, getValueFormat, getColorFromHexRgbOrName } from '@grafana/ui'; class SingleStatCtrl extends MetricsPanelCtrl { static templateUrl = 'module.html'; @@ -192,7 +191,8 @@ class SingleStatCtrl extends MetricsPanelCtrl { data.valueRounded = 0; } else { const decimalInfo = this.getDecimalsForValue(data.value); - const formatFunc = kbn.valueFormats[this.panel.format]; + const formatFunc = getValueFormat(this.panel.format); + data.valueFormatted = formatFunc( datapoint[this.panel.tableColumn], decimalInfo.decimals, @@ -301,6 +301,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { if (this.series && this.series.length > 0) { const lastPoint = _.last(this.series[0].datapoints); const lastValue = _.isArray(lastPoint) ? lastPoint[0] : null; + const formatFunc = getValueFormat(this.panel.format); if (this.panel.valueName === 'name') { data.value = 0; @@ -311,7 +312,6 @@ class SingleStatCtrl extends MetricsPanelCtrl { data.valueFormatted = _.escape(lastValue); data.valueRounded = 0; } else if (this.panel.valueName === 'last_time') { - const formatFunc = kbn.valueFormats[this.panel.format]; data.value = lastPoint[1]; data.valueRounded = data.value; data.valueFormatted = formatFunc(data.value, 0, 0, this.dashboard.isTimezoneUtc()); @@ -320,7 +320,6 @@ class SingleStatCtrl extends MetricsPanelCtrl { data.flotpairs = this.series[0].flotpairs; const decimalInfo = this.getDecimalsForValue(data.value); - const formatFunc = kbn.valueFormats[this.panel.format]; data.valueFormatted = formatFunc( data.value, diff --git a/public/app/plugins/panel/table/renderer.ts b/public/app/plugins/panel/table/renderer.ts index ccaf3ddf423..90479a67602 100644 --- a/public/app/plugins/panel/table/renderer.ts +++ b/public/app/plugins/panel/table/renderer.ts @@ -1,8 +1,7 @@ import _ from 'lodash'; import moment from 'moment'; import kbn from 'app/core/utils/kbn'; -import { getColorFromHexRgbOrName } from '@grafana/ui'; -import { GrafanaTheme } from '@grafana/ui'; +import { GrafanaTheme, getValueFormat, getColorFromHexRgbOrName } from '@grafana/ui'; export class TableRenderer { formatters: any[]; @@ -170,7 +169,7 @@ export class TableRenderer { } if (column.style.type === 'number') { - const valueFormatter = kbn.valueFormats[column.unit || column.style.unit]; + const valueFormatter = getValueFormat(column.unit || column.style.unit); return v => { if (v === null || v === void 0) { From ca7afc10a947e968e38f66b104a1b5120a14ff2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 07:30:45 +0100 Subject: [PATCH 34/43] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54d22ae7b99..c44bffcc4f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Minor +* **Templating**: Built in time range variables `$__from` and `$__to`, [#1909](https://github.com/grafana/grafana/issues/1909) * **Alerting**: Use separate timeouts for alert evals and notifications [#14701](https://github.com/grafana/grafana/issues/14701), thx [@sharkpc0813](https://github.com/sharkpc0813) * **Elasticsearch**: Add support for offset in date histogram aggregation [#12653](https://github.com/grafana/grafana/issues/12653), thx [@mattiarossi](https://github.com/mattiarossi) * **Elasticsearch**: Add support for moving average and derivative using doc count (metric count) [#8843](https://github.com/grafana/grafana/issues/8843) [#11175](https://github.com/grafana/grafana/issues/11175) From 08cfa5e32a6507e011776d9a0363f835c8e40f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 07:31:12 +0100 Subject: [PATCH 35/43] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c44bffcc4f6..e6fdc78842a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ -# 6.0.0-beta1 (unreleased) +# 6.0.0-beta2 (unreleased) + +# 6.0.0-beta1 (2019-01-30) ### New Features From ab812e73f69d97be511d069c6883e846366003f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 07:47:44 +0100 Subject: [PATCH 36/43] Updated what's new article --- docs/sources/guides/whats-new-in-v6-0.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/sources/guides/whats-new-in-v6-0.md b/docs/sources/guides/whats-new-in-v6-0.md index f1bf91f88d1..61eec0ac390 100644 --- a/docs/sources/guides/whats-new-in-v6-0.md +++ b/docs/sources/guides/whats-new-in-v6-0.md @@ -26,6 +26,7 @@ The main highlights are: - [Google Stackdriver Datasource]({{< relref "#google-stackdriver-datasource" >}}) is out of beta and is officially released. - [Azure Monitor]({{< relref "#azure-monitor-datasource" >}}) plugin is ported from being an external plugin to being a core datasource - [React Plugin]({{< relref "#react-panels-query-editors" >}}) support enables an easier way to build plugins. +- [Named Colors]({{< relref "#named-colors" >}}) in our new improved color picker. ## Explore @@ -110,6 +111,7 @@ source** plugins can be written in React using our published `@grafana/ui` sdk l will be shared closer to or just after release. {{< docs-imagebox img="/img/docs/v60/react_panels.png" max-width="600px" caption="React Panel" >}} +
### Google Stackdriver Datasource @@ -134,11 +136,23 @@ If you are using `Auth proxy` for authentication the session storage will still This release will force all users to log in again since their previous token is not valid anymore. +### Named Colors + +{{< docs-imagebox img="/img/docs/v60/named_colors.png" max-width="400px" class="docs-image--right" caption="Named Colors" >}} + +We have updated the color picker to show named colors and primary colors. We hope this will improve accessibility and +helps making colors more consistent across dashboards. We hope to do more in this color picker in the future, like show +colors used in the dashboard. + +Named colors also enables Grafana to adapt colors to the current theme. + +
+ ### Other features - The ElasticSearch datasource now supports [bucket script pipeline aggregations](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-bucket-script-aggregation.html). This gives the ability to do per bucket computations like the difference or ratio between two metrics. - - Support for Google Hangouts Chat alert notifications +- New built in template variables for the current time range in `$__from` and `$__to` ## Changelog From 474185c977b8721710becb468ab26feb12fbf368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 08:37:15 +0100 Subject: [PATCH 37/43] Moved a few things around --- .../DashboardRow}/DashboardRow.test.tsx | 4 ++-- .../DashboardRow}/DashboardRow.tsx | 4 ++-- .../dashboard/components/DashboardRow/index.ts | 1 + .../{dashboard_ctrl.ts => containers/DashboardCtrl.ts} | 4 ++-- .../app/features/dashboard/dashgrid/DashboardPanel.tsx | 2 +- public/app/features/dashboard/index.ts | 2 +- public/app/routes/ReactContainer.tsx | 10 +--------- public/sass/components/_view_states.scss | 1 + 8 files changed, 11 insertions(+), 17 deletions(-) rename public/app/features/dashboard/{specs => components/DashboardRow}/DashboardRow.test.tsx (93%) rename public/app/features/dashboard/{dashgrid => components/DashboardRow}/DashboardRow.tsx (96%) create mode 100644 public/app/features/dashboard/components/DashboardRow/index.ts rename public/app/features/dashboard/{dashboard_ctrl.ts => containers/DashboardCtrl.ts} (97%) diff --git a/public/app/features/dashboard/specs/DashboardRow.test.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx similarity index 93% rename from public/app/features/dashboard/specs/DashboardRow.test.tsx rename to public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx index 77c6cb39d9d..3e8c9b11159 100644 --- a/public/app/features/dashboard/specs/DashboardRow.test.tsx +++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { DashboardRow } from '../dashgrid/DashboardRow'; -import { PanelModel } from '../panel_model'; +import { DashboardRow } from './DashboardRow'; +import { PanelModel } from '../../panel_model'; describe('DashboardRow', () => { let wrapper, panel, dashboardMock; diff --git a/public/app/features/dashboard/dashgrid/DashboardRow.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx similarity index 96% rename from public/app/features/dashboard/dashgrid/DashboardRow.tsx rename to public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx index 5b8ced9b2b1..22feac4f99c 100644 --- a/public/app/features/dashboard/dashgrid/DashboardRow.tsx +++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classNames from 'classnames'; -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { PanelModel } from '../../panel_model'; +import { DashboardModel } from '../../dashboard_model'; import templateSrv from 'app/features/templating/template_srv'; import appEvents from 'app/core/app_events'; diff --git a/public/app/features/dashboard/components/DashboardRow/index.ts b/public/app/features/dashboard/components/DashboardRow/index.ts new file mode 100644 index 00000000000..3f71e03c80c --- /dev/null +++ b/public/app/features/dashboard/components/DashboardRow/index.ts @@ -0,0 +1 @@ +export { DashboardRow } from './DashboardRow'; diff --git a/public/app/features/dashboard/dashboard_ctrl.ts b/public/app/features/dashboard/containers/DashboardCtrl.ts similarity index 97% rename from public/app/features/dashboard/dashboard_ctrl.ts rename to public/app/features/dashboard/containers/DashboardCtrl.ts index 5c4480dbad5..d28c8acd830 100644 --- a/public/app/features/dashboard/dashboard_ctrl.ts +++ b/public/app/features/dashboard/containers/DashboardCtrl.ts @@ -5,10 +5,10 @@ import coreModule from 'app/core/core_module'; import { removePanel } from 'app/features/dashboard/utils/panel'; // Services -import { AnnotationsSrv } from '../annotations/annotations_srv'; +import { AnnotationsSrv } from '../../annotations/annotations_srv'; // Types -import { DashboardModel } from './dashboard_model'; +import { DashboardModel } from '../dashboard_model'; export class DashboardCtrl { dashboard: DashboardModel; diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index cfff64cb042..4838405e91b 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -7,7 +7,7 @@ import { importPluginModule } from 'app/features/plugins/plugin_loader'; import { AddPanelWidget } from '../components/AddPanelWidget'; import { getPanelPluginNotFound } from './PanelPluginNotFound'; -import { DashboardRow } from './DashboardRow'; +import { DashboardRow } from '../components/DashboardRow'; import { PanelChrome } from './PanelChrome'; import { PanelEditor } from '../panel_editor/PanelEditor'; diff --git a/public/app/features/dashboard/index.ts b/public/app/features/dashboard/index.ts index efa54f0ee07..750fdc25247 100644 --- a/public/app/features/dashboard/index.ts +++ b/public/app/features/dashboard/index.ts @@ -1,4 +1,4 @@ -import './dashboard_ctrl'; +import './containers/DashboardCtrl'; import './time_srv'; import './dashgrid/DashboardGridDirective'; diff --git a/public/app/routes/ReactContainer.tsx b/public/app/routes/ReactContainer.tsx index 807608e6960..19cdff03b69 100644 --- a/public/app/routes/ReactContainer.tsx +++ b/public/app/routes/ReactContainer.tsx @@ -4,8 +4,6 @@ import { Provider } from 'react-redux'; import coreModule from 'app/core/core_module'; import { store } from 'app/store/store'; -import { BackendSrv } from 'app/core/services/backend_srv'; -import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; import { ContextSrv } from 'app/core/services/context_srv'; function WrapInProvider(store, Component, props) { @@ -20,8 +18,6 @@ function WrapInProvider(store, Component, props) { export function reactContainer( $route, $location, - backendSrv: BackendSrv, - datasourceSrv: DatasourceSrv, contextSrv: ContextSrv ) { return { @@ -42,11 +38,7 @@ export function reactContainer( component = component.default; } - const props = { - backendSrv: backendSrv, - datasourceSrv: datasourceSrv, - routeParams: $route.current.params, - }; + const props = { }; ReactDOM.render(WrapInProvider(store, component, props), elem[0]); diff --git a/public/sass/components/_view_states.scss b/public/sass/components/_view_states.scss index b92bd596193..518d5d0f446 100644 --- a/public/sass/components/_view_states.scss +++ b/public/sass/components/_view_states.scss @@ -50,3 +50,4 @@ display: none; } } + From 6663b2fab9e354d1ddb94c8d054af0942979fa82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 08:44:46 +0100 Subject: [PATCH 38/43] Moved time_srv to services folder, this should not belong to dashboard feature but it is too dependant on dashboard to move it out now, needs a bigger refactoring to isolate from dashboard --- public/app/features/annotations/specs/annotations_srv.test.ts | 2 -- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 2 +- .../dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx | 2 +- public/app/features/dashboard/index.ts | 1 - .../{specs/time_srv.test.ts => services/TimeSrv.test.ts} | 3 +-- .../features/dashboard/{time_srv.ts => services/TimeSrv.ts} | 0 public/app/features/explore/QueryEditor.tsx | 2 +- public/app/features/templating/variable_srv.ts | 2 +- public/app/routes/GrafanaCtrl.ts | 2 +- 9 files changed, 6 insertions(+), 10 deletions(-) rename public/app/features/dashboard/{specs/time_srv.test.ts => services/TimeSrv.test.ts} (98%) rename public/app/features/dashboard/{time_srv.ts => services/TimeSrv.ts} (100%) diff --git a/public/app/features/annotations/specs/annotations_srv.test.ts b/public/app/features/annotations/specs/annotations_srv.test.ts index a00fc9b841d..f304c722b74 100644 --- a/public/app/features/annotations/specs/annotations_srv.test.ts +++ b/public/app/features/annotations/specs/annotations_srv.test.ts @@ -1,5 +1,3 @@ -import '../annotations_srv'; -import 'app/features/dashboard/time_srv'; import { AnnotationsSrv } from '../annotations_srv'; describe('AnnotationsSrv', () => { diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 359965bc9ad..b3d93ff556b 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -3,7 +3,7 @@ import React, { PureComponent } from 'react'; import { AutoSizer } from 'react-virtualized'; // Services -import { getTimeSrv, TimeSrv } from '../time_srv'; +import { getTimeSrv, TimeSrv } from '../services/TimeSrv'; // Components import { PanelHeader } from './PanelHeader/PanelHeader'; diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx index 4f5a74f820b..06f39876242 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx @@ -4,7 +4,7 @@ import { Tooltip } from '@grafana/ui'; import { PanelModel } from 'app/features/dashboard/panel_model'; import templateSrv from 'app/features/templating/template_srv'; import { LinkSrv } from 'app/features/panel/panellinks/link_srv'; -import { getTimeSrv, TimeSrv } from 'app/features/dashboard/time_srv'; +import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv'; enum InfoModes { Error = 'Error', diff --git a/public/app/features/dashboard/index.ts b/public/app/features/dashboard/index.ts index 750fdc25247..9f2935660ef 100644 --- a/public/app/features/dashboard/index.ts +++ b/public/app/features/dashboard/index.ts @@ -1,5 +1,4 @@ import './containers/DashboardCtrl'; -import './time_srv'; import './dashgrid/DashboardGridDirective'; // Services diff --git a/public/app/features/dashboard/specs/time_srv.test.ts b/public/app/features/dashboard/services/TimeSrv.test.ts similarity index 98% rename from public/app/features/dashboard/specs/time_srv.test.ts rename to public/app/features/dashboard/services/TimeSrv.test.ts index db0d11f2ebe..e5b4c240785 100644 --- a/public/app/features/dashboard/specs/time_srv.test.ts +++ b/public/app/features/dashboard/services/TimeSrv.test.ts @@ -1,5 +1,4 @@ -import { TimeSrv } from '../time_srv'; -import '../time_srv'; +import { TimeSrv } from './TimeSrv'; import moment from 'moment'; describe('timeSrv', () => { diff --git a/public/app/features/dashboard/time_srv.ts b/public/app/features/dashboard/services/TimeSrv.ts similarity index 100% rename from public/app/features/dashboard/time_srv.ts rename to public/app/features/dashboard/services/TimeSrv.ts diff --git a/public/app/features/explore/QueryEditor.tsx b/public/app/features/explore/QueryEditor.tsx index 266e6fb42df..083cd8a2e17 100644 --- a/public/app/features/explore/QueryEditor.tsx +++ b/public/app/features/explore/QueryEditor.tsx @@ -3,7 +3,7 @@ import React, { PureComponent } from 'react'; // Services import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; -import { getTimeSrv } from 'app/features/dashboard/time_srv'; +import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; // Types import { Emitter } from 'app/core/utils/emitter'; diff --git a/public/app/features/templating/variable_srv.ts b/public/app/features/templating/variable_srv.ts index dff798ace29..588bbb99d8e 100644 --- a/public/app/features/templating/variable_srv.ts +++ b/public/app/features/templating/variable_srv.ts @@ -7,7 +7,7 @@ import coreModule from 'app/core/core_module'; import { variableTypes } from './variable'; import { Graph } from 'app/core/utils/dag'; import { TemplateSrv } from 'app/features/templating/template_srv'; -import { TimeSrv } from 'app/features/dashboard/time_srv'; +import { TimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { DashboardModel } from 'app/features/dashboard/dashboard_model'; // Types diff --git a/public/app/routes/GrafanaCtrl.ts b/public/app/routes/GrafanaCtrl.ts index 4e4dd8121cf..70bdf49e5e4 100644 --- a/public/app/routes/GrafanaCtrl.ts +++ b/public/app/routes/GrafanaCtrl.ts @@ -8,7 +8,7 @@ import coreModule from 'app/core/core_module'; import { profiler } from 'app/core/profiler'; import appEvents from 'app/core/app_events'; import { BackendSrv, setBackendSrv } from 'app/core/services/backend_srv'; -import { TimeSrv, setTimeSrv } from 'app/features/dashboard/time_srv'; +import { TimeSrv, setTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { DatasourceSrv, setDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader'; import { configureStore } from 'app/store/configureStore'; From aafd4a339a4a4501fbf15b1b70fcf357659e27b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 08:56:17 +0100 Subject: [PATCH 39/43] Moved dashboard state components to state folder --- public/app/core/services/backend_srv.ts | 2 +- public/app/features/alerting/AlertTab.tsx | 4 ++-- public/app/features/alerting/StateHistory.tsx | 2 +- public/app/features/alerting/TestRuleResult.test.tsx | 2 +- public/app/features/alerting/TestRuleResult.tsx | 2 +- public/app/features/annotations/annotations_srv.ts | 2 +- .../dashboard/components/AddPanelWidget/AddPanelWidget.tsx | 4 ++-- .../components/DashExportModal/DashboardExporter.test.ts | 2 +- .../dashboard/components/DashExportModal/DashboardExporter.ts | 2 +- .../app/features/dashboard/components/DashNav/DashNavCtrl.ts | 2 +- .../dashboard/components/DashboardRow/DashboardRow.test.tsx | 2 +- .../dashboard/components/DashboardRow/DashboardRow.tsx | 4 ++-- .../dashboard/components/DashboardSettings/SettingsCtrl.ts | 2 +- .../dashboard/components/VersionHistory/HistoryListCtrl.ts | 2 +- .../dashboard/components/VersionHistory/HistorySrv.test.ts | 2 +- .../dashboard/components/VersionHistory/HistorySrv.ts | 2 +- public/app/features/dashboard/containers/DashboardCtrl.ts | 2 +- public/app/features/dashboard/dashgrid/DashboardGrid.tsx | 3 +-- public/app/features/dashboard/dashgrid/DashboardPanel.tsx | 3 +-- public/app/features/dashboard/dashgrid/PanelChrome.tsx | 4 ++-- .../features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx | 4 ++-- .../dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx | 2 +- .../dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx | 4 ++-- public/app/features/dashboard/dashgrid/PanelResizer.tsx | 2 +- public/app/features/dashboard/panel_editor/GeneralTab.tsx | 2 +- public/app/features/dashboard/panel_editor/PanelEditor.tsx | 4 ++-- public/app/features/dashboard/panel_editor/QueriesTab.tsx | 4 ++-- public/app/features/dashboard/panel_editor/QueryEditorRow.tsx | 2 +- public/app/features/dashboard/panel_editor/QueryOptions.tsx | 2 +- .../app/features/dashboard/panel_editor/VisualizationTab.tsx | 4 ++-- public/app/features/dashboard/services/ChangeTracker.test.ts | 4 ++-- public/app/features/dashboard/services/ChangeTracker.ts | 2 +- public/app/features/dashboard/services/DashboardSrv.ts | 2 +- .../features/dashboard/services/DashboardViewStateSrv.test.ts | 2 +- .../app/features/dashboard/services/DashboardViewStateSrv.ts | 2 +- .../DashboardMigrator.test.ts} | 4 ++-- .../{dashboard_migration.ts => state/DashboardMigrator.ts} | 4 ++-- .../repeat.test.ts => state/DashboardModel.repeat.test.ts} | 2 +- .../dashboard_model.test.ts => state/DashboardModel.test.ts} | 4 ++-- .../dashboard/{dashboard_model.ts => state/DashboardModel.ts} | 4 ++-- .../{specs/panel_model.test.ts => state/PanelModel.test.ts} | 2 +- .../dashboard/{panel_model.ts => state/PanelModel.ts} | 0 public/app/features/dashboard/state/index.ts | 2 ++ public/app/features/dashboard/utils/getPanelMenu.ts | 4 ++-- public/app/features/dashboard/utils/panel.ts | 4 ++-- public/app/features/panel/specs/metrics_panel_ctrl.test.ts | 2 +- public/app/features/templating/specs/variable_srv.test.ts | 2 +- .../app/features/templating/specs/variable_srv_init.test.ts | 2 +- public/app/features/templating/variable_srv.ts | 2 +- public/test/specs/helpers.ts | 2 +- 50 files changed, 66 insertions(+), 66 deletions(-) rename public/app/features/dashboard/{specs/dashboard_migration.test.ts => state/DashboardMigrator.test.ts} (99%) rename public/app/features/dashboard/{dashboard_migration.ts => state/DashboardMigrator.ts} (99%) rename public/app/features/dashboard/{specs/repeat.test.ts => state/DashboardModel.repeat.test.ts} (99%) rename public/app/features/dashboard/{specs/dashboard_model.test.ts => state/DashboardModel.test.ts} (99%) rename public/app/features/dashboard/{dashboard_model.ts => state/DashboardModel.ts} (99%) rename public/app/features/dashboard/{specs/panel_model.test.ts => state/PanelModel.test.ts} (96%) rename public/app/features/dashboard/{panel_model.ts => state/PanelModel.ts} (100%) create mode 100644 public/app/features/dashboard/state/index.ts diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index 854169ad4b0..38d7f2b76cb 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import coreModule from 'app/core/core_module'; import appEvents from 'app/core/app_events'; -import { DashboardModel } from 'app/features/dashboard/dashboard_model'; +import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; export class BackendSrv { private inFlightRequests = {}; diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index 549d84c2808..6343b4ca2c9 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -12,8 +12,8 @@ import StateHistory from './StateHistory'; import 'app/features/alerting/AlertTabCtrl'; // Types -import { DashboardModel } from '../dashboard/dashboard_model'; -import { PanelModel } from '../dashboard/panel_model'; +import { DashboardModel } from '../dashboard/state/DashboardModel'; +import { PanelModel } from '../dashboard/state/PanelModel'; import { TestRuleResult } from './TestRuleResult'; interface Props { diff --git a/public/app/features/alerting/StateHistory.tsx b/public/app/features/alerting/StateHistory.tsx index eb5541f6094..be34552e50d 100644 --- a/public/app/features/alerting/StateHistory.tsx +++ b/public/app/features/alerting/StateHistory.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import alertDef from './state/alertDef'; import { getBackendSrv } from 'app/core/services/backend_srv'; -import { DashboardModel } from '../dashboard/dashboard_model'; +import { DashboardModel } from '../dashboard/state/DashboardModel'; import appEvents from '../../core/app_events'; interface Props { diff --git a/public/app/features/alerting/TestRuleResult.test.tsx b/public/app/features/alerting/TestRuleResult.test.tsx index 9beb5ade632..ff8422ccf4b 100644 --- a/public/app/features/alerting/TestRuleResult.test.tsx +++ b/public/app/features/alerting/TestRuleResult.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { DashboardModel } from '../dashboard/dashboard_model'; +import { DashboardModel } from '../dashboard/state/DashboardModel'; import { Props, TestRuleResult } from './TestRuleResult'; jest.mock('app/core/services/backend_srv', () => ({ diff --git a/public/app/features/alerting/TestRuleResult.tsx b/public/app/features/alerting/TestRuleResult.tsx index 4014e529597..e8f0551d707 100644 --- a/public/app/features/alerting/TestRuleResult.tsx +++ b/public/app/features/alerting/TestRuleResult.tsx @@ -1,7 +1,7 @@ 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 { DashboardModel } from '../dashboard/state/DashboardModel'; import { LoadingPlaceholder } from '@grafana/ui/src'; export interface Props { diff --git a/public/app/features/annotations/annotations_srv.ts b/public/app/features/annotations/annotations_srv.ts index 1f580319188..d728adfca2e 100644 --- a/public/app/features/annotations/annotations_srv.ts +++ b/public/app/features/annotations/annotations_srv.ts @@ -10,7 +10,7 @@ import coreModule from 'app/core/core_module'; import { makeRegions, dedupAnnotations } from './events_processing'; // Types -import { DashboardModel } from '../dashboard/dashboard_model'; +import { DashboardModel } from '../dashboard/state/DashboardModel'; export class AnnotationsSrv { globalAnnotationsPromise: any; diff --git a/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx b/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx index 4d46d88a1d2..8c1ab93cec1 100644 --- a/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx +++ b/public/app/features/dashboard/components/AddPanelWidget/AddPanelWidget.tsx @@ -1,8 +1,8 @@ import React from 'react'; import _ from 'lodash'; import config from 'app/core/config'; -import { PanelModel } from '../../panel_model'; -import { DashboardModel } from '../../dashboard_model'; +import { PanelModel } from '../../state/PanelModel'; +import { DashboardModel } from '../../state/DashboardModel'; import store from 'app/core/store'; import { LS_PANEL_COPY_KEY } from 'app/core/constants'; import { updateLocation } from 'app/core/actions'; diff --git a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts index 20ab21541a5..ac1b5f08632 100644 --- a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts +++ b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.test.ts @@ -7,7 +7,7 @@ jest.mock('app/core/store', () => { import _ from 'lodash'; import config from 'app/core/config'; import { DashboardExporter } from './DashboardExporter'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; describe('given dashboard with repeated panels', () => { let dash, exported; diff --git a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts index 22b93b767d6..6cf14f81c86 100644 --- a/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts +++ b/public/app/features/dashboard/components/DashExportModal/DashboardExporter.ts @@ -1,6 +1,6 @@ import config from 'app/core/config'; import _ from 'lodash'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; export class DashboardExporter { constructor(private datasourceSrv) {} diff --git a/public/app/features/dashboard/components/DashNav/DashNavCtrl.ts b/public/app/features/dashboard/components/DashNav/DashNavCtrl.ts index d7305b948dc..e75c1468a1f 100644 --- a/public/app/features/dashboard/components/DashNav/DashNavCtrl.ts +++ b/public/app/features/dashboard/components/DashNav/DashNavCtrl.ts @@ -1,7 +1,7 @@ import moment from 'moment'; import angular from 'angular'; import { appEvents, NavModel } from 'app/core/core'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; export class DashNavCtrl { dashboard: DashboardModel; diff --git a/public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx index 3e8c9b11159..9ac6a6b74e1 100644 --- a/public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx +++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { DashboardRow } from './DashboardRow'; -import { PanelModel } from '../../panel_model'; +import { PanelModel } from '../../state/PanelModel'; describe('DashboardRow', () => { let wrapper, panel, dashboardMock; diff --git a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx index 22feac4f99c..f9a56718c5e 100644 --- a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx +++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classNames from 'classnames'; -import { PanelModel } from '../../panel_model'; -import { DashboardModel } from '../../dashboard_model'; +import { PanelModel } from '../../state/PanelModel'; +import { DashboardModel } from '../../state/DashboardModel'; import templateSrv from 'app/features/templating/template_srv'; import appEvents from 'app/core/app_events'; diff --git a/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts b/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts index a0eb5c8c6b3..e5cfac97d5f 100755 --- a/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts +++ b/public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts @@ -1,5 +1,5 @@ import { coreModule, appEvents, contextSrv } from 'app/core/core'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; import $ from 'jquery'; import _ from 'lodash'; import angular from 'angular'; diff --git a/public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.ts b/public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.ts index b8632e2eeae..19795ffc564 100644 --- a/public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.ts +++ b/public/app/features/dashboard/components/VersionHistory/HistoryListCtrl.ts @@ -3,7 +3,7 @@ import angular from 'angular'; import moment from 'moment'; import locationUtil from 'app/core/utils/location_util'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; import { HistoryListOpts, RevisionsModel, CalculateDiffOptions, HistorySrv } from './HistorySrv'; export class HistoryListCtrl { diff --git a/public/app/features/dashboard/components/VersionHistory/HistorySrv.test.ts b/public/app/features/dashboard/components/VersionHistory/HistorySrv.test.ts index 75766060e7f..04f0eff1cb8 100644 --- a/public/app/features/dashboard/components/VersionHistory/HistorySrv.test.ts +++ b/public/app/features/dashboard/components/VersionHistory/HistorySrv.test.ts @@ -1,6 +1,6 @@ import { versions, restore } from './__mocks__/history'; import { HistorySrv } from './HistorySrv'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; jest.mock('app/core/store'); describe('historySrv', () => { diff --git a/public/app/features/dashboard/components/VersionHistory/HistorySrv.ts b/public/app/features/dashboard/components/VersionHistory/HistorySrv.ts index d52f3ab879c..a06212f9a7a 100644 --- a/public/app/features/dashboard/components/VersionHistory/HistorySrv.ts +++ b/public/app/features/dashboard/components/VersionHistory/HistorySrv.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; import coreModule from 'app/core/core_module'; -import { DashboardModel } from '../../dashboard_model'; +import { DashboardModel } from '../../state/DashboardModel'; export interface HistoryListOpts { limit: number; diff --git a/public/app/features/dashboard/containers/DashboardCtrl.ts b/public/app/features/dashboard/containers/DashboardCtrl.ts index d28c8acd830..74795315504 100644 --- a/public/app/features/dashboard/containers/DashboardCtrl.ts +++ b/public/app/features/dashboard/containers/DashboardCtrl.ts @@ -8,7 +8,7 @@ import { removePanel } from 'app/features/dashboard/utils/panel'; import { AnnotationsSrv } from '../../annotations/annotations_srv'; // Types -import { DashboardModel } from '../dashboard_model'; +import { DashboardModel } from '../state/DashboardModel'; export class DashboardCtrl { dashboard: DashboardModel; diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index c9c1dd0d7b0..658bfad3816 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -3,8 +3,7 @@ import { hot } from 'react-hot-loader'; import ReactGridLayout, { ItemCallback } 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'; -import { PanelModel } from '../panel_model'; +import { DashboardModel, PanelModel } from '../state'; import classNames from 'classnames'; import sizeMe from 'react-sizeme'; diff --git a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx index 4838405e91b..2d794bec4d4 100644 --- a/public/app/features/dashboard/dashgrid/DashboardPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardPanel.tsx @@ -11,8 +11,7 @@ import { DashboardRow } from '../components/DashboardRow'; import { PanelChrome } from './PanelChrome'; import { PanelEditor } from '../panel_editor/PanelEditor'; -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { PanelModel, DashboardModel } from '../state'; import { PanelPlugin } from 'app/types'; import { PanelResizer } from './PanelResizer'; diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index b3d93ff556b..bdb6aca870a 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -14,8 +14,8 @@ import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; import { PANEL_HEADER_HEIGHT } from 'app/core/constants'; // Types -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { PanelModel } from '../state/PanelModel'; +import { DashboardModel } from '../state/DashboardModel'; import { PanelPlugin } from 'app/types'; import { TimeRange } from '@grafana/ui'; diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx index 6dd4af2dc03..ebc89673387 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx @@ -6,8 +6,8 @@ import PanelHeaderCorner from './PanelHeaderCorner'; import { PanelHeaderMenu } from './PanelHeaderMenu'; import templateSrv from 'app/features/templating/template_srv'; -import { DashboardModel } from 'app/features/dashboard/dashboard_model'; -import { PanelModel } from 'app/features/dashboard/panel_model'; +import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { ClickOutsideWrapper } from 'app/core/components/ClickOutsideWrapper/ClickOutsideWrapper'; export interface Props { diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx index 06f39876242..159c9d92914 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import Remarkable from 'remarkable'; import { Tooltip } from '@grafana/ui'; -import { PanelModel } from 'app/features/dashboard/panel_model'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import templateSrv from 'app/features/templating/template_srv'; import { LinkSrv } from 'app/features/panel/panellinks/link_srv'; import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv'; diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx index 1d17ec6cefc..5a0b6bbecb6 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; -import { DashboardModel } from 'app/features/dashboard/dashboard_model'; -import { PanelModel } from 'app/features/dashboard/panel_model'; +import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { PanelHeaderMenuItem } from './PanelHeaderMenuItem'; import { getPanelMenu } from 'app/features/dashboard/utils/getPanelMenu'; import { PanelMenuItem } from '@grafana/ui'; diff --git a/public/app/features/dashboard/dashgrid/PanelResizer.tsx b/public/app/features/dashboard/dashgrid/PanelResizer.tsx index 1ee5b3884a0..4571b5bcbf5 100644 --- a/public/app/features/dashboard/dashgrid/PanelResizer.tsx +++ b/public/app/features/dashboard/dashgrid/PanelResizer.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { throttle } from 'lodash'; import Draggable, { DraggableEventHandler } from 'react-draggable'; -import { PanelModel } from '../panel_model'; +import { PanelModel } from '../state/PanelModel'; interface Props { isEditing: boolean; diff --git a/public/app/features/dashboard/panel_editor/GeneralTab.tsx b/public/app/features/dashboard/panel_editor/GeneralTab.tsx index 91e236c8b31..d91737195f1 100644 --- a/public/app/features/dashboard/panel_editor/GeneralTab.tsx +++ b/public/app/features/dashboard/panel_editor/GeneralTab.tsx @@ -3,7 +3,7 @@ import React, { PureComponent } from 'react'; import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; import { EditorTabBody } from './EditorTabBody'; -import { PanelModel } from '../panel_model'; +import { PanelModel } from '../state/PanelModel'; import './../../panel/GeneralTabCtrl'; interface Props { diff --git a/public/app/features/dashboard/panel_editor/PanelEditor.tsx b/public/app/features/dashboard/panel_editor/PanelEditor.tsx index 123204aa239..7b8097b9f65 100644 --- a/public/app/features/dashboard/panel_editor/PanelEditor.tsx +++ b/public/app/features/dashboard/panel_editor/PanelEditor.tsx @@ -11,8 +11,8 @@ import { store } from 'app/store/store'; import { updateLocation } from 'app/core/actions'; import { AngularComponent } from 'app/core/services/AngularLoader'; -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { PanelModel } from '../state/PanelModel'; +import { DashboardModel } from '../state/DashboardModel'; import { PanelPlugin } from 'app/types/plugins'; import { Tooltip } from '@grafana/ui'; diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 28d822e3ad5..140bb4b0fd7 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -16,8 +16,8 @@ import { BackendSrv, getBackendSrv } from 'app/core/services/backend_srv'; import config from 'app/core/config'; // Types -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { PanelModel } from '../state/PanelModel'; +import { DashboardModel } from '../state/DashboardModel'; import { DataQuery, DataSourceSelectItem } from '@grafana/ui/src/types'; import { PluginHelp } from 'app/core/components/PluginHelp/PluginHelp'; diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index 2651ab0608c..b07b4be6f56 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -9,7 +9,7 @@ import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoa import { Emitter } from 'app/core/utils/emitter'; // Types -import { PanelModel } from '../panel_model'; +import { PanelModel } from '../state/PanelModel'; import { DataQuery, DataSourceApi } from '@grafana/ui'; interface Props { diff --git a/public/app/features/dashboard/panel_editor/QueryOptions.tsx b/public/app/features/dashboard/panel_editor/QueryOptions.tsx index 2ffa4ef59d3..d203f3bc25f 100644 --- a/public/app/features/dashboard/panel_editor/QueryOptions.tsx +++ b/public/app/features/dashboard/panel_editor/QueryOptions.tsx @@ -13,7 +13,7 @@ import DataSourceOption from './DataSourceOption'; import { FormLabel } from '@grafana/ui'; // Types -import { PanelModel } from '../panel_model'; +import { PanelModel } from '../state/PanelModel'; import { DataSourceSelectItem } from '@grafana/ui/src/types'; import { ValidationEvents } from 'app/types'; diff --git a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx index 64bf3165ddc..35b9b71112a 100644 --- a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx +++ b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx @@ -11,8 +11,8 @@ import { PluginHelp } from 'app/core/components/PluginHelp/PluginHelp'; import { FadeIn } from 'app/core/components/Animations/FadeIn'; // Types -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { PanelModel } from '../state/PanelModel'; +import { DashboardModel } from '../state/DashboardModel'; import { PanelPlugin } from 'app/types/plugins'; interface Props { diff --git a/public/app/features/dashboard/services/ChangeTracker.test.ts b/public/app/features/dashboard/services/ChangeTracker.test.ts index dfc9b3fa03f..31e5f8f5052 100644 --- a/public/app/features/dashboard/services/ChangeTracker.test.ts +++ b/public/app/features/dashboard/services/ChangeTracker.test.ts @@ -1,7 +1,7 @@ import { ChangeTracker } from './ChangeTracker'; import { contextSrv } from 'app/core/services/context_srv'; -import { DashboardModel } from '../dashboard_model'; -import { PanelModel } from '../panel_model'; +import { DashboardModel } from '../state/DashboardModel'; +import { PanelModel } from '../state/PanelModel'; jest.mock('app/core/services/context_srv', () => ({ contextSrv: { diff --git a/public/app/features/dashboard/services/ChangeTracker.ts b/public/app/features/dashboard/services/ChangeTracker.ts index ef3d456db48..77434525085 100644 --- a/public/app/features/dashboard/services/ChangeTracker.ts +++ b/public/app/features/dashboard/services/ChangeTracker.ts @@ -1,6 +1,6 @@ import angular from 'angular'; import _ from 'lodash'; -import { DashboardModel } from '../dashboard_model'; +import { DashboardModel } from '../state/DashboardModel'; export class ChangeTracker { current: any; diff --git a/public/app/features/dashboard/services/DashboardSrv.ts b/public/app/features/dashboard/services/DashboardSrv.ts index 67a4938c6aa..03aeb34ed36 100644 --- a/public/app/features/dashboard/services/DashboardSrv.ts +++ b/public/app/features/dashboard/services/DashboardSrv.ts @@ -1,5 +1,5 @@ import coreModule from 'app/core/core_module'; -import { DashboardModel } from '../dashboard_model'; +import { DashboardModel } from '../state/DashboardModel'; import locationUtil from 'app/core/utils/location_util'; export class DashboardSrv { diff --git a/public/app/features/dashboard/services/DashboardViewStateSrv.test.ts b/public/app/features/dashboard/services/DashboardViewStateSrv.test.ts index 20215017e1d..12bb11b7a08 100644 --- a/public/app/features/dashboard/services/DashboardViewStateSrv.test.ts +++ b/public/app/features/dashboard/services/DashboardViewStateSrv.test.ts @@ -1,6 +1,6 @@ import config from 'app/core/config'; import { DashboardViewStateSrv } from './DashboardViewStateSrv'; -import { DashboardModel } from '../dashboard_model'; +import { DashboardModel } from '../state/DashboardModel'; describe('when updating view state', () => { const location = { diff --git a/public/app/features/dashboard/services/DashboardViewStateSrv.ts b/public/app/features/dashboard/services/DashboardViewStateSrv.ts index 816b6d8bd2d..fc38c3b241f 100644 --- a/public/app/features/dashboard/services/DashboardViewStateSrv.ts +++ b/public/app/features/dashboard/services/DashboardViewStateSrv.ts @@ -2,7 +2,7 @@ import angular from 'angular'; import _ from 'lodash'; import config from 'app/core/config'; import appEvents from 'app/core/app_events'; -import { DashboardModel } from '../dashboard_model'; +import { DashboardModel } from '../state/DashboardModel'; // represents the transient view state // like fullscreen panel & edit diff --git a/public/app/features/dashboard/specs/dashboard_migration.test.ts b/public/app/features/dashboard/state/DashboardMigrator.test.ts similarity index 99% rename from public/app/features/dashboard/specs/dashboard_migration.test.ts rename to public/app/features/dashboard/state/DashboardMigrator.test.ts index e15bd65d5a5..fdb309b5db5 100644 --- a/public/app/features/dashboard/specs/dashboard_migration.test.ts +++ b/public/app/features/dashboard/state/DashboardMigrator.test.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; -import { DashboardModel } from '../dashboard_model'; -import { PanelModel } from '../panel_model'; +import { DashboardModel } from '../state/DashboardModel'; +import { PanelModel } from '../state/PanelModel'; import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants'; import { expect } from 'test/lib/common'; diff --git a/public/app/features/dashboard/dashboard_migration.ts b/public/app/features/dashboard/state/DashboardMigrator.ts similarity index 99% rename from public/app/features/dashboard/dashboard_migration.ts rename to public/app/features/dashboard/state/DashboardMigrator.ts index 2dbeb6c6e80..ba631102b81 100644 --- a/public/app/features/dashboard/dashboard_migration.ts +++ b/public/app/features/dashboard/state/DashboardMigrator.ts @@ -7,8 +7,8 @@ import { MIN_PANEL_HEIGHT, DEFAULT_PANEL_SPAN, } from 'app/core/constants'; -import { PanelModel } from './panel_model'; -import { DashboardModel } from './dashboard_model'; +import { PanelModel } from './PanelModel'; +import { DashboardModel } from './DashboardModel'; import getFactors from 'app/core/utils/factors'; export class DashboardMigrator { diff --git a/public/app/features/dashboard/specs/repeat.test.ts b/public/app/features/dashboard/state/DashboardModel.repeat.test.ts similarity index 99% rename from public/app/features/dashboard/specs/repeat.test.ts rename to public/app/features/dashboard/state/DashboardModel.repeat.test.ts index 49fb4ea9ee7..723cf1f9d16 100644 --- a/public/app/features/dashboard/specs/repeat.test.ts +++ b/public/app/features/dashboard/state/DashboardModel.repeat.test.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { DashboardModel } from '../dashboard_model'; +import { DashboardModel } from '../state/DashboardModel'; import { expect } from 'test/lib/common'; jest.mock('app/core/services/context_srv', () => ({})); diff --git a/public/app/features/dashboard/specs/dashboard_model.test.ts b/public/app/features/dashboard/state/DashboardModel.test.ts similarity index 99% rename from public/app/features/dashboard/specs/dashboard_model.test.ts rename to public/app/features/dashboard/state/DashboardModel.test.ts index e59d52f2410..cd30fc2ecdc 100644 --- a/public/app/features/dashboard/specs/dashboard_model.test.ts +++ b/public/app/features/dashboard/state/DashboardModel.test.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; -import { DashboardModel } from '../dashboard_model'; -import { PanelModel } from '../panel_model'; +import { DashboardModel } from '../state/DashboardModel'; +import { PanelModel } from '../state/PanelModel'; jest.mock('app/core/services/context_srv', () => ({})); diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/state/DashboardModel.ts similarity index 99% rename from public/app/features/dashboard/dashboard_model.ts rename to public/app/features/dashboard/state/DashboardModel.ts index f7cc49223df..06dc9450425 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -7,8 +7,8 @@ import { Emitter } from 'app/core/utils/emitter'; import { contextSrv } from 'app/core/services/context_srv'; import sortByKeys from 'app/core/utils/sort_by_keys'; -import { PanelModel } from './panel_model'; -import { DashboardMigrator } from './dashboard_migration'; +import { PanelModel } from './PanelModel'; +import { DashboardMigrator } from './DashboardMigrator'; import { TimeRange } from '@grafana/ui/src'; export class DashboardModel { diff --git a/public/app/features/dashboard/specs/panel_model.test.ts b/public/app/features/dashboard/state/PanelModel.test.ts similarity index 96% rename from public/app/features/dashboard/specs/panel_model.test.ts rename to public/app/features/dashboard/state/PanelModel.test.ts index 89976fa275a..b751caaa8f1 100644 --- a/public/app/features/dashboard/specs/panel_model.test.ts +++ b/public/app/features/dashboard/state/PanelModel.test.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { PanelModel } from '../panel_model'; +import { PanelModel } from '../state/PanelModel'; describe('PanelModel', () => { describe('when creating new panel model', () => { diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/state/PanelModel.ts similarity index 100% rename from public/app/features/dashboard/panel_model.ts rename to public/app/features/dashboard/state/PanelModel.ts diff --git a/public/app/features/dashboard/state/index.ts b/public/app/features/dashboard/state/index.ts new file mode 100644 index 00000000000..253d4aa7ac3 --- /dev/null +++ b/public/app/features/dashboard/state/index.ts @@ -0,0 +1,2 @@ +export { DashboardModel } from './DashboardModel'; +export { PanelModel } from './PanelModel'; diff --git a/public/app/features/dashboard/utils/getPanelMenu.ts b/public/app/features/dashboard/utils/getPanelMenu.ts index 190451671ad..568e9ba4f7f 100644 --- a/public/app/features/dashboard/utils/getPanelMenu.ts +++ b/public/app/features/dashboard/utils/getPanelMenu.ts @@ -2,8 +2,8 @@ import { updateLocation } from 'app/core/actions'; import { store } from 'app/store/store'; import { removePanel, duplicatePanel, copyPanel, editPanelJson, sharePanel } from 'app/features/dashboard/utils/panel'; -import { PanelModel } from 'app/features/dashboard/panel_model'; -import { DashboardModel } from 'app/features/dashboard/dashboard_model'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; +import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelMenuItem } from '@grafana/ui'; export const getPanelMenu = (dashboard: DashboardModel, panel: PanelModel) => { diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index cfbe094125f..c0d753477a7 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -2,8 +2,8 @@ import store from 'app/core/store'; // Models -import { DashboardModel } from 'app/features/dashboard/dashboard_model'; -import { PanelModel } from 'app/features/dashboard/panel_model'; +import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { TimeRange } from '@grafana/ui'; // Utils diff --git a/public/app/features/panel/specs/metrics_panel_ctrl.test.ts b/public/app/features/panel/specs/metrics_panel_ctrl.test.ts index 8b9607d39ad..d647af616a9 100644 --- a/public/app/features/panel/specs/metrics_panel_ctrl.test.ts +++ b/public/app/features/panel/specs/metrics_panel_ctrl.test.ts @@ -11,7 +11,7 @@ jest.mock('app/core/config', () => { }); import q from 'q'; -import { PanelModel } from 'app/features/dashboard/panel_model'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { MetricsPanelCtrl } from '../metrics_panel_ctrl'; describe('MetricsPanelCtrl', () => { diff --git a/public/app/features/templating/specs/variable_srv.test.ts b/public/app/features/templating/specs/variable_srv.test.ts index 7e5d0ff98c7..db42df7f516 100644 --- a/public/app/features/templating/specs/variable_srv.test.ts +++ b/public/app/features/templating/specs/variable_srv.test.ts @@ -1,6 +1,6 @@ import '../all'; import { VariableSrv } from '../variable_srv'; -import { DashboardModel } from '../../dashboard/dashboard_model'; +import { DashboardModel } from '../../dashboard/state/DashboardModel'; import moment from 'moment'; import $q from 'q'; diff --git a/public/app/features/templating/specs/variable_srv_init.test.ts b/public/app/features/templating/specs/variable_srv_init.test.ts index 4e5e025522f..b8cabf711ac 100644 --- a/public/app/features/templating/specs/variable_srv_init.test.ts +++ b/public/app/features/templating/specs/variable_srv_init.test.ts @@ -2,7 +2,7 @@ import '../all'; import _ from 'lodash'; import { VariableSrv } from '../variable_srv'; -import { DashboardModel } from '../../dashboard/dashboard_model'; +import { DashboardModel } from '../../dashboard/state/DashboardModel'; import $q from 'q'; describe('VariableSrv init', function(this: any) { diff --git a/public/app/features/templating/variable_srv.ts b/public/app/features/templating/variable_srv.ts index 588bbb99d8e..b2f8b43fb08 100644 --- a/public/app/features/templating/variable_srv.ts +++ b/public/app/features/templating/variable_srv.ts @@ -8,7 +8,7 @@ import { variableTypes } from './variable'; import { Graph } from 'app/core/utils/dag'; import { TemplateSrv } from 'app/features/templating/template_srv'; import { TimeSrv } from 'app/features/dashboard/services/TimeSrv'; -import { DashboardModel } from 'app/features/dashboard/dashboard_model'; +import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; // Types import { TimeRange } from '@grafana/ui/src'; diff --git a/public/test/specs/helpers.ts b/public/test/specs/helpers.ts index 536b277eec3..1570c7dd9b7 100644 --- a/public/test/specs/helpers.ts +++ b/public/test/specs/helpers.ts @@ -2,7 +2,7 @@ import _ from 'lodash'; import config from 'app/core/config'; import * as dateMath from 'app/core/utils/datemath'; import { angularMocks, sinon } from '../lib/common'; -import { PanelModel } from 'app/features/dashboard/panel_model'; +import { PanelModel } from 'app/features/dashboard/state/PanelModel'; export function ControllerTestContext(this: any) { const self = this; From ddfccec2ead1c5fda72d3a02057054dc5863fba8 Mon Sep 17 00:00:00 2001 From: Leonard Gram Date: Thu, 31 Jan 2019 09:40:18 +0100 Subject: [PATCH 40/43] build: enterprise release co project. --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 209cf5c98cc..8144956773b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -333,6 +333,7 @@ jobs: docker: - image: grafana/grafana-ci-deploy:1.2.0 steps: + - checkout - attach_workspace: at: . - run: From a43c00ce708b346bd68b6e0125a8a55a57cf3d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 31 Jan 2019 11:37:34 +0100 Subject: [PATCH 41/43] Fixed row options html template location, fixes #15157 --- .../features/dashboard/components/RowOptions/RowOptionsCtrl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/dashboard/components/RowOptions/RowOptionsCtrl.ts b/public/app/features/dashboard/components/RowOptions/RowOptionsCtrl.ts index a855791f1ea..d2526c92cd0 100644 --- a/public/app/features/dashboard/components/RowOptions/RowOptionsCtrl.ts +++ b/public/app/features/dashboard/components/RowOptions/RowOptionsCtrl.ts @@ -24,7 +24,7 @@ export class RowOptionsCtrl { export function rowOptionsDirective() { return { restrict: 'E', - templateUrl: 'public/app/features/dashboard/partials/row_options.html', + templateUrl: 'public/app/features/dashboard/components/RowOptions/template.html', controller: RowOptionsCtrl, bindToController: true, controllerAs: 'ctrl', From a2cba6685c78f37958e11172fc6a92eb93bb5daa Mon Sep 17 00:00:00 2001 From: Dominik Prokop Date: Thu, 31 Jan 2019 12:20:55 +0100 Subject: [PATCH 42/43] Do not render time region line or fill if colors not provided --- .../graph/specs/time_region_manager.test.ts | 19 +++++++++++++++++++ .../panel/graph/time_region_manager.ts | 8 ++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/panel/graph/specs/time_region_manager.test.ts b/public/app/plugins/panel/graph/specs/time_region_manager.test.ts index fc0b86d1b68..691247a0f75 100644 --- a/public/app/plugins/panel/graph/specs/time_region_manager.test.ts +++ b/public/app/plugins/panel/graph/specs/time_region_manager.test.ts @@ -43,6 +43,25 @@ describe('TimeRegionManager', () => { }); } + describe('When colors missing in config', () => { + plotOptionsScenario('should not throw an error when fillColor is undefined', ctx => { + const regions = [ + { fromDayOfWeek: 1, toDayOfWeek: 1, fill: true, line: true, lineColor: '#ffffff', colorMode: 'custom' }, + ]; + const from = moment('2018-01-01T00:00:00+01:00'); + const to = moment('2018-01-01T23:59:00+01:00'); + expect(() => ctx.setup(regions, from, to)).not.toThrow(); + }); + plotOptionsScenario('should not throw an error when lineColor is undefined', ctx => { + const regions = [ + { fromDayOfWeek: 1, toDayOfWeek: 1, fill: true, fillColor: '#ffffff', line: true, colorMode: 'custom' }, + ]; + const from = moment('2018-01-01T00:00:00+01:00'); + const to = moment('2018-01-01T23:59:00+01:00'); + expect(() => ctx.setup(regions, from, to)).not.toThrow(); + }); + }); + describe('When creating plot markings using local time', () => { plotOptionsScenario('for day of week region', ctx => { const regions = [{ fromDayOfWeek: 1, toDayOfWeek: 1, fill: true, line: true, colorMode: 'red' }]; diff --git a/public/app/plugins/panel/graph/time_region_manager.ts b/public/app/plugins/panel/graph/time_region_manager.ts index be5de722fe2..2917583ff36 100644 --- a/public/app/plugins/panel/graph/time_region_manager.ts +++ b/public/app/plugins/panel/graph/time_region_manager.ts @@ -50,8 +50,8 @@ function getColor(timeRegion, theme: GrafanaTheme): TimeRegionColorDefinition { if (timeRegion.colorMode === 'custom') { return { - fill: getColorFromHexRgbOrName(timeRegion.fillColor, theme), - line: getColorFromHexRgbOrName(timeRegion.lineColor, theme), + fill: timeRegion.fill && timeRegion.fillColor ? getColorFromHexRgbOrName(timeRegion.fillColor, theme) : null, + line: timeRegion.line && timeRegion.lineColor ? getColorFromHexRgbOrName(timeRegion.lineColor, theme) : null, }; } @@ -62,8 +62,8 @@ function getColor(timeRegion, theme: GrafanaTheme): TimeRegionColorDefinition { } return { - fill: getColorFromHexRgbOrName(colorMode.color.fill, theme), - line: getColorFromHexRgbOrName(colorMode.color.line, theme), + fill: timeRegion.fill ? getColorFromHexRgbOrName(colorMode.color.fill, theme) : null, + line: timeRegion.fill ? getColorFromHexRgbOrName(colorMode.color.line, theme) : null, }; } From 53331772ef465484b3fbcd3c61bc61185cbc5ef8 Mon Sep 17 00:00:00 2001 From: bergquist Date: Thu, 31 Jan 2019 13:42:24 +0100 Subject: [PATCH 43/43] changelog: adds note about closing #10780 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6fdc78842a..7164f5d99a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # 6.0.0-beta2 (unreleased) +### Minor +* **Pushover**: Adds support for images in pushover notifier [#10780](https://github.com/grafana/grafana/issues/10780), thx [@jpenalbae](https://github.com/jpenalbae) + # 6.0.0-beta1 (2019-01-30) ### New Features