From 3c23b8cd9a15e071b7e8b9cd195ec85ede1fd3bf Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 26 Jun 2018 14:01:26 -0700 Subject: [PATCH] WIP template variable replacement frontend --- ui/src/tempVars/utils/replace.ts | 52 ++++++++++ ui/src/types/tempVars.ts | 1 + ui/test/tempVars/utils/replace.test.ts | 125 +++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 ui/src/tempVars/utils/replace.ts create mode 100644 ui/test/tempVars/utils/replace.test.ts diff --git a/ui/src/tempVars/utils/replace.ts b/ui/src/tempVars/utils/replace.ts new file mode 100644 index 0000000000..962f9e3b4c --- /dev/null +++ b/ui/src/tempVars/utils/replace.ts @@ -0,0 +1,52 @@ +import {Template, TemplateValueType, TemplateValue} from 'src/types/tempVars' + +const templateReplace = (q: string, tempVars: Template[]) => { + const query = tempVars.reduce((acc, template) => { + const qu = renderTemplate(acc, template) + return qu + }, q) + + return query +} + +const renderTemplate = (query: string, template: Template): string => { + if (!template.values.length) { + return query + } + + if (query && !query.includes(template.tempVar)) { + return query + } + + const templateValue: TemplateValue = template.values.find(v => v.selected) + + if (!templateValue) { + return query + } + + const {tempVar} = template + const {value, type} = templateValue + + switch (type) { + case TemplateValueType.TagKey: + case TemplateValueType.FieldKey: + case TemplateValueType.Measurement: + case TemplateValueType.Database: + return replaceAll(query, tempVar, `"${value}"`) + case TemplateValueType.TagValue: + case TemplateValueType.TimeStamp: + return replaceAll(query, tempVar, `'${value}'`) + case TemplateValueType.CSV: + case TemplateValueType.Constant: + case TemplateValueType.MetaQuery: + return replaceAll(query, tempVar, value) + default: + return query + } +} + +const replaceAll = (query: string, search: string, replacement: string) => { + return query.split(search).join(replacement) +} + +export default templateReplace diff --git a/ui/src/types/tempVars.ts b/ui/src/types/tempVars.ts index cc17663c4a..1d524aa101 100644 --- a/ui/src/types/tempVars.ts +++ b/ui/src/types/tempVars.ts @@ -10,6 +10,7 @@ export enum TemplateValueType { Points = 'points', Constant = 'constant', MetaQuery = 'influxql', + TimeStamp = 'timeStamp', } export interface TemplateValue { diff --git a/ui/test/tempVars/utils/replace.test.ts b/ui/test/tempVars/utils/replace.test.ts new file mode 100644 index 0000000000..a5189e6847 --- /dev/null +++ b/ui/test/tempVars/utils/replace.test.ts @@ -0,0 +1,125 @@ +import templateReplace from 'src/tempVars/utils/replace' +import {TemplateValueType} from 'src/types/tempVars' + +describe('templates.utils.replace', () => { + describe('template replacement', () => { + it('can replace select with parameters', () => { + const query = + ':method: field1, :field: FROM :measurement: WHERE temperature > :temperature:' + + const vars = [ + { + tempVar: ':temperature:', + values: [{type: TemplateValueType.CSV, value: '10', selected: true}], + }, + { + tempVar: ':field:', + values: [ + {type: TemplateValueType.FieldKey, value: 'field2', selected: true}, + ], + }, + { + tempVar: ':method:', + values: [ + {type: TemplateValueType.CSV, value: 'SELECT', selected: true}, + ], + }, + { + tempVar: ':measurement:', + values: [ + {type: TemplateValueType.CSV, value: `"cpu"`, selected: true}, + ], + }, + ] + + const expected = `SELECT field1, "field2" FROM "cpu" WHERE temperature > 10` + + const actual = templateReplace(query, vars) + expect(actual).toBe(expected) + }) + }) + + it('can replace all in a select with paramaters and aggregates', () => { + const vars = [ + { + tempVar: ':value:', + values: [ + { + type: TemplateValueType.TagValue, + value: 'howdy.com', + selected: true, + }, + ], + }, + { + tempVar: ':tag:', + values: [ + {type: TemplateValueType.TagKey, value: 'host', selected: true}, + ], + }, + { + tempVar: ':field:', + values: [ + {type: TemplateValueType.FieldKey, value: 'field', selected: true}, + ], + }, + ] + + const query = `SELECT mean(:field:) FROM "cpu" WHERE :tag: = :value: GROUP BY :tag:` + const expected = `SELECT mean("field") FROM "cpu" WHERE "host" = 'howdy.com' GROUP BY "host"` + const actual = templateReplace(query, vars) + + expect(actual).toBe(expected) + }) + + describe('sad path', () => { + describe('with no templates', () => { + it('does not do a replacement', () => { + const query = `SELECT :field: FROM "cpu"` + const expected = query + const actual = templateReplace(query, []) + + expect(actual).toBe(expected) + }) + }) + + describe('with no template values', () => { + it('does not do a replacement', () => { + const vars = [ + { + tempVar: ':field:', + values: [], + }, + ] + const query = `SELECT :field: FROM "cpu"` + const expected = query + const actual = templateReplace(query, []) + + expect(actual).toBe(expected) + }) + }) + + describe('with an unknown template type', () => { + it('does not do a replacement', () => { + const vars = [ + { + tempVar: ':field:', + values: [ + { + type: 'howdy', + value: 'field', + selected: true, + }, + ], + }, + ] + + const query = `SELECT :field: FROM "cpu"` + const expected = query + const actual = templateReplace(query, vars) + + expect(actual).toBe(expected) + }) + }) + }) +})