Browse Source

Merge branch 'develop' of https://github.com/grafana/grafana into develop

Erik Sundell 7 years ago
parent
commit
f673d60dae
100 changed files with 9185 additions and 2150 deletions
  1. 13 5
      CHANGELOG.md
  2. 4 0
      conf/defaults.ini
  3. 4 0
      conf/sample.ini
  4. 52 1
      devenv/datasources.yaml
  5. 5394 0
      devenv/dev-dashboards/datasource_tests_elasticsearch_compare.json
  6. 649 0
      devenv/dev-dashboards/datasource_tests_elasticsearch_v2.json
  7. 651 0
      devenv/dev-dashboards/datasource_tests_elasticsearch_v5.json
  8. 649 0
      devenv/dev-dashboards/datasource_tests_elasticsearch_v6.json
  9. 1 1
      devenv/docker/blocks/elastic/docker-compose.yaml
  10. 7 4
      devenv/docker/blocks/elastic5/docker-compose.yaml
  11. 7 5
      devenv/docker/blocks/influxdb/docker-compose.yaml
  12. 162 0
      docs/sources/features/explore/index.md
  13. 2 2
      latest.json
  14. 1 1
      package.json
  15. 11 11
      packaging/publish/publish_both.sh
  16. 2 2
      pkg/services/provisioning/dashboards/file_reader.go
  17. 3 0
      pkg/services/sqlstore/migrations/datasource_mig.go
  18. 3 0
      pkg/tsdb/elasticsearch/models.go
  19. 18 4
      pkg/tsdb/elasticsearch/time_series_query.go
  20. 60 0
      pkg/tsdb/elasticsearch/time_series_query_test.go
  21. 1 0
      public/app/core/components/AppNotifications/AppNotificationItem.tsx
  22. 2 2
      public/app/core/components/CustomScrollbar/CustomScrollbar.tsx
  23. 4 4
      public/app/core/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap
  24. 7 2
      public/app/core/components/Form/Input.tsx
  25. 9 9
      public/app/core/components/PermissionList/AddPermission.tsx
  26. 8 7
      public/app/core/components/PermissionList/DisabledPermissionListItem.tsx
  27. 9 7
      public/app/core/components/PermissionList/PermissionListItem.tsx
  28. 0 26
      public/app/core/components/Picker/DescriptionOption.tsx
  29. 0 52
      public/app/core/components/Picker/DescriptionPicker.tsx
  30. 0 18
      public/app/core/components/Picker/NoOptionsMessage.tsx
  31. 0 60
      public/app/core/components/Picker/Select.tsx
  32. 0 52
      public/app/core/components/Picker/SimplePicker.tsx
  33. 0 22
      public/app/core/components/Picker/Unit/UnitOption.tsx
  34. 0 81
      public/app/core/components/Picker/Unit/UnitPicker.tsx
  35. 6 17
      public/app/core/components/Select/DataSourcePicker.tsx
  36. 2 2
      public/app/core/components/Select/IndicatorsContainer.tsx
  37. 20 0
      public/app/core/components/Select/NoOptionsMessage.tsx
  38. 5 5
      public/app/core/components/Select/OptionGroup.tsx
  39. 0 0
      public/app/core/components/Select/PickerOption.test.tsx
  40. 1 1
      public/app/core/components/Select/PickerOption.tsx
  41. 0 0
      public/app/core/components/Select/ResetStyles.tsx
  42. 232 0
      public/app/core/components/Select/Select.tsx
  43. 0 0
      public/app/core/components/Select/TeamPicker.test.tsx
  44. 3 17
      public/app/core/components/Select/TeamPicker.tsx
  45. 51 0
      public/app/core/components/Select/UnitPicker.tsx
  46. 0 0
      public/app/core/components/Select/UserPicker.test.tsx
  47. 10 17
      public/app/core/components/Select/UserPicker.tsx
  48. 0 0
      public/app/core/components/Select/__snapshots__/PickerOption.test.tsx.snap
  49. 0 29
      public/app/core/components/Select/__snapshots__/TeamPicker.test.tsx.snap
  50. 0 29
      public/app/core/components/Select/__snapshots__/UserPicker.test.tsx.snap
  51. 13 15
      public/app/core/components/SharedPreferences/SharedPreferences.tsx
  52. 10 5
      public/app/core/components/TagFilter/TagFilter.tsx
  53. 1 1
      public/app/core/components/TagFilter/TagOption.tsx
  54. 1 1
      public/app/core/components/code_editor/code_editor.ts
  55. 45 7
      public/app/core/logs_model.ts
  56. 34 11
      public/app/core/specs/logs_model.test.ts
  57. 175 171
      public/app/features/alerting/partials/alert_tab.html
  58. 0 1
      public/app/features/dashboard/dashboard_migration.ts
  59. 71 168
      public/app/features/dashboard/dashgrid/AddPanelPanel.tsx
  60. 4 12
      public/app/features/dashboard/dashgrid/DashboardGrid.tsx
  61. 9 12
      public/app/features/dashboard/dashgrid/DashboardPanel.tsx
  62. 12 10
      public/app/features/dashboard/dashgrid/EditorTabBody.tsx
  63. 17 5
      public/app/features/dashboard/dashgrid/PanelEditor.tsx
  64. 26 0
      public/app/features/dashboard/dashgrid/PanelOptionSection.tsx
  65. 36 113
      public/app/features/dashboard/dashgrid/QueriesTab.tsx
  66. 2 8
      public/app/features/dashboard/dashgrid/QueryInspector.tsx
  67. 167 0
      public/app/features/dashboard/dashgrid/QueryOptions.tsx
  68. 0 97
      public/app/features/dashboard/dashgrid/TimeRangeOptions.tsx
  69. 13 8
      public/app/features/dashboard/dashgrid/VisualizationTab.tsx
  70. 1 1
      public/app/features/dashboard/dashnav/dashnav.ts
  71. 0 4
      public/app/features/dashboard/panellinks/module.html
  72. 0 46
      public/app/features/dashboard/specs/AddPanelPanel.test.tsx
  73. 3 3
      public/app/features/datasources/settings/DataSourceSettings.tsx
  74. 15 15
      public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap
  75. 1 1
      public/app/features/datasources/state/actions.ts
  76. 9 27
      public/app/features/explore/Explore.tsx
  77. 12 19
      public/app/features/explore/Logs.tsx
  78. 0 1
      public/app/features/panel/all.ts
  79. 0 28
      public/app/features/panel/panel_header.ts
  80. 47 35
      public/app/features/panel/partials/general_tab.html
  81. 0 188
      public/app/features/panel/query_troubleshooter.ts
  82. 0 71
      public/app/features/panel/viz_tab.ts
  83. 1 1
      public/app/features/teams/TeamMembers.tsx
  84. 57 0
      public/app/features/users/InviteeRow.tsx
  85. 0 1
      public/app/features/users/InviteesTable.test.tsx
  86. 4 37
      public/app/features/users/InviteesTable.tsx
  87. 0 1
      public/app/features/users/UsersListPage.test.tsx
  88. 2 8
      public/app/features/users/UsersListPage.tsx
  89. 1 1
      public/app/features/users/__mocks__/userMocks.ts
  90. 120 258
      public/app/features/users/__snapshots__/InviteesTable.test.tsx.snap
  91. 14 17
      public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.ts
  92. 8 1
      public/app/plugins/datasource/elasticsearch/query_builder.ts
  93. 7 0
      public/app/plugins/datasource/elasticsearch/query_def.ts
  94. 49 0
      public/app/plugins/datasource/elasticsearch/specs/query_builder.test.ts
  95. 92 192
      public/app/plugins/datasource/loki/img/loki_icon.svg
  96. 4 5
      public/app/plugins/panel/gauge/MappingRow.tsx
  97. 16 18
      public/app/plugins/panel/gauge/ValueOptions.tsx
  98. 6 6
      public/app/plugins/panel/graph/tab_display.html
  99. 10 10
      public/app/plugins/panel/table/column_options.html
  100. 7 15
      public/app/plugins/panel/text/editor.html

+ 13 - 5
CHANGELOG.md

@@ -6,27 +6,35 @@
 ### Minor
 
 * **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)
 * **Auth**: Prevent password reset when login form is disabled or either LDAP or Auth Proxy is enabled [#14246](https://github.com/grafana/grafana/issues/14246), thx [@SilverFire](https://github.com/SilverFire)
 * **Dataproxy**: Override incoming Authorization header [#13815](https://github.com/grafana/grafana/issues/13815), thx [@kornholi](https://github.com/kornholi)
 * **Admin**: Fix prevent removing last grafana admin permissions [#11067](https://github.com/grafana/grafana/issues/11067), thx [@danielbh](https://github.com/danielbh)
+* **Templating**: Escaping "Custom" template variables [#13754](https://github.com/grafana/grafana/issues/13754), thx [@IntegersOfK](https://github.com/IntegersOfK)
+
+# 5.4.2 (2018-12-13)
+
+* **Datasource admin**: Fix for issue creating new data source when same name exists [#14467](https://github.com/grafana/grafana/issues/14467)
+* **OAuth**: Fix for oauth auto login setting, can now be set using env variable [#14435](https://github.com/grafana/grafana/issues/14435)
+* **Dashboard search**: Fix for searching tags in tags filter dropdown. 
 
 # 5.4.1 (2018-12-10)
 
 * **Stackdriver**: Fixes issue with data proxy and Authorization header [#14262](https://github.com/grafana/grafana/issues/14262)
-* **Units**: fixedUnit for Flow:l/min and mL/min [#14294](https://github.com/grafana/grafana/issues/14294), thx [@flopp999](https://github.com/flopp999). 
+* **Units**: fixedUnit for Flow:l/min and mL/min [#14294](https://github.com/grafana/grafana/issues/14294), thx [@flopp999](https://github.com/flopp999).
 * **Logging**: Fix for issue where data proxy logged a secret when debug logging was enabled, now redacted. [#14319](https://github.com/grafana/grafana/issues/14319)
 * **InfluxDB**: Add support for alerting on InfluxDB queries that use the cumulative_sum function. [#14314](https://github.com/grafana/grafana/pull/14314), thx [@nitti](https://github.com/nitti)
-* **Plugins**: Panel plugins should no receive the panel-initialized event again as usual. 
+* **Plugins**: Panel plugins should no receive the panel-initialized event again as usual.
 * **Embedded Graphs**: Iframe graph panels should now work as usual. [#14284](https://github.com/grafana/grafana/issues/14284)
 * **Postgres**: Improve PostgreSQL Query Editor if using different Schemas, [#14313](
 https://github.com/grafana/grafana/pull/14313)
 * **Quotas**: Fixed for updating org & user quotas. [#14347](https://github.com/grafana/grafana/pull/14347), thx [#moznion](https://github.com/moznion)
 * **Cloudwatch**: Add the AWS/SES Cloudwatch metrics of BounceRate and ComplaintRate to auto complete list. [#14401](https://github.com/grafana/grafana/pull/14401), thx [@sglajchEG](https://github.com/sglajchEG)
-* **Dashboard Search**: Fixed filtering by tag issues. 
+* **Dashboard Search**: Fixed filtering by tag issues.
 * **Graph**: Fixed time region issues, [#14425](https://github.com/grafana/grafana/issues/14425), [#14280](https://github.com/grafana/grafana/issues/14280)
-* **Graph**: Fixed issue with series color picker popover being placed outside window. 
+* **Graph**: Fixed issue with series color picker popover being placed outside window.
+
 
- 
 
 # 5.4.0 (2018-12-03)
 

+ 4 - 0
conf/defaults.ini

@@ -246,6 +246,10 @@ disable_signout_menu = false
 # URL to redirect the user to after sign out
 signout_redirect_url =
 
+# Set to true to attempt login with OAuth automatically, skipping the login screen.
+# This setting is ignored if multiple OAuth providers are configured.
+oauth_auto_login = false
+
 #################################### Anonymous Auth ######################
 [auth.anonymous]
 # enable anonymous access

+ 4 - 0
conf/sample.ini

@@ -226,6 +226,10 @@ log_queries =
 # URL to redirect the user to after sign out
 ;signout_redirect_url =
 
+# Set to true to attempt login with OAuth automatically, skipping the login screen.
+# This setting is ignored if multiple OAuth providers are configured.
+;oauth_auto_login = false
+
 #################################### Anonymous Auth ##########################
 [auth.anonymous]
 # enable anonymous access

+ 52 - 1
devenv/datasources.yaml

@@ -35,7 +35,7 @@ datasources:
       tsdbResolution: 1
       tsdbVersion: 1
 
-  - name: gdev-elasticsearch-metrics
+  - name: gdev-elasticsearch-v2-metrics
     type: elasticsearch
     access: proxy
     database: "[metrics-]YYYY.MM.DD"
@@ -43,6 +43,57 @@ datasources:
     jsonData:
       interval: Daily
       timeField: "@timestamp"
+      esVersion: 2
+
+  - name: gdev-elasticsearch-v2-logs
+    type: elasticsearch
+    access: proxy
+    database: "[logs-]YYYY.MM.DD"
+    url: http://localhost:9200
+    jsonData:
+      interval: Daily
+      timeField: "@timestamp"
+      esVersion: 2
+
+  - name: gdev-elasticsearch-v5-metrics
+    type: elasticsearch
+    access: proxy
+    database: "[metrics-]YYYY.MM.DD"
+    url: http://localhost:10200
+    jsonData:
+      interval: Daily
+      timeField: "@timestamp"
+      esVersion: 5
+
+  - name: gdev-elasticsearch-v5-logs
+    type: elasticsearch
+    access: proxy
+    database: "[logs-]YYYY.MM.DD"
+    url: http://localhost:10200
+    jsonData:
+      interval: Daily
+      timeField: "@timestamp"
+      esVersion: 5
+
+  - name: gdev-elasticsearch-v6-metrics
+    type: elasticsearch
+    access: proxy
+    database: "[metrics-]YYYY.MM.DD"
+    url: http://localhost:11200
+    jsonData:
+      interval: Daily
+      timeField: "@timestamp"
+      esVersion: 60
+
+  - name: gdev-elasticsearch-v6-logs
+    type: elasticsearch
+    access: proxy
+    database: "[logs-]YYYY.MM.DD"
+    url: http://localhost:11200
+    jsonData:
+      interval: Daily
+      timeField: "@timestamp"
+      esVersion: 60
 
   - name: gdev-mysql
     type: mysql

+ 5394 - 0
devenv/dev-dashboards/datasource_tests_elasticsearch_compare.json

@@ -0,0 +1,5394 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": false,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "limit": 100,
+        "name": "Annotations & Alerts",
+        "showIn": 0,
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "iteration": 1542304484522,
+  "links": [
+    {
+      "icon": "external link",
+      "tags": [
+        "gdev",
+        "elasticsearch"
+      ],
+      "type": "dashboards"
+    }
+  ],
+  "panels": [
+    {
+      "collapsed": true,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 5,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 1
+          },
+          "id": 2,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "Basic (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 1
+          },
+          "id": 3,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "Basic (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 10
+          },
+          "id": 8,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "1m",
+                    "min_doc_count": 50,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "Basic (version one) - interval 1m + min doc count 50",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 10
+          },
+          "id": 9,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "1m",
+                    "min_doc_count": 50,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "Basic (version two) - interval 1m + min doc count 50",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 19
+          },
+          "id": 6,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 10
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "Basic (version one) - interval 5m + trim edges=10",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 19
+          },
+          "id": 7,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 10
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "Basic (version two) - interval 5m + trim edges=10",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        }
+      ],
+      "title": "Basic date histogram with count",
+      "type": "row"
+    },
+    {
+      "collapsed": true,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 1
+      },
+      "id": 11,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 2
+          },
+          "id": 12,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {
+                    "missing": null
+                  },
+                  "type": "avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "avg (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 2
+          },
+          "id": 13,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {
+                    "missing": null
+                  },
+                  "type": "avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "avg (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 11
+          },
+          "id": 14,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {
+                    "missing": null
+                  },
+                  "type": "sum"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "sum (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 11
+          },
+          "id": 15,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {
+                    "missing": null
+                  },
+                  "type": "sum"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "sum (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 20
+          },
+          "id": 16,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": true,
+            "max": true,
+            "min": true,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "max"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "max (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 20
+          },
+          "id": 21,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": true,
+            "max": true,
+            "min": true,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "max"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "max (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 29
+          },
+          "id": 17,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "min"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "min (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 29
+          },
+          "id": 22,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "min"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "min (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 38
+          },
+          "id": 18,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "rightSide": true,
+            "show": true,
+            "sort": "min",
+            "sortDesc": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {
+                    "avg": true,
+                    "count": true,
+                    "max": true,
+                    "min": true,
+                    "std_deviation": true,
+                    "std_deviation_bounds_lower": true,
+                    "std_deviation_bounds_upper": true,
+                    "sum": true
+                  },
+                  "settings": {},
+                  "type": "extended_stats"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "extended stats (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 38
+          },
+          "id": 23,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "rightSide": true,
+            "show": true,
+            "sort": "min",
+            "sortDesc": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {
+                    "avg": true,
+                    "count": true,
+                    "max": true,
+                    "min": true,
+                    "std_deviation": true,
+                    "std_deviation_bounds_lower": true,
+                    "std_deviation_bounds_upper": true,
+                    "sum": true
+                  },
+                  "settings": {},
+                  "type": "extended_stats"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "extended stats (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 47
+          },
+          "id": 19,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "rightSide": true,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {
+                    "percents": [
+                      25,
+                      50,
+                      75,
+                      95,
+                      99
+                    ]
+                  },
+                  "type": "percentiles"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "percentiles (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 47
+          },
+          "id": 24,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "rightSide": true,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {
+                    "missing": null,
+                    "percents": [
+                      25,
+                      50,
+                      75,
+                      95,
+                      99
+                    ]
+                  },
+                  "type": "percentiles"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "percentiles (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 56
+          },
+          "id": 20,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "rightSide": false,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "cardinality"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "unique count (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 56
+          },
+          "id": 25,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": false,
+            "max": true,
+            "min": true,
+            "rightSide": false,
+            "show": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "",
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": null
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "cardinality"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "unique count (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        }
+      ],
+      "title": "Basic date histogram with metric aggregation",
+      "type": "row"
+    },
+    {
+      "collapsed": true,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 2
+      },
+      "id": 27,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 3
+          },
+          "id": 55,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "count"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "count (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 3
+          },
+          "id": 34,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "count"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "count (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 12
+          },
+          "id": 29,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "avg (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 12
+          },
+          "id": 56,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "avg (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 21
+          },
+          "id": 30,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "sum"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "sum (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 21
+          },
+          "id": 35,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "sum"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "sum (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 30
+          },
+          "id": 31,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "max"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "max (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 30
+          },
+          "id": 36,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "max"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "max (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 39
+          },
+          "id": 32,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "min"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "min (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 39
+          },
+          "id": 37,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "min"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "min (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 48
+          },
+          "id": 33,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "cardinality"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "unique count (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 48
+          },
+          "id": 38,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "cardinality"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {
+                    "minimize": false,
+                    "model": "simple",
+                    "window": 5
+                  },
+                  "type": "moving_avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "unique count (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        }
+      ],
+      "title": "Basic date histogram with moving average aggregation",
+      "type": "row"
+    },
+    {
+      "collapsed": true,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 3
+      },
+      "id": 39,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 4
+          },
+          "id": 57,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "count"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "count (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 4
+          },
+          "id": 41,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "count"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "count (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 13
+          },
+          "id": 40,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "avg (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 13
+          },
+          "id": 58,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "avg (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 22
+          },
+          "id": 42,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "sum"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "sum (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 22
+          },
+          "id": 43,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "sum"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "sum (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 31
+          },
+          "id": 44,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "max"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "max (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 31
+          },
+          "id": 45,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "max"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "max (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 40
+          },
+          "id": 46,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "min"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "min (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 40
+          },
+          "id": 47,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "min"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "min (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 49
+          },
+          "id": 48,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "cardinality"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "unique count (version one) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 49
+          },
+          "id": 49,
+          "legend": {
+            "avg": false,
+            "current": false,
+            "max": false,
+            "min": false,
+            "show": true,
+            "total": false,
+            "values": false
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": false,
+          "steppedLine": false,
+          "targets": [
+            {
+              "bucketAggs": [
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "5m",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "@value",
+                  "hide": true,
+                  "id": "1",
+                  "meta": {},
+                  "settings": {},
+                  "type": "cardinality"
+                },
+                {
+                  "field": "1",
+                  "id": "3",
+                  "meta": {},
+                  "pipelineAgg": "1",
+                  "settings": {},
+                  "type": "derivative"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "unique count (version two) - interval 5m",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        }
+      ],
+      "title": "Basic date histogram with derivative aggregation",
+      "type": "row"
+    },
+    {
+      "collapsed": true,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 4
+      },
+      "id": 54,
+      "panels": [
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_one",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 0,
+            "y": 5
+          },
+          "id": 51,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": true,
+            "max": true,
+            "min": true,
+            "rightSide": true,
+            "show": true,
+            "sort": "min",
+            "sortDesc": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": true,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "{{@source}} - {{@hostname}} - {{@metric}} {{metric}}",
+              "bucketAggs": [
+                {
+                  "fake": true,
+                  "field": "@source",
+                  "id": "4",
+                  "settings": {
+                    "min_doc_count": 1,
+                    "order": "desc",
+                    "orderBy": "_count",
+                    "size": "10"
+                  },
+                  "type": "terms"
+                },
+                {
+                  "fake": true,
+                  "field": "@metric",
+                  "id": "5",
+                  "settings": {
+                    "min_doc_count": 1,
+                    "order": "desc",
+                    "orderBy": "_term",
+                    "size": "10"
+                  },
+                  "type": "terms"
+                },
+                {
+                  "fake": true,
+                  "field": "@hostname",
+                  "id": "3",
+                  "settings": {
+                    "min_doc_count": 1,
+                    "order": "desc",
+                    "orderBy": "_term",
+                    "size": "5"
+                  },
+                  "type": "terms"
+                },
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                },
+                {
+                  "field": "@value",
+                  "id": "6",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "count/average with triple terms agg (version one) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        },
+        {
+          "aliasColors": {},
+          "bars": false,
+          "dashLength": 10,
+          "dashes": false,
+          "datasource": "$version_two",
+          "decimals": 3,
+          "fill": 1,
+          "gridPos": {
+            "h": 9,
+            "w": 12,
+            "x": 12,
+            "y": 5
+          },
+          "id": 52,
+          "legend": {
+            "alignAsTable": true,
+            "avg": true,
+            "current": true,
+            "max": true,
+            "min": true,
+            "rightSide": true,
+            "show": true,
+            "sort": "min",
+            "sortDesc": true,
+            "total": true,
+            "values": true
+          },
+          "lines": true,
+          "linewidth": 1,
+          "links": [],
+          "nullPointMode": "null",
+          "percentage": false,
+          "pointradius": 5,
+          "points": false,
+          "renderer": "flot",
+          "seriesOverrides": [],
+          "spaceLength": 10,
+          "stack": true,
+          "steppedLine": false,
+          "targets": [
+            {
+              "alias": "{{@source}} - {{@hostname}} - {{@metric}} {{metric}}",
+              "bucketAggs": [
+                {
+                  "fake": true,
+                  "field": "@source",
+                  "id": "4",
+                  "settings": {
+                    "min_doc_count": 1,
+                    "order": "desc",
+                    "orderBy": "_count",
+                    "size": "10"
+                  },
+                  "type": "terms"
+                },
+                {
+                  "fake": true,
+                  "field": "@metric",
+                  "id": "5",
+                  "settings": {
+                    "min_doc_count": 1,
+                    "order": "desc",
+                    "orderBy": "_term",
+                    "size": "10"
+                  },
+                  "type": "terms"
+                },
+                {
+                  "fake": true,
+                  "field": "@hostname",
+                  "id": "3",
+                  "settings": {
+                    "min_doc_count": 1,
+                    "order": "desc",
+                    "orderBy": "_term",
+                    "size": "5"
+                  },
+                  "type": "terms"
+                },
+                {
+                  "field": "@timestamp",
+                  "id": "2",
+                  "settings": {
+                    "interval": "auto",
+                    "min_doc_count": 0,
+                    "trimEdges": 0
+                  },
+                  "type": "date_histogram"
+                }
+              ],
+              "metrics": [
+                {
+                  "field": "select field",
+                  "id": "1",
+                  "type": "count"
+                },
+                {
+                  "field": "@value",
+                  "id": "6",
+                  "meta": {},
+                  "settings": {},
+                  "type": "avg"
+                }
+              ],
+              "refId": "A",
+              "target": "",
+              "timeField": "@timestamp"
+            }
+          ],
+          "thresholds": [],
+          "timeFrom": null,
+          "timeRegions": [],
+          "timeShift": null,
+          "title": "count/average with triple terms agg (version two) - interval auto",
+          "tooltip": {
+            "shared": true,
+            "sort": 0,
+            "value_type": "individual"
+          },
+          "type": "graph",
+          "xaxis": {
+            "buckets": null,
+            "mode": "time",
+            "name": null,
+            "show": true,
+            "values": []
+          },
+          "yaxes": [
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            },
+            {
+              "format": "short",
+              "label": null,
+              "logBase": 1,
+              "max": null,
+              "min": null,
+              "show": true
+            }
+          ],
+          "yaxis": {
+            "align": false,
+            "alignLevel": null
+          }
+        }
+      ],
+      "title": "Multiple metrics and aggregations",
+      "type": "row"
+    }
+  ],
+  "refresh": false,
+  "schemaVersion": 16,
+  "style": "dark",
+  "tags": [
+    "gdev",
+    "elasticsearch"
+  ],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "text": "gdev-elasticsearch-v2-metrics",
+          "value": "gdev-elasticsearch-v2-metrics"
+        },
+        "hide": 0,
+        "label": "Version One",
+        "name": "version_one",
+        "options": [],
+        "query": "elasticsearch",
+        "refresh": 1,
+        "regex": "/^gdev.*metrics$/",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "current": {
+          "text": "gdev-elasticsearch-v5-metrics",
+          "value": "gdev-elasticsearch-v5-metrics"
+        },
+        "hide": 0,
+        "label": "Version Two",
+        "name": "version_two",
+        "options": [],
+        "query": "elasticsearch",
+        "refresh": 1,
+        "regex": "/^gdev.*metrics$/",
+        "skipUrlSync": false,
+        "type": "datasource"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-3h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "",
+  "title": "Datasource tests - Elasticsearch comparison",
+  "uid": "fuFWehBmk",
+  "version": 10
+}

+ 649 - 0
devenv/dev-dashboards/datasource_tests_elasticsearch_v2.json

@@ -0,0 +1,649 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": false,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "limit": 100,
+        "name": "Annotations & Alerts",
+        "showIn": 0,
+        "type": "dashboard"
+      },
+      {
+        "datasource": "Elastic 5 Logs",
+        "enable": false,
+        "iconColor": "rgba(255, 96, 96, 1)",
+        "limit": 100,
+        "name": "test",
+        "query": "",
+        "showIn": 0,
+        "textField": "description",
+        "type": "alert"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "iteration": 1542303970887,
+  "links": [
+    {
+      "icon": "external link",
+      "tags": [
+        "gdev",
+        "elasticsearch"
+      ],
+      "type": "dashboards"
+    }
+  ],
+  "panels": [
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v2-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 1,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": true,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "bucketAggs": [
+            {
+              "field": "@hostname",
+              "id": "3",
+              "settings": {
+                "min_doc_count": 1,
+                "order": "asc",
+                "orderBy": "1",
+                "size": "5"
+              },
+              "type": "terms"
+            },
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "auto",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {},
+              "type": "max"
+            }
+          ],
+          "query": "*",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Top 5 servers",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {
+        "Count": "#6ED0E0"
+      },
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v2-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 6,
+        "w": 12,
+        "x": 0,
+        "y": 7
+      },
+      "id": 2,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "Count",
+          "lines": false,
+          "yaxis": 2,
+          "zindex": -1
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "{{metric}}",
+          "bucketAggs": [
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "5m",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {
+                "percents": [
+                  25,
+                  50,
+                  75,
+                  95,
+                  99
+                ]
+              },
+              "type": "percentiles"
+            }
+          ],
+          "query": "@metric:cpu",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Percentiles & Metric filter",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {
+        "Count": "#6ED0E0"
+      },
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v2-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 6,
+        "w": 12,
+        "x": 12,
+        "y": 7
+      },
+      "id": 3,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "Count",
+          "lines": false,
+          "yaxis": 2,
+          "zindex": -1
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "{{metric}}",
+          "bucketAggs": [
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "auto",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {
+                "std_deviation_bounds_lower": true,
+                "std_deviation_bounds_upper": true
+              },
+              "settings": {},
+              "type": "extended_stats"
+            }
+          ],
+          "query": "@metric:cpu",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Standard dev",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "columns": [
+        {
+          "text": "@hostname",
+          "value": "@hostname"
+        },
+        {
+          "text": "Average",
+          "value": "Average"
+        },
+        {
+          "text": "Max",
+          "value": "Max"
+        },
+        {
+          "text": "Sum",
+          "value": "Sum"
+        }
+      ],
+      "datasource": "gdev-elasticsearch-v2-metrics",
+      "editable": true,
+      "error": false,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 13
+      },
+      "id": 6,
+      "links": [],
+      "pageSize": null,
+      "scroll": true,
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "styles": [
+        {
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "@timestamp",
+          "type": "date"
+        },
+        {
+          "colorMode": null,
+          "colors": [
+            "rgba(245, 54, 54, 0.9)",
+            "rgba(237, 129, 40, 0.89)",
+            "rgba(50, 172, 45, 0.97)"
+          ],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "pattern": "/.*/",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        }
+      ],
+      "targets": [
+        {
+          "bucketAggs": [
+            {
+              "field": "@hostname",
+              "id": "2",
+              "settings": {
+                "min_doc_count": 1,
+                "order": "asc",
+                "orderBy": "_term",
+                "size": "0"
+              },
+              "type": "terms"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {},
+              "type": "avg"
+            },
+            {
+              "field": "@value",
+              "id": "3",
+              "meta": {},
+              "settings": {},
+              "type": "max"
+            },
+            {
+              "field": "@value",
+              "id": "4",
+              "meta": {},
+              "settings": {},
+              "type": "sum"
+            }
+          ],
+          "refId": "B",
+          "timeField": "@timestamp"
+        }
+      ],
+      "title": "ES Metrics",
+      "transform": "table",
+      "type": "table"
+    },
+    {
+      "columns": [
+        {
+          "text": "@timestamp",
+          "value": "@timestamp"
+        },
+        {
+          "text": "@message",
+          "value": "@message"
+        },
+        {
+          "text": "tags",
+          "value": "tags"
+        },
+        {
+          "text": "description",
+          "value": "description"
+        }
+      ],
+      "datasource": "gdev-elasticsearch-v2-logs",
+      "editable": true,
+      "error": false,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 20
+      },
+      "id": 5,
+      "links": [],
+      "pageSize": null,
+      "scroll": true,
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "styles": [
+        {
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "@timestamp",
+          "type": "date"
+        }
+      ],
+      "targets": [
+        {
+          "bucketAggs": [],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "select field",
+              "id": "1",
+              "meta": {},
+              "settings": {
+                "size": 500
+              },
+              "type": "raw_document"
+            }
+          ],
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "title": "ES Log query",
+      "transform": "json",
+      "type": "table"
+    }
+  ],
+  "schemaVersion": 16,
+  "style": "dark",
+  "tags": [
+    "elasticsearch",
+    "gdev"
+  ],
+  "templating": {
+    "list": [
+      {
+        "datasource": "gdev-elasticsearch-v2-metrics",
+        "filters": [],
+        "hide": 0,
+        "label": "",
+        "name": "Filters",
+        "skipUrlSync": false,
+        "type": "adhoc"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-30m",
+    "to": "now"
+  },
+  "timepicker": {
+    "collapse": false,
+    "enable": true,
+    "notice": false,
+    "now": true,
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "status": "Stable",
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ],
+    "type": "timepicker"
+  },
+  "timezone": "browser",
+  "title": "Datasource tests - Elasticsearch v2",
+  "uid": "RlqLq2fiz",
+  "version": 2
+}

+ 651 - 0
devenv/dev-dashboards/datasource_tests_elasticsearch_v5.json

@@ -0,0 +1,651 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": false,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "limit": 100,
+        "name": "Annotations & Alerts",
+        "showIn": 0,
+        "type": "dashboard"
+      },
+      {
+        "datasource": "Elastic 5 Logs",
+        "enable": false,
+        "iconColor": "rgba(255, 96, 96, 1)",
+        "limit": 100,
+        "name": "test",
+        "query": "",
+        "showIn": 0,
+        "textField": "description",
+        "type": "alert"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "iteration": 1542303896062,
+  "links": [
+    {
+      "asDropdown": false,
+      "icon": "external link",
+      "tags": [
+        "gdev",
+        "elasticsearch"
+      ],
+      "title": "Dashboard",
+      "type": "dashboards"
+    }
+  ],
+  "panels": [
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v5-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 1,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": true,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "bucketAggs": [
+            {
+              "field": "@hostname",
+              "id": "3",
+              "settings": {
+                "min_doc_count": 1,
+                "order": "asc",
+                "orderBy": "1",
+                "size": "5"
+              },
+              "type": "terms"
+            },
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "auto",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {},
+              "type": "max"
+            }
+          ],
+          "query": "*",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Top 5 servers",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {
+        "Count": "#6ED0E0"
+      },
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v5-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 6,
+        "w": 12,
+        "x": 0,
+        "y": 7
+      },
+      "id": 2,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "Count",
+          "lines": false,
+          "yaxis": 2,
+          "zindex": -1
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "{{metric}}",
+          "bucketAggs": [
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "5m",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {
+                "percents": [
+                  25,
+                  50,
+                  75,
+                  95,
+                  99
+                ]
+              },
+              "type": "percentiles"
+            }
+          ],
+          "query": "@metric:cpu",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Percentiles & Metric filter",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {
+        "Count": "#6ED0E0"
+      },
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v5-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 6,
+        "w": 12,
+        "x": 12,
+        "y": 7
+      },
+      "id": 3,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "Count",
+          "lines": false,
+          "yaxis": 2,
+          "zindex": -1
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "{{metric}}",
+          "bucketAggs": [
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "auto",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {
+                "std_deviation_bounds_lower": true,
+                "std_deviation_bounds_upper": true
+              },
+              "settings": {},
+              "type": "extended_stats"
+            }
+          ],
+          "query": "@metric:cpu",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Standard dev",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "columns": [
+        {
+          "text": "@hostname",
+          "value": "@hostname"
+        },
+        {
+          "text": "Average",
+          "value": "Average"
+        },
+        {
+          "text": "Max",
+          "value": "Max"
+        },
+        {
+          "text": "Sum",
+          "value": "Sum"
+        }
+      ],
+      "datasource": "gdev-elasticsearch-v5-metrics",
+      "editable": true,
+      "error": false,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 13
+      },
+      "id": 6,
+      "links": [],
+      "pageSize": null,
+      "scroll": true,
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "styles": [
+        {
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "@timestamp",
+          "type": "date"
+        },
+        {
+          "colorMode": null,
+          "colors": [
+            "rgba(245, 54, 54, 0.9)",
+            "rgba(237, 129, 40, 0.89)",
+            "rgba(50, 172, 45, 0.97)"
+          ],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "pattern": "/.*/",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        }
+      ],
+      "targets": [
+        {
+          "bucketAggs": [
+            {
+              "field": "@hostname",
+              "id": "2",
+              "settings": {
+                "min_doc_count": 1,
+                "order": "asc",
+                "orderBy": "_term",
+                "size": "0"
+              },
+              "type": "terms"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {},
+              "type": "avg"
+            },
+            {
+              "field": "@value",
+              "id": "3",
+              "meta": {},
+              "settings": {},
+              "type": "max"
+            },
+            {
+              "field": "@value",
+              "id": "4",
+              "meta": {},
+              "settings": {},
+              "type": "sum"
+            }
+          ],
+          "refId": "B",
+          "timeField": "@timestamp"
+        }
+      ],
+      "title": "ES Metrics",
+      "transform": "table",
+      "type": "table"
+    },
+    {
+      "columns": [
+        {
+          "text": "@timestamp",
+          "value": "@timestamp"
+        },
+        {
+          "text": "@message",
+          "value": "@message"
+        },
+        {
+          "text": "tags",
+          "value": "tags"
+        },
+        {
+          "text": "description",
+          "value": "description"
+        }
+      ],
+      "datasource": "gdev-elasticsearch-v5-logs",
+      "editable": true,
+      "error": false,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 20
+      },
+      "id": 5,
+      "links": [],
+      "pageSize": null,
+      "scroll": true,
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "styles": [
+        {
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "@timestamp",
+          "type": "date"
+        }
+      ],
+      "targets": [
+        {
+          "bucketAggs": [],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "select field",
+              "id": "1",
+              "meta": {},
+              "settings": {
+                "size": 500
+              },
+              "type": "raw_document"
+            }
+          ],
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "title": "ES Log query",
+      "transform": "json",
+      "type": "table"
+    }
+  ],
+  "schemaVersion": 16,
+  "style": "dark",
+  "tags": [
+    "elasticsearch",
+    "gdev"
+  ],
+  "templating": {
+    "list": [
+      {
+        "datasource": "gdev-elasticsearch-v5-metrics",
+        "filters": [],
+        "hide": 0,
+        "label": "",
+        "name": "Filters",
+        "skipUrlSync": false,
+        "type": "adhoc"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-30m",
+    "to": "now"
+  },
+  "timepicker": {
+    "collapse": false,
+    "enable": true,
+    "notice": false,
+    "now": true,
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "status": "Stable",
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ],
+    "type": "timepicker"
+  },
+  "timezone": "browser",
+  "title": "Datasource tests - Elasticsearch v5",
+  "uid": "8HjT32Bmz",
+  "version": 27
+}

+ 649 - 0
devenv/dev-dashboards/datasource_tests_elasticsearch_v6.json

@@ -0,0 +1,649 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": false,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "limit": 100,
+        "name": "Annotations & Alerts",
+        "showIn": 0,
+        "type": "dashboard"
+      },
+      {
+        "datasource": "Elastic 5 Logs",
+        "enable": false,
+        "iconColor": "rgba(255, 96, 96, 1)",
+        "limit": 100,
+        "name": "test",
+        "query": "",
+        "showIn": 0,
+        "textField": "description",
+        "type": "alert"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "iteration": 1542303999511,
+  "links": [
+    {
+      "icon": "external link",
+      "tags": [
+        "gdev",
+        "elasticsearch"
+      ],
+      "type": "dashboards"
+    }
+  ],
+  "panels": [
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v6-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 1,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": true,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "bucketAggs": [
+            {
+              "field": "@hostname",
+              "id": "3",
+              "settings": {
+                "min_doc_count": 1,
+                "order": "asc",
+                "orderBy": "1",
+                "size": "5"
+              },
+              "type": "terms"
+            },
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "auto",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {},
+              "type": "max"
+            }
+          ],
+          "query": "*",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Top 5 servers",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {
+        "Count": "#6ED0E0"
+      },
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v6-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 6,
+        "w": 12,
+        "x": 0,
+        "y": 7
+      },
+      "id": 2,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "Count",
+          "lines": false,
+          "yaxis": 2,
+          "zindex": -1
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "{{metric}}",
+          "bucketAggs": [
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "5m",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {
+                "percents": [
+                  25,
+                  50,
+                  75,
+                  95,
+                  99
+                ]
+              },
+              "type": "percentiles"
+            }
+          ],
+          "query": "@metric:cpu",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Percentiles & Metric filter",
+      "tooltip": {
+        "msResolution": false,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {
+        "Count": "#6ED0E0"
+      },
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "gdev-elasticsearch-v6-metrics",
+      "editable": true,
+      "error": false,
+      "fill": 1,
+      "grid": {},
+      "gridPos": {
+        "h": 6,
+        "w": 12,
+        "x": 12,
+        "y": 7
+      },
+      "id": 3,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 2,
+      "links": [],
+      "nullPointMode": "connected",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [
+        {
+          "alias": "Count",
+          "lines": false,
+          "yaxis": 2,
+          "zindex": -1
+        }
+      ],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "alias": "{{metric}}",
+          "bucketAggs": [
+            {
+              "field": "@timestamp",
+              "id": "2",
+              "settings": {
+                "interval": "auto",
+                "min_doc_count": 0,
+                "trimEdges": 0
+              },
+              "type": "date_histogram"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {
+                "std_deviation_bounds_lower": true,
+                "std_deviation_bounds_upper": true
+              },
+              "settings": {},
+              "type": "extended_stats"
+            }
+          ],
+          "query": "@metric:cpu",
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeRegions": [],
+      "timeShift": null,
+      "title": "Standard dev",
+      "tooltip": {
+        "msResolution": true,
+        "shared": true,
+        "sort": 0,
+        "value_type": "cumulative"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "columns": [
+        {
+          "text": "@hostname",
+          "value": "@hostname"
+        },
+        {
+          "text": "Average",
+          "value": "Average"
+        },
+        {
+          "text": "Max",
+          "value": "Max"
+        },
+        {
+          "text": "Sum",
+          "value": "Sum"
+        }
+      ],
+      "datasource": "gdev-elasticsearch-v6-metrics",
+      "editable": true,
+      "error": false,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 13
+      },
+      "id": 6,
+      "links": [],
+      "pageSize": null,
+      "scroll": true,
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "styles": [
+        {
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "@timestamp",
+          "type": "date"
+        },
+        {
+          "colorMode": null,
+          "colors": [
+            "rgba(245, 54, 54, 0.9)",
+            "rgba(237, 129, 40, 0.89)",
+            "rgba(50, 172, 45, 0.97)"
+          ],
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "decimals": 2,
+          "pattern": "/.*/",
+          "thresholds": [],
+          "type": "number",
+          "unit": "short"
+        }
+      ],
+      "targets": [
+        {
+          "bucketAggs": [
+            {
+              "field": "@hostname",
+              "id": "2",
+              "settings": {
+                "min_doc_count": 1,
+                "order": "asc",
+                "orderBy": "_term",
+                "size": "0"
+              },
+              "type": "terms"
+            }
+          ],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "@value",
+              "id": "1",
+              "meta": {},
+              "settings": {},
+              "type": "avg"
+            },
+            {
+              "field": "@value",
+              "id": "3",
+              "meta": {},
+              "settings": {},
+              "type": "max"
+            },
+            {
+              "field": "@value",
+              "id": "4",
+              "meta": {},
+              "settings": {},
+              "type": "sum"
+            }
+          ],
+          "refId": "B",
+          "timeField": "@timestamp"
+        }
+      ],
+      "title": "ES Metrics",
+      "transform": "table",
+      "type": "table"
+    },
+    {
+      "columns": [
+        {
+          "text": "@timestamp",
+          "value": "@timestamp"
+        },
+        {
+          "text": "@message",
+          "value": "@message"
+        },
+        {
+          "text": "tags",
+          "value": "tags"
+        },
+        {
+          "text": "description",
+          "value": "description"
+        }
+      ],
+      "datasource": "gdev-elasticsearch-v6-logs",
+      "editable": true,
+      "error": false,
+      "fontSize": "100%",
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 20
+      },
+      "id": 5,
+      "links": [],
+      "pageSize": null,
+      "scroll": true,
+      "showHeader": true,
+      "sort": {
+        "col": 0,
+        "desc": true
+      },
+      "styles": [
+        {
+          "dateFormat": "YYYY-MM-DD HH:mm:ss",
+          "pattern": "@timestamp",
+          "type": "date"
+        }
+      ],
+      "targets": [
+        {
+          "bucketAggs": [],
+          "dsType": "elasticsearch",
+          "metrics": [
+            {
+              "field": "select field",
+              "id": "1",
+              "meta": {},
+              "settings": {
+                "size": 500
+              },
+              "type": "raw_document"
+            }
+          ],
+          "refId": "A",
+          "target": "",
+          "timeField": "@timestamp"
+        }
+      ],
+      "title": "ES Log query",
+      "transform": "json",
+      "type": "table"
+    }
+  ],
+  "schemaVersion": 16,
+  "style": "dark",
+  "tags": [
+    "elasticsearch",
+    "gdev"
+  ],
+  "templating": {
+    "list": [
+      {
+        "datasource": "gdev-elasticsearch-v6-metrics",
+        "filters": [],
+        "hide": 0,
+        "label": "",
+        "name": "Filters",
+        "skipUrlSync": false,
+        "type": "adhoc"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-30m",
+    "to": "now"
+  },
+  "timepicker": {
+    "collapse": false,
+    "enable": true,
+    "notice": false,
+    "now": true,
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "status": "Stable",
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ],
+    "type": "timepicker"
+  },
+  "timezone": "browser",
+  "title": "Datasource tests - Elasticsearch v6",
+  "uid": "NF8Pq2Biz",
+  "version": 2
+}

+ 1 - 1
devenv/docker/blocks/elastic/docker-compose.yaml

@@ -5,7 +5,7 @@
       - "9200:9200"
       - "9300:9300"
     volumes:
-      - ./blocks/elastic/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
+      - ./docker/blocks/elastic/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
 
   fake-elastic-data:
     image: grafana/fake-data-gen

+ 7 - 4
devenv/docker/blocks/elastic5/docker-compose.yaml

@@ -1,15 +1,18 @@
 # You need to run 'sysctl -w vm.max_map_count=262144' on the host machine
-
+version: '2'
+services:
   elasticsearch5:
     image: elasticsearch:5
     command: elasticsearch
     ports:
-      - "10200:9200"
-      - "10300:9300"
+      - '10200:9200'
+      - '10300:9300'
 
   fake-elastic5-data:
     image: grafana/fake-data-gen
-    network_mode: bridge
+    links:
+      - elasticsearch5
+    # network_mode: bridge
     environment:
       FD_DATASOURCE: elasticsearch
       FD_PORT: 10200

+ 7 - 5
devenv/docker/blocks/influxdb/docker-compose.yaml

@@ -1,17 +1,19 @@
+version: '2'
+services:
   influxdb:
     image: influxdb:latest
     container_name: influxdb
     ports:
-      - "2004:2004"
-      - "8083:8083"
-      - "8086:8086"
+      - '2004:2004'
+      - '8083:8083'
+      - '8086:8086'
     volumes:
       - ./docker/blocks/influxdb/influxdb.conf:/etc/influxdb/influxdb.conf
 
   fake-influxdb-data:
     image: grafana/fake-data-gen
-    network_mode: bridge
+    links:
+      - influxdb
     environment:
       FD_DATASOURCE: influxdb
       FD_PORT: 8086
-

+ 162 - 0
docs/sources/features/explore/index.md

@@ -0,0 +1,162 @@
++++
+title = "Explore"
+type = "docs"
+[menu.docs]
+name = "Explore"
+identifier = "explore"
+parent = "features"
+weight = 5
++++
+
+# Introduction
+
+One of the major new features of Grafana 6.0 is the new query-focused Explore workflow for troubleshooting and/or for data exploration.
+
+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. This creates a new debugging workflow where you can:
+
+1. Receive an alert
+2. Drill down and examine metrics
+3. Drill down again and search logs related to the metric and time interval (and in the future, distributed traces).
+
+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.
+
+{{< docs-imagebox img="/img/docs/v60/explore_menu.png" class="docs-image--no-shadow" caption="Screenshot of the new Explore Icon" >}}
+
+If you want to start with an existing query in a panel then choose the Explore option from the Panel menu. This opens an Explore tab with the query from the panel and allows you to tweak or iterate in the query outside of your dashboard.
+
+{{< docs-imagebox img="/img/docs/v60/explore_panel_menu.png" class="docs-image--no-shadow" caption="Screenshot of the new Explore option in the panel menu" >}}
+
+Choose your datasource in the dropdown in the top left. Prometheus has a custom Explore implementation, the other datasources (for now) use their standard query editor.
+
+The query field is where you can write your query and explore your data. There are three buttons beside the query field, a clear button (X), an add query button (+) and the remove query button (-). Just like the normal query editor, you can add and remove multiple queries.
+
+## Split and Compare
+
+The Split feature is an easy way to compare graphs and tables side-by-side or to look at related data together on one page. Click the split button to duplicate the current query and split the page into two side-by-side queries. It is possible to select another datasource for the new query which for example, allows you to compare the same query for two different servers or to compare the staging environment to the production environment.
+
+{{< 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" >}}
+
+You can close the newly created query by clicking on the Close Split button.
+
+## Prometheus-specific Features
+
+The first version of Explore features a custom querying experience for Prometheus. When a query is executed, it actually executes two queries, a normal Prometheus query for the graph and an Instant Query for the table. An Instant Query returns the last value for each time series which shows a good summary of the data shown in the graph.
+
+### Metrics Explorer
+
+On the left-hand side of the query field is a `Metrics` button, clicking on this opens the Metric Explorer. This shows a hierarchical menu with metrics grouped by their prefix. For example, all the Alert Manager metrics will be grouped under the `alertmanager` prefix. This is a good starting point if you just want to explore which metrics are available.
+
+{{< docs-imagebox img="/img/docs/v60/explore_metric_explorer.png" class="docs-image--no-shadow" caption="Screenshot of the new Explore option in the panel menu" >}}
+
+### Query Field
+
+The Query field supports autocomplete for metric names, function and works mostly the same way as the standard Prometheus query editor. Press the enter key to execute a query.
+
+The autocomplete menu can be trigger by pressing Ctrl + Space. The Autocomplete menu contains a new History section with a list of recently executed queries.
+
+Suggestions can appear under the query field - click on them to update your query with the suggested change.
+
+- For counters (monotonously increasing metrics), a rate function will be suggested.
+- For buckets, a histogram function will be suggested.
+- For recording rules, possible to expand the rules.
+
+### Table Filters
+
+Click on the filter button <span title="Filter for label" class="logs-label__icon fa fa-search-plus"></span> in a labels column in the Table panel to add filters to the query expression. This works with multiple queries too - the filter will be added for all the queries.
+
+## Logs Integration - Loki-specific Features
+
+For Grafana 6.0, the first log integration is for the new open source log aggregation system from Grafana Labs - [Loki](https://github.com/grafana/loki). Loki 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 the Grafana Labs hosted variant: [Grafana Cloud Logs](https://grafana.com/loki).
+
+### Switching from Metrics to Logs
+
+If you switch from a Prometheus query to a logs query (you can do a split first to have your metrics and logs side by side) then it will keep the labels from your query that exist in the logs and use those to query the log streams. For example, the following Prometheus query:
+
+`grafana_alerting_active_alerts{job="grafana"}`
+
+after switching to the Logs datasource, the query changes to:
+
+`{job="grafana"}`
+
+This will return a chunk of logs in the selected time range that can be grepped/text searched.
+
+### Log Queries
+
+A log query consists of two parts: **log stream selector**, and a **search expression**. For performance reasons you need to start by choosing a log stream by selecting a log label.
+
+The Logs Explorer (the `Log labels` button) next to the query field shows a list of labels of available log streams. An alternative way to write a query is to use the query field's autocomplete - you start by typing a left curly brace `{` and the autocomplete menu will suggest a list of labels. Press the `enter` key to execute the query.
+
+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
+
+For the label part of the query expression, wrap it in curly braces `{}` and then use the key value syntax for selecting labels. Multiple label expressions are separated by a comma:
+
+`{app="mysql",name="mysql-backup"}`
+
+The following label matching operators are currently supported:
+
+- `=` exactly equal.
+- `!=` not equal.
+- `=~` regex-match.
+- `!~` do not regex-match.
+
+Examples:
+
+- `{name=~"mysql.+"}`
+- `{name!~"mysql.+"}`
+
+The [same rules that apply for Prometheus Label Selectors](https://prometheus.io/docs/prometheus/latest/querying/basics/#instant-vector-selectors) apply for Loki Log Stream Selectors.
+
+Another way to add a label selector, is in the table section, clicking on the **Filter** button beside a label will add the label to the query expression. This even works for multiple queries and will the label selector to each query.
+
+#### Search Expression
+
+After writing the Log Stream Selector, you can filter the results further by writing a search expression. The search expression can be just text or a regex expression.
+
+Example queries:
+
+- `{job="mysql"} error`
+- `{name="kafka"} tsdb-ops.*io:2003`
+- `{instance=~"kafka-[23]",name="kafka"} kafka.server:type=ReplicaManager`
+
+### Deduping
+
+Log data can be very repetitive and Explore can help by hiding duplicate log lines. There are a few different deduplication algorithms that you can use:
+
+- `exact` Exact matches are done on the whole line, except for date fields.
+- `numbers` Matches on the line after stripping out numbers (durations, IP addresses etc.).
+- `signature` The most aggressive deduping - strips all letters and numbers, and matches on the remaining whitespace and punctuation.
+
+### Timestamp, Local time and Labels
+
+There are some other check boxes under the logging graph apart from the Deduping options.
+
+- Timestamp: shows/hides the Timestamp column
+- Local time: shows/hides the Local time column
+- Labels: shows/hides the label filters column

+ 2 - 2
latest.json

@@ -1,4 +1,4 @@
 {
-  "stable": "5.4.0",
-  "testing": "5.4.0"
+  "stable": "5.4.2",
+  "testing": "5.4.2"
 }

+ 1 - 1
package.json

@@ -155,7 +155,7 @@
     "react-popper": "^1.3.0",
     "react-highlight-words": "0.11.0",
     "react-redux": "^5.0.7",
-    "react-select": "2.1.0",
+    "@torkelo/react-select": "2.1.1",
     "react-sizeme": "^2.3.6",
     "react-table": "^6.8.6",
     "react-transition-group": "^2.2.1",

+ 11 - 11
packaging/publish/publish_both.sh

@@ -1,17 +1,17 @@
 #! /usr/bin/env bash
-version=5.4.1
+version=5.4.2
 
-wget https://dl.grafana.com/oss/release/grafana_${version}_amd64.deb
+# wget https://dl.grafana.com/oss/release/grafana_${version}_amd64.deb
+#
+# package_cloud push grafana/stable/debian/jessie grafana_${version}_amd64.deb
+# package_cloud push grafana/stable/debian/wheezy grafana_${version}_amd64.deb
+# package_cloud push grafana/stable/debian/stretch grafana_${version}_amd64.deb
+#
+# package_cloud push grafana/testing/debian/jessie grafana_${version}_amd64.deb
+# package_cloud push grafana/testing/debian/wheezy grafana_${version}_amd64.deb --verbose
+# package_cloud push grafana/testing/debian/stretch grafana_${version}_amd64.deb --verbose
 
-package_cloud push grafana/stable/debian/jessie grafana_${version}_amd64.deb
-package_cloud push grafana/stable/debian/wheezy grafana_${version}_amd64.deb
-package_cloud push grafana/stable/debian/stretch grafana_${version}_amd64.deb
-
-package_cloud push grafana/testing/debian/jessie grafana_${version}_amd64.deb
-package_cloud push grafana/testing/debian/wheezy grafana_${version}_amd64.deb --verbose
-package_cloud push grafana/testing/debian/stretch grafana_${version}_amd64.deb --verbose
-
-wget https://dl.grafana.com/release/grafana-${version}-1.x86_64.rpm
+wget https://dl.grafana.com/oss/release/grafana-${version}-1.x86_64.rpm
 
 package_cloud push grafana/testing/el/6 grafana-${version}-1.x86_64.rpm --verbose
 package_cloud push grafana/testing/el/7 grafana-${version}-1.x86_64.rpm --verbose

+ 2 - 2
pkg/services/provisioning/dashboards/file_reader.go

@@ -333,12 +333,12 @@ func (fr *fileReader) resolvePath(path string) string {
 	copy := path
 	path, err := filepath.Abs(path)
 	if err != nil {
-		fr.log.Error("Could not create absolute path ", "path", path)
+		fr.log.Error("Could not create absolute path", "path", copy, "error", err)
 	}
 
 	path, err = filepath.EvalSymlinks(path)
 	if err != nil {
-		fr.log.Error("Failed to read content of symlinked path: %s", path)
+		fr.log.Error("Failed to read content of symlinked path", "path", copy, "error", err)
 	}
 
 	if path == "" {

+ 3 - 0
pkg/services/sqlstore/migrations/datasource_mig.go

@@ -127,4 +127,7 @@ func addDataSourceMigration(mg *Migrator) {
 	mg.AddMigration("Add read_only data column", NewAddColumnMigration(tableV2, &Column{
 		Name: "read_only", Type: DB_Bool, Nullable: true,
 	}))
+
+	const migrateLoggingToLoki = `UPDATE data_source SET type = 'loki' WHERE type = 'logging'`
+	mg.AddMigration("Migrate logging ds to loki ds", NewRawSqlMigration(migrateLoggingToLoki))
 }

+ 3 - 0
pkg/tsdb/elasticsearch/models.go

@@ -73,5 +73,8 @@ func isPipelineAgg(metricType string) bool {
 
 func describeMetric(metricType, field string) string {
 	text := metricAggType[metricType]
+	if metricType == countType {
+		return text
+	}
 	return text + " " + field
 }

+ 18 - 4
pkg/tsdb/elasticsearch/time_series_query.go

@@ -89,15 +89,29 @@ func (e *timeSeriesQuery) execute() (*tsdb.Response, error) {
 		}
 
 		for _, m := range q.Metrics {
-			if m.Type == "count" {
+			if m.Type == countType {
 				continue
 			}
 
 			if isPipelineAgg(m.Type) {
 				if _, err := strconv.Atoi(m.PipelineAggregate); err == nil {
-					aggBuilder.Pipeline(m.ID, m.Type, m.PipelineAggregate, func(a *es.PipelineAggregation) {
-						a.Settings = m.Settings.MustMap()
-					})
+					var appliedAgg *MetricAgg
+					for _, pipelineMetric := range q.Metrics {
+						if pipelineMetric.ID == m.PipelineAggregate {
+							appliedAgg = pipelineMetric
+							break
+						}
+					}
+					if appliedAgg != nil {
+						bucketPath := m.PipelineAggregate
+						if appliedAgg.Type == countType {
+							bucketPath = "_count"
+						}
+
+						aggBuilder.Pipeline(m.ID, m.Type, bucketPath, func(a *es.PipelineAggregation) {
+							a.Settings = m.Settings.MustMap()
+						})
+					}
 				} else {
 					continue
 				}

+ 60 - 0
pkg/tsdb/elasticsearch/time_series_query_test.go

@@ -418,6 +418,38 @@ func TestExecuteTimeSeriesQuery(t *testing.T) {
 			So(pl.BucketPath, ShouldEqual, "3")
 		})
 
+		Convey("With moving average doc count", func() {
+			c := newFakeClient(5)
+			_, err := executeTsdbQuery(c, `{
+				"timeField": "@timestamp",
+				"bucketAggs": [
+					{ "type": "date_histogram", "field": "@timestamp", "id": "4" }
+				],
+				"metrics": [
+					{ "id": "3", "type": "count", "field": "select field" },
+					{
+						"id": "2",
+						"type": "moving_avg",
+						"field": "3",
+						"pipelineAgg": "3"
+					}
+				]
+			}`, from, to, 15*time.Second)
+			So(err, ShouldBeNil)
+			sr := c.multisearchRequests[0].Requests[0]
+
+			firstLevel := sr.Aggs[0]
+			So(firstLevel.Key, ShouldEqual, "4")
+			So(firstLevel.Aggregation.Type, ShouldEqual, "date_histogram")
+			So(firstLevel.Aggregation.Aggs, ShouldHaveLength, 1)
+
+			movingAvgAgg := firstLevel.Aggregation.Aggs[0]
+			So(movingAvgAgg.Key, ShouldEqual, "2")
+			So(movingAvgAgg.Aggregation.Type, ShouldEqual, "moving_avg")
+			pl := movingAvgAgg.Aggregation.Aggregation.(*es.PipelineAggregation)
+			So(pl.BucketPath, ShouldEqual, "_count")
+		})
+
 		Convey("With broken moving average", func() {
 			c := newFakeClient(5)
 			_, err := executeTsdbQuery(c, `{
@@ -483,6 +515,34 @@ func TestExecuteTimeSeriesQuery(t *testing.T) {
 			So(plAgg.BucketPath, ShouldEqual, "3")
 		})
 
+		Convey("With derivative doc count", func() {
+			c := newFakeClient(5)
+			_, err := executeTsdbQuery(c, `{
+				"timeField": "@timestamp",
+				"bucketAggs": [
+					{ "type": "date_histogram", "field": "@timestamp", "id": "4" }
+				],
+				"metrics": [
+					{ "id": "3", "type": "count", "field": "select field" },
+					{
+						"id": "2",
+						"type": "derivative",
+						"pipelineAgg": "3"
+					}
+				]
+			}`, from, to, 15*time.Second)
+			So(err, ShouldBeNil)
+			sr := c.multisearchRequests[0].Requests[0]
+
+			firstLevel := sr.Aggs[0]
+			So(firstLevel.Key, ShouldEqual, "4")
+			So(firstLevel.Aggregation.Type, ShouldEqual, "date_histogram")
+
+			derivativeAgg := firstLevel.Aggregation.Aggs[0]
+			So(derivativeAgg.Key, ShouldEqual, "2")
+			plAgg := derivativeAgg.Aggregation.Aggregation.(*es.PipelineAggregation)
+			So(plAgg.BucketPath, ShouldEqual, "_count")
+		})
 	})
 }
 

+ 1 - 0
public/app/core/components/AppNotifications/AppNotificationItem.tsx

@@ -20,6 +20,7 @@ export default class AppNotificationItem extends Component<Props> {
 
   render() {
     const { appNotification, onClearNotification } = this.props;
+
     return (
       <div className={`alert-${appNotification.severity} alert`}>
         <div className="alert-icon">

+ 2 - 2
public/app/core/components/CustomScrollbar/CustomScrollbar.tsx

@@ -28,8 +28,8 @@ class CustomScrollbar extends PureComponent<Props> {
       <Scrollbars
         className={customClassName}
         autoHeight={true}
-        autoHeightMin={'100%'}
-        autoHeightMax={'100%'}
+        autoHeightMin={'inherit'}
+        autoHeightMax={'inherit'}
         renderTrackHorizontal={props => <div {...props} className="track-horizontal" />}
         renderTrackVertical={props => <div {...props} className="track-vertical" />}
         renderThumbHorizontal={props => <div {...props} className="thumb-horizontal" />}

+ 4 - 4
public/app/core/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap

@@ -6,8 +6,8 @@ exports[`CustomScrollbar renders correctly 1`] = `
   style={
     Object {
       "height": "auto",
-      "maxHeight": "100%",
-      "minHeight": "100%",
+      "maxHeight": "inherit",
+      "minHeight": "inherit",
       "overflow": "hidden",
       "position": "relative",
       "width": "100%",
@@ -23,8 +23,8 @@ exports[`CustomScrollbar renders correctly 1`] = `
         "left": undefined,
         "marginBottom": 0,
         "marginRight": 0,
-        "maxHeight": "calc(100% + 0px)",
-        "minHeight": "calc(100% + 0px)",
+        "maxHeight": "calc(inherit + 0px)",
+        "minHeight": "calc(inherit + 0px)",
         "overflow": "scroll",
         "position": "relative",
         "right": undefined,

+ 7 - 2
public/app/core/components/Form/Input.tsx

@@ -1,4 +1,5 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent } from 'react';
+import classNames from 'classnames';
 import { ValidationEvents, ValidationRule } from 'app/types';
 import { validate, hasValidationEvent } from 'app/core/utils/validate';
 
@@ -31,6 +32,10 @@ interface Props extends React.HTMLProps<HTMLInputElement> {
 }
 
 export class Input extends PureComponent<Props> {
+  static defaultProps = {
+    className: '',
+  };
+
   state = {
     error: null,
   };
@@ -76,7 +81,7 @@ export class Input extends PureComponent<Props> {
   render() {
     const { validationEvents, className, hideErrorMessage, ...restProps } = this.props;
     const { error } = this.state;
-    const inputClassName = 'gf-form-input' + (this.isInvalid ? ' invalid' : '');
+    const inputClassName = classNames('gf-form-input', { invalid: this.isInvalid }, className);
     const inputElementProps = this.populateEventPropsWithStatus(restProps, validationEvents);
 
     return (

+ 9 - 9
public/app/core/components/PermissionList/AddPermission.tsx

@@ -1,7 +1,7 @@
 import React, { Component } from 'react';
-import { UserPicker } from 'app/core/components/Picker/UserPicker';
-import { TeamPicker, Team } from 'app/core/components/Picker/TeamPicker';
-import DescriptionPicker, { OptionWithDescription } from 'app/core/components/Picker/DescriptionPicker';
+import { UserPicker } from 'app/core/components/Select/UserPicker';
+import { TeamPicker, Team } from 'app/core/components/Select/TeamPicker';
+import { Select, SelectOptionItem } from 'app/core/components/Select/Select';
 import { User } from 'app/types';
 import {
   dashboardPermissionLevels,
@@ -61,7 +61,7 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
     this.setState({ teamId: team && !Array.isArray(team) ? team.id : 0 });
   };
 
-  onPermissionChanged = (permission: OptionWithDescription) => {
+  onPermissionChanged = (permission: SelectOptionItem) => {
     this.setState({ permission: permission.value });
   };
 
@@ -121,11 +121,11 @@ class AddPermissions extends Component<Props, NewDashboardAclItem> {
             ) : null}
 
             <div className="gf-form">
-              <DescriptionPicker
-                optionsWithDesc={dashboardPermissionLevels}
-                onSelected={this.onPermissionChanged}
-                disabled={false}
-                className={'gf-form-select-box__control--menu-right'}
+              <Select
+                isSearchable={false}
+                options={dashboardPermissionLevels}
+                onChange={this.onPermissionChanged}
+                className="gf-form-select-box__control--menu-right"
               />
             </div>
 

+ 8 - 7
public/app/core/components/PermissionList/DisabledPermissionListItem.tsx

@@ -1,5 +1,5 @@
 import React, { Component } from 'react';
-import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
+import Select from 'app/core/components/Select/Select';
 import { dashboardPermissionLevels } from 'app/types/acl';
 
 export interface Props {
@@ -9,6 +9,7 @@ export interface Props {
 export default class DisabledPermissionListItem extends Component<Props, any> {
   render() {
     const { item } = this.props;
+    const currentPermissionLevel = dashboardPermissionLevels.find(dp => dp.value === item.permission);
 
     return (
       <tr className="gf-form-disabled">
@@ -23,12 +24,12 @@ export default class DisabledPermissionListItem extends Component<Props, any> {
         <td className="query-keyword">Can</td>
         <td>
           <div className="gf-form">
-            <DescriptionPicker
-              optionsWithDesc={dashboardPermissionLevels}
-              onSelected={() => {}}
-              disabled={true}
-              className={'gf-form-select-box__control--menu-right'}
-              value={item.permission}
+            <Select
+              options={dashboardPermissionLevels}
+              onChange={() => {}}
+              isDisabled={true}
+              className="gf-form-select-box__control--menu-right"
+              value={currentPermissionLevel}
             />
           </div>
         </td>

+ 9 - 7
public/app/core/components/PermissionList/PermissionListItem.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
+import { Select } from 'app/core/components/Select/Select';
 import { dashboardPermissionLevels, DashboardAcl, PermissionLevel } from 'app/types/acl';
 import { FolderInfo } from 'app/types';
 
@@ -50,6 +50,7 @@ export default class PermissionsListItem extends PureComponent<Props> {
   render() {
     const { item, folderInfo } = this.props;
     const inheritedFromRoot = item.dashboardId === -1 && !item.inherited;
+    const currentPermissionLevel = dashboardPermissionLevels.find(dp => dp.value === item.permission);
 
     return (
       <tr className={setClassNameHelper(item.inherited)}>
@@ -74,12 +75,13 @@ export default class PermissionsListItem extends PureComponent<Props> {
         <td className="query-keyword">Can</td>
         <td>
           <div className="gf-form">
-            <DescriptionPicker
-              optionsWithDesc={dashboardPermissionLevels}
-              onSelected={this.onPermissionChanged}
-              disabled={item.inherited}
-              className={'gf-form-select-box__control--menu-right'}
-              value={item.permission}
+            <Select
+              isSearchable={false}
+              options={dashboardPermissionLevels}
+              onChange={this.onPermissionChanged}
+              isDisabled={item.inherited}
+              className="gf-form-select-box__control--menu-right"
+              value={currentPermissionLevel}
             />
           </div>
         </td>

+ 0 - 26
public/app/core/components/Picker/DescriptionOption.tsx

@@ -1,26 +0,0 @@
-import React from 'react';
-import { components } from 'react-select';
-import { OptionProps } from 'react-select/lib/components/Option';
-
-// https://github.com/JedWatson/react-select/issues/3038
-interface ExtendedOptionProps extends OptionProps<any> {
-  data: any;
-}
-
-export const Option = (props: ExtendedOptionProps) => {
-  const { children, isSelected, data } = props;
-
-  return (
-    <components.Option {...props}>
-      <div className="gf-form-select-box__desc-option">
-        <div className="gf-form-select-box__desc-option__body">
-          <div>{children}</div>
-          {data.description && <div className="gf-form-select-box__desc-option__desc">{data.description}</div>}
-        </div>
-        {isSelected && <i className="fa fa-check" aria-hidden="true" />}
-      </div>
-    </components.Option>
-  );
-};
-
-export default Option;

+ 0 - 52
public/app/core/components/Picker/DescriptionPicker.tsx

@@ -1,52 +0,0 @@
-import React, { Component } from 'react';
-import Select from 'react-select';
-import DescriptionOption from './DescriptionOption';
-import IndicatorsContainer from './IndicatorsContainer';
-import ResetStyles from './ResetStyles';
-import NoOptionsMessage from './NoOptionsMessage';
-
-export interface OptionWithDescription {
-  value: any;
-  label: string;
-  description: string;
-}
-
-export interface Props {
-  optionsWithDesc: OptionWithDescription[];
-  onSelected: (permission) => void;
-  disabled: boolean;
-  className?: string;
-  value?: any;
-}
-
-const getSelectedOption = (optionsWithDesc, value) => optionsWithDesc.find(option => option.value === value);
-
-class DescriptionPicker extends Component<Props, any> {
-  render() {
-    const { optionsWithDesc, onSelected, disabled, className, value } = this.props;
-    const selectedOption = getSelectedOption(optionsWithDesc, value);
-    return (
-      <div className="permissions-picker">
-        <Select
-          placeholder="Choose"
-          classNamePrefix={`gf-form-select-box`}
-          className={`width-7 gf-form-input gf-form-input--form-dropdown ${className || ''}`}
-          options={optionsWithDesc}
-          components={{
-            Option: DescriptionOption,
-            IndicatorsContainer,
-            NoOptionsMessage,
-          }}
-          styles={ResetStyles}
-          isDisabled={disabled}
-          onChange={onSelected}
-          getOptionValue={i => i.value}
-          getOptionLabel={i => i.label}
-          value={selectedOption}
-        />
-      </div>
-    );
-  }
-}
-
-export default DescriptionPicker;

+ 0 - 18
public/app/core/components/Picker/NoOptionsMessage.tsx

@@ -1,18 +0,0 @@
-import React from 'react';
-import { components } from 'react-select';
-import { OptionProps } from 'react-select/lib/components/Option';
-
-export interface Props {
-  children: Element;
-}
-
-export const PickerOption = (props: OptionProps<any>) => {
-  const { children, className } = props;
-  return (
-    <components.Option {...props}>
-      <div className={`description-picker-option__button btn btn-link ${className}`}>{children}</div>
-    </components.Option>
-  );
-};
-
-export default PickerOption;

+ 0 - 60
public/app/core/components/Picker/Select.tsx

@@ -1,60 +0,0 @@
-// import React, { PureComponent } from 'react';
-// import Select as ReactSelect from 'react-select';
-// import DescriptionOption from './DescriptionOption';
-// import IndicatorsContainer from './IndicatorsContainer';
-// import ResetStyles from './ResetStyles';
-//
-// export interface OptionType {
-//   label: string;
-//   value: string;
-// }
-//
-// interface Props {
-//   defaultValue?: any;
-//   getOptionLabel: (item: T) => string;
-//   getOptionValue: (item: T) => string;
-//   onChange: (item: T) => {} | void;
-//   options: T[];
-//   placeholder?: string;
-//   width?: number;
-//   value: T;
-//   className?: string;
-// }
-//
-// export class Select<T> extends PureComponent<Props<T>> {
-//   static defaultProps = {
-//     width: null,
-//     className: '',
-//   }
-//
-//   render() {
-//     const { defaultValue, getOptionLabel, getOptionValue, onSelected, options, placeholder, width, value, className } = this.props;
-//     let widthClass = '';
-//     if (width) {
-//       widthClass = 'width-'+width;
-//     }
-//
-//   return (
-//     <ReactSelect
-//       classNamePrefix="gf-form-select-box"
-//       className={`gf-form-input gf-form-input--form-dropdown ${widthClass} ${className}`}
-//       components={{
-//         Option: DescriptionOption,
-//         IndicatorsContainer,
-//       }}
-//       defaultValue={defaultValue}
-//       value={value}
-//       getOptionLabel={getOptionLabel}
-//       getOptionValue={getOptionValue}
-//       menuShouldScrollIntoView={false}
-//       isSearchable={false}
-//       onChange={onSelected}
-//       options={options}
-//       placeholder={placeholder || 'Choose'}
-//       styles={ResetStyles}
-//     />
-//   );
-// }
-// }
-//
-// export default Select;

+ 0 - 52
public/app/core/components/Picker/SimplePicker.tsx

@@ -1,52 +0,0 @@
-import React, { SFC } from 'react';
-import Select from 'react-select';
-import DescriptionOption from './DescriptionOption';
-import IndicatorsContainer from './IndicatorsContainer';
-import ResetStyles from './ResetStyles';
-
-interface Props {
-  className?: string;
-  defaultValue?: any;
-  getOptionLabel: (item: any) => string;
-  getOptionValue: (item: any) => string;
-  onSelected: (item: any) => {} | void;
-  options: any[];
-  placeholder?: string;
-  width?: number;
-  value: any;
-}
-
-const SimplePicker: SFC<Props> = ({
-  className,
-  defaultValue,
-  getOptionLabel,
-  getOptionValue,
-  onSelected,
-  options,
-  placeholder,
-  width,
-  value,
-}) => {
-  return (
-    <Select
-      classNamePrefix="gf-form-select-box"
-      className={`${width ? 'width-' + width : ''} gf-form-input gf-form-input--form-dropdown ${className || ''}`}
-      components={{
-        Option: DescriptionOption,
-        IndicatorsContainer,
-      }}
-      defaultValue={defaultValue}
-      value={value}
-      getOptionLabel={getOptionLabel}
-      getOptionValue={getOptionValue}
-      menuShouldScrollIntoView={false}
-      isSearchable={false}
-      onChange={onSelected}
-      options={options}
-      placeholder={placeholder || 'Choose'}
-      styles={ResetStyles}
-    />
-  );
-};
-
-export default SimplePicker;

+ 0 - 22
public/app/core/components/Picker/Unit/UnitOption.tsx

@@ -1,22 +0,0 @@
-import React, { SFC } from 'react';
-import { components } from 'react-select';
-import { OptionProps } from 'react-select/lib/components/Option';
-
-interface ExtendedOptionProps extends OptionProps<any> {
-  data: any;
-}
-
-const UnitOption: SFC<ExtendedOptionProps> = props => {
-  const { children, isSelected, className } = props;
-
-  return (
-    <components.Option {...props}>
-      <div className={`unit-picker-option__button btn btn-link ${className}`}>
-        {isSelected && <i className="fa fa-check pull-right" aria-hidden="true" />}
-        <div className="gf-form">{children}</div>
-      </div>
-    </components.Option>
-  );
-};
-
-export default UnitOption;

+ 0 - 81
public/app/core/components/Picker/Unit/UnitPicker.tsx

@@ -1,81 +0,0 @@
-import React, { PureComponent } from 'react';
-import Select from 'react-select';
-import UnitGroup from './UnitGroup';
-import UnitOption from './UnitOption';
-import ResetStyles from '../ResetStyles';
-import kbn from '../../../utils/kbn';
-
-interface Props {
-  onSelected: (item: any) => {} | void;
-  defaultValue?: string;
-  width?: number;
-}
-
-export default class UnitPicker extends PureComponent<Props> {
-  static defaultProps = {
-    width: 12,
-  };
-
-  render() {
-    const { defaultValue, onSelected, width } = this.props;
-
-    const unitGroups = kbn.getUnitFormats();
-
-    // Need to transform the data structure to work well with Select
-    const groupOptions = unitGroups.map(group => {
-      const options = group.submenu.map(unit => {
-        return {
-          label: unit.text,
-          value: unit.value,
-        };
-      });
-
-      return {
-        label: group.text,
-        options,
-      };
-    });
-
-    const styles = {
-      ...ResetStyles,
-      menu: () => ({
-        maxHeight: '75%',
-        overflow: 'scroll',
-      }),
-      menuList: () =>
-        ({
-          overflowY: 'auto',
-          position: 'relative',
-        } as React.CSSProperties),
-      valueContainer: () =>
-        ({
-          overflow: 'hidden',
-          textOverflow: 'ellipsis',
-          maxWidth: '90px',
-          whiteSpace: 'nowrap',
-        } as React.CSSProperties),
-    };
-
-    const value = groupOptions.map(group => {
-      return group.options.find(option => option.value === defaultValue);
-    });
-
-    return (
-      <Select
-        classNamePrefix="gf-form-select-box"
-        className={`width-${width} gf-form-input gf-form-input--form-dropdown`}
-        defaultValue={value}
-        isSearchable={true}
-        menuShouldScrollIntoView={false}
-        options={groupOptions}
-        placeholder="Choose"
-        onChange={onSelected}
-        components={{
-          Group: UnitGroup,
-          Option: UnitOption,
-        }}
-        styles={styles}
-      />
-    );
-  }
-}

+ 6 - 17
public/app/features/dashboard/dashgrid/DataSourcePicker.tsx → public/app/core/components/Select/DataSourcePicker.tsx

@@ -3,16 +3,13 @@ import React, { PureComponent } from 'react';
 import _ from 'lodash';
 
 // Components
-import ResetStyles from 'app/core/components/Picker/ResetStyles';
-import { Option, SingleValue } from 'app/core/components/Picker/PickerOption';
-import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
-import Select from 'react-select';
+import Select from './Select';
 
 // Types
 import { DataSourceSelectItem } from 'app/types';
 
 export interface Props {
-  onChangeDataSource: (ds: DataSourceSelectItem) => void;
+  onChange: (ds: DataSourceSelectItem) => void;
   datasources: DataSourceSelectItem[];
   current: DataSourceSelectItem;
   onBlur?: () => void;
@@ -32,7 +29,7 @@ export class DataSourcePicker extends PureComponent<Props> {
 
   onChange = item => {
     const ds = this.props.datasources.find(ds => ds.name === item.value);
-    this.props.onChangeDataSource(ds);
+    this.props.onChange(ds);
   };
 
   render() {
@@ -53,27 +50,19 @@ export class DataSourcePicker extends PureComponent<Props> {
     return (
       <div className="gf-form-inline">
         <Select
-          classNamePrefix={`gf-form-select-box`}
+          className="ds-picker"
           isMulti={false}
-          menuShouldScrollIntoView={false}
           isClearable={false}
-          className="gf-form-input gf-form-input--form-dropdown ds-picker"
-          onChange={item => this.onChange(item)}
+          backspaceRemovesValue={false}
+          onChange={this.onChange}
           options={options}
-          styles={ResetStyles}
           autoFocus={autoFocus}
           onBlur={onBlur}
           openMenuOnFocus={true}
           maxMenuHeight={500}
           placeholder="Select datasource"
-          loadingMessage={() => 'Loading datasources...'}
           noOptionsMessage={() => 'No datasources found'}
           value={value}
-          components={{
-            Option,
-            SingleValue,
-            IndicatorsContainer,
-          }}
         />
       </div>
     );

+ 2 - 2
public/app/core/components/Picker/IndicatorsContainer.tsx → public/app/core/components/Select/IndicatorsContainer.tsx

@@ -1,5 +1,5 @@
-import React from 'react';
-import { components } from 'react-select';
+import React from 'react';
+import { components } from '@torkelo/react-select';
 
 export const IndicatorsContainer = props => {
   const isOpen = props.selectProps.menuIsOpen;

+ 20 - 0
public/app/core/components/Select/NoOptionsMessage.tsx

@@ -0,0 +1,20 @@
+import React from 'react';
+import { components } from '@torkelo/react-select';
+import { OptionProps } from '@torkelo/react-select/lib/components/Option';
+
+export interface Props {
+  children: Element;
+}
+
+export const NoOptionsMessage = (props: OptionProps<any>) => {
+  const { children } = props;
+  return (
+    <components.Option {...props}>
+      <div className="gf-form-select-box__desc-option">
+        <div className="gf-form-select-box__desc-option__body">{children}</div>
+      </div>
+    </components.Option>
+  );
+};
+
+export default NoOptionsMessage;

+ 5 - 5
public/app/core/components/Picker/Unit/UnitGroup.tsx → public/app/core/components/Select/OptionGroup.tsx

@@ -9,7 +9,7 @@ interface State {
   expanded: boolean;
 }
 
-export default class UnitGroup extends PureComponent<ExtendedGroupProps, State> {
+export default class OptionGroup extends PureComponent<ExtendedGroupProps, State> {
   state = {
     expanded: false,
   };
@@ -41,10 +41,10 @@ export default class UnitGroup extends PureComponent<ExtendedGroupProps, State>
     const { expanded } = this.state;
 
     return (
-      <div className="width-21 unit-picker-group" style={{ marginBottom: '5px' }}>
-        <div className="unit-picker-group-item" onClick={this.onToggleChildren}>
-          <span style={{ textTransform: 'capitalize' }}>{label}</span>
-          <i className={`fa ${expanded ? 'fa-minus' : 'fa-plus'}`} />{' '}
+      <div className="gf-form-select-box__option-group">
+        <div className="gf-form-select-box__option-group__header" onClick={this.onToggleChildren}>
+          <span className="flex-grow">{label}</span>
+          <i className={`fa ${expanded ? 'fa-caret-left' : 'fa-caret-down'}`} />{' '}
         </div>
         {expanded && children}
       </div>

+ 0 - 0
public/app/core/components/Picker/PickerOption.test.tsx → public/app/core/components/Select/PickerOption.test.tsx


+ 1 - 1
public/app/core/components/Picker/PickerOption.tsx → public/app/core/components/Select/PickerOption.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { components } from 'react-select';
+import { components } from '@torkelo/react-select';
 import { OptionProps } from 'react-select/lib/components/Option';
 
 // https://github.com/JedWatson/react-select/issues/3038

+ 0 - 0
public/app/core/components/Picker/ResetStyles.tsx → public/app/core/components/Select/ResetStyles.tsx


+ 232 - 0
public/app/core/components/Select/Select.tsx

@@ -0,0 +1,232 @@
+// Libraries
+import classNames from 'classnames';
+import React, { PureComponent } from 'react';
+import { default as ReactSelect } from '@torkelo/react-select';
+import { default as ReactAsyncSelect } from '@torkelo/react-select/lib/Async';
+import { components } from '@torkelo/react-select';
+
+// Components
+import { Option, SingleValue } from './PickerOption';
+import OptionGroup from './OptionGroup';
+import IndicatorsContainer from './IndicatorsContainer';
+import NoOptionsMessage from './NoOptionsMessage';
+import ResetStyles from './ResetStyles';
+import CustomScrollbar from '../CustomScrollbar/CustomScrollbar';
+
+export interface SelectOptionItem {
+  label?: string;
+  value?: any;
+  imgUrl?: string;
+  description?: string;
+  [key: string]: any;
+}
+
+interface CommonProps {
+  defaultValue?: any;
+  getOptionLabel?: (item: SelectOptionItem) => string;
+  getOptionValue?: (item: SelectOptionItem) => string;
+  onChange: (item: SelectOptionItem) => {} | void;
+  placeholder?: string;
+  width?: number;
+  value?: SelectOptionItem;
+  className?: string;
+  isDisabled?: boolean;
+  isSearchable?: boolean;
+  isClearable?: boolean;
+  autoFocus?: boolean;
+  openMenuOnFocus?: boolean;
+  onBlur?: () => void;
+  maxMenuHeight?: number;
+  isLoading: boolean;
+  noOptionsMessage?: () => string;
+  isMulti?: boolean;
+  backspaceRemovesValue: boolean;
+}
+
+interface SelectProps {
+  options: SelectOptionItem[];
+}
+
+interface AsyncProps {
+  defaultOptions: boolean;
+  loadOptions: (query: string) => Promise<SelectOptionItem[]>;
+  loadingMessage?: () => string;
+}
+
+export const MenuList = props => {
+  return (
+    <components.MenuList {...props}>
+      <CustomScrollbar autoHide={false}>{props.children}</CustomScrollbar>
+    </components.MenuList>
+  );
+};
+
+export class Select extends PureComponent<CommonProps & SelectProps> {
+  static defaultProps = {
+    width: null,
+    className: '',
+    isDisabled: false,
+    isSearchable: true,
+    isClearable: false,
+    isMulti: false,
+    openMenuOnFocus: false,
+    autoFocus: false,
+    isLoading: false,
+    backspaceRemovesValue: true,
+    maxMenuHeight: 300,
+  };
+
+  render() {
+    const {
+      defaultValue,
+      getOptionLabel,
+      getOptionValue,
+      onChange,
+      options,
+      placeholder,
+      width,
+      value,
+      className,
+      isDisabled,
+      isLoading,
+      isSearchable,
+      isClearable,
+      backspaceRemovesValue,
+      isMulti,
+      autoFocus,
+      openMenuOnFocus,
+      onBlur,
+      maxMenuHeight,
+      noOptionsMessage,
+    } = this.props;
+
+    let widthClass = '';
+    if (width) {
+      widthClass = 'width-' + width;
+    }
+
+    const selectClassNames = classNames('gf-form-input', 'gf-form-input--form-dropdown', widthClass, className);
+
+    return (
+      <ReactSelect
+        classNamePrefix="gf-form-select-box"
+        className={selectClassNames}
+        components={{
+          Option,
+          SingleValue,
+          IndicatorsContainer,
+          MenuList,
+          Group: OptionGroup,
+        }}
+        defaultValue={defaultValue}
+        value={value}
+        getOptionLabel={getOptionLabel}
+        getOptionValue={getOptionValue}
+        menuShouldScrollIntoView={false}
+        isSearchable={isSearchable}
+        onChange={onChange}
+        options={options}
+        placeholder={placeholder || 'Choose'}
+        styles={ResetStyles}
+        isDisabled={isDisabled}
+        isLoading={isLoading}
+        isClearable={isClearable}
+        autoFocus={autoFocus}
+        onBlur={onBlur}
+        openMenuOnFocus={openMenuOnFocus}
+        maxMenuHeight={maxMenuHeight}
+        noOptionsMessage={noOptionsMessage}
+        isMulti={isMulti}
+        backspaceRemovesValue={backspaceRemovesValue}
+      />
+    );
+  }
+}
+
+export class AsyncSelect extends PureComponent<CommonProps & AsyncProps> {
+  static defaultProps = {
+    width: null,
+    className: '',
+    components: {},
+    loadingMessage: () => 'Loading...',
+    isDisabled: false,
+    isClearable: false,
+    isMulti: false,
+    isSearchable: true,
+    backspaceRemovesValue: true,
+    autoFocus: false,
+    openMenuOnFocus: false,
+    maxMenuHeight: 300,
+  };
+
+  render() {
+    const {
+      defaultValue,
+      getOptionLabel,
+      getOptionValue,
+      onChange,
+      placeholder,
+      width,
+      value,
+      className,
+      loadOptions,
+      defaultOptions,
+      isLoading,
+      loadingMessage,
+      noOptionsMessage,
+      isDisabled,
+      isSearchable,
+      isClearable,
+      backspaceRemovesValue,
+      autoFocus,
+      onBlur,
+      openMenuOnFocus,
+      maxMenuHeight,
+      isMulti,
+    } = this.props;
+
+    let widthClass = '';
+    if (width) {
+      widthClass = 'width-' + width;
+    }
+
+    const selectClassNames = classNames('gf-form-input', 'gf-form-input--form-dropdown', widthClass, className);
+
+    return (
+      <ReactAsyncSelect
+        classNamePrefix="gf-form-select-box"
+        className={selectClassNames}
+        components={{
+          Option,
+          SingleValue,
+          IndicatorsContainer,
+          NoOptionsMessage,
+        }}
+        defaultValue={defaultValue}
+        value={value}
+        getOptionLabel={getOptionLabel}
+        getOptionValue={getOptionValue}
+        menuShouldScrollIntoView={false}
+        onChange={onChange}
+        loadOptions={loadOptions}
+        isLoading={isLoading}
+        defaultOptions={defaultOptions}
+        placeholder={placeholder || 'Choose'}
+        styles={ResetStyles}
+        loadingMessage={loadingMessage}
+        noOptionsMessage={noOptionsMessage}
+        isDisabled={isDisabled}
+        isSearchable={isSearchable}
+        isClearable={isClearable}
+        autoFocus={autoFocus}
+        onBlur={onBlur}
+        openMenuOnFocus={openMenuOnFocus}
+        maxMenuHeight={maxMenuHeight}
+        isMulti={isMulti}
+        backspaceRemovesValue={backspaceRemovesValue}
+      />
+    );
+  }
+}
+
+export default Select;

+ 0 - 0
public/app/core/components/Picker/TeamPicker.test.tsx → public/app/core/components/Select/TeamPicker.test.tsx


+ 3 - 17
public/app/core/components/Picker/TeamPicker.tsx → public/app/core/components/Select/TeamPicker.tsx

@@ -1,11 +1,7 @@
 import React, { Component } from 'react';
-import AsyncSelect from 'react-select/lib/Async';
-import PickerOption from './PickerOption';
+import { AsyncSelect } from './Select';
 import { debounce } from 'lodash';
 import { getBackendSrv } from 'app/core/services/backend_srv';
-import ResetStyles from './ResetStyles';
-import IndicatorsContainer from './IndicatorsContainer';
-import NoOptionsMessage from './NoOptionsMessage';
 
 export interface Team {
   id: number;
@@ -45,6 +41,7 @@ export class TeamPicker extends Component<Props, State> {
       const teams = result.teams.map(team => {
         return {
           id: team.id,
+          value: team.id,
           label: team.name,
           name: team.name,
           imgUrl: team.avatarUrl,
@@ -62,24 +59,13 @@ export class TeamPicker extends Component<Props, State> {
     return (
       <div className="user-picker">
         <AsyncSelect
-          classNamePrefix={`gf-form-select-box`}
-          isMulti={false}
           isLoading={isLoading}
           defaultOptions={true}
           loadOptions={this.debouncedSearch}
           onChange={onSelected}
-          className={`gf-form-input gf-form-input--form-dropdown ${className || ''}`}
-          styles={ResetStyles}
-          components={{
-            Option: PickerOption,
-            IndicatorsContainer,
-            NoOptionsMessage,
-          }}
+          className={className}
           placeholder="Select a team"
-          loadingMessage={() => 'Loading...'}
           noOptionsMessage={() => 'No teams found'}
-          getOptionValue={i => i.id}
-          getOptionLabel={i => i.label}
         />
       </div>
     );

+ 51 - 0
public/app/core/components/Select/UnitPicker.tsx

@@ -0,0 +1,51 @@
+import React, { PureComponent } from 'react';
+import Select from './Select';
+import kbn from 'app/core/utils/kbn';
+
+interface Props {
+  onChange: (item: any) => {} | void;
+  defaultValue?: string;
+  width?: number;
+}
+
+export default class UnitPicker extends PureComponent<Props> {
+  static defaultProps = {
+    width: 12,
+  };
+
+  render() {
+    const { defaultValue, onChange, width } = this.props;
+
+    const unitGroups = kbn.getUnitFormats();
+
+    // Need to transform the data structure to work well with Select
+    const groupOptions = unitGroups.map(group => {
+      const options = group.submenu.map(unit => {
+        return {
+          label: unit.text,
+          value: unit.value,
+        };
+      });
+
+      return {
+        label: group.text,
+        options,
+      };
+    });
+
+    const value = groupOptions.map(group => {
+      return group.options.find(option => option.value === defaultValue);
+    });
+
+    return (
+      <Select
+        width={width}
+        defaultValue={value}
+        isSearchable={true}
+        options={groupOptions}
+        placeholder="Choose"
+        onChange={onChange}
+      />
+    );
+  }
+}

+ 0 - 0
public/app/core/components/Picker/UserPicker.test.tsx → public/app/core/components/Select/UserPicker.test.tsx


+ 10 - 17
public/app/core/components/Picker/UserPicker.tsx → public/app/core/components/Select/UserPicker.tsx

@@ -1,12 +1,15 @@
+// Libraries
 import React, { Component } from 'react';
-import AsyncSelect from 'react-select/lib/Async';
-import PickerOption from './PickerOption';
+
+// Components
+import { AsyncSelect } from './Select';
+
+// Utils & Services
 import { debounce } from 'lodash';
 import { getBackendSrv } from 'app/core/services/backend_srv';
+
+// Types
 import { User } from 'app/types';
-import ResetStyles from './ResetStyles';
-import IndicatorsContainer from './IndicatorsContainer';
-import NoOptionsMessage from './NoOptionsMessage';
 
 export interface Props {
   onSelected: (user: User) => void;
@@ -40,6 +43,7 @@ export class UserPicker extends Component<Props, State> {
       .then(result => {
         return result.map(user => ({
           id: user.userId,
+          value: user.userId,
           label: user.login === user.email ? user.login : `${user.login} - ${user.email}`,
           imgUrl: user.avatarUrl,
           login: user.login,
@@ -57,24 +61,13 @@ export class UserPicker extends Component<Props, State> {
     return (
       <div className="user-picker">
         <AsyncSelect
-          classNamePrefix={`gf-form-select-box`}
-          isMulti={false}
+          className={className}
           isLoading={isLoading}
           defaultOptions={true}
           loadOptions={this.debouncedSearch}
           onChange={onSelected}
-          className={`gf-form-input gf-form-input--form-dropdown ${className || ''}`}
-          styles={ResetStyles}
-          components={{
-            Option: PickerOption,
-            IndicatorsContainer,
-            NoOptionsMessage,
-          }}
           placeholder="Select user"
-          loadingMessage={() => 'Loading...'}
           noOptionsMessage={() => 'No users found'}
-          getOptionValue={i => i.id}
-          getOptionLabel={i => i.label}
         />
       </div>
     );

+ 0 - 0
public/app/core/components/Picker/__snapshots__/PickerOption.test.tsx.snap → public/app/core/components/Select/__snapshots__/PickerOption.test.tsx.snap


+ 0 - 29
public/app/core/components/Picker/__snapshots__/TeamPicker.test.tsx.snap → public/app/core/components/Select/__snapshots__/TeamPicker.test.tsx.snap

@@ -57,35 +57,6 @@ exports[`TeamPicker renders correctly 1`] = `
                 }
               }
               tabIndex="0"
-              theme={
-                Object {
-                  "borderRadius": 4,
-                  "colors": Object {
-                    "danger": "#DE350B",
-                    "dangerLight": "#FFBDAD",
-                    "neutral0": "hsl(0, 0%, 100%)",
-                    "neutral10": "hsl(0, 0%, 90%)",
-                    "neutral20": "hsl(0, 0%, 80%)",
-                    "neutral30": "hsl(0, 0%, 70%)",
-                    "neutral40": "hsl(0, 0%, 60%)",
-                    "neutral5": "hsl(0, 0%, 95%)",
-                    "neutral50": "hsl(0, 0%, 50%)",
-                    "neutral60": "hsl(0, 0%, 40%)",
-                    "neutral70": "hsl(0, 0%, 30%)",
-                    "neutral80": "hsl(0, 0%, 20%)",
-                    "neutral90": "hsl(0, 0%, 10%)",
-                    "primary": "#2684FF",
-                    "primary25": "#DEEBFF",
-                    "primary50": "#B2D4FF",
-                    "primary75": "#4C9AFF",
-                  },
-                  "spacing": Object {
-                    "baseUnit": 4,
-                    "controlHeight": 38,
-                    "menuGutter": 8,
-                  },
-                }
-              }
               type="text"
               value=""
             />

+ 0 - 29
public/app/core/components/Picker/__snapshots__/UserPicker.test.tsx.snap → public/app/core/components/Select/__snapshots__/UserPicker.test.tsx.snap

@@ -57,35 +57,6 @@ exports[`UserPicker renders correctly 1`] = `
                 }
               }
               tabIndex="0"
-              theme={
-                Object {
-                  "borderRadius": 4,
-                  "colors": Object {
-                    "danger": "#DE350B",
-                    "dangerLight": "#FFBDAD",
-                    "neutral0": "hsl(0, 0%, 100%)",
-                    "neutral10": "hsl(0, 0%, 90%)",
-                    "neutral20": "hsl(0, 0%, 80%)",
-                    "neutral30": "hsl(0, 0%, 70%)",
-                    "neutral40": "hsl(0, 0%, 60%)",
-                    "neutral5": "hsl(0, 0%, 95%)",
-                    "neutral50": "hsl(0, 0%, 50%)",
-                    "neutral60": "hsl(0, 0%, 40%)",
-                    "neutral70": "hsl(0, 0%, 30%)",
-                    "neutral80": "hsl(0, 0%, 20%)",
-                    "neutral90": "hsl(0, 0%, 10%)",
-                    "primary": "#2684FF",
-                    "primary25": "#DEEBFF",
-                    "primary50": "#B2D4FF",
-                    "primary75": "#4C9AFF",
-                  },
-                  "spacing": Object {
-                    "baseUnit": 4,
-                    "controlHeight": 38,
-                    "menuGutter": 8,
-                  },
-                }
-              }
               type="text"
               value=""
             />

+ 13 - 15
public/app/core/components/SharedPreferences/SharedPreferences.tsx

@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
 
 import { Label } from 'app/core/components/Label/Label';
-import SimplePicker from 'app/core/components/Picker/SimplePicker';
+import Select from 'app/core/components/Select/Select';
 import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
 
 import { DashboardSearchHit } from 'app/types';
@@ -17,12 +17,12 @@ export interface State {
   dashboards: DashboardSearchHit[];
 }
 
-const themes = [{ value: '', text: 'Default' }, { value: 'dark', text: 'Dark' }, { value: 'light', text: 'Light' }];
+const themes = [{ value: '', label: 'Default' }, { value: 'dark', label: 'Dark' }, { value: 'light', label: 'Light' }];
 
 const timezones = [
-  { value: '', text: 'Default' },
-  { value: 'browser', text: 'Local browser time' },
-  { value: 'utc', text: 'UTC' },
+  { value: '', label: 'Default' },
+  { value: 'browser', label: 'Local browser time' },
+  { value: 'utc', label: 'UTC' },
 ];
 
 export class SharedPreferences extends PureComponent<Props, State> {
@@ -91,12 +91,11 @@ export class SharedPreferences extends PureComponent<Props, State> {
         <h3 className="page-heading">Preferences</h3>
         <div className="gf-form">
           <span className="gf-form-label width-11">UI Theme</span>
-          <SimplePicker
+          <Select
+            isSearchable={false}
             value={themes.find(item => item.value === theme)}
             options={themes}
-            getOptionValue={i => i.value}
-            getOptionLabel={i => i.text}
-            onSelected={theme => this.onThemeChanged(theme.value)}
+            onChange={theme => this.onThemeChanged(theme.value)}
             width={20}
           />
         </div>
@@ -107,11 +106,11 @@ export class SharedPreferences extends PureComponent<Props, State> {
           >
             Home Dashboard
           </Label>
-          <SimplePicker
+          <Select
             value={dashboards.find(dashboard => dashboard.id === homeDashboardId)}
             getOptionValue={i => i.id}
             getOptionLabel={i => i.title}
-            onSelected={(dashboard: DashboardSearchHit) => this.onHomeDashboardChanged(dashboard.id)}
+            onChange={(dashboard: DashboardSearchHit) => this.onHomeDashboardChanged(dashboard.id)}
             options={dashboards}
             placeholder="Chose default dashboard"
             width={20}
@@ -119,11 +118,10 @@ export class SharedPreferences extends PureComponent<Props, State> {
         </div>
         <div className="gf-form">
           <label className="gf-form-label width-11">Timezone</label>
-          <SimplePicker
+          <Select
+            isSearchable={false}
             value={timezones.find(item => item.value === timezone)}
-            getOptionValue={i => i.value}
-            getOptionLabel={i => i.text}
-            onSelected={timezone => this.onTimeZoneChanged(timezone.value)}
+            onChange={timezone => this.onTimeZoneChanged(timezone.value)}
             options={timezones}
             width={20}
           />

+ 10 - 5
public/app/core/components/TagFilter/TagFilter.tsx

@@ -1,11 +1,12 @@
 import React from 'react';
-import AsyncSelect from 'react-select/lib/Async';
+import AsyncSelect from '@torkelo/react-select/lib/Async';
+
 import { TagOption } from './TagOption';
 import { TagBadge } from './TagBadge';
-import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
-import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage';
-import { components } from 'react-select';
-import ResetStyles from 'app/core/components/Picker/ResetStyles';
+import IndicatorsContainer from 'app/core/components/Select/IndicatorsContainer';
+import NoOptionsMessage from 'app/core/components/Select/NoOptionsMessage';
+import { components } from '@torkelo/react-select';
+import ResetStyles from 'app/core/components/Select/ResetStyles';
 
 export interface Props {
   tags: string[];
@@ -51,6 +52,10 @@ export class TagFilter extends React.Component<Props, any> {
       getOptionLabel: i => i.label,
       value: tags,
       styles: ResetStyles,
+      filterOption: (option, searchQuery) => {
+        const regex = RegExp(searchQuery, 'i');
+        return regex.test(option.value);
+      },
       components: {
         Option: TagOption,
         IndicatorsContainer,

+ 1 - 1
public/app/core/components/TagFilter/TagOption.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
-import { components } from 'react-select';
+import { components } from '@torkelo/react-select';
 import { OptionProps } from 'react-select/lib/components/Option';
 import { TagBadge } from './TagBadge';
 

+ 1 - 1
public/app/core/components/code_editor/code_editor.ts

@@ -84,7 +84,7 @@ function link(scope, elem, attrs) {
   // disable depreacation warning
   codeEditor.$blockScrolling = Infinity;
   // Padding hacks
-  (codeEditor.renderer as any).setScrollMargin(15, 15);
+  (codeEditor.renderer as any).setScrollMargin(10, 10);
   codeEditor.renderer.setPadding(10);
 
   setThemeMode();

+ 45 - 7
public/app/core/logs_model.ts

@@ -108,11 +108,21 @@ export interface LogsParser {
    * Used to filter rows, and first capture group contains the value.
    */
   buildMatcher: (label: string) => RegExp;
+
+  /**
+   * Returns all parsable substrings from a line, used for highlighting
+   */
+  getFields: (line: string) => string[];
+
+  /**
+   * Gets the label name from a parsable substring of a line
+   */
+  getLabelFromField: (field: string) => string;
+
   /**
-   * Regex to find a field in the log line.
-   * First capture group contains the label value, second capture group the value.
+   * Gets the label value from a parsable substring of a line
    */
-  fieldRegex: RegExp;
+  getValueFromField: (field: string) => string;
   /**
    * Function to verify if this is a valid parser for the given line.
    * The parser accepts the line unless it returns undefined.
@@ -120,20 +130,48 @@ export interface LogsParser {
   test: (line: string) => any;
 }
 
+const LOGFMT_REGEXP = /(?:^|\s)(\w+)=("[^"]*"|\S+)/;
+
 export const LogsParsers: { [name: string]: LogsParser } = {
   JSON: {
-    buildMatcher: label => new RegExp(`(?:{|,)\\s*"${label}"\\s*:\\s*"([^"]*)"`),
-    fieldRegex: /"(\w+)"\s*:\s*"([^"]*)"/,
+    buildMatcher: label => new RegExp(`(?:{|,)\\s*"${label}"\\s*:\\s*"?([\\d\\.]+|[^"]*)"?`),
+    getFields: line => {
+      const fields = [];
+      try {
+        const parsed = JSON.parse(line);
+        _.map(parsed, (value, key) => {
+          const fieldMatcher = new RegExp(`"${key}"\\s*:\\s*"?${_.escapeRegExp(JSON.stringify(value))}"?`);
+
+          const match = line.match(fieldMatcher);
+          if (match) {
+            fields.push(match[0]);
+          }
+        });
+      } catch {}
+      return fields;
+    },
+    getLabelFromField: field => (field.match(/^"(\w+)"\s*:/) || [])[1],
+    getValueFromField: field => (field.match(/:\s*(.*)$/) || [])[1],
     test: line => {
       try {
         return JSON.parse(line);
       } catch (error) {}
     },
   },
+
   logfmt: {
     buildMatcher: label => new RegExp(`(?:^|\\s)${label}=("[^"]*"|\\S+)`),
-    fieldRegex: /(?:^|\s)(\w+)=("[^"]*"|\S+)/,
-    test: line => LogsParsers.logfmt.fieldRegex.test(line),
+    getFields: line => {
+      const fields = [];
+      line.replace(new RegExp(LOGFMT_REGEXP, 'g'), substring => {
+        fields.push(substring.trim());
+        return '';
+      });
+      return fields;
+    },
+    getLabelFromField: field => (field.match(LOGFMT_REGEXP) || [])[1],
+    getValueFromField: field => (field.match(LOGFMT_REGEXP) || [])[2],
+    test: line => LOGFMT_REGEXP.test(line),
   },
 };
 

+ 34 - 11
public/app/core/specs/logs_model.test.ts

@@ -240,11 +240,16 @@ describe('LogsParsers', () => {
       expect(parser.test('foo=bar')).toBeTruthy();
     });
 
-    test('should have a valid fieldRegex', () => {
-      const match = 'foo=bar'.match(parser.fieldRegex);
-      expect(match).toBeDefined();
-      expect(match[1]).toBe('foo');
-      expect(match[2]).toBe('bar');
+    test('should return parsed fields', () => {
+      expect(parser.getFields('foo=bar baz="42 + 1"')).toEqual(['foo=bar', 'baz="42 + 1"']);
+    });
+
+    test('should return label for field', () => {
+      expect(parser.getLabelFromField('foo=bar')).toBe('foo');
+    });
+
+    test('should return value for field', () => {
+      expect(parser.getValueFromField('foo=bar')).toBe('bar');
     });
 
     test('should build a valid value matcher', () => {
@@ -263,18 +268,36 @@ describe('LogsParsers', () => {
       expect(parser.test('{"foo":"bar"}')).toBeTruthy();
     });
 
-    test('should have a valid fieldRegex', () => {
-      const match = '{"foo":"bar"}'.match(parser.fieldRegex);
-      expect(match).toBeDefined();
-      expect(match[1]).toBe('foo');
-      expect(match[2]).toBe('bar');
+    test('should return parsed fields', () => {
+      expect(parser.getFields('{ "foo" : "bar", "baz" : 42 }')).toEqual(['"foo" : "bar"', '"baz" : 42']);
     });
 
-    test('should build a valid value matcher', () => {
+    test('should return parsed fields for nested quotes', () => {
+      expect(parser.getFields(`{"foo":"bar: '[value=\\"42\\"]'"}`)).toEqual([`"foo":"bar: '[value=\\"42\\"]'"`]);
+    });
+
+    test('should return label for field', () => {
+      expect(parser.getLabelFromField('"foo" : "bar"')).toBe('foo');
+    });
+
+    test('should return value for field', () => {
+      expect(parser.getValueFromField('"foo" : "bar"')).toBe('"bar"');
+      expect(parser.getValueFromField('"foo" : 42')).toBe('42');
+      expect(parser.getValueFromField('"foo" : 42.1')).toBe('42.1');
+    });
+
+    test('should build a valid value matcher for strings', () => {
       const matcher = parser.buildMatcher('foo');
       const match = '{"foo":"bar"}'.match(matcher);
       expect(match).toBeDefined();
       expect(match[1]).toBe('bar');
     });
+
+    test('should build a valid value matcher for integers', () => {
+      const matcher = parser.buildMatcher('foo');
+      const match = '{"foo":42.1}'.match(matcher);
+      expect(match).toBeDefined();
+      expect(match[1]).toBe('42.1');
+    });
   });
 });

+ 175 - 171
public/app/features/alerting/partials/alert_tab.html

@@ -1,187 +1,191 @@
-<div class="edit-tab-with-sidemenu" ng-if="ctrl.alert">
-  <aside class="edit-sidemenu-aside">
-    <ul class="edit-sidemenu">
-      <li ng-class="{active: ctrl.subTabIndex === 0}">
-        <a ng-click="ctrl.changeTabIndex(0)">Alert Config</a>
-      </li>
-      <li ng-class="{active: ctrl.subTabIndex === 1}">
-        <a ng-click="ctrl.changeTabIndex(1)">
-          Notifications <span class="muted">({{ctrl.alertNotifications.length}})</span>
-        </a>
-      </li>
-      <li ng-class="{active: ctrl.subTabIndex === 2}">
-        <a ng-click="ctrl.changeTabIndex(2)">State history</a>
-      </li>
-      <li>
-        <a ng-click="ctrl.delete()">Delete</a>
-      </li>
-    </ul>
-  </aside>
+<div class="panel-option-section__body" ng-if="ctrl.alert">
+	<div class="edit-tab-with-sidemenu">
+		<aside class="edit-sidemenu-aside">
+			<ul class="edit-sidemenu">
+				<li ng-class="{active: ctrl.subTabIndex === 0}">
+					<a ng-click="ctrl.changeTabIndex(0)">Alert Config</a>
+				</li>
+				<li ng-class="{active: ctrl.subTabIndex === 1}">
+					<a ng-click="ctrl.changeTabIndex(1)">
+						Notifications <span class="muted">({{ctrl.alertNotifications.length}})</span>
+					</a>
+				</li>
+				<li ng-class="{active: ctrl.subTabIndex === 2}">
+					<a ng-click="ctrl.changeTabIndex(2)">State history</a>
+				</li>
+				<li>
+					<a ng-click="ctrl.delete()">Delete</a>
+				</li>
+			</ul>
+		</aside>
 
-  <div class="edit-tab-content">
-    <div ng-if="ctrl.subTabIndex === 0">
-      <div class="alert alert-error m-b-2" ng-show="ctrl.error">
-        <i class="fa fa-warning"></i> {{ctrl.error}}
-      </div>
+		<div class="edit-tab-content">
+			<div ng-if="ctrl.subTabIndex === 0">
+				<div class="alert alert-error m-b-2" ng-show="ctrl.error">
+					<i class="fa fa-warning"></i> {{ctrl.error}}
+				</div>
 
-      <div class="gf-form-group">
-        <h5 class="section-heading">Alert Config</h5>
-        <div class="gf-form">
-          <span class="gf-form-label width-6">Name</span>
-          <input type="text" class="gf-form-input width-20" ng-model="ctrl.alert.name">
-        </div>
-        <div class="gf-form-inline">
-          <div class="gf-form">
-            <span class="gf-form-label width-9">Evaluate every</span>
-            <input class="gf-form-input max-width-6" type="text" ng-model="ctrl.alert.frequency">
-          </div>
-          <div class="gf-form max-width-11">
-            <label class="gf-form-label width-5">For</label>
-            <input type="text" class="gf-form-input max-width-6" ng-model="ctrl.alert.for" spellcheck='false' placeholder="5m">
-            <info-popover mode="right-absolute">
-                If an alert rule has a configured For and the query violates the configured threshold it will first go from OK to Pending. 
-                Going from OK to Pending Grafana will not send any notifications. Once the alert rule has been firing for more than For duration, it will change to Alerting and send alert notifications. 
-            </info-popover>
-          </div>
-        </div>
-      </div>
+				<div class="gf-form-group">
+					<h5 class="section-heading">Alert Config</h5>
+					<div class="gf-form">
+						<span class="gf-form-label width-6">Name</span>
+						<input type="text" class="gf-form-input width-20" ng-model="ctrl.alert.name">
+					</div>
+					<div class="gf-form-inline">
+						<div class="gf-form">
+							<span class="gf-form-label width-9">Evaluate every</span>
+							<input class="gf-form-input max-width-6" type="text" ng-model="ctrl.alert.frequency">
+						</div>
+						<div class="gf-form max-width-11">
+							<label class="gf-form-label width-5">For</label>
+							<input type="text" class="gf-form-input max-width-6" ng-model="ctrl.alert.for" spellcheck='false' placeholder="5m">
+							<info-popover mode="right-absolute">
+									If an alert rule has a configured For and the query violates the configured threshold it will first go from OK to Pending.
+									Going from OK to Pending Grafana will not send any notifications. Once the alert rule has been firing for more than For duration, it will change to Alerting and send alert notifications.
+							</info-popover>
+						</div>
+					</div>
+				</div>
 
-      <div class="gf-form-group">
-        <h5 class="section-heading">Conditions</h5>
-        <div class="gf-form-inline" ng-repeat="conditionModel in ctrl.conditionModels">
-          <div class="gf-form">
-            <metric-segment-model css-class="query-keyword width-5" ng-if="$index" property="conditionModel.operator.type" options="ctrl.evalOperators" custom="false"></metric-segment-model>
-            <span class="gf-form-label query-keyword width-5" ng-if="$index===0">WHEN</span>
-          </div>
-                <div class="gf-form">
-            <query-part-editor class="gf-form-label query-part width-9" part="conditionModel.reducerPart" handle-event="ctrl.handleReducerPartEvent(conditionModel, $event)">
-            </query-part-editor>
-                  <span class="gf-form-label query-keyword">OF</span>
-          </div>
-          <div class="gf-form">
-            <query-part-editor class="gf-form-label query-part" part="conditionModel.queryPart" handle-event="ctrl.handleQueryPartEvent(conditionModel, $event)">
-            </query-part-editor>
-          </div>
-          <div class="gf-form">
-            <metric-segment-model property="conditionModel.evaluator.type" options="ctrl.evalFunctions" custom="false" css-class="query-keyword" on-change="ctrl.evaluatorTypeChanged(conditionModel.evaluator)"></metric-segment-model>
-            <input class="gf-form-input max-width-9" type="number" step="any" ng-hide="conditionModel.evaluator.params.length === 0" ng-model="conditionModel.evaluator.params[0]" ng-change="ctrl.evaluatorParamsChanged()">
-            <label class="gf-form-label query-keyword" ng-show="conditionModel.evaluator.params.length === 2">TO</label>
-            <input class="gf-form-input max-width-9" type="number" step="any" ng-if="conditionModel.evaluator.params.length === 2" ng-model="conditionModel.evaluator.params[1]" ng-change="ctrl.evaluatorParamsChanged()">
-          </div>
-          <div class="gf-form">
-            <label class="gf-form-label">
-              <a class="pointer" tabindex="1" ng-click="ctrl.removeCondition($index)">
-                <i class="fa fa-trash"></i>
-              </a>
-            </label>
-          </div>
-        </div>
+				<div class="gf-form-group">
+					<h5 class="section-heading">Conditions</h5>
+					<div class="gf-form-inline" ng-repeat="conditionModel in ctrl.conditionModels">
+						<div class="gf-form">
+							<metric-segment-model css-class="query-keyword width-5" ng-if="$index" property="conditionModel.operator.type" options="ctrl.evalOperators" custom="false"></metric-segment-model>
+							<span class="gf-form-label query-keyword width-5" ng-if="$index===0">WHEN</span>
+						</div>
+									<div class="gf-form">
+							<query-part-editor class="gf-form-label query-part width-9" part="conditionModel.reducerPart" handle-event="ctrl.handleReducerPartEvent(conditionModel, $event)">
+							</query-part-editor>
+										<span class="gf-form-label query-keyword">OF</span>
+						</div>
+						<div class="gf-form">
+							<query-part-editor class="gf-form-label query-part" part="conditionModel.queryPart" handle-event="ctrl.handleQueryPartEvent(conditionModel, $event)">
+							</query-part-editor>
+						</div>
+						<div class="gf-form">
+							<metric-segment-model property="conditionModel.evaluator.type" options="ctrl.evalFunctions" custom="false" css-class="query-keyword" on-change="ctrl.evaluatorTypeChanged(conditionModel.evaluator)"></metric-segment-model>
+							<input class="gf-form-input max-width-9" type="number" step="any" ng-hide="conditionModel.evaluator.params.length === 0" ng-model="conditionModel.evaluator.params[0]" ng-change="ctrl.evaluatorParamsChanged()">
+							<label class="gf-form-label query-keyword" ng-show="conditionModel.evaluator.params.length === 2">TO</label>
+							<input class="gf-form-input max-width-9" type="number" step="any" ng-if="conditionModel.evaluator.params.length === 2" ng-model="conditionModel.evaluator.params[1]" ng-change="ctrl.evaluatorParamsChanged()">
+						</div>
+						<div class="gf-form">
+							<label class="gf-form-label">
+								<a class="pointer" tabindex="1" ng-click="ctrl.removeCondition($index)">
+									<i class="fa fa-trash"></i>
+								</a>
+							</label>
+						</div>
+					</div>
 
-        <div class="gf-form">
-          <label class="gf-form-label dropdown">
-            <a class="pointer dropdown-toggle" data-toggle="dropdown">
-              <i class="fa fa-plus"></i>
-            </a>
-            <ul class="dropdown-menu" role="menu">
-              <li ng-repeat="ct in ctrl.conditionTypes" role="menuitem">
-                <a ng-click="ctrl.addCondition(ct.value);">{{ct.text}}</a>
-              </li>
-            </ul>
-          </label>
-        </div>
-      </div>
+					<div class="gf-form">
+						<label class="gf-form-label dropdown">
+							<a class="pointer dropdown-toggle" data-toggle="dropdown">
+								<i class="fa fa-plus"></i>
+							</a>
+							<ul class="dropdown-menu" role="menu">
+								<li ng-repeat="ct in ctrl.conditionTypes" role="menuitem">
+									<a ng-click="ctrl.addCondition(ct.value);">{{ct.text}}</a>
+								</li>
+							</ul>
+						</label>
+					</div>
+				</div>
 
-      <div class="gf-form-group">
-        <div class="gf-form">
-                <span class="gf-form-label width-18">If no data or all values are null</span>
-                <span class="gf-form-label query-keyword">SET STATE TO</span>
-          <div class="gf-form-select-wrapper">
-            <select class="gf-form-input" ng-model="ctrl.alert.noDataState" ng-options="f.value as f.text for f in ctrl.noDataModes">
-            </select>
-          </div>
-        </div>
+				<div class="gf-form-group">
+					<div class="gf-form">
+									<span class="gf-form-label width-18">If no data or all values are null</span>
+									<span class="gf-form-label query-keyword">SET STATE TO</span>
+						<div class="gf-form-select-wrapper">
+							<select class="gf-form-input" ng-model="ctrl.alert.noDataState" ng-options="f.value as f.text for f in ctrl.noDataModes">
+							</select>
+						</div>
+					</div>
 
-        <div class="gf-form">
-                <span class="gf-form-label width-18">If execution error or timeout</span>
-                <span class="gf-form-label query-keyword">SET STATE TO</span>
-          <div class="gf-form-select-wrapper">
-            <select class="gf-form-input" ng-model="ctrl.alert.executionErrorState" ng-options="f.value as f.text for f in ctrl.executionErrorModes">
-            </select>
-          </div>
-        </div>
+					<div class="gf-form">
+									<span class="gf-form-label width-18">If execution error or timeout</span>
+									<span class="gf-form-label query-keyword">SET STATE TO</span>
+						<div class="gf-form-select-wrapper">
+							<select class="gf-form-input" ng-model="ctrl.alert.executionErrorState" ng-options="f.value as f.text for f in ctrl.executionErrorModes">
+							</select>
+						</div>
+					</div>
 
-        <div class="gf-form-button-row">
-          <button class="btn btn-inverse" ng-click="ctrl.test()">
-            Test Rule
-          </button>
-        </div>
-      </div>
+					<div class="gf-form-button-row">
+						<button class="btn btn-inverse" ng-click="ctrl.test()">
+							Test Rule
+						</button>
+					</div>
+				</div>
 
-      <div class="gf-form-group" ng-if="ctrl.testing">
-        Evaluating rule <i class="fa fa-spinner fa-spin"></i>
-      </div>
+				<div class="gf-form-group" ng-if="ctrl.testing">
+					Evaluating rule <i class="fa fa-spinner fa-spin"></i>
+				</div>
 
-      <div class="gf-form-group" ng-if="ctrl.testResult">
-        <json-tree root-name="result" object="ctrl.testResult" start-expanded="true"></json-tree>
-      </div>
-    </div>
+				<div class="gf-form-group" ng-if="ctrl.testResult">
+					<json-tree root-name="result" object="ctrl.testResult" start-expanded="true"></json-tree>
+				</div>
+			</div>
 
-    <div class="gf-form-group" ng-if="ctrl.subTabIndex === 1">
-      <h5 class="section-heading">Notifications</h5>
-      <div class="gf-form-inline">
-        <div class="gf-form max-width-30">
-          <span class="gf-form-label width-8">Send to</span>
-          <span class="gf-form-label" ng-repeat="nc in ctrl.alertNotifications" ng-style="{'background-color': nc.bgColor }">
-            <i class="{{nc.iconClass}}"></i>&nbsp;{{nc.name}}&nbsp;
-            <i class="fa fa-remove pointer muted" ng-click="ctrl.removeNotification($index)" ng-if="nc.isDefault === false"></i>
-          </span>
-          <metric-segment segment="ctrl.addNotificationSegment" get-options="ctrl.getNotifications()" on-change="ctrl.notificationAdded()"></metric-segment>
-        </div>
-      </div>
-      <div class="gf-form gf-form--v-stretch">
-        <span class="gf-form-label width-8">Message</span>
-        <textarea class="gf-form-input" rows="10" ng-model="ctrl.alert.message"  placeholder="Notification message details..."></textarea>
-      </div>
-    </div>
+			<div class="gf-form-group" ng-if="ctrl.subTabIndex === 1">
+				<h5 class="section-heading">Notifications</h5>
+				<div class="gf-form-inline">
+					<div class="gf-form max-width-30">
+						<span class="gf-form-label width-8">Send to</span>
+						<span class="gf-form-label" ng-repeat="nc in ctrl.alertNotifications" ng-style="{'background-color': nc.bgColor }">
+							<i class="{{nc.iconClass}}"></i>&nbsp;{{nc.name}}&nbsp;
+							<i class="fa fa-remove pointer muted" ng-click="ctrl.removeNotification($index)" ng-if="nc.isDefault === false"></i>
+						</span>
+						<metric-segment segment="ctrl.addNotificationSegment" get-options="ctrl.getNotifications()" on-change="ctrl.notificationAdded()"></metric-segment>
+					</div>
+				</div>
+				<div class="gf-form gf-form--v-stretch">
+					<span class="gf-form-label width-8">Message</span>
+					<textarea class="gf-form-input" rows="10" ng-model="ctrl.alert.message"  placeholder="Notification message details..."></textarea>
+				</div>
+			</div>
 
-    <div class="gf-form-group" style="max-width: 720px;" ng-if="ctrl.subTabIndex === 2">
-      <button class="btn btn-mini btn-danger pull-right" ng-click="ctrl.clearHistory()"><i class="fa fa-trash"></i>&nbsp;Clear history</button>
-          <h5 class="section-heading" style="whitespace: nowrap">
-        State history <span class="muted small">(last 50 state changes)</span>
-      </h5>
+			<div class="gf-form-group" style="max-width: 720px;" ng-if="ctrl.subTabIndex === 2">
+				<button class="btn btn-mini btn-danger pull-right" ng-click="ctrl.clearHistory()"><i class="fa fa-trash"></i>&nbsp;Clear history</button>
+						<h5 class="section-heading" style="whitespace: nowrap">
+					State history <span class="muted small">(last 50 state changes)</span>
+				</h5>
 
-      <div ng-show="ctrl.alertHistory.length === 0">
-        <br>
-        <i>No state changes recorded</i>
-      </div>
+				<div ng-show="ctrl.alertHistory.length === 0">
+					<br>
+					<i>No state changes recorded</i>
+				</div>
 
-      <ol class="alert-rule-list" >
-        <li class="alert-rule-item" ng-repeat="al in ctrl.alertHistory">
-          <div class="alert-rule-item__icon {{al.stateModel.stateClass}}">
-            <i class="{{al.stateModel.iconClass}}"></i>
-          </div>
-          <div class="alert-rule-item__body">
-            <div class="alert-rule-item__header">
-              <div class="alert-rule-item__text">
-                <span class="{{al.stateModel.stateClass}}">{{al.stateModel.text}}</span>
-              </div>
-            </div>
-            <span class="alert-list-info">{{al.info}}</span>
-          </div>
-          <div class="alert-rule-item__time">
-            <span>{{al.time}}</span>
-          </div>
-        </li>
-      </ol>
-    </div>
-  </div>
+				<ol class="alert-rule-list" >
+					<li class="alert-rule-item" ng-repeat="al in ctrl.alertHistory">
+						<div class="alert-rule-item__icon {{al.stateModel.stateClass}}">
+							<i class="{{al.stateModel.iconClass}}"></i>
+						</div>
+						<div class="alert-rule-item__body">
+							<div class="alert-rule-item__header">
+								<div class="alert-rule-item__text">
+									<span class="{{al.stateModel.stateClass}}">{{al.stateModel.text}}</span>
+								</div>
+							</div>
+							<span class="alert-list-info">{{al.info}}</span>
+						</div>
+						<div class="alert-rule-item__time">
+							<span>{{al.time}}</span>
+						</div>
+					</li>
+				</ol>
+			</div>
+		</div>
+	</div>
 </div>
 
-<div class="gf-form-group" ng-if="!ctrl.alert">
-  <div class="gf-form-button-row">
-    <button class="btn btn-inverse" ng-click="ctrl.enable()">
-      <i class="icon-gf icon-gf-alert"></i>
-      Create Alert
-    </button>
-  </div>
+<div class="gf-form-group p-t-4 p-b-4" ng-if="!ctrl.alert">
+	<div class="empty-list-cta">
+		<div class="empty-list-cta__title">Panel has no alert rule defined</div>
+			<button class="empty-list-cta__button btn btn-xlarge btn-success" ng-click="ctrl.enable()">
+				<i class="icon-gf icon-gf-alert"></i>
+				Create Alert
+			</button>
+		</div>
+	</div>
 </div>

+ 0 - 1
public/app/features/dashboard/dashboard_migration.ts

@@ -141,7 +141,6 @@ export class DashboardMigrator {
 
       // ensure query refIds
       panelUpgrades.push(panel => {
-        console.log('asdasd', panel);
         _.each(panel.targets, target => {
           if (!target.refId) {
             target.refId = panel.getNextQueryLetter && panel.getNextQueryLetter();

+ 71 - 168
public/app/features/dashboard/dashgrid/AddPanelPanel.tsx

@@ -1,13 +1,12 @@
 import React from 'react';
 import _ from 'lodash';
-import classNames from 'classnames';
 import config from 'app/core/config';
 import { PanelModel } from '../panel_model';
 import { DashboardModel } from '../dashboard_model';
-import ScrollBar from 'app/core/components/ScrollBar/ScrollBar';
 import store from 'app/core/store';
 import { LS_PANEL_COPY_KEY } from 'app/core/constants';
-import Highlighter from 'react-highlight-words';
+import { updateLocation } from 'app/core/actions';
+import { store as reduxStore } from 'app/store/store';
 
 export interface AddPanelPanelProps {
   panel: PanelModel;
@@ -15,64 +14,25 @@ export interface AddPanelPanelProps {
 }
 
 export interface AddPanelPanelState {
-  filter: string;
-  panelPlugins: any[];
   copiedPanelPlugins: any[];
-  tab: string;
 }
 
 export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelPanelState> {
-  private scrollbar: ScrollBar;
-
   constructor(props) {
     super(props);
     this.handleCloseAddPanel = this.handleCloseAddPanel.bind(this);
-    this.renderPanelItem = this.renderPanelItem.bind(this);
-    this.panelSizeChanged = this.panelSizeChanged.bind(this);
 
     this.state = {
-      panelPlugins: this.getPanelPlugins(''),
-      copiedPanelPlugins: this.getCopiedPanelPlugins(''),
-      filter: '',
-      tab: 'Add',
+      copiedPanelPlugins: this.getCopiedPanelPlugins(),
     };
   }
 
-  componentDidMount() {
-    this.props.panel.events.on('panel-size-changed', this.panelSizeChanged);
-  }
-
-  componentWillUnmount() {
-    this.props.panel.events.off('panel-size-changed', this.panelSizeChanged);
-  }
-
-  panelSizeChanged() {
-    setTimeout(() => {
-      this.scrollbar.update();
-    });
-  }
-
-  getPanelPlugins(filter) {
-    let panels = _.chain(config.panels)
-      .filter({ hideFromList: false })
-      .map(item => item)
-      .value();
-
-    // add special row type
-    panels.push({ id: 'row', name: 'Row', sort: 8, info: { logos: { small: 'public/img/icn-row.svg' } } });
-
-    panels = this.filterPanels(panels, filter);
-
-    // add sort by sort property
-    return _.sortBy(panels, 'sort');
-  }
-
-  getCopiedPanelPlugins(filter) {
+  getCopiedPanelPlugins() {
     const panels = _.chain(config.panels)
       .filter({ hideFromList: false })
       .map(item => item)
       .value();
-    let copiedPanels = [];
+    const copiedPanels = [];
 
     const copiedPanelJson = store.get(LS_PANEL_COPY_KEY);
     if (copiedPanelJson) {
@@ -86,32 +46,64 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
         copiedPanels.push(pluginCopy);
       }
     }
+    return _.sortBy(copiedPanels, 'sort');
+  }
 
-    copiedPanels = this.filterPanels(copiedPanels, filter);
+  handleCloseAddPanel(evt) {
+    evt.preventDefault();
+    this.props.dashboard.removePanel(this.props.dashboard.panels[0]);
+  }
 
-    return _.sortBy(copiedPanels, 'sort');
+  copyButton(panel) {
+    return (
+      <button className="btn-inverse btn" onClick={() => this.onPasteCopiedPanel(panel)} title={panel.name}>
+        Paste copied Panel
+      </button>
+    );
   }
 
-  onAddPanel = panelPluginInfo => {
+  moveToEdit(panel) {
+    reduxStore.dispatch(
+      updateLocation({
+        query: {
+          panelId: panel.id,
+          edit: true,
+          fullscreen: true,
+        },
+        partial: true,
+      })
+    );
+  }
+
+  onCreateNewPanel = () => {
     const dashboard = this.props.dashboard;
     const { gridPos } = this.props.panel;
 
     const newPanel: any = {
-      type: panelPluginInfo.id,
+      type: 'graph',
       title: 'Panel Title',
       gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
     };
 
-    if (panelPluginInfo.id === 'row') {
-      newPanel.title = 'Row title';
-      newPanel.gridPos = { x: 0, y: 0 };
-    }
+    dashboard.addPanel(newPanel);
+    dashboard.removePanel(this.props.panel);
+
+    this.moveToEdit(newPanel);
+  };
+
+  onPasteCopiedPanel = panelPluginInfo => {
+    const dashboard = this.props.dashboard;
+    const { gridPos } = this.props.panel;
+
+    const newPanel: any = {
+      type: panelPluginInfo.id,
+      title: 'Panel Title',
+      gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
+    };
 
     // apply panel template / defaults
     if (panelPluginInfo.defaults) {
       _.defaults(newPanel, panelPluginInfo.defaults);
-      newPanel.gridPos.w = panelPluginInfo.defaults.gridPos.w;
-      newPanel.gridPos.h = panelPluginInfo.defaults.gridPos.h;
       newPanel.title = panelPluginInfo.defaults.title;
       store.delete(LS_PANEL_COPY_KEY);
     }
@@ -120,133 +112,44 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
     dashboard.removePanel(this.props.panel);
   };
 
-  handleCloseAddPanel(evt) {
-    evt.preventDefault();
-    this.props.dashboard.removePanel(this.props.dashboard.panels[0]);
-  }
-
-  renderText(text: string) {
-    const searchWords = this.state.filter.split('');
-    return <Highlighter highlightClassName="highlight-search-match" textToHighlight={text} searchWords={searchWords} />;
-  }
-
-  renderPanelItem(panel, index) {
-    return (
-      <div key={index} className="add-panel__item" onClick={() => this.onAddPanel(panel)} title={panel.name}>
-        <img className="add-panel__item-img" src={panel.info.logos.small} />
-        <div className="add-panel__item-name">{this.renderText(panel.name)}</div>
-      </div>
-    );
-  }
-
-  noCopiedPanelPlugins() {
-    return <div className="add-panel__no-panels">No copied panels yet.</div>;
-  }
-
-  filterChange(evt) {
-    this.setState({
-      filter: evt.target.value,
-      panelPlugins: this.getPanelPlugins(evt.target.value),
-      copiedPanelPlugins: this.getCopiedPanelPlugins(evt.target.value),
-    });
-  }
-
-  filterKeyPress(evt) {
-    if (evt.key === 'Enter') {
-      const panel = _.head(this.state.panelPlugins);
-      if (panel) {
-        this.onAddPanel(panel);
-      }
-    }
-  }
-
-  filterPanels(panels, filter) {
-    const regex = new RegExp(filter, 'i');
-    return panels.filter(panel => {
-      return regex.test(panel.name);
-    });
-  }
+  onCreateNewRow = () => {
+    const dashboard = this.props.dashboard;
 
-  openCopy() {
-    this.setState({
-      tab: 'Copy',
-      filter: '',
-      panelPlugins: this.getPanelPlugins(''),
-      copiedPanelPlugins: this.getCopiedPanelPlugins(''),
-    });
-  }
+    const newRow: any = {
+      type: 'row',
+      title: 'Row title',
+      gridPos: { x: 0, y: 0 },
+    };
 
-  openAdd() {
-    this.setState({
-      tab: 'Add',
-      filter: '',
-      panelPlugins: this.getPanelPlugins(''),
-      copiedPanelPlugins: this.getCopiedPanelPlugins(''),
-    });
-  }
+    dashboard.addPanel(newRow);
+    dashboard.removePanel(this.props.panel);
+  };
 
   render() {
-    const addClass = classNames({
-      'active active--panel': this.state.tab === 'Add',
-      '': this.state.tab === 'Copy',
-    });
-
-    const copyClass = classNames({
-      '': this.state.tab === 'Add',
-      'active active--panel': this.state.tab === 'Copy',
-    });
-
-    let panelTab;
-
-    if (this.state.tab === 'Add') {
-      panelTab = this.state.panelPlugins.map(this.renderPanelItem);
-    } else if (this.state.tab === 'Copy') {
-      if (this.state.copiedPanelPlugins.length > 0) {
-        panelTab = this.state.copiedPanelPlugins.map(this.renderPanelItem);
-      } else {
-        panelTab = this.noCopiedPanelPlugins();
-      }
+    let addCopyButton;
+
+    if (this.state.copiedPanelPlugins.length === 1) {
+      addCopyButton = this.copyButton(this.state.copiedPanelPlugins[0]);
     }
 
     return (
       <div className="panel-container add-panel-container">
         <div className="add-panel">
-          <div className="add-panel__header">
+          <div className="add-panel__header grid-drag-handle">
             <i className="gicon gicon-add-panel" />
-            <span className="add-panel__title">New Panel</span>
-            <ul className="gf-tabs">
-              <li className="gf-tabs-item">
-                <div className={'gf-tabs-link pointer ' + addClass} onClick={this.openAdd.bind(this)}>
-                  Add
-                </div>
-              </li>
-              <li className="gf-tabs-item">
-                <div className={'gf-tabs-link pointer ' + copyClass} onClick={this.openCopy.bind(this)}>
-                  Paste
-                </div>
-              </li>
-            </ul>
             <button className="add-panel__close" onClick={this.handleCloseAddPanel}>
               <i className="fa fa-close" />
             </button>
           </div>
-          <ScrollBar ref={element => (this.scrollbar = element)} className="add-panel__items">
-            <div className="add-panel__searchbar">
-              <label className="gf-form gf-form--grow gf-form--has-input-icon">
-                <input
-                  type="text"
-                  autoFocus
-                  className="gf-form-input gf-form--grow"
-                  placeholder="Panel Search Filter"
-                  value={this.state.filter}
-                  onChange={this.filterChange.bind(this)}
-                  onKeyPress={this.filterKeyPress.bind(this)}
-                />
-                <i className="gf-form-input-icon fa fa-search" />
-              </label>
-            </div>
-            {panelTab}
-          </ScrollBar>
+          <div className="add-panel-btn-container">
+            <button className="btn-success btn btn-large" onClick={this.onCreateNewPanel}>
+              Edit Panel
+            </button>
+            {addCopyButton}
+            <button className="btn-inverse btn" onClick={this.onCreateNewRow}>
+              Add Row
+            </button>
+          </div>
         </div>
       </div>
     );

+ 4 - 12
public/app/features/dashboard/dashgrid/DashboardGrid.tsx

@@ -45,7 +45,7 @@ function GridWrapper({
       isResizable={isResizable}
       measureBeforeMount={false}
       containerPadding={[0, 0]}
-      useCSSTransforms={true}
+      useCSSTransforms={false}
       margin={[GRID_CELL_VMARGIN, GRID_CELL_VMARGIN]}
       cols={GRID_COLUMN_COUNT}
       rowHeight={GRID_CELL_HEIGHT}
@@ -67,7 +67,7 @@ export interface DashboardGridProps {
   dashboard: DashboardModel;
 }
 
-export class DashboardGrid extends React.Component<DashboardGridProps, any> {
+export class DashboardGrid extends React.Component<DashboardGridProps> {
   gridToPanelMap: any;
   panelMap: { [id: string]: PanelModel };
 
@@ -79,8 +79,6 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
     this.onDragStop = this.onDragStop.bind(this);
     this.onWidthChange = this.onWidthChange.bind(this);
 
-    this.state = { animated: false };
-
     // subscribe to dashboard events
     const dashboard = this.props.dashboard;
     dashboard.on('panel-added', this.triggerForceUpdate.bind(this));
@@ -145,7 +143,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
 
   onViewModeChanged(payload) {
     ignoreNextWidthChange = true;
-    this.setState({ animated: !payload.fullscreen });
+    this.forceUpdate();
   }
 
   updateGridPos(item, layout) {
@@ -169,12 +167,6 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
     this.updateGridPos(newItem, layout);
   }
 
-  componentDidMount() {
-    setTimeout(() => {
-      this.setState({ animated: true });
-    });
-  }
-
   renderPanels() {
     const panelElements = [];
 
@@ -198,7 +190,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
   render() {
     return (
       <SizedReactLayoutGrid
-        className={classNames({ layout: true, animated: this.state.animated })}
+        className={classNames({ layout: true })}
         layout={this.buildLayout()}
         isResizable={this.props.dashboard.meta.canEdit}
         isDraggable={this.props.dashboard.meta.canEdit}

+ 9 - 12
public/app/features/dashboard/dashgrid/DashboardPanel.tsx

@@ -76,15 +76,15 @@ export class DashboardPanel extends PureComponent<Props, State> {
       // unmount angular panel
       this.cleanUpAngularPanel();
 
+      if (panel.type !== pluginId) {
+        this.props.panel.changeType(pluginId, fromAngularPanel);
+      }
+
       if (plugin.exports) {
-        this.setState({ plugin: plugin });
+        this.setState({ plugin: plugin, angularPanel: null });
       } else {
         plugin.exports = await importPluginModule(plugin.module);
-        this.setState({ plugin: plugin });
-      }
-
-      if (panel.type !== pluginId) {
-        this.props.panel.changeType(pluginId, fromAngularPanel);
+        this.setState({ plugin: plugin, angularPanel: null });
       }
     }
   }
@@ -106,18 +106,15 @@ export class DashboardPanel extends PureComponent<Props, State> {
     this.setState({ angularPanel });
   }
 
-  cleanUpAngularPanel(unmounted?: boolean) {
+  cleanUpAngularPanel() {
     if (this.state.angularPanel) {
       this.state.angularPanel.destroy();
-
-      if (!unmounted) {
-        this.setState({ angularPanel: null });
-      }
+      this.element = null;
     }
   }
 
   componentWillUnmount() {
-    this.cleanUpAngularPanel(true);
+    this.cleanUpAngularPanel();
   }
 
   onMouseEnter = () => {

+ 12 - 10
public/app/features/dashboard/dashgrid/EditorTabBody.tsx

@@ -1,6 +1,10 @@
+// Libraries
 import React, { PureComponent } from 'react';
+
+// Components
 import CustomScrollbar from 'app/core/components/CustomScrollbar/CustomScrollbar';
 import { FadeIn } from 'app/core/components/Animations/FadeIn';
+import { PanelOptionSection } from './PanelOptionSection';
 
 interface Props {
   children: JSX.Element;
@@ -10,7 +14,8 @@ interface Props {
 }
 
 export interface EditorToolBarView {
-  title: string;
+  title?: string;
+  heading?: string;
   imgSrc?: string;
   icon?: string;
   disabled?: boolean;
@@ -88,12 +93,9 @@ export class EditorTabBody extends PureComponent<Props, State> {
 
   renderOpenView(view: EditorToolBarView) {
     return (
-      <div className="toolbar-subview">
-        <button className="toolbar-subview__close" onClick={this.onCloseOpenView}>
-          <i className="fa fa-chevron-up" />
-        </button>
-        {view.render(this.onCloseOpenView)}
-      </div>
+      <PanelOptionSection title={view.title || view.heading} onClose={this.onCloseOpenView}>
+        {view.render()}
+      </PanelOptionSection>
     );
   }
 
@@ -115,10 +117,10 @@ export class EditorTabBody extends PureComponent<Props, State> {
         </div>
         <div className="panel-editor__scroll">
           <CustomScrollbar autoHide={false}>
-            <FadeIn in={isOpen} duration={200} unmountOnExit={true}>
-              <div className="panel-editor__toolbar-view">{openView && this.renderOpenView(openView)}</div>
-            </FadeIn>
             <div className="panel-editor__content">
+              <FadeIn in={isOpen} duration={200} unmountOnExit={true}>
+                {openView && this.renderOpenView(openView)}
+              </FadeIn>
               <FadeIn in={fadeIn} duration={50}>
                 {children}
               </FadeIn>

+ 17 - 5
public/app/features/dashboard/dashgrid/PanelEditor.tsx

@@ -53,7 +53,7 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
         return <GeneralTab panel={panel} />;
       case 'queries':
         return <QueriesTab panel={panel} dashboard={dashboard} />;
-      case 'alerts':
+      case 'alert':
         return <AlertTab angularPanel={angularPanel} />;
       case 'visualization':
         return (
@@ -72,18 +72,30 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
 
   render() {
     const { plugin } = this.props;
-    const activeTab = store.getState().location.query.tab || 'queries';
+    let activeTab = store.getState().location.query.tab || 'queries';
 
-    const tabs = [
+    const tabs: PanelEditorTab[] = [
       { id: 'queries', text: 'Queries' },
       { id: 'visualization', text: 'Visualization' },
       { id: 'advanced', text: 'Panel Options' },
     ];
 
+    // handle panels that do not have queries tab
+    if (plugin.exports.PanelCtrl) {
+      if (!plugin.exports.PanelCtrl.prototype.onDataReceived) {
+        // remove queries tab
+        tabs.shift();
+        // switch tab
+        if (activeTab === 'queries') {
+          activeTab = 'visualization';
+        }
+      }
+    }
+
     if (config.alertingEnabled && plugin.id === 'graph') {
       tabs.push({
-        id: 'alerts',
-        text: 'Alerts',
+        id: 'alert',
+        text: 'Alert',
       });
     }
 

+ 26 - 0
public/app/features/dashboard/dashgrid/PanelOptionSection.tsx

@@ -0,0 +1,26 @@
+// Libraries
+import React, { SFC } from 'react';
+
+interface Props {
+  title?: string;
+  onClose?: () => void;
+  children: JSX.Element | JSX.Element[];
+}
+
+export const PanelOptionSection: SFC<Props> = props => {
+  return (
+    <div className="panel-option-section">
+      {props.title && (
+        <div className="panel-option-section__header">
+          {props.title}
+          {props.onClose && (
+            <button className="btn btn-link" onClick={props.onClose}>
+              <i className="fa fa-remove" />
+            </button>
+          )}
+        </div>
+      )}
+      <div className="panel-option-section__body">{props.children}</div>
+    </div>
+  );
+};

+ 36 - 113
public/app/features/dashboard/dashgrid/QueriesTab.tsx

@@ -4,13 +4,13 @@ import Remarkable from 'remarkable';
 import _ from 'lodash';
 
 // Components
-import DataSourceOption from './DataSourceOption';
+import './../../panel/metrics_tab';
 import { EditorTabBody } from './EditorTabBody';
-import { DataSourcePicker } from './DataSourcePicker';
+import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
 import { QueryInspector } from './QueryInspector';
-import { TimeRangeOptions } from './TimeRangeOptions';
-import './../../panel/metrics_tab';
+import { QueryOptions } from './QueryOptions';
 import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab';
+import { PanelOptionSection } from './PanelOptionSection';
 
 // Services
 import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
@@ -157,75 +157,6 @@ export class QueriesTab extends PureComponent<Props, State> {
     }
   };
 
-  renderOptions = close => {
-    const { currentDS } = this.state;
-    const { queryOptions } = currentDS.meta;
-    const { panel } = this.props;
-
-    const onChangeFn = (panelKey: string) => {
-      return (value: string | number) => {
-        panel[panelKey] = value;
-        panel.refresh();
-      };
-    };
-
-    const allOptions = {
-      cacheTimeout: {
-        label: 'Cache timeout',
-        placeholder: '60',
-        name: 'cacheTimeout',
-        value: panel.cacheTimeout,
-        tooltipInfo: (
-          <>
-            If your time series store has a query cache this option can override the default cache timeout. Specify a
-            numeric value in seconds.
-          </>
-        ),
-      },
-      maxDataPoints: {
-        label: 'Max data points',
-        placeholder: 'auto',
-        name: 'maxDataPoints',
-        value: panel.maxDataPoints,
-        tooltipInfo: (
-          <>
-            The maximum data points the query should return. For graphs this is automatically set to one data point per
-            pixel.
-          </>
-        ),
-      },
-      minInterval: {
-        label: 'Min time interval',
-        placeholder: '0',
-        name: 'minInterval',
-        value: panel.interval,
-        panelKey: 'interval',
-        tooltipInfo: (
-          <>
-            A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '}
-            <code>1m</code> if your data is written every minute. Access auto interval via variable{' '}
-            <code>$__interval</code> for time range string and <code>$__interval_ms</code> for numeric variable that can
-            be used in math expressions.
-          </>
-        ),
-      },
-    };
-
-    const dsOptions = queryOptions
-      ? Object.keys(queryOptions).map(key => {
-          const options = allOptions[key];
-          return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />;
-        })
-      : null;
-
-    return (
-      <>
-        <TimeRangeOptions panel={this.props.panel} />
-        {dsOptions}
-      </>
-    );
-  };
-
   renderQueryInspector = () => {
     const { panel } = this.props;
     return <QueryInspector panel={panel} LoadingPlaceholder={LoadingPlaceholder} />;
@@ -274,20 +205,14 @@ export class QueriesTab extends PureComponent<Props, State> {
   renderToolbar = () => {
     const { currentDS } = this.state;
 
-    return (
-      <DataSourcePicker
-        datasources={this.datasources}
-        onChangeDataSource={this.onChangeDataSource}
-        current={currentDS}
-      />
-    );
+    return <DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />;
   };
 
   renderMixedPicker = () => {
     return (
       <DataSourcePicker
         datasources={this.datasources}
-        onChangeDataSource={this.onAddMixedQuery}
+        onChange={this.onAddMixedQuery}
         current={null}
         autoFocus={true}
         onBlur={this.onMixedPickerBlur}
@@ -316,46 +241,44 @@ export class QueriesTab extends PureComponent<Props, State> {
     };
 
     const dsHelp = {
-      title: '',
+      heading: 'Help',
       icon: 'fa fa-question',
       disabled: !hasQueryHelp,
       onClick: this.loadHelp,
       render: this.renderHelp,
     };
 
-    const options = {
-      title: 'Time Range',
-      icon: '',
-      disabled: false,
-      render: this.renderOptions,
-    };
-
     return (
-      <EditorTabBody
-        heading="Queries"
-        renderToolbar={this.renderToolbar}
-        toolbarItems={[options, queryInspector, dsHelp]}
-      >
-        <div className="query-editor-rows gf-form-group">
-          <div ref={element => (this.element = element)} />
-
-          <div className="gf-form-query">
-            <div className="gf-form gf-form-query-letter-cell">
-              <label className="gf-form-label">
-                <span className="gf-form-query-letter-cell-carret muted">
-                  <i className="fa fa-caret-down" />
-                </span>
-                <span className="gf-form-query-letter-cell-letter">{panel.getNextQueryLetter()}</span>
-              </label>
-              {!isAddingMixed && (
-                <button className="btn btn-secondary gf-form-btn" onClick={this.onAddQueryClick}>
-                  Add Query
-                </button>
-              )}
-              {isAddingMixed && this.renderMixedPicker()}
+      <EditorTabBody heading="Queries" renderToolbar={this.renderToolbar} toolbarItems={[queryInspector, dsHelp]}>
+        <>
+          <PanelOptionSection>
+            <div className="query-editor-rows">
+              <div ref={element => (this.element = element)} />
+
+              <div className="gf-form-query">
+                <div className="gf-form gf-form-query-letter-cell">
+                  <label className="gf-form-label">
+                    <span className="gf-form-query-letter-cell-carret muted">
+                      <i className="fa fa-caret-down" />
+                    </span>{' '}
+                    <span className="gf-form-query-letter-cell-letter">{panel.getNextQueryLetter()}</span>
+                  </label>
+                </div>
+                <div className="gf-form">
+                  {!isAddingMixed && (
+                    <button className="btn btn-secondary gf-form-btn" onClick={this.onAddQueryClick}>
+                      Add Query
+                    </button>
+                  )}
+                  {isAddingMixed && this.renderMixedPicker()}
+                </div>
+              </div>
             </div>
-          </div>
-        </div>
+          </PanelOptionSection>
+          <PanelOptionSection>
+            <QueryOptions panel={panel} datasource={currentDS} />
+          </PanelOptionSection>
+        </>
       </EditorTabBody>
     );
   }

+ 2 - 8
public/app/features/dashboard/dashgrid/QueryInspector.tsx

@@ -1,4 +1,4 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent } from 'react';
 import { JSONFormatter } from 'app/core/components/JSONFormatter/JSONFormatter';
 import appEvents from 'app/core/app_events';
 import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
@@ -187,16 +187,10 @@ export class QueryInspector extends PureComponent<Props, State> {
 
     return (
       <>
-        <div>
-          {/*
-          <button className="btn btn-transparent btn-p-x-0 m-r-1" onClick={this.onToggleMocking}>
-            Mock response
-          </button>
-          */}
+        <div className="pull-right">
           <button className="btn btn-transparent btn-p-x-0 m-r-1" onClick={this.onToggleExpand}>
             {this.renderExpandCollapse()}
           </button>
-
           <CopyToClipboard
             className="btn btn-transparent btn-p-x-0"
             text={this.getTextForClipboard}

+ 167 - 0
public/app/features/dashboard/dashgrid/QueryOptions.tsx

@@ -0,0 +1,167 @@
+// Libraries
+import React, { PureComponent } from 'react';
+
+// Utils
+import { isValidTimeSpan } from 'app/core/utils/rangeutil';
+
+// Components
+import { Switch } from 'app/core/components/Switch/Switch';
+import { Input } from 'app/core/components/Form';
+import { EventsWithValidation } from 'app/core/components/Form/Input';
+import { InputStatus } from 'app/core/components/Form/Input';
+import DataSourceOption from './DataSourceOption';
+
+// Types
+import { PanelModel } from '../panel_model';
+import { ValidationEvents, DataSourceSelectItem } from 'app/types';
+
+const timeRangeValidationEvents: ValidationEvents = {
+  [EventsWithValidation.onBlur]: [
+    {
+      rule: value => {
+        if (!value) {
+          return true;
+        }
+        return isValidTimeSpan(value);
+      },
+      errorMessage: 'Not a valid timespan',
+    },
+  ],
+};
+
+const emptyToNull = (value: string) => {
+  return value === '' ? null : value;
+};
+
+interface Props {
+  panel: PanelModel;
+  datasource: DataSourceSelectItem;
+}
+
+export class QueryOptions extends PureComponent<Props> {
+  onOverrideTime = (evt, status: InputStatus) => {
+    const { value } = evt.target;
+    const { panel } = this.props;
+    const emptyToNullValue = emptyToNull(value);
+    if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
+      panel.timeFrom = emptyToNullValue;
+      panel.refresh();
+    }
+  };
+
+  onTimeShift = (evt, status: InputStatus) => {
+    const { value } = evt.target;
+    const { panel } = this.props;
+    const emptyToNullValue = emptyToNull(value);
+    if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) {
+      panel.timeShift = emptyToNullValue;
+      panel.refresh();
+    }
+  };
+
+  onToggleTimeOverride = () => {
+    const { panel } = this.props;
+    panel.hideTimeOverride = !panel.hideTimeOverride;
+    panel.refresh();
+  };
+
+  renderOptions() {
+    const { datasource, panel } = this.props;
+    const { queryOptions } = datasource.meta;
+
+    if (!queryOptions) {
+      return null;
+    }
+
+    const onChangeFn = (panelKey: string) => {
+      return (value: string | number) => {
+        panel[panelKey] = value;
+        panel.refresh();
+      };
+    };
+
+    const allOptions = {
+      cacheTimeout: {
+        label: 'Cache timeout',
+        placeholder: '60',
+        name: 'cacheTimeout',
+        value: panel.cacheTimeout,
+        tooltipInfo: (
+          <>
+            If your time series store has a query cache this option can override the default cache timeout. Specify a
+            numeric value in seconds.
+          </>
+        ),
+      },
+      maxDataPoints: {
+        label: 'Max data points',
+        placeholder: 'auto',
+        name: 'maxDataPoints',
+        value: panel.maxDataPoints,
+        tooltipInfo: (
+          <>
+            The maximum data points the query should return. For graphs this is automatically set to one data point per
+            pixel.
+          </>
+        ),
+      },
+      minInterval: {
+        label: 'Min time interval',
+        placeholder: '0',
+        name: 'minInterval',
+        value: panel.interval,
+        panelKey: 'interval',
+        tooltipInfo: (
+          <>
+            A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '}
+            <code>1m</code> if your data is written every minute. Access auto interval via variable{' '}
+            <code>$__interval</code> for time range string and <code>$__interval_ms</code> for numeric variable that can
+            be used in math expressions.
+          </>
+        ),
+      },
+    };
+
+    return Object.keys(queryOptions).map(key => {
+      const options = allOptions[key];
+      return <DataSourceOption key={key} {...options} onChange={onChangeFn(allOptions[key].panelKey || key)} />;
+    });
+  }
+
+  render = () => {
+    const hideTimeOverride = this.props.panel.hideTimeOverride;
+    return (
+      <div className="gf-form-inline">
+        {this.renderOptions()}
+
+        <div className="gf-form">
+          <span className="gf-form-label">Relative time</span>
+          <Input
+            type="text"
+            className="width-6"
+            placeholder="1h"
+            onBlur={this.onOverrideTime}
+            validationEvents={timeRangeValidationEvents}
+            hideErrorMessage={true}
+          />
+        </div>
+
+        <div className="gf-form">
+          <span className="gf-form-label">Time shift</span>
+          <Input
+            type="text"
+            className="width-6"
+            placeholder="1h"
+            onBlur={this.onTimeShift}
+            validationEvents={timeRangeValidationEvents}
+            hideErrorMessage={true}
+          />
+        </div>
+
+        <div className="gf-form-inline">
+          <Switch label="Hide time info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} />
+        </div>
+      </div>
+    );
+  };
+}

+ 0 - 97
public/app/features/dashboard/dashgrid/TimeRangeOptions.tsx

@@ -1,97 +0,0 @@
-import React, { PureComponent } from 'react';
-import { Switch } from 'app/core/components/Switch/Switch';
-import { Input } from 'app/core/components/Form';
-import { isValidTimeSpan } from 'app/core/utils/rangeutil';
-import { ValidationEvents } from 'app/types';
-import { EventsWithValidation } from 'app/core/components/Form/Input';
-import { PanelModel } from '../panel_model';
-import { InputStatus } from 'app/core/components/Form/Input';
-
-const timeRangeValidationEvents: ValidationEvents = {
-  [EventsWithValidation.onBlur]: [
-    {
-      rule: value => {
-        if (!value) {
-          return true;
-        }
-        return isValidTimeSpan(value);
-      },
-      errorMessage: 'Not a valid timespan',
-    },
-  ],
-};
-
-const emptyToNull = (value: string) => {
-  return value === '' ? null : value;
-};
-
-interface Props {
-  panel: PanelModel;
-}
-
-export class TimeRangeOptions extends PureComponent<Props> {
-  onOverrideTime = (evt, status: InputStatus) => {
-    const { value } = evt.target;
-    const { panel } = this.props;
-    const emptyToNullValue = emptyToNull(value);
-    if (status === InputStatus.Valid && panel.timeFrom !== emptyToNullValue) {
-      panel.timeFrom = emptyToNullValue;
-      panel.refresh();
-    }
-  };
-
-  onTimeShift = (evt, status: InputStatus) => {
-    const { value } = evt.target;
-    const { panel } = this.props;
-    const emptyToNullValue = emptyToNull(value);
-    if (status === InputStatus.Valid && panel.timeShift !== emptyToNullValue) {
-      panel.timeShift = emptyToNullValue;
-      panel.refresh();
-    }
-  };
-
-  onToggleTimeOverride = () => {
-    const { panel } = this.props;
-    panel.hideTimeOverride = !panel.hideTimeOverride;
-    panel.refresh();
-  };
-
-  render = () => {
-    const hideTimeOverride = this.props.panel.hideTimeOverride;
-    return (
-      <>
-        <h5 className="section-heading">Time Range</h5>
-
-        <div className="gf-form-group">
-          <div className="gf-form">
-            <span className="gf-form-label width-12">Override relative time</span>
-            <Input
-              type="text"
-              className="gf-form-input max-width-8"
-              placeholder="1h"
-              onBlur={this.onOverrideTime}
-              validationEvents={timeRangeValidationEvents}
-              hideErrorMessage={true}
-            />
-          </div>
-
-          <div className="gf-form">
-            <span className="gf-form-label width-12">Add time shift</span>
-            <Input
-              type="text"
-              className="gf-form-input max-width-8"
-              placeholder="1h"
-              onBlur={this.onTimeShift}
-              validationEvents={timeRangeValidationEvents}
-              hideErrorMessage={true}
-            />
-          </div>
-
-          <div className="gf-form-inline">
-            <Switch label="Hide time override info" checked={hideTimeOverride} onChange={this.onToggleTimeOverride} />
-          </div>
-        </div>
-      </>
-    );
-  };
-}

+ 13 - 8
public/app/features/dashboard/dashgrid/VisualizationTab.tsx

@@ -8,6 +8,7 @@ import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoa
 import { EditorTabBody } from './EditorTabBody';
 import { VizTypePicker } from './VizTypePicker';
 import { FadeIn } from 'app/core/components/Animations/FadeIn';
+import { PanelOptionSection } from './PanelOptionSection';
 
 // Types
 import { PanelModel } from '../panel_model';
@@ -59,11 +60,15 @@ export class VisualizationTab extends PureComponent<Props, State> {
       return <div ref={element => (this.element = element)} />;
     }
 
-    if (PanelOptions) {
-      return <PanelOptions options={this.getPanelDefaultOptions()} onChange={this.onPanelOptionsChanged} />;
-    } else {
-      return <p>Visualization has no options</p>;
-    }
+    return (
+      <PanelOptionSection>
+        {PanelOptions ? (
+          <PanelOptions options={this.getPanelDefaultOptions()} onChange={this.onPanelOptionsChanged} />
+        ) : (
+          <p>Visualization has no options</p>
+        )}
+      </PanelOptionSection>
+    );
   }
 
   componentDidMount() {
@@ -105,9 +110,9 @@ export class VisualizationTab extends PureComponent<Props, State> {
     for (let i = 0; i < panelCtrl.editorTabs.length; i++) {
       template +=
         `
-      <div class="form-section" ng-cloak>` +
-        (i > -1 ? `<div class="form-section__header">{{ctrl.editorTabs[${i}].title}}</div>` : '') +
-        `<div class="form-section__body">
+      <div class="panel-option-section" ng-cloak>` +
+        (i > 0 ? `<div class="panel-option-section__header">{{ctrl.editorTabs[${i}].title}}</div>` : '') +
+        `<div class="panel-option-section__body">
           <panel-editor-tab editor-tab="ctrl.editorTabs[${i}]" ctrl="ctrl"></panel-editor-tab>
         </div>
       </div>

+ 1 - 1
public/app/features/dashboard/dashnav/dashnav.ts

@@ -91,7 +91,7 @@ export class DashNavCtrl {
 
     this.dashboard.addPanel({
       type: 'add-panel',
-      gridPos: { x: 0, y: 0, w: 12, h: 9 },
+      gridPos: { x: 0, y: 0, w: 12, h: 8 },
       title: 'Panel Title',
     });
   }

+ 0 - 4
public/app/features/dashboard/panellinks/module.html

@@ -1,8 +1,4 @@
 <div class="editor-row">
-	<h5 class="section-heading">
-		Drilldown / detail link<tip>These links appear in the dropdown menu in the panel menu. </tip></h5>
-	</h5>
-
 	<div class="gf-form-group" ng-repeat="link in panel.links">
 		<div class="section">
 			<div class="gf-form max-width-25">

+ 0 - 46
public/app/features/dashboard/specs/AddPanelPanel.test.tsx

@@ -1,46 +0,0 @@
-import React from 'react';
-import { AddPanelPanel } from './../dashgrid/AddPanelPanel';
-import { PanelModel } from '../panel_model';
-import { shallow } from 'enzyme';
-import config from '../../../core/config';
-import { getPanelPlugin } from 'app/features/plugins/__mocks__/pluginMocks';
-
-jest.mock('app/core/store', () => ({
-  get: key => {
-    return null;
-  },
-  delete: key => {
-    return null;
-  },
-}));
-
-describe('AddPanelPanel', () => {
-  let wrapper, dashboardMock, panel;
-
-  beforeEach(() => {
-    config.panels = [
-      getPanelPlugin({ id: 'singlestat', sort: 2 }),
-      getPanelPlugin({ id: 'hidden', sort: 100, hideFromList: true }),
-      getPanelPlugin({ id: 'graph', sort: 1 }),
-      getPanelPlugin({ id: 'alexander_zabbix', sort: 100 }),
-      getPanelPlugin({ id: 'piechart', sort: 100 }),
-    ];
-
-    dashboardMock = { toggleRow: jest.fn() };
-
-    panel = new PanelModel({ collapsed: false });
-    wrapper = shallow(<AddPanelPanel panel={panel} dashboard={dashboardMock} />);
-  });
-
-  it('should fetch all panels sorted with core plugins first', () => {
-    expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('singlestat');
-    expect(wrapper.find('.add-panel__item').get(4).props.title).toBe('piechart');
-  });
-
-  it('should filter', () => {
-    wrapper.find('input').simulate('change', { target: { value: 'p' } });
-
-    expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('piechart');
-    expect(wrapper.find('.add-panel__item').get(0).props.title).toBe('graph');
-  });
-});

+ 3 - 3
public/app/features/datasources/settings/DataSourceSettings.tsx

@@ -177,6 +177,9 @@ export class DataSourceSettings extends PureComponent<Props, State> {
           <div className="page-container page-body">
             <div>
               <form onSubmit={this.onSubmit}>
+                {this.isReadOnly() && this.renderIsReadOnlyMessage()}
+                {this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
+
                 <BasicSettings
                   dataSourceName={dataSource.name}
                   isDefault={dataSource.isDefault}
@@ -184,9 +187,6 @@ export class DataSourceSettings extends PureComponent<Props, State> {
                   onNameChange={name => setDataSourceName(name)}
                 />
 
-                {this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
-
-                {this.isReadOnly() && this.renderIsReadOnlyMessage()}
                 {dataSourceMeta.module && (
                   <PluginSettings
                     dataSource={dataSource}

+ 15 - 15
public/app/features/datasources/settings/__snapshots__/DataSourceSettings.test.tsx.snap

@@ -12,17 +12,17 @@ exports[`Render should render alpha info text 1`] = `
       <form
         onSubmit={[Function]}
       >
+        <div
+          className="grafana-info-box"
+        >
+          This plugin is marked as being in alpha state, which means it is in early development phase and updates will include breaking changes.
+        </div>
         <BasicSettings
           dataSourceName="gdev-cloudwatch"
           isDefault={false}
           onDefaultChange={[Function]}
           onNameChange={[Function]}
         />
-        <div
-          className="grafana-info-box"
-        >
-          This plugin is marked as being in alpha state, which means it is in early development phase and updates will include breaking changes.
-        </div>
         <PluginSettings
           dataSource={
             Object {
@@ -111,17 +111,17 @@ exports[`Render should render beta info text 1`] = `
       <form
         onSubmit={[Function]}
       >
+        <div
+          className="grafana-info-box"
+        >
+          This plugin is marked as being in a beta development state. This means it is in currently in active development and could be missing important features.
+        </div>
         <BasicSettings
           dataSourceName="gdev-cloudwatch"
           isDefault={false}
           onDefaultChange={[Function]}
           onNameChange={[Function]}
         />
-        <div
-          className="grafana-info-box"
-        >
-          This plugin is marked as being in a beta development state. This means it is in currently in active development and could be missing important features.
-        </div>
         <PluginSettings
           dataSource={
             Object {
@@ -304,17 +304,17 @@ exports[`Render should render is ready only message 1`] = `
       <form
         onSubmit={[Function]}
       >
+        <div
+          className="grafana-info-box span8"
+        >
+          This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.
+        </div>
         <BasicSettings
           dataSourceName="gdev-cloudwatch"
           isDefault={false}
           onDefaultChange={[Function]}
           onNameChange={[Function]}
         />
-        <div
-          className="grafana-info-box span8"
-        >
-          This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.
-        </div>
         <PluginSettings
           dataSource={
             Object {

+ 1 - 1
public/app/features/datasources/state/actions.ts

@@ -191,7 +191,7 @@ export function deleteDataSource(): ThunkResult<void> {
 export function nameExits(dataSources, name) {
   return (
     dataSources.filter(dataSource => {
-      return dataSource.name === name;
+      return dataSource.name.toLowerCase() === name.toLowerCase();
     }).length > 0
   );
 }

+ 9 - 27
public/app/features/explore/Explore.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import { hot } from 'react-hot-loader';
-import Select from 'react-select';
 import _ from 'lodash';
 
 import { DataSource } from 'app/types/datasources';
@@ -25,10 +24,7 @@ import {
   makeTimeSeriesList,
   updateHistory,
 } from 'app/core/utils/explore';
-import ResetStyles from 'app/core/components/Picker/ResetStyles';
-import PickerOption from 'app/core/components/Picker/PickerOption';
-import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer';
-import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage';
+import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
 import TableModel from 'app/core/table_model';
 import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
 import { Emitter } from 'app/core/utils/emitter';
@@ -158,10 +154,12 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
     if (!datasourceSrv) {
       throw new Error('No datasource service passed as props.');
     }
+
     const datasources = datasourceSrv.getExternal();
     const exploreDatasources = datasources.map(ds => ({
       value: ds.name,
-      label: ds.name,
+      name: ds.name,
+      meta: ds.meta,
     }));
 
     if (datasources.length > 0) {
@@ -885,7 +883,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
     } = this.state;
     const graphHeight = showingGraph && showingTable ? '200px' : '400px';
     const exploreClass = split ? 'explore explore-split' : 'explore';
-    const selectedDatasource = datasource ? exploreDatasources.find(d => d.label === datasource.name) : undefined;
+    const selectedDatasource = datasource ? exploreDatasources.find(d => d.name === datasource.name) : undefined;
     const graphLoading = queryTransactions.some(qt => qt.resultType === 'Graph' && !qt.done);
     const tableLoading = queryTransactions.some(qt => qt.resultType === 'Table' && !qt.done);
     const logsLoading = queryTransactions.some(qt => qt.resultType === 'Logs' && !qt.done);
@@ -910,26 +908,10 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
           )}
           {!datasourceMissing ? (
             <div className="navbar-buttons">
-              <Select
-                classNamePrefix={`gf-form-select-box`}
-                isMulti={false}
-                menuShouldScrollIntoView={false}
-                isLoading={datasourceLoading}
-                isClearable={false}
-                className="gf-form-input gf-form-input--form-dropdown datasource-picker"
+              <DataSourcePicker
                 onChange={this.onChangeDatasource}
-                options={exploreDatasources}
-                styles={ResetStyles}
-                maxMenuHeight={500}
-                placeholder="Select datasource"
-                loadingMessage={() => 'Loading datasources...'}
-                noOptionsMessage={() => 'No datasources found'}
-                value={selectedDatasource}
-                components={{
-                  Option: PickerOption,
-                  IndicatorsContainer,
-                  NoOptionsMessage,
-                }}
+                datasources={exploreDatasources}
+                current={selectedDatasource}
               />
             </div>
           ) : null}
@@ -948,7 +930,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
             </button>
           </div>
           <div className="navbar-buttons relative">
-            <button className="btn navbar-button--primary" onClick={this.onSubmit}>
+            <button className="btn navbar-button navbar-button--primary" onClick={this.onSubmit}>
               Run Query{' '}
               {loading ? <i className="fa fa-spinner fa-spin run-icon" /> : <i className="fa fa-level-down run-icon" />}
             </button>

+ 12 - 19
public/app/features/explore/Logs.tsx

@@ -73,7 +73,7 @@ interface RowState {
   fieldStats: LogsLabelStat[];
   fieldValue: string;
   parsed: boolean;
-  parser: LogsParser;
+  parser?: LogsParser;
   parsedFieldHighlights: string[];
   showFieldStats: boolean;
 }
@@ -94,7 +94,7 @@ class Row extends PureComponent<RowProps, RowState> {
     fieldStats: null,
     fieldValue: null,
     parsed: false,
-    parser: null,
+    parser: undefined,
     parsedFieldHighlights: [],
     showFieldStats: false,
   };
@@ -110,19 +110,16 @@ class Row extends PureComponent<RowProps, RowState> {
   onClickHighlight = (fieldText: string) => {
     const { getRows } = this.props;
     const { parser } = this.state;
+    const allRows = getRows();
 
-    const fieldMatch = fieldText.match(parser.fieldRegex);
-    if (fieldMatch) {
-      const allRows = getRows();
-      // Build value-agnostic row matcher based on the field label
-      const fieldLabel = fieldMatch[1];
-      const fieldValue = fieldMatch[2];
-      const matcher = parser.buildMatcher(fieldLabel);
-      const fieldStats = calculateFieldStats(allRows, matcher);
-      const fieldCount = fieldStats.reduce((sum, stat) => sum + stat.count, 0);
-
-      this.setState({ fieldCount, fieldLabel, fieldStats, fieldValue, showFieldStats: true });
-    }
+    // Build value-agnostic row matcher based on the field label
+    const fieldLabel = parser.getLabelFromField(fieldText);
+    const fieldValue = parser.getValueFromField(fieldText);
+    const matcher = parser.buildMatcher(fieldLabel);
+    const fieldStats = calculateFieldStats(allRows, matcher);
+    const fieldCount = fieldStats.reduce((sum, stat) => sum + stat.count, 0);
+
+    this.setState({ fieldCount, fieldLabel, fieldStats, fieldValue, showFieldStats: true });
   };
 
   onMouseOverMessage = () => {
@@ -141,11 +138,7 @@ class Row extends PureComponent<RowProps, RowState> {
       const parser = getParser(row.entry);
       if (parser) {
         // Use parser to highlight detected fields
-        const parsedFieldHighlights = [];
-        this.props.row.entry.replace(new RegExp(parser.fieldRegex, 'g'), substring => {
-          parsedFieldHighlights.push(substring.trim());
-          return '';
-        });
+        const parsedFieldHighlights = parser.getFields(this.props.row.entry);
         this.setState({ parsedFieldHighlights, parsed: true, parser });
       }
     }

+ 0 - 1
public/app/features/panel/all.ts

@@ -4,4 +4,3 @@ import './solo_panel_ctrl';
 import './query_ctrl';
 import './panel_editor_tab';
 import './query_editor_row';
-import './query_troubleshooter';

+ 0 - 28
public/app/features/panel/panel_header.ts

@@ -1,4 +1,3 @@
-import $ from 'jquery';
 import { coreModule } from 'app/core/core';
 
 const template = `
@@ -93,40 +92,13 @@ function panelHeader($compile) {
         }
       });
 
-      elem.find('.panel-menu-toggle').click(() => {
-        togglePanelStackPosition();
-      });
-
       function togglePanelMenu(e) {
         if (!isDragged) {
           e.stopPropagation();
-          togglePanelStackPosition();
           elem.find('[data-toggle=dropdown]').dropdown('toggle');
         }
       }
 
-      /**
-       * Hack for adding special class 'dropdown-menu-open' to the panel.
-       * This class sets z-index for panel and prevents menu overlapping.
-       */
-      function togglePanelStackPosition() {
-        const menuOpenClass = 'dropdown-menu-open';
-        const panelGridClass = '.react-grid-item.panel';
-
-        let panelElem = elem
-          .find('[data-toggle=dropdown]')
-          .parentsUntil('.panel')
-          .parent();
-        const menuElem = elem.find('[data-toggle=dropdown]').parent();
-        panelElem = panelElem && panelElem.length ? panelElem[0] : undefined;
-        if (panelElem) {
-          panelElem = $(panelElem);
-          $(panelGridClass).removeClass(menuOpenClass);
-          const state = !menuElem.hasClass('open');
-          panelElem.toggleClass(menuOpenClass, state);
-        }
-      }
-
       let mouseX, mouseY;
       elem.mousedown(e => {
         mouseX = e.pageX;

+ 47 - 35
public/app/features/panel/partials/general_tab.html

@@ -1,37 +1,49 @@
-<div class="editor-row">
-	<div class="section gf-form-group">
-		<h5 class="section-heading">Info</h5>
-		<div class="gf-form">
-			<span class="gf-form-label width-7">Title</span>
-			<input type="text" class="gf-form-input width-25" ng-model='ctrl.panel.title' ng-model-onblur></input>
-		</div>
-		<div class="gf-form gf-form--v-stretch">
-			<span class="gf-form-label width-7">Description</span>
-			<textarea class="gf-form-input width-25" rows="3" ng-model="ctrl.panel.description" ng-model-onblur placeholder="Panel description, supports markdown & links"></textarea>
-		</div>
-    <gf-form-switch class="gf-form" label-class="width-7" switch-class="max-width-6" label="Transparent" checked="ctrl.panel.transparent" on-change="ctrl.render()"></gf-form-switch>
-	</div>
-
-  <div class="section gf-form-group">
-    <h5 class="section-heading">Repeat</h5>
-		<div class="gf-form">
-			<span class="gf-form-label width-9">For each value of</span>
-			<dash-repeat-option panel="ctrl.panel"></dash-repeat-option>
-		</div>
-    <div class="gf-form" ng-show="ctrl.panel.repeat">
-			<span class="gf-form-label width-9">Direction</span>
-			<select class="gf-form-input" ng-model="ctrl.panel.repeatDirection" ng-options="f.value as f.text for f in [{value: 'v', text: 'Vertical'}, {value: 'h', text: 'Horizontal'}]">
-				<option value=""></option>
-			</select>
-		</div>
-		<div class="gf-form" ng-show="ctrl.panel.repeat && ctrl.panel.repeatDirection == 'h'">
-			<span class="gf-form-label width-9">Min width</span>
-			<select class="gf-form-input" ng-model="ctrl.panel.minSpan" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]">
-				<option value=""></option>
-			</select>
-		</div>
-	</div>
-
-	<panel-links-editor panel="ctrl.panel"></panel-links-editor>
+<div class="panel-option-section">
+  <!-- <div class="panel&#45;option&#45;section__header">Information</div> -->
+  <div class="panel-option-section__body">
+    <div class="section">
+      <div class="gf-form">
+        <span class="gf-form-label width-7">Title</span>
+        <input type="text" class="gf-form-input width-25" ng-model='ctrl.panel.title' ng-model-onblur></input>
+      </div>
+      <gf-form-switch class="gf-form" label-class="width-7" switch-class="max-width-6" label="Transparent" checked="ctrl.panel.transparent" on-change="ctrl.render()"></gf-form-switch>
+    </div>
+    <div class="section">
+      <div class="gf-form gf-form--v-stretch">
+        <span class="gf-form-label width-7">Description</span>
+        <textarea class="gf-form-input width-25" rows="5" ng-model="ctrl.panel.description" ng-model-onblur placeholder="Panel description, supports markdown & links"></textarea>
+      </div>
+    </div>
+  </div>
+</div>
 
+<div class="panel-option-section">
+  <div class="panel-option-section__header">Repeating</div>
+  <div class="panel-option-section__body">
+    <div class="section">
+      <div class="gf-form">
+        <span class="gf-form-label width-9">Repat</span>
+        <dash-repeat-option panel="ctrl.panel"></dash-repeat-option>
+      </div>
+      <div class="gf-form" ng-show="ctrl.panel.repeat">
+        <span class="gf-form-label width-9">Direction</span>
+        <select class="gf-form-input" ng-model="ctrl.panel.repeatDirection" ng-options="f.value as f.text for f in [{value: 'v', text: 'Vertical'}, {value: 'h', text: 'Horizontal'}]">
+          <option value=""></option>
+        </select>
+      </div>
+      <div class="gf-form" ng-show="ctrl.panel.repeat && ctrl.panel.repeatDirection == 'h'">
+        <span class="gf-form-label width-9">Min width</span>
+        <select class="gf-form-input" ng-model="ctrl.panel.minSpan" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]">
+          <option value=""></option>
+        </select>
+      </div>
+      </div>
+  </div>
+</div>
 
+<div class="panel-option-section">
+  <div class="panel-option-section__header">Drildown Links</div>
+  <div class="panel-option-section__body">
+    <panel-links-editor panel="ctrl.panel"></panel-links-editor>
+  </div>
+</div>

+ 0 - 188
public/app/features/panel/query_troubleshooter.ts

@@ -1,188 +0,0 @@
-import _ from 'lodash';
-import appEvents from 'app/core/app_events';
-import { coreModule, JsonExplorer } from 'app/core/core';
-
-const template = `
-<div class="query-troubleshooter" ng-if="ctrl.isOpen">
-  <div class="query-troubleshooter__header">
-    <a class="pointer" ng-click="ctrl.toggleMocking()">Mock Response</a>
-    <a class="pointer" ng-click="ctrl.toggleExpand()" ng-hide="ctrl.allNodesExpanded">
-      <i class="fa fa-plus-square-o"></i> Expand All
-    </a>
-    <a class="pointer" ng-click="ctrl.toggleExpand()" ng-show="ctrl.allNodesExpanded">
-      <i class="fa fa-minus-square-o"></i> Collapse All
-    </a>
-    <a class="pointer" clipboard-button="ctrl.getClipboardText()"><i class="fa fa-clipboard"></i> Copy to Clipboard</a>
-  </div>
-  <div class="query-troubleshooter__body" ng-hide="ctrl.isMocking">
-    <i class="fa fa-spinner fa-spin" ng-show="ctrl.isLoading"></i>
-    <div class="query-troubleshooter-json"></div>
-  </div>
-  <div class="query-troubleshooter__body" ng-show="ctrl.isMocking">
-    <div class="gf-form p-l-1 gf-form--v-stretch">
-			<textarea class="gf-form-input" style="width: 95%" rows="10" ng-model="ctrl.mockedResponse"  placeholder="JSON"></textarea>
-    </div>
-  </div>
-</div>
-`;
-
-export class QueryTroubleshooterCtrl {
-  isOpen: any;
-  isLoading: boolean;
-  showResponse: boolean;
-  panelCtrl: any;
-  renderJsonExplorer: (data) => void;
-  onRequestErrorEventListener: any;
-  onRequestResponseEventListener: any;
-  hasError: boolean;
-  allNodesExpanded: boolean;
-  isMocking: boolean;
-  mockedResponse: string;
-  jsonExplorer: JsonExplorer;
-
-  /** @ngInject */
-  constructor($scope, private $timeout) {
-    this.onRequestErrorEventListener = this.onRequestError.bind(this);
-    this.onRequestResponseEventListener = this.onRequestResponse.bind(this);
-
-    appEvents.on('ds-request-response', this.onRequestResponseEventListener);
-    appEvents.on('ds-request-error', this.onRequestErrorEventListener);
-
-    $scope.$on('$destroy', this.removeEventsListeners.bind(this));
-    $scope.$watch('ctrl.isOpen', this.stateChanged.bind(this));
-  }
-
-  removeEventsListeners() {
-    appEvents.off('ds-request-response', this.onRequestResponseEventListener);
-    appEvents.off('ds-request-error', this.onRequestErrorEventListener);
-  }
-
-  toggleMocking() {
-    this.isMocking = !this.isMocking;
-  }
-
-  onRequestError(err) {
-    // ignore if closed
-    if (!this.isOpen) {
-      return;
-    }
-
-    this.isOpen = true;
-    this.hasError = true;
-    this.onRequestResponse(err);
-  }
-
-  stateChanged() {
-    if (this.isOpen) {
-      this.panelCtrl.refresh();
-      this.isLoading = true;
-    }
-  }
-
-  getClipboardText(): string {
-    if (this.jsonExplorer) {
-      return JSON.stringify(this.jsonExplorer.json, null, 2);
-    }
-    return '';
-  }
-
-  handleMocking(data) {
-    let mockedData;
-    try {
-      mockedData = JSON.parse(this.mockedResponse);
-    } catch (err) {
-      appEvents.emit('alert-error', ['Failed to parse mocked response']);
-      return;
-    }
-
-    data.data = mockedData;
-  }
-
-  onRequestResponse(data) {
-    // ignore if closed
-    if (!this.isOpen) {
-      return;
-    }
-
-    if (this.isMocking) {
-      this.handleMocking(data);
-      return;
-    }
-
-    this.isLoading = false;
-    data = _.cloneDeep(data);
-
-    if (data.headers) {
-      delete data.headers;
-    }
-
-    if (data.config) {
-      data.request = data.config;
-      delete data.config;
-      delete data.request.transformRequest;
-      delete data.request.transformResponse;
-      delete data.request.paramSerializer;
-      delete data.request.jsonpCallbackParam;
-      delete data.request.headers;
-      delete data.request.requestId;
-      delete data.request.inspect;
-      delete data.request.retry;
-      delete data.request.timeout;
-    }
-
-    if (data.data) {
-      data.response = data.data;
-
-      if (data.status === 200) {
-        // if we are in error state, assume we automatically opened
-        // and auto close it again
-        if (this.hasError) {
-          this.hasError = false;
-          this.isOpen = false;
-        }
-      }
-
-      delete data.data;
-      delete data.status;
-      delete data.statusText;
-      delete data.$$config;
-    }
-
-    this.$timeout(_.partial(this.renderJsonExplorer, data));
-  }
-
-  toggleExpand(depth) {
-    if (this.jsonExplorer) {
-      this.allNodesExpanded = !this.allNodesExpanded;
-      this.jsonExplorer.openAtDepth(this.allNodesExpanded ? 20 : 1);
-    }
-  }
-}
-
-export function queryTroubleshooter() {
-  return {
-    restrict: 'E',
-    template: template,
-    controller: QueryTroubleshooterCtrl,
-    bindToController: true,
-    controllerAs: 'ctrl',
-    scope: {
-      panelCtrl: '=',
-      isOpen: '=',
-    },
-    link: (scope, elem, attrs, ctrl) => {
-      ctrl.renderJsonExplorer = data => {
-        const jsonElem = elem.find('.query-troubleshooter-json');
-
-        ctrl.jsonExplorer = new JsonExplorer(data, 3, {
-          animateOpen: true,
-        });
-
-        const html = ctrl.jsonExplorer.render(true);
-        jsonElem.html(html);
-      };
-    },
-  };
-}
-
-coreModule.directive('queryTroubleshooter', queryTroubleshooter);

+ 0 - 71
public/app/features/panel/viz_tab.ts

@@ -1,71 +0,0 @@
-import coreModule from 'app/core/core_module';
-import { DashboardModel } from '../dashboard/dashboard_model';
-import { VizTypePicker } from '../dashboard/dashgrid/VizTypePicker';
-import { react2AngularDirective } from 'app/core/utils/react2angular';
-import { PanelPlugin } from 'app/types/plugins';
-
-export class VizTabCtrl {
-  panelCtrl: any;
-  dashboard: DashboardModel;
-
-  /** @ngInject */
-  constructor($scope) {
-    this.panelCtrl = $scope.ctrl;
-    this.dashboard = this.panelCtrl.dashboard;
-
-    $scope.ctrl = this;
-  }
-
-  onTypeChanged = (plugin: PanelPlugin) => {};
-}
-
-const template = `
-<div class="gf-form-group ">
-  <div class="gf-form-query">
-    <div class="gf-form">
-      <label class="gf-form-label">
-        <img src="public/app/plugins/panel/graph/img/icn-graph-panel.svg" style="width: 16px; height: 16px" />
-        Graph
-        <i class="fa fa-caret-down" />
-      </label>
-		</div>
-
-		<div class="gf-form gf-form--grow">
-			<label class="gf-form-label gf-form-label--grow"></label>
-		</div>
-	</div>
-
-	<br />
-	<br />
-
-  <div class="query-editor-rows gf-form-group">
-	  <div ng-repeat="tab in ctrl.panelCtrl.optionTabs">
-	    <div class="gf-form-query">
-		    <div class="gf-form gf-form-query-letter-cell">
-			    <label class="gf-form-label">
-				    <span class="gf-form-query-letter-cell-carret">
-					    <i class="fa fa-caret-down"></i>
-				    </span>
-				    <span class="gf-form-query-letter-cell-letter">{{tab.title}}</span>
-          </label>
-			  </div>
-        <div class="gf-form gf-form--grow">
-			    <label class="gf-form-label gf-form-label--grow"></label>
-		    </div>
-			</div>
-		</div>
-	</div>
-</div>`;
-
-/** @ngInject */
-export function vizTabDirective() {
-  'use strict';
-  return {
-    restrict: 'E',
-    template: template,
-    controller: VizTabCtrl,
-  };
-}
-
-react2AngularDirective('vizTypePicker', VizTypePicker, ['currentType', ['onTypeChanged', { watchDepth: 'reference' }]]);
-coreModule.directive('vizTab', vizTabDirective);

+ 1 - 1
public/app/features/teams/TeamMembers.tsx

@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import SlideDown from 'app/core/components/Animations/SlideDown';
-import { UserPicker } from 'app/core/components/Picker/UserPicker';
+import { UserPicker } from 'app/core/components/Select/UserPicker';
 import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
 import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
 import { TeamMember, User } from 'app/types';

+ 57 - 0
public/app/features/users/InviteeRow.tsx

@@ -0,0 +1,57 @@
+import React, { createRef, PureComponent } from 'react';
+import { connect } from 'react-redux';
+import { Invitee } from 'app/types';
+import { revokeInvite } from './state/actions';
+
+export interface Props {
+  invitee: Invitee;
+  revokeInvite: typeof revokeInvite;
+}
+
+class InviteeRow extends PureComponent<Props> {
+  private copyUrlRef = createRef<HTMLTextAreaElement>();
+
+  copyToClipboard = () => {
+    const node = this.copyUrlRef.current;
+
+    if (node) {
+      node.select();
+      document.execCommand('copy');
+    }
+  };
+
+  render() {
+    const { invitee, revokeInvite } = this.props;
+    return (
+      <tr>
+        <td>{invitee.email}</td>
+        <td>{invitee.name}</td>
+        <td className="text-right">
+          <button className="btn btn-inverse btn-mini" onClick={this.copyToClipboard}>
+            <textarea
+              readOnly={true}
+              value={invitee.url}
+              style={{ position: 'absolute', right: -1000 }}
+              ref={this.copyUrlRef}
+            />
+            <i className="fa fa-clipboard" /> Copy Invite
+          </button>
+          &nbsp;
+        </td>
+        <td>
+          <button className="btn btn-danger btn-mini" onClick={() => revokeInvite(invitee.code)}>
+            <i className="fa fa-remove" />
+          </button>
+        </td>
+      </tr>
+    );
+  }
+}
+
+const mapDispatchToProps = {
+  revokeInvite,
+};
+
+export default connect(() => {
+  return {};
+}, mapDispatchToProps)(InviteeRow);

+ 0 - 1
public/app/features/users/InviteesTable.test.tsx

@@ -7,7 +7,6 @@ import { getMockInvitees } from './__mocks__/userMocks';
 const setup = (propOverrides?: object) => {
   const props: Props = {
     invitees: [] as Invitee[],
-    onRevokeInvite: jest.fn(),
   };
 
   Object.assign(props, propOverrides);

+ 4 - 37
public/app/features/users/InviteesTable.tsx

@@ -1,25 +1,14 @@
-import React, { createRef, PureComponent } from 'react';
+import React, { PureComponent } from 'react';
 import { Invitee } from 'app/types';
+import InviteeRow from './InviteeRow';
 
 export interface Props {
   invitees: Invitee[];
-  onRevokeInvite: (code: string) => void;
 }
 
 export default class InviteesTable extends PureComponent<Props> {
-  private copyUrlRef = createRef<HTMLTextAreaElement>();
-
-  copyToClipboard = () => {
-    const node = this.copyUrlRef.current;
-
-    if (node) {
-      node.select();
-      document.execCommand('copy');
-    }
-  };
-
   render() {
-    const { invitees, onRevokeInvite } = this.props;
+    const { invitees } = this.props;
 
     return (
       <table className="filter-table form-inline">
@@ -33,29 +22,7 @@ export default class InviteesTable extends PureComponent<Props> {
         </thead>
         <tbody>
           {invitees.map((invitee, index) => {
-            return (
-              <tr key={`${invitee.id}-${index}`}>
-                <td>{invitee.email}</td>
-                <td>{invitee.name}</td>
-                <td className="text-right">
-                  <button className="btn btn-inverse btn-mini" onClick={this.copyToClipboard}>
-                    <textarea
-                      readOnly={true}
-                      value={invitee.url}
-                      style={{ position: 'absolute', right: -1000 }}
-                      ref={this.copyUrlRef}
-                    />
-                    <i className="fa fa-clipboard" /> Copy Invite
-                  </button>
-                  &nbsp;
-                </td>
-                <td>
-                  <button className="btn btn-danger btn-mini" onClick={() => onRevokeInvite(invitee.code)}>
-                    <i className="fa fa-remove" />
-                  </button>
-                </td>
-              </tr>
-            );
+            return <InviteeRow key={`${invitee.id}-${index}`} invitee={invitee} />;
           })}
         </tbody>
       </table>

+ 0 - 1
public/app/features/users/UsersListPage.test.tsx

@@ -16,7 +16,6 @@ const setup = (propOverrides?: object) => {
     invitees: [] as Invitee[],
     searchQuery: '',
     externalUserMngInfo: '',
-    revokeInvite: jest.fn(),
     loadInvitees: jest.fn(),
     loadUsers: jest.fn(),
     updateUser: jest.fn(),

+ 2 - 8
public/app/features/users/UsersListPage.tsx

@@ -9,7 +9,7 @@ import UsersTable from './UsersTable';
 import InviteesTable from './InviteesTable';
 import { Invitee, NavModel, OrgUser } from 'app/types';
 import appEvents from 'app/core/app_events';
-import { loadUsers, loadInvitees, revokeInvite, setUsersSearchQuery, updateUser, removeUser } from './state/actions';
+import { loadUsers, loadInvitees, setUsersSearchQuery, updateUser, removeUser } from './state/actions';
 import { getNavModel } from '../../core/selectors/navModel';
 import { getInvitees, getUsers, getUsersSearchQuery } from './state/selectors';
 
@@ -25,7 +25,6 @@ export interface Props {
   setUsersSearchQuery: typeof setUsersSearchQuery;
   updateUser: typeof updateUser;
   removeUser: typeof removeUser;
-  revokeInvite: typeof revokeInvite;
 }
 
 export interface State {
@@ -79,10 +78,6 @@ export class UsersListPage extends PureComponent<Props, State> {
     });
   };
 
-  onRevokeInvite = code => {
-    this.props.revokeInvite(code);
-  };
-
   onShowInvites = () => {
     this.setState(prevState => ({
       showInvites: !prevState.showInvites,
@@ -93,7 +88,7 @@ export class UsersListPage extends PureComponent<Props, State> {
     const { invitees, users } = this.props;
 
     if (this.state.showInvites) {
-      return <InviteesTable invitees={invitees} onRevokeInvite={code => this.onRevokeInvite(code)} />;
+      return <InviteesTable invitees={invitees} />;
     } else {
       return (
         <UsersTable
@@ -141,7 +136,6 @@ const mapDispatchToProps = {
   setUsersSearchQuery,
   updateUser,
   removeUser,
-  revokeInvite,
 };
 
 export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(UsersListPage));

+ 1 - 1
public/app/features/users/__mocks__/userMocks.ts

@@ -48,7 +48,7 @@ export const getMockInvitees = (amount: number) => {
       orgId: 1,
       role: 'viewer',
       status: 'not accepted',
-      url: `localhost/invite/$${i}`,
+      url: `localhost/invite/${i}`,
     });
   }
 

+ 120 - 258
public/app/features/users/__snapshots__/InviteesTable.test.tsx.snap

@@ -49,270 +49,132 @@ exports[`Render should render invitees 1`] = `
     </tr>
   </thead>
   <tbody>
-    <tr
+    <Connect(InviteeRow)
+      invitee={
+        Object {
+          "code": "asdfasdfsadf-0",
+          "createdOn": "2018-10-02",
+          "email": "invitee-0@test.com",
+          "emailSent": true,
+          "emailSentOn": "2018-10-02",
+          "id": 0,
+          "invitedByEmail": "admin@grafana.com",
+          "invitedByLogin": "admin",
+          "invitedByName": "admin",
+          "name": "invitee-0",
+          "orgId": 1,
+          "role": "viewer",
+          "status": "not accepted",
+          "url": "localhost/invite/0",
+        }
+      }
       key="0-0"
-    >
-      <td>
-        invitee-0@test.com
-      </td>
-      <td>
-        invitee-0
-      </td>
-      <td
-        className="text-right"
-      >
-        <button
-          className="btn btn-inverse btn-mini"
-          onClick={[Function]}
-        >
-          <textarea
-            readOnly={true}
-            style={
-              Object {
-                "position": "absolute",
-                "right": -1000,
-              }
-            }
-            value="localhost/invite/$0"
-          />
-          <i
-            className="fa fa-clipboard"
-          />
-           Copy Invite
-        </button>
-         
-      </td>
-      <td>
-        <button
-          className="btn btn-danger btn-mini"
-          onClick={[Function]}
-        >
-          <i
-            className="fa fa-remove"
-          />
-        </button>
-      </td>
-    </tr>
-    <tr
+    />
+    <Connect(InviteeRow)
+      invitee={
+        Object {
+          "code": "asdfasdfsadf-1",
+          "createdOn": "2018-10-02",
+          "email": "invitee-1@test.com",
+          "emailSent": true,
+          "emailSentOn": "2018-10-02",
+          "id": 1,
+          "invitedByEmail": "admin@grafana.com",
+          "invitedByLogin": "admin",
+          "invitedByName": "admin",
+          "name": "invitee-1",
+          "orgId": 1,
+          "role": "viewer",
+          "status": "not accepted",
+          "url": "localhost/invite/1",
+        }
+      }
       key="1-1"
-    >
-      <td>
-        invitee-1@test.com
-      </td>
-      <td>
-        invitee-1
-      </td>
-      <td
-        className="text-right"
-      >
-        <button
-          className="btn btn-inverse btn-mini"
-          onClick={[Function]}
-        >
-          <textarea
-            readOnly={true}
-            style={
-              Object {
-                "position": "absolute",
-                "right": -1000,
-              }
-            }
-            value="localhost/invite/$1"
-          />
-          <i
-            className="fa fa-clipboard"
-          />
-           Copy Invite
-        </button>
-         
-      </td>
-      <td>
-        <button
-          className="btn btn-danger btn-mini"
-          onClick={[Function]}
-        >
-          <i
-            className="fa fa-remove"
-          />
-        </button>
-      </td>
-    </tr>
-    <tr
+    />
+    <Connect(InviteeRow)
+      invitee={
+        Object {
+          "code": "asdfasdfsadf-2",
+          "createdOn": "2018-10-02",
+          "email": "invitee-2@test.com",
+          "emailSent": true,
+          "emailSentOn": "2018-10-02",
+          "id": 2,
+          "invitedByEmail": "admin@grafana.com",
+          "invitedByLogin": "admin",
+          "invitedByName": "admin",
+          "name": "invitee-2",
+          "orgId": 1,
+          "role": "viewer",
+          "status": "not accepted",
+          "url": "localhost/invite/2",
+        }
+      }
       key="2-2"
-    >
-      <td>
-        invitee-2@test.com
-      </td>
-      <td>
-        invitee-2
-      </td>
-      <td
-        className="text-right"
-      >
-        <button
-          className="btn btn-inverse btn-mini"
-          onClick={[Function]}
-        >
-          <textarea
-            readOnly={true}
-            style={
-              Object {
-                "position": "absolute",
-                "right": -1000,
-              }
-            }
-            value="localhost/invite/$2"
-          />
-          <i
-            className="fa fa-clipboard"
-          />
-           Copy Invite
-        </button>
-         
-      </td>
-      <td>
-        <button
-          className="btn btn-danger btn-mini"
-          onClick={[Function]}
-        >
-          <i
-            className="fa fa-remove"
-          />
-        </button>
-      </td>
-    </tr>
-    <tr
+    />
+    <Connect(InviteeRow)
+      invitee={
+        Object {
+          "code": "asdfasdfsadf-3",
+          "createdOn": "2018-10-02",
+          "email": "invitee-3@test.com",
+          "emailSent": true,
+          "emailSentOn": "2018-10-02",
+          "id": 3,
+          "invitedByEmail": "admin@grafana.com",
+          "invitedByLogin": "admin",
+          "invitedByName": "admin",
+          "name": "invitee-3",
+          "orgId": 1,
+          "role": "viewer",
+          "status": "not accepted",
+          "url": "localhost/invite/3",
+        }
+      }
       key="3-3"
-    >
-      <td>
-        invitee-3@test.com
-      </td>
-      <td>
-        invitee-3
-      </td>
-      <td
-        className="text-right"
-      >
-        <button
-          className="btn btn-inverse btn-mini"
-          onClick={[Function]}
-        >
-          <textarea
-            readOnly={true}
-            style={
-              Object {
-                "position": "absolute",
-                "right": -1000,
-              }
-            }
-            value="localhost/invite/$3"
-          />
-          <i
-            className="fa fa-clipboard"
-          />
-           Copy Invite
-        </button>
-         
-      </td>
-      <td>
-        <button
-          className="btn btn-danger btn-mini"
-          onClick={[Function]}
-        >
-          <i
-            className="fa fa-remove"
-          />
-        </button>
-      </td>
-    </tr>
-    <tr
+    />
+    <Connect(InviteeRow)
+      invitee={
+        Object {
+          "code": "asdfasdfsadf-4",
+          "createdOn": "2018-10-02",
+          "email": "invitee-4@test.com",
+          "emailSent": true,
+          "emailSentOn": "2018-10-02",
+          "id": 4,
+          "invitedByEmail": "admin@grafana.com",
+          "invitedByLogin": "admin",
+          "invitedByName": "admin",
+          "name": "invitee-4",
+          "orgId": 1,
+          "role": "viewer",
+          "status": "not accepted",
+          "url": "localhost/invite/4",
+        }
+      }
       key="4-4"
-    >
-      <td>
-        invitee-4@test.com
-      </td>
-      <td>
-        invitee-4
-      </td>
-      <td
-        className="text-right"
-      >
-        <button
-          className="btn btn-inverse btn-mini"
-          onClick={[Function]}
-        >
-          <textarea
-            readOnly={true}
-            style={
-              Object {
-                "position": "absolute",
-                "right": -1000,
-              }
-            }
-            value="localhost/invite/$4"
-          />
-          <i
-            className="fa fa-clipboard"
-          />
-           Copy Invite
-        </button>
-         
-      </td>
-      <td>
-        <button
-          className="btn btn-danger btn-mini"
-          onClick={[Function]}
-        >
-          <i
-            className="fa fa-remove"
-          />
-        </button>
-      </td>
-    </tr>
-    <tr
+    />
+    <Connect(InviteeRow)
+      invitee={
+        Object {
+          "code": "asdfasdfsadf-5",
+          "createdOn": "2018-10-02",
+          "email": "invitee-5@test.com",
+          "emailSent": true,
+          "emailSentOn": "2018-10-02",
+          "id": 5,
+          "invitedByEmail": "admin@grafana.com",
+          "invitedByLogin": "admin",
+          "invitedByName": "admin",
+          "name": "invitee-5",
+          "orgId": 1,
+          "role": "viewer",
+          "status": "not accepted",
+          "url": "localhost/invite/5",
+        }
+      }
       key="5-5"
-    >
-      <td>
-        invitee-5@test.com
-      </td>
-      <td>
-        invitee-5
-      </td>
-      <td
-        className="text-right"
-      >
-        <button
-          className="btn btn-inverse btn-mini"
-          onClick={[Function]}
-        >
-          <textarea
-            readOnly={true}
-            style={
-              Object {
-                "position": "absolute",
-                "right": -1000,
-              }
-            }
-            value="localhost/invite/$5"
-          />
-          <i
-            className="fa fa-clipboard"
-          />
-           Copy Invite
-        </button>
-         
-      </td>
-      <td>
-        <button
-          className="btn btn-danger btn-mini"
-          onClick={[Function]}
-        >
-          <i
-            className="fa fa-remove"
-          />
-        </button>
-      </td>
-    </tr>
+    />
   </tbody>
 </table>
 `;

+ 14 - 17
public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.ts

@@ -2,21 +2,6 @@ import angular from 'angular';
 import coreModule from 'app/core/core_module';
 import _ from 'lodash';
 
-export class CloudWatchQueryParameter {
-  constructor() {
-    return {
-      templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/query.parameter.html',
-      controller: 'CloudWatchQueryParameterCtrl',
-      restrict: 'E',
-      scope: {
-        target: '=',
-        datasource: '=',
-        onChange: '&',
-      },
-    };
-  }
-}
-
 export class CloudWatchQueryParameterCtrl {
   /** @ngInject */
   constructor($scope, templateSrv, uiSegmentSrv, datasourceSrv, $q) {
@@ -240,5 +225,17 @@ export class CloudWatchQueryParameterCtrl {
   }
 }
 
-coreModule.directive('cloudwatchQueryParameter', CloudWatchQueryParameter);
-coreModule.controller('CloudWatchQueryParameterCtrl', CloudWatchQueryParameterCtrl);
+export function cloudWatchQueryParameter() {
+  return {
+    templateUrl: 'public/app/plugins/datasource/cloudwatch/partials/query.parameter.html',
+    controller: CloudWatchQueryParameterCtrl,
+    restrict: 'E',
+    scope: {
+      target: '=',
+      datasource: '=',
+      onChange: '&',
+    },
+  };
+}
+
+coreModule.directive('cloudwatchQueryParameter', cloudWatchQueryParameter);

+ 8 - 1
public/app/plugins/datasource/elasticsearch/query_builder.ts

@@ -270,7 +270,14 @@ export class ElasticQueryBuilder {
 
       if (queryDef.isPipelineAgg(metric.type)) {
         if (metric.pipelineAgg && /^\d*$/.test(metric.pipelineAgg)) {
-          metricAgg = { buckets_path: metric.pipelineAgg };
+          const appliedAgg = queryDef.findMetricById(target.metrics, metric.pipelineAgg);
+          if (appliedAgg) {
+            if (appliedAgg.type === 'count') {
+              metricAgg = { buckets_path: '_count' };
+            } else {
+              metricAgg = { buckets_path: metric.pipelineAgg };
+            }
+          }
         } else {
           continue;
         }

+ 7 - 0
public/app/plugins/datasource/elasticsearch/query_def.ts

@@ -213,6 +213,9 @@ export function describeOrder(order) {
 
 export function describeMetric(metric) {
   const def = _.find(metricAggTypes, { value: metric.type });
+  if (!def.requiresField && !isPipelineAgg(metric.type)) {
+    return def.text;
+  }
   return def.text + ' ' + metric.field;
 }
 
@@ -236,3 +239,7 @@ export function defaultMetricAgg() {
 export function defaultBucketAgg() {
   return { type: 'date_histogram', id: '2', settings: { interval: 'auto' } };
 }
+
+export const findMetricById = (metrics: any[], id: any) => {
+  return _.find(metrics, { id: id });
+};

+ 49 - 0
public/app/plugins/datasource/elasticsearch/specs/query_builder.test.ts

@@ -250,6 +250,31 @@ describe('ElasticQueryBuilder', () => {
     expect(firstLevel.aggs['2'].moving_avg.buckets_path).toBe('3');
   });
 
+  it('with moving average doc count', () => {
+    const query = builder.build({
+      metrics: [
+        {
+          id: '3',
+          type: 'count',
+          field: 'select field',
+        },
+        {
+          id: '2',
+          type: 'moving_avg',
+          field: '3',
+          pipelineAgg: '3',
+        },
+      ],
+      bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '4' }],
+    });
+
+    const firstLevel = query.aggs['4'];
+
+    expect(firstLevel.aggs['2']).not.toBe(undefined);
+    expect(firstLevel.aggs['2'].moving_avg).not.toBe(undefined);
+    expect(firstLevel.aggs['2'].moving_avg.buckets_path).toBe('_count');
+  });
+
   it('with broken moving average', () => {
     const query = builder.build({
       metrics: [
@@ -304,6 +329,30 @@ describe('ElasticQueryBuilder', () => {
     expect(firstLevel.aggs['2'].derivative.buckets_path).toBe('3');
   });
 
+  it('with derivative doc count', () => {
+    const query = builder.build({
+      metrics: [
+        {
+          id: '3',
+          type: 'count',
+          field: 'select field',
+        },
+        {
+          id: '2',
+          type: 'derivative',
+          pipelineAgg: '3',
+        },
+      ],
+      bucketAggs: [{ type: 'date_histogram', field: '@timestamp', id: '4' }],
+    });
+
+    const firstLevel = query.aggs['4'];
+
+    expect(firstLevel.aggs['2']).not.toBe(undefined);
+    expect(firstLevel.aggs['2'].derivative).not.toBe(undefined);
+    expect(firstLevel.aggs['2'].derivative.buckets_path).toBe('_count');
+  });
+
   it('with histogram', () => {
     const query = builder.build({
       metrics: [{ id: '1', type: 'count' }],

+ 92 - 192
public/app/plugins/datasource/loki/img/loki_icon.svg

@@ -2,7 +2,8 @@
 <!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 width="200px" height="200px" viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
+	 width="264.2px" height="318px" viewBox="-181.1 -67 264.2 318" style="enable-background:new -181.1 -67 264.2 318;"
+	 xml:space="preserve">
 <style type="text/css">
 	.st0{fill:url(#SVGID_1_);}
 	.st1{fill:url(#SVGID_2_);}
@@ -19,198 +20,97 @@
 	.st12{fill:url(#SVGID_13_);}
 	.st13{fill:url(#SVGID_14_);}
 	.st14{fill:url(#SVGID_15_);}
-	.st15{fill:url(#SVGID_16_);}
-	.st16{fill:url(#SVGID_17_);}
-	.st17{fill:url(#SVGID_18_);}
-	.st18{fill:url(#SVGID_19_);}
-	.st19{fill:url(#SVGID_20_);}
-	.st20{fill:url(#SVGID_21_);}
-	.st21{fill:url(#SVGID_22_);}
-	.st22{fill:url(#SVGID_23_);}
-	.st23{fill:url(#SVGID_24_);}
-	.st24{fill:url(#SVGID_25_);}
-	.st25{fill:url(#SVGID_26_);}
-	.st26{fill:url(#SVGID_27_);}
-	.st27{fill:url(#SVGID_28_);}
-	.st28{fill:url(#SVGID_29_);}
-	.st29{fill:url(#SVGID_30_);}
-	.st30{fill:url(#SVGID_31_);}
-	.st31{fill:url(#SVGID_32_);}
 </style>
 <g>
-	<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="135.0285" y1="238.7858" x2="135.0285" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st0" d="M179.5,130c-6.9-9.5-18.6-16.1-30.2-17.9l-38.1-4.6l0,22.4l34.7,4c5.8,0.9,12.3,4.3,15.8,9.1
-		c3.5,4.7,4.9,10.5,4,16.3c-1.7,10.8-11,18.5-21.6,18.5c-1.1,0-2.3-0.1-3.4-0.3l-37.9-4.7c-5.1,8-12.2,14.7-20.6,19.2l55.2,7.4
-		c2.3,0.4,4.6,0.5,6.8,0.5c21.3,0,40-15.6,43.4-37.3C189.3,151.1,186.4,139.5,179.5,130z"/>
-	<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="56.0866" y1="238.7858" x2="56.0866" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st1" d="M90.5,171c1.3-1.6,2.4-3.3,3.5-5.1c1-1.7,1.9-3.4,2.7-5.2c2.3-5.3,3.5-11.2,3.5-17.3l0-4l0-5.6l0-5.6l0-22.4
-		l0-5.6l0-5.6L100,43.9C100,19.7,80.2,0,55.9,0S12,19.8,12,44.1l0.1,66.7c5.7-7.6,13.3-13.7,22.1-17.6L34.1,44
-		c0-12.1,9.8-21.9,21.8-21.9c12.1,0,21.9,9.8,21.9,21.8L78,91.2l0,5.6l0,5.6l0,22.4l0,5.6l0,5.6l0,7.5c0,5.2-1.8,9.9-4.8,13.7
-		c-1.5,1.9-3.3,3.5-5.3,4.8c-3.4,2.2-7.4,3.5-11.7,3.5c-0.7,0-1.4,0-2,0l-1.4-0.2c-10.8-1.7-18.6-11.1-18.5-21.8
-		c0-1.1,0.1-2.1,0.2-3.2c0.7-4.3,2.6-8.1,5.3-11.1c1.6-1.8,3.5-3.3,5.5-4.5c3.2-1.8,6.9-2.9,10.8-2.9c1.1,0,2.3,0.1,3.4,0.3l7.5,1.2
-		l0-22.4l-4-0.6c-2.3-0.4-4.6-0.5-6.8-0.5c-3.7,0-7.3,0.5-10.8,1.4c-1.9,0.5-3.7,1.1-5.5,1.8c-1.9,0.8-3.8,1.7-5.5,2.7
-		c-11.2,6.4-19.4,17.7-21.6,31.4c-0.4,2.4-0.5,4.9-0.5,7.3c0,1.2,0.1,2.3,0.2,3.5c0,0.3,0.1,0.6,0.1,0.9c0.1,1.1,0.3,2.3,0.5,3.4
-		c0.1,0.3,0.1,0.7,0.2,1c0.2,1.1,0.5,2.1,0.8,3.2c0.1,0.4,0.2,0.7,0.3,1.1c0.3,1,0.7,2,1.1,3c0.1,0.3,0.3,0.7,0.4,1
-		c0.4,1,0.9,1.9,1.4,2.9c0.2,0.3,0.3,0.6,0.5,0.9c0.5,1,1.1,1.9,1.7,2.8c0.2,0.2,0.3,0.5,0.5,0.7c0.7,1,1.4,1.9,2.1,2.9
-		c0.1,0.1,0.2,0.3,0.4,0.4c0.8,1,1.7,1.9,2.6,2.8c0.1,0.1,0.1,0.1,0.2,0.2c1,1,2,1.9,3,2.7c0,0,0.1,0,0.1,0.1
-		c1.1,0.9,2.2,1.7,3.3,2.5c0,0,0,0,0.1,0.1c1.1,0.8,2.3,1.5,3.5,2.1c0.1,0,0.1,0.1,0.2,0.1c1.1,0.6,2.3,1.2,3.5,1.7
-		c0.2,0.1,0.3,0.1,0.5,0.2c1.1,0.5,2.2,0.9,3.3,1.2c0.3,0.1,0.6,0.2,0.9,0.3c1,0.3,2.1,0.6,3.2,0.8c0.4,0.1,0.8,0.2,1.2,0.2
-		c2.7,0.5,5.5,0.8,8.3,0.8C70.1,187.5,82.4,181.1,90.5,171z"/>
-	<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="26.7057" y1="238.7858" x2="26.7057" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st2" d="M28.2,177.5c-1-0.9-2-1.8-3-2.7"/>
-	<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="12.7354" y1="238.7858" x2="12.7354" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st3" d="M13,151.9c-0.2-1.1-0.4-2.2-0.5-3.4"/>
-	<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="14.8849" y1="238.7858" x2="14.8849" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st4" d="M15.4,160.1c-0.4-1-0.8-2-1.1-3"/>
-	<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="18.6023" y1="238.7858" x2="18.6023" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st5" d="M19.5,167.8c-0.6-0.9-1.2-1.9-1.7-2.8"/>
-	<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="16.5561" y1="238.7858" x2="16.5561" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st6" d="M17.2,164c-0.5-0.9-1-1.9-1.4-2.9"/>
-	<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="12.2907" y1="238.7858" x2="12.2907" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st7" d="M12.2,144.1c0,1.2,0.1,2.3,0.2,3.5"/>
-	<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="23.7117" y1="238.7858" x2="23.7117" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st8" d="M25,174.6c-0.9-0.9-1.8-1.9-2.6-2.8"/>
-	<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="20.9974" y1="238.7858" x2="20.9974" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st9" d="M22.1,171.3c-0.8-0.9-1.5-1.9-2.1-2.9"/>
-	<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="13.6059" y1="238.7858" x2="13.6059" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st10" d="M14,156.1c-0.3-1-0.6-2.1-0.8-3.2"/>
-	<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="37.1094" y1="238.7858" x2="37.1094" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st11" d="M38.8,184c-1.2-0.5-2.3-1.1-3.5-1.7"/>
-	<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="45.1619" y1="238.7858" x2="45.1619" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st12" d="M46.8,186.5c-1.1-0.2-2.1-0.5-3.2-0.8"/>
-	<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="29.9487" y1="238.7858" x2="29.9487" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st13" d="M31.6,180c-1.1-0.8-2.2-1.6-3.3-2.5"/>
-	<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="41.0239" y1="238.7858" x2="41.0239" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st14" d="M42.7,185.4c-1.1-0.4-2.3-0.8-3.3-1.2"/>
-	<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="33.4189" y1="238.7858" x2="33.4189" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st15" d="M35.2,182.2c-1.2-0.7-2.4-1.4-3.5-2.1"/>
-	<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="53.9595" y1="238.7858" x2="53.9595" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st16" d="M54.1,154.2c-0.1,0-0.1,0-0.2-0.1"/>
-	<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="21.1405" y1="238.7858" x2="21.1405" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st17" d="M21.4,178.8c-0.2-0.2-0.3-0.3-0.5-0.5"/>
-	<linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="35.2646" y1="238.7858" x2="35.2646" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st18" d="M35.2,182.2c0.1,0,0.1,0.1,0.2,0.1"/>
-	<linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="39.0979" y1="238.7858" x2="39.0979" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st19" d="M39.3,184.2c-0.2-0.1-0.3-0.1-0.5-0.2"/>
-	<linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="31.6434" y1="238.7858" x2="31.6434" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st20" d="M31.7,180.1C31.7,180.1,31.6,180.1,31.7,180.1"/>
-	<linearGradient id="SVGID_22_" gradientUnits="userSpaceOnUse" x1="28.2485" y1="238.7858" x2="28.2485" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st21" d="M28.3,177.6C28.3,177.5,28.2,177.5,28.3,177.6"/>
-	<linearGradient id="SVGID_23_" gradientUnits="userSpaceOnUse" x1="43.1314" y1="238.7858" x2="43.1314" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st22" d="M43.6,185.7c-0.3-0.1-0.6-0.2-0.9-0.3"/>
-	<linearGradient id="SVGID_24_" gradientUnits="userSpaceOnUse" x1="47.3468" y1="238.7858" x2="47.3468" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st23" d="M46.8,186.5c0.4,0.1,0.8,0.2,1.2,0.2"/>
-	<linearGradient id="SVGID_25_" gradientUnits="userSpaceOnUse" x1="19.6975" y1="238.7858" x2="19.6975" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st24" d="M19.9,168.4c-0.2-0.2-0.3-0.5-0.5-0.7"/>
-	<linearGradient id="SVGID_26_" gradientUnits="userSpaceOnUse" x1="17.4923" y1="238.7858" x2="17.4923" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st25" d="M17.7,164.9c-0.2-0.3-0.3-0.6-0.5-0.9"/>
-	<linearGradient id="SVGID_27_" gradientUnits="userSpaceOnUse" x1="12.4278" y1="238.7858" x2="12.4278" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st26" d="M12.5,148.5c0-0.3-0.1-0.6-0.1-0.9"/>
-	<linearGradient id="SVGID_28_" gradientUnits="userSpaceOnUse" x1="13.0965" y1="238.7858" x2="13.0965" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st27" d="M13.2,152.9c-0.1-0.3-0.1-0.7-0.2-1"/>
-	<linearGradient id="SVGID_29_" gradientUnits="userSpaceOnUse" x1="14.1769" y1="238.7858" x2="14.1769" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st28" d="M14.3,157.1c-0.1-0.3-0.2-0.7-0.3-1.1"/>
-	<linearGradient id="SVGID_30_" gradientUnits="userSpaceOnUse" x1="15.6479" y1="238.7858" x2="15.6479" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st29" d="M15.9,161.1c-0.2-0.3-0.3-0.7-0.4-1"/>
-	<linearGradient id="SVGID_31_" gradientUnits="userSpaceOnUse" x1="22.2436" y1="238.7858" x2="22.2436" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st30" d="M22.4,171.7c-0.1-0.1-0.2-0.3-0.4-0.4"/>
-	<linearGradient id="SVGID_32_" gradientUnits="userSpaceOnUse" x1="25.1051" y1="238.7858" x2="25.1051" y2="2.4079">
-		<stop  offset="0" style="stop-color:#FBED1D"/>
-		<stop  offset="1" style="stop-color:#F05A2A"/>
-	</linearGradient>
-	<path class="st31" d="M25.2,174.8c-0.1-0.1-0.1-0.1-0.2-0.2"/>
+	
+		<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="342.6804" y1="897.3058" x2="342.6804" y2="547.4434" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st0" points="-127.3,-58.2 -127.5,-59.1 -128.3,-58.9 	"/>
+	
+		<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="295.8044" y1="887.3397" x2="295.8044" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st1" points="-108.3,219.3 -130.7,223.8 -126.2,246.3 -103.8,241.8 	"/>
+	
+		<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="442.4363" y1="887.3397" x2="442.4363" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st2" points="-27.8,190 71.3,170.1 66.8,147.7 -32.3,167.5 	"/>
+	
+		<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="367.5056" y1="887.3397" x2="367.5056" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st3" points="-67.5,174.6 -63,197 -40.5,192.5 -45,170.1 	"/>
+	
+		<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="331.6549" y1="887.3397" x2="331.6549" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st4" points="-68.6,234.7 -73.1,212.3 -95.6,216.8 -91.1,239.2 	"/>
+	
+		<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="295.8044" y1="887.3397" x2="295.8044" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st5" points="-133.3,211.1 -110.8,206.6 -115.3,184.2 -137.8,188.7 	"/>
+	
+		<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="442.4363" y1="887.3397" x2="442.4363" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st6" points="73.8,182.8 -25.3,202.7 -20.8,225.1 78.3,205.3 	"/>
+	
+		<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="367.5056" y1="887.3397" x2="367.5056" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st7" points="-60.4,209.7 -55.9,232.2 -33.5,227.7 -38,205.2 	"/>
+	
+		<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="331.6549" y1="887.3397" x2="331.6549" y2="537.4772" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st8" points="-98.1,204.1 -75.7,199.6 -80.2,177.1 -102.6,181.6 	"/>
+	
+		<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="289.1909" y1="880.5443" x2="289.1909" y2="548.7296" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st9" points="-140.3,176 -130.8,174.1 -166.8,-5.6 -176.3,-3.7 	"/>
+	
+		<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="302.4872" y1="889.7463" x2="302.4872" y2="533.4922" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st10" points="-127.3,173.4 -117.8,171.5 -156.4,-21.4 -165.9,-19.5 	"/>
+	
+		<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="325.1889" y1="908.8145" x2="325.1889" y2="501.9178" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st11" points="-105,168.9 -95.5,167 -139.7,-53.3 -149.2,-51.4 	"/>
+	
+		<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="338.4852" y1="896.2529" x2="338.4852" y2="522.7181" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st12" points="-92,166.3 -82.5,164.4 -123,-37.9 -132.5,-36 	"/>
+	
+		<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="360.8988" y1="870.7903" x2="360.8988" y2="564.8808" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st13" points="-70,161.9 -60.5,160 -93.7,-5.7 -103.2,-3.8 	"/>
+	
+		<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="374.1951" y1="875.2039" x2="374.1951" y2="557.5726" gradientTransform="matrix(0.9805 -0.1964 0.1964 0.9805 -567.5302 -509.0906)">
+		<stop  offset="0" style="stop-color:#F9EC1C"/>
+		<stop  offset="1" style="stop-color:#F05A2B"/>
+	</linearGradient>
+	<polygon class="st14" points="-57,159.3 -47.5,157.4 -81.9,-14.6 -91.4,-12.7 	"/>
 </g>
 </svg>

+ 4 - 5
public/app/plugins/panel/gauge/MappingRow.tsx

@@ -1,6 +1,6 @@
 import React, { PureComponent } from 'react';
 import { Label } from 'app/core/components/Label/Label';
-import SimplePicker from 'app/core/components/Picker/SimplePicker';
+import { Select } from 'app/core/components/Select/Select';
 import { MappingType, RangeMap, ValueMap } from 'app/types';
 
 interface Props {
@@ -135,13 +135,12 @@ export default class MappingRow extends PureComponent<Props, State> {
       <div className="mapping-row">
         <div className="gf-form-inline mapping-row-type">
           <Label width={5}>Type</Label>
-          <SimplePicker
+          <Select
             placeholder="Choose type"
+            isSearchable={false}
             options={mappingOptions}
             value={mappingOptions.find(o => o.value === type)}
-            getOptionLabel={i => i.label}
-            getOptionValue={i => i.value}
-            onSelected={type => this.onMappingTypeChange(type.value)}
+            onChange={type => this.onMappingTypeChange(type.value)}
             width={7}
           />
         </div>

+ 16 - 18
public/app/plugins/panel/gauge/ValueOptions.tsx

@@ -1,21 +1,21 @@
 import React, { PureComponent } from 'react';
 import { Label } from 'app/core/components/Label/Label';
-import SimplePicker from 'app/core/components/Picker/SimplePicker';
-import UnitPicker from 'app/core/components/Picker/Unit/UnitPicker';
+import Select from 'app/core/components/Select/Select';
+import UnitPicker from 'app/core/components/Select/UnitPicker';
 import { OptionModuleProps } from './module';
 
 const statOptions = [
-  { value: 'min', text: 'Min' },
-  { value: 'max', text: 'Max' },
-  { value: 'avg', text: 'Average' },
-  { value: 'current', text: 'Current' },
-  { value: 'total', text: 'Total' },
-  { value: 'name', text: 'Name' },
-  { value: 'first', text: 'First' },
-  { value: 'delta', text: 'Delta' },
-  { value: 'diff', text: 'Difference' },
-  { value: 'range', text: 'Range' },
-  { value: 'last_time', text: 'Time of last point' },
+  { value: 'min', label: 'Min' },
+  { value: 'max', label: 'Max' },
+  { value: 'avg', label: 'Average' },
+  { value: 'current', label: 'Current' },
+  { value: 'total', label: 'Total' },
+  { value: 'name', label: 'Name' },
+  { value: 'first', label: 'First' },
+  { value: 'delta', label: 'Delta' },
+  { value: 'diff', label: 'Difference' },
+  { value: 'range', label: 'Range' },
+  { value: 'last_time', label: 'Time of last point' },
 ];
 
 const labelWidth = 6;
@@ -43,18 +43,16 @@ export default class ValueOptions extends PureComponent<OptionModuleProps> {
         <h5 className="page-heading">Value</h5>
         <div className="gf-form-inline">
           <Label width={labelWidth}>Stat</Label>
-          <SimplePicker
+          <Select
             width={12}
             options={statOptions}
-            getOptionLabel={i => i.text}
-            getOptionValue={i => i.value}
-            onSelected={this.onStatChange}
+            onChange={this.onStatChange}
             value={statOptions.find(option => option.value === stat)}
           />
         </div>
         <div className="gf-form-inline">
           <Label width={labelWidth}>Unit</Label>
-          <UnitPicker defaultValue={unit} onSelected={value => this.onUnitChange(value)} />
+          <UnitPicker defaultValue={unit} onChange={this.onUnitChange} />
         </div>
         <div className="gf-form-inline">
           <Label width={labelWidth}>Decimals</Label>

+ 6 - 6
public/app/plugins/panel/graph/tab_display.html

@@ -22,10 +22,10 @@
 			</div>
 			<gf-form-switch ng-disabled="!ctrl.panel.lines" class="gf-form" label="Staircase" label-class="width-8" checked="ctrl.panel.steppedLine" on-change="ctrl.render()">
 			</gf-form-switch>
-			<div class="gf-form">
+			<div class="gf-form" ng-if="ctrl.panel.points">
 				<label class="gf-form-label width-8">Point Radius</label>
 				<div class="gf-form-select-wrapper max-width-5">
-					<select class="gf-form-input" ng-model="ctrl.panel.pointradius" ng-options="f for f in [0.5,1,2,3,4,5,6,7,8,9,10]" ng-change="ctrl.render()" ng-disabled="!ctrl.panel.points"></select>
+					<select class="gf-form-input" ng-model="ctrl.panel.pointradius" ng-options="f for f in [0.5,1,2,3,4,5,6,7,8,9,10]" ng-change="ctrl.render()"></select>
 				</div>
 			</div>
 		</div>
@@ -66,7 +66,7 @@
 		</div>
 	</div>
 
-		<div class="gf-form-group">
+		<div>
 			<div class="gf-form-inline" ng-repeat="override in ctrl.panel.seriesOverrides" ng-controller="SeriesOverridesCtrl">
 				<div class="gf-form">
 					<label class="gf-form-label">alias or regex</label>
@@ -85,16 +85,16 @@
 						</span>
 					</label>
 				</div>
-	
+
 				<div class="gf-form">
 					<span class="dropdown" dropdown-typeahead="overrideMenu" dropdown-typeahead-on-select="setOverride($item, $subItem)">
 					</span>
 				</div>
-	
+
 				<div class="gf-form gf-form--grow">
 					<div class="gf-form-label gf-form-label--grow"></div>
 				</div>
-	
+
 				<div class="gf-form">
 					<label class="gf-form-label">
 						<i class="fa fa-trash pointer" ng-click="ctrl.removeSeriesOverride(override)"></i>

+ 10 - 10
public/app/plugins/panel/table/column_options.html

@@ -3,51 +3,51 @@
     <h5 class="section-heading">Options</h5>
     <div class="gf-form-inline">
       <div class="gf-form">
-        <label class="gf-form-label width-13">Apply to columns named</label>
+        <label class="gf-form-label width-12">Apply to columns named</label>
         <input type="text" placeholder="Name or regex" class="gf-form-input width-13" ng-model="style.pattern" bs-tooltip="'Specify regex using /my.*regex/ syntax'"
             bs-typeahead="editor.getColumnNames" ng-blur="editor.render()" data-min-length=0 data-items=100 ng-model-onblur
             data-placement="right">
       </div>
     </div>
     <div class="gf-form" ng-if="style.type !== 'hidden'">
-      <label class="gf-form-label width-13">Column Header</label>
-      <input type="text" class="gf-form-input width-13" ng-model="style.alias" ng-change="editor.render()" ng-model-onblur placeholder="Override header label">
+      <label class="gf-form-label width-12">Column Header</label>
+      <input type="text" class="gf-form-input width-12" ng-model="style.alias" ng-change="editor.render()" ng-model-onblur placeholder="Override header label">
     </div>
-    <gf-form-switch class="gf-form" label-class="width-13" label="Render value as link" checked="style.link" change="editor.render()"></gf-form-switch>
+    <gf-form-switch class="gf-form" label-class="width-12" label="Render value as link" checked="style.link" change="editor.render()"></gf-form-switch>
   </div>
 
   <div class="section gf-form-group">
     <h5 class="section-heading">Type</h5>
 
     <div class="gf-form">
-      <label class="gf-form-label width-11">Type</label>
+      <label class="gf-form-label width-10">Type</label>
       <div class="gf-form-select-wrapper width-16">
         <select class="gf-form-input" ng-model="style.type" ng-options="c.value as c.text for c in editor.columnTypes" ng-change="editor.render()"></select>
       </div>
     </div>
     <div class="gf-form" ng-if="style.type === 'date'">
-      <label class="gf-form-label width-11">Date Format</label>
+      <label class="gf-form-label width-10">Date Format</label>
       <gf-form-dropdown model="style.dateFormat" css-class="gf-form-input width-16" lookup-text="true"
         	get-options="editor.dateFormats" on-change="editor.render()" allow-custom="true">
       </gf-form-dropdown>
     </div>
 
     <div ng-if="style.type === 'string'">
-      <gf-form-switch class="gf-form" label-class="width-11" ng-if="style.type === 'string'" label="Sanitize HTML" checked="style.sanitize"
+      <gf-form-switch class="gf-form" label-class="width-10" ng-if="style.type === 'string'" label="Sanitize HTML" checked="style.sanitize"
           change="editor.render()"></gf-form-switch>
     </div>
     <div ng-if="style.type === 'string'">
-      <gf-form-switch class="gf-form" label-class="width-11" ng-if="style.type === 'string'" label="Preserve Formatting" checked="style.preserveFormat"
+      <gf-form-switch class="gf-form" label-class="width-10" ng-if="style.type === 'string'" label="Preserve Formatting" checked="style.preserveFormat"
           change="editor.render()"></gf-form-switch>
     </div>
 
     <div ng-if="style.type === 'number'">
       <div class="gf-form">
-        <label class="gf-form-label width-11">Unit</label>
+        <label class="gf-form-label width-10">Unit</label>
         <div class="gf-form-dropdown-typeahead width-16" ng-model="style.unit" dropdown-typeahead2="editor.unitFormats" dropdown-typeahead-on-select="editor.setUnitFormat(style, $subItem)"></div>
       </div>
       <div class="gf-form">
-        <label class="gf-form-label width-11">Decimals</label>
+        <label class="gf-form-label width-10">Decimals</label>
         <input type="number" class="gf-form-input width-4" data-placement="right" ng-model="style.decimals" ng-change="editor.render()"
             ng-model-onblur>
       </div>

+ 7 - 15
public/app/plugins/panel/text/editor.html

@@ -1,23 +1,15 @@
-<div class="gf-form-group">
-	<div class="gf-form-inline">
-		<div class="gf-form">
-			<span class="gf-form-label">Mode</span>
-			<span class="gf-form-select-wrapper">
-				<select class="gf-form-input" ng-model="ctrl.panel.mode" ng-options="f for f in ['html','markdown']"></select>
-			</span>
-		</div>
+<div class="gf-form-inline">
+	<div class="gf-form">
+		<span class="gf-form-label">Mode</span>
+		<span class="gf-form-select-wrapper">
+			<select class="gf-form-input" ng-model="ctrl.panel.mode" ng-options="f for f in ['html','markdown']"></select>
+		</span>
 	</div>
 </div>
 
-<h3 class="page-heading">Content</h3>
-
-<span ng-show="ctrl.panel.mode == 'markdown'">
-	(This area uses <a target="_blank" href="http://en.wikipedia.org/wiki/Markdown">Markdown</a>. HTML is not supported)
-</span>
-
 <div class="gf-form-inline">
 	<div class="gf-form gf-form--grow">
-		<code-editor content="ctrl.panel.content" on-change="ctrl.render()" data-mode="markdown" data-max-lines=20 code-editor-focus="true">
+		<code-editor content="ctrl.panel.content" on-change="ctrl.render()" data-mode="markdown" data-max-lines=20>
 		</code-editor>
 	</div>
 </div>

Some files were not shown because too many files changed in this diff