Made scrollbar have scrollTop and setScrollTop props so we can control scroll position
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
import Scrollbars from 'react-custom-scrollbars';
|
import Scrollbars from 'react-custom-scrollbars';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -8,6 +9,8 @@ interface Props {
|
|||||||
autoHideDuration?: number;
|
autoHideDuration?: number;
|
||||||
autoMaxHeight?: string;
|
autoMaxHeight?: string;
|
||||||
hideTracksWhenNotNeeded?: boolean;
|
hideTracksWhenNotNeeded?: boolean;
|
||||||
|
scrollTop?: number;
|
||||||
|
setScrollTop: (value: React.MouseEvent<HTMLElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,13 +24,43 @@ export class CustomScrollbar extends PureComponent<Props> {
|
|||||||
autoHideDuration: 200,
|
autoHideDuration: 200,
|
||||||
autoMaxHeight: '100%',
|
autoMaxHeight: '100%',
|
||||||
hideTracksWhenNotNeeded: false,
|
hideTracksWhenNotNeeded: false,
|
||||||
|
scrollTop: 0,
|
||||||
|
setScrollTop: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private ref: React.RefObject<Scrollbars>;
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.ref = React.createRef<Scrollbars>();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScroll() {
|
||||||
|
const ref = this.ref.current;
|
||||||
|
|
||||||
|
if (ref && !_.isNil(this.props.scrollTop)) {
|
||||||
|
if (this.props.scrollTop > 10000) {
|
||||||
|
ref.scrollToBottom();
|
||||||
|
} else {
|
||||||
|
ref.scrollTop(this.props.scrollTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.updateScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.updateScroll();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { customClassName, children, autoMaxHeight } = this.props;
|
const { customClassName, children, autoMaxHeight } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Scrollbars
|
<Scrollbars
|
||||||
|
ref={this.ref}
|
||||||
className={customClassName}
|
className={customClassName}
|
||||||
autoHeight={true}
|
autoHeight={true}
|
||||||
// These autoHeightMin & autoHeightMax options affect firefox and chrome differently.
|
// These autoHeightMin & autoHeightMax options affect firefox and chrome differently.
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ interface Props {
|
|||||||
heading: string;
|
heading: string;
|
||||||
renderToolbar?: () => JSX.Element;
|
renderToolbar?: () => JSX.Element;
|
||||||
toolbarItems?: EditorToolbarView[];
|
toolbarItems?: EditorToolbarView[];
|
||||||
|
scrollTop?: number;
|
||||||
|
setScrollTop?: (value: React.MouseEvent<HTMLElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EditorToolbarView {
|
export interface EditorToolbarView {
|
||||||
@@ -103,7 +105,7 @@ export class EditorTabBody extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children, renderToolbar, heading, toolbarItems } = this.props;
|
const { children, renderToolbar, heading, toolbarItems, scrollTop, setScrollTop } = this.props;
|
||||||
const { openView, fadeIn, isOpen } = this.state;
|
const { openView, fadeIn, isOpen } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -119,7 +121,7 @@ export class EditorTabBody extends PureComponent<Props, State> {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-editor__scroll">
|
<div className="panel-editor__scroll">
|
||||||
<CustomScrollbar autoHide={false}>
|
<CustomScrollbar autoHide={false} scrollTop={scrollTop} setScrollTop={setScrollTop}>
|
||||||
<div className="panel-editor__content">
|
<div className="panel-editor__content">
|
||||||
<FadeIn in={isOpen} duration={200} unmountOnExit={true}>
|
<FadeIn in={isOpen} duration={200} unmountOnExit={true}>
|
||||||
{openView && this.renderOpenView(openView)}
|
{openView && this.renderOpenView(openView)}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ interface State {
|
|||||||
isLoadingHelp: boolean;
|
isLoadingHelp: boolean;
|
||||||
isPickerOpen: boolean;
|
isPickerOpen: boolean;
|
||||||
isAddingMixed: boolean;
|
isAddingMixed: boolean;
|
||||||
|
scrollTop: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueriesTab extends PureComponent<Props, State> {
|
export class QueriesTab extends PureComponent<Props, State> {
|
||||||
@@ -44,6 +45,7 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
helpContent: null,
|
helpContent: null,
|
||||||
isPickerOpen: false,
|
isPickerOpen: false,
|
||||||
isAddingMixed: false,
|
isAddingMixed: false,
|
||||||
|
scrollTop: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
findCurrentDataSource(): DataSourceSelectItem {
|
findCurrentDataSource(): DataSourceSelectItem {
|
||||||
@@ -104,7 +106,7 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.props.panel.addQuery();
|
this.props.panel.addQuery();
|
||||||
this.forceUpdate();
|
this.setState({ scrollTop: this.state.scrollTop + 100000 });
|
||||||
};
|
};
|
||||||
|
|
||||||
onRemoveQuery = (query: DataQuery) => {
|
onRemoveQuery = (query: DataQuery) => {
|
||||||
@@ -127,9 +129,21 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderToolbar = () => {
|
renderToolbar = () => {
|
||||||
const { currentDS } = this.state;
|
const { currentDS, isAddingMixed } = this.state;
|
||||||
|
|
||||||
return <DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />;
|
return (
|
||||||
|
<>
|
||||||
|
<DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} />
|
||||||
|
<div className="m-l-2">
|
||||||
|
{!isAddingMixed && (
|
||||||
|
<button className="btn navbar-button navbar-button--primary" onClick={this.onAddQueryClick}>
|
||||||
|
Add Query
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{isAddingMixed && this.renderMixedPicker()}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderMixedPicker = () => {
|
renderMixedPicker = () => {
|
||||||
@@ -146,16 +160,21 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
onAddMixedQuery = datasource => {
|
onAddMixedQuery = datasource => {
|
||||||
this.onAddQuery({ datasource: datasource.name });
|
this.onAddQuery({ datasource: datasource.name });
|
||||||
this.setState({ isAddingMixed: false });
|
this.setState({ isAddingMixed: false, scrollTop: this.state.scrollTop + 10000 });
|
||||||
};
|
};
|
||||||
|
|
||||||
onMixedPickerBlur = () => {
|
onMixedPickerBlur = () => {
|
||||||
this.setState({ isAddingMixed: false });
|
this.setState({ isAddingMixed: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setScrollTop = (event: React.MouseEvent<HTMLElement>) => {
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
this.setState({ scrollTop: target.scrollTop });
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { panel } = this.props;
|
const { panel } = this.props;
|
||||||
const { currentDS, isAddingMixed } = this.state;
|
const { currentDS, scrollTop } = this.state;
|
||||||
|
|
||||||
const queryInspector: EditorToolbarView = {
|
const queryInspector: EditorToolbarView = {
|
||||||
title: 'Query Inspector',
|
title: 'Query Inspector',
|
||||||
@@ -169,7 +188,13 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditorTabBody heading="Queries" renderToolbar={this.renderToolbar} toolbarItems={[queryInspector, dsHelp]}>
|
<EditorTabBody
|
||||||
|
heading="Data Source"
|
||||||
|
renderToolbar={this.renderToolbar}
|
||||||
|
toolbarItems={[queryInspector, dsHelp]}
|
||||||
|
setScrollTop={this.setScrollTop}
|
||||||
|
scrollTop={scrollTop}
|
||||||
|
>
|
||||||
<>
|
<>
|
||||||
<div className="query-editor-rows">
|
<div className="query-editor-rows">
|
||||||
{panel.targets.map((query, index) => (
|
{panel.targets.map((query, index) => (
|
||||||
@@ -185,23 +210,6 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="query-editor-box">
|
|
||||||
<div className="query-editor-row__header">
|
|
||||||
<div className="query-editor-row__ref-id">
|
|
||||||
<i className="fa fa-caret-down" />
|
|
||||||
{' '}
|
|
||||||
<span>{panel.getNextQueryLetter()}</span>
|
|
||||||
</div>
|
|
||||||
<div className="gf-form">
|
|
||||||
{!isAddingMixed && (
|
|
||||||
<button className="btn btn-secondary gf-form-btn" onClick={this.onAddQueryClick}>
|
|
||||||
Add Query
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{isAddingMixed && this.renderMixedPicker()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<PanelOptionsGroup>
|
<PanelOptionsGroup>
|
||||||
<QueryOptions panel={panel} datasource={currentDS} />
|
<QueryOptions panel={panel} datasource={currentDS} />
|
||||||
</PanelOptionsGroup>
|
</PanelOptionsGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user