From 4a385776f6e0eb99cf9e5f85c225473445a7254c Mon Sep 17 00:00:00 2001 From: ppisljar Date: Tue, 28 Jul 2020 06:56:38 -0700 Subject: [PATCH 1/8] theme function --- .../common/expression_functions/specs/font.ts | 15 +++-- .../expression_functions/specs/index.ts | 3 + .../expression_functions/specs/theme.ts | 66 +++++++++++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 src/plugins/expressions/common/expression_functions/specs/theme.ts diff --git a/src/plugins/expressions/common/expression_functions/specs/font.ts b/src/plugins/expressions/common/expression_functions/specs/font.ts index c46ce0adadef0..52692f72cebb2 100644 --- a/src/plugins/expressions/common/expression_functions/specs/font.ts +++ b/src/plugins/expressions/common/expression_functions/specs/font.ts @@ -64,7 +64,7 @@ export const font: ExpressionFunctionFont = { inputTypes: ['null'], args: { align: { - default: 'left', + default: '{ theme "font.align" default="left" }', help: i18n.translate('expressions.functions.font.args.alignHelpText', { defaultMessage: 'The horizontal text alignment.', }), @@ -72,13 +72,14 @@ export const font: ExpressionFunctionFont = { types: ['string'], }, color: { + default: `{ theme "font.color" }`, help: i18n.translate('expressions.functions.font.args.colorHelpText', { defaultMessage: 'The text color.', }), types: ['string'], }, family: { - default: `"${openSans.value}"`, + default: `{ theme "font.family" default="${openSans.value}" }`, help: i18n.translate('expressions.functions.font.args.familyHelpText', { defaultMessage: 'An acceptable {css} web font string', values: { @@ -88,7 +89,7 @@ export const font: ExpressionFunctionFont = { types: ['string'], }, italic: { - default: false, + default: `{ theme "font.italic" default=false }`, help: i18n.translate('expressions.functions.font.args.italicHelpText', { defaultMessage: 'Italicize the text?', }), @@ -96,7 +97,7 @@ export const font: ExpressionFunctionFont = { types: ['boolean'], }, lHeight: { - default: null, + default: `{ theme "font.lHeight" }`, aliases: ['lineHeight'], help: i18n.translate('expressions.functions.font.args.lHeightHelpText', { defaultMessage: 'The line height in pixels', @@ -104,14 +105,14 @@ export const font: ExpressionFunctionFont = { types: ['number', 'null'], }, size: { - default: 14, + default: `{ theme "font.size" default=14 }`, help: i18n.translate('expressions.functions.font.args.sizeHelpText', { defaultMessage: 'The font size in pixels', }), types: ['number'], }, underline: { - default: false, + default: `{ theme "font.underline" default=false }`, help: i18n.translate('expressions.functions.font.args.underlineHelpText', { defaultMessage: 'Underline the text?', }), @@ -119,7 +120,7 @@ export const font: ExpressionFunctionFont = { types: ['boolean'], }, weight: { - default: 'normal', + default: `{ theme "font.weight" default="normal" }`, help: i18n.translate('expressions.functions.font.args.weightHelpText', { defaultMessage: 'The font weight. For example, {list}, or {end}.', values: { diff --git a/src/plugins/expressions/common/expression_functions/specs/index.ts b/src/plugins/expressions/common/expression_functions/specs/index.ts index f7471a8fd9d75..5b9562dae5f2e 100644 --- a/src/plugins/expressions/common/expression_functions/specs/index.ts +++ b/src/plugins/expressions/common/expression_functions/specs/index.ts @@ -24,6 +24,7 @@ import { kibanaContextFunction } from './kibana_context'; import { variableSet } from './var_set'; import { variable } from './var'; import { AnyExpressionFunctionDefinition } from '../types'; +import { theme } from './theme'; export const functionSpecs: AnyExpressionFunctionDefinition[] = [ clog, @@ -32,6 +33,7 @@ export const functionSpecs: AnyExpressionFunctionDefinition[] = [ kibanaContextFunction, variableSet, variable, + theme, ]; export * from './clog'; @@ -40,3 +42,4 @@ export * from './kibana'; export * from './kibana_context'; export * from './var_set'; export * from './var'; +export * from './theme'; diff --git a/src/plugins/expressions/common/expression_functions/specs/theme.ts b/src/plugins/expressions/common/expression_functions/specs/theme.ts new file mode 100644 index 0000000000000..e0aeedc1a0bbf --- /dev/null +++ b/src/plugins/expressions/common/expression_functions/specs/theme.ts @@ -0,0 +1,66 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; +import { ExpressionFunctionDefinition } from '../types'; + +interface Arguments { + variable: string; + default: string | number | boolean; +} + +type Output = string | number | boolean | undefined; + +export type ExpressionFunctionTheme = ExpressionFunctionDefinition< + 'theme', + null, + Arguments, + Output +>; + +export const theme: ExpressionFunctionTheme = { + name: 'theme', + aliases: [], + help: i18n.translate('expressions.functions.fontHelpText', { + defaultMessage: 'Reads a theme setting.', + }), + inputTypes: ['null'], + args: { + variable: { + aliases: ['_'], + help: i18n.translate('expressions.functions.theme.args.variableHelpText', { + defaultMessage: 'theme variable to read.', + }), + required: true, + types: ['string'], + }, + default: { + help: i18n.translate('expressions.functions.font.args.defaultHelpText', { + defaultMessage: 'default value in case theming info is not available.', + }), + types: ['string', 'number'], + }, + }, + fn: (input, args, handlers) => { + // currently we use variable `theme`, but external theme service would be preferable + const vars = handlers.variables.theme || {}; + return get(vars, args.variable, args.default); + }, +}; From 64c4dcca93379c9d2884d8a3407a1ce0fb4ab080 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Wed, 29 Jul 2020 02:41:49 -0700 Subject: [PATCH 2/8] fixing i18n --- .../expressions/common/expression_functions/specs/theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/expressions/common/expression_functions/specs/theme.ts b/src/plugins/expressions/common/expression_functions/specs/theme.ts index e0aeedc1a0bbf..602c5296ef12f 100644 --- a/src/plugins/expressions/common/expression_functions/specs/theme.ts +++ b/src/plugins/expressions/common/expression_functions/specs/theme.ts @@ -38,7 +38,7 @@ export type ExpressionFunctionTheme = ExpressionFunctionDefinition< export const theme: ExpressionFunctionTheme = { name: 'theme', aliases: [], - help: i18n.translate('expressions.functions.fontHelpText', { + help: i18n.translate('expressions.functions.themeHelpText', { defaultMessage: 'Reads a theme setting.', }), inputTypes: ['null'], From d90c3474459ec5b1521e8ce3806493722feba5c8 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Thu, 30 Jul 2020 06:54:09 -0700 Subject: [PATCH 3/8] fixing tests --- .../specs/tests/font.test.ts | 97 ++++++------------- .../expression_functions/specs/theme.ts | 3 +- 2 files changed, 32 insertions(+), 68 deletions(-) diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts index 62e5fd4e0b668..ca4570e9589ca 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts @@ -24,8 +24,19 @@ import { functionWrapper } from './utils'; describe('font', () => { const fn = functionWrapper(font); + const args = { + align: 'left', + color: null, + family: openSans.value, + italic: false, + lHeight: null, + size: 14, + underline: false, + weight: 'normal', + }; + describe('default output', () => { - const result = fn(null); + const result = fn(null, args); it('returns a style', () => { expect(result).toMatchObject({ @@ -39,7 +50,7 @@ describe('font', () => { describe('args', () => { describe('size', () => { it('sets font size', () => { - const result = fn(null, { size: 20 }); + const result = fn(null, { ...args, size: 20 }); expect(result).toMatchObject({ spec: { fontSize: '20px', @@ -47,21 +58,11 @@ describe('font', () => { }); expect(result.css).toContain('font-size:20px'); }); - - it('defaults to 14px', () => { - const result = fn(null); - expect(result).toMatchObject({ - spec: { - fontSize: '14px', - }, - }); - expect(result.css).toContain('font-size:14px'); - }); }); describe('lHeight', () => { it('sets line height', () => { - const result = fn(null, { lHeight: 30 }); + const result = fn(null, { ...args, lHeight: 30 }); expect(result).toMatchObject({ spec: { lineHeight: '30px', @@ -69,31 +70,19 @@ describe('font', () => { }); expect(result.css).toContain('line-height:30px'); }); - - it('defaults to 1', () => { - const result = fn(null); - expect(result.spec.lineHeight).toBe('1'); - expect(result.css).toContain('line-height:1'); - }); }); describe('family', () => { it('sets font family', () => { - const result = fn(null, { family: 'Optima, serif' }); + const result = fn(null, { ...args, family: 'Optima, serif' }); expect(result.spec.fontFamily).toBe('Optima, serif'); expect(result.css).toContain('font-family:Optima, serif'); }); - - it(`defaults to "${openSans.value}"`, () => { - const result = fn(null); - expect(result.spec.fontFamily).toBe(`"${openSans.value}"`); - expect(result.css).toContain(`font-family:"${openSans.value}"`); - }); }); describe('color', () => { it('sets font color', () => { - const result = fn(null, { color: 'blue' }); + const result = fn(null, { ...args, color: 'blue' }); expect(result.spec.color).toBe('blue'); expect(result.css).toContain('color:blue'); }); @@ -101,51 +90,39 @@ describe('font', () => { describe('weight', () => { it('sets font weight', () => { - let result = fn(null, { weight: 'normal' }); + let result = fn(null, { ...args, weight: 'normal' }); expect(result.spec.fontWeight).toBe('normal'); expect(result.css).toContain('font-weight:normal'); - result = fn(null, { weight: 'bold' }); + result = fn(null, { ...args, weight: 'bold' }); expect(result.spec.fontWeight).toBe('bold'); expect(result.css).toContain('font-weight:bold'); - result = fn(null, { weight: 'bolder' }); + result = fn(null, { ...args, weight: 'bolder' }); expect(result.spec.fontWeight).toBe('bolder'); expect(result.css).toContain('font-weight:bolder'); - result = fn(null, { weight: 'lighter' }); + result = fn(null, { ...args, weight: 'lighter' }); expect(result.spec.fontWeight).toBe('lighter'); expect(result.css).toContain('font-weight:lighter'); - result = fn(null, { weight: '400' }); + result = fn(null, { ...args, weight: '400' }); expect(result.spec.fontWeight).toBe('400'); expect(result.css).toContain('font-weight:400'); }); - it("defaults to 'normal'", () => { - const result = fn(null); - expect(result.spec.fontWeight).toBe('normal'); - expect(result.css).toContain('font-weight:normal'); - }); - it('throws when provided an invalid weight', () => { - expect(() => fn(null, { weight: 'foo' })).toThrow(); + expect(() => fn(null, { ...args, weight: 'foo' })).toThrow(); }); }); describe('underline', () => { it('sets text underline', () => { - let result = fn(null, { underline: true }); + let result = fn(null, { ...args, underline: true }); expect(result.spec.textDecoration).toBe('underline'); expect(result.css).toContain('text-decoration:underline'); - result = fn(null, { underline: false }); - expect(result.spec.textDecoration).toBe('none'); - expect(result.css).toContain('text-decoration:none'); - }); - - it('defaults to false', () => { - const result = fn(null); + result = fn(null, { ...args, underline: false }); expect(result.spec.textDecoration).toBe('none'); expect(result.css).toContain('text-decoration:none'); }); @@ -153,17 +130,11 @@ describe('font', () => { describe('italic', () => { it('sets italic', () => { - let result = fn(null, { italic: true }); + let result = fn(null, { ...args, italic: true }); expect(result.spec.fontStyle).toBe('italic'); expect(result.css).toContain('font-style:italic'); - result = fn(null, { italic: false }); - expect(result.spec.fontStyle).toBe('normal'); - expect(result.css).toContain('font-style:normal'); - }); - - it('defaults to false', () => { - const result = fn(null); + result = fn(null, { ...args, italic: false }); expect(result.spec.fontStyle).toBe('normal'); expect(result.css).toContain('font-style:normal'); }); @@ -171,31 +142,25 @@ describe('font', () => { describe('align', () => { it('sets text alignment', () => { - let result = fn(null, { align: 'left' }); + let result = fn(null, { ...args, align: 'left' }); expect(result.spec.textAlign).toBe('left'); expect(result.css).toContain('text-align:left'); - result = fn(null, { align: 'center' }); + result = fn(null, { ...args, align: 'center' }); expect(result.spec.textAlign).toBe('center'); expect(result.css).toContain('text-align:center'); - result = fn(null, { align: 'right' }); + result = fn(null, { ...args, align: 'right' }); expect(result.spec.textAlign).toBe('right'); expect(result.css).toContain('text-align:right'); - result = fn(null, { align: 'justify' }); + result = fn(null, { ...args, align: 'justify' }); expect(result.spec.textAlign).toBe('justify'); expect(result.css).toContain('text-align:justify'); }); - it(`defaults to 'left'`, () => { - const result = fn(null); - expect(result.spec.textAlign).toBe('left'); - expect(result.css).toContain('text-align:left'); - }); - it('throws when provided an invalid alignment', () => { - expect(() => fn(null, { align: 'foo' })).toThrow(); + expect(() => fn(null, { ...args, align: 'foo' })).toThrow(); }); }); }); diff --git a/src/plugins/expressions/common/expression_functions/specs/theme.ts b/src/plugins/expressions/common/expression_functions/specs/theme.ts index 602c5296ef12f..8b1b2a1d7bd06 100644 --- a/src/plugins/expressions/common/expression_functions/specs/theme.ts +++ b/src/plugins/expressions/common/expression_functions/specs/theme.ts @@ -52,10 +52,9 @@ export const theme: ExpressionFunctionTheme = { types: ['string'], }, default: { - help: i18n.translate('expressions.functions.font.args.defaultHelpText', { + help: i18n.translate('expressions.functions.theme.args.defaultHelpText', { defaultMessage: 'default value in case theming info is not available.', }), - types: ['string', 'number'], }, }, fn: (input, args, handlers) => { From 18acd74f6a292e59cb722fefce0c2c4d9cb4c829 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Mon, 3 Aug 2020 14:06:45 +0200 Subject: [PATCH 4/8] Update src/plugins/expressions/common/expression_functions/specs/theme.ts Co-authored-by: Luke Elmers --- .../expressions/common/expression_functions/specs/theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/expressions/common/expression_functions/specs/theme.ts b/src/plugins/expressions/common/expression_functions/specs/theme.ts index 8b1b2a1d7bd06..1db25b79076c5 100644 --- a/src/plugins/expressions/common/expression_functions/specs/theme.ts +++ b/src/plugins/expressions/common/expression_functions/specs/theme.ts @@ -46,7 +46,7 @@ export const theme: ExpressionFunctionTheme = { variable: { aliases: ['_'], help: i18n.translate('expressions.functions.theme.args.variableHelpText', { - defaultMessage: 'theme variable to read.', + defaultMessage: 'Name of the theme variable to read.', }), required: true, types: ['string'], From 2658d66f726cc9135a700b991a968d67150a8d0b Mon Sep 17 00:00:00 2001 From: ppisljar Date: Mon, 3 Aug 2020 05:13:22 -0700 Subject: [PATCH 5/8] adding test --- .../specs/tests/theme.test.ts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts new file mode 100644 index 0000000000000..93fd64e3a3130 --- /dev/null +++ b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { functionWrapper } from './utils'; +import { theme } from '../theme'; +import { ExecutionContext } from '../../../execution/types'; +import { KibanaContext } from '../../../expression_types'; + +describe('expression_functions', () => { + describe('theme', () => { + const fn = functionWrapper(theme); + let context: ExecutionContext; + + let themeProps; + + beforeEach(() => { + themeProps = { + font: { + family: 'Arial', + size: 14, + }, + }; + + context = { + getInitialInput: () => input, + types: {}, + variables: { theme: themeProps }, + abortSignal: {} as any, + inspectorAdapters: {} as any, + }; + }); + + it('returns the selected variable', () => { + const actual = fn(null, { variable: 'font.family' }, context); + expect(actual).toEqual('Arial'); + }); + + it('returns undefined if variable does not exist', () => { + const actual = fn(null, { variable: 'font.weight' }, context); + expect(actual).toEqual(undefined); + }); + + it('returns default if variable does not exist and default is provided', () => { + const actual = fn(null, { variable: 'font.weight', default: 'normal' }, context); + expect(actual).toEqual('normal'); + }); + }); +}); From 9acb737857c339fbd8a2d57c2656e50c9301b30c Mon Sep 17 00:00:00 2001 From: ppisljar Date: Thu, 6 Aug 2020 06:15:29 -0700 Subject: [PATCH 6/8] updating --- src/plugins/expressions/common/expression_functions/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/expressions/common/expression_functions/types.ts b/src/plugins/expressions/common/expression_functions/types.ts index 5979bcffb3175..d58d872aff722 100644 --- a/src/plugins/expressions/common/expression_functions/types.ts +++ b/src/plugins/expressions/common/expression_functions/types.ts @@ -28,6 +28,7 @@ import { ExpressionFunctionKibana, ExpressionFunctionVarSet, ExpressionFunctionVar, + ExpressionFunctionTheme, } from './specs'; /** @@ -122,4 +123,5 @@ export interface ExpressionFunctionDefinitions { kibana: ExpressionFunctionKibana; var_set: ExpressionFunctionVarSet; var: ExpressionFunctionVar; + theme: ExpressionFunctionTheme; } From 6fd6675972538c297f14dace860941ad61d91995 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Thu, 6 Aug 2020 08:17:07 -0700 Subject: [PATCH 7/8] fixing test --- .../common/expression_functions/specs/tests/theme.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts index 93fd64e3a3130..263409f0caca2 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts @@ -20,7 +20,6 @@ import { functionWrapper } from './utils'; import { theme } from '../theme'; import { ExecutionContext } from '../../../execution/types'; -import { KibanaContext } from '../../../expression_types'; describe('expression_functions', () => { describe('theme', () => { @@ -38,7 +37,7 @@ describe('expression_functions', () => { }; context = { - getInitialInput: () => input, + getInitialInput: () => {}, types: {}, variables: { theme: themeProps }, abortSignal: {} as any, From 2265a21116cc10df4768744e957ed12832d1a792 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Thu, 6 Aug 2020 08:17:38 -0700 Subject: [PATCH 8/8] updating type --- .../expressions/common/expression_functions/specs/theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/expressions/common/expression_functions/specs/theme.ts b/src/plugins/expressions/common/expression_functions/specs/theme.ts index 1db25b79076c5..e27b01674cb5e 100644 --- a/src/plugins/expressions/common/expression_functions/specs/theme.ts +++ b/src/plugins/expressions/common/expression_functions/specs/theme.ts @@ -26,7 +26,7 @@ interface Arguments { default: string | number | boolean; } -type Output = string | number | boolean | undefined; +type Output = any; export type ExpressionFunctionTheme = ExpressionFunctionDefinition< 'theme',