mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 01:15:46 +08:00

* feat(grafana-ui): introduce development exports to prevent importing from grafana/ui/src * refactor(theme-generation): move theme templates into scripts so themes continue to build * refactor(frontend): replace grafana/ui paths that use nested src with /internal or /unstable * chore(betterer): update better results file * feat(grafana-ui): support enterprise, remove Text component from internal * docs(packages): update readme with exporting code conventions
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import { useEffect, useState } from 'react';
|
|
|
|
import { AnnotationQuery, EventBus, GrafanaTheme2 } from '@grafana/data';
|
|
import { selectors } from '@grafana/e2e-selectors';
|
|
import { InlineField, InlineFieldRow, InlineSwitch, useStyles2 } from '@grafana/ui';
|
|
import { LoadingIndicator } from '@grafana/ui/internal';
|
|
|
|
import { AnnotationQueryFinished, AnnotationQueryStarted } from '../../../../types/events';
|
|
import { getDashboardQueryRunner } from '../../../query/state/DashboardQueryRunner/DashboardQueryRunner';
|
|
|
|
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.getStream(AnnotationQueryStarted).subscribe({
|
|
next: (event) => {
|
|
if (event.payload === annotation) {
|
|
setLoading(true);
|
|
}
|
|
},
|
|
});
|
|
const stopped = events.getStream(AnnotationQueryFinished).subscribe({
|
|
next: (event) => {
|
|
if (event.payload === annotation) {
|
|
setLoading(false);
|
|
}
|
|
},
|
|
});
|
|
|
|
return () => {
|
|
started.unsubscribe();
|
|
stopped.unsubscribe();
|
|
};
|
|
});
|
|
|
|
return (
|
|
<div key={annotation.name} className={styles.annotation}>
|
|
<InlineFieldRow>
|
|
<InlineField
|
|
label={annotation.name}
|
|
disabled={loading}
|
|
data-testid={selectors.pages.Dashboard.SubMenu.Annotations.annotationLabel(annotation.name)}
|
|
>
|
|
<InlineSwitch
|
|
label={annotation.name}
|
|
value={annotation.enable}
|
|
onChange={() => onEnabledChanged(annotation)}
|
|
disabled={loading}
|
|
data-testid={selectors.pages.Dashboard.SubMenu.Annotations.annotationToggle(annotation.name)}
|
|
/>
|
|
</InlineField>
|
|
<div className={styles.indicator}>
|
|
<LoadingIndicator loading={loading} onCancel={onCancel} />
|
|
</div>
|
|
</InlineFieldRow>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
function getStyles(theme: GrafanaTheme2) {
|
|
return {
|
|
annotation: css({
|
|
display: 'inline-block',
|
|
marginRight: theme.spacing(1),
|
|
'.fa-caret-down': {
|
|
fontSize: '75%',
|
|
paddingLeft: theme.spacing(1),
|
|
},
|
|
'.gf-form-inline .gf-form': {
|
|
marginBottom: 0,
|
|
},
|
|
}),
|
|
indicator: css({
|
|
alignSelf: 'center',
|
|
padding: `0 ${theme.spacing(0.5)}`,
|
|
}),
|
|
};
|
|
}
|