mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Annotations: Adds loading indicators and cancellation (#33404)
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { AnnotationQuery, EventBus, GrafanaThemeV2 } from '@grafana/data';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { getDashboardQueryRunner } from '../../../query/state/DashboardQueryRunner/DashboardQueryRunner';
|
||||
import { AnnotationQueryFinished, AnnotationQueryStarted } from '../../../../types/events';
|
||||
import { InlineField, InlineSwitch, useStyles2 } from '@grafana/ui';
|
||||
import { LoadingIndicator } from '@grafana/ui/src/components/PanelChrome/LoadingIndicator';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
export interface AnnotationPickerProps {
|
||||
events: EventBus;
|
||||
annotation: AnnotationQuery;
|
||||
onEnabledChanged: (annotation: AnnotationQuery) => void;
|
||||
}
|
||||
|
||||
export const AnnotationPicker = ({ annotation, events, onEnabledChanged }: AnnotationPickerProps): JSX.Element => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const styles = useStyles2(getStyles);
|
||||
const onCancel = () => getDashboardQueryRunner().cancel(annotation);
|
||||
|
||||
useEffect(() => {
|
||||
const started = events.subscribe(AnnotationQueryStarted, (event) => {
|
||||
if (event.payload === annotation) {
|
||||
setLoading(true);
|
||||
}
|
||||
});
|
||||
const stopped = events.subscribe(AnnotationQueryFinished, (event) => {
|
||||
if (event.payload === annotation) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
started.unsubscribe();
|
||||
stopped.unsubscribe();
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div key={annotation.name} className={styles.annotation}>
|
||||
<InlineField label={annotation.name} disabled={loading}>
|
||||
<>
|
||||
<InlineSwitch value={annotation.enable} onChange={() => onEnabledChanged(annotation)} disabled={loading} />
|
||||
<div className={styles.indicator}>
|
||||
<LoadingIndicator loading={loading} onCancel={onCancel} />
|
||||
</div>
|
||||
</>
|
||||
</InlineField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function getStyles(theme: GrafanaThemeV2) {
|
||||
return {
|
||||
annotation: css`
|
||||
display: inline-block;
|
||||
margin-right: ${theme.spacing(1)};
|
||||
|
||||
.fa-caret-down {
|
||||
font-size: 75%;
|
||||
padding-left: ${theme.spacing(1)};
|
||||
}
|
||||
|
||||
.gf-form-inline .gf-form {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`,
|
||||
indicator: css`
|
||||
align-self: center;
|
||||
padding: 0 ${theme.spacing(0.5)};
|
||||
`,
|
||||
};
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
import React, { FunctionComponent, useEffect, useState } from 'react';
|
||||
import { AnnotationQuery } from '@grafana/data';
|
||||
import { InlineField, InlineSwitch } from '@grafana/ui';
|
||||
import { AnnotationQuery, EventBus } from '@grafana/data';
|
||||
import { AnnotationPicker } from './AnnotationPicker';
|
||||
|
||||
interface Props {
|
||||
events: EventBus;
|
||||
annotations: AnnotationQuery[];
|
||||
onAnnotationChanged: (annotation: any) => void;
|
||||
}
|
||||
|
||||
export const Annotations: FunctionComponent<Props> = ({ annotations, onAnnotationChanged }) => {
|
||||
const [visibleAnnotations, setVisibleAnnotations] = useState<any>([]);
|
||||
export const Annotations: FunctionComponent<Props> = ({ annotations, onAnnotationChanged, events }) => {
|
||||
const [visibleAnnotations, setVisibleAnnotations] = useState<AnnotationQuery[]>([]);
|
||||
useEffect(() => {
|
||||
setVisibleAnnotations(annotations.filter((annotation) => annotation.hide !== true));
|
||||
}, [annotations]);
|
||||
@@ -19,15 +20,14 @@ export const Annotations: FunctionComponent<Props> = ({ annotations, onAnnotatio
|
||||
|
||||
return (
|
||||
<>
|
||||
{visibleAnnotations.map((annotation: any) => {
|
||||
return (
|
||||
<div key={annotation.name} className={'submenu-item'}>
|
||||
<InlineField label={annotation.name}>
|
||||
<InlineSwitch value={annotation.enable} onChange={() => onAnnotationChanged(annotation)} />
|
||||
</InlineField>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{visibleAnnotations.map((annotation) => (
|
||||
<AnnotationPicker
|
||||
events={events}
|
||||
annotation={annotation}
|
||||
onEnabledChanged={onAnnotationChanged}
|
||||
key={annotation.name}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -48,7 +48,11 @@ class SubMenuUnConnected extends PureComponent<Props> {
|
||||
return (
|
||||
<div className="submenu-controls">
|
||||
<SubMenuItems variables={variables} />
|
||||
<Annotations annotations={annotations} onAnnotationChanged={this.onAnnotationStateChanged} />
|
||||
<Annotations
|
||||
annotations={annotations}
|
||||
onAnnotationChanged={this.onAnnotationStateChanged}
|
||||
events={dashboard.events}
|
||||
/>
|
||||
<div className="gf-form gf-form--grow" />
|
||||
{dashboard && <DashboardLinks dashboard={dashboard} links={links} />}
|
||||
<div className="clearfix" />
|
||||
|
||||
Reference in New Issue
Block a user