diff --git a/.betterer.results b/.betterer.results
index d9446d6b110..bb7e73b4731 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -256,6 +256,17 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
+ "packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "3"]
+ ],
+ "packages/grafana-data/src/transformations/transformers/nulls/nullToUndefThreshold.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Do not use any type assertions.", "2"]
+ ],
"packages/grafana-data/src/transformations/transformers/reduce.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -796,40 +807,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "packages/grafana-ui/src/components/Graph/GraphContextMenu.tsx:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
- ],
- "packages/grafana-ui/src/components/Graph/utils.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
- ],
- "packages/grafana-ui/src/components/GraphNG/GraphNG.tsx:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
- [0, 0, 0, "Do not use any type assertions.", "5"],
- [0, 0, 0, "Do not use any type assertions.", "6"],
- [0, 0, 0, "Do not use any type assertions.", "7"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "8"],
- [0, 0, 0, "Do not use any type assertions.", "9"],
- [0, 0, 0, "Do not use any type assertions.", "10"],
- [0, 0, 0, "Do not use any type assertions.", "11"]
- ],
- "packages/grafana-ui/src/components/GraphNG/hooks.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
- "packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "3"]
- ],
- "packages/grafana-ui/src/components/GraphNG/nullToUndefThreshold.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
- [0, 0, 0, "Do not use any type assertions.", "2"]
- ],
"packages/grafana-ui/src/components/InfoBox/InfoBox.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -981,11 +958,6 @@ exports[`better eslint`] = {
"packages/grafana-ui/src/components/Tags/Tag.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "packages/grafana-ui/src/components/TimeSeries/utils.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
- ],
"packages/grafana-ui/src/components/ValuePicker/ValuePicker.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
@@ -1032,6 +1004,45 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
+ "packages/grafana-ui/src/graveyard/Graph/GraphContextMenu.tsx:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
+ ],
+ "packages/grafana-ui/src/graveyard/Graph/utils.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
+ ],
+ "packages/grafana-ui/src/graveyard/GraphNG/GraphNG.tsx:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
+ [0, 0, 0, "Do not use any type assertions.", "5"],
+ [0, 0, 0, "Do not use any type assertions.", "6"],
+ [0, 0, 0, "Do not use any type assertions.", "7"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "8"],
+ [0, 0, 0, "Do not use any type assertions.", "9"],
+ [0, 0, 0, "Do not use any type assertions.", "10"],
+ [0, 0, 0, "Do not use any type assertions.", "11"]
+ ],
+ "packages/grafana-ui/src/graveyard/GraphNG/hooks.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
+ "packages/grafana-ui/src/graveyard/GraphNG/nullInsertThreshold.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "3"]
+ ],
+ "packages/grafana-ui/src/graveyard/GraphNG/nullToUndefThreshold.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Do not use any type assertions.", "2"]
+ ],
+ "packages/grafana-ui/src/graveyard/TimeSeries/utils.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Do not use any type assertions.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
+ ],
"packages/grafana-ui/src/options/builder/axis.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -1177,6 +1188,23 @@ exports[`better eslint`] = {
"public/app/core/components/ForgottenPassword/ForgottenPassword.tsx:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"]
],
+ "public/app/core/components/GraphNG/GraphNG.tsx:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
+ [0, 0, 0, "Do not use any type assertions.", "5"],
+ [0, 0, 0, "Do not use any type assertions.", "6"],
+ [0, 0, 0, "Do not use any type assertions.", "7"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "8"],
+ [0, 0, 0, "Do not use any type assertions.", "9"],
+ [0, 0, 0, "Do not use any type assertions.", "10"],
+ [0, 0, 0, "Do not use any type assertions.", "11"]
+ ],
+ "public/app/core/components/GraphNG/hooks.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
"public/app/core/components/Layers/LayerDragDropList.tsx:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"],
[0, 0, 0, "Styles should be written using objects.", "1"],
@@ -1411,6 +1439,11 @@ exports[`better eslint`] = {
[0, 0, 0, "Styles should be written using objects.", "1"],
[0, 0, 0, "Styles should be written using objects.", "2"]
],
+ "public/app/core/components/TimeSeries/utils.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Do not use any type assertions.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
+ ],
"public/app/core/components/TraceToLogs/TagMappingInput.tsx:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"],
[0, 0, 0, "Styles should be written using objects.", "1"],
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 81b5d3e891b..125af1b3853 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -312,9 +312,6 @@
/packages/grafana-ui/src/components/Table/ @grafana/grafana-bi-squad
/packages/grafana-ui/src/components/Gauge/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/BarGauge/ @grafana/dataviz-squad
-/packages/grafana-ui/src/components/GraphNG/ @grafana/dataviz-squad
-/packages/grafana-ui/src/components/Graph/ @grafana/dataviz-squad
-/packages/grafana-ui/src/components/TimeSeries/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/uPlot/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/DataLinks/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/ValuePicker/ @grafana/dataviz-squad
@@ -322,6 +319,9 @@
/packages/grafana-ui/src/components/VizLegend/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/VizRepeater/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/VizTooltip/ @grafana/dataviz-squad
+/packages/grafana-ui/src/graveyard/Graph/ @grafana/dataviz-squad
+/packages/grafana-ui/src/graveyard/GraphNG/ @grafana/dataviz-squad
+/packages/grafana-ui/src/graveyard/TimeSeries/ @grafana/dataviz-squad
/packages/grafana-ui/src/utils/storybook/ @grafana/plugins-platform-frontend
/packages/grafana-data/src/transformations/ @grafana/grafana-bi-squad
/packages/grafana-data/src/**/*logs* @grafana/observability-logs
@@ -366,6 +366,8 @@ cypress.config.js @grafana/grafana-frontend-platform
/public/app/core/components/TimePicker/ @grafana/grafana-frontend-platform
/public/app/core/components/Layers/ @grafana/dataviz-squad
/public/app/core/components/TraceToLogs @grafana/observability-traces-and-profiling
+/public/app/core/components/GraphNG/ @grafana/dataviz-squad
+/public/app/core/components/TimeSeries/ @grafana/dataviz-squad
/public/app/features/all.ts @grafana/grafana-frontend-platform
/public/app/features/admin/ @grafana/grafana-authnz-team
/public/app/features/auth-config/ @grafana/grafana-authnz-team
diff --git a/docs/sources/administration/api-keys/index.md b/docs/sources/administration/api-keys/index.md
index f2e1be18e75..6ea11889724 100644
--- a/docs/sources/administration/api-keys/index.md
+++ b/docs/sources/administration/api-keys/index.md
@@ -48,7 +48,7 @@ To follow these instructions, you need at least one of the following:
To create an API, complete the following steps:
1. Sign in to Grafana.
-1. Click **Administration** in the left-side menu and select **API Keys**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **API Keys**.
1. Click **Add API key**.
1. Enter a unique name for the key.
1. In the **Role** field, select one of the following access levels you want to assign to the key.
@@ -101,7 +101,7 @@ For more information about permissions, refer to [Roles and permissions]({{< rel
To migrate all API keys to service accounts, complete the following steps:
-1. Sign in to Grafana, point to **Configuration** (the gear icon), and click **API Keys**.
+1. Sign in to Grafana, point to **Administration**, **Users and access**, and click **API Keys**.
1. In the top of the page, find the section which says **Switch from API keys to service accounts**
1. Click **Migrate to service accounts now**.
1. A confirmation window will appear, asking to confirm the migration. Click **Yes, migrate now** if you are willing to continue.
@@ -110,7 +110,7 @@ To migrate all API keys to service accounts, complete the following steps:
To migrate a single API key to a service account, complete the following steps:
1. Sign in to Grafana.
-1. Click **Administration** in the left-side menu and select **API Keys**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **API Keys**.
1. Find the API Key you want to migrate.
1. Click **Migrate to service account**.
diff --git a/docs/sources/administration/enterprise-licensing/_index.md b/docs/sources/administration/enterprise-licensing/_index.md
index 966e0889d72..fc8e07e7123 100644
--- a/docs/sources/administration/enterprise-licensing/_index.md
+++ b/docs/sources/administration/enterprise-licensing/_index.md
@@ -52,7 +52,7 @@ There is more than one way to add the license to a Grafana instance:
This is the preferred option for single instance installations of Grafana Enterprise.
1. Sign in as a Grafana server administrator.
-1. Click **Administration > Stats and license** in the side navigation menu.
+1. Click **Administration > General > Stats and license** in the side navigation menu.
1. Click **Upload a new token**.
1. Select your license file, and upload it.
@@ -207,6 +207,8 @@ To determine the number of active users:
1. Click **Administration** in the side navigation menu.
+1. Click **General**.
+
1. Click **Stats and license**.
1. Review the utilization count on the **Utilization** panel.
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md
index 6f6a35e5eea..fa06cd3aa02 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md
@@ -112,6 +112,6 @@ In this task you configure Grafana Enterprise to validate the license with AWS i
### Task 4: Start or restart Grafana
1. To restart Grafana and activate your license, update the service running Grafana to use the latest revision of the task definition that you created.
-1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to **Administration > Stats and license** to validate that your license is active.
+1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to **Administration > General > Stats and license** to validate that your license is active.
For more information about validating that your license is active, refer to [Grafana Enterprise license restrictions]({{< relref "../../#grafana-enterprise-license-restrictions" >}}).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md
index a63c1af461d..49060c0989d 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md
@@ -123,7 +123,7 @@ To restart Grafana on a Kubernetes cluster,
1. Run the command `kubectl rollout restart deployment my-release`.
-1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to **Administration > Stats and license** to validate that your license is active.
+1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to **Administration > General > Stats and license** to validate that your license is active.
For more information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/start-restart-grafana/" >}}).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md
index 74a1152a1a3..56ba176742d 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md
@@ -36,7 +36,7 @@ You can use AWS Marketplace to make the following modifications to your Grafana
1. Sign in to Grafana as a Server Administrator.
-1. Click **Administration** in the side navigation menu, and then **Stats and license**.
+1. Click **Administration** in the side navigation menu, **General**, and then **Stats and license**.
1. In the **Token** section under **Enterprise License**, click **Renew token**.
diff --git a/docs/sources/administration/organization-management/index.md b/docs/sources/administration/organization-management/index.md
index 0d93b93e5d6..a332c8110db 100644
--- a/docs/sources/administration/organization-management/index.md
+++ b/docs/sources/administration/organization-management/index.md
@@ -59,7 +59,7 @@ Complete this task when you want to view a list of existing organizations.
**To view a list of organizations:**
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Organizations**.
+1. Click **Administration** in the left-side menu, **General**, and then **Organizations**.
## Create an organization
@@ -72,7 +72,7 @@ Create an organization when you want to isolate dashboards and other resources f
**To create an organization:**
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Organizations**.
+1. Click **Administration** in the left-side menu, **General**, and then **Organizations**.
1. Click **+ New org**.
1. Enter the name of the new organization and click **Create**.
@@ -100,7 +100,7 @@ Deleting the organization also deletes all teams and dashboards associated the o
**To delete an organization:**
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Organizations**.
+1. Click **Administration** in the left-side menu, **General**, and then **Organizations**.
1. Click the red **X** next to the organization that you want to delete.
1. Click **Delete**.
@@ -115,6 +115,6 @@ Edit an organization when you want to change its name.
**To edit an organization:**
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Organizations**.
+1. Click **Administration** in the left-side menu, **General**, and then **Organizations**.
1. Click the organization you want to edit.
1. Update the organization name and click **Update**.
diff --git a/docs/sources/administration/organization-preferences/index.md b/docs/sources/administration/organization-preferences/index.md
index 211deadfa17..913f6ca8345 100644
--- a/docs/sources/administration/organization-preferences/index.md
+++ b/docs/sources/administration/organization-preferences/index.md
@@ -44,6 +44,7 @@ Grafana server administrators and organization administrators can change organiz
Follow these instructions if you are a Grafana Server Admin.
1. Click **Administration** in the left-side menu.
+1. Click **General**.
1. Click **Organizations**.
1. In the organization list, click the name of the organization that you want to change.
1. In **Name**, enter the new organization name.
@@ -54,6 +55,7 @@ Follow these instructions if you are a Grafana Server Admin.
If you are an Organization Admin, follow these steps:
1. Click **Administration** in the left-side menu.
+1. Click **General**.
1. Click **Default preferences**.
1. In **Organization name**, enter the new name.
1. Click **Update organization name**.
@@ -63,7 +65,7 @@ If you are an Organization Admin, follow these steps:
Organization administrators and team administrators can change team names and email addresses.
To change the team name or email, follow these steps:
-1. Click **Administration** in the left-side menu and select **Team**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Team**.
1. In the team list, click the name of the team that you want to change.
1. Click the **Settings** tab.
1. In the Team details section, you can edit the following:
@@ -112,6 +114,7 @@ To see what the current settings are, refer to [View server settings]({{< relref
Organization administrators can change the UI theme for all users in an organization.
1. Click **Administration** in the left-side menu.
+1. Click **General**.
1. Click **Default preferences**.
1. In the Preferences section, select the UI theme.
1. Click **Save**.
@@ -120,7 +123,7 @@ Organization administrators can change the UI theme for all users in an organiza
Organization and team administrators can change the UI theme for all users on a team.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the team for which you want to change the UI theme.
1. Click the **Settings** tab.
1. In the Preferences section, select the UI theme.
@@ -149,6 +152,7 @@ Grafana server administrators can choose a default timezone for all users on the
Organization administrators can choose a default timezone for their organization.
1. Click **Administration** in the left-side menu.
+1. Click **General**.
1. Click **Default preferences**.
1. Click to select an option in the **Timezone** list. **Default** is either the browser local timezone or the timezone selected at a higher level.
1. Click **Save**.
@@ -157,7 +161,7 @@ Organization administrators can choose a default timezone for their organization
Organization administrators and team administrators can choose a default timezone for all users on a team.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the team for which you want to change the timezone.
1. Click the **Settings** tab.
1. Click to select an option in the **Timezone** list. **Default** is either the browser local timezone or the timezone selected at a higher level.
@@ -209,6 +213,7 @@ Organization administrators can choose a default home dashboard for their organi
1. Navigate to the dashboard you want to set as the home dashboard.
1. Click the star next to the dashboard title to mark the dashboard as a favorite if it is not already.
1. Click **Administration** in the left-side menu.
+1. Click **General**.
1. Click **Default preferences**.
1. In the **Home Dashboard** field, select the dashboard that you want to use for your home dashboard. Options include all starred dashboards.
1. Click **Save**.
@@ -219,7 +224,7 @@ Organization administrators and Team Admins can set a default home dashboard for
1. Navigate to the dashboard you want to set as the home dashboard.
1. Click the star next to the dashboard title to mark the dashboard as a favorite if it is not already.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the team for which you want to change the home dashboard.
1. Click the **Settings** tab.
1. In the **Home Dashboard** field, select the dashboard that you want to use for your home dashboard. Options include all starred dashboards.
@@ -246,6 +251,7 @@ Grafana server administrators can change the default Grafana UI language for all
Organization administrators can change the language for all users in an organization.
1. Click **Administration** in the left-side menu.
+1. Click **General**.
1. Click **Default preferences**.
1. In the Preferences section, select an option in the **Language** dropdown.
1. Click **Save**.
@@ -254,7 +260,7 @@ Organization administrators can change the language for all users in an organiza
Organization and team administrators can set a default language for all users on a team.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the team for which you want to change the language.
1. Click the **Settings** tab.
1. In the Preferences section, select an option in the **Language** dropdown.
diff --git a/docs/sources/administration/plugin-management/index.md b/docs/sources/administration/plugin-management/index.md
index bf84e299280..2fd0da04432 100644
--- a/docs/sources/administration/plugin-management/index.md
+++ b/docs/sources/administration/plugin-management/index.md
@@ -85,13 +85,13 @@ Before following the steps below, make sure you are logged in as a Grafana admin
-Administrators can find the Plugin catalog at **Administration > Plugins**.
+Administrators can find the Plugin catalog at **Administration > Plugins and data > Plugins**.
### Browse plugins
To browse for available plugins:
-1. In Grafana, click **Administration > Plugins** in the side navigation menu to view installed plugins.
+1. In Grafana, click **Administration > Plugins and data > Plugins** in the side navigation menu to view installed plugins.
1. Click the **All** filter to browse all available plugins.
1. Click the **Data sources**, **Panels**, or **Applications** buttons to filter by plugin type.
@@ -99,7 +99,7 @@ To browse for available plugins:
To install a plugin:
-1. In Grafana, click **Administration > Plugins** in the side navigation menu to view installed plugins.
+1. In Grafana, click **Administration > Plugins and data > Plugins** in the side navigation menu to view installed plugins.
1. Click the **All** filter to browse all available plugins.
1. Browse and find a plugin.
1. Click on the plugin logo.
@@ -111,7 +111,7 @@ When the update is complete, you see a confirmation message that the installatio
To update a plugin:
-1. In Grafana, click **Administration > Plugins** in the side navigation menu to view installed plugins.
+1. In Grafana, click **Administration > Plugins and data > Plugins** in the side navigation menu to view installed plugins.
1. Click on the plugin logo.
1. Click **Update**.
@@ -121,7 +121,7 @@ When the update is complete, you see a confirmation message that the update was
To uninstall a plugin:
-1. In Grafana, click **Administration > Plugins** in the side navigation menu to view installed plugins.
+1. In Grafana, click **Administration > Plugins and data > Plugins** in the side navigation menu to view installed plugins.
1. Click on the plugin logo.
1. Click **Uninstall**.
diff --git a/docs/sources/administration/provisioning/index.md b/docs/sources/administration/provisioning/index.md
index 0f3c5f1e846..3a96f6e3111 100644
--- a/docs/sources/administration/provisioning/index.md
+++ b/docs/sources/administration/provisioning/index.md
@@ -157,6 +157,8 @@ datasources:
password:
# Sets the basic authorization password.
basicAuthPassword:
+ # Sets the version. Used to compare versions when
+ # updating. Ignored when creating a new data source.
version: 1
# Allows users to edit data sources from the
# Grafana UI.
diff --git a/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md b/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md
index a86cc311720..5f442a00dfa 100644
--- a/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md
+++ b/docs/sources/administration/roles-and-permissions/access-control/assign-rbac-roles/index.md
@@ -54,14 +54,14 @@ In both cases, the assignment applies only to the user, team or service account
For more information about switching organizations, refer to [Switch organizations]({{< relref "../../../user-management/user-preferences/_index.md#switch-organizations" >}}).
-3. In the left-side menu, click **Administration** and then **Users**, **Teams**, or **Service accounts**.
+3. In the left-side menu, click **Administration**, **Users and access**, and then **Users**, **Teams**, or **Service accounts**.
4. In the **Role** column, select the fixed role that you want to assign to the user, team, or service account.
5. Click **Update**.
**To assign a fixed role as a server administrator:**
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. In the Organizations section, click **Change role**.
1. Select a role within an organization that you want to assign to the user.
diff --git a/docs/sources/administration/stats-and-license/index.md b/docs/sources/administration/stats-and-license/index.md
index 52255d2e021..1643fd505cf 100644
--- a/docs/sources/administration/stats-and-license/index.md
+++ b/docs/sources/administration/stats-and-license/index.md
@@ -34,7 +34,7 @@ If you are a Grafana server administrator, use the Settings tab to view the sett
### View server settings
1. Log in to your Grafana server with an account that has the Grafana Admin flag set.
-1. Click **Administration** in the left-side menu, and then **Settings**.
+1. Click **Administration** in the left-side menu, **General**, and then **Settings**.
### Available settings
@@ -51,7 +51,7 @@ If you are a Grafana server admin, then you can view useful statistics about you
### View server stats
1. Log in to your Grafana server with an account that has the Grafana Admin flag set.
-1. Click **Administration** in the left-side menu, and then **Stats and license**.
+1. Click **Administration** in the left-side menu, **General**, and then **Stats and license**.
### Available stats
diff --git a/docs/sources/administration/team-management/index.md b/docs/sources/administration/team-management/index.md
index 9ade42e2555..747f55e1971 100644
--- a/docs/sources/administration/team-management/index.md
+++ b/docs/sources/administration/team-management/index.md
@@ -45,7 +45,7 @@ A user can belong to multiple teams.
To create a team:
1. Sign in to Grafana as an organization administrator or team administrator.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click **New Team**.
1. Complete the fields and click **Create**.
1. Click **Add member**.
@@ -59,7 +59,7 @@ Add a team member to an existing team whenever you want to provide access to tea
To add a team member:
1. Sign in to Grafana as an organization administrator.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the name of the team to which you want to add members, and click **Add member**.
1. Locate and select a user.
1. Choose if you want to add the user as a team Member or an Admin.
@@ -72,7 +72,7 @@ Complete this task when you want to add or modify team member permissions.
To grant team member permissions:
1. Sign in to Grafana as an organization administrator or a team administrator.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the name of the team for which you want to add or modify team member permissions.
1. In the team member list, find and click the user that you want to change. You can use the search field to filter the list if necessary.
1. In the Permission column, select the new user permission level.
@@ -84,7 +84,7 @@ You can remove a team member when you no longer want to apply team permissions t
To remove a team member:
1. Sign in to Grafana as an organization administrator or team administrator.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click a team from which you want to remove a user.
1. Click the **X** next to the name of the user.
@@ -95,7 +95,7 @@ Delete a team when you no longer need it. This action permanently deletes the te
To delete a team:
1. Sign in to Grafana as an organization administrator.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
1. Click the **X** next to the name of the team.
1. Click **Delete**.
@@ -106,7 +106,7 @@ See the complete list of teams in your Grafana organization.
To view a list of teams:
1. Sign in to Grafana as an organization administrator or a team administrator.
-1. Click **Administration** in the left-side menu and select **Teams**.
+1. Click **Administration** in the left-side menu, **Users and access**, and select **Teams**.
The role you use to sign in to Grafana determines how you see team lists.
diff --git a/docs/sources/administration/user-management/manage-org-users/index.md b/docs/sources/administration/user-management/manage-org-users/index.md
index c01c8546679..85c8a8bb882 100644
--- a/docs/sources/administration/user-management/manage-org-users/index.md
+++ b/docs/sources/administration/user-management/manage-org-users/index.md
@@ -38,7 +38,7 @@ You can see a list of users with accounts in your Grafana organization. If neces
**To view a list of organization users**:
1. Sign in to Grafana as an organization administrator.
-1. Navigate to **Administration > Users**.
+1. Navigate to **Administration > Users and access > Users**.
{{% admonition type="note" %}}
If you have [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can also [view a global list of users]({{< relref "../server-user-management#view-a-list-of-users" >}}) in the Server Admin section of Grafana.
@@ -59,7 +59,7 @@ Organization roles sync from the authentication provider on user sign-in. To pre
**To change the organization role of a user**:
1. Sign in to Grafana as an organization administrator.
-1. Navigate to **Administration > Users**.
+1. Navigate to **Administration > Users and access > Users**.
1. Find the user account for which you want to change the role.
If necessary, use the search field to filter the list.
@@ -96,7 +96,7 @@ If you have [server administrator]({{< relref "../../roles-and-permissions/#graf
> **Note**: It might be that you are currently in the proper organization and don't need to switch organizations.
-1. Navigate to **Administration > Users**.
+1. Navigate to **Administration > Users and access > Users**.
1. Click **Organization users**.
1. Click **Invite**.
1. Enter the following information:
@@ -127,7 +127,7 @@ The **Pending Invites** button is only visible if there are unanswered invitatio
**To manage a pending invitation**:
1. Sign in to Grafana as an organization administrator.
-1. Navigate to **Administration > Users**.
+1. Navigate to **Administration > Users and access > Users**.
1. Click **Pending Invites**.
The **Pending Invites** button appears only when there are unaccepted invitations.
@@ -149,7 +149,7 @@ This action does not remove the user account from the Grafana server.
**To remove a user from an organization**:
1. Sign in to Grafana as an organization administrator.
-1. Navigate to **Administration > Users**.
+1. Navigate to **Administration > Users and access > Users**.
1. Find the user account that you want to remove from the organization.
Use the search field to filter the list, if necessary.
diff --git a/docs/sources/administration/user-management/server-user-management/_index.md b/docs/sources/administration/user-management/server-user-management/_index.md
index 50a38bed569..f5d14efcd25 100644
--- a/docs/sources/administration/user-management/server-user-management/_index.md
+++ b/docs/sources/administration/user-management/server-user-management/_index.md
@@ -39,7 +39,7 @@ You can see a list of users with accounts on your Grafana server. This action mi
**To view a list of users**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
{{% admonition type="note" %}}
If you have [organization administrator]({{< relref "../../roles-and-permissions/#organization-roles" >}}) permissions and _not_ [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can still [view of list of users in a given organization]({{< relref "../manage-org-users/#view-a-list-of-organization-users" >}}).
@@ -56,7 +56,7 @@ View user details when you want to see login, and organizations and permissions
**To view user details**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
A user account contains the following sections.
@@ -88,7 +88,7 @@ Edit a user account when you want to modify user login credentials, or delete, d
**To edit a user account**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. Complete any of the following actions, as necessary.
@@ -115,7 +115,7 @@ When you configure advanced authentication using Oauth, SAML, LDAP, or the Auth
**To add a user**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click **New user**.
1. Complete the fields and click **Create user**.
@@ -136,7 +136,7 @@ The force logout action can apply to one device that is logged in to Grafana, or
- Ensure you have Grafana server administrator privileges
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. Scroll down to the Sessions section.
1. Perform one of the following actions:
diff --git a/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md b/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md
index 1d8f5a70ac3..04ddd0dc490 100644
--- a/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md
+++ b/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md
@@ -31,7 +31,7 @@ You are required to specify an Admin role for each organization. The first user
**To add a user to an organization**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. In the Organizations section, click **Add user to organization**.
1. Select an organization and a role.
@@ -57,7 +57,7 @@ Remove a user from an organization when they no longer require access to the das
**To remove a user from an organization**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. In the Organization section, click **Remove from organization** next to the organization from which you want to remove the user.
1. Click **Confirm removal**.
diff --git a/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md b/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md
index d02cc9c19a3..c017f104bdd 100644
--- a/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md
+++ b/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md
@@ -27,7 +27,7 @@ Server administrators are "super-admins" with full permissions to create, read,
**To assign or remove Grafana administrator privileges**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. In the Permissions section, next to Grafana Admin, click **Change**.
1. Click **Yes** or **No**, depending on whether or not you want this user to have the Grafana server administrator role.
diff --git a/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md b/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md
index 3a72c6b15b1..4569a5ac8f2 100644
--- a/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md
+++ b/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md
@@ -21,7 +21,7 @@ Update organization permissions when you want to enhance or restrict a user's ac
**To change a user's organization permissions**:
1. Sign in to Grafana as a server administrator.
-1. Click **Administration** in the left-side menu, and then **Users**.
+1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
1. Click a user.
1. In the Organizations section, click **Change role** for the role you want to change
1. Select another role.
diff --git a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md
index 1452d8774fd..df4d192de5f 100644
--- a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md
+++ b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md
@@ -202,7 +202,7 @@ Create alerts from any panel type. This means you can reuse the queries in the p
1. Navigate to a dashboard in the **Dashboards** section.
2. In the top right corner of the panel, click on the three dots (ellipses).
-3. From the dropdown menu, select **More...** and then choose **Create alert**.
+3. From the dropdown menu, select **More...** and then choose **New alert rule**.
This will open the alert rule form, allowing you to configure and create your alert based on the current panel's query.
diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
index 705b76079a0..9aec15cb7fe 100644
--- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
+++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
@@ -59,7 +59,6 @@ Some features are enabled by default. You can disable these feature by setting t
| Feature toggle name | Description |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `trimDefaults` | Use cue schema to remove values that will be applied automatically |
| `panelTitleSearch` | Search for dashboards using panel title |
| `migrationLocking` | Lock database during migrations |
| `correlations` | Correlations page |
@@ -162,6 +161,8 @@ Experimental features might be changed or removed without prior notice.
| `alertmanagerRemotePrimary` | Enable Grafana to have a remote Alertmanager instance as the primary Alertmanager. |
| `alertmanagerRemoteOnly` | Disable the internal Alertmanager and only use the external one defined. |
| `annotationPermissionUpdate` | Separate annotation permissions from dashboard permissions to allow for more granular control. |
+| `extractFieldsNameDeduplication` | Make sure extracted field names are unique in the dataframe |
+| `dashboardSceneForViewers` | Enables dashboard rendering using Scenes for viewer roles |
## Development feature toggles
diff --git a/docs/sources/tutorials/create-alerts-with-logs/index.md b/docs/sources/tutorials/create-alerts-with-logs/index.md
index d62cd413fb4..faaad9a2839 100644
--- a/docs/sources/tutorials/create-alerts-with-logs/index.md
+++ b/docs/sources/tutorials/create-alerts-with-logs/index.md
@@ -44,7 +44,7 @@ In these steps you'll create an alert and define an expression to evaluate. Thes
### Create a Grafana-managed alert
-1. Navigate in Grafana to **Alerting**, then to **Alert Rules** and click **+ Create alert rule**.
+1. Navigate in Grafana to **Alerting**, then to **Alert Rules** and click **+ New alert rule**.
1. Choose **Grafana Managed Alert** to create an alert that uses expressions.
1. Select your Loki datasource from the drop-down.
1. Enter the alert query in the query editor, switch to **code** mode in the top right corner of the editor to paste the query below:
diff --git a/docs/sources/tutorials/grafana-fundamentals/index.md b/docs/sources/tutorials/grafana-fundamentals/index.md
index abff02d94af..e2dd6d1ed8d 100644
--- a/docs/sources/tutorials/grafana-fundamentals/index.md
+++ b/docs/sources/tutorials/grafana-fundamentals/index.md
@@ -328,7 +328,7 @@ We have now created a dummy webhook endpoint and created a new Alerting Contact
Now that Grafana knows how to notify us, it's time to set up an alert rule:
1. In the sidebar, click **Alert rules**.
-1. Click **Create alert rule**.
+1. Click **New alert rule**.
1. In section **1**, name the rule `fundamentals-test`.
1. For section **2**, select **Grafana Managed Alert** as the rule type. Next, find query box **A**. Choose your Prometheus datasource and enter the same query that we used in our earlier panel: `sum(rate(tns_request_duration_seconds_count[5m])) by(route)`. Click **Run queries**. You should see some data in the graph.
1. Now scroll down to query box **B**. Change the operation from **Reduce** to **Classic condition**. [You can read more about classic and multi-dimensional conditions here](/docs/grafana/latest/alerting/unified-alerting/alerting-rules/create-grafana-managed-rule/#single-and-multi-dimensional-rule). For conditions enter the following: `WHEN last() OF A IS ABOVE 0.2`. Delete query **C**.
diff --git a/docs/sources/tutorials/integrate-hubot/index.md b/docs/sources/tutorials/integrate-hubot/index.md
index d6b769987f1..35299df80b6 100644
--- a/docs/sources/tutorials/integrate-hubot/index.md
+++ b/docs/sources/tutorials/integrate-hubot/index.md
@@ -25,10 +25,7 @@ Grafana 2.0 shipped with a great feature that enables it to render any graph or
No matter what data source you are using, the PNG image of the Graph will look the same as it does in your browser.
-This guide will show you how to install and configure the [Hubot-Grafana](https://github.com/stephenyeargin/hubot-grafana) plugin. This plugin allows you to tell hubot to render any dashboard or graph right from a channel in Slack, Hipchat or Basecamp. The bot will respond with an image of the graph and a link that will take you to the graph.
-
-> _Amazon S3 Required_: The hubot-grafana script will upload the rendered graphs to Amazon S3. This
-> is so Hipchat and Slack can show them reliably (they require the image to be publicly available).
+This guide shows you how to install and configure the [Hubot-Grafana](https://github.com/stephenyeargin/hubot-grafana) plugin. This plugin allows you to tell Hubot to render any dashboard or graph right from a channel in Slack, Basecamp, or any other supported Hubot adapter. The bot will respond with an image of the graph and a link that will take you to the graph.
{{< figure src="/static/img/docs/tutorials/hubot_grafana.png" max-width="800px" >}}
@@ -40,7 +37,7 @@ This guide will show you how to install and configure the [Hubot-Grafana](https:
Hubot is very easy to install and host. If you do not already have a bot up and running please read the official [Getting Started With Hubot](https://hubot.github.com/docs/) guide.
-## Install Hubot-Grafana script
+## Install the Hubot-Grafana script
In your Hubot project repo install the Grafana plugin using `npm`:
@@ -56,18 +53,15 @@ Edit the file external-scripts.json, and add hubot-grafana to the list of plugin
## Configure
-The `hubot-grafana` plugin requires a number of environment variables to be set in order to work properly.
+The Hubot-Grafana plugin requires two environment variables to be set in order to work properly.
```bash
export HUBOT_GRAFANA_HOST=https://play.grafana.org
export HUBOT_GRAFANA_API_KEY=abcd01234deadbeef01234
-export HUBOT_GRAFANA_S3_BUCKET=mybucket
-export HUBOT_GRAFANA_S3_ACCESS_KEY_ID=ABCDEF123456XYZ
-export HUBOT_GRAFANA_S3_SECRET_ACCESS_KEY=aBcD01234dEaDbEef01234
-export HUBOT_GRAFANA_S3_PREFIX=graphs
-export HUBOT_GRAFANA_S3_REGION=us-standard
```
+There are [additional environment variables](https://github.com/stephenyeargin/hubot-grafana?tab=readme-ov-file#general-settings) that you can set to control the appearance of the graphs.
+
### Grafana server side rendering
The hubot plugin will take advantage of the Grafana server side rendering feature that can render any panel on the server using phantomjs. Grafana ships with a phantomjs binary (Linux only).
@@ -80,9 +74,9 @@ To verify that this feature works try the `Direct link to rendered image` link i
You need to set the environment variable `HUBOT_GRAFANA_API_KEY` to a Grafana API Key. You can add these from the API Keys page which you find in the Organization dropdown.
-### Amazon S3
+### Image uploading
-The `S3` options are optional but for the images to work properly in services like Slack and Hipchat they need to publicly available. By specifying the `S3` options the hubot-grafana script will publish the rendered panel to `S3` and it will use that URL when it posts to Slack or Hipchat.
+There are several approaches to uploading the rendered graphs. If you are using Slack, Rocket.Chat, or Telegram, the adapter's native uploader will take care of sending it through their respective API. If your Hubot is hosted on a platform that doesn't support uploads (such as IRC), you can use the [built-in S3 uploader](https://github.com/stephenyeargin/hubot-grafana/wiki/Amazon-S3-Image-Hosting). Note if you configure S3, it will not use the adapter's upload features.
## Hubot commands
diff --git a/docs/sources/whatsnew/whats-new-next/index.md b/docs/sources/whatsnew/whats-new-next/index.md
index 743f5457d0c..61e4375d39d 100644
--- a/docs/sources/whatsnew/whats-new-next/index.md
+++ b/docs/sources/whatsnew/whats-new-next/index.md
@@ -229,6 +229,17 @@ The Grafana Assume Role authentication provider lets Grafana Cloud users of the
To learn more, refer to the [CloudWatch authentication documentation](/docs/grafana/next/datasources/aws-cloudwatch/aws-authentication).
+## Create alerts from panels
+
+
+
+
+October 23, 2023
+
+_Generally available in Grafana Cloud_
+
+Create alerts from dashboard panels. You can reuse the panel queries and create alerts based on them.
+
## No basic role
diff --git a/go.mod b/go.mod
index 14b37ffc1c7..cf38d15efaf 100644
--- a/go.mod
+++ b/go.mod
@@ -65,7 +65,7 @@ require (
github.com/grafana/cuetsy v0.1.10 // @grafana/grafana-as-code
github.com/grafana/grafana-aws-sdk v0.19.1 // @grafana/aws-datasources
github.com/grafana/grafana-azure-sdk-go v1.9.0 // @grafana/backend-platform
- github.com/grafana/grafana-plugin-sdk-go v0.187.0 // @grafana/plugins-platform-backend
+ github.com/grafana/grafana-plugin-sdk-go v0.189.0 // @grafana/plugins-platform-backend
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/backend-platform
github.com/hashicorp/go-hclog v1.5.0 // @grafana/plugins-platform-backend
github.com/hashicorp/go-plugin v1.4.9 // @grafana/plugins-platform-backend
diff --git a/go.sum b/go.sum
index 9de11b6e870..94188a7f9f9 100644
--- a/go.sum
+++ b/go.sum
@@ -1841,6 +1841,8 @@ github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW3
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
github.com/grafana/grafana-plugin-sdk-go v0.187.0 h1:lOwoFbbTs27KqR3F32GvOX9Et3Ek8p8qsFw+SUJtAAM=
github.com/grafana/grafana-plugin-sdk-go v0.187.0/go.mod h1:PHK8eQOz3ES28RmImdTHNOTxBZaH6mb/ytJGxk7VVJc=
+github.com/grafana/grafana-plugin-sdk-go v0.189.0 h1:30n0dtehLT0Z0DdRfatk1INwXOKfCb9LKaSFl8zBj9g=
+github.com/grafana/grafana-plugin-sdk-go v0.189.0/go.mod h1:nctofuR6fyhx3Stbnh5ha6setroeqqBgO0Rj9s4t86o=
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 h1:1YNoeIhii4UIIQpCPU+EXidnqf449d0C3ZntAEt4KSo=
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482/go.mod h1:GNcfpy5+SY6RVbNGQW264gC0r336Dm+0zgQ5vt6+M8Y=
github.com/grafana/prometheus-alertmanager v0.25.1-0.20231027171310-70c52bf65758 h1:ATUhvJSJwzdzhnmzUI92fxVFqyqmcnzJ47wtHTK3LW4=
diff --git a/package.json b/package.json
index 96f39cd20f2..77b88bd2d83 100644
--- a/package.json
+++ b/package.json
@@ -252,7 +252,7 @@
"@grafana/flamegraph": "workspace:*",
"@grafana/google-sdk": "0.1.1",
"@grafana/lezer-logql": "0.2.1",
- "@grafana/lezer-traceql": "0.0.8",
+ "@grafana/lezer-traceql": "0.0.9",
"@grafana/monaco-logql": "^0.0.7",
"@grafana/runtime": "workspace:*",
"@grafana/scenes": "^1.20.1",
diff --git a/packages/grafana-data/src/field/fieldState.ts b/packages/grafana-data/src/field/fieldState.ts
index 6f816ca5cf5..55754aa9179 100644
--- a/packages/grafana-data/src/field/fieldState.ts
+++ b/packages/grafana-data/src/field/fieldState.ts
@@ -159,7 +159,7 @@ export function calculateFieldDisplayName(field: Field, frame?: DataFrame, allFr
return displayName;
}
-function getUniqueFieldName(field: Field, frame?: DataFrame) {
+export function getUniqueFieldName(field: Field, frame?: DataFrame) {
let dupeCount = 0;
let foundSelf = false;
diff --git a/packages/grafana-data/src/field/index.ts b/packages/grafana-data/src/field/index.ts
index b457d674034..e7b483bdd88 100644
--- a/packages/grafana-data/src/field/index.ts
+++ b/packages/grafana-data/src/field/index.ts
@@ -14,5 +14,5 @@ export { FieldConfigOptionsRegistry } from './FieldConfigOptionsRegistry';
export { sortThresholds, getActiveThreshold } from './thresholds';
export { applyFieldOverrides, validateFieldConfig, applyRawFieldOverrides, useFieldOverrides } from './fieldOverrides';
export { getFieldDisplayValuesProxy } from './getFieldDisplayValuesProxy';
-export { getFieldDisplayName, getFrameDisplayName, cacheFieldDisplayNames } from './fieldState';
+export { getFieldDisplayName, getFrameDisplayName, cacheFieldDisplayNames, getUniqueFieldName } from './fieldState';
export { getScaleCalculator, getFieldConfigWithMinMax, getMinMaxAndDelta } from './scale';
diff --git a/packages/grafana-data/src/transformations/index.ts b/packages/grafana-data/src/transformations/index.ts
index 1fd3229f897..4cdd4ea2f8b 100644
--- a/packages/grafana-data/src/transformations/index.ts
+++ b/packages/grafana-data/src/transformations/index.ts
@@ -20,3 +20,6 @@ export type { RenameByRegexTransformerOptions } from './transformers/renameByReg
export { joinDataFrames as outerJoinDataFrames, isLikelyAscendingVector } from './transformers/joinDataFrames';
export * from './transformers/histogram';
export { ensureTimeField } from './transformers/convertFieldType';
+
+// Required for Sparklines util to work in @grafana/data, but ideally kept internal
+export { applyNullInsertThreshold } from './transformers/nulls/nullInsertThreshold';
diff --git a/packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.test.ts b/packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.test.ts
similarity index 100%
rename from packages/grafana-ui/src/components/GraphNG/nullInsertThreshold.test.ts
rename to packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.test.ts
diff --git a/packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.ts b/packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.ts
new file mode 100644
index 00000000000..94d8dd2e3c0
--- /dev/null
+++ b/packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.ts
@@ -0,0 +1,186 @@
+import { DataFrame, FieldType } from '../../../types';
+
+type InsertMode = (prev: number, next: number, threshold: number) => number;
+
+const INSERT_MODES = {
+ threshold: (prev: number, next: number, threshold: number) => prev + threshold,
+ midpoint: (prev: number, next: number, threshold: number) => (prev + next) / 2,
+ // previous time + 1ms to prevent StateTimeline from forward-interpolating prior state
+ plusone: (prev: number, next: number, threshold: number) => prev + 1,
+};
+
+interface NullInsertOptions {
+ frame: DataFrame;
+ refFieldName?: string | null;
+ refFieldPseudoMax?: number;
+ refFieldPseudoMin?: number;
+ insertMode?: InsertMode;
+}
+
+function getRefField(frame: DataFrame, refFieldName?: string | null) {
+ return frame.fields.find((field) => {
+ // note: getFieldDisplayName() would require full DF[]
+ return refFieldName != null ? field.name === refFieldName : field.type === FieldType.time;
+ });
+}
+
+/** @internal */
+export function applyNullInsertThreshold(opts: NullInsertOptions): DataFrame {
+ if (opts.frame.length === 0) {
+ return opts.frame;
+ }
+
+ let thorough = true;
+ let { frame, refFieldName, refFieldPseudoMax, refFieldPseudoMin, insertMode } = opts;
+
+ if (!insertMode) {
+ insertMode = INSERT_MODES.threshold;
+ }
+
+ const refField = getRefField(frame, refFieldName);
+
+ if (refField == null) {
+ return frame;
+ }
+
+ refField.state = {
+ ...refField.state,
+ nullThresholdApplied: true,
+ };
+
+ const thresholds = frame.fields.map((field) => field.config.custom?.insertNulls || refField.config.interval || null);
+
+ const uniqueThresholds = new Set(thresholds);
+
+ uniqueThresholds.delete(null as any);
+
+ if (uniqueThresholds.size === 0) {
+ return frame;
+ }
+
+ if (uniqueThresholds.size === 1) {
+ const threshold = uniqueThresholds.values().next().value;
+
+ if (threshold <= 0) {
+ return frame;
+ }
+
+ const refValues = refField.values;
+
+ const frameValues = frame.fields.map((field) => field.values);
+
+ const filledFieldValues = nullInsertThreshold(
+ refValues,
+ frameValues,
+ threshold,
+ refFieldPseudoMin,
+ refFieldPseudoMax,
+ insertMode,
+ thorough
+ );
+
+ if (filledFieldValues === frameValues) {
+ return frame;
+ }
+
+ return {
+ ...frame,
+ length: filledFieldValues[0].length,
+ fields: frame.fields.map((field, i) => ({
+ ...field,
+ values: filledFieldValues[i],
+ })),
+ };
+ }
+
+ // TODO: unique threshold-per-field (via overrides) is unimplemented
+ // should be done by processing each (refField + thresholdA-field1 + thresholdA-field2...)
+ // as a separate nullInsertThreshold() dataset, then re-join into single dataset via join()
+ return frame;
+}
+
+function nullInsertThreshold(
+ refValues: number[],
+ frameValues: any[][],
+ threshold: number,
+ refFieldPseudoMin: number | null = null,
+ // will insert a trailing null when refFieldPseudoMax > last datapoint + threshold
+ refFieldPseudoMax: number | null = null,
+ getInsertValue: InsertMode,
+ // will insert the value at every missing interval
+ thorough: boolean
+) {
+ const len = refValues.length;
+ const refValuesNew: number[] = [];
+
+ // Continuously subtract the threshold from the first data point, filling in insert values accordingly
+ if (refFieldPseudoMin != null && refFieldPseudoMin < refValues[0]) {
+ let preFillCount = Math.ceil((refValues[0] - refFieldPseudoMin) / threshold);
+ // this will be 0 or 1 threshold increment left of visible range
+ let prevSlot = refValues[0] - preFillCount * threshold;
+
+ while (prevSlot < refValues[0]) {
+ // (prevSlot - threshold) is used to simulate the previous 'real' data point, as getInsertValue expects
+ refValuesNew.push(getInsertValue(prevSlot - threshold, prevSlot, threshold));
+ prevSlot += threshold;
+ }
+ }
+
+ // Insert initial value
+ refValuesNew.push(refValues[0]);
+
+ let prevValue: number = refValues[0];
+
+ // Fill nulls when a value is greater than the threshold value
+ for (let i = 1; i < len; i++) {
+ const curValue = refValues[i];
+
+ while (curValue - prevValue > threshold) {
+ refValuesNew.push(getInsertValue(prevValue, curValue, threshold));
+
+ prevValue += threshold;
+
+ if (!thorough) {
+ break;
+ }
+ }
+
+ refValuesNew.push(curValue);
+
+ prevValue = curValue;
+ }
+
+ // At the end of the sequence
+ if (refFieldPseudoMax != null && refFieldPseudoMax > prevValue) {
+ while (prevValue + threshold < refFieldPseudoMax) {
+ refValuesNew.push(getInsertValue(prevValue, refFieldPseudoMax, threshold));
+ prevValue += threshold;
+ }
+ }
+
+ const filledLen = refValuesNew.length;
+
+ if (filledLen === len) {
+ return frameValues;
+ }
+
+ const filledFieldValues: any[][] = [];
+
+ for (let fieldValues of frameValues) {
+ let filledValues;
+
+ if (fieldValues !== refValues) {
+ filledValues = Array(filledLen);
+
+ for (let i = 0, j = 0; i < filledLen; i++) {
+ filledValues[i] = refValues[j] === refValuesNew[i] ? fieldValues[j++] : null;
+ }
+ } else {
+ filledValues = refValuesNew;
+ }
+
+ filledFieldValues.push(filledValues);
+ }
+
+ return filledFieldValues;
+}
diff --git a/packages/grafana-ui/src/components/GraphNG/nullToUndefThreshold.ts b/packages/grafana-data/src/transformations/transformers/nulls/nullToUndefThreshold.ts
similarity index 100%
rename from packages/grafana-ui/src/components/GraphNG/nullToUndefThreshold.ts
rename to packages/grafana-data/src/transformations/transformers/nulls/nullToUndefThreshold.ts
diff --git a/packages/grafana-ui/src/components/GraphNG/nullToValue.test.ts b/packages/grafana-data/src/transformations/transformers/nulls/nullToValue.test.ts
similarity index 100%
rename from packages/grafana-ui/src/components/GraphNG/nullToValue.test.ts
rename to packages/grafana-data/src/transformations/transformers/nulls/nullToValue.test.ts
diff --git a/packages/grafana-data/src/transformations/transformers/nulls/nullToValue.ts b/packages/grafana-data/src/transformations/transformers/nulls/nullToValue.ts
new file mode 100644
index 00000000000..4c3ba5a81e6
--- /dev/null
+++ b/packages/grafana-data/src/transformations/transformers/nulls/nullToValue.ts
@@ -0,0 +1,27 @@
+import { DataFrame } from '../../../types';
+
+export function nullToValue(frame: DataFrame) {
+ return {
+ ...frame,
+ fields: frame.fields.map((field) => {
+ const noValue = +field.config?.noValue!;
+
+ if (!Number.isNaN(noValue)) {
+ const transformedVals = field.values.slice();
+
+ for (let i = 0; i < transformedVals.length; i++) {
+ if (transformedVals[i] === null) {
+ transformedVals[i] = noValue;
+ }
+ }
+
+ return {
+ ...field,
+ values: transformedVals,
+ };
+ } else {
+ return field;
+ }
+ }),
+ };
+}
diff --git a/packages/grafana-data/src/types/explore.ts b/packages/grafana-data/src/types/explore.ts
index 0bd99acbfbd..ea196a1fa03 100644
--- a/packages/grafana-data/src/types/explore.ts
+++ b/packages/grafana-data/src/types/explore.ts
@@ -33,10 +33,13 @@ export interface ExplorePanelsState extends Partial;
vars: Record;
}
diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts
index b99a9573f11..9315579eb18 100644
--- a/packages/grafana-data/src/types/featureToggles.gen.ts
+++ b/packages/grafana-data/src/types/featureToggles.gen.ts
@@ -18,7 +18,6 @@
* @public
*/
export interface FeatureToggles {
- trimDefaults?: boolean;
disableEnvelopeEncryption?: boolean;
['live-service-web-worker']?: boolean;
queryOverLive?: boolean;
@@ -156,4 +155,6 @@ export interface FeatureToggles {
alertmanagerRemotePrimary?: boolean;
alertmanagerRemoteOnly?: boolean;
annotationPermissionUpdate?: boolean;
+ extractFieldsNameDeduplication?: boolean;
+ dashboardSceneForViewers?: boolean;
}
diff --git a/packages/grafana-data/src/valueFormats/valueFormats.test.ts b/packages/grafana-data/src/valueFormats/valueFormats.test.ts
index 5bac61ae896..b0776ae4b41 100644
--- a/packages/grafana-data/src/valueFormats/valueFormats.test.ts
+++ b/packages/grafana-data/src/valueFormats/valueFormats.test.ts
@@ -72,7 +72,7 @@ describe('valueFormats', () => {
${'dtdurationms'} | ${undefined} | ${100000} | ${'1 minute'}
${'dtdurationms'} | ${undefined} | ${150000} | ${'2 minutes'}
`(
- 'With format=$format decimals=$decimals and value=$value then result shoudl be = $expected',
+ 'With format=$format decimals=$decimals and value=$value then result should be = $expected',
async ({ format, value, decimals, expected }) => {
const result = getValueFormat(format)(value, decimals, undefined, undefined);
const full = formattedValueToString(result);
diff --git a/packages/grafana-ui/src/components/CustomScrollbar/ScrollIndicators.tsx b/packages/grafana-ui/src/components/CustomScrollbar/ScrollIndicators.tsx
index eed018c3648..b22711457ff 100644
--- a/packages/grafana-ui/src/components/CustomScrollbar/ScrollIndicators.tsx
+++ b/packages/grafana-ui/src/components/CustomScrollbar/ScrollIndicators.tsx
@@ -1,11 +1,9 @@
import { css, cx } from '@emotion/css';
-import classNames from 'classnames';
import React, { useEffect, useRef, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../themes';
-import { Icon } from '../Icon/Icon';
export const ScrollIndicators = ({ children }: React.PropsWithChildren<{}>) => {
const [showScrollTopIndicator, setShowTopScrollIndicator] = useState(false);
@@ -39,9 +37,7 @@ export const ScrollIndicators = ({ children }: React.PropsWithChildren<{}>) => {
className={cx(styles.scrollIndicator, styles.scrollTopIndicator, {
[styles.scrollIndicatorVisible]: showScrollTopIndicator,
})}
- >
-
-
+ />