diff --git a/CHANGELOG.md b/CHANGELOG.md index eae246c4a64..c09a9d5c911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,13 @@ - UX changes to nav & side menu - New dashboard grid layout system -# 4.5.0 (unreleased) - -## Enhancements +# 4.5.0 (2017-09-14) +## Fixes & Enhancements since beta1 +* **Security**: Security fix for api vulnerability (in multiple org setups). * **Shortcuts**: Adds shortcut for creating new dashboard [#8876](https://github.com/grafana/grafana/pull/8876) thx [@mtanda](https://github.com/mtanda) +* **Graph**: Right Y-Axis label position fixed [#9172](https://github.com/grafana/grafana/pull/9172) +* **General**: Improve rounding of time intervals [#9197](https://github.com/grafana/grafana/pull/9197), thx [@alin-amana](https://github.com/alin-amana) # 4.5.0-beta1 (2017-09-05) diff --git a/docs/sources/features/datasources/graphite.md b/docs/sources/features/datasources/graphite.md index a625b93e8d8..05a7df7fea8 100644 --- a/docs/sources/features/datasources/graphite.md +++ b/docs/sources/features/datasources/graphite.md @@ -41,7 +41,9 @@ Proxy access means that the Grafana backend will proxy all requests from the bro Click the ``Select metric`` link to start navigating the metric space. One you start you can continue using the mouse or keyboard arrow keys. You can select a wildcard and still continue. -![](/img/docs/animated_gifs/graphite_query1.gif) +{{< docs-imagebox img="/img/docs/v45/graphite_query1_still.png" + animated-gif="/img/docs/v45/graphite_query1.gif" >}} + ### Functions @@ -50,18 +52,26 @@ a function is selected it will be added and your focus will be in the text box o a parameter just click on it and it will turn into a text box. To delete a function click the function name followed by the x icon. -![](/img/docs/animated_gifs/graphite_query2.gif) +{{< docs-imagebox img="/img/docs/v45/graphite_query2_still.png" + animated-gif="/img/docs/v45/graphite_query2.gif" >}} + ### Optional parameters Some functions like aliasByNode support an optional second argument. To add this parameter specify for example 3,-2 as the first parameter and the function editor will adapt and move the -2 to a second parameter. To remove the second optional parameter just click on it and leave it blank and the editor will remove it. -![](/img/docs/animated_gifs/func_editor_optional_params.gif) +{{< docs-imagebox img="/img/docs/v45/graphite_query3_still.png" + animated-gif="/img/docs/v45/graphite_query3.gif" >}} + ### Nested Queries You can reference queries by the row “letter” that they’re on (similar to Microsoft Excel). If you add a second query to a graph, you can reference the first query simply by typing in #A. This provides an easy and convenient way to build compounded queries. +{{< docs-imagebox img="/img/docs/v45/graphite_nested_queries_still.png" + animated-gif="/img/docs/v45/graphite_nested_queries.gif" >}} + + ## Point consolidation All Graphite metrics are consolidated so that Graphite doesn't return more data points than there are pixels in the graph. By default, diff --git a/docs/sources/features/datasources/influxdb.md b/docs/sources/features/datasources/influxdb.md index 8f4f5981124..97e523cd151 100644 --- a/docs/sources/features/datasources/influxdb.md +++ b/docs/sources/features/datasources/influxdb.md @@ -41,7 +41,7 @@ mode is also more secure as the username & password will never reach the browser ## Query Editor -![](/assets/img/blog/v2.6/influxdb_editor_v3.gif) +{{< docs-imagebox img="/img/docs/v45/influxdb_query_still.png" class="docs-image--no-shadow" animated-gif="/img/docs/v45/influxdb_query.gif" >}} You find the InfluxDB editor in the metrics tab in Graph or Singlestat panel's edit mode. You enter edit mode by clicking the panel title, then edit. The editor allows you to select metrics and tags. @@ -57,10 +57,8 @@ will automatically adjust the filter tag condition to use the InfluxDB regex mat ### Field & Aggregation functions In the `SELECT` row you can specify what fields and functions you want to use. If you have a -group by time you need an aggregation function. Some functions like derivative require an aggregation function. - -The editor tries simplify and unify this part of the query. For example: -![](/img/docs/influxdb/select_editor.png) +group by time you need an aggregation function. Some functions like derivative require an aggregation function. The editor tries simplify and unify this part of the query. For example:
+![](/img/docs/influxdb/select_editor.png)
The above will generate the following InfluxDB `SELECT` clause: diff --git a/docs/sources/features/datasources/mysql.md b/docs/sources/features/datasources/mysql.md index 02e821050fa..f277f45f3c8 100644 --- a/docs/sources/features/datasources/mysql.md +++ b/docs/sources/features/datasources/mysql.md @@ -11,8 +11,7 @@ weight = 7 # Using MySQL in Grafana -> Only available in Grafana v4.3+. This data source is not ready for -> production use, currently in development (alpha state). +> Only available in Grafana v4.3+. Grafana ships with a built-in MySQL data source plugin that allow you to query any visualize data from a MySQL compatible database. @@ -58,8 +57,7 @@ If the `Format as` query option is set to `Table` then you can basically do any Query editor with example query: -![](/img/docs/v43/mysql_table_query.png) - +{{< docs-imagebox img="/img/docs/v45/mysql_table_query.png" >}} The query: diff --git a/docs/sources/features/datasources/prometheus.md b/docs/sources/features/datasources/prometheus.md index a6f544914b8..dceb2254e41 100644 --- a/docs/sources/features/datasources/prometheus.md +++ b/docs/sources/features/datasources/prometheus.md @@ -39,7 +39,8 @@ Name | Description Open a graph in edit mode by click the title > Edit (or by pressing `e` key while hovering over panel). -![](/img/docs/v43/prometheus_query_editor.png) +{{< docs-imagebox img="/img/docs/v45/prometheus_query_editor_still.png" + animated-gif="/img/docs/v45/prometheus_query_editor.gif" >}} Name | Description ------- | -------- diff --git a/docs/sources/features/panels/graph.md b/docs/sources/features/panels/graph.md index 5dbf307b484..726a11bec3a 100644 --- a/docs/sources/features/panels/graph.md +++ b/docs/sources/features/panels/graph.md @@ -50,15 +50,11 @@ populate the template variable to a desired value from the link. The metrics tab defines what series data and sources to render. Each datasource provides different options. -## Axes & Grid +## Axes ![](/img/docs/v43/graph_axes_grid_options.png) -The Axes & Grid tab controls the display of axes, grids and legend. - -### Axes - -The ``Left Y`` and ``Right Y`` can be customized using: +The Axes tab controls the display of axes, grids and legend. The ``Left Y`` and ``Right Y`` can be customized using: - ``Unit`` - The display unit for the Y value - ``Grid Max`` - The maximum Y value. (default auto) diff --git a/docs/sources/features/panels/table_panel.md b/docs/sources/features/panels/table_panel.md index 69cd02fdbcc..9c112c81265 100644 --- a/docs/sources/features/panels/table_panel.md +++ b/docs/sources/features/panels/table_panel.md @@ -12,7 +12,7 @@ weight = 2 # Table Panel - + The new table panel is very flexible, supporting both multiple modes for time series as well as for table, annotation and raw JSON data. It also provides date formatting and value formatting and coloring options. @@ -22,55 +22,63 @@ To view table panels in action and test different configurations with sample dat ## Options overview The table panel has many ways to manipulate your data for optimal presentation. +{{< docs-imagebox img="/img/docs/v45/table_options.png" class="docs-image--no-shadow" max-width= "500px" >}} - 1. `Data`: Control how your query is transformed into a table. -2. `Table Display`: Table display options. -3. `Column Styles`: Column value formatting and display options. +2. `Paging`: Table display options. + ## Data to Table - +{{< docs-imagebox img="/img/docs/v45/table_data_options.png" max-width="500px" class="docs-image--right">}} The data section contains the **To Table Transform (1)**. This is the primary option for how your data/metric query should be transformed into a table format. The **Columns (2)** option allows you to select what columns you want in the table. Only applicable for some transforms. +
+ ### Time series to rows - +{{< docs-imagebox img="/img/docs/v45/table_ts_to_rows.png" >}} In the most simple mode you can turn time series to rows. This means you get a `Time`, `Metric` and a `Value` column. Where `Metric` is the name of the time series. ### Time series to columns -![](/img/docs/v2/table_ts_to_columns2.png) +{{< docs-imagebox img="/img/docs/v45/table_ts_to_columns.png" >}} + This transform allows you to take multiple time series and group them by time. Which will result in the primary column being `Time` and a column for each time series. ### Time series aggregations -![](/img/docs/v2/table_ts_to_aggregations2.png) +{{< docs-imagebox img="/img/docs/v45/table_ts_to_aggregations.png" >}} + This table transformation will lay out your table into rows by metric, allowing columns of `Avg`, `Min`, `Max`, `Total`, `Current` and `Count`. More than one column can be added. ### Annotations -![](/img/docs/v2/table_annotations.png) + +{{< docs-imagebox img="/img/docs/v45/table_annotations.png" >}} + If you have annotations enabled in the dashboard you can have the table show them. If you configure this mode then any queries you have in the metrics tab will be ignored. ### JSON Data -![](/img/docs/v2/table_json_data.png) + +{{< docs-imagebox img="/img/docs/v45/table_json_data.png" max-width="500px" >}} If you have an Elasticsearch **Raw Document** query or an Elasticsearch query without a `date histogram` use this transform mode and pick the columns using the **Columns** section. -![](/img/docs/v2/elastic_raw_doc.png) + +{{< docs-imagebox img="/img/docs/v45/elastic_raw_doc.png" >}} ## Table Display - +{{< docs-imagebox img="/img/docs/v45/table_paging.png" class="docs-image--no-shadow docs-image--right" max-width="350px" >}} 1. `Pagination (Page Size)`: The table display fields allow you to control The `Pagination` (page size) is the threshold at which the table rows will be broken into pages. For example, if your table had 95 records with a pagination value of 10, your table would be split across 9 pages. 2. `Scroll`: The `scroll bar` checkbox toggles the ability to scroll within the panel, when unchecked, the panel height will grow to display all rows. @@ -81,13 +89,11 @@ transform mode and pick the columns using the **Columns** section. The column styles allow you control how dates and numbers are formatted. - +{{< docs-imagebox img="/img/docs/v45/table_column_styles.png" class="docs-image--no-shadow" >}} 1. `Name or regex`: The Name or Regex field controls what columns the rule should be applied to. The regex or name filter will be matched against the column name not against column values. -2. `Type`: The three supported types of types are `Number`, `String` and `Date`. -3. `Title`: Title for the column, when using a Regex the title can include replacement strings like `$1`. -4. `Format`: Specify date format. Only available when `Type` is set to `Date`. -5. `Coloring` and `Thresholds`: Specify color mode and thresholds limits. -6. `Unit` and `Decimals`: Specify unit and decimal precision for numbers. -7. `Add column style rule`: Add new column rule. +2. `Column Header`: Title for the column, when using a Regex the title can include replacement strings like `$1`. +3. `Add column style rule`: Add new column rule. +4. `Thresholds` and `Coloring`: Specify color mode and thresholds limits. +5. `Type`: The three supported types of types are `Number`, `String` and `Date`. `Unit` and `Decimals`: Specify unit and decimal precision for numbers.`Format`: Specify date format for dates. diff --git a/docs/sources/features/shortcuts.md b/docs/sources/features/shortcuts.md index ec7250b7a5a..caad521446e 100644 --- a/docs/sources/features/shortcuts.md +++ b/docs/sources/features/shortcuts.md @@ -8,7 +8,7 @@ weight = 7 # Keyboard shortcuts -{{< docs-imagebox img="/img/docs/v4/shortcuts.png" max-width="20rem" >}} +{{< docs-imagebox img="/img/docs/v4/shortcuts.png" max-width="20rem" class="docs-image--right" >}} Grafana v4 introduces a number of really powerful keyboard shortcuts. You can now focus a panel by hovering over it with your mouse. With a panel focused you can simple hit `e` to toggle panel diff --git a/docs/sources/guides/whats-new-in-v4-5.md b/docs/sources/guides/whats-new-in-v4-5.md index abce3fc4095..b2de451308a 100644 --- a/docs/sources/guides/whats-new-in-v4-5.md +++ b/docs/sources/guides/whats-new-in-v4-5.md @@ -16,16 +16,13 @@ weight = -4 ### New prometheus query editor -The new query editor has full syntax highlighting. As well as auto complete for metrics, functions, and range vectors. +The new query editor has full syntax highlighting. As well as auto complete for metrics, functions, and range vectors. There is also integrated function docs right from the query editor! -![](/img/docs/v45/new_prom_editor_1.png) - -There is also integrated function docs right from the query editor! - -![](/img/docs/v45/new_prom_editor_2.png) +{{< docs-imagebox img="/img/docs/v45/prometheus_query_editor_still.png" class="docs-image--block" animated-gif="/img/docs/v45/prometheus_query_editor.gif" >}} ### Elasticsearch: Add ad-hoc filters from the table panel -![](/img/docs/v45/elastic_ad_hoc_filters.png) + +{{< docs-imagebox img="/img/docs/v45/elastic_ad_hoc_filters.png" class="docs-image--block" >}} ### Table cell links! Create column styles that turn cells into links that use the value in the cell (or other other row values) to generate a url to another dashboard or system: diff --git a/docs/sources/installation/windows.md b/docs/sources/installation/windows.md index 97d17a2ca8e..112838d530a 100644 --- a/docs/sources/installation/windows.md +++ b/docs/sources/installation/windows.md @@ -27,7 +27,7 @@ this folder to anywhere you want Grafana to run from. Go into the The default Grafana port is `3000`, this port requires extra permissions on windows. Edit `custom.ini` and uncomment the `http_port` -configuration option and change it to something like `8080` or similar. +configuration option (`;` is the comment character in ini files) and change it to something like `8080` or similar. That port should not require extra Windows privileges. Start Grafana by executing `grafana-server.exe`, preferably from the diff --git a/docs/sources/reference/playlist.md b/docs/sources/reference/playlist.md index e2d59bc322d..f509ae4dc0d 100644 --- a/docs/sources/reference/playlist.md +++ b/docs/sources/reference/playlist.md @@ -16,7 +16,7 @@ Since Grafana automatically scales Dashboards to any resolution they're perfect ## Creating a Playlist -{{< docs-imagebox img="/img/docs/v3/playlist.png" max-width="25rem" >}} +{{< docs-imagebox img="/img/docs/v3/playlist.png" max-width="25rem" class="docs-image--right">}} The Playlist feature can be accessed from Grafana's sidemenu, in the Dashboard submenu. @@ -43,3 +43,25 @@ Playlists can also be manually controlled utilizing the Playlist controls at the Click the stop button to stop the Playlist, and exit to the current Dashboard. Click the next button to advance to the next Dashboard in the Playlist. Click the back button to rewind to the previous Dashboard in the Playlist. + +## TV or Kiosk Mode + +In TV mode the top navbar, row & panel controls will all fade to transparent. + +This happens automatically after one minute of user inactivity but can also be toggled manually +with the `d v` sequence shortcut. Any mouse movement or keyboard action will +restore navbar & controls. + +Another feature is the kiosk mode - in kiosk mode the navbar is completely hidden/removed from view. This can be enabled with the `d k` +shortcut. + +To put a playlist into kiosk mode, use the `d k` shortcut after the playlist has started. The same shortcut will toggle the playlist out of kiosk mode. + +### Linking to the Playlist in Kiosk Mode + +If you want to create a link to the playlist with kiosk mode enabled: + +1. Copy the Start Url (by right clicking on the Play button and choosing Copy link address). +2. Add the `?kiosk` parameter to the url. + +For example, to open the first playlist on the Grafana Play site in kiosk mode: [http://play.grafana.org/playlists/play/1?kiosk](http://play.grafana.org/playlists/play/1?kiosk) diff --git a/docs/sources/tutorials/hubot_howto.md b/docs/sources/tutorials/hubot_howto.md index 2c886b94f29..8a8b90529bb 100644 --- a/docs/sources/tutorials/hubot_howto.md +++ b/docs/sources/tutorials/hubot_howto.md @@ -74,7 +74,9 @@ If you do not get an image when opening this link verify that the required font ### Grafana API Key - + +{{< docs-imagebox img="/img/docs/v2/orgdropdown_api_keys.png" max-width="150px" class="docs-image--right">}} + You need to set the environment variable `HUBOT_GRAFANA_API_KEY` to a Grafana API Key. You can add these from the API Keys page which you find in the Organization dropdown. diff --git a/package.json b/package.json index 5ac5c01d8d9..72983f8c480 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "company": "Grafana Labs" }, "name": "grafana", - "version": "4.5.0-beta1", + "version": "4.5.0", "repository": { "type": "git", "url": "http://github.com/grafana/grafana.git" @@ -53,10 +53,6 @@ "systemjs": "0.19.41", "zone.js": "^0.7.2" }, - "engines": { - "node": "4.x", - "npm": "2.14.x" - }, "scripts": { "build": "./node_modules/grunt-cli/bin/grunt", "test": "./node_modules/grunt-cli/bin/grunt test", diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index e35e35cdab6..48c8d884329 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -29,7 +29,7 @@ func QueryMetrics(c *middleware.Context, reqDto dtos.MetricRequest) Response { return ApiError(400, "Query missing datasourceId", nil) } - dsQuery := models.GetDataSourceByIdQuery{Id: dsId} + dsQuery := models.GetDataSourceByIdQuery{Id: dsId, OrgId: c.OrgId} if err := bus.Dispatch(&dsQuery); err != nil { return ApiError(500, "failed to fetch data source", err) } diff --git a/pkg/services/alerting/conditions/query.go b/pkg/services/alerting/conditions/query.go index ae8008deb75..433eb1b597f 100644 --- a/pkg/services/alerting/conditions/query.go +++ b/pkg/services/alerting/conditions/query.go @@ -5,6 +5,8 @@ import ( "strings" "time" + gocontext "context" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/null" "github.com/grafana/grafana/pkg/components/simplejson" @@ -112,6 +114,10 @@ func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange * resp, err := c.HandleRequest(context.Ctx, req) if err != nil { + if err == gocontext.DeadlineExceeded { + return nil, fmt.Errorf("Alert execution exceeded the timeout") + } + return nil, fmt.Errorf("tsdb.HandleRequest() error %v", err) } diff --git a/pkg/util/encryption.go b/pkg/util/encryption.go index 2f8b5d7af56..d41665bafd6 100644 --- a/pkg/util/encryption.go +++ b/pkg/util/encryption.go @@ -27,12 +27,13 @@ func Decrypt(payload []byte, secret string) ([]byte, error) { } iv := payload[saltLength : saltLength+aes.BlockSize] payload = payload[saltLength+aes.BlockSize:] + payloadDst := make([]byte, len(payload)) stream := cipher.NewCFBDecrypter(block, iv) // XORKeyStream can work in-place if the two arguments are the same. - stream.XORKeyStream(payload, payload) - return payload, nil + stream.XORKeyStream(payloadDst, payload) + return payloadDst, nil } func Encrypt(payload []byte, secret string) ([]byte, error) { diff --git a/public/app/core/components/code_editor/code_editor.ts b/public/app/core/components/code_editor/code_editor.ts index 151ebffab5d..61ebb17d9b3 100644 --- a/public/app/core/components/code_editor/code_editor.ts +++ b/public/app/core/components/code_editor/code_editor.ts @@ -40,11 +40,11 @@ const DEFAULT_MAX_LINES = 10; const DEFAULT_TAB_SIZE = 2; const DEFAULT_BEHAVIOURS = true; -const GRAFANA_MODULES = ['mode-prometheus', 'snippets-prometheus', 'theme-grafana-dark']; +const GRAFANA_MODULES = ['theme-grafana-dark']; const GRAFANA_MODULE_BASE = "public/app/core/components/code_editor/"; // Trick for loading additional modules -function setModuleUrl(moduleType, name) { +function setModuleUrl(moduleType, name, pluginBaseUrl = null) { let baseUrl = ACE_SRC_BASE; let aceModeName = `ace/${moduleType}/${name}`; let moduleName = `${moduleType}-${name}`; @@ -54,6 +54,10 @@ function setModuleUrl(moduleType, name) { baseUrl = GRAFANA_MODULE_BASE; } + if (pluginBaseUrl) { + baseUrl = pluginBaseUrl + '/'; + } + if (moduleType === 'snippets') { componentName = `${moduleType}/${name}.js`; } @@ -111,6 +115,17 @@ function link(scope, elem, attrs) { let textarea = elem.find("textarea"); textarea.addClass('gf-form-input'); + if (scope.codeEditorFocus) { + setTimeout(function () { + textarea.focus(); + var domEl = textarea[0]; + if (domEl.setSelectionRange) { + var pos = textarea.val().length * 2; + domEl.setSelectionRange(pos, pos); + } + }, 100); + } + // Event handlers editorSession.on('change', (e) => { scope.$apply(() => { @@ -148,8 +163,8 @@ function link(scope, elem, attrs) { function setLangMode(lang) { let aceModeName = `ace/mode/${lang}`; - setModuleUrl("mode", lang); - setModuleUrl("snippets", lang); + setModuleUrl("mode", lang, scope.datasource.meta.baseUrl || null); + setModuleUrl("snippets", lang, scope.datasource.meta.baseUrl || null); editorSession.setMode(aceModeName); ace.config.loadModule("ace/ext/language_tools", (language_tools) => { @@ -199,6 +214,8 @@ export function codeEditorDirective() { template: editorTemplate, scope: { content: "=", + datasource: "=", + codeEditorFocus: "<", onChange: "&", getCompleter: "&" }, diff --git a/public/app/core/services/alert_srv.ts b/public/app/core/services/alert_srv.ts index ced6ffc6467..1786e526285 100644 --- a/public/app/core/services/alert_srv.ts +++ b/public/app/core/services/alert_srv.ts @@ -16,7 +16,7 @@ export class AlertSrv { init() { this.$rootScope.onAppEvent('alert-error', (e, alert) => { - this.set(alert[0], alert[1], 'error', 7000); + this.set(alert[0], alert[1], 'error', 12000); }, this.$rootScope); this.$rootScope.onAppEvent('alert-warning', (e, alert) => { @@ -33,6 +33,14 @@ export class AlertSrv { appEvents.on('confirm-modal', this.showConfirmModal.bind(this)); } + getIconForSeverity(severity) { + switch (severity) { + case 'success': return 'fa fa-check'; + case 'error': return 'fa fa-exclamation-triangle'; + default: return 'fa fa-exclamation'; + } + } + set(title, text, severity, timeout) { if (_.isObject(text)) { console.log('alert error', text); @@ -45,6 +53,7 @@ export class AlertSrv { title: title || '', text: text || '', severity: severity || 'info', + icon: this.getIconForSeverity(severity) }; var newAlertJson = angular.toJson(newAlert); diff --git a/public/app/core/services/backend_srv.ts b/public/app/core/services/backend_srv.ts index b753ae98530..e712fe2790d 100644 --- a/public/app/core/services/backend_srv.ts +++ b/public/app/core/services/backend_srv.ts @@ -64,7 +64,13 @@ export class BackendSrv { } if (data.message) { - this.alertSrv.set("Problem!", data.message, data.severity, 10000); + let description = ""; + let message = data.message; + if (message.length > 80) { + description = message; + message = "Error"; + } + this.alertSrv.set(message, description, data.severity, 10000); } throw data; @@ -97,7 +103,7 @@ export class BackendSrv { return results.data; }, err => { // handle unauthorized - if (err.status === 401 && firstAttempt) { + if (err.status === 401 && this.contextSrv.user.isSignedIn && firstAttempt) { return this.loginPing().then(() => { options.retry = 1; return this.request(options); diff --git a/public/app/core/utils/kbn.js b/public/app/core/utils/kbn.js index 37888fb10ac..97078071e45 100644 --- a/public/app/core/utils/kbn.js +++ b/public/app/core/utils/kbn.js @@ -17,90 +17,87 @@ function($, _) { kbn.round_interval = function(interval) { switch (true) { // 0.015s - case (interval <= 15): + case (interval < 15): return 10; // 0.01s // 0.035s - case (interval <= 35): + case (interval < 35): return 20; // 0.02s // 0.075s - case (interval <= 75): + case (interval < 75): return 50; // 0.05s // 0.15s - case (interval <= 150): + case (interval < 150): return 100; // 0.1s // 0.35s - case (interval <= 350): + case (interval < 350): return 200; // 0.2s // 0.75s - case (interval <= 750): + case (interval < 750): return 500; // 0.5s // 1.5s - case (interval <= 1500): + case (interval < 1500): return 1000; // 1s // 3.5s - case (interval <= 3500): + case (interval < 3500): return 2000; // 2s // 7.5s - case (interval <= 7500): + case (interval < 7500): return 5000; // 5s // 12.5s - case (interval <= 12500): + case (interval < 12500): return 10000; // 10s // 17.5s - case (interval <= 17500): + case (interval < 17500): return 15000; // 15s // 25s - case (interval <= 25000): + case (interval < 25000): return 20000; // 20s // 45s - case (interval <= 45000): + case (interval < 45000): return 30000; // 30s // 1.5m - case (interval <= 90000): + case (interval < 90000): return 60000; // 1m // 3.5m - case (interval <= 210000): + case (interval < 210000): return 120000; // 2m // 7.5m - case (interval <= 450000): + case (interval < 450000): return 300000; // 5m // 12.5m - case (interval <= 750000): + case (interval < 750000): return 600000; // 10m // 12.5m - case (interval <= 1050000): + case (interval < 1050000): return 900000; // 15m // 25m - case (interval <= 1500000): + case (interval < 1500000): return 1200000; // 20m // 45m - case (interval <= 2700000): + case (interval < 2700000): return 1800000; // 30m // 1.5h - case (interval <= 5400000): + case (interval < 5400000): return 3600000; // 1h // 2.5h - case (interval <= 9000000): + case (interval < 9000000): return 7200000; // 2h // 4.5h - case (interval <= 16200000): + case (interval < 16200000): return 10800000; // 3h // 9h - case (interval <= 32400000): + case (interval < 32400000): return 21600000; // 6h - // 24h - case (interval <= 86400000): + // 1d + case (interval < 86400000): return 43200000; // 12h - // 48h - case (interval <= 172800000): - return 86400000; // 24h // 1w - case (interval <= 604800000): - return 86400000; // 24h + case (interval < 604800000): + return 86400000; // 1d // 3w - case (interval <= 1814400000): + case (interval < 1814400000): return 604800000; // 1w - // 2y + // 6w case (interval < 3628800000): return 2592000000; // 30d default: @@ -134,7 +131,7 @@ function($, _) { return nummilliseconds + 'ms'; } - return 'less then a millisecond'; //'just now' //or other string you like; + return 'less than a millisecond'; //'just now' //or other string you like; }; kbn.to_percent = function(number,outof) { diff --git a/public/app/features/dashboard/dashboard_srv.ts b/public/app/features/dashboard/dashboard_srv.ts index 9d622f4bbc7..f3350061caa 100644 --- a/public/app/features/dashboard/dashboard_srv.ts +++ b/public/app/features/dashboard/dashboard_srv.ts @@ -83,7 +83,7 @@ export class DashboardSrv { } this.$rootScope.appEvent('dashboard-saved', this.dash); - this.$rootScope.appEvent('alert-success', ['Dashboard saved', 'Saved as ' + clone.title]); + this.$rootScope.appEvent('alert-success', ['Dashboard saved']); } save(clone, options) { diff --git a/public/app/features/dashboard/time_srv.ts b/public/app/features/dashboard/time_srv.ts index abde4152b63..2c16915b5aa 100644 --- a/public/app/features/dashboard/time_srv.ts +++ b/public/app/features/dashboard/time_srv.ts @@ -116,16 +116,14 @@ class TimeSrv { setAutoRefresh(interval) { this.dashboard.refresh = interval; + this.cancelNextRefresh(); if (interval) { var intervalMs = kbn.interval_to_ms(interval); - this.$timeout(() => { + this.refreshTimer = this.timer.register(this.$timeout(() => { this.startNextRefreshTimer(intervalMs); this.refreshDashboard(); - }, intervalMs); - - } else { - this.cancelNextRefresh(); + }, intervalMs)); } // update url diff --git a/public/app/features/panel/metrics_tab.ts b/public/app/features/panel/metrics_tab.ts index 4feaf516438..53d53cdbbff 100644 --- a/public/app/features/panel/metrics_tab.ts +++ b/public/app/features/panel/metrics_tab.ts @@ -9,7 +9,7 @@ export class MetricsTabCtrl { panel: any; panelCtrl: any; datasources: any[]; - current: any; + datasourceInstance: any; nextRefId: string; dashboard: DashboardModel; panelDsValue: any; @@ -29,23 +29,26 @@ export class MetricsTabCtrl { this.panel = this.panelCtrl.panel; this.dashboard = this.panelCtrl.dashboard; this.datasources = datasourceSrv.getMetricSources(); - this.panelDsValue = this.panelCtrl.panel.datasource || null; + this.panelDsValue = this.panelCtrl.panel.datasource; for (let ds of this.datasources) { if (ds.value === this.panelDsValue) { - this.current = ds; + this.datasourceInstance = ds; } } this.addQueryDropdown = {text: 'Add Query', value: null, fake: true}; + // update next ref id this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel); this.updateDatasourceOptions(); } updateDatasourceOptions() { - this.hasQueryHelp = this.current.meta.hasQueryHelp; - this.queryOptions = this.current.meta.queryOptions; + if (this.datasourceInstance) { + this.hasQueryHelp = this.datasourceInstance.meta.hasQueryHelp; + this.queryOptions = this.datasourceInstance.meta.queryOptions; + } } getOptions(includeBuiltin) { @@ -61,7 +64,7 @@ export class MetricsTabCtrl { return; } - this.current = option.datasource; + this.datasourceInstance = option.datasource; this.panelCtrl.setDatasource(option.datasource); this.updateDatasourceOptions(); } @@ -85,7 +88,7 @@ export class MetricsTabCtrl { this.queryTroubleshooterOpen = false; this.helpOpen = !this.helpOpen; - this.backendSrv.get(`/api/plugins/${this.current.meta.id}/markdown/query_help`).then(res => { + this.backendSrv.get(`/api/plugins/${this.datasourceInstance.meta.id}/markdown/query_help`).then(res => { var md = new Remarkable(); this.helpHtml = this.$sce.trustAsHtml(md.render(res)); }); diff --git a/public/app/features/panel/partials/metrics_tab.html b/public/app/features/panel/partials/metrics_tab.html index c3643152716..03a2c374a14 100644 --- a/public/app/features/panel/partials/metrics_tab.html +++ b/public/app/features/panel/partials/metrics_tab.html @@ -73,7 +73,7 @@ -
+
@@ -89,11 +89,11 @@ {{ctrl.panelCtrl.nextRefId}} - -