mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
LogContext: Add button to scroll to center (#70821)
add scroll to center button
This commit is contained in:
@@ -7,7 +7,7 @@ import { LogContextButtons } from './LogContextButtons';
|
|||||||
describe('LogContextButtons', () => {
|
describe('LogContextButtons', () => {
|
||||||
it('should call onChangeWrapLines when the checkbox is used, case 1', async () => {
|
it('should call onChangeWrapLines when the checkbox is used, case 1', async () => {
|
||||||
const onChangeWrapLines = jest.fn();
|
const onChangeWrapLines = jest.fn();
|
||||||
render(<LogContextButtons onChangeWrapLines={onChangeWrapLines} />);
|
render(<LogContextButtons onChangeWrapLines={onChangeWrapLines} onScrollCenterClick={jest.fn()} />);
|
||||||
const wrapLinesBox = screen.getByRole('checkbox', {
|
const wrapLinesBox = screen.getByRole('checkbox', {
|
||||||
name: 'Wrap lines',
|
name: 'Wrap lines',
|
||||||
});
|
});
|
||||||
@@ -18,7 +18,7 @@ describe('LogContextButtons', () => {
|
|||||||
|
|
||||||
it('should call onChangeWrapLines when the checkbox is used, case 2', async () => {
|
it('should call onChangeWrapLines when the checkbox is used, case 2', async () => {
|
||||||
const onChangeWrapLines = jest.fn();
|
const onChangeWrapLines = jest.fn();
|
||||||
render(<LogContextButtons onChangeWrapLines={onChangeWrapLines} wrapLines />);
|
render(<LogContextButtons onChangeWrapLines={onChangeWrapLines} onScrollCenterClick={jest.fn()} wrapLines />);
|
||||||
const wrapLinesBox = screen.getByRole('checkbox', {
|
const wrapLinesBox = screen.getByRole('checkbox', {
|
||||||
name: 'Wrap lines',
|
name: 'Wrap lines',
|
||||||
});
|
});
|
||||||
@@ -26,4 +26,12 @@ describe('LogContextButtons', () => {
|
|||||||
expect(onChangeWrapLines).toHaveBeenCalledTimes(1);
|
expect(onChangeWrapLines).toHaveBeenCalledTimes(1);
|
||||||
expect(onChangeWrapLines).toHaveBeenCalledWith(false);
|
expect(onChangeWrapLines).toHaveBeenCalledWith(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call onScrollCenterClick when the button is clicked', async () => {
|
||||||
|
const onScrollCenterClick = jest.fn();
|
||||||
|
render(<LogContextButtons onChangeWrapLines={jest.fn()} onScrollCenterClick={onScrollCenterClick} />);
|
||||||
|
const scrollButton = screen.getByRole('button');
|
||||||
|
await userEvent.click(scrollButton);
|
||||||
|
expect(onScrollCenterClick).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,15 +1,28 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { reportInteraction } from '@grafana/runtime';
|
import { reportInteraction } from '@grafana/runtime';
|
||||||
import { InlineSwitch } from '@grafana/ui';
|
import { Button, InlineSwitch, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
wrapLines?: boolean;
|
wrapLines?: boolean;
|
||||||
onChangeWrapLines: (wrapLines: boolean) => void;
|
onChangeWrapLines: (wrapLines: boolean) => void;
|
||||||
|
onScrollCenterClick: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getStyles(theme: GrafanaTheme2) {
|
||||||
|
return {
|
||||||
|
buttons: css({
|
||||||
|
display: 'flex',
|
||||||
|
gap: theme.spacing(1),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export const LogContextButtons = (props: Props) => {
|
export const LogContextButtons = (props: Props) => {
|
||||||
const { wrapLines, onChangeWrapLines } = props;
|
const styles = useStyles2(getStyles);
|
||||||
|
const { wrapLines, onChangeWrapLines, onScrollCenterClick } = props;
|
||||||
const internalOnChangeWrapLines = useCallback(
|
const internalOnChangeWrapLines = useCallback(
|
||||||
(event: React.FormEvent<HTMLInputElement>) => {
|
(event: React.FormEvent<HTMLInputElement>) => {
|
||||||
const state = event.currentTarget.checked;
|
const state = event.currentTarget.checked;
|
||||||
@@ -21,5 +34,12 @@ export const LogContextButtons = (props: Props) => {
|
|||||||
[onChangeWrapLines]
|
[onChangeWrapLines]
|
||||||
);
|
);
|
||||||
|
|
||||||
return <InlineSwitch showLabel value={wrapLines} onChange={internalOnChangeWrapLines} label="Wrap lines" />;
|
return (
|
||||||
|
<div className={styles.buttons}>
|
||||||
|
<InlineSwitch showLabel value={wrapLines} onChange={internalOnChangeWrapLines} label="Wrap lines" />
|
||||||
|
<Button variant="secondary" onClick={onScrollCenterClick}>
|
||||||
|
Center matched line
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -362,6 +362,11 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
|
|||||||
};
|
};
|
||||||
}); // on every render, why not
|
}); // on every render, why not
|
||||||
|
|
||||||
|
const scrollToCenter = useCallback(() => {
|
||||||
|
preEntryElement.current?.scrollIntoView({ block: 'center' });
|
||||||
|
entryElement.current?.scrollIntoView({ block: 'center' });
|
||||||
|
}, [preEntryElement, entryElement]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const scrollE = scrollElement.current;
|
const scrollE = scrollElement.current;
|
||||||
if (scrollE == null) {
|
if (scrollE == null) {
|
||||||
@@ -373,8 +378,7 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
|
|||||||
prevClientHeightRef.current = currentClientHeight;
|
prevClientHeightRef.current = currentClientHeight;
|
||||||
if (prevClientHeight !== currentClientHeight) {
|
if (prevClientHeight !== currentClientHeight) {
|
||||||
// height has changed, we scroll to the center
|
// height has changed, we scroll to the center
|
||||||
preEntryElement.current?.scrollIntoView({ block: 'center' });
|
scrollToCenter();
|
||||||
entryElement.current?.scrollIntoView({ block: 'center' });
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +389,7 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
|
|||||||
const newScrollTop = scrollE.scrollTop + (currentHeight - prevScrollHeight);
|
const newScrollTop = scrollE.scrollTop + (currentHeight - prevScrollHeight);
|
||||||
scrollE.scrollTop = newScrollTop;
|
scrollE.scrollTop = newScrollTop;
|
||||||
}
|
}
|
||||||
}, [context.above.rows]);
|
}, [context.above.rows, scrollToCenter]);
|
||||||
|
|
||||||
useAsync(updateContextQuery, [getRowContextQuery, row]);
|
useAsync(updateContextQuery, [getRowContextQuery, row]);
|
||||||
|
|
||||||
@@ -405,7 +409,11 @@ export const LogRowContextModal: React.FunctionComponent<LogRowContextModalProps
|
|||||||
)}
|
)}
|
||||||
<div className={cx(styles.flexRow, styles.paddingBottom)}>
|
<div className={cx(styles.flexRow, styles.paddingBottom)}>
|
||||||
<div>
|
<div>
|
||||||
<LogContextButtons wrapLines={wrapLines} onChangeWrapLines={setWrapLines} />
|
<LogContextButtons
|
||||||
|
wrapLines={wrapLines}
|
||||||
|
onChangeWrapLines={setWrapLines}
|
||||||
|
onScrollCenterClick={scrollToCenter}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref={scrollElement} className={styles.logRowGroups}>
|
<div ref={scrollElement} className={styles.logRowGroups}>
|
||||||
|
|||||||
Reference in New Issue
Block a user