Compare commits

...

98 Commits

Author SHA1 Message Date
Jev Forsberg
ccd7b6ce7e Chore: Add bash to dagger env and fix rgm tag step (#108349)
baldm0mma/ add bash and fix rgm tag step
2025-07-18 14:18:43 -06:00
grafana-delivery-bot[bot]
1fdeca1015 [release-12.1.0] Security: Fixes for CVE-2025-6197 and CVE-2025-6023 (#108333)
Security: Fixes for CVE-2025-6197 and CVE-2025-6023 (#108330)

apply security patch: main/439-202506251632.patch

(cherry picked from commit 7f3977c54548dc82d9b2c44c125b30b3dbc2069a)


(cherry picked from commit 4669b586e9)

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-07-18 16:24:10 +01:00
grafana-delivery-bot[bot]
6be2d4128f [release-12.1.0] Chore: Update supported versions doc (#108234)
Co-authored-by: Jev Forsberg <46619047+baldm0mma@users.noreply.github.com>
2025-07-17 14:03:08 +01:00
grafana-delivery-bot[bot]
1194671ac0 [release-12.1.0] Docs: Remove references to DD feature toggle (#108183)
Co-authored-by: Isabel Matwawana <76437239+imatwawana@users.noreply.github.com>
2025-07-16 10:29:35 -04:00
grafana-delivery-bot[bot]
bd602fd6d9 [release-12.1.0] Docs: Update actions with variables (#108151)
Co-authored-by: Adela Almasan <88068998+adela-almasan@users.noreply.github.com>
2025-07-15 15:36:41 -04:00
Jack Baldry
f1c1311961 Revert "Docs: Reporting redesign docs (#105078)" (#108136) 2025-07-15 16:53:36 +01:00
grafana-delivery-bot[bot]
ea7eb59bac [release-12.1.0] Docs: Fix format of quick_ranges (#108133)
Co-authored-by: Josh Hunt <joshhunt@users.noreply.github.com>
Fix format of quick_ranges (#107973)
2025-07-15 16:42:59 +02:00
grafana-delivery-bot[bot]
0b985cfd8d [release-12.1.0] Alerting: Fix flakey test for group loader (#108038)
Alerting: Fix flakey test for group loader (#107909)

(cherry picked from commit 889cf57055)

Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2025-07-11 19:12:22 +01:00
grafana-delivery-bot[bot]
7d65c5c2a6 [release-12.1.0] docs: Clarifying the support level of SCIM (#108040)
Co-authored-by: Jacob Valdez <jacob.valdez@grafana.com>
2025-07-11 13:09:58 -05:00
Stephanie Hingtgen
df07305465 Revert: Future-proofing query and data source model in Dashboard Sche… (#107985)
* Revert: Future-proofing query and data source model in Dashboard Schema v2

---------

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
2025-07-10 15:13:14 -05:00
Stephanie Hingtgen
f25d2fe7e2 Revert "Schema V2: Simplify annotations v1<->v2 conversions" (#107984)
Revert "Schema V2: Simplify annotations v1<->v2 conversions (#107390)"

This reverts commit d5a1781fb6.
2025-07-10 15:13:13 -05:00
Gabriel MABILLE
0417533b61 iam: add description field to roles (#107888)
* iam: add description field to roles

* Openapi gen

* Revert launch change
2025-07-10 15:13:13 -05:00
Nathan Verzemnieks
6d4a443aaf Prometheus: use patched grafana-aws-sdk middleware for panic handling 2025-07-10 18:59:18 +02:00
maicon
4228ed789b Folders: disable TestIntegrationFoldersGetAPIEndpointK8S (#107897)
* Folders: disable TestIntegrationFoldersGetAPIEndpointK8S

it's breaking the enteprise CI pipeline

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>

* Run only against sqlite

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>

* noop: force backend change

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>

---------

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>
2025-07-09 15:44:20 +00:00
Peter Štibraný
9d2eadcfd2 PoC: replace using testing.Short in storage/unified package with integration test skip method (#107887)
* PoC: check if testing.Short is called from integration tests only.

* Rename helper function.

* Fix logic.

* Remove skipping of integration tests from non-integration tests.

* Remove skipping of integration tests from non-integration tests.

* Fix import.
2025-07-09 15:32:10 +00:00
Matias Chomicki
5108225785 Logs Panel: Explose details mode and default to inline (#107902)
Logs Panel: Explose details mode
2025-07-09 17:31:10 +02:00
renovate[bot]
4ab519c825 Update dependency expose-loader to v5.0.1 (#107877)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 15:18:09 +00:00
Will Browne
1e0fd825eb Plugins: Simplify assetpath logic (#107876)
* simplify assetpath logic

* fix tests
2025-07-09 15:48:52 +01:00
Misi
1d252de1e9 Docs: Clean up ssoSettingsApi references from docs (#107896)
* Clean up ssoSettingsApi references from docs

* lint
2025-07-09 14:22:07 +00:00
Matias Chomicki
2e58ce7980 Log Line Details: Add inline mode for the Details component (#107718)
* LogLineContext: add sidebar mode

* LogLine: initial support for inline details

* LogLine: finally figure out field overflow

* LogLineDetails: support inline details in unwrapped mode

* LogLineDetails: fix borders in inline mode

* LogLineDetails: support unwrapped inline details

* LogLineDetails: fix inline unwrapped mode

* LogLineDetails: debug and translations

* Fix types

* LogLine: update test

* LogLineDetails: slightly taller

* LogListContext: fix NaN default width

* Remove console log

* LogList: add inline details test

* virtualization: update test

* Fix imports
2025-07-09 16:07:19 +02:00
Gilles De Mey
5d92f3eee5 Alerting: Fix silence / delete on new list view (#107885) 2025-07-09 13:44:44 +00:00
Bruno
8283d35e56 Secrets: make operations sync (#107732)
* Secrets: make operations sync

* k8s gen / update query to list secure values to include the version

* always store new version of a secret

* make update-workspace

* go mod tidy

* update queries

* update queries

* improve and use testutils in decrypt_store_test

* fix broken test

* make update-workspace

* ./hack/update-codegen.sh secret

* update Test_SecureValueMetadataStorage_CreateAndRead

* undo dependency changes

* linter: fix remaining errors

---------

Co-authored-by: Matheus Macabu <macabu.matheus@gmail.com>
Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com>
2025-07-09 10:43:34 -03:00
Gilles De Mey
ded7912ea3 Use Group Loader for the group detail view (#107780) 2025-07-09 15:41:20 +02:00
Nathan Vērzemnieks
f34a9fc0c2 CloudWatch: Fix http client handling + assume role bug (#107893) 2025-07-09 15:28:50 +02:00
Jack Westbrook
c5fbf6217c Frontend: Replace LogicMonitor logo (#107881)
* chore(frontend): replace 2.75mb logicmonitor logo with smaller svg

* chore(frontend): update logicmonitor logo to match previous dimensions
2025-07-09 14:12:58 +02:00
Roberto Jiménez Sánchez
b249942b61 Bump nanogit 2025-07-09 (#107871)
* Bump nanogit 2025-07-09

This version contains significant performance improvements in memory and
CPU thanks to optimizing buffers, using a faster zlib library and using
streaming instead of loading everything in memory.
2025-07-09 14:03:29 +02:00
Hugo Häggmark
0f3edd3b5f Plugins: renames snake cased plugin files (#107862)
* Plugins: renames plugin_loader

* test(pluginloader): fix mock paths to pluginLoader

* chore: rename sandbox files

* Trigger build

* Trigger build

---------

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
2025-07-09 13:18:44 +02:00
Jack Westbrook
d786316766 Plugin Configs: Use nodes strip types for processing webpack configs (#105542)
* feat(plugin-configs): update configs to work with nodes strip-types feature

* build(parca): use nodes experimental-strip-types so build works with node 22 - 24

* build(decoupled-plugins): support nodes strip types feature for webpack builds

* build(e2e-test-plugins): update build scripts and config to work with node strip types

* style(plugin-configs): fix import/order lint errors

* refactor(plugins): use allowImportingTsExtensions in favour of ts-ignore comments

* refactor(plugin-configs): clean up ts-ignore and ts-expect-error comments in webpack.config

* refactor(plugin-configs): fix up changes for nodes strip-types flag

* chore(loki): fix up build command for node 24 support
2025-07-09 10:38:17 +00:00
renovate[bot]
99f3dc859d Update dependency eslint-plugin-react to v7.37.5 (#107873)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 10:32:05 +00:00
Konrad Lalik
89c09a14b8 Alerting: Extensible Settings module (#107831)
* Add extension points to the Settings page

* wip

* Update Settings page routing to catch unmatched routes and redirect to alertmanager

* Add settings page extension

* Refactor settings navigation

* Refactor settings navigation hook

* Update import paths

* Add Settings page tests for custom tabs

* Update translations

* Add a route explanation

---------

Co-authored-by: Sonia Aguilar <soniaaguilarpeiron@gmail.com>
2025-07-09 12:29:39 +02:00
Ashley Harrison
92121a1030 Cascader: Fix icon not showing (#107869)
* fix image path for angle-right

* use proper icon utils
2025-07-09 11:24:21 +01:00
renovate[bot]
07ca8ca3e7 Update dependency eslint-plugin-no-barrel-files to v1.2.1 (#107868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 10:04:10 +00:00
renovate[bot]
ae7a3db917 Update dependency @grafana/google-sdk to v0.3.4 (#107865)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 09:38:46 +00:00
Ashley Harrison
ca73093573 i18n actions: only run in main repo (#107864)
* don't run download/upload in the security mirror

* better check
2025-07-09 09:18:33 +00:00
renovate[bot]
df3bb9fba4 Update dependency i18next to v25.3.2 (#107863)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 10:14:20 +01:00
Nathan Vērzemnieks
c3eeb1fcd9 CloudWatch: Fix proxy transport issue (#107807)
CloudWatch: fix proxy transport issue
2025-07-09 11:03:53 +02:00
Piotr Jamróz
e78411f17a Tempo: Fix showing dangling edges in NodeGraph (#107245)
* Tempo: Fix showing dangling edges in NodeGraph

* Remove comment
2025-07-09 10:53:31 +02:00
renovate[bot]
aa17dd8056 Update dependency esbuild to v0.25.6 (#107799)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 09:36:22 +01:00
Ryan McKinley
3f502f305d Chore: Update mocks with recent mockery (#107816) 2025-07-09 09:15:34 +02:00
Alex Khomenko
39904d7b9b Provisioning: Move dashboard from setting page (#107793)
* Provisioning: Move dashboard from the settings page

* Cleanup

* i18n

* Add noMargin

* Add test

* Use new pr param

* Cleanup

* Fix tests

* i18n

* betterer
2025-07-09 10:10:05 +03:00
Daniele Stefano Ferru
d7f7a19c56 Dashboard permissions: Update integration tests to take into account kubernetesDashboards flag value (#107706)
Dashboard permissions: Update integration tests to take into account  flag value
2025-07-09 08:46:27 +02:00
xavi
e4743a9092 IAM: Return 401 if identity type is not valid in GetUserPreferences (#107760)
fix(GetUserPreferences): Return 401 if identity type is not valid
2025-07-09 08:35:18 +02:00
Hugo Häggmark
20c700dd52 Chore: reduces barrel files part II (#107688)
* Chore: reduce barrel files

* chore: fixes unit test

* Chore: reduces barrel files part II

* chore: fix import sorting
2025-07-09 06:15:33 +02:00
grafana-pr-automation[bot]
5e1d7cbd2e I18n: Download translations from Crowdin (#107813)
New Crowdin translations by GitHub Action

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-09 00:38:37 +00:00
Alyssa Joyner
6c20ad0013 [InfluxDB] Change default HTTP method to POST (#107787) 2025-07-08 15:19:22 -06:00
Alex Spencer
869094bb37 SQL Expressions: Reconfigure add expression button for improved UX (#106797)
* feat: reconfigure expression button for improved UX

* chore: fix broken test

* chore: refactor to use improved UX + combine another UI PR.

* chore: i18n

* chore: memoize options + add data test ids for tracking

* chore: common component for expression dropdown

* chore: streamline common component

* chore: add event tracking

* chore: put event tracking in its own PR
2025-07-08 14:11:54 -07:00
maicon
79ebe2dc10 Folders: Ensure all folder tests under /pkg/tests/apis/folders are handled as integrations tests (#107801)
Folders: ensure integration tests are executed in our CI pipeline

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>
2025-07-08 16:32:41 -03:00
Leon Sorokin
dd1fce5c8a Search: Use case-insensitive substring matching in fuzzySearch fallback (#107661) 2025-07-08 14:14:00 -05:00
Alex Spencer
efe46c8aad Limit: Invalidate field reducer calcs on applying limit transformation (#106723)
* fix: clear state calcs when limit transformation is applied

* chore: fix limit tests expected values
2025-07-08 11:37:54 -07:00
Leon Sorokin
68ee251c5c TableNG: Extract links and actions tooltip into cell root renderer (#107667)
* TableNG: Extract links and actions tooltip into cell root renderer

* make TS happy

* fixes & tweaks

* lint

* skip datalinks and actions tooltip on those cell types

* add todo

* withTooltip lookup

* fix

* optional getActions

* fix

* kill cursor: 'context-menu'

* stop event propagation from TableCellActions

* update tests to move tooltip tests up to TableNG

* remove safety assertion

* add value back to DataLinksActionsTooltip

---------

Co-authored-by: Paul Marbach <paul.marbach@grafana.com>
2025-07-08 14:24:03 -04:00
Yunwen Zheng
412415ab39 NewProvisionedFolderForm: pass in empty title for new folder form (#107733)
Co-authored-by: Clarity-89 <homes89@ukr.net>
2025-07-08 18:00:51 +00:00
renovate[bot]
0b28a53923 Update dependency @grafana/lezer-logql to v0.2.8 (#107797)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 16:53:35 +00:00
Kristina
fdc6a0d774 Transformations: For Convert Field Type, clone conversions as to not mutate defaultOptions (#107752)
Clone conversions as to not mutate defaultOptions
2025-07-08 11:29:14 -05:00
renovate[bot]
1eef358deb Update dependency css-minimizer-webpack-plugin to v7.0.2 (#107796)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 17:26:48 +01:00
Tim Levett
0fdcae4e26 Tables: Pills for Table Cells (#107485)
* v2 of pills for tables

* cleanup bettererrrrr

* cleanup pretty

* i18n changes

* add in the option for value mapping

* value mapping

* change to just use the value mapping from the table component

* tests fixed

* betterer all better now

* fix pretty

* i18n

* fix gen issue

* i18n

* fix merge issue

* Refactor pillcell to an interface for said pill, cleanup tests

* mind the space says prettier
2025-07-08 10:56:39 -05:00
renovate[bot]
0459382b25 Update dependency chrome-remote-interface to v0.33.3 (#107792)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 15:54:26 +00:00
renovate[bot]
56dcb6c08a Update dependency chance to v1.1.13 (#107790)
* Update dependency chance to v1.1.13

* use same version of chance everywhere

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: joshhunt <josh.hunt@grafana.com>
2025-07-08 15:13:54 +00:00
renovate[bot]
7728a51972 Update dependency chance to v1.1.13 (#107785)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 14:28:26 +00:00
maicon
53537148e1 Folders: reenable unit tests (#107751)
* Folders: reenable unit test TestFoldersCreateAPIEndpointK8S

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>

* reenable unit test TestFoldersGetAPIEndpointK8S

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>

---------

Signed-off-by: Maicon Costa <maiconscosta@gmail.com>
2025-07-08 11:26:45 -03:00
Bruno
0f23988132 JWT.Authenticate: remove err != nil check for error that has already been checked (#107727) 2025-07-08 11:19:39 -03:00
Alyssa Joyner
4830969305 Add influx DRBP mapping (#107744) 2025-07-08 14:14:47 +00:00
renovate[bot]
e920bd2d29 Update dependency autoprefixer to v10.4.21 (#107781)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 13:54:06 +00:00
Matt Cowley
dbbd9f23d1 Plugin Extensions: Expose PluginMeta generic in usePluginContext (#107577)
* Plugin Extensions: Expose PluginMeta generic in usePluginContext

* Plugin Extensions: Cast usePluginContext type on return

* Plugin Extensions: Fix PluginContext export
2025-07-08 15:51:30 +02:00
Jo
1e1fd3db38 OAuth: Add access token as third source for user info extraction (#107636)
* Add access token as third source for user info extraction

- Add extractFromAccessToken method to extract user info from JWT access tokens
- Mutualize code by creating parseUserInfoFromJSON helper method
- Rename methods for clarity: extractFromToken -> extractFromIDToken, retrieveRawIDToken -> retrieveRawJWTPayload
- Update test suite to include comprehensive access token retrieval scenarios
- Support three sources in priority order: ID token, API response, access token
- Maintain backward compatibility while adding new functionality

* Update Generic OAuth documentation to reflect access token support

- Add access token as a third source for user information extraction
- Update configuration sections to mention access tokens alongside ID tokens and UserInfo endpoint
- Document the priority order: ID token → UserInfo endpoint → access token
- Update configuration option descriptions to reflect new functionality
- Maintain consistency with implementation changes

* Refactor access token test cases to use parameter instead of hardcoded logic

- Add AccessToken field to test case struct for explicit access token specification
- Remove hardcoded string matching logic that determined access token based on test name
- Update all access token test cases to include the AccessToken field with appropriate JWT values
- Improve test maintainability and clarity by making access tokens explicit parameters
- Remove unused strings import that was only needed for the hardcoded logic

* fix doc lint

* reduce cyclomatic complexity
2025-07-08 15:38:11 +02:00
renovate[bot]
15967cb7ab Update dependency @types/webpack-env to v1.18.8 (#107777)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 14:26:25 +01:00
Alexa Vargas
2e3c2df6bf Dashboard: Add Alert icon in library panels (#107723)
* Use panel.id from the dashboard to filter alterts properly

* add unit test

* Fix linting

* add fix back

* fix betterer in test, use same pattern as DashboardDatasourceBehaviour
2025-07-08 15:08:01 +02:00
Alexa Vargas
e33047bdf1 Dashboard: Library Panels - Add ability to search by folder name (#106997)
* Dashboard: Add ability to search by folder name in library panels

* restore to main to fix linting issues

* restore from main to avoid go linting issues

* add logic to the writers.go that search by folder title if folder is not passed

* add missing left joing from the folder table

* Add extra logic to prevent folder searches without permission

* fix go linting issue about memory

* Add test when searching by folder name

* Refactor tests to include a bit more validation

* apply feedback and use SearchFolder from search folder service

* clean up comments

* Update pkg/services/libraryelements/database.go

Co-authored-by: Ezequiel Victorero <ezequiel.victorero@grafana.com>

* Fix logic of early return

* Extract into a function and remove the left join

* Apply feedback to be aligned with idiomatic go

* Apply suggestion from @evictorero

Co-authored-by: Ezequiel Victorero <ezequiel.victorero@grafana.com>

* fix liting

---------

Co-authored-by: Ezequiel Victorero <ezequiel.victorero@grafana.com>
2025-07-08 15:07:22 +02:00
Kevin Minehart
047349638d CI: Run lerna bump version before yarn build (#107731)
lerna bump version before yarn build

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
2025-07-08 14:58:45 +02:00
renovate[bot]
35bf093201 Update dependency @types/systemjs to v6.15.3 (#107774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 12:56:49 +00:00
Hugo Kiyodi Oshiro
6c1ff32501 Plugins: Improve levitate report on forks (#107252) 2025-07-08 14:52:02 +02:00
Dominik Prokop
d5a1781fb6 Schema V2: Simplify annotations v1<->v2 conversions (#107390)
* Initial migration pending to test

* Update tests

* apply feedback

* Remove unnecessary types

* Fix types

* Update tests

* fixing tests

* Default DS for transformer

* Update the default DS

* Update the generated sdk files

* Restore commented tests

* Update tests

* Updating snapshots

* fix

* Do not preserve empty datasource in panel spec

* update provisioning v2 sample dashboard

* Fix test

* Prettier

* Fix import e2e

* Prettier

* restore commented tests

* Update to support annotations

* Lint

* Make gen apps

* Make the build pass

Signed-off-by: Igor Suleymanov <igor.suleymanov@grafana.com>

* Update grafana-app-sdk to 0.39.2

* Workspace update

* make gen-cue

* Runtime error fix

* Update dashboard spec

* Update go workspaces

* Schema V2: Simplify annotations v1<->v2 conversions

* Update public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts

* Cleanup and some more tests

* test improvement

* Update public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts

* Update go.sum

* make generate

* Update public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts

Co-authored-by: Haris Rozajac <58232930+harisrozajac@users.noreply.github.com>

* ts

* make gen-apps

* Update response transformers to correctly handle v2->v1 annotations

* Update dashboards openapi snapshot

---------

Signed-off-by: Igor Suleymanov <igor.suleymanov@grafana.com>
Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com>
Co-authored-by: alexandra vargas <alexa1866@gmail.com>
Co-authored-by: Haris Rozajac <haris.rozajac12@gmail.com>
Co-authored-by: Igor Suleymanov <igor.suleymanov@grafana.com>
Co-authored-by: spinillos <selenepinillos@gmail.com>
Co-authored-by: Haris Rozajac <58232930+harisrozajac@users.noreply.github.com>
2025-07-08 14:42:30 +02:00
Dominik Prokop
feedb5c0a6 PublicDashboardsBadge: Fix react warning (#107768) 2025-07-08 14:40:13 +02:00
Josh Hunt
a9e70d4a1d Storybook: Rearrange and tidy stories (#107270)
* Tidy up storybook a little bit

* change sort order, delete some stories

* More tidy up of actions

* More tidy up of actions

* tweak story sorting, again

* Make all internal stories public

* fix sort

* Add ESLint rule to enforce storybook titles

* update verify storybook test

* simplify glob
2025-07-08 12:37:09 +00:00
renovate[bot]
d27d8f02b6 Update dependency @types/node-forge to v1.3.12 (#107769)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 12:32:29 +00:00
renovate[bot]
2fabedc363 Update dependency @types/lodash to v4.17.20 (#107767)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 11:50:43 +00:00
Gilles De Mey
95d4909475 Alerting: Add oncall contact point type and narrow create hook function (#107711) 2025-07-08 13:35:09 +02:00
renovate[bot]
5d2bbfd3ee Update dependency @rollup/plugin-node-resolve to v16.0.1 (#107766)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 11:27:09 +00:00
Yunwen Zheng
2de7f424f5 BrowseDashboardsPage: added new pull request banner on new folder creation (#107596)
* BrowseDashboardsPage: added ProvisionedFolderPreviewBanner to display new provisioned folder on branch alert

* add comment

* fix test

* i18n

* Added test for PreviewBannerViewPR

* fix test, i18n fix
2025-07-08 14:24:16 +03:00
Dominik Prokop
365234c2fe PublicDashboards: Use API to render public dashboard badge (#107638)
* PublicDashboards: Use API to render public dashboard badge

* i18n

* Keine console bitte

* Update public/app/features/dashboard-scene/scene/NavToolbarActions.tsx

* Update tests
2025-07-08 13:11:25 +02:00
renovate[bot]
285c69c487 Update dependency react-calendar to v6 (#107726)
* Update dependency react-calendar to v6

* add esmodules to jest config

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
2025-07-08 10:53:50 +00:00
grafana-pr-automation[bot]
d22842b52b I18n: Download translations from Crowdin (#107750)
New Crowdin translations by GitHub Action

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-08 10:03:08 +00:00
Matias Chomicki
89e8a03859 New Log Details: Add support to sort displayed fields (#107635)
* Create LogLineDetailsDisplayedFields

* Log labels: properly implement plurals

* Pluralize

* LogListContext: pass setDisplayedFields

* LogLineDetailsDisplayedFields: update displayed fields

* LogLineDetails: scroll to item after opening details

* LogListContext: serve logOptionsStorageKey

* Update test

* Missing translations

* LogLineDetailsDisplayedFields: update styles

* LogLineDetails: update text selectors

* Update tests

* Reorganize log details: improve discoverability

* Update test
2025-07-08 11:57:28 +02:00
Tobias Skarhed
509990ca89 Variables: Change vis library from visj-network to vis-network (#107712)
* Change from visj-network to vis-network

* Check that ref exists

* Remove vis-util as a direct dependency

* Update betterer

* Address PR feedback
2025-07-08 09:30:46 +00:00
Fayzal Ghantiwala
de50c5a497 Alerting: Fix crypto_test.go errors in CI (#107759)
Fix test
2025-07-08 11:03:26 +02:00
Levente Balogh
5b7f06c24e Extensions: Wrap extension components with a sandbox wrapper div (#103064)
* feat(sandbox): wrap extension components with sandbox wrapper div

* fix: remove circular dependency

This was caused by sandbox_plugin_loader_registry -> helpers -> backend_srv -> ... plugin_loader -> setup.

* fix: add dependency to react hook

* tests: add tests for extensions sandbox wrapper

* fix: only wrap modal content after plugin loading

* chore: remove unused code

* Wip

* review(actions.ts): extract logic to function

* test: remove testing app id

* tests: fix extension utils tests

* tests: remove unnecessary code
2025-07-08 07:10:19 +02:00
Jacob Valdez
6c2574848f Docs: Updating team sync availability (#107721) 2025-07-07 16:07:50 -05:00
Gabriel MABILLE
1244f5c53d AuthZ: Add CoreRoleStorageBackend to the extension set (#103912)
* Wiring

* Trigger CI

---------

Co-authored-by: mohammad-hamid <mohammad.hamid@grafana.com>
2025-07-07 20:08:44 +02:00
Kristina
0f2284d5e6 Transformations: Reduce > Reduce fields should not persist labels between reducers (#107590)
Reduce fields should not persist labels updates between reducers
2025-07-07 12:05:55 -05:00
Paul Marbach
7181f8d89d TableNG: Update description for wrapHeaderText (#107722) 2025-07-07 12:36:41 -04:00
renovate[bot]
34c7ea9c28 Update dependency marked to v16 (#107717)
* Update dependency marked to v16

* mark marked as esmodule for jest

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
2025-07-07 16:18:37 +00:00
Yuri Tseretyan
c93fd3ee9e Alerting: idempotent decrypt\encrypt operations on extra configs (#107592)
* add prefix to encrypted string to distinguish between unencrypted and encrypted ones

---------

Co-authored-by: Alexander Akhmetov <me@alx.cx>
2025-07-07 12:17:41 -04:00
Yuri Tseretyan
d15e1ad8d0 Alerting: Fix route validation in provisioning service (#107550)
* introduce ExtraConfigsCrypto
* delete getLastConfiguration and move all code into method Get
* update legacy store to encrypt ExtraConfigs same way we do in MultiOrgAlertmanager
* update legacy store init
* delete PersistConfig
* remove unnecessary unmarshalling
* add better error

* add tests for legacy store

* add tests that cover extra config validation

* add integration test for conflicting routes

---------

Signed-off-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
2025-07-07 12:16:31 -04:00
Ashley Harrison
757886c704 Chore: ignore /mocks/** from the betterer results (#107708)
ignore /mocks/** from the betterer results
2025-07-07 17:02:59 +01:00
renovate[bot]
381cd95932 Update dependency i18next to v25 (#107707)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 16:48:05 +01:00
Ashley Harrison
31b71f79dd Internationalisation: Manual mark up following review (#107625)
* mark up and add confirmText to lint rule

* mark up and add ariaLabel to lint rule

* add confirmText to propertiesToCheck

* mark up and add body to propsToCheck

* mark up latest

* mark up 'Dashboard saved'

* mark up filterbyvalue options

* mark up tooltip options

* mark up and add lint rules for noOptionsMessage/loadingMessage

* mark up 'Convert field type'

* mark up placeholderText/noOptionsMessage

* mark up run query

* mark up variable editor fields

* mark up week start options

* mark up dashboard link options

* mark up prom options

* mark up builder/code toggles

* make CI happy

* kick CI
2025-07-07 16:43:19 +01:00
Yunwen Zheng
a2a28b207c KBARResults: Add Cmd+Enter/Ctrl+Enter to open links in new tab (#107537)
* KBARResults:add command+enter to open selected link in new tab
2025-07-07 11:37:35 -04:00
Todd Treece
37c480def4 K8s: Add support for stored subresources in app runner (#105481) 2025-07-07 11:25:23 -04:00
renovate[bot]
14eaa3975b Update scenes to v6.27.1 (#107703)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 14:56:40 +00:00
1412 changed files with 20385 additions and 11079 deletions

View File

@@ -104,6 +104,7 @@ module.exports = [
'**/__mocks__/**',
'**/public/test/**',
'**/mocks.{ts,tsx}',
'**/mocks/**/*.{ts,tsx}',
'**/spec/**/*.{ts,tsx}',
],
rules: {

View File

@@ -489,9 +489,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"]
],
"packages/grafana-prometheus/src/test/mocks/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-prometheus/src/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -961,9 +958,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not re-export imported variable (\`profiler\`)", "6"],
[0, 0, 0, "Do not re-export imported variable (\`updateLegendValues\`)", "7"]
],
"public/app/core/navigation/mocks/routeProps.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/core/navigation/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -1555,9 +1549,6 @@ exports[`better eslint`] = {
"public/app/features/correlations/components/EmptyCorrelationsCTA.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Card components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"]
],
"public/app/features/correlations/mocks/useCorrelations.mocks.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/correlations/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -1696,15 +1687,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/serialization/transformToV1TypesUtils.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/settings/GeneralSettingsEditView.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "2"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "3"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "4"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "6"]
],
"public/app/features/dashboard-scene/settings/annotations/AnnotationSettingsEdit.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -2522,16 +2504,6 @@ exports[`better eslint`] = {
"public/app/features/plugins/admin/components/PluginDetailsPage.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/admin/mocks/catalogPlugin.mock.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/features/plugins/admin/mocks/localPlugin.mock.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/admin/mocks/remotePlugin.mock.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/admin/pages/Browse.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -2566,10 +2538,10 @@ exports[`better eslint`] = {
"public/app/features/plugins/loader/sharedDependencies.ts:5381": [
[0, 0, 0, "* import is invalid because \'Layout,HorizontalGroup,VerticalGroup\' from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
],
"public/app/features/plugins/sandbox/distortion_map.ts:5381": [
"public/app/features/plugins/sandbox/distortions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/sandbox/sandbox_plugin_loader.ts:5381": [
"public/app/features/plugins/sandbox/sandboxPluginLoader.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
@@ -2882,12 +2854,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"]
],
"public/app/features/users/mocks/userMocks.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"]
],
"public/app/features/variables/adapters.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -2922,10 +2888,7 @@ exports[`better eslint`] = {
],
"public/app/features/variables/inspect/NetworkGraph.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, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/variables/inspect/VariablesUnknownTable.tsx:5381": [
[0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"],
@@ -3108,21 +3071,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "5"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "6"]
],
"public/app/plugins/datasource/azuremonitor/mocks/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/azuremonitor/mocks/panelData.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
],
"public/app/plugins/datasource/azuremonitor/mocks/utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/azuremonitor/mocks/variables.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/azuremonitor/types/query.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "1"],
@@ -3165,14 +3113,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringDatasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
],
"public/app/plugins/datasource/cloud-monitoring/mocks/cloudMonitoringInstanceSettings.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloud-monitoring/types/query.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "0"],
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "1"],
@@ -3181,9 +3121,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/cloud-monitoring/types/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/plugins/datasource/cloud-monitoring/webpack.config.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
],
"public/app/plugins/datasource/cloudwatch/components/ConfigEditor/ConfigEditor.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -3221,124 +3158,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/plugins/datasource/cloudwatch/mocks/CloudWatchVariables.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/commentOnlyQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/multiLineFullQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/multiLineFullQueryWithCaseClause.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/partialQueryWithFunction.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/partialQueryWithSubquery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/singleLineFullQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-sql-test-data/whitespaceQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/commentOnlyQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/filterQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/multiLineFullQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/newCommandQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/singleLineFullQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/sortQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-logs-test-data/whitespaceQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-ppl-test-data/multilineQueries.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-ppl-test-data/newCommandQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-ppl-test-data/singleLineQueries.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Do not use any type assertions.", "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, "Do not use any type assertions.", "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"],
[0, 0, 0, "Do not use any type assertions.", "12"],
[0, 0, 0, "Do not use any type assertions.", "13"],
[0, 0, 0, "Do not use any type assertions.", "14"],
[0, 0, 0, "Do not use any type assertions.", "15"],
[0, 0, 0, "Do not use any type assertions.", "16"],
[0, 0, 0, "Do not use any type assertions.", "17"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/multiLineFullQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/multiLineIncompleteQueryWithoutNamespace.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/singleLineEmptyQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/singleLineFullQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/cloudwatch-sql-test-data/singleLineTwoQueries.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/dashboardOnLoadedEvent.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/dynamic-label-test-data/afterLabelValue.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/dynamic-label-test-data/insideLabelValue.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/afterFunctionQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/secondArgAfterSearchQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/secondArgQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/singleLineEmptyQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/thirdArgAfterSearchQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/metric-math-test-data/withinStringQuery.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/cloudwatch/mocks/monarch/Monaco.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/cloudwatch/types.ts:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3411,9 +3230,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/elasticsearch/components/QueryEditor/MetricAggregationsEditor/state/reducer.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/elasticsearch/configuration/mocks/configOptions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/elasticsearch/datasource.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3471,9 +3287,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/plugins/datasource/grafana-testdata-datasource/webpack.config.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
],
"public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx:5381": [
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"],
[0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "1"],
@@ -3623,10 +3436,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
"public/app/plugins/datasource/influxdb/mocks/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/influxdb/query_part.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -3694,13 +3503,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/plugins/datasource/loki/mocks/datasource.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"]
],
"public/app/plugins/datasource/loki/mocks/metadataRequest.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/loki/querybuilder/components/LokiQueryBuilder.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -3836,9 +3638,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"public/app/plugins/datasource/tempo/webpack.config.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
],
"public/app/plugins/datasource/zipkin/QueryField.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -3849,9 +3648,6 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/zipkin/utils/transforms.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/plugins/datasource/zipkin/webpack.config.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`config\`)", "0"]
],
"public/app/plugins/panel/annolist/AnnoListPanel.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -4195,9 +3991,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/types/acl.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`OrgRole\`)", "0"]
],
"public/app/types/alerting.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -4219,29 +4012,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
"public/app/types/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`CoreEvents\`)", "0"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "3"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "4"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "5"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "6"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "7"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "8"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "9"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "10"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "11"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "12"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "13"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "14"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "15"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "16"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "17"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "18"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "19"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "20"]
],
"public/app/types/jquery/jquery.d.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -4311,6 +4081,15 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/CallToActionCard/CallToActionCard.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/ColorPicker/SeriesColorPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4326,12 +4105,27 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/Dropdown/ButtonSelect.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/FormField/FormField.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/InfoTooltip/InfoTooltip.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/List/List.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/PageLayout/PageToolbar.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/QueryField/QueryField.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/SecretFormField/SecretFormField.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/SecretTextArea/SecretTextArea.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4344,6 +4138,9 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/Select/SelectPerf.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/Slider/RangeSlider.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4353,9 +4150,21 @@ exports[`no undocumented stories`] = {
"packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/ThemeDemos/BorderRadius.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/ThemeDemos/EmotionPerfTest.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/ThemeDemos/ThemeDemo.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/ThemeDemos/Typography.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/components/UnitPicker/UnitPicker.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
@@ -4367,6 +4176,9 @@ exports[`no undocumented stories`] = {
],
"packages/grafana-ui/src/components/VizTooltip/SeriesTable.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
],
"packages/grafana-ui/src/utils/useDelayedSwitch.story.tsx:5381": [
[0, 0, 0, "No undocumented stories are allowed, please add an .mdx file with some documentation", "5381"]
]
}`
};

View File

@@ -193,7 +193,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
@@ -661,7 +661,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
- docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
@@ -1757,7 +1757,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_main.sh
@@ -1831,13 +1831,30 @@ platform:
os: linux
services: []
steps:
- commands:
- echo $(/usr/bin/github-app-external-token) > /github-app/token
environment:
GITHUB_APP_ID:
from_secret: github-app-app-id
GITHUB_APP_INSTALLATION_ID:
from_secret: github-app-installation-id
GITHUB_APP_PRIVATE_KEY:
from_secret: github-app-private-key
failure: ignore
image: us-docker.pkg.dev/grafanalabs-global/docker-deployment-tools-prod/github-app-secret-writer:2024-11-05-v11688112090.1-83920c59
name: github-app-generate-token
volumes:
- name: github-app
path: /github-app
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh
depends_on:
- github-app-generate-token
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
@@ -1889,6 +1906,10 @@ volumes:
- host:
path: /var/run/docker.sock
name: docker
- name: github-app
path: /github-app
- name: github-app
temp: {}
---
clone:
retries: 3
@@ -1953,7 +1974,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_tag_grafana.sh
@@ -2060,7 +2081,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_build_nightly_grafana.sh
@@ -2204,7 +2225,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GRAFANA_DIR=$$(pwd)
- export GITHUB_TOKEN=$(cat /github-app/token)
- ./pkg/build/daggerbuild/scripts/drone_publish_nightly_grafana.sh
@@ -2333,7 +2354,7 @@ steps:
- commands:
- wget -qO- https://github.com/dagger/dagger/releases/download/v0.18.8/dagger_v0.18.8_linux_amd64.tar.gz
| tar zx -C /bin
- apk add docker
- apk add docker bash
- export GITHUB_TOKEN=$(cat /github-app/token)
- dagger run --silent go run ./pkg/build/cmd artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
--enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --build-id=$${DRONE_BUILD_NUMBER}
@@ -2986,6 +3007,6 @@ kind: secret
name: gcr_credentials
---
kind: signature
hmac: 1198b1489e48a9ced211633a0325d112814553246847fc7320fb5ac2bcb32b7d
hmac: dce4ef9b8d45f32e1b2153b8418f668144325ed9fc0c51f2f8245fb091a4cba2
...

View File

@@ -158,6 +158,7 @@ jobs:
- id: 'auth'
uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f'
if: github.event.pull_request.head.repo.full_name == github.repository
with:
workload_identity_provider: projects/304398677251/locations/global/workloadIdentityPools/github/providers/github-provider
service_account: github-plugins-data-levitate@grafanalabs-workload-identity.iam.gserviceaccount.com
@@ -165,6 +166,7 @@ jobs:
- name: 'Set up Cloud SDK'
uses: 'google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a'
if: github.event.pull_request.head.repo.full_name == github.repository
with:
version: '>= 363.0.0'
project_id: 'grafanalabs-global'
@@ -175,6 +177,7 @@ jobs:
run: ./scripts/check-breaking-changes.sh
env:
FORCE_COLOR: 3
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }} # used in check-breaking-changes.sh and levitate-parse-json-report.js
- name: Persisting the check output
run: |
@@ -199,6 +202,7 @@ jobs:
permissions:
contents: read
id-token: write
if: github.event.pull_request.head.repo.full_name == github.repository
steps:
- id: get-secrets

View File

@@ -7,6 +7,7 @@ on:
jobs:
download-sources-from-crowdin:
if: github.repository == 'grafana/grafana'
uses: grafana/grafana-github-actions/.github/workflows/crowdin-download.yml@main
with:
crowdin_project_id: 5

View File

@@ -14,6 +14,7 @@ on:
jobs:
upload-sources-to-crowdin:
if: github.repository == 'grafana/grafana'
uses: grafana/grafana-github-actions/.github/workflows/crowdin-upload.yml@main
with:
crowdin_project_id: 5

View File

@@ -19,6 +19,9 @@ update-app-sdk: ## Update the Grafana App SDK dependency in go.mod
go mod tidy
.PHONY: generate
generate: install-app-sdk update-app-sdk
generate: do-generate ## Run Grafana App SDK code generation
.PHONY: do-generate
do-generate: install-app-sdk update-app-sdk
## --defencoding=none and noschemasinmanifest are needed to avoid infinite loop while generating recursive models (see routingtree.cue)
@$(APP_SDK_BIN) generate --grouping=group --gogenpath=./pkg/apis --defencoding=none --postprocess --noschemasinmanifest

View File

@@ -14,8 +14,6 @@ import (
v0alpha1 "github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/alerting/v0alpha1"
)
var ()
var appManifestData = app.ManifestData{
AppName: "alerting",
Group: "notifications.alerting.grafana.app",

View File

@@ -1,4 +1,4 @@
APP_SDK_VERSION := v0.39.2
APP_SDK_VERSION := v0.39.0
APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION)
APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk

View File

@@ -111,8 +111,6 @@ DashboardLink: {
keepTime: bool | *false
}
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
DataSourceRef: {
// The plugin type-id
type?: string
@@ -387,7 +385,8 @@ VizConfigKind: {
}
AnnotationQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
query?: DataQueryKind
enable: bool
hide: bool
iconColor: string
@@ -413,19 +412,15 @@ QueryOptionsSpec: {
}
DataQueryKind: {
kind: "DataQuery"
group: string
version: string | *"v0"
// New type for datasource reference
// Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.
datasource?: {
name?: string
}
// The kind of a DataQueryKind is the datasource type
kind: string
spec: [string]: _
}
PanelQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
refId: string
hidden: bool
}
@@ -728,6 +723,7 @@ QueryVariableSpec: {
refresh: VariableRefresh
skipUrlSync: bool | *false
description?: string
datasource?: DataSourceRef
query: DataQueryKind
regex: string | *""
sort: VariableSort

View File

@@ -115,8 +115,6 @@ DashboardLink: {
keepTime: bool | *false
}
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
DataSourceRef: {
// The plugin type-id
type?: string
@@ -391,7 +389,8 @@ VizConfigKind: {
}
AnnotationQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
query?: DataQueryKind
enable: bool
hide: bool
iconColor: string
@@ -417,19 +416,15 @@ QueryOptionsSpec: {
}
DataQueryKind: {
kind: "DataQuery"
group: string
version: string | *"v0"
// New type for datasource reference
// Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.
datasource?: {
name?: string
}
// The kind of a DataQueryKind is the datasource type
kind: string
spec: [string]: _
}
PanelQuerySpec: {
query: DataQueryKind
datasource?: DataSourceRef
refId: string
hidden: bool
}
@@ -732,6 +727,7 @@ QueryVariableSpec: {
refresh: VariableRefresh
skipUrlSync: bool | *false
description?: string
datasource?: DataSourceRef
query: DataQueryKind
regex: string | *""
sort: VariableSort

View File

@@ -23,13 +23,14 @@ func NewDashboardAnnotationQueryKind() *DashboardAnnotationQueryKind {
// +k8s:openapi-gen=true
type DashboardAnnotationQuerySpec struct {
Query DashboardDataQueryKind `json:"query"`
Enable bool `json:"enable"`
Hide bool `json:"hide"`
IconColor string `json:"iconColor"`
Name string `json:"name"`
BuiltIn *bool `json:"builtIn,omitempty"`
Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"`
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
Query *DashboardDataQueryKind `json:"query,omitempty"`
Enable bool `json:"enable"`
Hide bool `json:"hide"`
IconColor string `json:"iconColor"`
Name string `json:"name"`
BuiltIn *bool `json:"builtIn,omitempty"`
Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"`
// Catch-all field for datasource-specific properties
LegacyOptions map[string]interface{} `json:"legacyOptions,omitempty"`
}
@@ -37,28 +38,34 @@ type DashboardAnnotationQuerySpec struct {
// NewDashboardAnnotationQuerySpec creates a new DashboardAnnotationQuerySpec object.
func NewDashboardAnnotationQuerySpec() *DashboardAnnotationQuerySpec {
return &DashboardAnnotationQuerySpec{
Query: *NewDashboardDataQueryKind(),
BuiltIn: (func(input bool) *bool { return &input })(false),
}
}
// +k8s:openapi-gen=true
type DashboardDataSourceRef struct {
// The plugin type-id
Type *string `json:"type,omitempty"`
// Specific datasource instance
Uid *string `json:"uid,omitempty"`
}
// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object.
func NewDashboardDataSourceRef() *DashboardDataSourceRef {
return &DashboardDataSourceRef{}
}
// +k8s:openapi-gen=true
type DashboardDataQueryKind struct {
Kind string `json:"kind"`
Group string `json:"group"`
Version string `json:"version"`
// New type for datasource reference
// Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.
Datasource *DashboardV2alpha1DataQueryKindDatasource `json:"datasource,omitempty"`
Spec map[string]interface{} `json:"spec"`
// The kind of a DataQueryKind is the datasource type
Kind string `json:"kind"`
Spec map[string]interface{} `json:"spec"`
}
// NewDashboardDataQueryKind creates a new DashboardDataQueryKind object.
func NewDashboardDataQueryKind() *DashboardDataQueryKind {
return &DashboardDataQueryKind{
Kind: "DataQuery",
Version: "v0",
Spec: map[string]interface{}{},
Spec: map[string]interface{}{},
}
}
@@ -192,9 +199,10 @@ func NewDashboardPanelQueryKind() *DashboardPanelQueryKind {
// +k8s:openapi-gen=true
type DashboardPanelQuerySpec struct {
Query DashboardDataQueryKind `json:"query"`
RefId string `json:"refId"`
Hidden bool `json:"hidden"`
Query DashboardDataQueryKind `json:"query"`
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
RefId string `json:"refId"`
Hidden bool `json:"hidden"`
}
// NewDashboardPanelQuerySpec creates a new DashboardPanelQuerySpec object.
@@ -755,9 +763,7 @@ type DashboardRepeatOptions struct {
// NewDashboardRepeatOptions creates a new DashboardRepeatOptions object.
func NewDashboardRepeatOptions() *DashboardRepeatOptions {
return &DashboardRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardRepeatOptions{}
}
// other repeat modes will be added in the future: label, frame
@@ -932,9 +938,7 @@ type DashboardRowRepeatOptions struct {
// NewDashboardRowRepeatOptions creates a new DashboardRowRepeatOptions object.
func NewDashboardRowRepeatOptions() *DashboardRowRepeatOptions {
return &DashboardRowRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardRowRepeatOptions{}
}
// +k8s:openapi-gen=true
@@ -1007,9 +1011,7 @@ type DashboardAutoGridRepeatOptions struct {
// NewDashboardAutoGridRepeatOptions creates a new DashboardAutoGridRepeatOptions object.
func NewDashboardAutoGridRepeatOptions() *DashboardAutoGridRepeatOptions {
return &DashboardAutoGridRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardAutoGridRepeatOptions{}
}
// +k8s:openapi-gen=true
@@ -1075,9 +1077,7 @@ type DashboardTabRepeatOptions struct {
// NewDashboardTabRepeatOptions creates a new DashboardTabRepeatOptions object.
func NewDashboardTabRepeatOptions() *DashboardTabRepeatOptions {
return &DashboardTabRepeatOptions{
Mode: DashboardRepeatMode,
}
return &DashboardTabRepeatOptions{}
}
// Links with references to other dashboards or external resources
@@ -1221,6 +1221,7 @@ type DashboardQueryVariableSpec struct {
Refresh DashboardVariableRefresh `json:"refresh"`
SkipUrlSync bool `json:"skipUrlSync"`
Description *string `json:"description,omitempty"`
Datasource *DashboardDataSourceRef `json:"datasource,omitempty"`
Query DashboardDataQueryKind `json:"query"`
Regex string `json:"regex"`
Sort DashboardVariableSort `json:"sort"`
@@ -1626,21 +1627,6 @@ func NewDashboardGroupByVariableSpec() *DashboardGroupByVariableSpec {
}
}
// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec
// This type is widely used in the codebase and changing it will have a big impact
// +k8s:openapi-gen=true
type DashboardDataSourceRef struct {
// The plugin type-id
Type *string `json:"type,omitempty"`
// Specific datasource instance
Uid *string `json:"uid,omitempty"`
}
// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object.
func NewDashboardDataSourceRef() *DashboardDataSourceRef {
return &DashboardDataSourceRef{}
}
// Adhoc variable kind
// +k8s:openapi-gen=true
type DashboardAdhocVariableKind struct {
@@ -1701,9 +1687,7 @@ type DashboardAdHocFilterWithLabels struct {
// NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object.
func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels {
return &DashboardAdHocFilterWithLabels{
Origin: DashboardFilterOrigin,
}
return &DashboardAdHocFilterWithLabels{}
}
// Determine the origin of the adhoc variable filter
@@ -1774,16 +1758,6 @@ func NewDashboardSpec() *DashboardSpec {
}
}
// +k8s:openapi-gen=true
type DashboardV2alpha1DataQueryKindDatasource struct {
Name *string `json:"name,omitempty"`
}
// NewDashboardV2alpha1DataQueryKindDatasource creates a new DashboardV2alpha1DataQueryKindDatasource object.
func NewDashboardV2alpha1DataQueryKindDatasource() *DashboardV2alpha1DataQueryKindDatasource {
return &DashboardV2alpha1DataQueryKindDatasource{}
}
// +k8s:openapi-gen=true
type DashboardV2alpha1FieldConfigSourceOverrides struct {
Matcher DashboardMatcherConfig `json:"matcher"`

View File

@@ -109,7 +109,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2alpha1_DashboardTimeRangeOption(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardTimeSettingsSpec(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2alpha1_DashboardTransformationKind(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1DataQueryKindDatasource(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1FieldConfigSourceOverrides(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1RangeMapOptions": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1RangeMapOptions(ref),
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1RegexMapOptions": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1RegexMapOptions(ref),
@@ -596,10 +595,14 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common.
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"datasource": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
},
},
"query": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"),
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"),
},
},
"enable": {
@@ -657,11 +660,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common.
},
},
},
Required: []string{"query", "enable", "hide", "iconColor", "name"},
Required: []string{"enable", "hide", "iconColor", "name"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"},
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"},
}
}
@@ -1502,29 +1505,10 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataQueryKind(ref common.Refere
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"group": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"datasource": {
SchemaProps: spec.SchemaProps{
Description: "New type for datasource reference Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.",
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource"),
Description: "The kind of a DataQueryKind is the datasource type",
Default: "",
Type: []string{"string"},
Format: "",
},
},
"spec": {
@@ -1542,11 +1526,9 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataQueryKind(ref common.Refere
},
},
},
Required: []string{"kind", "group", "version", "spec"},
Required: []string{"kind", "spec"},
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource"},
}
}
@@ -1554,8 +1536,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataSourceRef(ref common.Refere
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec This type is widely used in the codebase and changing it will have a big impact",
Type: []string{"object"},
Type: []string{"object"},
Properties: map[string]spec.Schema{
"type": {
SchemaProps: spec.SchemaProps{
@@ -2909,6 +2890,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardPanelQuerySpec(ref common.Refer
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"),
},
},
"datasource": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
},
},
"refId": {
SchemaProps: spec.SchemaProps{
Default: "",
@@ -2928,7 +2914,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardPanelQuerySpec(ref common.Refer
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"},
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"},
}
}
@@ -3264,6 +3250,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re
Format: "",
},
},
"datasource": {
SchemaProps: spec.SchemaProps{
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"),
},
},
"query": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
@@ -3341,7 +3332,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re
},
},
Dependencies: []string{
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"},
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"},
}
}
@@ -4329,24 +4320,6 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardTransformationKind(ref common.R
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1DataQueryKindDatasource(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1FieldConfigSourceOverrides(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{

View File

@@ -14,8 +14,6 @@ import (
v1beta1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1"
)
var ()
var appManifestData = app.ManifestData{
AppName: "folder",
Group: "folder.grafana.app",

View File

@@ -10,6 +10,7 @@ RoleSpec: {
// Display name of the role
title: string
description: string
version: int
group: string

View File

@@ -18,9 +18,10 @@ func NewCoreRolespecPermission() *CoreRolespecPermission {
// +k8s:openapi-gen=true
type CoreRoleSpec struct {
// Display name of the role
Title string `json:"title"`
Version int64 `json:"version"`
Group string `json:"group"`
Title string `json:"title"`
Description string `json:"description"`
Version int64 `json:"version"`
Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?

View File

@@ -18,9 +18,10 @@ func NewGlobalRolespecPermission() *GlobalRolespecPermission {
// +k8s:openapi-gen=true
type GlobalRoleSpec struct {
// Display name of the role
Title string `json:"title"`
Version int64 `json:"version"`
Group string `json:"group"`
Title string `json:"title"`
Description string `json:"description"`
Version int64 `json:"version"`
Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?

View File

@@ -18,9 +18,10 @@ func NewRolespecPermission() *RolespecPermission {
// +k8s:openapi-gen=true
type RoleSpec struct {
// Display name of the role
Title string `json:"title"`
Version int64 `json:"version"`
Group string `json:"group"`
Title string `json:"title"`
Description string `json:"description"`
Version int64 `json:"version"`
Group string `json:"group"`
// TODO:
// delegatable?: bool
// created?

View File

@@ -186,6 +186,13 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -215,7 +222,7 @@ func schema_pkg_apis_iam_v0alpha1_CoreRoleSpec(ref common.ReferenceCallback) com
},
},
},
Required: []string{"title", "version", "group", "permissions"},
Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -740,6 +747,13 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -769,7 +783,7 @@ func schema_pkg_apis_iam_v0alpha1_GlobalRoleSpec(ref common.ReferenceCallback) c
},
},
},
Required: []string{"title", "version", "group", "permissions"},
Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{
@@ -1600,6 +1614,13 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
Format: "",
},
},
"description": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"version": {
SchemaProps: spec.SchemaProps{
Default: 0,
@@ -1629,7 +1650,7 @@ func schema_pkg_apis_iam_v0alpha1_RoleSpec(ref common.ReferenceCallback) common.
},
},
},
Required: []string{"title", "version", "group", "permissions"},
Required: []string{"title", "description", "version", "group", "permissions"},
},
},
Dependencies: []string{

View File

@@ -14,6 +14,8 @@ import (
v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1"
)
var ()
var appManifestData = app.ManifestData{
AppName: "iam",
Group: "iam.grafana.app",

View File

@@ -10,44 +10,14 @@
"kind": "AnnotationQuery",
"spec": {
"builtIn": true,
"enable": true,
"filter": {
"exclude": false,
"ids": [1]
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations \u0026 Alerts",
"query": {
"group": "grafana",
"kind": "DataQuery",
"spec": {},
"version": "v0"
}
}
},
{
"kind": "AnnotationQuery",
"spec": {
"query": {
"kind": "DataQuery",
"group": "grafana-testdata-datasource",
"version": "v0",
"spec": {
"lines": 10,
"refId": "Anno",
"scenarioId": "annotations"
}
},
"enable": true,
"hide": false,
"iconColor": "red",
"name": "Test data annotations",
"builtIn": false,
"filter": {
"exclude": false,
"ids": [1]
}
"name": "Annotations \u0026 Alerts"
}
}
],
@@ -67,16 +37,8 @@
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-testdata"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {
"scenarioId": "random_walk",
"seriesCount": 3
},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -89,7 +51,7 @@
"description": "",
"id": 1,
"links": [],
"title": "Simple timeseries (WITH DS REF)",
"title": "Simle timeseries",
"vizConfig": {
"kind": "timeseries",
"spec": {
@@ -131,12 +93,12 @@
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
"color": "green"
},
{
"color": "red",
@@ -160,7 +122,7 @@
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
"pluginVersion": "12.0.0-pre"
}
}
}
@@ -177,13 +139,8 @@
"spec": {
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {
"scenarioId": "random_walk",
"seriesCount": 4
},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -196,7 +153,7 @@
"description": "",
"id": 2,
"links": [],
"title": "Simple stat (NO DS REF)",
"title": "Simple stat",
"vizConfig": {
"kind": "stat",
"spec": {
@@ -205,12 +162,12 @@
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
"color": "green"
},
{
"color": "red",
@@ -236,496 +193,7 @@
"textMode": "auto",
"wideLayout": true
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-3": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"instant": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 3,
"links": [],
"title": "Panel with NO REF to gdev-prometheus",
"vizConfig": {
"kind": "timeseries",
"spec": {
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-4": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-prometheus"
},
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"instant": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 4,
"links": [],
"title": "Panel with ref to gdev-prometheus",
"vizConfig": {
"kind": "timeseries",
"spec": {
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-5": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-prometheus"
},
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
},
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"datasource": {
"name": "gdev-testdata"
},
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
},
"refId": "B"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 5,
"links": [],
"title": "Mixed DS WITH REFS",
"vizConfig": {
"kind": "timeseries",
"spec": {
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
}
}
}
},
"panel-6": {
"kind": "Panel",
"spec": {
"data": {
"kind": "QueryGroup",
"spec": {
"queries": [
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"group": "prometheus",
"kind": "DataQuery",
"spec": {
"disableTextWrap": false,
"editorMode": "builder",
"expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])",
"fullMetaSearch": false,
"includeNullMetadata": false,
"legendFormat": "__auto",
"range": true,
"useBackend": false
},
"version": "v0"
},
"refId": "A"
}
},
{
"kind": "PanelQuery",
"spec": {
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
},
"refId": "B"
}
}
],
"queryOptions": {},
"transformations": []
}
},
"description": "",
"id": 6,
"links": [],
"title": "Mixed DS WITHOUT REFS",
"vizConfig": {
"kind": "timeseries",
"spec": {
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": 0
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"hideZeros": false,
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "12.1.0-pre"
"pluginVersion": "12.0.0-pre"
}
}
}
@@ -736,24 +204,6 @@
"spec": {
"columnWidthMode": "standard",
"items": [
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-3"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-4"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
@@ -771,24 +221,6 @@
"name": "panel-1"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-5"
}
}
},
{
"kind": "AutoGridLayoutItem",
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-6"
}
}
}
],
"maxColumnCount": 3,
@@ -803,7 +235,7 @@
"autoRefresh": "",
"autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"fiscalYearStartMonth": 0,
"from": "now-5m",
"from": "now-6h",
"hideTimepicker": false,
"timezone": "browser",
"to": "now"

View File

@@ -78,18 +78,10 @@ refs:
# Create and manage reports
{{< admonition type="note" >}}
The redesigned reporting feature is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available. To use this feature, enable the `newShareReportDrawer` feature toggle in your Grafana configuration file or, for Grafana Cloud, contact Support.
{{< /admonition >}}
**Reporting** allows you to send automated and scheduled emails from any of your dashboards.
You can configure several elements of these reports and generate PDFs and CSV files.
You can configure several elements of these reports and generate PDFs, CSV files, and embedded images.
Any changes you make to a dashboard used in a report are reflected the next time the report is sent.
{{< figure src="/media/docs/grafana/dashboards/screenshot-report-config-v12.0.png" max-width="600px" alt="The report configuration screen" >}}
## Requirements
For Grafana Enterprise, the Reporting feature has the following requirements:
@@ -116,89 +108,28 @@ Refer to specific guides to understand what permissions are required.
## Create a report
The report creation process is multi-step, but you don't need to complete these steps in order.
The report creation process is multi-step, but you don't need to complete these steps in order and you can skip steps by clicking a step name at the top of the page.
You can also save the report as a draft at any point during the initial creation process.
You can also save the report as a draft at any step in the process:
You can create directly from a dashboard or from the **Reporting** page.
Select one of the following tabs for directions on each option.
![Reporting wizard](/media/docs/grafana/dashboards/screenshot-reporting-wizard-v11.5.png)
To create a report, follow these steps:
{{< tabs >}}
{{< tab-content name="Create a report directly from a dashboard" >}}
1. In the main menu, click **Dashboards**.
1. Navigate to the dashboard from which you want to create a report.
1. Click the **Share** drop-down list in the top-right corner of the dashboard.
1. Click **Schedule report**.
The **Schedule report** drawer opens. Any other reports using this dashboard are listed in the drawer. You can also click **See all reports** to navigate to **Reporting** for a full list of reports generated from all dashboards.
1. Click **+ Create a new report**.
1. Update the name of the report, if needed.
By default, the report name is the name of the dashboard.
1. Expand and complete each section of the report, as needed:
- [Dashboards](#1-dashboards)
- [Schedule](#2-schedule)
- [Email settings](#3-email-settings)
- [Recipients](#4-recipients)
- [Attachments](#5-attachments)
1. Click one of the following buttons at the bottom of the **Schedule report** drawer:
- The menu icon to access the following options:
- **Download CSV**
- **Preview PDF**
- **Report settings** - Takes you to **Reporting** in a new browser tab and opens the **Report template settings** drawer, where you can configure organization-level report settings.
- **Send preview** - Send a preview of the report to your desired recipient. You can choose to use the report recipients:
{{< figure src="/media/docs/grafana/dashboards/screenshot-send-preview-v12.0.png" max-width="350px" alt="The Send preview modal" >}}
- **Schedule report** - The report is sent according the schedule you've set.
- **Save draft** - You can save a draft at any point during the initial report creation process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
If you click the **x** at the top of the drawer without scheduling or saving the report as a draft, the report is discarded. This action can't be reversed.
1. When you finish configuring the report, click the **x** at the top of the **Schedule report** drawer to close it.
{{< /tab-content >}}
{{< tab-content name="Create a report from Reporting" >}}
1. In the main menu, click **Dashboards > Reporting**.
1. Click **+ Create a new report**.
1. Complete the report steps, as needed:
- [Select dashboard](#1-select-dashboard)
- [Format report](#2-format-report)
- [Schedule](#3-schedule)
- [Share](#4-share)
- [Confirm](#5-confirm)
1. Click one of the following buttons in the top-right corner of the screen:
- **Send now** or **Schedule send** - The report is sent according the schedule you've set.
- **Save as draft** - You can save a draft at any point during the report creation or update process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
- **Discard** - Delete the report draft. This action can't be reversed.
The **Schedule report** drawer opens.
1. Enter a name for the report.
1. Expand and complete each section of the report, as needed:
- [Dashboards](#1-dashboards)
- [Schedule](#2-schedule)
- [Email settings](#3-email-settings)
- [Recipients](#4-recipients)
- [Attachments](#5-attachments)
1. Click one of the following buttons at the bottom of the **Schedule report** drawer:
- The menu icon to access the following options:
- **Download CSV**
- **Preview PDF**
- **Report settings** - Opens the **Report template settings** drawer, where you can configure organization-level report settings.
- **Send preview** - Send a preview of the report to your desired recipient. You can choose to use the report recipients:
{{< figure src="/media/docs/grafana/dashboards/screenshot-send-preview-v12.0.png" max-width="350px" alt="The Send preview modal" >}}
- **Schedule report** - The report is sent according the schedule you've set.
- **Save draft** - Save a draft at any point during the initial report creation process, even if it's missing required fields. The report won't be sent according to its schedule while it's a draft.
If you click the **x** at the top of the drawer without scheduling or saving the report as a draft, the report is discarded. This action can't be reversed.
1. When you finish configuring the report, click the **x** at the top of the **Schedule report** drawer to close it.
{{< /tab-content >}}
{{< /tabs >}}
### 1. Dashboards
### 1. Select dashboard
At this step, select the dashboard or dashboards on which the report is based, as well as the variables and time ranges for those dashboards.
The options are:
@@ -207,53 +138,35 @@ The options are:
| Option | Description |
| ------ | ----------- |
| Source dashboard (required) | Select or update the dashboard from which you want to generate the report. If you've created your report directly from a dashboard, this field is already filled in with the name of the current dashboard. |
| [Time range](#time-range) | Update the report time range. If you've created the report directly from a dashboard, the default time range is that of the dashboard. Otherwise, the default time range is **Last 6 hours**. |
| [Customize template variables](#customize-template-variables) | Select and customize the variable values for the selected dashboard. This section is only displayed if the dashboard has variables. |
| + Add dashboard | Add more dashboards to the report. |
| Source dashboard (required) | Select the dashboard from which you want to generate the report. |
| [Template variables](#template-variables) | Select the variable values for the selected dashboard. This option is only displayed if the dashboard has variables. |
| [Time range](#time-range) | If you leave the field empty, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report. |
| Add another dashboard | Add more dashboards to the report. |
<!-- prettier-ignore-end -->
#### Template variables
This option is only displayed if the dashboard has variables.
You can configure report-specific template variables for the dashboard on the report page.
The variables that you select override the variables from the dashboard.
For detailed information about using template variables, refer to [Variables](ref:templates-and-variables).
The query variables saved with a report might become out-of-date if the results of that query change.
For example, if your template variable queries for a list of hostnames and a new hostname is added, then it won't be included in the report.
If that occurs, the selected variables must be manually updated in the report.
If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
#### Time range
If you leave the **Time range** field empty, reports use the saved time range of the dashboard.
Optionally, you can change the time range of the report by setting it in the **Time range** field.
If specified, the custom time range overrides the time range from the report's dashboard.
#### Customize template variables
The page header of the report displays the time range for the dashboard's data queries.
Configure report-specific template variables for the dashboard.
The variables that you select override the variables from the dashboard.
For detailed information about using template variables, refer to [Variables](ref:templates-and-variables).
The query variables saved with a report might become out of date if the results of that query change.
For example, if your template variable queries for a list of hostnames and a new hostname is added, then it won't be included in the report.
If that occurs, the selected variables must be manually updated in the report.
If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
This option is only displayed if the dashboard has variables.
### 2. Schedule
At this step, set scheduling information.
Options vary depending on the frequency you select.
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Schedule | Choose one of the following:<ul><li>**Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date.</li><li>**Send later** schedules a report for a later date. When you select this option, the required **Start date**, **Start time**, and **Time zone** options are displayed.</li></ul> |
| Frequency | You can schedule reports to be sent once, repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. |
| Start date | Set the date when the report should start being sent. |
| Start time | Set the time when the report should start being sent. |
| [Time zone](#time-zone) | Set the time zone of the report. |
| End date | Set the date when the report should stop being sent. If you leave this field empty, the report is sent out indefinitely. |
| Send only from Monday to Friday | For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday. |
| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select the **Send on the last day of the month** option. This way, the report is sent on the last day of every month regardless of how many days there are in the month. |
<!-- prettier-ignore-end -->
#### Time zone
##### Report time zones
Reports use the time zone of the dashboard from which they're generated.
You can control the time zone for your reports by setting the dashboard to a specific time zone.
@@ -265,54 +178,34 @@ If you want to use a specific time zone, save the dashboard with a fixed time zo
Each dashboard's time zone setting is visible in the [time range controls](ref:time-range-controls).
### 3. Email settings
### 2. Format report
At this step, configure the report email:
<!-- vale Grafana.GoogleLyHyphens = NO -->
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Email subject | If you leave this field empty, the report name is used as the email subject line. |
| Message | The body of the message in the report email. |
| Reply-to-email address | The address that appears in the **Reply to** field of the email. |
| Include a dashboard link | Include links to the dashboards in the report email. |
| Embed dashboard image | The report email is sent with an images of the dashboards embedded in it so recipients see them at a glance. |
<!-- prettier-ignore-end -->
<!-- vale Grafana.GoogleLyHyphens = YES -->
### 4. Recipients
Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons.
### 5. Attachments
At this step, select one or more report attachment options.
At this step, select one or more report formatting options.
You can select multiple options, but you must select _at least one_:
- **Attach the report as a PDF** - Attach the report as one PDF file.
- **[Attach a separate PDF of table data](#table-data-in-pdf)** - Attach a separate PDF file to the report email for each table panel on the selected dashboard. Public preview only.
- **Attach a CSV file of table panel data** - Attach a CSV file to the report email for each table panel on the selected dashboard.
- [Attach the report as a PDF](#attach-the-report-as-a-pdf)
- [Include table data as PDF appendix](#table-data-in-pdf) (Public preview only)
- [Embed a dashboard image in the email](#embed-a-dashboard-as-an-image-in-the-email)
- [Attach a CSV file of the table panel data](#attach-a-csv-file-of-the-table-panel-data)
- [Attach a separate PDF of table data](#table-data-in-pdf) (Public preview only)
#### PDF format
#### Attach the report as a PDF
If you selected a PDF attachment, configure the following formatting options:
If you selected the PDF format option under the **Style the PDF** section, you can configure the following options:
<!-- prettier-ignore-start -->
- **Configure multiple PDFs** - Click the **Combine all dashboard PDFs in one file** checkbox if you want to generate one PDF file for all the dashboards included in the report. This option is only displayed if your report includes multiple dashboards.
- **Configure report header** - Click the **Show template variables** checkbox to show dashboard variables.
- **Orientation** - Set the report orientation in **Portrait** or **Landscape**. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
- **Layout** - Select one of the following:
| Option | Description |
|---------------------------------|-------------------------------------------------------------------------------------------------|
| Orientation | Set the report orientation in **Portrait** or **Landscape**. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples. |
| Layout | Select one of the following:<ul><li>**Simple** - Renders each panel as full-width across the PDF.</li><li>**Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard.</li></ul>Refer to the [Layout and orientation table](#layout-and-orientation) to see examples. |
| Zoom | Zoom in to enlarge text in your PDF or zoom out to see more data (like table columns) per panel. |
| Combine all dashboard PDFs in one file | Click the checkbox if you want to generate one PDF file for all the dashboards included in the report. This option is only displayed if there are multiple dashboards in the report. |
| Show template variables | Click the checkbox to show dashboard variables. This option is only displayed if the report contains variables. |
| [Include table data as PDF appendix](#table-data-in-pdf) | Add an appendix of the dashboard table data to the report PDF. This is useful when there's more data in your table visualization than can be shown in the dashboard PDF. _Public preview only._ |
<!-- prettier-ignore-end -->
- **Simple** - Renders each panel as full-width across the PDF.
- **Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard.
Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
- **Zoom** - Zoom in to enlarge text in your PDF, or zoom out to see more data (like table columns) per panel.
Click **Preview PDF** in the top-right corner of the screen to view a rendered PDF with the options you selected.
##### Layout and orientation
@@ -327,6 +220,17 @@ If you selected a PDF attachment, configure the following formatting options:
<!-- prettier-ignore-end -->
#### Embed a dashboard as an image in the email
You can send a report email with an image of the dashboard embedded in the email.
This lets the email recipients see the dashboard at a glance.
#### Attach a CSV file of the table panel data
You can attach a CSV file to the report email for each table panel on the selected dashboard.
Click **Download CSV** in the top-right corner of the screen to download a zipped file of the CSV files for your selected dashboard.
#### Table data in PDF
{{< admonition type="note" >}}
@@ -338,66 +242,94 @@ When there's more data in your table visualizations than can be shown in the das
- **Include table data as PDF appendix** - Adds an appendix to the dashboard PDF.
- **Attach a separate PDF of table data** - Generates a separate PDF file.
### 3. Schedule
At this step, set scheduling information.
Options vary depending on the frequency you select.
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Frequency | You can schedule reports to be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**. For example, you might want to [send the report using the API](#send-a-report-using-the-api). |
| Time | Choose one of the following:<ul><li>**Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date.</li><li>**Send later** schedules a report for a later date. When you select this option, the required **Start date**, **Start time**, and **Time zone** options are displayed.</li></ul> |
| End date | If you leave this field empty, the report is sent out indefinitely. |
| Send only from Monday to Friday | For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday. |
| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select the **Send on the last day of the month** option. This way, the report is sent on the last day of every month regardless of how many days there are in the month. |
<!-- prettier-ignore-end -->
### 4. Share
At this step, enter information related to sharing the report:
<!-- vale Grafana.GoogleLyHyphens = NO -->
<!-- prettier-ignore-start -->
| Option | Description |
| ------ | ----------- |
| Report name (required) | The name of the report as you want it to appear in the **Reports** list. The report name also populates the email subject line. |
| Recipients (required) | Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons. |
| Reply-to email address | The address that appears in the **Reply to** field of the email. |
| Message | The body of the message in the email with the report. |
| Include a dashboard link | Include a links to the dashboards in the report email. |
<!-- prettier-ignore-end -->
<!-- vale Grafana.GoogleLyHyphens = YES -->
Click **Send test email** in the top-right corner of the screen to verify that the configuration works as expected and to verify that emails are working.
You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing.
### 5. Confirm
At this step, the confirmation page displays all the report settings.
Review them and confirm that they're correct or click the provided **Edit** links for each section to make updates.
Then, click **Send now** or **Schedule send**.
You can also save the report as a draft or discard it. Discarding the report is irreversible.
## Send a report using the API
You can send reports programmatically with the [send report](ref:send-report) endpoint using the HTTP API.
## Manage reports
You can view and manage all your reports, and create new ones, on the **Reporting** page:
On the **Reports** page, you can view and manage your existing reports or create new ones.
{{< figure src="/media/docs/grafana/dashboards/screenshot-reporting-page-v12.0.png" max-width="750px" alt="The Reporting page" >}}
Alternatively, from any dashboard you can view and manage any reports generated from that dashboard, as well as create a new report
You can also navigate to the list of all reports from the dashboard-specific list:
{{< figure src="/media/docs/grafana/dashboards/screenshot-report-drawer-v12.0.png" max-width="750px" alt="The open Report schedule drawer with an existing report" >}}
![Reports page](/media/docs/grafana/dashboards/screenshot-reports-page-v11.5.png)
### Edit reports
To edit a report, follow these steps:
1. Do one of the following:
- In the main menu, click **Dashboards > Reporting**.
- Navigate to the dashboard from which the report was generated and click **Share > Schedule report**.
1. In the main menu, click **Dashboards > Reporting**.
1. Click the row of the report you want to update.
1. Make the necessary changes.
1. Click the **Edit report** button in the top-right hand corner or click the **Edit** link for a specific section to go to that one directly.
1. When you've finished making changes, click **Confirm** at the top of the screen to go to the last step.
1. Click **Update report**.
1. Click the **x** at the top of the drawer to close it.
### Pause or resume reports
### Pause or resume reports {#pause-a-report}
You can pause and resume sending reports from the report list view.
To do this, follow these steps:
1. Do one of the following:
- In the main menu, click **Dashboards > Reporting**.
- Navigate to the dashboard from which the report was generated and click **Share > Schedule report**.
1. In the main menu, click **Dashboards > Reporting**.
1. On the row of the report you want to update, do one of the following:
- Click the pause icon - The report won't be sent according to its schedule until it's resumed.
- Click the resume icon - The report resumes on its previous schedule.
You can also pause or resume a report from **Update report** drawer.
### Delete reports
To delete a report, follow these steps:
1. Do one of the following:
- In the main menu, click **Dashboards > Reporting**.
- Navigate to the dashboard from which the report was generated and click **Share > Schedule report**.
1. In the main menu, click **Dashboards > Reporting**.
1. On the row of the report you want to update, click the trash can icon.
1. Click **Delete** to confirm.
You can also delete a report from **Update report** drawer.
Deleting a report is irreversible.
## Troubleshoot Reporting

View File

@@ -21,19 +21,8 @@ refs:
# Reporting settings
You can configure organization-wide report settings and branding options in **Dashboards > Reporting**.
These settings are applied to all the reports for the current organization.
To access the settings, go to **Dashboards > Reporting** and click the **Report settings** button.
This opens the **Report template settings** drawer, where you can make changes.
{{< admonition type="note" >}}
The redesigned reporting feature, including the report settings drawer, is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available. To use this feature, enable the `newShareReportDrawer` feature toggle in your Grafana configuration file or, for Grafana Cloud, contact Support.
{{< /admonition >}}
You can also navigate these settings from the **Schedule report** drawer that opens when you create a report directly from a dashboard.
You can configure organization-wide report settings and branding options in **Dashboards > Reporting > Settings**.
Settings are applied to all the reports for the current organization.
## Attachment settings

View File

@@ -20,7 +20,7 @@ weight: 200
{{< admonition type="caution" >}}
Dashboard JSON schema v2 is an experimental feature. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. Enable the `dashboardNewLayouts` feature toggle in Grafana to use this feature.
Dashboard JSON schema v2 is an [experimental](https://grafana.com/docs/release-life-cycle/) feature. Engineering and on-call support is not available. Documentation is either limited or not provided outside of code comments. No SLA is provided. To get early access to this feature, request it through [this form](https://docs.google.com/forms/d/e/1FAIpQLSd73nQzuhzcHJOrLFK4ef_uMxHAQiPQh1-rsQUT2MRqbeMLpg/viewform?usp=dialog).
**Do not enable this feature in production environments as it may result in the irreversible loss of data.**
@@ -32,7 +32,8 @@ Observability as Code works with all versions of the JSON model, and it's fully
## Before you begin
Schema v2 is automatically enabled with the Dynamic Dashboards feature toggle, `dashboardNewLayouts`.
Schema v2 is automatically enabled with the Dynamic Dashboards feature toggle.
To get early access to this feature, request it through [this form](https://docs.google.com/forms/d/e/1FAIpQLSd73nQzuhzcHJOrLFK4ef_uMxHAQiPQh1-rsQUT2MRqbeMLpg/viewform?usp=dialog).
It also requires the new dashboards API feature toggle, `kubernetesDashboards`, to be enabled as well.
For more information on how dashboards behave depending on your feature flag configuration, refer to [Notes and limitations](#notes-and-limitations).
@@ -217,18 +218,18 @@ Upon saving, theyll be updated to the new schema where you can take advantage
### Dashboard behavior with disabled feature flags
If you disable the `dashboardNewLayouts` or `kubernetesDashboards` feature flags, you should be aware of how dashboards will behave.
If you disable the Dynamic dashboards or `kubernetesDashboards` feature flags, you should be aware of how dashboards will behave.
#### Disable `dashboardNewLayouts`
#### Disable Dynamic dashboards
If `dashboardNewLayouts` feature toggle is disabled, depending on how the dashboard was built, it will behave differently:
If the Dynamic dashboards feature toggle is disabled, depending on how the dashboard was built, it will behave differently:
- Dashboards built on the new schema through the UI - View only
- Dashboards built on Schema v1 - View and edit
- Dashboards built on the new schema by way of Terraform or the CLI - View and edit
- Provisioned dashboards built on the new schema - View and edit, but the edit experience will be the old experience
#### Disable `dashboardNewLayouts` and `kubernetesDashboards`
#### Disable Dynamic dashboards and `kubernetesDashboards`
Youll be unable to view or edit dashboards created or updated in the new schema.

View File

@@ -2838,22 +2838,14 @@ For example:
```ini
[time_picker]
quick_ranges = [
{
"display": "Last 5 minutes",
"from": "now-5m",
"to": "now",
},
{
"display": "Yesterday",
"from": "now-1d/d",
},
{
"display": "Today so far",
"from": "now/d",
"to": "now",
}
]
quick_ranges = """[
{"from":"now-6s","to":"now","display":"Last 6 seconds"},
{"from":"now-10m","to":"now","display":"Last 10 minutes"},
{"from":"now-25h","to":"now","display":"Last 24 hours"},
{"from":"now/w","to":"now/w","display":"This week"},
{"from":"now-1w/w","to":"now-1w/w","display":"Last week"},
{"from":"now-10d","to":"now","display":"Last 10 days"}
]"""
```
### `[expressions]`

View File

@@ -236,9 +236,11 @@ With our Grafana and Apache containers running, you can now connect to http://lo
If the user is deleted from Grafana, the user will be not be able to login and resync until after the `sync_ttl` has expired.
{{< /admonition >}}
### Team Sync (Enterprise only)
### Team Sync
> Only available in Grafana Enterprise v6.3+
{{< admonition type="note" >}}
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
With Team Sync, it's possible to set up synchronization between teams in your authentication provider and Grafana. You can send Grafana values as part of an HTTP header and have Grafana map them to your team structure. This allows you to put users into specific teams automatically.

View File

@@ -239,10 +239,6 @@ Ensure that you have followed the steps in [Create the Microsoft Entra ID applic
## Configure Azure AD authentication client using the Grafana UI
{{< admonition type="note" >}}
Available in Public Preview in Grafana 10.4 behind the `ssoSettingsApi` feature toggle.
{{< /admonition >}}
As a Grafana Admin, you can configure your Azure AD/Entra ID OAuth client from within Grafana using the Grafana UI. To do this, navigate to the **Administration > Authentication > Azure AD** page and fill in the form. If you have a current configuration in the Grafana configuration file, the form will be pre-populated with those values. Otherwise the form will contain default values.
After you have filled in the form, click **Save** to save the configuration. If the save was successful, Grafana will apply the new configurations.
@@ -255,10 +251,6 @@ If you run Grafana in high availability mode, configuration changes may not get
## Configure Azure AD authentication client using the Terraform provider
{{< admonition type="note" >}}
Available in Public Preview in Grafana 10.4 behind the `ssoSettingsApi` feature toggle. Supported in the Terraform provider since v2.12.0.
{{< /admonition >}}
```terraform
resource "grafana_sso_settings" "azuread_sso_settings" {
provider_name = "azuread"
@@ -426,7 +418,11 @@ This setting is ignored if multiple auth providers are configured to use auto lo
auto_login = true
```
### Team Sync (Enterprise only)
### Team Sync
{{< admonition type="note" >}}
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
With Team Sync you can map your Entra ID groups to teams in Grafana so that your users will automatically be added to
the correct teams.

View File

@@ -49,10 +49,6 @@ If Users use the same email address in Azure AD that they use with other authent
## Configure generic OAuth authentication client using the Grafana UI
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
{{< /admonition >}}
As a Grafana Admin, you can configure Generic OAuth client from within Grafana using the Generic OAuth UI. To do this, navigate to **Administration > Authentication > Generic OAuth** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values.
After you have filled in the form, click **Save** to save the configuration. If the save was successful, Grafana will apply the new configurations.
@@ -67,10 +63,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure generic OAuth authentication client using the Terraform provider
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
{{< /admonition >}}
```terraform
resource "grafana_sso_settings" "generic_sso_settings" {
provider_name = "generic_oauth"
@@ -134,7 +126,7 @@ To integrate your OAuth2 provider with Grafana using our Generic OAuth authentic
### Configure login
Grafana can resolve a user's login from the OAuth2 ID token or user information retrieved from the OAuth2 UserInfo endpoint.
Grafana can resolve a user's login from the OAuth2 ID token, user information retrieved from the OAuth2 UserInfo endpoint, or the OAuth2 access token.
Grafana looks at these sources in the order listed until it finds a login.
If no login is found, then the user's login is set to user's email address.
@@ -146,10 +138,12 @@ Refer to the following table for information on what to configure based on how y
| Another field of the OAuth2 ID token. | Set `login_attribute_path` configuration option. |
| `login` or `username` field of the user information from the UserInfo endpoint. | N/A |
| Another field of the user information from the UserInfo endpoint. | Set `login_attribute_path` configuration option. |
| `login` or `username` field of the OAuth2 access token. | N/A |
| Another field of the OAuth2 access token. | Set `login_attribute_path` configuration option. |
### Configure display name
Grafana can resolve a user's display name from the OAuth2 ID token or user information retrieved from the OAuth2 UserInfo endpoint.
Grafana can resolve a user's display name from the OAuth2 ID token, user information retrieved from the OAuth2 UserInfo endpoint, or the OAuth2 access token.
Grafana looks at these sources in the order listed until it finds a display name.
If no display name is found, then user's login is displayed instead.
@@ -161,10 +155,12 @@ Refer to the following table for information on what you need to configure depen
| Another field of the OAuth2 ID token. | Set `name_attribute_path` configuration option. |
| `name` or `display_name` field of the user information from the UserInfo endpoint. | N/A |
| Another field of the user information from the UserInfo endpoint. | Set `name_attribute_path` configuration option. |
| `name` or `display_name` field of the OAuth2 access token. | N/A |
| Another field of the OAuth2 access token. | Set `name_attribute_path` configuration option. |
### Configure email address
Grafana can resolve the user's email address from the OAuth2 ID token, the user information retrieved from the OAuth2 UserInfo endpoint, or the OAuth2 `/emails` endpoint.
Grafana can resolve the user's email address from the OAuth2 ID token, the user information retrieved from the OAuth2 UserInfo endpoint, the OAuth2 access token, or the OAuth2 `/emails` endpoint.
Grafana looks at these sources in the order listed until an email address is found.
If no email is found, then the email address of the user is set to an empty string.
@@ -177,6 +173,10 @@ Refer to the following table for information on what to configure based on how t
| `upn` field of the OAuth2 ID token. | N/A |
| `email` field of the user information from the UserInfo endpoint. | N/A |
| Another field of the user information from the UserInfo endpoint. | Set `email_attribute_path` configuration option. |
| `email` field of the OAuth2 access token. | N/A |
| `attributes` map of the OAuth2 access token. | Set `email_attribute_name` configuration option. By default, Grafana searches for email under `email:primary` key. |
| `upn` field of the OAuth2 access token. | N/A |
| Another field of the OAuth2 access token. | Set `email_attribute_path` configuration option. |
| Email address marked as primary from the `/emails` endpoint of <br /> the OAuth2 provider (obtained by appending `/emails` to the URL <br /> configured with `api_url`) | N/A |
### Configure a refresh token
@@ -199,6 +199,7 @@ The `accessTokenExpirationCheck` feature toggle has been removed in Grafana v10.
Unless `skip_org_role_sync` option is enabled, the user's role will be set to the role retrieved from the auth provider upon user login.
The user's role is retrieved using a [JMESPath](http://jmespath.org/examples.html) expression from the `role_attribute_path` configuration option.
Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no role is found, the expression will be evaluated using the OAuth2 access token.
To map the server administrator role, use the `allow_assign_grafana_admin` configuration option.
Refer to [configuration options](#configuration-options) for more information.
@@ -319,13 +320,14 @@ org_mapping = org_foo:org_foo:Viewer org_bar:org_bar:Editor *:org_baz:Editor
## Configure team synchronization
{{< admonition type="note" >}}
Available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can link your OAuth2 groups to teams within Grafana. This will automatically assign users to the appropriate teams.
Teams for each user are synchronized when the user logs in.
Generic OAuth groups can be referenced by group ID, such as `8bab1c86-8fba-33e5-2089-1d1c80ec267d` or `myteam`.
Group information can be extracted from the OAuth2 ID token, user information from the UserInfo endpoint, or the OAuth2 access token.
For information on configuring OAuth2 groups with Grafana using the `groups_attribute_path` configuration option, refer to [configuration options](#configuration-options).
To learn more about Team Sync, refer to [Configure team sync](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-team-sync/).
@@ -359,46 +361,46 @@ The following table outlines the various Generic OAuth configuration options. Yo
If the configuration option requires a JMESPath expression that includes a colon, enclose the entire expression in quotes to prevent parsing errors. For example `role_attribute_path: "role:view"`
{{< /admonition >}}
| Setting | Required | Supported on Cloud | Description | Default |
| ---------------------------- | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `enabled` | No | Yes | Enables Generic OAuth authentication. | `false` |
| `name` | No | Yes | Name that refers to the Generic OAuth authentication from the Grafana user interface. | `OAuth` |
| `icon` | No | Yes | Icon used for the Generic OAuth authentication in the Grafana user interface. | `signin` |
| `client_id` | Yes | Yes | Client ID provided by your OAuth2 app. | |
| `client_secret` | Yes | Yes | Client secret provided by your OAuth2 app. | |
| `auth_url` | Yes | Yes | Authorization endpoint of your OAuth2 provider. | |
| `token_url` | Yes | Yes | Endpoint used to obtain the OAuth2 access token. | |
| `api_url` | Yes | Yes | Endpoint used to obtain user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | |
| `auth_style` | No | Yes | Name of the [OAuth2 AuthStyle](https://pkg.go.dev/golang.org/x/oauth2#AuthStyle) to be used when ID token is requested from OAuth2 provider. It determines how `client_id` and `client_secret` are sent to Oauth2 provider. Available values are `AutoDetect`, `InParams` and `InHeader`. | `AutoDetect` |
| `scopes` | No | Yes | List of comma- or space-separated OAuth2 scopes. | `user:email` |
| `empty_scopes` | No | Yes | Set to `true` to use an empty scope during authentication. | `false` |
| `allow_sign_up` | No | Yes | Controls Grafana user creation through the Generic OAuth login. Only existing Grafana users can log in with Generic OAuth if set to `false`. | `true` |
| `auto_login` | No | Yes | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `id_token_attribute_name` | No | Yes | The name of the key used to extract the ID token from the returned OAuth2 token. | `id_token` |
| `login_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user login lookup from the user ID token. For more information on how user login is retrieved, refer to [Configure login](#configure-login). | |
| `name_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user name lookup from the user ID token. This name will be used as the user's display name. For more information on how user display name is retrieved, refer to [Configure display name](#configure-display-name). | |
| `email_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user email lookup from the user information. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | |
| `email_attribute_name` | No | Yes | Name of the key to use for user email lookup within the `attributes` map of OAuth2 ID token. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | `email:primary` |
| `role_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | |
| `role_attribute_strict` | No | Yes | Set to `true` to deny user login if the Grafana org role cannot be extracted using `role_attribute_path` or `org_mapping`. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
| `skip_org_role_sync` | No | Yes | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
| `org_attribute_path` | No | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana org to role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no value is returned, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation will be mapped to org roles based on `org_mapping`. For more information on org to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `org_mapping` | No | No | List of comma- or space-separated `<ExternalOrgName>:<OrgIdOrName>:<Role>` mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. For more information on external organization to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `allow_assign_grafana_admin` | No | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
| `groups_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user group lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no groups are found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. The result of the evaluation should be a string array of groups. | |
| `allowed_groups` | No | Yes | List of comma- or space-separated groups. The user should be a member of at least one group to log in. If you configure `allowed_groups`, you must also configure `groups_attribute_path`. | |
| `allowed_organizations` | No | Yes | List of comma- or space-separated organizations. The user should be a member of at least one organization to log in. | |
| `allowed_domains` | No | Yes | List of comma- or space-separated domains. The user should belong to at least one domain to log in. | |
| `team_ids` | No | Yes | String list of team IDs. If set, the user must be a member of one of the given teams to log in. If you configure `team_ids`, you must also configure `teams_url` and `team_ids_attribute_path`. | |
| `team_ids_attribute_path` | No | Yes | The [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana team ID lookup within the results returned by the `teams_url` endpoint. | |
| `teams_url` | No | Yes | The URL used to query for team IDs. If not set, the default value is `/teams`. If you configure `teams_url`, you must also configure `team_ids_attribute_path`. | |
| `tls_skip_verify_insecure` | No | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
| `tls_client_cert` | No | No | The path to the certificate. | |
| `tls_client_key` | No | No | The path to the key. | |
| `tls_client_ca` | No | No | The path to the trusted certificate authority list. | |
| `use_pkce` | No | Yes | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `false` |
| `use_refresh_token` | No | Yes | Set to `true` to use refresh token and check access token expiration. | `false` |
| `signout_redirect_url` | No | Yes | URL to redirect to after the user logs out. | |
| Setting | Required | Supported on Cloud | Description | Default |
| ---------------------------- | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `enabled` | No | Yes | Enables Generic OAuth authentication. | `false` |
| `name` | No | Yes | Name that refers to the Generic OAuth authentication from the Grafana user interface. | `OAuth` |
| `icon` | No | Yes | Icon used for the Generic OAuth authentication in the Grafana user interface. | `signin` |
| `client_id` | Yes | Yes | Client ID provided by your OAuth2 app. | |
| `client_secret` | Yes | Yes | Client secret provided by your OAuth2 app. | |
| `auth_url` | Yes | Yes | Authorization endpoint of your OAuth2 provider. | |
| `token_url` | Yes | Yes | Endpoint used to obtain the OAuth2 access token. | |
| `api_url` | Yes | Yes | Endpoint used to obtain user information compatible with [OpenID UserInfo](https://connect2id.com/products/server/docs/api/userinfo). | |
| `auth_style` | No | Yes | Name of the [OAuth2 AuthStyle](https://pkg.go.dev/golang.org/x/oauth2#AuthStyle) to be used when ID token is requested from OAuth2 provider. It determines how `client_id` and `client_secret` are sent to Oauth2 provider. Available values are `AutoDetect`, `InParams` and `InHeader`. | `AutoDetect` |
| `scopes` | No | Yes | List of comma- or space-separated OAuth2 scopes. | `user:email` |
| `empty_scopes` | No | Yes | Set to `true` to use an empty scope during authentication. | `false` |
| `allow_sign_up` | No | Yes | Controls Grafana user creation through the Generic OAuth login. Only existing Grafana users can log in with Generic OAuth if set to `false`. | `true` |
| `auto_login` | No | Yes | Set to `true` to enable users to bypass the login screen and automatically log in. This setting is ignored if you configure multiple auth providers to use auto-login. | `false` |
| `id_token_attribute_name` | No | Yes | The name of the key used to extract the ID token from the returned OAuth2 token. | `id_token` |
| `login_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user login lookup from the user ID token. For more information on how user login is retrieved, refer to [Configure login](#configure-login). | |
| `name_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user name lookup from the user ID token. This name will be used as the user's display name. For more information on how user display name is retrieved, refer to [Configure display name](#configure-display-name). | |
| `email_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user email lookup from the user information. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | |
| `email_attribute_name` | No | Yes | Name of the key to use for user email lookup within the `attributes` map of OAuth2 ID token. For more information on how user email is retrieved, refer to [Configure email address](#configure-email-address). | `email:primary` |
| `role_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no role is found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no role is found, the expression will be evaluated using the OAuth2 access token. The result of the evaluation should be a valid Grafana role (`None`, `Viewer`, `Editor`, `Admin` or `GrafanaAdmin`). For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | |
| `role_attribute_strict` | No | Yes | Set to `true` to deny user login if the Grafana org role cannot be extracted using `role_attribute_path` or `org_mapping`. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
| `skip_org_role_sync` | No | Yes | Set to `true` to stop automatically syncing user roles. This will allow you to set organization roles for your users from within Grafana manually. | `false` |
| `org_attribute_path` | No | No | [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana org to role lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no value is returned, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no value is returned, the expression will be evaluated using the OAuth2 access token. The result of the evaluation will be mapped to org roles based on `org_mapping`. For more information on org to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `org_mapping` | No | No | List of comma- or space-separated `<ExternalOrgName>:<OrgIdOrName>:<Role>` mappings. Value can be `*` meaning "All users". Role is optional and can have the following values: `None`, `Viewer`, `Editor` or `Admin`. For more information on external organization to role mapping, refer to [Org roles mapping example](#org-roles-mapping-example). | |
| `allow_assign_grafana_admin` | No | No | Set to `true` to enable automatic sync of the Grafana server administrator role. If this option is set to `true` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user the server administrator privileges and organization administrator role. If this option is set to `false` and the result of evaluating `role_attribute_path` for a user is `GrafanaAdmin`, Grafana grants the user only organization administrator role. For more information on user role mapping, refer to [Configure role mapping](#configure-role-mapping). | `false` |
| `groups_attribute_path` | No | Yes | [JMESPath](http://jmespath.org/examples.html) expression to use for user group lookup. Grafana will first evaluate the expression using the OAuth2 ID token. If no groups are found, the expression will be evaluated using the user information obtained from the UserInfo endpoint. If still no groups are found, the expression will be evaluated using the OAuth2 access token. The result of the evaluation should be a string array of groups. | |
| `allowed_groups` | No | Yes | List of comma- or space-separated groups. The user should be a member of at least one group to log in. If you configure `allowed_groups`, you must also configure `groups_attribute_path`. | |
| `allowed_organizations` | No | Yes | List of comma- or space-separated organizations. The user should be a member of at least one organization to log in. | |
| `allowed_domains` | No | Yes | List of comma- or space-separated domains. The user should belong to at least one domain to log in. | |
| `team_ids` | No | Yes | String list of team IDs. If set, the user must be a member of one of the given teams to log in. If you configure `team_ids`, you must also configure `teams_url` and `team_ids_attribute_path`. | |
| `team_ids_attribute_path` | No | Yes | The [JMESPath](http://jmespath.org/examples.html) expression to use for Grafana team ID lookup within the results returned by the `teams_url` endpoint. | |
| `teams_url` | No | Yes | The URL used to query for team IDs. If not set, the default value is `/teams`. If you configure `teams_url`, you must also configure `team_ids_attribute_path`. | |
| `tls_skip_verify_insecure` | No | No | If set to `true`, the client accepts any certificate presented by the server and any host name in that certificate. _You should only use this for testing_, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks. | `false` |
| `tls_client_cert` | No | No | The path to the certificate. | |
| `tls_client_key` | No | No | The path to the key. | |
| `tls_client_ca` | No | No | The path to the trusted certificate authority list. | |
| `use_pkce` | No | Yes | Set to `true` to use [Proof Key for Code Exchange (PKCE)](https://datatracker.ietf.org/doc/html/rfc7636). Grafana uses the SHA256 based `S256` challenge method and a 128 bytes (base64url encoded) code verifier. | `false` |
| `use_refresh_token` | No | Yes | Set to `true` to use refresh token and check access token expiration. | `false` |
| `signout_redirect_url` | No | Yes | URL to redirect to after the user logs out. | |
## Examples of setting up Generic OAuth

View File

@@ -43,10 +43,6 @@ Ensure you know how to create a GitHub OAuth app. Consult GitHub's documentation
## Configure GitHub authentication client using the Grafana UI
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
{{< /admonition >}}
As a Grafana Admin, you can configure GitHub OAuth client from within Grafana using the GitHub UI. To do this, navigate to **Administration > Authentication > GitHub** page and fill in the form. If you have a current configuration in the Grafana configuration file, the form will be pre-populated with those values. Otherwise the form will contain default values.
After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations.
@@ -61,10 +57,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure GitHub authentication client using the Terraform provider
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
{{< /admonition >}}
```terraform
resource "grafana_sso_settings" "github_sso_settings" {
provider_name = "github"
@@ -219,7 +211,7 @@ role_attribute_path = [login=='octocat'][0] && 'GrafanaAdmin' || 'Viewer'
## Configure team synchronization
{{< admonition type="note" >}}
Available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and Grafana Cloud.
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can map teams from your GitHub organization to teams within Grafana. This will automatically assign users to the appropriate teams.

View File

@@ -57,10 +57,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure GitLab authentication client using the Terraform provider
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
{{< /admonition >}}
```terraform
resource "grafana_sso_settings" "gitlab_sso_settings" {
provider_name = "gitlab"
@@ -241,7 +237,7 @@ use_refresh_token = true
## Configure team synchronization
{{< admonition type="note" >}}
Available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can map GitLab groups to teams within Grafana. This will automatically assign users to the appropriate teams.

View File

@@ -45,10 +45,6 @@ First, you need to create a Google OAuth Client:
## Configure Google authentication client using the Grafana UI
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
{{< /admonition >}}
As a Grafana Admin, you can configure Google OAuth client from within Grafana using the Google UI. To do this, navigate to **Administration > Authentication > Google** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values.
After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations.
@@ -61,10 +57,6 @@ If you run Grafana in high availability mode, configuration changes may not get
## Configure Google authentication client using the Terraform provider
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
{{< /admonition >}}
```terraform
resource "grafana_sso_settings" "google_sso_settings" {
provider_name = "google"
@@ -167,6 +159,10 @@ auto_login = true
### Configure team synchronization
{{< admonition type="note" >}}
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
With team sync, you can easily add users to teams by utilizing their Google groups. To set up team sync for Google OAuth, refer to the following example.
To set up team sync for Google OAuth:

View File

@@ -106,10 +106,10 @@ editor
viewer
```
## Teamsync
## Team sync
{{< admonition type="note" >}}
Available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
[Teamsync](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-team-sync/) is a feature that allows you to map groups from your identity provider to Grafana teams. This is useful if you want to give your users access to specific dashboards or folders based on their group membership.

View File

@@ -101,10 +101,6 @@ If you want to configure the role for all users in the Okta directory, you can a
## Configure Okta authentication client using the Grafana UI
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default.
{{< /admonition >}}
As a Grafana Admin, you can configure Okta OAuth2 client from within Grafana using the Okta UI. To do this, navigate to **Administration > Authentication > Okta** page and fill in the form. If you have a current configuration in the Grafana configuration file then the form will be pre-populated with those values otherwise the form will contain default values.
After you have filled in the form, click **Save**. If the save was successful, Grafana will apply the new configurations.
@@ -119,10 +115,6 @@ Refer to [configuration options](#configuration-options) for more information.
## Configure Okta authentication client using the Terraform provider
{{< admonition type="note" >}}
Available behind the `ssoSettingsAPI` feature toggle, which is enabled by default. Supported in the Terraform provider since v2.12.0.
{{< /admonition >}}
```terraform
resource "grafana_sso_settings" "okta_sso_settings" {
provider_name = "okta"
@@ -243,10 +235,10 @@ org_attribute_path = groups
org_mapping = ["Group 1:org_foo:Viewer", "Group 2:org_bar:Editor", "*:3:Editor"]
```
### Configure team synchronization (Enterprise only)
### Configure team synchronization
{{< admonition type="note" >}}
Available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](../../../../introduction/grafana-cloud).
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
By using Team Sync, you can link your Okta groups to teams within Grafana. This will automatically assign users to the appropriate teams.

View File

@@ -40,7 +40,7 @@ If you are using Okta or Azure AD as Identity Provider, see the following docume
- [Configure SAML with Okta](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/saml/configure-saml-with-okta/)
{{< admonition type="note" >}}
The API and Terraform support are available in Public Preview in Grafana v11.1 behind the `ssoSettingsSAML` feature toggle. You must also enable the `ssoSettingsApi` flag.
The API and Terraform support are available in Public Preview in Grafana v11.1 behind the `ssoSettingsSAML` feature toggle.
{{< /admonition >}}
All methods offer the same configuration options. However, if you want to keep all of Grafana authentication settings in one place, use the Grafana configuration file or the Terraform provider. If you are a Grafana Cloud user, you do not have access to Grafana configuration file. Instead, configure SAML through the other methods.

View File

@@ -11,6 +11,10 @@ weight: 540
# Configure team sync for SAML
{{< admonition type="note" >}}
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
To use SAML Team sync, set [`assertion_attribute_groups`](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/enterprise-configuration/#assertion_attribute_groups) to the attribute name where you store user groups. Then Grafana will use attribute values extracted from SAML assertion to add user into the groups with the same name configured on the External group sync tab.
{{< admonition type="warning" >}}

View File

@@ -20,7 +20,8 @@ weight: 300
System for Cross-domain Identity Management (SCIM) is an open standard that allows automated user provisioning and management. With SCIM, you can automate the provisioning of users and groups from your identity provider to Grafana.
{{< admonition type="note" >}}
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/) in [public preview](https://grafana.com/docs/release-life-cycle/).
Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
{{< /admonition >}}
{{< admonition type="note" >}}

View File

@@ -16,7 +16,9 @@ weight: 1000
Team sync lets you set up synchronization between your auth providers teams and teams in Grafana. This enables LDAP, OAuth, or SAML users who are members of certain teams or groups to automatically be added or removed as members of certain teams in Grafana.
> **Note:** Available in [Grafana Enterprise](../../../introduction/grafana-enterprise/) and [Grafana Cloud Pro and Advanced](/docs/grafana-cloud/).
{{< admonition type="note" >}}
Only available in [Grafana Enterprise](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud Advanced](https://grafana.com/docs/grafana-cloud/).
{{< /admonition >}}
Grafana keeps track of all synchronized users in teams, and you can see which users have been synchronized in the team members list, see `LDAP` label in screenshot.
This mechanism allows Grafana to remove an existing synchronized user from a team when its group membership changes. This mechanism also enables you to manually add a user as member of a team, and it will not be removed when the user signs in. This gives you flexibility to combine LDAP group memberships and Grafana team memberships.
@@ -27,14 +29,14 @@ This mechanism allows Grafana to remove an existing synchronized user from a tea
## Supported providers
- [Auth Proxy](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/auth-proxy/#team-sync-enterprise-only)
- [Azure AD](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/azuread/#team-sync-enterprise-only)
- [Auth Proxy](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/auth-proxy/#team-sync)
- [Azure AD](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/azuread/#team-sync)
- [Generic OAuth integration](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/generic-oauth/#configure-team-synchronization)
- [GitHub OAuth](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/github/#configure-team-synchronization)
- [GitLab OAuth](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/gitlab/#configure-team-synchronization)
- [Google OAuth](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/google/#configure-team-synchronization)
- [LDAP](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/enhanced-ldap/)
- [Okta](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/okta/#configure-team-synchronization-enterprise-only)
- [Okta](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/okta/#configure-team-synchronization)
- [SAML](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-authentication/saml/)
## Synchronize a Grafana team with an external group

View File

@@ -26,6 +26,7 @@ For each action, define the following API call settings:
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Variables | **Key** and **Name** pairs with a type selection. Click the **+** icon to add as many variables as you need. To add a variable to the request, prefix the key with `$`. You can set the values for the variables when performing an action. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |

View File

@@ -28,6 +28,7 @@ For each action, define the following API call settings:
| Confirmation message | A descriptive prompt to confirm or cancel the action. |
| Method | Select from **POST**, **PUT**, or **GET**. |
| URL | The request URL.</p><p>To add a variable, click in the **URL** field and enter `$` or press Ctrl+Space or Cmd+Space to see a list of available variables. |
| Variables | **Key** and **Name** pairs with a type selection. Click the **+** icon to add as many variables as you need. To add a variable to the request, prefix the key with `$`. You can set the values for the variables when performing an action. |
| Query parameters | **Key** and **Value** pairs. Click the **+** icon to add as many key/value pairs as you need. |
| Headers | Comprised of **Key** and **Value** pairs and a **Content-Type**.</p><p>Click the **+** icon to add as many key/value pairs as you need. |
| Content-Type | Select from the following: **application/json**, **text/plain**, **application/XML**, and **application/x-www-form-urlencoded**. |

View File

@@ -96,27 +96,24 @@ For self-managed Grafana (both Enterprise and OSS), the support for versions fol
- Each minor release is supported for 9 months after its release date
- The last minor release of a major version receives extended support for 15 months after its release date
- Support levels change as new versions are released:
- **Full Support**: The most recently released major/minor (and the last minor of the previous major) version receive full support including new features, bug fixes, and security patches
- **Security & Critical Bugs Only**: Versions that are not the most recently released major/minor (or the last minor of the previous major) version, but still within their support period, receive only security patches and critical bug fixes
- **Full Support**: The most recently released major/minor version receive full support including new features, bug fixes, and security patches
- **Security & Critical Bugs Only**: Versions that are outside of the most recently released major/minor version, but still within their support period, receive only security patches and critical bug fixes
- **Not Supported**: Versions beyond their support period receive no updates
Here is an overview of version support through 2026:
| **Version** | **Release date** | **Support end date** | **Support level** |
| ------------------------- | ------------------ | -------------------- | ----------------------------- |
| 9.5.x (Last minor of 9) | April 26, 2023 | July 26, 2024 | Supported for Azure Only |
| 10.0.x | June 13, 2023 | March 13, 2024 | Not Supported |
| 10.1.x | August 22, 2023 | May 22, 2024 | Not Supported |
| 10.2.x | October 24, 2023 | July 24, 2024 | Not Supported |
| 10.3.x | January 23, 2024 | October 23, 2024 | Not Supported |
| 10.4.x (Last minor of 10) | March 5, 2024 | June 5, 2025 | Security & Critical Bugs Only |
| 11.0.x | May 14, 2024 | February 14, 2025 | Security & Critical Bugs Only |
| 11.1.x | June 25, 2024 | April 23, 2025 | Security & Critical Bugs Only |
| 11.2.x | August 27, 2024 | May 27, 2025 | Security & Critical Bugs Only |
| 10.4.x (Last minor of 10) | March 5, 2024 | June 5, 2025 | Not Supported |
| 11.0.x | May 14, 2024 | February 14, 2025 | Not Supported |
| 11.1.x | June 25, 2024 | April 23, 2025 | Not Supported |
| 11.2.x | August 27, 2024 | May 27, 2025 | Not Supported |
| 11.3.x | October 22, 2024 | July 22, 2025 | Security & Critical Bugs Only |
| 11.4.x | December 5, 2024 | September 5, 2025 | Security & Critical Bugs Only |
| 11.5.x | January 28, 2025 | October 28, 2025 | Security & Critical Bugs Only |
| 11.6.x (Last minor of 11) | March 25, 2025 | May 25, 2026 | Full Support |
| 11.6.x (Last minor of 11) | March 25, 2025 | May 25, 2026 | Security & Critical Bugs Only |
| 12.0.x | May 5, 2025 | February 5, 2026 | Full Support until next minor |
| 12.1.x | July 22, 2025 | April 22, 2026 | Full Support until next minor |
| 12.2.x | September 23, 2025 | June 23, 2026 | Full Support until next minor |

View File

@@ -2,11 +2,21 @@
"apiVersion": "dashboard.grafana.app/v2alpha1",
"kind": "Dashboard",
"metadata": {
"name": "fa400625-2a44-4add-a369-e6c972eb4bd6",
"name": "admjzp8",
"namespace": "default",
"uid": "hrbekBWXeM7nC7GtouIbcngFyuqt8Xx7KlE4AnTwV7AX",
"resourceVersion": "1",
"generation": 1,
"creationTimestamp": "2025-05-27T11:40:22Z",
"labels": {},
"annotations": {}
"creationTimestamp": "2025-05-16T09:41:56Z",
"labels": {
"grafana.app/deprecatedInternalID": "182"
},
"annotations": {
"grafana.app/createdBy": "user:cejvsh18uudxcf",
"grafana.app/updatedBy": "user:cejvsh18uudxcf",
"grafana.app/updatedTimestamp": "2025-05-16T09:41:56Z",
"grafana.app/folder": ""
}
},
"spec": {
"annotations": [
@@ -14,20 +24,19 @@
"kind": "AnnotationQuery",
"spec": {
"builtIn": true,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"query": {
"group": "grafana",
"kind": "DataQuery",
"spec": {},
"version": "v0"
}
"name": "Annotations & Alerts"
}
}
],
"cursorSync": "Off",
"description": "",
"editable": true,
"elements": {
"panel-1": {
@@ -40,12 +49,14 @@
{
"kind": "PanelQuery",
"spec": {
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -144,12 +155,14 @@
{
"kind": "PanelQuery",
"spec": {
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -248,12 +261,14 @@
{
"kind": "PanelQuery",
"spec": {
"datasource": {
"type": "grafana-testdata-datasource",
"uid": "PD8C576611E62080A"
},
"hidden": false,
"query": {
"group": "grafana-testdata-datasource",
"kind": "DataQuery",
"spec": {},
"version": "v0"
"kind": "grafana-testdata-datasource",
"spec": {}
},
"refId": "A"
}
@@ -365,7 +380,7 @@
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-3"
"name": "panel-2"
},
"height": 8,
"width": 12,
@@ -378,7 +393,7 @@
"spec": {
"element": {
"kind": "ElementReference",
"name": "panel-2"
"name": "panel-3"
},
"height": 8,
"width": 12,
@@ -402,7 +417,7 @@
"timezone": "browser",
"to": "now"
},
"title": "Test V2 Dashboard",
"title": "New Test V2 Dashboard",
"variables": []
},
"status": {}

View File

@@ -3,7 +3,7 @@
// NOTE: storybook must already be running (`yarn storybook`) for this test to work
describe('Verify storybook', () => {
it('Loads the button story correctly', () => {
cy.visit('?path=/story/buttons-button--basic');
cy.visit('?path=/story/inputs-button--basic');
getIframeBody().find('button:contains("Example button")').should('be.visible');
});
});

View File

@@ -3,8 +3,8 @@
"version": "12.1.0-pre",
"private": true,
"scripts": {
"build": "webpack -c ./webpack.config.ts --env production",
"dev": "webpack -w -c ./webpack.config.ts --env development",
"build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production",
"dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development",
"typecheck": "tsc --noEmit",
"lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx ."
},

View File

@@ -1,7 +1,7 @@
import CopyWebpackPlugin from 'copy-webpack-plugin';
import grafanaConfig from '@grafana/plugin-configs/webpack.config';
import grafanaConfig from '@grafana/plugin-configs/webpack.config.ts';
import { mergeWithCustomize, unique } from 'webpack-merge';
import { Configuration } from 'webpack';
import { type Configuration } from 'webpack';
function skipFiles(f: string): boolean {
if (f.includes('/dist/')) {

View File

@@ -3,8 +3,8 @@
"version": "12.1.0-pre",
"private": true,
"scripts": {
"build": "webpack -c ./webpack.config.ts --env production",
"dev": "webpack -w -c ./webpack.config.ts --env development",
"build": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -c ./webpack.config.ts --env production",
"dev": "NODE_OPTIONS='--experimental-strip-types --no-warnings=ExperimentalWarning' webpack -w -c ./webpack.config.ts --env development",
"typecheck": "tsc --noEmit",
"lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx ."
},

View File

@@ -1,7 +1,7 @@
import CopyWebpackPlugin from 'copy-webpack-plugin';
import grafanaConfig from '@grafana/plugin-configs/webpack.config';
import grafanaConfig from '@grafana/plugin-configs/webpack.config.ts';
import { mergeWithCustomize, unique } from 'webpack-merge';
import { Configuration } from 'webpack';
import { type Configuration } from 'webpack';
function skipFiles(f: string): boolean {
if (f.includes('/dist/')) {

View File

@@ -17,9 +17,5 @@ export const importV2Dashboard = ({ title }: ImportDashboardConfig) => {
if (title) {
e2e.components.ImportDashboardForm.name().clear().type(title);
}
e2e.components.DataSourcePicker.inputV2().click();
cy.get('div[data-testid="data-source-card"]').first().click();
e2e.components.ImportDashboardForm.submit().click();
};

View File

@@ -176,6 +176,13 @@ module.exports = [
'react/react-in-jsx-scope': 'off',
},
},
{
name: 'grafana/story-rules',
files: ['packages/grafana-ui/src/**/*.story.tsx'],
rules: {
'@grafana/consistent-story-titles': 'error',
},
},
{
name: 'grafana/public-dashboards-overrides',
files: ['public/dashboards/scripted*.js'],

4
go.mod
View File

@@ -99,14 +99,14 @@ require (
github.com/grafana/grafana-api-golang-client v0.27.0 // @grafana/alerting-backend
github.com/grafana/grafana-app-sdk v0.39.2 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana-app-sdk/logging v0.39.1 // @grafana/grafana-app-platform-squad
github.com/grafana/grafana-aws-sdk v1.0.2 // @grafana/aws-datasources
github.com/grafana/grafana-aws-sdk v1.0.4 // @grafana/aws-datasources
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 // @grafana/partner-datasources
github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 // @grafana/grafana-operator-experience-squad
github.com/grafana/grafana-google-sdk-go v0.4.1 // @grafana/partner-datasources
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 // @grafana/grafana-backend-group
github.com/grafana/grafana-plugin-sdk-go v0.278.0 // @grafana/plugins-platform-backend
github.com/grafana/loki/v3 v3.2.1 // @grafana/observability-logs
github.com/grafana/nanogit v0.0.0-20250625082556-a4828b879bbb // @grafana-app-platform-squad
github.com/grafana/nanogit v0.0.0-20250709085038-55508a6a9f40 // @grafana-app-platform-squad
github.com/grafana/otel-profiling-go v0.5.1 // @grafana/grafana-backend-group
github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // @grafana/observability-traces-and-profiling
github.com/grafana/pyroscope/api v1.2.1-0.20250415190842-3ff7247547ae // @grafana/observability-traces-and-profiling

8
go.sum
View File

@@ -1610,8 +1610,8 @@ github.com/grafana/grafana-app-sdk v0.39.2 h1:ymfr+1318t+JC9U2OYrzVpGmNG/aJONUmF
github.com/grafana/grafana-app-sdk v0.39.2/go.mod h1:t0m6q561lpoHQCixS9LUHFUhUzDClzNtm7BH60gHVSY=
github.com/grafana/grafana-app-sdk/logging v0.39.1 h1:lI5rbrheuwVPuyIM6LIuEYOCSpgmXahfKtqeMyhbGPU=
github.com/grafana/grafana-app-sdk/logging v0.39.1/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss=
github.com/grafana/grafana-aws-sdk v1.0.2/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
github.com/grafana/grafana-aws-sdk v1.0.4 h1:D14UAehsOqpjliHmHzveRQ1p43KCsMzdmb7GovWj+SY=
github.com/grafana/grafana-aws-sdk v1.0.4/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6 h1:OfCkitCuomzZKW1WYHrG8MxKwtMhALb7jqoj+487eTg=
github.com/grafana/grafana-azure-sdk-go/v2 v2.1.6/go.mod h1:V7y2BmsWxS3A9Ohebwn4OiSfJJqi//4JQydQ8fHTduo=
github.com/grafana/grafana-cloud-migration-snapshot v1.6.0 h1:S4kHwr//AqhtL9xHBtz1gqVgZQeCRGTxjgsRBAkpjKY=
@@ -1654,8 +1654,8 @@ github.com/grafana/loki/pkg/push v0.0.0-20231124142027-e52380921608 h1:ZYk42718k
github.com/grafana/loki/pkg/push v0.0.0-20231124142027-e52380921608/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0=
github.com/grafana/loki/v3 v3.2.1 h1:VB7u+KHfvL5aHAxgoVBvz5wVhsdGuqKC7uuOFOOe7jw=
github.com/grafana/loki/v3 v3.2.1/go.mod h1:WvdLl6wOS+yahaeQY+xhD2m2XzkHDfKr5FZaX7D/X2Y=
github.com/grafana/nanogit v0.0.0-20250625082556-a4828b879bbb h1:JR672zBiCkfiKuRRsU76TRC2q12q0VfZl2SP8jBIAJQ=
github.com/grafana/nanogit v0.0.0-20250625082556-a4828b879bbb/go.mod h1:tN93IZUaAmnSWgL0IgnKdLv6DNeIhTJGvl1wvQMrWco=
github.com/grafana/nanogit v0.0.0-20250709085038-55508a6a9f40 h1:wsIgOI4Ou1o/UtxtJlemLufpVBpMdcXVJxedk0wLoCM=
github.com/grafana/nanogit v0.0.0-20250709085038-55508a6a9f40/go.mod h1:ToqLjIdvV3AZQa3K6e5m9hy/nsGaUByc2dWQlctB9iA=
github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8=
github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls=
github.com/grafana/prometheus-alertmanager v0.25.1-0.20250620093340-be61a673dee6 h1:oJnbhG6ZNy10AjsgNeAtAKeGHogIGOMfAsBH6fYYa5M=

View File

@@ -347,6 +347,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV
github.com/RaveNoX/go-jsoncommentstrip v1.0.0 h1:t527LHHE3HmiHrq74QMpNPZpGCIJzTx+apLkMKt4HC0=
github.com/RoaringBitmap/gocroaring v0.4.0 h1:5nufXUgWpBEUNEJXw7926YAA58ZAQRpWPrQV1xCoSjc=
github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76 h1:ZYlhPbqQFU+AHfgtCdHGDTtRW1a8geZyiE8c6Q+Sl1s=
github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76/go.mod h1:oM0MHmQ3nDsq609SS36p+oYbRi16+oVvU2Bw4Ipv0SE=
github.com/Sereal/Sereal/Go/sereal v0.0.0-20231009093132-b9187f1a92c6 h1:5kUcJJAKWWI82Xnp/CaU0eu5hLlHkmm9acjowSkwCd0=
github.com/Sereal/Sereal/Go/sereal v0.0.0-20231009093132-b9187f1a92c6/go.mod h1:JwrycNnC8+sZPDyzM3MQ86LvaGzSpfxg885KOOwFRW4=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
@@ -570,6 +571,7 @@ github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQ
github.com/envoyproxy/go-control-plane/envoy v1.32.3/go.mod h1:F6hWupPfh75TBXGKA++MCT/CZHFq5r9/uwt/kQYkZfE=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/expr-lang/expr v1.17.0/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
@@ -679,6 +681,8 @@ github.com/grafana/alerting v0.0.0-20250403153742-418bc7118d05 h1:hMzOzI/S0nkZt0
github.com/grafana/alerting v0.0.0-20250403153742-418bc7118d05/go.mod h1:K3YAJumchx5EEZItGv4D3pCv/Ux796hmoOibP/p/eYk=
github.com/grafana/alerting v0.0.0-20250429131604-de176b4a0309 h1:H2p3XKDHnTBGkMXLCgXiqb2dFnHbQ4zPDXOwKK4Ne3Y=
github.com/grafana/alerting v0.0.0-20250429131604-de176b4a0309/go.mod h1:pMfhRxL2LZ3Pm8iy7VcVsb9CLYuBtjFYbf1oxgx7yFA=
github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945 h1:3imTbxFpZSVI6IBIB9mn+Xc40lUweWjfMaBSgXR7rLs=
github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945/go.mod h1:gtR7agmxVfJOmNKV/n2ZULgOYTYNL+PDKYB5N48tQ7Q=
github.com/grafana/authlib v0.0.0-20250123104008-e99947858901/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
github.com/grafana/authlib/types v0.0.0-20250120144156-d6737a7dc8f5/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
@@ -693,6 +697,8 @@ github.com/grafana/grafana-app-sdk/logging v0.39.0 h1:3GgN5+dUZYqq74Q+GT9/ET+yo+
github.com/grafana/grafana-app-sdk/logging v0.39.0/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk=
github.com/grafana/grafana-aws-sdk v0.38.2 h1:TzQD0OpWsNjtldi5G5TLDlBRk8OyDf+B5ujcoAu4Dp0=
github.com/grafana/grafana-aws-sdk v0.38.2/go.mod h1:j3vi+cXYHEFqjhBGrI6/lw1TNM+dl0Y3f0cSnDOPy+s=
github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss=
github.com/grafana/grafana-aws-sdk v1.0.2/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE=
github.com/grafana/grafana-plugin-sdk-go v0.263.0/go.mod h1:U43Cnrj/9DNYyvFcNdeUWNjMXTKNB0jcTcQGpWKd2gw=
github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q=
github.com/grafana/grafana-plugin-sdk-go v0.269.1/go.mod h1:yv2KbO4mlr9WuDK2f+2gHAMTwwLmLuqaEnrPXTRU+OI=
@@ -1270,6 +1276,7 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhp
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -1297,6 +1304,7 @@ golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/plot v0.15.2 h1:Tlfh/jBk2tqjLZ4/P8ZIwGrLEWQSPDLRm/SNWKNXiGI=
gonum.org/v1/plot v0.15.2/go.mod h1:DX+x+DWso3LTha+AdkJEv5Txvi+Tql3KAGkehP0/Ubg=
@@ -1382,6 +1390,7 @@ k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1
k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kms v0.33.2/go.mod h1:C1I8mjFFBNzfUZXYt9FZVJ8MJl7ynFbGgZFbBzkBJ3E=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg=
modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM=

View File

@@ -5,16 +5,22 @@ process.env.TZ = 'Pacific/Easter'; // UTC-06:00 or UTC-05:00 depending on daylig
const esModules = [
'@glideapps/glide-data-grid',
'@wojtekmaj/date-utils',
'ol',
'd3',
'd3-color',
'd3-interpolate',
'delaunator',
'get-user-locale',
'internmap',
'robust-predicates',
'leven',
'nanoid',
'marked',
'memoize',
'mimic-function',
'monaco-promql',
'react-calendar',
'@kusto/monaco-kusto',
'monaco-editor',
'@msagl',

View File

@@ -111,7 +111,7 @@
"@testing-library/user-event": "14.6.1",
"@types/babel__core": "^7",
"@types/babel__preset-env": "^7",
"@types/chance": "^1.1.3",
"@types/chance": "^1.1.7",
"@types/common-tags": "^1.8.0",
"@types/confusing-browser-globals": "^1",
"@types/d3": "7.4.3",
@@ -130,7 +130,7 @@
"@types/jquery": "3.5.32",
"@types/js-yaml": "^4.0.5",
"@types/jsurl": "^1.2.28",
"@types/lodash": "4.17.15",
"@types/lodash": "4.17.20",
"@types/logfmt": "^1.2.3",
"@types/lucene": "^2",
"@types/node": "22.15.0",
@@ -156,7 +156,7 @@
"@types/slate-plain-serializer": "0.7.5",
"@types/slate-react": "0.22.9",
"@types/swagger-ui-react": "5.18.0",
"@types/systemjs": "6.15.1",
"@types/systemjs": "6.15.3",
"@types/tinycolor2": "1.4.6",
"@types/uuid": "10.0.0",
"@types/webpack-assets-manifest": "^5",
@@ -164,23 +164,23 @@
"@types/yargs": "17.0.33",
"@typescript-eslint/eslint-plugin": "8.35.1",
"@typescript-eslint/parser": "8.35.1",
"autoprefixer": "10.4.20",
"autoprefixer": "10.4.21",
"babel-loader": "9.2.1",
"blob-polyfill": "9.0.20240710",
"browserslist": "^4.21.4",
"chance": "^1.0.10",
"chrome-remote-interface": "0.33.2",
"chance": "^1.1.13",
"chrome-remote-interface": "0.33.3",
"codeowners": "^5.1.1",
"confusing-browser-globals": "^1.0.11",
"copy-webpack-plugin": "12.0.2",
"core-js": "3.40.0",
"crashme": "0.0.15",
"css-loader": "7.1.2",
"css-minimizer-webpack-plugin": "7.0.0",
"css-minimizer-webpack-plugin": "7.0.2",
"cypress": "14.3.2",
"cypress-file-upload": "5.0.8",
"cypress-recurse": "^1.35.3",
"esbuild": "0.25.0",
"esbuild": "0.25.6",
"esbuild-loader": "4.3.0",
"esbuild-plugin-browserslist": "^1.0.0",
"eslint": "9.19.0",
@@ -192,13 +192,13 @@
"eslint-plugin-jsx-a11y": "6.10.2",
"eslint-plugin-lodash": "8.0.0",
"eslint-plugin-no-barrel-files": "^1.1.1",
"eslint-plugin-react": "7.37.4",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "5.1.0",
"eslint-plugin-testing-library": "^7.0.0",
"eslint-plugin-unicorn": "^56.0.0",
"eslint-scope": "^8.1.0",
"eslint-webpack-plugin": "4.2.0",
"expose-loader": "5.0.0",
"expose-loader": "5.0.1",
"fishery": "^2.2.2",
"fork-ts-checker-webpack-plugin": "9.0.2",
"glob": "11.0.1",
@@ -279,9 +279,9 @@
"@grafana/faro-web-sdk": "^1.13.2",
"@grafana/faro-web-tracing": "^1.13.2",
"@grafana/flamegraph": "workspace:*",
"@grafana/google-sdk": "0.3.2",
"@grafana/google-sdk": "0.3.4",
"@grafana/i18n": "workspace:*",
"@grafana/lezer-logql": "0.2.7",
"@grafana/lezer-logql": "0.2.8",
"@grafana/llm": "0.22.1",
"@grafana/monaco-logql": "^0.0.8",
"@grafana/o11y-ds-frontend": "workspace:*",
@@ -340,7 +340,7 @@
"fast-json-patch": "3.1.1",
"file-saver": "2.0.5",
"history": "4.10.1",
"i18next": "^24.0.0",
"i18next": "^25.0.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-pseudo": "^2.2.1",
"immer": "10.1.1",
@@ -358,7 +358,7 @@
"lru-cache": "11.1.0",
"lru-memoize": "^1.1.0",
"lucene": "^2.1.1",
"marked": "15.0.12",
"marked": "16.0.0",
"memoize-one": "6.0.0",
"micro-memoize": "^4.1.2",
"ml-regression-polynomial": "^3.0.0",
@@ -424,7 +424,8 @@
"type-fest": "^4.18.2",
"uplot": "1.6.32",
"uuid": "11.1.0",
"visjs-network": "4.25.0",
"vis-data": "^7.1.10",
"vis-network": "9.1.13",
"whatwg-fetch": "3.6.20"
},
"resolutions": {

View File

@@ -51,7 +51,26 @@ type SlackIntegration = OverrideProperties<
}
>;
export type Integration = EmailIntegration | SlackIntegration | GenericIntegration;
// Based on https://github.com/grafana/alerting/blob/main/receivers/oncall/config.go#L14-L27
type OnCallIntegration = OverrideProperties<
GenericIntegration,
{
type: 'OnCall';
settings: {
url: string;
httpMethod?: 'POST' | 'PUT';
maxAlerts?: number;
authorization_scheme?: string;
authorization_credentials?: string;
username?: string;
password?: string;
title?: string;
message?: string;
};
}
>;
export type Integration = EmailIntegration | SlackIntegration | OnCallIntegration | GenericIntegration;
// Enhanced version of ContactPoint with typed integrations
// ⚠️ MergeDeep does not check if the property you are overriding exists in the base type and there is no "DeepOverrideProperties" helper

View File

@@ -3,7 +3,7 @@ import { chain } from 'lodash';
import { Combobox, ComboboxOption } from '@grafana/ui';
import type { ContactPoint } from '../../../api/v0alpha1/types';
import { useListContactPointsv0alpha1 } from '../../hooks/useContactPoints';
import { useListContactPoints } from '../../hooks/v0alpha1/useContactPoints';
import { getContactPointDescription } from '../../utils';
import { CustomComboBoxProps } from './ComboBox.types';
@@ -17,7 +17,7 @@ export type ContactPointSelectorProps = CustomComboBoxProps<ContactPoint>;
* @TODO make ComboBox accept a ReactNode so we can use icons and such
*/
function ContactPointSelector(props: ContactPointSelectorProps) {
const { currentData: contactPoints, isLoading } = useListContactPointsv0alpha1();
const { currentData: contactPoints, isLoading } = useListContactPoints();
// Create a mapping of options with their corresponding contact points
const contactPointOptions = chain(contactPoints?.items)

View File

@@ -1,25 +0,0 @@
import { type TypedUseQueryHookResult, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { type ListReceiverApiArg, alertingAPI } from '../../api/v0alpha1/api.gen';
import type { EnhancedListReceiverApiResponse } from '../../api/v0alpha1/types';
// this is a workaround for the fact that the generated types are not narrow enough
type EnhancedHookResult = TypedUseQueryHookResult<
EnhancedListReceiverApiResponse,
ListReceiverApiArg,
ReturnType<typeof fetchBaseQuery>
>;
/**
* useListContactPoints is a hook that fetches a list of contact points
*
* This function wraps the alertingAPI.useListReceiverQuery with proper typing
* to ensure that the returned ContactPoints are correctly typed in the data.items array.
*
* It automatically uses the configured namespace for the query.
*/
function useListContactPointsv0alpha1() {
return alertingAPI.useListReceiverQuery<EnhancedHookResult>({});
}
export { useListContactPointsv0alpha1 };

View File

@@ -0,0 +1,62 @@
import {
type TypedUseMutationResult,
type TypedUseQueryHookResult,
fetchBaseQuery,
} from '@reduxjs/toolkit/query/react';
import { OverrideProperties } from 'type-fest';
import { CreateReceiverApiArg, type ListReceiverApiArg, alertingAPI } from '../../../api/v0alpha1/api.gen';
import type { ContactPoint, EnhancedListReceiverApiResponse } from '../../../api/v0alpha1/types';
// this is a workaround for the fact that the generated types are not narrow enough
type ListContactPointsHookResult = TypedUseQueryHookResult<
EnhancedListReceiverApiResponse,
ListReceiverApiArg,
ReturnType<typeof fetchBaseQuery>
>;
/**
* useListContactPoints is a hook that fetches a list of contact points
*
* This function wraps the alertingAPI.useListReceiverQuery with proper typing
* to ensure that the returned ContactPoints are correctly typed in the data.items array.
*
* It automatically uses the configured namespace for the query.
*/
export function useListContactPoints() {
return alertingAPI.useListReceiverQuery<ListContactPointsHookResult>({});
}
// type narrowing mutations requires us to define a few helper types
type CreateContactPointArgs = OverrideProperties<
CreateReceiverApiArg,
{ receiver: Omit<ContactPoint, 'status' | 'metadata'> }
>;
type CreateContactPointMutation = TypedUseMutationResult<
ContactPoint,
CreateContactPointArgs,
ReturnType<typeof fetchBaseQuery>
>;
type UseCreateContactPointOptions = Parameters<
typeof alertingAPI.endpoints.createReceiver.useMutation<CreateContactPointMutation>
>[0];
/**
* useCreateContactPoint is a hook that creates a new contact point with one or more integrations
*
* This function wraps the alertingAPI.useCreateReceiverMutation with proper typing
* to ensure that the payload supports type narrowing.
*/
export function useCreateContactPoint(options?: UseCreateContactPointOptions) {
const [updateFn, result] = alertingAPI.endpoints.createReceiver.useMutation<CreateContactPointMutation>(options);
const typedUpdateFn = (args: CreateContactPointArgs) => {
// @ts-expect-error this one is just impossible for me to figure out
const response = updateFn(args);
return response;
};
return [typedUpdateFn, result] as const;
}

View File

@@ -4,14 +4,8 @@
// Contact Points
export * from './grafana/api/v0alpha1/types';
export { useListContactPointsv0alpha1 } from './grafana/contactPoints/hooks/useContactPoints';
export { useListContactPoints } from './grafana/contactPoints/hooks/v0alpha1/useContactPoints';
export { ContactPointSelector } from './grafana/contactPoints/components/ContactPointSelector/ContactPointSelector';
// Low-level API hooks
export { alertingAPI as alertingAPIv0alpha1 } from './grafana/api/v0alpha1/api.gen';
// model factories / mocks
export * as mocksV0alpha1 from './grafana/api/v0alpha1/mocks/fakes/Receivers';
// MSW handlers
export * as handlersV0alpha1 from './grafana/api/v0alpha1/mocks/handlers';
export { alertingAPI } from './grafana/api/v0alpha1/api.gen';

View File

@@ -2,13 +2,13 @@ import { configureStore } from '@reduxjs/toolkit';
import { useEffect } from 'react';
import { Provider } from 'react-redux';
import { alertingAPIv0alpha1 } from '../src/unstable';
import { alertingAPI } from '../src/unstable';
// create an empty store
export const store = configureStore({
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(alertingAPIv0alpha1.middleware),
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(alertingAPI.middleware),
reducer: {
[alertingAPIv0alpha1.reducerPath]: alertingAPIv0alpha1.reducer,
[alertingAPI.reducerPath]: alertingAPI.reducer,
},
});
@@ -35,7 +35,7 @@ export const getDefaultWrapper = () => {
function useResetQueryCacheAfterUnmount() {
useEffect(() => {
return () => {
store.dispatch(alertingAPIv0alpha1.util.resetApiState());
store.dispatch(alertingAPI.util.resetApiState());
};
}, []);
}

View File

@@ -60,7 +60,7 @@
"@leeoniya/ufuzzy": "1.0.18",
"@types/d3-interpolate": "^3.0.0",
"@types/string-hash": "1.1.3",
"@types/systemjs": "6.15.1",
"@types/systemjs": "6.15.3",
"d3-interpolate": "3.0.1",
"date-fns": "4.1.0",
"dompurify": "3.2.6",
@@ -68,7 +68,7 @@
"fast_array_intersect": "1.1.0",
"history": "4.10.1",
"lodash": "4.17.21",
"marked": "15.0.12",
"marked": "16.0.0",
"marked-mangle": "1.1.11",
"moment": "2.30.1",
"moment-timezone": "0.5.47",
@@ -84,15 +84,15 @@
},
"devDependencies": {
"@grafana/tsconfig": "^2.0.0",
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-node-resolve": "16.0.1",
"@types/history": "4.7.11",
"@types/lodash": "4.17.15",
"@types/lodash": "4.17.20",
"@types/node": "22.15.0",
"@types/papaparse": "5.3.16",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5",
"@types/tinycolor2": "1.4.6",
"esbuild": "0.25.0",
"esbuild": "0.25.6",
"react": "18.3.1",
"react-dom": "18.3.1",
"rimraf": "6.0.1",

View File

@@ -2,7 +2,7 @@ import { PropsWithChildren, ReactElement, useMemo } from 'react';
import { DataSourceInstanceSettings } from '../../types/datasource';
import { Context, DataSourcePluginContextType } from './PluginContext';
import { PluginContext, DataSourcePluginContextType } from './PluginContext';
export type DataSourcePluginContextProviderProps = {
instanceSettings: DataSourceInstanceSettings;
@@ -16,5 +16,5 @@ export function DataSourcePluginContextProvider(
return { instanceSettings, meta: instanceSettings.meta };
}, [instanceSettings]);
return <Context.Provider value={value}>{children}</Context.Provider>;
return <PluginContext.Provider value={value}>{children}</PluginContext.Provider>;
}

View File

@@ -1,14 +1,15 @@
import { createContext } from 'react';
import { KeyValue } from '../../types/data';
import { DataSourceInstanceSettings } from '../../types/datasource';
import { PluginMeta } from '../../types/plugin';
export interface PluginContextType {
meta: PluginMeta;
export interface PluginContextType<T extends KeyValue = KeyValue> {
meta: PluginMeta<T>;
}
export interface DataSourcePluginContextType extends PluginContextType {
export interface DataSourcePluginContextType<T extends KeyValue = KeyValue> extends PluginContextType<T> {
instanceSettings: DataSourceInstanceSettings;
}
export const Context = createContext<PluginContextType | undefined>(undefined);
export const PluginContext = createContext<PluginContextType | undefined>(undefined);

View File

@@ -2,7 +2,7 @@ import { PropsWithChildren, ReactElement } from 'react';
import { PluginMeta } from '../../types/plugin';
import { Context } from './PluginContext';
import { PluginContext } from './PluginContext';
export type PluginContextProviderProps = {
meta: PluginMeta;
@@ -10,5 +10,5 @@ export type PluginContextProviderProps = {
export function PluginContextProvider(props: PropsWithChildren<PluginContextProviderProps>): ReactElement {
const { children, ...rest } = props;
return <Context.Provider value={rest}>{children}</Context.Provider>;
return <PluginContext.Provider value={rest}>{children}</PluginContext.Provider>;
}

View File

@@ -1,5 +1,9 @@
import { KeyValue } from '../../types/data';
import { type DataSourcePluginContextType, type PluginContextType } from './PluginContext';
export function isDataSourcePluginContext(context: PluginContextType): context is DataSourcePluginContextType {
export function isDataSourcePluginContext<T extends KeyValue = KeyValue>(
context: PluginContextType<T>
): context is DataSourcePluginContextType<T> {
return 'instanceSettings' in context && 'meta' in context;
}

View File

@@ -1,9 +1,11 @@
import { useContext } from 'react';
import { Context, PluginContextType } from './PluginContext';
import { KeyValue } from '../../types/data';
export function usePluginContext(): PluginContextType | null {
const context = useContext(Context);
import { PluginContext, PluginContextType } from './PluginContext';
export function usePluginContext<T extends KeyValue = KeyValue>(): PluginContextType<T> | null {
const context = useContext(PluginContext);
// The extensions hooks (e.g. `usePluginLinks()`) are using this hook to check
// if they are inside a plugin or not (core Grafana), so we should be able to return an empty state as well (`null`).
@@ -11,5 +13,6 @@ export function usePluginContext(): PluginContextType | null {
return null;
}
return context;
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return context as PluginContextType<T>;
}

View File

@@ -435,7 +435,7 @@ export { type GroupingToMatrixTransformerOptions } from './transformations/trans
export {
type PluginContextType,
type DataSourcePluginContextType,
Context as PluginContext,
PluginContext,
} from './context/plugins/PluginContext';
export { type PluginContextProviderProps, PluginContextProvider } from './context/plugins/PluginContextProvider';
export {

View File

@@ -35,18 +35,21 @@ describe('Limit transformer', () => {
{
name: 'time',
type: FieldType.time,
state: { calcs: undefined },
values: [3000, 4000, 5000],
config: {},
},
{
name: 'message',
type: FieldType.string,
state: { calcs: undefined },
values: ['one', 'two', 'two'],
config: {},
},
{
name: 'values',
type: FieldType.number,
state: { calcs: undefined },
values: [1, 2, 2],
config: {},
},
@@ -79,18 +82,21 @@ describe('Limit transformer', () => {
{
name: 'time',
type: FieldType.time,
state: { calcs: undefined },
values: [6000, 7000, 8000],
config: {},
},
{
name: 'message',
type: FieldType.string,
state: { calcs: undefined },
values: ['three', 'three', 'three'],
config: {},
},
{
name: 'values',
type: FieldType.number,
state: { calcs: undefined },
values: [3, 3, 3],
config: {},
},

View File

@@ -37,6 +37,12 @@ export const limitTransformer: DataTransformerInfo<LimitTransformerOptions> = {
fields: frame.fields.map((f) => {
return {
...f,
// Clear cached field calculations since applying a limit changes the dataset
// and previously computed stats (min, max, mean, etc.) are no longer valid
state: {
...f.state,
calcs: undefined,
},
values:
limit >= 0 ? f.values.slice(0, limit) : f.values.slice(f.values.length + limit, f.values.length),
};

View File

@@ -8,7 +8,7 @@ import { notTimeFieldMatcher } from '../matchers/predicates';
import { transformDataFrame } from '../transformDataFrame';
import { DataTransformerID } from './ids';
import { reduceFields, reduceTransformer, ReduceTransformerOptions } from './reduce';
import { reduceFields, reduceTransformer, ReduceTransformerMode, ReduceTransformerOptions } from './reduce';
const seriesAWithSingleField = toDataFrame({
name: 'A',
@@ -582,4 +582,62 @@ describe('Reducer Transformer', () => {
`);
});
});
it('reduce fields mode keeps distinct label values with multiple reducers', async () => {
const cfg: DataTransformerConfig<ReduceTransformerOptions> = {
id: DataTransformerID.reduce,
options: {
mode: ReduceTransformerMode.ReduceFields,
reducers: [ReducerID.max, ReducerID.count],
labelsToFields: false,
},
};
const seriesA = toDataFrame({
length: 3,
fields: [{ name: 'value', config: {}, labels: { category: 'apple' }, type: FieldType.number, values: [3, 4, 5] }],
});
const seriesB = toDataFrame({
fields: [
{ name: 'value', config: {}, labels: { category: 'orange' }, type: FieldType.number, values: [6, 7, 8] },
],
});
await expect(transformDataFrame([cfg], [seriesA, seriesB])).toEmitValuesWith((received) => {
const processed = received[0];
expect(processed.length).toEqual(2);
expect(processed[0].fields).toMatchInlineSnapshot(`
[
{
"config": {},
"labels": {
"category": "apple",
"reducer": "Max",
},
"name": "value",
"state": undefined,
"type": "number",
"values": [
5,
],
},
{
"config": {},
"labels": {
"category": "apple",
"reducer": "Count",
},
"name": "value",
"state": undefined,
"type": "number",
"values": [
3,
],
},
]
`);
});
});
});

View File

@@ -230,10 +230,11 @@ export function reduceFields(data: DataFrame[], matcher: FieldMatcher, reducerId
const value = results[reducer];
const copy = {
...field,
labels: { ...field.labels },
type: getFieldType(reducer, field),
values: [value],
state: undefined,
};
copy.state = undefined;
if (reducers.length > 1) {
if (!copy.labels) {
copy.labels = {};

View File

@@ -48,6 +48,14 @@ describe('fuzzySearch', () => {
expect(result.map((idx) => haystack[idx])).toEqual(['A水']);
});
it('should do case-insensitive substring match when needle contains non-ascii characters', () => {
const haystack = ['Über'];
const needle = 'ü';
const result = fuzzySearch(haystack, needle);
expect(result.map((idx) => haystack[idx])).toEqual(['Über']);
});
it('should handle multiple non-latin characters', () => {
const haystack = ['台灣省', '台中市', '台北市', '台南市', '南投縣', '高雄市', '台中第一高級中學'];
const needle = '南';

View File

@@ -1,5 +1,7 @@
import uFuzzy from '@leeoniya/ufuzzy';
import { escapeRegex } from '../text/string';
// https://catonmat.net/my-favorite-regex :)
const REGEXP_NON_ASCII = /[^ -~]/m;
// https://www.asciitable.com/
@@ -36,11 +38,13 @@ export function fuzzySearch(haystack: string[], needle: string): number[] {
needle.length > maxNeedleLength ||
uf.split(needle).length > maxFuzzyTerms
) {
const needleRegex = new RegExp(escapeRegex(needle), 'i');
const indices: number[] = [];
for (let i = 0; i < haystack.length; i++) {
let item = haystack[i];
if (item.includes(needle)) {
if (needleRegex.test(item)) {
indices.push(i);
}
}

View File

@@ -39,10 +39,10 @@
"postpack": "mv package.json.bak package.json"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-node-resolve": "16.0.1",
"@types/node": "22.15.0",
"@types/semver": "7.7.0",
"esbuild": "0.25.0",
"esbuild": "0.25.6",
"rimraf": "6.0.1",
"rollup": "^4.22.4",
"rollup-plugin-esbuild": "6.2.0",

View File

@@ -1179,11 +1179,6 @@ export const versionedComponents = {
'12.1.0': 'data-testid Data links actions tooltip wrapper',
},
},
TablePanel: {
autoCell: {
'12.1.0': 'data-testid Table panel auto cell',
},
},
CodeEditor: {
container: {
'10.2.3': 'data-testid Code editor container',

View File

@@ -113,3 +113,30 @@ const getStyles = (theme: GrafanaTheme2) => ({
### `theme-token-usage`
Used to find all instances of `theme` tokens being used in the codebase and emit the counts as metrics. Should **not** be used as an actual lint rule!
### `consistent-story-titles`
Enforce consistent Storybook titles in `.story.tsx` files.
Storybook titles should not contain more than one `/` for sections (resulting in maximum 2 parts), unless one of the sections is 'Deprecated'. This helps maintain a clean and organized Storybook structure.
#### Examples
```tsx
// Bad ❌
export default { title: 'Components/Forms/Button' };
// Good ✅
export default { title: 'Components/Button' };
// Good ✅ - Deprecated allows any number of sections
export default { title: 'Components/Deprecated/Forms/Button/Extra' };
// Good ✅ - Variable assignment pattern
const storyConfig = { title: 'Components/Button' };
export default storyConfig;
// Bad ❌ - Variable assignment with too many sections
const storyConfig = { title: 'Components/Forms/Button' };
export default storyConfig;
```

View File

@@ -3,6 +3,7 @@ const noBorderRadiusLiteral = require('./rules/no-border-radius-literal.cjs');
const noUnreducedMotion = require('./rules/no-unreduced-motion.cjs');
const themeTokenUsage = require('./rules/theme-token-usage.cjs');
const noRestrictedImgSrcs = require('./rules/no-restricted-img-srcs.cjs');
const consistentStoryTitles = require('./rules/consistent-story-titles.cjs');
module.exports = {
rules: {
@@ -11,5 +12,6 @@ module.exports = {
'no-border-radius-literal': noBorderRadiusLiteral,
'theme-token-usage': themeTokenUsage,
'no-restricted-img-srcs': noRestrictedImgSrcs,
'consistent-story-titles': consistentStoryTitles,
},
};

View File

@@ -0,0 +1,106 @@
// @ts-check
const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
const createRule = ESLintUtils.RuleCreator(
(name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`
);
/**
* @param {string} title
* @returns {boolean}
*/
const isValidStorybookTitle = (title) => {
if (typeof title !== 'string') {
return true; // Skip non-string titles
}
const sections = title.split('/');
// Allow up to 3 sections if one of them is 'Deprecated'
if (sections.some((section) => section.trim() === 'Deprecated')) {
return sections.length <= 3;
}
// Otherwise, limit to maximum 2 sections (1 slash)
return sections.length <= 2;
};
/**
* @param {import('@typescript-eslint/utils').TSESTree.ObjectExpression} objectNode
* @param {import('@typescript-eslint/utils/ts-eslint').RuleContext<'invalidTitle', []>} context
*/
const checkObjectForTitle = (objectNode, context) => {
const titleProperty = objectNode.properties.find(
(prop) =>
prop.type === AST_NODE_TYPES.Property && prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === 'title'
);
if (
titleProperty &&
titleProperty.type === AST_NODE_TYPES.Property &&
titleProperty.value.type === AST_NODE_TYPES.Literal
) {
const titleValue = titleProperty.value.value;
if (typeof titleValue === 'string' && !isValidStorybookTitle(titleValue)) {
context.report({
node: titleProperty.value,
messageId: 'invalidTitle',
data: {
title: titleValue,
},
});
}
}
};
const consistentStoryTitlesRule = createRule({
create(context) {
return {
ExportDefaultDeclaration(node) {
// Only check .story.tsx files
const filename = context.filename;
if (!filename || !filename.endsWith('.story.tsx')) {
return;
}
if (node.declaration.type === AST_NODE_TYPES.ObjectExpression) {
// Handle direct object export: export default { title: '...' }
checkObjectForTitle(node.declaration, context);
} else if (node.declaration.type === AST_NODE_TYPES.Identifier) {
// Handle variable reference export: export default storyConfig
const variableName = node.declaration.name;
const scope = context.sourceCode.getScope(node);
const variable = scope.set.get(variableName);
if (variable) {
// Find the variable declaration
const declaration = variable.defs.find((def) => def.type === 'Variable');
if (
declaration &&
declaration.node.init &&
declaration.node.init.type === AST_NODE_TYPES.ObjectExpression
) {
checkObjectForTitle(declaration.node.init, context);
}
}
}
},
};
},
name: 'consistent-story-titles',
meta: {
type: 'problem',
docs: {
description: 'Enforce consistent Storybook titles with maximum two sections (1 slash) unless one is "Deprecated"',
},
messages: {
invalidTitle:
'Storybook title "{{ title }}" has too many sections. Use maximum 2 sections (1 slash) unless one section is "Deprecated".',
},
schema: [],
},
defaultOptions: [],
});
module.exports = consistentStoryTitlesRule;

View File

@@ -0,0 +1,117 @@
import { RuleTester } from 'eslint';
import consistentStories from '../rules/consistent-story-titles.cjs';
RuleTester.setDefaultConfig({
languageOptions: {
ecmaVersion: 2018,
sourceType: 'module',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
});
const ruleTester = new RuleTester();
ruleTester.run('eslint consistent-stories', consistentStories, {
valid: [
{
name: 'simple title',
code: `export default { title: 'Button' };`,
filename: 'Button.story.tsx',
},
{
name: 'one section',
code: `export default { title: 'Components/Button' };`,
filename: 'Button.story.tsx',
},
{
name: 'deprecated can have 3 sections',
code: `export default { title: 'Components/Deprecated/Button' };`,
filename: 'Button.story.tsx',
},
{
name: 'not a story file',
code: `export default { title: 'Components/Forms/Button/Extra/Section' };`,
filename: 'Button.tsx',
},
{
name: 'non-string title',
code: `export default { title: 123 };`,
filename: 'Button.story.tsx',
},
{
name: 'no title property',
code: `export default { component: Button };`,
filename: 'Button.story.tsx',
},
{
name: 'variable assignment - simple title',
code: `
const storyConfig = { title: 'Button' };
export default storyConfig;`,
filename: 'Button.story.tsx',
},
{
name: 'variable assignment - one section',
code: `
const storyConfig = { title: 'Components/Button' };
export default storyConfig;`,
filename: 'Button.story.tsx',
},
{
name: 'variable assignment - with Deprecated',
code: `
const storyConfig = { title: 'Components/Deprecated/Button' };
export default storyConfig;`,
filename: 'Button.story.tsx',
},
],
invalid: [
{
name: 'too many sections without Deprecated',
code: `export default { title: 'Components/Forms/Button' };`,
filename: 'Button.story.tsx',
errors: [
{
messageId: 'invalidTitle',
},
],
},
{
name: 'too many sections without Deprecated',
code: `export default { title: 'Components/Forms/Button/Extra' };`,
filename: 'Button.story.tsx',
errors: [
{
messageId: 'invalidTitle',
},
],
},
{
name: 'with spaces around sections',
code: `export default { title: 'Components / Forms / Button' };`,
filename: 'Button.story.tsx',
errors: [
{
messageId: 'invalidTitle',
},
],
},
{
name: 'variable assignment - too many sections',
code: `
const storyConfig = { title: 'Components/Forms/Button' };
export default storyConfig;`,
filename: 'Button.story.tsx',
errors: [
{
messageId: 'invalidTitle',
},
],
},
],
});

View File

@@ -60,20 +60,20 @@
"@babel/preset-env": "7.26.9",
"@babel/preset-react": "7.26.3",
"@grafana/tsconfig": "^2.0.0",
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-node-resolve": "16.0.1",
"@testing-library/dom": "10.4.0",
"@testing-library/jest-dom": "^6.1.2",
"@testing-library/react": "16.2.0",
"@testing-library/user-event": "14.6.1",
"@types/d3": "^7",
"@types/jest": "^29.5.4",
"@types/lodash": "4.17.15",
"@types/lodash": "4.17.20",
"@types/node": "22.15.0",
"@types/react": "18.3.18",
"@types/react-virtualized-auto-sizer": "1.0.4",
"@types/tinycolor2": "1.4.6",
"babel-jest": "29.7.0",
"esbuild": "0.25.0",
"esbuild": "0.25.6",
"jest": "^29.6.4",
"jest-canvas-mock": "2.5.2",
"rollup": "^4.22.4",

View File

@@ -56,7 +56,7 @@
"@formatjs/intl-durationformat": "^0.7.0",
"@typescript-eslint/utils": "^8.33.1",
"fast-deep-equal": "^3.1.3",
"i18next": "^24.0.0",
"i18next": "^25.0.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-pseudo": "^2.2.1",
"micro-memoize": "^4.1.2",

View File

@@ -24,7 +24,21 @@ const createRule = ESLintUtils.RuleCreator(
/**
* JSX props to check for untranslated strings
*/
const propsToCheck = ['content', 'label', 'description', 'placeholder', 'aria-label', 'title', 'text', 'tooltip'];
const propsToCheck = [
'content',
'label',
'description',
'placeholder',
'aria-label',
'ariaLabel',
'title',
'text',
'tooltip',
'confirmText',
'body',
'noOptionsMessage',
'loadingMessage',
];
/**
* Object properties to check for untranslated strings
@@ -34,11 +48,15 @@ const propertiesToCheck = [
'description',
'placeholder',
'aria-label',
'ariaLabel',
'title',
'subTitle',
'text',
'tooltip',
'message',
'confirmText',
'placeholderText',
'noFieldsMessage',
];
/** @type {RuleDefinition} */

View File

@@ -38,7 +38,7 @@
"@types/jest": "^29.5.4",
"@types/node": "22.15.0",
"@types/react": "18.3.18",
"@types/systemjs": "6.15.1",
"@types/systemjs": "6.15.3",
"jest": "^29.6.4",
"react": "18.3.1",
"ts-jest": "29.2.5",

View File

@@ -6,6 +6,7 @@
"dependencies": {
"tslib": "2.8.1"
},
"type": "module",
"devDependencies": {
"@grafana/tsconfig": "^2.0.0",
"@swc/core": "1.10.12",

View File

@@ -4,19 +4,11 @@
"alwaysStrict": true,
"declaration": false,
"resolveJsonModule": true,
"moduleResolution": "bundler"
},
"ts-node": {
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"moduleResolution": "Node",
"esModuleInterop": true
},
"transpileOnly": true
"moduleResolution": "bundler",
"noEmit": true,
"allowImportingTsExtensions": true
},
"extends": "@grafana/tsconfig",
"exclude": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"],
"include": ["./types", "."]
}

View File

@@ -0,0 +1,23 @@
declare module 'replace-in-file-webpack-plugin' {
import { Compiler, Plugin } from 'webpack';
interface ReplaceRule {
search: string | RegExp;
replace: string | ((match: string) => string);
}
interface ReplaceOption {
dir?: string;
files?: string[];
test?: RegExp | RegExp[];
rules: ReplaceRule[];
}
class ReplaceInFilePlugin extends Plugin {
constructor(options?: ReplaceOption[]);
options: ReplaceOption[];
apply(compiler: Compiler): void;
}
export = ReplaceInFilePlugin;
}

View File

@@ -3,12 +3,19 @@ import { glob } from 'glob';
import path from 'path';
import process from 'process';
// Support for node 22 and 24. Due to the many changes in importing json files
// across recent node versions we load the json files using fs for simplicity.
function loadJson(path: string) {
const rawJson = fs.readFileSync(path, 'utf8');
return JSON.parse(rawJson);
}
export function getPackageJson() {
return require(path.resolve(process.cwd(), 'package.json'));
return loadJson(path.resolve(process.cwd(), 'package.json'));
}
export function getPluginJson() {
return require(path.resolve(process.cwd(), 'plugin.json'));
return loadJson(path.resolve(process.cwd(), 'plugin.json'));
}
export async function getEntries(): Promise<Record<string, string>> {

View File

@@ -2,15 +2,14 @@ import CopyWebpackPlugin from 'copy-webpack-plugin';
import ESLintPlugin from 'eslint-webpack-plugin';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import path from 'path';
// @ts-expect-error - there are no types for this package
import ReplaceInFileWebpackPlugin from 'replace-in-file-webpack-plugin';
import TerserPlugin from 'terser-webpack-plugin';
import { type Configuration, BannerPlugin } from 'webpack';
import webpack, { type Configuration } from 'webpack';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import VirtualModulesPlugin from 'webpack-virtual-modules';
import { DIST_DIR } from './constants';
import { getPackageJson, getPluginJson, getEntries, hasLicense } from './utils';
import { DIST_DIR } from './constants.ts';
import { getPackageJson, getPluginJson, getEntries, hasLicense } from './utils.ts';
function skipFiles(f: string): boolean {
if (f.includes('/dist/')) {
@@ -54,9 +53,13 @@ const config = async (env: Env): Promise<Configuration> => {
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
config: [import.meta.filename],
},
cacheDirectory: path.resolve(__dirname, '../../node_modules/.cache/webpack', path.basename(process.cwd())),
cacheDirectory: path.resolve(
import.meta.dirname,
'../../node_modules/.cache/webpack',
path.basename(process.cwd())
),
},
context: process.cwd(),
@@ -114,7 +117,7 @@ const config = async (env: Env): Promise<Configuration> => {
test: /module\.tsx?$/,
use: [
{
loader: require.resolve('imports-loader'),
loader: 'imports-loader',
options: {
imports: `side-effects grafana-public-path`,
},
@@ -125,10 +128,10 @@ const config = async (env: Env): Promise<Configuration> => {
exclude: /(node_modules)/,
test: /\.[tj]sx?$/,
use: {
loader: require.resolve('swc-loader'),
loader: 'swc-loader',
options: {
jsc: {
baseUrl: path.resolve(__dirname),
baseUrl: path.resolve(import.meta.dirname),
target: 'es2015',
loose: false,
parser: {
@@ -209,7 +212,7 @@ const config = async (env: Env): Promise<Configuration> => {
plugins: [
virtualPublicPath,
// Insert create plugin version information into the bundle so Grafana will load from cdn with script tags.
new BannerPlugin({
new webpack.BannerPlugin({
banner: '/* [create-plugin] version: 5.22.0 */',
raw: true,
entryOnly: true,
@@ -264,7 +267,7 @@ const config = async (env: Env): Promise<Configuration> => {
extensions: ['.ts', '.tsx'],
lintDirtyModulesOnly: true, // don't lint on start, only lint changed files
cacheLocation: path.resolve(
__dirname,
import.meta.dirname,
'../../node_modules/.cache/eslint-webpack-plugin',
path.basename(process.cwd()),
'.eslintcache'

View File

@@ -56,7 +56,7 @@
"@prometheus-io/lezer-promql": "0.304.2",
"@reduxjs/toolkit": "2.5.1",
"@types/debounce-promise": "3.1.9",
"@types/lodash": "4.17.15",
"@types/lodash": "4.17.20",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5",
"@types/react-highlight-words": "0.20.0",
@@ -82,7 +82,7 @@
"@rollup/plugin-dynamic-import-vars": "2.1.5",
"@rollup/plugin-image": "3.0.3",
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-node-resolve": "16.0.1",
"@testing-library/jest-dom": "6.6.3",
"@testing-library/react": "16.2.0",
"@testing-library/user-event": "14.6.1",
@@ -90,7 +90,7 @@
"@types/node": "22.15.0",
"@types/pluralize": "^0.0.33",
"@types/prismjs": "1.26.5",
"esbuild": "0.25.0",
"esbuild": "0.25.6",
"i18next-parser": "9.3.0",
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",

View File

@@ -40,11 +40,6 @@ const httpOptions = [
{ value: 'GET', label: 'GET' },
];
const editorOptions = [
{ value: QueryEditorMode.Builder, label: 'Builder' },
{ value: QueryEditorMode.Code, label: 'Code' },
];
const cacheValueOptions = [
{ value: PrometheusCacheLevel.Low, label: 'Low' },
{ value: PrometheusCacheLevel.Medium, label: 'Medium' },
@@ -86,6 +81,17 @@ export const PromSettings = (props: Props) => {
const styles = overhaulStyles(theme);
const { onOptionsChange } = props;
const editorOptions = [
{
value: QueryEditorMode.Builder,
label: t('grafana-prometheus.configuration.prom-settings.editor-options.label-builder', 'Builder'),
},
{
value: QueryEditorMode.Code,
label: t('grafana-prometheus.configuration.prom-settings.editor-options.label-code', 'Code'),
},
];
const optionsWithDefaults = getOptionsWithDefaults(props.options);
const [validDuration, updateValidDuration] = useState<ValidDuration>({
timeInterval: '',

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Poskytnout zpětnou vazbu",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -276,6 +301,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Formát",
"label-min-step": "",
@@ -290,6 +320,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Spustit dotaz",
"label-explain": "",
"run-queries": "",
@@ -306,6 +338,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Feedback geben",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Format",
"label-min-step": "",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Starten Sie Ihre Abfrage",
"label-explain": "",
"run-queries": "",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "{{promType}} type",
"aria-label-prometheus-type": "Prometheus type",
"aria-label-select-http-method": "Select HTTP method",
"editor-options": {
"label-builder": "Builder",
"label-code": "Code"
},
"label-cache-level": "Cache level",
"label-custom-query-parameters": "Custom query parameters",
"label-default-editor": "Default editor",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": "Checking this option will favor the series endpoint with {{exampleParameter}} parameter over the label values endpoint with {{exampleParameter}} parameter. While the label values endpoint is considered more performant, some users may prefer the series because it has a POST method while the label values endpoint only has a GET method."
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "Only includes unique labels",
"description-custom": "Provide a naming template",
"description-verbose": "All label names and values",
"label-auto": "Auto",
"label-custom": "Custom",
"label-verbose": "Verbose"
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "Filter metric names by regex search, using an additional call on the Prometheus API.",
@@ -204,6 +218,13 @@
"give-feedback": "Give feedback",
"title-give-feedback": "The metrics explorer is new, please let us know how we can improve it"
},
"get-collapsed-info": {
"exemplars": "Exemplars: {{value}}",
"format": "Format: {{value}}",
"legend": "Legend: {{value}}",
"step": "Step: {{value}}",
"type": "Type: {{value}}"
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": "Query parsing is ambiguous."
@@ -219,6 +240,10 @@
"label-label-filters": "Label filters",
"tooltip-label-filters": "Optional: used to filter the metric select for this query type."
},
"label-param-editor": {
"loadingMessage-loading-labels": "Loading labels",
"noOptionsMessage-no-labels-found": "No labels found"
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "Open metrics explorer",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "Set lower limit for the step parameter",
"aria-label-select-resolution": "Select resolution",
"format-options": {
"label-heatmap": "Heatmap",
"label-table": "Table",
"label-time-series": "Time series"
},
"label-exemplars": "Exemplars",
"label-format": "Format",
"label-min-step": "Min step",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": "The number of metric names exceeds the autocomplete limit. Only the {{autocompleteLimit}}-most relevant metrics are displayed. You can adjust the threshold in the data source settings."
},
"prom-query-editor-selector": {
"body-syntax-error": "There is a syntax error, or the query structure cannot be visualized when switching to the builder mode. Parts of the query may be lost.",
"confirmText-continue": "Continue",
"kick-start-your-query": "Kick start your query",
"label-explain": "Explain",
"run-queries": "Run queries",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": "hint: {{hintDetails}}"
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "Builder",
"label-code": "Code"
}
},
"query-pattern": {
"apply-query": "Apply query",
"aria-label-apply-query-starter-button": "apply query starter button",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Enviar comentarios",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Formato",
"label-min-step": "",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Inicie su consulta",
"label-explain": "",
"run-queries": "",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Publiez votre commentaire",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Format",
"label-min-step": "",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Lancer votre requête",
"label-explain": "",
"run-queries": "",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Visszajelzés küldése",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Formátum",
"label-min-step": "",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Előbeállításos lekérdezés",
"label-explain": "",
"run-queries": "",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Berikan umpan balik",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -273,6 +298,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Format",
"label-min-step": "",
@@ -287,6 +317,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Mulai kueri Anda",
"label-explain": "",
"run-queries": "",
@@ -303,6 +335,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Lascia un feedback",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Formato",
"label-min-step": "",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Avvia la query",
"label-explain": "",
"run-queries": "",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "フィードバックを送信",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -273,6 +298,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "形式",
"label-min-step": "",
@@ -287,6 +317,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "クエリを開始",
"label-explain": "",
"run-queries": "",
@@ -303,6 +335,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "피드백 제출하기",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -273,6 +298,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "형식",
"label-min-step": "",
@@ -287,6 +317,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "쿼리 시작하기",
"label-explain": "",
"run-queries": "",
@@ -303,6 +335,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

View File

@@ -157,6 +157,10 @@
"aria-label-prom-type-type": "",
"aria-label-prometheus-type": "",
"aria-label-select-http-method": "",
"editor-options": {
"label-builder": "",
"label-code": ""
},
"label-cache-level": "",
"label-custom-query-parameters": "",
"label-default-editor": "",
@@ -195,6 +199,16 @@
"tooltip-use-series-endpoint": ""
}
},
"prom-query-legend-editor": {
"get-legend-mode-options": {
"description-auto": "",
"description-custom": "",
"description-verbose": "",
"label-auto": "",
"label-custom": "",
"label-verbose": ""
}
},
"querybuilder": {
"additional-settings": {
"content-filter-metric-names-regex-search-using": "",
@@ -204,6 +218,13 @@
"give-feedback": "Feedback geven",
"title-give-feedback": ""
},
"get-collapsed-info": {
"exemplars": "",
"format": "",
"legend": "",
"step": "",
"type": ""
},
"handle-function": {
"text": {
"query-parsing-is-ambiguous": ""
@@ -219,6 +240,10 @@
"label-label-filters": "",
"tooltip-label-filters": ""
},
"label-param-editor": {
"loadingMessage-loading-labels": "",
"noOptionsMessage-no-labels-found": ""
},
"metric-combobox": {
"async-select": {
"aria-label-open-metrics-explorer": "",
@@ -274,6 +299,11 @@
"prom-query-builder-options": {
"aria-label-lower-limit-parameter": "",
"aria-label-select-resolution": "",
"format-options": {
"label-heatmap": "",
"label-table": "",
"label-time-series": ""
},
"label-exemplars": "",
"label-format": "Formaat",
"label-min-step": "",
@@ -288,6 +318,8 @@
"tooltip-autocomplete-suggestions-limited": ""
},
"prom-query-editor-selector": {
"body-syntax-error": "",
"confirmText-continue": "",
"kick-start-your-query": "Start je query",
"label-explain": "",
"run-queries": "",
@@ -304,6 +336,12 @@
"query-editor-hints": {
"hint-details": ""
},
"query-editor-mode-toggle": {
"editor-modes": {
"label-builder": "",
"label-code": ""
}
},
"query-pattern": {
"apply-query": "",
"aria-label-apply-query-starter-button": "",

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