Compare commits

...

8 Commits

Author SHA1 Message Date
Paul Marbach
5977350c51 updates from review 2025-12-05 13:24:20 -05:00
Alex Spencer
d965857ff0 chore: alex - fix debug background 2025-12-05 09:39:18 -08:00
Develer
444eabcabb Merge branch 'data-manipulation-improvements' of github.com:grafana/grafana into data-manipulation-improvements 2025-12-05 18:08:34 +01:00
Develer
f55e17f853 update debug icon 2025-12-05 18:08:14 +01:00
Paul Marbach
18f99ceaa9 Merge branch 'data-manipulation-improvements-resize-issue' into data-manipulation-improvements 2025-12-05 12:01:33 -05:00
Paul Marbach
d2f44c3859 layout update with height issue 2025-12-05 11:59:38 -05:00
Paul Marbach
21e82214a6 good enough 2025-12-05 11:59:12 -05:00
Develer
c2b8e7fcd5 cleanup styles 2025-12-05 16:48:15 +01:00
10 changed files with 87 additions and 38 deletions

View File

@@ -41,6 +41,7 @@ export const availableIconsIndex = {
asserts: true,
'expand-arrows': true,
'expand-arrows-alt': true,
'expand-alt': true,
at: true,
ai: true,
'ai-pointer': true,
@@ -87,6 +88,7 @@ export const availableIconsIndex = {
'comments-alt': true,
compass: true,
'compress-arrows': true,
'compress-alt': true,
copy: true,
'corner-up-left': true,
'corner-up-right': true,
@@ -97,6 +99,7 @@ export const availableIconsIndex = {
cube: true,
dashboard: true,
database: true,
'debug-handle': true,
'dice-three': true,
docker: true,
'document-info': true,

View File

@@ -56,6 +56,7 @@
"unicons/comment-alt-share",
"unicons/comments-alt",
"unicons/compass",
"unicons/compress-alt",
"unicons/copy",
"unicons/corner-down-right-alt",
"unicons/corner-up-left",
@@ -63,6 +64,7 @@
"unicons/cube",
"unicons/dashboard",
"unicons/database",
"unicons/debug-handle",
"unicons/document-info",
"unicons/download-alt",
"unicons/draggabledots",
@@ -73,6 +75,7 @@
"unicons/exchange-alt",
"unicons/exclamation-circle",
"unicons/exclamation-triangle",
"unicons/expand-alt",
"unicons/external-link-alt",
"unicons/eye",
"unicons/eye-slash",

View File

@@ -135,7 +135,7 @@ export const AddDataItemMenu = memo(
const getStyles = (theme: GrafanaTheme2) => ({
textButton: css({
paddingLeft: 0,
paddingLeft: theme.spacing(1),
fontFamily: theme.typography.fontFamilyMonospace,
}),
queryLibraryMenuItem: css({

View File

@@ -102,6 +102,7 @@ export function PanelDataSidebar({
return selectedQueryTransform;
}, [transformPickerIndex, selectedQueryTransform, allItems]);
const selectedItem = useMemo(() => allItems.find((item) => item.id === selectedId), [allItems, selectedId]);
const shouldShowAlerting = useMemo(() => tabs.some((tab) => tab.tabId === TabId.Alert), [tabs]);
const updateQuerySelectionOnStateChange = useCallback(
(index: number) => {
@@ -329,6 +330,7 @@ export function PanelDataSidebar({
transformItems={transformItems}
selectedId={selectedId}
sidebarSize={sidebarState.size}
hasAlerting={shouldShowAlerting}
onResizeSidebar={(size: SidebarSize) => setSidebarState((prevState) => ({ ...prevState, size }))}
onCollapseSidebar={() => setSidebarState((prevState) => ({ ...prevState, collapsed: true }))}
onSelect={(id) => {

View File

@@ -313,7 +313,7 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
},
}),
content: css({
padding: theme.spacing(1.5),
padding: theme.spacing(0.75) + ' ' + theme.spacing(1),
}),
datasourceIcon: css({
width: '16px',

View File

@@ -4,7 +4,7 @@ import { HTMLAttributes, memo, useCallback, useEffect, useMemo, useRef, useState
import { GrafanaTheme2 } from '@grafana/data';
import { t } from '@grafana/i18n';
import { Button, Icon, ScrollContainer, Stack, useStyles2 } from '@grafana/ui';
import { Button, Icon, IconButton, ScrollContainer, Stack, useStyles2 } from '@grafana/ui';
import { ExpressionQueryType } from 'app/features/expressions/types';
import { AddDataItemMenu } from './AddDataItemMenu';
@@ -25,6 +25,7 @@ interface QueryTransformListProps {
sidebarSize: SidebarSize;
transformItems: TransformItem[];
selectedId: string | null;
hasAlerting?: boolean;
onSelect: (id: string) => void;
onAddQuery: (index?: number) => void;
onAddFromSavedQueries: (index?: number) => void;
@@ -50,6 +51,7 @@ export const QueryTransformList = memo(
allItems,
selectedId,
sidebarSize,
hasAlerting,
onSelect,
onAddQuery,
onAddFromSavedQueries,
@@ -357,17 +359,30 @@ export const QueryTransformList = memo(
<div className={styles.container} onMouseLeave={() => setHovered(null)}>
<div className={styles.header}>
<Stack justifyContent="space-between" alignItems="center" gap={2}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<div
className={styles.headerTitle}
onClick={() => onResizeSidebar(sidebarSize === SidebarSize.Mini ? SidebarSize.Full : SidebarSize.Mini)}
>
<Stack direction="row" alignItems="center" gap={1}>
<Icon name={sidebarSize === SidebarSize.Mini ? 'expand-arrows' : 'compress-arrows'} />
<span>{t('dashboard-scene.query-transform-list.header', 'Pipeline flow')}</span>
</Stack>
</div>
<Stack direction="row" alignItems="center" gap={1}>
<IconButton
tooltip={
sidebarSize === SidebarSize.Mini
? t('dashboard-scene.query-transform-list.expand-sidebar', 'Expand sidebar')
: t('dashboard-scene.query-transform-list.collapse-sidebar', 'Collapse sidebar')
}
onClick={() => onResizeSidebar(sidebarSize === SidebarSize.Mini ? SidebarSize.Full : SidebarSize.Mini)}
className={styles.rotate90}
name={sidebarSize === SidebarSize.Mini ? 'expand-alt' : 'compress-alt'}
/>
<span className={styles.headerTitle}>{t('dashboard-scene.query-transform-list.header', 'Pipeline')}</span>
</Stack>
<Stack direction="row" gap={0.5}>
{hasAlerting && (
<Button
variant="secondary"
fill="text"
size="sm"
tooltip={t('dashboard-scene.query-transform-list.notifications-tooltip', 'Alerts (coming soon)')}
>
<Icon name="bell" size="sm" />
</Button>
)}
<Button
variant="secondary"
fill="text"
@@ -449,7 +464,7 @@ export const QueryTransformList = memo(
)}
data-testid="query-transform-list-content"
>
<Stack direction="column" gap={3}>
<Stack direction="column" gap={2}>
{/* Data Sources Section (Queries + Expressions) */}
<Stack direction="column" gap={2}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
@@ -565,7 +580,7 @@ export const QueryTransformList = memo(
}}
>
<div className={styles.debugLineHandle}>
<Icon name="draggabledots" size="sm" />
<Icon name="debug-handle" size="sm" />
</div>
</div>
)}
@@ -721,7 +736,7 @@ export const QueryTransformList = memo(
}}
>
<div className={styles.debugLineHandle}>
<Icon name="draggabledots" size="sm" />
<Icon name="debug-handle" size="sm" />
</div>
</div>
)}
@@ -821,7 +836,6 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
fontFamily: theme.typography.fontFamilyMonospace,
textTransform: 'uppercase',
color: theme.colors.text.primary,
cursor: 'pointer',
}),
sectionLabel: css({
cursor: 'pointer',
@@ -1018,7 +1032,8 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
letterSpacing: '0.05em',
}),
debugButtonActive: css({
'&:focus, &:active, &:focus:active': {
background: '#441306',
'&:hover, &:focus, &:active, &:focus:active': {
background: '#441306',
},
}),
@@ -1050,7 +1065,8 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
top: '50%',
transform: 'translate(-50%, -50%)',
background: colors.query.accent,
borderRadius: theme.shape.radius.circle,
borderRadius: theme.shape.radius.default,
height: theme.spacing(2),
padding: theme.spacing(0.5),
display: 'flex',
alignItems: 'center',
@@ -1061,5 +1077,8 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
cursor: 'grabbing',
},
}),
rotate90: css({
transform: 'rotate(90deg)',
}),
};
};

View File

@@ -25,6 +25,11 @@ export function PanelEditorRenderer({ model }: SceneComponentProps<PanelEditor>)
const { optionsPane } = model.useState();
const styles = useStyles2(getWrapperStyles);
const [isInitiallyCollapsed, setIsCollapsed] = useEditPaneCollapsed();
const [containerRef, { height: containerHeight }] = useMeasure<HTMLDivElement>();
useEffect(() => {
console.log('PanelEditorRenderer containerHeight', containerHeight);
}, [containerHeight]);
const isScrollingLayout = useScrollReflowLimit();
@@ -46,7 +51,7 @@ export function PanelEditorRenderer({ model }: SceneComponentProps<PanelEditor>)
}, [splitterState.collapsed, setIsCollapsed]);
return (
<>
<div style={{ height: '100%' }} ref={containerRef}>
<NavToolbarActions dashboard={dashboard} />
<div
{...containerProps}
@@ -54,7 +59,7 @@ export function PanelEditorRenderer({ model }: SceneComponentProps<PanelEditor>)
data-testid={selectors.components.PanelEditor.General.content}
>
<div {...primaryProps} className={cx(primaryProps.className, styles.body)}>
<VizAndDataPane model={model} />
<VizAndDataPane model={model} containerHeight={Math.max(containerHeight, 500)} />
</div>
<div {...splitterProps} />
<div {...secondaryProps} className={cx(secondaryProps.className, styles.optionsPane)}>
@@ -77,11 +82,14 @@ export function PanelEditorRenderer({ model }: SceneComponentProps<PanelEditor>)
{!splitterState.collapsed && !optionsPane && <Spinner />}
</div>
</div>
</>
</div>
);
}
function VizAndDataPane({ model }: SceneComponentProps<PanelEditor>) {
function VizAndDataPane({
model,
containerHeight = 800,
}: SceneComponentProps<PanelEditor> & { containerHeight?: number }) {
const dashboard = getDashboardSceneFor(model);
const { dataPane, showLibraryPanelSaveModal, showLibraryPanelUnlinkModal, tableView } = model.useState();
const panel = model.getPanel();
@@ -107,7 +115,6 @@ function VizAndDataPane({ model }: SceneComponentProps<PanelEditor>) {
rows.push(`${vizHeight}px`);
if (dataPane) {
// rows.push(`${(containerHeight - vizHeight) + 40}px`);
rows.push('auto');
grid.push(['sidebar', 'data-pane']);
if (sidebarState.size === SidebarSize.Full) {
@@ -118,10 +125,16 @@ function VizAndDataPane({ model }: SceneComponentProps<PanelEditor>) {
}
return {
height: containerHeight,
maxHeight: containerHeight,
gridTemplateAreas: '\n' + grid.map((row) => `"${row.join(' ')}"`).join('\n'),
gridTemplateRows: rows.map((r) => r).join(' '),
};
}, [controls, dataPane, sidebarState.size, vizHeight]);
}, [controls, dataPane, sidebarState.size, vizHeight, containerHeight]);
if (!containerHeight) {
return null;
}
return (
<div className={styles.pageContainer} style={gridStyles}>
@@ -131,7 +144,11 @@ function VizAndDataPane({ model }: SceneComponentProps<PanelEditor>) {
</div>
)}
<div ref={vizRef} style={{ height: 550 }} className={cx(styles.viz, isScrollingLayout && styles.fixedSizeViz)}>
<div
className={cx(styles.viz, isScrollingLayout && styles.fixedSizeViz)}
ref={vizRef}
style={{ height: containerHeight / 2, maxHeight: containerHeight - 80 }}
>
{tableView ? <tableView.Component model={tableView} /> : <panel.Component model={panel} />}
</div>
@@ -215,9 +232,6 @@ function getStyles(theme: GrafanaTheme2, sidebarState: SidebarState) {
display: 'grid',
gap: theme.spacing(2),
gridTemplateColumns: `auto 1fr`,
height: '100%',
minHeight: '100%',
maxHeight: '100%',
overflow: 'hidden',
[scrollReflowMediaQuery]: {
gridTemplateColumns: `100%`,
@@ -238,14 +252,14 @@ function getStyles(theme: GrafanaTheme2, sidebarState: SidebarState) {
overflow: 'auto',
resize: 'vertical',
height: '100%',
minHeight: 200,
maxHeight: 700, // FIXME: needs a dynamic height
minHeight: 100,
...(sidebarState.size === SidebarSize.Mini && {
paddingLeft: theme.spacing(2),
}),
}),
dataPane: css({
gridArea: 'data-pane',
overflow: 'hidden',
}),
controlsWrapper: css({
gridArea: 'controls',

View File

@@ -158,7 +158,7 @@ function PanelOptionsPaneComponent({ model }: SceneComponentProps<PanelOptionsPa
}, [pluginId]);
return (
<>
<div className={styles.wrapper}>
{!isVizPickerOpen && (
<>
<div className={styles.top}>
@@ -235,12 +235,19 @@ function PanelOptionsPaneComponent({ model }: SceneComponentProps<PanelOptionsPa
showBackButton={config.featureToggles.newVizSuggestions ? hasPickedViz || !isNewPanel : true}
/>
)}
</>
</div>
);
}
function getStyles(theme: GrafanaTheme2) {
return {
wrapper: css({
display: 'contents',
'& h6': {
fontFamily: theme.typography.fontFamilyMonospace,
textTransform: 'uppercase',
},
}),
top: css({
display: 'flex',
flexDirection: 'row',

View File

@@ -0,0 +1,3 @@
<svg viewBox="0 0 16 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.8 1.66667H15.2C15.4122 1.66667 15.6157 1.57887 15.7657 1.42259C15.9157 1.26631 16 1.05435 16 0.833333C16 0.61232 15.9157 0.400358 15.7657 0.244078C15.6157 0.0877975 15.4122 0 15.2 0H0.8C0.587827 0 0.384344 0.0877975 0.234315 0.244078C0.0842854 0.400358 0 0.61232 0 0.833333C0 1.05435 0.0842854 1.26631 0.234315 1.42259C0.384344 1.57887 0.587827 1.66667 0.8 1.66667ZM15.2 3.33333H0.8C0.587827 3.33333 0.384344 3.42113 0.234315 3.57741C0.0842854 3.73369 0 3.94565 0 4.16667C0 4.38768 0.0842854 4.59964 0.234315 4.75592C0.384344 4.9122 0.587827 5 0.8 5H15.2C15.4122 5 15.6157 4.9122 15.7657 4.75592C15.9157 4.59964 16 4.38768 16 4.16667C16 3.94565 15.9157 3.73369 15.7657 3.57741C15.6157 3.42113 15.4122 3.33333 15.2 3.33333Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 837 B

View File

@@ -6005,6 +6005,7 @@
"hide-response": "Hide response",
"input-data": "Input data",
"output-data": "Output data",
"query-inspector": "Query inspector",
"remove-query": "Remove",
"remove-transform": "Remove",
"run-query": "RUN QUERY",
@@ -6325,8 +6326,9 @@
"debug-mode-enter": "Step through your pipeline",
"debug-mode-exit": "Exit debug mode",
"debug-position": "Debug position",
"header": "Pipeline flow",
"header": "Pipeline",
"nodes": "nodes",
"notifications-tooltip": "Alerts (coming soon)",
"queries-expressions": "Queries & Expressions",
"transformations": "Transformations"
},
@@ -6631,10 +6633,6 @@
"aria-label-change-visualization": "Change visualization",
"text": "Change"
},
"viz-and-data-pane": {
"aria-label-open-query-pane": "Open query pane",
"tooltip-open-query-pane": "Open query pane"
},
"viz-panel-links-renderer": {
"aria-label-panel-links": "Panel links"
}