mirror of
https://github.com/grafana/grafana.git
synced 2025-12-21 03:54:29 +08:00
Compare commits
145 Commits
docs/add-t
...
v8.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53f5c6a44c | ||
|
|
5407140306 | ||
|
|
0a66eb3a8a | ||
|
|
468735b7a2 | ||
|
|
eb1e411991 | ||
|
|
3afbc685fc | ||
|
|
129734d1f5 | ||
|
|
2443ddf518 | ||
|
|
dc3dc215d8 | ||
|
|
fe7e1292cb | ||
|
|
80b8629f58 | ||
|
|
0743f84f50 | ||
|
|
f1fe8a870b | ||
|
|
5a3e45dd6c | ||
|
|
bbdad0fb27 | ||
|
|
3384269133 | ||
|
|
2a35b4fcef | ||
|
|
d5e0ba2e43 | ||
|
|
f3c1c06753 | ||
|
|
4dec7e8387 | ||
|
|
f4566647bf | ||
|
|
50c883a346 | ||
|
|
077f4c3079 | ||
|
|
8789c6b2ae | ||
|
|
bd0ff79e28 | ||
|
|
e6728d1434 | ||
|
|
6cd56ee459 | ||
|
|
2d7625ac1b | ||
|
|
37c34c6d5b | ||
|
|
3179d548bb | ||
|
|
5b73b4e070 | ||
|
|
122f8b257d | ||
|
|
48e5624095 | ||
|
|
7c079483eb | ||
|
|
2932cc8ec8 | ||
|
|
c630e0ce4f | ||
|
|
1308e19197 | ||
|
|
a682943b24 | ||
|
|
fd83e14400 | ||
|
|
19a88b3e6f | ||
|
|
3d2fbcba2d | ||
|
|
e43e5c3c42 | ||
|
|
67fc8ecbe3 | ||
|
|
709b49fdc8 | ||
|
|
6fdb1d0440 | ||
|
|
f0f4348aa5 | ||
|
|
eeab540874 | ||
|
|
47c3f21c26 | ||
|
|
b00b61f565 | ||
|
|
f5c43af76a | ||
|
|
382600c9eb | ||
|
|
099e6ee22d | ||
|
|
3a04080972 | ||
|
|
16870af3e8 | ||
|
|
3af0331022 | ||
|
|
1edb8f0a5d | ||
|
|
18056a148c | ||
|
|
a7f0fb5052 | ||
|
|
32ce82b874 | ||
|
|
0a9406b26c | ||
|
|
527e5bb6f8 | ||
|
|
3e351914fd | ||
|
|
f5212e4d5a | ||
|
|
6c0652989f | ||
|
|
a5637bd2ac | ||
|
|
162466cad4 | ||
|
|
c897372237 | ||
|
|
843c1c71d9 | ||
|
|
8d60ca53c5 | ||
|
|
0aac670de0 | ||
|
|
57fa05501b | ||
|
|
232fdd195a | ||
|
|
e6d0f5367f | ||
|
|
82fc75cacc | ||
|
|
ef9779c4c3 | ||
|
|
bab2f84155 | ||
|
|
0ff1be7ccc | ||
|
|
3fda778e6d | ||
|
|
4c55c450c3 | ||
|
|
6c370d7d66 | ||
|
|
90316bedee | ||
|
|
7b67b1c961 | ||
|
|
ff8e53a347 | ||
|
|
1f1d599815 | ||
|
|
24411c633c | ||
|
|
5aef9ffb19 | ||
|
|
f8b27f44c0 | ||
|
|
82b20b7c43 | ||
|
|
daf7c5fe93 | ||
|
|
0680dff343 | ||
|
|
87dfe0a523 | ||
|
|
66b1f6722f | ||
|
|
bcff7ec68f | ||
|
|
66f9e505e7 | ||
|
|
da3c22d3be | ||
|
|
4697ef8b81 | ||
|
|
b07267f3e3 | ||
|
|
fb3d542562 | ||
|
|
62a3b5a94d | ||
|
|
dca648f034 | ||
|
|
8291389f6c | ||
|
|
3fdbc461f1 | ||
|
|
08ad99c36e | ||
|
|
c6a58003d1 | ||
|
|
eb666f12a7 | ||
|
|
4f21d4dabe | ||
|
|
836168eb13 | ||
|
|
c4da73ce4d | ||
|
|
d9eb80f7f5 | ||
|
|
6459fd73ed | ||
|
|
be7782032e | ||
|
|
206b447a37 | ||
|
|
32198a472f | ||
|
|
bfd38ece7e | ||
|
|
ce185ce6a3 | ||
|
|
cc9d96e1dc | ||
|
|
d18f53977f | ||
|
|
6295ce8149 | ||
|
|
63b7770220 | ||
|
|
6671367781 | ||
|
|
53313e4a2d | ||
|
|
6909246a7a | ||
|
|
ee54923bdd | ||
|
|
2b516126cf | ||
|
|
ae33b9fce9 | ||
|
|
8ff34fa36e | ||
|
|
36edcfe208 | ||
|
|
358db0d130 | ||
|
|
9e0acc9ece | ||
|
|
5a1fc33eb4 | ||
|
|
c5aaf9526e | ||
|
|
d20ac04120 | ||
|
|
1fe18694ad | ||
|
|
e37dde0036 | ||
|
|
60fcb87a6b | ||
|
|
6292749014 | ||
|
|
d7ba4dd293 | ||
|
|
a7ad5ee55f | ||
|
|
71a0ae7931 | ||
|
|
b4579334d4 | ||
|
|
e031568aa4 | ||
|
|
918f1d943a | ||
|
|
d0871959b6 | ||
|
|
0a90d1eeeb | ||
|
|
c52dae0296 |
272
.drone.yml
272
.drone.yml
@@ -11,7 +11,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -111,7 +111,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -309,15 +309,18 @@ steps:
|
||||
- package
|
||||
image: grafana/build-container:1.4.9
|
||||
name: copy-packages-for-docker
|
||||
- depends_on:
|
||||
- commands:
|
||||
- ./bin/grabpl build-docker --edition oss -archs amd64
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
image: grafana/drone-grafana-docker:0.3.2
|
||||
environment:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: build-docker-images
|
||||
settings:
|
||||
archs: amd64
|
||||
dry_run: true
|
||||
edition: oss
|
||||
ubuntu: false
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
trigger:
|
||||
event:
|
||||
- pull_request
|
||||
@@ -359,7 +362,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -420,7 +423,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -521,7 +524,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -761,30 +764,66 @@ steps:
|
||||
- package
|
||||
image: grafana/build-container:1.4.9
|
||||
name: copy-packages-for-docker
|
||||
- depends_on:
|
||||
- commands:
|
||||
- ./bin/grabpl build-docker --edition oss
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
image: grafana/drone-grafana-docker:0.3.2
|
||||
environment:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: build-docker-images
|
||||
settings:
|
||||
dry_run: false
|
||||
edition: oss
|
||||
password:
|
||||
from_secret: docker_password
|
||||
ubuntu: false
|
||||
username:
|
||||
from_secret: docker_user
|
||||
- depends_on:
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl build-docker --edition oss --ubuntu
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
image: grafana/drone-grafana-docker:0.3.2
|
||||
environment:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: build-docker-images-ubuntu
|
||||
settings:
|
||||
dry_run: false
|
||||
edition: oss
|
||||
password:
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --dockerhub-repo grafana --base alpine --base
|
||||
ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
depends_on:
|
||||
- build-docker-images
|
||||
- build-docker-images-ubuntu
|
||||
environment:
|
||||
DOCKER_PASSWORD:
|
||||
from_secret: docker_password
|
||||
ubuntu: true
|
||||
username:
|
||||
from_secret: docker_user
|
||||
DOCKER_USER:
|
||||
from_secret: docker_username
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: publish-images-grafana
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --dockerhub-repo grafana-oss --base alpine
|
||||
--base ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
depends_on:
|
||||
- build-docker-images
|
||||
- build-docker-images-ubuntu
|
||||
environment:
|
||||
DOCKER_PASSWORD:
|
||||
from_secret: docker_password
|
||||
DOCKER_USER:
|
||||
from_secret: docker_username
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: publish-images-grafana-oss
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./scripts/circle-release-canary-packages.sh
|
||||
depends_on:
|
||||
@@ -805,18 +844,18 @@ steps:
|
||||
- end-to-end-tests-smoke-tests-suite
|
||||
- end-to-end-tests-various-suite
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
image: grafana/grafana-ci-deploy:1.3.1
|
||||
name: upload-packages
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition oss --bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition oss --src-bucket "grafana-static-assets"
|
||||
depends_on:
|
||||
- grafana-server
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -870,7 +909,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -938,7 +977,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: initialize
|
||||
@@ -1021,7 +1060,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -1034,7 +1073,6 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: initialize
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- ./bin/grabpl store-packages --edition oss --gcp-key /tmp/gcpkey.json --build-id
|
||||
${DRONE_BUILD_NUMBER}
|
||||
depends_on:
|
||||
@@ -1094,7 +1132,7 @@ type: docker
|
||||
---
|
||||
depends_on: []
|
||||
kind: pipeline
|
||||
name: oss-build-publish-e2e-release
|
||||
name: oss-build-e2e-publish-release
|
||||
node:
|
||||
type: no-parallel
|
||||
platform:
|
||||
@@ -1104,7 +1142,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -1202,8 +1240,6 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: copy-packages-for-docker
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition oss --shouldSave
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -1211,13 +1247,11 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images
|
||||
name: build-docker-images
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition oss --shouldSave --ubuntu
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -1225,7 +1259,7 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images-ubuntu
|
||||
name: build-docker-images-ubuntu
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
@@ -1319,11 +1353,12 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: build-storybook
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition oss --bucket "$${PRERELEASE_BUCKET}/artifacts/static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition oss --src-bucket "$${PRERELEASE_BUCKET}" --src-dir
|
||||
artifacts/static-assets
|
||||
depends_on:
|
||||
- grafana-server
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -1337,7 +1372,7 @@ steps:
|
||||
- end-to-end-tests-smoke-tests-suite
|
||||
- end-to-end-tests-various-suite
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -1411,7 +1446,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -1532,7 +1567,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -1599,7 +1634,7 @@ volumes:
|
||||
medium: memory
|
||||
---
|
||||
depends_on:
|
||||
- oss-build-publish-e2e-release
|
||||
- oss-build-e2e-publish-release
|
||||
- oss-test-release
|
||||
- oss-integration-tests-release
|
||||
kind: pipeline
|
||||
@@ -1616,7 +1651,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: initialize
|
||||
@@ -1675,7 +1710,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -1807,8 +1842,6 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: copy-packages-for-docker
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition enterprise --shouldSave
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -1816,13 +1849,11 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images
|
||||
name: build-docker-images
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition enterprise --shouldSave --ubuntu
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -1830,7 +1861,7 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images-ubuntu
|
||||
name: build-docker-images-ubuntu
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
@@ -1916,11 +1947,12 @@ steps:
|
||||
- success
|
||||
- failure
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise --bucket "$${PRERELEASE_BUCKET}/artifacts/static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition enterprise --src-bucket "$${PRERELEASE_BUCKET}"
|
||||
--src-dir artifacts/static-assets
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -1931,7 +1963,7 @@ steps:
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -1959,11 +1991,12 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: package-enterprise2
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2 --bucket "$${PRERELEASE_BUCKET}/artifacts/static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2 --src-bucket "$${PRERELEASE_BUCKET}"
|
||||
--src-dir artifacts/static-assets
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -1974,7 +2007,7 @@ steps:
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -2017,7 +2050,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2190,7 +2223,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2318,7 +2351,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
|
||||
- cd grafana-enterprise
|
||||
@@ -2393,7 +2426,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2415,8 +2448,8 @@ steps:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --version-tag ${TAG} --dockerhub-repo grafana
|
||||
--base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
- ./bin/grabpl artifacts docker publish --dockerhub-repo grafana --base alpine --base
|
||||
ubuntu --arch amd64 --arch arm64 --arch armv7 --version-tag ${TAG}
|
||||
depends_on:
|
||||
- fetch-images-oss
|
||||
environment:
|
||||
@@ -2432,8 +2465,8 @@ steps:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --version-tag ${TAG} --dockerhub-repo grafana-oss
|
||||
--base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
- ./bin/grabpl artifacts docker publish --dockerhub-repo grafana-oss --base alpine
|
||||
--base ubuntu --arch amd64 --arch arm64 --arch armv7 --version-tag ${TAG}
|
||||
depends_on:
|
||||
- fetch-images-oss
|
||||
environment:
|
||||
@@ -2471,7 +2504,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2493,8 +2526,8 @@ steps:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --version-tag ${TAG} --dockerhub-repo grafana-enterprise
|
||||
--base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
- ./bin/grabpl artifacts docker publish --dockerhub-repo grafana-enterprise --base
|
||||
alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7 --version-tag ${TAG}
|
||||
depends_on:
|
||||
- fetch-images-enterprise
|
||||
environment:
|
||||
@@ -2532,7 +2565,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2554,8 +2587,8 @@ steps:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --security --version-tag ${TAG} --dockerhub-repo
|
||||
grafana --base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
- ./bin/grabpl artifacts docker publish --security --dockerhub-repo grafana --base
|
||||
alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7 --version-tag ${TAG}
|
||||
depends_on:
|
||||
- fetch-images-oss
|
||||
environment:
|
||||
@@ -2571,8 +2604,9 @@ steps:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --security --version-tag ${TAG} --dockerhub-repo
|
||||
grafana-oss --base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7
|
||||
- ./bin/grabpl artifacts docker publish --security --dockerhub-repo grafana-oss
|
||||
--base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7 --version-tag
|
||||
${TAG}
|
||||
depends_on:
|
||||
- fetch-images-oss
|
||||
environment:
|
||||
@@ -2610,7 +2644,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2632,9 +2666,9 @@ steps:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- ./bin/grabpl artifacts docker publish --security --version-tag ${TAG} --dockerhub-repo
|
||||
grafana-enterprise --base alpine --base ubuntu --arch amd64 --arch arm64 --arch
|
||||
armv7
|
||||
- ./bin/grabpl artifacts docker publish --security --dockerhub-repo grafana-enterprise
|
||||
--base alpine --base ubuntu --arch amd64 --arch arm64 --arch armv7 --version-tag
|
||||
${TAG}
|
||||
depends_on:
|
||||
- fetch-images-enterprise
|
||||
environment:
|
||||
@@ -2672,7 +2706,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2708,7 +2742,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2755,7 +2789,7 @@ steps:
|
||||
name: initialize
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2803,12 +2837,11 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- ./bin/grabpl store-packages --edition oss --packages-bucket grafana-downloads
|
||||
--gcp-key /tmp/gcpkey.json ${DRONE_TAG}
|
||||
depends_on:
|
||||
@@ -2827,7 +2860,6 @@ steps:
|
||||
image: grafana/grafana-ci-deploy:1.3.1
|
||||
name: store-packages-oss
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- ./bin/grabpl store-packages --edition enterprise --packages-bucket grafana-downloads
|
||||
--gcp-key /tmp/gcpkey.json ${DRONE_TAG}
|
||||
depends_on:
|
||||
@@ -2858,7 +2890,7 @@ volumes:
|
||||
---
|
||||
depends_on: []
|
||||
kind: pipeline
|
||||
name: oss-build-publish-e2e-release-branch
|
||||
name: oss-build-e2e-publish-release-branch
|
||||
node:
|
||||
type: no-parallel
|
||||
platform:
|
||||
@@ -2868,7 +2900,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2963,8 +2995,6 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: copy-packages-for-docker
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition oss --shouldSave
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -2972,13 +3002,11 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images
|
||||
name: build-docker-images
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition oss --shouldSave --ubuntu
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -2986,7 +3014,7 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images-ubuntu
|
||||
name: build-docker-images-ubuntu
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
@@ -3080,11 +3108,11 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: build-storybook
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition oss --bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition oss --src-bucket "grafana-static-assets"
|
||||
depends_on:
|
||||
- grafana-server
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -3098,7 +3126,7 @@ steps:
|
||||
- end-to-end-tests-smoke-tests-suite
|
||||
- end-to-end-tests-various-suite
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -3131,7 +3159,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3245,7 +3273,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3305,7 +3333,7 @@ volumes:
|
||||
medium: memory
|
||||
---
|
||||
depends_on:
|
||||
- oss-build-publish-e2e-release-branch
|
||||
- oss-build-e2e-publish-release-branch
|
||||
- oss-test-release-branch
|
||||
- oss-integration-tests-release-branch
|
||||
kind: pipeline
|
||||
@@ -3322,7 +3350,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: initialize
|
||||
@@ -3370,7 +3398,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3496,8 +3524,6 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: copy-packages-for-docker
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition enterprise --shouldSave
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -3505,13 +3531,11 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images
|
||||
name: build-docker-images
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
- commands:
|
||||
- printenv GCP_KEY | base64 -d > /tmp/gcpkey.json
|
||||
- gcloud auth activate-service-account --key-file=/tmp/gcpkey.json
|
||||
- ./bin/grabpl build-docker --edition enterprise --shouldSave --ubuntu
|
||||
depends_on:
|
||||
- copy-packages-for-docker
|
||||
@@ -3519,7 +3543,7 @@ steps:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
image: google/cloud-sdk
|
||||
name: package-docker-images-ubuntu
|
||||
name: build-docker-images-ubuntu
|
||||
volumes:
|
||||
- name: docker
|
||||
path: /var/run/docker.sock
|
||||
@@ -3614,11 +3638,11 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: build-storybook
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise --bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition enterprise --src-bucket "grafana-static-assets"
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -3629,7 +3653,7 @@ steps:
|
||||
depends_on:
|
||||
- package
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -3657,11 +3681,11 @@ steps:
|
||||
image: grafana/build-container:1.4.9
|
||||
name: package-enterprise2
|
||||
- commands:
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2 --bucket "grafana-static-assets"
|
||||
- ./bin/grabpl upload-cdn --edition enterprise2 --src-bucket "grafana-static-assets"
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -3672,7 +3696,7 @@ steps:
|
||||
depends_on:
|
||||
- package-enterprise2
|
||||
environment:
|
||||
GCP_GRAFANA_UPLOAD_KEY:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_key
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
@@ -3709,7 +3733,7 @@ services: []
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3874,7 +3898,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3994,7 +4018,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.8.7/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.9.2/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
- git clone "https://$$env:GITHUB_TOKEN@github.com/grafana/grafana-enterprise.git"
|
||||
- cd grafana-enterprise
|
||||
@@ -4191,6 +4215,6 @@ kind: secret
|
||||
name: gcp_upload_artifacts_key
|
||||
---
|
||||
kind: signature
|
||||
hmac: 4d1a5696bf1e510fb51a021c07e240c50cb913724ce08ed52cce037ff02dd8de
|
||||
hmac: a29229ea9d7c398be08208f7294bebc889c74f2b886822c295aeabd844eabf8e
|
||||
|
||||
...
|
||||
|
||||
@@ -43,18 +43,18 @@ jobs:
|
||||
name: buildPr
|
||||
path: './pr/pr_built_packages.zip'
|
||||
|
||||
buildMain:
|
||||
name: Build Main
|
||||
buildBase:
|
||||
name: Build Base
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: './main'
|
||||
working-directory: './base'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
path: './main'
|
||||
ref: 'main'
|
||||
path: './base'
|
||||
ref: ${{ github.event.pull_request.base.ref }}
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
@@ -76,18 +76,18 @@ jobs:
|
||||
run: yarn packages:build
|
||||
|
||||
- name: Zip built packages
|
||||
run: zip -r ./main_built_packages.zip ./packages/**/dist
|
||||
run: zip -r ./base_built_packages.zip ./packages/**/dist
|
||||
|
||||
- name: Upload build output as artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: buildMain
|
||||
path: './main/main_built_packages.zip'
|
||||
name: buildBase
|
||||
path: './base/base_built_packages.zip'
|
||||
|
||||
Detect:
|
||||
name: Detect breaking changes
|
||||
runs-on: ubuntu-latest
|
||||
needs: ['buildPR', 'buildMain']
|
||||
needs: ['buildPR', 'buildBase']
|
||||
env:
|
||||
GITHUB_STEP_NUMBER: 7
|
||||
|
||||
@@ -99,16 +99,16 @@ jobs:
|
||||
with:
|
||||
name: buildPr
|
||||
|
||||
- name: Get built packages from main
|
||||
- name: Get built packages from base
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: buildMain
|
||||
name: buildBase
|
||||
|
||||
- name: Unzip artifact from pr
|
||||
run: unzip pr_built_packages.zip -d ./pr && rm pr_built_packages.zip
|
||||
|
||||
- name: Unzip artifact from main
|
||||
run: unzip main_built_packages.zip -d ./main && rm main_built_packages.zip
|
||||
- name: Unzip artifact from base
|
||||
run: unzip base_built_packages.zip -d ./base && rm base_built_packages.zip
|
||||
|
||||
- name: Get link for the Github Action job
|
||||
id: job
|
||||
|
||||
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
@@ -3,7 +3,7 @@ name: publish_docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- v8.4.x
|
||||
paths:
|
||||
- 'docs/sources/**'
|
||||
- 'packages/grafana-*/**'
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
host: github.com
|
||||
github_pat: '${{ secrets.GH_BOT_ACCESS_TOKEN }}'
|
||||
source_folder: docs/sources
|
||||
target_folder: content/docs/grafana/next
|
||||
target_folder: content/docs/grafana/latest
|
||||
allow_no_changes: 'true'
|
||||
- shell: bash
|
||||
run: |
|
||||
|
||||
30
.yarnrc.yml
30
.yarnrc.yml
@@ -9,28 +9,28 @@ packageExtensions:
|
||||
"@mdx-js/loader@1.6.22":
|
||||
peerDependencies:
|
||||
react: 17.0.1
|
||||
"@storybook/addon-docs@6.4.13":
|
||||
"@storybook/addon-docs@6.4.15":
|
||||
peerDependencies:
|
||||
"@storybook/manager-webpack5": 6.4.13
|
||||
"@storybook/addon-essentials@6.4.13":
|
||||
"@storybook/manager-webpack5": 6.4.15
|
||||
"@storybook/addon-essentials@6.4.15":
|
||||
peerDependencies:
|
||||
"@storybook/components": 6.4.13
|
||||
"@storybook/core-events": 6.4.13
|
||||
"@storybook/manager-webpack5": 6.4.13
|
||||
"@storybook/theming": 6.4.13
|
||||
"@storybook/core-server@6.4.13":
|
||||
"@storybook/components": 6.4.15
|
||||
"@storybook/core-events": 6.4.15
|
||||
"@storybook/manager-webpack5": 6.4.15
|
||||
"@storybook/theming": 6.4.15
|
||||
"@storybook/core-server@6.4.15":
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
"@storybook/core@6.4.13":
|
||||
"@storybook/core@6.4.15":
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
"@storybook/manager-webpack5": 6.4.13
|
||||
"@storybook/csf-tools@6.4.13":
|
||||
"@storybook/manager-webpack5": 6.4.15
|
||||
"@storybook/csf-tools@6.4.15":
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
"@storybook/react@6.4.13":
|
||||
"@storybook/react@6.4.15":
|
||||
peerDependencies:
|
||||
"@storybook/manager-webpack5": 6.4.13
|
||||
"@storybook/manager-webpack5": 6.4.15
|
||||
doctrine@3.0.0:
|
||||
dependencies:
|
||||
assert: 2.0.0
|
||||
@@ -60,10 +60,6 @@ packageExtensions:
|
||||
react-simple-compat: 1.2.1
|
||||
peerDependencies:
|
||||
framework-utils: ^1.1.0
|
||||
react-dev-utils@11.0.4:
|
||||
peerDependencies:
|
||||
typescript: 4.4.3
|
||||
webpack: 5.51.1
|
||||
react-docgen-typescript-loader@3.7.2:
|
||||
peerDependencies:
|
||||
webpack: 4.41.5
|
||||
|
||||
92
CHANGELOG.md
92
CHANGELOG.md
@@ -1,3 +1,87 @@
|
||||
<!-- 8.4.0 START -->
|
||||
|
||||
# 8.4.0 (2022-02-16)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **API:** Extract OpenAPI specification from source code using go-swagger. [#40528](https://github.com/grafana/grafana/pull/40528), [@papagian](https://github.com/papagian)
|
||||
- **AccessControl:** Disable user remove and user update roles when they do not have the permissions. [#43429](https://github.com/grafana/grafana/pull/43429), [@Jguer](https://github.com/Jguer)
|
||||
- **AccessControl:** Provisioning for teams. [#43767](https://github.com/grafana/grafana/pull/43767), [@gamab](https://github.com/gamab)
|
||||
- **API:** Add usage stats preview endpoint. [#43899](https://github.com/grafana/grafana/pull/43899), [@Jguer](https://github.com/Jguer)
|
||||
- **Alerting:** Move slow queries in the scheduler to another goroutine. [#44423](https://github.com/grafana/grafana/pull/44423), [@grobinson-grafana](https://github.com/grobinson-grafana)
|
||||
- **Alerting:** Use time.Ticker instead of alerting.Ticker in ngalert. [#44395](https://github.com/grafana/grafana/pull/44395), [@grobinson-grafana](https://github.com/grobinson-grafana)
|
||||
- **Alerting:** add custom grouping to Alert Panel. [#44559](https://github.com/grafana/grafana/pull/44559), [@gillesdemey](https://github.com/gillesdemey)
|
||||
- **Analytics:** Add user id tracking to google analytics. [#42763](https://github.com/grafana/grafana/pull/42763), [@autoric](https://github.com/autoric)
|
||||
- **Angular:** Add AngularJS plugin support deprecation plan to docs site. [#45149](https://github.com/grafana/grafana/pull/45149), [@torkelo](https://github.com/torkelo)
|
||||
- **Auth:** implement auto_sign_up for auth.jwt. [#43502](https://github.com/grafana/grafana/pull/43502), [@sakjur](https://github.com/sakjur)
|
||||
- **Azure Monitor Logs:** Order subscriptions in resource picker by name. [#45228](https://github.com/grafana/grafana/pull/45228), [@sunker](https://github.com/sunker)
|
||||
- **Azure monitor Logs:** Optimize data fetching in resource picker. [#44549](https://github.com/grafana/grafana/pull/44549), [@sunker](https://github.com/sunker)
|
||||
- **AzureMonitor:** Filter list of resources by resourceType. [#43522](https://github.com/grafana/grafana/pull/43522), [@andresmgot](https://github.com/andresmgot)
|
||||
- **BarChart:** color by field, x time field, bar radius, label skipping. [#43257](https://github.com/grafana/grafana/pull/43257), [@leeoniya](https://github.com/leeoniya)
|
||||
- **Chore:** Implement OpenTelemetry in Grafana. [#42674](https://github.com/grafana/grafana/pull/42674), [@idafurjes](https://github.com/idafurjes)
|
||||
- **Cloud Monitoring:** Adds metric type to Metric drop down options. [#43268](https://github.com/grafana/grafana/pull/43268), [@tw1nk](https://github.com/tw1nk)
|
||||
- **CloudWatch:** Add Data Lifecycle Manager metrics and dimension. [#43310](https://github.com/grafana/grafana/pull/43310), [@ilyastoli](https://github.com/ilyastoli)
|
||||
- **CloudWatch:** Add Missing Elasticache Host-level metrics. [#43455](https://github.com/grafana/grafana/pull/43455), [@dhendo](https://github.com/dhendo)
|
||||
- **CloudWatch:** Add all ElastiCache Redis Metrics. [#43336](https://github.com/grafana/grafana/pull/43336), [@siavashs](https://github.com/siavashs)
|
||||
- **CloudWatch:** Add new AWS/ES metrics. [#43034](https://github.com/grafana/grafana/pull/43034), [@sunker](https://github.com/sunker)
|
||||
- **Cloudwatch:** Add syntax highlighting and autocomplete for "Metric Search". [#43985](https://github.com/grafana/grafana/pull/43985), [@sarahzinger](https://github.com/sarahzinger)
|
||||
- **Explore:** Support custom display label for exemplar links for Prometheus datasource. [#42732](https://github.com/grafana/grafana/pull/42732), [@JokerQueue](https://github.com/JokerQueue)
|
||||
- **Hotkeys:** Make time range absolute/permanent. [#43802](https://github.com/grafana/grafana/pull/43802), [@davkal](https://github.com/davkal)
|
||||
- **Playlists:** Enable sharing direct links to playlists. [#44161](https://github.com/grafana/grafana/pull/44161), [@ashharrison90](https://github.com/ashharrison90)
|
||||
- **SQLStore:** Prevent concurrent migrations. [#44101](https://github.com/grafana/grafana/pull/44101), [@papagian](https://github.com/papagian)
|
||||
- **SSE:** Add Mode to drop NaN/Inf/Null in Reduction operations. [#43583](https://github.com/grafana/grafana/pull/43583), [@kylebrandt](https://github.com/kylebrandt)
|
||||
- **Setting:** Support configuring feature toggles with bools instead of just passing an array. [#43326](https://github.com/grafana/grafana/pull/43326), [@bergquist](https://github.com/bergquist)
|
||||
- **TimeSeries:** Add support for negative Y and constant transform. [#44774](https://github.com/grafana/grafana/pull/44774), [@dprokop](https://github.com/dprokop)
|
||||
- **Transformations:** Add 'JSON' field type to ConvertFieldTypeTransformer. [#42624](https://github.com/grafana/grafana/pull/42624), [@sd2k](https://github.com/sd2k)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Auth:** Guarantee consistency of signed SigV4 headers. [#45054](https://github.com/grafana/grafana/pull/45054), [@wbrowne](https://github.com/wbrowne)
|
||||
- **CloudWatch:** Fix MetricName resetting on Namespace change. [#44165](https://github.com/grafana/grafana/pull/44165), [@yaelleC](https://github.com/yaelleC)
|
||||
- **Cloudwatch :** Fixed resetting metric name when changing namespace in Metric Query. [#44612](https://github.com/grafana/grafana/pull/44612), [@yaelleC](https://github.com/yaelleC)
|
||||
- **Explore:** Avoid locking timepicker when range is inverted. [#44790](https://github.com/grafana/grafana/pull/44790), [@Elfo404](https://github.com/Elfo404)
|
||||
- **Instrumentation:** Fix HTTP request instrumentation of authentication failures. [#44234](https://github.com/grafana/grafana/pull/44234), [@marefr](https://github.com/marefr)
|
||||
- **LibraryPanels:** Prevent long descriptions and names from obscuring the delete button. [#45190](https://github.com/grafana/grafana/pull/45190), [@zuchka](https://github.com/zuchka)
|
||||
- **OAuth:** Fix parsing of ID token if header contains non-string value. [#44159](https://github.com/grafana/grafana/pull/44159), [@marefr](https://github.com/marefr)
|
||||
- **Panel Edit:** Visualization search now works correctly with special characters. [#45137](https://github.com/grafana/grafana/pull/45137), [@ashharrison90](https://github.com/ashharrison90)
|
||||
- **Provisioning:** Fix duplicate validation when multiple organizations have been configured. [#44151](https://github.com/grafana/grafana/pull/44151), [@marefr](https://github.com/marefr)
|
||||
- **QueryField:** Fix issue with undo history when suggestion is inserted (#28656). [#39114](https://github.com/grafana/grafana/pull/39114), [@glintik](https://github.com/glintik)
|
||||
- **TablePanel:** Do not prefix columns with frame name if multiple frames and override active. [#45174](https://github.com/grafana/grafana/pull/45174), [@mdvictor](https://github.com/mdvictor)
|
||||
|
||||
### Deprecations
|
||||
|
||||
AngularJS plugin support is now in a deprecated state, meaning it will be removed in a future release. Currently, that is planned for version 10 (in 2023). The documentation site has an [article](https://grafana.com/docs/grafana/next/developers/angular_deprecation/) with more details on why, when, and how. Issue [#45149](https://github.com/grafana/grafana/issues/45149)
|
||||
|
||||
<!-- 8.4.0 END -->
|
||||
<!-- 8.4.0-beta1 START -->
|
||||
|
||||
# 8.4.0-beta1 (2022-02-02)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Alerting:** Support WeCom as a contact point type. [#40975](https://github.com/grafana/grafana/pull/40975), [@smallpath](https://github.com/smallpath)
|
||||
- **Alerting:** UI for mute timings. [#41578](https://github.com/grafana/grafana/pull/41578), [@nathanrodman](https://github.com/nathanrodman)
|
||||
- **Alerting:** add settings for peer reconnection in HA mode. [#42300](https://github.com/grafana/grafana/pull/42300), [@JohnnyQQQQ](https://github.com/JohnnyQQQQ)
|
||||
- **Auth:** implement auto_sign_up for auth.jwt. [#37040](https://github.com/grafana/grafana/pull/37040), [@Roguelazer](https://github.com/Roguelazer)
|
||||
- **Dashboard:** Add Show unknown variables toggle to dashboard settings. [#41854](https://github.com/grafana/grafana/pull/41854), [@hugohaggmark](https://github.com/hugohaggmark)
|
||||
- **Instrumentation:** Logger migration from log15 to gokit/log. [#41636](https://github.com/grafana/grafana/pull/41636), [@ying-jeanne](https://github.com/ying-jeanne)
|
||||
- **MSSQL:** Change regex to validate Provider connection string. [#40248](https://github.com/grafana/grafana/pull/40248), [@ianselmi](https://github.com/ianselmi)
|
||||
- **MSSQL:** Configuration of certificate verification for TLS connection. [#31865](https://github.com/grafana/grafana/pull/31865), [@mortenaa](https://github.com/mortenaa)
|
||||
- **Middleware:** Don't require HTTPS for HSTS headers to be emitted. [#35147](https://github.com/grafana/grafana/pull/35147), [@alexmv](https://github.com/alexmv)
|
||||
- **Navigation:** Implement Keyboard Navigation. [#41618](https://github.com/grafana/grafana/pull/41618), [@axelavargas](https://github.com/axelavargas)
|
||||
- **News:** Reload feed when changing the time range or refreshing. [#42217](https://github.com/grafana/grafana/pull/42217), [@ashharrison90](https://github.com/ashharrison90)
|
||||
- **UI/Plot:** Implement keyboard controls for plot cursor. [#42244](https://github.com/grafana/grafana/pull/42244), [@kaydelaney](https://github.com/kaydelaney)
|
||||
|
||||
<!-- 8.4.0-beta1 END -->
|
||||
<!-- 8.3.5 START -->
|
||||
|
||||
# 8.3.5 (2022-02-08)
|
||||
|
||||
- **Security**: Fixes CVE-2022-21702. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21703. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21713. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
|
||||
<!-- 8.3.5 END -->
|
||||
<!-- 8.3.4 START -->
|
||||
|
||||
# 8.3.4 (2022-01-17)
|
||||
@@ -1259,7 +1343,15 @@ Issue [#33352](https://github.com/grafana/grafana/issues/33352)
|
||||
- **AGPL License:** Update license from Apache 2.0 to the GNU Affero General Public License (AGPL). [#33184](https://github.com/grafana/grafana/pull/33184)
|
||||
|
||||
<!-- 8.0.0-beta1 END -->
|
||||
<!-- 7.5.15 START -->
|
||||
|
||||
# 7.5.15 (2022-02-08)
|
||||
|
||||
- **Security**: Fixes CVE-2022-21702. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21703. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21713. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
|
||||
<!-- 7.5.15 END -->
|
||||
<!-- 7.5.13 START -->
|
||||
|
||||
# 7.5.13 (2022-01-18)
|
||||
|
||||
@@ -11,7 +11,7 @@ COPY plugins-bundled plugins-bundled
|
||||
|
||||
RUN yarn install
|
||||
|
||||
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json ./
|
||||
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json .linguirc ./
|
||||
COPY public public
|
||||
COPY tools tools
|
||||
COPY scripts scripts
|
||||
@@ -30,6 +30,7 @@ COPY go.mod go.sum embed.go Makefile build.go package.json ./
|
||||
COPY cue cue
|
||||
COPY packages/grafana-schema packages/grafana-schema
|
||||
COPY public/app/plugins public/app/plugins
|
||||
COPY public/api-spec.json public/api-spec.json
|
||||
COPY pkg pkg
|
||||
COPY scripts scripts
|
||||
COPY cue.mod cue.mod
|
||||
|
||||
@@ -12,7 +12,7 @@ COPY plugins-bundled plugins-bundled
|
||||
|
||||
RUN yarn install
|
||||
|
||||
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json ./
|
||||
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json .linguirc ./
|
||||
COPY public public
|
||||
COPY tools tools
|
||||
COPY scripts scripts
|
||||
@@ -33,6 +33,7 @@ COPY cue cue/
|
||||
COPY cue.mod cue.mod/
|
||||
COPY packages/grafana-schema packages/grafana-schema/
|
||||
COPY public/app/plugins public/app/plugins/
|
||||
COPY public/api-spec.json public/api-spec.json
|
||||
|
||||
RUN go mod verify
|
||||
RUN make build-go
|
||||
|
||||
60
Makefile
60
Makefile
@@ -7,11 +7,13 @@ WIRE_TAGS = "oss"
|
||||
-include local/Makefile
|
||||
include .bingo/Variables.mk
|
||||
|
||||
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-full lint-go golangci-lint test-go test-js gen-ts test run run-frontend clean devenv devenv-down protobuf drone help
|
||||
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-full build-docker-full-ubuntu lint-go golangci-lint test-go test-js gen-ts test run run-frontend clean devenv devenv-down protobuf drone help
|
||||
|
||||
GO = go
|
||||
GO_FILES ?= ./pkg/...
|
||||
SH_FILES ?= $(shell find ./scripts -name *.sh)
|
||||
API_DEFINITION_FILES = $(shell find ./pkg/api/docs/definitions -name '*.go' -print)
|
||||
SWAGGER_TAG ?= latest
|
||||
|
||||
all: deps build
|
||||
|
||||
@@ -28,13 +30,62 @@ node_modules: package.json yarn.lock ## Install node modules.
|
||||
@echo "install frontend dependencies"
|
||||
YARN_ENABLE_PROGRESS_BARS=false yarn install --immutable
|
||||
|
||||
##@ Swagger
|
||||
SPEC_TARGET = public/api-spec.json
|
||||
MERGED_SPEC_TARGET := public/api-merged.json
|
||||
NGALERT_SPEC_TARGET = pkg/services/ngalert/api/tooling/post.json
|
||||
|
||||
$(SPEC_TARGET): $(API_DEFINITION_FILES) ## Generate API spec
|
||||
docker run --rm -it \
|
||||
-e GOPATH=${HOME}/go:/go \
|
||||
-e SWAGGER_GENERATE_EXTENSION=false \
|
||||
-v ${HOME}/go:/go \
|
||||
-v $$(pwd):/grafana \
|
||||
-w $$(pwd)/pkg/api/docs quay.io/goswagger/swagger:$(SWAGGER_TAG) \
|
||||
generate spec -m -o /grafana/public/api-spec.json \
|
||||
-w /grafana/pkg/server \
|
||||
-x "grafana/grafana/pkg/services/ngalert/api/tooling/definitions" \
|
||||
-x "github.com/prometheus/alertmanager" \
|
||||
-i /grafana/pkg/api/docs/tags.json
|
||||
|
||||
swagger-api-spec: gen-go $(SPEC_TARGET) $(MERGED_SPEC_TARGET)
|
||||
|
||||
$(NGALERT_SPEC_TARGET):
|
||||
+$(MAKE) -C pkg/services/ngalert/api/tooling post.json
|
||||
|
||||
$(MERGED_SPEC_TARGET): $(SPEC_TARGET) $(NGALERT_SPEC_TARGET) ## Merge generated and ngalert API specs
|
||||
go run pkg/api/docs/merge/merge_specs.go -o=public/api-merged.json $(<) pkg/services/ngalert/api/tooling/post.json
|
||||
|
||||
ensure_go-swagger_mac:
|
||||
@hash swagger &>/dev/null || (brew tap go-swagger/go-swagger && brew install go-swagger)
|
||||
|
||||
--swagger-api-spec-mac: ensure_go-swagger_mac $(API_DEFINITION_FILES) ## Generate API spec (for M1 Mac)
|
||||
swagger generate spec -m -w pkg/server -o public/api-spec.json \
|
||||
-x "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" \
|
||||
-x "github.com/prometheus/alertmanager" \
|
||||
-i pkg/api/docs/tags.json
|
||||
|
||||
swagger-api-spec-mac: gen-go --swagger-api-spec-mac $(MERGED_SPEC_TARGET)
|
||||
|
||||
validate-api-spec: $(MERGED_SPEC_TARGET) ## Validate API spec
|
||||
docker run --rm -it \
|
||||
-e GOPATH=${HOME}/go:/go \
|
||||
-e SWAGGER_GENERATE_EXTENSION=false \
|
||||
-v ${HOME}/go:/go \
|
||||
-v $$(pwd):/grafana \
|
||||
-w $$(pwd)/pkg/api/docs quay.io/goswagger/swagger:$(SWAGGER_TAG) \
|
||||
validate /grafana/$(<)
|
||||
|
||||
clean-api-spec:
|
||||
rm $(SPEC_TARGET) $(MERGED_SPEC_TARGET)
|
||||
|
||||
##@ Building
|
||||
|
||||
gen-go: $(WIRE)
|
||||
@echo "generate go files"
|
||||
$(WIRE) gen -tags $(WIRE_TAGS) ./pkg/server ./pkg/cmd/grafana-cli/runner
|
||||
|
||||
build-go: gen-go ## Build all Go binaries.
|
||||
build-go: $(MERGED_SPEC_TARGET) gen-go ## Build all Go binaries.
|
||||
@echo "build go files"
|
||||
$(GO) run build.go build
|
||||
|
||||
@@ -99,6 +150,11 @@ build-docker-full: ## Build Docker image for development.
|
||||
@echo "build docker container"
|
||||
docker build --tag grafana/grafana:dev .
|
||||
|
||||
build-docker-full-ubuntu: ## Build Docker image based on Ubuntu for development.
|
||||
@echo "build docker container"
|
||||
docker build --tag grafana/grafana:dev-ubuntu -f ./Dockerfile.ubuntu .
|
||||
|
||||
|
||||
##@ Services
|
||||
|
||||
# create docker-compose file with provided sources and start them
|
||||
|
||||
@@ -122,6 +122,9 @@ path = grafana.db
|
||||
# For "sqlite3" only. cache mode setting used for connecting to the database
|
||||
cache_mode = private
|
||||
|
||||
# For "mysql" only if lockingMigration feature toggle is set. How many seconds to wait before failing to lock the database for the migrations, default is 0.
|
||||
locking_attempt_timeout_sec = 0
|
||||
|
||||
#################################### Cache server #############################
|
||||
[remote_cache]
|
||||
# Either "redis", "memcached" or "database" default is "database"
|
||||
@@ -403,6 +406,9 @@ api_key_max_seconds_to_live = -1
|
||||
# Set to true to enable SigV4 authentication option for HTTP-based datasources
|
||||
sigv4_auth_enabled = false
|
||||
|
||||
# Set to true to enable verbose logging of SigV4 request signing
|
||||
sigv4_verbose_logging = false
|
||||
|
||||
#################################### Anonymous Auth ######################
|
||||
[auth.anonymous]
|
||||
# enable anonymous access
|
||||
@@ -491,6 +497,7 @@ allowed_groups =
|
||||
#################################### Okta OAuth #######################
|
||||
[auth.okta]
|
||||
name = Okta
|
||||
icon = okta
|
||||
enabled = false
|
||||
allow_sign_up = true
|
||||
client_id = some_id
|
||||
@@ -507,6 +514,7 @@ role_attribute_strict = false
|
||||
#################################### Generic OAuth #######################
|
||||
[auth.generic_oauth]
|
||||
name = OAuth
|
||||
icon = signin
|
||||
enabled = false
|
||||
allow_sign_up = true
|
||||
client_id = some_id
|
||||
|
||||
@@ -123,6 +123,9 @@
|
||||
# For "sqlite3" only. cache mode setting used for connecting to the database. (private, shared)
|
||||
;cache_mode = private
|
||||
|
||||
# For "mysql" only if lockingMigration feature toggle is set. How many seconds to wait before failing to lock the database for the migrations, default is 0.
|
||||
;locking_attempt_timeout_sec = 0
|
||||
|
||||
################################### Data sources #########################
|
||||
[datasources]
|
||||
# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API.
|
||||
@@ -397,6 +400,9 @@
|
||||
# Set to true to enable SigV4 authentication option for HTTP-based datasources.
|
||||
;sigv4_auth_enabled = false
|
||||
|
||||
# Set to true to enable verbose logging of SigV4 request signing
|
||||
;sigv4_verbose_logging = false
|
||||
|
||||
#################################### Anonymous Auth ######################
|
||||
[auth.anonymous]
|
||||
# enable anonymous access
|
||||
|
||||
@@ -314,6 +314,10 @@ The maximum number of open connections to the database.
|
||||
|
||||
Sets the maximum amount of time a connection may be reused. The default is 14400 (which means 14400 seconds or 4 hours). For MySQL, this setting should be shorter than the [`wait_timeout`](https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_wait_timeout) variable.
|
||||
|
||||
### locking_attempt_timeout_sec
|
||||
|
||||
For "mysql", if `lockingMigration` feature toggle is set, specify the time (in seconds) to wait before failing to lock the database for the migrations. Default is 0.
|
||||
|
||||
### log_queries
|
||||
|
||||
Set to `true` to log the sql calls and execution times.
|
||||
@@ -757,6 +761,12 @@ Limit of API key seconds to live before expiration. Default is -1 (unlimited).
|
||||
|
||||
Set to `true` to enable the AWS Signature Version 4 Authentication option for HTTP-based datasources. Default is `false`.
|
||||
|
||||
### sigv4_verbose_logging
|
||||
|
||||
> Only available in Grafana 8.4+.
|
||||
|
||||
Set to `true` to enable verbose request signature logging when AWS Signature Version 4 Authentication is enabled. Default is `false`.
|
||||
|
||||
<hr />
|
||||
|
||||
## [auth.anonymous]
|
||||
|
||||
@@ -15,10 +15,11 @@ Grafana 8.0 introduced new and improved alerting that centralizes alerting infor
|
||||
|
||||
Grafana alerting is enabled by default for new OSS installations. For older installations, it is still an [opt-in]({{< relref "./unified-alerting/opt-in.md" >}}) feature.
|
||||
|
||||
| Release | Cloud | Enterprise | OSS |
|
||||
| ----------- | ------------- | ---------- | -------------------------------- |
|
||||
| Grafana 8.2 | On by default | Opt-in | Opt-in |
|
||||
| Grafana 8.3 | On by default | Opt-in | On by default for new installs\* |
|
||||
| Release | Cloud | Enterprise | OSS |
|
||||
| ------------------------ | ------------- | ------------- | -------------------------------- |
|
||||
| Grafana 8.2 | On by default | Opt-in | Opt-in |
|
||||
| Grafana 8.3 | On by default | Opt-in | On by default for new installs\* |
|
||||
| Grafana 9.0 (unreleased) | On by default | On by default | On by default |
|
||||
|
||||
> **Note:** New installs include existing installs which do not have any alerts configured.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ weight = 114
|
||||
|
||||
Grafana alerting is enabled by default for new OSS installations. For older installations, it is still an [opt-in]({{< relref "../unified-alerting/opt-in.md" >}}) feature.
|
||||
|
||||
> **Note**: Legacy dashboard alerts is deprecated and will be removed in a future release. We encourage you to migrate to [Grafana alerting]({{< relref "../unified-alerting/_index.md" >}}) for all existing installations.
|
||||
> **Note**: Legacy dashboard alerts are deprecated and will be removed in Grafana 9. We encourage you to migrate to [Grafana alerting]({{< relref "../unified-alerting/_index.md" >}}) for all existing installations.
|
||||
|
||||
Legacy dashboard alerts have two main components:
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ Example config:
|
||||
|
||||
```bash
|
||||
[auth.generic_oauth]
|
||||
name = OAuth
|
||||
icon = signin
|
||||
enabled = true
|
||||
client_id = YOUR_APP_CLIENT_ID
|
||||
client_secret = YOUR_APP_CLIENT_SECRET
|
||||
|
||||
@@ -38,6 +38,7 @@ Before you can sign a user in, you need to create an Okta application from the O
|
||||
```ini
|
||||
[auth.okta]
|
||||
name = Okta
|
||||
icon = okta
|
||||
enabled = true
|
||||
allow_sign_up = true
|
||||
client_id = some_id
|
||||
|
||||
@@ -43,7 +43,7 @@ Each derived field consists of:
|
||||
|
||||
- **Name -** Shown in the log details as a label.
|
||||
- **Regex -** A Regex pattern that runs on the log message and captures part of it as the value of the new field. Can only contain a single capture group.
|
||||
- **URL/query -** If the link is external, then enter the full link URL. If the link is internal link, then this input serves as query for the target data source. In both cases, you can interpolate the value from the field with `${__value.raw }` macro.
|
||||
- **URL/query -** If the link is external, then enter the full link URL. If the link is internal link, then this input serves as query for the target data source. In both cases, you can interpolate the value from the field with `${__value.raw}` macro.
|
||||
- **URL Label -** (Optional) Set a custom display label for the link. The link label defaults to the full external URL or name of the linked internal data source and is overridden by this setting.
|
||||
- **Internal link -** Select if the link is internal or external. In case of internal link, a data source selector allows you to select the target data source. Only tracing data sources are supported.
|
||||
|
||||
|
||||
32
docs/sources/developers/angular_deprecation.md
Normal file
32
docs/sources/developers/angular_deprecation.md
Normal file
@@ -0,0 +1,32 @@
|
||||
+++
|
||||
title = "Angular support deprecation"
|
||||
keywords = ["grafana", "documentation", "developers", "resources"]
|
||||
+++
|
||||
|
||||
# Angular support deprecation
|
||||
|
||||
Angular plugin support is deprecated, and it will be removed in a future release. There are still many community plugins that depend on Grafana’s angular plugin support for them to work. The same is true for many internal (private) plugins developed over the years by Grafana users. Grafana version 9 will have a server configuration option, global for the whole instance, that will control if angular plugin support is available or not. By default, angular plugin support will be disabled.
|
||||
|
||||
## Why are we deprecating angular support?
|
||||
|
||||
AngularJS is an old frontend framework that stopped active development many years ago. As a result, it is a security risk. AngularJS also requires unsafe-eval in the CSP (Content Security Policy) settings which also reduces the security level of how javascript is executed in the browser.
|
||||
|
||||
## When will angular plugins stop working?
|
||||
|
||||
In Grafana version 9 coming in June 2022, all angular plugins will stop working unless a new server configuration option is turned on. If you still depend on community or internally developed plugins that require AngularJS then you will have to turn this option on.
|
||||
|
||||
This is a good time to start working on migrating plugins to React.
|
||||
|
||||
Our plan is to fully remove angular plugin support in version 10 released in 2023. Meaning all plugins that do depend on angular will stop working and this temporary option to enable it introduced in v9 will be removed.
|
||||
|
||||
## How do I migrate an angular plugin to React?
|
||||
|
||||
Depending on if it’s a data source plugin, panel plugin, or app plugin the process will differ.
|
||||
|
||||
For panels, the rendering logic could in some cases be easily preserved but all options need to be redone to use the declarative options framework. For data source plugins the query editor and config options will likely need a total rewrite.
|
||||
|
||||
### Links
|
||||
|
||||
- [Migrate Angular to React](https://grafana.com/docs/grafana/latest/developers/plugins/migration-guide/#migrate-a-plugin-from-angular-to-react)
|
||||
- [Build a panel plugin](https://grafana.com/tutorials/build-a-panel-plugin/)
|
||||
- [Build a data source plugin](https://grafana.com/tutorials/build-a-data-source-plugin/)
|
||||
@@ -80,26 +80,19 @@ For more information on the available variable formats, refer to [Advanced varia
|
||||
|
||||
## Set a variable from your plugin
|
||||
|
||||
Not only can you read the value of a variable, you can also update the variable from your plugin. Use LocationSrv.update()
|
||||
Not only can you read the value of a variable, you can also update the variable from your plugin. Use `locationService.partial(query, replace)`.
|
||||
|
||||
The following example shows how to update a variable called `service`.
|
||||
|
||||
- `query` contains the query parameters you want to update. Query parameters controlling variables are prefixed with `var-`.
|
||||
- `partial: true` makes the update only affect the query parameters listed in `query`, and leaves the other query parameters unchanged.
|
||||
- `replace: true` tells Grafana to update the current URL state, rather than creating a new history entry.
|
||||
|
||||
```ts
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
```
|
||||
|
||||
```ts
|
||||
getLocationSrv().update({
|
||||
query: {
|
||||
'var-service': 'billing',
|
||||
},
|
||||
partial: true,
|
||||
replace: true,
|
||||
});
|
||||
locationService.partial({ 'var-service': 'billing' }, true);
|
||||
```
|
||||
|
||||
> **Note:** Grafana queries your data source whenever you update a variable. Excessive updates to variables can slow down Grafana and lead to a poor user experience.
|
||||
|
||||
@@ -15,6 +15,8 @@ This guide helps you identify the steps you need to take based on the Grafana ve
|
||||
- [From version 8.3.x to 8.4.x](#from-version-83x-to-84x)
|
||||
- [Value Mapping Editor has been removed from @grafana-ui library](#value-mapping-editor-has-been-removed-from-grafana-ui-library)
|
||||
- [Thresholds Editor has been removed from @grafana-ui library](#thresholds-editor-has-been-removed-from-grafana-ui-library)
|
||||
- [8.4 Deprecations](#84-deprecations)
|
||||
- [LocationService replaces getLocationSrv](#locationservice-replaces-getlocationsrv)
|
||||
- [From version 7.x.x to 8.x.x](#from-version-7xx-to-8xx)
|
||||
- [Backend plugin v1 support has been dropped](#backend-plugin-v1-support-has-been-dropped)
|
||||
- [1. Add dependency on grafana-plugin-sdk-go](#1-add-dependency-on-grafana-plugin-sdk-go)
|
||||
@@ -48,6 +50,81 @@ Removed due to being an internal component.
|
||||
|
||||
Removed due to being an internal component.
|
||||
|
||||
### 8.4 deprecations
|
||||
|
||||
#### LocationService replaces getLocationSrv
|
||||
|
||||
In a previous release, we migrated to use a new routing system and introduced a new service for managing locations, navigation, and related information. In this release, we are making that new service the primary service.
|
||||
|
||||
**Example:** Import the service.
|
||||
|
||||
```ts
|
||||
// before
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
|
||||
// after
|
||||
import { locationService } from '@grafana/runtime';
|
||||
```
|
||||
|
||||
**Example:** Navigate to a path and add a new record in the navigation history so that you can navigate back to the previous one.
|
||||
|
||||
```ts
|
||||
// before
|
||||
getLocationSrv.update({
|
||||
path: '/route-to-navigate-to',
|
||||
replace: false,
|
||||
});
|
||||
|
||||
// after
|
||||
locationService.push('/route-to-navigate-to');
|
||||
```
|
||||
|
||||
**Example:** Navigate to a path and replace the current record in the navigation history.
|
||||
|
||||
```ts
|
||||
// before
|
||||
getLocationSrv.update({
|
||||
path: '/route-to-navigate-to',
|
||||
replace: true,
|
||||
});
|
||||
|
||||
// after
|
||||
locationService.replace('/route-to-navigate-to');
|
||||
```
|
||||
|
||||
**Example:** Update the search or query parameter for the current route and add a new record in the navigation history so that you can navigate back to the previous one.
|
||||
|
||||
```ts
|
||||
// How to navigate to a new path
|
||||
// before
|
||||
getLocationSrv.update({
|
||||
query: {
|
||||
value: 1,
|
||||
},
|
||||
partial: true,
|
||||
replace: false,
|
||||
});
|
||||
|
||||
// after
|
||||
locationService.partial({ value: 1 });
|
||||
```
|
||||
|
||||
**Example:** Update the search or query parameter for the current route and add replacing it in the navigation history.
|
||||
|
||||
```ts
|
||||
// before
|
||||
getLocationSrv.update({
|
||||
query: {
|
||||
'var-variable': 1,
|
||||
},
|
||||
partial: true,
|
||||
replace: true,
|
||||
});
|
||||
|
||||
// after
|
||||
locationService.partial({ 'var-variable': 1 }, true);
|
||||
```
|
||||
|
||||
## From version 7.x.x to 8.x.x
|
||||
|
||||
This section explains how to migrate Grafana v7.x.x plugins to the updated plugin system available in Grafana v8.x.x. Depending on your plugin, you need to perform one or more of the following steps. We have documented the breaking changes in Grafana v8.x.x and the steps you need to take to upgrade your plugin.
|
||||
|
||||
@@ -38,13 +38,14 @@ The reference information that follows complements conceptual information about
|
||||
| `fixed:organization:reader` | `orgs:read`<br>`orgs.quotas:read` | Read an organization and its quotas. |
|
||||
| `fixed:organization:writer` | All permissions from `fixed:organization:reader` and <br> `orgs:write`<br>`orgs.preferences:read`<br>`orgs.preferences:write` | Read an organization, its quotas, or its preferences. Update organization properties, or its preferences. |
|
||||
| `fixed:organization:maintainer` | All permissions from `fixed:organization:reader` and <br> `orgs:write`<br>`orgs:create`<br>`orgs:delete`<br>`orgs.quotas:write` | Create, read, write, or delete an organization. Read or write its quotas. This role needs to be assigned globally. |
|
||||
| |
|
||||
| `fixed:teams:creator` ` | `teams:create`<br>`org.users:read` | Create a team and list organization users (required to manage the created team). |
|
||||
| `fixed:teams:writer` | `teams:create`<br>`teams:delete`<br>`teams:read`<br>`teams:write`<br>`teams.permissions:read`<br>`teams.permissions:write` | Create, read, update and delete teams and manage team memberships. |
|
||||
|
||||
## Default built-in role assignments
|
||||
|
||||
| Built-in role | Associated role | Description |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Grafana Admin | `fixed:roles:reader`<br>`fixed:roles:writer`<br>`fixed:users:reader`<br>`fixed:users:writer`<br>`fixed:org.users:reader`<br>`fixed:org.users:writer`<br>`fixed:ldap:reader`<br>`fixed:ldap:writer`<br>`fixed:stats:reader`<br>`fixed:settings:reader`<br>`fixed:settings:writer`<br>`fixed:provisioning:writer`<br>`fixed:organization:reader`<br>`fixed:organization:maintainer`<br>`fixed:licensing:reader`<br>`fixed:licensing:writer` | Default [Grafana server administrator]({{< relref "../../permissions/_index.md#grafana-server-admin-role" >}}) assignments. |
|
||||
| Admin | `fixed:reports:reader`<br>`fixed:reports:writer`<br>`fixed:datasources:reader`<br>`fixed:datasources:writer`<br>`fixed:organization:writer`<br>`fixed:datasources.permissions:reader`<br>`fixed:datasources.permissions:writer`<br> | Default [Grafana organization administrator]({{< relref "../../permissions/organization_roles.md" >}}) assignments. |
|
||||
| Editor | `fixed:datasources:explorer` | Default [Editor]({{< relref "../../permissions/organization_roles.md" >}}) assignments. |
|
||||
| Admin | `fixed:reports:reader`<br>`fixed:reports:writer`<br>`fixed:datasources:reader`<br>`fixed:datasources:writer`<br>`fixed:organization:writer`<br>`fixed:datasources.permissions:reader`<br>`fixed:datasources.permissions:writer`<br>`fixed:teams:writer`<br> | Default [Grafana organization administrator]({{< relref "../../permissions/organization_roles.md" >}}) assignments. |
|
||||
| Editor | `fixed:datasources:explorer` and <br> `fixed:teams:creator` if the `editors_can_admin` configuration flag is enabled | Default [Editor]({{< relref "../../permissions/organization_roles.md" >}}) assignments. |
|
||||
| Viewer | `fixed:datasources:id:reader`<br>`fixed:organization:reader` | Default [Viewer]({{< relref "../../permissions/organization_roles.md" >}}) assignments. |
|
||||
|
||||
@@ -91,6 +91,12 @@ The following list contains fine-grained access control actions.
|
||||
| `licensing:update` | n/a | Update the license token. |
|
||||
| `licensing:delete` | n/a | Delete the license token. |
|
||||
| `licensing.reports:read` | n/a | Get custom permission reports. |
|
||||
| `teams:create` | n/a | Create teams. |
|
||||
| `teams:read` | `teams:*`<br>`teams:id:*` | Read one or more teams and team preferences. |
|
||||
| `teams:write` | `teams:*`<br>`teams:id:*` | Update one or more teams and team preferences. |
|
||||
| `teams:delete` | `teams:*`<br>`teams:id:*` | Delete one or more teams. |
|
||||
| `teams.permissions:read` | `teams:*`<br>`teams:id:*` | Read members and External Group Synchronization setup for teams. |
|
||||
| `teams.permissions:write` | `teams:*`<br>`teams:id:*` | Add, remove and update members and manage External Group Synchronization setup for teams. |
|
||||
|
||||
## Scope definitions
|
||||
|
||||
|
||||
@@ -501,9 +501,3 @@ The org id of the datasource where the query data will be written.
|
||||
|
||||
If all `default_remote_write_*` properties are set, this information will be populated at startup. If a remote write target has
|
||||
already been configured, nothing will happen.
|
||||
|
||||
## [feature_highlights]
|
||||
|
||||
### enabled
|
||||
|
||||
Whether the feature highlights feature is enabled
|
||||
|
||||
@@ -23,13 +23,15 @@ During an infrastructure monitoring and incident response, you can dig deeper in
|
||||
|
||||
Results of log queries are shown as histograms in the graph and individual logs are explained in the following sections.
|
||||
|
||||
If the data source supports a full range log volume histogram, the graph with log distribution for all entered log queries is shown automatically. This feature is currently supported by Elasticsearch data source.
|
||||
If the data source supports a full range log volume histogram, the graph with log distribution for all entered log queries is shown automatically. This feature is currently supported by Elasticsearch and Loki data sources.
|
||||
|
||||
If the data source does not support loading full range log volume histogram, the logs model computes a time series based on the log row counts bucketed by an automatically calculated time interval, and the first log row's timestamp then anchors the start of the histogram from the result. The end of the time series is anchored to the time picker's **To** range.
|
||||
|
||||
#### Log level
|
||||
|
||||
For logs where a level label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to parse the log using logfmt and JSON parsers to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with an unknown log level.
|
||||
For logs where a level label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with an unknown log level.
|
||||
|
||||
> **Tip:** If you use Loki data source and the "level" is in you log content, try to use parsers (JSON, logfmt, regex,..) to extract level information into level label that is used to determine log level.
|
||||
|
||||
**Supported log levels and mapping of log level abbreviation and expressions:**
|
||||
|
||||
|
||||
@@ -433,9 +433,10 @@ Accept: application/json
|
||||
```
|
||||
|
||||
#### JSON body schema
|
||||
| Field Name | Data Type | Required | Description |
|
||||
| ---------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| roleUid | string | Yes | UID of the role. |
|
||||
|
||||
| Field Name | Data Type | Required | Description |
|
||||
| ---------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| roleUid | string | Yes | UID of the role. |
|
||||
| global | boolean | No | A flag indicating if the assignment is global or not. If set to `false`, the default org ID of the authenticated user will be used from the request to create organization local assignment. |
|
||||
|
||||
#### Example response
|
||||
|
||||
@@ -9,10 +9,21 @@ aliases = ["/docs/grafana/latest/http_api/external_group_sync/"]
|
||||
|
||||
> External Group Synchronization is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "../enterprise" >}}).
|
||||
|
||||
> If you have [Fine-grained access control]({{< relref "../enterprise/access-control/_index.md" >}}) enabled, access to endpoints will be controlled by Fine-grained access control permissions.
|
||||
> Refer to specific endpoints to understand what permissions are required.
|
||||
|
||||
## Get External Groups
|
||||
|
||||
`GET /api/teams/:teamId/groups`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ---------------------- | -------- |
|
||||
| teams.permissions:read | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
@@ -47,6 +58,14 @@ Status Codes:
|
||||
| Action | Scope |
|
||||
| ----------------------- | -------- |
|
||||
| teams.permissions:write | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
POST /api/teams/1/members HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
|
||||
```
|
||||
|
||||
@@ -81,6 +100,14 @@ Status Codes:
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
DELETE /api/teams/1/groups/cn=editors,ou=groups,dc=grafana,dc=org HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
@@ -269,8 +269,8 @@ Creates a new library element.
|
||||
|
||||
JSON Body schema:
|
||||
|
||||
- **folderId** – ID of the folder where the library element is stored.
|
||||
- **name** – Name of the library element.
|
||||
- **folderId** – Optional, the ID of the folder where the library element is stored.
|
||||
- **name** – Optional, the name of the library element.
|
||||
- **model** – The JSON model for the library element.
|
||||
- **kind** – Kind of element to create, Use `1` for library panels or `2` for library variables.
|
||||
- **uid** – Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
|
||||
|
||||
@@ -7,7 +7,17 @@ aliases = ["/docs/grafana/latest/http_api/team/"]
|
||||
|
||||
# Team API
|
||||
|
||||
This API can be used to create/update/delete Teams and to add/remove users to Teams. All actions require that the user has the Admin role for the organization.
|
||||
This API can be used to manage Teams and Team Memberships.
|
||||
|
||||
Access to these API endpoints is restricted as follows:
|
||||
|
||||
- All authenticated users are able to view details of teams they are a member of.
|
||||
- Organization Admins are able to manage all teams and team members.
|
||||
- If you enable `editors_can_admin` configuration flag, then Organization Editors can create teams and manage teams where they are Admin.
|
||||
- If you enable `editors_can_admin` configuration flag, Editors can find out whether a team that they are not members of exists by trying to create a team with the same name.
|
||||
|
||||
> If you are running Grafana Enterprise and have [Fine-grained access control]({{< relref "../enterprise/access-control/_index.md" >}}) enabled, access to endpoints will be controlled by Fine-grained access control permissions.
|
||||
> Refer to specific endpoints to understand what permissions are required.
|
||||
|
||||
## Team Search With Paging
|
||||
|
||||
@@ -17,25 +27,23 @@ or
|
||||
|
||||
`GET /api/teams/search?name=myteam`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ---------- | -------- |
|
||||
| teams:read | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
GET /api/teams/search?perpage=10&page=1&query=myteam HTTP/1.1
|
||||
GET /api/teams/search?perpage=10&page=1&query=mytestteam HTTP/1.1
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
### Using the query parameter
|
||||
|
||||
Default value for the `perpage` parameter is `1000` and for the `page` parameter is `1`.
|
||||
|
||||
The `totalCount` field in the response can be used for pagination of the teams list E.g. if `totalCount` is equal to 100 teams and the `perpage` parameter is set to 10 then there are 10 pages of teams.
|
||||
|
||||
The `query` parameter is optional and it will return results where the query value is contained in the `name` field. Query values with spaces need to be URL encoded e.g. `query=my%20team`.
|
||||
|
||||
### Using the name parameter
|
||||
|
||||
The `name` parameter returns a single team if the parameter matches the `name` field.
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
@@ -59,7 +67,19 @@ Content-Type: application/json
|
||||
#### Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
Accept: application/json
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found (if searching by name)
|
||||
|
||||
## Get Team By Id
|
||||
|
||||
`GET /api/teams/:id`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ---------- | -------- |
|
||||
| teams:read | teams:\* |
|
||||
|
||||
@@ -70,6 +90,14 @@ Status Codes:
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
@@ -108,6 +136,14 @@ The Team `name` needs to be unique. `name` is required and `email`,`orgId` is op
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **409** - Team name is taken
|
||||
|
||||
## Update Team
|
||||
@@ -145,6 +181,14 @@ There are two fields that can be updated for a team: `name` and `email`.
|
||||
Status Codes:
|
||||
|
||||
- **200** - Ok
|
||||
- **401** - Unauthorized
|
||||
- **403** - Permission denied
|
||||
- **404** - Team not found
|
||||
- **409** - Team name is taken
|
||||
|
||||
## Delete Team By Id
|
||||
|
||||
`DELETE /api/teams/:id`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
@@ -180,6 +224,14 @@ Status Codes:
|
||||
|
||||
## Get Team Members
|
||||
|
||||
`GET /api/teams/:teamId/members`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ---------------------- | -------- |
|
||||
| teams.permissions:read | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
@@ -209,6 +261,14 @@ Status Codes:
|
||||
|
||||
`POST /api/teams/:teamId/members`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ----------------------- | -------- |
|
||||
| teams.permissions:write | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
@@ -254,6 +314,14 @@ Status Codes:
|
||||
Accept: application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Basic YWRtaW46YWRtaW4=
|
||||
```
|
||||
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
@@ -288,6 +356,14 @@ Status Codes:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: application/json
|
||||
|
||||
```
|
||||
|
||||
## Update Team Preferences
|
||||
|
||||
`PUT /api/teams/:teamId/preferences`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
@@ -317,6 +393,14 @@ Status Codes:
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
|
||||
```
|
||||
| Action | Scope |
|
||||
| ---------- | -------- |
|
||||
| teams:read | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
@@ -343,6 +427,14 @@ Content-Type: application/json
|
||||
|
||||
`PUT /api/teams/:teamId/preferences`
|
||||
|
||||
#### Required permissions
|
||||
|
||||
See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
|
||||
|
||||
| Action | Scope |
|
||||
| ----------- | -------- |
|
||||
| teams:write | teams:\* |
|
||||
|
||||
**Example Request**:
|
||||
|
||||
```http
|
||||
|
||||
@@ -8,6 +8,8 @@ weight = 10000
|
||||
Here you can find detailed release notes that list everything that is included in every release as well as notices
|
||||
about deprecations, breaking changes as well as changes that relate to plugin development.
|
||||
|
||||
- [Release notes for 8.4.0-beta1]({{< relref "release-notes-8-4-0-beta1" >}})
|
||||
- [Release notes for 8.3.5]({{< relref "release-notes-8-3-5" >}})
|
||||
- [Release notes for 8.3.4]({{< relref "release-notes-8-3-4" >}})
|
||||
- [Release notes for 8.3.3]({{< relref "release-notes-8-3-3" >}})
|
||||
- [Release notes for 8.3.2]({{< relref "release-notes-8-3-2" >}})
|
||||
@@ -48,6 +50,7 @@ about deprecations, breaking changes as well as changes that relate to plugin de
|
||||
- [Release notes for 8.0.0-beta3]({{< relref "release-notes-8-0-0-beta3" >}})
|
||||
- [Release notes for 8.0.0-beta2]({{< relref "release-notes-8-0-0-beta2" >}})
|
||||
- [Release notes for 8.0.0-beta1]({{< relref "release-notes-8-0-0-beta1" >}})
|
||||
- [Release notes for 7.5.15]({{< relref "release-notes-7-5-15" >}})
|
||||
- [Release notes for 7.5.13]({{< relref "release-notes-7-5-13" >}})
|
||||
- [Release notes for 7.5.12]({{< relref "release-notes-7-5-12" >}})
|
||||
- [Release notes for 7.5.11]({{< relref "release-notes-7-5-11" >}})
|
||||
|
||||
11
docs/sources/release-notes/release-notes-7-5-15.md
Normal file
11
docs/sources/release-notes/release-notes-7-5-15.md
Normal file
@@ -0,0 +1,11 @@
|
||||
+++
|
||||
title = "Release notes for Grafana 7.5.15"
|
||||
[_build]
|
||||
list = false
|
||||
+++
|
||||
|
||||
# Release notes for Grafana 7.5.15
|
||||
|
||||
- **Security**: Fixes CVE-2022-21702. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21703. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21713. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
11
docs/sources/release-notes/release-notes-8-3-5.md
Normal file
11
docs/sources/release-notes/release-notes-8-3-5.md
Normal file
@@ -0,0 +1,11 @@
|
||||
+++
|
||||
title = "Release notes for Grafana 8.3.5"
|
||||
[_build]
|
||||
list = false
|
||||
+++
|
||||
|
||||
# Release notes for Grafana 8.3.5
|
||||
|
||||
- **Security**: Fixes CVE-2022-21702. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21703. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
- **Security**: Fixes CVE-2022-21713. For more information, see our [blog](https://grafana.com/blog/2022/02/08/grafana-7.5.15-and-8.3.5-released-with-moderate-severity-security-fixes/)
|
||||
23
docs/sources/release-notes/release-notes-8-4-0-beta1.md
Normal file
23
docs/sources/release-notes/release-notes-8-4-0-beta1.md
Normal file
@@ -0,0 +1,23 @@
|
||||
+++
|
||||
title = "Release notes for Grafana 8.4.0-beta1"
|
||||
hide_menu = true
|
||||
+++
|
||||
|
||||
<!-- Auto generated by update changelog github action -->
|
||||
|
||||
# Release notes for Grafana 8.4.0-beta1
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Alerting:** Support WeCom as a contact point type. [#40975](https://github.com/grafana/grafana/pull/40975), [@smallpath](https://github.com/smallpath)
|
||||
- **Alerting:** UI for mute timings. [#41578](https://github.com/grafana/grafana/pull/41578), [@nathanrodman](https://github.com/nathanrodman)
|
||||
- **Alerting:** add settings for peer reconnection in HA mode. [#42300](https://github.com/grafana/grafana/pull/42300), [@JohnnyQQQQ](https://github.com/JohnnyQQQQ)
|
||||
- **Auth:** implement auto_sign_up for auth.jwt. [#37040](https://github.com/grafana/grafana/pull/37040), [@Roguelazer](https://github.com/Roguelazer)
|
||||
- **Dashboard:** Add Show unknown variables toggle to dashboard settings. [#41854](https://github.com/grafana/grafana/pull/41854), [@hugohaggmark](https://github.com/hugohaggmark)
|
||||
- **Instrumentation:** Logger migration from log15 to gokit/log. [#41636](https://github.com/grafana/grafana/pull/41636), [@ying-jeanne](https://github.com/ying-jeanne)
|
||||
- **MSSQL:** Change regex to validate Provider connection string. [#40248](https://github.com/grafana/grafana/pull/40248), [@ianselmi](https://github.com/ianselmi)
|
||||
- **MSSQL:** Configuration of certificate verification for TLS connection. [#31865](https://github.com/grafana/grafana/pull/31865), [@mortenaa](https://github.com/mortenaa)
|
||||
- **Middleware:** Don't require HTTPS for HSTS headers to be emitted. [#35147](https://github.com/grafana/grafana/pull/35147), [@alexmv](https://github.com/alexmv)
|
||||
- **Navigation:** Implement Keyboard Navigation. [#41618](https://github.com/grafana/grafana/pull/41618), [@axelavargas](https://github.com/axelavargas)
|
||||
- **News:** Reload feed when changing the time range or refreshing. [#42217](https://github.com/grafana/grafana/pull/42217), [@ashharrison90](https://github.com/ashharrison90)
|
||||
- **UI/Plot:** Implement keyboard controls for plot cursor. [#42244](https://github.com/grafana/grafana/pull/42244), [@kaydelaney](https://github.com/kaydelaney)
|
||||
58
docs/sources/release-notes/release-notes-8-4-0.md
Normal file
58
docs/sources/release-notes/release-notes-8-4-0.md
Normal file
@@ -0,0 +1,58 @@
|
||||
+++
|
||||
title = "Release notes for Grafana 8.4.0"
|
||||
hide_menu = true
|
||||
+++
|
||||
|
||||
<!-- Auto generated by update changelog github action -->
|
||||
|
||||
# Release notes for Grafana 8.4.0
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **API:** Extract OpenAPI specification from source code using go-swagger. [#40528](https://github.com/grafana/grafana/pull/40528), [@papagian](https://github.com/papagian)
|
||||
- **AccessControl:** Disable user remove and user update roles when they do not have the permissions. [#43429](https://github.com/grafana/grafana/pull/43429), [@Jguer](https://github.com/Jguer)
|
||||
- **AccessControl:** Provisioning for teams. [#43767](https://github.com/grafana/grafana/pull/43767), [@gamab](https://github.com/gamab)
|
||||
- **API:** Add usage stats preview endpoint. [#43899](https://github.com/grafana/grafana/pull/43899), [@Jguer](https://github.com/Jguer)
|
||||
- **Alerting:** Move slow queries in the scheduler to another goroutine. [#44423](https://github.com/grafana/grafana/pull/44423), [@grobinson-grafana](https://github.com/grobinson-grafana)
|
||||
- **Alerting:** Use time.Ticker instead of alerting.Ticker in ngalert. [#44395](https://github.com/grafana/grafana/pull/44395), [@grobinson-grafana](https://github.com/grobinson-grafana)
|
||||
- **Alerting:** add custom grouping to Alert Panel. [#44559](https://github.com/grafana/grafana/pull/44559), [@gillesdemey](https://github.com/gillesdemey)
|
||||
- **Analytics:** Add user id tracking to google analytics. [#42763](https://github.com/grafana/grafana/pull/42763), [@autoric](https://github.com/autoric)
|
||||
- **Angular:** Add AngularJS plugin support deprecation plan to docs site. [#45149](https://github.com/grafana/grafana/pull/45149), [@torkelo](https://github.com/torkelo)
|
||||
- **Auth:** implement auto_sign_up for auth.jwt. [#43502](https://github.com/grafana/grafana/pull/43502), [@sakjur](https://github.com/sakjur)
|
||||
- **Azure Monitor Logs:** Order subscriptions in resource picker by name. [#45228](https://github.com/grafana/grafana/pull/45228), [@sunker](https://github.com/sunker)
|
||||
- **Azure monitor Logs:** Optimize data fetching in resource picker. [#44549](https://github.com/grafana/grafana/pull/44549), [@sunker](https://github.com/sunker)
|
||||
- **AzureMonitor:** Filter list of resources by resourceType. [#43522](https://github.com/grafana/grafana/pull/43522), [@andresmgot](https://github.com/andresmgot)
|
||||
- **BarChart:** color by field, x time field, bar radius, label skipping. [#43257](https://github.com/grafana/grafana/pull/43257), [@leeoniya](https://github.com/leeoniya)
|
||||
- **Chore:** Implement OpenTelemetry in Grafana. [#42674](https://github.com/grafana/grafana/pull/42674), [@idafurjes](https://github.com/idafurjes)
|
||||
- **Cloud Monitoring:** Adds metric type to Metric drop down options. [#43268](https://github.com/grafana/grafana/pull/43268), [@tw1nk](https://github.com/tw1nk)
|
||||
- **CloudWatch:** Add Data Lifecycle Manager metrics and dimension. [#43310](https://github.com/grafana/grafana/pull/43310), [@ilyastoli](https://github.com/ilyastoli)
|
||||
- **CloudWatch:** Add Missing Elasticache Host-level metrics. [#43455](https://github.com/grafana/grafana/pull/43455), [@dhendo](https://github.com/dhendo)
|
||||
- **CloudWatch:** Add all ElastiCache Redis Metrics. [#43336](https://github.com/grafana/grafana/pull/43336), [@siavashs](https://github.com/siavashs)
|
||||
- **CloudWatch:** Add new AWS/ES metrics. [#43034](https://github.com/grafana/grafana/pull/43034), [@sunker](https://github.com/sunker)
|
||||
- **Cloudwatch:** Add syntax highlighting and autocomplete for "Metric Search". [#43985](https://github.com/grafana/grafana/pull/43985), [@sarahzinger](https://github.com/sarahzinger)
|
||||
- **Explore:** Support custom display label for exemplar links for Prometheus datasource. [#42732](https://github.com/grafana/grafana/pull/42732), [@JokerQueue](https://github.com/JokerQueue)
|
||||
- **Hotkeys:** Make time range absolute/permanent. [#43802](https://github.com/grafana/grafana/pull/43802), [@davkal](https://github.com/davkal)
|
||||
- **Playlists:** Enable sharing direct links to playlists. [#44161](https://github.com/grafana/grafana/pull/44161), [@ashharrison90](https://github.com/ashharrison90)
|
||||
- **SQLStore:** Prevent concurrent migrations. [#44101](https://github.com/grafana/grafana/pull/44101), [@papagian](https://github.com/papagian)
|
||||
- **SSE:** Add Mode to drop NaN/Inf/Null in Reduction operations. [#43583](https://github.com/grafana/grafana/pull/43583), [@kylebrandt](https://github.com/kylebrandt)
|
||||
- **Setting:** Support configuring feature toggles with bools instead of just passing an array. [#43326](https://github.com/grafana/grafana/pull/43326), [@bergquist](https://github.com/bergquist)
|
||||
- **TimeSeries:** Add support for negative Y and constant transform. [#44774](https://github.com/grafana/grafana/pull/44774), [@dprokop](https://github.com/dprokop)
|
||||
- **Transformations:** Add 'JSON' field type to ConvertFieldTypeTransformer. [#42624](https://github.com/grafana/grafana/pull/42624), [@sd2k](https://github.com/sd2k)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Auth:** Guarantee consistency of signed SigV4 headers. [#45054](https://github.com/grafana/grafana/pull/45054), [@wbrowne](https://github.com/wbrowne)
|
||||
- **CloudWatch:** Fix MetricName resetting on Namespace change. [#44165](https://github.com/grafana/grafana/pull/44165), [@yaelleC](https://github.com/yaelleC)
|
||||
- **Cloudwatch :** Fixed resetting metric name when changing namespace in Metric Query. [#44612](https://github.com/grafana/grafana/pull/44612), [@yaelleC](https://github.com/yaelleC)
|
||||
- **Explore:** Avoid locking timepicker when range is inverted. [#44790](https://github.com/grafana/grafana/pull/44790), [@Elfo404](https://github.com/Elfo404)
|
||||
- **Instrumentation:** Fix HTTP request instrumentation of authentication failures. [#44234](https://github.com/grafana/grafana/pull/44234), [@marefr](https://github.com/marefr)
|
||||
- **LibraryPanels:** Prevent long descriptions and names from obscuring the delete button. [#45190](https://github.com/grafana/grafana/pull/45190), [@zuchka](https://github.com/zuchka)
|
||||
- **OAuth:** Fix parsing of ID token if header contains non-string value. [#44159](https://github.com/grafana/grafana/pull/44159), [@marefr](https://github.com/marefr)
|
||||
- **Panel Edit:** Visualization search now works correctly with special characters. [#45137](https://github.com/grafana/grafana/pull/45137), [@ashharrison90](https://github.com/ashharrison90)
|
||||
- **Provisioning:** Fix duplicate validation when multiple organizations have been configured. [#44151](https://github.com/grafana/grafana/pull/44151), [@marefr](https://github.com/marefr)
|
||||
- **QueryField:** Fix issue with undo history when suggestion is inserted (#28656). [#39114](https://github.com/grafana/grafana/pull/39114), [@glintik](https://github.com/glintik)
|
||||
- **TablePanel:** Do not prefix columns with frame name if multiple frames and override active. [#45174](https://github.com/grafana/grafana/pull/45174), [@mdvictor](https://github.com/mdvictor)
|
||||
|
||||
### Deprecations
|
||||
|
||||
AngularJS plugin support is now in a deprecated state, meaning it will be removed in a future release. Currently, that is planned for version 10 (in 2023). The documentation site has an [article](https://grafana.com/docs/grafana/next/developers/angular_deprecation/) with more details on why, when, and how. Issue [#45149](https://github.com/grafana/grafana/issues/45149)
|
||||
@@ -70,7 +70,7 @@ The markers layer allows you to display data points as different marker shapes s
|
||||
|
||||

|
||||
|
||||
- **Marker Color** configures the color of the marker. The default `Fixed size` keeps all points a single color. There is an alternate option to have multiple colors depending on the data point values and the threshold set at the `Thresholds` section.
|
||||
- **Marker Color** configures the color of the marker. The default `Single color` keeps all points a single color. There is an alternate option to have multiple colors depending on the data point values and the threshold set at the `Thresholds` section.
|
||||
- **Marker Size** configures the size of the marker. Default is `Fixed size`, making all marker size the same regardless of the data points. However, there is also an option to scale the circles to the corresponding data points. `Min` and `Max` marker size has to be set such that the Marker layer can scale within this range.
|
||||
- **Marker Shape** allows you to choose the shape, icon, or graphic to aid in providing additional visual context to your data. Choose from assets that are included with Grafana such as simple shapes or the Unicon library. You can also specify a URL containing an image asset. The image must be a scalable vector graphic (SVG).
|
||||
- **Fill opacity** configures the transparency of each marker.
|
||||
|
||||
@@ -17,7 +17,7 @@ To limit the number of lines rendered, you can use the **Max data points** setti
|
||||
|
||||
## Log level
|
||||
|
||||
For logs where a **level** label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we parse the log to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with **unknown** log level. See [supported log levels and mappings of log level abbreviation and expressions]({{< relref "../explore/_index.md#log-level" >}}).
|
||||
For logs where a **level** label is specified, we use the value of the label to determine the log level and update color accordingly. If the log doesn't have a level label specified, we try to find out if its content matches any of the supported expressions (see below for more information). The log level is always determined by the first match. In case Grafana is not able to determine a log level, it will be visualized with **unknown** log level. See [supported log levels and mappings of log level abbreviation and expressions]({{< relref "../explore/_index.md#log-level" >}}).
|
||||
|
||||
## Log details
|
||||
|
||||
|
||||
@@ -35,6 +35,15 @@ Use these options to choose how to display your time series data.
|
||||
- [Graph stacked time series]({{< relref "./graph-time-series-stacking.md" >}})
|
||||
- [Graph and color schemes]({{< relref "./graph-color-scheme.md" >}})
|
||||
|
||||
### Transform
|
||||
|
||||
Use this option to transform the series values without affecting the values shown in the tooltip, context menu, and legend.
|
||||
|
||||
- **Negative Y transform -** Flip the results to negative values on the Y axis.
|
||||
- **Constant -** Show first value as a constant line.
|
||||
|
||||
> **Note:** Transform option is only available as an override.
|
||||
|
||||
## Axis
|
||||
|
||||
For more information about adjusting your time series axes, refer to [Change axis display]({{< relref "change-axis-display.md" >}}).
|
||||
|
||||
@@ -11,6 +11,7 @@ as info on deprecations, breaking changes and plugin development read the [relea
|
||||
|
||||
## Grafana 8
|
||||
|
||||
- [What's new in 8.4]({{< relref "whats-new-in-v8-4" >}})
|
||||
- [What's new in 8.3]({{< relref "whats-new-in-v8-3" >}})
|
||||
- [What's new in 8.2]({{< relref "whats-new-in-v8-2" >}})
|
||||
- [What's new in 8.1]({{< relref "whats-new-in-v8-1" >}})
|
||||
|
||||
144
docs/sources/whatsnew/whats-new-in-v8-4.md
Normal file
144
docs/sources/whatsnew/whats-new-in-v8-4.md
Normal file
@@ -0,0 +1,144 @@
|
||||
+++
|
||||
title = "What's new in Grafana v8.4"
|
||||
description = "Feature and improvement highlights for Grafana v8.4"
|
||||
keywords = ["grafana", "new", "documentation", "8.4", "release notes"]
|
||||
weight = -33
|
||||
aliases = ["/docs/grafana/latest/guides/whats-new-in-v8-4/"]
|
||||
[_build]
|
||||
list = false
|
||||
+++
|
||||
|
||||
# What’s new in Grafana v8.4
|
||||
|
||||
We’re excited to announce Grafana v8.4, with a variety of improvements that focus on Grafana’s usability, performance, and security. Read on to learn about Alerting enhancements like a WeCom contact point, improved Alert panel and custom mute timings, as well as visualization improvements and details to help you share playlists more easily. In Grafana Enterprise, we’ve made caching more powerful to save you time and money while loading dashboards, boosted database encryption to keep secrets safe in your Grafana database, and made usability improvements to Recorded Queries, which allow you to track any data point over time.
|
||||
|
||||
We’ve summarized what’s new in the release here, but you might also be interested in the announcement blog post. If you’d like all the details you can check out the complete [changelog](https://github.com/grafana/grafana/blob/master/CHANGELOG.md).
|
||||
|
||||
# OSS
|
||||
|
||||
## Ease of use
|
||||
|
||||
### Share playlists
|
||||
|
||||
You can now share links to your playlists the same way as with dashboards, to easily set up the same playlist on multiple devices or kiosks.
|
||||
|
||||
{{< figure src="/static/img/docs/dashboards/share-playlists-8-4.png" max-width="1200px" caption="Share playlist" >}}
|
||||
|
||||
### `$__interval` and `$__interval_ms` in panel title
|
||||
|
||||
We’ve expanded the functionality of this existing and popular feature. You can now use `$__interval` and `$__interval_ms` in panel titles. This new function displays the interval that’s used in a specific panel without requiring edit mode.
|
||||
|
||||
{{< figure src="/static/img/docs/panels/interval-8-4.png" max-width="1200px" caption="Time intervals" >}}
|
||||
|
||||
### Accessibility improvements
|
||||
|
||||
We’re continuing to improve accessibility across Grafana, particularly focusing on keyboard navigation and screen readers.
|
||||
|
||||
- Navigation: We’ve improved our keyboard navigation support in our main navbar, added focus states, and removed keyboard traps.
|
||||
- General components (tooltips, color pickers, modals, dropdowns, and so forth): we’ve ensured they’re keyboard navigable, improved focus trapping, and improved screen reader support.
|
||||
- Time series panel: charts are one of our main areas of limited accessibility. As of 8.4, you can also move a panel and make range selections using your keyboard. - Press arrow keys to move the cursor around. - Hold Shift to increase cursor speed. - Hold space to start rage selection.
|
||||
You can read our accessibility statement [here](https://grafana.com/accessibility/) and reach out to us with accessibility issues using our community Slack or our community forums.
|
||||
|
||||
### New option to configure OpenTelemetry
|
||||
|
||||
Grafana is used to visualize traces and metrics, but Grafana itself can be traced as well. For example, users running a Grafana instance can export all the traces of endpoints and database requests to Jaeger, which helps you view all Grafana traffic.
|
||||
|
||||
We’re currently using OpenTracing for this, but since the repository is being deprecated, we’ve started our work to migrate to OpenTelemetry and remove OpenTracing. This release is the first step toward this goal. It also adds the option to configure OpenTelemetry instead of OpenTracing.
|
||||
|
||||
### Rotate your encryption key
|
||||
|
||||
In Grafana 8.3, we upgraded Grafana to use envelope encryption, which adds a layer of indirection to the encryption process. Instead of encrypting all secrets in the database with a single key, Grafana uses a set of keys, called data encryption keys (DEKs), to encrypt them. These data encryption keys are themselves encrypted with a single key-encryption key (KEK).
|
||||
|
||||
As of 8.4, you can rotate your KEK and quickly re-encrypt your DEKs in case a key is compromised.
|
||||
|
||||
Envelope encryption is not enabled by default in version 8.4. You can enable it by adding the term `envelopeEncryption` to the list of feature toggles in your [Grafana configuration](https://grafana.com/docs/grafana/next/administration/configuration/#feature_toggles?mdm=email), or by sending a request to support if you use Grafana Cloud.
|
||||
|
||||
{{< figure src="/static/img/docs/encryption/rotate-encryption-8-4.png" max-width="1200px" caption="Rotate encryption" >}}
|
||||
|
||||
## Alerting
|
||||
|
||||
### Support for mute timings
|
||||
|
||||
[Mute timings](https://grafana.com/docs/grafana/next/alerting/unified-alerting/notifications/mute-timings/) have been a popular request from the community. They are a powerful addition to the new alerting feature set and allow you to suppress specific alerts on a recurring interval or schedule, [contrary to](https://grafana.com/docs/grafana/next/alerting/unified-alerting/notifications/mute-timings/#mute-timings-vs-silences) Silences.
|
||||
|
||||
Paired with the existing Silences, this gives you even more control over when alerts should be sent and contact points notified.
|
||||
|
||||
### Custom grouping for the Alert Panel
|
||||
|
||||
The new Alert Panel displays your alerts and associated alert instances, and supports grouping by one or more custom labels. You can also display all alert instances in an ungrouped list by choosing the custom grouping mode without any configured labels.
|
||||
|
||||
Traditionally alerts in the Alert Panel were grouped by the alert rule that created them. When you are monitoring a complex resource like an industrial pump, you typically have multiple alerts defined for that resource to observe different metrics. The new custom grouping feature allows you to view all alert instances for individual resource by specifying a label such as “pump identifier”.
|
||||
|
||||
{{< figure src="/static/img/docs/alerting/unified/custom-grouping-8-4.png" max-width="1200px" caption="Custom grouping in alerting" >}}
|
||||
|
||||
### WeCom contact point
|
||||
|
||||
Starting with Grafana 8.4, you can [configure a WeCom](https://grafana.com/docs/grafana/next/alerting/unified-alerting/contact-points/#wecom) contact point, to send alert notifications to WeCom.
|
||||
|
||||
## New panel options
|
||||
|
||||
### Bar chart
|
||||
|
||||
We’ve expanded the bar chart so that you can:
|
||||
|
||||
- Use time for the x-axis.
|
||||
- Color bars using a field property (that is, build success).
|
||||
- Use labels effectively:
|
||||
- Skip values when there are too many labels.
|
||||
- Rotate labels.
|
||||
|
||||
{{< figure src="/static/img/docs/bar-chart-panel/bar-chart-8-4.png" max-width="1200px" caption="Updated bar chart" >}}
|
||||
|
||||
### Geomap
|
||||
|
||||
Geomap now supports tooltips with data-links across multiple layers.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-tooltips-multiple-layers-8-4.png" max-width="1200px" caption="Assign SAML users role" >}}
|
||||
|
||||
## OpenAPI v2 specification
|
||||
|
||||
The HTTP API details are now [specified](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/papagian/api-spec/public/api-merged.json) using OpenAPI v2.
|
||||
|
||||
The grafana server serves a [SwaggerUI](https://swagger.io/tools/swagger-ui/) editor via the /swagger-ui endpoint that enables users to make requests to the HTTP API via the browser. This is disabled by default and it’s enabled when the `swaggerUi` feature toggle is set.
|
||||
|
||||
# Grafana Enterprise
|
||||
|
||||
## Security improvements
|
||||
|
||||
### Fine-grained access control works for teams
|
||||
|
||||
Occasionally, Viewer, Editor, and Admin roles don’t fit what a certain user needs to do in Grafana. Now you can assign fine-grained roles directly to users so they can create reports, use Explore mode, create data sources, and perform other specific actions in Grafana. Fine-grained access control is currently in beta.
|
||||
|
||||
In Grafana 8.4, you can assign roles to teams, which apply to all members of that team. This is a convenient way to grant certain permissions to a group of users all at once. It also makes permissions easier to manage when you synchronize groups from an SSO provider, like Google Oauth or Okta, to teams in Grafana.
|
||||
|
||||
In 8.4 you can also control access to Team and API key functionality itself, like viewing or editing API keys and adding members to certain teams.
|
||||
|
||||
Enable fine-grained access control by adding the term `accesscontrol` to the list of feature toggles in your [Grafana configuration](https://grafana.com/docs/grafana/next/administration/configuration/#feature_toggles?mdm=email), or by sending a request to support if you use Grafana Cloud. Learn more about fine-grained access control in the [fine-grained access control section of the docs](https://grafana.com/docs/grafana/next/enterprise/access-control/).
|
||||
|
||||
{{< figure src="/static/img/docs/enterprise/8-4-fine-grain-access-control.png" max-width="1200px" caption="Assign SAML users role" >}}
|
||||
|
||||
### Assign SAML users different roles in different Organizations
|
||||
|
||||
You can use Grafana’s SAML integration to map organizations in your SAML service to [Organizations](https://grafana.com/docs/grafana/latest/manage-users/server-admin/server-admin-manage-orgs/) in Grafana so that users who authenticate using SAML have the right permissions. Previously, you could only choose a single role (Viewer, Editor, or Admin) for users, which would apply to all of their Organizations. Now, you can map a given SAML user or org to different roles in different Organizations, so that, for example, they can be a Viewer in one Organization and an Admin in another.
|
||||
|
||||
Additionally, you can now grant multiple SAML organizations access to Grafana, using the `allowed_organizations` attribute. Previously, you could only map one.
|
||||
|
||||
{{< figure src="/static/img/docs/enterprise/8-4-SAML-auth.png" max-width="1200px" caption="Assign SAML users role" >}}
|
||||
|
||||
Learn more in our [SAML docs](https://grafana.com/docs/grafana/next/enterprise/saml/).
|
||||
|
||||
## Performance improvements
|
||||
|
||||
### Recorded queries is more stable and usable
|
||||
|
||||
We’ve made stability and usability improvements to Recorded Queries, and removed the feature flag so you can get started with Recorded Queries out of the box.
|
||||
|
||||
### Measure query cache hit rate and clear the cache
|
||||
|
||||
[Query caching](https://grafana.com/blog/2021/09/02/reduce-costs-and-increase-performance-with-query-caching-in-grafana-cloud/) significantly reduces load times and costs of Grafana dashboards, by temporarily storing query results in a cache. Now you can measure the hit rate of your query cache, to see how many queries (and therefore how much time and money) it is saving. You can also use these measurements to tune the cache time to live (TTL), to balance performance and up-to-date data.
|
||||
|
||||
You can also now manually clear the cache for a given data source in case data becomes stale, so that the next set of queries run against the data source itself.
|
||||
|
||||
To learn more, refer to [query caching in the Grafana Enterprise docs](https://grafana.com/docs/grafana/next/enterprise/query-caching/)
|
||||
|
||||
{{< figure src="/static/img/docs/enterprise/8-4-query-caching.png" max-width="1200px" caption="Grafana Enterprise query caching" >}}
|
||||
@@ -7,7 +7,7 @@ e2e.scenario({
|
||||
itName: 'Tests various Panel edit scenarios',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: true,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
e2e().intercept('/api/ds/query').as('query');
|
||||
e2e.flows.openDashboard({ uid: 'TkZXxlNG3' });
|
||||
@@ -46,11 +46,16 @@ e2e.scenario({
|
||||
// Can change to Alerts tab (graph panel is the default vis so the alerts tab should be rendered)
|
||||
e2e.components.Tab.title('Alert').should('be.visible').click();
|
||||
e2e.components.Tab.active().should('have.text', 'Alert0'); // there's no alert so therefore Alert + 0
|
||||
e2e.components.AlertTab.content().should('not.exist');
|
||||
|
||||
// Needs to be disabled until Grafana EE turns unified alerting on by default
|
||||
// e2e.components.AlertTab.content().should('not.exist');
|
||||
|
||||
e2e.components.QueryTab.content().should('not.exist');
|
||||
e2e.components.TransformTab.content().should('not.exist');
|
||||
e2e.components.PanelAlertTabContent.content().should('exist');
|
||||
e2e.components.PanelAlertTabContent.content().should('be.visible');
|
||||
|
||||
// Needs to be disabled until Grafana EE turns unified alerting on by default
|
||||
// e2e.components.PanelAlertTabContent.content().should('exist');
|
||||
// e2e.components.PanelAlertTabContent.content().should('be.visible');
|
||||
|
||||
e2e.components.Tab.title('Query').should('be.visible').click();
|
||||
});
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<!-- The template body needs to be wrapped in div to prevent Premailer from adding </tr></td> tags which breaks the HTML structure -->
|
||||
<div>
|
||||
|
||||
[[Subject .Subject "[[.Title]]"]]
|
||||
|
||||
[[ define "alert" ]]
|
||||
<tr>
|
||||
<td colspan="2" class="value">
|
||||
<span class="value-heading">Value:</span> <span class="value-value">[[ .ValueString ]]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="value">
|
||||
<span class="value-heading">Value:</span> <span class="value-value">[[ .ValueString ]]</span>
|
||||
</td>
|
||||
</tr>
|
||||
[[ if gt (len .Annotations.SortedPairs) 0 ]]
|
||||
<tr>
|
||||
<td colspan="2" class="annotations">
|
||||
@@ -187,62 +190,63 @@
|
||||
<tr>
|
||||
<td class="twelve">
|
||||
<table>
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
<tr>
|
||||
<td colspan="2" class="section-heading">
|
||||
Firing: [[ .Alerts.Firing | len ]] alert[[ if gt (len .Alerts.Firing) 1 ]]s[[ end ]][[ if gt (len .GroupLabels.SortedPairs) 1 ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]][[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ range .Alerts.Firing ]]
|
||||
[[ if gt (len .Alerts.Firing) 0 ]]
|
||||
<tr>
|
||||
<td colspan="2" class="section-heading">
|
||||
Firing: [[ .Alerts.Firing | len ]] alert[[ if gt (len .Alerts.Firing) 1 ]]s[[ end ]][[ if gt (len .GroupLabels.SortedPairs) 1 ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]][[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ range .Alerts.Firing ]]
|
||||
<tr>
|
||||
<td
|
||||
class="status-tag status-firing"
|
||||
width="68"
|
||||
>
|
||||
Firing
|
||||
</td>
|
||||
<td class="alert-label">
|
||||
[[ .Labels.alertname ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ template "alert" . ]]
|
||||
[[ end ]]
|
||||
[[ end ]]
|
||||
[[ if gt (len .Alerts.Resolved) 0 ]]
|
||||
<tr>
|
||||
<td colspan="2" class="section-heading">
|
||||
Resolved: [[ .Alerts.Resolved | len ]] alert[[ if gt (len .Alerts.Resolved) 1 ]]s[[ end ]][[ if gt (len .GroupLabels.SortedPairs) 1 ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]][[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ range .Alerts.Resolved ]]
|
||||
<tr>
|
||||
<td
|
||||
class="status-tag status-resolved"
|
||||
width="68"
|
||||
>
|
||||
Resolved
|
||||
</td>
|
||||
<td class="alert-label">
|
||||
[[ .Labels.alertname ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ template "alert" . ]]
|
||||
[[ end ]]
|
||||
[[ end ]]
|
||||
<tr>
|
||||
<td
|
||||
class="status-tag status-firing"
|
||||
width="68"
|
||||
>
|
||||
Firing
|
||||
</td>
|
||||
<td class="alert-label">
|
||||
[[ .Labels.alertname ]]
|
||||
<td colspan="2">
|
||||
<a href="[[ .AlertPageUrl ]]" class="button">Go to alerts page</a>
|
||||
</td>
|
||||
</tr>
|
||||
[[ template "alert" . ]]
|
||||
[[ end ]]
|
||||
[[ end ]]
|
||||
[[ if gt (len .Alerts.Resolved) 0 ]]
|
||||
<tr>
|
||||
<td colspan="2" class="section-heading">
|
||||
Resolved: [[ .Alerts.Resolved | len ]] alert[[ if gt (len .Alerts.Resolved) 1 ]]s[[ end ]][[ if gt (len .GroupLabels.SortedPairs) 1 ]] for
|
||||
[[ range .GroupLabels.SortedPairs ]]
|
||||
[[ .Name ]]=[[ .Value ]]
|
||||
[[ end ]][[ end ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ range .Alerts.Resolved ]]
|
||||
<tr>
|
||||
<td
|
||||
class="status-tag status-resolved"
|
||||
width="68"
|
||||
>
|
||||
Resolved
|
||||
</td>
|
||||
<td class="alert-label">
|
||||
[[ .Labels.alertname ]]
|
||||
</td>
|
||||
</tr>
|
||||
[[ template "alert" . ]]
|
||||
[[ end ]]
|
||||
[[ end ]]
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<a href="[[ .AlertPageUrl ]]" class="button">Go to alerts page</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
[[ end ]]
|
||||
|
||||
</div>
|
||||
|
||||
19
go.mod
19
go.mod
@@ -53,7 +53,7 @@ require (
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/gosimple/slug v1.9.0
|
||||
github.com/grafana/cuetsy v0.0.0-20211119211437-8c25464cc9bf
|
||||
github.com/grafana/grafana-aws-sdk v0.9.1
|
||||
github.com/grafana/grafana-aws-sdk v0.10.0
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.125.0
|
||||
github.com/grafana/loki v1.6.2-0.20211015002020-7832783b1caa
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
@@ -77,7 +77,7 @@ require (
|
||||
github.com/ohler55/ojg v1.12.9
|
||||
github.com/opentracing/opentracing-go v1.2.0
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/alertmanager v0.23.1-0.20211116083607-e2a10119aaf7
|
||||
github.com/prometheus/client_golang v1.12.1
|
||||
@@ -105,7 +105,7 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
|
||||
golang.org/x/exp v0.0.0-20210220032938-85be41e4509f // indirect
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f
|
||||
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||
@@ -167,10 +167,10 @@ require (
|
||||
github.com/go-openapi/analysis v0.20.1 // indirect
|
||||
github.com/go-openapi/errors v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/loads v0.20.2 // indirect
|
||||
github.com/go-openapi/runtime v0.19.29 // indirect
|
||||
github.com/go-openapi/spec v0.20.3 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-openapi/validate v0.20.2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
@@ -239,9 +239,9 @@ require (
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/weaveworks/promrus v1.2.0 // indirect
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
|
||||
go.mongodb.org/mongo-driver v1.5.2 // indirect
|
||||
go.mongodb.org/mongo-driver v1.7.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/atomic v1.9.0
|
||||
go.uber.org/goleak v1.1.10 // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||
@@ -252,7 +252,10 @@ require (
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
)
|
||||
|
||||
require cloud.google.com/go/kms v1.1.0
|
||||
require (
|
||||
cloud.google.com/go/kms v1.1.0
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.15 // indirect
|
||||
|
||||
17
go.sum
17
go.sum
@@ -867,6 +867,8 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9
|
||||
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
@@ -907,6 +909,8 @@ github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFut
|
||||
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
|
||||
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
|
||||
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.17.2/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
@@ -1040,6 +1044,7 @@ github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA=
|
||||
github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs=
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
@@ -1238,6 +1243,8 @@ github.com/grafana/go-mssqldb v0.0.0-20210326084033-d0ce3c521036 h1:GplhUk6Xes5J
|
||||
github.com/grafana/go-mssqldb v0.0.0-20210326084033-d0ce3c521036/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/grafana/grafana-aws-sdk v0.9.1 h1:jMZlsLsWnqOwLt2UNcLUsJ2z6289hLYlscK35QgS158=
|
||||
github.com/grafana/grafana-aws-sdk v0.9.1/go.mod h1:6KaQ8uUD4KpXr/b7bAC7zbfSXTVOiTk4XhIrwkGWn4w=
|
||||
github.com/grafana/grafana-aws-sdk v0.10.0 h1:q7+mJtT/vsU5InDN57yM+BJ2z1kJDf1W4WwWPEZ0Cxw=
|
||||
github.com/grafana/grafana-aws-sdk v0.10.0/go.mod h1:vFIOHEnY1u5nY0/tge1IHQjPuG6DRKr2ISf/HikUdjE=
|
||||
github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58 h1:2ud7NNM7LrGPO4x0NFR8qLq68CqI4SmB7I2yRN2w9oE=
|
||||
github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE=
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW39s+c+LetqSCjFj7xxPC5+M=
|
||||
@@ -1953,8 +1960,8 @@ github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuR
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982 h1:TdFv+3Gr3GaghJ/o80aulO4ian7GHGWMdLBXoLZH1Is=
|
||||
github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -2468,8 +2475,9 @@ go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4S
|
||||
go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
|
||||
go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
|
||||
go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
|
||||
go.mongodb.org/mongo-driver v1.5.2 h1:AsxOLoJTgP6YNM0fXWw4OjdluYmWzQYp+lFJL7xu9fU=
|
||||
go.mongodb.org/mongo-driver v1.5.2/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw=
|
||||
go.mongodb.org/mongo-driver v1.7.0 h1:hHrvOBWlWB2c7+8Gh/Xi5jj82AgidK/t7KVXBZ+IyUA=
|
||||
go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
@@ -2725,8 +2733,9 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg=
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e h1:Xj+JO91noE97IN6F/7WZxzC5QE6yENAQPrwIYhW3bsA=
|
||||
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"stable": "8.3.4",
|
||||
"testing": "8.3.4"
|
||||
"stable": "8.4.0",
|
||||
"testing": "8.4.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"packages": ["packages/*"],
|
||||
"version": "8.4.0-pre"
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "8.4.1"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"license": "AGPL-3.0-only",
|
||||
"private": true,
|
||||
"name": "grafana",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"repository": "github:grafana/grafana",
|
||||
"scripts": {
|
||||
"api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js",
|
||||
@@ -35,7 +35,7 @@
|
||||
"packages:typecheck": "lerna run typecheck",
|
||||
"packages:clean": "lerna run clean",
|
||||
"precommit": "yarn run lint-staged",
|
||||
"prettier:check": "prettier --list-different \"**/*.{scss,md,mdx}\"",
|
||||
"prettier:check": "prettier --check --list-different=false --loglevel=warn \"**/*.{scss,md,mdx}\"",
|
||||
"prettier:write": "prettier --list-different \"**/*.{scss,md,mdx}\" --write",
|
||||
"start": "yarn themes:generate && yarn dev --watch",
|
||||
"start:noTsCheck": "yarn start --env noTsCheck=1",
|
||||
@@ -248,6 +248,7 @@
|
||||
"@opentelemetry/semantic-conventions": "1.0.1",
|
||||
"@popperjs/core": "2.11.2",
|
||||
"@react-aria/button": "3.3.4",
|
||||
"@react-aria/dialog": "3.1.4",
|
||||
"@react-aria/focus": "3.5.0",
|
||||
"@react-aria/interactions": "3.7.0",
|
||||
"@react-aria/menu": "3.3.0",
|
||||
@@ -361,7 +362,7 @@
|
||||
"tether-drop": "https://github.com/torkelo/drop",
|
||||
"tinycolor2": "1.4.2",
|
||||
"tslib": "2.3.1",
|
||||
"uplot": "1.6.18",
|
||||
"uplot": "1.6.19",
|
||||
"uuid": "8.3.2",
|
||||
"vendor": "link:./public/vendor",
|
||||
"visjs-network": "4.25.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/data",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana Data Library",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "5.0.2",
|
||||
"@grafana/schema": "8.4.0-pre",
|
||||
"@grafana/schema": "8.4.1",
|
||||
"@types/d3-interpolate": "^1.4.0",
|
||||
"d3-interpolate": "1.4.0",
|
||||
"date-fns": "2.28.0",
|
||||
@@ -38,7 +38,7 @@
|
||||
"regenerator-runtime": "0.13.9",
|
||||
"rxjs": "7.5.1",
|
||||
"tslib": "2.3.1",
|
||||
"uplot": "1.6.18",
|
||||
"uplot": "1.6.19",
|
||||
"xss": "1.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -38,14 +38,16 @@ export function getFrameDisplayName(frame: DataFrame, index?: number) {
|
||||
|
||||
export function getFieldDisplayName(field: Field, frame?: DataFrame, allFrames?: DataFrame[]): string {
|
||||
const existingTitle = field.state?.displayName;
|
||||
const multipleFrames = Boolean(allFrames && allFrames.length > 1);
|
||||
|
||||
if (existingTitle) {
|
||||
if (existingTitle && multipleFrames === field.state?.multipleFrames) {
|
||||
return existingTitle;
|
||||
}
|
||||
|
||||
const displayName = calculateFieldDisplayName(field, frame, allFrames);
|
||||
field.state = field.state || {};
|
||||
field.state.displayName = displayName;
|
||||
field.state.multipleFrames = multipleFrames;
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,8 @@ export const valueMappingsOverrideProcessor = (
|
||||
export interface SelectFieldConfigSettings<T> {
|
||||
allowCustomValue?: boolean;
|
||||
|
||||
isClearable?: boolean;
|
||||
|
||||
/** The default options */
|
||||
options: Array<SelectableValue<T>>;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export function createShadows(colors: ThemeColors): ThemeShadows {
|
||||
return {
|
||||
z1: '0px 1px 2px rgba(24, 26, 27, 0.75)',
|
||||
z2: '0px 4px 8px rgba(24, 26, 27, 0.75)',
|
||||
z3: '0px 10px 20px rgb(20,20,20)',
|
||||
z3: '0px 8px 24px rgb(1,4,9)',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ describe('Order Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'temperature',
|
||||
multipleFrames: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -57,6 +58,7 @@ describe('Order Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'humidity',
|
||||
multipleFrames: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -67,6 +69,7 @@ describe('Order Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'time',
|
||||
multipleFrames: false,
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -108,6 +111,7 @@ describe('Order Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'humidity',
|
||||
multipleFrames: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -118,6 +122,7 @@ describe('Order Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'time',
|
||||
multipleFrames: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -128,6 +133,7 @@ describe('Order Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'pressure',
|
||||
multipleFrames: false,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -52,6 +52,7 @@ describe('OrganizeFields Transformer', () => {
|
||||
name: 'temperature',
|
||||
state: {
|
||||
displayName: 'temperature',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10.3, 10.4, 10.5, 10.6]),
|
||||
@@ -64,6 +65,7 @@ describe('OrganizeFields Transformer', () => {
|
||||
name: 'humidity',
|
||||
state: {
|
||||
displayName: 'renamed_humidity',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10000.3, 10000.4, 10000.5, 10000.6]),
|
||||
@@ -113,6 +115,7 @@ describe('OrganizeFields Transformer', () => {
|
||||
name: 'time',
|
||||
state: {
|
||||
displayName: 'renamed_time',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.time,
|
||||
values: new ArrayVector([3000, 4000, 5000, 6000]),
|
||||
@@ -123,6 +126,7 @@ describe('OrganizeFields Transformer', () => {
|
||||
name: 'pressure',
|
||||
state: {
|
||||
displayName: 'pressure',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10.3, 10.4, 10.5, 10.6]),
|
||||
|
||||
@@ -164,7 +164,7 @@ describe('Reducer Transformer', () => {
|
||||
{
|
||||
name: 'Field',
|
||||
type: FieldType.string,
|
||||
values: new ArrayVector(['A temperature', 'A humidity']),
|
||||
values: new ArrayVector(['temperature', 'humidity']),
|
||||
config: {},
|
||||
},
|
||||
{
|
||||
@@ -213,7 +213,7 @@ describe('Reducer Transformer', () => {
|
||||
{
|
||||
name: 'Field',
|
||||
type: FieldType.string,
|
||||
values: new ArrayVector(['A temperature']),
|
||||
values: new ArrayVector(['temperature']),
|
||||
config: {},
|
||||
},
|
||||
{
|
||||
@@ -286,16 +286,16 @@ describe('Reducer Transformer', () => {
|
||||
const seriesA = toDataFrame({
|
||||
name: 'a',
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [3000, 4000, 5000, 6000] },
|
||||
{ name: 'value', type: FieldType.number, values: [3, 4, 5, 6], state: { displayName: 'a' } },
|
||||
{ name: 'Time', type: FieldType.time, values: [3000, 4000, 5000, 6000] },
|
||||
{ name: 'Value', type: FieldType.number, values: [3, 4, 5, 6] },
|
||||
],
|
||||
});
|
||||
|
||||
const seriesB = toDataFrame({
|
||||
name: '2021',
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [3000, 4000, 5000, 6000] },
|
||||
{ name: 'value', type: FieldType.number, values: [7, 8, 9, 10], state: { displayName: '2021' } },
|
||||
{ name: 'Time', type: FieldType.time, values: [3000, 4000, 5000, 6000] },
|
||||
{ name: 'Value', type: FieldType.number, values: [7, 8, 9, 10] },
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ describe('Rename Transformer', () => {
|
||||
name: 'time',
|
||||
state: {
|
||||
displayName: 'Total time',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.time,
|
||||
values: new ArrayVector([3000, 4000, 5000, 6000]),
|
||||
@@ -60,6 +61,7 @@ describe('Rename Transformer', () => {
|
||||
name: 'temperature',
|
||||
state: {
|
||||
displayName: 'how cold is it?',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10.3, 10.4, 10.5, 10.6]),
|
||||
@@ -72,6 +74,7 @@ describe('Rename Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'Moistness',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10000.3, 10000.4, 10000.5, 10000.6]),
|
||||
@@ -115,6 +118,7 @@ describe('Rename Transformer', () => {
|
||||
labels: undefined,
|
||||
state: {
|
||||
displayName: 'ttl',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.time,
|
||||
values: new ArrayVector([3000, 4000, 5000, 6000]),
|
||||
@@ -125,6 +129,7 @@ describe('Rename Transformer', () => {
|
||||
name: 'pressure',
|
||||
state: {
|
||||
displayName: 'pressure',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10.3, 10.4, 10.5, 10.6]),
|
||||
@@ -137,6 +142,7 @@ describe('Rename Transformer', () => {
|
||||
name: 'humidity',
|
||||
state: {
|
||||
displayName: 'hum',
|
||||
multipleFrames: false,
|
||||
},
|
||||
type: FieldType.number,
|
||||
values: new ArrayVector([10000.3, 10000.4, 10000.5, 10000.6]),
|
||||
|
||||
@@ -46,6 +46,7 @@ describe('Rename By Regex Transformer', () => {
|
||||
"name": "Time",
|
||||
"state": Object {
|
||||
"displayName": "Time",
|
||||
"multipleFrames": false,
|
||||
},
|
||||
"type": "time",
|
||||
"values": Array [
|
||||
@@ -62,6 +63,7 @@ describe('Rename By Regex Transformer', () => {
|
||||
"name": "Value",
|
||||
"state": Object {
|
||||
"displayName": "web-01",
|
||||
"multipleFrames": false,
|
||||
},
|
||||
"type": "number",
|
||||
"values": Array [
|
||||
@@ -96,6 +98,7 @@ describe('Rename By Regex Transformer', () => {
|
||||
"name": "Time",
|
||||
"state": Object {
|
||||
"displayName": "Time",
|
||||
"multipleFrames": false,
|
||||
},
|
||||
"type": "time",
|
||||
"values": Array [
|
||||
@@ -112,6 +115,7 @@ describe('Rename By Regex Transformer', () => {
|
||||
"name": "Value",
|
||||
"state": Object {
|
||||
"displayName": "web-01.example.com",
|
||||
"multipleFrames": false,
|
||||
},
|
||||
"type": "number",
|
||||
"values": Array [
|
||||
@@ -147,6 +151,7 @@ describe('Rename By Regex Transformer', () => {
|
||||
"name": "Time",
|
||||
"state": Object {
|
||||
"displayName": "Time",
|
||||
"multipleFrames": false,
|
||||
},
|
||||
"type": "time",
|
||||
"values": Array [
|
||||
@@ -163,6 +168,7 @@ describe('Rename By Regex Transformer', () => {
|
||||
"name": "Value",
|
||||
"state": Object {
|
||||
"displayName": "web-01.example.com",
|
||||
"multipleFrames": false,
|
||||
},
|
||||
"type": "number",
|
||||
"values": Array [
|
||||
|
||||
@@ -170,7 +170,9 @@ describe('SeriesToColumns Transformer', () => {
|
||||
"name": "even",
|
||||
},
|
||||
"name": "time",
|
||||
"state": Object {},
|
||||
"state": Object {
|
||||
"multipleFrames": true,
|
||||
},
|
||||
"type": "time",
|
||||
"values": Array [
|
||||
3000,
|
||||
@@ -208,7 +210,9 @@ describe('SeriesToColumns Transformer', () => {
|
||||
"name": "odd",
|
||||
},
|
||||
"name": "time",
|
||||
"state": Object {},
|
||||
"state": Object {
|
||||
"multipleFrames": true,
|
||||
},
|
||||
"type": "time",
|
||||
"values": Array [
|
||||
undefined,
|
||||
@@ -267,7 +271,9 @@ describe('SeriesToColumns Transformer', () => {
|
||||
Object {
|
||||
"config": Object {},
|
||||
"name": "time",
|
||||
"state": Object {},
|
||||
"state": Object {
|
||||
"multipleFrames": true,
|
||||
},
|
||||
"type": "time",
|
||||
"values": Array [
|
||||
1000,
|
||||
|
||||
@@ -65,6 +65,26 @@ export type PreloadPlugin = {
|
||||
version: string;
|
||||
};
|
||||
|
||||
/** Supported OAuth services
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type OAuth =
|
||||
| 'github'
|
||||
| 'gitlab'
|
||||
| 'google'
|
||||
| 'generic_oauth'
|
||||
// | 'grafananet' Deprecated. Key always changed to "grafana_com"
|
||||
| 'grafana_com'
|
||||
| 'azuread'
|
||||
| 'okta';
|
||||
|
||||
/** Map of enabled OAuth services and their respective names
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type OAuthSettings = Partial<Record<OAuth, { name: string; icon?: string }>>;
|
||||
|
||||
/**
|
||||
* Describes all the different Grafana configuration values available for an instance.
|
||||
*
|
||||
|
||||
@@ -67,6 +67,12 @@ export interface FieldConfig<TOptions = any> {
|
||||
min?: number | null;
|
||||
max?: number | null;
|
||||
|
||||
// Interval indicates the expected regular step between values in the series.
|
||||
// When an interval exists, consumers can identify "missing" values when the expected value is not present.
|
||||
// The grafana timeseries visualization will render disconnected values when missing values are found it the time field.
|
||||
// The interval uses the same units as the values. For time.Time, this is defined in milliseconds.
|
||||
interval?: number | null;
|
||||
|
||||
// Convert input values into a display string
|
||||
mappings?: ValueMapping[];
|
||||
|
||||
@@ -169,6 +175,12 @@ export interface FieldState {
|
||||
* @internal -- we will try to make this unnecessary
|
||||
*/
|
||||
origin?: DataFrameFieldIndex;
|
||||
|
||||
/**
|
||||
* Boolean value is true if field is in a larger data set with multiple frames.
|
||||
* This is only related to the cached displayName property above.
|
||||
*/
|
||||
multipleFrames?: boolean;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
|
||||
@@ -36,4 +36,7 @@ export interface FeatureToggles {
|
||||
showFeatureFlagsInUI?: boolean;
|
||||
disable_http_request_histogram?: boolean;
|
||||
validatedQueries?: boolean;
|
||||
swaggerUi?: boolean;
|
||||
featureHighlights?: boolean;
|
||||
migrationLocking?: boolean;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface NavModelItem {
|
||||
onClick?: () => void;
|
||||
menuItemType?: NavMenuItemType;
|
||||
highlightText?: string;
|
||||
highlightId?: string;
|
||||
tabSuffix?: ComponentType<{ className?: string }>;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/e2e-selectors",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana End-to-End Test Selectors Library",
|
||||
"keywords": [
|
||||
"cli",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/e2e",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana End-to-End Test Library",
|
||||
"keywords": [
|
||||
"cli",
|
||||
@@ -48,7 +48,7 @@
|
||||
"@babel/core": "7.16.7",
|
||||
"@babel/preset-env": "7.16.7",
|
||||
"@cypress/webpack-preprocessor": "5.11.0",
|
||||
"@grafana/e2e-selectors": "8.4.0-pre",
|
||||
"@grafana/e2e-selectors": "8.4.1",
|
||||
"@grafana/tsconfig": "^1.0.0-rc1",
|
||||
"@mochajs/json-file-reporter": "^1.2.0",
|
||||
"babel-loader": "8.2.3",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/runtime",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana Runtime Library",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -22,9 +22,9 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grafana/data": "8.4.0-pre",
|
||||
"@grafana/e2e-selectors": "8.4.0-pre",
|
||||
"@grafana/ui": "8.4.0-pre",
|
||||
"@grafana/data": "8.4.1",
|
||||
"@grafana/e2e-selectors": "8.4.1",
|
||||
"@grafana/ui": "8.4.1",
|
||||
"@sentry/browser": "6.17.2",
|
||||
"history": "4.10.1",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { attachDebugger, createLogger } from '@grafana/ui';
|
||||
import { config } from '../config';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* @public
|
||||
* A wrapper to help work with browser location and history
|
||||
*/
|
||||
export interface LocationService {
|
||||
@@ -120,7 +120,7 @@ export class HistoryWrapper implements LocationService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* @public
|
||||
* Parses a location search string to an object
|
||||
* */
|
||||
export function locationSearchToObject(search: string | number): UrlQueryMap {
|
||||
@@ -137,12 +137,13 @@ export function locationSearchToObject(search: string | number): UrlQueryMap {
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* @public
|
||||
*/
|
||||
export let locationService: LocationService = new HistoryWrapper();
|
||||
|
||||
/** @internal
|
||||
/**
|
||||
* Used for tests only
|
||||
* @internal
|
||||
*/
|
||||
export const setLocationService = (location: LocationService) => {
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
/**
|
||||
* Passed as options to the {@link LocationSrv} to describe how the automatically navigation
|
||||
* should be performed.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
import { UrlQueryMap } from '@grafana/data';
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @deprecated in favor of {@link locationService} and will be removed in Grafana 9
|
||||
*/
|
||||
export interface LocationUpdate {
|
||||
/**
|
||||
@@ -47,6 +42,7 @@ export interface LocationUpdate {
|
||||
* be done via the LocationSrv and it will make sure to update the application state accordingly.
|
||||
*
|
||||
* @public
|
||||
* @deprecated in favor of {@link locationService} and will be removed in Grafana 9
|
||||
*/
|
||||
export interface LocationSrv {
|
||||
update(options: LocationUpdate): void;
|
||||
@@ -69,6 +65,7 @@ export function setLocationSrv(instance: LocationSrv) {
|
||||
* the user to a new place in Grafana.
|
||||
*
|
||||
* @public
|
||||
* @deprecated in favor of {@link locationService} and will be removed in Grafana 9
|
||||
*/
|
||||
export function getLocationSrv(): LocationSrv {
|
||||
return singletonInstance;
|
||||
|
||||
@@ -40,8 +40,8 @@ export class CopyPanelEvent extends BusEventWithPayload<PanelModel> {
|
||||
let singletonInstance: EventBus;
|
||||
|
||||
/**
|
||||
* Used during startup by Grafana to set the LocationSrv so it is available
|
||||
* via the {@link getLocationSrv} to the rest of the application.
|
||||
* Used during startup by Grafana to set the setAppEvents so it is available
|
||||
* via the {@link setAppEvents} to the rest of the application.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/schema",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana Schema Library",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
|
||||
@@ -7,6 +7,7 @@ LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cue
|
||||
ScaleDistribution: "linear" | "log" | "ordinal" @cuetsy(kind="enum")
|
||||
GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(kind="enum")
|
||||
StackingMode: "none" | "normal" | "percent" @cuetsy(kind="enum")
|
||||
GraphTransform: "constant" | "negative-Y" @cuetsy(kind="enum")
|
||||
BarAlignment: -1 | 0 | 1 @cuetsy(kind="enum",memberNames="Before|Center|After")
|
||||
ScaleOrientation: 0 | 1 @cuetsy(kind="enum",memberNames="Horizontal|Vertical")
|
||||
ScaleDirection: 1 | 1 | -1 | -1 @cuetsy(kind="enum",memberNames="Up|Right|Down|Left")
|
||||
@@ -84,4 +85,5 @@ GraphFieldConfig: {
|
||||
drawStyle?: GraphDrawStyle
|
||||
gradientMode?: GraphGradientMode
|
||||
thresholdsStyle?: GraphThresholdsStyleConfig
|
||||
transform?: GraphTransform
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
@@ -24,6 +24,11 @@ export enum GraphDrawStyle {
|
||||
Points = 'points',
|
||||
}
|
||||
|
||||
export enum GraphTransform {
|
||||
Constant = 'constant',
|
||||
NegativeY = 'negative-Y',
|
||||
}
|
||||
|
||||
export enum LineInterpolation {
|
||||
Linear = 'linear',
|
||||
Smooth = 'smooth',
|
||||
@@ -256,6 +261,7 @@ export interface GraphFieldConfig
|
||||
drawStyle?: GraphDrawStyle;
|
||||
gradientMode?: GraphGradientMode;
|
||||
thresholdsStyle?: GraphThresholdsStyleConfig;
|
||||
transform?: GraphTransform;
|
||||
}
|
||||
|
||||
export interface VizLegendOptions {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/toolkit",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana Toolkit",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -28,10 +28,10 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "7.13.14",
|
||||
"@babel/preset-env": "7.13.12",
|
||||
"@grafana/data": "8.4.0-pre",
|
||||
"@grafana/data": "8.4.1",
|
||||
"@grafana/eslint-config": "2.5.2",
|
||||
"@grafana/tsconfig": "^1.0.0-rc1",
|
||||
"@grafana/ui": "8.4.0-pre",
|
||||
"@grafana/ui": "8.4.1",
|
||||
"@jest/core": "26.6.3",
|
||||
"@rushstack/eslint-patch": "1.0.6",
|
||||
"@types/command-exists": "^1.2.0",
|
||||
@@ -86,7 +86,7 @@
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-preset-env": "6.7.0",
|
||||
"prettier": "2.5.1",
|
||||
"react-dev-utils": "^11.0.4",
|
||||
"react-dev-utils": "^12.0.0",
|
||||
"replace-in-file": "^4.1.0",
|
||||
"replace-in-file-webpack-plugin": "^1.0.6",
|
||||
"rimraf": "^3.0.0",
|
||||
|
||||
@@ -166,34 +166,6 @@ module.exports = {
|
||||
})
|
||||
);
|
||||
|
||||
config.plugins = fixProcessResolution(config.plugins);
|
||||
|
||||
return config;
|
||||
},
|
||||
// This webpack config only affects the manager (storybook UI) and generally shouldn't need to be changed.
|
||||
// If stories are failing to build check `webpackFinal` property above.
|
||||
managerWebpack: async (config: any) => {
|
||||
config.plugins = fixProcessResolution(config.plugins);
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
// Storybook 6.4.13 introduced https://github.com/storybookjs/storybook/pull/17213
|
||||
// which appears to prevent resolving correctly with yarn pnp.
|
||||
// We can probably remove this in the next patch release.
|
||||
function fixProcessResolution(plugins: any[]) {
|
||||
plugins.forEach((p: any, i: number) => {
|
||||
if (p.constructor.name === 'ProvidePlugin') {
|
||||
plugins.splice(
|
||||
i,
|
||||
1,
|
||||
new ProvidePlugin({
|
||||
process: require.resolve('process/browser.js'),
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/ui",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"description": "Grafana Components Library",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -33,13 +33,14 @@
|
||||
"@emotion/css": "11.7.1",
|
||||
"@emotion/react": "11.7.1",
|
||||
"@grafana/aws-sdk": "0.0.31",
|
||||
"@grafana/data": "8.4.0-pre",
|
||||
"@grafana/e2e-selectors": "8.4.0-pre",
|
||||
"@grafana/schema": "8.4.0-pre",
|
||||
"@grafana/data": "8.4.1",
|
||||
"@grafana/e2e-selectors": "8.4.1",
|
||||
"@grafana/schema": "8.4.1",
|
||||
"@grafana/slate-react": "0.22.10-grafana",
|
||||
"@monaco-editor/react": "4.3.1",
|
||||
"@popperjs/core": "2.11.2",
|
||||
"@react-aria/button": "3.3.4",
|
||||
"@react-aria/dialog": "3.1.4",
|
||||
"@react-aria/focus": "3.5.0",
|
||||
"@react-aria/menu": "3.3.0",
|
||||
"@react-aria/overlays": "3.7.3",
|
||||
@@ -88,7 +89,7 @@
|
||||
"slate-plain-serializer": "0.7.10",
|
||||
"tinycolor2": "1.4.2",
|
||||
"tslib": "2.3.1",
|
||||
"uplot": "1.6.18",
|
||||
"uplot": "1.6.19",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -98,20 +99,20 @@
|
||||
"@rollup/plugin-commonjs": "21.0.1",
|
||||
"@rollup/plugin-image": "2.1.1",
|
||||
"@rollup/plugin-node-resolve": "13.1.3",
|
||||
"@storybook/addon-a11y": "6.4.13",
|
||||
"@storybook/addon-actions": "6.4.13",
|
||||
"@storybook/addon-docs": "6.4.13",
|
||||
"@storybook/addon-essentials": "6.4.13",
|
||||
"@storybook/addon-a11y": "6.4.15",
|
||||
"@storybook/addon-actions": "6.4.15",
|
||||
"@storybook/addon-docs": "6.4.15",
|
||||
"@storybook/addon-essentials": "6.4.15",
|
||||
"@storybook/addon-knobs": "6.4.0",
|
||||
"@storybook/addon-storysource": "6.4.13",
|
||||
"@storybook/addons": "6.4.13",
|
||||
"@storybook/api": "6.4.13",
|
||||
"@storybook/builder-webpack5": "6.4.13",
|
||||
"@storybook/components": "6.4.13",
|
||||
"@storybook/core-events": "6.4.13",
|
||||
"@storybook/manager-webpack5": "6.4.13",
|
||||
"@storybook/react": "6.4.13",
|
||||
"@storybook/theming": "6.4.13",
|
||||
"@storybook/addon-storysource": "6.4.15",
|
||||
"@storybook/addons": "6.4.15",
|
||||
"@storybook/api": "6.4.15",
|
||||
"@storybook/builder-webpack5": "6.4.15",
|
||||
"@storybook/components": "6.4.15",
|
||||
"@storybook/core-events": "6.4.15",
|
||||
"@storybook/manager-webpack5": "6.4.15",
|
||||
"@storybook/react": "6.4.15",
|
||||
"@storybook/theming": "6.4.15",
|
||||
"@swc/helpers": "0.3.2",
|
||||
"@testing-library/dom": "8.11.1",
|
||||
"@testing-library/jest-dom": "5.16.1",
|
||||
|
||||
@@ -29,6 +29,8 @@ export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: ToolbarButtonVariant;
|
||||
/** Hide any children and only show icon */
|
||||
iconOnly?: boolean;
|
||||
/** Show highlight dot */
|
||||
isHighlighted?: boolean;
|
||||
}
|
||||
|
||||
export type ToolbarButtonVariant = 'default' | 'primary' | 'destructive' | 'active';
|
||||
@@ -48,6 +50,7 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
||||
variant = 'default',
|
||||
iconOnly,
|
||||
'aria-label': ariaLabel,
|
||||
isHighlighted,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
@@ -84,6 +87,7 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
||||
{children && !iconOnly && <div className={contentStyles}>{children}</div>}
|
||||
{isOpen === false && <Icon name="angle-down" />}
|
||||
{isOpen === true && <Icon name="angle-up" />}
|
||||
{isHighlighted && <div className={styles.highlight} />}
|
||||
</button>
|
||||
);
|
||||
|
||||
@@ -122,6 +126,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
button: css`
|
||||
label: toolbar-button;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: ${theme.spacing(theme.components.height.md)};
|
||||
@@ -209,5 +214,15 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
contentWithRightIcon: css`
|
||||
padding-right: ${theme.spacing(0.5)};
|
||||
`,
|
||||
highlight: css`
|
||||
background-color: ${theme.colors.success.main};
|
||||
border-radius: 50%;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
z-index: 1;
|
||||
`,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -104,9 +104,9 @@ class UnThemedColorPickerPopover<T extends CustomPickersDescriptor> extends Reac
|
||||
<>
|
||||
{Object.keys(customPickers).map((key) => {
|
||||
return (
|
||||
<div className={this.getTabClassName(key)} onClick={this.onTabChange(key)} key={key}>
|
||||
<button className={this.getTabClassName(key)} onClick={this.onTabChange(key)} key={key}>
|
||||
{customPickers[key].name}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
@@ -118,7 +118,11 @@ class UnThemedColorPickerPopover<T extends CustomPickersDescriptor> extends Reac
|
||||
const styles = getStyles(theme);
|
||||
return (
|
||||
<FocusScope contain restoreFocus autoFocus>
|
||||
<div className={styles.colorPickerPopover}>
|
||||
{/*
|
||||
tabIndex=-1 is needed here to support highlighting text within the picker when using FocusScope
|
||||
see https://github.com/adobe/react-spectrum/issues/1604#issuecomment-781574668
|
||||
*/}
|
||||
<div tabIndex={-1} className={styles.colorPickerPopover}>
|
||||
<div className={styles.colorPickerPopoverTabs}>
|
||||
<button className={this.getTabClassName('palette')} onClick={this.onTabChange('palette')}>
|
||||
Colors
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { Field } from '../../Forms/Field';
|
||||
import { getInputStyles, Input } from '../../Input/Input';
|
||||
import { Icon } from '../../Icon/Icon';
|
||||
import { Tooltip } from '../../Tooltip/Tooltip';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -115,14 +116,13 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps): Re
|
||||
</CustomScrollbar>
|
||||
<div className={styles.rightSide}>
|
||||
<div className={styles.title}>
|
||||
<TimePickerTitle>Specify time range</TimePickerTitle>
|
||||
<div className={styles.description}>
|
||||
Specify a relative time range, for more information see{' '}
|
||||
<a href="https://grafana.com/docs/grafana/latest/dashboards/time-range-controls/">
|
||||
docs <Icon name="external-link-alt" />
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
<TimePickerTitle>
|
||||
<Tooltip content={<TooltipContent />} placement="bottom" theme="info">
|
||||
<div>
|
||||
Specify time range <Icon name="info-circle" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</TimePickerTitle>
|
||||
</div>
|
||||
<Field label="From" invalid={!from.validation.isValid} error={from.validation.errorMessage}>
|
||||
<Input
|
||||
@@ -152,6 +152,38 @@ export function RelativeTimeRangePicker(props: RelativeTimeRangePickerProps): Re
|
||||
);
|
||||
}
|
||||
|
||||
const TooltipContent = () => {
|
||||
const styles = useStyles2(toolTipStyles);
|
||||
return (
|
||||
<>
|
||||
<div className={styles.supported}>
|
||||
Supported formats: <code className={styles.tooltip}>now-[digit]s/m/h/d/w</code>
|
||||
</div>
|
||||
<div>Example: to select a time range from 10 minutes ago to now</div>
|
||||
<code className={styles.tooltip}>From: now-10m To: now</code>
|
||||
<div className={styles.link}>
|
||||
For more information see{' '}
|
||||
<a href="https://grafana.com/docs/grafana/latest/dashboards/time-range-controls/">
|
||||
docs <Icon name="external-link-alt" />
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const toolTipStyles = (theme: GrafanaTheme2) => ({
|
||||
supported: css`
|
||||
margin-bottom: ${theme.spacing(1)};
|
||||
`,
|
||||
tooltip: css`
|
||||
margin: 0;
|
||||
`,
|
||||
link: css`
|
||||
margin-top: ${theme.spacing(1)};
|
||||
`,
|
||||
});
|
||||
|
||||
const getStyles = (fromError?: string, toError?: string) => (theme: GrafanaTheme2) => {
|
||||
const inputStyles = getInputStyles({ theme, invalid: false });
|
||||
const bodyMinimumHeight = 250;
|
||||
|
||||
@@ -25,6 +25,7 @@ import { Themeable } from '../../types';
|
||||
import { quickOptions } from './options';
|
||||
import { ButtonGroup, ToolbarButton } from '../Button';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { useDialog } from '@react-aria/dialog';
|
||||
import { useOverlay } from '@react-aria/overlays';
|
||||
import { FocusScope } from '@react-aria/focus';
|
||||
|
||||
@@ -86,6 +87,7 @@ export function UnthemedTimeRangePicker(props: TimeRangePickerProps): ReactEleme
|
||||
|
||||
const ref = createRef<HTMLElement>();
|
||||
const { overlayProps } = useOverlay({ onClose, isDismissable: true, isOpen }, ref);
|
||||
const { dialogProps } = useDialog({}, ref);
|
||||
|
||||
const styles = getStyles(theme);
|
||||
const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
||||
@@ -118,7 +120,7 @@ export function UnthemedTimeRangePicker(props: TimeRangePickerProps): ReactEleme
|
||||
</Tooltip>
|
||||
{isOpen && (
|
||||
<FocusScope contain autoFocus restoreFocus>
|
||||
<section ref={ref} {...overlayProps}>
|
||||
<section ref={ref} {...overlayProps} {...dialogProps}>
|
||||
<TimePickerContent
|
||||
timeZone={timeZone}
|
||||
fiscalYearStartMonth={fiscalYearStartMonth}
|
||||
|
||||
@@ -78,6 +78,10 @@ export const getBodyStyles = (theme: GrafanaTheme2) => {
|
||||
background-color: ${theme.colors.background.primary};
|
||||
width: 268px;
|
||||
|
||||
.react-calendar__navigation {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.react-calendar__navigation__label,
|
||||
.react-calendar__navigation__arrow,
|
||||
.react-calendar__navigation {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data';
|
||||
import { useTheme2 } from '../../../themes';
|
||||
import { Header } from './CalendarHeader';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { useDialog } from '@react-aria/dialog';
|
||||
import { FocusScope } from '@react-aria/focus';
|
||||
import { OverlayContainer, useOverlay } from '@react-aria/overlays';
|
||||
import { Body } from './CalendarBody';
|
||||
@@ -77,6 +78,12 @@ function TimePickerCalendar(props: TimePickerCalendarProps) {
|
||||
const styles = getStyles(theme, props.isReversed);
|
||||
const { isOpen, isFullscreen, onClose } = props;
|
||||
const ref = React.createRef<HTMLElement>();
|
||||
const { dialogProps } = useDialog(
|
||||
{
|
||||
'aria-label': selectors.components.TimePicker.calendar.label,
|
||||
},
|
||||
ref
|
||||
);
|
||||
const { overlayProps } = useOverlay(
|
||||
{
|
||||
isDismissable: true,
|
||||
@@ -93,13 +100,7 @@ function TimePickerCalendar(props: TimePickerCalendarProps) {
|
||||
if (isFullscreen) {
|
||||
return (
|
||||
<FocusScope contain restoreFocus autoFocus>
|
||||
<section
|
||||
className={styles.container}
|
||||
onClick={stopPropagation}
|
||||
aria-label={selectors.components.TimePicker.calendar.label}
|
||||
ref={ref}
|
||||
{...overlayProps}
|
||||
>
|
||||
<section className={styles.container} onClick={stopPropagation} ref={ref} {...overlayProps} {...dialogProps}>
|
||||
<Header {...props} />
|
||||
<Body {...props} />
|
||||
</section>
|
||||
@@ -110,7 +111,7 @@ function TimePickerCalendar(props: TimePickerCalendarProps) {
|
||||
return (
|
||||
<OverlayContainer>
|
||||
<FocusScope contain autoFocus restoreFocus>
|
||||
<section className={styles.modal} onClick={stopPropagation} ref={ref} {...overlayProps}>
|
||||
<section className={styles.modal} onClick={stopPropagation} ref={ref} {...overlayProps} {...dialogProps}>
|
||||
<div className={styles.content} aria-label={selectors.components.TimePicker.calendar.label}>
|
||||
<Header {...props} />
|
||||
<Body {...props} />
|
||||
|
||||
@@ -14,120 +14,6 @@ import { getFocusStyles } from '../../../themes/mixins';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { FilterInput } from '../..';
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRanges, isContainerTall) => {
|
||||
return {
|
||||
container: css`
|
||||
background: ${theme.colors.background.primary};
|
||||
box-shadow: ${theme.shadows.z3};
|
||||
position: absolute;
|
||||
z-index: ${theme.zIndex.dropdown};
|
||||
width: 546px;
|
||||
top: 116%;
|
||||
border-radius: 2px;
|
||||
border: 1px solid ${theme.colors.border.weak};
|
||||
${isReversed ? 'left' : 'right'}: 0;
|
||||
|
||||
@media only screen and (max-width: ${theme.breakpoints.values.lg}px) {
|
||||
width: 262px;
|
||||
}
|
||||
`,
|
||||
body: css`
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
height: ${isContainerTall ? '381px' : '217px'};
|
||||
`,
|
||||
leftSide: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: ${isReversed ? 'none' : `1px solid ${theme.colors.border.weak}`};
|
||||
width: ${!hideQuickRanges ? '60%' : '100%'};
|
||||
overflow: hidden;
|
||||
order: ${isReversed ? 1 : 0};
|
||||
`,
|
||||
rightSide: css`
|
||||
width: 40% !important;
|
||||
border-right: ${isReversed ? `1px solid ${theme.colors.border.weak}` : 'none'};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@media only screen and (max-width: ${theme.breakpoints.values.lg}px) {
|
||||
width: 100% !important;
|
||||
}
|
||||
`,
|
||||
timeRangeFilter: css`
|
||||
padding: ${theme.spacing(1)};
|
||||
`,
|
||||
spacing: css`
|
||||
margin-top: 16px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
header: css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid ${theme.colors.border.weak};
|
||||
padding: 7px 9px 7px 9px;
|
||||
`,
|
||||
expandButton: css`
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
&:focus-visible {
|
||||
${getFocusStyles(theme)}
|
||||
}
|
||||
`,
|
||||
body: css`
|
||||
border-bottom: 1px solid ${theme.colors.border.weak};
|
||||
`,
|
||||
form: css`
|
||||
padding: 7px 9px 7px 9px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const getFullScreenStyles = stylesFactory((theme: GrafanaTheme2, hideQuickRanges?: boolean) => {
|
||||
return {
|
||||
container: css`
|
||||
padding-top: 9px;
|
||||
padding-left: 11px;
|
||||
padding-right: ${!hideQuickRanges ? '20%' : '11px'};
|
||||
`,
|
||||
title: css`
|
||||
margin-bottom: 11px;
|
||||
`,
|
||||
recent: css`
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-top: ${theme.spacing(1)};
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const getEmptyListStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
container: css`
|
||||
padding: 12px;
|
||||
margin: 12px;
|
||||
|
||||
a,
|
||||
span {
|
||||
font-size: 13px;
|
||||
}
|
||||
`,
|
||||
link: css`
|
||||
color: ${theme.colors.text.link};
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
interface Props {
|
||||
value: TimeRange;
|
||||
onChange: (timeRange: TimeRange) => void;
|
||||
@@ -363,3 +249,117 @@ const useTimeOption = (raw: RawTimeRange, quickOptions: TimeOption[]): TimeOptio
|
||||
});
|
||||
}, [raw, quickOptions]);
|
||||
};
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRanges, isContainerTall) => {
|
||||
return {
|
||||
container: css`
|
||||
background: ${theme.colors.background.primary};
|
||||
box-shadow: ${theme.shadows.z3};
|
||||
position: absolute;
|
||||
z-index: ${theme.zIndex.dropdown};
|
||||
width: 546px;
|
||||
top: 116%;
|
||||
border-radius: 2px;
|
||||
border: 1px solid ${theme.colors.border.weak};
|
||||
${isReversed ? 'left' : 'right'}: 0;
|
||||
|
||||
@media only screen and (max-width: ${theme.breakpoints.values.lg}px) {
|
||||
width: 262px;
|
||||
}
|
||||
`,
|
||||
body: css`
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
height: ${isContainerTall ? '381px' : '217px'};
|
||||
`,
|
||||
leftSide: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: ${isReversed ? 'none' : `1px solid ${theme.colors.border.weak}`};
|
||||
width: ${!hideQuickRanges ? '60%' : '100%'};
|
||||
overflow: hidden;
|
||||
order: ${isReversed ? 1 : 0};
|
||||
`,
|
||||
rightSide: css`
|
||||
width: 40% !important;
|
||||
border-right: ${isReversed ? `1px solid ${theme.colors.border.weak}` : 'none'};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@media only screen and (max-width: ${theme.breakpoints.values.lg}px) {
|
||||
width: 100% !important;
|
||||
}
|
||||
`,
|
||||
timeRangeFilter: css`
|
||||
padding: ${theme.spacing(1)};
|
||||
`,
|
||||
spacing: css`
|
||||
margin-top: 16px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
header: css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid ${theme.colors.border.weak};
|
||||
padding: 7px 9px 7px 9px;
|
||||
`,
|
||||
expandButton: css`
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
&:focus-visible {
|
||||
${getFocusStyles(theme)}
|
||||
}
|
||||
`,
|
||||
body: css`
|
||||
border-bottom: 1px solid ${theme.colors.border.weak};
|
||||
`,
|
||||
form: css`
|
||||
padding: 7px 9px 7px 9px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const getFullScreenStyles = stylesFactory((theme: GrafanaTheme2, hideQuickRanges?: boolean) => {
|
||||
return {
|
||||
container: css`
|
||||
padding-top: 9px;
|
||||
padding-left: 11px;
|
||||
padding-right: ${!hideQuickRanges ? '20%' : '11px'};
|
||||
`,
|
||||
title: css`
|
||||
margin-bottom: 11px;
|
||||
`,
|
||||
recent: css`
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
padding-top: ${theme.spacing(1)};
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
const getEmptyListStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
container: css`
|
||||
padding: 12px;
|
||||
margin: 12px;
|
||||
|
||||
a,
|
||||
span {
|
||||
font-size: 13px;
|
||||
}
|
||||
`,
|
||||
link: css`
|
||||
color: ${theme.colors.text.link};
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
|
||||
import { IconButton } from '../IconButton/IconButton';
|
||||
import { stylesFactory, useTheme2 } from '../../themes';
|
||||
import { FocusScope } from '@react-aria/focus';
|
||||
import { useDialog } from '@react-aria/dialog';
|
||||
import { useOverlay } from '@react-aria/overlays';
|
||||
|
||||
export interface Props {
|
||||
@@ -34,6 +35,11 @@ export interface Props {
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2, scrollableContent: boolean) => {
|
||||
return {
|
||||
container: css`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
`,
|
||||
drawer: css`
|
||||
.drawer-content {
|
||||
background-color: ${theme.colors.background.primary};
|
||||
@@ -76,10 +82,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, scrollableContent: boolea
|
||||
`,
|
||||
content: css`
|
||||
padding: ${theme.spacing(2)};
|
||||
flex-grow: 1;
|
||||
flex: 1;
|
||||
overflow: ${!scrollableContent ? 'hidden' : 'auto'};
|
||||
z-index: 0;
|
||||
height: 100%;
|
||||
`,
|
||||
};
|
||||
});
|
||||
@@ -101,6 +106,7 @@ export const Drawer: FC<Props> = ({
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const currentWidth = isExpanded ? '100%' : width;
|
||||
const overlayRef = React.useRef(null);
|
||||
const { dialogProps, titleProps } = useDialog({}, overlayRef);
|
||||
const { overlayProps } = useOverlay(
|
||||
{
|
||||
isDismissable: true,
|
||||
@@ -132,45 +138,47 @@ export const Drawer: FC<Props> = ({
|
||||
}
|
||||
>
|
||||
<FocusScope restoreFocus contain autoFocus>
|
||||
{typeof title === 'string' && (
|
||||
<div className={drawerStyles.header} {...overlayProps} ref={overlayRef}>
|
||||
<div className={drawerStyles.actions}>
|
||||
{expandable && !isExpanded && (
|
||||
<div className={drawerStyles.container} {...overlayProps} {...dialogProps} ref={overlayRef}>
|
||||
{typeof title === 'string' && (
|
||||
<div className={drawerStyles.header}>
|
||||
<div className={drawerStyles.actions}>
|
||||
{expandable && !isExpanded && (
|
||||
<IconButton
|
||||
name="angle-left"
|
||||
size="xl"
|
||||
onClick={() => setIsExpanded(true)}
|
||||
surface="header"
|
||||
aria-label={selectors.components.Drawer.General.expand}
|
||||
/>
|
||||
)}
|
||||
{expandable && isExpanded && (
|
||||
<IconButton
|
||||
name="angle-right"
|
||||
size="xl"
|
||||
onClick={() => setIsExpanded(false)}
|
||||
surface="header"
|
||||
aria-label={selectors.components.Drawer.General.contract}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
name="angle-left"
|
||||
name="times"
|
||||
size="xl"
|
||||
onClick={() => setIsExpanded(true)}
|
||||
onClick={onClose}
|
||||
surface="header"
|
||||
aria-label={selectors.components.Drawer.General.expand}
|
||||
aria-label={selectors.components.Drawer.General.close}
|
||||
/>
|
||||
)}
|
||||
{expandable && isExpanded && (
|
||||
<IconButton
|
||||
name="angle-right"
|
||||
size="xl"
|
||||
onClick={() => setIsExpanded(false)}
|
||||
surface="header"
|
||||
aria-label={selectors.components.Drawer.General.contract}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
name="times"
|
||||
size="xl"
|
||||
onClick={onClose}
|
||||
surface="header"
|
||||
aria-label={selectors.components.Drawer.General.close}
|
||||
/>
|
||||
</div>
|
||||
<div className={drawerStyles.titleWrapper}>
|
||||
<h3>{title}</h3>
|
||||
{typeof subtitle === 'string' && <div className="muted">{subtitle}</div>}
|
||||
{typeof subtitle !== 'string' && subtitle}
|
||||
</div>
|
||||
<div className={drawerStyles.titleWrapper}>
|
||||
<h3 {...titleProps}>{title}</h3>
|
||||
{typeof subtitle === 'string' && <div className="muted">{subtitle}</div>}
|
||||
{typeof subtitle !== 'string' && subtitle}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{typeof title !== 'string' && title}
|
||||
<div className={drawerStyles.content}>
|
||||
{!scrollableContent ? children : <CustomScrollbar>{children}</CustomScrollbar>}
|
||||
</div>
|
||||
)}
|
||||
{typeof title !== 'string' && title}
|
||||
<div className={drawerStyles.content} {...overlayProps} ref={overlayRef}>
|
||||
{!scrollableContent ? children : <CustomScrollbar>{children}</CustomScrollbar>}
|
||||
</div>
|
||||
</FocusScope>
|
||||
</RcDrawer>
|
||||
|
||||
@@ -57,7 +57,11 @@ const ButtonSelectComponent = <T,>(props: Props<T>) => {
|
||||
<div className={styles.menuWrapper}>
|
||||
<ClickOutsideWrapper onClick={state.close} parent={document} includeButtonPress={false}>
|
||||
<FocusScope contain autoFocus restoreFocus>
|
||||
<Menu onClose={state.close} {...menuProps}>
|
||||
{/*
|
||||
tabIndex=-1 is needed here to support highlighting text within the menu when using FocusScope
|
||||
see https://github.com/adobe/react-spectrum/issues/1604#issuecomment-781574668
|
||||
*/}
|
||||
<Menu tabIndex={-1} onClose={state.close} {...menuProps}>
|
||||
{options.map((item) => (
|
||||
<MenuItem
|
||||
key={`${item.value}`}
|
||||
|
||||
@@ -60,12 +60,14 @@ Object {
|
||||
],
|
||||
"bands": Array [
|
||||
Object {
|
||||
"dir": -1,
|
||||
"series": Array [
|
||||
2,
|
||||
1,
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"dir": -1,
|
||||
"series": Array [
|
||||
4,
|
||||
3,
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
import { ArrayVector, FieldType, MutableDataFrame } from '@grafana/data';
|
||||
import { applyNullInsertThreshold } from './nullInsertThreshold';
|
||||
|
||||
function randInt(min: number, max: number) {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||
}
|
||||
|
||||
function genFrame() {
|
||||
let fieldCount = 10;
|
||||
let valueCount = 3000;
|
||||
let step = 1000;
|
||||
let skipProb = 0.5;
|
||||
let skipSteps = [1, 5]; // min, max
|
||||
|
||||
let allValues = Array(fieldCount);
|
||||
|
||||
allValues[0] = Array(valueCount);
|
||||
|
||||
for (let i = 0, curStep = Date.now(); i < valueCount; i++) {
|
||||
curStep = allValues[0][i] = curStep + step * (Math.random() < skipProb ? randInt(skipSteps[0], skipSteps[1]) : 1);
|
||||
}
|
||||
|
||||
for (let fi = 1; fi < fieldCount; fi++) {
|
||||
let values = Array(valueCount);
|
||||
|
||||
for (let i = 0; i < valueCount; i++) {
|
||||
values[i] = Math.random() * 100;
|
||||
}
|
||||
|
||||
allValues[fi] = values;
|
||||
}
|
||||
|
||||
return {
|
||||
length: valueCount,
|
||||
fields: allValues.map((values, i) => {
|
||||
return {
|
||||
name: 'A-' + i,
|
||||
type: i === 0 ? FieldType.time : FieldType.number,
|
||||
config: {
|
||||
interval: i === 0 ? step : null,
|
||||
},
|
||||
values: new ArrayVector(values),
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
describe('nullInsertThreshold Transformer', () => {
|
||||
test('should insert nulls at +threshold between adjacent > threshold: 1', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, values: [1, 3, 10] },
|
||||
{ name: 'One', type: FieldType.number, config: { custom: { insertNulls: 1 } }, values: [4, 6, 8] },
|
||||
{ name: 'Two', type: FieldType.string, config: { custom: { insertNulls: 1 } }, values: ['a', 'b', 'c'] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([1, 2, 3, 4, 10]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([4, null, 6, null, 8]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual(['a', null, 'b', null, 'c']);
|
||||
});
|
||||
|
||||
test('should insert nulls at +threshold between adjacent > threshold: 2', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, values: [5, 7, 11] },
|
||||
{ name: 'One', type: FieldType.number, config: { custom: { insertNulls: 2 } }, values: [4, 6, 8] },
|
||||
{ name: 'Two', type: FieldType.string, config: { custom: { insertNulls: 2 } }, values: ['a', 'b', 'c'] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([5, 7, 9, 11]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([4, 6, null, 8]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual(['a', 'b', null, 'c']);
|
||||
});
|
||||
|
||||
test('should insert nulls at +interval between adjacent > interval: 1', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 1 }, values: [1, 3, 10] },
|
||||
{ name: 'One', type: FieldType.number, values: [4, 6, 8] },
|
||||
{ name: 'Two', type: FieldType.string, values: ['a', 'b', 'c'] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([1, 2, 3, 4, 10]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([4, null, 6, null, 8]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual(['a', null, 'b', null, 'c']);
|
||||
});
|
||||
|
||||
// TODO: make this work
|
||||
test.skip('should insert nulls at +threshold (when defined) instead of +interval', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 2 }, values: [5, 7, 11] },
|
||||
{ name: 'One', type: FieldType.number, config: { custom: { insertNulls: 1 } }, values: [4, 6, 8] },
|
||||
{ name: 'Two', type: FieldType.string, config: { custom: { insertNulls: 1 } }, values: ['a', 'b', 'c'] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([5, 6, 7, 8, 11]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([4, null, 6, null, 8]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual(['a', null, 'b', null, 'c']);
|
||||
});
|
||||
|
||||
test('should insert nulls at midpoints between adjacent > interval: 2', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 2 }, values: [5, 7, 11] },
|
||||
{ name: 'One', type: FieldType.number, values: [4, 6, 8] },
|
||||
{ name: 'Two', type: FieldType.string, values: ['a', 'b', 'c'] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result.fields[0].values.toArray()).toStrictEqual([5, 7, 9, 11]);
|
||||
expect(result.fields[1].values.toArray()).toStrictEqual([4, 6, null, 8]);
|
||||
expect(result.fields[2].values.toArray()).toStrictEqual(['a', 'b', null, 'c']);
|
||||
});
|
||||
|
||||
test('should noop on fewer than two values', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 1 }, values: [1] },
|
||||
{ name: 'Value', type: FieldType.number, values: [1] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result).toBe(df);
|
||||
});
|
||||
|
||||
test('should noop on invalid threshold', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, values: [1, 2, 4] },
|
||||
{ name: 'Value', type: FieldType.number, config: { custom: { insertNulls: -1 } }, values: [1, 1, 1] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result).toBe(df);
|
||||
});
|
||||
|
||||
test('should noop on invalid interval', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: -1 }, values: [1, 2, 4] },
|
||||
{ name: 'Value', type: FieldType.number, values: [1, 1, 1] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result).toBe(df);
|
||||
});
|
||||
|
||||
test('should noop when no missing steps', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 1 }, values: [1, 2, 3] },
|
||||
{ name: 'Value', type: FieldType.number, values: [1, 1, 1] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df);
|
||||
|
||||
expect(result).toBe(df);
|
||||
});
|
||||
|
||||
test('should noop when refFieldName not found', () => {
|
||||
const df = new MutableDataFrame({
|
||||
refId: 'A',
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, config: { interval: 1 }, values: [1, 2, 5] },
|
||||
{ name: 'Value', type: FieldType.number, values: [1, 1, 1] },
|
||||
],
|
||||
});
|
||||
|
||||
const result = applyNullInsertThreshold(df, 'Time2');
|
||||
|
||||
expect(result).toBe(df);
|
||||
});
|
||||
|
||||
test('perf stress test should be <= 10ms', () => {
|
||||
// 10 fields x 3,000 values with 50% skip (output = 10 fields x 6,000 values)
|
||||
let bigFrameA = genFrame();
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.time('insertValues-10x3k');
|
||||
applyNullInsertThreshold(bigFrameA);
|
||||
// eslint-disable-next-line no-console
|
||||
console.timeEnd('insertValues-10x3k');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,115 @@
|
||||
import { ArrayVector, DataFrame, FieldType } from '@grafana/data';
|
||||
|
||||
type InsertMode = (prev: number, next: number, threshold: number) => number;
|
||||
|
||||
const INSERT_MODES = {
|
||||
threshold: (prev: number, next: number, threshold: number) => prev + threshold,
|
||||
midpoint: (prev: number, next: number, threshold: number) => (prev + next) / 2,
|
||||
// previous time + 1ms to prevent StateTimeline from forward-interpolating prior state
|
||||
plusone: (prev: number, next: number, threshold: number) => prev + 1,
|
||||
};
|
||||
|
||||
export function applyNullInsertThreshold(
|
||||
frame: DataFrame,
|
||||
refFieldName?: string | null,
|
||||
insertMode: InsertMode = INSERT_MODES.threshold
|
||||
): DataFrame {
|
||||
if (frame.length < 2) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
const refField = frame.fields.find((field) => {
|
||||
// note: getFieldDisplayName() would require full DF[]
|
||||
return refFieldName != null ? field.name === refFieldName : field.type === FieldType.time;
|
||||
});
|
||||
|
||||
if (refField == null) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
const thresholds = frame.fields.map((field) => field.config.custom?.insertNulls ?? refField.config.interval ?? null);
|
||||
|
||||
const uniqueThresholds = new Set<number>(thresholds);
|
||||
|
||||
uniqueThresholds.delete(null as any);
|
||||
|
||||
if (uniqueThresholds.size === 0) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
if (uniqueThresholds.size === 1) {
|
||||
const threshold = uniqueThresholds.values().next().value;
|
||||
|
||||
if (threshold <= 0) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
const refValues = refField.values.toArray();
|
||||
|
||||
const frameValues = frame.fields.map((field) => field.values.toArray());
|
||||
|
||||
const filledFieldValues = nullInsertThreshold(refValues, frameValues, threshold, insertMode);
|
||||
|
||||
if (filledFieldValues === frameValues) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
return {
|
||||
...frame,
|
||||
length: filledFieldValues[0].length,
|
||||
fields: frame.fields.map((field, i) => ({
|
||||
...field,
|
||||
values: new ArrayVector(filledFieldValues[i]),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: unique threshold-per-field (via overrides) is unimplemented
|
||||
// should be done by processing each (refField + thresholdA-field1 + thresholdA-field2...)
|
||||
// as a separate nullInsertThreshold() dataset, then re-join into single dataset via join()
|
||||
return frame;
|
||||
}
|
||||
|
||||
function nullInsertThreshold(refValues: number[], frameValues: any[][], threshold: number, getInsertValue: InsertMode) {
|
||||
const len = refValues.length;
|
||||
let prevValue: number = refValues[0];
|
||||
const refValuesNew: number[] = [prevValue];
|
||||
|
||||
for (let i = 1; i < len; i++) {
|
||||
const curValue = refValues[i];
|
||||
|
||||
if (curValue - prevValue > threshold) {
|
||||
refValuesNew.push(getInsertValue(prevValue, curValue, threshold));
|
||||
}
|
||||
|
||||
refValuesNew.push(curValue);
|
||||
|
||||
prevValue = curValue;
|
||||
}
|
||||
|
||||
const filledLen = refValuesNew.length;
|
||||
|
||||
if (filledLen === len) {
|
||||
return frameValues;
|
||||
}
|
||||
|
||||
const filledFieldValues: any[][] = [];
|
||||
|
||||
for (let fieldValues of frameValues) {
|
||||
let filledValues;
|
||||
|
||||
if (fieldValues !== refValues) {
|
||||
filledValues = Array(filledLen);
|
||||
|
||||
for (let i = 0, j = 0; i < filledLen; i++) {
|
||||
filledValues[i] = refValues[j] === refValuesNew[i] ? fieldValues[j++] : null;
|
||||
}
|
||||
} else {
|
||||
filledValues = refValuesNew;
|
||||
}
|
||||
|
||||
filledFieldValues.push(filledValues);
|
||||
}
|
||||
|
||||
return filledFieldValues;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { XYFieldMatchers } from './types';
|
||||
import { ArrayVector, DataFrame, FieldConfig, FieldType, outerJoinDataFrames } from '@grafana/data';
|
||||
import { nullToUndefThreshold } from './nullToUndefThreshold';
|
||||
import { applyNullInsertThreshold } from './nullInsertThreshold';
|
||||
import { AxisPlacement, GraphFieldConfig, ScaleDistribution, ScaleDistributionConfig } from '@grafana/schema';
|
||||
import { FIXED_UNIT } from './GraphNG';
|
||||
|
||||
@@ -16,13 +17,11 @@ function applySpanNullsThresholds(frame: DataFrame) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.type === FieldType.number) {
|
||||
let spanNulls = field.config.custom?.spanNulls;
|
||||
let spanNulls = field.config.custom?.spanNulls;
|
||||
|
||||
if (typeof spanNulls === 'number') {
|
||||
if (spanNulls !== -1) {
|
||||
field.values = new ArrayVector(nullToUndefThreshold(refValues, field.values.toArray(), spanNulls));
|
||||
}
|
||||
if (typeof spanNulls === 'number') {
|
||||
if (spanNulls !== -1) {
|
||||
field.values = new ArrayVector(nullToUndefThreshold(refValues, field.values.toArray(), spanNulls));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +31,7 @@ function applySpanNullsThresholds(frame: DataFrame) {
|
||||
|
||||
export function preparePlotFrame(frames: DataFrame[], dimFields: XYFieldMatchers) {
|
||||
let alignedFrame = outerJoinDataFrames({
|
||||
frames: frames,
|
||||
frames: frames.map((frame) => applyNullInsertThreshold(frame)),
|
||||
joinBy: dimFields.x,
|
||||
keep: dimFields.y,
|
||||
keepOriginIndices: true,
|
||||
|
||||
@@ -80,7 +80,11 @@ export function Modal(props: PropsWithChildren<Props>) {
|
||||
onClick={onClickBackdrop || (closeOnBackdropClick ? onDismiss : undefined)}
|
||||
/>
|
||||
<FocusScope contain={trapFocus} autoFocus restoreFocus>
|
||||
<div className={cx(styles.modal, className)}>
|
||||
{/*
|
||||
tabIndex=-1 is needed here to support highlighting text within the modal when using FocusScope
|
||||
see https://github.com/adobe/react-spectrum/issues/1604#issuecomment-781574668
|
||||
*/}
|
||||
<div tabIndex={-1} className={cx(styles.modal, className)}>
|
||||
<div className={headerClass}>
|
||||
{typeof title === 'string' && <DefaultModalHeader {...props} title={title} />}
|
||||
{typeof title !== 'string' && title}
|
||||
|
||||
@@ -67,7 +67,8 @@ export class SelectValueEditor<T> extends React.PureComponent<Props<T>, State<T>
|
||||
value={current}
|
||||
defaultValue={value}
|
||||
allowCustomValue={settings?.allowCustomValue}
|
||||
onChange={(e) => onChange(e.value)}
|
||||
isClearable={settings?.isClearable}
|
||||
onChange={(e) => onChange(e?.value)}
|
||||
options={options}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -20,7 +20,6 @@ import { useTheme2 } from '../../themes';
|
||||
import { getSelectStyles } from './getSelectStyles';
|
||||
import { cleanValue, findSelectedValue } from './utils';
|
||||
import { ActionMeta, SelectBaseProps, SelectValue } from './types';
|
||||
import { deprecationWarning } from '@grafana/data';
|
||||
|
||||
interface ExtraValuesIndicatorProps {
|
||||
maxVisibleValues?: number | undefined;
|
||||
@@ -119,6 +118,7 @@ export function SelectBase<T>({
|
||||
maxVisibleValues,
|
||||
menuPlacement = 'auto',
|
||||
menuPosition,
|
||||
// TODO change this to default to true for Grafana 9
|
||||
menuShouldPortal = false,
|
||||
noOptionsMessage = 'No options found',
|
||||
onBlur,
|
||||
@@ -139,9 +139,6 @@ export function SelectBase<T>({
|
||||
width,
|
||||
isValidNewOption,
|
||||
}: SelectBaseProps<T>) {
|
||||
if (menuShouldPortal === false) {
|
||||
deprecationWarning('SelectBase', 'menuShouldPortal={false}', 'menuShouldPortal={true}');
|
||||
}
|
||||
const theme = useTheme2();
|
||||
const styles = getSelectStyles(theme);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ const getSelectContainerStyles = stylesFactory((theme: GrafanaTheme2, focused: b
|
||||
/* The display property is set by the styles prop in SelectBase because it's dependant on the width prop */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
|
||||
min-height: 32px;
|
||||
|
||||
@@ -46,9 +46,8 @@ export interface SelectCommonProps<T> {
|
||||
menuPlacement?: 'auto' | 'bottom' | 'top';
|
||||
menuPosition?: 'fixed' | 'absolute';
|
||||
/**
|
||||
* @deprecated
|
||||
* Setting to true will portal the menu to `document.body`.
|
||||
* This property will soon be removed and portalling will be the default behavior.
|
||||
* This property will soon default to true and portalling will be the default behavior.
|
||||
*/
|
||||
menuShouldPortal?: boolean;
|
||||
/** The message to display when no options could be found */
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { DataFrame, FieldConfig, FieldSparkline, IndexVector } from '@grafana/data';
|
||||
import { GraphFieldConfig } from '@grafana/schema';
|
||||
import { applyNullInsertThreshold } from '../GraphNG/nullInsertThreshold';
|
||||
|
||||
/** @internal
|
||||
* Given a sparkline config returns a DataFrame ready to be turned into Plot data set
|
||||
@@ -11,7 +12,7 @@ export function preparePlotFrame(sparkline: FieldSparkline, config?: FieldConfig
|
||||
...config,
|
||||
};
|
||||
|
||||
return {
|
||||
return applyNullInsertThreshold({
|
||||
refId: 'sparkline',
|
||||
fields: [
|
||||
sparkline.x ?? IndexVector.newField(length),
|
||||
@@ -21,5 +22,5 @@ export function preparePlotFrame(sparkline: FieldSparkline, config?: FieldConfig
|
||||
},
|
||||
],
|
||||
length,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
VizLegendOptions,
|
||||
StackingMode,
|
||||
} from '@grafana/schema';
|
||||
import { collectStackingGroups, orderIdsByCalcs, preparePlotData } from '../uPlot/utils';
|
||||
import { collectStackingGroups, INTERNAL_NEGATIVE_Y_PREFIX, orderIdsByCalcs, preparePlotData } from '../uPlot/utils';
|
||||
import uPlot from 'uplot';
|
||||
import { buildScaleKey } from '../GraphNG/utils';
|
||||
|
||||
@@ -332,11 +332,12 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{
|
||||
}
|
||||
|
||||
if (stackingGroups.size !== 0) {
|
||||
for (const [_, seriesIds] of stackingGroups.entries()) {
|
||||
for (const [group, seriesIds] of stackingGroups.entries()) {
|
||||
const seriesIdxs = orderIdsByCalcs({ ids: seriesIds, legend, frame });
|
||||
for (let j = seriesIdxs.length - 1; j > 0; j--) {
|
||||
builder.addBand({
|
||||
series: [seriesIdxs[j], seriesIdxs[j - 1]],
|
||||
dir: group.startsWith(INTERNAL_NEGATIVE_Y_PREFIX) ? 1 : -1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useStyles2 } from '../../themes';
|
||||
*/
|
||||
export interface SeriesTableRowProps {
|
||||
color?: string;
|
||||
label?: string;
|
||||
label?: React.ReactNode;
|
||||
value?: string | GraphSeriesValue;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export const VizTooltipContainer: React.FC<VizTooltipContainerProps> = ({
|
||||
position: { x: positionX, y: positionY },
|
||||
offset: { x: offsetX, y: offsetY },
|
||||
children,
|
||||
allowPointerEvents,
|
||||
allowPointerEvents = false,
|
||||
className,
|
||||
...otherProps
|
||||
}) => {
|
||||
|
||||
@@ -134,6 +134,10 @@ export function scaleGradient(u: uPlot, scaleKey: string, scaleStops: ScaleValue
|
||||
|
||||
let range = minStopPos - maxStopPos;
|
||||
|
||||
if (range === 0) {
|
||||
return scaleStops[maxStopIdx!][1];
|
||||
}
|
||||
|
||||
let x0, y0, x1, y1;
|
||||
|
||||
if (u.scales.x!.ori === ScaleOrientation.Horizontal) {
|
||||
|
||||
@@ -231,6 +231,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
|
||||
const v = otherProps.data.fields[i].values.get(focusedPointIdxs[i]!);
|
||||
const display = field.display!(v);
|
||||
|
||||
sortIdx.push([series.length, v]);
|
||||
series.push({
|
||||
color: display.color || FALLBACK_COLOR,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { orderIdsByCalcs, preparePlotData, timeFormatToTemplate } from './utils';
|
||||
import { FieldType, MutableDataFrame } from '@grafana/data';
|
||||
import { StackingMode } from '@grafana/schema';
|
||||
import { GraphTransform, StackingMode } from '@grafana/schema';
|
||||
|
||||
describe('timeFormatToTemplate', () => {
|
||||
it.each`
|
||||
@@ -53,6 +53,76 @@ describe('preparePlotData', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
describe('transforms', () => {
|
||||
it('negative-y transform', () => {
|
||||
const df = new MutableDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [9997, 9998, 9999] },
|
||||
{ name: 'a', values: [-10, 20, 10] },
|
||||
{ name: 'b', values: [10, 10, 10] },
|
||||
{ name: 'c', values: [20, 20, 20], config: { custom: { transform: GraphTransform.NegativeY } } },
|
||||
],
|
||||
});
|
||||
expect(preparePlotData([df])).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
9997,
|
||||
9998,
|
||||
9999,
|
||||
],
|
||||
Array [
|
||||
-10,
|
||||
20,
|
||||
10,
|
||||
],
|
||||
Array [
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
],
|
||||
Array [
|
||||
-20,
|
||||
-20,
|
||||
-20,
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
it('constant transform', () => {
|
||||
const df = new MutableDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [9997, 9998, 9999] },
|
||||
{ name: 'a', values: [-10, 20, 10], config: { custom: { transform: GraphTransform.Constant } } },
|
||||
{ name: 'b', values: [10, 10, 10] },
|
||||
{ name: 'c', values: [20, 20, 20] },
|
||||
],
|
||||
});
|
||||
expect(preparePlotData([df])).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
9997,
|
||||
9998,
|
||||
9999,
|
||||
],
|
||||
Array [
|
||||
-10,
|
||||
-10,
|
||||
-10,
|
||||
],
|
||||
Array [
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
],
|
||||
Array [
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe('stacking', () => {
|
||||
it('none', () => {
|
||||
const df = new MutableDataFrame({
|
||||
@@ -148,6 +218,67 @@ describe('preparePlotData', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('standard with negative y transform', () => {
|
||||
const df = new MutableDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [9997, 9998, 9999] },
|
||||
{
|
||||
name: 'a',
|
||||
values: [-10, 20, 10],
|
||||
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } },
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
values: [10, 10, 10],
|
||||
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } },
|
||||
},
|
||||
{
|
||||
name: 'c',
|
||||
values: [20, 20, 20],
|
||||
config: {
|
||||
custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' }, transform: GraphTransform.NegativeY },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'd',
|
||||
values: [10, 10, 10],
|
||||
config: {
|
||||
custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' }, transform: GraphTransform.NegativeY },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(preparePlotData([df])).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
9997,
|
||||
9998,
|
||||
9999,
|
||||
],
|
||||
Array [
|
||||
-10,
|
||||
20,
|
||||
10,
|
||||
],
|
||||
Array [
|
||||
0,
|
||||
30,
|
||||
20,
|
||||
],
|
||||
Array [
|
||||
-20,
|
||||
-20,
|
||||
-20,
|
||||
],
|
||||
Array [
|
||||
-30,
|
||||
-30,
|
||||
-30,
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('standard with multiple groups', () => {
|
||||
const df = new MutableDataFrame({
|
||||
fields: [
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { DataFrame, ensureTimeField, Field, FieldType } from '@grafana/data';
|
||||
import { StackingMode, VizLegendOptions } from '@grafana/schema';
|
||||
import { GraphFieldConfig, GraphTransform, StackingMode, VizLegendOptions } from '@grafana/schema';
|
||||
import { orderBy } from 'lodash';
|
||||
import uPlot, { AlignedData, Options, PaddingSide } from 'uplot';
|
||||
import { attachDebugger } from '../../utils';
|
||||
import { createLogger } from '../../utils/logger';
|
||||
|
||||
const ALLOWED_FORMAT_STRINGS_REGEX = /\b(YYYY|YY|MMMM|MMM|MM|M|DD|D|WWWW|WWW|HH|H|h|AA|aa|a|mm|m|ss|s|fff)\b/g;
|
||||
export const INTERNAL_NEGATIVE_Y_PREFIX = '__internalNegY';
|
||||
|
||||
export function timeFormatToTemplate(f: string) {
|
||||
return f.replace(ALLOWED_FORMAT_STRINGS_REGEX, (match) => `{${match}}`);
|
||||
@@ -60,7 +61,16 @@ export function preparePlotData(
|
||||
}
|
||||
|
||||
collectStackingGroups(f, stackingGroups, seriesIndex);
|
||||
result.push(f.values.toArray());
|
||||
const customConfig: GraphFieldConfig = f.config.custom || {};
|
||||
|
||||
const values = f.values.toArray();
|
||||
if (customConfig.transform === GraphTransform.NegativeY) {
|
||||
result.push(values.map((v) => v * -1));
|
||||
} else if (customConfig.transform === GraphTransform.Constant) {
|
||||
result.push(new Array(values.length).fill(values[0]));
|
||||
} else {
|
||||
result.push(values);
|
||||
}
|
||||
seriesIndex++;
|
||||
}
|
||||
|
||||
@@ -128,10 +138,15 @@ export function collectStackingGroups(f: Field, groups: Map<string, number[]>, s
|
||||
customConfig.stacking?.group &&
|
||||
!customConfig.hideFrom?.viz
|
||||
) {
|
||||
if (!groups.has(customConfig.stacking.group)) {
|
||||
groups.set(customConfig.stacking.group, [seriesIdx]);
|
||||
const group =
|
||||
customConfig.transform === GraphTransform.NegativeY
|
||||
? `${INTERNAL_NEGATIVE_Y_PREFIX}-${customConfig.stacking.group}`
|
||||
: customConfig.stacking.group;
|
||||
|
||||
if (!groups.has(group)) {
|
||||
groups.set(group, [seriesIdx]);
|
||||
} else {
|
||||
groups.set(customConfig.stacking.group, groups.get(customConfig.stacking.group)!.concat(seriesIdx));
|
||||
groups.set(group, groups.get(group)!.concat(seriesIdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ export function SuggestionsPlugin({
|
||||
};
|
||||
|
||||
return editor
|
||||
.snapshotSelection()
|
||||
.deleteBackward(backward)
|
||||
.deleteForward(forward)
|
||||
.insertText(suggestionText)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@jaegertracing/jaeger-ui-components",
|
||||
"version": "8.4.0-pre",
|
||||
"version": "8.4.1",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -18,7 +18,6 @@
|
||||
"@types/prop-types": "^15",
|
||||
"@types/react": "17.0.38",
|
||||
"@types/react-icons": "2.2.7",
|
||||
"@types/recompose": "0.30.10",
|
||||
"@types/reselect": "2.2.0",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"enzyme": "3.11.0",
|
||||
@@ -27,8 +26,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/css": "11.7.1",
|
||||
"@grafana/data": "8.4.0-pre",
|
||||
"@grafana/ui": "8.4.0-pre",
|
||||
"@grafana/data": "8.4.1",
|
||||
"@grafana/ui": "8.4.1",
|
||||
"chance": "^1.0.10",
|
||||
"classnames": "^2.2.5",
|
||||
"combokeys": "^3.0.0",
|
||||
@@ -46,7 +45,6 @@
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-icons": "2.2.7",
|
||||
"recompose": "0.30.0",
|
||||
"reselect": "4.1.5",
|
||||
"tinycolor2": "1.4.2",
|
||||
"tslib": "2.3.1",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import UIElementsContext, { UIPopover } from '../uiElementsContext';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import SpanBar from './SpanBar';
|
||||
|
||||
@@ -83,9 +84,13 @@ describe('<SpanBar>', () => {
|
||||
const { onMouseOver, onMouseLeave } = wrapper.find('[data-test-id="SpanBar--wrapper"]').props();
|
||||
const labelElm = wrapper.find('[data-test-id="SpanBar--label"]');
|
||||
expect(labelElm.text()).toBe(shortLabel);
|
||||
onMouseOver();
|
||||
act(() => {
|
||||
onMouseOver();
|
||||
});
|
||||
expect(labelElm.text()).toBe(longLabel);
|
||||
onMouseLeave();
|
||||
act(() => {
|
||||
onMouseLeave();
|
||||
});
|
||||
expect(labelElm.text()).toBe(shortLabel);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
import cx from 'classnames';
|
||||
import { css } from '@emotion/css';
|
||||
import { groupBy as _groupBy } from 'lodash';
|
||||
import React from 'react';
|
||||
import { compose, onlyUpdateForKeys, withProps, withState } from 'recompose';
|
||||
import React, { useState } from 'react';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { autoColor } from '../Theme';
|
||||
@@ -90,7 +89,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
};
|
||||
};
|
||||
|
||||
type TCommonProps = {
|
||||
type Props = {
|
||||
color: string;
|
||||
onClick?: (evt: React.MouseEvent<any>) => void;
|
||||
viewEnd: number;
|
||||
@@ -107,39 +106,32 @@ type TCommonProps = {
|
||||
span: TraceSpan;
|
||||
className?: string;
|
||||
labelClassName?: string;
|
||||
};
|
||||
|
||||
type TInnerProps = {
|
||||
label: string;
|
||||
setLongLabel: () => void;
|
||||
setShortLabel: () => void;
|
||||
} & TCommonProps;
|
||||
|
||||
type TOuterProps = {
|
||||
longLabel: string;
|
||||
shortLabel: string;
|
||||
} & TCommonProps;
|
||||
};
|
||||
|
||||
function toPercent(value: number) {
|
||||
return `${(value * 100).toFixed(1)}%`;
|
||||
}
|
||||
|
||||
function SpanBar(props: TInnerProps) {
|
||||
const {
|
||||
viewEnd,
|
||||
viewStart,
|
||||
getViewedBounds,
|
||||
color,
|
||||
label,
|
||||
onClick,
|
||||
setLongLabel,
|
||||
setShortLabel,
|
||||
rpc,
|
||||
traceStartTime,
|
||||
span,
|
||||
className,
|
||||
labelClassName,
|
||||
} = props;
|
||||
function SpanBar({
|
||||
viewEnd,
|
||||
viewStart,
|
||||
getViewedBounds,
|
||||
color,
|
||||
shortLabel,
|
||||
longLabel,
|
||||
onClick,
|
||||
rpc,
|
||||
traceStartTime,
|
||||
span,
|
||||
className,
|
||||
labelClassName,
|
||||
}: Props) {
|
||||
const [label, setLabel] = useState(shortLabel);
|
||||
const setShortLabel = () => setLabel(shortLabel);
|
||||
const setLongLabel = () => setLabel(longLabel);
|
||||
|
||||
// group logs based on timestamps
|
||||
const logGroups = _groupBy(span.logs, (log) => {
|
||||
const posPercent = getViewedBounds(log.timestamp, log.timestamp).start;
|
||||
@@ -197,21 +189,4 @@ function SpanBar(props: TInnerProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export default compose<TInnerProps, TOuterProps>(
|
||||
withState('label', 'setLabel', (props: { shortLabel: string }) => props.shortLabel),
|
||||
withProps(
|
||||
({
|
||||
setLabel,
|
||||
shortLabel,
|
||||
longLabel,
|
||||
}: {
|
||||
setLabel: (label: string) => void;
|
||||
shortLabel: string;
|
||||
longLabel: string;
|
||||
}) => ({
|
||||
setLongLabel: () => setLabel(longLabel),
|
||||
setShortLabel: () => setLabel(shortLabel),
|
||||
})
|
||||
),
|
||||
onlyUpdateForKeys(['label', 'rpc', 'viewStart', 'viewEnd'])
|
||||
)(SpanBar);
|
||||
export default React.memo(SpanBar);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user