Browse Source

Merge branch 'master' into piechart-react

corpglory-dev 6 years ago
parent
commit
e842e86e2a
100 changed files with 1746 additions and 204 deletions
  1. 6 0
      .gitignore
  2. 11 1
      CHANGELOG.md
  3. 5 5
      README.md
  4. 3 0
      conf/defaults.ini
  5. 3 0
      conf/sample.ini
  6. 5 4
      docs/sources/alerting/rules.md
  7. 271 0
      docs/sources/features/datasources/azuremonitor.md
  8. 4 4
      docs/sources/features/datasources/cloudwatch.md
  9. 8 5
      docs/sources/features/datasources/index.md
  10. 1 1
      docs/sources/features/datasources/influxdb.md
  11. 1 1
      docs/sources/features/datasources/loki.md
  12. 1 1
      docs/sources/features/datasources/opentsdb.md
  13. 1 1
      docs/sources/features/datasources/prometheus.md
  14. 4 4
      docs/sources/features/datasources/stackdriver.md
  15. 5 5
      docs/sources/guides/whats-new-in-v6-0.md
  16. 13 5
      docs/sources/index.md
  17. 3 3
      docs/sources/project/building_from_source.md
  18. 2 2
      latest.json
  19. 20 3
      package.json
  20. 6 0
      packages/grafana-ui/CHANGELOG.md
  21. 16 2
      packages/grafana-ui/README.md
  22. 7 0
      packages/grafana-ui/index.js
  23. 17 3
      packages/grafana-ui/package.json
  24. 54 0
      packages/grafana-ui/rollup.config.ts
  25. 2 2
      packages/grafana-ui/src/components/ColorPicker/ColorInput.tsx
  26. 2 23
      packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx
  27. 1 1
      packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.test.tsx
  28. 17 3
      packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx
  29. 2 1
      packages/grafana-ui/src/components/ColorPicker/NamedColorsGroup.tsx
  30. 1 2
      packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx
  31. 9 0
      packages/grafana-ui/src/components/ColorPicker/warnAboutColorPickerPropsDeprecation.ts
  32. 6 6
      packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx
  33. 8 1
      packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss
  34. 1 1
      packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap
  35. 1 1
      packages/grafana-ui/src/components/FormField/FormField.tsx
  36. 6 6
      packages/grafana-ui/src/components/Gauge/Gauge.tsx
  37. 1 1
      packages/grafana-ui/src/components/Select/Select.tsx
  38. 2 2
      packages/grafana-ui/src/components/Switch/Switch.tsx
  39. 1 1
      packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx
  40. 3 1
      packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx
  41. 1 1
      packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx
  42. 1 1
      packages/grafana-ui/src/components/ValueMappingsEditor/_ValueMappingsEditor.scss
  43. 0 1
      packages/grafana-ui/src/index.ts
  44. 2 2
      packages/grafana-ui/src/themes/ThemeContext.tsx
  45. 396 0
      packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts
  46. 383 0
      packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts
  47. 265 0
      packages/grafana-ui/src/themes/_variables.scss.tmpl.ts
  48. 27 18
      packages/grafana-ui/src/themes/dark.ts
  49. 6 5
      packages/grafana-ui/src/themes/default.ts
  50. 15 0
      packages/grafana-ui/src/themes/getTheme.ts
  51. 3 13
      packages/grafana-ui/src/themes/index.ts
  52. 22 13
      packages/grafana-ui/src/themes/light.ts
  53. 17 5
      packages/grafana-ui/src/types/theme.ts
  54. 12 8
      packages/grafana-ui/src/utils/colors.ts
  55. 10 0
      packages/grafana-ui/src/utils/generatedFileBanner.ts
  56. 1 0
      packages/grafana-ui/src/utils/index.ts
  57. 2 2
      packages/grafana-ui/src/utils/namedColorsPalette.ts
  58. 2 2
      packages/grafana-ui/src/utils/processTimeSeries.ts
  59. 1 1
      packages/grafana-ui/src/utils/storybook/withTheme.tsx
  60. 12 0
      packages/grafana-ui/tsconfig.build.json
  61. 4 2
      packages/grafana-ui/tsconfig.json
  62. 1 1
      pkg/api/admin_users.go
  63. 1 1
      pkg/api/dashboard.go
  64. 1 1
      pkg/api/dashboard_snapshot.go
  65. 1 1
      pkg/api/dataproxy.go
  66. 1 0
      pkg/api/frontendsettings.go
  67. 1 1
      pkg/api/login.go
  68. 2 2
      pkg/api/login_oauth.go
  69. 1 1
      pkg/api/org.go
  70. 1 1
      pkg/api/org_invite.go
  71. 1 1
      pkg/api/search.go
  72. 1 1
      pkg/api/signup.go
  73. 1 1
      pkg/api/user.go
  74. 1 1
      pkg/cmd/grafana-server/main.go
  75. 3 3
      pkg/cmd/grafana-server/server.go
  76. 0 0
      pkg/infra/metrics/graphitebridge/graphite.go
  77. 0 0
      pkg/infra/metrics/graphitebridge/graphite_test.go
  78. 0 0
      pkg/infra/metrics/metrics.go
  79. 1 1
      pkg/infra/metrics/service.go
  80. 1 1
      pkg/infra/metrics/settings.go
  81. 0 0
      pkg/infra/tracing/tracing.go
  82. 0 0
      pkg/infra/tracing/tracing_test.go
  83. 1 1
      pkg/infra/usagestats/service.go
  84. 1 1
      pkg/infra/usagestats/usage_stats.go
  85. 0 0
      pkg/login/social/common.go
  86. 0 0
      pkg/login/social/generic_oauth.go
  87. 0 0
      pkg/login/social/github_oauth.go
  88. 0 0
      pkg/login/social/gitlab_oauth.go
  89. 0 0
      pkg/login/social/google_oauth.go
  90. 0 0
      pkg/login/social/grafana_com_oauth.go
  91. 0 0
      pkg/login/social/social.go
  92. 1 1
      pkg/middleware/request_metrics.go
  93. 1 1
      pkg/services/alerting/eval_handler.go
  94. 1 1
      pkg/services/alerting/notifier.go
  95. 1 1
      pkg/services/alerting/reader.go
  96. 1 1
      pkg/services/alerting/result_handler.go
  97. 1 1
      pkg/services/sqlstore/dashboard.go
  98. 1 1
      pkg/services/sqlstore/datasource.go
  99. 5 0
      pkg/setting/setting.go
  100. 1 1
      pkg/tsdb/cloudwatch/cloudwatch.go

+ 6 - 0
.gitignore

@@ -78,3 +78,9 @@ debug.test
 
 /scripts/build/release_publisher/release_publisher
 *.patch
+
+
+# Ignoring frontend packages specifics
+/packages/**/dist
+/packages/**/compiled
+/packages/**/.rpt2_cache

+ 11 - 1
CHANGELOG.md

@@ -1,4 +1,12 @@
-# 6.0.0-beta3 (unreleased)
+# 6.0.0 stable (2019-02-25)
+
+### Bug Fixes
+* **Stackdriver**: fix for float64 bounds for distribution metrics [#14509](https://github.com/grafana/grafana/issues/14509)
+* **Stackdriver**: no reducers available for distribution type [#15179](https://github.com/grafana/grafana/issues/15179)
+* **Dashboard**: fixes click after scroll in series override menu [#15621](https://github.com/grafana/grafana/issues/15621)
+* **MySQL**: fix mysql query using _interval_ms variable throws error [#14507](https://github.com/grafana/grafana/issues/14507)
+
+# 6.0.0-beta3 (2019-02-19)
 
 ### Minor
 * **CLI**: Grafana CLI should preserve permissions for backend binaries for Linux and Darwin [#15500](https://github.com/grafana/grafana/issues/15500)
@@ -30,6 +38,7 @@
 * **AzureMonitor**: improve autocomplete for Log Analytics and App Insights editor [#15131](https://github.com/grafana/grafana/issues/15131)
 * **LDAP**: Fix IPA/FreeIPA v4.6.4 does not allow LDAP searches with empty attributes [#14432](https://github.com/grafana/grafana/issues/14432)
 * **Provisioning**: Allow testing data sources that were added by config [#12164](https://github.com/grafana/grafana/issues/12164)
+* **Security**: Fix CSRF Token validation for POSTs [#1441](https://github.com/grafana/grafana/issues/1441)
 
 ### Breaking changes
 
@@ -53,6 +62,7 @@
 * **Snapshots**: Enable deletion of public snapshot [#14109](https://github.com/grafana/grafana/issues/14109)
 * **Provisioning**: Provisioning support for alert notifiers [#10487](https://github.com/grafana/grafana/issues/10487), thx [@pbakulev](https://github.com/pbakulev)
 * **Explore**: A whole new way to do ad-hoc metric queries and exploration. Split view in half and compare metrics & logs and much much more. [Read more here](http://docs.grafana.org/features/explore/)
+* **Auth**: Replace remember me cookie solution for Grafana's builtin, LDAP and OAuth authentication with a solution based on short-lived tokens [#15303](https://github.com/grafana/grafana/issues/15303)
 
 ### Minor
 

+ 5 - 5
README.md

@@ -9,7 +9,7 @@ Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB.
 
 ![](https://www.grafanacon.org/2019/images/grafanacon_la_nav-logo.png)
 
-Join us Feb 25-26 in Los Angeles, California for GrafanaCon - a two-day event with talks focused on Grafana and the surrounding open source monitoring ecosystem. Get deep dives into Loki, the Explore workflow and all of the new features of Grafana 6, plus participate in hands on workshops to help you get the most out of your data. 
+Join us Feb 25-26 in Los Angeles, California for GrafanaCon - a two-day event with talks focused on Grafana and the surrounding open source monitoring ecosystem. Get deep dives into Loki, the Explore workflow and all of the new features of Grafana 6, plus participate in hands on workshops to help you get the most out of your data.
 
 Time is running out - grab your ticket now! http://grafanacon.org
 
@@ -75,15 +75,15 @@ $GOPATH/bin/bra run
 Rebuild on file change, and serve them by Grafana's webserver (http://localhost:3000):
 
 ```bash
-yarn watch
+yarn start
 ```
 
 Build the assets, rebuild on file change with Hot Module Replacement (HMR), and serve them by webpack-dev-server (http://localhost:3333):
 
 ```bash
-yarn start
+yarn start:hot
 # OR set a theme
-env GRAFANA_THEME=light yarn start
+env GRAFANA_THEME=light yarn start:hot
 ```
 
 *Note: HMR for Angular is not supported. If you edit files in the Angular part of the app, the whole page will reload.*
@@ -158,7 +158,7 @@ GRAFANA_TEST_DB=postgres go test ./pkg/...
 
 If you have any ideas for improvement or have found a bug, do not hesitate to open an issue.
 And if you have time, clone this repo and submit a pull request to help me make Grafana
-the kickass metrics & devops dashboard we all dream about! 
+the kickass metrics & devops dashboard we all dream about!
 
 Read the [contributing](https://github.com/grafana/grafana/blob/master/CONTRIBUTING.md) guide then check the [`beginner friendly`](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22) label to find issues that are easy and that we would like help with.
 

+ 3 - 0
conf/defaults.ini

@@ -243,6 +243,9 @@ external_manage_info =
 # Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
 viewers_can_edit = false
 
+# Editors can administrate dashboard, folders and teams they create
+editors_can_own = false
+
 [auth]
 # Login cookie name
 login_cookie_name = grafana_session

+ 3 - 0
conf/sample.ini

@@ -223,6 +223,9 @@ log_queries =
 # Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
 ;viewers_can_edit = false
 
+# Editors can administrate dashboard, folders and teams they create
+;editors_can_own = false
+
 [auth]
 # Login cookie name
 ;login_cookie_name = grafana_session

+ 5 - 4
docs/sources/alerting/rules.md

@@ -27,9 +27,10 @@ and the conditions that need to be met for the alert to change state and trigger
 ## Execution
 
 The alert rules are evaluated in the Grafana backend in a scheduler and query execution engine that is part
-of core Grafana. Only some data sources are supported right now. They include `Graphite`, `Prometheus`, `Elasticsearch`, `InfluxDB`, `OpenTSDB`, `MySQL`, `Postgres` and `Cloudwatch`.
+of core Grafana. Only some data sources are supported right now. They include `Graphite`, `Prometheus`, `InfluxDB`, `Elasticsearch`,
+`Stackdriver`, `Cloudwatch`, `Azure Monitor`, `MySQL`, `PostgreSQL`, `MSSQL` and `OpenTSDB`.
 
-> Alerting support for Elasticsearch is only available in Grafana v5.2 and above.
+> Alerting support for Azure Monitor is only available in Grafana v6.0 and above.
 
 ### Clustering
 
@@ -52,9 +53,9 @@ Here you can specify the name of the alert rule and how often the scheduler shou
 
 > This setting is available in Grafana 5.4 and above.
 
-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. 
+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.
 
-Typically, it's always a good idea to use this setting since it's often worse to get false positive than wait a few minutes before the alert notification triggers. Looking at the `Alert list` or `Alert list panels` you will be able to see alerts in pending state. 
+Typically, it's always a good idea to use this setting since it's often worse to get false positive than wait a few minutes before the alert notification triggers. Looking at the `Alert list` or `Alert list panels` you will be able to see alerts in pending state.
 
 Below you can see an example timeline of an alert using the `For` setting. At ~16:04 the alert state changes to `Pending` and after 4 minutes it changes to `Alerting` which is when alert notifications are sent. Once the series falls back to normal the alert rule goes back to `OK`.
 {{< imgbox img="/img/docs/v54/alerting-for-dark-theme.png" caption="Alerting For" >}}

+ 271 - 0
docs/sources/features/datasources/azuremonitor.md

@@ -0,0 +1,271 @@
++++
+title = "Using Azure Monitor in Grafana"
+description = "Guide for using Azure Monitor in Grafana"
+keywords = ["grafana", "microsoft", "azure", "monitor", "application", "insights", "log", "analytics", "guide"]
+type = "docs"
+aliases = ["/datasources/azuremonitor"]
+[menu.docs]
+name = "Azure Monitor"
+parent = "datasources"
+weight = 5
++++
+
+# Using Azure Monitor in Grafana
+
+> Officially released in Grafana v6.0.0
+
+As of Grafana 6.0, the Azure Monitor plugin has been moved into Grafana so it now ships with built-in support for Azure Monitor.
+
+The Azure Monitor Datasource supports multiple services in the Azure cloud:
+
+- **[Azure Monitor]({{< relref "#querying-the-azure-monitor-service" >}})** is the platform service that provides a single source for monitoring Azure resources.
+- **[Application Insights]({{< relref "#querying-the-application-insights-service" >}})** is an extensible Application Performance Management (APM) service for web developers on multiple platforms and can be used to monitor your live web application - it will automatically detect performance anomalies.
+- **[Azure Log Analytics]({{< relref "#querying-the-azure-log-analytics-service" >}})** (or Azure Logs) gives you access to log data collected by Azure Monitor.
+- **[Application Insights Analytics]({{< relref "#writing-analytics-queries-for-the-application-insights-service" >}})** allows you to query [Application Insights data](https://docs.microsoft.com/en-us/azure/azure-monitor/app/analytics) using the same query language used for Azure Log Analytics.
+
+## Adding the data source to Grafana
+
+The datasource can access metrics from four different services. You can configure access to the services that you use. It is also possible to use the same credentials for multiple services if that is how you have set it up in Azure AD.
+
+- [Guide to setting up an Azure Active Directory Application for Azure Monitor.](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal)
+- [Guide to setting up an Azure Active Directory Application for Azure Log Analytics.](https://dev.loganalytics.io/documentation/Authorization/AAD-Setup)
+- [Quickstart Guide for Application Insights.](https://dev.applicationinsights.io/quickstart/)
+
+1. Accessed from the Grafana main menu, newly installed data sources can be added immediately within the Data Sources section. Next, click the  "Add data source" button in the upper right. The data source will be available for selection in the Type select box.
+
+2. Select Azure Monitor from the Type dropdown:<br/>
+![Data Source Type](https://raw.githubusercontent.com/grafana/azure-monitor-datasource/master/src/img/config_1_select_type.png)
+3. In the name field, fill in a name for the data source. It can be anything. Some suggestions are Azure Monitor or App Insights.
+
+4. If you are using Azure Monitor, then you need 4 pieces of information from the Azure portal (see link above for detailed instructions):
+    - **Tenant Id** (Azure Active Directory -> Properties -> Directory ID)
+    - **Subscription Id** (Subscriptions -> Choose subscription -> Overview -> Subscription ID)
+    - **Client Id** (Azure Active Directory -> App Registrations -> Choose your app -> Application ID)
+    - **Client Secret** ( Azure Active Directory -> App Registrations -> Choose your app -> Keys)
+
+5. Paste these four items into the fields in the Azure Monitor API Details section:<br/>
+![Azure Monitor API Details](https://raw.githubusercontent.com/grafana/azure-monitor-datasource/master/src/img/config_2_azure_monitor_api_details.png)
+
+6. If you are also using the Azure Log Analytics service, then you need to specify these two config values (or you can reuse the Client Id and Secret from the previous step).
+    - Client Id (Azure Active Directory -> App Registrations -> Choose your app -> Application ID)
+    - Client Secret ( Azure Active Directory -> App Registrations -> Choose your app -> Keys -> Create a key -> Use client secret)
+
+7. If you are are using  Application Insights, then you need two pieces of information from the Azure Portal (see link above for detailed instructions):
+    - Application ID
+    - API Key
+
+8. Paste these two items into the appropriate fields in the Application Insights API Details section:<br/>
+![Application Insights API Details](https://raw.githubusercontent.com/grafana/azure-monitor-datasource/master/src/img/config_3_app_insights_api_details.png)
+
+9. Test that the configuration details are correct by clicking on the "Save & Test" button:<br/>
+![Azure Monitor API Details](https://raw.githubusercontent.com/grafana/azure-monitor-datasource/master/src/img/config_4_save_and_test.png)
+
+Alternatively on step 4 if creating a new Azure Active Directory App, use the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest):
+
+```bash
+az ad sp create-for-rbac -n "http://localhost:3000"
+```
+
+## Choose a Service
+
+In the query editor for a panel, after choosing your Azure Monitor datasource, the first option is to choose a service. There are three options here: Azure Monitor, Application Insights and Azure Log Analytics. The query editor will change depending on which one you pick. Azure Monitor is the default.
+
+## Querying the Azure Monitor Service
+
+The Azure Monitor service provides metrics for all the Azure services that you have running. It helps you understand how your applications on Azure are performing and to proactively find issues affecting your applications.
+
+Examples of metrics that you can get from the service are:
+
+- Microsoft.Compute/virtualMachines - Percentage CPU
+- Microsoft.Network/networkInterfaces - Bytes sent
+- Microsoft.Storage/storageAccounts - Used Capacity
+
+{{< docs-imagebox img="/img/docs/v60/azuremonitor-service-query-editor.png" class="docs-image--no-shadow" caption="Azure Monitor Query Editor" >}}
+
+### Formatting Legend Keys with Aliases for the Azure Monitor Service
+
+The default legend formatting for the Azure Monitor API is:
+
+`resourceName{dimensionValue=dimensionName}.metricName`
+
+These can be quite long but this formatting can be changed using aliases. In the Legend Format field, the aliases which are defined below can be combined any way you want.
+
+Azure Monitor Examples:
+
+- `dimension: {{dimensionvalue}}`
+- `{{resourcegroup}} - {{resourcename}}`
+
+### Alias Patterns for Azure Monitor
+
+- `{{resourcegroup}}` = replaced with the value of the Resource Group
+- `{{namespace}}` = replaced with the value of the Namespace (e.g. Microsoft.Compute/virtualMachines)
+- `{{resourcename}}` = replaced with the value of the Resource Name
+- `{{metric}}` = replaced with metric name (e.g. Percentage CPU)
+- `{{dimensionname}}` = replaced with dimension key/label (e.g. blobtype)
+- `{{dimensionvalue}}` = replaced with dimension value (e.g. BlockBlob)
+
+### Templating with Variables for the Azure Monitor Service
+
+Instead of hard-coding things like server, application and sensor name in you metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns makes it easy to change the data being displayed in your dashboard.
+
+Note that the Azure Monitor service does not support multiple values yet. If you want to visualize multiple time series (for example, metrics for server1 and server2) then you have to add multiple queries to able to view them on the same graph or in the same table.
+
+The Azure Monitor Datasource Plugin provides the following queries you can specify in the `Query` field in the Variable edit view. They allow you to fill a variable's options list.
+
+| Name                                                     | Description                                                    |
+| -------------------------------------------------------- | -------------------------------------------------------------- |
+| *ResourceGroups()*                                       | Returns a list of resource groups.                             |
+| *Namespaces(aResourceGroup)*                             | Returns a list of namespaces for the specified resource group. |
+| *ResourceNames(aResourceGroup, aNamespace)*              | Returns a list of resource names.                              |
+| *MetricNames(aResourceGroup, aNamespace, aResourceName)* | Returns a list of metric names.                                |
+
+Examples:
+
+- Resource Groups query: `ResourceGroups()`
+- Passing in metric name variable: `Namespaces(cosmo)`
+- Chaining template variables: `ResourceNames($rg, $ns)`
+- Do not quote parameters: `MetricNames(hg, Microsoft.Network/publicIPAddresses, grafanaIP)`
+
+{{< docs-imagebox img="/img/docs/v60/azuremonitor-service-variables.png" class="docs-image--no-shadow" caption="Nested Azure Monitor Template Variables" >}}
+
+Checkout the [Templating]({{< relref "reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
+types of template variables.
+
+### Azure Monitor Metrics Whitelist
+
+Not all metrics returned by the Azure Monitor API have values. The Grafana datasource has a whitelist to only return metric names if it is possible they might have values. This whitelist is updated regularly as new services and metrics are added to the Azure cloud. You can find the current whitelist [here](https://github.com/grafana/grafana/blob/master/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/supported_namespaces.ts).
+
+### Azure Monitor Alerting
+
+Grafana alerting is supported for the Azure Monitor service. This is not Azure Alerts support. Read more about how alerting in Grafana works [here]({{< relref "alerting/rules.md" >}}).
+
+{{< docs-imagebox img="/img/docs/v60/azuremonitor-alerting.png" class="docs-image--no-shadow" caption="Azure Monitor Alerting" >}}
+
+## Querying the Application Insights Service
+
+{{< docs-imagebox img="/img/docs/v60/appinsights-service-query-editor.png" class="docs-image--no-shadow" caption="Application Insights Query Editor" >}}
+
+### Formatting Legend Keys with Aliases for the Application Insights Service
+
+The default legend formatting is:
+
+`metric/name{group/by="groupbyvalue"}`
+
+In the Legend Format field, the aliases which are defined below can be combined any way you want.
+
+Application Insights Examples:
+
+- `server: {{groupbyvalue}}`
+- `city: {{groupbyvalue}}`
+- `{{groupbyname}}: {{groupbyvalue}}`
+
+### Alias Patterns for Application Insights
+
+- `{{groupbyvalue}}` = replaced with the value of the group by
+- `{{groupbyname}}` = replaced with the name/label of the group by
+- `{{metric}}` = replaced with metric name (e.g. requests/count)
+
+### Filter Expressions for Application Insights
+
+The filter field takes an OData filter expression.
+
+Examples:
+
+- `client/city eq 'Boydton'`
+- `client/city ne 'Boydton'`
+- `client/city ne 'Boydton' and client/city ne 'Dublin'`
+- `client/city eq 'Boydton' or client/city eq 'Dublin'`
+
+### Templating with Variables for Application Insights
+
+Use the one of the following queries in the `Query` field in the Variable edit view.
+
+Checkout the [Templating]({{< relref "reference/templating.md" >}}) documentation for an introduction to the templating feature and the different
+types of template variables.
+
+| Name                               | Description                                                |
+| ---------------------------------- | ---------------------------------------------------------- |
+| *AppInsightsMetricNames()*         | Returns a list of metric names.                            |
+| *AppInsightsGroupBys(aMetricName)* | Returns a list of group bys for the specified metric name. |
+
+Examples:
+
+- Metric Names query: `AppInsightsMetricNames()`
+- Passing in metric name variable: `AppInsightsGroupBys(requests/count)`
+- Chaining template variables: `AppInsightsGroupBys($metricnames)`
+
+{{< docs-imagebox img="/img/docs/v60/appinsights-service-variables.png" class="docs-image--no-shadow" caption="Nested Application Insights Template Variables" >}}
+
+### Application Insights Alerting
+
+Not implemented yet.
+
+## Querying the Azure Log Analytics Service
+
+Queries are written in the new [Azure Log Analytics (or KustoDB) Query Language](https://docs.loganalytics.io/index). A Log Analytics Query can be formatted as Time Series data or as Table data.
+
+Time Series queries are for the Graph Panel (and other panels like the Single Stat panel) and must contain a datetime column, a metric name column and a value column. Here is an example query that returns the aggregated count grouped by the Category column and grouped by hour:
+
+```
+AzureActivity
+| where $__timeFilter(TimeGenerated)
+| summarize count() by Category, bin(TimeGenerated, 1h)
+| order by TimeGenerated asc
+```
+
+Table queries are mainly used in the Table panel and row a list of columns and rows. This example query returns rows with the 6 specified columns:
+
+```
+AzureActivity
+| where $__timeFilter()
+| project TimeGenerated, ResourceGroup, Category, OperationName, ActivityStatus, Caller
+| order by TimeGenerated desc
+```
+
+{{< docs-imagebox img="/img/docs/v60/azureloganalytics-service-query-editor.png" class="docs-image--no-shadow" caption="Azure Log Analytics Query Editor" >}}
+
+### Azure Log Analytics Macros
+
+To make writing queries easier there are several Grafana macros that can be used in the where clause of a query:
+
+- `$__timeFilter()` - Expands to
+    `TimeGenerated ≥ datetime(2018-06-05T18:09:58.907Z) and`
+    `TimeGenerated ≤ datetime(2018-06-05T20:09:58.907Z)` where the from and to datetimes are from the Grafana time picker.
+
+- `$__timeFilter(datetimeColumn)` - Expands to
+    `datetimeColumn  ≥ datetime(2018-06-05T18:09:58.907Z) and`
+    `datetimeColumn ≤ datetime(2018-06-05T20:09:58.907Z)` where the from and to datetimes are from the Grafana time picker.
+
+- `$__escapeMulti($myVar)` - is to be used with multi-value template variables that contains illegal characters. If $myVar has the value  `'\\grafana-vm\Network(eth0)\Total','\\hello!'`, it expands to: `@'\\grafana-vm\Network(eth0)\Total', @'\\hello!'`. If using single value variables there no need for this macro, simply escape the variable inline instead - `@'\$myVar'`
+
+- `$__contains(colName, $myVar)` - is to be used with multi-value template variables. If $myVar has the value `'value1','value2'`, it expands to: `colName in ('value1','value2')`.
+
+     If using the `All` option, then check the `Include All Option` checkbox and in the `Custom all value` field type in the following value: `all`. If $myVar has value `all` then the macro will instead expand to `1 == 1`. For template variables with a lot of options, this will increase the query performance by not building a large where..in clause.
+
+### Azure Log Analytics Builtin Variables
+
+There are also some Grafana variables that can be used in Azure Log Analytics queries:
+
+- `$__from` - Returns the From datetime from the Grafana picker. Example: `datetime(2018-06-05T18:09:58.907Z)`.
+- `$__to` - Returns the From datetime from the Grafana picker. Example: `datetime(2018-06-05T20:09:58.907Z)`.
+- `$__interval` - Grafana calculates the minimum time grain that can be used to group by time in queries. More details on how it works [here]({{< relref "reference/templating.md#interval-variables" >}}). It returns a time grain like `5m` or `1h` that can be used in the bin function. E.g. `summarize count() by bin(TimeGenerated, $__interval)`
+
+### Azure Log Analytics Alerting
+
+Not implemented yet.
+
+### Writing Analytics Queries For the Application Insights Service
+
+If you change the service type to "Application Insights", the menu icon to the right adds another option, "Toggle Edit Mode". Once clicked, the query edit mode changes to give you a full text area in which to write log analytics queries. (This is identical to how the InfluxDB datasource lets you write raw queries.)
+
+Once a query is written, the column names are automatically parsed out of the response data. You can then select them in the "X-axis", "Y-axis", and "Split On" dropdown menus, or just type them out.
+
+There are some important caveats to remember:
+
+- You'll want to order your y-axis in the query, eg. `order by timestamp asc`. The graph may come out looking bizarre otherwise. It's better to have Microsoft sort it on their side where it's faster, than to implement this in the plugin.
+
+- If you copy a log analytics query, typically they'll end with a render instruction, like `render barchart`. This is unnecessary, but harmless.
+
+- Currently, four default dashboard variables are supported: `$__timeFilter()`, `$__from`, `$__to`, and `$__interval`. If you're searching in timestamped data, replace the beginning of your where clause to `where $__timeFilter()`. Dashboard changes by time region are handled as you'd expect, as long as you leave the name of the `timestamp` column alone. Likewise, `$__interval` will automatically change based on the dashboard's time region _and_ the width of the chart being displayed. Use it in bins, so `bin(timestamp,$__interval)` changes into something like `bin(timestamp,1s)`. Use `$__from` and `$__to` if you just want the formatted dates to be inserted.
+
+- Templated dashboard variables are not yet supported! They will come in a future version.

+ 4 - 4
docs/sources/features/datasources/cloudwatch.md

@@ -8,7 +8,7 @@ aliases = ["/datasources/cloudwatch"]
 name = "AWS Cloudwatch"
 identifier = "cloudwatch"
 parent = "datasources"
-weight = 10
+weight = 5
 +++
 
 # Using AWS CloudWatch in Grafana
@@ -77,9 +77,9 @@ Here is a minimal policy example:
         },
         {
             "Sid": "AllowReadingResourcesForTags",
-            "Effect" : "Allow",      
-            "Action" : "tag:GetResources",      
-            "Resource" : "*"      
+            "Effect" : "Allow",
+            "Action" : "tag:GetResources",
+            "Resource" : "*"
         }
     ]
 }

+ 8 - 5
docs/sources/features/datasources/index.md

@@ -22,15 +22,18 @@ The query language and capabilities of each Data Source are obviously very diffe
 The following datasources are officially supported:
 
 * [Graphite]({{< relref "graphite.md" >}})
-* [Elasticsearch]({{< relref "elasticsearch.md" >}})
-* [CloudWatch]({{< relref "cloudwatch.md" >}})
-* [InfluxDB]({{< relref "influxdb.md" >}})
-* [OpenTSDB]({{< relref "opentsdb.md" >}})
 * [Prometheus]({{< relref "prometheus.md" >}})
+* [InfluxDB]({{< relref "influxdb.md" >}})
+* [Elasticsearch]({{< relref "elasticsearch.md" >}})
+* [Google Stackdriver]({{< relref "stackdriver.md" >}})
+* [AWS CloudWatch]({{< relref "cloudwatch.md" >}})
+* [Azure Monitor]({{< relref "azuremonitor.md" >}})
 * [Loki]({{< relref "loki.md" >}})
 * [MySQL]({{< relref "mysql.md" >}})
-* [Postgres]({{< relref "postgres.md" >}})
+* [PostgreSQL]({{< relref "postgres.md" >}})
 * [Microsoft SQL Server (MSSQL)]({{< relref "mssql.md" >}})
+* [OpenTSDB]({{< relref "opentsdb.md" >}})
+* [Testdata]({{< relref "testdata.md" >}})
 
 ## Data source plugins
 

+ 1 - 1
docs/sources/features/datasources/influxdb.md

@@ -7,7 +7,7 @@ aliases = ["/datasources/influxdb"]
 [menu.docs]
 name = "InfluxDB"
 parent = "datasources"
-weight = 3
+weight = 2
 +++
 
 # Using InfluxDB in Grafana

+ 1 - 1
docs/sources/features/datasources/loki.md

@@ -7,7 +7,7 @@ aliases = ["/datasources/loki"]
 [menu.docs]
 name = "Loki"
 parent = "datasources"
-weight = 11
+weight = 6
 +++
 
 # Using Loki in Grafana

+ 1 - 1
docs/sources/features/datasources/opentsdb.md

@@ -7,7 +7,7 @@ aliases = ["/datasources/opentsdb",	"docs/features/opentsdb"]
 [menu.docs]
 name = "OpenTSDB"
 parent = "datasources"
-weight = 5
+weight = 19
 +++
 
 # Using OpenTSDB in Grafana

+ 1 - 1
docs/sources/features/datasources/prometheus.md

@@ -7,7 +7,7 @@ aliases = ["/datasources/prometheus"]
 [menu.docs]
 name = "Prometheus"
 parent = "datasources"
-weight = 2
+weight = 1
 +++
 
 # Using Prometheus in Grafana

+ 4 - 4
docs/sources/features/datasources/stackdriver.md

@@ -5,9 +5,9 @@ keywords = ["grafana", "stackdriver", "google", "guide"]
 type = "docs"
 aliases = ["/datasources/stackdriver"]
 [menu.docs]
-name = "Stackdriver"
+name = "Google Stackdriver"
 parent = "datasources"
-weight = 11
+weight = 4
 +++
 
 # Using Google Stackdriver in Grafana
@@ -66,7 +66,7 @@ Click on the links above and click the `Enable` button:
 4. Some new fields will appear. Fill in a name for the service account in the `Service account name` field and then choose the `Monitoring Viewer` role from the `Role` dropdown:
 
     {{< docs-imagebox img="/img/docs/v53/stackdriver_service_account_choose_role.png" class="docs-image--no-shadow" caption="Choose role" >}}
-  
+
 5. Click the Create button. A JSON key file will be created and downloaded to your computer. Store this file in a secure place as it allows access to your Stackdriver data.
 6. Upload it to Grafana on the datasource Configuration page. You can either upload the file or paste in the contents of the file.
 
@@ -156,7 +156,7 @@ Example Alias By: `{{metric.type}} - {{metric.labels.instance_name}}`
 
 Example Result: `compute.googleapis.com/instance/cpu/usage_time - server1-prod`
 
-It is also possible to resolve the name of the Monitored Resource Type. 
+It is also possible to resolve the name of the Monitored Resource Type.
 
 | Alias Pattern Format | Description                                     | Example Result |
 | -------------------- | ----------------------------------------------- | -------------- |

+ 5 - 5
docs/sources/guides/whats-new-in-v6-0.md

@@ -14,8 +14,6 @@ weight = -11
 
 This update to Grafana introduces a new way of exploring your data, support for log data and tons of other features.
 
-Grafana v6.0 is out in **Beta**, [Download Now!](https://grafana.com/grafana/download/beta)
-
 The main highlights are:
 
 - [Explore]({{< relref "#explore" >}}) - A new query focused workflow for ad-hoc data exploration and troubleshooting.
@@ -107,9 +105,9 @@ continue to refine and start using in other panels.
 ### React Panels & Query Editors
 
 A major part of all the work that has gone into Grafana v6.0 has been on the migration to React. This investment
-is part of the future proofing of Grafana and it's code base and ecosystem. Starting in v6.0 **Panels** and **Data
+is part of the future proofing of Grafana's code base and ecosystem. Starting in v6.0 **Panels** and **Data
 source** plugins can be written in React using our published `@grafana/ui` sdk library. More information on this
-will be shared closer to or just after release.
+will be shared soon.
 
 {{< docs-imagebox img="/img/docs/v60/react_panels.png" max-width="600px" caption="React Panel" >}}
 <br />
@@ -122,10 +120,12 @@ To get started read the guide: [Using Google Stackdriver in Grafana](/features/d
 
 ## Azure Monitor Datasource
 
-One of the goals of the Grafana v6.0 release is to add support for the three major clouds. Amazon Cloudwatch has been a core datasource for years and Google Stackdriver is also now supported. We developed an external plugin for Azure Monitor last year and for this release the [plugin](https://grafana.com/plugins/grafana-azure-monitor-datasource) is being moved into Grafana to be one of the built-in datasources. For users of the external plugin, Grafana will automatically start using the built-in version. As a core datasource, the Azure Monitor datasource will get alerting support for the official 6.0 release.
+One of the goals of the Grafana v6.0 release is to add support for the three major clouds. Amazon Cloudwatch has been a core datasource for years and Google Stackdriver is also now supported. We developed an external plugin for Azure Monitor last year and for this release the [plugin](https://grafana.com/plugins/grafana-azure-monitor-datasource) is being moved into Grafana to be one of the built-in datasources. For users of the external plugin, Grafana will automatically start using the built-in version. As a core datasource, the Azure Monitor datasource is able to get alerting support, in the 6.0 release alerting is supported for the Azure Monitor service, with the rest to follow.
 
 The Azure Monitor datasource integrates four Azure services with Grafana - Azure Monitor, Azure Log Analytics, Azure Application Insights and Azure Application Insights Analytics.
 
+Please read [Using Azure Monitor in Grafana documentation](/features/datasources/azuremonitor/) for more detailed information on how to get started and use it.
+
 ## Provisioning support for alert notifiers
 
 Grafana now added support for provisioning alert notifiers from configuration files. Allowing operators to provision notifiers without using the UI or the API. A new field called `uid` has been introduced which is a string identifier that the administrator can set themselves. Same kind of identifier used for dashboards since v5.0. This feature makes it possible to use the same notifier configuration in multiple environments and refer to notifiers in dashboard json by a string identifier instead of the numeric id which depends on insert order and how many notifiers that exists in the instance.

+ 13 - 5
docs/sources/index.md

@@ -60,9 +60,9 @@ aliases = ["v1.1", "guides/reference/admin"]
         <h4>Provisioning</h4>
         <p>A guide to help you automate your Grafana setup & configuration.</p>
     </a>
-    <a href="{{< relref "guides/whats-new-in-v5-4.md" >}}" class="nav-cards__item nav-cards__item--guide">
-        <h4>What's new in v5.4</h4>
-        <p>Article on all the new cool features and enhancements in v5.4</p>
+    <a href="{{< relref "guides/whats-new-in-v6-0.md" >}}" class="nav-cards__item nav-cards__item--guide">
+        <h4>What's new in v6.0</h4>
+        <p>Article on all the new cool features and enhancements in v6.0</p>
     </a>
     <a href="{{< relref "tutorials/screencasts.md" >}}" class="nav-cards__item nav-cards__item--guide">
         <h4>Screencasts</h4>
@@ -89,12 +89,20 @@ aliases = ["v1.1", "guides/reference/admin"]
       <h5>Prometheus</h5>
     </a>
     <a href="{{< relref "features/datasources/stackdriver.md" >}}" class="nav-cards__item nav-cards__item--ds">
-      <img src="/img/docs/logos/stackdriver_logo.png">
+      <img src="/img/docs/logos/icon_stackdriver.svg">
       <h5>Google Stackdriver</h5>
     </a>
     <a href="{{< relref "features/datasources/cloudwatch.md" >}}" class="nav-cards__item nav-cards__item--ds">
       <img src="/img/docs/logos/icon_cloudwatch.svg">
-      <h5>Cloudwatch</h5>
+      <h5>AWS CloudWatch</h5>
+    </a>
+    <a href="{{< relref "features/datasources/azuremonitor.md" >}}" class="nav-cards__item nav-cards__item--ds">
+      <img src="/img/docs/logos/icon_azure_monitor.jpg">
+      <h5>Azure Monitor</h5>
+    </a>
+    <a href="{{< relref "features/datasources/loki.md" >}}" class="nav-cards__item nav-cards__item--ds">
+      <img src="/img/docs/logos/icon_loki.svg">
+      <h5>Loki</h5>
     </a>
     <a href="{{< relref "features/datasources/mysql.md" >}}" class="nav-cards__item nav-cards__item--ds">
       <img src="/img/docs/logos/icon_mysql.png" >

+ 3 - 3
docs/sources/project/building_from_source.md

@@ -57,7 +57,7 @@ For this you need nodejs (v.6+).
 ```bash
 npm install -g yarn
 yarn install --pure-lockfile
-yarn watch
+yarn start
 ```
 
 ## Running Grafana Locally
@@ -83,7 +83,7 @@ go get github.com/Unknwon/bra
 bra run
 ```
 
-You'll also need to run `yarn watch` to watch for changes to the front-end (typescript, html, sass)
+You'll also need to run `yarn start` to watch for changes to the front-end (typescript, html, sass)
 
 ### Running tests
 
@@ -145,4 +145,4 @@ Please contribute to the Grafana project and submit a pull request! Build new fe
 ## Logging in for the first time
 
 To run Grafana open your browser and go to the default port http://localhost:3000 or the port you have configured.
-Then follow the instructions [here](/guides/getting_started/).
+Then follow the instructions [here](/guides/getting_started/).

+ 2 - 2
latest.json

@@ -1,4 +1,4 @@
 {
-  "stable": "5.4.3",
-  "testing": "5.4.3"
+  "stable": "6.0.0",
+  "testing": "6.0.0"
 }

+ 20 - 3
package.json

@@ -17,9 +17,12 @@
     "@babel/preset-react": "^7.0.0",
     "@babel/preset-typescript": "^7.1.0",
     "@rtsao/plugin-proposal-class-properties": "^7.0.1-patch.1",
+    "@types/chalk": "^2.2.0",
     "@types/classnames": "^2.2.6",
+    "@types/commander": "^2.12.2",
     "@types/d3": "^4.10.1",
     "@types/enzyme": "^3.1.13",
+    "@types/inquirer": "^0.0.43",
     "@types/jest": "^23.3.2",
     "@types/jquery": "^1.10.35",
     "@types/node": "^8.0.31",
@@ -36,13 +39,16 @@
     "babel-jest": "^23.6.0",
     "babel-loader": "^8.0.4",
     "babel-plugin-angularjs-annotate": "^0.9.0",
+    "chalk": "^2.4.2",
     "clean-webpack-plugin": "^0.1.19",
+    "concurrently": "^4.1.0",
     "css-loader": "^0.28.7",
     "enzyme": "^3.6.0",
     "enzyme-adapter-react-16": "^1.5.0",
     "enzyme-to-json": "^3.3.4",
     "es6-promise": "^3.0.2",
     "es6-shim": "^0.35.3",
+    "execa": "^1.0.0",
     "expect.js": "~0.2.0",
     "expose-loader": "^0.7.3",
     "file-loader": "^1.1.11",
@@ -66,6 +72,7 @@
     "html-webpack-harddisk-plugin": "^0.2.0",
     "html-webpack-plugin": "^3.2.0",
     "husky": "^1.3.1",
+    "inquirer": "^6.2.2",
     "jest": "^23.6.0",
     "jest-date-mock": "^1.0.6",
     "lint-staged": "^8.1.3",
@@ -79,6 +86,7 @@
     "node-sass": "^4.11.0",
     "npm": "^5.4.2",
     "optimize-css-assets-webpack-plugin": "^4.0.2",
+    "ora": "^3.1.0",
     "phantomjs-prebuilt": "^2.1.15",
     "postcss-browser-reporter": "^0.5.0",
     "postcss-loader": "^2.0.6",
@@ -88,14 +96,17 @@
     "react-test-renderer": "^16.5.0",
     "redux-mock-store": "^1.5.3",
     "regexp-replace-loader": "^1.0.1",
+    "rimraf": "^2.6.3",
     "sass-lint": "^1.10.2",
     "sass-loader": "^7.0.1",
+    "semver": "^5.6.0",
     "sinon": "1.17.6",
     "style-loader": "^0.21.0",
     "systemjs": "0.20.19",
     "systemjs-plugin-css": "^0.1.36",
     "ts-jest": "^23.10.4",
     "ts-loader": "^5.1.0",
+    "ts-node": "^8.0.2",
     "tslib": "^1.9.3",
     "tslint": "^5.8.0",
     "tslint-loader": "^3.5.3",
@@ -112,8 +123,10 @@
   },
   "scripts": {
     "dev": "webpack --progress --colors --mode development --config scripts/webpack/webpack.dev.js",
-    "start": "webpack-dev-server --progress --colors --mode development --config scripts/webpack/webpack.hot.js",
-    "watch": "webpack --progress --colors --watch --mode development --config scripts/webpack/webpack.dev.js",
+    "start": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --theme",
+    "start:hot": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --hot --theme",
+    "start:ignoreTheme": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --hot",
+    "watch": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --theme -d watch,start",
     "build": "grunt build",
     "test": "grunt test",
     "tslint": "tslint -c tslint.json --project tsconfig.json",
@@ -121,7 +134,10 @@
     "jest": "jest --notify --watch",
     "api-tests": "jest --notify --watch --config=tests/api/jest.js",
     "storybook": "cd packages/grafana-ui && yarn storybook",
-    "prettier:check": "prettier --list-different \"**/*.{ts,tsx,scss}\""
+    "themes:generate": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/generateSassVariableFiles.ts",
+    "prettier:check": "prettier --list-different \"**/*.{ts,tsx,scss}\"",
+    "gui:build": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --build",
+    "gui:release": "ts-node --project ./scripts/cli/tsconfig.json ./scripts/cli/index.ts --release"
   },
   "husky": {
     "hooks": {
@@ -168,6 +184,7 @@
     "moment": "^2.22.2",
     "mousetrap": "^1.6.0",
     "mousetrap-global-bind": "^1.1.0",
+    "nodemon": "^1.18.10",
     "prismjs": "^1.6.0",
     "prop-types": "^15.6.2",
     "rc-cascader": "^0.14.0",

+ 6 - 0
packages/grafana-ui/CHANGELOG.md

@@ -0,0 +1,6 @@
+# 6.0.0-alpha.0 (2019-02-22)
+Version update to 6.0.0 to keep @grafana/ui version in sync with [Grafana](https://github.com/grafana/grafana)
+
+# 1.0.0-alpha.0 (2019-02-21)
+First public release
+

+ 16 - 2
packages/grafana-ui/README.md

@@ -1,3 +1,17 @@
-# Grafana (WIP) shared component library
+# Grafana UI components library
 
-Used by internal & external plugins.
+@grafana/ui is a collection of components used by [Grafana](https://github.com/grafana/grafana)
+
+Our goal is to deliver Grafana's common UI elements for plugins developers and contributors.
+
+See [package source](https://github.com/grafana/grafana/tree/master/packages/grafana-ui) for more details.
+
+## Installation
+
+`yarn add @grafana/ui`
+
+`npm install @grafana/ui`
+
+## Versioning
+To limit the confusion related to @grafana/ui and Grafana versioning we decided to keep the major version in sync between those two.
+This means, that first version of @grafana/ui is taged with 6.0.0-alpha.0 to keep version in sync with Grafana 6.0 release.

+ 7 - 0
packages/grafana-ui/index.js

@@ -0,0 +1,7 @@
+'use strict'
+
+if (process.env.NODE_ENV === 'production') {
+  module.exports = require('./index.production.js');
+} else {
+  module.exports = require('./index.development.js');
+}

+ 17 - 3
packages/grafana-ui/package.json

@@ -1,12 +1,19 @@
 {
   "name": "@grafana/ui",
-  "version": "1.0.0",
-  "description": "",
+  "version": "6.0.1-alpha.0",
+  "description": "Grafana Components Library",
+  "keywords": [
+    "typescript",
+    "react",
+    "react-component"
+  ],
   "main": "src/index.ts",
   "scripts": {
     "tslint": "tslint -c tslint.json --project tsconfig.json",
     "typecheck": "tsc --noEmit",
-    "storybook": "start-storybook -p 9001 -c .storybook -s ../../public"
+    "storybook": "start-storybook -p 9001 -c .storybook -s ../../public",
+    "clean": "rimraf ./dist ./compiled",
+    "build": "rollup -c rollup.config.ts"
   },
   "author": "Grafana Labs",
   "license": "Apache-2.0",
@@ -53,6 +60,13 @@
     "react-docgen-typescript-loader": "^3.0.0",
     "react-docgen-typescript-webpack-plugin": "^1.1.0",
     "react-test-renderer": "^16.7.0",
+    "rollup": "^1.1.2",
+    "rollup-plugin-commonjs": "^9.2.0",
+    "rollup-plugin-node-resolve": "^4.0.0",
+    "rollup-plugin-sourcemaps": "^0.4.2",
+    "rollup-plugin-terser": "^4.0.4",
+    "rollup-plugin-typescript2": "^0.19.2",
+    "rollup-plugin-visualizer": "^0.9.2",
     "typescript": "^3.2.2"
   },
   "resolutions": {

+ 54 - 0
packages/grafana-ui/rollup.config.ts

@@ -0,0 +1,54 @@
+import resolve from 'rollup-plugin-node-resolve';
+import commonjs from 'rollup-plugin-commonjs';
+import sourceMaps from 'rollup-plugin-sourcemaps';
+import { terser } from 'rollup-plugin-terser';
+
+const pkg = require('./package.json');
+
+const libraryName = pkg.name;
+
+const buildCjsPackage = ({ env }) => {
+  return {
+    input: `compiled/index.js`,
+    output: [
+      {
+        file: `dist/index.${env}.js`,
+        name: libraryName,
+        format: 'cjs',
+        sourcemap: true,
+        exports: 'named',
+        globals: {
+          react: 'React',
+          'prop-types': 'PropTypes',
+        },
+      },
+    ],
+    external: ['react', 'react-dom'],
+    plugins: [
+      commonjs({
+        include: /node_modules/,
+        namedExports: {
+          '../../node_modules/lodash/lodash.js': [
+            'flatten',
+            'find',
+            'upperFirst',
+            'debounce',
+            'isNil',
+            'isNumber',
+            'flattenDeep',
+            'map',
+            'chunk',
+            'sortBy',
+            'uniqueId',
+            'zip',
+          ],
+          '../../node_modules/react-color/lib/components/common': ['Saturation', 'Hue', 'Alpha'],
+        },
+      }),
+      resolve(),
+      sourceMaps(),
+      env === 'production' && terser(),
+    ],
+  };
+};
+export default [buildCjsPackage({ env: 'development' }), buildCjsPackage({ env: 'production' })];

+ 2 - 2
packages/grafana-ui/src/components/ColorPicker/ColorInput.tsx

@@ -1,7 +1,7 @@
 import React from 'react';
-import { ColorPickerProps } from './ColorPicker';
+import { ColorPickerProps } from './ColorPickerPopover';
 import tinycolor from 'tinycolor2';
-import { debounce } from 'lodash';
+import debounce from 'lodash/debounce';
 
 interface ColorInputState {
   previousColor: string;

+ 2 - 23
packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx

@@ -1,32 +1,11 @@
 import React, { Component, createRef } from 'react';
 import { PopperController } from '../Tooltip/PopperController';
 import { Popper } from '../Tooltip/Popper';
-import { ColorPickerPopover } from './ColorPickerPopover';
-import { Themeable } from '../../types';
+import { ColorPickerPopover, ColorPickerProps, ColorPickerChangeHandler } from './ColorPickerPopover';
 import { getColorFromHexRgbOrName } from '../../utils/namedColorsPalette';
 import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
-import propDeprecationWarning from '../../utils/propDeprecationWarning';
-import { withTheme } from '../../themes/ThemeContext';
-type ColorPickerChangeHandler = (color: string) => void;
-
-export interface ColorPickerProps extends Themeable {
-  color: string;
-  onChange: ColorPickerChangeHandler;
-
-  /**
-   * @deprecated Use onChange instead
-   */
-  onColorChange?: ColorPickerChangeHandler;
-  enableNamedColors?: boolean;
-  children?: JSX.Element;
-}
 
-export const warnAboutColorPickerPropsDeprecation = (componentName: string, props: ColorPickerProps) => {
-  const { onColorChange } = props;
-  if (onColorChange) {
-    propDeprecationWarning(componentName, 'onColorChange', 'onChange');
-  }
-};
+import { withTheme } from '../../themes/ThemeContext';
 
 export const colorPickerFactory = <T extends ColorPickerProps>(
   popover: React.ComponentType<T>,

+ 1 - 1
packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.test.tsx

@@ -3,7 +3,7 @@ import { mount, ReactWrapper } from 'enzyme';
 import { ColorPickerPopover } from './ColorPickerPopover';
 import { getColorDefinitionByName, getNamedColorPalette } from '../../utils/namedColorsPalette';
 import { ColorSwatch } from './NamedColorsGroup';
-import { flatten } from 'lodash';
+import flatten from 'lodash/flatten';
 import { GrafanaThemeType } from '../../types';
 import { getTheme } from '../../themes';
 

+ 17 - 3
packages/grafana-ui/src/components/ColorPicker/ColorPickerPopover.tsx

@@ -1,23 +1,37 @@
 import React from 'react';
 import { NamedColorsPalette } from './NamedColorsPalette';
 import { getColorName, getColorFromHexRgbOrName } from '../../utils/namedColorsPalette';
-import { ColorPickerProps, warnAboutColorPickerPropsDeprecation } from './ColorPicker';
 import { PopperContentProps } from '../Tooltip/PopperController';
 import SpectrumPalette from './SpectrumPalette';
-import { GrafanaThemeType } from '../../types/theme';
+import { GrafanaThemeType, Themeable } from '../../types/theme';
+import { warnAboutColorPickerPropsDeprecation } from './warnAboutColorPickerPropsDeprecation';
 
+export type ColorPickerChangeHandler = (color: string) => void;
+
+export interface ColorPickerProps extends Themeable {
+  color: string;
+  onChange: ColorPickerChangeHandler;
+
+  /**
+   * @deprecated Use onChange instead
+   */
+  onColorChange?: ColorPickerChangeHandler;
+  enableNamedColors?: boolean;
+  children?: JSX.Element;
+}
 export interface Props<T> extends ColorPickerProps, PopperContentProps {
   customPickers?: T;
 }
 
 type PickerType = 'palette' | 'spectrum';
 
-interface CustomPickersDescriptor {
+export interface CustomPickersDescriptor {
   [key: string]: {
     tabComponent: React.ComponentType<ColorPickerProps>;
     name: string;
   };
 }
+
 interface State<T> {
   activePicker: PickerType | keyof T;
 }

+ 2 - 1
packages/grafana-ui/src/components/ColorPicker/NamedColorsGroup.tsx

@@ -2,7 +2,8 @@ import React, { FunctionComponent } from 'react';
 import { Themeable } from '../../types';
 import { ColorDefinition, getColorForTheme } from '../../utils/namedColorsPalette';
 import { Color } from 'csstype';
-import { find, upperFirst } from 'lodash';
+import upperFirst from 'lodash/upperFirst';
+import find from 'lodash/find';
 import { selectThemeVariant } from '../../themes/selectThemeVariant';
 
 type ColorChangeHandler = (color: ColorDefinition) => void;

+ 1 - 2
packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx

@@ -1,7 +1,6 @@
 import React, { FunctionComponent } from 'react';
 
-import { ColorPickerPopover } from './ColorPickerPopover';
-import { ColorPickerProps } from './ColorPicker';
+import { ColorPickerPopover, ColorPickerProps } from './ColorPickerPopover';
 import { PopperContentProps } from '../Tooltip/PopperController';
 import { Switch } from '../Switch/Switch';
 import { withTheme } from '../../themes/ThemeContext';

+ 9 - 0
packages/grafana-ui/src/components/ColorPicker/warnAboutColorPickerPropsDeprecation.ts

@@ -0,0 +1,9 @@
+import propDeprecationWarning from '../../utils/propDeprecationWarning';
+import { ColorPickerProps } from './ColorPickerPopover';
+
+export const warnAboutColorPickerPropsDeprecation = (componentName: string, props: ColorPickerProps) => {
+  const { onColorChange } = props;
+  if (onColorChange) {
+    propDeprecationWarning(componentName, 'onColorChange', 'onChange');
+  }
+};

+ 6 - 6
packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx

@@ -1,9 +1,10 @@
 import React, { PureComponent } from 'react';
-import _ from 'lodash';
+import isNil from 'lodash/isNil';
+import classNames from 'classnames';
 import Scrollbars from 'react-custom-scrollbars';
 
 interface Props {
-  customClassName?: string;
+  className?: string;
   autoHide?: boolean;
   autoHideTimeout?: number;
   autoHideDuration?: number;
@@ -21,7 +22,6 @@ interface Props {
  */
 export class CustomScrollbar extends PureComponent<Props> {
   static defaultProps: Partial<Props> = {
-    customClassName: 'custom-scrollbars',
     autoHide: false,
     autoHideTimeout: 200,
     autoHideDuration: 200,
@@ -41,7 +41,7 @@ export class CustomScrollbar extends PureComponent<Props> {
   updateScroll() {
     const ref = this.ref.current;
 
-    if (ref && !_.isNil(this.props.scrollTop)) {
+    if (ref && !isNil(this.props.scrollTop)) {
       if (this.props.scrollTop > 10000) {
         ref.scrollToBottom();
       } else {
@@ -60,7 +60,7 @@ export class CustomScrollbar extends PureComponent<Props> {
 
   render() {
     const {
-      customClassName,
+      className,
       children,
       autoHeightMax,
       autoHeightMin,
@@ -75,7 +75,7 @@ export class CustomScrollbar extends PureComponent<Props> {
     return (
       <Scrollbars
         ref={this.ref}
-        className={customClassName}
+        className={classNames('custom-scrollbar', className)}
         onScroll={setScrollTop}
         autoHeight={true}
         autoHide={autoHide}

+ 8 - 1
packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss

@@ -1,4 +1,4 @@
-.custom-scrollbars {
+.custom-scrollbar {
   // Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to
   // make scroll working it should fit outer container size (scroll appears only when inner container size is
   // greater than outer one).
@@ -37,4 +37,11 @@
     @include gradient-horizontal($scrollbarBackground, $scrollbarBackground2);
     border-radius: 6px;
   }
+
+  // page scrollbar should stick to left side to aid hitting it
+  &--page {
+    .track-vertical {
+      right: 0;
+    }
+  }
 }

+ 1 - 1
packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap

@@ -2,7 +2,7 @@
 
 exports[`CustomScrollbar renders correctly 1`] = `
 <div
-  className="custom-scrollbars"
+  className="custom-scrollbar"
   style={
     Object {
       "height": "auto",

+ 1 - 1
packages/grafana-ui/src/components/FormField/FormField.tsx

@@ -1,5 +1,5 @@
 import React, { InputHTMLAttributes, FunctionComponent } from 'react';
-import { FormLabel } from '..';
+import { FormLabel } from '../FormLabel/FormLabel';
 
 export interface Props extends InputHTMLAttributes<HTMLInputElement> {
   label: string;

+ 6 - 6
packages/grafana-ui/src/components/Gauge/Gauge.tsx

@@ -1,10 +1,10 @@
 import React, { PureComponent } from 'react';
 import $ from 'jquery';
-
-import { ValueMapping, Threshold, BasicGaugeColor, GrafanaThemeType } from '../../types';
 import { getMappedValue } from '../../utils/valueMappings';
-import { getColorFromHexRgbOrName, getValueFormat } from '../../utils';
-import { Themeable } from '../../index';
+import { getColorFromHexRgbOrName } from '../../utils/namedColorsPalette';
+import { Themeable, GrafanaThemeType } from '../../types/theme';
+import { ValueMapping, Threshold, BasicGaugeColor } from '../../types/panel';
+import { getValueFormat } from '../../utils/valueFormats/valueFormats';
 
 type TimeSeriesValue = string | number | null;
 
@@ -115,9 +115,9 @@ export class Gauge extends PureComponent<Props> {
 
   getFontScale(length: number): number {
     if (length > 12) {
-      return FONT_SCALE - (length * 5) / 120;
+      return FONT_SCALE - (length * 5) / 110;
     }
-    return FONT_SCALE - (length * 5) / 105;
+    return FONT_SCALE - (length * 5) / 100;
   }
 
   draw() {

+ 1 - 1
packages/grafana-ui/src/components/Select/Select.tsx

@@ -16,7 +16,7 @@ import SelectOptionGroup from './SelectOptionGroup';
 import IndicatorsContainer from './IndicatorsContainer';
 import NoOptionsMessage from './NoOptionsMessage';
 import resetSelectStyles from './resetSelectStyles';
-import { CustomScrollbar } from '..';
+import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
 
 export interface SelectOptionItem {
   label?: string;

+ 2 - 2
packages/grafana-ui/src/components/Switch/Switch.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import _ from 'lodash';
+import uniqueId from 'lodash/uniqueId';
 
 export interface Props {
   label: string;
@@ -17,7 +17,7 @@ export interface State {
 
 export class Switch extends PureComponent<Props, State> {
   state = {
-    id: _.uniqueId('check-'),
+    id: uniqueId(),
   };
 
   internalOnChange = (event: React.FormEvent<HTMLInputElement>) => {

+ 1 - 1
packages/grafana-ui/src/components/ThresholdsEditor/ThresholdsEditor.tsx

@@ -55,7 +55,7 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
     const value = afterThresholdValue - (afterThresholdValue - beforeThresholdValue) / 2;
 
     // Set a color
-    const color = colors.filter(c => !newThresholds.some(t => t.color === c))[0];
+    const color = colors.filter(c => !newThresholds.some(t => t.color === c))[1];
 
     this.setState(
       {

+ 3 - 1
packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx

@@ -1,7 +1,9 @@
 import React, { ChangeEvent, PureComponent } from 'react';
 
 import { MappingType, ValueMapping } from '../../types';
-import { FormField, FormLabel, Select } from '..';
+import { Select } from '../Select/Select';
+import { FormField } from '../FormField/FormField';
+import { FormLabel } from '../FormLabel/FormLabel';
 
 export interface Props {
   valueMapping: ValueMapping;

+ 1 - 1
packages/grafana-ui/src/components/ValueMappingsEditor/ValueMappingsEditor.tsx

@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
 
 import MappingRow from './MappingRow';
 import { MappingType, ValueMapping } from '../../types';
-import { PanelOptionsGroup } from '..';
+import { PanelOptionsGroup } from '../PanelOptionsGroup/PanelOptionsGroup';
 
 export interface Props {
   valueMappings: ValueMapping[];

+ 1 - 1
packages/grafana-ui/src/components/ValueMappingsEditor/_ValueMappingsEditor.scss

@@ -17,7 +17,7 @@
   align-items: center;
   justify-content: center;
   width: 36px;
-  background-color: $green;
+  background-color: $green-base;
 }
 
 .add-mapping-row-label {

+ 0 - 1
packages/grafana-ui/src/index.ts

@@ -2,4 +2,3 @@ export * from './components';
 export * from './types';
 export * from './utils';
 export * from './themes';
-export * from './themes/ThemeContext';

+ 2 - 2
packages/grafana-ui/src/themes/ThemeContext.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
-import { GrafanaThemeType, Themeable } from '../types';
-import { getTheme } from './index';
+import { getTheme } from './getTheme';
+import { GrafanaThemeType, Themeable } from '../types/theme';
 
 type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
 type Subtract<T, K> = Omit<T, keyof K>;

+ 396 - 0
packages/grafana-ui/src/themes/_variables.dark.scss.tmpl.ts

@@ -0,0 +1,396 @@
+/* tslint:disable:max-line-length */
+
+import { GrafanaTheme } from '../types';
+import { renderGeneratedFileBanner } from '../utils/generatedFileBanner';
+
+export const darkThemeVarsTemplate = (theme: GrafanaTheme) =>
+  `${renderGeneratedFileBanner('grafana-ui/src/themes/dark.ts', 'grafana-ui/src/themes/_variables.dark.scss.tmpl.ts')}
+// Global values
+// --------------------------------------------------
+
+$theme-name: dark;
+
+// New Colors
+// -------------------------
+$blue-faint: ${theme.colors.blueFaint};
+$blue-light: ${theme.colors.blueLight};
+$blue-base: ${theme.colors.blueBase};
+$blue-shade: ${theme.colors.blueShade};
+$red-base: ${theme.colors.redBase};
+$red-shade: ${theme.colors.redShade};
+$green-base: ${theme.colors.greenBase};
+$green-shade: ${theme.colors.greenShade};
+
+// Grays
+// -------------------------
+$black: ${theme.colors.black};
+$dark-1: ${theme.colors.dark1};
+$dark-2: ${theme.colors.dark2};
+$dark-3: ${theme.colors.dark3};
+$dark-4: ${theme.colors.dark4};
+$dark-5: ${theme.colors.dark5};
+$dark-6: ${theme.colors.dark6};
+$dark-7: ${theme.colors.dark7};
+$dark-8: ${theme.colors.dark8};
+$dark-9: ${theme.colors.dark9};
+$dark-10: ${theme.colors.dark10};
+$gray-1: ${theme.colors.gray1};
+$gray-2: ${theme.colors.gray2};
+$gray-3: ${theme.colors.gray3};
+$gray-4: ${theme.colors.gray4};
+$gray-5: ${theme.colors.gray5};
+
+$gray-blue: ${theme.colors.grayBlue};
+$input-black: #09090b;
+
+$white: ${theme.colors.white};
+
+// Accent colors
+// -------------------------
+$blue: ${theme.colors.blue};
+$red: $red-base;
+$yellow: ${theme.colors.yellow};
+$orange: ${theme.colors.orange};
+$purple: ${theme.colors.purple};
+$variable: ${theme.colors.variable};
+
+$brand-primary: $orange;
+$brand-success: $green-base;
+$brand-warning: $brand-primary;
+$brand-danger: $red-base;
+
+$query-red: $red-base;
+$query-green: #74e680;
+$query-purple: #fe85fc;
+$query-keyword: #66d9ef;
+$query-orange: $orange;
+
+// Status colors
+// -------------------------
+$online: $green-base;
+$warn: #f79520;
+$critical: $red-base;
+
+// Scaffolding
+// -------------------------
+$body-bg: ${theme.colors.bodyBg};
+$page-bg: ${theme.colors.pageBg};
+
+$body-color: $gray-4;
+$text-color: $gray-4;
+$text-color-strong: $white;
+$text-color-weak: $gray-2;
+$text-color-faint: $dark-10;
+$text-color-emphasis: $gray-5;
+
+$text-shadow-faint: 1px 1px 4px rgb(45, 45, 45);
+$textShadow: none;
+
+// gradients
+$brand-gradient: linear-gradient(
+  to right,
+  rgba(255, 213, 0, 0.7) 0%,
+  rgba(255, 68, 0, 0.7) 99%,
+  rgba(255, 68, 0, 0.7) 100%
+);
+
+$page-gradient: linear-gradient(180deg, $dark-5 10px, dark-2 100px);
+$edit-gradient: linear-gradient(180deg, $dark-2 50%, $input-black);
+
+// Links
+// -------------------------
+$link-color: darken($white, 11%);
+$link-color-disabled: darken($link-color, 30%);
+$link-hover-color: $white;
+$external-link-color: $blue-light;
+
+// Typography
+// -------------------------
+$headings-color: darken($white, 11%);
+$abbr-border-color: $gray-2 !default;
+$text-muted: $text-color-weak;
+
+$hr-border-color: $dark-9;
+
+// Panel
+// -------------------------
+$panel-bg: $dark-4;
+$panel-border: solid 1px $dark-1;
+$panel-header-hover-bg: $dark-9;
+$panel-corner: $panel-bg;
+
+// page header
+$page-header-bg: linear-gradient(90deg, $dark-7, $black);
+$page-header-shadow: inset 0px -4px 14px $dark-3;
+$page-header-border-color: $dark-9;
+
+$divider-border-color: $gray-1;
+
+// Graphite Target Editor
+$tight-form-func-bg: $dark-9;
+$tight-form-func-highlight-bg: $dark-10;
+
+$modal-backdrop-bg: #353c42;
+$code-tag-bg: $dark-1;
+$code-tag-border: $dark-9;
+
+// cards
+$card-background: linear-gradient(135deg, $dark-8, $dark-6);
+$card-background-hover: linear-gradient(135deg, $dark-9, $dark-6);
+$card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, 0.1), 1px 1px 0 0 rgba(0, 0, 0, 0.3);
+
+// Lists
+$list-item-bg: $card-background;
+$list-item-hover-bg: $card-background-hover;
+$list-item-link-color: $text-color;
+$list-item-shadow: $card-shadow;
+
+$empty-list-cta-bg: $gray-blue;
+
+// Scrollbars
+$scrollbarBackground: #404357;
+$scrollbarBackground2: $dark-10;
+$scrollbarBorder: black;
+
+// Tables
+// -------------------------
+$table-bg-accent: $dark-6; // for striping
+$table-border: $dark-6; // table and cell border
+
+$table-bg-odd: $dark-3;
+$table-bg-hover: $dark-6;
+
+// Buttons
+// -------------------------
+$btn-secondary-bg: $blue-base;
+$btn-secondary-bg-hl: $blue-shade;
+
+$btn-primary-bg: $green-base;
+$btn-primary-bg-hl: $green-shade;
+
+$btn-success-bg: $green-base;
+$btn-success-bg-hl: $green-shade;
+
+$btn-danger-bg: $red-base;
+$btn-danger-bg-hl: $red-shade;
+
+$btn-inverse-bg: $dark-6;
+$btn-inverse-bg-hl: lighten($dark-6, 4%);
+$btn-inverse-text-color: $link-color;
+$btn-inverse-text-shadow: 0px 1px 0 rgba(0, 0, 0, 0.1);
+
+$btn-link-color: $gray-3;
+
+$iconContainerBackground: $black;
+
+$btn-divider-left: $dark-9;
+$btn-divider-right: $dark-3;
+
+$btn-drag-image: '../img/grab_dark.svg';
+
+// Forms
+// -------------------------
+$input-bg: $input-black;
+$input-bg-disabled: $dark-6;
+
+$input-color: $gray-4;
+$input-border-color: $dark-6;
+$input-box-shadow: inset 1px 0px 0.3rem 0px rgba(150, 150, 150, 0.1);
+$input-border-focus: $dark-6 !default;
+$input-box-shadow-focus: $blue-light !default;
+$input-color-placeholder: $gray-1 !default;
+$input-label-bg: $gray-blue;
+$input-label-border-color: $dark-6;
+$input-color-select-arrow: $white;
+
+// Input placeholder text color
+$placeholderText: darken($text-color, 25%);
+
+// Search
+$search-shadow: 0 0 30px 0 $black;
+$search-filter-box-bg: $gray-blue;
+
+// Typeahead
+$typeahead-shadow: 0 5px 10px 0 $black;
+$typeahead-selected-bg: $dark-9;
+$typeahead-selected-color: $yellow;
+
+// Dropdowns
+// -------------------------
+$dropdownBackground: $dark-6;
+$dropdownBorder: rgba(0, 0, 0, 0.2);
+$dropdownDividerTop: transparent;
+$dropdownDividerBottom: #444;
+
+$dropdownLinkColor: $text-color;
+$dropdownLinkColorHover: $white;
+$dropdownLinkColorActive: $white;
+
+$dropdownLinkBackgroundHover: $dark-9;
+
+// Horizontal forms & lists
+// -------------------------
+$horizontalComponentOffset: 180px;
+
+// Navbar
+// -------------------------
+$navbarHeight: 55px;
+
+$navbarBackground: $panel-bg;
+$navbarBorder: 1px solid $dark-6;
+
+$navbarButtonBackground: $navbarBackground;
+$navbarButtonBackgroundHighlight: $body-bg;
+
+$navbar-button-border: #2f2f32;
+
+// Sidemenu
+// -------------------------
+$side-menu-bg: $black;
+$side-menu-bg-mobile: $side-menu-bg;
+$side-menu-item-hover-bg: $dark-3;
+$side-menu-shadow: 0 0 20px black;
+$side-menu-link-color: $link-color;
+
+// Menu dropdowns
+// -------------------------
+$menu-dropdown-bg: $body-bg;
+$menu-dropdown-hover-bg: $dark-3;
+$menu-dropdown-shadow: 5px 5px 20px -5px $black;
+
+// Tabs
+// -------------------------
+$tab-border-color: $dark-9;
+
+// Toolbar
+$toolbar-bg: $input-black;
+
+// Form states and alerts
+// -------------------------
+$warning-text-color: $warn;
+$error-text-color: #e84d4d;
+$success-text-color: #12d95a;
+
+$alert-error-bg: linear-gradient(90deg, $red-base, $red-shade);
+$alert-success-bg: linear-gradient(90deg, $green-base, $green-shade);
+$alert-warning-bg: linear-gradient(90deg, $red-base, $red-shade);
+$alert-info-bg: linear-gradient(100deg, $blue-base, $blue-shade);
+
+// popover
+$popover-bg: $dark-2;
+$popover-color: $text-color;
+$popover-border-color: $dark-9;
+$popover-shadow: 0 0 20px black;
+
+$popover-help-bg: $btn-secondary-bg;
+$popover-help-color: $text-color;
+
+$popover-error-bg: $btn-danger-bg;
+
+// Tooltips and popovers
+// -------------------------
+$tooltipColor: $popover-help-color;
+$tooltipArrowWidth: 5px;
+$tooltipLinkColor: $link-color;
+$graph-tooltip-bg: $dark-1;
+
+$tooltipBackground: $black;
+$tooltipColor: $gray-4;
+$tooltipArrowColor: $tooltipBackground;
+$tooltipBackgroundError: $brand-danger;
+
+// images
+$checkboxImageUrl: '../img/checkbox.png';
+
+// info box
+$info-box-border-color: $blue-base;
+
+// footer
+$footer-link-color: $gray-2;
+$footer-link-hover: $gray-4;
+
+// json-explorer
+$json-explorer-default-color: $text-color;
+$json-explorer-string-color: #23d662;
+$json-explorer-number-color: $variable;
+$json-explorer-boolean-color: $variable;
+$json-explorer-null-color: #eec97d;
+$json-explorer-undefined-color: rgb(239, 143, 190);
+$json-explorer-function-color: #fd48cb;
+$json-explorer-rotate-time: 100ms;
+$json-explorer-toggler-opacity: 0.6;
+$json-explorer-bracket-color: #9494ff;
+$json-explorer-key-color: #23a0db;
+$json-explorer-url-color: #027bff;
+
+// Changelog and diff
+// -------------------------
+$diff-label-bg: $dark-3;
+$diff-label-fg: $white;
+
+$diff-group-bg: $dark-9;
+$diff-arrow-color: $white;
+
+$diff-json-bg: $dark-9;
+$diff-json-fg: $gray-5;
+
+$diff-json-added: $blue-shade;
+$diff-json-deleted: $red-shade;
+
+$diff-json-old: #a04338;
+$diff-json-new: #457740;
+
+$diff-json-changed-fg: $gray-5;
+$diff-json-changed-num: $text-color;
+
+$diff-json-icon: $gray-5;
+
+//Submenu
+$variable-option-bg: $dropdownLinkBackgroundHover;
+
+//Switch Slider
+// -------------------------
+$switch-bg: $input-bg;
+$switch-slider-color: $dark-3;
+$switch-slider-off-bg: $gray-1;
+$switch-slider-on-bg: linear-gradient(90deg, #eb7b18, #d44a3a);
+$switch-slider-shadow: 0 0 3px black;
+
+//Checkbox
+// -------------------------
+$checkbox-bg: $dark-1;
+$checkbox-border: 1px solid $gray-1;
+$checkbox-checked-bg: linear-gradient(0deg, #eb7b18, #d44a3a);
+$checkbox-color: $dark-1;
+
+//Panel Edit
+// -------------------------
+$panel-editor-shadow: 0 0 20px black;
+$panel-editor-side-menu-shadow: drop-shadow(0 0 10px $black);
+$panel-editor-viz-item-shadow: 0 0 8px $dark-10;
+$panel-editor-viz-item-border: 1px solid $dark-10;
+$panel-editor-viz-item-shadow-hover: 0 0 4px $blue-light;
+$panel-editor-viz-item-border-hover: 1px solid $blue-light;
+$panel-editor-viz-item-bg: $input-black;
+$panel-editor-tabs-line-color: #e3e3e3;
+
+$panel-editor-viz-item-bg-hover: darken($blue-base, 46%);
+
+$panel-options-group-border: none;
+$panel-options-group-header-bg: $gray-blue;
+
+$panel-grid-placeholder-bg: $blue-faint;
+$panel-grid-placeholder-shadow: 0 0 4px $blue-shade;
+
+// logs
+$logs-color-unkown: $gray-2;
+
+// toggle-group
+$button-toggle-group-btn-active-bg: linear-gradient(90deg, #eb7b18, #d44a3a);
+$button-toggle-group-btn-active-shadow: inset 0 0 4px $black;
+$button-toggle-group-btn-seperator-border: 1px solid $dark-2;
+
+$vertical-resize-handle-bg: $dark-10;
+$vertical-resize-handle-dots: $gray-1;
+$vertical-resize-handle-dots-hover: $gray-2;
+`;

+ 383 - 0
packages/grafana-ui/src/themes/_variables.light.scss.tmpl.ts

@@ -0,0 +1,383 @@
+/* tslint:disable:max-line-length */
+
+import { GrafanaTheme } from '../types';
+import { renderGeneratedFileBanner } from '../utils/generatedFileBanner';
+
+export const lightThemeVarsTemplate = (theme: GrafanaTheme) =>
+  `${renderGeneratedFileBanner('grafana-ui/src/themes/light.ts', 'grafana-ui/src/themes/_variable.light.scss.tmpl.ts')}
+// Global values
+// --------------------------------------------------
+
+$theme-name: light;
+
+// New Colors
+// -------------------------
+$blue-faint: ${theme.colors.blueFaint};
+$blue-light: ${theme.colors.blueLight};
+$blue-base: ${theme.colors.blueBase};
+$blue-shade: ${theme.colors.blueShade};
+$red-base: ${theme.colors.redBase};
+$red-shade: ${theme.colors.redShade};
+$green-base: ${theme.colors.greenBase};
+$green-shade: ${theme.colors.greenShade};
+
+// Grays
+// -------------------------
+$black: ${theme.colors.black};
+
+$dark-1: ${theme.colors.dark1};
+$dark-2: ${theme.colors.dark2};
+$gray-1: ${theme.colors.gray1};
+$gray-2: ${theme.colors.gray2};
+$gray-3: ${theme.colors.gray3};
+$gray-4: ${theme.colors.gray4};
+$gray-5: ${theme.colors.gray5};
+$gray-6: ${theme.colors.gray6};
+$gray-7: ${theme.colors.gray7};
+
+$white: ${theme.colors.white};
+
+// Accent colors
+// -------------------------
+$blue: ${theme.colors.blue};
+$red: $red-base;
+$yellow: ${theme.colors.yellow};
+$orange: ${theme.colors.orange};
+$purple: ${theme.colors.purple};
+$variable: ${theme.colors.variable};
+
+$brand-primary: $orange;
+$brand-success: $green-base;
+$brand-warning: $orange;
+$brand-danger: $red-base;
+
+$query-red: $red-base;
+$query-green: $green-base;
+$query-purple: $purple;
+$query-orange: $orange;
+$query-keyword: $blue-base;
+
+// Status colors
+// -------------------------
+$online: $green-shade;
+$warn: #f79520;
+$critical: $red-shade;
+
+// Scaffolding
+// -------------------------
+$body-bg: ${theme.colors.bodyBg};
+$page-bg: ${theme.colors.pageBg};
+
+$body-color: $gray-1;
+$text-color: $gray-1;
+$text-color-strong: $dark-1;
+$text-color-weak: $gray-2;
+$text-color-faint: $gray-4;
+$text-color-emphasis: $dark-2;
+
+$text-shadow-faint: none;
+
+// gradients
+$brand-gradient: linear-gradient(to right, rgba(255, 213, 0, 1) 0%, rgba(255, 68, 0, 1) 99%, rgba(255, 68, 0, 1) 100%);
+
+$page-gradient: linear-gradient(180deg, $white 10px, $gray-7 100px);
+$edit-gradient: linear-gradient(-60deg, $gray-7, #f5f6f9 70%, $gray-7 98%);
+
+// Links
+// -------------------------
+$link-color: $gray-1;
+$link-color-disabled: lighten($link-color, 30%);
+$link-hover-color: darken($link-color, 20%);
+$external-link-color: $blue-shade;
+
+// Typography
+// -------------------------
+$headings-color: $text-color;
+$abbr-border-color: $gray-2 !default;
+$text-muted: $text-color-weak;
+
+$hr-border-color: $gray-4 !default;
+
+// Panel
+// -------------------------
+$panel-bg: $white;
+$panel-border: solid 1px $gray-5;
+$panel-header-hover-bg: $gray-6;
+$panel-corner: $gray-4;
+
+// Page header
+$page-header-bg: linear-gradient(90deg, $white, $gray-7);
+$page-header-shadow: inset 0px -3px 10px $gray-6;
+$page-header-border-color: $gray-4;
+
+$divider-border-color: $gray-2;
+
+// Graphite Target Editor
+$tight-form-func-bg: $gray-5;
+$tight-form-func-highlight-bg: $gray-6;
+
+$modal-backdrop-bg: $body-bg;
+$code-tag-bg: $gray-6;
+$code-tag-border: $gray-4;
+
+// cards
+$card-background: linear-gradient(135deg, $gray-6, $gray-5);
+$card-background-hover: linear-gradient(135deg, $gray-5, $gray-6);
+$card-shadow: -1px -1px 0 0 hsla(0, 0%, 100%, 0.1), 1px 1px 0 0 rgba(0, 0, 0, 0.1);
+
+// Lists
+$list-item-bg: linear-gradient(135deg, $gray-5, $gray-6); //$card-background;
+$list-item-hover-bg: darken($gray-5, 5%);
+$list-item-link-color: $text-color;
+$list-item-shadow: $card-shadow;
+
+$empty-list-cta-bg: $gray-6;
+
+// Scrollbars
+$scrollbarBackground: $gray-4;
+$scrollbarBackground2: $gray-4;
+$scrollbarBorder: $gray-7;
+
+// Tables
+// -------------------------
+$table-bg-accent: $gray-5; // for striping
+$table-border: $gray-3; // table and cell border
+
+$table-bg-odd: $gray-6;
+$table-bg-hover: $gray-5;
+
+// Buttons
+// -------------------------
+$btn-primary-bg: $green-base;
+$btn-primary-bg-hl: $green-shade;
+
+$btn-secondary-bg: $blue-base;
+$btn-secondary-bg-hl: $blue-shade;
+
+$btn-success-bg: $green-base;
+$btn-success-bg-hl: $green-shade;
+
+$btn-danger-bg: $red-base;
+$btn-danger-bg-hl: $red-shade;
+
+$btn-inverse-bg: $gray-5;
+$btn-inverse-bg-hl: darken($gray-5, 5%);
+$btn-inverse-bg-hl: $gray-4;
+$btn-inverse-text-color: $gray-1;
+$btn-inverse-text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
+
+$btn-link-color: $gray-1;
+
+$iconContainerBackground: $white;
+
+$btn-divider-left: $gray-4;
+$btn-divider-right: $gray-7;
+
+$btn-drag-image: '../img/grab_light.svg';
+
+// Forms
+// -------------------------
+$input-bg: $white;
+$input-bg-disabled: $gray-5;
+
+$input-color: $dark-2;
+$input-border-color: $gray-5;
+$input-box-shadow: none;
+$input-border-focus: $gray-5 !default;
+$input-box-shadow-focus: $blue-light !default;
+$input-color-placeholder: $gray-4 !default;
+$input-label-bg: $gray-5;
+$input-label-border-color: $gray-5;
+$input-color-select-arrow: $gray-1;
+
+// Input placeholder text color
+$placeholderText: $gray-2;
+
+// search
+$search-shadow: 0 5px 30px 0 $gray-4;
+$search-filter-box-bg: $gray-7;
+
+// Typeahead
+$typeahead-shadow: 0 5px 10px 0 $gray-5;
+$typeahead-selected-bg: $gray-6;
+$typeahead-selected-color: $yellow;
+
+// Dropdowns
+// -------------------------
+$dropdownBackground: $white;
+$dropdownBorder: $gray-4;
+$dropdownDividerTop: $gray-6;
+$dropdownDividerBottom: $white;
+
+$dropdownLinkColor: $dark-2;
+$dropdownLinkColorHover: $link-color;
+$dropdownLinkColorActive: $link-color;
+
+$dropdownLinkBackgroundHover: $gray-6;
+
+// Horizontal forms & lists
+// -------------------------
+$horizontalComponentOffset: 180px;
+
+// Navbar
+// -------------------------
+$navbarHeight: 52px;
+
+$navbarBackground: $white;
+$navbarBorder: 1px solid $gray-5;
+
+$navbarButtonBackground: lighten($navbarBackground, 3%);
+$navbarButtonBackgroundHighlight: lighten($navbarBackground, 5%);
+
+$navbar-button-border: $gray-4;
+
+// Sidemenu
+// -------------------------
+$side-menu-bg: $dark-1;
+$side-menu-bg-mobile: rgba(0, 0, 0, 0); //$gray-6;
+$side-menu-item-hover-bg: $gray-1;
+$side-menu-shadow: 5px 0px 10px -5px $gray-1;
+$side-menu-link-color: $gray-6;
+
+// Menu dropdowns
+// -------------------------
+$menu-dropdown-bg: $gray-7;
+$menu-dropdown-hover-bg: $gray-6;
+$menu-dropdown-shadow: 5px 5px 10px -5px $gray-1;
+
+// Tabs
+// -------------------------
+$tab-border-color: $gray-5;
+
+// Toolbar
+$toolbar-bg: white;
+
+// Form states and alerts
+// -------------------------
+$warning-text-color: lighten($orange, 10%);
+$error-text-color: $red-shade;
+$success-text-color: lighten($green-base, 10%);
+
+$alert-error-bg: linear-gradient(90deg, $red-base, $red-shade);
+$alert-success-bg: linear-gradient(90deg, $green-base, $green-shade);
+$alert-warning-bg: linear-gradient(90deg, $red-base, $red-shade);
+$alert-info-bg: linear-gradient(100deg, $blue-base, $blue-shade);
+
+// popover
+$popover-bg: $page-bg;
+$popover-color: $text-color;
+$popover-border-color: $gray-5;
+$popover-shadow: 0 0 20px $white;
+
+$popover-help-bg: $btn-secondary-bg;
+$popover-help-color: $gray-6;
+
+$popover-error-bg: $btn-danger-bg;
+
+// Tooltips and popovers
+// -------------------------
+$tooltipColor: $popover-help-color;
+$tooltipArrowWidth: 5px;
+$tooltipLinkColor: lighten($popover-help-color, 5%);
+$graph-tooltip-bg: $gray-5;
+
+$tooltipBackground: $gray-1;
+$tooltipColor: $gray-7;
+$tooltipArrowColor: $tooltipBackground; // Used by Angular tooltip
+$tooltipBackgroundError: $brand-danger;
+
+// images
+$checkboxImageUrl: '../img/checkbox_white.png';
+
+// info box
+$info-box-border-color: $blue-base;
+
+// footer
+$footer-link-color: $gray-3;
+$footer-link-hover: $dark-2;
+
+// json explorer
+$json-explorer-default-color: black;
+$json-explorer-string-color: green;
+$json-explorer-number-color: $blue-base;
+$json-explorer-boolean-color: $red-base;
+$json-explorer-null-color: #855a00;
+$json-explorer-undefined-color: rgb(202, 11, 105);
+$json-explorer-function-color: #ff20ed;
+$json-explorer-rotate-time: 100ms;
+$json-explorer-toggler-opacity: 0.6;
+$json-explorer-bracket-color: $blue-base;
+$json-explorer-key-color: #00008b;
+$json-explorer-url-color: $blue-base;
+
+// Changelog and diff
+// -------------------------
+$diff-label-bg: $gray-7;
+$diff-label-fg: $gray-2;
+
+$diff-arrow-color: $dark-2;
+$diff-group-bg: $gray-6;
+
+$diff-json-bg: $gray-6;
+$diff-json-fg: $gray-1;
+
+$diff-json-added: $blue-shade;
+$diff-json-deleted: $red-shade;
+
+$diff-json-old: #5a372a;
+$diff-json-new: #664e33;
+
+$diff-json-changed-fg: $gray-7;
+$diff-json-changed-num: $gray-4;
+
+$diff-json-icon: $gray-4;
+
+//Submenu
+$variable-option-bg: $dropdownLinkBackgroundHover;
+
+//Switch Slider
+// -------------------------
+$switch-bg: $white;
+$switch-slider-color: $gray-7;
+$switch-slider-off-bg: $gray-5;
+$switch-slider-on-bg: linear-gradient(90deg, #ff9830, #e55400);
+$switch-slider-shadow: 0 0 3px $dark-2;
+
+//Checkbox
+// -------------------------
+$checkbox-bg: $gray-6;
+$checkbox-border: 1px solid $gray-3;
+$checkbox-checked-bg: linear-gradient(0deg, #ff9830, #e55400);
+$checkbox-color: $gray-7;
+
+//Panel Edit
+// -------------------------
+$panel-editor-shadow: 0px 0px 8px $gray-3;
+$panel-editor-side-menu-shadow: drop-shadow(0 0 2px $gray-3);
+$panel-editor-viz-item-shadow: 0 0 4px $gray-3;
+$panel-editor-viz-item-border: 1px solid $gray-3;
+$panel-editor-viz-item-shadow-hover: 0 0 4px $blue-light;
+$panel-editor-viz-item-border-hover: 1px solid $blue-light;
+$panel-editor-viz-item-bg: $white;
+$panel-editor-tabs-line-color: $dark-2;
+
+$panel-editor-viz-item-bg-hover: lighten($blue-base, 45%);
+
+$panel-options-group-border: none;
+$panel-options-group-header-bg: $gray-5;
+
+$panel-grid-placeholder-bg: $blue-faint;
+$panel-grid-placeholder-shadow: 0 0 4px $blue-light;
+
+// logs
+$logs-color-unkown: $gray-5;
+
+// toggle-group
+$button-toggle-group-btn-active-bg: $brand-primary;
+$button-toggle-group-btn-active-shadow: inset 0 0 4px $white;
+$button-toggle-group-btn-seperator-border: 1px solid $gray-6;
+
+$vertical-resize-handle-bg: $gray-4;
+$vertical-resize-handle-dots: $gray-3;
+$vertical-resize-handle-dots-hover: $gray-2;
+`;

+ 265 - 0
packages/grafana-ui/src/themes/_variables.scss.tmpl.ts

@@ -0,0 +1,265 @@
+/* tslint:disable:max-line-length */
+
+import { GrafanaThemeCommons } from '../types';
+import { renderGeneratedFileBanner } from '../utils/generatedFileBanner';
+
+export const commonThemeVarsTemplate = (theme: GrafanaThemeCommons) =>
+  `${renderGeneratedFileBanner('grafana-ui/src/themes/default.ts', 'grafana-ui/src/themes/_variables.scss.tmpl.ts')}
+// Options
+//
+// Quickly modify global styling by enabling or disabling optional features.
+
+$enable-flex: true !default;
+$enable-hover-media-query: false !default;
+
+// Spacing
+//
+// Control the default styling of most Bootstrap elements by modifying these
+// variables. Mostly focused on spacing.
+
+$spacer: 1rem !default;
+$spacer-x: $spacer !default;
+$spacer-y: $spacer !default;
+$spacers: (
+  0: (
+    x: 0,
+    y: 0,
+  ),
+  1: (
+    x: $spacer-x,
+    y: $spacer-y,
+  ),
+  2: (
+    x: (
+      $spacer-x * 1.5,
+    ),
+    y: (
+      $spacer-y * 1.5,
+    ),
+  ),
+  3: (
+    x: (
+      $spacer-x * 3,
+    ),
+    y: (
+      $spacer-y * 3,
+    ),
+  ),
+) !default;
+$border-width: 1px !default;
+
+// Grid breakpoints
+//
+// Define the minimum and maximum dimensions at which your layout will change,
+// adapting to different screen sizes, for use in media queries.
+
+$grid-breakpoints: (
+  xs: 0,
+  sm: 544px,
+  md: 768px,
+  lg: 992px,
+  xl: 1200px,
+) !default;
+
+// Grid containers
+//
+// Define the maximum width of \`.container\` for different screen sizes.
+
+$container-max-widths: (
+  sm: 576px,
+  md: 720px,
+  lg: 940px,
+  xl: 1080px,
+) !default;
+
+// Grid columns
+//
+// Set the number of columns and specify the width of the gutters.
+
+$grid-columns: 12 !default;
+$grid-gutter-width: 30px !default;
+
+$enable-flex: true;
+
+// Typography
+// -------------------------
+
+$font-family-sans-serif: 'Roboto', Helvetica, Arial, sans-serif;
+$font-family-serif: Georgia, 'Times New Roman', Times, serif;
+$font-family-monospace: Menlo, Monaco, Consolas, 'Courier New', monospace;
+$font-family-base: $font-family-sans-serif !default;
+
+$font-size-root: 14px !default;
+$font-size-base: 13px !default;
+
+$font-size-lg: 18px !default;
+$font-size-md: 14px !default;
+$font-size-sm: 12px !default;
+$font-size-xs: 10px !default;
+
+$line-height-base: 1.5 !default;
+$font-weight-semi-bold: 500;
+
+$font-size-h1: 2rem !default;
+$font-size-h2: 1.75rem !default;
+$font-size-h3: 1.5rem !default;
+$font-size-h4: 1.3rem !default;
+$font-size-h5: 1.2rem !default;
+$font-size-h6: 1rem !default;
+
+$display1-size: 6rem !default;
+$display2-size: 5.5rem !default;
+$display3-size: 4.5rem !default;
+$display4-size: 3.5rem !default;
+
+$display1-weight: 400 !default;
+$display2-weight: 400 !default;
+$display3-weight: 400 !default;
+$display4-weight: 400 !default;
+
+$lead-font-size: 1.25rem !default;
+$lead-font-weight: 300 !default;
+
+$headings-margin-bottom: ($spacer / 2) !default;
+$headings-font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+$headings-font-weight: 400 !default;
+$headings-line-height: 1.1 !default;
+
+$hr-border-width: $border-width !default;
+$dt-font-weight: bold !default;
+
+// Components
+//
+// Define common padding and border radius sizes and more.
+
+$line-height-lg: (4 / 3) !default;
+$line-height-sm: 1.5 !default;
+
+$border-radius: 3px !default;
+$border-radius-lg: 5px !default;
+$border-radius-sm: 2px !default;
+
+// Page
+
+$page-sidebar-width: 11rem;
+$page-sidebar-margin: 4rem;
+
+// Links
+// -------------------------
+$link-decoration: none !default;
+$link-hover-decoration: none !default;
+
+// Tables
+//
+// Customizes the \`.table\` component with basic values, each used across all table variations.
+
+$table-cell-padding: 4px 10px !default;
+
+// Forms
+$input-padding-x: 10px !default;
+$input-padding-y: 8px !default;
+$input-line-height: 18px !default;
+
+$input-btn-border-width: 1px;
+$input-border-radius: 0 $border-radius $border-radius 0 !default;
+$input-border-radius-sm: 0 $border-radius-sm $border-radius-sm 0 !default;
+
+$label-border-radius: $border-radius 0 0 $border-radius !default;
+$label-border-radius-sm: $border-radius-sm 0 0 $border-radius-sm !default;
+
+$input-padding-y-sm: 4px !default;
+
+$input-padding-x-lg: 20px !default;
+$input-padding-y-lg: 10px !default;
+
+$input-height: 35px !default;
+
+$gf-form-margin: 0.2rem;
+$gf-form-input-height: 35px;
+
+$cursor-disabled: not-allowed !default;
+
+// Form validation icons
+$form-icon-success: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%235cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E") !default;
+$form-icon-warning: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E") !default;
+$form-icon-danger: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E") !default;
+
+// Z-index master list
+// -------------------------
+// Used for a bird's eye view of components dependent on the z-axis
+// Try to avoid customizing these :)
+$zindex-dropdown: 1000;
+$zindex-navbar-fixed: 1020;
+$zindex-sidemenu: 1025;
+$zindex-tooltip: 1030;
+$zindex-modal-backdrop: 1040;
+$zindex-modal: 1050;
+$zindex-typeahead: 1060;
+
+// Buttons
+//
+
+$btn-padding-x: 1rem !default;
+$btn-padding-y: 0.7rem !default;
+$btn-line-height: 1 !default;
+$btn-font-weight: 500 !default;
+
+$btn-padding-x-sm: 0.5rem !default;
+$btn-padding-y-sm: 0.25rem !default;
+
+$btn-padding-x-lg: 21px !default;
+$btn-padding-y-lg: 11px !default;
+
+$btn-padding-x-xl: 21px !default;
+$btn-padding-y-xl: 11px !default;
+
+$btn-border-radius: 2px;
+
+$btn-semi-transparent: rgba(0, 0, 0, 0.2) !default;
+
+// sidemenu
+$side-menu-width: 60px;
+
+// dashboard
+$panel-margin: 10px;
+$dashboard-padding: $panel-margin * 2;
+$panel-horizontal-padding: 10;
+$panel-vertical-padding: 5;
+$panel-padding: 0px $panel-horizontal-padding + 0px $panel-vertical-padding + 0px $panel-horizontal-padding + 0px;
+
+// tabs
+$tabs-padding: 10px 15px 9px;
+
+$external-services: (
+  github: (
+    bgColor: #464646,
+    borderColor: #393939,
+    icon: '',
+  ),
+  gitlab: (
+    bgColor: #fc6d26,
+    borderColor: #e24329,
+    icon: '',
+  ),
+  google: (
+    bgColor: #e84d3c,
+    borderColor: #b83e31,
+    icon: '',
+  ),
+  grafanacom: (
+    bgColor: #262628,
+    borderColor: #393939,
+    icon: '',
+  ),
+  oauth: (
+    bgColor: #262628,
+    borderColor: #393939,
+    icon: '',
+  ),
+) !default;
+
+:export {
+  panelhorizontalpadding: $panel-horizontal-padding;
+  panelverticalpadding: $panel-vertical-padding;
+}
+`;

+ 27 - 18
packages/grafana-ui/src/themes/dark.ts

@@ -6,25 +6,34 @@ const basicColors = {
   black: '#000000',
   white: '#ffffff',
   dark1: '#141414',
-  dark2: '#1f1f20',
-  dark3: '#262628',
-  dark4: '#333333',
-  dark5: '#444444',
+  dark2: '#161719',
+  dark3: '#1f1f20',
+  dark4: '#212124',
+  dark5: '#222426',
+  dark6: '#262628',
+  dark7: '#292a2d',
+  dark8: '#2f2f32',
+  dark9: '#343436',
+  dark10: '#424345',
   gray1: '#555555',
   gray2: '#8e8e8e',
   gray3: '#b3b3b3',
   gray4: '#d8d9da',
   gray5: '#ececec',
-  gray6: '#f4f5f8',
-  gray7: '#fbfbfb',
+  gray6: '#f4f5f8', // not used in dark theme
+  gray7: '#fbfbfb', // not used in dark theme
   grayBlue: '#212327',
+  blueBase: '#3274d9',
+  blueShade: '#1f60c4',
+  blueLight: '#5794f2',
+  blueFaint: '#041126',
+  redBase: '#e02f44',
+  redShade: '#c4162a',
+  greenBase: '#299c46',
+  greenShade: '#23843b',
   blue: '#33b5e5',
-  blueDark: '#005f81',
-  blueLight: '#00a8e6', // not used in dark theme
-  green: '#299c46',
   red: '#d44a3a',
   yellow: '#ecbb13',
-  pink: '#ff4444',
   purple: '#9933cc',
   variable: '#32d1df',
   orange: '#eb7b18',
@@ -37,16 +46,16 @@ const darkTheme: GrafanaTheme = {
   colors: {
     ...basicColors,
     inputBlack: '#09090b',
-    queryRed: '#e24d42',
+    queryRed: basicColors.redBase,
     queryGreen: '#74e680',
     queryPurple: '#fe85fc',
     queryKeyword: '#66d9ef',
-    queryOrange: 'eb7b18',
-    online: '#10a345',
+    queryOrange: basicColors.orange,
+    online: basicColors.greenBase,
     warn: '#f79520',
-    critical: '#ed2e18',
-    bodyBg: '#171819',
-    pageBg: '#161719',
+    critical: basicColors.redBase,
+    bodyBg: basicColors.dark2,
+    pageBg: basicColors.dark2,
     bodyColor: basicColors.gray4,
     textColor: basicColors.gray4,
     textColorStrong: basicColors.white,
@@ -61,8 +70,8 @@ const darkTheme: GrafanaTheme = {
   },
   background: {
     dropdown: basicColors.dark3,
-    scrollbar: '#aeb5df',
-    scrollbar2: '#3a3a3a',
+    scrollbar: basicColors.dark9,
+    scrollbar2: basicColors.dark9,
   },
 };
 

+ 6 - 5
packages/grafana-ui/src/themes/default.ts

@@ -1,10 +1,12 @@
-const theme = {
+import { GrafanaThemeCommons } from '../types/theme';
+
+const theme: GrafanaThemeCommons = {
   name: 'Grafana Default',
   typography: {
     fontFamily: {
-      sansSerif: "'Roboto', Helvetica, Arial, sans-serif;",
-      serif: "Georgia, 'Times New Roman', Times, serif;",
-      monospace: "Menlo, Monaco, Consolas, 'Courier New', monospace;",
+      sansSerif: "'Roboto', Helvetica, Arial, sans-serif",
+      serif: "Georgia, 'Times New Roman', Times, serif",
+      monospace: "Menlo, Monaco, Consolas, 'Courier New', monospace",
     },
     size: {
       base: '13px',
@@ -45,7 +47,6 @@ const theme = {
     s: '0.2rem',
     m: '1rem',
     l: '1.5rem',
-    xl: '3rem',
     gutter: '30px',
   },
   border: {

+ 15 - 0
packages/grafana-ui/src/themes/getTheme.ts

@@ -0,0 +1,15 @@
+import darkTheme from './dark';
+import lightTheme from './light';
+import { GrafanaTheme } from '../types/theme';
+
+let themeMock: ((name?: string) => GrafanaTheme) | null;
+
+export const getTheme = (name?: string) =>
+  (themeMock && themeMock(name)) || (name === 'light' ? lightTheme : darkTheme);
+
+export const mockTheme = (mock: (name?: string) => GrafanaTheme) => {
+  themeMock = mock;
+  return () => {
+    themeMock = null;
+  };
+};

+ 3 - 13
packages/grafana-ui/src/themes/index.ts

@@ -1,14 +1,4 @@
-import darkTheme from './dark';
-import lightTheme from './light';
-import { GrafanaTheme } from '../types/theme';
+import { ThemeContext, withTheme } from './ThemeContext';
+import { getTheme, mockTheme } from './getTheme';
 
-let themeMock: ((name?: string) => GrafanaTheme) | null;
-
-export let getTheme = (name?: string) => (themeMock && themeMock(name)) || (name === 'light' ? lightTheme : darkTheme);
-
-export const mockTheme = (mock: (name?: string) => GrafanaTheme) => {
-  themeMock = mock;
-  return () => {
-    themeMock = null;
-  };
-};
+export { ThemeContext, withTheme, mockTheme, getTheme };

+ 22 - 13
packages/grafana-ui/src/themes/light.ts

@@ -5,11 +5,16 @@ import { GrafanaTheme, GrafanaThemeType } from '../types/theme';
 const basicColors = {
   black: '#000000',
   white: '#ffffff',
-  dark1: '#13161d',
-  dark2: '#1e2028',
-  dark3: '#303133',
-  dark4: '#35373f',
-  dark5: '#41444b',
+  dark1: '#1e2028',
+  dark2: '#41444b',
+  dark3: '#303133', // not used in light theme
+  dark4: '#35373f', // not used in light theme
+  dark5: '#41444b', // not used in light theme
+  dark6: '#41444b', // not used in light theme
+  dark7: '#41444b', // not used in light theme
+  dark8: '#2f2f32', // not used in light theme
+  dark9: '#343436', // not used in light theme
+  dark10: '#424345', // not used in light theme
   gray1: '#52545c',
   gray2: '#767980',
   gray3: '#acb6bf',
@@ -18,15 +23,19 @@ const basicColors = {
   gray6: '#e9edf2',
   gray7: '#f7f8fa',
   grayBlue: '#212327', // not used in light theme
+  blueBase: '#3274d9',
+  blueShade: '#1f60c4',
+  blueLight: '#5794f2',
+  blueFaint: '#f5f9ff',
+  redBase: '#e02f44',
+  redShade: '#c4162a',
+  greenBase: '#3eb15b',
+  greenShade: '#369b4f',
   blue: '#0083b3',
-  blueDark: '#005f81',
-  blueLight: '#00a8e6',
-  green: '#3aa655',
   red: '#d44939',
   yellow: '#ff851b',
-  pink: '#e671b8',
   purple: '#9954bb',
-  variable: '#0083b3',
+  variable: '#007580',
   orange: '#ff7941',
 };
 
@@ -39,13 +48,13 @@ const lightTheme: GrafanaTheme = {
     variable: basicColors.blue,
     inputBlack: '#09090b',
     queryRed: basicColors.red,
-    queryGreen: basicColors.green,
+    queryGreen: basicColors.greenBase,
     queryPurple: basicColors.purple,
     queryKeyword: basicColors.blue,
     queryOrange: basicColors.orange,
-    online: '#01a64f',
+    online: basicColors.greenShade,
     warn: '#f79520',
-    critical: '#ec2128',
+    critical: basicColors.redShade,
     bodyBg: basicColors.gray7,
     pageBg: basicColors.gray7,
     bodyColor: basicColors.gray1,

+ 17 - 5
packages/grafana-ui/src/types/theme.ts

@@ -3,8 +3,7 @@ export enum GrafanaThemeType {
   Dark = 'dark',
 }
 
-export interface GrafanaTheme {
-  type: GrafanaThemeType;
+export interface GrafanaThemeCommons {
   name: string;
   // TODO: not sure if should be a part of theme
   brakpoints: {
@@ -62,6 +61,10 @@ export interface GrafanaTheme {
       m: string;
     };
   };
+}
+
+export interface GrafanaTheme extends GrafanaThemeCommons {
+  type: GrafanaThemeType;
   background: {
     dropdown: string;
     scrollbar: string;
@@ -75,6 +78,11 @@ export interface GrafanaTheme {
     dark3: string;
     dark4: string;
     dark5: string;
+    dark6: string;
+    dark7: string;
+    dark8: string;
+    dark9: string;
+    dark10: string;
     gray1: string;
     gray2: string;
     gray3: string;
@@ -87,12 +95,16 @@ export interface GrafanaTheme {
 
     // Accent colors
     blue: string;
+    blueBase: string;
+    blueShade: string;
     blueLight: string;
-    blueDark: string;
-    green: string;
+    blueFaint: string;
+    redBase: string;
+    redShade: string;
+    greenBase: string;
+    greenShade: string;
     red: string;
     yellow: string;
-    pink: string;
     purple: string;
     variable: string;
     orange: string;

+ 12 - 8
packages/grafana-ui/src/utils/colors.ts

@@ -1,4 +1,8 @@
-import _ from 'lodash';
+import map from 'lodash/map';
+import sortBy from 'lodash/sortBy';
+import flattenDeep from 'lodash/flattenDeep';
+import chunk from 'lodash/chunk';
+import zip from 'lodash/zip';
 import tinycolor from 'tinycolor2';
 
 export const PALETTE_ROWS = 4;
@@ -69,16 +73,16 @@ export const colors = [
 ];
 
 function sortColorsByHue(hexColors: string[]) {
-  const hslColors = _.map(hexColors, hexToHsl);
+  const hslColors = map(hexColors, hexToHsl);
 
-  const sortedHSLColors = _.sortBy(hslColors, ['h']);
-  const chunkedHSLColors = _.chunk(sortedHSLColors, PALETTE_ROWS);
-  const sortedChunkedHSLColors = _.map(chunkedHSLColors, chunk => {
-    return _.sortBy(chunk, 'l');
+  const sortedHSLColors = sortBy(hslColors, ['h']);
+  const chunkedHSLColors = chunk(sortedHSLColors, PALETTE_ROWS);
+  const sortedChunkedHSLColors = map(chunkedHSLColors, chunk => {
+    return sortBy(chunk, 'l');
   });
-  const flattenedZippedSortedChunkedHSLColors = _.flattenDeep(_.zip(...sortedChunkedHSLColors));
+  const flattenedZippedSortedChunkedHSLColors = flattenDeep(zip(...sortedChunkedHSLColors));
 
-  return _.map(flattenedZippedSortedChunkedHSLColors, hslToHex);
+  return map(flattenedZippedSortedChunkedHSLColors, hslToHex);
 }
 
 function hexToHsl(color: string) {

+ 10 - 0
packages/grafana-ui/src/utils/generatedFileBanner.ts

@@ -0,0 +1,10 @@
+export const renderGeneratedFileBanner = (themeFile: string, templateFile: string) => `/***
+ * !!! THIS FILE WAS GENERATED AUTOMATICALLY !!!
+ *
+ * Do not modify this file!
+ * - Edit ${themeFile} to regenerate
+ * - Edit ${templateFile} to update template
+ *
+ * !!! THIS FILE WAS GENERATED AUTOMATICALLY !!!
+ */
+`;

+ 1 - 0
packages/grafana-ui/src/utils/index.ts

@@ -2,3 +2,4 @@ export * from './processTimeSeries';
 export * from './valueFormats/valueFormats';
 export * from './colors';
 export * from './namedColorsPalette';
+export { getMappedValue } from './valueMappings';

+ 2 - 2
packages/grafana-ui/src/utils/namedColorsPalette.ts

@@ -1,5 +1,5 @@
-import { flatten } from 'lodash';
-import { GrafanaThemeType } from '../types';
+import flatten from 'lodash/flatten';
+import { GrafanaThemeType } from '../types/theme';
 import tinycolor from 'tinycolor2';
 
 type Hue = 'green' | 'yellow' | 'red' | 'blue' | 'orange' | 'purple';

+ 2 - 2
packages/grafana-ui/src/utils/processTimeSeries.ts

@@ -1,5 +1,5 @@
 // Libraries
-import _ from 'lodash';
+import isNumber from 'lodash/isNumber';
 
 import { colors } from './colors';
 
@@ -75,7 +75,7 @@ export function processTimeSeries({ timeSeries, nullValueMode }: Options): TimeS
       }
 
       if (currentValue !== null) {
-        if (_.isNumber(currentValue)) {
+        if (isNumber(currentValue)) {
           total += currentValue;
           allIsNull = false;
           nonNulls++;

+ 1 - 1
packages/grafana-ui/src/utils/storybook/withTheme.tsx

@@ -2,7 +2,7 @@ import React from 'react';
 import { RenderFunction } from '@storybook/react';
 import { ThemeContext } from '../../themes/ThemeContext';
 import { select } from '@storybook/addon-knobs';
-import { getTheme } from '../../themes';
+import { getTheme } from '../../themes/index';
 import { GrafanaThemeType } from '../../types';
 
 const ThemableStory: React.FunctionComponent<{}> = ({ children }) => {

+ 12 - 0
packages/grafana-ui/tsconfig.build.json

@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "exclude": [
+    "dist",
+    "node_modules",
+    "src/utils/storybook",
+    "**/*.test.ts",
+    "**/*.test.tsx",
+    "**/*.story.tsx",
+    "**/*.tmpl.ts"
+  ]
+}

+ 4 - 2
packages/grafana-ui/tsconfig.json

@@ -5,13 +5,15 @@
   "compilerOptions": {
     "rootDirs": [".", "stories"],
     "module": "esnext",
-    "outDir": "dist",
+    "outDir": "compiled",
     "declaration": true,
+    "declarationDir": "dist",
     "strict": true,
     "alwaysStrict": true,
     "noImplicitAny": true,
     "strictNullChecks": true,
     "typeRoots": ["./node_modules/@types", "types"],
-    "skipLibCheck": true // Temp workaround for Duplicate identifier tsc errors
+    "skipLibCheck": true, // Temp workaround for Duplicate identifier tsc errors,
+    "removeComments": false
   }
 }

+ 1 - 1
pkg/api/admin_users.go

@@ -3,7 +3,7 @@ package api
 import (
 	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/util"
 )

+ 1 - 1
pkg/api/dashboard.go

@@ -13,8 +13,8 @@ import (
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/components/dashdiffs"
 	"github.com/grafana/grafana/pkg/components/simplejson"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/plugins"
 	"github.com/grafana/grafana/pkg/services/guardian"

+ 1 - 1
pkg/api/dashboard_snapshot.go

@@ -10,7 +10,7 @@ import (
 	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/components/simplejson"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/guardian"
 	"github.com/grafana/grafana/pkg/setting"

+ 1 - 1
pkg/api/dataproxy.go

@@ -2,7 +2,7 @@ package api
 
 import (
 	"github.com/grafana/grafana/pkg/api/pluginproxy"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/plugins"
 )

+ 1 - 0
pkg/api/frontendsettings.go

@@ -167,6 +167,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *m.ReqContext) (map[string]interf
 		"externalUserMngLinkUrl":     setting.ExternalUserMngLinkUrl,
 		"externalUserMngLinkName":    setting.ExternalUserMngLinkName,
 		"viewersCanEdit":             setting.ViewersCanEdit,
+		"editorsCanOwn":              hs.Cfg.EditorsCanOwn,
 		"disableSanitizeHtml":        hs.Cfg.DisableSanitizeHtml,
 		"buildInfo": map[string]interface{}{
 			"version":       setting.BuildVersion,

+ 1 - 1
pkg/api/login.go

@@ -7,9 +7,9 @@ import (
 
 	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/login"
-	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/middleware"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"

+ 2 - 2
pkg/api/login_oauth.go

@@ -16,12 +16,12 @@ import (
 	"golang.org/x/oauth2"
 
 	"github.com/grafana/grafana/pkg/bus"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/login"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/login/social"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"
-	"github.com/grafana/grafana/pkg/social"
 )
 
 var (

+ 1 - 1
pkg/api/org.go

@@ -3,7 +3,7 @@ package api
 import (
 	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/util"

+ 1 - 1
pkg/api/org_invite.go

@@ -6,7 +6,7 @@ import (
 	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/events"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/util"

+ 1 - 1
pkg/api/search.go

@@ -4,7 +4,7 @@ import (
 	"strconv"
 
 	"github.com/grafana/grafana/pkg/bus"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/search"
 )

+ 1 - 1
pkg/api/signup.go

@@ -4,7 +4,7 @@ import (
 	"github.com/grafana/grafana/pkg/api/dtos"
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/events"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/util"

+ 1 - 1
pkg/api/user.go

@@ -121,7 +121,7 @@ func GetUserTeams(c *m.ReqContext) Response {
 	return getUserTeamList(c.OrgId, c.ParamsInt64(":id"))
 }
 
-func getUserTeamList(userID int64, orgID int64) Response {
+func getUserTeamList(orgID int64, userID int64) Response {
 	query := m.GetTeamsByUserQuery{OrgId: orgID, UserId: userID}
 
 	if err := bus.Dispatch(&query); err != nil {

+ 1 - 1
pkg/cmd/grafana-server/main.go

@@ -14,8 +14,8 @@ import (
 	"time"
 
 	"github.com/grafana/grafana/pkg/extensions"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics"
 	_ "github.com/grafana/grafana/pkg/services/alerting/conditions"
 	_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
 	"github.com/grafana/grafana/pkg/setting"

+ 3 - 3
pkg/cmd/grafana-server/server.go

@@ -16,9 +16,9 @@ import (
 	"github.com/grafana/grafana/pkg/api/routing"
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/login"
+	"github.com/grafana/grafana/pkg/login/social"
 	"github.com/grafana/grafana/pkg/middleware"
 	"github.com/grafana/grafana/pkg/registry"
-	"github.com/grafana/grafana/pkg/social"
 
 	"golang.org/x/sync/errgroup"
 
@@ -28,8 +28,9 @@ import (
 
 	// self registering services
 	_ "github.com/grafana/grafana/pkg/extensions"
+	_ "github.com/grafana/grafana/pkg/infra/metrics"
 	_ "github.com/grafana/grafana/pkg/infra/serverlock"
-	_ "github.com/grafana/grafana/pkg/metrics"
+	_ "github.com/grafana/grafana/pkg/infra/tracing"
 	_ "github.com/grafana/grafana/pkg/plugins"
 	_ "github.com/grafana/grafana/pkg/services/alerting"
 	_ "github.com/grafana/grafana/pkg/services/auth"
@@ -39,7 +40,6 @@ import (
 	_ "github.com/grafana/grafana/pkg/services/rendering"
 	_ "github.com/grafana/grafana/pkg/services/search"
 	_ "github.com/grafana/grafana/pkg/services/sqlstore"
-	_ "github.com/grafana/grafana/pkg/tracing"
 )
 
 func NewGrafanaServer() *GrafanaServerImpl {

+ 0 - 0
pkg/metrics/graphitebridge/graphite.go → pkg/infra/metrics/graphitebridge/graphite.go


+ 0 - 0
pkg/metrics/graphitebridge/graphite_test.go → pkg/infra/metrics/graphitebridge/graphite_test.go


+ 0 - 0
pkg/metrics/metrics.go → pkg/infra/metrics/metrics.go


+ 1 - 1
pkg/metrics/service.go → pkg/infra/metrics/service.go

@@ -3,8 +3,8 @@ package metrics
 import (
 	"context"
 
+	"github.com/grafana/grafana/pkg/infra/metrics/graphitebridge"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics/graphitebridge"
 	"github.com/grafana/grafana/pkg/registry"
 	"github.com/grafana/grafana/pkg/setting"
 )

+ 1 - 1
pkg/metrics/settings.go → pkg/infra/metrics/settings.go

@@ -5,7 +5,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/grafana/grafana/pkg/metrics/graphitebridge"
+	"github.com/grafana/grafana/pkg/infra/metrics/graphitebridge"
 	"github.com/grafana/grafana/pkg/setting"
 	"github.com/prometheus/client_golang/prometheus"
 )

+ 0 - 0
pkg/tracing/tracing.go → pkg/infra/tracing/tracing.go


+ 0 - 0
pkg/tracing/tracing_test.go → pkg/infra/tracing/tracing_test.go


+ 1 - 1
pkg/infra/usagestats/service.go

@@ -5,8 +5,8 @@ import (
 	"time"
 
 	"github.com/grafana/grafana/pkg/bus"
+	"github.com/grafana/grafana/pkg/login/social"
 	"github.com/grafana/grafana/pkg/services/sqlstore"
-	"github.com/grafana/grafana/pkg/social"
 
 	"github.com/grafana/grafana/pkg/log"
 	"github.com/grafana/grafana/pkg/registry"

+ 1 - 1
pkg/infra/usagestats/usage_stats.go

@@ -9,7 +9,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/plugins"
 	"github.com/grafana/grafana/pkg/setting"

+ 0 - 0
pkg/social/common.go → pkg/login/social/common.go


+ 0 - 0
pkg/social/generic_oauth.go → pkg/login/social/generic_oauth.go


+ 0 - 0
pkg/social/github_oauth.go → pkg/login/social/github_oauth.go


+ 0 - 0
pkg/social/gitlab_oauth.go → pkg/login/social/gitlab_oauth.go


+ 0 - 0
pkg/social/google_oauth.go → pkg/login/social/google_oauth.go


+ 0 - 0
pkg/social/grafana_com_oauth.go → pkg/login/social/grafana_com_oauth.go


+ 0 - 0
pkg/social/social.go → pkg/login/social/social.go


+ 1 - 1
pkg/middleware/request_metrics.go

@@ -6,7 +6,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"gopkg.in/macaron.v1"
 )
 

+ 1 - 1
pkg/services/alerting/eval_handler.go

@@ -5,8 +5,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics"
 )
 
 type DefaultEvalHandler struct {

+ 1 - 1
pkg/services/alerting/notifier.go

@@ -7,8 +7,8 @@ import (
 
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/components/imguploader"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics"
 	"github.com/grafana/grafana/pkg/services/rendering"
 	"github.com/grafana/grafana/pkg/setting"
 

+ 1 - 1
pkg/services/alerting/reader.go

@@ -5,8 +5,8 @@ import (
 	"time"
 
 	"github.com/grafana/grafana/pkg/bus"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 )
 

+ 1 - 1
pkg/services/alerting/result_handler.go

@@ -5,8 +5,8 @@ import (
 
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/components/simplejson"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/annotations"
 	"github.com/grafana/grafana/pkg/services/rendering"

+ 1 - 1
pkg/services/sqlstore/dashboard.go

@@ -5,7 +5,7 @@ import (
 	"time"
 
 	"github.com/grafana/grafana/pkg/bus"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/search"
 	"github.com/grafana/grafana/pkg/util"

+ 1 - 1
pkg/services/sqlstore/datasource.go

@@ -7,7 +7,7 @@ import (
 
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/components/securejsondata"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 	m "github.com/grafana/grafana/pkg/models"
 )
 

+ 5 - 0
pkg/setting/setting.go

@@ -237,6 +237,9 @@ type Cfg struct {
 	LoginMaxInactiveLifetimeDays int
 	LoginMaxLifetimeDays         int
 	TokenRotationIntervalMinutes int
+
+	// User
+	EditorsCanOwn bool
 }
 
 type CommandLineArgs struct {
@@ -644,6 +647,7 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
 	AdminUser = security.Key("admin_user").String()
 	AdminPassword = security.Key("admin_password").String()
 
+	// users
 	users := iniFile.Section("users")
 	AllowUserSignUp = users.Key("allow_sign_up").MustBool(true)
 	AllowUserOrgCreate = users.Key("allow_org_create").MustBool(true)
@@ -657,6 +661,7 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
 	ExternalUserMngLinkName = users.Key("external_manage_link_name").String()
 	ExternalUserMngInfo = users.Key("external_manage_info").String()
 	ViewersCanEdit = users.Key("viewers_can_edit").MustBool(false)
+	cfg.EditorsCanOwn = users.Key("editors_can_own").MustBool(false)
 
 	// auth
 	auth := iniFile.Section("auth")

+ 1 - 1
pkg/tsdb/cloudwatch/cloudwatch.go

@@ -24,7 +24,7 @@ import (
 	"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
 	"github.com/grafana/grafana/pkg/components/null"
 	"github.com/grafana/grafana/pkg/components/simplejson"
-	"github.com/grafana/grafana/pkg/metrics"
+	"github.com/grafana/grafana/pkg/infra/metrics"
 )
 
 type CloudWatchExecutor struct {

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