diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailView.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailView.tsx
new file mode 100644
index 00000000000..5d2e585ed33
--- /dev/null
+++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailView.tsx
@@ -0,0 +1,81 @@
+import { css } from '@emotion/css';
+import { memo, useCallback } from 'react';
+
+import { GrafanaTheme2 } from '@grafana/data';
+import { Trans } from '@grafana/i18n';
+import { VizPanel } from '@grafana/scenes';
+import { Container, ScrollContainer, useStyles2 } from '@grafana/ui';
+
+import { PanelDataTransformationsTab, PanelDataTransformationsTabRendered } from './PanelDataTransformationsTab';
+import { QueryDetailView } from './QueryDetailView';
+import { QueryTransformItem } from './QueryTransformList';
+import { TabId } from './types';
+
+interface DetailViewProps {
+ selectedItem: QueryTransformItem | undefined;
+ panel: VizPanel;
+ tabs: Array<{ tabId: TabId }>;
+}
+
+export const DetailView = memo(({ selectedItem, panel, tabs }: DetailViewProps) => {
+ const styles = useStyles2(getStyles);
+
+ const renderContent = useCallback(() => {
+ if (!selectedItem) {
+ return (
+
+
+
+ Select a query or transformation to edit
+
+
+
+ );
+ }
+
+ if (selectedItem.type === 'query' && 'refId' in selectedItem.data) {
+ const query = selectedItem.data;
+ return (
+
+
+
+ );
+ } else {
+ const transformsTab = tabs.find((t) => t.tabId === TabId.Transformations);
+ if (transformsTab instanceof PanelDataTransformationsTab && 'id' in selectedItem.data) {
+ return (
+
+
+
+
+
+ );
+ }
+ }
+
+ return null;
+ }, [selectedItem, panel, tabs, styles.emptyState]);
+
+ return {renderContent()}
;
+});
+
+DetailView.displayName = 'DetailView';
+
+const getStyles = (theme: GrafanaTheme2) => {
+ return {
+ container: css({
+ display: 'flex',
+ flexDirection: 'column',
+ height: '100%',
+ background: theme.colors.background.primary,
+ }),
+ emptyState: css({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: '100%',
+ color: theme.colors.text.secondary,
+ fontSize: theme.typography.h5.fontSize,
+ }),
+ };
+};
diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx
index 29313dc1986..cbfb9b2e1a5 100644
--- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx
+++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx
@@ -3,7 +3,6 @@ import { useCallback, useMemo, useState } from 'react';
import { DataTransformerConfig, GrafanaTheme2, SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
-import { Trans } from '@grafana/i18n';
import {
SceneComponentProps,
SceneObjectBase,
@@ -14,7 +13,7 @@ import {
VizPanel,
SceneDataTransformer,
} from '@grafana/scenes';
-import { Container, ScrollContainer, useStyles2 } from '@grafana/ui';
+import { useStyles2 } from '@grafana/ui';
import { getConfig } from 'app/core/config';
import { contextSrv } from 'app/core/services/context_srv';
import { getRulesPermissions } from 'app/features/alerting/unified/utils/access-control';
@@ -22,11 +21,11 @@ import { GRAFANA_RULES_SOURCE_NAME } from 'app/features/alerting/unified/utils/d
import { getQueryRunnerFor } from '../../utils/utils';
+import { DetailView } from './DetailView';
import { PanelDataAlertingTab } from './PanelDataAlertingTab';
import { PanelDataQueriesTab } from './PanelDataQueriesTab';
-import { PanelDataTransformationsTab, PanelDataTransformationsTabRendered } from './PanelDataTransformationsTab';
+import { PanelDataTransformationsTab } from './PanelDataTransformationsTab';
import { QueryTransformList, QueryTransformItem } from './QueryTransformList';
-import { SceneQueryDetailView } from './SceneQueryDetailView';
import { TransformationsDrawer } from './TransformationsDrawer';
import { PanelDataPaneTab, TabId } from './types';
@@ -286,46 +285,6 @@ function PanelDataPaneRendered({ model }: SceneComponentProps) {
[tabs, selectedId]
);
- const renderDetailPanel = useCallback(() => {
- if (!selectedItem) {
- return (
-
-
-
- Select a query or transformation to edit
-
-
-
- );
- }
-
- if (selectedItem.type === 'query' && 'refId' in selectedItem.data) {
- const query = selectedItem.data;
- return (
-
-
-
-
-
- );
- } else {
- const transformsTab = tabs.find((t) => t.tabId === TabId.Transformations);
- if (transformsTab instanceof PanelDataTransformationsTab && 'id' in selectedItem.data) {
- return (
-
- );
- }
- }
-
- return null;
- }, [selectedItem, tabs, styles, panel]);
-
// Get data for transformations drawer
const sourceData = queryRunner?.useState();
const series = sourceData?.data?.series || [];
@@ -347,7 +306,9 @@ function PanelDataPaneRendered({ model }: SceneComponentProps) {
onRemoveTransform={handleRemoveTransform}
/>
- {renderDetailPanel()}
+
+
+
(null);
const [dsSettings, setDsSettings] = useState(null);
@@ -129,7 +129,7 @@ export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDet
if (!datasource || !dsSettings) {
return (
- Loading data source...
+ Loading data source...
);
}
@@ -138,7 +138,7 @@ export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDet
if (!QueryEditor) {
return (
-
+
This data source does not have a query editor
@@ -170,7 +170,7 @@ export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDet
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 6ceb8e3cead..4c943e42886 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -6235,6 +6235,11 @@
"see-docs": "See <2>documentation2> for more information about provisioning.",
"title-cannot-delete-provisioned-dashboard": "Cannot delete provisioned dashboard"
},
+ "query-detail-view": {
+ "loading": "Loading data source...",
+ "no-editor": "This data source does not have a query editor",
+ "select-datasource": "Select data source"
+ },
"query-editor": {
"query": "Query"
},
@@ -6359,11 +6364,6 @@
"title-same-as-folder": "Dashboard name cannot be the same as the folder name",
"title-validation-failed": "Dashboard title validation failed."
},
- "scene-query-detail-view": {
- "loading": "Loading data source...",
- "no-editor": "This data source does not have a query editor",
- "select-datasource": "Select data source"
- },
"scenes-new-rule-from-panel-button": {
"body-no-alerting-capable-query-found": "Cannot create alerts from this panel because no query to an alerting capable datasource is found.",
"new-alert-rule": "New alert rule",