ConditionalRendering: Fix for repeated items (#114160)
This commit is contained in:
+51
-1
@@ -4,6 +4,8 @@ import { test, expect, E2ESelectorGroups, DashboardPage, DashboardPageArgs } fro
|
||||
|
||||
import testDashboard from '../dashboards/DashboardWithAllConditionalRendering.json';
|
||||
|
||||
import { checkRepeatedPanelTitles } from './utils';
|
||||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
kubernetesDashboards: true,
|
||||
@@ -93,7 +95,7 @@ test.describe('Dashboard - Conditional Rendering - Load and Change', { tag: ['@d
|
||||
|
||||
test.afterAll(async ({ request }) => {
|
||||
if (uid) {
|
||||
await request.delete(`/apis/dashboard.grafana.app/v1beta1/namespaces/default/dashboards/${uid}`);
|
||||
await request.delete(`/apis/dashboard.grafana.app/v1beta1/namespaces/stacks-12345/dashboards/${uid}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -407,4 +409,52 @@ test.describe('Dashboard - Conditional Rendering - Load and Change', { tag: ['@d
|
||||
await expect(getTabShowNotMatches(dashboardPage, selectors)).toBeVisible();
|
||||
await expect(getTabHideNotMatches(dashboardPage, selectors)).not.toBeVisible();
|
||||
});
|
||||
|
||||
test.describe('Variable repeat', () => {
|
||||
const repeatOptions = ['a', 'b', 'c'];
|
||||
|
||||
async function failTestDataRequestForOption(page: Page, option: string) {
|
||||
await page.route(/\/api\/ds\/query\?.*\bds_type=grafana-testdata-datasource/, async (route) => {
|
||||
const rawPostData = route.request().postData();
|
||||
if (!rawPostData) {
|
||||
return;
|
||||
}
|
||||
|
||||
// the first panel query has a label set to the current variable value
|
||||
if (JSON.parse(rawPostData).queries[0].labels === `key=${option}`) {
|
||||
await route.fulfill({ status: 500, body: '{}' });
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test('Hide when equals, hide when no data', async ({ page, gotoDashboardPage, selectors }) => {
|
||||
const dashboardPage = await loadDashboard(page, gotoDashboardPage);
|
||||
|
||||
await getTab(dashboardPage, selectors, 'repeated items').click();
|
||||
|
||||
const optionForHiddenPanels = repeatOptions[0];
|
||||
|
||||
await failTestDataRequestForOption(page, optionForHiddenPanels);
|
||||
|
||||
await checkRepeatedPanelTitles(
|
||||
dashboardPage,
|
||||
selectors,
|
||||
'Hide panel - ',
|
||||
[
|
||||
`custom variable equals ${optionForHiddenPanels} (current = ${optionForHiddenPanels})`,
|
||||
`no data (current = ${optionForHiddenPanels})`,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
const optionsForVisiblePanels = repeatOptions.slice(1);
|
||||
|
||||
await checkRepeatedPanelTitles(dashboardPage, selectors, 'Hide panel - ', [
|
||||
...optionsForVisiblePanels.map((o) => `custom variable equals ${optionForHiddenPanels} (current = ${o})`),
|
||||
...optionsForVisiblePanels.map((o) => `no data (current = ${o})`),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,12 +97,18 @@ export async function checkRepeatedPanelTitles(
|
||||
dashboardPage: DashboardPage,
|
||||
selectors: E2ESelectorGroups,
|
||||
title: string,
|
||||
options: Array<string | number>
|
||||
options: Array<string | number>,
|
||||
expectHidden = false
|
||||
) {
|
||||
for (const option of options) {
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(`${title}${option}`))
|
||||
).toBeVisible();
|
||||
const titleLocator = dashboardPage.getByGrafanaSelector(
|
||||
selectors.components.Panels.Panel.title(`${title}${option}`)
|
||||
);
|
||||
if (expectHidden) {
|
||||
await expect(titleLocator).toBeHidden();
|
||||
} else {
|
||||
await expect(titleLocator).toBeVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3308,6 +3308,170 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-37": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"hidden": false,
|
||||
"query": {
|
||||
"group": "",
|
||||
"kind": "DataQuery",
|
||||
"spec": {},
|
||||
"version": "v0"
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
}
|
||||
],
|
||||
"queryOptions": {},
|
||||
"transformations": []
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"id": 37,
|
||||
"links": [],
|
||||
"title": "Hide panel - custom variable equals a (current = ${myCustomVariable})",
|
||||
"vizConfig": {
|
||||
"group": "text",
|
||||
"kind": "VizConfig",
|
||||
"spec": {
|
||||
"fieldConfig": {
|
||||
"defaults": {},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"code": {
|
||||
"language": "plaintext",
|
||||
"showLineNumbers": false,
|
||||
"showMiniMap": false
|
||||
},
|
||||
"content": "",
|
||||
"mode": "markdown"
|
||||
}
|
||||
},
|
||||
"version": "12.2.0-pre"
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-38": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"hidden": false,
|
||||
"query": {
|
||||
"datasource": {
|
||||
"name": "PD8C576611E62080A"
|
||||
},
|
||||
"group": "grafana-testdata-datasource",
|
||||
"kind": "DataQuery",
|
||||
"spec": {
|
||||
"labels": "key=$myCustomVariable",
|
||||
"scenarioId": "random_walk",
|
||||
"seriesCount": 1
|
||||
},
|
||||
"version": "v0"
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
}
|
||||
],
|
||||
"queryOptions": {},
|
||||
"transformations": []
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"id": 38,
|
||||
"links": [],
|
||||
"title": "Hide panel - no data (current = ${myCustomVariable})",
|
||||
"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",
|
||||
"showValues": false,
|
||||
"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": {
|
||||
@@ -5091,6 +5255,80 @@
|
||||
},
|
||||
"title": "Tab - hide - time range <7d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "TabsLayoutTab",
|
||||
"spec": {
|
||||
"layout": {
|
||||
"kind": "AutoGridLayout",
|
||||
"spec": {
|
||||
"columnWidthMode": "standard",
|
||||
"items": [
|
||||
{
|
||||
"kind": "AutoGridLayoutItem",
|
||||
"spec": {
|
||||
"conditionalRendering": {
|
||||
"kind": "ConditionalRenderingGroup",
|
||||
"spec": {
|
||||
"condition": "and",
|
||||
"items": [
|
||||
{
|
||||
"kind": "ConditionalRenderingVariable",
|
||||
"spec": {
|
||||
"operator": "equals",
|
||||
"value": "a",
|
||||
"variable": "myCustomVariable"
|
||||
}
|
||||
}
|
||||
],
|
||||
"visibility": "hide"
|
||||
}
|
||||
},
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-37"
|
||||
},
|
||||
"repeat": {
|
||||
"mode": "variable",
|
||||
"value": "myCustomVariable"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "AutoGridLayoutItem",
|
||||
"spec": {
|
||||
"conditionalRendering": {
|
||||
"kind": "ConditionalRenderingGroup",
|
||||
"spec": {
|
||||
"condition": "and",
|
||||
"items": [
|
||||
{
|
||||
"kind": "ConditionalRenderingData",
|
||||
"spec": {
|
||||
"value": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"visibility": "hide"
|
||||
}
|
||||
},
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-38"
|
||||
},
|
||||
"repeat": {
|
||||
"mode": "variable",
|
||||
"value": "myCustomVariable"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"maxColumnCount": 3,
|
||||
"rowHeightMode": "standard"
|
||||
}
|
||||
},
|
||||
"title": "Tab - repeated items"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5122,6 +5360,39 @@
|
||||
"query": "",
|
||||
"skipUrlSync": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "CustomVariable",
|
||||
"spec": {
|
||||
"allowCustomValue": false,
|
||||
"current": {
|
||||
"text": "All",
|
||||
"value": "$__all"
|
||||
},
|
||||
"hide": "dontHide",
|
||||
"includeAll": true,
|
||||
"multi": false,
|
||||
"name": "myCustomVariable",
|
||||
"options": [
|
||||
{
|
||||
"selected": false,
|
||||
"text": "a",
|
||||
"value": "a"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "b",
|
||||
"value": "b"
|
||||
},
|
||||
{
|
||||
"selected": false,
|
||||
"text": "c",
|
||||
"value": "c"
|
||||
}
|
||||
],
|
||||
"query": "a, b, c",
|
||||
"skipUrlSync": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+15
-4
@@ -68,22 +68,29 @@ export class ConditionalRenderingData extends SceneObjectBase<ConditionalRenderi
|
||||
};
|
||||
}
|
||||
|
||||
private _getObjectDataProvider(): SceneDataProvider | undefined {
|
||||
private _getPanelFromObject(): VizPanel | undefined {
|
||||
const object = getObject(this);
|
||||
|
||||
if (!object) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let panel: VizPanel | undefined;
|
||||
if (object instanceof VizPanel) {
|
||||
return object;
|
||||
}
|
||||
|
||||
for (const val of Object.values(object.state)) {
|
||||
if (val instanceof VizPanel) {
|
||||
panel = val;
|
||||
break;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private _getObjectDataProvider(): SceneDataProvider | undefined {
|
||||
const panel = this._getPanelFromObject();
|
||||
|
||||
if (!panel) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -133,6 +140,10 @@ export class ConditionalRenderingData extends SceneObjectBase<ConditionalRenderi
|
||||
}
|
||||
}
|
||||
|
||||
public forceCheck() {
|
||||
this._check();
|
||||
}
|
||||
|
||||
public renderCmp(): ReactElement {
|
||||
return <this.Component model={this} key={this.state.key} />;
|
||||
}
|
||||
|
||||
+4
@@ -80,6 +80,10 @@ export class ConditionalRenderingTimeRangeSize extends SceneObjectBase<Condition
|
||||
}
|
||||
}
|
||||
|
||||
public forceCheck() {
|
||||
this._check();
|
||||
}
|
||||
|
||||
public renderCmp(): ReactElement {
|
||||
return <this.Component model={this} key={this.state.key} />;
|
||||
}
|
||||
|
||||
+26
-10
@@ -20,7 +20,7 @@ import { getLowerTranslatedObjectType } from '../object';
|
||||
|
||||
import { ConditionalRenderingConditionWrapper } from './ConditionalRenderingConditionWrapper';
|
||||
import { ConditionalRenderingConditionsSerializerRegistryItem } from './serializers';
|
||||
import { checkGroup, getObjectType } from './utils';
|
||||
import { checkGroup, getObject, getObjectType } from './utils';
|
||||
|
||||
type VariableConditionValueOperator = '=' | '!=' | '=~' | '!~';
|
||||
|
||||
@@ -40,14 +40,6 @@ export class ConditionalRenderingVariable extends SceneObjectBase<ConditionalRen
|
||||
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);
|
||||
|
||||
@@ -55,6 +47,20 @@ export class ConditionalRenderingVariable extends SceneObjectBase<ConditionalRen
|
||||
}
|
||||
|
||||
private _activationHandler() {
|
||||
const object = getObject(this);
|
||||
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._variableDependency = new VariableDependencyConfig(object, {
|
||||
onAnyVariableChanged: (v) => {
|
||||
if (v.state.name === this.state.variable) {
|
||||
this._check();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
this.forEachChild((child) => {
|
||||
if (!child.isActive) {
|
||||
this._subs.add(child.activate());
|
||||
@@ -78,7 +84,13 @@ export class ConditionalRenderingVariable extends SceneObjectBase<ConditionalRen
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const variable = sceneGraph.getVariables(this).getByName(this.state.variable);
|
||||
const object = getObject(this);
|
||||
|
||||
if (!object) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const variable = sceneGraph.getVariables(object).getByName(this.state.variable);
|
||||
|
||||
if (!variable) {
|
||||
return undefined;
|
||||
@@ -127,6 +139,10 @@ export class ConditionalRenderingVariable extends SceneObjectBase<ConditionalRen
|
||||
}
|
||||
}
|
||||
|
||||
public forceCheck() {
|
||||
this._check();
|
||||
}
|
||||
|
||||
public renderCmp(): ReactElement {
|
||||
return <this.Component model={this} key={this.state.key} />;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,13 @@ export function getGroup(condition: ConditionalRenderingConditions): Conditional
|
||||
}
|
||||
|
||||
export function getObject(condition: ConditionalRenderingConditions): SceneObject | undefined {
|
||||
const group = getGroup(condition);
|
||||
const groupTarget = group.getTarget();
|
||||
|
||||
if (groupTarget) {
|
||||
return groupTarget;
|
||||
}
|
||||
|
||||
return getGroup(condition).parent;
|
||||
}
|
||||
|
||||
|
||||
+22
-1
@@ -2,7 +2,14 @@ import { lowerCase } from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { t } from '@grafana/i18n';
|
||||
import { SceneComponentProps, sceneGraph, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||
import {
|
||||
SceneComponentProps,
|
||||
sceneGraph,
|
||||
SceneObject,
|
||||
SceneObjectBase,
|
||||
SceneObjectRef,
|
||||
SceneObjectState,
|
||||
} from '@grafana/scenes';
|
||||
import { ConditionalRenderingGroupKind } from '@grafana/schema/dist/esm/schema/dashboard/v2';
|
||||
import { Stack } from '@grafana/ui';
|
||||
|
||||
@@ -33,6 +40,7 @@ export class ConditionalRenderingGroup extends SceneObjectBase<ConditionalRender
|
||||
|
||||
private _shouldShow: boolean;
|
||||
private _shouldMatchAll: boolean;
|
||||
private _target?: SceneObjectRef<SceneObject>;
|
||||
|
||||
public constructor(state: ConditionalRenderingGroupState) {
|
||||
super(state);
|
||||
@@ -52,6 +60,19 @@ export class ConditionalRenderingGroup extends SceneObjectBase<ConditionalRender
|
||||
this.check();
|
||||
}
|
||||
|
||||
public setTarget(target: SceneObject | undefined) {
|
||||
this._target = target ? target.getRef() : undefined;
|
||||
this.forceCheck();
|
||||
}
|
||||
|
||||
public getTarget(): SceneObject | undefined {
|
||||
return this._target?.resolve();
|
||||
}
|
||||
|
||||
public forceCheck() {
|
||||
this.state.conditions.forEach((condition) => condition.forceCheck());
|
||||
}
|
||||
|
||||
public check() {
|
||||
// Filter out undefined results
|
||||
// Because we negate the result if shouldShow is false, we can use `condition.state.result ?? true` directly below
|
||||
|
||||
+6
-8
@@ -1,12 +1,13 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { SceneObject, useSceneObjectState } from '@grafana/scenes';
|
||||
import { 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();
|
||||
@@ -14,13 +15,10 @@ function getPlaceholderConditionalRendering(): ConditionalRenderingGroup {
|
||||
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, {
|
||||
export function useIsConditionallyHidden(
|
||||
conditionalRendering: ConditionalRenderingGroup = getPlaceholderConditionalRendering()
|
||||
): [boolean, string | undefined, ReactNode | null, boolean] {
|
||||
const { result, renderHidden } = useSceneObjectState(conditionalRendering, {
|
||||
shouldActivateOrKeepAlive: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { capitalize, lowerCase } from 'lodash';
|
||||
|
||||
import { t } from '@grafana/i18n';
|
||||
import { SceneObject } from '@grafana/scenes';
|
||||
import { SceneObject, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { AutoGridItem } from '../scene/layout-auto-grid/AutoGridItem';
|
||||
import { RowItem } from '../scene/layout-rows/RowItem';
|
||||
@@ -50,7 +50,7 @@ export function getLowerTranslatedObjectType(type: ObjectsWithConditionalRenderi
|
||||
export function extractObjectType(object: SceneObject | undefined): ObjectsWithConditionalRendering {
|
||||
if (!object) {
|
||||
return 'element';
|
||||
} else if (object instanceof AutoGridItem) {
|
||||
} else if (object instanceof AutoGridItem || object instanceof VizPanel) {
|
||||
return 'panel';
|
||||
} else if (object instanceof RowItem) {
|
||||
return 'row';
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface AutoGridItemState extends SceneObjectState {
|
||||
variableName?: string;
|
||||
isHidden?: boolean;
|
||||
conditionalRendering?: ConditionalRenderingGroup;
|
||||
repeatedConditionalRendering?: ConditionalRenderingGroup[];
|
||||
}
|
||||
|
||||
export class AutoGridItem extends SceneObjectBase<AutoGridItemState> implements DashboardLayoutItem {
|
||||
@@ -130,7 +131,21 @@ export class AutoGridItem extends SceneObjectBase<AutoGridItemState> implements
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ repeatedPanels });
|
||||
let repeatedConditionalRendering: ConditionalRenderingGroup[] | undefined;
|
||||
|
||||
if (this.state.conditionalRendering) {
|
||||
repeatedConditionalRendering = repeatedPanels.reduce<ConditionalRenderingGroup[]>((acc, panel) => {
|
||||
const conditionalRendering = this.state.conditionalRendering!.clone();
|
||||
conditionalRendering.setTarget(panel);
|
||||
acc.push(conditionalRendering);
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this.state.conditionalRendering.setTarget(panelToRepeat);
|
||||
}
|
||||
|
||||
this.setState({ repeatedPanels, repeatedConditionalRendering });
|
||||
this._prevRepeatValues = values;
|
||||
}
|
||||
|
||||
|
||||
+21
-18
@@ -5,6 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data/';
|
||||
import { LazyLoader, SceneComponentProps, VizPanel } from '@grafana/scenes';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { ConditionalRenderingGroup } from '../../conditional-rendering/group/ConditionalRenderingGroup';
|
||||
import { useIsConditionallyHidden } from '../../conditional-rendering/hooks/useIsConditionallyHidden';
|
||||
import { useDashboardState } from '../../utils/utils';
|
||||
import { renderMatchingSoloPanels, useSoloPanelContext } from '../SoloPanelContext';
|
||||
@@ -17,8 +18,6 @@ export function AutoGridItemRenderer({ model }: SceneComponentProps<AutoGridItem
|
||||
const { body, repeatedPanels = [], key } = model.useState();
|
||||
const { draggingKey } = model.getParentGrid().useState();
|
||||
const { isEditing, preload } = useDashboardState(model);
|
||||
const [isConditionallyHidden, conditionalRenderingClass, conditionalRenderingOverlay, renderHidden] =
|
||||
useIsConditionallyHidden(model);
|
||||
const styles = useStyles2(getStyles);
|
||||
const soloPanelContext = useSoloPanelContext();
|
||||
const isLazy = useMemo(() => getIsLazy(preload), [preload]);
|
||||
@@ -29,18 +28,23 @@ export function AutoGridItemRenderer({ model }: SceneComponentProps<AutoGridItem
|
||||
memo(
|
||||
({
|
||||
item,
|
||||
conditionalRendering,
|
||||
addDndContainer,
|
||||
isDragged,
|
||||
isDragging,
|
||||
isRepeat = false,
|
||||
}: {
|
||||
item: VizPanel;
|
||||
conditionalRendering?: ConditionalRenderingGroup;
|
||||
addDndContainer: boolean;
|
||||
isDragged: boolean;
|
||||
isDragging: boolean;
|
||||
isRepeat?: boolean;
|
||||
}) =>
|
||||
isConditionallyHidden && !isEditing && !renderHidden ? null : (
|
||||
}) => {
|
||||
const [isConditionallyHidden, conditionalRenderingClass, conditionalRenderingOverlay, renderHidden] =
|
||||
useIsConditionallyHidden(conditionalRendering);
|
||||
|
||||
return isConditionallyHidden && !isEditing && !renderHidden ? null : (
|
||||
<div
|
||||
{...(addDndContainer
|
||||
? { ref: model.containerRef, ['data-auto-grid-item-drop-target']: isDragging ? key : undefined }
|
||||
@@ -78,19 +82,10 @@ export function AutoGridItemRenderer({ model }: SceneComponentProps<AutoGridItem
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
),
|
||||
[
|
||||
conditionalRenderingClass,
|
||||
conditionalRenderingOverlay,
|
||||
isLazy,
|
||||
key,
|
||||
model.containerRef,
|
||||
styles,
|
||||
isConditionallyHidden,
|
||||
isEditing,
|
||||
renderHidden,
|
||||
]
|
||||
[model, isLazy, key, styles, isEditing]
|
||||
);
|
||||
|
||||
if (soloPanelContext) {
|
||||
@@ -102,10 +97,18 @@ export function AutoGridItemRenderer({ model }: SceneComponentProps<AutoGridItem
|
||||
|
||||
return (
|
||||
<>
|
||||
<Wrapper item={body} addDndContainer={true} key={body.state.key!} isDragged={isDragged} isDragging={isDragging} />
|
||||
{repeatedPanels.map((item) => (
|
||||
<Wrapper
|
||||
item={body}
|
||||
conditionalRendering={model.state.conditionalRendering}
|
||||
addDndContainer={true}
|
||||
key={body.state.key!}
|
||||
isDragged={isDragged}
|
||||
isDragging={isDragging}
|
||||
/>
|
||||
{repeatedPanels.map((item, idx) => (
|
||||
<Wrapper
|
||||
item={item}
|
||||
conditionalRendering={model.state.repeatedConditionalRendering?.[idx]}
|
||||
addDndContainer={false}
|
||||
key={item.state.key!}
|
||||
isDragged={isDragged}
|
||||
|
||||
@@ -20,8 +20,9 @@ export function RowItemRenderer({ model }: SceneComponentProps<RowItem>) {
|
||||
const { layout, collapse: isCollapsed, fillScreen, hideHeader: isHeaderHidden, isDropTarget, key } = model.useState();
|
||||
const isClone = isRepeatCloneOrChildOf(model);
|
||||
const { isEditing } = useDashboardState(model);
|
||||
const [isConditionallyHidden, conditionalRenderingClass, conditionalRenderingOverlay] =
|
||||
useIsConditionallyHidden(model);
|
||||
const [isConditionallyHidden, conditionalRenderingClass, conditionalRenderingOverlay] = useIsConditionallyHidden(
|
||||
model.state.conditionalRendering
|
||||
);
|
||||
const { isSelected, onSelect, isSelectable } = useElementSelection(key);
|
||||
const title = useInterpolatedTitle(model);
|
||||
const { rows } = model.getParentLayout().useState();
|
||||
|
||||
@@ -112,7 +112,10 @@ export function performRowRepeats(variable: MultiValueVariable, row: RowItem, co
|
||||
});
|
||||
|
||||
if (!isSourceRow) {
|
||||
rowClone.state.conditionalRendering?.setTarget(rowClone);
|
||||
clonedRows.push(rowClone);
|
||||
} else {
|
||||
row.state.conditionalRendering?.setTarget(row);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -292,6 +292,8 @@ export class RowsLayoutManager extends SceneObjectBase<RowsLayoutManagerState> i
|
||||
|
||||
const conditionalRendering = tab.state.conditionalRendering;
|
||||
conditionalRendering?.clearParent();
|
||||
// We need to clear the target since we don't want to point the original tab anymore (if it was set)
|
||||
conditionalRendering?.setTarget(undefined);
|
||||
|
||||
rows.push(
|
||||
new RowItem({
|
||||
|
||||
@@ -29,7 +29,7 @@ export function TabItemRenderer({ model }: SceneComponentProps<TabItem>) {
|
||||
const href = textUtil.sanitize(locationUtil.getUrlForPartial(location, { [urlKey]: mySlug }));
|
||||
const styles = useStyles2(getStyles);
|
||||
const pointerDistance = usePointerDistance();
|
||||
const [isConditionallyHidden] = useIsConditionallyHidden(model);
|
||||
const [isConditionallyHidden] = useIsConditionallyHidden(model.state.conditionalRendering);
|
||||
const isClone = isRepeatCloneOrChildOf(model);
|
||||
const soloPanelContext = useSoloPanelContext();
|
||||
|
||||
@@ -116,7 +116,9 @@ interface TabItemLayoutRendererProps {
|
||||
export function TabItemLayoutRenderer({ tab, isEditing }: TabItemLayoutRendererProps) {
|
||||
const { layout, key } = tab.useState();
|
||||
const styles = useStyles2(getStyles);
|
||||
const [_, conditionalRenderingClass, conditionalRenderingOverlay] = useIsConditionallyHidden(tab);
|
||||
const [_, conditionalRenderingClass, conditionalRenderingOverlay] = useIsConditionallyHidden(
|
||||
tab.state.conditionalRendering
|
||||
);
|
||||
|
||||
return (
|
||||
<TabContent
|
||||
|
||||
@@ -167,7 +167,10 @@ export function createTabRepeats({
|
||||
});
|
||||
|
||||
if (!isSourceTab) {
|
||||
tabClone.state.conditionalRendering?.setTarget(tabClone);
|
||||
repeats.push(tabClone);
|
||||
} else {
|
||||
tab.state.conditionalRendering?.setTarget(tab);
|
||||
}
|
||||
}
|
||||
return repeats;
|
||||
|
||||
@@ -417,6 +417,8 @@ export class TabsLayoutManager extends SceneObjectBase<TabsLayoutManagerState> i
|
||||
|
||||
const conditionalRendering = row.state.conditionalRendering;
|
||||
conditionalRendering?.clearParent();
|
||||
// We need to clear the target since we don't want to point the original row anymore (if it was set)
|
||||
conditionalRendering?.setTarget(undefined);
|
||||
|
||||
tabs.push(
|
||||
new TabItem({
|
||||
|
||||
Reference in New Issue
Block a user