Merge pull request #13367 from grafana/davkal/explore-julius-fixes

Explore: Query field fixes
This commit is contained in:
Marcus Efraimsson 2018-09-20 17:57:01 +02:00 committed by GitHub
commit a6c438c878
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 3 deletions

View File

@ -5,7 +5,9 @@ const LegendItem = ({ series }) => (
<div className="graph-legend-icon"> <div className="graph-legend-icon">
<i className="fa fa-minus pointer" style={{ color: series.color }} /> <i className="fa fa-minus pointer" style={{ color: series.color }} />
</div> </div>
<a className="graph-legend-alias pointer">{series.alias}</a> <a className="graph-legend-alias pointer" title={series.alias}>
{series.alias}
</a>
</div> </div>
); );

View File

@ -255,6 +255,8 @@ class PromQueryField extends React.Component<PromQueryFieldProps, PromQueryField
// Keep this DOM-free for testing // Keep this DOM-free for testing
getTypeahead({ prefix, wrapperClasses, text }: PromTypeaheadInput): TypeaheadOutput { getTypeahead({ prefix, wrapperClasses, text }: PromTypeaheadInput): TypeaheadOutput {
// Syntax spans have 3 classes by default. More indicate a recognized token
const tokenRecognized = wrapperClasses.length > 3;
// Determine candidates by CSS context // Determine candidates by CSS context
if (_.includes(wrapperClasses, 'context-range')) { if (_.includes(wrapperClasses, 'context-range')) {
// Suggestions for metric[|] // Suggestions for metric[|]
@ -266,7 +268,7 @@ class PromQueryField extends React.Component<PromQueryFieldProps, PromQueryField
return this.getAggregationTypeahead.apply(this, arguments); return this.getAggregationTypeahead.apply(this, arguments);
} else if ( } else if (
// Non-empty but not inside known token // Non-empty but not inside known token
(prefix && !_.includes(wrapperClasses, 'token')) || (prefix && !tokenRecognized) ||
(prefix === '' && !text.match(/^[)\s]+$/)) || // Empty context or after ')' (prefix === '' && !text.match(/^[)\s]+$/)) || // Empty context or after ')'
text.match(/[+\-*/^%]/) // After binary operator text.match(/[+\-*/^%]/) // After binary operator
) { ) {

View File

@ -53,4 +53,22 @@ describe('braces', () => {
handler(event, change); handler(event, change);
expect(Plain.serialize(change.value)).toEqual('sum(rate(metric{namespace="dev", cluster="c1"}[2m]))'); expect(Plain.serialize(change.value)).toEqual('sum(rate(metric{namespace="dev", cluster="c1"}[2m]))');
}); });
it('removes closing brace when opening brace is removed', () => {
const change = Plain.deserialize('time()').change();
let event;
change.move(5);
event = new window.KeyboardEvent('keydown', { key: 'Backspace' });
handler(event, change);
expect(Plain.serialize(change.value)).toEqual('time');
});
it('keeps closing brace when opening brace is removed and inner values exist', () => {
const change = Plain.deserialize('time(value)').change();
let event;
change.move(5);
event = new window.KeyboardEvent('keydown', { key: 'Backspace' });
const handled = handler(event, change);
expect(handled).toBeFalsy();
});
}); });

View File

@ -43,6 +43,22 @@ export default function BracesPlugin() {
return true; return true;
} }
case 'Backspace': {
const text = value.anchorText.text;
const offset = value.anchorOffset;
const previousChar = text[offset - 1];
const nextChar = text[offset];
if (BRACES[previousChar] && BRACES[previousChar] === nextChar) {
event.preventDefault();
// Remove closing brace if directly following
change
.deleteBackward()
.deleteForward()
.focus();
return true;
}
}
default: { default: {
break; break;
} }

View File

@ -46,7 +46,7 @@ export function determineQueryHints(series: any[], datasource?: any): any[] {
// Check for monotony // Check for monotony
const datapoints: number[][] = s.datapoints; const datapoints: number[][] = s.datapoints;
if (datapoints.length > 1) { if (query.indexOf('rate(') === -1 && datapoints.length > 1) {
let increasing = false; let increasing = false;
const monotonic = datapoints.filter(dp => dp[0] !== null).every((dp, index) => { const monotonic = datapoints.filter(dp => dp[0] !== null).every((dp, index) => {
if (index === 0) { if (index === 0) {

View File

@ -247,6 +247,12 @@ describe('PrometheusDatasource', () => {
}); });
}); });
it('returns no rate hint for a monotonously increasing series that already has a rate', () => {
const series = [{ datapoints: [[23, 1000], [24, 1001]], query: 'rate(metric[1m])', responseIndex: 0 }];
const hints = determineQueryHints(series);
expect(hints).toEqual([null]);
});
it('returns a rate hint w/o action for a complex monotonously increasing series', () => { it('returns a rate hint w/o action for a complex monotonously increasing series', () => {
const series = [{ datapoints: [[23, 1000], [24, 1001]], query: 'sum(metric)', responseIndex: 0 }]; const series = [{ datapoints: [[23, 1000], [24, 1001]], query: 'sum(metric)', responseIndex: 0 }];
const hints = determineQueryHints(series); const hints = determineQueryHints(series);