bug fixes

This commit is contained in:
Paul Marbach
2025-12-02 18:27:55 -05:00
parent ceee8f062c
commit 039292e047
7 changed files with 100 additions and 77 deletions
@@ -54,7 +54,7 @@ export interface ThemeTypographyInput {
}
const defaultFontFamily = "'Inter', 'Helvetica', 'Arial', sans-serif";
const defaultFontFamilyMonospace = "'Roboto Mono', monospace";
const defaultFontFamilyMonospace = "'CommitMono', monospace";
export function createTypography(colors: ThemeColors, typographyInput: ThemeTypographyInput = {}): ThemeTypography {
const {
+1 -1
View File
@@ -32,7 +32,7 @@ const theme: GrafanaThemeCommons = {
typography: {
fontFamily: {
sansSerif: '"Inter", "Helvetica", "Arial", sans-serif',
monospace: "'Roboto Mono', monospace",
monospace: "'CommitMono', monospace",
},
size: {
base: '14px',
@@ -90,11 +90,7 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
return undefined;
}, [selectedItem]);
// Get all queries for validation
const allQueries = useMemo(() => {
const queryRunner = getQueryRunnerFor(panel);
return queryRunner?.state.queries || [];
}, [panel]);
const queryRunner = getQueryRunnerFor(panel);
// Handle datasource change for queries
const handleDataSourceChange = useCallback(
@@ -177,7 +173,7 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
return;
}
for (const otherQuery of allQueries) {
for (const otherQuery of queryRunner?.state.queries || []) {
if (otherQuery !== selectedItem.data && newName === otherQuery.refId) {
setValidationError('Query name already exists');
return;
@@ -188,7 +184,7 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
setValidationError(null);
}
},
[allQueries, selectedItem.data, validationError]
[queryRunner, selectedItem.data, validationError]
);
const onEditQueryBlur = useCallback(
@@ -290,7 +286,7 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
<>
{!isEditing ? (
<button
className={styles.queryNameWrapper}
className={cx(styles.queryNameWrapper, styles.monospace)}
title={t('dashboard-scene.detail-view-header.edit-query-name', 'Edit query name')}
onClick={onEditQueryName}
type="button"
@@ -321,7 +317,14 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
{/* Right side: Run Query + Actions Menu */}
{(selectedItem.type === 'query' || selectedItem.type === 'expression') && (
<Stack gap={0.5} alignItems="center">
<Button variant="primary" fill="text" size="sm" onClick={onRunQuery} icon="play">
<Button
className={styles.monospace}
variant="primary"
fill="text"
size="sm"
onClick={onRunQuery}
icon="play"
>
{t('dashboard-scene.detail-view-header.run-query', 'RUN QUERY')}
</Button>
<Dropdown
@@ -365,6 +368,9 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
const getStyles = (theme: GrafanaTheme2, config: { color: string }) => {
return {
monospace: css({
fontFamily: theme.typography.fontFamilyMonospace,
}),
header: css({
padding: theme.spacing(0.5),
borderLeft: `4px solid ${config.color}`,
@@ -13,7 +13,7 @@ import {
import { Trans } from '@grafana/i18n';
import { getDataSourceSrv } from '@grafana/runtime';
import { SceneDataQuery, VizPanel, sceneGraph, SceneQueryRunner } from '@grafana/scenes';
import { Button, ErrorBoundaryAlert, useStyles2 } from '@grafana/ui';
import { Button, ErrorBoundaryAlert, Stack, useStyles2 } from '@grafana/ui';
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
import { QueryErrorAlert } from 'app/features/query/components/QueryErrorAlert';
import { QueryGroupOptionsEditor } from 'app/features/query/components/QueryGroupOptions';
@@ -334,45 +334,58 @@ export function QueryDetailView({ panel, query, queryIndex }: QueryDetailViewPro
return (
<div className={styles.container}>
<div className={cx(styles.contentWrapper, showOptions && styles.contentWrapperTwoColumn)}>
<div className={styles.mainContent}>
<QueryOperationRow
id={`query-${query.refId}`}
index={queryIndex}
draggable={false}
collapsable={false}
isOpen={true}
hideHeader={true}
className={styles.queryOperationRow}
>
<div className={styles.queryContent}>
{error && <QueryErrorAlert error={error} />}
{renderQueryEditor()}
</div>
</QueryOperationRow>
<div className={styles.footer}>
{renderCollapsedText()}
<div className={cx(styles.content, showOptions && styles.contentOptionsVisible)}>
<QueryOperationRow
id={`query-${query.refId}`}
index={queryIndex}
draggable={false}
collapsable={false}
isOpen={true}
hideHeader={true}
className={styles.queryOperationRow}
>
<div className={styles.queryContent}>
{error && <QueryErrorAlert error={error} />}
{renderQueryEditor()}
</div>
</QueryOperationRow>
<div className={styles.optionsColumn}>
<Stack gap={1} direction="column">
<Button
size="sm"
icon={showOptions ? 'angle-right' : 'angle-left'}
size="md"
icon="angle-right"
fill="text"
variant="secondary"
onClick={() => setShowOptions(!showOptions)}
className={styles.optionsButton}
>
<Trans i18nKey="dashboard-scene.query-detail-view.options">Options</Trans>
<Trans i18nKey="dashboard-scene.query-detail-view.query-options">Query Options</Trans>
</Button>
</div>
{datasource && panelData && (
<QueryGroupOptionsEditor
options={queryOptions}
dataSource={datasource}
data={panelData}
onChange={handleQueryOptionsChange}
/>
)}
</Stack>
</div>
{showOptions && datasource && panelData && (
<div className={styles.optionsColumn}>
<QueryGroupOptionsEditor
options={queryOptions}
dataSource={datasource}
data={panelData}
onChange={handleQueryOptionsChange}
/>
</div>
)}
</div>
{datasource && panelData && !showOptions && (
<div className={styles.optionsFooter}>
{renderCollapsedText()}
<Button
size="sm"
icon="angle-left"
fill="text"
onClick={() => setShowOptions(!showOptions)}
className={styles.optionsButton}
>
<Trans i18nKey="dashboard-scene.query-detail-view.options">Options</Trans>
</Button>
</div>
)}
</div>
);
}
@@ -382,36 +395,34 @@ const getStyles = (theme: GrafanaTheme2) => {
container: css({
width: '100%',
height: '100%',
}),
contentWrapper: css({
display: 'grid',
gridTemplateColumns: '1fr',
width: '100%',
height: '100%',
}),
contentWrapperTwoColumn: css({
gridTemplateColumns: '1fr 0.5fr',
}),
mainContent: css({
display: 'flex',
flexDirection: 'column',
position: 'relative',
overflow: 'scroll',
overflow: 'hidden',
}),
content: css({
display: 'flex',
flexDirection: 'row',
height: '100%',
width: 'calc(100% + 300px)',
[theme.transitions.handleMotion('no-preference', 'reduce')]: {
transition: theme.transitions.create(['width'], {
duration: theme.transitions.duration.short,
}),
},
}),
contentOptionsVisible: css({
width: '100%',
}),
queryContent: css({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(1),
padding: theme.spacing(2),
height: '100%',
overflow: 'scroll',
}),
queryOperationRow: css({
marginBottom: '0 !important', // need to beat specificty in the underling component
minHeight: 'calc(100% - 32px)', // 32px for the footer
overflow: 'scroll',
maxHeight: 'calc(100% - 32px)', // 32px for the footer
width: 'calc(100% - 300px)',
overflowY: 'auto',
}),
footer: css({
optionsFooter: css({
height: '32px',
display: 'flex',
justifyContent: 'flex-end',
@@ -424,12 +435,18 @@ const getStyles = (theme: GrafanaTheme2) => {
background: theme.colors.background.secondary,
}),
optionsColumn: css({
width: '300px',
display: 'flex',
flexDirection: 'column',
borderLeft: `1px solid ${theme.colors.border.weak}`,
background: theme.colors.background.secondary,
padding: theme.spacing(2),
}),
optionsButton: css({
paddingLeft: 0,
fontFamily: theme.typography.fontFamilyMonospace,
textTransform: 'uppercase',
}),
noEditor: css({
padding: theme.spacing(2),
textAlign: 'center',
@@ -224,7 +224,7 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
flexShrink: 0,
}),
typeLabel: css({
fontFamily: "'CommitMono', monospace",
fontFamily: theme.typography.fontFamilyMonospace,
fontSize: theme.typography.bodySmall.fontSize,
color: 'inherit',
textTransform: 'uppercase',
@@ -243,7 +243,7 @@ const getStyles = (theme: GrafanaTheme2, colors: ReturnType<typeof usePanelDataP
flexShrink: 0,
}),
name: css({
fontFamily: "'CommitMono', monospace",
fontFamily: theme.typography.fontFamilyMonospace,
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.text.maxContrast,
overflow: 'hidden',
@@ -231,7 +231,6 @@ QueryTransformList.displayName = 'QueryTransformList';
const getStyles = (theme: GrafanaTheme2) => {
const headerHeight = 41;
const footerHeight = 32;
const monoFont = "'CommitMono', monospace";
const barBase = {
padding: theme.spacing(0.5, 2),
background: theme.colors.background.secondary,
@@ -257,12 +256,12 @@ const getStyles = (theme: GrafanaTheme2) => {
borderBottom: `1px solid ${theme.colors.border.weak}`,
}),
headerTitle: css({
fontFamily: monoFont,
fontFamily: theme.typography.fontFamilyMonospace,
textTransform: 'uppercase',
color: theme.colors.text.primary,
}),
sectionLabel: css({
fontFamily: "'CommitMono', monospace",
fontFamily: theme.typography.fontFamilyMonospace
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.text.maxContrast,
textTransform: 'uppercase',
@@ -295,7 +294,7 @@ const getStyles = (theme: GrafanaTheme2) => {
zIndex: 20,
}),
footerStat: css({
fontFamily: monoFont,
fontFamily: theme.typography.fontFamilyMonospace,
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.text.primary,
textTransform: 'uppercase',
@@ -194,7 +194,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
const renderMaxDataPointsOption = () => {
const realMd = data.request?.maxDataPoints;
const value = options.maxDataPoints ?? '';
const isAuto = value === '';
// const isAuto = value === '';
return (
<>
@@ -220,7 +220,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
onBlur={onMaxDataPointsBlur}
defaultValue={value}
/>
{isAuto && (
{/* {isAuto && (
<>
<span className={cx(styles.noSquish, styles.operator)}>=</span>
<span className={cx(styles.noSquish, styles.left)}>
@@ -229,7 +229,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
</Trans>
</span>
</>
)}
)} */}
</>
);
};
@@ -274,12 +274,12 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
<Trans i18nKey="query.query-group-options-editor.render-interval-option.interval">Interval</Trans>
</InlineLabel>
<span className={styles.noSquish}>{realInterval}</span>
<span className={cx(styles.noSquish, styles.operator)}>=</span>
{/* <span className={cx(styles.noSquish, styles.operator)}>=</span>
<span className={cx(styles.noSquish, styles.left)}>
<Trans i18nKey="query.query-group-options-editor.render-interval-option.time-range-max-data-points">
Time range / max data points
</Trans>
</span>
</span> */}
</>
);
};
@@ -374,10 +374,11 @@ function getStyles(theme: GrafanaTheme2) {
return {
grid: css({
display: 'grid',
gridTemplateColumns: `auto minmax(5em, 1fr) auto 1fr`,
gridTemplateColumns: `auto 8em`,
gap: theme.spacing(0.5),
gridAutoRows: theme.spacing(4),
whiteSpace: 'nowrap',
minWidth: '100%',
}),
firstColumn: css({
gridColumn: 1,