PanelHeader: show streaming indicator (and allow unsubscribe) (#28682)

This commit is contained in:
Ryan McKinley 2020-11-05 08:03:34 -08:00 committed by GitHub
parent f39a8d630b
commit 7308028a90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 19 deletions

View File

@ -13,7 +13,7 @@ export interface PopoverContentProps {
export type PopoverContent = string | React.ReactElement<any> | ((props: PopoverContentProps) => JSX.Element);
export const Tooltip: FC<TooltipProps> = ({ children, theme, ...controllerProps }: TooltipProps) => {
export const Tooltip: FC<TooltipProps> = React.memo(({ children, theme, ...controllerProps }: TooltipProps) => {
const tooltipTriggerRef = createRef<PopperJS.ReferenceObject>();
const popperBackgroundClassName = 'popper__background' + (theme ? ' popper__background--' + theme : '');
@ -52,4 +52,4 @@ export const Tooltip: FC<TooltipProps> = ({ children, theme, ...controllerProps
}}
</PopoverController>
);
};
});

View File

@ -1,9 +1,9 @@
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
import classNames from 'classnames';
import { isEqual } from 'lodash';
import { DataLink, LoadingState, PanelData, PanelMenuItem, QueryResultMetaNotice, ScopedVars } from '@grafana/data';
import { AngularComponent, getTemplateSrv } from '@grafana/runtime';
import { ClickOutsideWrapper, Icon, IconName, Tooltip } from '@grafana/ui';
import { AngularComponent, config, getTemplateSrv } from '@grafana/runtime';
import { ClickOutsideWrapper, Icon, IconName, Tooltip, stylesFactory } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors';
import PanelHeaderCorner from './PanelHeaderCorner';
@ -14,6 +14,7 @@ import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
import { getPanelMenu } from 'app/features/dashboard/utils/getPanelMenu';
import { updateLocation } from 'app/core/actions';
import { css } from 'emotion';
export interface Props {
panel: PanelModel;
@ -41,7 +42,7 @@ interface State {
menuItems: PanelMenuItem[];
}
export class PanelHeader extends Component<Props, State> {
export class PanelHeader extends PureComponent<Props, State> {
clickCoordinates: ClickCoordinates = { x: 0, y: 0 };
state: State = {
@ -90,14 +91,28 @@ export class PanelHeader extends Component<Props, State> {
this.props.panel.getQueryRunner().cancelQuery();
};
private renderLoadingState(): JSX.Element {
return (
<div className="panel-loading" onClick={this.onCancelQuery}>
<Tooltip content="Cancel query">
<Icon className="panel-loading__spinner spin-clockwise" name="sync" />
</Tooltip>
</div>
);
renderLoadingState(state: LoadingState): JSX.Element | null {
if (state === LoadingState.Loading) {
return (
<div className="panel-loading" onClick={this.onCancelQuery}>
<Tooltip content="Cancel query">
<Icon className="panel-loading__spinner spin-clockwise" name="sync" />
</Tooltip>
</div>
);
}
if (state === LoadingState.Streaming) {
const styles = getStyles();
return (
<div className="panel-loading" onClick={this.onCancelQuery}>
<div title="Streaming (click to stop)" className={styles.streamIndicator} />
</div>
);
}
return null;
}
openInspect = (e: React.SyntheticEvent, tab: string) => {
@ -156,7 +171,7 @@ export class PanelHeader extends Component<Props, State> {
return (
<>
{data.state === LoadingState.Loading && this.renderLoadingState()}
{this.renderLoadingState(data.state)}
<div className={panelHeaderClass}>
<PanelHeaderCorner
panel={panel}
@ -201,3 +216,21 @@ export class PanelHeader extends Component<Props, State> {
);
}
}
/*
* Styles
*/
export const getStyles = stylesFactory(() => {
return {
streamIndicator: css`
width: 10px;
height: 10px;
background: ${config.theme.colors.textFaint};
box-shadow: 0 0 2px ${config.theme.colors.textFaint};
border-radius: 50%;
position: relative;
top: 6px;
right: 1px;
`,
};
});

View File

@ -10,7 +10,7 @@ exports[`Render should render component 1`] = `
>
External group sync
</h3>
<Component
<Memo()
content="Sync LDAP or OAuth groups with your Grafana teams."
placement="auto"
>
@ -18,7 +18,7 @@ exports[`Render should render component 1`] = `
className="icon--has-hover page-sub-heading-icon"
name="question-circle"
/>
</Component>
</Memo()>
<div
className="page-action-bar__spacer"
/>
@ -92,7 +92,7 @@ exports[`Render should render groups table 1`] = `
>
External group sync
</h3>
<Component
<Memo()
content="Sync LDAP or OAuth groups with your Grafana teams."
placement="auto"
>
@ -100,7 +100,7 @@ exports[`Render should render groups table 1`] = `
className="icon--has-hover page-sub-heading-icon"
name="question-circle"
/>
</Component>
</Memo()>
<div
className="page-action-bar__spacer"
/>

View File

@ -98,6 +98,7 @@ export function runSignalStream(
subscriber.next({
data: [data],
key: streamId,
state: LoadingState.Streaming,
});
timeoutId = setTimeout(pushNextEvent, speed);