From 1273c6060af651d3b9e4db5b829b895e34adeaa5 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Wed, 18 Jan 2023 14:01:32 +0100 Subject: [PATCH 1/7] feat(options): hideSearch/placeholder/cache invalidate --- src/plugins/controls/common/options_list/types.ts | 2 ++ .../options_list/components/options_list.scss | 6 ++++++ .../components/options_list_control.tsx | 4 +++- .../components/options_list_popover.tsx | 4 +++- .../embeddable/options_list_embeddable.tsx | 14 +++++++++++--- .../services/options_list/options_list_service.ts | 4 ++++ .../controls/public/services/options_list/types.ts | 2 ++ .../embeddable/public/lib/containers/container.ts | 6 ++++-- .../public/lib/embeddables/embeddable.tsx | 4 +++- .../public/lib/embeddables/i_embeddable.ts | 6 ++++-- 10 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/plugins/controls/common/options_list/types.ts b/src/plugins/controls/common/options_list/types.ts index 8835c7f5767f6..4fe05ed3f938d 100644 --- a/src/plugins/controls/common/options_list/types.ts +++ b/src/plugins/controls/common/options_list/types.ts @@ -23,7 +23,9 @@ export interface OptionsListEmbeddableInput extends DataControlInput { hideExclude?: boolean; hideExists?: boolean; hideSort?: boolean; + hideSearch?: boolean; exclude?: boolean; + placeholder?: string; } export type OptionsListField = FieldSpec & { diff --git a/src/plugins/controls/public/options_list/components/options_list.scss b/src/plugins/controls/public/options_list/components/options_list.scss index e88208ee4c623..fbd93dba2f671 100644 --- a/src/plugins/controls/public/options_list/components/options_list.scss +++ b/src/plugins/controls/public/options_list/components/options_list.scss @@ -1,3 +1,5 @@ +@import '../../control_group/control_group.scss'; + .optionsList__anchorOverride { display:block; } @@ -86,3 +88,7 @@ .optionsList--sortPopover { width: $euiSizeXL * 7; } + +.optionsList__popover { + min-width: $controlMinWidth; +} diff --git a/src/plugins/controls/public/options_list/components/options_list_control.tsx b/src/plugins/controls/public/options_list/components/options_list_control.tsx index 3035eada20caf..98f545718efc6 100644 --- a/src/plugins/controls/public/options_list/components/options_list_control.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_control.tsx @@ -47,6 +47,8 @@ export const OptionsListControl = ({ typeaheadSubject }: { typeaheadSubject: Sub const exclude = select((state) => state.explicitInput.exclude); const id = select((state) => state.explicitInput.id); + const placeholder = select((state) => state.explicitInput.placeholder); + const loading = select((state) => state.output.loading); // debounce loading state so loading doesn't flash when user types @@ -128,7 +130,7 @@ export const OptionsListControl = ({ typeaheadSubject }: { typeaheadSubject: Sub > {hasSelections || existsSelected ? selectionDisplayNode - : OptionsListStrings.control.getPlaceholder()} + : placeholder ?? OptionsListStrings.control.getPlaceholder()} ); diff --git a/src/plugins/controls/public/options_list/components/options_list_popover.tsx b/src/plugins/controls/public/options_list/components/options_list_popover.tsx index 70353524068cd..bc7cc9cfc0eb8 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover.tsx @@ -43,6 +43,7 @@ export const OptionsListPopover = ({ const field = select((state) => state.componentState.field); const hideExclude = select((state) => state.explicitInput.hideExclude); + const hideSearch = select((state) => state.explicitInput.hideSearch); const fieldName = select((state) => state.explicitInput.fieldName); const title = select((state) => state.explicitInput.title); const id = select((state) => state.explicitInput.id); @@ -52,12 +53,13 @@ export const OptionsListPopover = ({ return (
300 ? width : undefined }} data-test-subj={`optionsList-control-popover`} aria-label={OptionsListStrings.popover.getAriaLabel(fieldName)} > {title} - {field?.type !== 'boolean' && ( + {field?.type !== 'boolean' && !hideSearch && ( + this.reduxEmbeddableTools.getState().explicitInput.placeholder ?? + OptionsListStrings.control.getPlaceholder(); + private initialize = async () => { const { selectedOptions: initialSelectedOptions } = this.getInput(); if (!initialSelectedOptions) this.setInitializationFinished(); @@ -268,7 +273,7 @@ export class OptionsListEmbeddable extends Embeddable { + private runOptionsListQuery = async (clearCache: boolean = false) => { const { dispatch, getState, @@ -307,6 +312,9 @@ export class OptionsListEmbeddable extends Embeddable { - this.runOptionsListQuery(); + reload = (clearCache: boolean = false) => { + this.runOptionsListQuery(clearCache); }; public destroy = () => { diff --git a/src/plugins/controls/public/services/options_list/options_list_service.ts b/src/plugins/controls/public/services/options_list/options_list_service.ts index ab8e67666140b..888d2e2efb837 100644 --- a/src/plugins/controls/public/services/options_list/options_list_service.ts +++ b/src/plugins/controls/public/services/options_list/options_list_service.ts @@ -104,6 +104,10 @@ class OptionsListService implements ControlsOptionsListService { return { rejected: true } as OptionsListResponse; } }; + + public clearOptionsListCache = () => { + this.cachedOptionsListRequest.cache = new memoize.Cache(); + }; } export interface OptionsListServiceRequiredServices { diff --git a/src/plugins/controls/public/services/options_list/types.ts b/src/plugins/controls/public/services/options_list/types.ts index d493207df591c..569042b136419 100644 --- a/src/plugins/controls/public/services/options_list/types.ts +++ b/src/plugins/controls/public/services/options_list/types.ts @@ -13,4 +13,6 @@ export interface ControlsOptionsListService { request: OptionsListRequest, abortSignal: AbortSignal ) => Promise; + + clearOptionsListCache: () => void; } diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts index d04350ccf9e59..ecd481094817b 100644 --- a/src/plugins/embeddable/public/lib/containers/container.ts +++ b/src/plugins/embeddable/public/lib/containers/container.ts @@ -156,8 +156,10 @@ export abstract class Container< this.updateInput(panels as Partial); } - public reload() { - Object.values(this.children).forEach((child) => child.reload()); + public reload(clearCache: boolean = false) { + Object.values(this.children).forEach((child) => + child instanceof ErrorEmbeddable ? child.reload() : child.reload(clearCache) + ); } public async addNewEmbeddable< diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx index d1871ce2ffc98..93e891818d31f 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx @@ -119,6 +119,8 @@ export abstract class Embeddable< * * In case if input data did change and reload is requested input$ and output$ would still emit before `reload` is called * + * @param clearCache can be passed in case there is cache that needs to cleared before reloading the data + * * The order would be as follows: * input$ * output$ @@ -126,7 +128,7 @@ export abstract class Embeddable< * ---- * updated$ */ - public abstract reload(): void; + public abstract reload(clearCache?: boolean): void; /** * Merges input$ and output$ streams and debounces emit till next macro-task. diff --git a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts index 2370b62743466..6530278904622 100644 --- a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts +++ b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts @@ -189,9 +189,11 @@ export interface IEmbeddable< /** * Reload the embeddable so output and rendering is up to date. Especially relevant - * if the embeddable takes relative time as input (e.g. now to now-15) + * if the embeddable takes relative time as input (e.g. now to now-15). + * + * @param clearCache can be passed in case there is a need to clear any cache by the embeddable */ - reload(): void; + reload(clearCache?: boolean): void; /** * An embeddable can return inspector adapters if it wants the inspector to be From c9400bad795b39d107dfe9a4591892b515a6d6fc Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Wed, 18 Jan 2023 14:37:40 +0100 Subject: [PATCH 2/7] fix type issues --- .../options_list/embeddable/options_list_embeddable.tsx | 8 +++----- .../public/services/options_list/options_list.story.ts | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx index 756e039b50079..a2a374fa98735 100644 --- a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx +++ b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx @@ -273,7 +273,7 @@ export class OptionsListEmbeddable extends Embeddable { + private runOptionsListQuery = async () => { const { dispatch, getState, @@ -312,9 +312,6 @@ export class OptionsListEmbeddable extends Embeddable { - this.runOptionsListQuery(clearCache); + if (clearCache) this.optionsListService.clearOptionsListCache(); + this.runOptionsListQuery(); }; public destroy = () => { diff --git a/src/plugins/controls/public/services/options_list/options_list.story.ts b/src/plugins/controls/public/services/options_list/options_list.story.ts index 62686feee7495..c641e9ee8834a 100644 --- a/src/plugins/controls/public/services/options_list/options_list.story.ts +++ b/src/plugins/controls/public/services/options_list/options_list.story.ts @@ -26,6 +26,8 @@ let optionsListRequestMethod = async (request: OptionsListRequest, abortSignal: ) ); +const clearOptionsListCacheMock = () => {}; + export const replaceOptionsListMethod = ( newMethod: (request: OptionsListRequest, abortSignal: AbortSignal) => Promise ) => (optionsListRequestMethod = newMethod); @@ -33,5 +35,6 @@ export const replaceOptionsListMethod = ( export const optionsListServiceFactory: OptionsListServiceFactory = () => { return { runOptionsListRequest: optionsListRequestMethod, + clearOptionsListCache: clearOptionsListCacheMock, }; }; From 9221eaea6191f1c1dd5ae6f8508ee1bd5bef7240 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Sun, 22 Jan 2023 19:09:50 +0100 Subject: [PATCH 3/7] Reset embedable interface + reload clears cache --- .../embeddable/options_list_embeddable.tsx | 10 +++------- .../embeddable/public/lib/containers/container.ts | 6 ++---- .../embeddable/public/lib/embeddables/embeddable.tsx | 4 +--- .../embeddable/public/lib/embeddables/i_embeddable.ts | 4 +--- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx index a2a374fa98735..8d8fb505b5cdd 100644 --- a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx +++ b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx @@ -41,7 +41,6 @@ import { OptionsListControl } from '../components/options_list_control'; import { ControlsDataViewsService } from '../../services/data_views/types'; import { ControlsOptionsListService } from '../../services/options_list/types'; import { OptionsListField } from '../../../common/options_list/types'; -import { OptionsListStrings } from '../components/options_list_strings'; const diffDataFetchProps = ( last?: OptionsListDataFetchProps, @@ -113,10 +112,6 @@ export class OptionsListEmbeddable extends Embeddable - this.reduxEmbeddableTools.getState().explicitInput.placeholder ?? - OptionsListStrings.control.getPlaceholder(); - private initialize = async () => { const { selectedOptions: initialSelectedOptions } = this.getInput(); if (!initialSelectedOptions) this.setInitializationFinished(); @@ -410,8 +405,9 @@ export class OptionsListEmbeddable extends Embeddable { - if (clearCache) this.optionsListService.clearOptionsListCache(); + reload = () => { + // clear cache when reload is requested + this.optionsListService.clearOptionsListCache(); this.runOptionsListQuery(); }; diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts index ecd481094817b..d04350ccf9e59 100644 --- a/src/plugins/embeddable/public/lib/containers/container.ts +++ b/src/plugins/embeddable/public/lib/containers/container.ts @@ -156,10 +156,8 @@ export abstract class Container< this.updateInput(panels as Partial); } - public reload(clearCache: boolean = false) { - Object.values(this.children).forEach((child) => - child instanceof ErrorEmbeddable ? child.reload() : child.reload(clearCache) - ); + public reload() { + Object.values(this.children).forEach((child) => child.reload()); } public async addNewEmbeddable< diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx index 93e891818d31f..d1871ce2ffc98 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable.tsx @@ -119,8 +119,6 @@ export abstract class Embeddable< * * In case if input data did change and reload is requested input$ and output$ would still emit before `reload` is called * - * @param clearCache can be passed in case there is cache that needs to cleared before reloading the data - * * The order would be as follows: * input$ * output$ @@ -128,7 +126,7 @@ export abstract class Embeddable< * ---- * updated$ */ - public abstract reload(clearCache?: boolean): void; + public abstract reload(): void; /** * Merges input$ and output$ streams and debounces emit till next macro-task. diff --git a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts index 6530278904622..3072e627be1f6 100644 --- a/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts +++ b/src/plugins/embeddable/public/lib/embeddables/i_embeddable.ts @@ -190,10 +190,8 @@ export interface IEmbeddable< /** * Reload the embeddable so output and rendering is up to date. Especially relevant * if the embeddable takes relative time as input (e.g. now to now-15). - * - * @param clearCache can be passed in case there is a need to clear any cache by the embeddable */ - reload(clearCache?: boolean): void; + reload(): void; /** * An embeddable can return inspector adapters if it wants the inspector to be From 4474eabbddd7a4fb0623aa03c48b45f6018f299b Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Sun, 22 Jan 2023 19:47:17 +0100 Subject: [PATCH 4/7] rename hideSearch to hideActionBar --- src/plugins/controls/common/options_list/types.ts | 2 +- .../public/options_list/components/options_list.scss | 6 ------ .../options_list/components/options_list_popover.tsx | 7 +++---- .../embeddable/public/lib/embeddables/i_embeddable.ts | 2 +- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/plugins/controls/common/options_list/types.ts b/src/plugins/controls/common/options_list/types.ts index 4fe05ed3f938d..1c9555bdc8d90 100644 --- a/src/plugins/controls/common/options_list/types.ts +++ b/src/plugins/controls/common/options_list/types.ts @@ -23,7 +23,7 @@ export interface OptionsListEmbeddableInput extends DataControlInput { hideExclude?: boolean; hideExists?: boolean; hideSort?: boolean; - hideSearch?: boolean; + hideActionBar?: boolean; exclude?: boolean; placeholder?: string; } diff --git a/src/plugins/controls/public/options_list/components/options_list.scss b/src/plugins/controls/public/options_list/components/options_list.scss index fbd93dba2f671..e88208ee4c623 100644 --- a/src/plugins/controls/public/options_list/components/options_list.scss +++ b/src/plugins/controls/public/options_list/components/options_list.scss @@ -1,5 +1,3 @@ -@import '../../control_group/control_group.scss'; - .optionsList__anchorOverride { display:block; } @@ -88,7 +86,3 @@ .optionsList--sortPopover { width: $euiSizeXL * 7; } - -.optionsList__popover { - min-width: $controlMinWidth; -} diff --git a/src/plugins/controls/public/options_list/components/options_list_popover.tsx b/src/plugins/controls/public/options_list/components/options_list_popover.tsx index bc7cc9cfc0eb8..66600e56a79a1 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover.tsx @@ -43,7 +43,7 @@ export const OptionsListPopover = ({ const field = select((state) => state.componentState.field); const hideExclude = select((state) => state.explicitInput.hideExclude); - const hideSearch = select((state) => state.explicitInput.hideSearch); + const hideActionBar = select((state) => state.explicitInput.hideActionBar); const fieldName = select((state) => state.explicitInput.fieldName); const title = select((state) => state.explicitInput.title); const id = select((state) => state.explicitInput.id); @@ -53,13 +53,12 @@ export const OptionsListPopover = ({ return (
300 ? width : undefined }} + style={{ width }} data-test-subj={`optionsList-control-popover`} aria-label={OptionsListStrings.popover.getAriaLabel(fieldName)} > {title} - {field?.type !== 'boolean' && !hideSearch && ( + {field?.type !== 'boolean' && !hideActionBar && ( Date: Sun, 22 Jan 2023 19:56:53 +0100 Subject: [PATCH 5/7] fix width --- .../public/options_list/components/options_list_popover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/controls/public/options_list/components/options_list_popover.tsx b/src/plugins/controls/public/options_list/components/options_list_popover.tsx index 66600e56a79a1..b53014260edfb 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover.tsx @@ -53,7 +53,7 @@ export const OptionsListPopover = ({ return (
From 88ddd8ef36729a9ac15dd89a0989ca195c9eca37 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Sun, 22 Jan 2023 20:11:43 +0100 Subject: [PATCH 6/7] fix min width of popover --- .../public/options_list/components/options_list_popover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/controls/public/options_list/components/options_list_popover.tsx b/src/plugins/controls/public/options_list/components/options_list_popover.tsx index b53014260edfb..b5562c43f3be2 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover.tsx @@ -53,7 +53,7 @@ export const OptionsListPopover = ({ return (
From 5e3a9647dd0408d5dcbf7b9ba41efb0cdad2e372 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Sun, 22 Jan 2023 22:48:24 +0100 Subject: [PATCH 7/7] refactor: test correction --- .../options_list/components/options_list_popover.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/controls/public/options_list/components/options_list_popover.test.tsx b/src/plugins/controls/public/options_list/components/options_list_popover.test.tsx index acb5d24d80659..a8504aba372c8 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover.test.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover.test.tsx @@ -58,7 +58,7 @@ describe('Options list popover', () => { test('available options list width responds to container size', async () => { let popover = await mountComponent({ popoverProps: { width: 301 } }); let popoverDiv = findTestSubject(popover, 'optionsList-control-popover'); - expect(popoverDiv.getDOMNode().getAttribute('style')).toBe('width: 301px;'); + expect(popoverDiv.getDOMNode().getAttribute('style')).toBe('width: 301px; min-width: 300px;'); // the div cannot be smaller than 301 pixels wide popover = await mountComponent({ popoverProps: { width: 300 } });