From de4eaf9ae70cc225db8bb92a43661b8cfbd4ab85 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Mon, 8 Jun 2020 15:31:14 +0200 Subject: [PATCH 1/9] fix #66185 (#66186) --- ...-data-public.indexpattern._constructor_.md | 4 ++-- .../index_patterns/_pattern_cache.ts | 2 +- .../index_patterns/index_pattern.test.ts | 3 +++ .../index_patterns/index_pattern.ts | 19 +++++++++++-------- src/plugins/data/public/public.api.md | 3 ++- .../public/lib/resolve_saved_objects.ts | 5 +++-- .../apps/management/_import_objects.js | 1 - 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md index 4159247bb7c32..6256709e2ee36 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md @@ -9,7 +9,7 @@ Constructs a new instance of the `IndexPattern` class Signature: ```typescript -constructor(id: string | undefined, getConfig: any, savedObjectsClient: SavedObjectsClientContract, apiClient: IIndexPatternsApiClient, patternCache: any); +constructor(id: string | undefined, getConfig: any, savedObjectsClient: SavedObjectsClientContract, apiClient: IIndexPatternsApiClient, patternCache: PatternCache); ``` ## Parameters @@ -20,5 +20,5 @@ constructor(id: string | undefined, getConfig: any, savedObjectsClient: SavedObj | getConfig | any | | | savedObjectsClient | SavedObjectsClientContract | | | apiClient | IIndexPatternsApiClient | | -| patternCache | any | | +| patternCache | PatternCache | | diff --git a/src/plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts b/src/plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts index eb6c69b414316..a3653bb529fa3 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/_pattern_cache.ts @@ -19,7 +19,7 @@ import { IndexPattern } from './index_pattern'; -interface PatternCache { +export interface PatternCache { get: (id: string) => IndexPattern; set: (id: string, value: IndexPattern) => IndexPattern; clear: (id: string) => void; diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts index e4058007e0a57..84135bb5d1e2b 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.test.ts @@ -85,6 +85,9 @@ const savedObjectsClient = { const patternCache = { clear: jest.fn(), + get: jest.fn(), + set: jest.fn(), + clearAll: jest.fn(), }; const config = { diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts index 3d54009d0fdca..84ea12a1f684f 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -44,6 +44,7 @@ import { flattenHitWrapper } from './flatten_hit'; import { IIndexPatternsApiClient } from './index_patterns_api_client'; import { getNotifications, getFieldFormats } from '../../services'; import { TypeMeta } from './types'; +import { PatternCache } from './_pattern_cache'; const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3; const type = 'index-pattern'; @@ -65,12 +66,13 @@ export class IndexPattern implements IIndexPattern { private version: string | undefined; private savedObjectsClient: SavedObjectsClientContract; - private patternCache: any; + private patternCache: PatternCache; private getConfig: any; private sourceFilters?: []; private originalBody: { [key: string]: any } = {}; public fieldsFetcher: any; // probably want to factor out any direct usage and change to private private shortDotsEnable: boolean = false; + private apiClient: IIndexPatternsApiClient; private mapping: MappingObject = expandShorthand({ title: ES_FIELD_TYPES.TEXT, @@ -99,7 +101,7 @@ export class IndexPattern implements IIndexPattern { getConfig: any, savedObjectsClient: SavedObjectsClientContract, apiClient: IIndexPatternsApiClient, - patternCache: any + patternCache: PatternCache ) { this.id = id; this.savedObjectsClient = savedObjectsClient; @@ -117,6 +119,7 @@ export class IndexPattern implements IIndexPattern { }); this.fields = this.createFieldList(this, [], this.shortDotsEnable); + this.apiClient = apiClient; this.fieldsFetcher = createFieldsFetcher( this, apiClient, @@ -396,8 +399,8 @@ export class IndexPattern implements IIndexPattern { duplicateId, this.getConfig, this.savedObjectsClient, - this.patternCache, - this.fieldsFetcher + this.apiClient, + this.patternCache ); await duplicatePattern.destroy(); } @@ -445,8 +448,8 @@ export class IndexPattern implements IIndexPattern { this.id, this.getConfig, this.savedObjectsClient, - this.patternCache, - this.fieldsFetcher + this.apiClient, + this.patternCache ); return samePattern.init().then(() => { // What keys changed from now and what the server returned @@ -489,7 +492,7 @@ export class IndexPattern implements IIndexPattern { this.version = samePattern.version; // Clear cache - this.patternCache.clear(this.id); + this.patternCache.clear(this.id!); // Try the save again return this.save(saveAttempts); @@ -545,8 +548,8 @@ export class IndexPattern implements IIndexPattern { } destroy() { - this.patternCache.clear(this.id); if (this.id) { + this.patternCache.clear(this.id); return this.savedObjectsClient.delete(type, this.id); } } diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index dcdb528ac8b7d..e6f6ba0c1bd12 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -842,7 +842,8 @@ export type IMetricAggType = MetricAggType; // @public (undocumented) export class IndexPattern implements IIndexPattern { // Warning: (ae-forgotten-export) The symbol "IIndexPatternsApiClient" needs to be exported by the entry point index.d.ts - constructor(id: string | undefined, getConfig: any, savedObjectsClient: SavedObjectsClientContract, apiClient: IIndexPatternsApiClient, patternCache: any); + // Warning: (ae-forgotten-export) The symbol "PatternCache" needs to be exported by the entry point index.d.ts + constructor(id: string | undefined, getConfig: any, savedObjectsClient: SavedObjectsClientContract, apiClient: IIndexPatternsApiClient, patternCache: PatternCache); // (undocumented) [key: string]: any; // (undocumented) diff --git a/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts index 952e9628d2846..79b8c33b84cfe 100644 --- a/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts +++ b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts @@ -27,6 +27,7 @@ import { IIndexPattern, injectSearchSourceReferences, } from '../../../data/public'; +import { FailedImport } from './process_import_response'; type SavedObjectsRawDoc = Record; @@ -277,7 +278,7 @@ export async function resolveSavedObjects( // Keep track of how many we actually import because the user // can cancel an override let importedObjectCount = 0; - const failedImports: any[] = []; + const failedImports: FailedImport[] = []; // Start with the index patterns since everything is dependent on them await awaitEachItemInParallel(docTypes.indexPatterns, async (indexPatternDoc) => { try { @@ -291,7 +292,7 @@ export async function resolveSavedObjects( importedObjectCount++; } } catch (error) { - failedImports.push({ indexPatternDoc, error }); + failedImports.push({ obj: indexPatternDoc as any, error }); } }); diff --git a/test/functional/apps/management/_import_objects.js b/test/functional/apps/management/_import_objects.js index 6b40837808387..6306d11eadb65 100644 --- a/test/functional/apps/management/_import_objects.js +++ b/test/functional/apps/management/_import_objects.js @@ -356,7 +356,6 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.importFile( path.join(__dirname, 'exports', '_import_objects_with_index_patterns.json') ); - await PageObjects.settings.checkImportFailedWarning(); await PageObjects.settings.clickImportDone(); const objects = await PageObjects.settings.getSavedObjectsInTable(); From c29fcbb46bfde68b437df790f011c3d745c8585c Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Mon, 8 Jun 2020 09:45:06 -0400 Subject: [PATCH 2/9] Bump decompress package version (#68386) --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f4d5409f755ce..e47af2c6fe284 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11041,9 +11041,9 @@ decompress-unzip@^4.0.1: yauzl "^2.4.2" decompress@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" + integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== dependencies: decompress-tar "^4.0.0" decompress-tarbz2 "^4.0.0" From f89e911f64a40744b8d88e3221ee8403a72c9e54 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Mon, 8 Jun 2020 09:47:51 -0400 Subject: [PATCH 3/9] Kibana developer examples landing page (#67049) * Kibana developer examples * Batch explorer tests should be run in examples config * Fix tests * add codeowner for new developer examples plugin & readme cleanup * Try to frame embeddable wording based on what a developer's goals are. * Add noopener noreferer, fix bad merge * Remove bfetch.png Co-authored-by: Elastic Machine --- .github/CODEOWNERS | 1 + examples/alerting_example/kibana.json | 2 +- examples/alerting_example/public/plugin.tsx | 22 +++- examples/bfetch_explorer/kibana.json | 2 +- examples/bfetch_explorer/public/plugin.tsx | 25 +++- examples/developer_examples/README.md | 36 ++++++ examples/developer_examples/kibana.json | 9 ++ examples/developer_examples/navigation.png | Bin 0 -> 28522 bytes examples/developer_examples/public/app.tsx | 117 ++++++++++++++++++ .../developer_examples}/public/index.ts | 6 +- examples/developer_examples/public/plugin.ts | 68 ++++++++++ .../developer_examples/public/types.ts | 16 ++- examples/developer_examples/tsconfig.json | 15 +++ examples/embeddable_explorer/kibana.json | 2 +- .../public/embeddables.png | Bin 0 -> 88399 bytes .../embeddable_explorer/public/plugin.tsx | 31 ++++- examples/search_explorer/kibana.json | 2 +- examples/search_explorer/public/plugin.tsx | 31 ++++- .../state_containers_examples/kibana.json | 2 +- .../public/plugin.ts | 68 +++++++++- .../public/with_data_services/application.tsx | 2 +- .../with_data_services/components/app.tsx | 9 +- examples/ui_actions_explorer/kibana.json | 2 +- .../ui_actions_explorer/public/plugin.tsx | 28 ++++- .../ui_actions_explorer/public/ui_actions.png | Bin 0 -> 108883 bytes .../url_generators_examples/public/plugin.tsx | 3 +- examples/url_generators_explorer/kibana.json | 2 +- .../url_generators_explorer/public/plugin.tsx | 35 +++++- .../bfetch_explorer/batched_function.ts | 5 +- .../bfetch_explorer/index.ts | 7 +- test/examples/config.js | 1 + test/examples/embeddables/index.ts | 4 +- test/examples/search/index.ts | 4 +- test/examples/state_sync/index.ts | 2 - test/examples/state_sync/todo_app.ts | 7 +- test/examples/ui_actions/index.ts | 4 +- test/plugin_functional/config.js | 1 - .../kbn_tp_bfetch_explorer/kibana.json | 10 -- .../kbn_tp_bfetch_explorer/package.json | 17 --- .../kbn_tp_bfetch_explorer/tsconfig.json | 21 ---- 40 files changed, 510 insertions(+), 109 deletions(-) create mode 100644 examples/developer_examples/README.md create mode 100644 examples/developer_examples/kibana.json create mode 100644 examples/developer_examples/navigation.png create mode 100644 examples/developer_examples/public/app.tsx rename {test/plugin_functional/plugins/kbn_tp_bfetch_explorer => examples/developer_examples}/public/index.ts (82%) create mode 100644 examples/developer_examples/public/plugin.ts rename test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts => examples/developer_examples/public/types.ts (68%) create mode 100644 examples/developer_examples/tsconfig.json create mode 100644 examples/embeddable_explorer/public/embeddables.png create mode 100644 examples/ui_actions_explorer/public/ui_actions.png rename test/{plugin_functional/test_suites => examples}/bfetch_explorer/batched_function.ts (93%) rename test/{plugin_functional/test_suites => examples}/bfetch_explorer/index.ts (83%) delete mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json delete mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json delete mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 48d70910f9bf1..472d29ed29413 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -34,6 +34,7 @@ /src/legacy/core_plugins/kibana/public/home/np_ready/ @elastic/kibana-core-ui # App Architecture +/examples/developer_examples/ @elastic/kibana-app-arch /examples/url_generators_examples/ @elastic/kibana-app-arch /examples/url_generators_explorer/ @elastic/kibana-app-arch /packages/kbn-interpreter/ @elastic/kibana-app-arch diff --git a/examples/alerting_example/kibana.json b/examples/alerting_example/kibana.json index 2b6389649cef9..6c04218ca45e2 100644 --- a/examples/alerting_example/kibana.json +++ b/examples/alerting_example/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["triggers_actions_ui", "charts", "data", "alerts", "actions"], + "requiredPlugins": ["triggers_actions_ui", "charts", "data", "alerts", "actions", "developerExamples"], "optionalPlugins": [] } diff --git a/examples/alerting_example/public/plugin.tsx b/examples/alerting_example/public/plugin.tsx index 524ff18bd434e..f0635a1071f64 100644 --- a/examples/alerting_example/public/plugin.tsx +++ b/examples/alerting_example/public/plugin.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public'; +import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '../../../src/core/public'; import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerts/public'; import { ChartsPluginStart } from '../../../src/plugins/charts/public'; import { TriggersAndActionsUIPublicPluginSetup } from '../../../x-pack/plugins/triggers_actions_ui/public'; @@ -25,6 +25,7 @@ import { DataPublicPluginStart } from '../../../src/plugins/data/public'; import { getAlertType as getAlwaysFiringAlertType } from './alert_types/always_firing'; import { getAlertType as getPeopleInSpaceAlertType } from './alert_types/astros'; import { registerNavigation } from './alert_types'; +import { DeveloperExamplesSetup } from '../../developer_examples/public'; export type Setup = void; export type Start = void; @@ -32,6 +33,7 @@ export type Start = void; export interface AlertingExamplePublicSetupDeps { alerts: AlertingSetup; triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; + developerExamples: DeveloperExamplesSetup; } export interface AlertingExamplePublicStartDeps { @@ -44,11 +46,12 @@ export interface AlertingExamplePublicStartDeps { export class AlertingExamplePlugin implements Plugin { public setup( core: CoreSetup, - { alerts, triggers_actions_ui }: AlertingExamplePublicSetupDeps + { alerts, triggers_actions_ui, developerExamples }: AlertingExamplePublicSetupDeps ) { core.application.register({ id: 'AlertingExample', title: 'Alerting Example', + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const [coreStart, depsStart] = await core.getStartServices(); const { renderApp } = await import('./application'); @@ -60,6 +63,21 @@ export class AlertingExamplePlugin implements Plugin Promise<{ num: number }>; @@ -27,6 +28,7 @@ export interface ExplorerService { export interface BfetchExplorerSetupPlugins { bfetch: BfetchPublicSetup; + developerExamples: DeveloperExamplesSetup; } export interface BfetchExplorerStartPlugins { @@ -36,9 +38,9 @@ export interface BfetchExplorerStartPlugins { export class BfetchExplorerPlugin implements Plugin { public setup( core: CoreSetup, - plugins: BfetchExplorerSetupPlugins + { bfetch, developerExamples }: BfetchExplorerSetupPlugins ) { - const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({ + const double = bfetch.batchedFunction<{ num: number }, { num: number }>({ url: '/bfetch_explorer/double', }); @@ -49,8 +51,25 @@ export class BfetchExplorerPlugin implements Plugin { core.application.register({ id: 'bfetch-explorer', title: 'bfetch explorer', + navLinkStatus: AppNavLinkStatus.hidden, mount: mount(core, explorer), }); + + developerExamples.register({ + appId: 'bfetch-explorer', + title: 'bfetch', + description: + 'bfetch is a service that allows to batch HTTP requests and streams responses back.', + links: [ + { + label: 'README', + href: 'https://github.com/elastic/kibana/blob/master/src/plugins/bfetch/README.md', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + }); } public start() {} diff --git a/examples/developer_examples/README.md b/examples/developer_examples/README.md new file mode 100644 index 0000000000000..1a57838c43d24 --- /dev/null +++ b/examples/developer_examples/README.md @@ -0,0 +1,36 @@ +## Developer examples + +Owner: Kibana application architecture team + +The developer examples app is a landing page where developers go to search for working, tested examples of various developer +services. Add your a link to your example using the developerExamples `register` function offered on the `setup` contract: + +```ts + setup(core, { developerExamples }) { + developerExamples.register({ + appId: 'myFooExampleApp', + title: 'Foo services', + description: `Foo services let you do bar and zed.`, + links: [ + { + label: 'README', + href: 'https://github.com/elastic/kibana/tree/master/src/plugins/foo/README.md', + iconType: 'logoGithub', + target: '_blank', + size: 's', + }, + ], + image: img, + }); + } +``` + +Run Kibana with developer examples via: + +``` +yarn start --run-examples +``` + +Then navigate to "Developer examples": + + diff --git a/examples/developer_examples/kibana.json b/examples/developer_examples/kibana.json new file mode 100644 index 0000000000000..8c9ec2e4dcbfc --- /dev/null +++ b/examples/developer_examples/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "developerExamples", + "version": "0.0.1", + "kibanaVersion": "kibana", + "server": false, + "ui": true, + "requiredPlugins": [], + "optionalPlugins": [] +} diff --git a/examples/developer_examples/navigation.png b/examples/developer_examples/navigation.png new file mode 100644 index 0000000000000000000000000000000000000000..ac72f697e5db08e792b6ab5308e087de037cad47 GIT binary patch literal 28522 zcma&Nby!tf_XY||N`th(rn{xPI}Y6q(%mT=De3M~Lb|&JY3Yy#>25a7-FSra{hoXO zxI7!ycC9(bct@`^$m88u5;UwW(LrEl)(1pVQ0M!b#SV7@X zV&afr31ZMQ3?v33>SAwo5dg0HrvL2U=Y$LlG-*`ioKiqfyR?IrK*OM)t$xGlXIZh0 zpkat?<)3lVPKvq^j^x)>4aWx4SMe%XJJf;@Z~8jkX7je`3`9mmyi$ZY^h*NOXS2oc zF-VvB4L_=nVZd#8LquzYOh7yOGIYa2bc9_iY4Sse+I_3fOk`C39g2$IX8=T%N#InD z2utA9ji6Owhj(}v;sz<0f8t&x3sIAnovGR}@`-oO4d9vp*NqP0+=mK#EXE7jjfRRc z_%oxZdlZ>7*RMD3nq&A}NS=_<3ANbjA9yZNx}?qH{Ku?=tL50VuQ(xwu&{DuVIj)X zh_|kkUY5D&6M)0ST!~)65|k5(N_#g zMI|iGcW{3*F?8DpW(WTEwgvXM#V8Wum9Lg0%0-0XcHpugYp-dK#1;OgIZ&Xj!kEQ- z;2|M)`}n9ELq)8a!75IVN+~8%g2b$xNkCLs*J=G(G<_QqKZQg-r5&leO<2mkB9$mD zofsi(;@6<##_J2CFi|7h8W{D>Fm#glyvrR87Vxo75JvreO@3x%v%xZ7)=GePV9mYYpU9;N=VB zpis*|(S!Q}0s9F8OR*ycIUh&|usyKd4{D!eHT(!`0>FUt4-;oyi782q>9FFZdgUib z26ZabZZK7X`d09MMyT{=_Z5puH8f3>^)cda9aMP76}!Lz85SIRc-}y~6M-*hhGks# zR9g>)#v*d@;$LxAOm`49&_zOtyWxy*#?UxAU)u}tzR?RjB}8g$fDR{6C-NpS#G8uiDjgn|vFO_UIpsY3fvH22JTXPYC;2jB3K>#~Vg z?ooGR=-QtSdWQ`uD-nL7m7rBrtZ87l;_?)A2NZ7?T4ExJhAD5vA$fE^hV)K!tGFs1 zYHiJJ+=%fdG195D5kY<^a&D4MrylrFxtgZm_gng^E4Xq&XHf@I(N|)!ys%z&3Iu7W zcPCR1K!JFSxWB&-ejFFufv|_*H=c}acfOQ5c7eFqN;<);dR2?8t_Sz=jq?hIDdLbn zoBhX&21tb!SfC&k&TAvVSCWu%hDl=fe1jeDnJ|W4lV>B+!CDED|AMRgNMOM63l^^v z%^p1+I;lg|9%CW6xB#OCif@H)TLksfr%^N*qi_vCT?p&%Aa_zoNh2W{v0a>Cwo`MEwGQ`*%-3$ z!%+IKl9)21rIN*|h~qKp(2&uGI|>Tpjx#06SVAvF8L!^wqgIEohRB5Mg?fchhS+o? z8!?88vQTiv-AOT%5mINV2y02qiE+y}iSLs6kXgmh_t~y9InrnfXDTpI9+44|>XQmk zg8p%)u6wI5jVLCVBCjbvD{YalljE#(^UYJmt4M&&KUFM4qBMJ2c|?&&aoN(sLet{f zJYoXf>gQC^=v=Xj-d^Q2Wh(#A(4HK*TxxR}i+Kx5b2kgS9p@$jzK~4mkpjlNnQ?_N zqA>wW)|y}|r&{Par<&p#{F-u$_VJwUU%M496nk%X;`jDv8ox}G%8b=cY;2!8f7nyo zAslZloiFYk#V^GEnp9jbYFDrX-HLrf=EHNZ=;QBO`G9q=d_#a3ZuoPB=_(vLyfmCO zT>kYJ|5nHuz+m=}LA_A1P*hIaDpeO*mv9$N*Vmu}*>H>Abrz@O!Q|WI`sA$OWF$ir zG-OTQT;IN0VxsUMJZN0_2oaL@oHe1}3Jp-K4olR}_4mH!^ zU_oLTg-v1g())hEt@>5+P7QkReR1#jB+GXt!^YXFsj88IC7LnIwkg8m;As^ryFJ9c zscHIYK6Wg2V;i%%$=QYKykDO4pRH%+GOOKs9R{|>@XfUKwGBV`zg{FB zB_7G?Sq&l`8=GgIcW7NxrJU^Vl3G{UaQ=boa_Nl4Q|@MqFOIXxD$7!0_R9u46=6QF zBX4-)#D4Sm+v-^`2eKdAcQeu55KPkHh^x)r)zr17sf!26`xs;KVWL^y(}=V<{N>Vt zgCL$oz9FATuejU2e}=z)`pO>OwAOiyvsXF#^~YLqK~lj`^-}fVU=Quj;<>%LdVjYP z5c<&>KU9`M78k#SH~+Qg&F1al+5N=G55{@Bg5|KW%ddf7>mv`3>rc0??Jn(544`wN zt>2iV)F7@yPebv;S0STA*&uihyPABcbgR^dZiX2IqQLmATsfLK$bT{*UM0>WF3q{g z3C&5!iTYmhouzB{yXSYl?;k#8g#biF#Y;jOezL8dHr6g=GV2+eMQ{;Fg@s3zgnOfJ zyd@8_Bn*orV0E4P1v^$Z7Q5YpgW46LiFw8}&CkwwdCd8{;g^HzTIP?4@HAXEhD7}@(FybuZ_{oCF%4Kbd1dQ%VPLh;lmAa|r3UeoOCv6H_ zF@z~gQbxJPjE(xcwd3|FG3A?>W=$N2*S{(|=O5?qE0E@r7aYjmeh*unI`*7s+?m?p z^G5cgf6N0&R%nfqpJSK3pf98+OS`T&> z9v|1icY9nvoVd4wMi!Z)xEZ~c?9Ozz%F`chg-(H+M%BL?e-H=+KB}mH(Iug6Y#p^* z?Gd{oIr%dE<1lQ7{y~j~s#RlCOHJ?66yC4@N0!8c&WY3Gcz9mvAa9b5hP)1grmvOQ z%4Y)F3pK3LeGN8O)h^5F-SMfTX<1FD9B-BDp4!RU&$S1b|6t1PSx?jJgYuMAJgR9L zEEQ@kE`IN#>_P99+rZ5!wvSmG&-RR@b*CL#BQGx~8mlX}1vcav3|5y)X^-6hzLz;* zkFznIZ?jFZwp&K4Uvn;1w>glX$Qaxm zIM+`$C{Gj)-Hv(m_!9)~$2IT5A4={Tf1J%>+cHKv2fFCq`+PsjV9aB@ZIXEyz5RNV z&{h1}59Z#Z@q@R*meuUu1Bc8KUi;#M?PPP}(yt|nBd2AM57oW-okK6>k-`=~rJwH- z#{t5Q%n$Y6@}J8j?R?uK2S-V#CcIN>5CN}$_Cc)tbcNWahF~iDe%}Rk!KFYRa${X2 zydq$Dp{Yoo2{GA~=GZ*U1=*p;xeo+zyc;O>6h;+XT!al4U&lSPwPe8KJwfHa1huoh z{y2%)p|0uYw|w*PP_AuQ?0xvA! z?IksxARw^FpMD{wl*o?3YmN*H6%A(%IazLFI~xW=6FVbQ26r2K@Ms7KUUzQrR~u7j zLx8)DwXGAkJ0HoP5!~SKPp2740Dp!!Tk(--$SDFu>>N!2Yz*%im`M2F00019M-ww{ zB~kIe)4~7ZBQbY&w&!MKbaQiKaARe#bNs-_%*DmU$i%|P!a@%oLGR>Y>ul&wZ|g+* zuaIXsqNYy9ju!UL7IwCPC%J}3b}r6*BqUFYUVi??Y3gqApC((Uzh;3AWPG~9$jrdR z_#zuTmG|i^x1xo+skMfvg^j7L6Icg7`+FANKjZ&jSN_xZKQlG|o5{+`^uIIz=gQxi zyo^r<{EtEZdh5?wu)Fx*@G`!*p8t(a-Hix18t*Jb6;!~-S5Kh<|Kx#xss0|p-)VBs zzAa&ckM>fcLMrZ%`->hQ-tzn z+Dzy@eQ(*vFHVO$)y~qkoR8CRO}?)g2T8?{z@Lr?JobqM5Y{G^sMpt>H`adWsAadl z)5~wav$I-CSY$|Wny)+6vOS$(?3>p2ivvO<4CJ27ZVg#MvQ{}vn0c)Jm?`a7cWxD( ztLN#pifQ!%^?x;{)Si$p_ANSZ2D$Ft50rWn=sHR#4Cw6zaRVP}559UinZ~MH z)9EjlN4kNh8>W39Z-Hg}+cCXleD@Xc@(kpp!MtysHMfRP1X3yW=^y4&-*2ya1LCsFXC`G|GW*=4%P+i<_uf8U$H2;E#cbQz9WjYuiBLM@N z&@@Ck!}2C~+WHWDndbG7^`5)AO+6Wh&nP=ylIF1fARTCsyS4O?EfV~YNKD$J`SoIN zDh9u-RVgTP2pLP4u~~9hpuCjLZth&&bOJ>{)8DFl1=chhJ_t7@MX60k6PNqg*UPEO z3S^7R`e0$D)8$h?$ap%0aGCFZLPo7g(ywLGckJM}ebgQRyLGohBc7%sXDjBIM{W3V_e>M9-dvOz3-qRZH7^4@esCp zYv4QivIdcZTUJ`$B`#ZlPx^ApoeIe}o`S90Qa6E`OJx}(nFP8W>Yu9GY{+iE>Ol&) zT&}UTO)$B8KV4Y8C!wrbTubpBK?DzZ^4zQiU~?Pm`LDK7cp$7ocU@+jlO9{{+t?&z z)@oGbgUR*%Xjui4ja%Cf^7l6KW|nG}+;)HIooAtX+3P85c@{lVZMfiYI22hgS9WR1 z$y}e$A-*>cZG6bwj-J_@x#oE%A8L?0({|`Y)xI`{2)s$T%zlIzO1%#)(MT|p8~1zV zxjf#L`IGh)8~`=(BPCo@rKn<*`$%Rh%jQWz>x1(2PMeToaY}8ICM-P~?!qH~@%i`E zm8%?mvzxs90JW1y4prcdDgFTJKvMT=7cPtYm4=mH7$!Z9mRNymnLi8?m(-8XG6!=7 z+Ijw$EDG`|4BB-MmJxHRJ(s+Lu_Stm_}THF9~8H&)vhn?d9YF+osK=l$(XOXMR zJ)_*k0g5>F{(+qbXO#CPAd78!^UYf95EdGNpq-NJ~?kTC1Csr^+8uT1rqRKBxg zICWkP?1!nwVIKEmMk}>!^b^WV&!saI)$Hp__I3{P@MhPem}*%#YSpSwe41u{ydzC| z&OlwvgOnZjvmp2q+9;S54d~9I0+pEH+r^!$$^H5mz1yY)Mc-ahc;I}UUDBiN%|8Q) zQi(7Z_f`lG@(M|vQQ@`7l8?UO1Z|aLSfF&fy;o?AFvy=hw_N z1{cnqAqmr}l_fs5unua8Z^^v}y_*~4JVKkuo;YgbpT-WZJsu;%Lw`@VJ=&onusprz zx!1}aj>GrQB@w52gua^`$5^b&@~XaF8zpt&vSwTcNJoqoZudSwOE|ylHE5AxsyM^4 z)$O5=T9GSh3^Yt5;Fal=bzrgD!aWku+Ljp%AB8k{!arefO8`!AP^U-ON4`?kFbcJu zY`(H`tuKY-X_wK;?pLm+MJ?CEu+v62QRDZUzB0>}c1YA16bff|6Q;{a#kBViz3i+< zT(`#SkxQ+)wi#NP4nAwnV<+aYLiE%#<3H1f6`u2Z6-MZT{fsdV^STiAhLhcSV(DWX zWx>#>Zl(8B3M3>HYKUkD29$a!yJ}Z{%>aFbm^X?RKIS%d1m6{mP(~S~9k4KQoDqRw z*w#I<#&$~QGqy~;Zu8|p!KN=$>#AO`rK$q6eo(8^T~$5S={4Gu)4vRB<=Lp`ktb2p zXE1I95@=PU7n?x?Jx6}1NPx@i2-TXg&ra^3`>6FjQ`%A~Ek}=k3Xqk)da~^iexI_M z_7F~FurF_PXiIGLUm`rmp-g3To)>Db&}O%z*%%;Ci|tunZ+5{S;*%1X3-j_Rl%R#< zK1!OfA8*rjHI7A)t<58hLLOd0{Z<*$8Zf-EZ{hj6Z7GCk$NuWrP#Kt}``g^E*z}Ad zKeeHmZx^(?K(u@x+0$4rFv_uRaZzqZ9jk_9g;~i5^(O4H#ce5#e%ZTu0MA8F8Fw=g ztyRM2`m@R&zo2fmW8P<$;~cMjRq#TpZ0!t{^6wA9X@WwE3BC`e#k}|XVM3kf2$rJ(AnAW5 zjsc7!RQl+bmo=$}CsN9Mj1-N%0p5a$qI)TLZE6WGtQT4wf~F1p2O1-_%w3w*F!rLAL!+HC zT3TkX*5_gu2pwrUYqqxPmSZx#Zk^IWLp$%AP3!se_1Q)h(oRx8C}qcTd*yQvGl6>N z$ZNq^X40i|YUdmWoEXFEwnr>R{kSg==k03CqFhlYgP3o4R(Y;2(NPa;%jc0c+<0RF z-y%dPQY<}hkCKlnf33;kaa35M1223H7zh89W?6tOFq<&9uE^_T>QSRNO&N7EMd0qL zddmE}t%*^o{kg=N_{GL&hWs&qg@kaYl=P+GQ}R_Ex1&s-)6Vq9*gCUTr>YA*nSO?S z_cCXu#W?c{`1j@(Q@vRX(Rs@y$MNXD1}!c!UFW}mAUEG{`@|8YdNuFgB4rF(gbtYI z3;El@E7t(CeW$Z15ZjEJJjd*9QHEg%8=+~u2z-2&aPd>Fx*4fThmH7@!yH!=KCdksMIMDSrH$wb$u4o?D`!yTZ*vO34jw;4N#?-23 zd-f8?_Pg(mmoE33Trh2`sFK~$M=Mm!X;DpxpZ6TgEGO6GaXVn?+|E|T z)Ll{;OO%qYYqEmhs6HQb3+9Rp@FQT^!>%c+tsQAr41T@oD|CN4b`ge6OJh2ic(PZ| zJZTeHoqqUuNx)MI!;FVqla|_o>?x3^n^AVZZSfkL12HD^R)gRxjBqQ(<-6AQ3Ry=f zYW2F3sU#z+tU_YPX6nV8J;f$6Oh!vp@~v|eIjZ@=J(jueYDZt`{`n$0YIQBDf7=-; zBctKA!^QN-WO-bsRr^{0r(nfJO7PP&g=7UDNUK)*bKt$--Ps@?FlV245Rm=qCa{p; z+|nXXP21AS@aevT0GG!;U2u6k(*`j&9&yV6qUo8OrhBWpRigH?L9Dwz5r}YrC$9mb zn<0dl+(;Aqf?v&1Uy4uMhhN5h(@omWrq{i&Ai9CV`akjt@rDV)$WNm>zOGS(u{YQw zcWQNWC#~^;1wBbKL2w5e`0hzWV|)^nf91)z(h#aFJHrE8(t|KnteP;$*r<4ZV*ace zwF#`+nKn`M3GNf--_k1@sIqJdSj-Bj*;Dp98T!aDe=ni-{R6%>^dTyF&>Z`I~zc+F!#3JJ?=j0vbquI8$Xv1&^0;Iqg%u49@{~MM@+%Ib_A8f98Y# zFkk@Sn)W|cHvbj*QLqLI4mcKT!t;FM;~*5TP_!46uIuJ6-DfQTVX)@)eiAh4D(+|T zD=bfFDnkZ`-!+FlV-%$VM=c&soT`8K{|ZDGO3L7J#eTLhMDfXb&7_2wl>X`zHZz_%Z<7iLAZ8B+uy4-nat+s$Kv8P|!9?FbPYmNjy7zf!v-BE+uW^;QVCul>N3j-BaiD zCotUs;Mfullk`60g!@Dcc7rn!Mi61~zoC0_Jr>yYSL>B~&yEo!dj-`gd9Lx|6#GgD zq0t|dQMxafNzjg=Ix&l<%}fcogh9+P=2Z+YAW5Ep+~Qzou(@KsxD^OS@+QRk)$D6#VEhGuZ z1i2SWY*9I}pw!ayER}@+|A4pdR%2IJ;RA+?)ayG2CWC^u}|@A>F{4l&#Aq zi|V`;YEu4u+P~#ZZf;4^ch4v=ERQ_nm#B9vf^|rSW;ZL4c|EO_|F~jZ6~N|lKc?12 z{Y0>^1{SThpjYueYhRJ~pR&LwBhHC_D=9UfoRFC*4_4;!KgxI!a#H{roSkETw6U8& zzgU#;3J{uia)L9=eo_PWIUPb?|DViWTgi2V`#Tsl>y^`{FWPwrLvw@i=ye+_pHMV%o{t62 zOER7&fs@NG1Lg9iPI214VnzVxxzoZhG0~@IzkDJWL`4jXNcgujgA)OSfC{zfhs^cr z*+B5J7igeiUGg%eK_6fyWdEb6Rx?E+a?~gMwj3?;IrzU-z}KP=jenniUaj~m6JQIj zS`JP$T&OQ1?Vg~hAZ;CpR=j_Xfqe_K5f;>r#IbvpG(XC-6Z+D?cG&6BMLYxUju6}j z8tmSbbm8LG;6|dS;BjDh;^Ebc4e};=H`VoKw z6|DIZK3)W{z)g@Bl;7^fUFDfp_D7E_7jVNzZ;;QGuW{y_%7E?edAX}OJw#`9Z;U^* zIk{iDt>AT2h*6gGeM9;e!tv)9JD)ts)GnaeO$*l(&k2gamZTz64RVg_*1~ks zPbPm3m_HT#AH6*!*VJ%oyYrf#Im&VKln2aS28=?1{Ys67cmNf@HzhBv`wLJLsQKpE z!69G%wYD)UZ@o+|Z)l3%Nk95O={RuR3~>1+g9Cj-L-iwg{9~$J!Gloz$jr zFV>qsMU>hCzj}OP0v-rCEK(UXmFM^<^Loe-{n=&qcTY$P@sPdIF^Ur6l!KfTfKs9U z*akE&BhsHnfNv!~7=#2mngm$41d@Wpi>&^)&#AM*`Q+xZbwZ(bWld89Y-+9cqGe}_ zmvTob3~&`dqa*CulEb zY(JS%tTgk1V7QNSM;nP!-?=V+XO`le)iIWi%WcWqasCOzfk^SHFw$;^bSfV=DVNG0b!ddk7+NdGvU4Hxh zW_zA)^M33YG(uZ+n(fX(?a;AAkOp}GH}mKg{f(vnWRXkL40rhR-C^?N2TCUpGd!lW zl<9=J!Kx!U2@lV;$$?-eog%7E(>eZi`=003!Nsp$@qW2hPtSZJZf8k64jXD%ZWnFsO9l9o{*5!UD0#NzBS#;R(piRpFaw)y}F9@Z{GX^ z?vunLSiD3MZd?<8|FjbKD5i9E@&~4{!ddp~C6%cUMR$>UKPb8)BQleI%yH0uMAI5)X;MF)C+cOos%j=z+ZQ% z^=|jhHZX(j^n19LxLI(B^5%BSoN-83Yi%03c2A6_R_?KCiZnNlDacIOWxJoVD!Y7- z1%K{=2UV=fqq>xJkpm{S+3zPOnOZ z-TIgLbSV`Q-egj7d6SZKyyPj}(Jck*S;!D;X`ZrrK|fZtKr?7R0WY7srEE6J(`8Q@ zznTd8O~YfR((;1fyMQUNtz)+qUg z72w%MXy{s=QQ#Xc`tQzviVcy!?P7V{^5ZYFH&D`jH6OCVIT0=4TFwrAr%UB;+#b6$ z?QXn{yd%VU;PUfq;y;lD<_Y>9@l(VDwt1&qsd&p(kfdmmSJKJ<*2}Y0ECo_5jWEZ2QjTCwpM_1Iw|(Cpwles2xirp9_Yt(NZ0 zx91m$X%QZ+Ht6nT0g-Z6%82s7r2;#y5P_E# zvL)Vy6K80l|#QmJ{|`B*U+5~`3fDKB7`SAOEF!+{Rj2SyBv#L#OZ)- z9f1PS9LnllBauue5V}-sDUD0!@CX#W{JT`EE}DSHZ6HeEVVz@SHY>*t^<0}X7``hA zIkx$5-}vX$?uye~`X07XK;Xb2W4nr8@}{m!W|ssr?$a}>18#rWuY=}C7#ZTt6Xr>! z9(N+}Lt-t*lCwU}Pv)R*{KFg*b#i?2{Fky!A}Tl-ZUBbHK-k=y7kx#zm^t<-{CuIZT8!?AGnNdbfiQC zYqb%*y%8~)e0CN28*iZ`B5^1(7+M6!r%PgXCiG8l5Oq&t!*~Y6So1aK;Z*QAjjj}T zoNjHV?*d>SW7!Xe<1%>MG}mrKWS}3LS9wM_?fyKG9kD~m5Hm}N6;;0yLaF;w{s^O# z_P<+-GSDjy@?q@!9f)qSdsV5_uFJZt>A*o~i8}fE@%NdBqglqvRO%{}P^slK&4(?f zgXUFw%6Lcj$(yg-)ir{z5)7QewC>&CL<@GI!o!4K7Y77 zQ%gGQ>=}&<-CK`a7ocvv@EArU0qdW@;g=4(KexIyvYc&+{2crUj}v3cnY11K4s7X zjuMXH?v#~lEnLet&3ZC7P`$Ru?&6%t?~Zt_N8xR&K2tn#J)nX6Lc370tz{-3CdG^V z@uHlAcLL0^>*3EG{8Uy@fOpsb@d2ogdI!v}oou%0xB?X0OmQsV3c zH?=e9oz2`XNof)n7tLh)b2Vz4cK5TXzG6S;91nIrNVlBBB`KrsJ9N1?M($LRkG6U` z38c_#apRajVbs0LoBZaGy1bcMZ@o5!D$;D5a&`hc?Fa@My5KO=>bnP(7Ojn{WA(kw zZaJhAxbkp+Tk4C29r(*}c8LR+P2c&43d|I&V3LI6HNy)7;3O^fQfU@6$(an%#zpQB z_;7sKQ#fsEEEwdfDNz(7JT0tq9(J3!6%?uv3o|<%*0z(3ArV`joJSX8=ZEEB@3&?GF^sx zZine?&rk)wpfO~i0{=xgFZ0eXzQ9XJXU_808q2BieF*~1S{ku@{@WJ5K~HixPlrEE z(kJp2d>Eo_x2W2Teg*m3Hlmua?Sk~@trIk>wt23xHGkkraP<D5*5dKhDSEWVeAoAKGP z$bIgS4@eTcFJB^ecMn=tD!$ab+$>Sw+Jb75U@9jE&N=}jWIJDvO;@d`LOld9e-fuLL)MQqDi7IkJh7u}(IRY=!{rjNaBM!TtsA@Kh@)~sT4xF`I+H71dab&%{ zhuWmTz6aCMV!yZhNq!(;#%Mlz$i)^D(RThbsk`Gh*s&32;@7jf5WX=qZfa^$J*_mF zHxh$H4o4%LO=IM)0HM8@28~bhV~qqzo{)$YI3&F zY;iBtaqEi69GT?cSo$S$*j60n619AHjbPF@Dsd;x46X~WYpHxKdJytcn=7Y0J@y;m zeW!Mt%Atf*4gT;VA+>^ZK!a6xc;KAeQ2f}}JfYr1y{*+~>L0jGj-hv+#~)|T4M?$7 z_~dRTZE&n(ym=TW0m;gkCpPs9OU*GoQZ;P8uZ_i@*j*4S5#R!-K<4RPQpX9^o9ENn$`z&f&DS+L6d{b z4BrW-w9$g4S;tQ5DJN~Z<)0{QaJ!MPT51JWU9ojG+I!l?-0DXePRQjgyt)j#&N*z< zqwMe3uU!cbbo6gg(rb>)2=i#2DKmR`U+S4LRRzA`=4K2FhLb#M ztuN=`S;q(CRoV`>eZ{vhpnMYkB^g2j1#1FUs!WUX6jyOloJQ%YWGY!I*9dhq_rWfvI6n)_r(Fz;zKAl9jp`QM4Z0gF?{!&c^|!T z*(@6toF{Cm?&dKsX}%yy6K*Fh@+oHbkl@c0q(!a3oswWaU;Ps5P z;M$*0%BcfR7wv-IsOe{$xjZf@w{x!w!G(LUa_9IB3*mz4if#wEU zaJlrs81D?c^3bibS!U?peCQOsN4qJ*2y^f$J66MZQ~ULT)iUGIW!Z#|Kg#A`k|;V2 z>{$cLqCp~NH^T$*(_ecEH;wem56!XVmKnih3onhh$EDg*7TXItaV|1UOL;Xzo&>hR|ziuGUtCXgY9nZe)^RJ~l9^KVQnLRZ0b5WZe@u(M5 z*H0G`RUcFvJ`)iDO0eqA5dnP~Oq#@>kE&f=wjPo_EiC;bru{_i1Mx0}z7xi5#D(_2 zA#=YNa~Y%O?Fzva_cz@naEa8~G>@>If_;0S{aEJ0!SxUik{>7UZa6H7e-5g1XA<>) zAbzH((GLKeeh(GzSy~C2&ds{O9s3bY6zSO(uymXm! zGph^sg%Oc|!bvWpF6me`C=CVr@Q&RFnjsckV|i>M=Wo&B;ZK!rhkFmst^m)b2||AX zcS~hDq+(&1E(%ljH!-BA-*za>&a%7|wlSG=RK2)LMGG;SP`o++5;y5OufR29FsVRV z34X%Teacdq&70Ft9ci!iV^oUQtCJh9IUog4F8_Gb8 z{LHK`(173KXfPjRQ6|w4e^a7S%T7D-zS~{~#B9swzt8bZHldb1Rj|*P7D^@V%%B=P zWbDX`XYr8rPsx#=TarK$Dh4Lo+nIj({Y4ex_vFyY$%|OUTqf176Tcn%Pk*gharFm3 zmR%^|D8RJnJR{;I(Nnh!<`;hJ1K5Q|!CybAn^W06j-n2~Ly`u51Ya z4`zEHBE;lB?*#`uZ>nKGdDwEwKIc0H+-V3Gwm# zKBxalsvPk2m7>WD&0tm*bGCP@@J27YWdOCO=z;tDDQe^YN|^K0o}PmV?O&gL{I~~Y zgbDRX1Of5*c%EjW1_8nD^YrfNK?ZzF#1H&lqO#g?8cY&;(HyyNHRg=uq9lPT(vtmc zCZQppq@|j_2n0$~%jEGbgzbO6w2q-a{Jr#eC(gRr0!nv60kwcKoeu5zvs#W?SdUuH ze76pqd_gH5nbbArC!b4dYMcv|i-VYAAmF2)Ki!1>Db<^S2a^#qQz+Vp^g2z>32*7u zMBiMKL$R_}lld(3cQUiGPTYELN_~Wq{PzRMhkwhUqwxltflMqe_MBOO2VY&7iH%Q$ zh2?UCl94~{dEiH=FXGvfF=W(wHIkEaJimf|i^CnNP7K{%j=gfPcs+DOCiv>#Po*4y zy09XiO6|Qq_f8tBPKCLqT2Siuh#ov4tygCo^D81R>Q6%ieKlcxFn|cki68Qc3l|pN z2$euD#HA)mbanK;SQah#fJ&v=qLEpS8}30YX=U)>9qvu@Y`NePdLK%0ww*AOmU5Su z(!>rydi^qSmiS*dWYH*4D{?wj?n`Bu=W=l3wBAF9e1+FcZ@tN$B|yNh^Z9qlV2w-! zE5U72+wzD1XSFbf8XCecqBWqH*L+I!L$iE*r@sGlzB7s;!D5z#H-a}7>2+aOqP7TE;m`wgWQc~j;JSkM8IFn)f zKW#YA7JgKKLKlZ~{D79#hRQDU0>9$v?6@Y`|Hs&IlI;oX@Bga|3|vSH3gZ%gBkU#Z zu0#P2pA1ey#if(@r~ zrduyI$+au3^&sVWUR0y+TwF0YNE-A;X0TXJYRsPn6M8B}a_>r}ZNWdGe+%_wPh3*T zfV7-k1TL}rT13PKnDdO-#xGJkkhPd93Y;u-G8Da7t5o_bUf(b9Xg#BQG*Qs38;!LGLlKi3bN zk79Fk$(*PSBi{nyS>xf)Nd6qX(a-_@I{%IzCMiR0*-WL~_)N<%(G{PNK#tF08=K|# zAf{HLL2fnkfWzbsCX5qq51V;bv`9>-pfC*IV(bxsk5;^YvLsj>VEAd}JB~K#_M1*v zB5Ovu)CF|sPi8+;>AQj=5UKFN{c^gKe8fkqlgu2{a1feo%Y!l;#ZvNV1QY5 z&bJ$Mv4lLsBr$J<5N8?N?`TT3m#rjFtYETyE-lhPnbvbPn*7%$k#{$Hc2!=W_PL$) z{pu0)1#rWlY3Gu{y!N^?iV%GO%>6`{Mm8RUM`=+eu?}H910X0bXP{ zZTV8T&w$A|sj)9&wZF^(^o9 z{n+l{7cuIalzcvolqkMSoVeQF6xI(G!wnxnja!-QN)7gg+L3X(&942}`rf4_Gqknj zJR)2s8TP`seADVW4u$U=y3rsnVon^*m)kNrm`S;~#IP7-r`MbxuD9MiIQ71IB%;%8 zl1-$$7V?>C2Cwy%|%} z^hL`?J&%r>)_cmzvB0fNd`9K`7Avo_Y3=d>Das7%dB;;=LJJznJ!T* zX%wC5V2jO2DjVrG${IKo$?3K0DnXrL z_F@kgU^H4b^Zk5WW^FQc#Qr$_5sC(D=#l=MbLdx19%no@G91g^U!8Zx z$2J{)->2bX@$m`caVyS+$qL;0gL$_;`ug{* zn)hAP-^PBjN5#!nZ}mqLcfBry9_#?Jxb92RUK*e^AGN&}HaK2+a6I|pQoZrfArIaB1)X2c};`7JfN;(A>a z2vpXJ_^pIxM%S&@`RE}8RMjzlz7l{Ee7EXqm&|#x0fA7W4k6U{crgP5!m^kttHm0C z#1=7eoJgu)&ZHR;5a_H!{AX8d+4Fqcsx)YOi?+PQpdEW5K8~s$sW`466OUpmQ+q=1 z)bS%G=ANMlIoznao(HK)WgEZYcPH>3U%?#rA;_p?w1;+4?KHjR?(}SKz?{MBb_WyK zc)z*z^Hw%Y@T^5q;?D5(!?^~sSjY_cQFBKIejYI;wg!=+0ddx`=(V(0M{6vMJy!f* zPyFcb58H^5@cd=B3Pc#50PdAk7ZqC66Pzx2v6}8qTGX|Oh0ULAV2+G09zFTPYf4jYUQ_;TbO=dm@a=4!n<;e_1#$+0bD2p+aO z-tJ!PRkr>`VeQ2XjXEKEmlIC`o`Byds=u5Jh`_&{#w! z-|bEzS-Oac;T#ftV(7fB6?qzm-I&MSH{o258LUPD9aO+XL3^oRgG1cR_q7bdOLGG*fdLTc|# zpL_rJw|4jEV&%>sA&N|SCP85(|u(+;8KL*p&MK(hcVuk8I!Uw9+Q?}e)c}(N?f$5vk_p@Rs zDr2CRI? zPoWeBm^NPRg@o7ZIwlnVF6^SQC!6|yhpp4d$xd1ovKF7CZBffoJRGN})biUFrl&|S zG9sJ-pUs>Xi`kGB`|TkakLtEOuE>JHPxXo##|=xUn-T54)BVrBSwz7!)l=(zn5ll5w`~RnDRp~mC95X_zla?6K!lrT_A@UrxMB6@ zr4S_EhRn>u>V$k9)b}Cl=M0}?f!XT$NBTWkUgOJfnI<!QSUzL$aCW}eVK(H`GlVpjx(AQ_8D-~sm_Vb>+IW76XrwGKF| zqDXYT4pgOaT&K453{U2)7LT`Ah*wWx!%!NfAJei7RkQ)Kg$SKa ztpYJn8iP_^X(GOS$EZB8&xS~Ef@8^Dchn4EZrfTLNYA) zB-rfL=dWYf^+K|R&3j{tSk_I`t+2|M8cE#Bf#5e;ZUcn^bF~H1QJtX^8~>lizB($Z zFKYV-jxvDAAOcDw0wN(O-3>}gcOy!73dl%zgQTc{$S`!5gdiX#G33zQ-SFK(1>g0( zf4pnW;*Y!Ty=U)z_Bne$&))aY!T_58`Tl(elq4In6C}2M)7~e8WQwd+2XW7;`r~GY zkr~;2HsyvbT%Xcxq9%0mC30OllpDOl2NE7g$78Ah`tqDS0myh4f$em2&6iB0@y#8! zc^I!{;4pIWD_!3a7c9Ebfh{v5l4W-p$9f7&S%<#CYc%^cYRbDkIQJ!a2B}9q-Mmi5 z_G;o3%9zxd@~YtJHEgdG1Xn*yq%0K^*m2n+;J)~T+-&#?q@lItI8))+)_0S%tSvte zNF(P}i{>HTHbIyKo)`pF!{>@}G_ke#y^`bWlLK#pCRi0&nAI$6BAlyl5K-59C{ z%pM;ExvVaa`Qq*)s!|$QQN1CVU!^}Pc1lrdq5u}NdNCt|(Ks*`#dHwqP3GzsR3Q=C zlDH=eK>vrHUe{t;v^?`;Nis)cp_2N}oh2MI+oMn6PCcsF+oH1s;pIcSo-n2PhJePj zWY?D_ykqlN>}uf3bwAUNr2Q8^9F^hk&@+efYdap4d4TNvh+gLVysh2HWXHS(hS(!Z zg7UX~6F+k7PX+8cny7p;2PRcSEnp+<)y{W5tdDT}c{p0wy-dagd~n+Y%exX^T44u0 zPgnj^$!q1)g6ffD3DJl2pq{P@d%>GF609CA1$uSD1MXak*j9k*Ww=So`nD&6e&0sH z2RL-3oUZXkg3oycC*2v5Q(%j{h>1vJB^`_cMjmNj&@ zS^{FIJyAa6rixJ!8jnJaluMw8AbzQBH?xDXaZfcW83_<*ba!o`z;T(QL~V1mG%Gz* zVDnlyyTiuAX2YGYDmlg@zSoqxaY#6d4F4k(Sn+)8;D^-|LZNJZwAG%MVLk4>XZMgU zVE54q7-W?3JZs?`NDH(IDnvR6pt^aT3aqyb#D!gmqpL$k_g-KOh^WIyi=EeXXT^RY z*Z}k$h&9%Cvg1b8#u{e&=tJ>qVC@t6}7%V~(NM2i)~vt8M0W zUh6||gpr6+WXUF37?D+?jNk%aP7mbE%-L+T5_^EIN`02*DlqIvvz}lSCgGSex@U`~ zDyv@D7Q?L@FM5;zcmD7r?a zRjsu0<*8Bg9TEiVsLSkLl7DnZ03OC3_P*73|8u>`Z$`}+Ud83oWZi1CDCF@28%19j zafj)Dz809x13SkiMBwzc=u|r34)Wl9+}!DvkFGmE(^}Wp_qm-)WaZ|tyTtyh)+5Ve z%x!
X|5_dox4VPq5q12i%9%Xo&6<+Tu%p3&*hlm#sIJjiH~X*kxe(Z)41C z{xXIqtY88uYt$Ul$IDiZ7~LCNP7v`6*xbW4XVUZX5Gnny32C{bzbh)!0)sJj49d(- z-dp%YV$GVIZ*zR7l{+;)sn&%*T&EtZ2U&fno5JmK}u;??KsLbui!^-2s*=wk8>aJ_5B*0Eul`NBb~_5S1kfrosh(<|6=dPIX%1V zQ99xoOjwr9!iE9Gbzc_wR&P`ZP)*h1h4S2_IHX)`-wG3RqblEWV8TldRneIF zEJ)KGK~SAW3o)z?QdQ&bT+}K31;5p0b}k9`B{$AM+0pJ}HQmOPLZ)f3YCPg%_ZS9E z>3}`=>S5wVd&b=+;x3PGR1(xIk=B{LhGQ31y zXIpEs7E40K)F(mjoj4FR4O1!3wAV}45|1KDaWftRbhJ*Y>zwPz$6XZrIK$lyJkt1FzvA2pH>WiSynd#)Yvuc@ z&Gi8)Td1altc%zn9ZIN#88tztCF3F)T3gW!2~wZf+8; zn0y8Ste7fV`*?4E0gXYH9L8RFSTW83H7eHMh6FlOp$d8QnlhNeaJ-rM3nhQk;TV#X zNZ*Mm8isv&oEA-?#djn(252vyLd6sBYC4pFi@#KknV{O#3HubdX;Oa~YRLEnLw*15 zIK_Q;`M*~q_J3df|L>Iq(?0Hc-t{BkeU0DragqM|C0UMzj)H2f(yAr~;ln&7W;14^ zPV3J)`cJFhUy=P&z9>`5;k2~VwRlEd7FMuOk2(+r#>xksUW7oD#sNgAot;SHb?8KD zpF``NdvmW}3QBCW}xG@%u;Fg&D)BD+APQVzRn+Wx>qP zH6ml9%HB?11}SbQ_lVEO`sTsR^gcqX2vJAeD4eiE|yh1;-0|ESiZEt)GB z*>nRd{89s3(f^S3>e%XR^z>Z_kQ>$a6v$5PfB$GGgzgX2GB&!)H-Z+}|a}}rl`wS(T9_9fp=o6Vhvl^B~@?Yb;1z}O5 zVb!B^Exa+g8sI;)aUaSozeDfK%0+~b1^$LC_=rG~rPQ|2`BH%g5J4cjn>K|FDqTGu z@CfbiX6@jHBk5Q^cv)Hb4^u4st(S;R!ENa4JJ24IN2Owa-Bbv@hh`!PVtkOWaO;lN z?{$LG7r;Bf$jnlzXct? zo)0txJyqU2F*UFlUXZAO>88Bp`FW+h5DYbA&51<;44@oUZXL?4h$q0xY#-N}4HxA6 zair%N?R7SU$MUkoJcS|G%9_*$=bjAiW32+sHc~yFmh2e|&TaIo$!tQoY0v(LBgYU6X$vOyD1y9(yiN(m0y8zRps;`B3uZh~S9H_qLL)?Yz2n;8ddQ zc4-P{*jFuKX1J0x5DODm$@kG2W4G&0bk7dV-=TV-p2w^1tA3@-N>vn=6I_iU<&X8! z+z)f{m6j|)Dh^4XBh~-g{zXi1#s*VKqzCkV7 z`MQ&r-XA2uq?tmm^&AGHS3#n|QyZ?6+F z$EoCa^&KvmrqHu@3MhH1*J>)pF{%-c=w%cW2j4*G5yX^P`p{i^8y-+Bx#_*QTZW8W zkA29RZ5=LWC-Qz;R<+WBgmNQDqJgJDn)$0qyG`N4Sq#_Jj%+G2+(r(Ja>3{Q!ex$^vqYd>YTE=@zl zr5(~bzTes(qe+n1&jhmQS$2MPMWtQ`JTaSijFIcg?b+wCa@-pGb;{Y)=xgp)C(DI~ z{hA&)%gn4Q)=k;jKiJ>fDy((;%Gh2W}TnRj^WC1 z%;24_BR&-shLA&w;1C~m4#N>k9lXL{8t?HS>0`couQPS^B~OqZOCV-&q=FPvuQ zlt7M|0ca_w)$^zl@&ts?3S;3!XuD>20DE3QqH=)K&Xp-ayDDG!+j?F&2lHN zF!44ryNMl^j2#_6yj5A!6(3hNX1EQ9un~1B^iGs?3Q7jn8Jh7a?)H_^Uq!!(Zh%(z zGvGYQw%uCxGC!u2;BhV=8Ms9Qa$Y}EtK26uTP`v8s7hA)l-MynGtHgWp6sgke5jD_ z3%iX4QMyzCLSx{;j>}L4@wnLhZc*T8i`z8hM4N2>noZ;xz%Wet z@GRYDqV9Yx(#pdx!3;gUFH@!WKh~Gn{B-7C+K)e_xew`D_J0iQtDPWC;-srP+w*_J zVxHRid_=WlM|shq1a1>n1m7q?>J-ZIPGE2AYN1HLBfz_C~{U(JpygXrSh2|o-g zpBS&bakZYah>k6w#vqRY6X%kO4LpkUzw@(KgXm;Gd|4bPZ+=eJy7c?H%(;|6%6Unr zdzSxs*1%bZT5r3QZo1!VJ+8n6kT=nz`p9OkB({oKw~DD>!44{F;D*NXPlZw!#oCJ; z5fz+SZX%H3IPt5zPD{k|1ANjz|8hkxnH>0j_s({k0ktwTepTGel5_y0vXwvs=!bt! z?gdNIN}fJ^OZCZkJ1)0Uw_~Y)CY7Vizj}Ui(r7jhC&|IJqS8+z zOLC>D1Y$`$gse!laMODb1|Ce9Z_tN5NIfTD2CJU9KgXYZiy?q%%1Pc1}s7pmm9 z^}$2RH-I(!%!EjK+VA)~7Qlf*AL^Bzskv^iE~1WhGk!;F4Nl-x{z2T-Bg&)u{pQMe zj&%32h>n9VgW+`~5@zt_>+mu{o%fxum#uh)?ZUU1osAb=BOJ#L>vtiz-K%xEcj_@= z8ML>keDy)!)P4VCDj&swZK7Pirx13NpbIXSd(A-nW8b`}S#t_jsBtJIDG&18Cd?zw zoS^Z0vd@PKJmJ{*JauY8__4;o7xuUC=o?Grs*gGM$TN*4an`L90~Z1)2f==!K3pC) zec;&9MRUYtV_%D=D2!W71SaBRQ6IBus`uto-gW%1YsBI^=g2CprAqG8Ygtj$=fQMR zR0;S@anZk1d!ZdLkU>s!zqv^&;P%DQ6KHZsEXEV@?Xx1G6@LVh^|05@cIt3(oVvpR zo@D1eYHiuk6tX_4SLh@M->q?NAFpiv{Q3T{TfooYJek7!_@4Pl(c{FH8>GFze$7sj zUt4AOaTdNy%xMrx-SqL94o_*Xfk8+_O-4Ptoyw_OraDF4iJP}f>QQQqQ@%N=Ew%55 z?=62bmW>pE`p4L$@UrTL&adZ=SYS59Q-%a4iD1?X_B)w@>!G{OkT5vDU&S~H3-P2L zMHXqYw#>Tof}e*w(mFUIb}>P_@i8%l>X{GOCbeEczWs(BY{wtZNE=LarXw@!5xRG%n9;98nkfgBt^pu%rDmEXNYpRabu zwsNdjUQqlNgNCA7I>h1G=HJBo1eNNdSixm@t@ipI^x}ND!DC%;x#O}|N=@1+omXR-h`p?{GG^B~ddF&bh#(x2 zy{gGsmTq7pc=VsO1uUIyF|u?2c}5W3GNbQ@^akobY1o1MMf9=-QGXADFhUduu{uz; z)p?{~k4yJ~ZB6uM!=qUFSSBy)=#u9%6(gBCPR}e~50`sedgcvt8*OZ`x`pf5Pf zF$9lVKPoTTG~_TL8!1z@OnX`AhVtv5#T;0a9PK%dE`sMr?r){U4&sqxJU2W9N9V`v zZXqH>zH^G*%k1|LaiRTi4(ZM3vN|@cf+>ykR;;h%w2M-KgJk|>IT4%yBoVb~jzf>@#voV6FfathW~ zo_|}?)8{RY7x&!;bAU&kr{Gwse8!5~->n=s3{al{#}&vBoqtR}Itdv{eXJ}lPv^PJ#ay>E~wu*<^df@N!2(bBda9@kmdQ%7wK z%r81=;|FtBWhxjzqPdZ5ju+(6g`_{o0Q@mwNCWCmEK$d#h~|~?_v9p{o^XM_ej&4I zm{=TeTO=~GCOf-O{Cc1t(c?9LutQC}y&1;-q^J6Pn1WJMhRPd}>4eDMnx2O(Yg7>5 zDrG?|dc5GpJ);tE;M;goO9FVW)40{XdG*pcI{<$thIq7pS=IkvFMMY_a!u>jzTBi-F{D zsuEoPZ$j1kYEv)R&2e9urHK@UCWGt)+y@BjvwWLIXjXWy8n;7|LbjkV_=BK@m&GhBco=*O97-P zAED&BNr4}`X+V7mY#vOIpkWD*cNZG`l?&jUEK&0Y@Kbx=ivFQ2P$UDXu&4Ibvyc&B z$1rk#Gst`O@J1+VB2C0qHQjh>{5(i_IR4@2DyS#YAlfh=ePUnzH9vpnORXc`di|De zdi+DdKa5Ji4HSlj8WSk+yhF?Q#42U+?#e7Dloy`V9X@H8^p8;d0L#;3)EajQA*3kb zUD_ zj#2p_?bX}>R1MH39LWT9$iI#%G_C-?FQO+(R?`7MFkuZ|;AC9s`XK!{lT>6OT?(bC zN-iVN#27S*EHuBAjvH@7{tw6aW532v4W><9H1A=+J!;omqF5l}nuP1Tb>?qxJa(k# z5ZmC3-F|H!N&oEGGvEMR7mf36>!Tw8lgBXQmSQ7hv}0?wn$L~>Z@-a3Xgj`F&b6x) z@IP1`UbY3;#Jx6;PDp<#*p4-ken3jWL z33U9xd6j(-E6vVCJ|rCk~G<3A^zLSBZ*{EQ% z#cg(TL~DX=-h%y!k;@?VMQg^z4i|8NP1O^L$ytnJERcmNxN<%B#f@k1J+2eh+PpT{ zQgj7!BdrXL=^J*7G$oE_hnV;#LqYvVCjfcz86Yt%YFq>{X+Q>;D@fBXD??Rkb%wnX zoNXq%OHIeih39{)s_+3t&Dv=hldT$xcY$oESdPN#J$GJi@=ML@wuzW@Akohkd2rW_9@a z5-{&gl@c)PkO%dNgXNREXey$C{K{A=aavU1_VI)G@n3{}Z#zM)Gi(gSc6nXsiE;$*{~&&9R=&T1kknIfCPhoCv0{djHW)mnYwDyY>^rO9A+> zPkF=EEzxBTRssFiEv5gqn-g9n{jk9QD7}qkwMNr79y3m2a2d`x{3quZlJNifgs80b#{JwBb?;x_Wd^T@q2f*slrlN&NCGT>DwZsIs!F$2`AS?_s|sCs`Of`)RgL^tfz^9+%I-J?czF2T zpA`&oXD8c!o+76eOC)Sh7_5idb+MN-JG6`^x_e4bo)CP@%Es!SruBi};g-9xL^AT!9ygs;>%#4 zX4y%#1^GF$B4IaL&>}TXo&p@2IHo0#x?NG50kDQo>=wLt!!yZ95ohJP5`z1MHEf1b z6!gG%5FOhj;tX)8kI6LbnCq~2Xee>VCV#EAkiLV0?*TxevaDy4U{TL>8>S$Ne#s6#;h))7H&{6MV>&D|eD5BelN`tvflYdc$*0 zLUW|*v*Q1{>oL{BS}oMHzKHl14{~PhXo?9te%)qV$BAObW>@|4yB$cPkT*V5sOPv~ za=_qYVURpx(YurNrb@{oSyK2R6-e+suO4vV$q1jKwKzuBd;M0jVEx&2xG(lO{-0*F zi@*nd065a`50|zKbCs5bTw=aS&grA0-LdrGk0Mh9xaJY zh;n|ttI>Nq1>uMp3NK9x7MkE2RBfrGzkroes&xvS&tF@mHT=XLN{{gG=aG!o_9s$* zYS8b{3s73-{s{p3Ud--m#1&-JKjIt~f%H} void; + getUrlForApp: (appId: string) => string; +} + +function DeveloperExamples({ examples, navigateToApp, getUrlForApp }: Props) { + const [search, setSearch] = useState(''); + + const lcSearch = search.toLowerCase(); + const filteredExamples = !lcSearch + ? examples + : examples.filter((def) => { + if (def.description.toLowerCase().indexOf(lcSearch) >= 0) return true; + if (def.title.toLowerCase().indexOf(lcSearch) >= 0) return true; + return false; + }); + + return ( + + + +

Developer examples

+

+ The following examples showcase services and APIs that are available to developers. + setSearch(e.target.value)} + isClearable={true} + aria-label="Search developer examples" + /> +

+
+
+ + {filteredExamples.map((def) => ( + + + {def.description} + + } + title={ + + { + navigateToApp(def.appId); + }} + > + + {def.title} + + + + window.open(getUrlForApp(def.appId), '_blank', 'noopener, noreferrer') + } + > + Open in new tab + + + } + image={def.image} + footer={def.links ? : undefined} + /> + + ))} + +
+ ); +} + +export const renderApp = (props: Props, element: AppMountParameters['element']) => { + ReactDOM.render(, element); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts b/examples/developer_examples/public/index.ts similarity index 82% rename from test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts rename to examples/developer_examples/public/index.ts index 547dfe2aa38d2..616fb011e3705 100644 --- a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts +++ b/examples/developer_examples/public/index.ts @@ -17,4 +17,8 @@ * under the License. */ -export * from '../../../../../examples/bfetch_explorer/public'; +import { DeveloperExamplesPlugin } from './plugin'; + +export const plugin = () => new DeveloperExamplesPlugin(); + +export { DeveloperExamplesSetup } from './plugin'; diff --git a/examples/developer_examples/public/plugin.ts b/examples/developer_examples/public/plugin.ts new file mode 100644 index 0000000000000..a0aa601660f37 --- /dev/null +++ b/examples/developer_examples/public/plugin.ts @@ -0,0 +1,68 @@ +/* + * 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 { + CoreSetup, + Plugin, + AppMountParameters, + DEFAULT_APP_CATEGORIES, +} from '../../../src/core/public'; + +import { ExampleDefinition } from './types'; + +export interface DeveloperExamplesSetup { + register: (def: ExampleDefinition) => void; +} + +export class DeveloperExamplesPlugin implements Plugin { + private examplesRegistry: ExampleDefinition[] = []; + + public setup(core: CoreSetup) { + const examples = this.examplesRegistry; + core.application.register({ + id: 'developerExamples', + title: 'Developer examples', + order: -2000, + category: DEFAULT_APP_CATEGORIES.kibana, + async mount(params: AppMountParameters) { + const { renderApp } = await import('./app'); + const [coreStart] = await core.getStartServices(); + return renderApp( + { + examples, + navigateToApp: (appId: string) => coreStart.application.navigateToApp(appId), + getUrlForApp: (appId: string) => coreStart.application.getUrlForApp(appId), + }, + params.element + ); + }, + }); + + const api: DeveloperExamplesSetup = { + register: (def) => { + this.examplesRegistry.push(def); + }, + }; + return api; + } + + public start() {} + + public stop() {} +} diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts b/examples/developer_examples/public/types.ts similarity index 68% rename from test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts rename to examples/developer_examples/public/types.ts index b4370eb53311e..0ef359ef64a23 100644 --- a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts +++ b/examples/developer_examples/public/types.ts @@ -17,4 +17,18 @@ * under the License. */ -export * from '../../../../../examples/bfetch_explorer/server'; +import { EuiListGroupItemProps } from '@elastic/eui'; + +export interface ExampleDefinition { + /** + * The application id that is the landing page for the example. + */ + appId: string; + title: string; + description: string; + image?: string; + /** + * Any additional links you want to show, for example to the github README. + */ + links?: EuiListGroupItemProps[]; +} diff --git a/examples/developer_examples/tsconfig.json b/examples/developer_examples/tsconfig.json new file mode 100644 index 0000000000000..d508076b33199 --- /dev/null +++ b/examples/developer_examples/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../typings/**/*", + ], + "exclude": [] +} diff --git a/examples/embeddable_explorer/kibana.json b/examples/embeddable_explorer/kibana.json index 3e4b074fb6b12..aa14549d0460f 100644 --- a/examples/embeddable_explorer/kibana.json +++ b/examples/embeddable_explorer/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": false, "ui": true, - "requiredPlugins": ["uiActions", "inspector", "embeddable", "embeddableExamples"], + "requiredPlugins": ["uiActions", "inspector", "embeddable", "embeddableExamples", "developerExamples"], "optionalPlugins": [] } diff --git a/examples/embeddable_explorer/public/embeddables.png b/examples/embeddable_explorer/public/embeddables.png new file mode 100644 index 0000000000000000000000000000000000000000..90b287962d24823c6717265bee595c9b746ba0e1 GIT binary patch literal 88399 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%0DD=Jqw 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

^U2q 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 literal 0 HcmV?d00001 diff --git a/examples/embeddable_explorer/public/plugin.tsx b/examples/embeddable_explorer/public/plugin.tsx index bba1b1748e207..2a5023d2dd63a 100644 --- a/examples/embeddable_explorer/public/plugin.tsx +++ b/examples/embeddable_explorer/public/plugin.tsx @@ -16,12 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - -import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public'; import { EmbeddableExamplesStart } from 'examples/embeddable_examples/public/plugin'; +import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '../../../src/core/public'; import { UiActionsService } from '../../../src/plugins/ui_actions/public'; import { EmbeddableStart } from '../../../src/plugins/embeddable/public'; import { Start as InspectorStart } from '../../../src/plugins/inspector/public'; +import { DeveloperExamplesSetup } from '../../developer_examples/public'; +import img from './embeddables.png'; interface StartDeps { uiActions: UiActionsService; @@ -30,11 +31,16 @@ interface StartDeps { embeddableExamples: EmbeddableExamplesStart; } +interface SetupDeps { + developerExamples: DeveloperExamplesSetup; +} + export class EmbeddableExplorerPlugin implements Plugin { - public setup(core: CoreSetup) { + public setup(core: CoreSetup, { developerExamples }: SetupDeps) { core.application.register({ id: 'embeddableExplorer', title: 'Embeddable explorer', + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const [coreStart, depsStart] = await core.getStartServices(); const { renderApp } = await import('./app'); @@ -55,6 +61,25 @@ export class EmbeddableExplorerPlugin implements Plugin) { + public setup( + core: CoreSetup, + { developerExamples }: SetupDeps + ) { core.application.register({ id: 'searchExplorer', title: 'Search Explorer', + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const [coreStart, depsStart] = await core.getStartServices(); const { renderApp } = await import('./application'); return renderApp(coreStart, depsStart, params); }, }); + + developerExamples.register({ + appId: 'searchExplorer', + title: 'Data search strategy services', + description: `Data search services can be used to query Elasticsearch in away that supports background search + and partial results, when available. It also automatically incorporates settings such as requestTimeout and includeFrozen. + Use the provided ES search strategy, or register your own. + `, + links: [ + { + label: 'README', + href: + 'https://github.com/elastic/kibana/blob/master/src/plugins/data/public/search/README.md', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + }); } public start() {} diff --git a/examples/state_containers_examples/kibana.json b/examples/state_containers_examples/kibana.json index 581b399e3ffba..66da207cb4e77 100644 --- a/examples/state_containers_examples/kibana.json +++ b/examples/state_containers_examples/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["navigation", "data"], + "requiredPlugins": ["navigation", "data", "developerExamples"], "optionalPlugins": [] } diff --git a/examples/state_containers_examples/public/plugin.ts b/examples/state_containers_examples/public/plugin.ts index 38ebf315789c0..a4cf7dfd798f3 100644 --- a/examples/state_containers_examples/public/plugin.ts +++ b/examples/state_containers_examples/public/plugin.ts @@ -17,15 +17,21 @@ * under the License. */ -import { AppMountParameters, CoreSetup, Plugin } from 'kibana/public'; +import { AppMountParameters, CoreSetup, Plugin, AppNavLinkStatus } from '../../../src/core/public'; import { AppPluginDependencies } from './with_data_services/types'; import { PLUGIN_ID, PLUGIN_NAME } from '../common'; +import { DeveloperExamplesSetup } from '../../developer_examples/public'; + +interface SetupDeps { + developerExamples: DeveloperExamplesSetup; +} export class StateContainersExamplesPlugin implements Plugin { - public setup(core: CoreSetup) { + public setup(core: CoreSetup, { developerExamples }: SetupDeps) { core.application.register({ id: 'stateContainersExampleBrowserHistory', title: 'State containers example - browser history routing', + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const { renderApp, History } = await import('./todo/app'); return renderApp(params, { @@ -38,6 +44,7 @@ export class StateContainersExamplesPlugin implements Plugin { core.application.register({ id: 'stateContainersExampleHashHistory', title: 'State containers example - hash history routing', + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const { renderApp, History } = await import('./todo/app'); return renderApp(params, { @@ -51,6 +58,7 @@ export class StateContainersExamplesPlugin implements Plugin { core.application.register({ id: PLUGIN_ID, title: PLUGIN_NAME, + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { // Load application bundle const { renderApp } = await import('./with_data_services/application'); @@ -60,6 +68,62 @@ export class StateContainersExamplesPlugin implements Plugin { return renderApp(coreStart, depsStart as AppPluginDependencies, params); }, }); + + developerExamples.register({ + appId: 'stateContainersExampleBrowserHistory', + title: 'State containers using browser history', + description: `An example todo app that uses browser history and state container utilities like createStateContainerReactHelpers, + createStateContainer, createKbnUrlStateStorage, createSessionStorageStateStorage, + syncStates and getStateFromKbnUrl to keep state in sync with the URL. Change some parameters, navigate away and then back, and the + state should be preserved.`, + links: [ + { + label: 'README', + href: + 'https://github.com/elastic/kibana/tree/master/src/plugins/kibana_utils/docs/state_containers/README.md', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + }); + + developerExamples.register({ + appId: 'stateContainersExampleHashHistory', + title: 'State containers using hash history', + description: `An example todo app that uses hash history and state container utilities like createStateContainerReactHelpers, + createStateContainer, createKbnUrlStateStorage, createSessionStorageStateStorage, + syncStates and getStateFromKbnUrl to keep state in sync with the URL. Change some parameters, navigate away and then back, and the + state should be preserved.`, + links: [ + { + label: 'README', + href: + 'https://github.com/elastic/kibana/tree/master/src/plugins/kibana_utils/docs/state_containers/README.md', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + }); + + developerExamples.register({ + appId: PLUGIN_ID, + title: 'Sync state from a query bar with the url', + description: `Shows how to use data.syncQueryStateWitUrl in combination with state container utilities from kibana_utils to + show a query bar that stores state in the url and is kept in sync. + `, + links: [ + { + label: 'README', + href: + 'https://github.com/elastic/kibana/blob/master/src/plugins/data/public/query/state_sync/README.md', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + }); } public start() {} diff --git a/examples/state_containers_examples/public/with_data_services/application.tsx b/examples/state_containers_examples/public/with_data_services/application.tsx index 67a2a8b791ae5..d09b77fbf25ee 100644 --- a/examples/state_containers_examples/public/with_data_services/application.tsx +++ b/examples/state_containers_examples/public/with_data_services/application.tsx @@ -27,7 +27,7 @@ import { createKbnUrlStateStorage } from '../../../../src/plugins/kibana_utils/p export const renderApp = ( { notifications, http }: CoreStart, { navigation, data }: AppPluginDependencies, - { appBasePath, element, history }: AppMountParameters + { element, history }: AppMountParameters ) => { const kbnUrlStateStorage = createKbnUrlStateStorage({ useHash: false, history }); diff --git a/examples/state_containers_examples/public/with_data_services/components/app.tsx b/examples/state_containers_examples/public/with_data_services/components/app.tsx index baf627fd62a32..04bdb53efa502 100644 --- a/examples/state_containers_examples/public/with_data_services/components/app.tsx +++ b/examples/state_containers_examples/public/with_data_services/components/app.tsx @@ -78,14 +78,7 @@ const { useContainer: useAppStateContainer, } = createStateContainerReactHelpers>(); -const App = ({ - notifications, - http, - navigation, - data, - history, - kbnUrlStateStorage, -}: StateDemoAppDeps) => { +const App = ({ navigation, data, history, kbnUrlStateStorage }: StateDemoAppDeps) => { const appStateContainer = useAppStateContainer(); const appState = useAppState(); diff --git a/examples/ui_actions_explorer/kibana.json b/examples/ui_actions_explorer/kibana.json index e88739a9e44d6..f57072e89b06d 100644 --- a/examples/ui_actions_explorer/kibana.json +++ b/examples/ui_actions_explorer/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": false, "ui": true, - "requiredPlugins": ["uiActions", "uiActionsExamples"], + "requiredPlugins": ["uiActions", "uiActionsExamples", "developerExamples"], "optionalPlugins": [] } diff --git a/examples/ui_actions_explorer/public/plugin.tsx b/examples/ui_actions_explorer/public/plugin.tsx index de86b51aee3a8..670138b43b9c4 100644 --- a/examples/ui_actions_explorer/public/plugin.tsx +++ b/examples/ui_actions_explorer/public/plugin.tsx @@ -17,8 +17,8 @@ * under the License. */ -import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public'; -import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public'; +import { UiActionsStart, UiActionsSetup } from '../../../src/plugins/ui_actions/public'; +import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '../../../src/core/public'; import { PHONE_TRIGGER, USER_TRIGGER, @@ -39,6 +39,8 @@ import { ACTION_VIEW_IN_MAPS, ACTION_PHONE_USER, } from './actions/actions'; +import { DeveloperExamplesSetup } from '../../developer_examples/public'; +import image from './ui_actions.png'; interface StartDeps { uiActions: UiActionsStart; @@ -46,6 +48,7 @@ interface StartDeps { interface SetupDeps { uiActions: UiActionsSetup; + developerExamples: DeveloperExamplesSetup; } declare module '../../../src/plugins/ui_actions/public' { @@ -66,7 +69,7 @@ declare module '../../../src/plugins/ui_actions/public' { } export class UiActionsExplorerPlugin implements Plugin { - public setup(core: CoreSetup<{ uiActions: UiActionsStart }>, deps: SetupDeps) { + public setup(core: CoreSetup, deps: SetupDeps) { deps.uiActions.registerTrigger({ id: COUNTRY_TRIGGER, }); @@ -98,6 +101,7 @@ export class UiActionsExplorerPlugin implements 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%0A1oI=Hc7h?x?s1Q}vv~W7j#?*+P{x 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 literal 0 HcmV?d00001 diff --git a/examples/url_generators_examples/public/plugin.tsx b/examples/url_generators_examples/public/plugin.tsx index 016494037ec05..77f7d66ccf103 100644 --- a/examples/url_generators_examples/public/plugin.tsx +++ b/examples/url_generators_examples/public/plugin.tsx @@ -18,7 +18,7 @@ */ import { SharePluginStart, SharePluginSetup } from '../../../src/plugins/share/public'; -import { Plugin, CoreSetup, AppMountParameters } from '../../../src/core/public'; +import { Plugin, CoreSetup, AppMountParameters, AppNavLinkStatus } from '../../../src/core/public'; import { HelloLinkGeneratorState, createHelloPageLinkGenerator, @@ -58,6 +58,7 @@ export class AccessLinksExamplesPlugin implements Plugin { - public setup(core: CoreSetup) { +interface SetupDeps { + developerExamples: DeveloperExamplesSetup; +} + +export class AccessLinksExplorerPlugin implements Plugin { + public setup(core: CoreSetup, { developerExamples }: SetupDeps) { core.application.register({ id: 'urlGeneratorsExplorer', title: 'Access links explorer', + navLinkStatus: AppNavLinkStatus.hidden, async mount(params: AppMountParameters) { const depsStart = (await core.getStartServices())[1]; const { renderApp } = await import('./app'); @@ -40,6 +45,26 @@ export class AccessLinksExplorerPlugin implements Plugin { beforeEach(async () => { - await appsMenu.clickLink('bfetch explorer'); await testSubjects.click('count-until'); await testSubjects.click('double-integers'); }); diff --git a/test/plugin_functional/test_suites/bfetch_explorer/index.ts b/test/examples/bfetch_explorer/index.ts similarity index 83% rename from test/plugin_functional/test_suites/bfetch_explorer/index.ts rename to test/examples/bfetch_explorer/index.ts index a68a5090b9bed..1f039a2ea415c 100644 --- a/test/plugin_functional/test_suites/bfetch_explorer/index.ts +++ b/test/examples/bfetch_explorer/index.ts @@ -17,18 +17,17 @@ * under the License. */ -import { FtrProviderContext } from '../../../functional/ftr_provider_context'; +import { FtrProviderContext } from '../../functional/ftr_provider_context'; +// eslint-disable-next-line import/no-default-export export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) { const browser = getService('browser'); - const appsMenu = getService('appsMenu'); const PageObjects = getPageObjects(['common', 'header']); describe('bfetch explorer', function () { before(async () => { await browser.setWindowSize(1300, 900); - await PageObjects.common.navigateToApp('settings'); - await appsMenu.clickLink('bfetch explorer'); + await PageObjects.common.navigateToApp('bfetch-explorer', { insertTimestamp: false }); }); loadTestFile(require.resolve('./batched_function')); diff --git a/test/examples/config.js b/test/examples/config.js index aedd06c31d413..228af71a1f5d0 100644 --- a/test/examples/config.js +++ b/test/examples/config.js @@ -27,6 +27,7 @@ export default async function ({ readConfigFile }) { testFiles: [ require.resolve('./search'), require.resolve('./embeddables'), + require.resolve('./bfetch_explorer'), require.resolve('./ui_actions'), require.resolve('./state_sync'), ], diff --git a/test/examples/embeddables/index.ts b/test/examples/embeddables/index.ts index 878b1b9277ba1..d0d7d4a01fbae 100644 --- a/test/examples/embeddables/index.ts +++ b/test/examples/embeddables/index.ts @@ -26,14 +26,12 @@ export default function ({ loadTestFile, }: PluginFunctionalProviderContext) { const browser = getService('browser'); - const appsMenu = getService('appsMenu'); const PageObjects = getPageObjects(['common', 'header']); describe('embeddable explorer', function () { before(async () => { await browser.setWindowSize(1300, 900); - await PageObjects.common.navigateToApp('settings'); - await appsMenu.clickLink('Embeddable explorer'); + await PageObjects.common.navigateToApp('embeddableExplorer'); }); loadTestFile(require.resolve('./hello_world_embeddable')); diff --git a/test/examples/search/index.ts b/test/examples/search/index.ts index 2fb37afd248e2..706e9659fc010 100644 --- a/test/examples/search/index.ts +++ b/test/examples/search/index.ts @@ -22,7 +22,6 @@ import { FtrProviderContext } from 'test/functional/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) { const browser = getService('browser'); - const appsMenu = getService('appsMenu'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'header']); @@ -36,8 +35,7 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid defaultIndex: 'logstash-*', }); await browser.setWindowSize(1300, 900); - await PageObjects.common.navigateToApp('settings'); - await appsMenu.clickLink('Search Explorer'); + await PageObjects.common.navigateToApp('searchExplorer'); }); after(async function () { diff --git a/test/examples/state_sync/index.ts b/test/examples/state_sync/index.ts index ea1c7692f64fe..297cd8f472b95 100644 --- a/test/examples/state_sync/index.ts +++ b/test/examples/state_sync/index.ts @@ -26,12 +26,10 @@ export default function ({ loadTestFile, }: PluginFunctionalProviderContext) { const browser = getService('browser'); - const PageObjects = getPageObjects(['common']); describe('state sync examples', function () { before(async () => { await browser.setWindowSize(1300, 900); - await PageObjects.common.navigateToApp('settings'); }); loadTestFile(require.resolve('./todo_app')); diff --git a/test/examples/state_sync/todo_app.ts b/test/examples/state_sync/todo_app.ts index 71b491a05ae2f..1ac5376b9ed8d 100644 --- a/test/examples/state_sync/todo_app.ts +++ b/test/examples/state_sync/todo_app.ts @@ -26,7 +26,6 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const testSubjects = getService('testSubjects'); const find = getService('find'); const retry = getService('retry'); - const appsMenu = getService('appsMenu'); const browser = getService('browser'); const PageObjects = getPageObjects(['common']); const log = getService('log'); @@ -38,7 +37,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide before(async () => { base = await PageObjects.common.getHostPort(); - await appsMenu.clickLink('State containers example - browser history routing'); + await PageObjects.common.navigateToApp(appId, { insertTimestamp: false }); }); it('links are rendered correctly and state is preserved in links', async () => { @@ -119,7 +118,9 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide describe('TODO app with hash history ', async () => { before(async () => { - await appsMenu.clickLink('State containers example - hash history routing'); + await PageObjects.common.navigateToApp('stateContainersExampleHashHistory', { + insertTimestamp: false, + }); }); it('Links are rendered correctly and state is preserved in links', async () => { diff --git a/test/examples/ui_actions/index.ts b/test/examples/ui_actions/index.ts index 55137e2acc2b7..957cd0c46e1d0 100644 --- a/test/examples/ui_actions/index.ts +++ b/test/examples/ui_actions/index.ts @@ -26,14 +26,12 @@ export default function ({ loadTestFile, }: PluginFunctionalProviderContext) { const browser = getService('browser'); - const appsMenu = getService('appsMenu'); const PageObjects = getPageObjects(['common', 'header']); describe('ui actions explorer', function () { before(async () => { await browser.setWindowSize(1300, 900); - await PageObjects.common.navigateToApp('settings'); - await appsMenu.clickLink('Ui Actions Explorer'); + await PageObjects.common.navigateToApp('uiActionsExplorer'); }); loadTestFile(require.resolve('./ui_actions')); diff --git a/test/plugin_functional/config.js b/test/plugin_functional/config.js index 9039f7e734a6e..74d52b842662b 100644 --- a/test/plugin_functional/config.js +++ b/test/plugin_functional/config.js @@ -37,7 +37,6 @@ export default async function ({ readConfigFile }) { require.resolve('./test_suites/embeddable_explorer'), require.resolve('./test_suites/core_plugins'), require.resolve('./test_suites/management'), - require.resolve('./test_suites/bfetch_explorer'), require.resolve('./test_suites/doc_views'), ], services: { diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json deleted file mode 100644 index 1acc7df871c94..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "kbn_tp_bfetch_explorer", - "version": "0.0.1", - "kibanaVersion": "kibana", - "configPath": ["kbn_tp_bfetch_explorer"], - "server": true, - "ui": true, - "requiredPlugins": ["bfetch"], - "optionalPlugins": [] -} diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json deleted file mode 100644 index e396489a1ffc4..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "kbn_tp_bfetch_explorer", - "version": "1.0.0", - "main": "target/examples/kbn_tp_bfetch_explorer", - "kibana": { - "version": "kibana", - "templateVersion": "1.0.0" - }, - "license": "Apache-2.0", - "scripts": { - "kbn": "node ../../scripts/kbn.js", - "build": "rm -rf './target' && tsc" - }, - "devDependencies": { - "typescript": "3.7.2" - } -} diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json deleted file mode 100644 index 994f81e396763..0000000000000 --- a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../../tsconfig.json", - "compilerOptions": { - "outDir": "./target", - "skipLibCheck": true, - "types": [ - "node", - "jest", - "react" - ] - }, - "include": [ - "index.ts", - "public/**/*.ts", - "public/**/*.tsx", - "server/**/*.ts", - "server/**/*.tsx", - "../../../../typings/**/*", - ], - "exclude": [] -} From e66eaf74fd5b02a8466864d3df80a7457a4568c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez?= Date: Mon, 8 Jun 2020 15:49:26 +0200 Subject: [PATCH 4/9] [Logs UI] View in context tweaks (#67777) Co-authored-by: Elastic Machine --- .../log_entry_actions_column.tsx | 56 +++++++++---------- .../logs/stream/page_view_log_in_context.tsx | 54 ++++++++++++------ .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_actions_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_actions_column.tsx index 1ac2e00abca70..e27de7fd6b5a8 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_actions_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_actions_column.tsx @@ -5,19 +5,11 @@ */ import React, { useCallback } from 'react'; -import { EuiButtonIcon } from '@elastic/eui'; +import { EuiButtonIcon, EuiPopover, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { LogEntryColumnContent } from './log_entry_column'; -import { - euiStyled, - ActionMenu, - Section, - SectionTitle, - SectionLinks, - SectionLink, -} from '../../../../../observability/public'; +import { euiStyled } from '../../../../../observability/public'; interface LogEntryActionsColumnProps { isHovered: boolean; @@ -78,29 +70,32 @@ export const LogEntryActionsColumn: React.FC = ({ ); + const items = [ + + {LOG_DETAILS_LABEL} + , + ]; + + if (onViewLogInContext !== undefined) { + items.push( + + {LOG_VIEW_IN_CONTEXT_LABEL} + + ); + } + return ( {isHovered || isMenuOpen ? ( - -

- - - - - - {onViewLogInContext !== undefined ? ( - - ) : null} - -
- + + + ) : null} @@ -115,10 +110,11 @@ const ActionsColumnContent = euiStyled(LogEntryColumnContent)` const ButtonWrapper = euiStyled.div` background: ${(props) => props.theme.eui.euiColorPrimary}; border-radius: 50%; + padding: 4px; + transform: translateY(-6px); `; // this prevents the button from influencing the line height const AbsoluteWrapper = euiStyled.div` - overflow: hidden; position: absolute; `; diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx index cf3eae263ed59..3ef32c920e293 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_view_log_in_context.tsx @@ -8,12 +8,13 @@ import { EuiFlexGroup, EuiFlexItem, EuiModal, - EuiModalBody, EuiOverlayMask, EuiText, EuiTextColor, EuiToolTip, + EuiSpacer, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; import { noop } from 'lodash'; import React, { useCallback, useContext, useMemo } from 'react'; import { LogEntry } from '../../../../common/http_api'; @@ -22,6 +23,7 @@ import { useLogSourceContext } from '../../../containers/logs/log_source'; import { LogViewConfiguration } from '../../../containers/logs/log_view_configuration'; import { ViewLogInContext } from '../../../containers/logs/view_log_in_context'; import { useViewportDimensions } from '../../../utils/use_viewport_dimensions'; +import { euiStyled } from '../../../../../observability/public'; const MODAL_MARGIN = 25; @@ -55,7 +57,7 @@ export const PageViewLogInContext: React.FC = () => { return ( - + { > + { /> - + ); }; +const LogInContextWrapper = euiStyled.div<{ width: number | string; height: number | string }>` + padding: 16px; + width: ${(props) => (typeof props.width === 'number' ? `${props.width}px` : props.width)}; + height: ${(props) => (typeof props.height === 'number' ? `${props.height}px` : props.height)}; +`; + const LogEntryContext: React.FC<{ context: LogEntry['context'] }> = ({ context }) => { + let text; if ('container.id' in context) { - return

Displayed logs are from container {context['container.id']}

; + text = ( + + ); } if ('host.name' in context) { @@ -105,21 +121,27 @@ const LogEntryContext: React.FC<{ context: LogEntry['context'] }> = ({ context } context['log.file.path'].length > 45 ? context['log.file.path'].slice(0, 20) + '...' + context['log.file.path'].slice(-25) : context['log.file.path']; - - return ( - -

- - Displayed logs are from file{' '} + text = ( + {shortenedFilePath} - {' '} - and host {context['host.name']} - -

-
+ + ), + host: context['host.name'], + }} + /> ); } - return null; + return ( + +

+ {text} +

+
+ ); }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9d3bc008106c6..aa45fd4bcb292 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7605,7 +7605,6 @@ "xpack.infra.logs.lastUpdate": "前回の更新 {timestamp}", "xpack.infra.logs.loadingNewEntriesText": "新しいエントリーを読み込み中", "xpack.infra.logs.logEntryActionsDetailsButton": "詳細を表示", - "xpack.infra.logs.logEntryActionsMenuTitle": "行詳細のログ", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlButtonLabel": "ML で分析", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlTooltipDescription": "ML アプリでこのカテゴリーを分析します。", "xpack.infra.logs.logEntryCategories.categoryColumnTitle": "カテゴリー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6992d4004e24e..56d373a6fcd2f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7609,7 +7609,6 @@ "xpack.infra.logs.lastUpdate": "上次更新时间 {timestamp}", "xpack.infra.logs.loadingNewEntriesText": "正在加载新条目", "xpack.infra.logs.logEntryActionsDetailsButton": "查看详情", - "xpack.infra.logs.logEntryActionsMenuTitle": "日志行详情", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlButtonLabel": "在 ML 中分析", "xpack.infra.logs.logEntryCategories.analyzeCategoryInMlTooltipDescription": "在 ML 应用中分析此类别。", "xpack.infra.logs.logEntryCategories.categoryColumnTitle": "类别", From fcab9745e0691af3878d7538681011b381ae2c71 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 8 Jun 2020 17:29:20 +0300 Subject: [PATCH 5/9] [Telemetry] collect number of visualization saved in the past 7, 30 and 90 days (#67865) * Update telemetry for visualizations to also count the vis from the past 30 and 90 days * Also add metrics for the saved visualizations for the past 7 days Co-authored-by: Elastic Machine --- .../server/lib/get_past_days.test.ts | 22 +++++ .../oss_telemetry/server/lib/get_past_days.ts | 11 +++ .../tasks/visualizations/task_runner.test.ts | 92 ++++++++++++++++--- .../lib/tasks/visualizations/task_runner.ts | 14 ++- .../oss_telemetry/server/test_utils/index.ts | 2 + 5 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 x-pack/plugins/oss_telemetry/server/lib/get_past_days.test.ts create mode 100644 x-pack/plugins/oss_telemetry/server/lib/get_past_days.ts diff --git a/x-pack/plugins/oss_telemetry/server/lib/get_past_days.test.ts b/x-pack/plugins/oss_telemetry/server/lib/get_past_days.test.ts new file mode 100644 index 0000000000000..28909779343a5 --- /dev/null +++ b/x-pack/plugins/oss_telemetry/server/lib/get_past_days.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import moment from 'moment'; +import { getPastDays } from './get_past_days'; + +describe('getPastDays', () => { + test('Returns 2 days that have passed from the current date', () => { + const pastDate = moment().subtract(2, 'days').startOf('day').toString(); + + expect(getPastDays(pastDate)).toEqual(2); + }); + + test('Returns 30 days that have passed from the current date', () => { + const pastDate = moment().subtract(30, 'days').startOf('day').toString(); + + expect(getPastDays(pastDate)).toEqual(30); + }); +}); diff --git a/x-pack/plugins/oss_telemetry/server/lib/get_past_days.ts b/x-pack/plugins/oss_telemetry/server/lib/get_past_days.ts new file mode 100644 index 0000000000000..4f25ef147ad43 --- /dev/null +++ b/x-pack/plugins/oss_telemetry/server/lib/get_past_days.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +export const getPastDays = (dateString: string): number => { + const date = new Date(dateString); + const today = new Date(); + const diff = Math.abs(date.getTime() - today.getTime()); + return Math.trunc(diff / (1000 * 60 * 60 * 24)); +}; diff --git a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts index 6a47983a6f4d9..c064f39f4bc6a 100644 --- a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts +++ b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts @@ -13,6 +13,7 @@ import { import { visualizationsTaskRunner } from './task_runner'; import { TaskInstance } from '../../../../../task_manager/server'; import { getNextMidnight } from '../../get_next_midnight'; +import moment from 'moment'; describe('visualizationsTaskRunner', () => { let mockTaskInstance: TaskInstance; @@ -55,6 +56,9 @@ describe('visualizationsTaskRunner', () => { spaces_max: 1, spaces_min: 1, total: 1, + saved_7_days_total: 1, + saved_30_days_total: 1, + saved_90_days_total: 1, }, }, }, @@ -69,6 +73,7 @@ describe('visualizationsTaskRunner', () => { _source: { type: 'visualization', visualization: { visState: '{"type": "cave_painting"}' }, + updated_at: moment().subtract(7, 'days').startOf('day').toString(), }, }, { @@ -76,11 +81,16 @@ describe('visualizationsTaskRunner', () => { _source: { type: 'visualization', visualization: { visState: '{"type": "printing_press"}' }, + updated_at: moment().subtract(20, 'days').startOf('day').toString(), }, }, { _id: 'meat:visualization:coolviz-789', - _source: { type: 'visualization', visualization: { visState: '{"type": "floppy_disk"}' } }, + _source: { + type: 'visualization', + visualization: { visState: '{"type": "floppy_disk"}' }, + updated_at: moment().subtract(2, 'months').startOf('day').toString(), + }, }, // meat space { @@ -88,38 +98,99 @@ describe('visualizationsTaskRunner', () => { _source: { type: 'visualization', visualization: { visState: '{"type": "cave_painting"}' }, + updated_at: moment().subtract(89, 'days').startOf('day').toString(), }, }, { _id: 'meat:visualization:coolviz-789', - _source: { type: 'visualization', visualization: { visState: '{"type": "cuneiform"}' } }, + _source: { + type: 'visualization', + visualization: { visState: '{"type": "cuneiform"}' }, + updated_at: moment().subtract(5, 'months').startOf('day').toString(), + }, }, { _id: 'meat:visualization:coolviz-789', - _source: { type: 'visualization', visualization: { visState: '{"type": "cuneiform"}' } }, + _source: { + type: 'visualization', + visualization: { visState: '{"type": "cuneiform"}' }, + updated_at: moment().subtract(2, 'days').startOf('day').toString(), + }, }, { _id: 'meat:visualization:coolviz-789', - _source: { type: 'visualization', visualization: { visState: '{"type": "floppy_disk"}' } }, + _source: { + type: 'visualization', + visualization: { visState: '{"type": "floppy_disk"}' }, + updated_at: moment().subtract(7, 'days').startOf('day').toString(), + }, }, // cyber space { _id: 'cyber:visualization:coolviz-789', - _source: { type: 'visualization', visualization: { visState: '{"type": "floppy_disk"}' } }, + _source: { + type: 'visualization', + visualization: { visState: '{"type": "floppy_disk"}' }, + updated_at: moment().subtract(7, 'months').startOf('day').toString(), + }, }, { _id: 'cyber:visualization:coolviz-789', - _source: { type: 'visualization', visualization: { visState: '{"type": "floppy_disk"}' } }, + _source: { + type: 'visualization', + visualization: { visState: '{"type": "floppy_disk"}' }, + updated_at: moment().subtract(3, 'days').startOf('day').toString(), + }, }, { _id: 'cyber:visualization:coolviz-123', _source: { type: 'visualization', visualization: { visState: '{"type": "cave_painting"}' }, + updated_at: moment().subtract(15, 'days').startOf('day').toString(), }, }, ]); + const expectedStats = { + cave_painting: { + total: 3, + spaces_min: 1, + spaces_max: 1, + spaces_avg: 1, + saved_7_days_total: 1, + saved_30_days_total: 2, + saved_90_days_total: 3, + }, + printing_press: { + total: 1, + spaces_min: 1, + spaces_max: 1, + spaces_avg: 1, + saved_7_days_total: 0, + saved_30_days_total: 1, + saved_90_days_total: 1, + }, + cuneiform: { + total: 2, + spaces_min: 2, + spaces_max: 2, + spaces_avg: 2, + saved_7_days_total: 1, + saved_30_days_total: 1, + saved_90_days_total: 1, + }, + floppy_disk: { + total: 4, + spaces_min: 2, + spaces_max: 2, + spaces_avg: 2, + saved_7_days_total: 2, + saved_30_days_total: 2, + saved_90_days_total: 3, + }, + }; + const runner = visualizationsTaskRunner( mockTaskInstance, getMockConfig(), @@ -131,13 +202,10 @@ describe('visualizationsTaskRunner', () => { error: undefined, state: { runs: 1, - stats: { - cave_painting: { total: 3, spaces_min: 1, spaces_max: 1, spaces_avg: 1 }, - printing_press: { total: 1, spaces_min: 1, spaces_max: 1, spaces_avg: 1 }, - cuneiform: { total: 2, spaces_min: 2, spaces_max: 2, spaces_avg: 2 }, - floppy_disk: { total: 4, spaces_min: 2, spaces_max: 2, spaces_avg: 2 }, - }, + stats: expectedStats, }, }); + + expect(result.state.stats).toMatchObject(expectedStats); }); }); diff --git a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts index b15ead36a75f6..5f7f70ee5d62a 100644 --- a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts +++ b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts @@ -10,12 +10,14 @@ import { first } from 'rxjs/operators'; import { APICaller, IClusterClient } from 'src/core/server'; import { getNextMidnight } from '../../get_next_midnight'; +import { getPastDays } from '../../get_past_days'; import { TaskInstance } from '../../../../../task_manager/server'; import { ESSearchHit } from '../../../../../apm/typings/elasticsearch'; interface VisSummary { type: string; space: string; + past_days: number; } /* @@ -26,7 +28,11 @@ async function getStats(callCluster: APICaller, index: string) { size: 10000, // elasticsearch index.max_result_window default value index, ignoreUnavailable: true, - filterPath: ['hits.hits._id', 'hits.hits._source.visualization'], + filterPath: [ + 'hits.hits._id', + 'hits.hits._source.visualization', + 'hits.hits._source.updated_at', + ], body: { query: { bool: { filter: { term: { type: 'visualization' } } }, @@ -43,13 +49,14 @@ async function getStats(callCluster: APICaller, index: string) { const visSummaries: VisSummary[] = esResponse.hits.hits.map( (hit: ESSearchHit<{ visState: string }>) => { const spacePhrases: string[] = hit._id.split(':'); + const lastUpdated: string = _.get(hit, '_source.updated_at'); const space = spacePhrases.length === 3 ? spacePhrases[0] : 'default'; // if in a custom space, the format of a saved object ID is space:type:id const visualization = _.get(hit, '_source.visualization', { visState: '{}' }); const visState: { type?: string } = JSON.parse(visualization.visState); - return { type: visState.type || '_na_', space, + past_days: getPastDays(lastUpdated), }; } ); @@ -68,6 +75,9 @@ async function getStats(callCluster: APICaller, index: string) { spaces_min: _.min(spaceCounts), spaces_max: _.max(spaceCounts), spaces_avg: total / spaceCounts.length, + saved_7_days_total: curr.filter((c) => c.past_days <= 7).length, + saved_30_days_total: curr.filter((c) => c.past_days <= 30).length, + saved_90_days_total: curr.filter((c) => c.past_days <= 90).length, }; }); } diff --git a/x-pack/plugins/oss_telemetry/server/test_utils/index.ts b/x-pack/plugins/oss_telemetry/server/test_utils/index.ts index 428909dc7feed..93bde69629fbd 100644 --- a/x-pack/plugins/oss_telemetry/server/test_utils/index.ts +++ b/x-pack/plugins/oss_telemetry/server/test_utils/index.ts @@ -7,6 +7,7 @@ import { APICaller } from 'kibana/server'; import { of } from 'rxjs'; +import moment from 'moment'; import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; import { ConcreteTaskInstance, @@ -38,6 +39,7 @@ const defaultMockSavedObjects = [ _source: { type: 'visualization', visualization: { visState: '{"type": "shell_beads"}' }, + updated_at: moment().subtract(7, 'days').startOf('day').toString(), }, }, ]; From 2bedb59c8e0968eb05d2033d36e9426e556a40be Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Mon, 8 Jun 2020 07:30:14 -0700 Subject: [PATCH 6/9] Closes #66867 by adding missing, requried API params (#68465) Co-authored-by: Elastic Machine --- x-pack/plugins/apm/public/services/rest/watcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/services/rest/watcher.ts b/x-pack/plugins/apm/public/services/rest/watcher.ts index 3027164e2863e..246ed061eb20e 100644 --- a/x-pack/plugins/apm/public/services/rest/watcher.ts +++ b/x-pack/plugins/apm/public/services/rest/watcher.ts @@ -19,6 +19,6 @@ export async function createWatch({ return callApi(http, { method: 'PUT', pathname: `/api/watcher/watch/${id}`, - body: { type: 'json', id, watch }, + body: { type: 'json', id, watch, isNew: true, isActive: true }, }); } From bc3918671cb9bc7ba33a192fa1ffc7c0ee1af93c Mon Sep 17 00:00:00 2001 From: Robert Austin Date: Mon, 8 Jun 2020 10:43:10 -0400 Subject: [PATCH 7/9] [security_solution] enable react-hooks/exhaustive-deps (#68470) * Enable `react-hooks/exhaustive-deps` rule for security_solution * Disable it anywhere that it would catch an issue --- .eslintrc.js | 4 --- .../alerts_histogram_panel/index.tsx | 6 ++++ .../alerts/components/alerts_table/index.tsx | 7 +++- .../components/rules/add_item_form/index.tsx | 1 + .../alerts/components/rules/mitre/index.tsx | 3 +- .../components/rules/pick_timeline/index.tsx | 2 ++ .../components/rules/query_bar/index.tsx | 8 +++-- .../rules/rule_actions_field/index.tsx | 3 ++ .../rules/rule_actions_overflow/index.tsx | 1 + .../components/rules/rule_switch/index.tsx | 3 ++ .../rules/schedule_item_form/index.tsx | 3 ++ .../rules/step_about_rule/index.tsx | 3 ++ .../rules/step_define_rule/index.tsx | 3 ++ .../rules/step_rule_actions/index.tsx | 4 +++ .../rules/step_schedule_rule/index.tsx | 3 ++ .../rules/throttle_select_field/index.tsx | 1 + .../alerts/components/user_info/index.tsx | 8 +++++ .../alerts/use_privilege_user.tsx | 1 + .../alerts/use_signal_index.tsx | 1 + .../rules/fetch_index_patterns.tsx | 1 + .../detection_engine/rules/persist_rule.tsx | 1 + .../rules/use_pre_packaged_rules.tsx | 1 + .../detection_engine/rules/use_rule.tsx | 1 + .../rules/use_rule_status.tsx | 2 ++ .../detection_engine/rules/use_rules.tsx | 6 ++-- .../detection_engine/rules/use_tags.tsx | 1 + .../detection_engine/rules/all/index.tsx | 2 ++ .../rules_table_filters.tsx | 1 + .../detection_engine/rules/create/index.tsx | 3 ++ .../detection_engine/rules/details/index.tsx | 2 ++ .../detection_engine/rules/edit/index.tsx | 6 ++++ .../cases/components/add_comment/index.tsx | 4 ++- .../cases/components/all_cases/index.tsx | 11 +++++++ .../components/all_cases/table_filters.tsx | 6 ++++ .../cases/components/case_view/actions.tsx | 1 + .../components/configure_cases/connectors.tsx | 1 + .../configure_cases/connectors_dropdown.tsx | 1 + .../configure_cases/field_mapping.tsx | 2 ++ .../components/configure_cases/index.tsx | 7 ++++ .../components/connector_selector/form.tsx | 1 + .../public/cases/components/create/index.tsx | 2 ++ .../components/open_closed_stats/index.tsx | 1 + .../components/use_push_to_service/index.tsx | 2 ++ .../components/user_action_tree/index.tsx | 4 +++ .../user_action_tree/user_action_markdown.tsx | 2 ++ .../cases/components/user_list/index.tsx | 1 + .../containers/configure/use_configure.tsx | 3 ++ .../containers/configure/use_connectors.tsx | 2 ++ .../cases/containers/use_bulk_update_case.tsx | 2 ++ .../cases/containers/use_delete_cases.tsx | 4 +++ .../containers/use_get_action_license.tsx | 2 ++ .../public/cases/containers/use_get_case.tsx | 2 ++ .../containers/use_get_case_user_actions.tsx | 2 ++ .../public/cases/containers/use_get_cases.tsx | 4 +++ .../cases/containers/use_get_cases_status.tsx | 2 ++ .../cases/containers/use_get_reporters.tsx | 2 ++ .../public/cases/containers/use_get_tags.tsx | 1 + .../public/cases/containers/use_post_case.tsx | 1 + .../cases/containers/use_post_comment.tsx | 1 + .../containers/use_post_push_to_service.tsx | 1 + .../cases/containers/use_update_case.tsx | 1 + .../cases/containers/use_update_comment.tsx | 1 + .../components/alerts_viewer/alerts_table.tsx | 1 + .../common/components/alerts_viewer/index.tsx | 1 + .../common/components/charts/common.tsx | 1 + .../drag_drop_context_wrapper.tsx | 1 + .../drag_and_drop/draggable_wrapper.tsx | 1 + .../draggable_wrapper_hover_content.tsx | 2 ++ .../events_viewer/events_viewer.tsx | 2 ++ .../common/components/events_viewer/index.tsx | 1 + .../exceptions/viewer/exception_entries.tsx | 1 + .../components/generic_downloader/index.tsx | 1 + .../components/header_page/editable_title.tsx | 1 + .../common/components/help_menu/index.tsx | 1 + .../components/import_data_modal/index.tsx | 1 + .../public/common/components/links/index.tsx | 1 + .../components/markdown_editor/index.tsx | 1 + .../components/matrix_histogram/index.tsx | 33 ++++++++----------- .../components/matrix_histogram/types.ts | 6 ---- .../ml/anomaly/use_anomalies_table_data.ts | 4 +++ .../permissions/ml_capabilities_provider.tsx | 1 + .../ml_popover/hooks/use_siem_jobs.tsx | 1 + .../filters/groups_filter_popover.tsx | 1 + .../common/components/navigation/index.tsx | 1 + .../common/components/search_bar/index.tsx | 6 ++++ .../common/components/stat_items/index.tsx | 1 + .../components/super_date_picker/index.tsx | 3 ++ .../common/components/toasters/index.test.tsx | 1 + .../public/common/components/top_n/index.tsx | 1 + .../components/url_state/use_url_state.tsx | 3 +- .../anomalies_query_tab_body/index.tsx | 1 + .../events/last_event_time/index.ts | 3 +- .../common/containers/global_time/index.tsx | 1 + .../containers/matrix_histogram/index.ts | 3 +- .../public/common/containers/source/index.tsx | 3 +- .../common/hooks/use_add_to_timeline.tsx | 1 + .../common/hooks/use_index_patterns.tsx | 1 + .../components/connector_flyout/index.tsx | 6 ++++ .../public/common/lib/kibana/hooks.ts | 2 ++ .../public/common/utils/route/spy_routes.tsx | 2 ++ .../utils/timeline/use_show_timeline.tsx | 1 + .../view/details/overview/index.tsx | 1 + .../containers/hosts/first_last_seen/index.ts | 1 + .../components/management_page_view.tsx | 1 + .../view/details/host_details.tsx | 1 + .../components/embeddables/embedded_map.tsx | 4 +++ .../embeddables/map_tool_tip/map_tool_tip.tsx | 4 +-- .../source_destination/country_flag.tsx | 1 + .../network/components/tls_table/index.tsx | 1 + .../network/components/users_table/index.tsx | 1 + .../components/alerts_by_category/index.tsx | 2 ++ .../components/recent_timelines/index.tsx | 1 + .../components/signals_by_category/index.tsx | 1 + .../fields_browser/category_columns.tsx | 1 + .../fields_browser/field_browser.tsx | 1 + .../components/fields_browser/index.tsx | 2 ++ .../components/flyout/pane/index.tsx | 4 ++- .../components/manage_timeline/index.tsx | 1 + .../open_timeline/edit_timeline_actions.tsx | 1 + .../edit_timeline_batch_actions.tsx | 1 + .../components/open_timeline/index.tsx | 5 +++ .../open_timeline/use_timeline_types.tsx | 2 ++ .../timeline/body/column_headers/index.tsx | 3 +- .../body/events/event_column_view.tsx | 2 ++ .../timeline/body/events/stateful_event.tsx | 1 + .../timeline/body/stateful_body.tsx | 9 +++++ .../data_providers/provider_item_badge.tsx | 3 ++ .../timeline/fetch_kql_timeline.tsx | 1 + .../components/timeline/footer/index.tsx | 1 + .../timelines/components/timeline/index.tsx | 7 ++++ .../insert_timeline_popover/index.tsx | 1 + .../use_insert_timeline.tsx | 2 ++ .../timeline/properties/helpers.tsx | 1 + .../components/timeline/properties/index.tsx | 1 + .../components/timeline/query_bar/index.tsx | 6 ++++ .../timeline/search_or_filter/index.tsx | 5 +++ .../timeline/selectable_timeline/index.tsx | 1 + .../components/timeline/timeline.tsx | 3 ++ .../public/timelines/containers/all/index.tsx | 3 +- 139 files changed, 313 insertions(+), 46 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f0b7d6864bef0..c33f4de15b919 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -758,10 +758,6 @@ module.exports = { 'react/jsx-no-target-blank': 'error', 'react/jsx-fragments': 'error', 'react/jsx-sort-default-props': 'error', - // might be introduced after the other warns are fixed - // 'react/jsx-sort-props': 'error', - // might be introduced after the other warns are fixed - 'react-hooks/exhaustive-deps': 'off', 'require-atomic-updates': 'error', 'symbol-description': 'error', 'vars-on-top': 'error', diff --git a/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx index 7451ea6ec0ca1..ed98a37775576 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/alerts_histogram_panel/index.tsx @@ -131,6 +131,7 @@ export const AlertsHistogramPanel = memo( totalAlertsObj.value, totalAlertsObj.relation === 'gte' ? '>' : totalAlertsObj.relation === 'lte' ? '<' : '' ), + // eslint-disable-next-line react-hooks/exhaustive-deps [totalAlertsObj] ); @@ -138,6 +139,7 @@ export const AlertsHistogramPanel = memo( setSelectedStackByOption( stackByOptions?.find((co) => co.value === event.target.value) ?? defaultStackByOption ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const formattedAlertsData = useMemo(() => formatAlertsData(alertsData), [alertsData]); @@ -154,6 +156,7 @@ export const AlertsHistogramPanel = memo( value: bucket.key, })) : NO_LEGEND_DATA, + // eslint-disable-next-line react-hooks/exhaustive-deps [alertsData, selectedStackByOption.value] ); @@ -175,6 +178,7 @@ export const AlertsHistogramPanel = memo( deleteQuery({ id: uniqueQueryId }); } }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { @@ -189,6 +193,7 @@ export const AlertsHistogramPanel = memo( refetch, }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [setQuery, isLoadingAlerts, alertsData, response, request, refetch]); useEffect(() => { @@ -219,6 +224,7 @@ export const AlertsHistogramPanel = memo( !isEmpty(converted) ? [converted] : [] ) ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedStackByOption.value, from, to, query, filters]); const linkButton = useMemo(() => { diff --git a/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx index 685e66e73ced2..2be20a9d47f67 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx @@ -117,6 +117,7 @@ export const AlertsTableComponent: React.FC = ({ }); } return null; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [browserFields, globalFilters, globalQuery, indexPatterns, kibana, to, from]); // Callback for creating a new timeline -- utilized by row/batch actions @@ -143,6 +144,7 @@ export const AlertsTableComponent: React.FC = ({ ({ eventIds, isLoading }: SetEventsLoadingProps) => { setEventsLoading!({ id: ALERTS_TABLE_TIMELINE_ID, eventIds, isLoading }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [setEventsLoading, ALERTS_TABLE_TIMELINE_ID] ); @@ -150,6 +152,7 @@ export const AlertsTableComponent: React.FC = ({ ({ eventIds, isDeleted }: SetEventsDeletedProps) => { setEventsDeleted!({ id: ALERTS_TABLE_TIMELINE_ID, eventIds, isDeleted }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [setEventsDeleted, ALERTS_TABLE_TIMELINE_ID] ); @@ -210,7 +213,7 @@ export const AlertsTableComponent: React.FC = ({ }, [setSelectAll, setShowClearSelectionAction]); const updateAlertsStatusCallback: UpdateAlertsStatusCallback = useCallback( - async (refetchQuery: inputsModel.Refetch, { alertIds, status }: UpdateAlertsStatusProps) => { + async (refetchQuery: inputsModel.Refetch, { status }: UpdateAlertsStatusProps) => { await updateAlertStatusAction({ query: showClearSelectionAction ? getGlobalQuery()?.filterQuery : undefined, alertIds: Object.keys(selectedEventIds), @@ -314,6 +317,7 @@ export const AlertsTableComponent: React.FC = ({ title: i18n.ALERTS_TABLE_TITLE, selectAll: canUserCRUD ? selectAll : false, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { setTimelineRowActions({ @@ -321,6 +325,7 @@ export const AlertsTableComponent: React.FC = ({ queryFields: requiredFieldsForActions, timelineRowActions: additionalActions, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [additionalActions]); const headerFilterGroup = useMemo( () => , diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/add_item_form/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/add_item_form/index.tsx index c8eb6f69c95ba..b0098d62cc9e5 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/add_item_form/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/add_item_form/index.tsx @@ -126,6 +126,7 @@ export const AddItem = ({ inputsRef.current[haveBeenKeyboardDeleted].focus(); setHaveBeenKeyboardDeleted(-1); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [haveBeenKeyboardDeleted, inputsRef.current]); const values = field.value as string[]; diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/mitre/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/mitre/index.tsx index 88edd0e795531..e898a362c7771 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/mitre/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/mitre/index.tsx @@ -40,7 +40,7 @@ interface AddItemProps { isDisabled: boolean; } -export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddItemProps) => { +export const AddMitreThreat = ({ field, idAria, isDisabled }: AddItemProps) => { const [showValidation, setShowValidation] = useState(false); const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); @@ -101,6 +101,7 @@ export const AddMitreThreat = ({ dataTestSubj, field, idAria, isDisabled }: AddI ...values.slice(index + 1), ]); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [field] ); diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/pick_timeline/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/pick_timeline/index.tsx index 0029e70e4edda..4b27daf3180ec 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/pick_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/pick_timeline/index.tsx @@ -39,6 +39,7 @@ export const PickTimeline = ({ setTimelineId(id); setTimelineTitle(title); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field.value]); const handleOnTimelineChange = useCallback( @@ -49,6 +50,7 @@ export const PickTimeline = ({ field.setValue({ id, title }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [field] ); diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/query_bar/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/query_bar/index.tsx index 82206b6ba5e3d..c53a9ccc22d8b 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/query_bar/index.tsx @@ -16,7 +16,6 @@ import { Query, FilterManager, SavedQuery, - SavedQueryTimeFilter, } from '../../../../../../../../src/plugins/data/public'; import { BrowserFields } from '../../../../common/containers/source'; @@ -111,6 +110,7 @@ export const QueryBarDefineRule = ({ isSubscribed = false; subscriptions.unsubscribe(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field.value]); useEffect(() => { @@ -143,10 +143,11 @@ export const QueryBarDefineRule = ({ return () => { isSubscribed = false; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field.value]); const onSubmitQuery = useCallback( - (newQuery: Query, timefilter?: SavedQueryTimeFilter) => { + (newQuery: Query) => { const { query } = field.value as FieldValueQueryBar; if (!deepEqual(query, newQuery)) { field.setValue({ ...(field.value as FieldValueQueryBar), query: newQuery }); @@ -179,6 +180,7 @@ export const QueryBarDefineRule = ({ } } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [field.value] ); @@ -214,7 +216,7 @@ export const QueryBarDefineRule = ({ [browserFields, field, indexPattern] ); - const onMutation = (event: unknown, observer: unknown) => { + const onMutation = () => { if (resizeParentContainer != null) { const suggestionContainer = document.getElementById('kbnTypeahead__items'); if (suggestionContainer != null) { diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_field/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_field/index.tsx index b77de683d5f20..c6ff25f311d9c 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_field/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_field/index.tsx @@ -56,6 +56,7 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables updatedActions[index] = deepMerge(updatedActions[index], { id }); field.setValue(updatedActions); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [field.setValue, actions] ); @@ -71,6 +72,7 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables updatedActions[index].params[key] = value; field.setValue(updatedActions); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [field.setValue, actions] ); @@ -82,6 +84,7 @@ export const RuleActionsField: ThrottleSelectField = ({ field, messageVariables ); setSupportedActionTypes(supportedTypes); })(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_overflow/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_overflow/index.tsx index 5a5156fa2b9a3..66f04c9bc6add 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_overflow/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/rule_actions_overflow/index.tsx @@ -101,6 +101,7 @@ const RuleActionsOverflowComponent = ({ , ] : [], + // eslint-disable-next-line react-hooks/exhaustive-deps [rule, userHasNoPermissions] ); diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/rule_switch/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/rule_switch/index.tsx index 79a16bfb386ec..c85676ce51052 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/rule_switch/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/rule_switch/index.tsx @@ -94,6 +94,7 @@ export const RuleSwitchComponent = ({ } setMyIsLoading(false); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [dispatch, id] ); @@ -101,12 +102,14 @@ export const RuleSwitchComponent = ({ if (myEnabled !== enabled) { setMyEnabled(enabled); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [enabled]); useEffect(() => { if (myIsLoading !== isLoading) { setMyIsLoading(isLoading ?? false); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLoading]); return ( diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/schedule_item_form/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/schedule_item_form/index.tsx index 9a4f9b25e01f4..bb33767f4f5d5 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/schedule_item_form/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/schedule_item_form/index.tsx @@ -78,6 +78,7 @@ export const ScheduleItem = ({ setTimeType(e.target.value); field.setValue(`${timeVal}${e.target.value}`); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [timeVal] ); @@ -87,6 +88,7 @@ export const ScheduleItem = ({ setTimeVal(sanitizedValue); field.setValue(`${sanitizedValue}${timeType}`); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [timeType] ); @@ -111,6 +113,7 @@ export const ScheduleItem = ({ setTimeType(filterTimeType[0]); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field.value]); // EUI missing some props diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/index.tsx index e41416f2a0ccb..f23c51e019f24 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/step_about_rule/index.tsx @@ -101,6 +101,7 @@ const StepAboutRuleComponent: FC = ({ setMyStepData({ ...data, isNew: false } as AboutStepRule); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); useEffect(() => { @@ -113,12 +114,14 @@ const StepAboutRuleComponent: FC = ({ setMyStepData(myDefaultValues); setFieldValue(form, schema, myDefaultValues); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultValues]); useEffect(() => { if (setForm != null) { setForm(RuleStep.aboutRule, form); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); return isReadOnlyView && myStepData.name != null ? ( diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/index.tsx index fc875908bd4ef..b56e1794eef63 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/index.tsx @@ -123,6 +123,7 @@ const StepDefineRuleComponent: FC = ({ setMyStepData({ ...data, isNew: false } as DefineStepRule); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); useEffect(() => { @@ -132,12 +133,14 @@ const StepDefineRuleComponent: FC = ({ setMyStepData(newValues); setFieldValue(form, schema, newValues); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultValues, setMyStepData, setFieldValue]); useEffect(() => { if (setForm != null) { setForm(RuleStep.defineRule, form); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); const handleResetIndices = useCallback(() => { diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/step_rule_actions/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/step_rule_actions/index.tsx index 778c6bd92bc73..9334bd59bebf5 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/step_rule_actions/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/step_rule_actions/index.tsx @@ -99,6 +99,7 @@ const StepRuleActionsComponent: FC = ({ } } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [form] ); @@ -112,12 +113,14 @@ const StepRuleActionsComponent: FC = ({ setMyStepData(myDefaultValues); setFieldValue(form, schema, myDefaultValues); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultValues]); useEffect(() => { if (setForm != null) { setForm(RuleStep.ruleActions, form); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); const updateThrottle = useCallback((throttle) => setMyStepData({ ...myStepData, throttle }), [ @@ -142,6 +145,7 @@ const StepRuleActionsComponent: FC = ({ options: throttleOptions, }, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [isLoading, updateThrottle] ); diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/step_schedule_rule/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/step_schedule_rule/index.tsx index fa49637a0c830..60855bc5fa25f 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/step_schedule_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/step_schedule_rule/index.tsx @@ -62,6 +62,7 @@ const StepScheduleRuleComponent: FC = ({ setMyStepData({ ...data, isNew: false } as ScheduleStepRule); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); useEffect(() => { @@ -74,12 +75,14 @@ const StepScheduleRuleComponent: FC = ({ setMyStepData(myDefaultValues); setFieldValue(form, schema, myDefaultValues); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultValues]); useEffect(() => { if (setForm != null) { setForm(RuleStep.scheduleRule, form); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); return isReadOnlyView && myStepData != null ? ( diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/throttle_select_field/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/throttle_select_field/index.tsx index 133f25ef3a03f..bf3498b28cd45 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/throttle_select_field/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/throttle_select_field/index.tsx @@ -31,6 +31,7 @@ export const ThrottleSelectField: ThrottleSelectField = (props) => { props.field.setValue(throttle); props.handleChange(throttle); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [props.field.setValue, props.handleChange] ); const newEuiFieldProps = { ...props.euiFieldProps, onChange }; diff --git a/x-pack/plugins/security_solution/public/alerts/components/user_info/index.tsx b/x-pack/plugins/security_solution/public/alerts/components/user_info/index.tsx index 8753064751f76..fc3fec7c29c1f 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/user_info/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/user_info/index.tsx @@ -171,18 +171,21 @@ export const useUserInfo = (): State => { if (loading !== privilegeLoading || indexNameLoading) { dispatch({ type: 'updateLoading', loading: privilegeLoading || indexNameLoading }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, privilegeLoading, indexNameLoading]); useEffect(() => { if (!loading && hasIndexManage !== hasApiIndexManage && hasApiIndexManage != null) { dispatch({ type: 'updateHasIndexManage', hasIndexManage: hasApiIndexManage }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, hasIndexManage, hasApiIndexManage]); useEffect(() => { if (!loading && hasIndexWrite !== hasApiIndexWrite && hasApiIndexWrite != null) { dispatch({ type: 'updateHasIndexWrite', hasIndexWrite: hasApiIndexWrite }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, hasIndexWrite, hasApiIndexWrite]); useEffect(() => { @@ -193,30 +196,35 @@ export const useUserInfo = (): State => { ) { dispatch({ type: 'updateIsSignalIndexExists', isSignalIndexExists: isApiSignalIndexExists }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, isSignalIndexExists, isApiSignalIndexExists]); useEffect(() => { if (!loading && isAuthenticated !== isApiAuthenticated && isApiAuthenticated != null) { dispatch({ type: 'updateIsAuthenticated', isAuthenticated: isApiAuthenticated }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, isAuthenticated, isApiAuthenticated]); useEffect(() => { if (!loading && hasEncryptionKey !== isApiEncryptionKey && isApiEncryptionKey != null) { dispatch({ type: 'updateHasEncryptionKey', hasEncryptionKey: isApiEncryptionKey }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, hasEncryptionKey, isApiEncryptionKey]); useEffect(() => { if (!loading && canUserCRUD !== capabilitiesCanUserCRUD && capabilitiesCanUserCRUD != null) { dispatch({ type: 'updateCanUserCRUD', canUserCRUD: capabilitiesCanUserCRUD }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, canUserCRUD, capabilitiesCanUserCRUD]); useEffect(() => { if (!loading && signalIndexName !== apiSignalIndexName && apiSignalIndexName != null) { dispatch({ type: 'updateSignalIndexName', signalIndexName: apiSignalIndexName }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loading, signalIndexName, apiSignalIndexName]); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_privilege_user.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_privilege_user.tsx index e67afd686a7ca..dda9b50239cde 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_privilege_user.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_privilege_user.tsx @@ -83,6 +83,7 @@ export const usePrivilegeUser = (): ReturnPrivilegeUser => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { loading, ...privilegeUser }; diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_signal_index.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_signal_index.tsx index 6c428bd9354ee..65a2721013b5e 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_signal_index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/alerts/use_signal_index.tsx @@ -103,6 +103,7 @@ export const useSignalIndex = (): ReturnSignalIndex => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { loading, ...signalIndex }; diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/fetch_index_patterns.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/fetch_index_patterns.tsx index 157f1490971f1..640d6f9a17fd1 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/fetch_index_patterns.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/fetch_index_patterns.tsx @@ -94,6 +94,7 @@ export const useFetchIndexPatterns = (defaultIndices: string[] = []): Return => isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [indices]); return [{ browserFields, isLoading, indices, indicesExists, indexPatterns }, setIndices]; diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/persist_rule.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/persist_rule.tsx index 03080bf68cbf5..fd139d59c0a27 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/persist_rule.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/persist_rule.tsx @@ -53,6 +53,7 @@ export const usePersistRule = (): ReturnPersistRule => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [rule]); return [{ isLoading, isSaved }, setRule]; diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_pre_packaged_rules.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_pre_packaged_rules.tsx index de4037ce7134c..5f5ee53c29caf 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_pre_packaged_rules.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_pre_packaged_rules.tsx @@ -185,6 +185,7 @@ export const usePrePackagedRules = ({ isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [canUserCRUD, hasIndexWrite, isAuthenticated, hasEncryptionKey, isSignalIndexExists]); return { diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule.tsx index 6ae5da3e56ff6..3256273fb8425 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule.tsx @@ -55,6 +55,7 @@ export const useRule = (id: string | undefined): ReturnRule => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [id]); return [loading, rule]; diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule_status.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule_status.tsx index b9f5e1f152c21..ec1da29de4ba8 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule_status.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rule_status.tsx @@ -64,6 +64,7 @@ export const useRuleStatus = (id: string | undefined | null): ReturnRuleStatus = isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [id]); return [loading, ruleStatus, fetchRuleStatus.current]; @@ -119,6 +120,7 @@ export const useRulesStatuses = (rules: Rules): ReturnRulesStatuses => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [rules]); return { loading, rulesStatuses }; diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rules.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rules.tsx index 3a074f2bc3785..1a1dbc6e2b368 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rules.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_rules.tsx @@ -46,7 +46,7 @@ export const useRules = ({ let isSubscribed = true; const abortCtrl = new AbortController(); - async function fetchData(forceReload: boolean = false) { + async function fetchData() { try { setLoading(true); const fetchRulesResult = await fetchRules({ @@ -80,7 +80,7 @@ export const useRules = ({ fetchData(); reFetchRules.current = (refreshPrePackagedRule: boolean = false) => { - fetchData(true); + fetchData(); if (refreshPrePackagedRule && refetchPrePackagedRulesStatus != null) { refetchPrePackagedRulesStatus(); } @@ -89,12 +89,14 @@ export const useRules = ({ isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ pagination.page, pagination.perPage, filterOptions.filter, filterOptions.sortField, filterOptions.sortOrder, + // eslint-disable-next-line react-hooks/exhaustive-deps filterOptions.tags?.sort().join(), filterOptions.showCustomRules, filterOptions.showElasticRules, diff --git a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_tags.tsx b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_tags.tsx index ebfe73f2f0863..038f974e1394e 100644 --- a/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_tags.tsx +++ b/x-pack/plugins/security_solution/public/alerts/containers/detection_engine/rules/use_tags.tsx @@ -53,6 +53,7 @@ export const useTags = (): ReturnTags => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return [loading, tags, reFetchTags.current]; diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/index.tsx index 9e61ec0eb3bcf..80ef5681189c5 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/index.tsx @@ -235,6 +235,7 @@ export const AllRules = React.memo( : [], reFetchRules: reFetchRulesData, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ dispatch, dispatchToaster, @@ -313,6 +314,7 @@ export const AllRules = React.memo( ))} ), + // eslint-disable-next-line react-hooks/exhaustive-deps [allRulesTabs, allRulesTab, setAllRulesTab] ); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx index 2bc19ae45a078..c65271c3cc014 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx @@ -45,6 +45,7 @@ const RulesTableFiltersComponent = ({ useEffect(() => { reFetchTags(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [rulesCustomInstalled, rulesInstalled]); // Propagate filter changes to parent diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/create/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/create/index.tsx index dd290ec1ae582..de7c99acee6e5 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/create/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/create/index.tsx @@ -114,6 +114,7 @@ const CreateRulePageComponent: React.FC = () => { const actionMessageParams = useMemo( () => getActionMessageParams((stepsData.current['define-rule'].data as DefineStepRule).ruleType), + // eslint-disable-next-line react-hooks/exhaustive-deps [stepsData.current['define-rule'].data] ); @@ -155,6 +156,7 @@ const CreateRulePageComponent: React.FC = () => { } } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [isStepRuleInReadOnlyView, openAccordionId, stepsData.current, setRule] ); @@ -171,6 +173,7 @@ const CreateRulePageComponent: React.FC = () => { } return 'passive'; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [openAccordionId, stepsData.current] ); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx index ebd6ed118f937..43792e8bd19f4 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx @@ -191,6 +191,7 @@ export const RuleDetailsPageComponent: FC = ({ ))} ), + // eslint-disable-next-line react-hooks/exhaustive-deps [ruleDetailTabs, ruleDetailTab, setRuleDetailTab] ); const ruleError = useMemo( @@ -203,6 +204,7 @@ export const RuleDetailsPageComponent: FC = ({ date={rule?.last_failure_at} /> ) : null, + // eslint-disable-next-line react-hooks/exhaustive-deps [rule, ruleDetailTab] ); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/edit/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/edit/index.tsx index 8fc646c01b17c..73e76165183c5 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/edit/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/edit/index.tsx @@ -104,6 +104,7 @@ const EditRulePageComponent: FC = () => { }); const [{ isLoading, isSaved }, setRule] = usePersistRule(); const [tabHasError, setTabHasError] = useState([]); + // eslint-disable-next-line react-hooks/exhaustive-deps const actionMessageParams = useMemo(() => getActionMessageParams(rule?.type), [rule]); const setStepsForm = useCallback( (step: RuleStep, form: FormHook) => { @@ -113,6 +114,7 @@ const EditRulePageComponent: FC = () => { form.submit(); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [initForm, selectedTab] ); const tabs = useMemo( @@ -206,6 +208,7 @@ const EditRulePageComponent: FC = () => { ), }, ], + // eslint-disable-next-line react-hooks/exhaustive-deps [ rule, loading, @@ -265,6 +268,7 @@ const EditRulePageComponent: FC = () => { } else { setTabHasError(invalidForms); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ stepsForm, myAboutRuleForm, @@ -320,6 +324,7 @@ const EditRulePageComponent: FC = () => { setInitForm(true); setSelectedTab(tab); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedTab, stepsForm.current] ); @@ -338,6 +343,7 @@ const EditRulePageComponent: FC = () => { useEffect(() => { const tabIndex = rule?.immutable ? 3 : 0; setSelectedTab(tabs[tabIndex]); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [rule]); if (isSaved) { diff --git a/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx b/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx index 277352c39df65..a57fae8081bea 100644 --- a/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx @@ -59,6 +59,7 @@ export const AddComment = React.memo( `${comment}${comment.length > 0 ? '\n\n' : ''}${insertQuote}` ); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [insertQuote]); const onSubmit = useCallback(async () => { @@ -67,9 +68,10 @@ export const AddComment = React.memo( if (onCommentSaving != null) { onCommentSaving(); } - await postComment(data, onCommentPosted); + postComment(data, onCommentPosted); form.reset(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form, onCommentPosted, onCommentSaving]); return ( diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx b/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx index 12f0d02eb10f6..32a7c4078071e 100644 --- a/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx @@ -134,6 +134,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { (refetchFilter: () => void) => { filterRefetch.current = refetchFilter; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [filterRefetch.current] ); const refreshCases = useCallback( @@ -146,6 +147,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { filterRefetch.current(); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [filterOptions, queryParams, filterRefetch.current] ); @@ -158,6 +160,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { refreshCases(); dispatchResetIsUpdated(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isDeleted, isUpdated]); const confirmDeleteModal = useMemo( () => ( @@ -172,12 +175,14 @@ export const AllCases = React.memo(({ userCanCrud }) => { )} /> ), + // eslint-disable-next-line react-hooks/exhaustive-deps [deleteBulk, deleteThisCase, isDisplayConfirmDeleteModal] ); const toggleDeleteModal = useCallback((deleteCase: Case) => { handleToggleModal(); setDeleteThisCase(deleteCase); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const toggleBulkDeleteModal = useCallback( @@ -192,6 +197,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { const convertToDeleteCases: DeleteCase[] = caseIds.map((id) => ({ id })); setDeleteBulk(convertToDeleteCases); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedCases] ); @@ -199,6 +205,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { (status: string) => { updateBulkStatus(selectedCases, status); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedCases] ); @@ -220,6 +227,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { })} /> ), + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedCaseIds, filterOptions.status, toggleBulkDeleteModal] ); const handleDispatchUpdate = useCallback( @@ -261,6 +269,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { setQueryParams(newQueryParams); refreshCases(false); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [queryParams] ); @@ -274,6 +283,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { setFilters(newFilterOptions); refreshCases(false); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [filterOptions, queryParams] ); @@ -296,6 +306,7 @@ export const AllCases = React.memo(({ userCanCrud }) => { }; const euiBasicTableSelectionProps = useMemo>( () => ({ onSelectionChange: setSelectedCases }), + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedCases] ); const isCasesLoading = useMemo( diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases/table_filters.tsx b/x-pack/plugins/security_solution/public/cases/components/all_cases/table_filters.tsx index 42340b455c3af..63172bd6ad6bb 100644 --- a/x-pack/plugins/security_solution/public/cases/components/all_cases/table_filters.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases/table_filters.tsx @@ -66,12 +66,14 @@ const CasesTableFiltersComponent = ({ const newReporters = selectedReporters.filter((r) => reporters.includes(r)); handleSelectedReporters(newReporters); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [reporters]); useEffect(() => { if (selectedTags.length) { const newTags = selectedTags.filter((t) => tags.includes(t)); handleSelectedTags(newTags); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [tags]); const handleSelectedReporters = useCallback( @@ -84,6 +86,7 @@ const CasesTableFiltersComponent = ({ onFilterChanged({ reporters: reportersObj }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedReporters, respReporters] ); @@ -94,6 +97,7 @@ const CasesTableFiltersComponent = ({ onFilterChanged({ tags: newTags }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedTags] ); const handleOnSearch = useCallback( @@ -104,6 +108,7 @@ const CasesTableFiltersComponent = ({ onFilterChanged({ search: trimSearch }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [search] ); const handleToggleFilter = useCallback( @@ -113,6 +118,7 @@ const CasesTableFiltersComponent = ({ onFilterChanged({ status: showOpen ? 'open' : 'closed' }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [showOpenCases] ); return ( diff --git a/x-pack/plugins/security_solution/public/cases/components/case_view/actions.tsx b/x-pack/plugins/security_solution/public/cases/components/case_view/actions.tsx index cd9318a355e3c..df1082ec48f91 100644 --- a/x-pack/plugins/security_solution/public/cases/components/case_view/actions.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/case_view/actions.tsx @@ -44,6 +44,7 @@ const CaseViewActionsComponent: React.FC = ({ onConfirm={handleOnDeleteConfirm.bind(null, [{ id: caseData.id, title: caseData.title }])} /> ), + // eslint-disable-next-line react-hooks/exhaustive-deps [isDisplayConfirmDeleteModal, caseData] ); const propertyActions = useMemo( diff --git a/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors.tsx b/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors.tsx index 947d68fd04f7b..b8151cb6fe18c 100644 --- a/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors.tsx @@ -68,6 +68,7 @@ const ConnectorsComponent: React.FC = ({ ), + // eslint-disable-next-line react-hooks/exhaustive-deps [connectorsName, updateConnectorDisabled] ); diff --git a/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors_dropdown.tsx b/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors_dropdown.tsx index c5481f592e750..018d3a0fdb4e0 100644 --- a/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors_dropdown.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/configure_cases/connectors_dropdown.tsx @@ -91,6 +91,7 @@ const ConnectorsDropdownComponent: React.FC = ({ } return connectorsFormatted; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [connectors]); return ( diff --git a/x-pack/plugins/security_solution/public/cases/components/configure_cases/field_mapping.tsx b/x-pack/plugins/security_solution/public/cases/components/configure_cases/field_mapping.tsx index 415faa96eeedd..fe5c0c19820a1 100644 --- a/x-pack/plugins/security_solution/public/cases/components/configure_cases/field_mapping.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/configure_cases/field_mapping.tsx @@ -95,6 +95,7 @@ const FieldMappingComponent: React.FC = ({ const myMapping = mapping ?? defaultMapping; onChangeMapping(setActionTypeToMapping(caseField, newActionType, myMapping)); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [mapping] ); @@ -103,6 +104,7 @@ const FieldMappingComponent: React.FC = ({ const myMapping = mapping ?? defaultMapping; onChangeMapping(setThirdPartyToMapping(caseField, newThirdPartyField, myMapping)); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [mapping] ); diff --git a/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx b/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx index 6e1ef293fd5c4..256c8893be941 100644 --- a/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/configure_cases/index.tsx @@ -77,6 +77,7 @@ const ConfigureCasesComponent: React.FC = ({ userC // ActionsConnectorsContextProvider reloadConnectors prop expects a Promise. // TODO: Fix it if reloadConnectors type change. + // eslint-disable-next-line react-hooks/exhaustive-deps const reloadConnectors = useCallback(async () => refetchConnectors(), []); const isLoadingAny = isLoadingConnectors || persistLoading || loadingCaseConfigure; const updateConnectorDisabled = isLoadingAny || !connectorIsValid || connectorId === 'none'; @@ -89,6 +90,7 @@ const ConfigureCasesComponent: React.FC = ({ userC (isVisible: boolean) => { setAddFlyoutVisibility(isVisible); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [currentConfiguration, connectorId, closureType] ); @@ -96,6 +98,7 @@ const ConfigureCasesComponent: React.FC = ({ userC (isVisible: boolean) => { setEditFlyoutVisibility(isVisible); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [currentConfiguration, connectorId, closureType] ); @@ -113,6 +116,7 @@ const ConfigureCasesComponent: React.FC = ({ userC closureType, }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [connectorId, closureType, version] ); @@ -125,6 +129,7 @@ const ConfigureCasesComponent: React.FC = ({ userC closureType: type, }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [connectorId, closureType, version] ); @@ -141,6 +146,7 @@ const ConfigureCasesComponent: React.FC = ({ userC ) { setConnectorIsValid(true); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [connectors, connectorId]); useEffect(() => { @@ -149,6 +155,7 @@ const ConfigureCasesComponent: React.FC = ({ userC connectors.find((c) => c.id === connectorId) as ActionConnectorTableItem ); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [connectors, connectorId]); return ( diff --git a/x-pack/plugins/security_solution/public/cases/components/connector_selector/form.tsx b/x-pack/plugins/security_solution/public/cases/components/connector_selector/form.tsx index 9e058ee5cf09e..1706fa38bb8a0 100644 --- a/x-pack/plugins/security_solution/public/cases/components/connector_selector/form.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/connector_selector/form.tsx @@ -33,6 +33,7 @@ export const ConnectorSelector = ({ useEffect(() => { field.setValue(defaultValue); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultValue]); const handleContentChange = useCallback( diff --git a/x-pack/plugins/security_solution/public/cases/components/create/index.tsx b/x-pack/plugins/security_solution/public/cases/components/create/index.tsx index ae0ffe498c391..1b65b2582c760 100644 --- a/x-pack/plugins/security_solution/public/cases/components/create/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/create/index.tsx @@ -91,8 +91,10 @@ export const Create = React.memo(() => { const onSubmit = useCallback(async () => { const { isValid, data } = await form.submit(); if (isValid) { + // `postCase`'s type is incorrect, it actually returns a promise await postCase(data); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [form]); const handleSetIsCancel = useCallback(() => { diff --git a/x-pack/plugins/security_solution/public/cases/components/open_closed_stats/index.tsx b/x-pack/plugins/security_solution/public/cases/components/open_closed_stats/index.tsx index b9dab13090aca..e7d5299842494 100644 --- a/x-pack/plugins/security_solution/public/cases/components/open_closed_stats/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/open_closed_stats/index.tsx @@ -24,6 +24,7 @@ export const OpenClosedStats = React.memo( description: isLoading ? : caseCount ?? 'N/A', }, ], + // eslint-disable-next-line react-hooks/exhaustive-deps [caseCount, caseStatus, isLoading, dataTestSubj] ); return ( diff --git a/x-pack/plugins/security_solution/public/cases/components/use_push_to_service/index.tsx b/x-pack/plugins/security_solution/public/cases/components/use_push_to_service/index.tsx index 2e9e3cce4306a..f18870787ded1 100644 --- a/x-pack/plugins/security_solution/public/cases/components/use_push_to_service/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/use_push_to_service/index.tsx @@ -141,6 +141,7 @@ export const usePushToService = ({ errors = [...errors, getKibanaConfigError()]; } return errors; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [actionLicense, caseStatus, connectors.length, caseConnectorId, loadingLicense, urlSearch]); const pushToServiceButton = useMemo(() => { @@ -160,6 +161,7 @@ export const usePushToService = ({ : i18n.PUSH_THIRD(caseConnectorName)} ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ caseConnectorId, caseConnectorName, diff --git a/x-pack/plugins/security_solution/public/cases/components/user_action_tree/index.tsx b/x-pack/plugins/security_solution/public/cases/components/user_action_tree/index.tsx index da49014eb0204..52c2779a93fc0 100644 --- a/x-pack/plugins/security_solution/public/cases/components/user_action_tree/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/user_action_tree/index.tsx @@ -85,6 +85,7 @@ export const UserActionTree = React.memo( updateCase, }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [caseData, handleManageMarkdownEditId, patchComment, updateCase] ); @@ -109,6 +110,7 @@ export const UserActionTree = React.memo( window.clearTimeout(handlerTimeoutId.current); }, 2400); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [handlerTimeoutId.current] ); @@ -155,6 +157,7 @@ export const UserActionTree = React.memo( showLoading={false} /> ), + // eslint-disable-next-line react-hooks/exhaustive-deps [caseData.id, handleUpdate, insertQuote, userCanCrud] ); @@ -165,6 +168,7 @@ export const UserActionTree = React.memo( handleOutlineComment(commentId); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [commentId, initLoading, isLoadingUserActions, isLoadingIds]); return ( <> diff --git a/x-pack/plugins/security_solution/public/cases/components/user_action_tree/user_action_markdown.tsx b/x-pack/plugins/security_solution/public/cases/components/user_action_tree/user_action_markdown.tsx index 03dd599da88e5..b3a5f1e0158d8 100644 --- a/x-pack/plugins/security_solution/public/cases/components/user_action_tree/user_action_markdown.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/user_action_tree/user_action_markdown.tsx @@ -74,6 +74,7 @@ export const UserActionMarkdown = ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [apolloClient] ); @@ -114,6 +115,7 @@ export const UserActionMarkdown = ({ ); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [handleCancelAction, handleSaveAction] ); return isEditable ? ( diff --git a/x-pack/plugins/security_solution/public/cases/components/user_list/index.tsx b/x-pack/plugins/security_solution/public/cases/components/user_list/index.tsx index 0606da371d16a..86ff42561c409 100644 --- a/x-pack/plugins/security_solution/public/cases/components/user_list/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/user_list/index.tsx @@ -84,6 +84,7 @@ export const UserList = React.memo(({ email, headline, loading, users }: UserLis window.open(`mailto:${emailAddress}?subject=${email.subject}&body=${email.body}`, '_blank'); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [email.subject] ); return users.filter(({ username }) => username != null && username !== '').length > 0 ? ( diff --git a/x-pack/plugins/security_solution/public/cases/containers/configure/use_configure.tsx b/x-pack/plugins/security_solution/public/cases/containers/configure/use_configure.tsx index 5a85a3a0633bc..e89212036ec20 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/configure/use_configure.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/configure/use_configure.tsx @@ -253,6 +253,7 @@ export const useCaseConfigure = (): ReturnUseCaseConfigure => { didCancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [state.firstLoad]); const persistCaseConfigure = useCallback( @@ -311,11 +312,13 @@ export const useCaseConfigure = (): ReturnUseCaseConfigure => { abortCtrl.abort(); }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [state.version] ); useEffect(() => { refetchCaseConfigure(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { diff --git a/x-pack/plugins/security_solution/public/cases/containers/configure/use_connectors.tsx b/x-pack/plugins/security_solution/public/cases/containers/configure/use_connectors.tsx index 9cd755864d37b..812e580ad653f 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/configure/use_connectors.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/configure/use_connectors.tsx @@ -50,10 +50,12 @@ export const useConnectors = (): ReturnConnectors => { didCancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { refetchConnectors(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_bulk_update_case.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_bulk_update_case.tsx index ef68f4f48b1a0..c333ff4207833 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_bulk_update_case.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_bulk_update_case.tsx @@ -108,6 +108,7 @@ export const useUpdateCases = (): UseUpdateCases => { cancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const dispatchResetIsUpdated = useCallback(() => { @@ -121,6 +122,7 @@ export const useUpdateCases = (): UseUpdateCases => { version: theCase.version, })); dispatchUpdateCases(updateCasesStatus); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { ...state, updateBulkStatus, dispatchResetIsUpdated }; }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_delete_cases.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_delete_cases.tsx index 2e8c7dfae2313..f47e9e51f865a 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_delete_cases.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_delete_cases.tsx @@ -110,6 +110,7 @@ export const useDeleteCases = (): UseDeleteCase => { abortCtrl.abort(); cancel = true; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const dispatchToggleDeleteModal = useCallback(() => { @@ -118,6 +119,7 @@ export const useDeleteCases = (): UseDeleteCase => { const dispatchResetIsDeleted = useCallback(() => { dispatch({ type: 'RESET_IS_DELETED' }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [state.isDisplayConfirmDeleteModal]); const handleOnDeleteConfirm = useCallback( @@ -125,10 +127,12 @@ export const useDeleteCases = (): UseDeleteCase => { dispatchDeleteCases(cases); dispatchToggleDeleteModal(); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [state.isDisplayConfirmDeleteModal] ); const handleToggleModal = useCallback(() => { dispatchToggleDeleteModal(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [state.isDisplayConfirmDeleteModal]); return { ...state, dispatchResetIsDeleted, handleOnDeleteConfirm, handleToggleModal }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_action_license.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_action_license.tsx index 563e2a4a58c70..e289a1973cf6e 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_action_license.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_action_license.tsx @@ -65,10 +65,12 @@ export const useGetActionLicense = (): ActionLicenseState => { didCancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [actionLicenseState]); useEffect(() => { fetchActionLicense(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { ...actionLicenseState }; }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_case.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_case.tsx index 01ada00ba9b72..ea4da41151993 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_case.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_case.tsx @@ -118,10 +118,12 @@ export const useGetCase = (caseId: string): UseGetCase => { didCancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [caseId]); useEffect(() => { callFetch(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [caseId]); return { ...state, fetchCase: callFetch, updateCase }; }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_case_user_actions.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_case_user_actions.tsx index 050b2815dc511..76d939de06a0a 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_case_user_actions.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_case_user_actions.tsx @@ -210,6 +210,7 @@ export const useGetCaseUserActions = ( abortCtrl.abort(); }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [caseUserActionsState, caseConnectorId] ); @@ -217,6 +218,7 @@ export const useGetCaseUserActions = ( if (!isEmpty(caseId)) { fetchCaseUserActions(caseId); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [caseId, caseConnectorId]); return { ...caseUserActionsState, fetchCaseUserActions }; }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_cases.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_cases.tsx index 45b571a8fe7e2..fdf526a1e4d88 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_cases.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_cases.tsx @@ -184,8 +184,10 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { abortCtrl.abort(); didCancel = true; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => fetchCases(state.filterOptions, state.queryParams), [ state.queryParams, state.filterOptions, @@ -224,11 +226,13 @@ export const useGetCases = (initialQueryParams?: QueryParams): UseGetCases => { didCancel = true; }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [state.filterOptions, state.queryParams] ); const refetchCases = useCallback(() => { fetchCases(state.filterOptions, state.queryParams); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [state.filterOptions, state.queryParams]); return { diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_cases_status.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_cases_status.tsx index 476462b7e4c28..5260b6d5cc283 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_cases_status.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_cases_status.tsx @@ -69,10 +69,12 @@ export const useGetCasesStatus = (): UseGetCasesStatus => { didCancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [casesStatusState]); useEffect(() => { fetchCasesStatus(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_reporters.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_reporters.tsx index d723b8cc37c23..b4ca775660910 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_reporters.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_reporters.tsx @@ -79,10 +79,12 @@ export const useGetReporters = (): UseGetReporters => { didCancel = true; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [reportersState]); useEffect(() => { fetchReporters(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { ...reportersState, fetchReporters }; }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_get_tags.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_get_tags.tsx index 14f5e35bc4976..eded326719e52 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_get_tags.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_get_tags.tsx @@ -89,6 +89,7 @@ export const useGetTags = (): UseGetTags => { }; useEffect(() => { callFetch(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { ...state, fetchTags: callFetch }; }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_post_case.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_post_case.tsx index 13cfc2738620f..0752fe9b2071c 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_post_case.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_post_case.tsx @@ -86,6 +86,7 @@ export const usePostCase = (): UsePostCase => { abortCtrl.abort(); cancel = true; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { ...state, postCase: postMyCase }; diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_post_comment.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_post_comment.tsx index 9a52eaaf0db6b..e6cb8a9c3d150 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_post_comment.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_post_comment.tsx @@ -79,6 +79,7 @@ export const usePostComment = (caseId: string): UsePostComment => { cancel = true; }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [caseId] ); diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.tsx index 4d25ac7fbf0db..0d8a4c04ca7cd 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.tsx @@ -146,6 +146,7 @@ export const usePostPushToService = (): UsePostPushToService => { abortCtrl.abort(); }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_update_case.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_update_case.tsx index 77cf53165d914..18dd9f5278503 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_update_case.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_update_case.tsx @@ -118,6 +118,7 @@ export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => abortCtrl.abort(); }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_update_comment.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_update_comment.tsx index 821fd5523a751..f896185dbccfb 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_update_comment.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_update_comment.tsx @@ -111,6 +111,7 @@ export const useUpdateComment = (): UseUpdateComment => { abortCtrl.abort(); }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx b/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx index b19343a9f4a5c..bb6ba01821835 100644 --- a/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx @@ -69,6 +69,7 @@ const AlertsTableComponent: React.FC = ({ endDate, startDate, pageFilters title: i18n.ALERTS_TABLE_TITLE, unit: i18n.UNIT, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( { const isDarkMode = useUiSetting(DEFAULT_DARK_MODE); const defaultTheme = isDarkMode ? DARK_THEME : LIGHT_THEME; + // eslint-disable-next-line react-hooks/exhaustive-deps const themeValue = useMemo(() => mergeWithDefaultTheme(theme, defaultTheme), []); return themeValue; diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx index c33677e41db0e..32f05e7c837a7 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -126,6 +126,7 @@ export const DragDropContextWrapperComponent = React.memo( () => () => { unRegisterProvider(); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx index 998d18291f638..4eeefdbe2fca0 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx @@ -63,6 +63,7 @@ const DraggableWrapperHoverContentComponent: React.FC = ({ onFilterAdded(); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field, value, filterManager, onFilterAdded]); const filterOutValue = useCallback(() => { @@ -77,6 +78,7 @@ const DraggableWrapperHoverContentComponent: React.FC = ({ onFilterAdded(); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [field, value, filterManager, onFilterAdded]); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index d0bd87188e541..6b4baac0ff26c 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -103,9 +103,11 @@ const EventsViewerComponent: React.FC = ({ } = useManageTimeline(); useEffect(() => { setIsTimelineLoading({ id, isLoading: isQueryLoading }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isQueryLoading]); useEffect(() => { setTimelineFilterManager({ id, filterManager }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [filterManager]); const { queryFields, title, unit } = useMemo(() => getManageTimelineById(id), [ diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index ec726cd603579..9f1d71108e2f1 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -74,6 +74,7 @@ const StatefulEventsViewerComponent: React.FC = ({ return () => { deleteEventQuery({ id, inputId: 'global' }); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onChangeItemsPerPage: OnChangeItemsPerPage = useCallback( diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.tsx index d0236adc27c6c..fa21d61b06ebe 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.tsx @@ -109,6 +109,7 @@ const ExceptionEntriesComponent = ({ }, }, ], + // eslint-disable-next-line react-hooks/exhaustive-deps [entries] ); diff --git a/x-pack/plugins/security_solution/public/common/components/generic_downloader/index.tsx b/x-pack/plugins/security_solution/public/common/components/generic_downloader/index.tsx index 2f68da0c18727..2e8d5f77afc83 100644 --- a/x-pack/plugins/security_solution/public/common/components/generic_downloader/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/generic_downloader/index.tsx @@ -95,6 +95,7 @@ export const GenericDownloaderComponent = ({ isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ids]); return ; diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx b/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx index 0c6f7258d09dc..6f6c94a0b1124 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx @@ -57,6 +57,7 @@ const EditableTitleComponent: React.FC = ({ onSubmit(changedTitle); } setEditMode(false); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [changedTitle, title]); const handleOnChange = useCallback( diff --git a/x-pack/plugins/security_solution/public/common/components/help_menu/index.tsx b/x-pack/plugins/security_solution/public/common/components/help_menu/index.tsx index ba9c136445983..56f0c825aa59e 100644 --- a/x-pack/plugins/security_solution/public/common/components/help_menu/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/help_menu/index.tsx @@ -45,6 +45,7 @@ export const HelpMenu = React.memo(() => { }, ], }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return null; diff --git a/x-pack/plugins/security_solution/public/common/components/import_data_modal/index.tsx b/x-pack/plugins/security_solution/public/common/components/import_data_modal/index.tsx index c4e0a0de5ae81..a42628cecff8e 100644 --- a/x-pack/plugins/security_solution/public/common/components/import_data_modal/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/import_data_modal/index.tsx @@ -109,6 +109,7 @@ export const ImportDataModalComponent = ({ errorToToaster({ title: errorMessage, error, dispatchToaster }); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedFiles, overwrite]); const handleCloseModal = useCallback(() => { diff --git a/x-pack/plugins/security_solution/public/common/components/links/index.tsx b/x-pack/plugins/security_solution/public/common/components/links/index.tsx index 8a41d4c36edbb..637f0d8d53057 100644 --- a/x-pack/plugins/security_solution/public/common/components/links/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links/index.tsx @@ -242,6 +242,7 @@ const ReputationLinkComponent: React.FC<{ name: isDefaultReputationLink(name) ? defaultNameMapping[name] : name, url_template: url_template.replace(`{{ip}}`, encodeURIComponent(domain)), })), + // eslint-disable-next-line react-hooks/exhaustive-deps [ipReputationLinksSetting, domain, defaultNameMapping, allItemsLimit] ); diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/index.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/index.tsx index b0df2b6b5b60f..d92952992d997 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/index.tsx @@ -135,6 +135,7 @@ export const MarkdownEditor = React.memo<{ ), }, ], + // eslint-disable-next-line react-hooks/exhaustive-deps [content, isDisabled, placeholder] ); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx index 08edae208fefa..3e196c4b7bad4 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.tsx @@ -19,12 +19,7 @@ import { MatrixLoader } from './matrix_loader'; import { Panel } from '../panel'; import { getBarchartConfigs, getCustomChartData } from './utils'; import { useQuery } from '../../containers/matrix_histogram'; -import { - MatrixHistogramProps, - MatrixHistogramOption, - HistogramAggregation, - MatrixHistogramQueryProps, -} from './types'; +import { MatrixHistogramProps, MatrixHistogramOption, MatrixHistogramQueryProps } from './types'; import { InspectButtonContainer } from '../inspect'; import { State, inputsSelectors } from '../../store'; @@ -125,6 +120,7 @@ export const MatrixHistogramComponent: React.FC< yTickFormatter, showLegend, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [ chartHeight, startDate, @@ -145,21 +141,20 @@ export const MatrixHistogramComponent: React.FC< stackByOptions.find((co) => co.value === event.target.value) ?? defaultStackByOption ); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); - const { data, loading, inspect, totalCount, refetch = noop } = useQuery<{}, HistogramAggregation>( - { - endDate, - errorMessage, - filterQuery, - histogramType, - indexToAdd, - startDate, - isInspected, - stackByField: selectedStackByOption.value, - } - ); + const { data, loading, inspect, totalCount, refetch = noop } = useQuery({ + endDate, + errorMessage, + filterQuery, + histogramType, + indexToAdd, + startDate, + isInspected, + stackByField: selectedStackByOption.value, + }); const titleWithStackByField = useMemo( () => (title != null && typeof title === 'function' ? title(selectedStackByOption) : title), @@ -260,7 +255,7 @@ export const MatrixHistogram = React.memo(MatrixHistogramComponent); const makeMapStateToProps = () => { const getQuery = inputsSelectors.globalQueryByIdSelector(); - const mapStateToProps = (state: State, { type, id }: OwnProps) => { + const mapStateToProps = (state: State, { id }: OwnProps) => { const { isInspected } = getQuery(state, id); return { isInspected, diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts index e30f1e9374c26..a9e6cdd19bb20 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/types.ts @@ -99,12 +99,6 @@ export interface GroupBucket { }; } -export interface HistogramAggregation { - histogramAgg: { - buckets: GroupBucket[]; - }; -} - export interface BarchartConfigs { series: { xScaleType: ScaleType; diff --git a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts index a76c4c850b8d9..8568c7e6b5575 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts @@ -121,13 +121,17 @@ export const useAnomaliesTableData = ({ isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ + // eslint-disable-next-line react-hooks/exhaustive-deps influencersOrCriteriaToString(influencers), + // eslint-disable-next-line react-hooks/exhaustive-deps influencersOrCriteriaToString(criteriaFields), startDate, endDate, skip, userPermissions, + // eslint-disable-next-line react-hooks/exhaustive-deps siemJobIds.sort().join(), ]); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/permissions/ml_capabilities_provider.tsx b/x-pack/plugins/security_solution/public/common/components/ml/permissions/ml_capabilities_provider.tsx index 1d5c1b36e22af..c83271a56be5a 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/permissions/ml_capabilities_provider.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/permissions/ml_capabilities_provider.tsx @@ -60,6 +60,7 @@ export const MlCapabilitiesProvider = React.memo<{ children: JSX.Element }>(({ c isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_siem_jobs.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_siem_jobs.tsx index a84d88782926c..7f0a8dea1913e 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_siem_jobs.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/hooks/use_siem_jobs.tsx @@ -74,6 +74,7 @@ export const useSiemJobs = (refetchData: boolean): Return => { isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [refetchData, userPermissions]); return [loading, siemJobs]; diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/groups_filter_popover.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/groups_filter_popover.tsx index dd6e2d3f47110..de4185c8644a7 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/groups_filter_popover.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/groups_filter_popover.tsx @@ -46,6 +46,7 @@ export const GroupsFilterPopoverComponent = ({ useEffect(() => { onSelectedGroupsChanged(selectedGroups); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedGroups.sort().join()]); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index e0a24a5fc083c..0cbff9e70eff7 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -54,6 +54,7 @@ export const SiemNavigationComponent: React.FC< chrome ); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [chrome, pathName, search, navTabs, urlState, state]); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index b0b9309b44c68..a182102329f05 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -134,6 +134,7 @@ const SearchBarComponent = memo( window.setTimeout(() => updateSearch(updateSearchBar), 0); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [id, end, filterQuery, fromStr, queries, start, toStr] ); @@ -153,6 +154,7 @@ const SearchBarComponent = memo( queries.forEach((q) => q.refetch && (q.refetch as inputsModel.Refetch)()); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [id, queries, filterManager] ); @@ -160,6 +162,7 @@ const SearchBarComponent = memo( (newSavedQuery: SavedQuery) => { setSavedQuery({ id, savedQuery: newSavedQuery }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -196,6 +199,7 @@ const SearchBarComponent = memo( updateSearch(updateSearchBar); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [id, end, fromStr, start, toStr] ); @@ -218,6 +222,7 @@ const SearchBarComponent = memo( filterManager, }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [id, end, filterManager, fromStr, start, toStr, savedQuery]); useEffect(() => { @@ -241,6 +246,7 @@ const SearchBarComponent = memo( isSubscribed = false; subscriptions.unsubscribe(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const indexPatterns = useMemo(() => [indexPattern], [indexPattern]); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/stat_items/index.tsx b/x-pack/plugins/security_solution/public/common/components/stat_items/index.tsx index ec9cfc62ebada..dee730059b03a 100644 --- a/x-pack/plugins/security_solution/public/common/components/stat_items/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/stat_items/index.tsx @@ -183,6 +183,7 @@ export const useKpiMatrixStatus = ( }; }) ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [data]); return statItemsProps; diff --git a/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.tsx b/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.tsx index 6b979df653eb4..84ff1120f6496 100644 --- a/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.tsx @@ -117,6 +117,7 @@ export const SuperDatePickerComponent = React.memo( refetchQuery(queries); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [end, id, isQuickSelection, kqlQuery, start, timelineId] ); @@ -136,6 +137,7 @@ export const SuperDatePickerComponent = React.memo( refetchQuery(queries); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [id, isQuickSelection, duration, policy, toStr] ); @@ -175,6 +177,7 @@ export const SuperDatePickerComponent = React.memo( setIsQuickSelection(newIsQuickSelection); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [recentlyUsedRanges, kqlQuery] ); diff --git a/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx index 944e8f6d1fb39..35036ef4b16b5 100644 --- a/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/toasters/index.test.tsx @@ -69,6 +69,7 @@ describe('Toaster', () => { if (toasts.length === 0) { dispatch({ type: 'addToaster', toast: mockToast }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( <> diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx index 3e83866c7cf62..c28f5ab8aa44f 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx @@ -109,6 +109,7 @@ const StatefulTopNComponent: React.FC = ({ isManagedTimeline(ACTIVE_TIMELINE_REDUX_ID) ? getManageTimelineById(ACTIVE_TIMELINE_REDUX_ID) : { documentType: null, id: null, indexToAdd: null }, + // eslint-disable-next-line react-hooks/exhaustive-deps [getManageTimelineById] ); diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx index b3436a7da8297..ef60967e70ac3 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx @@ -46,7 +46,6 @@ export const useUrlStateHooks = ({ pathName, search, setInitialStateFromUrl, - tabName, updateTimeline, updateTimelineIsLoading, urlState, @@ -206,10 +205,12 @@ export const useUrlStateHooks = ({ } else if (pathName !== prevProps.pathName) { handleInitialize(type, pageName === SiemPageName.detections); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isInitializing, history, pathName, pageName, prevProps, urlState]); useEffect(() => { document.title = `${getTitle(pageName, detailName, navTabs)} - Kibana`; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [pageName]); return null; diff --git a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx index a5574bd2a57c7..0beecc500e722 100644 --- a/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/anomalies/anomalies_query_tab_body/index.tsx @@ -35,6 +35,7 @@ export const AnomaliesQueryTabBody = ({ deleteQuery({ id: ID }); } }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const [, siemJobs] = useSiemJobs(true); diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts index 260b13c23f39c..6050dafc0b191 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts @@ -33,7 +33,7 @@ export interface OwnProps extends QueryTemplateProps { indexKey: LastEventIndexKey; } -export function useLastEventTimeQuery( +export function useLastEventTimeQuery( indexKey: LastEventIndexKey, details: LastTimeDetails, sourceId: string @@ -84,6 +84,7 @@ export function useLastEventTimeQuery( const signal = abortCtrl.signal; fetchLastEventTime(signal); return () => abortCtrl.abort(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [apolloClient, indexKey, details.hostName, details.ip]); return { lastSeen, loading, errorMessage }; diff --git a/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx b/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx index 4632e9aee3fdd..9b9b5c5d815b9 100644 --- a/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/global_time/index.tsx @@ -59,6 +59,7 @@ export const GlobalTimeComponent: React.FC = ({ return () => { deleteAllQuery({ id: 'global' }); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts index c675c2745c66a..8c7acfc18ece6 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts @@ -17,7 +17,7 @@ import { inputsModel } from '../../store'; import { MatrixHistogramGqlQuery } from './index.gql_query'; import { GetMatrixHistogramQuery, MatrixOverTimeHistogramData } from '../../../graphql/types'; -export const useQuery = ({ +export const useQuery = ({ endDate, errorMessage, filterQuery, @@ -102,6 +102,7 @@ export const useQuery = ({ isSubscribed = false; abortCtrl.abort(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ defaultIndex, errorMessage, diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx index 26fb14c6a9c1e..ad480ad2c496b 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx @@ -75,7 +75,7 @@ export const getIndexFields = memoizeOne( ); export const getBrowserFields = memoizeOne( - (title: string, fields: IndexField[]): BrowserFields => + (_title: string, fields: IndexField[]): BrowserFields => fields && fields.length > 0 ? fields.reduce( (accumulator: BrowserFields, field: IndexField) => @@ -173,6 +173,7 @@ export const useWithSource = (sourceId: string, indices: string[]) => { const signal = abortCtrl.signal; fetchSource(signal); return () => abortCtrl.abort(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [apolloClient, sourceId, indices]); return { indicesExist, browserFields, indexPattern, loading, errorMessage }; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_add_to_timeline.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_add_to_timeline.tsx index b73c400bc0460..eba8d14d60538 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_add_to_timeline.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_add_to_timeline.tsx @@ -159,6 +159,7 @@ export const useAddToTimeline = ({ document.body.classList.remove(IS_DRAGGING_CLASS_NAME); // it was not possible to perform a drag and drop } }, 0); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [_sensorApiSingleton, draggableId]); return startDragToTimeline; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_index_patterns.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_index_patterns.tsx index 05b0521e35217..837d6d5f70b5d 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_index_patterns.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_index_patterns.tsx @@ -45,6 +45,7 @@ export const useIndexPatterns = (refreshToggle = false): Return => { return () => { isSubscribed = false; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [refreshToggle]); return [isLoading, indexPatterns]; diff --git a/x-pack/plugins/security_solution/public/common/lib/connectors/components/connector_flyout/index.tsx b/x-pack/plugins/security_solution/public/common/lib/connectors/components/connector_flyout/index.tsx index cb227563b697a..30e2c650a70cc 100644 --- a/x-pack/plugins/security_solution/public/common/lib/connectors/components/connector_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/common/lib/connectors/components/connector_flyout/index.tsx @@ -53,6 +53,7 @@ export const withConnectorFlyout = ({ if (!isEmpty(apiUrl)) { secretKeys.forEach((key: string) => editActionSecrets(key, '')); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); if (isEmpty(mapping)) { @@ -64,6 +65,7 @@ export const withConnectorFlyout = ({ const handleOnChangeActionConfig = useCallback( (key: string, value: string) => editActionConfig(key, value), + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); @@ -73,11 +75,13 @@ export const withConnectorFlyout = ({ editActionConfig(key, ''); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [action.config] ); const handleOnChangeSecretConfig = useCallback( (key: string, value: string) => editActionSecrets(key, value), + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); @@ -87,6 +91,7 @@ export const withConnectorFlyout = ({ editActionSecrets(key, ''); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [action.secrets] ); @@ -96,6 +101,7 @@ export const withConnectorFlyout = ({ ...action.config.casesConfiguration, mapping: newMapping, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [action.config] ); diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/hooks.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/hooks.ts index afd57cade5559..bc16e8334e81c 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/hooks.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/hooks.ts @@ -89,10 +89,12 @@ export const useCurrentUser = (): AuthenticatedElasticUser | null => { return () => { didCancel = true; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [security]); useEffect(() => { fetchUser(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return user; }; diff --git a/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx b/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx index 9030e2713548b..072bbcf31c900 100644 --- a/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx @@ -32,6 +32,7 @@ export const SpyRouteComponent = memo( }); setIsInitializing(false); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [search]); useEffect(() => { if (pageName && !deepEqual(route.pathName, pathname)) { @@ -81,6 +82,7 @@ export const SpyRouteComponent = memo( }); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [pathname, search, pageName, detailName, tabName, flowTarget, state]); return null; } diff --git a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx index 78f22a86c1893..37c6a6583f0fb 100644 --- a/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/timeline/use_show_timeline.tsx @@ -25,6 +25,7 @@ export const useShowTimeline = () => { } else if (!showTimeline) { setShowTimeline(true); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentLocation.pathname]); return [showTimeline]; diff --git a/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx b/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx index 937e3727ca613..86c8e00c0a56f 100644 --- a/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx +++ b/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx @@ -90,6 +90,7 @@ const AlertDetailsOverviewComponent = memo(() => { history.push(locationObject); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [alertDetailsTabId] ); diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.ts b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.ts index 55a3a4b060dad..a4f8fca23e8aa 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.ts +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.ts @@ -79,6 +79,7 @@ export function useFirstLastSeenHostQuery( const signal = abortCtrl.signal; fetchFirstLastSeenHost(signal); return () => abortCtrl.abort(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { firstSeen, lastSeen, loading, errorMessage }; diff --git a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx index 5b140a53a363b..4fbbcfc8d948a 100644 --- a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx +++ b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx @@ -35,6 +35,7 @@ export const ManagementPageView = memo>((options) => href: getManagementUrl({ name: 'policyList' }), }, ]; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [tabName]); return ; }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx index b05cdfb3be840..6c447df618791 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx @@ -137,6 +137,7 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => { description: details.agent.version, }, ]; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ details.agent.version, details.endpoint.policy.id, diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx index 5e0aa76e1d139..39b253439aff0 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/embedded_map.tsx @@ -149,6 +149,7 @@ export const EmbeddedMapComponent = ({ return () => { isSubscribed = false; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loadingKibanaIndexPatterns, kibanaIndexPatterns]); // queryExpression updated useEffect @@ -156,12 +157,14 @@ export const EmbeddedMapComponent = ({ if (embeddable != null) { embeddable.updateInput({ query }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [query]); useEffect(() => { if (embeddable != null) { embeddable.updateInput({ filters }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters]); // DateRange updated useEffect @@ -173,6 +176,7 @@ export const EmbeddedMapComponent = ({ }; embeddable.updateInput({ timeRange }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [startDate, endDate]); return isError ? null : ( diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx index 3472cb629b9fe..d2b8322c8121e 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/map_tool_tip.tsx @@ -20,10 +20,8 @@ import * as i18n from '../translations'; import { ITooltipProperty } from '../../../../../../maps/public'; export const MapToolTipComponent = ({ - addFilters, closeTooltip, features = [], - isLocked, getLayerName, loadFeatureProperties, loadFeatureGeometry, @@ -78,8 +76,10 @@ export const MapToolTipComponent = ({ }; fetchFeatureProps(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ featureIndex, + // eslint-disable-next-line react-hooks/exhaustive-deps features .map((f) => `${f.id}-${f.layerId}`) .sort() diff --git a/x-pack/plugins/security_solution/public/network/components/source_destination/country_flag.tsx b/x-pack/plugins/security_solution/public/network/components/source_destination/country_flag.tsx index b9c01826e9e74..cb1af5513c846 100644 --- a/x-pack/plugins/security_solution/public/network/components/source_destination/country_flag.tsx +++ b/x-pack/plugins/security_solution/public/network/components/source_destination/country_flag.tsx @@ -31,6 +31,7 @@ export const CountryFlag = memo<{ if (displayCountryNameOnHover && isEmpty(countries.getNames('en'))) { countries.registerLocale(countryJson); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const flag = getFlag(countryCode); diff --git a/x-pack/plugins/security_solution/public/network/components/tls_table/index.tsx b/x-pack/plugins/security_solution/public/network/components/tls_table/index.tsx index 0fc4629c95470..d0e001466518d 100644 --- a/x-pack/plugins/security_solution/public/network/components/tls_table/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/tls_table/index.tsx @@ -108,6 +108,7 @@ const TlsTableComponent = React.memo( [sort, type, tableType, updateNetworkTable] ); + // eslint-disable-next-line react-hooks/exhaustive-deps const columns = useMemo(() => getTlsColumns(tlsTableId), [tlsTableId]); return ( diff --git a/x-pack/plugins/security_solution/public/network/components/users_table/index.tsx b/x-pack/plugins/security_solution/public/network/components/users_table/index.tsx index 51634a784d4da..af9d2b0ffefe3 100644 --- a/x-pack/plugins/security_solution/public/network/components/users_table/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/users_table/index.tsx @@ -114,6 +114,7 @@ const UsersTableComponent = React.memo( [sort, type, updateNetworkTable] ); + // eslint-disable-next-line react-hooks/exhaustive-deps const columns = useMemo(() => getUsersColumns(flowTarget, usersTableId), [ flowTarget, usersTableId, diff --git a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx index 574260a819071..fe66ae2624c2a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/alerts_by_category/index.tsx @@ -71,6 +71,7 @@ const AlertsByCategoryComponent: React.FC = ({ deleteQuery({ id: ID }); } }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const kibana = useKibana(); @@ -98,6 +99,7 @@ const AlertsByCategoryComponent: React.FC = ({ `${SHOWING}: ${numeral(totalCount).format(defaultNumberFormat)} ${UNIT(totalCount)}`, legendPosition: Position.Right, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx b/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx index 75b157a282eeb..ab76219b3cc00 100644 --- a/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/recent_timelines/index.tsx @@ -82,6 +82,7 @@ const StatefulRecentTimelinesComponent = React.memo( onlyUserFavorite: filterBy === 'favorites', timelineType: TimelineType.default, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [filterBy]); return ( diff --git a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx index f2ad45be93522..5010fd9c06eb7 100644 --- a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/index.tsx @@ -61,6 +61,7 @@ const SignalsByCategoryComponent: React.FC = ({ const [min, max] = x; setAbsoluteRangeDatePicker({ id: setAbsoluteRangeDatePickerTarget, from: min, to: max }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [setAbsoluteRangeDatePicker] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/category_columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/category_columns.tsx index b0a8dc311228a..14c17b7262724 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/category_columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/category_columns.tsx @@ -50,6 +50,7 @@ interface ToolTipProps { const ToolTip = React.memo( ({ categoryId, browserFields, onUpdateColumns, timelineId }) => { const { getManageTimelineById } = useManageTimeline(); + // eslint-disable-next-line react-hooks/exhaustive-deps const { isLoading } = useMemo(() => getManageTimelineById(timelineId) ?? { isLoading: false }, [ timelineId, ]); diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/field_browser.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/field_browser.tsx index c255bd062bb4c..8f538e03835f8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/field_browser.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/field_browser.tsx @@ -180,6 +180,7 @@ const FieldsBrowserComponent: React.FC = ({ useEffect(() => { scrollViews(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedCategoryId, timelineId]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx index 11c44cce89956..a3e93ff3c90eb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx @@ -108,6 +108,7 @@ export const StatefulFieldsBrowserComponent = React.memo { onUpdateColumns(columns); // show the category columns in the timeline + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); /** Invoked when the field browser should be hidden */ diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx index 33aca80b940fe..fbe3c475c9fe6 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/pane/index.tsx @@ -50,7 +50,7 @@ const FlyoutPaneComponent: React.FC = ({ const dispatch = useDispatch(); const onResizeStop: ResizeCallback = useCallback( - (e, direction, ref, delta) => { + (_e, _direction, _ref, delta) => { const bodyClientWidthPixels = document.body.clientWidth; if (delta.width) { @@ -65,6 +65,7 @@ const FlyoutPaneComponent: React.FC = ({ ); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [dispatch] ); const resizableDefaultSize = useMemo( @@ -72,6 +73,7 @@ const FlyoutPaneComponent: React.FC = ({ width, height: '100%', }), + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); const resizableHandleComponent = useMemo( diff --git a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx index c82a8bd18e6f8..8856805e6b660 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx @@ -190,6 +190,7 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT initializeTimeline({ id }); return { ...timelineDefaults, id }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [state] ); const isManagedTimeline = useCallback((id: string): boolean => state[id] != null, [state]); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_actions.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_actions.tsx index 112e73a47ce7d..f88690ccd8aef 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_actions.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_actions.tsx @@ -16,6 +16,7 @@ export const useEditTimelineActions = () => { const onCloseDeleteTimelineModal = useCallback(() => { setIsDeleteTimelineModalOpen(false); setActionTimeline(null); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [actionItem]); const onOpenDeleteTimelineModal = useCallback((selectedActionItem?: OpenTimelineResult) => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_batch_actions.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_batch_actions.tsx index 7fb03b98432d0..4d45b74e9b1b4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_batch_actions.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/edit_timeline_batch_actions.tsx @@ -47,6 +47,7 @@ export const useEditTimelineBatchActions = ({ disableExportTimelineDownloader(); onCloseDeleteTimelineModal(); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [disableExportTimelineDownloader, onCloseDeleteTimelineModal, tableRef.current] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx index f9c9d28ad89e1..92a8fc9338877 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx @@ -125,6 +125,7 @@ export const StatefulOpenTimelineComponent = React.memo( onlyUserFavorite: onlyFavorites, timelineType, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [pageIndex, pageSize, search, sortField, sortDirection, timelineType, onlyFavorites]); /** Invoked when the user presses enters to submit the text in the search input */ @@ -177,6 +178,7 @@ export const StatefulOpenTimelineComponent = React.memo( const onDeleteOneTimeline: OnDeleteOneTimeline = useCallback( async (timelineIds: string[]) => { + // The type for `deleteTimelines` is incorrect, it returns a Promise await deleteTimelines(timelineIds); }, [deleteTimelines] @@ -184,6 +186,7 @@ export const StatefulOpenTimelineComponent = React.memo( /** Invoked when the user clicks the action to delete the selected timelines */ const onDeleteSelected: OnDeleteSelected = useCallback(async () => { + // The type for `deleteTimelines` is incorrect, it returns a Promise await deleteTimelines(getSelectedTimelineIds(selectedItems)); // NOTE: we clear the selection state below, but if the server fails to @@ -191,6 +194,7 @@ export const StatefulOpenTimelineComponent = React.memo( resetSelectionState(); // TODO: the query must re-execute to show the results of the deletion + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedItems, deleteTimelines]); /** Invoked when the user selects (or de-selects) timelines */ @@ -244,6 +248,7 @@ export const StatefulOpenTimelineComponent = React.memo( updateTimeline, }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [apolloClient, updateIsLoading, updateTimeline] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx index f99d8c566c4a5..afc66e337d7b2 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_types.tsx @@ -79,6 +79,7 @@ export const useTimelineTypes = (): { ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [tabName]); const timelineFilters = useMemo(() => { @@ -95,6 +96,7 @@ export const useTimelineTypes = (): { ))} ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [timelineType]); return { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx index 2d9f907cc7179..2bb78c0dcb0ad 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/column_headers/index.tsx @@ -108,7 +108,7 @@ export const ColumnHeadersComponent = ({ ); const renderClone: DraggableChildrenFn = useCallback( - (dragProvided, dragSnapshot, rubric) => { + (dragProvided, _dragSnapshot, rubric) => { // TODO: Remove after github.com/DefinitelyTyped/DefinitelyTyped/pull/43057 is merged // eslint-disable-next-line @typescript-eslint/no-explicit-any const index = (rubric as any).source.index; @@ -151,6 +151,7 @@ export const ColumnHeadersComponent = ({ sort={sort} /> )), + // eslint-disable-next-line react-hooks/exhaustive-deps [ columnHeaders, timelineId, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx index 3808a10e851e6..a9ade7b34344e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx @@ -106,6 +106,7 @@ export const EventColumnView = React.memo( const onClickCb = useCallback((cb: () => void) => { cb(); closePopover(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const additionalActions = useMemo(() => { @@ -175,6 +176,7 @@ export const EventColumnView = React.memo( , ] : grouped.icon; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [button, ecsData, timelineActions, isPopoverOpen]); // , isPopoverOpen, closePopover, onButtonClick]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx index 61c5809518928..cf76cd3ddb8d4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx @@ -174,6 +174,7 @@ const StatefulEventComponent: React.FC = ({ return () => { _isMounted = false; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Number of current columns plus one for actions. diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx index 351465dd45137..2d5e64fb09ffc 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx @@ -94,6 +94,7 @@ const StatefulBodyComponent = React.memo( const onAddNoteToEvent: AddNoteToEvent = useCallback( ({ eventId, noteId }: { eventId: string; noteId: string }) => addNoteToEvent!({ id, eventId, noteId }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -131,27 +132,34 @@ const StatefulBodyComponent = React.memo( (sorted) => { updateSort!({ id, sort: sorted }); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); const onColumnRemoved: OnColumnRemoved = useCallback( (columnId) => removeColumn!({ id, columnId }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); const onColumnResized: OnColumnResized = useCallback( ({ columnId, delta }) => applyDeltaToColumnWidth!({ id, columnId, delta }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); + // eslint-disable-next-line react-hooks/exhaustive-deps const onPinEvent: OnPinEvent = useCallback((eventId) => pinEvent!({ id, eventId }), [id]); + // eslint-disable-next-line react-hooks/exhaustive-deps const onUnPinEvent: OnUnPinEvent = useCallback((eventId) => unPinEvent!({ id, eventId }), [id]); + // eslint-disable-next-line react-hooks/exhaustive-deps const onUpdateNote: UpdateNote = useCallback((note: Note) => updateNote!({ note }), []); const onUpdateColumns: OnUpdateColumns = useCallback( (columns) => updateColumns!({ id, columns }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -160,6 +168,7 @@ const StatefulBodyComponent = React.memo( if (selectAll) { onSelectAll({ isSelected: true }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectAll]); // onSelectAll dependency not necessary return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/provider_item_badge.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/provider_item_badge.tsx index aaf73487c4878..1f6fe998a44e9 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/provider_item_badge.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/provider_item_badge.tsx @@ -71,11 +71,13 @@ export const ProviderItemBadge = React.memo( const onToggleEnabledProvider = useCallback(() => { toggleEnabledProvider(); closePopover(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [toggleEnabledProvider]); const onToggleExcludedProvider = useCallback(() => { toggleExcludedProvider(); closePopover(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [toggleExcludedProvider]); const [providerRegistered, setProviderRegistered] = useState(false); @@ -100,6 +102,7 @@ export const ProviderItemBadge = React.memo( () => () => { unRegisterProvider(); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/fetch_kql_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/fetch_kql_timeline.tsx index 77bd9aeba3ed2..cec889fe6ee34 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/fetch_kql_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/fetch_kql_timeline.tsx @@ -39,6 +39,7 @@ const TimelineKqlFetchComponent = memo( timelineId: id, }), }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [kueryFilterQueryDraft, kueryFilterQuery, id]); return null; }, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx index 607e004a8294e..594bf6d43e285 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx @@ -266,6 +266,7 @@ export const FooterComponent = ({ if (updatedAt === null || !isLoading) { setUpdatedAt(getUpdatedAt()); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLoading]); if (isLoading && !paginationLoading) { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx index 42fd6422d3a38..b53a34041a689 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx @@ -78,6 +78,7 @@ const StatefulTimelineComponent = React.memo( const onDataProviderRemoved: OnDataProviderRemoved = useCallback( (providerId: string, andProviderId?: string) => removeProvider!({ id, providerId, andProviderId }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -89,6 +90,7 @@ const StatefulTimelineComponent = React.memo( providerId, andProviderId, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -100,6 +102,7 @@ const StatefulTimelineComponent = React.memo( providerId, andProviderId, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -114,11 +117,13 @@ const StatefulTimelineComponent = React.memo( providerId, value, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); const onChangeItemsPerPage: OnChangeItemsPerPage = useCallback( (itemsChangedPerPage) => updateItemsPerPage!({ id, itemsPerPage: itemsChangedPerPage }), + // eslint-disable-next-line react-hooks/exhaustive-deps [id] ); @@ -141,6 +146,7 @@ const StatefulTimelineComponent = React.memo( }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [columns, id] ); @@ -148,6 +154,7 @@ const StatefulTimelineComponent = React.memo( if (createTimeline != null) { createTimeline({ id, columns: defaultHeaders, show: false }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx index 2a673427d906c..ed4d742bb8b4d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx @@ -52,6 +52,7 @@ export const InsertTimelinePopoverComponent: React.FC = ({ ); setRouterState(null); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [routerState]); const handleClosePopover = useCallback(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx index 1a81c131de015..0f9e64082a603 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx @@ -28,12 +28,14 @@ export const useInsertTimeline = (form: FormHook, fieldNa ].join(''); form.setFieldValue(fieldName, newValue); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [form] ); const handleCursorChange = useCallback( (cp: CursorPosition) => { setCursorPosition(cp); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [cursorPosition] ); return { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx index 3ef10d394bc7b..38a85a7a92631 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx @@ -142,6 +142,7 @@ export const NewCase = React.memo( }, }, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [onClosePopover, history, timelineId, timelineTitle]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx index d8966a58748ed..1532a64e4083e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx @@ -87,6 +87,7 @@ export const Properties = React.memo( const onOpenTimelineModal = useCallback(() => { onClosePopover(); setShowTimelineModal(true); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const datePickerWidth = useMemo( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx index 9852fc7dd300a..80729eda051b1 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx @@ -120,6 +120,7 @@ export const QueryBarTimeline = memo( isSubscribed = false; subscriptions.unsubscribe(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { @@ -129,6 +130,7 @@ export const QueryBarTimeline = memo( if (!deepEqual(filters, filterWithoutDropArea)) { filterManager.setFilters(filters); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters]); useEffect(() => { @@ -188,6 +190,7 @@ export const QueryBarTimeline = memo( return () => { isSubscribed = false; }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [savedQueryId]); const onChangedQuery = useCallback( @@ -203,6 +206,7 @@ export const QueryBarTimeline = memo( ); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [filterQueryDraft] ); @@ -232,6 +236,7 @@ export const QueryBarTimeline = memo( }); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [filterQuery, timelineId] ); @@ -274,6 +279,7 @@ export const QueryBarTimeline = memo( setSavedQueryId(null); } }, + // eslint-disable-next-line react-hooks/exhaustive-deps [dataProvidersDsl, savedQueryId, savedQueryServices] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx index 22fbaadf2e816..5f35bc5212d37 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx @@ -78,6 +78,7 @@ const StatefulSearchOrFilterComponent = React.memo( serializedQuery: convertKueryToElasticSearchQuery(expression, indexPattern), }, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [indexPattern, timelineId] ); @@ -90,6 +91,7 @@ const StatefulSearchOrFilterComponent = React.memo( expression, }, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [timelineId] ); @@ -99,6 +101,7 @@ const StatefulSearchOrFilterComponent = React.memo( id: timelineId, filters: newFilters, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [timelineId] ); @@ -108,6 +111,7 @@ const StatefulSearchOrFilterComponent = React.memo( id: timelineId, savedQueryId: newSavedQueryId, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [timelineId] ); @@ -117,6 +121,7 @@ const StatefulSearchOrFilterComponent = React.memo( id: timelineId, eventType: newEventType, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [timelineId] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx index 2d215267d8382..2e12ebad2f99d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx @@ -258,6 +258,7 @@ const SelectableTimelineComponent: React.FC = ({ onlyUserFavorite: onlyFavorites, timelineType, }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [onlyFavorites, pageSize, searchTimelineValue, timelineType]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx index 340818efa5514..884d693ca6ade 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx @@ -171,12 +171,15 @@ export const TimelineComponent: React.FC = ({ } = useManageTimeline(); useEffect(() => { initializeTimeline({ id, indexToAdd }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { setIsTimelineLoading({ id, isLoading: isQueryLoading || loadingIndexName }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [loadingIndexName, isQueryLoading]); useEffect(() => { setTimelineFilterManager({ id, filterManager }); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [filterManager]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/containers/all/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/all/index.tsx index 3bca7ce5f1c08..19112221cbfd0 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/all/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/all/index.tsx @@ -48,7 +48,7 @@ export interface AllTimelinesVariables { export const ALL_TIMELINE_QUERY_ID = 'FETCH_ALL_TIMELINES'; export const getAllTimeline = memoizeOne( - (variables: string, timelines: TimelineResult[]): OpenTimelineResult[] => + (_variables: string, timelines: TimelineResult[]): OpenTimelineResult[] => timelines.map((timeline) => ({ created: timeline.created, description: timeline.description, @@ -168,6 +168,7 @@ export const useGetAllTimeline = (): AllTimelinesArgs => { abortCtrl.abort(); }; }, + // eslint-disable-next-line react-hooks/exhaustive-deps [apolloClient, allTimelines] ); From e2f11e9fe93bdf1e5d0ef63f8f4e3ae5fd4ff617 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 8 Jun 2020 11:19:01 -0400 Subject: [PATCH 8/9] [ML] DFAnalytics results: ensure ml result fields are shown in data grid (#68305) * wip: ensure top classes and influencer result col show up correctly * ensure ml subFields columns are populated --- .../components/data_grid/common.ts | 6 ++++- .../data_frame_analytics/common/analytics.ts | 10 +++++++++ .../data_frame_analytics/common/constants.ts | 1 + .../data_frame_analytics/common/fields.ts | 22 ++++++++++++++++--- .../use_exploration_results.ts | 11 +++++++--- 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/data_grid/common.ts b/x-pack/plugins/ml/public/application/components/data_grid/common.ts index 44a2473f75937..7d0559c215114 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/common.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/common.ts @@ -29,6 +29,7 @@ import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE, + TOP_CLASSES, } from '../../data_frame_analytics/common/constants'; import { formatHumanReadableDateTimeSeconds } from '../../util/date_utils'; import { getNestedProperty } from '../../util/object_utils'; @@ -110,7 +111,10 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results schema = 'numeric'; } - if (field.includes(`${resultsField}.${FEATURE_IMPORTANCE}`)) { + if ( + field.includes(`${resultsField}.${FEATURE_IMPORTANCE}`) || + field.includes(`${resultsField}.${TOP_CLASSES}`) + ) { schema = 'json'; } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 0b4e6d27b96e5..16d888a9da27b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -228,6 +228,16 @@ export const getPredictionFieldName = ( return predictionFieldName; }; +export const getNumTopClasses = ( + analysis: AnalysisConfig +): ClassificationAnalysis['classification']['num_top_classes'] => { + let numTopClasses; + if (isClassificationAnalysis(analysis) && analysis.classification.num_top_classes !== undefined) { + numTopClasses = analysis.classification.num_top_classes; + } + return numTopClasses; +}; + export const getNumTopFeatureImportanceValues = ( analysis: AnalysisConfig ): diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/constants.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/constants.ts index 51b2918012c8d..2f14dfdfdfca3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/constants.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/constants.ts @@ -7,4 +7,5 @@ export const DEFAULT_RESULTS_FIELD = 'ml'; export const FEATURE_IMPORTANCE = 'feature_importance'; export const FEATURE_INFLUENCE = 'feature_influence'; +export const TOP_CLASSES = 'top_classes'; export const OUTLIER_SCORE = 'outlier_score'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts index 8db349b395cfc..0a64886c80a63 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/fields.ts @@ -5,6 +5,7 @@ */ import { + getNumTopClasses, getNumTopFeatureImportanceValues, getPredictedFieldName, getDependentVar, @@ -18,7 +19,7 @@ import { Field } from '../../../../common/types/fields'; import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; import { newJobCapsService } from '../../services/new_job_capabilities_service'; -import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE } from './constants'; +import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE, TOP_CLASSES } from './constants'; export type EsId = string; export type EsDocSource = Record; @@ -177,6 +178,7 @@ export const getDefaultFieldsFromJobCaps = ( const featureImportanceFields = []; const featureInfluenceFields = []; + const topClassesFields = []; const allFields: any = []; let type: ES_FIELD_TYPES | undefined; let predictedField: string | undefined; @@ -207,13 +209,14 @@ export const getDefaultFieldsFromJobCaps = ( type = newJobCapsService.getFieldById(dependentVariable)?.type; const predictionFieldName = getPredictionFieldName(jobConfig.analysis); const numTopFeatureImportanceValues = getNumTopFeatureImportanceValues(jobConfig.analysis); + const numTopClasses = getNumTopClasses(jobConfig.analysis); const defaultPredictionField = `${dependentVariable}_prediction`; predictedField = `${resultsField}.${ predictionFieldName ? predictionFieldName : defaultPredictionField }`; - if ((numTopFeatureImportanceValues ?? 0) > 0 && needsDestIndexFields === true) { + if ((numTopFeatureImportanceValues ?? 0) > 0) { featureImportanceFields.push({ id: `${resultsField}.${FEATURE_IMPORTANCE}`, name: `${resultsField}.${FEATURE_IMPORTANCE}`, @@ -221,6 +224,14 @@ export const getDefaultFieldsFromJobCaps = ( }); } + if ((numTopClasses ?? 0) > 0) { + topClassesFields.push({ + id: `${resultsField}.${TOP_CLASSES}`, + name: `${resultsField}.${TOP_CLASSES}`, + type: KBN_FIELD_TYPES.UNKNOWN, + }); + } + // Only need to add these fields if we didn't use dest index pattern to get the fields if (needsDestIndexFields === true) { allFields.push( @@ -234,7 +245,12 @@ export const getDefaultFieldsFromJobCaps = ( } } - allFields.push(...fields, ...featureImportanceFields, ...featureInfluenceFields); + allFields.push( + ...fields, + ...featureImportanceFields, + ...featureInfluenceFields, + ...topClassesFields + ); allFields.sort(({ name: a }: { name: string }, { name: b }: { name: string }) => sortExplorationResultsFields(a, b, jobConfig) ); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts index e391b90e6eb96..b8b5a16c84e85 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts @@ -19,7 +19,11 @@ import { import { SavedSearchQuery } from '../../../../../contexts/ml'; import { getIndexData, getIndexFields, DataFrameAnalyticsConfig } from '../../../../common'; -import { DEFAULT_RESULTS_FIELD, FEATURE_IMPORTANCE } from '../../../../common/constants'; +import { + DEFAULT_RESULTS_FIELD, + FEATURE_IMPORTANCE, + TOP_CLASSES, +} from '../../../../common/constants'; import { sortExplorationResultsFields, ML__ID_COPY } from '../../../../common/fields'; export const useExplorationResults = ( @@ -47,8 +51,9 @@ export const useExplorationResults = ( 25, // reduce default selected rows from 20 to 8 for performance reasons. 8, - // by default, hide feature-importance columns and the doc id copy - (d) => !d.includes(`.${FEATURE_IMPORTANCE}.`) && d !== ML__ID_COPY + // by default, hide feature-importance and top-classes columns and the doc id copy + (d) => + !d.includes(`.${FEATURE_IMPORTANCE}.`) && !d.includes(`.${TOP_CLASSES}.`) && d !== ML__ID_COPY ); useEffect(() => { From 0189ae5c3ff7d3d49a8f182138de743ad748eb78 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 8 Jun 2020 11:51:04 -0400 Subject: [PATCH 9/9] [Maps] Enable gridding/clustering/heatmaps for geo_shape fields (#67886) Enables heatmap, clusters, and grid layers for index-patterns with geo_shape field. This feature is only available for Gold+ users. --- .../create_source_editor.js | 4 +- .../es_geo_grid_source/es_geo_grid_source.js | 7 ++ .../es_pew_pew_source/create_source_editor.js | 5 +- .../maps/public/elasticsearch_geo_utils.js | 45 +++++---- .../public/elasticsearch_geo_utils.test.js | 93 +++++++++++++++++++ .../plugins/maps/public/index_pattern_util.js | 13 ++- .../maps/public/index_pattern_util.test.js | 81 +++++++++++++++- .../plugins/maps/public/kibana_services.d.ts | 2 + x-pack/plugins/maps/public/kibana_services.js | 9 ++ x-pack/plugins/maps/public/plugin.ts | 25 +++-- .../apps/maps/es_geo_grid_source.js | 33 +++++++ .../es_archives/maps/kibana/data.json | 33 ++++++- 12 files changed, 308 insertions(+), 42 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js index 7661ad7020194..91dcb057dd837 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js @@ -14,7 +14,7 @@ import { NoIndexPatternCallout } from '../../../components/no_index_pattern_call import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSpacer } from '@elastic/eui'; -import { AGGREGATABLE_GEO_FIELD_TYPES, getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; +import { getAggregatableGeoFieldTypes, getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; import { RenderAsSelect } from './render_as_select'; export class CreateSourceEditor extends Component { @@ -176,7 +176,7 @@ export class CreateSourceEditor extends Component { placeholder={i18n.translate('xpack.maps.source.esGeoGrid.indexPatternPlaceholder', { defaultMessage: 'Select index pattern', })} - fieldTypes={AGGREGATABLE_GEO_FIELD_TYPES} + fieldTypes={getAggregatableGeoFieldTypes()} onNoIndexPatterns={this._onNoIndexPatterns} /> diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index e77fd93872612..c05c1f2dd7c1e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -21,6 +21,7 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { AbstractESAggSource } from '../es_agg_source'; import { DataRequestAbortError } from '../../util/data_request'; import { registerSource } from '../source_registry'; +import { makeESBbox } from '../../../elasticsearch_geo_utils'; export const MAX_GEOTILE_LEVEL = 29; @@ -146,6 +147,7 @@ export class ESGeoGridSource extends AbstractESAggSource { registerCancelCallback, bucketsPerGrid, isRequestStillActive, + bufferedExtent, }) { const gridsPerRequest = Math.floor(DEFAULT_MAX_BUCKETS_LIMIT / bucketsPerGrid); const aggs = { @@ -156,6 +158,7 @@ export class ESGeoGridSource extends AbstractESAggSource { { gridSplit: { geotile_grid: { + bounds: makeESBbox(bufferedExtent), field: this._descriptor.geoField, precision, }, @@ -234,10 +237,12 @@ export class ESGeoGridSource extends AbstractESAggSource { precision, layerName, registerCancelCallback, + bufferedExtent, }) { searchSource.setField('aggs', { gridSplit: { geotile_grid: { + bounds: makeESBbox(bufferedExtent), field: this._descriptor.geoField, precision, }, @@ -282,6 +287,7 @@ export class ESGeoGridSource extends AbstractESAggSource { precision: searchFilters.geogridPrecision, layerName, registerCancelCallback, + bufferedExtent: searchFilters.buffer, }) : await this._compositeAggRequest({ searchSource, @@ -291,6 +297,7 @@ export class ESGeoGridSource extends AbstractESAggSource { registerCancelCallback, bucketsPerGrid, isRequestStillActive, + bufferedExtent: searchFilters.buffer, }); return { diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js index f599ba93d40d6..38a5850537200 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js @@ -14,7 +14,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFormRow, EuiCallOut } from '@elastic/eui'; -import { AGGREGATABLE_GEO_FIELD_TYPES, getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; +import { getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; +import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; export class CreateSourceEditor extends Component { static propTypes = { @@ -177,7 +178,7 @@ export class CreateSourceEditor extends Component { placeholder={i18n.translate('xpack.maps.source.pewPew.indexPatternPlaceholder', { defaultMessage: 'Select index pattern', })} - fieldTypes={AGGREGATABLE_GEO_FIELD_TYPES} + fieldTypes={[ES_GEO_FIELD_TYPE.GEO_POINT]} /> ); diff --git a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js index b89fda29554ee..efd243595db3e 100644 --- a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js @@ -225,39 +225,36 @@ export function geoShapeToGeometry(value, accumulator) { accumulator.push(geoJson); } -function createGeoBoundBoxFilter({ maxLat, maxLon, minLat, minLon }, geoFieldName) { - const top = clampToLatBounds(maxLat); +export function makeESBbox({ maxLat, maxLon, minLat, minLon }) { const bottom = clampToLatBounds(minLat); - - // geo_bounding_box does not support ranges outside of -180 and 180 - // When the area crosses the 180° meridian, - // the value of the lower left longitude will be greater than the value of the upper right longitude. - // http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#30 - let boundingBox; + const top = clampToLatBounds(maxLat); + let esBbox; if (maxLon - minLon >= 360) { - boundingBox = { + esBbox = { top_left: [-180, top], bottom_right: [180, bottom], }; - } else if (maxLon > 180) { - const overflow = maxLon - 180; - boundingBox = { - top_left: [minLon, top], - bottom_right: [-180 + overflow, bottom], - }; - } else if (minLon < -180) { - const overflow = Math.abs(minLon) - 180; - boundingBox = { - top_left: [180 - overflow, top], - bottom_right: [maxLon, bottom], - }; } else { - boundingBox = { - top_left: [minLon, top], - bottom_right: [maxLon, bottom], + // geo_bounding_box does not support ranges outside of -180 and 180 + // When the area crosses the 180° meridian, + // the value of the lower left longitude will be greater than the value of the upper right longitude. + // http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#30 + // + // This ensures bbox goes West->East in the happy case, + // but will be formatted East->West in case it crosses the date-line + const newMinlon = ((minLon + 180 + 360) % 360) - 180; + const newMaxlon = ((maxLon + 180 + 360) % 360) - 180; + esBbox = { + top_left: [newMinlon, top], + bottom_right: [newMaxlon, bottom], }; } + return esBbox; +} + +function createGeoBoundBoxFilter({ maxLat, maxLon, minLat, minLon }, geoFieldName) { + const boundingBox = makeESBbox({ maxLat, maxLon, minLat, minLon }); return { geo_bounding_box: { [geoFieldName]: boundingBox, diff --git a/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js b/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js index 05f6a9eec5bd5..a1e4e43f3ab75 100644 --- a/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js +++ b/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js @@ -19,6 +19,7 @@ import { createExtentFilter, roundCoordinates, extractFeaturesFromFilters, + makeESBbox, } from './elasticsearch_geo_utils'; import { indexPatterns } from '../../../../src/plugins/data/public'; @@ -594,3 +595,95 @@ describe('extractFeaturesFromFilters', () => { expect(extractFeaturesFromFilters([spatialFilter])).toEqual([]); }); }); + +describe('makeESBbox', () => { + it('Should invert Y-axis', () => { + const bbox = makeESBbox({ + minLon: 10, + maxLon: 20, + minLat: 0, + maxLat: 1, + }); + expect(bbox).toEqual({ bottom_right: [20, 0], top_left: [10, 1] }); + }); + + it('Should snap to 360 width', () => { + const bbox = makeESBbox({ + minLon: 10, + maxLon: 400, + minLat: 0, + maxLat: 1, + }); + expect(bbox).toEqual({ bottom_right: [180, 0], top_left: [-180, 1] }); + }); + + it('Should clamp latitudes', () => { + const bbox = makeESBbox({ + minLon: 10, + maxLon: 400, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [180, -89], top_left: [-180, 89] }); + }); + + it('Should swap West->East orientation to East->West orientation when crossing dateline (West extension)', () => { + const bbox = makeESBbox({ + minLon: -190, + maxLon: 20, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [20, -89], top_left: [170, 89] }); + }); + + it('Should swap West->East orientation to East->West orientation when crossing dateline (West extension) (overrated)', () => { + const bbox = makeESBbox({ + minLon: -190 + 360 + 360, + maxLon: 20 + 360 + 360, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [20, -89], top_left: [170, 89] }); + }); + + it('Should swap West->East orientation to East->West orientation when crossing dateline (east extension)', () => { + const bbox = makeESBbox({ + minLon: 175, + maxLon: 190, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [-170, -89], top_left: [175, 89] }); + }); + + it('Should preserve West->East orientation when _not_ crossing dateline', () => { + const bbox = makeESBbox({ + minLon: 20, + maxLon: 170, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [170, -89], top_left: [20, 89] }); + }); + + it('Should preserve West->East orientation when _not_ crossing dateline _and_ snap longitudes (west extension)', () => { + const bbox = makeESBbox({ + minLon: -190, + maxLon: -185, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [175, -89], top_left: [170, 89] }); + }); + + it('Should preserve West->East orientation when _not_ crossing dateline _and_ snap longitudes (east extension)', () => { + const bbox = makeESBbox({ + minLon: 185, + maxLon: 190, + minLat: -100, + maxLat: 100, + }); + expect(bbox).toEqual({ bottom_right: [-170, -89], top_left: [-175, 89] }); + }); +}); diff --git a/x-pack/plugins/maps/public/index_pattern_util.js b/x-pack/plugins/maps/public/index_pattern_util.js index d695d1087a38d..514feeaa22072 100644 --- a/x-pack/plugins/maps/public/index_pattern_util.js +++ b/x-pack/plugins/maps/public/index_pattern_util.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getIndexPatternService } from './kibana_services'; +import { getIndexPatternService, getIsGoldPlus } from './kibana_services'; import { indexPatterns } from '../../../../src/plugins/data/public'; import { ES_GEO_FIELD_TYPE } from '../common/constants'; @@ -30,19 +30,24 @@ export function getTermsFields(fields) { }); } -export const AGGREGATABLE_GEO_FIELD_TYPES = [ES_GEO_FIELD_TYPE.GEO_POINT]; +export function getAggregatableGeoFieldTypes() { + const aggregatableFieldTypes = [ES_GEO_FIELD_TYPE.GEO_POINT]; + if (getIsGoldPlus()) { + aggregatableFieldTypes.push(ES_GEO_FIELD_TYPE.GEO_SHAPE); + } + return aggregatableFieldTypes; +} export function getFieldsWithGeoTileAgg(fields) { return fields.filter(supportsGeoTileAgg); } export function supportsGeoTileAgg(field) { - // TODO add geo_shape support with license check return ( field && field.aggregatable && !indexPatterns.isNestedField(field) && - field.type === ES_GEO_FIELD_TYPE.GEO_POINT + getAggregatableGeoFieldTypes().includes(field.type) ); } diff --git a/x-pack/plugins/maps/public/index_pattern_util.test.js b/x-pack/plugins/maps/public/index_pattern_util.test.js index 7f8f1c175cf15..4fa9eb3cadb49 100644 --- a/x-pack/plugins/maps/public/index_pattern_util.test.js +++ b/x-pack/plugins/maps/public/index_pattern_util.test.js @@ -6,7 +6,12 @@ jest.mock('./kibana_services', () => ({})); -import { getSourceFields } from './index_pattern_util'; +import { + getSourceFields, + getAggregatableGeoFieldTypes, + supportsGeoTileAgg, +} from './index_pattern_util'; +import { ES_GEO_FIELD_TYPE } from '../common/constants'; describe('getSourceFields', () => { test('Should remove multi fields from field list', () => { @@ -27,3 +32,77 @@ describe('getSourceFields', () => { expect(sourceFields).toEqual([{ name: 'agent' }]); }); }); + +describe('Gold+ licensing', () => { + const testStubs = [ + { + field: { + type: 'geo_point', + aggregatable: true, + }, + supportedInBasic: true, + supportedInGold: true, + }, + { + field: { + type: 'geo_shape', + aggregatable: false, + }, + supportedInBasic: false, + supportedInGold: false, + }, + { + field: { + type: 'geo_shape', + aggregatable: true, + }, + supportedInBasic: false, + supportedInGold: true, + }, + ]; + + describe('basic license', () => { + beforeEach(() => { + require('./kibana_services').getIsGoldPlus = () => false; + }); + + describe('getAggregatableGeoFieldTypes', () => { + test('Should only include geo_point fields ', () => { + const aggregatableGeoFieldTypes = getAggregatableGeoFieldTypes(); + expect(aggregatableGeoFieldTypes).toEqual([ES_GEO_FIELD_TYPE.GEO_POINT]); + }); + }); + + describe('supportsGeoTileAgg', () => { + testStubs.forEach((stub, index) => { + test(`stub: ${index}`, () => { + const supported = supportsGeoTileAgg(stub.field); + expect(supported).toEqual(stub.supportedInBasic); + }); + }); + }); + }); + + describe('gold license', () => { + beforeEach(() => { + require('./kibana_services').getIsGoldPlus = () => true; + }); + describe('getAggregatableGeoFieldTypes', () => { + test('Should add geo_shape field', () => { + const aggregatableGeoFieldTypes = getAggregatableGeoFieldTypes(); + expect(aggregatableGeoFieldTypes).toEqual([ + ES_GEO_FIELD_TYPE.GEO_POINT, + ES_GEO_FIELD_TYPE.GEO_SHAPE, + ]); + }); + }); + describe('supportsGeoTileAgg', () => { + testStubs.forEach((stub, index) => { + test(`stub: ${index}`, () => { + const supported = supportsGeoTileAgg(stub.field); + expect(supported).toEqual(stub.supportedInGold); + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/maps/public/kibana_services.d.ts b/x-pack/plugins/maps/public/kibana_services.d.ts index 45a4ace8e27a5..d45d7286ebf68 100644 --- a/x-pack/plugins/maps/public/kibana_services.d.ts +++ b/x-pack/plugins/maps/public/kibana_services.d.ts @@ -48,6 +48,7 @@ export function getShowMapsInspectorAdapter(): boolean; export function getPreserveDrawingBuffer(): boolean; export function getEnableVectorTiles(): boolean; export function getProxyElasticMapsServiceInMaps(): boolean; +export function getIsGoldPlus(): boolean; export function setLicenseId(args: unknown): void; export function setInspector(args: unknown): void; @@ -74,3 +75,4 @@ export function setSearchService(args: DataPublicPluginStart['search']): void; export function setKibanaCommonConfig(config: MapsLegacyConfigType): void; export function setMapAppConfig(config: MapsConfigType): void; export function setKibanaVersion(version: string): void; +export function setIsGoldPlus(isGoldPlus: boolean): void; diff --git a/x-pack/plugins/maps/public/kibana_services.js b/x-pack/plugins/maps/public/kibana_services.js index ba7be7a3b2464..1684acfb0f463 100644 --- a/x-pack/plugins/maps/public/kibana_services.js +++ b/x-pack/plugins/maps/public/kibana_services.js @@ -166,3 +166,12 @@ export const getProxyElasticMapsServiceInMaps = () => getKibanaCommonConfig().proxyElasticMapsServiceInMaps; export const getRegionmapLayers = () => _.get(getKibanaCommonConfig(), 'regionmap.layers', []); export const getTilemap = () => _.get(getKibanaCommonConfig(), 'tilemap', []); + +let isGoldPlus = false; +export const setIsGoldPlus = (igp) => { + isGoldPlus = igp; +}; + +export const getIsGoldPlus = () => { + return isGoldPlus; +}; diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 3a20f6738a05a..319be46870ebc 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Plugin, CoreSetup, CoreStart, PluginInitializerContext } from 'src/core/public'; +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/public'; import { Setup as InspectorSetupContract } from 'src/plugins/inspector/public'; // @ts-ignore import { MapView } from './inspector/views/map_view'; @@ -21,29 +21,31 @@ import { setIndexPatternSelect, setIndexPatternService, setInspector, + setIsGoldPlus, + setKibanaCommonConfig, + setKibanaVersion, setLicenseId, + setMapAppConfig, setMapsCapabilities, setNavigation, setSavedObjectsClient, + setSearchService, setTimeFilter, setToasts, setUiActions, setUiSettings, setVisualizations, - setSearchService, - setMapAppConfig, - setKibanaCommonConfig, - setKibanaVersion, } from './kibana_services'; import { featureCatalogueEntry } from './feature_catalogue_entry'; // @ts-ignore import { getMapsVisTypeAlias } from './maps_vis_type_alias'; import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { VisualizationsSetup } from '../../../../src/plugins/visualizations/public'; -import { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; +import { APP_ID, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; import { MapEmbeddableFactory } from './embeddable/map_embeddable_factory'; import { EmbeddableSetup } from '../../../../src/plugins/embeddable/public'; -import { MapsXPackConfig, MapsConfigType } from '../config'; +import { MapsConfigType, MapsXPackConfig } from '../config'; +import { ILicense } from '../../licensing/common/types'; export interface MapsPluginSetupDependencies { inspector: InspectorSetupContract; @@ -76,7 +78,14 @@ export const bindSetupCoreAndPlugins = ( }; export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { - const { fileUpload, data, inspector } = plugins; + const { fileUpload, data, inspector, licensing } = plugins; + if (licensing) { + licensing.license$.subscribe((license: ILicense) => { + const gold = license.check(APP_ID, 'gold'); + setIsGoldPlus(gold.state === 'valid'); + }); + } + setInspector(inspector); setFileUpload(fileUpload); setIndexPatternSelect(data.ui.IndexPatternSelect); diff --git a/x-pack/test/functional/apps/maps/es_geo_grid_source.js b/x-pack/test/functional/apps/maps/es_geo_grid_source.js index 7346ab842ff59..f5a603742c89a 100644 --- a/x-pack/test/functional/apps/maps/es_geo_grid_source.js +++ b/x-pack/test/functional/apps/maps/es_geo_grid_source.js @@ -241,5 +241,38 @@ export default function ({ getPageObjects, getService }) { }); }); }); + + describe('vector grid with geo_shape', () => { + before(async () => { + await PageObjects.maps.loadSavedMap('geo grid vector grid example with shape'); + }); + + const LAYER_ID = 'g1xkv'; + it('should get expected number of grid cells', async () => { + const mapboxStyle = await PageObjects.maps.getMapboxStyle(); + expect(mapboxStyle.sources[LAYER_ID].data.features.length).to.equal(13); + }); + + describe('inspector', () => { + afterEach(async () => { + await inspector.close(); + }); + + it('should contain geotile_grid aggregation elasticsearch request', async () => { + await inspector.open(); + await inspector.openInspectorRequestsView(); + const requestStats = await inspector.getTableData(); + const totalHits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits (total)'); + expect(totalHits).to.equal('4'); //4 geometries result in 13 cells due to way they overlap geotile_grid cells + const hits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits'); + expect(hits).to.equal('0'); // aggregation requests do not return any documents + const indexPatternName = PageObjects.maps.getInspectorStatRowHit( + requestStats, + 'Index pattern' + ); + expect(indexPatternName).to.equal('geo_shapes*'); + }); + }); + }); }); } diff --git a/x-pack/test/functional/es_archives/maps/kibana/data.json b/x-pack/test/functional/es_archives/maps/kibana/data.json index d313fd2046c03..c173d75075041 100644 --- a/x-pack/test/functional/es_archives/maps/kibana/data.json +++ b/x-pack/test/functional/es_archives/maps/kibana/data.json @@ -36,7 +36,7 @@ "index": ".kibana", "source": { "index-pattern": { - "fields" : "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"geometry\",\"type\":\"geo_shape\",\"esTypes\":[\"geo_shape\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"prop1\",\"type\":\"number\",\"esTypes\":[\"byte\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "fields" : "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"geometry\",\"type\":\"geo_shape\",\"esTypes\":[\"geo_shape\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"prop1\",\"type\":\"number\",\"esTypes\":[\"byte\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", "title": "geo_shapes*" }, "type": "index-pattern" @@ -553,6 +553,37 @@ } } +{ + "type": "doc", + "value": { + "id": "map:0c86d024-a767-11ea-bb37-0242ac130002", + "index": ".kibana", + "source": { + "map": { + "bounds": { + "coordinates": [ + [ + -160, + 60 + ], + [ + 160, + -60 + ] + ], + "type": "envelope" + }, + "description": "", + "layerListJSON": "[{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEO_GRID\",\"id\":\"64ddd934-a767-11ea-bb37-0242ac130002\",\"indexPatternId\":\"561253e0-f731-11e8-8487-11b9dd924f96\",\"geoField\":\"geometry\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\"}]", + "mapStateJSON": "{\"zoom\":3,\"center\":{\"lon\":76,\"lat\":4},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}", + "title": "geo grid vector grid example with shape", + "uiStateJSON": "{\"isDarkMode\":false}" + }, + "type": "map" + } + } +} + { "type": "doc", "value": {