Loki: Label browser sticky footer (#73243)

* Create sticky footer section in loki metrics browser for query preview and action buttons
This commit is contained in:
Galen Kistler
2023-08-17 11:01:30 -05:00
committed by GitHub
parent 48c3dc7203
commit f33f3a55a0

View File

@@ -110,9 +110,11 @@ export function facetLabels(
const getStyles = (theme: GrafanaTheme2) => ({ const getStyles = (theme: GrafanaTheme2) => ({
wrapper: css` wrapper: css`
background-color: ${theme.colors.background.secondary}; background-color: ${theme.colors.background.secondary};
padding: ${theme.spacing(2)};
width: 100%; width: 100%;
`, `,
wrapperPadding: css`
padding: ${theme.spacing(2)};
`,
list: css` list: css`
margin-top: ${theme.spacing(1)}; margin-top: ${theme.spacing(1)};
display: flex; display: flex;
@@ -124,11 +126,20 @@ const getStyles = (theme: GrafanaTheme2) => ({
& + & { & + & {
margin: ${theme.spacing(2, 0)}; margin: ${theme.spacing(2, 0)};
} }
position: relative; position: relative;
`, `,
footerSectionStyles: css`
padding: ${theme.spacing(1)};
background-color: ${theme.colors.background.primary};
position: sticky;
bottom: -${theme.spacing(3)}; /* offset the padding on modal */
left: 0;
`,
selector: css` selector: css`
font-family: ${theme.typography.fontFamilyMonospace}; font-family: ${theme.typography.fontFamilyMonospace};
margin-bottom: ${theme.spacing(1)}; margin-bottom: ${theme.spacing(1)};
width: 100%;
`, `,
status: css` status: css`
margin-bottom: ${theme.spacing(1)}; margin-bottom: ${theme.spacing(1)};
@@ -138,6 +149,8 @@ const getStyles = (theme: GrafanaTheme2) => ({
text-overflow: ellipsis; text-overflow: ellipsis;
transition: opacity 100ms linear; transition: opacity 100ms linear;
opacity: 0; opacity: 0;
font-size: ${theme.typography.bodySmall.fontSize};
height: calc(${theme.typography.bodySmall.fontSize} + 10px);
`, `,
statusShowing: css` statusShowing: css`
opacity: 1; opacity: 1;
@@ -434,87 +447,89 @@ export class UnthemedLokiLabelBrowser extends React.Component<BrowserProps, Brow
} }
return ( return (
<div className={styles.wrapper}> <>
<div className={styles.section}> <div className={styles.wrapper}>
<Label description="Which labels would you like to consider for your search?"> <div className={cx(styles.section, styles.wrapperPadding)}>
1. Select labels to search in <Label description="Which labels would you like to consider for your search?">
</Label> 1. Select labels to search in
<div className={styles.list}> </Label>
{labels.map((label) => ( <div className={styles.list}>
<LokiLabel {labels.map((label) => (
key={label.name} <LokiLabel
name={label.name} key={label.name}
loading={label.loading} name={label.name}
active={label.selected} loading={label.loading}
hidden={label.hidden} active={label.selected}
facets={label.facets} hidden={label.hidden}
onClick={this.onClickLabel} facets={label.facets}
onClick={this.onClickLabel}
/>
))}
</div>
</div>
<div className={cx(styles.section, styles.wrapperPadding)}>
<Label description="Choose the label values that you would like to use for the query. Use the search field to find values across selected labels.">
2. Find values for the selected labels
</Label>
<div>
<Input
onChange={this.onChangeSearch}
aria-label="Filter expression for values"
value={searchTerm}
placeholder={'Enter a label value'}
/> />
))} </div>
</div> <div className={styles.valueListArea}>
</div> {selectedLabels.map((label) => (
<div className={styles.section}> <div role="list" key={label.name} className={styles.valueListWrapper}>
<Label description="Choose the label values that you would like to use for the query. Use the search field to find values across selected labels."> <div className={styles.valueTitle} aria-label={`Values for ${label.name}`}>
2. Find values for the selected labels <LokiLabel
</Label> name={label.name}
<div> loading={label.loading}
<Input active={label.selected}
onChange={this.onChangeSearch} hidden={label.hidden}
aria-label="Filter expression for values" //If no facets, we want to show number of all label values
value={searchTerm} facets={label.facets || label.values?.length}
placeholder={'Enter a label value'} onClick={this.onClickLabel}
/> />
</div> </div>
<div className={styles.valueListArea}> <FixedSizeList
{selectedLabels.map((label) => ( height={200}
<div role="list" key={label.name} className={styles.valueListWrapper}> itemCount={label.values?.length || 0}
<div className={styles.valueTitle} aria-label={`Values for ${label.name}`}> itemSize={28}
<LokiLabel itemKey={(i) => (label.values as FacettableValue[])[i].name}
name={label.name} width={200}
loading={label.loading} className={styles.valueList}
active={label.selected} >
hidden={label.hidden} {({ index, style }) => {
//If no facets, we want to show number of all label values const value = label.values?.[index];
facets={label.facets || label.values?.length} if (!value) {
onClick={this.onClickLabel} return null;
/> }
return (
<div style={style}>
<LokiLabel
name={label.name}
value={value?.name}
active={value?.selected}
highlightParts={value?.highlightParts}
onClick={this.onClickValue}
searchTerm={searchTerm}
/>
</div>
);
}}
</FixedSizeList>
</div> </div>
<FixedSizeList ))}
height={200} </div>
itemCount={label.values?.length || 0}
itemSize={28}
itemKey={(i) => (label.values as FacettableValue[])[i].name}
width={200}
className={styles.valueList}
>
{({ index, style }) => {
const value = label.values?.[index];
if (!value) {
return null;
}
return (
<div style={style}>
<LokiLabel
name={label.name}
value={value?.name}
active={value?.selected}
highlightParts={value?.highlightParts}
onClick={this.onClickValue}
searchTerm={searchTerm}
/>
</div>
);
}}
</FixedSizeList>
</div>
))}
</div> </div>
</div> </div>
<div className={styles.section}> <div className={styles.footerSectionStyles}>
<Label>3. Resulting selector</Label> <Label>3. Resulting selector</Label>
<div aria-label="selector" className={styles.selector}> <pre aria-label="selector" className={styles.selector}>
{selector} {selector}
</div> </pre>
{validationStatus && <div className={styles.validationStatus}>{validationStatus}</div>} {validationStatus && <div className={styles.validationStatus}>{validationStatus}</div>}
<div className={cx(styles.status, (status || error) && styles.statusShowing)}> <div className={cx(styles.status, (status || error) && styles.statusShowing)}>
<span className={error ? styles.error : ''}>{error || status}</span> <span className={error ? styles.error : ''}>{error || status}</span>
@@ -544,7 +559,7 @@ export class UnthemedLokiLabelBrowser extends React.Component<BrowserProps, Brow
</Button> </Button>
</HorizontalGroup> </HorizontalGroup>
</div> </div>
</div> </>
); );
} }
} }