mirror of
https://github.com/grafana/grafana.git
synced 2025-09-21 04:12:52 +08:00
Elasticsearch: Migrate annotation editor to react (#49529)
* Migrate annotation editor to react * Gio patch * Update types * Optional and conform to older design
This commit is contained in:
@ -0,0 +1,91 @@
|
||||
import React from 'react';
|
||||
|
||||
import { AnnotationQuery } from '@grafana/data';
|
||||
import { EditorRow, EditorField } from '@grafana/experimental';
|
||||
import { Input } from '@grafana/ui';
|
||||
|
||||
import { ElasticsearchQuery } from '../../types';
|
||||
|
||||
import { ElasticQueryEditorProps, ElasticSearchQueryField } from './index';
|
||||
|
||||
type Props = ElasticQueryEditorProps & {
|
||||
annotation?: AnnotationQuery<ElasticsearchQuery>;
|
||||
onAnnotationChange?: (annotation: AnnotationQuery<ElasticsearchQuery>) => void;
|
||||
};
|
||||
|
||||
export function ElasticsearchAnnotationsQueryEditor(props: Props) {
|
||||
const annotation = props.annotation!;
|
||||
const onAnnotationChange = props.onAnnotationChange!;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="gf-form-group">
|
||||
<ElasticSearchQueryField
|
||||
value={annotation.target?.query}
|
||||
onChange={(query) => {
|
||||
onAnnotationChange({
|
||||
...annotation,
|
||||
query,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="gf-form-group">
|
||||
<h6>Field mappings</h6>
|
||||
<EditorRow>
|
||||
<EditorField label="Time">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="@timestamp"
|
||||
value={annotation.timeField}
|
||||
onChange={(e) => {
|
||||
onAnnotationChange({
|
||||
...annotation,
|
||||
timeField: e.currentTarget.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</EditorField>
|
||||
<EditorField label="Time End">
|
||||
<Input
|
||||
type="text"
|
||||
value={annotation.timeEndField}
|
||||
onChange={(e) => {
|
||||
onAnnotationChange({
|
||||
...annotation,
|
||||
timeEndField: e.currentTarget.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</EditorField>
|
||||
<EditorField label="Text">
|
||||
<Input
|
||||
type="text"
|
||||
value={annotation.textField}
|
||||
onChange={(e) => {
|
||||
onAnnotationChange({
|
||||
...annotation,
|
||||
textField: e.currentTarget.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</EditorField>
|
||||
<EditorField label="Tags">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="tags"
|
||||
value={annotation.tagsField}
|
||||
onChange={(e) => {
|
||||
onAnnotationChange({
|
||||
...annotation,
|
||||
tagsField: e.currentTarget.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</EditorField>
|
||||
</EditorRow>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -53,13 +53,31 @@ interface Props {
|
||||
value: ElasticsearchQuery;
|
||||
}
|
||||
|
||||
export const ElasticSearchQueryField = ({ value, onChange }: { value?: string; onChange: (v: string) => void }) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div className={styles.queryFieldWrapper}>
|
||||
<QueryField
|
||||
query={value}
|
||||
// By default QueryField calls onChange if onBlur is not defined, this will trigger a rerender
|
||||
// And slate will claim the focus, making it impossible to leave the field.
|
||||
onBlur={() => {}}
|
||||
onChange={onChange}
|
||||
placeholder="Lucene Query"
|
||||
portalOrigin="elasticsearch"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const QueryEditorForm = ({ value }: Props) => {
|
||||
const dispatch = useDispatch();
|
||||
const nextId = useNextId();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
// To be considered a time series query, the last bucked aggregation must be a Date Histogram
|
||||
const isTimeSeriesQuery = value.bucketAggs?.slice(-1)[0]?.type === 'date_histogram';
|
||||
const isTimeSeriesQuery = value?.bucketAggs?.slice(-1)[0]?.type === 'date_histogram';
|
||||
|
||||
const showBucketAggregationsEditor = value.metrics?.every(
|
||||
(metric) => !metricAggregationConfig[metric.type].isSingleMetric
|
||||
@ -69,17 +87,8 @@ const QueryEditorForm = ({ value }: Props) => {
|
||||
<>
|
||||
<div className={styles.root}>
|
||||
<InlineLabel width={17}>Query</InlineLabel>
|
||||
<div className={styles.queryFieldWrapper}>
|
||||
<QueryField
|
||||
query={value.query}
|
||||
// By default QueryField calls onChange if onBlur is not defined, this will trigger a rerender
|
||||
// And slate will claim the focus, making it impossible to leave the field.
|
||||
onBlur={() => {}}
|
||||
onChange={(query) => dispatch(changeQuery(query))}
|
||||
placeholder="Lucene Query"
|
||||
portalOrigin="elasticsearch"
|
||||
/>
|
||||
</div>
|
||||
<ElasticSearchQueryField onChange={(query) => dispatch(changeQuery(query))} value={value?.query} />
|
||||
|
||||
<InlineField
|
||||
label="Alias"
|
||||
labelWidth={15}
|
||||
|
@ -31,6 +31,7 @@ import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContext
|
||||
import { queryLogsVolume } from 'app/core/logs_model';
|
||||
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
|
||||
|
||||
import { ElasticsearchAnnotationsQueryEditor } from './components/QueryEditor/AnnotationQueryEditor';
|
||||
import {
|
||||
BucketAggregation,
|
||||
isBucketAggregationWithField,
|
||||
@ -117,6 +118,9 @@ export class ElasticDatasource
|
||||
this.logLevelField = settingsData.logLevelField || '';
|
||||
this.dataLinks = settingsData.dataLinks || [];
|
||||
this.includeFrozen = settingsData.includeFrozen ?? false;
|
||||
this.annotations = {
|
||||
QueryEditor: ElasticsearchAnnotationsQueryEditor,
|
||||
};
|
||||
|
||||
if (this.logMessageField === '') {
|
||||
this.logMessageField = undefined;
|
||||
|
@ -4,11 +4,4 @@ import { QueryEditor } from './components/QueryEditor';
|
||||
import { ConfigEditor } from './configuration/ConfigEditor';
|
||||
import { ElasticDatasource } from './datasource';
|
||||
|
||||
class ElasticAnnotationsQueryCtrl {
|
||||
static templateUrl = 'partials/annotations.editor.html';
|
||||
}
|
||||
|
||||
export const plugin = new DataSourcePlugin(ElasticDatasource)
|
||||
.setQueryEditor(QueryEditor)
|
||||
.setConfigEditor(ConfigEditor)
|
||||
.setAnnotationQueryCtrl(ElasticAnnotationsQueryCtrl);
|
||||
export const plugin = new DataSourcePlugin(ElasticDatasource).setQueryEditor(QueryEditor).setConfigEditor(ConfigEditor);
|
||||
|
@ -1,38 +0,0 @@
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form" ng-if="ctrl.annotation.index">
|
||||
<span class="gf-form-label width-14">Index name</span>
|
||||
<input type="text" class="gf-form-input max-width-20" ng-model='ctrl.annotation.index' placeholder="events-*"></input>
|
||||
</div>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
<input type="text" class="gf-form-input" ng-model='ctrl.annotation.query'
|
||||
placeholder="Elasticsearch lucene query"></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-group">
|
||||
<h6>Field mappings</h6>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Time</span>
|
||||
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.timeField' placeholder="@timestamp"></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Time End</span>
|
||||
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.timeEndField' placeholder=""></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Text</span>
|
||||
<input type="text" class="gf-form-input max-width-14" ng-model='ctrl.annotation.textField' placeholder=""></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label">Tags</span>
|
||||
<input type="text" class="gf-form-input max-width-10" ng-model='ctrl.annotation.tagsField' placeholder="tags"></input>
|
||||
</div>
|
||||
<div class="gf-form" ng-show="ctrl.annotation.titleField">
|
||||
<span class="gf-form-label">Title <em class="muted">(deprecated)</em></span>
|
||||
<input type="text" class="gf-form-input max-width-16" ng-model='ctrl.annotation.titleField' placeholder="desc"></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user