mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Fix: Show an ellipsis if Query row title is too long (#27648)
* add overflow hidden to titleWrapper * show ellipsis and css labels for components * readd drag handle after bad merge * rewrite userpicker test with rtl * update test after adding css label to icon component * fix more tests..
This commit is contained in:
parent
1e5309a788
commit
6a14f830ba
@ -19,6 +19,7 @@ export interface IconProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
const getIconStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
container: css`
|
||||
label: Icon;
|
||||
display: inline-block;
|
||||
`,
|
||||
icon: css`
|
||||
|
@ -119,6 +119,7 @@ const getStyles = stylesFactory(
|
||||
|
||||
return {
|
||||
layout: css`
|
||||
label: HorizontalGroup;
|
||||
display: flex;
|
||||
flex-direction: ${orientation === Orientation.Vertical ? 'column' : 'row'};
|
||||
flex-wrap: ${wrap ? 'wrap' : 'nowrap'};
|
||||
|
@ -68,10 +68,10 @@ export const QueryOperationRow: React.FC<QueryOperationRowProps> = ({
|
||||
<div className={styles.header}>
|
||||
<div className={styles.titleWrapper} onClick={onRowToggle} aria-label="Query operation row title">
|
||||
<Icon name={isContentVisible ? 'angle-down' : 'angle-right'} className={styles.collapseIcon} />
|
||||
{title && <span className={styles.title}>{titleElement}</span>}
|
||||
{title && <div className={styles.title}>{titleElement}</div>}
|
||||
{headerElement}
|
||||
</div>
|
||||
{actions && actionsElement}
|
||||
{actions && <div>{actionsElement}</div>}
|
||||
{draggable && (
|
||||
<Icon title="Drag and drop to reorder" name="draggabledots" size="lg" className={styles.dragIcon} />
|
||||
)}
|
||||
@ -113,7 +113,6 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
border-radius: ${theme.border.radius.sm};
|
||||
background: ${theme.colors.bg2};
|
||||
min-height: ${theme.spacing.formInputHeight}px;
|
||||
line-height: ${theme.spacing.sm}px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -143,6 +142,7 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
font-weight: ${theme.typography.weight.semibold};
|
||||
color: ${theme.colors.textBlue};
|
||||
margin-left: ${theme.spacing.sm};
|
||||
overflow: hidden;
|
||||
`,
|
||||
content: css`
|
||||
margin-top: ${theme.spacing.inlineFormMargin};
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import renderer from 'react-test-renderer';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { TeamPicker } from './TeamPicker';
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
@ -18,7 +17,7 @@ describe('TeamPicker', () => {
|
||||
const props = {
|
||||
onSelected: () => {},
|
||||
};
|
||||
const tree = renderer.create(<TeamPicker {...props} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<TeamPicker {...props} />);
|
||||
expect(screen.getByTestId('teamPicker')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ export class TeamPicker extends Component<Props, State> {
|
||||
const { onSelected, className } = this.props;
|
||||
const { isLoading } = this.state;
|
||||
return (
|
||||
<div className="user-picker">
|
||||
<div className="user-picker" data-testid="teamPicker">
|
||||
<AsyncSelect
|
||||
isLoading={isLoading}
|
||||
defaultOptions={true}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import renderer from 'react-test-renderer';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { UserPicker } from './UserPicker';
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
@ -9,7 +8,7 @@ jest.mock('@grafana/runtime', () => ({
|
||||
|
||||
describe('UserPicker', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer.create(<UserPicker onSelected={() => {}} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<UserPicker onSelected={() => {}} />);
|
||||
expect(screen.getByTestId('userPicker')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ export class UserPicker extends Component<Props, State> {
|
||||
const { isLoading } = this.state;
|
||||
|
||||
return (
|
||||
<div className="user-picker">
|
||||
<div className="user-picker" data-testid="userPicker">
|
||||
<AsyncSelect
|
||||
className={className}
|
||||
isLoading={isLoading}
|
||||
|
@ -1,112 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TeamPicker renders correctly 1`] = `
|
||||
<div
|
||||
className="user-picker"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className="gf-form-input gf-form-input--form-dropdown css-at6rp9-SelectContainer"
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__control css-ia584n-Control"
|
||||
onMouseDown={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__value-container css-1q9zhbr-ValueContainer"
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__placeholder css-d8h0m4-Placeholder"
|
||||
>
|
||||
Select a team
|
||||
</div>
|
||||
<div
|
||||
className="css-zz0hea-Input"
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__input"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
autoCapitalize="none"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
disabled={false}
|
||||
id="react-select-2-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
spellCheck="false"
|
||||
style={
|
||||
Object {
|
||||
"background": 0,
|
||||
"border": 0,
|
||||
"boxSizing": "content-box",
|
||||
"color": "inherit",
|
||||
"fontSize": "inherit",
|
||||
"label": "input",
|
||||
"opacity": 1,
|
||||
"outline": 0,
|
||||
"padding": 0,
|
||||
"width": "1px",
|
||||
}
|
||||
}
|
||||
tabIndex="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"height": 0,
|
||||
"left": 0,
|
||||
"overflow": "scroll",
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"visibility": "hidden",
|
||||
"whiteSpace": "pre",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="gf-form-select-box__indicators css-q46mcr-IndicatorsContainer"
|
||||
>
|
||||
<div
|
||||
className="css-1cvxpvr"
|
||||
>
|
||||
<svg
|
||||
className="css-sr6nr"
|
||||
fill="currentColor"
|
||||
height={16}
|
||||
style={
|
||||
Object {
|
||||
"marginTop": "7px",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 24 24"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17,9.17a1,1,0,0,0-1.41,0L12,12.71,8.46,9.17a1,1,0,0,0-1.41,0,1,1,0,0,0,0,1.42l4.24,4.24a1,1,0,0,0,1.42,0L17,10.59A1,1,0,0,0,17,9.17Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,112 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`UserPicker renders correctly 1`] = `
|
||||
<div
|
||||
className="user-picker"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className="gf-form-input gf-form-input--form-dropdown css-at6rp9-SelectContainer"
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__control css-ia584n-Control"
|
||||
onMouseDown={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__value-container css-1q9zhbr-ValueContainer"
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__placeholder css-d8h0m4-Placeholder"
|
||||
>
|
||||
Select user
|
||||
</div>
|
||||
<div
|
||||
className="css-zz0hea-Input"
|
||||
>
|
||||
<div
|
||||
className="gf-form-select-box__input"
|
||||
style={
|
||||
Object {
|
||||
"display": "inline-block",
|
||||
}
|
||||
}
|
||||
>
|
||||
<input
|
||||
aria-autocomplete="list"
|
||||
autoCapitalize="none"
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
disabled={false}
|
||||
id="react-select-2-input"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
spellCheck="false"
|
||||
style={
|
||||
Object {
|
||||
"background": 0,
|
||||
"border": 0,
|
||||
"boxSizing": "content-box",
|
||||
"color": "inherit",
|
||||
"fontSize": "inherit",
|
||||
"label": "input",
|
||||
"opacity": 1,
|
||||
"outline": 0,
|
||||
"padding": 0,
|
||||
"width": "1px",
|
||||
}
|
||||
}
|
||||
tabIndex="0"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"height": 0,
|
||||
"left": 0,
|
||||
"overflow": "scroll",
|
||||
"position": "absolute",
|
||||
"top": 0,
|
||||
"visibility": "hidden",
|
||||
"whiteSpace": "pre",
|
||||
}
|
||||
}
|
||||
>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="gf-form-select-box__indicators css-q46mcr-IndicatorsContainer"
|
||||
>
|
||||
<div
|
||||
className="css-1cvxpvr"
|
||||
>
|
||||
<svg
|
||||
className="css-sr6nr"
|
||||
fill="currentColor"
|
||||
height={16}
|
||||
style={
|
||||
Object {
|
||||
"marginTop": "7px",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 24 24"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17,9.17a1,1,0,0,0-1.41,0L12,12.71,8.46,9.17a1,1,0,0,0-1.41,0,1,1,0,0,0,0,1.42l4.24,4.24a1,1,0,0,0,1.42,0L17,10.59A1,1,0,0,0,17,9.17Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { DataQuery, DataSourceApi, GrafanaTheme } from '@grafana/data';
|
||||
import { HorizontalGroup, stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
interface QueryEditorRowTitleProps {
|
||||
@ -25,7 +25,7 @@ export const QueryEditorRowTitle: React.FC<QueryEditorRowTitleProps> = ({
|
||||
const styles = getQueryEditorRowTitleStyles(theme);
|
||||
|
||||
return (
|
||||
<HorizontalGroup align="center">
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.refId} aria-label={selectors.components.QueryEditorRow.title(query.refId)}>
|
||||
<span>{query.refId}</span>
|
||||
{inMixedMode && <em className={styles.contextInfo}> ({datasource.name})</em>}
|
||||
@ -36,12 +36,17 @@ export const QueryEditorRowTitle: React.FC<QueryEditorRowTitleProps> = ({
|
||||
{collapsedText}
|
||||
</div>
|
||||
)}
|
||||
</HorizontalGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const getQueryEditorRowTitleStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
wrapper: css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`,
|
||||
|
||||
refId: css`
|
||||
font-weight: ${theme.typography.weight.semibold};
|
||||
color: ${theme.colors.textBlue};
|
||||
@ -53,10 +58,8 @@ const getQueryEditorRowTitleStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
font-weight: ${theme.typography.weight.regular};
|
||||
font-size: ${theme.typography.size.sm};
|
||||
color: ${theme.colors.textWeak};
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
padding-left: ${theme.spacing.sm};
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
font-style: italic;
|
||||
overflow: hidden;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Segment } from '@grafana/ui';
|
||||
import { Aggregations, Props } from './Aggregations';
|
||||
@ -22,8 +22,8 @@ const props: Props = {
|
||||
|
||||
describe('Aggregations', () => {
|
||||
it('renders correctly', () => {
|
||||
const tree = renderer.create(<Aggregations {...props} />).toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<Aggregations {...props} />);
|
||||
expect(screen.getByTestId('aggregations')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('options', () => {
|
||||
|
@ -22,7 +22,7 @@ export const Aggregations: FC<Props> = props => {
|
||||
const selected = useSelectedFromOptions(aggOptions, props);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="aggregations">
|
||||
<div className="gf-form-inline">
|
||||
<label className="gf-form-label query-keyword width-9">Aggregation</label>
|
||||
<Segment
|
||||
@ -40,7 +40,7 @@ export const Aggregations: FC<Props> = props => {
|
||||
},
|
||||
]}
|
||||
placeholder="Select Reducer"
|
||||
></Segment>
|
||||
/>
|
||||
<div className="gf-form gf-form--grow">
|
||||
<label className="gf-form-label gf-form-label--grow">
|
||||
<a onClick={() => setDisplayAdvancedOptions(!displayAdvancedOptions)}>
|
||||
@ -52,7 +52,7 @@ export const Aggregations: FC<Props> = props => {
|
||||
</div>
|
||||
</div>
|
||||
{props.children(displayAdvancedOptions)}
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,55 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Aggregations renders correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="gf-form-inline"
|
||||
>
|
||||
<label
|
||||
className="gf-form-label query-keyword width-9"
|
||||
>
|
||||
Aggregation
|
||||
</label>
|
||||
<div
|
||||
className="gf-form"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<a
|
||||
className="gf-form-label query-part query-placeholder"
|
||||
>
|
||||
Select Reducer
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className="gf-form gf-form--grow"
|
||||
>
|
||||
<label
|
||||
className="gf-form-label gf-form-label--grow"
|
||||
>
|
||||
<a
|
||||
onClick={[Function]}
|
||||
>
|
||||
<div
|
||||
className="css-1cvxpvr"
|
||||
>
|
||||
<svg
|
||||
className="css-sr6nr"
|
||||
fill="currentColor"
|
||||
height={16}
|
||||
viewBox="0 0 24 24"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14.83,11.29,10.59,7.05a1,1,0,0,0-1.42,0,1,1,0,0,0,0,1.41L12.71,12,9.17,15.54a1,1,0,0,0,0,1.41,1,1,0,0,0,.71.29,1,1,0,0,0,.71-.29l4.24-4.24A1,1,0,0,0,14.83,11.29Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
Advanced Options
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>,
|
||||
<div />,
|
||||
]
|
||||
`;
|
@ -1,21 +1,19 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { Stats } from './Stats';
|
||||
|
||||
const toOption = (value: any) => ({ label: value, value });
|
||||
|
||||
describe('Stats', () => {
|
||||
it('should render component', () => {
|
||||
const tree = renderer
|
||||
.create(
|
||||
<Stats
|
||||
values={['Average', 'Minimum']}
|
||||
variableOptionGroup={{ label: 'templateVar', value: 'templateVar' }}
|
||||
onChange={() => {}}
|
||||
stats={['Average', 'Maximum', 'Minimum', 'Sum', 'SampleCount'].map(toOption)}
|
||||
/>
|
||||
)
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(
|
||||
<Stats
|
||||
values={['Average', 'Minimum']}
|
||||
variableOptionGroup={{ label: 'templateVar', value: 'templateVar' }}
|
||||
onChange={() => {}}
|
||||
stats={['Average', 'Maximum', 'Minimum', 'Sum', 'SampleCount'].map(toOption)}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByTestId('stats')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ const removeText = '-- remove stat --';
|
||||
const removeOption: SelectableValue<string> = { label: removeText, value: removeText };
|
||||
|
||||
export const Stats: FunctionComponent<Props> = ({ stats, values, onChange, variableOptionGroup }) => (
|
||||
<>
|
||||
<div data-testid="stats">
|
||||
{values &&
|
||||
values.map((value, index) => (
|
||||
<Segment
|
||||
@ -41,5 +41,5 @@ export const Stats: FunctionComponent<Props> = ({ stats, values, onChange, varia
|
||||
onChange={({ value }) => onChange([...values, value!])}
|
||||
options={[...stats.filter(({ value }) => !values.includes(value!)), variableOptionGroup]}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,51 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Stats should render component 1`] = `
|
||||
Array [
|
||||
<div
|
||||
className="gf-form"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<a
|
||||
className="gf-form-label query-part"
|
||||
>
|
||||
Average
|
||||
</a>
|
||||
</div>,
|
||||
<div
|
||||
className="gf-form"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<a
|
||||
className="gf-form-label query-part"
|
||||
>
|
||||
Minimum
|
||||
</a>
|
||||
</div>,
|
||||
<div
|
||||
className="gf-form"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<a
|
||||
className="gf-form-label query-part"
|
||||
>
|
||||
<div
|
||||
className="css-1cvxpvr"
|
||||
>
|
||||
<svg
|
||||
className="css-sr6nr"
|
||||
fill="currentColor"
|
||||
height={16}
|
||||
viewBox="0 0 24 24"
|
||||
width={16}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19,11H13V5a1,1,0,0,0-2,0v6H5a1,1,0,0,0,0,2h6v6a1,1,0,0,0,2,0V13h6a1,1,0,0,0,0-2Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</a>
|
||||
</div>,
|
||||
]
|
||||
`;
|
Loading…
Reference in New Issue
Block a user