chore: alex - header + footer + splitter padding + various styles updates
This commit is contained in:
@@ -90,6 +90,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
background: theme.colors.background.primary,
|
||||
border: `1px solid ${theme.colors.border.weak}`,
|
||||
}),
|
||||
emptyState: css({
|
||||
display: 'flex',
|
||||
|
||||
@@ -265,7 +265,7 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
|
||||
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
<Stack justifyContent="space-between" alignItems="center" gap={2}>
|
||||
<div className={styles.headerContent}>
|
||||
{/* Left side: Icon, Datasource, Name */}
|
||||
<Stack gap={1} alignItems="center" grow={1} minWidth={0}>
|
||||
<Icon name={config.icon} className={styles.icon} />
|
||||
@@ -358,7 +358,7 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
|
||||
</Dropdown>
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -366,10 +366,18 @@ export const DetailViewHeader = ({ selectedItem, panel }: DetailViewHeaderProps)
|
||||
const getStyles = (theme: GrafanaTheme2, config: { color: string }) => {
|
||||
return {
|
||||
header: css({
|
||||
padding: theme.spacing(1.5, 2),
|
||||
padding: theme.spacing(0.5),
|
||||
borderLeft: `4px solid ${config.color}`,
|
||||
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
||||
background: theme.colors.background.secondary,
|
||||
minHeight: '41px',
|
||||
}),
|
||||
headerContent: css({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(2),
|
||||
height: '100%',
|
||||
}),
|
||||
icon: css({
|
||||
color: theme.colors.text.secondary,
|
||||
|
||||
@@ -473,7 +473,7 @@ function PanelDataPaneRendered({ model }: SceneComponentProps<PanelDataPane>) {
|
||||
<div
|
||||
{...splitterProps}
|
||||
className={cx(splitterProps.className, styles.splitter)}
|
||||
style={{ ...splitterProps.style, width: 0 }}
|
||||
style={{ ...splitterProps.style, width: '16px' }}
|
||||
/>
|
||||
<div {...secondaryProps}>
|
||||
<DetailView selectedItem={selectedItem} panel={panel} tabs={tabs} />
|
||||
@@ -517,24 +517,12 @@ function getStyles(theme: GrafanaTheme2) {
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
background: theme.colors.background.primary,
|
||||
border: `1px solid ${theme.colors.border.weak}`,
|
||||
borderLeft: 'none',
|
||||
borderBottom: 'none',
|
||||
borderTopRightRadius: theme.shape.radius.default,
|
||||
overflow: 'hidden',
|
||||
}),
|
||||
splitter: css({
|
||||
position: 'relative',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
left: '50%',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: '1px',
|
||||
background: theme.colors.border.weak,
|
||||
transform: 'translateX(-50%)',
|
||||
},
|
||||
background: theme.colors.background.canvas,
|
||||
cursor: 'col-resize',
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ export function QueryDetailView({ panel, query, queryIndex }: QueryDetailViewPro
|
||||
<div className={styles.footer}>
|
||||
{renderCollapsedText()}
|
||||
<Button
|
||||
size="xs"
|
||||
size="sm"
|
||||
icon={showOptions ? 'angle-right' : 'angle-left'}
|
||||
fill="text"
|
||||
onClick={() => setShowOptions(!showOptions)}
|
||||
@@ -408,10 +408,11 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
}),
|
||||
queryOperationRow: css({
|
||||
marginBottom: '0 !important', // need to beat specificty in the underling component
|
||||
minHeight: 'calc(100% - 49px)', // 49px for the footer
|
||||
minHeight: 'calc(100% - 32px)', // 32px for the footer
|
||||
overflow: 'scroll',
|
||||
}),
|
||||
footer: css({
|
||||
height: '32px',
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
@@ -419,7 +420,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
position: 'sticky',
|
||||
bottom: 0,
|
||||
zIndex: theme.zIndex.navbarFixed,
|
||||
padding: theme.spacing(1, 2),
|
||||
padding: theme.spacing(0.5, 2),
|
||||
background: theme.colors.background.secondary,
|
||||
}),
|
||||
optionsColumn: css({
|
||||
|
||||
+107
-26
@@ -2,8 +2,9 @@ import { css } from '@emotion/css';
|
||||
import { memo, useMemo } from 'react';
|
||||
|
||||
import { DataTransformerConfig, GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { SceneDataQuery } from '@grafana/scenes';
|
||||
import { ScrollContainer, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { Icon, ScrollContainer, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { ExpressionQueryType } from 'app/features/expressions/types';
|
||||
|
||||
import { AddDataItemMenu } from './AddDataItemMenu';
|
||||
@@ -122,32 +123,69 @@ export const QueryTransformList = memo(
|
||||
}
|
||||
};
|
||||
|
||||
const stats = useMemo(() => {
|
||||
const totalCards = items.length;
|
||||
const queries = items.filter((item) => item.type === 'query' || item.type === 'expression');
|
||||
const hiddenQueries = queries.filter((item) => 'hide' in item.data && item.data.hide);
|
||||
const visibleQueries = queries.length - hiddenQueries.length;
|
||||
|
||||
return {
|
||||
totalCards,
|
||||
visibleQueries,
|
||||
hiddenQueries: hiddenQueries.length,
|
||||
};
|
||||
}, [items]);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<Stack justifyContent="space-between" alignItems="center" gap={2}>
|
||||
<span className={styles.headerTitle}>
|
||||
{t('dashboard-scene.query-transform-list.header', 'Pipeline flow')}
|
||||
</span>
|
||||
</Stack>
|
||||
</div>
|
||||
<ConnectionLines connections={visibleConnections} />
|
||||
<ScrollContainer data-scrollcontainer>
|
||||
<div className={styles.content}>
|
||||
<Stack direction="column" gap={2}>
|
||||
{items.map((item) => (
|
||||
<QueryTransformCard
|
||||
key={item.id}
|
||||
item={item.data}
|
||||
type={item.type}
|
||||
index={item.index}
|
||||
isSelected={selectedId === item.id}
|
||||
onClick={() => onSelect(item.id)}
|
||||
{...getHandlers(item)}
|
||||
/>
|
||||
))}
|
||||
<div className={styles.scrollWrapper}>
|
||||
<ScrollContainer data-scrollcontainer>
|
||||
<div className={styles.content}>
|
||||
<Stack direction="column" gap={2}>
|
||||
{items.map((item) => (
|
||||
<QueryTransformCard
|
||||
key={item.id}
|
||||
item={item.data}
|
||||
type={item.type}
|
||||
index={item.index}
|
||||
isSelected={selectedId === item.id}
|
||||
onClick={() => onSelect(item.id)}
|
||||
{...getHandlers(item)}
|
||||
/>
|
||||
))}
|
||||
|
||||
<AddDataItemMenu
|
||||
onAddQuery={onAddQuery}
|
||||
onAddTransform={onAddTransform}
|
||||
onAddExpression={onAddExpression}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
<AddDataItemMenu
|
||||
onAddQuery={onAddQuery}
|
||||
onAddTransform={onAddTransform}
|
||||
onAddExpression={onAddExpression}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<Stack direction="row" gap={1.5}>
|
||||
<span className={styles.footerStat}>
|
||||
{stats.totalCards} {t('dashboard-scene.query-transform-list.nodes-total', 'nodes total')}
|
||||
</span>
|
||||
<span className={styles.footerStat}>
|
||||
<Icon size="xs" name="eye" />
|
||||
{t('dashboard-scene.query-transform-list.visible-queries', 'Visible')}: {stats.visibleQueries}
|
||||
</span>
|
||||
<span className={styles.footerStat}>
|
||||
<Icon size="xs" name="eye-slash" />
|
||||
{t('dashboard-scene.query-transform-list.hidden-queries', 'Hidden')}: {stats.hiddenQueries}
|
||||
</span>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -156,6 +194,17 @@ export const QueryTransformList = memo(
|
||||
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,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexShrink: 0,
|
||||
};
|
||||
|
||||
return {
|
||||
container: css({
|
||||
position: 'relative',
|
||||
@@ -164,12 +213,44 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
overflow: 'hidden',
|
||||
border: `1px solid ${theme.colors.border.weak}`,
|
||||
}),
|
||||
header: css({
|
||||
...barBase,
|
||||
height: headerHeight,
|
||||
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
||||
}),
|
||||
headerTitle: css({
|
||||
fontFamily: monoFont,
|
||||
textTransform: 'uppercase',
|
||||
color: theme.colors.text.primary,
|
||||
}),
|
||||
scrollWrapper: css({
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
position: 'relative',
|
||||
}),
|
||||
content: css({
|
||||
position: 'relative',
|
||||
padding: theme.spacing(2),
|
||||
paddingRight: theme.spacing(6), // Extra space for the connection line
|
||||
zIndex: 1,
|
||||
paddingRight: theme.spacing(6),
|
||||
}),
|
||||
footer: css({
|
||||
...barBase,
|
||||
height: footerHeight,
|
||||
borderTop: `1px solid ${theme.colors.border.weak}`,
|
||||
gap: theme.spacing(1),
|
||||
position: 'relative',
|
||||
zIndex: 20,
|
||||
}),
|
||||
footerStat: css({
|
||||
fontFamily: monoFont,
|
||||
fontSize: '10px',
|
||||
color: theme.colors.text.primary,
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.05em',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(0.5),
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5976,6 +5976,15 @@
|
||||
"description-label": {
|
||||
"description": "Description"
|
||||
},
|
||||
"detail-view-header": {
|
||||
"actions": "Actions",
|
||||
"duplicate-query": "Duplicate",
|
||||
"edit-query-name": "Edit query name",
|
||||
"hide-response": "Hide response",
|
||||
"remove-query": "Remove",
|
||||
"run-query": "RUN QUERY",
|
||||
"show-response": "Show response"
|
||||
},
|
||||
"edit-link-view": {
|
||||
"edit-link-page-nav": {
|
||||
"text": {
|
||||
@@ -6253,7 +6262,7 @@
|
||||
"query-detail-view": {
|
||||
"loading": "Loading data source...",
|
||||
"no-editor": "This data source does not have a query editor",
|
||||
"select-datasource": "Select data source"
|
||||
"options": "Options"
|
||||
},
|
||||
"query-editor": {
|
||||
"query": "Query"
|
||||
@@ -6265,6 +6274,12 @@
|
||||
"remove-transform": "Remove transformation",
|
||||
"show-response": "Show response"
|
||||
},
|
||||
"query-transform-list": {
|
||||
"header": "Pipeline flow",
|
||||
"hidden-queries": "Hidden",
|
||||
"nodes-total": "nodes total",
|
||||
"visible-queries": "Visible"
|
||||
},
|
||||
"query-variable-editor-form": {
|
||||
"description-examples": "Named capture groups can be used to separate the display text and value (<1>see examples</1> ).",
|
||||
"description-optional": "Optional, if you want to extract part of a series name or metric node segment.",
|
||||
@@ -12320,10 +12335,14 @@
|
||||
"title-data-source-help": "Data source help"
|
||||
},
|
||||
"query-group-options-editor": {
|
||||
"collapsed-interval": "Interval = {{intervalDesc}}",
|
||||
"collapsed-max-data-points": "MD = {{mdDesc}}",
|
||||
"collapsed-cache-timeout-label": "Cache timeout",
|
||||
"collapsed-cache-ttl-label": "Cache TTL",
|
||||
"collapsed-interval-label": "Interval",
|
||||
"collapsed-max-data-points-label": "Max data points",
|
||||
"collapsed-min-interval-label": "Min interval",
|
||||
"collapsed-relative-time-label": "Relative time",
|
||||
"collapsed-time-shift-label": "Time shift",
|
||||
"hide-time-info": "Hide time info",
|
||||
"Query options-title-query-options": "Query options",
|
||||
"relative-time": "Relative time",
|
||||
"relative-time-tooltip": "Overrides the relative time range for individual panels, which causes them to be different than what is selected in the dashboard time picker in the top-right corner of the dashboard. For example to configure the Last 5 minutes the Relative time should be <1>{{relativeFrom}}</1> and <4>{{relativeTo}}</4>, or variables like <6>{{variable}}</6>.",
|
||||
"render-cache-timeout-option": {
|
||||
|
||||
Reference in New Issue
Block a user