diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fb0144ca5e8..26736002dde 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -414,6 +414,8 @@ /e2e-playwright/dashboard-cujs/ @grafana/dashboards-squad /e2e-playwright/dashboards-search-suite/ @grafana/dashboards-squad /e2e-playwright/dashboards/cujs/ @grafana/dashboards-squad +/e2e-playwright/dashboards/DashboardForConditionalRendering.json @grafana/dashboards-squad +/e2e-playwright/dashboards/DashboardWithAllConditionalRendering.json @grafana/dashboards-squad /e2e-playwright/dashboards/AdHocFilterTest.json @grafana/datapro /e2e-playwright/dashboards/DashboardLiveTest.json @grafana/dashboards-squad /e2e-playwright/dashboards/DataLinkWithoutSlugTest.json @grafana/dashboards-squad diff --git a/e2e-playwright/dashboard-new-layouts/dashboard-conditional-rendering-load-change.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboard-conditional-rendering-load-change.spec.ts new file mode 100644 index 00000000000..7d2662ddb27 --- /dev/null +++ b/e2e-playwright/dashboard-new-layouts/dashboard-conditional-rendering-load-change.spec.ts @@ -0,0 +1,409 @@ +import { Page } from '@playwright/test'; + +import { test, expect, E2ESelectorGroups, DashboardPage, DashboardPageArgs } from '@grafana/plugin-e2e'; + +import testDashboard from '../dashboards/DashboardWithAllConditionalRendering.json'; + +test.use({ + featureToggles: { + kubernetesDashboards: true, + dashboardNewLayouts: true, + groupByVariable: true, + }, + viewport: { width: 1920, height: 1080 }, +}); + +test.describe('Dashboard - Conditional Rendering - Load and Change', { tag: ['@dashboards'] }, () => { + let uid: string; + + const loadDashboard = async ( + page: Page, + gotoDashboardPage: (args: DashboardPageArgs) => Promise, + options?: { from?: string; to?: string; myVariable?: string } + ) => { + const params: DashboardPageArgs = { uid }; + + if (options?.from && options?.to) { + params.timeRange = { + from: options.from, + to: options.to, + }; + } + + if (options?.myVariable) { + params.queryParams = new URLSearchParams(); + params.queryParams.set('var-myVariable', options.myVariable); + } + + const dashboardPage = await gotoDashboardPage(params); + await expect(page.getByText(testDashboard.spec.title)).toBeVisible(); + await page.waitForLoadState('networkidle'); + return dashboardPage; + }; + + const fillVariable = async (page: Page, dashboardPage: DashboardPage, selectors: E2ESelectorGroups, text: string) => { + const variable = dashboardPage + .getByGrafanaSelector( + selectors.pages.Dashboard.SubMenu.submenuItemLabels(testDashboard.spec.variables[0].spec.name) + ) + .locator('..') + .locator('input'); + await variable.click(); + await variable.clear(); + await variable.fill(text); + await variable.press('Enter'); + await page.waitForLoadState('networkidle'); + }; + + const setTimeRange = async ( + page: Page, + dashboardPage: DashboardPage, + selectors: E2ESelectorGroups, + from: string, + to: string + ) => { + await dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton).click(); + const fromField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField); + await fromField.click(); + await fromField.fill(from); + const toField = dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField); + await toField.click(); + await toField.fill(to); + await dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.applyTimeRange).click(); + await page.waitForLoadState('networkidle'); + }; + + test.beforeAll(async ({ request }) => { + const response = await request.post('/apis/dashboard.grafana.app/v2beta1/namespaces/stacks-12345/dashboards', { + data: { + metadata: { + annotations: { + 'grafana.app/folder': '', + 'grafana.app/grant-permissions': 'default', + }, + generateName: 'ad', + }, + spec: testDashboard.spec, + }, + }); + const responseBody = await response.json(); + uid = responseBody.metadata.name; + }); + + test.afterAll(async ({ request }) => { + if (uid) { + await request.delete(`/apis/dashboard.grafana.app/v1beta1/namespaces/default/dashboards/${uid}`); + } + }); + + const getPanel = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups, title: string) => + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(`Panel - ${title}`)); + + const getPanelShowData = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - data'); + + const getPanelHideData = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - data'); + + const getPanelShowNoData = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - no data'); + + const getPanelHideNoData = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - no data'); + + const getPanelShowTimeRange = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - time range <7d'); + + const getPanelHideTimeRange = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - time range <7d'); + + const getPanelShowEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - variable - equals 1,2,3'); + + const getPanelHideEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - variable - equals 1,2,3'); + + const getPanelShowNotEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - variable - not equals 1,2,3'); + + const getPanelHideNotEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - variable - not equals 1,2,3'); + + const getPanelShowMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - variable - matches .*2.*'); + + const getPanelHideMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - variable - matches .*2.*'); + + const getPanelShowNotMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'show - variable - not matches .*2.*'); + + const getPanelHideNotMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getPanel(dashboardPage, selectors, 'hide - variable - not matches .*2.*'); + + const getRow = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups, title: string) => + dashboardPage.getByGrafanaSelector(selectors.components.DashboardRow.title(`Row - ${title}`)); + + const getRowShowTimeRange = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'show - time range <7d'); + + const getRowHideTimeRange = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'hide - time range <7d'); + + const getRowShowEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'show - variable - equals 1,2,3'); + + const getRowHideEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'hide - variable - equals 1,2,3'); + + const getRowShowNotEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'show - variable - not equals 1,2,3'); + + const getRowHideNotEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'hide - variable - not equals 1,2,3'); + + const getRowShowMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'show - variable - matches .*2.*'); + + const getRowHideMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'hide - variable - matches .*2.*'); + + const getRowShowNotMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'show - variable - not matches .*2.*'); + + const getRowHideNotMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getRow(dashboardPage, selectors, 'hide - variable - not matches .*2.*'); + + const getTab = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups, title: string) => + dashboardPage.getByGrafanaSelector(selectors.components.Tab.title(`Tab - ${title}`)); + + const getTabShowTimeRange = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'show - time range <7d'); + + const getTabHideTimeRange = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'hide - time range <7d'); + + const getTabShowEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'show - variable - equals 1,2,3'); + + const getTabHideEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'hide - variable - equals 1,2,3'); + + const getTabShowNotEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'show - variable - not equals 1,2,3'); + + const getTabHideNotEquals = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'hide - variable - not equals 1,2,3'); + + const getTabShowMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'show - variable - matches .*2.*'); + + const getTabHideMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'hide - variable - matches .*2.*'); + + const getTabShowNotMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'show - variable - not matches .*2.*'); + + const getTabHideNotMatches = (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => + getTab(dashboardPage, selectors, 'hide - variable - not matches .*2.*'); + + test('Load without data', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage); + + await expect(getPanelShowData(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideData(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelShowNoData(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideNoData(dashboardPage, selectors)).not.toBeVisible(); + + await fillVariable(page, dashboardPage, selectors, '1,2,3,4'); + + await expect(getPanelShowData(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideData(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelShowNoData(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideNoData(dashboardPage, selectors)).toBeVisible(); + }); + + test('Load with data', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage, { myVariable: '1,2,3,4' }); + + await expect(getPanelShowData(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideData(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelShowNoData(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideNoData(dashboardPage, selectors)).toBeVisible(); + + await fillVariable(page, dashboardPage, selectors, ''); + + await expect(getPanelShowData(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideData(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelShowNoData(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideNoData(dashboardPage, selectors)).not.toBeVisible(); + }); + + test('Load without time range', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage); + + await expect(getPanelShowTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideTimeRange(dashboardPage, selectors)).not.toBeVisible(); + + await setTimeRange(page, dashboardPage, selectors, 'now-8d', 'now'); + + await expect(getPanelShowTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideTimeRange(dashboardPage, selectors)).toBeVisible(); + }); + + test('Load with time range', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage, { from: 'now-8d', to: 'now' }); + + await expect(getPanelShowTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideTimeRange(dashboardPage, selectors)).toBeVisible(); + + await setTimeRange(page, dashboardPage, selectors, 'now-6h', 'now'); + + await expect(getPanelShowTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideTimeRange(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowTimeRange(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideTimeRange(dashboardPage, selectors)).not.toBeVisible(); + }); + + test('Load without variable equals/not equals', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage); + + await expect(getPanelShowEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelShowNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideNotEquals(dashboardPage, selectors)).not.toBeVisible(); + + await fillVariable(page, dashboardPage, selectors, '1,2,3'); + + await expect(getPanelShowEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelShowNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideNotEquals(dashboardPage, selectors)).toBeVisible(); + }); + + test('Load with variable equals/not equals', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage, { myVariable: '1,2,3' }); + + await expect(getPanelShowEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelShowNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideNotEquals(dashboardPage, selectors)).toBeVisible(); + + await fillVariable(page, dashboardPage, selectors, ''); + + await expect(getPanelShowEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelShowNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideNotEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowEquals(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowNotEquals(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideNotEquals(dashboardPage, selectors)).not.toBeVisible(); + }); + + test('Load without variable matches/not matches', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage); + + await expect(getPanelShowMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelShowNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideNotMatches(dashboardPage, selectors)).not.toBeVisible(); + + await fillVariable(page, dashboardPage, selectors, '1,2,3'); + + await expect(getPanelShowMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelShowNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideNotMatches(dashboardPage, selectors)).toBeVisible(); + }); + + test('Load with variable matches/not matches', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await loadDashboard(page, gotoDashboardPage, { myVariable: '1,2,3' }); + + await expect(getPanelShowMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelShowNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideNotMatches(dashboardPage, selectors)).toBeVisible(); + + await fillVariable(page, dashboardPage, selectors, ''); + + await expect(getPanelShowMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getPanelHideMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelShowNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getPanelHideNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowShowMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getRowHideMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowShowNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getRowHideNotMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabShowMatches(dashboardPage, selectors)).not.toBeVisible(); + await expect(getTabHideMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabShowNotMatches(dashboardPage, selectors)).toBeVisible(); + await expect(getTabHideNotMatches(dashboardPage, selectors)).not.toBeVisible(); + }); +}); diff --git a/e2e-playwright/dashboards/DashboardForConditionalRendering.json b/e2e-playwright/dashboards/DashboardForConditionalRendering.json new file mode 100644 index 00000000000..81dd4b8e758 --- /dev/null +++ b/e2e-playwright/dashboards/DashboardForConditionalRendering.json @@ -0,0 +1,491 @@ +{ + "apiVersion": "dashboard.grafana.app/v2beta1", + "kind": "Dashboard", + "metadata": { + "name": "adtbh3z", + "namespace": "default", + "uid": "l3FuRuXP1JYJT4L98cvFa41mh7nr4qjyQiO3wXAY5N8X", + "resourceVersion": "11", + "generation": 11, + "creationTimestamp": "2025-08-25T11:33:54Z", + "labels": { + "grafana.app/deprecatedInternalID": "148" + }, + "annotations": { + "grafana.app/createdBy": "user:u000000001", + "grafana.app/updatedBy": "user:u000000001", + "grafana.app/updatedTimestamp": "2025-08-25T13:23:31Z", + "grafana.app/folder": "" + } + }, + "spec": { + "annotations": [], + "cursorSync": "Off", + "description": "", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 1, + "links": [], + "title": "Panel 1", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-2": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 2, + "links": [], + "title": "Panel 2", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-3": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 3, + "links": [], + "title": "Panel 3", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + } + }, + "layout": { + "kind": "TabsLayout", + "spec": { + "tabs": [ + { + "kind": "TabsLayoutTab", + "spec": { + "layout": { + "kind": "RowsLayout", + "spec": { + "rows": [ + { + "kind": "RowsLayoutRow", + "spec": { + "collapse": false, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row 1" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-2" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row 2" + } + } + ] + } + }, + "title": "Tab 1" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-3" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab 2" + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": true, + "tags": [], + "timeSettings": { + "autoRefresh": "", + "autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], + "fiscalYearStartMonth": 0, + "from": "now-6h", + "hideTimepicker": false, + "timezone": "browser", + "to": "now" + }, + "title": "New dashboard for conditional rendering", + "variables": [ + { + "kind": "TextVariable", + "spec": { + "current": { + "text": "", + "value": "" + }, + "hide": "dontHide", + "name": "myVariable", + "query": "", + "skipUrlSync": false + } + } + ] + }, + "status": {} +} diff --git a/e2e-playwright/dashboards/DashboardWithAllConditionalRendering.json b/e2e-playwright/dashboards/DashboardWithAllConditionalRendering.json new file mode 100644 index 00000000000..f0d81daa233 --- /dev/null +++ b/e2e-playwright/dashboards/DashboardWithAllConditionalRendering.json @@ -0,0 +1,5129 @@ +{ + "apiVersion": "dashboard.grafana.app/v2beta1", + "kind": "Dashboard", + "metadata": { + "name": "adtbg2z", + "namespace": "default", + "uid": "l3FuRuXP1JYJT4L98cvFa41mh7nr4qjyQiO3wXAY5N8X", + "resourceVersion": "11", + "generation": 11, + "creationTimestamp": "2025-08-25T11:33:54Z", + "labels": { + "grafana.app/deprecatedInternalID": "148" + }, + "annotations": { + "grafana.app/createdBy": "user:u000000001", + "grafana.app/updatedBy": "user:u000000001", + "grafana.app/updatedTimestamp": "2025-08-25T13:23:31Z", + "grafana.app/folder": "" + } + }, + "spec": { + "annotations": [], + "cursorSync": "Off", + "description": "", + "editable": true, + "elements": { + "panel-1": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 1, + "links": [], + "title": "Panel - no conditional rendering", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-10": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 10, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-11": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 11, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-12": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 12, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-13": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 13, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-14": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 14, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-15": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 15, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-16": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 16, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-17": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 17, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-18": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 18, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-19": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 19, + "links": [], + "title": "Panel - show - variable - not equals 1,2,3", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-2": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 2, + "links": [], + "title": "Panel - show - data", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-20": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 20, + "links": [], + "title": "Panel - hide - variable - not equals 1,2,3", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-21": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 21, + "links": [], + "title": "Panel - show - variable - matches .*2.*", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-22": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 22, + "links": [], + "title": "Panel - hide - variable - matches .*2.*", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-23": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 23, + "links": [], + "title": "Panel - show - variable - not matches .*2.*", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-24": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 24, + "links": [], + "title": "Panel - hide - variable - not matches .*2.*", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-25": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 25, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-26": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 26, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-27": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 27, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-28": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 28, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-29": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 29, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-3": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 3, + "links": [], + "title": "Panel - hide - data", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-30": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 30, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-31": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 31, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-32": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 32, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-33": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 33, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-34": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 34, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-35": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 35, + "links": [], + "title": "Panel - show - time range <7d", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-36": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 36, + "links": [], + "title": "Panel - hide - time range <7d", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-4": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 4, + "links": [], + "title": "Panel - show - no data", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-5": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 5, + "links": [], + "title": "Panel - hide - no data", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-7": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 7, + "links": [], + "title": "Panel - show - variable - equals 1,2,3", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-8": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": { + "errorType": "server_panic", + "scenarioId": "server_error_500", + "stringInput": "$myVariable" + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 8, + "links": [], + "title": "Panel - hide - variable - equals 1,2,3", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + }, + "panel-9": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "gdev-testdata" + }, + "group": "grafana-testdata-datasource", + "kind": "DataQuery", + "spec": {}, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "", + "id": 9, + "links": [], + "title": "Panel", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + } + }, + "version": "12.2.0-pre" + } + } + } + }, + "layout": { + "kind": "TabsLayout", + "spec": { + "tabs": [ + { + "kind": "TabsLayoutTab", + "spec": { + "layout": { + "kind": "RowsLayout", + "spec": { + "rows": [ + { + "kind": "RowsLayoutRow", + "spec": { + "collapse": false, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-1" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingData", + "spec": { + "value": true + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-2" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingData", + "spec": { + "value": true + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-3" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingData", + "spec": { + "value": false + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-4" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingData", + "spec": { + "value": false + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-5" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "equals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-7" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "equals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-8" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notEquals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-19" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notEquals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-20" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "matches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-21" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "matches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-22" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notMatches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-23" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notMatches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-24" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "7d" + } + } + ], + "visibility": "show" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-35" + } + } + }, + { + "kind": "AutoGridLayoutItem", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "7d" + } + } + ], + "visibility": "hide" + } + }, + "element": { + "kind": "ElementReference", + "name": "panel-36" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - no conditional rendering" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "equals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-9" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - show - variable - equals 1,2,3" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "equals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-10" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - hide - variable - equals 1,2,3" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notEquals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-11" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - show - variable - not equals 1,2,3" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notEquals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-12" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - hide - variable - not equals 1,2,3" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "matches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-13" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - show - variable - matches .*2.*" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "matches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-14" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - hide - variable - matches .*2.*" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notMatches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-15" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - show - variable - not matches .*2.*" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notMatches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-16" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - hide - variable - not matches .*2.*" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "7d" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-17" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - show - time range <7d" + } + }, + { + "kind": "RowsLayoutRow", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "7d" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-18" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Row - hide - time range <7d" + } + } + ] + } + }, + "title": "Tab - no conditional rendering" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "equals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-25" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - show - variable - equals 1,2,3" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "equals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-26" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - hide - variable - equals 1,2,3" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notEquals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-27" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - show - variable - not equals 1,2,3" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notEquals", + "value": "1,2,3", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-28" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - hide - variable - not equals 1,2,3" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "matches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-29" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - show - variable - matches .*2.*" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "matches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-30" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - hide - variable - matches .*2.*" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notMatches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-31" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - show - variable - not matches .*2.*" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingVariable", + "spec": { + "operator": "notMatches", + "value": ".*2.*", + "variable": "myVariable" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-32" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - hide - variable - not matches .*2.*" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "7d" + } + } + ], + "visibility": "show" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-33" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - show - time range <7d" + } + }, + { + "kind": "TabsLayoutTab", + "spec": { + "conditionalRendering": { + "kind": "ConditionalRenderingGroup", + "spec": { + "condition": "and", + "items": [ + { + "kind": "ConditionalRenderingTimeRangeSize", + "spec": { + "value": "7d" + } + } + ], + "visibility": "hide" + } + }, + "layout": { + "kind": "AutoGridLayout", + "spec": { + "columnWidthMode": "standard", + "items": [ + { + "kind": "AutoGridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-34" + } + } + } + ], + "maxColumnCount": 3, + "rowHeightMode": "standard" + } + }, + "title": "Tab - hide - time range <7d" + } + } + ] + } + }, + "links": [], + "liveNow": false, + "preload": true, + "tags": [], + "timeSettings": { + "autoRefresh": "", + "autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], + "fiscalYearStartMonth": 0, + "from": "now-6h", + "hideTimepicker": false, + "timezone": "browser", + "to": "now" + }, + "title": "New dashboard all conditional rendering", + "variables": [ + { + "kind": "TextVariable", + "spec": { + "current": { + "text": "", + "value": "" + }, + "hide": "dontHide", + "name": "myVariable", + "query": "", + "skipUrlSync": false + } + } + ] + }, + "status": {} +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRendering.tsx b/public/app/features/dashboard-scene/conditional-rendering/ConditionalRendering.tsx deleted file mode 100644 index afbcbda926a..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRendering.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { t } from '@grafana/i18n'; -import { SceneComponentProps, sceneGraph, SceneObject, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; -import { ConditionalRenderingGroupKind } from '@grafana/schema/dist/esm/schema/dashboard/v2'; - -import { ConditionalRenderingChangedEvent } from '../edit-pane/shared'; - -import { ConditionalRenderingBase } from './ConditionalRenderingBase'; -import { ConditionalRenderingGroup } from './ConditionalRenderingGroup'; -import { ItemsWithConditionalRendering } from './types'; -import { getItemType, translatedItemType } from './utils'; - -export interface ConditionalRenderingState extends SceneObjectState { - rootGroup: ConditionalRenderingGroup; -} - -export class ConditionalRendering extends SceneObjectBase { - public static Component = ConditionalRenderingRenderer; - - public get info(): string { - return t( - 'dashboard.conditional-rendering.root.info', - 'Set rules to control {{type}} visibility by matching any or all rules.', - { type: translatedItemType(this.getItemType()) } - ); - } - - public constructor(state: ConditionalRenderingState) { - super(state); - - this.addActivationHandler(() => this._activationHandler()); - } - - private _activationHandler() { - // This ensures that all children are activated when conditional rendering is activated - // We need this to allow children to subscribe to variable changes etc. - this.forEachChild((child) => { - if (!child.isActive) { - this._subs.add(child.activate()); - } - }); - } - - public evaluate(): boolean { - return this.state.rootGroup.evaluate(); - } - - public notifyChange() { - this.parent?.forceRender(); - this.parent?.publishEvent(new ConditionalRenderingChangedEvent(this), true); - } - - public deleteItem(item: T) { - sceneGraph.getAncestor(item, ConditionalRenderingGroup).removeItem(item.state.key!); - } - - public serialize(): ConditionalRenderingGroupKind { - return this.state.rootGroup.serialize(); - } - - public getItem(): SceneObject { - return this.parent!; - } - - public getItemType(): ItemsWithConditionalRendering { - return getItemType(this.getItem()); - } - - public static createEmpty(): ConditionalRendering { - return new ConditionalRendering({ rootGroup: ConditionalRenderingGroup.createEmpty() }); - } -} - -function ConditionalRenderingRenderer({ model }: SceneComponentProps) { - const { rootGroup } = model.useState(); - - return rootGroup.render(false); -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingBase.tsx b/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingBase.tsx deleted file mode 100644 index 96c5fdde371..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingBase.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { ReactElement } from 'react'; - -import { Trans, t } from '@grafana/i18n'; -import { SceneComponentProps, sceneGraph, SceneObject, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; -import { Alert, Icon, IconButton, Stack, Text, Tooltip } from '@grafana/ui'; - -import { dashboardEditActions } from '../edit-pane/shared'; - -import { ConditionalRendering } from './ConditionalRendering'; -import { ConditionalRenderingGroup } from './ConditionalRenderingGroup'; -import { - ConditionalRenderingConditions, - ConditionalRenderingKindTypes, - ConditionValues, - ItemsWithConditionalRendering, -} from './types'; - -export interface ConditionalRenderingBaseState extends SceneObjectState { - value: V; -} - -export abstract class ConditionalRenderingBase< - S extends ConditionalRenderingBaseState = ConditionalRenderingBaseState, -> extends SceneObjectBase { - public constructor(state: S) { - super(state); - - this.addActivationHandler(() => this._baseActivationHandler()); - } - - private _baseActivationHandler() { - // Similarly to the ConditionalRendering activation handler, - // this ensures that all children are activated when conditional rendering is activated - // We need this to allow children to subscribe to variable changes, etc. - this.forEachChild((child) => { - if (!child.isActive) { - this._subs.add(child.activate()); - } - }); - } - - public readonly supportedItemTypes: ItemsWithConditionalRendering[] | undefined = undefined; - - public abstract readonly title: string; - - public abstract get info(): string | undefined; - - public abstract serialize(): ConditionalRenderingKindTypes; - - public abstract evaluate(): boolean; - - public onDelete() { - this._getConditionalLogicRoot().deleteItem(this); - } - - public render(withWrapper = true): ReactElement { - return ; - } - - public getItem(): SceneObject { - return this._getConditionalLogicRoot().getItem(); - } - - public getItemType(): ItemsWithConditionalRendering { - return this._getConditionalLogicRoot().getItemType(); - } - - public isItemSupported(): boolean { - if (!this.supportedItemTypes) { - return true; - } - - return this.supportedItemTypes.includes(this.getItemType()); - } - - public notifyChange() { - this._getConditionalLogicRoot().notifyChange(); - } - - public setStateAndNotify(state: Partial) { - this.setState(state); - this.notifyChange(); - } - - public findRule() { - return this.getRenderingGroup().getRule(this.state.key!); - } - - public undoDeleted(index: number, rule: ConditionalRenderingConditions) { - const group = this.getRenderingGroup(); - const restoredState = [...group.state.value]; - restoredState.splice(index, 0, rule); - group.setStateAndNotify({ value: restoredState }); - } - - private getRenderingGroup(): ConditionalRenderingGroup { - // TODO: Adjust once nested rules are introduced to get relevant ConditionalRenderingGroup - return this._getConditionalLogicRoot().state.rootGroup; - } - - private _getConditionalLogicRoot(): ConditionalRendering { - return sceneGraph.getAncestor(this, ConditionalRendering); - } -} - -function ConditionalRenderingBaseRenderer({ - model, - withWrapper, -}: SceneComponentProps & { withWrapper: boolean }) { - const comp = ; - - if (!withWrapper) { - return comp; - } - - return ( - - - {model.title} - {model.info && ( - - - - )} - - - - - {comp} - {!model.isItemSupported() && ( - - - This condition is not supported by the element, hence it will be ignored. - - - )} - - - { - const { rule, ruleIndex } = model.findRule(); - - dashboardEditActions.edit({ - description: t('dashboard.conditional-rendering.conditions.shared.delete-condition', 'Delete Condition'), - source: model, - perform: () => model.onDelete(), - undo: () => { - if (rule) { - model.undoDeleted(ruleIndex, rule); - } - }, - }); - }} - /> - - - ); -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingData.tsx b/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingData.tsx deleted file mode 100644 index 930fcd500f0..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingData.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { useMemo } from 'react'; - -import { PanelData } from '@grafana/data'; -import { t } from '@grafana/i18n'; -import { SceneComponentProps, sceneGraph } from '@grafana/scenes'; -import { ConditionalRenderingDataKind } from '@grafana/schema/dist/esm/schema/dashboard/v2'; -import { Combobox, ComboboxOption } from '@grafana/ui'; - -import { dashboardEditActions } from '../edit-pane/shared'; -import { AutoGridItem } from '../scene/layout-auto-grid/AutoGridItem'; - -import { ConditionalRenderingBase, ConditionalRenderingBaseState } from './ConditionalRenderingBase'; -import { ConditionalRenderingSerializerRegistryItem, DataConditionValue, ItemsWithConditionalRendering } from './types'; -import { translatedItemType } from './utils'; - -type ConditionalRenderingDataState = ConditionalRenderingBaseState; - -export class ConditionalRenderingData extends ConditionalRenderingBase { - public static Component = ConditionalRenderingDataRenderer; - - public static serializer: ConditionalRenderingSerializerRegistryItem = { - id: 'ConditionalRenderingData', - name: 'Data', - deserialize: this.deserialize, - }; - - public readonly supportedItemTypes: ItemsWithConditionalRendering[] = ['panel']; - - public get title(): string { - return t('dashboard.conditional-rendering.conditions.data.label', 'Query result'); - } - - public get info(): string { - return t( - 'dashboard.conditional-rendering.conditions.data.info', - 'Show or hide the {{type}} based on query results.', - { type: translatedItemType(this.getItemType()) } - ); - } - - public constructor(state: ConditionalRenderingDataState) { - super(state); - - this.addActivationHandler(() => this._activationHandler()); - } - - private _activationHandler() { - if (!this.isItemSupported()) { - return; - } - - const item = this.getItem(); - - if (item instanceof AutoGridItem) { - const dataProvider = sceneGraph.getData(item.state.body); - - if (!dataProvider) { - return; - } - - this._subs.add(dataProvider.subscribeToState(() => this.notifyChange())); - } - } - - public evaluate(): boolean { - if (!this.isItemSupported()) { - return true; - } - - const hasData = this._hasData(); - return (this.state.value && hasData) || (!this.state.value && !hasData); - } - - public serialize(): ConditionalRenderingDataKind { - return { kind: 'ConditionalRenderingData', spec: { value: this.state.value } }; - } - - private _hasData(): boolean { - const item = this.getItem(); - - let data: PanelData | undefined; - - if (item instanceof AutoGridItem) { - data = sceneGraph.getData(item.state.body).state.data; - } - - if (!data) { - return false; - } - - const series = data?.series ?? []; - - for (let seriesIdx = 0; seriesIdx < series.length; seriesIdx++) { - if (series[seriesIdx].length > 0) { - return true; - } - } - - return false; - } - - public static deserialize(model: ConditionalRenderingDataKind): ConditionalRenderingData { - return new ConditionalRenderingData({ value: model.spec.value }); - } - - public static createEmpty(): ConditionalRenderingData { - return new ConditionalRenderingData({ value: true }); - } -} - -function ConditionalRenderingDataRenderer({ model }: SceneComponentProps) { - const { value } = model.useState(); - - const enableConditionOptions: Array> = useMemo( - () => [ - { label: t('dashboard.conditional-rendering.conditions.data.enable', 'Has data'), value: 1 }, - { label: t('dashboard.conditional-rendering.conditions.data.disable', 'No data'), value: 0 }, - ], - [] - ); - - const enableConditionOption = useMemo( - () => enableConditionOptions.find((option) => Boolean(option.value) === value) ?? enableConditionOptions[0], - [enableConditionOptions, value] - ); - - return ( - { - dashboardEditActions.edit({ - description: t('dashboard.edit-actions.edit-query-result-rule', 'Change query result rule'), - source: model, - perform: () => model.setStateAndNotify({ value: Boolean(val) }), - undo: () => model.setStateAndNotify({ value }), - }); - }} - /> - ); -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroup.tsx b/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroup.tsx deleted file mode 100644 index 59fdccbd190..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroup.tsx +++ /dev/null @@ -1,204 +0,0 @@ -import { capitalize, lowerCase } from 'lodash'; -import { useMemo } from 'react'; - -import { t } from '@grafana/i18n'; -import { SceneComponentProps, sceneGraph } from '@grafana/scenes'; -import { ConditionalRenderingGroupKind } from '@grafana/schema/dist/esm/schema/dashboard/v2'; -import { Stack } from '@grafana/ui'; - -import { dashboardEditActions } from '../edit-pane/shared'; - -import { ConditionalRenderingBase, ConditionalRenderingBaseState } from './ConditionalRenderingBase'; -import { ConditionalRenderingData } from './ConditionalRenderingData'; -import { ConditionalRenderingGroupAdd } from './ConditionalRenderingGroupAdd'; -import { ConditionalRenderingGroupCondition } from './ConditionalRenderingGroupCondition'; -import { ConditionalRenderingGroupVisibility } from './ConditionalRenderingGroupVisibility'; -import { ConditionalRenderingTimeRangeSize } from './ConditionalRenderingTimeRangeSize'; -import { ConditionalRenderingVariable } from './ConditionalRenderingVariable'; -import { conditionalRenderingSerializerRegistry } from './serializers'; -import { - ConditionalRenderingKindTypes, - ConditionalRenderingSerializerRegistryItem, - GroupConditionCondition, - GroupConditionItemType, - GroupConditionVisibility, - GroupConditionValue, - ConditionalRenderingConditions, -} from './types'; -import { translatedItemType } from './utils'; - -export interface ConditionalRenderingGroupState extends ConditionalRenderingBaseState { - visibility: GroupConditionVisibility; - condition: GroupConditionCondition; -} - -export class ConditionalRenderingGroup extends ConditionalRenderingBase { - public static Component = ConditionalRenderingGroupRenderer; - - public static serializer: ConditionalRenderingSerializerRegistryItem = { - id: 'ConditionalRenderingGroup', - name: 'Group', - deserialize: this.deserialize, - }; - - public get title(): string { - return t('dashboard.conditional-rendering.conditions.group.label', 'Group'); - } - - public get info(): undefined { - return undefined; - } - - public evaluate(): boolean { - if (this.state.value.length === 0) { - return true; - } - - const value = - this.state.condition === 'and' - ? this.state.value.every((entry) => entry.evaluate()) - : this.state.value.some((entry) => entry.evaluate()); - - return this.state.visibility === 'show' ? value : !value; - } - - public changeVisibility(visibility: GroupConditionVisibility) { - this.setStateAndNotify({ visibility }); - } - - public changeCondition(condition: GroupConditionCondition) { - this.setStateAndNotify({ condition }); - } - - public createItem(itemType: GroupConditionItemType): ConditionalRenderingConditions { - switch (itemType) { - case 'data': - return ConditionalRenderingData.createEmpty(); - - case 'timeRangeSize': - return ConditionalRenderingTimeRangeSize.createEmpty(); - - case 'variable': - return ConditionalRenderingVariable.createEmpty(sceneGraph.getVariables(this).state.variables[0].state.name); - } - } - - public addItem(item: ConditionalRenderingConditions) { - // We don't use `setStateAndNotify` here because - // We need to set a parent and activate the new condition before notifying the root - this.setState({ value: [...this.state.value, item] }); - - if (this.isActive && !item.isActive) { - item.activate(); - } - - this.notifyChange(); - } - - public removeItem(key: string) { - this.setStateAndNotify({ value: this.state.value.filter((condition) => condition.state.key !== key) }); - } - - public removeLastItem() { - const newValues = [...this.state.value]; - newValues.pop(); - this.setStateAndNotify({ value: newValues }); - } - - public getRule(key: string) { - const ruleIndex = this.state.value.findIndex((rule) => rule.state.key === key); - const rule = this.state.value[ruleIndex]; - return { rule, ruleIndex }; - } - - public serialize(): ConditionalRenderingGroupKind { - if (this.state.value.some((item) => item instanceof ConditionalRenderingGroup)) { - throw new Error('ConditionalRenderingGroup cannot contain nested ConditionalRenderingGroups'); - } - - return { - kind: 'ConditionalRenderingGroup', - spec: { - visibility: this.state.visibility, - condition: this.state.condition, - items: this.state.value - .map((condition) => condition.serialize()) - .filter((item) => item.kind !== 'ConditionalRenderingGroup'), - }, - }; - } - - public static deserialize(model: ConditionalRenderingGroupKind): ConditionalRenderingGroup { - return new ConditionalRenderingGroup({ - condition: model.spec.condition, - visibility: model.spec.visibility, - value: model.spec.items.map((item: ConditionalRenderingKindTypes) => { - const serializerRegistryItem = conditionalRenderingSerializerRegistry.getIfExists(item.kind); - - if (!serializerRegistryItem) { - throw new Error(`No serializer found for conditional rendering kind: ${item.kind}`); - } - - return serializerRegistryItem.deserialize(item); - }), - }); - } - - public static createEmpty(): ConditionalRenderingGroup { - return new ConditionalRenderingGroup({ condition: 'and', visibility: 'show', value: [] }); - } -} - -function ConditionalRenderingGroupRenderer({ model }: SceneComponentProps) { - const { condition, visibility, value } = model.useState(); - const { variables } = sceneGraph.getVariables(model).useState(); - const itemType = useMemo(() => model.getItemType(), [model]); - - return ( - - { - dashboardEditActions.edit({ - description: t('dashboard.conditional-rendering.conditions.group.visibility.label', '{{type}} visibility', { - type: capitalize(translatedItemType(itemType)), - }), - source: model, - perform: () => model.changeVisibility(value), - undo: () => model.changeVisibility(visibility), - }); - }} - /> - {value.length > 1 && ( - { - dashboardEditActions.edit({ - description: t('dashboard.conditional-rendering.conditions.group.condition.label', 'Match rules'), - source: model, - perform: () => model.changeCondition(value), - undo: () => model.changeCondition(condition), - }); - }} - /> - )} - {value.map((entry) => entry.render())} - 0} - onAdd={({ value, label }) => { - const item = model.createItem(value!); - dashboardEditActions.edit({ - description: t('dashboard.edit-actions.add-conditional-rule', 'Add {{ruleDescription}} rule', { - ruleDescription: lowerCase(label), - }), - source: model, - perform: () => model.addItem(item), - undo: () => model.removeLastItem(), - }); - }} - /> - - ); -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingVariable.tsx b/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingVariable.tsx deleted file mode 100644 index 1b074c8c149..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingVariable.tsx +++ /dev/null @@ -1,256 +0,0 @@ -import { useEffect, useMemo, useState } from 'react'; - -import { t } from '@grafana/i18n'; -import { SceneComponentProps, sceneGraph, VariableDependencyConfig } from '@grafana/scenes'; -import { - ConditionalRenderingVariableKind, - ConditionalRenderingVariableSpec, -} from '@grafana/schema/dist/esm/schema/dashboard/v2'; -import { Box, Combobox, ComboboxOption, Field, Input, Stack } from '@grafana/ui'; - -import { dashboardEditActions } from '../edit-pane/shared'; - -import { ConditionalRenderingBase, ConditionalRenderingBaseState } from './ConditionalRenderingBase'; -import { - ConditionalRenderingSerializerRegistryItem, - VariableConditionValue, - VariableConditionValueOperator, -} from './types'; -import { translatedItemType } from './utils'; - -type ConditionalRenderingVariableState = ConditionalRenderingBaseState; - -export class ConditionalRenderingVariable extends ConditionalRenderingBase { - public static Component = ConditionalRenderingVariableRenderer; - - public static serializer: ConditionalRenderingSerializerRegistryItem = { - id: 'ConditionalRenderingVariable', - name: 'Variable', - deserialize: this.deserialize, - }; - - public get title(): string { - return t('dashboard.conditional-rendering.conditions.variable.label', 'Template variable'); - } - - public get info(): string { - return t( - 'dashboard.conditional-rendering.conditions.variable.info', - 'Show or hide the {{type}} dynamically based on the variable value.', - { type: translatedItemType(this.getItemType()) } - ); - } - - protected _variableDependency = new VariableDependencyConfig(this, { - onAnyVariableChanged: (v) => { - if (v.state.name === this.state.value.name) { - this.notifyChange(); - } - }, - }); - - public evaluate(): boolean { - if (!this.state.value.name) { - return true; - } - - const variable = sceneGraph.getVariables(this).getByName(this.state.value.name); - - if (!variable) { - return true; - } - - const variableValue = variable.getValue() ?? ''; - - let hit: boolean; - - if (this.state.value.operator === '=' || this.state.value.operator === '!=') { - hit = Array.isArray(variableValue) - ? variableValue.includes(this.state.value.value.toString()) - : variableValue === this.state.value.value.toString(); - } else { - try { - const regex = new RegExp(this.state.value.value); - hit = Array.isArray(variableValue) - ? variableValue.some((currentVariableValue) => regex.test(currentVariableValue.toString())) - : regex.test(variableValue.toString()); - } catch (err) { - return true; - } - } - - return this.state.value.operator === '!=' || this.state.value.operator === '!~' ? !hit : hit; - } - - public serialize(): ConditionalRenderingVariableKind { - return { - kind: 'ConditionalRenderingVariable', - spec: { - variable: this.state.value.name, - operator: this._getLongOperator(this.state.value.operator), - value: this.state.value.value, - }, - }; - } - - public static deserialize(model: ConditionalRenderingVariableKind): ConditionalRenderingVariable { - return new ConditionalRenderingVariable({ - value: { - name: model.spec.variable, - operator: ConditionalRenderingVariable._getShortOperator(model.spec.operator), - value: model.spec.value, - }, - }); - } - - public static createEmpty(name: string): ConditionalRenderingVariable { - return new ConditionalRenderingVariable({ value: { name, operator: '=', value: '' } }); - } - - private _getLongOperator(operator: VariableConditionValueOperator): ConditionalRenderingVariableSpec['operator'] { - switch (operator) { - case '=': - return 'equals'; - - case '!=': - return 'notEquals'; - - case '=~': - return 'matches'; - - case '!~': - return 'notMatches'; - } - } - - private static _getShortOperator( - operator: ConditionalRenderingVariableSpec['operator'] - ): VariableConditionValueOperator { - switch (operator) { - case 'equals': - return '='; - - case 'notEquals': - return '!='; - - case 'matches': - return '=~'; - - case 'notMatches': - return '!~'; - } - } -} - -function ConditionalRenderingVariableRenderer({ model }: SceneComponentProps) { - const { value } = model.useState(); - - const [actualValue, setActualValue] = useState(value.value); - - useEffect(() => { - setActualValue(value.value); - }, [value.value]); - - const variables = useMemo(() => sceneGraph.getVariables(model), [model]); - - const variableNames: ComboboxOption[] = useMemo( - () => variables.state.variables.map((v) => ({ value: v.state.name, label: v.state.label ?? v.state.name })), - [variables.state.variables] - ); - - const operatorOptions: Array> = useMemo( - () => [ - { value: '=', description: t('dashboard.conditional-rendering.conditions.variable.operator.equals', 'Equals') }, - { - value: '!=', - description: t('dashboard.conditional-rendering.conditions.variable.operator.not-equals', 'Not equals'), - }, - { - value: '=~', - description: t('dashboard.conditional-rendering.conditions.variable.operator.matches', 'Matches'), - }, - { - value: '!~', - description: t('dashboard.conditional-rendering.conditions.variable.operator.not-matches', 'Not matches'), - }, - ], - [] - ); - - const valueError = useMemo(() => { - if (value.operator === '=~' || value.operator === '!~') { - try { - new RegExp(actualValue); - return ''; - } catch (err) { - return t('dashboard.conditional-rendering.conditions.variable.error.invalid-regex', 'Invalid regex'); - } - } - - return ''; - }, [actualValue, value.operator]); - - const undoText = t('dashboard.edit-actions.edit-template-variable-rule', 'Change template variable rule'); - - return ( - - - - { - if (option.value !== value.name) { - dashboardEditActions.edit({ - description: undoText, - source: model, - perform: () => model.setStateAndNotify({ value: { ...value, name: option.value } }), - undo: () => model.setStateAndNotify({ value: { ...value, name: value.name } }), - }); - } - }} - /> - - - { - if (option.value !== value.operator) { - dashboardEditActions.edit({ - description: undoText, - source: model, - perform: () => model.setStateAndNotify({ value: { ...value, operator: option.value } }), - undo: () => model.setStateAndNotify({ value: { ...value, operator: value.operator } }), - }); - } - }} - /> - - - { - if (evt.currentTarget.value !== value.value) { - setActualValue(evt.currentTarget.value); - } - }} - onBlur={() => { - if (actualValue !== value.value) { - dashboardEditActions.edit({ - description: undoText, - source: model, - perform: () => model.setStateAndNotify({ value: { ...value, value: actualValue } }), - undo: () => model.setStateAndNotify({ value: { ...value, value: value.value } }), - }); - } - }} - /> - - - ); -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingConditionWrapper.tsx b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingConditionWrapper.tsx new file mode 100644 index 00000000000..3320f2478d7 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingConditionWrapper.tsx @@ -0,0 +1,64 @@ +import { ReactNode } from 'react'; + +import { t, Trans } from '@grafana/i18n'; +import { Alert, Icon, IconButton, Stack, Text, Tooltip } from '@grafana/ui'; + +import { dashboardEditActions } from '../../edit-pane/shared'; + +import { ConditionalRenderingConditions } from './types'; +import { getConditionIndex, removeCondition, undoRemoveCondition } from './utils'; + +interface Props { + children: ReactNode; + info: string; + isObjectSupported: boolean; + model: ConditionalRenderingConditions; + title: string; +} + +export function ConditionalRenderingConditionWrapper({ children, info, isObjectSupported, model, title }: Props) { + return ( + + + {title} + {info && ( + + + + )} + + + + + {children} + {!isObjectSupported && ( + + + This condition is not supported by the element, hence it will be ignored. + + + )} + + + { + const index = getConditionIndex(model); + + dashboardEditActions.edit({ + description: t('dashboard.conditional-rendering.conditions.wrapper.delete-condition', 'Delete Condition'), + source: model, + perform: () => removeCondition(model), + undo: () => { + if (index > -1) { + undoRemoveCondition(model, index); + } + }, + }); + }} + /> + + + ); +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingData.tsx b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingData.tsx new file mode 100644 index 00000000000..bb366768d06 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingData.tsx @@ -0,0 +1,196 @@ +import { ReactElement, useMemo } from 'react'; + +import { LoadingState } from '@grafana/data'; +import { t } from '@grafana/i18n'; +import { + CancelActivationHandler, + SceneComponentProps, + SceneDataProvider, + sceneGraph, + SceneObjectBase, + SceneObjectState, + VizPanel, +} from '@grafana/scenes'; +import { ConditionalRenderingDataKind } from '@grafana/schema/dist/esm/schema/dashboard/v2'; +import { Combobox, ComboboxOption } from '@grafana/ui'; + +import { dashboardEditActions } from '../../edit-pane/shared'; +import { getLowerTranslatedObjectType } from '../object'; + +import { ConditionalRenderingConditionWrapper } from './ConditionalRenderingConditionWrapper'; +import { ConditionalRenderingConditionsSerializerRegistryItem } from './serializers'; +import { checkGroup, getObject, getObjectType } from './utils'; + +interface ConditionalRenderingDataState extends SceneObjectState { + value: boolean; + result: boolean | undefined; +} + +export class ConditionalRenderingData extends SceneObjectBase { + public static Component = ConditionalRenderingDataRenderer; + + public static serializer: ConditionalRenderingConditionsSerializerRegistryItem = { + id: 'ConditionalRenderingData', + name: 'Data', + deserialize: this.deserialize, + }; + + private _dataProvider: SceneDataProvider | undefined = undefined; + + public constructor(state: ConditionalRenderingDataState) { + super(state); + + this.addActivationHandler(() => this._activationHandler()); + } + + private _activationHandler() { + this.forEachChild((child) => { + if (!child.isActive) { + this._subs.add(child.activate()); + } + }); + + this._dataProvider = this._getObjectDataProvider(); + + if (!this._dataProvider) { + return; + } + + // Be sure to activate the data provider so it doesn't get deactivated on item unmount + const dpDeactivate: CancelActivationHandler = this._dataProvider.activate(); + + this._check(); + + this._subs.add(this._dataProvider.subscribeToState(() => this._check())); + + return () => { + dpDeactivate?.(); + }; + } + + private _getObjectDataProvider(): SceneDataProvider | undefined { + const object = getObject(this); + + if (!object) { + return undefined; + } + + let panel: VizPanel | undefined; + + for (const val of Object.values(object.state)) { + if (val instanceof VizPanel) { + panel = val; + break; + } + } + + if (!panel) { + return undefined; + } + + return sceneGraph.getData(panel) ?? undefined; + } + + private _check() { + const result = this._evaluate(); + + if (result !== this.state.result) { + this.setState({ ...this.state, result }); + checkGroup(this); + } + } + + private _evaluate(): boolean | undefined { + if ( + !this._dataProvider || + !this._dataProvider.state.data || + this._dataProvider.state.data.state === LoadingState.Loading || + this._dataProvider.state.data.state === LoadingState.NotStarted + ) { + return undefined; + } + + const series = this._dataProvider?.state.data?.series ?? []; + let hasData = false; + + for (let seriesIdx = 0; seriesIdx < series.length; seriesIdx++) { + if (series[seriesIdx].length > 0) { + hasData = true; + break; + } + } + + // The logic here is pretty simple: + // If value is true (meaning "has data"), then we check if the object has data + // If value is false (meaning "no data"), then we check if the object doesn't have data + return this.state.value === hasData; + } + + public changeValue(value: boolean) { + if (this.state.value !== value) { + this.setState({ value }); + this._check(); + } + } + + public render(): ReactElement { + return ; + } + + public serialize(): ConditionalRenderingDataKind { + return { kind: 'ConditionalRenderingData', spec: { value: this.state.value } }; + } + + public static deserialize(model: ConditionalRenderingDataKind): ConditionalRenderingData { + return new ConditionalRenderingData({ value: model.spec.value, result: undefined }); + } + + public static createEmpty(): ConditionalRenderingData { + return new ConditionalRenderingData({ value: true, result: undefined }); + } +} + +function ConditionalRenderingDataRenderer({ model }: SceneComponentProps) { + const { value } = model.useState(); + + const enableConditionOptions: Array> = useMemo( + () => [ + { label: t('dashboard.conditional-rendering.conditions.data.enable', 'Has data'), value: 1 }, + { label: t('dashboard.conditional-rendering.conditions.data.disable', 'No data'), value: 0 }, + ], + [] + ); + + const enableConditionOption = useMemo( + () => enableConditionOptions.find((option) => Boolean(option.value) === value) ?? enableConditionOptions[0], + [enableConditionOptions, value] + ); + + const objectType = getObjectType(model); + + return ( + + { + dashboardEditActions.edit({ + description: t('dashboard.edit-actions.edit-query-result-rule', 'Change query result rule'), + source: model, + perform: () => model.changeValue(Boolean(newValue)), + undo: () => model.changeValue(value), + }); + }} + /> + + ); +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingTimeRangeSize.tsx b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingTimeRangeSize.tsx similarity index 60% rename from public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingTimeRangeSize.tsx rename to public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingTimeRangeSize.tsx index 82282dee713..fadd4c623e0 100644 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingTimeRangeSize.tsx +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingTimeRangeSize.tsx @@ -1,40 +1,33 @@ -import { css } from '@emotion/css'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { ReactElement, useCallback, useEffect, useMemo, useState } from 'react'; import { rangeUtil, SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; -import { SceneComponentProps, sceneGraph } from '@grafana/scenes'; +import { SceneComponentProps, sceneGraph, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; import { ConditionalRenderingTimeRangeSizeKind } from '@grafana/schema/dist/esm/schema/dashboard/v2'; -import { Field, Select, useStyles2 } from '@grafana/ui'; +import { Field, Select } from '@grafana/ui'; -import { dashboardEditActions } from '../edit-pane/shared'; +import { dashboardEditActions } from '../../edit-pane/shared'; +import { getLowerTranslatedObjectType } from '../object'; -import { ConditionalRenderingBase, ConditionalRenderingBaseState } from './ConditionalRenderingBase'; -import { ConditionalRenderingSerializerRegistryItem, TimeRangeSizeConditionValue } from './types'; -import { translatedItemType } from './utils'; +import { ConditionalRenderingConditionWrapper } from './ConditionalRenderingConditionWrapper'; +import { ConditionalRenderingConditionsSerializerRegistryItem } from './serializers'; +import { checkGroup, getObjectType } from './utils'; -type ConditionalRenderingTimeRangeSizeState = ConditionalRenderingBaseState; +interface ConditionalRenderingTimeRangeSizeState extends SceneObjectState { + value: string; + result: boolean | undefined; +} -export class ConditionalRenderingTimeRangeSize extends ConditionalRenderingBase { +export class ConditionalRenderingTimeRangeSize extends SceneObjectBase { public static Component = ConditionalRenderingTimeRangeSizeRenderer; - public static serializer: ConditionalRenderingSerializerRegistryItem = { + public static serializer: ConditionalRenderingConditionsSerializerRegistryItem = { id: 'ConditionalRenderingTimeRangeSize', name: 'Time Range Size', deserialize: this.deserialize, }; - public get title(): string { - return t('dashboard.conditional-rendering.conditions.time-range-size.label', 'Time range less than'); - } - - public get info(): string { - return t( - 'dashboard.conditional-rendering.conditions.time-range-size.info', - 'Show or hide the {{type}} if the dashboard time range is shorter than the selected time frame.', - { type: translatedItemType(this.getItemType()) } - ); - } + public readonly validateIntervalRegex = /^(\d+(?:\.\d+)?)[Mwdhmsy]$/; public constructor(state: ConditionalRenderingTimeRangeSizeState) { super(state); @@ -43,26 +36,52 @@ export class ConditionalRenderingTimeRangeSize extends ConditionalRenderingBase< } private _activationHandler() { - this._subs.add(sceneGraph.getTimeRange(this).subscribeToState(() => this.notifyChange())); + this.forEachChild((child) => { + if (!child.isActive) { + this._subs.add(child.activate()); + } + }); + + this._check(); + + this._subs.add(sceneGraph.getTimeRange(this).subscribeToState(() => this._check())); } - public evaluate(): boolean { + private _check() { + const result = this._evaluate(); + + if (result !== this.state.result) { + this.setState({ ...this.state, result }); + checkGroup(this); + } + + return result; + } + + private _evaluate(): boolean | undefined { try { - if (!validateIntervalRegex.test(this.state.value)) { - return true; + if (!this.validateIntervalRegex.test(this.state.value)) { + return undefined; } const interval = rangeUtil.intervalToSeconds(this.state.value); const timeRange = sceneGraph.getTimeRange(this); - if (timeRange.state.value.to.unix() - timeRange.state.value.from.unix() <= interval) { - return true; - } + return timeRange.state.value.to.unix() - timeRange.state.value.from.unix() <= interval; } catch { - return false; + return undefined; } + } - return false; + public changeValue(value: string) { + if (this.state.value !== value) { + this.setState({ value }); + this._check(); + } + } + + public render(): ReactElement { + return ; } public serialize(): ConditionalRenderingTimeRangeSizeKind { @@ -70,20 +89,19 @@ export class ConditionalRenderingTimeRangeSize extends ConditionalRenderingBase< } public static deserialize(model: ConditionalRenderingTimeRangeSizeKind): ConditionalRenderingTimeRangeSize { - return new ConditionalRenderingTimeRangeSize({ value: model.spec.value }); + return new ConditionalRenderingTimeRangeSize({ value: model.spec.value, result: undefined }); } public static createEmpty(): ConditionalRenderingTimeRangeSize { - return new ConditionalRenderingTimeRangeSize({ value: '7d' }); + return new ConditionalRenderingTimeRangeSize({ value: '7d', result: undefined }); } } function ConditionalRenderingTimeRangeSizeRenderer({ model }: SceneComponentProps) { const { value } = model.useState(); - const [isValid, setIsValid] = useState(validateIntervalRegex.test(value)); - const styles = useStyles2(getStyles); + const [isValid, setIsValid] = useState(model.validateIntervalRegex.test(value)); - useEffect(() => setIsValid(validateIntervalRegex.test(value)), [value]); + useEffect(() => setIsValid(model.validateIntervalRegex.test(value)), [model, value]); const staticOptions = useMemo>>( () => [ @@ -200,35 +218,38 @@ function ConditionalRenderingTimeRangeSizeRenderer({ model }: SceneComponentProp dashboardEditActions.edit({ description: t('dashboard.edit-actions.edit-time-range-rule', 'Change time range rule'), source: model, - perform: () => model.setStateAndNotify({ value: newValue }), - undo: () => model.setStateAndNotify({ value }), + perform: () => model.changeValue(newValue ?? ''), + undo: () => model.changeValue(value), }); }, [model, value] ); return ( - - handleChange(value)} + value={value} + options={options} + onChange={({ value }) => handleChange(value)} + /> + + ); } - -const getStyles = () => ({ - container: css({ - margin: 0, - }), -}); - -const validateIntervalRegex = /^(\d+(?:\.\d+)?)[Mwdhmsy]$/; diff --git a/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingVariable.tsx b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingVariable.tsx new file mode 100644 index 00000000000..39d81f80ef7 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/ConditionalRenderingVariable.tsx @@ -0,0 +1,318 @@ +import { ReactElement, useEffect, useMemo, useState } from 'react'; + +import { t } from '@grafana/i18n'; +import { + SceneComponentProps, + sceneGraph, + SceneObjectBase, + SceneObjectState, + VariableDependencyConfig, +} from '@grafana/scenes'; +import { + ConditionalRenderingVariableKind, + ConditionalRenderingVariableSpec, +} from '@grafana/schema/dist/esm/schema/dashboard/v2'; +import { Box, Combobox, ComboboxOption, Field, Input, Stack } from '@grafana/ui'; + +import { dashboardEditActions } from '../../edit-pane/shared'; +import { getDashboardSceneFor } from '../../utils/utils'; +import { getLowerTranslatedObjectType } from '../object'; + +import { ConditionalRenderingConditionWrapper } from './ConditionalRenderingConditionWrapper'; +import { ConditionalRenderingConditionsSerializerRegistryItem } from './serializers'; +import { checkGroup, getObjectType } from './utils'; + +type VariableConditionValueOperator = '=' | '!=' | '=~' | '!~'; + +interface ConditionalRenderingVariableState extends SceneObjectState { + variable: string; + operator: VariableConditionValueOperator; + value: string; + result: boolean | undefined; +} + +export class ConditionalRenderingVariable extends SceneObjectBase { + public static Component = ConditionalRenderingVariableRenderer; + + public static serializer: ConditionalRenderingConditionsSerializerRegistryItem = { + id: 'ConditionalRenderingVariable', + name: 'Variable', + deserialize: this.deserialize, + }; + + protected _variableDependency = new VariableDependencyConfig(this, { + onAnyVariableChanged: (v) => { + if (v.state.name === this.state.variable) { + this._check(); + } + }, + }); + + public constructor(state: ConditionalRenderingVariableState) { + super(state); + + this.addActivationHandler(() => this._activationHandler()); + } + + private _activationHandler() { + this.forEachChild((child) => { + if (!child.isActive) { + this._subs.add(child.activate()); + } + }); + + this._check(); + } + + public _check() { + const result = this._evaluate(); + + if (result !== this.state.result) { + this.setState({ result }); + checkGroup(this); + } + } + + private _evaluate(): boolean | undefined { + if (!this.state.variable) { + return undefined; + } + + const variable = sceneGraph.getVariables(this).getByName(this.state.variable); + + if (!variable) { + return undefined; + } + + const variableValue = variable.getValue() ?? ''; + + let hit: boolean; + + if (this.state.operator === '=' || this.state.operator === '!=') { + hit = Array.isArray(variableValue) + ? variableValue.includes(this.state.value.toString()) + : variableValue === this.state.value.toString(); + } else { + try { + const regex = new RegExp(this.state.value); + hit = Array.isArray(variableValue) + ? variableValue.some((currentVariableValue) => regex.test(currentVariableValue.toString())) + : regex.test(variableValue.toString()); + } catch (err) { + return true; + } + } + + return this.state.operator === '!=' || this.state.operator === '!~' ? !hit : hit; + } + + public changeVariable(variable: string) { + if (this.state.variable !== variable) { + this.setState({ variable }); + this._check(); + } + } + + public changeOperator(operator: VariableConditionValueOperator) { + if (this.state.operator !== operator) { + this.setState({ operator }); + this._check(); + } + } + + public changeValue(value: string) { + if (this.state.value !== value) { + this.setState({ value }); + this._check(); + } + } + + public render(): ReactElement { + return ; + } + + public serialize(): ConditionalRenderingVariableKind { + return { + kind: 'ConditionalRenderingVariable', + spec: { + variable: this.state.variable, + operator: this._getLongOperator(this.state.operator), + value: this.state.value, + }, + }; + } + + public static deserialize(model: ConditionalRenderingVariableKind): ConditionalRenderingVariable { + return new ConditionalRenderingVariable({ + variable: model.spec.variable, + operator: ConditionalRenderingVariable._getShortOperator(model.spec.operator), + value: model.spec.value, + result: undefined, + }); + } + + public static createEmpty(variable: string): ConditionalRenderingVariable { + return new ConditionalRenderingVariable({ variable, operator: '=', value: '', result: undefined }); + } + + private _getLongOperator(operator: VariableConditionValueOperator): ConditionalRenderingVariableSpec['operator'] { + switch (operator) { + case '=': + return 'equals'; + + case '!=': + return 'notEquals'; + + case '=~': + return 'matches'; + + case '!~': + return 'notMatches'; + } + } + + private static _getShortOperator( + operator: ConditionalRenderingVariableSpec['operator'] + ): VariableConditionValueOperator { + switch (operator) { + case 'equals': + return '='; + + case 'notEquals': + return '!='; + + case 'matches': + return '=~'; + + case 'notMatches': + return '!~'; + } + } +} + +function ConditionalRenderingVariableRenderer({ model }: SceneComponentProps) { + const { variable, operator, value } = model.useState(); + + const [newValue, setNewValue] = useState(value); + + useEffect(() => setNewValue(value), [value]); + + const variables = sceneGraph.getVariables(getDashboardSceneFor(model)); + + const variableNames: ComboboxOption[] = useMemo( + () => variables.state.variables.map((v) => ({ value: v.state.name, label: v.state.label ?? v.state.name })), + [variables.state.variables] + ); + + const operatorOptions: Array> = useMemo( + () => [ + { value: '=', description: t('dashboard.conditional-rendering.conditions.variable.operator.equals', 'Equals') }, + { + value: '!=', + description: t('dashboard.conditional-rendering.conditions.variable.operator.not-equals', 'Not equals'), + }, + { + value: '=~', + description: t('dashboard.conditional-rendering.conditions.variable.operator.matches', 'Matches'), + }, + { + value: '!~', + description: t('dashboard.conditional-rendering.conditions.variable.operator.not-matches', 'Not matches'), + }, + ], + [] + ); + + const valueError = useMemo(() => { + if (operator === '=~' || operator === '!~') { + try { + new RegExp(newValue); + return ''; + } catch (err) { + return t('dashboard.conditional-rendering.conditions.variable.error.invalid-regex', 'Invalid regex'); + } + } + + return ''; + }, [newValue, operator]); + + const undoText = t('dashboard.edit-actions.edit-template-variable-rule', 'Change template variable rule'); + + return ( + + + + + { + const newVariable = option.value; + + if (newVariable !== variable) { + dashboardEditActions.edit({ + description: undoText, + source: model, + perform: () => model.changeVariable(newVariable), + undo: () => model.changeVariable(variable), + }); + } + }} + /> + + + { + const newOperator = option.value; + + if (newOperator !== operator) { + dashboardEditActions.edit({ + description: undoText, + source: model, + perform: () => model.changeOperator(newOperator), + undo: () => model.changeOperator(operator), + }); + } + }} + /> + + + + { + if (evt.currentTarget.value !== value) { + setNewValue(evt.currentTarget.value); + } + }} + onBlur={() => { + if (newValue !== value) { + dashboardEditActions.edit({ + description: undoText, + source: model, + perform: () => model.changeValue(newValue), + undo: () => model.changeValue(value), + }); + } + }} + /> + + + + ); +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/conditions/serializers.ts b/public/app/features/dashboard-scene/conditional-rendering/conditions/serializers.ts new file mode 100644 index 00000000000..12e72dd7ba2 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/serializers.ts @@ -0,0 +1,29 @@ +import { Registry, RegistryItem } from '@grafana/data'; +import { + ConditionalRenderingDataKind, + ConditionalRenderingTimeRangeSizeKind, + ConditionalRenderingVariableKind, +} from '@grafana/schema/dist/esm/schema/dashboard/v2'; + +import { ConditionalRenderingData } from './ConditionalRenderingData'; +import { ConditionalRenderingTimeRangeSize } from './ConditionalRenderingTimeRangeSize'; +import { ConditionalRenderingVariable } from './ConditionalRenderingVariable'; +import { ConditionalRenderingConditions } from './types'; + +export type ConditionalRenderingConditionsKindTypes = + | ConditionalRenderingVariableKind + | ConditionalRenderingDataKind + | ConditionalRenderingTimeRangeSizeKind; + +export interface ConditionalRenderingConditionsSerializerRegistryItem extends RegistryItem { + deserialize(model: ConditionalRenderingConditionsKindTypes): ConditionalRenderingConditions; +} + +export const conditionalRenderingSerializerRegistry = + new Registry(() => { + return [ + ConditionalRenderingVariable.serializer, + ConditionalRenderingData.serializer, + ConditionalRenderingTimeRangeSize.serializer, + ]; + }); diff --git a/public/app/features/dashboard-scene/conditional-rendering/conditions/types.ts b/public/app/features/dashboard-scene/conditional-rendering/conditions/types.ts new file mode 100644 index 00000000000..8fda408f5d3 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/types.ts @@ -0,0 +1,8 @@ +import { type ConditionalRenderingData } from './ConditionalRenderingData'; +import { type ConditionalRenderingTimeRangeSize } from './ConditionalRenderingTimeRangeSize'; +import { type ConditionalRenderingVariable } from './ConditionalRenderingVariable'; + +export type ConditionalRenderingConditions = + | ConditionalRenderingVariable + | ConditionalRenderingData + | ConditionalRenderingTimeRangeSize; diff --git a/public/app/features/dashboard-scene/conditional-rendering/conditions/utils.ts b/public/app/features/dashboard-scene/conditional-rendering/conditions/utils.ts new file mode 100644 index 00000000000..af8a4110a11 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/conditions/utils.ts @@ -0,0 +1,38 @@ +import { sceneGraph, SceneObject } from '@grafana/scenes'; + +import { ConditionalRenderingGroup } from '../group/ConditionalRenderingGroup'; +import { extractObjectType, ObjectsWithConditionalRendering } from '../object'; + +import { ConditionalRenderingConditions } from './types'; + +export function getGroup(condition: ConditionalRenderingConditions): ConditionalRenderingGroup { + if (condition.parent instanceof ConditionalRenderingGroup) { + return condition.parent; + } + + return sceneGraph.getAncestor(condition, ConditionalRenderingGroup); +} + +export function getObject(condition: ConditionalRenderingConditions): SceneObject | undefined { + return getGroup(condition).parent; +} + +export function getObjectType(condition: ConditionalRenderingConditions): ObjectsWithConditionalRendering { + return extractObjectType(getObject(condition)); +} + +export function removeCondition(condition: ConditionalRenderingConditions) { + getGroup(condition).removeCondition(condition); +} + +export function undoRemoveCondition(condition: ConditionalRenderingConditions, index: number) { + getGroup(condition).undoRemoveCondition(condition, index); +} + +export function getConditionIndex(condition: ConditionalRenderingConditions): number { + return getGroup(condition).getConditionIndex(condition); +} + +export function checkGroup(condition: ConditionalRenderingConditions) { + getGroup(condition).check(); +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroup.tsx b/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroup.tsx new file mode 100644 index 00000000000..37253e0e448 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroup.tsx @@ -0,0 +1,240 @@ +import { lowerCase } from 'lodash'; +import { useMemo } from 'react'; + +import { t } from '@grafana/i18n'; +import { SceneComponentProps, sceneGraph, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; +import { ConditionalRenderingGroupKind } from '@grafana/schema/dist/esm/schema/dashboard/v2'; +import { Stack } from '@grafana/ui'; + +import { ConditionalRenderingChangedEvent, dashboardEditActions } from '../../edit-pane/shared'; +import { getDashboardSceneFor } from '../../utils/utils'; +import { ConditionalRenderingData } from '../conditions/ConditionalRenderingData'; +import { ConditionalRenderingTimeRangeSize } from '../conditions/ConditionalRenderingTimeRangeSize'; +import { ConditionalRenderingVariable } from '../conditions/ConditionalRenderingVariable'; +import { conditionalRenderingSerializerRegistry } from '../conditions/serializers'; +import { ConditionalRenderingConditions } from '../conditions/types'; +import { extractObjectType, getTranslatedObjectType } from '../object'; + +import { ConditionalRenderingGroupAdd } from './ConditionalRenderingGroupAdd'; +import { ConditionalRenderingGroupCondition } from './ConditionalRenderingGroupCondition'; +import { ConditionalRenderingGroupVisibility } from './ConditionalRenderingGroupVisibility'; +import { GroupConditionCondition, GroupConditionConditionType, GroupConditionVisibility } from './types'; + +export interface ConditionalRenderingGroupState extends SceneObjectState { + conditions: ConditionalRenderingConditions[]; + visibility: GroupConditionVisibility; + condition: GroupConditionCondition; + renderHidden: boolean; + result: boolean; +} + +export class ConditionalRenderingGroup extends SceneObjectBase { + public static Component = ConditionalRenderingGroupRenderer; + + private _shouldShow: boolean; + private _shouldMatchAll: boolean; + + public constructor(state: ConditionalRenderingGroupState) { + super(state); + this._shouldShow = state.visibility === 'show'; + this._shouldMatchAll = state.condition === 'and'; + + this.addActivationHandler(() => this._activationHandler()); + } + + private _activationHandler() { + this.forEachChild((child) => { + if (!child.isActive) { + this._subs.add(child.activate()); + } + }); + + this.check(); + } + + public check() { + // Filter out undefined results + // Because we negate the result if shouldShow is false, we can use `condition.state.result ?? true` directly below + const validConditions = this.state.conditions.filter((condition) => condition.state.result !== undefined); + + let result = true; + + if (validConditions.length > 0) { + result = this._shouldMatchAll + ? validConditions.every((condition) => condition.state.result) + : validConditions.some((condition) => condition.state.result); + + if (!this._shouldShow) { + result = !result; + } + } + + if (result !== this.state.result) { + this.setState({ ...this.state, result }); + this.publishEvent(new ConditionalRenderingChangedEvent(this), true); + } + } + + public changeVisibility(visibility: GroupConditionVisibility) { + if (visibility !== this.state.visibility) { + this._shouldShow = visibility === 'show'; + this.setState({ visibility }); + this.check(); + } + } + + public changeCondition(condition: GroupConditionCondition) { + if (condition !== this.state.condition) { + this._shouldMatchAll = condition === 'and'; + this.setState({ condition }); + this.check(); + } + } + + public createCondition(conditionType: GroupConditionConditionType): ConditionalRenderingConditions { + switch (conditionType) { + case 'data': + return ConditionalRenderingData.createEmpty(); + + case 'timeRangeSize': + return ConditionalRenderingTimeRangeSize.createEmpty(); + + case 'variable': + return ConditionalRenderingVariable.createEmpty( + sceneGraph.getVariables(getDashboardSceneFor(this)).state.variables[0].state.name + ); + } + } + + public addCondition(condition: ConditionalRenderingConditions) { + const conditions = [...this.state.conditions, condition]; + this.setState({ + conditions, + renderHidden: conditions.some((condition) => condition instanceof ConditionalRenderingData), + }); + + if (this.isActive && !condition.isActive) { + condition.activate(); + } + + this.check(); + } + + public removeCondition(condition: ConditionalRenderingConditions) { + const conditions = this.state.conditions.filter((currentCondition) => currentCondition !== condition); + + this.setState({ + conditions, + renderHidden: conditions.some((condition) => condition instanceof ConditionalRenderingData), + }); + this.check(); + } + + public undoRemoveCondition(condition: ConditionalRenderingConditions, index: number) { + const conditions = [...this.state.conditions]; + conditions.splice(index, 0, condition); + this.setState({ conditions }); + this.check(); + } + + public removeLastCondition() { + const conditions = [...this.state.conditions]; + conditions.pop(); + this.setState({ conditions }); + this.check(); + } + + public getConditionIndex(condition: ConditionalRenderingConditions): number { + return this.state.conditions.findIndex((currentCondition) => currentCondition === condition); + } + + public serialize(): ConditionalRenderingGroupKind { + return { + kind: 'ConditionalRenderingGroup', + spec: { + visibility: this.state.visibility, + condition: this.state.condition, + items: this.state.conditions.map((condition) => condition.serialize()), + }, + }; + } + + public static createEmpty(): ConditionalRenderingGroup { + return new ConditionalRenderingGroup({ + condition: 'and', + visibility: 'show', + conditions: [], + result: true, + renderHidden: false, + }); + } + + public static deserialize(model: ConditionalRenderingGroupKind): ConditionalRenderingGroup { + const conditions = model.spec.items.map((item) => + conditionalRenderingSerializerRegistry.get(item.kind).deserialize(item) + ); + + return new ConditionalRenderingGroup({ + condition: model.spec.condition, + visibility: model.spec.visibility, + conditions, + result: true, + renderHidden: conditions.some((condition) => condition instanceof ConditionalRenderingData), + }); + } +} + +function ConditionalRenderingGroupRenderer({ model }: SceneComponentProps) { + const { condition, visibility, conditions } = model.useState(); + const { variables } = sceneGraph.getVariables(model).useState(); + const objectType = useMemo(() => extractObjectType(model.parent), [model]); + + return ( + + { + dashboardEditActions.edit({ + description: t('dashboard.conditional-rendering.conditions.group.visibility.label', '{{type}} visibility', { + type: getTranslatedObjectType(objectType), + }), + source: model, + perform: () => model.changeVisibility(value), + undo: () => model.changeVisibility(visibility), + }); + }} + /> + {conditions.length > 1 && ( + { + dashboardEditActions.edit({ + description: t('dashboard.conditional-rendering.conditions.group.condition.label', 'Match rules'), + source: model, + perform: () => model.changeCondition(value), + undo: () => model.changeCondition(condition), + }); + }} + /> + )} + {conditions.map((currentCondition) => currentCondition.render())} + 0} + onAdd={({ value, label }) => { + const condition = model.createCondition(value!); + + dashboardEditActions.edit({ + description: t('dashboard.edit-actions.add-conditional-rule', 'Add {{ruleDescription}} rule', { + ruleDescription: lowerCase(label), + }), + source: model, + perform: () => model.addCondition(condition), + undo: () => model.removeLastCondition(), + }); + }} + /> + + ); +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroupAdd.tsx b/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroupAdd.tsx similarity index 64% rename from public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroupAdd.tsx rename to public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroupAdd.tsx index e423870f6c8..04ea113b769 100644 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroupAdd.tsx +++ b/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroupAdd.tsx @@ -4,17 +4,19 @@ import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; import { ValuePicker } from '@grafana/ui'; -import { GroupConditionItemType, ItemsWithConditionalRendering } from './types'; +import { ObjectsWithConditionalRendering } from '../object'; + +import { GroupConditionConditionType } from './types'; interface Props { - itemType: ItemsWithConditionalRendering; + objectType: ObjectsWithConditionalRendering; hasVariables: boolean; - onAdd: (option: SelectableValue) => void; + onAdd: (option: SelectableValue) => void; } -export const ConditionalRenderingGroupAdd = ({ itemType, hasVariables, onAdd }: Props) => { - const options = useMemo>>(() => { - const allOptions: Array> = [ +export const ConditionalRenderingGroupAdd = ({ objectType, hasVariables, onAdd }: Props) => { + const options = useMemo>>(() => { + const allOptions: Array> = [ { label: t('dashboard.conditional-rendering.conditions.group.add.data', 'Query result'), value: 'data' }, { label: t('dashboard.conditional-rendering.conditions.group.add.variable', 'Template variable'), @@ -27,12 +29,12 @@ export const ConditionalRenderingGroupAdd = ({ itemType, hasVariables, onAdd }: }, ]; - if (itemType !== 'panel') { + if (objectType !== 'panel') { allOptions.shift(); } return allOptions; - }, [itemType, hasVariables]); + }, [objectType, hasVariables]); return ( { - const styles = useStyles2(getStyles); - const options: Array> = useMemo( () => [ { label: t('dashboard.conditional-rendering.conditions.group.condition.all', 'Match all'), value: 'and' }, @@ -24,17 +21,8 @@ export const ConditionalRenderingGroupCondition = ({ value, onChange }: Props) = ); return ( - + ); }; - -const getStyles = () => ({ - container: css({ - margin: 0, - }), -}); diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroupVisibility.tsx b/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroupVisibility.tsx similarity index 57% rename from public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroupVisibility.tsx rename to public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroupVisibility.tsx index 0c105d798c5..e7f29f575b6 100644 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingGroupVisibility.tsx +++ b/public/app/features/dashboard-scene/conditional-rendering/group/ConditionalRenderingGroupVisibility.tsx @@ -1,23 +1,20 @@ -import { css } from '@emotion/css'; -import { capitalize } from 'lodash'; import { useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; import { t } from '@grafana/i18n'; -import { Field, RadioButtonGroup, useStyles2 } from '@grafana/ui'; +import { Field, RadioButtonGroup } from '@grafana/ui'; -import { GroupConditionVisibility, ItemsWithConditionalRendering } from './types'; -import { translatedItemType } from './utils'; +import { getTranslatedObjectType, ObjectsWithConditionalRendering } from '../object'; + +import { GroupConditionVisibility } from './types'; interface Props { - itemType: ItemsWithConditionalRendering; + objectType: ObjectsWithConditionalRendering; value: GroupConditionVisibility; onChange: (value: GroupConditionVisibility) => void; } -export const ConditionalRenderingGroupVisibility = ({ itemType, value, onChange }: Props) => { - const styles = useStyles2(getStyles); - +export const ConditionalRenderingGroupVisibility = ({ objectType, value, onChange }: Props) => { const options: Array> = useMemo( () => [ { label: t('dashboard.conditional-rendering.conditions.group.visibility.show', 'Show'), value: 'show' }, @@ -29,17 +26,11 @@ export const ConditionalRenderingGroupVisibility = ({ itemType, value, onChange return ( ); }; - -const getStyles = () => ({ - container: css({ - margin: 0, - }), -}); diff --git a/public/app/features/dashboard-scene/conditional-rendering/group/types.ts b/public/app/features/dashboard-scene/conditional-rendering/group/types.ts new file mode 100644 index 00000000000..9db0ed3c754 --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/group/types.ts @@ -0,0 +1,3 @@ +export type GroupConditionVisibility = 'show' | 'hide'; +export type GroupConditionCondition = 'and' | 'or'; +export type GroupConditionConditionType = 'data' | 'timeRangeSize' | 'variable'; diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingOverlay.tsx b/public/app/features/dashboard-scene/conditional-rendering/hooks/ConditionalRenderingOverlay.tsx similarity index 100% rename from public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingOverlay.tsx rename to public/app/features/dashboard-scene/conditional-rendering/hooks/ConditionalRenderingOverlay.tsx diff --git a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingEditor.tsx b/public/app/features/dashboard-scene/conditional-rendering/hooks/useConditionalRenderingEditor.tsx similarity index 51% rename from public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingEditor.tsx rename to public/app/features/dashboard-scene/conditional-rendering/hooks/useConditionalRenderingEditor.tsx index 30b958a1642..13416c90cef 100644 --- a/public/app/features/dashboard-scene/conditional-rendering/ConditionalRenderingEditor.tsx +++ b/public/app/features/dashboard-scene/conditional-rendering/hooks/useConditionalRenderingEditor.tsx @@ -3,25 +3,20 @@ import { Icon, Stack, Tooltip } from '@grafana/ui'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; -import { ConditionalRendering } from './ConditionalRendering'; -import { ConditionalRenderingGroup } from './ConditionalRenderingGroup'; +import { ConditionalRenderingGroup } from '../group/ConditionalRenderingGroup'; +import { extractObjectType, getLowerTranslatedObjectType } from '../object'; -let placeholderConditionalRendering: ConditionalRendering | undefined; -function getPlaceholderConditionalRendering(): ConditionalRendering { +let placeholderConditionalRendering: ConditionalRenderingGroup | undefined; + +function getPlaceholderConditionalRendering(): ConditionalRenderingGroup { if (!placeholderConditionalRendering) { - placeholderConditionalRendering = new ConditionalRendering({ - rootGroup: new ConditionalRenderingGroup({ - visibility: 'show', - condition: 'and', - value: [], - }), - }); + placeholderConditionalRendering = ConditionalRenderingGroup.createEmpty(); } return placeholderConditionalRendering; } export function useConditionalRenderingEditor( - conditionalRendering?: ConditionalRendering, + conditionalRendering?: ConditionalRenderingGroup, disabledText?: string ): OptionsPaneCategoryDescriptor { const title = t('dashboard.conditional-rendering.root.title', 'Show / hide rules'); @@ -34,22 +29,32 @@ export function useConditionalRenderingEditor( ? undefined : (disabledText ?? t( - 'dashboard.conditional-rendering.editor.unsupported-item-type', + 'dashboard.conditional-rendering.editor.unsupported-object-type', 'Conditional rendering not supported for this item type' )), id: 'conditional-rendering-options', - renderTitle: () => ( - -
{title}
- {conditionalRendering ? ( - - - - ) : ( - - )} -
- ), + renderTitle: () => { + const { result } = conditionalRenderingToRender.useState(); + + return ( + +
{title}
+ {conditionalRendering ? ( + + + + ) : ( + + )} +
+ ); + }, isOpenDefault: true, }).addItem( new OptionsPaneItemDescriptor({ diff --git a/public/app/features/dashboard-scene/conditional-rendering/hooks/useIsConditionallyHidden.tsx b/public/app/features/dashboard-scene/conditional-rendering/hooks/useIsConditionallyHidden.tsx new file mode 100644 index 00000000000..2292b63500a --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/hooks/useIsConditionallyHidden.tsx @@ -0,0 +1,33 @@ +import { ReactNode } from 'react'; + +import { SceneObject, useSceneObjectState } from '@grafana/scenes'; + +import { ConditionalRenderingGroup } from '../group/ConditionalRenderingGroup'; + +import { ConditionalRenderingOverlay } from './ConditionalRenderingOverlay'; + +let placeholderConditionalRendering: ConditionalRenderingGroup | undefined; +function getPlaceholderConditionalRendering(): ConditionalRenderingGroup { + if (!placeholderConditionalRendering) { + placeholderConditionalRendering = ConditionalRenderingGroup.createEmpty(); + } + return placeholderConditionalRendering; +} + +export function useIsConditionallyHidden(scene: SceneObject): [boolean, string | undefined, ReactNode | null, boolean] { + const conditionalRenderingToRender = + 'conditionalRendering' in scene.state && scene.state.conditionalRendering instanceof ConditionalRenderingGroup + ? scene.state.conditionalRendering + : getPlaceholderConditionalRendering(); + + const { result, renderHidden } = useSceneObjectState(conditionalRenderingToRender, { + shouldActivateOrKeepAlive: true, + }); + + return [ + !result, + result ? undefined : 'dashboard-visible-hidden-element', + result ? null : , + renderHidden, + ]; +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/object.ts b/public/app/features/dashboard-scene/conditional-rendering/object.ts new file mode 100644 index 00000000000..67fca6942be --- /dev/null +++ b/public/app/features/dashboard-scene/conditional-rendering/object.ts @@ -0,0 +1,62 @@ +import { capitalize, lowerCase } from 'lodash'; + +import { t } from '@grafana/i18n'; +import { SceneObject } from '@grafana/scenes'; + +import { AutoGridItem } from '../scene/layout-auto-grid/AutoGridItem'; +import { RowItem } from '../scene/layout-rows/RowItem'; +import { TabItem } from '../scene/layout-tabs/TabItem'; + +export type ObjectsWithConditionalRendering = 'panel' | 'row' | 'tab' | 'element'; + +const translatedObjectTypes = { + get panel() { + return t('dashboard.edit-pane.elements.panel', 'Panel'); + }, + get row() { + return t('dashboard.edit-pane.elements.row', 'Row'); + }, + get tab() { + return t('dashboard.edit-pane.elements.tab', 'Tab'); + }, + get element() { + return t('dashboard.edit-pane.elements.element', 'Element'); + }, +} as const; + +const translatedObjectTypesLower: Record = { + get panel() { + return lowerCase(t('dashboard.edit-pane.elements.panel', 'Panel')); + }, + get row() { + return lowerCase(t('dashboard.edit-pane.elements.row', 'Row')); + }, + get tab() { + return lowerCase(t('dashboard.edit-pane.elements.tab', 'Tab')); + }, + get element() { + return lowerCase(t('dashboard.edit-pane.elements.element', 'Element')); + }, +} as const; + +export function getTranslatedObjectType(type: ObjectsWithConditionalRendering): string { + return translatedObjectTypes[type] ?? capitalize(type); +} + +export function getLowerTranslatedObjectType(type: ObjectsWithConditionalRendering): string { + return translatedObjectTypesLower[type] ?? type; +} + +export function extractObjectType(object: SceneObject | undefined): ObjectsWithConditionalRendering { + if (!object) { + return 'element'; + } else if (object instanceof AutoGridItem) { + return 'panel'; + } else if (object instanceof RowItem) { + return 'row'; + } else if (object instanceof TabItem) { + return 'tab'; + } + + return 'element'; +} diff --git a/public/app/features/dashboard-scene/conditional-rendering/serializers.ts b/public/app/features/dashboard-scene/conditional-rendering/serializers.ts deleted file mode 100644 index 77a858d2201..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/serializers.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Registry } from '@grafana/data'; - -import { ConditionalRenderingData } from './ConditionalRenderingData'; -import { ConditionalRenderingGroup } from './ConditionalRenderingGroup'; -import { ConditionalRenderingTimeRangeSize } from './ConditionalRenderingTimeRangeSize'; -import { ConditionalRenderingVariable } from './ConditionalRenderingVariable'; -import { ConditionalRenderingSerializerRegistryItem } from './types'; - -export const conditionalRenderingSerializerRegistry = new Registry(() => { - return [ - ConditionalRenderingGroup.serializer, - ConditionalRenderingVariable.serializer, - ConditionalRenderingData.serializer, - ConditionalRenderingTimeRangeSize.serializer, - ]; -}); diff --git a/public/app/features/dashboard-scene/conditional-rendering/types.ts b/public/app/features/dashboard-scene/conditional-rendering/types.ts deleted file mode 100644 index f07330967de..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/types.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { RegistryItem } from '@grafana/data'; -import { - ConditionalRenderingDataKind, - ConditionalRenderingGroupKind, - ConditionalRenderingTimeRangeSizeKind, - ConditionalRenderingVariableKind, -} from '@grafana/schema/dist/esm/schema/dashboard/v2'; - -import { ConditionalRenderingData } from './ConditionalRenderingData'; -import { ConditionalRenderingGroup } from './ConditionalRenderingGroup'; -import { ConditionalRenderingTimeRangeSize } from './ConditionalRenderingTimeRangeSize'; -import { ConditionalRenderingVariable } from './ConditionalRenderingVariable'; - -export type ItemsWithConditionalRendering = 'panel' | 'row' | 'tab' | 'element'; - -export type DataConditionValue = boolean; - -export type GroupConditionVisibility = 'show' | 'hide'; -export type GroupConditionCondition = 'and' | 'or'; -export type GroupConditionItemType = 'data' | 'timeRangeSize' | 'variable'; -export type GroupConditionValue = ConditionalRenderingConditions[]; - -export type TimeRangeSizeConditionValue = string; - -export type VariableConditionValueOperator = '=' | '!=' | '=~' | '!~'; - -export type VariableConditionValue = { - name: string; - operator: VariableConditionValueOperator; - value: string; -}; - -export type ConditionValues = - | DataConditionValue - | VariableConditionValue - | GroupConditionValue - | TimeRangeSizeConditionValue; - -export type ConditionalRenderingConditions = - | ConditionalRenderingData - | ConditionalRenderingVariable - | ConditionalRenderingTimeRangeSize - | ConditionalRenderingGroup; - -export type ConditionalRenderingKindTypes = - | ConditionalRenderingGroupKind - | ConditionalRenderingVariableKind - | ConditionalRenderingDataKind - | ConditionalRenderingTimeRangeSizeKind; - -export interface ConditionalRenderingSerializerRegistryItem extends RegistryItem { - deserialize(model: ConditionalRenderingKindTypes): ConditionalRenderingConditions; -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/useIsConditionallyHidden.tsx b/public/app/features/dashboard-scene/conditional-rendering/useIsConditionallyHidden.tsx deleted file mode 100644 index 6c285e1f852..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/useIsConditionallyHidden.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { ReactNode } from 'react'; - -import { SceneObject } from '@grafana/scenes'; - -import { ConditionalRendering } from './ConditionalRendering'; -import { ConditionalRenderingOverlay } from './ConditionalRenderingOverlay'; - -export function useIsConditionallyHidden(scene: SceneObject): [boolean, string | undefined, ReactNode | null] { - const state = scene.useState(); - - if (!('conditionalRendering' in state) || !(state.conditionalRendering instanceof ConditionalRendering)) { - return [false, undefined, null]; - } - - const value = state.conditionalRendering.evaluate() ?? true; - - return [ - !value, - value ? undefined : 'dashboard-visible-hidden-element', - value ? null : , - ]; -} diff --git a/public/app/features/dashboard-scene/conditional-rendering/utils.ts b/public/app/features/dashboard-scene/conditional-rendering/utils.ts deleted file mode 100644 index d8e1b841692..00000000000 --- a/public/app/features/dashboard-scene/conditional-rendering/utils.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { lowerCase } from 'lodash'; - -import { t } from '@grafana/i18n'; -import { SceneObject } from '@grafana/scenes'; - -import { AutoGridItem } from '../scene/layout-auto-grid/AutoGridItem'; -import { RowItem } from '../scene/layout-rows/RowItem'; -import { TabItem } from '../scene/layout-tabs/TabItem'; - -import { ItemsWithConditionalRendering } from './types'; - -export function getItemType(object: SceneObject): ItemsWithConditionalRendering { - if (object instanceof AutoGridItem) { - return 'panel'; - } else if (object instanceof RowItem) { - return 'row'; - } else if (object instanceof TabItem) { - return 'tab'; - } - - return 'element'; -} - -export const translatedItemType = (item: ItemsWithConditionalRendering) => { - const translations: { [key in ItemsWithConditionalRendering]: string } = { - panel: lowerCase(t('dashboard.edit-pane.elements.panel', 'Panel')), - row: lowerCase(t('dashboard.edit-pane.elements.row', 'Row')), - tab: lowerCase(t('dashboard.edit-pane.elements.tab', 'Tab')), - element: lowerCase(t('dashboard.edit-pane.elements.element', 'Element')), - }; - - return translations[item] || item; -}; diff --git a/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts b/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts index 5b02068f80c..658cf97fa1f 100644 --- a/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts +++ b/public/app/features/dashboard-scene/saving/DashboardSceneChangeTracker.ts @@ -15,10 +15,10 @@ import { } from '@grafana/scenes'; import { createWorker } from 'app/features/dashboard-scene/saving/createDetectChangesWorker'; -import { ConditionalRenderingData } from '../conditional-rendering/ConditionalRenderingData'; -import { ConditionalRenderingGroup } from '../conditional-rendering/ConditionalRenderingGroup'; -import { ConditionalRenderingTimeRangeSize } from '../conditional-rendering/ConditionalRenderingTimeRangeSize'; -import { ConditionalRenderingVariable } from '../conditional-rendering/ConditionalRenderingVariable'; +import { ConditionalRenderingData } from '../conditional-rendering/conditions/ConditionalRenderingData'; +import { ConditionalRenderingTimeRangeSize } from '../conditional-rendering/conditions/ConditionalRenderingTimeRangeSize'; +import { ConditionalRenderingVariable } from '../conditional-rendering/conditions/ConditionalRenderingVariable'; +import { ConditionalRenderingGroup } from '../conditional-rendering/group/ConditionalRenderingGroup'; import { DashboardAnnotationsDataLayer } from '../scene/DashboardAnnotationsDataLayer'; import { DashboardControls } from '../scene/DashboardControls'; import { DashboardScene, PERSISTED_PROPS } from '../scene/DashboardScene'; diff --git a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItem.tsx b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItem.tsx index 2235985ba7e..f98461ca936 100644 --- a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItem.tsx +++ b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItem.tsx @@ -13,7 +13,7 @@ import { } from '@grafana/scenes'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; -import { ConditionalRendering } from '../../conditional-rendering/ConditionalRendering'; +import { ConditionalRenderingGroup } from '../../conditional-rendering/group/ConditionalRenderingGroup'; import { getCloneKey, getLocalVariableValueSet } from '../../utils/clone'; import { getMultiVariableValues } from '../../utils/utils'; import { scrollCanvasElementIntoView } from '../layouts-shared/scrollCanvasElementIntoView'; @@ -29,7 +29,7 @@ export interface AutoGridItemState extends SceneObjectState { repeatedPanels?: VizPanel[]; variableName?: string; isHidden?: boolean; - conditionalRendering?: ConditionalRendering; + conditionalRendering?: ConditionalRenderingGroup; } export class AutoGridItem extends SceneObjectBase implements DashboardLayoutItem { @@ -45,7 +45,7 @@ export class AutoGridItem extends SceneObjectBase implements private _prevRepeatValues?: VariableValueSingle[]; public constructor(state: AutoGridItemState) { - super({ ...state, conditionalRendering: state?.conditionalRendering ?? ConditionalRendering.createEmpty() }); + super({ ...state, conditionalRendering: state?.conditionalRendering ?? ConditionalRenderingGroup.createEmpty() }); this.addActivationHandler(() => this._activationHandler()); } diff --git a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemEditor.tsx b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemEditor.tsx index 0d7b7d8138c..f30acb5a049 100644 --- a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemEditor.tsx +++ b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemEditor.tsx @@ -3,7 +3,7 @@ import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; import { RepeatRowSelect2 } from 'app/features/dashboard/components/RepeatRowSelect/RepeatRowSelect'; -import { useConditionalRenderingEditor } from '../../conditional-rendering/ConditionalRenderingEditor'; +import { useConditionalRenderingEditor } from '../../conditional-rendering/hooks/useConditionalRenderingEditor'; import { dashboardEditActions } from '../../edit-pane/shared'; import { AutoGridItem } from './AutoGridItem'; diff --git a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemRenderer.tsx b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemRenderer.tsx index 12903f1e727..a41fb80a233 100644 --- a/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemRenderer.tsx @@ -5,7 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data/'; import { LazyLoader, SceneComponentProps, VizPanel } from '@grafana/scenes'; import { useStyles2 } from '@grafana/ui'; -import { useIsConditionallyHidden } from '../../conditional-rendering/useIsConditionallyHidden'; +import { useIsConditionallyHidden } from '../../conditional-rendering/hooks/useIsConditionallyHidden'; import { useDashboardState } from '../../utils/utils'; import { renderMatchingSoloPanels, useSoloPanelContext } from '../SoloPanelContext'; import { getIsLazy } from '../layouts-shared/utils'; @@ -17,7 +17,7 @@ export function AutoGridItemRenderer({ model }: SceneComponentProps ( -
- {isDragged &&
} - {isLazy ? ( - - - {conditionalRenderingOverlay} - - ) : ( -
- - {conditionalRenderingOverlay} -
- )} -
- ) + }) => + isConditionallyHidden && !isEditing && !renderHidden ? null : ( +
+ {isDragged &&
} + { + // The lazy loader causes issues when used with conditional rendering + isLazy && (!isConditionallyHidden || !renderHidden) ? ( + + + {conditionalRenderingOverlay} + + ) : ( +
+ + {conditionalRenderingOverlay} +
+ ) + } +
+ ) ), - [conditionalRenderingClass, conditionalRenderingOverlay, isLazy, key, model.containerRef, styles] + [ + conditionalRenderingClass, + conditionalRenderingOverlay, + isLazy, + key, + model.containerRef, + styles, + isConditionallyHidden, + isEditing, + renderHidden, + ] ); if (soloPanelContext) { return renderMatchingSoloPanels(soloPanelContext, [body, ...repeatedPanels]); } - if (isConditionallyHidden && !isEditing) { - return null; - } - const isDragging = !!draggingKey; const isDragged = draggingKey === key; @@ -127,4 +138,7 @@ const getStyles = (theme: GrafanaTheme2) => ({ background: `${theme.colors.primary.transparent}`, zIndex: -1, }), + hidden: css({ + display: 'none', + }), }); diff --git a/public/app/features/dashboard-scene/scene/layout-default/DashboardGridItemEditor.tsx b/public/app/features/dashboard-scene/scene/layout-default/DashboardGridItemEditor.tsx index fcbe1c9d193..09ed968bd72 100644 --- a/public/app/features/dashboard-scene/scene/layout-default/DashboardGridItemEditor.tsx +++ b/public/app/features/dashboard-scene/scene/layout-default/DashboardGridItemEditor.tsx @@ -9,7 +9,7 @@ import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; import { RepeatRowSelect2 } from 'app/features/dashboard/components/RepeatRowSelect/RepeatRowSelect'; -import { useConditionalRenderingEditor } from '../../conditional-rendering/ConditionalRenderingEditor'; +import { useConditionalRenderingEditor } from '../../conditional-rendering/hooks/useConditionalRenderingEditor'; import { dashboardEditActions } from '../../edit-pane/shared'; import { DashboardGridItem } from './DashboardGridItem'; diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx index 72e34058ab8..57d4e0d6698 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowItem.tsx @@ -17,7 +17,7 @@ import kbn from 'app/core/utils/kbn'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; import { ShowConfirmModalEvent } from 'app/types/events'; -import { ConditionalRendering } from '../../conditional-rendering/ConditionalRendering'; +import { ConditionalRenderingGroup } from '../../conditional-rendering/group/ConditionalRenderingGroup'; import { serializeRow } from '../../serialization/layoutSerializers/RowsLayoutSerializer'; import { getElements } from '../../serialization/layoutSerializers/utils'; import { getDashboardSceneFor } from '../../utils/utils'; @@ -42,7 +42,7 @@ export interface RowItemState extends SceneObjectState { hideHeader?: boolean; fillScreen?: boolean; isDropTarget?: boolean; - conditionalRendering?: ConditionalRendering; + conditionalRendering?: ConditionalRenderingGroup; repeatByVariable?: string; repeatedRows?: RowItem[]; /** Marks object as a repeated object and a key pointer to source object */ @@ -68,7 +68,7 @@ export class RowItem ...state, title: state?.title ?? t('dashboard.rows-layout.row.new', 'New row'), layout: state?.layout ?? AutoGridLayoutManager.createEmpty(), - conditionalRendering: state?.conditionalRendering ?? ConditionalRendering.createEmpty(), + conditionalRendering: state?.conditionalRendering ?? ConditionalRenderingGroup.createEmpty(), }); this.addActivationHandler(() => this._activationHandler()); diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowItemEditor.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowItemEditor.tsx index 540334845f1..7e99742cb17 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowItemEditor.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowItemEditor.tsx @@ -9,7 +9,7 @@ import { RepeatRowSelect2 } from 'app/features/dashboard/components/RepeatRowSel import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard/constants'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { useConditionalRenderingEditor } from '../../conditional-rendering/ConditionalRenderingEditor'; +import { useConditionalRenderingEditor } from '../../conditional-rendering/hooks/useConditionalRenderingEditor'; import { dashboardEditActions } from '../../edit-pane/shared'; import { getQueryRunnerFor, useDashboard } from '../../utils/utils'; import { useLayoutCategory } from '../layouts-shared/DashboardLayoutSelector'; diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx index dff4f5c763e..2b5f3bcfca2 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowItemRenderer.tsx @@ -8,7 +8,7 @@ import { t } from '@grafana/i18n'; import { SceneComponentProps } from '@grafana/scenes'; import { clearButtonStyles, Icon, Tooltip, useElementSelection, usePointerDistance, useStyles2 } from '@grafana/ui'; -import { useIsConditionallyHidden } from '../../conditional-rendering/useIsConditionallyHidden'; +import { useIsConditionallyHidden } from '../../conditional-rendering/hooks/useIsConditionallyHidden'; import { isRepeatCloneOrChildOf } from '../../utils/clone'; import { useDashboardState, useInterpolatedTitle } from '../../utils/utils'; import { DashboardScene } from '../DashboardScene'; diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx index 23d17df71ef..f706747e1d9 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx @@ -17,7 +17,7 @@ import kbn from 'app/core/utils/kbn'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; import { ShowConfirmModalEvent } from 'app/types/events'; -import { ConditionalRendering } from '../../conditional-rendering/ConditionalRendering'; +import { ConditionalRenderingGroup } from '../../conditional-rendering/group/ConditionalRenderingGroup'; import { serializeTab } from '../../serialization/layoutSerializers/TabsLayoutSerializer'; import { getElements } from '../../serialization/layoutSerializers/utils'; import { getDashboardSceneFor, getDefaultVizPanel } from '../../utils/utils'; @@ -39,7 +39,7 @@ export interface TabItemState extends SceneObjectState { layout: DashboardLayoutManager; title?: string; isDropTarget?: boolean; - conditionalRendering?: ConditionalRendering; + conditionalRendering?: ConditionalRenderingGroup; repeatByVariable?: string; repeatedTabs?: TabItem[]; /** Marks object as a repeated object and a key pointer to source object */ @@ -66,7 +66,7 @@ export class TabItem ...state, title: state?.title ?? t('dashboard.tabs-layout.tab.new', 'New tab'), layout: state?.layout ?? AutoGridLayoutManager.createEmpty(), - conditionalRendering: state?.conditionalRendering ?? ConditionalRendering.createEmpty(), + conditionalRendering: state?.conditionalRendering ?? ConditionalRenderingGroup.createEmpty(), }); this.addActivationHandler(() => this._activationHandler()); diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx index 4ec8545fd8f..0e080c62485 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx @@ -9,7 +9,7 @@ import { RepeatRowSelect2 } from 'app/features/dashboard/components/RepeatRowSel import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard/constants'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { useConditionalRenderingEditor } from '../../conditional-rendering/ConditionalRenderingEditor'; +import { useConditionalRenderingEditor } from '../../conditional-rendering/hooks/useConditionalRenderingEditor'; import { dashboardEditActions } from '../../edit-pane/shared'; import { getQueryRunnerFor, useDashboard } from '../../utils/utils'; import { useLayoutCategory } from '../layouts-shared/DashboardLayoutSelector'; diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemRenderer.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemRenderer.tsx index 3390e4c0133..1c3e30d4aeb 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemRenderer.tsx @@ -7,7 +7,7 @@ import { t } from '@grafana/i18n'; import { SceneComponentProps, sceneGraph } from '@grafana/scenes'; import { Box, Icon, Tab, TabContent, Tooltip, useElementSelection, usePointerDistance, useStyles2 } from '@grafana/ui'; -import { useIsConditionallyHidden } from '../../conditional-rendering/useIsConditionallyHidden'; +import { useIsConditionallyHidden } from '../../conditional-rendering/hooks/useIsConditionallyHidden'; import { isRepeatCloneOrChildOf } from '../../utils/clone'; import { useDashboardState } from '../../utils/utils'; import { useSoloPanelContext } from '../SoloPanelContext'; diff --git a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts index 8f0736a7a9b..78ab49707cd 100644 --- a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts +++ b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts @@ -23,9 +23,7 @@ import { } from '@grafana/schema/dist/esm/schema/dashboard/v2'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { ConditionalRendering } from '../../conditional-rendering/ConditionalRendering'; -import { ConditionalRenderingGroup } from '../../conditional-rendering/ConditionalRenderingGroup'; -import { conditionalRenderingSerializerRegistry } from '../../conditional-rendering/serializers'; +import { ConditionalRenderingGroup } from '../../conditional-rendering/group/ConditionalRenderingGroup'; import { CustomTimeRangeCompare } from '../../scene/CustomTimeRangeCompare'; import { DashboardDatasourceBehaviour } from '../../scene/DashboardDatasourceBehaviour'; import { DashboardScene } from '../../scene/DashboardScene'; @@ -293,20 +291,12 @@ export function getLayout(sceneState: DashboardLayoutManager): DashboardV2Spec[' export function getConditionalRendering( item: TabsLayoutTabKind | RowsLayoutRowKind | AutoGridLayoutItemKind -): ConditionalRendering { +): ConditionalRenderingGroup { if (!item.spec.conditionalRendering) { - return ConditionalRendering.createEmpty(); + return ConditionalRenderingGroup.createEmpty(); } - const rootGroup = conditionalRenderingSerializerRegistry - .get(item.spec.conditionalRendering.kind) - .deserialize(item.spec.conditionalRendering); - - if (rootGroup && !(rootGroup instanceof ConditionalRenderingGroup)) { - throw new Error(`Conditional rendering must always start with a root group`); - } - - return new ConditionalRendering({ rootGroup: rootGroup }); + return ConditionalRenderingGroup.deserialize(item.spec.conditionalRendering); } export function getElements(layout: DashboardLayoutManager, scene: DashboardScene): DashboardV2Spec['elements'] { diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index ddf60d46082..b38bb01241f 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -4506,17 +4506,12 @@ "any": "Match any", "label": "Match rules" }, - "label": "Group", "visibility": { "hide": "Hide", "label": "{{type}} visibility", "show": "Show" } }, - "shared": { - "delete-condition": "Delete Condition", - "unsupported-item-type": "This condition is not supported by the element, hence it will be ignored." - }, "time-range-size": { "info": "Show or hide the {{type}} if the dashboard time range is shorter than the selected time frame.", "invalid-message": "Invalid interval", @@ -4545,17 +4540,21 @@ "not-matches": "Not matches" }, "value": "Value" + }, + "wrapper": { + "delete-condition": "Delete Condition", + "unsupported-object-type": "This condition is not supported by the element, hence it will be ignored." } }, "editor": { + "info": "Set rules to control {{type}} visibility by matching any or all rules.", "not-supported-for-custom-grid": "Conditional rendering is not supported for the custom grid layout. Switch to auto grid to use conditional rendering.", - "unsupported-item-type": "Conditional rendering not supported for this item type" + "unsupported-object-type": "Conditional rendering not supported for this item type" }, "overlay": { "tooltip": "Element is hidden due to conditional rendering." }, "root": { - "info": "Set rules to control {{type}} visibility by matching any or all rules.", "title": "Show / hide rules" } },