mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -110,9 +110,11 @@ export function facetLabels(
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
wrapper: css`
|
||||
background-color: ${theme.colors.background.secondary};
|
||||
padding: ${theme.spacing(2)};
|
||||
width: 100%;
|
||||
`,
|
||||
wrapperPadding: css`
|
||||
padding: ${theme.spacing(2)};
|
||||
`,
|
||||
list: css`
|
||||
margin-top: ${theme.spacing(1)};
|
||||
display: flex;
|
||||
@@ -124,11 +126,20 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
& + & {
|
||||
margin: ${theme.spacing(2, 0)};
|
||||
}
|
||||
|
||||
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`
|
||||
font-family: ${theme.typography.fontFamilyMonospace};
|
||||
margin-bottom: ${theme.spacing(1)};
|
||||
width: 100%;
|
||||
`,
|
||||
status: css`
|
||||
margin-bottom: ${theme.spacing(1)};
|
||||
@@ -138,6 +149,8 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
text-overflow: ellipsis;
|
||||
transition: opacity 100ms linear;
|
||||
opacity: 0;
|
||||
font-size: ${theme.typography.bodySmall.fontSize};
|
||||
height: calc(${theme.typography.bodySmall.fontSize} + 10px);
|
||||
`,
|
||||
statusShowing: css`
|
||||
opacity: 1;
|
||||
@@ -434,87 +447,89 @@ export class UnthemedLokiLabelBrowser extends React.Component<BrowserProps, Brow
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.section}>
|
||||
<Label description="Which labels would you like to consider for your search?">
|
||||
1. Select labels to search in
|
||||
</Label>
|
||||
<div className={styles.list}>
|
||||
{labels.map((label) => (
|
||||
<LokiLabel
|
||||
key={label.name}
|
||||
name={label.name}
|
||||
loading={label.loading}
|
||||
active={label.selected}
|
||||
hidden={label.hidden}
|
||||
facets={label.facets}
|
||||
onClick={this.onClickLabel}
|
||||
<>
|
||||
<div className={styles.wrapper}>
|
||||
<div className={cx(styles.section, styles.wrapperPadding)}>
|
||||
<Label description="Which labels would you like to consider for your search?">
|
||||
1. Select labels to search in
|
||||
</Label>
|
||||
<div className={styles.list}>
|
||||
{labels.map((label) => (
|
||||
<LokiLabel
|
||||
key={label.name}
|
||||
name={label.name}
|
||||
loading={label.loading}
|
||||
active={label.selected}
|
||||
hidden={label.hidden}
|
||||
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.section}>
|
||||
<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 className={styles.valueListArea}>
|
||||
{selectedLabels.map((label) => (
|
||||
<div role="list" key={label.name} className={styles.valueListWrapper}>
|
||||
<div className={styles.valueTitle} aria-label={`Values for ${label.name}`}>
|
||||
<LokiLabel
|
||||
name={label.name}
|
||||
loading={label.loading}
|
||||
active={label.selected}
|
||||
hidden={label.hidden}
|
||||
//If no facets, we want to show number of all label values
|
||||
facets={label.facets || label.values?.length}
|
||||
onClick={this.onClickLabel}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.valueListArea}>
|
||||
{selectedLabels.map((label) => (
|
||||
<div role="list" key={label.name} className={styles.valueListWrapper}>
|
||||
<div className={styles.valueTitle} aria-label={`Values for ${label.name}`}>
|
||||
<LokiLabel
|
||||
name={label.name}
|
||||
loading={label.loading}
|
||||
active={label.selected}
|
||||
hidden={label.hidden}
|
||||
//If no facets, we want to show number of all label values
|
||||
facets={label.facets || label.values?.length}
|
||||
onClick={this.onClickLabel}
|
||||
/>
|
||||
</div>
|
||||
<FixedSizeList
|
||||
height={200}
|
||||
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>
|
||||
<FixedSizeList
|
||||
height={200}
|
||||
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 className={styles.section}>
|
||||
<div className={styles.footerSectionStyles}>
|
||||
<Label>3. Resulting selector</Label>
|
||||
<div aria-label="selector" className={styles.selector}>
|
||||
<pre aria-label="selector" className={styles.selector}>
|
||||
{selector}
|
||||
</div>
|
||||
</pre>
|
||||
{validationStatus && <div className={styles.validationStatus}>{validationStatus}</div>}
|
||||
<div className={cx(styles.status, (status || error) && styles.statusShowing)}>
|
||||
<span className={error ? styles.error : ''}>{error || status}</span>
|
||||
@@ -544,7 +559,7 @@ export class UnthemedLokiLabelBrowser extends React.Component<BrowserProps, Brow
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user