re-org components

This commit is contained in:
Develer
2025-12-01 15:34:15 +01:00
parent edabcd8b43
commit d3e8bdd928
4 changed files with 97 additions and 90 deletions
@@ -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 (
<div className={styles.emptyState}>
<p>
<Trans i18nKey="dashboard-scene.panel-data-pane.empty-state">
Select a query or transformation to edit
</Trans>
</p>
</div>
);
}
if (selectedItem.type === 'query' && 'refId' in selectedItem.data) {
const query = selectedItem.data;
return (
<ScrollContainer>
<QueryDetailView panel={panel} query={query} queryIndex={selectedItem.index} />
</ScrollContainer>
);
} else {
const transformsTab = tabs.find((t) => t.tabId === TabId.Transformations);
if (transformsTab instanceof PanelDataTransformationsTab && 'id' in selectedItem.data) {
return (
<ScrollContainer>
<Container>
<PanelDataTransformationsTabRendered model={transformsTab} />
</Container>
</ScrollContainer>
);
}
}
return null;
}, [selectedItem, panel, tabs, styles.emptyState]);
return <div className={styles.container}>{renderContent()}</div>;
});
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,
}),
};
};
@@ -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<PanelDataPane>) {
[tabs, selectedId]
);
const renderDetailPanel = useCallback(() => {
if (!selectedItem) {
return (
<div className={styles.emptyState}>
<p>
<Trans i18nKey="dashboard-scene.panel-data-pane.empty-state">
Select a query or transformation to edit
</Trans>
</p>
</div>
);
}
if (selectedItem.type === 'query' && 'refId' in selectedItem.data) {
const query = selectedItem.data;
return (
<div className={styles.detailContent}>
<ScrollContainer>
<SceneQueryDetailView panel={panel} query={query} queryIndex={selectedItem.index} />
</ScrollContainer>
</div>
);
} else {
const transformsTab = tabs.find((t) => t.tabId === TabId.Transformations);
if (transformsTab instanceof PanelDataTransformationsTab && 'id' in selectedItem.data) {
return (
<div className={styles.detailContent}>
<ScrollContainer>
<Container>
<PanelDataTransformationsTabRendered model={transformsTab} />
</Container>
</ScrollContainer>
</div>
);
}
}
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<PanelDataPane>) {
onRemoveTransform={handleRemoveTransform}
/>
</div>
<div className={styles.rightPanel}>{renderDetailPanel()}</div>
<div className={styles.rightPanel}>
<DetailView selectedItem={selectedItem} panel={panel} tabs={tabs} />
</div>
</div>
</div>
<TransformationsDrawer
@@ -411,40 +372,5 @@ function getStyles(theme: GrafanaTheme2) {
minWidth: 0,
overflow: 'hidden',
}),
detailContent: css({
display: 'flex',
flexDirection: 'column',
height: '100%',
background: theme.colors.background.primary,
}),
detailHeader: css({
padding: theme.spacing(2),
borderBottom: `1px solid ${theme.colors.border.weak}`,
background: theme.colors.background.secondary,
'& h3': {
margin: 0,
marginBottom: theme.spacing(0.5),
fontSize: theme.typography.h4.fontSize,
fontWeight: theme.typography.fontWeightMedium,
},
}),
detailHeaderSubtext: css({
margin: 0,
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.text.secondary,
}),
detailBody: css({
flex: 1,
overflow: 'auto',
minHeight: 0,
}),
emptyState: css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
color: theme.colors.text.secondary,
fontSize: theme.typography.h5.fontSize,
}),
};
}
@@ -21,13 +21,13 @@ import { QueryErrorAlert } from 'app/features/query/components/QueryErrorAlert';
import { getQueryRunnerFor } from '../../utils/utils';
interface SceneQueryDetailViewProps {
interface QueryDetailViewProps {
panel: VizPanel;
query: SceneDataQuery;
queryIndex: number;
}
export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDetailViewProps) {
export function QueryDetailView({ panel, query, queryIndex }: QueryDetailViewProps) {
const styles = useStyles2(getStyles);
const [datasource, setDatasource] = useState<DataSourceApi | null>(null);
const [dsSettings, setDsSettings] = useState<DataSourceInstanceSettings | null>(null);
@@ -129,7 +129,7 @@ export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDet
if (!datasource || !dsSettings) {
return (
<div className={styles.noEditor}>
<Trans i18nKey="dashboard-scene.scene-query-detail-view.loading">Loading data source...</Trans>
<Trans i18nKey="dashboard-scene.query-detail-view.loading">Loading data source...</Trans>
</div>
);
}
@@ -138,7 +138,7 @@ export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDet
if (!QueryEditor) {
return (
<div className={styles.noEditor}>
<Trans i18nKey="dashboard-scene.scene-query-detail-view.no-editor">
<Trans i18nKey="dashboard-scene.query-detail-view.no-editor">
This data source does not have a query editor
</Trans>
</div>
@@ -170,7 +170,7 @@ export function SceneQueryDetailView({ panel, query, queryIndex }: SceneQueryDet
<DataSourcePicker
current={dsSettings?.uid || query.datasource}
onChange={handleDataSourceChange}
placeholder={t('dashboard-scene.scene-query-detail-view.select-datasource', 'Select data source')}
placeholder={t('dashboard-scene.query-detail-view.select-datasource', 'Select data source')}
/>
</div>
+5 -5
View File
@@ -6235,6 +6235,11 @@
"see-docs": "See <2>documentation</2> 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",