diff --git a/package.json b/package.json index 05da90baf7a71..a669c4a64e846 100644 --- a/package.json +++ b/package.json @@ -71,11 +71,11 @@ "**/cross-fetch/node-fetch": "^2.6.1", "**/deepmerge": "^4.2.2", "**/fast-deep-equal": "^3.1.1", - "**/graphql-toolkit/lodash": "^4.17.15", + "**/graphql-toolkit/lodash": "^4.17.21", "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-fetch/node-fetch": "^2.6.1", "**/istanbul-instrumenter-loader/schema-utils": "1.0.0", - "**/load-grunt-config/lodash": "^4.17.20", + "**/load-grunt-config/lodash": "^4.17.21", "**/minimist": "^1.2.5", "**/node-jose/node-forge": "^0.10.0", "**/prismjs": "1.22.0", @@ -231,7 +231,7 @@ "json-stringify-safe": "5.0.1", "jsonwebtoken": "^8.5.1", "load-json-file": "^6.2.0", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "lru-cache": "^4.1.5", "markdown-it": "^10.0.0", "md5": "^2.1.0", diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts index fc26c837d5e52..267d671361184 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts @@ -96,8 +96,7 @@ describe('getSearchDsl', () => { mappings, opts.type, opts.sortField, - opts.sortOrder, - opts.pit + opts.sortOrder ); }); diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index cae5e43897bcf..9820544f02bd1 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -78,7 +78,7 @@ export function getSearchDsl( hasReferenceOperator, kueryNode, }), - ...getSortingParams(mappings, type, sortField, sortOrder, pit), + ...getSortingParams(mappings, type, sortField, sortOrder), ...(pit ? getPitParams(pit) : {}), ...(searchAfter ? { search_after: searchAfter } : {}), }; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts index 73c7065705fc5..1376f0d50a9da 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts @@ -79,11 +79,6 @@ describe('searchDsl/getSortParams', () => { ], }); }); - it('appends tiebreaker when PIT is provided', () => { - expect(getSortingParams(MAPPINGS, 'saved', 'title', undefined, { id: 'abc' }).sort).toEqual( - expect.arrayContaining([{ _shard_doc: 'asc' }]) - ); - }); }); describe('sortField is simple root property with multiple types', () => { it('returns correct params', () => { @@ -98,11 +93,6 @@ describe('searchDsl/getSortParams', () => { ], }); }); - it('appends tiebreaker when PIT is provided', () => { - expect( - getSortingParams(MAPPINGS, ['saved', 'pending'], 'type', undefined, { id: 'abc' }).sort - ).toEqual(expect.arrayContaining([{ _shard_doc: 'asc' }])); - }); }); describe('sortField is simple non-root property with multiple types', () => { it('returns correct params', () => { @@ -124,11 +114,6 @@ describe('searchDsl/getSortParams', () => { ], }); }); - it('appends tiebreaker when PIT is provided', () => { - expect( - getSortingParams(MAPPINGS, 'saved', 'title.raw', undefined, { id: 'abc' }).sort - ).toEqual(expect.arrayContaining([{ _shard_doc: 'asc' }])); - }); }); describe('sortField is multi-field with single type as array', () => { it('returns correct params', () => { @@ -143,11 +128,6 @@ describe('searchDsl/getSortParams', () => { ], }); }); - it('appends tiebreaker when PIT is provided', () => { - expect( - getSortingParams(MAPPINGS, ['saved'], 'title.raw', undefined, { id: 'abc' }).sort - ).toEqual(expect.arrayContaining([{ _shard_doc: 'asc' }])); - }); }); describe('sortField is root multi-field with multiple types', () => { it('returns correct params', () => { @@ -162,12 +142,6 @@ describe('searchDsl/getSortParams', () => { ], }); }); - it('appends tiebreaker when PIT is provided', () => { - expect( - getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw', undefined, { id: 'abc' }) - .sort - ).toEqual(expect.arrayContaining([{ _shard_doc: 'asc' }])); - }); }); describe('sortField is not-root multi-field with multiple types', () => { it('returns correct params', () => { diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts index abef9bfa0a300..e3bfba6a80f59 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts @@ -8,12 +8,6 @@ import Boom from '@hapi/boom'; import { getProperty, IndexMapping } from '../../../mappings'; -import { SavedObjectsPitParams } from '../../../types'; - -// TODO: The plan is for ES to automatically add this tiebreaker when -// using PIT. We should remove this logic once that is resolved. -// https://github.com/elastic/elasticsearch/issues/56828 -const ES_PROVIDED_TIEBREAKER = { _shard_doc: 'asc' }; const TOP_LEVEL_FIELDS = ['_id', '_score']; @@ -21,8 +15,7 @@ export function getSortingParams( mappings: IndexMapping, type: string | string[], sortField?: string, - sortOrder?: string, - pit?: SavedObjectsPitParams + sortOrder?: string ) { if (!sortField) { return {}; @@ -38,7 +31,6 @@ export function getSortingParams( order: sortOrder, }, }, - ...(pit ? [ES_PROVIDED_TIEBREAKER] : []), ], }; } @@ -59,7 +51,6 @@ export function getSortingParams( unmapped_type: rootField.type, }, }, - ...(pit ? [ES_PROVIDED_TIEBREAKER] : []), ], }; } @@ -84,7 +75,6 @@ export function getSortingParams( unmapped_type: field.type, }, }, - ...(pit ? [ES_PROVIDED_TIEBREAKER] : []), ], }; } diff --git a/src/plugins/discover/public/application/components/sidebar/lib/field_filter.ts b/src/plugins/discover/public/application/components/sidebar/lib/field_filter.ts index 5517011f05718..8c7e48f173031 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/field_filter.ts +++ b/src/plugins/discover/public/application/components/sidebar/lib/field_filter.ts @@ -59,6 +59,7 @@ export function isFieldFiltered( const scriptedOrMissing = !filterState.missing || field.type === '_source' || + field.type === 'unknown_selected' || field.scripted || fieldCounts[field.name] > 0; const needle = filterState.name ? filterState.name.toLowerCase() : ''; diff --git a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts index 9792e98ba84c7..68099fb0c8e2a 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts +++ b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.test.ts @@ -217,6 +217,20 @@ describe('group_fields', function () { ]); }); + it('should filter fields by a given name', function () { + const fieldFilterState = { ...getDefaultFieldFilter(), ...{ name: 'curr' } }; + + const actual1 = groupFields( + fields as IndexPatternField[], + ['customer_birth_date', 'currency', 'unknown'], + 5, + fieldCounts, + fieldFilterState, + false + ); + expect(actual1.selected.map((field) => field.name)).toEqual(['currency']); + }); + it('excludes unmapped fields if showUnmappedFields set to false', function () { const fieldFilterState = getDefaultFieldFilter(); const fieldsWithUnmappedField = [...fields]; diff --git a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx index eefb96b78aac6..dc6cbcedc8086 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx +++ b/src/plugins/discover/public/application/components/sidebar/lib/group_fields.tsx @@ -71,10 +71,18 @@ export function groupFields( } } } - // add columns, that are not part of the index pattern, to be removeable + // add selected columns, that are not part of the index pattern, to be removeable for (const column of columns) { - if (!result.selected.find((field) => field.name === column)) { - result.selected.push({ name: column, displayName: column } as IndexPatternField); + const tmpField = { + name: column, + displayName: column, + type: 'unknown_selected', + } as IndexPatternField; + if ( + !result.selected.find((field) => field.name === column) && + isFieldFiltered(tmpField, fieldFilterState, fieldCounts) + ) { + result.selected.push(tmpField); } } result.selected.sort((a, b) => { diff --git a/src/plugins/embeddable/README.asciidoc b/src/plugins/embeddable/README.asciidoc index daa6040eab7eb..007b16587e9f8 100644 --- a/src/plugins/embeddable/README.asciidoc +++ b/src/plugins/embeddable/README.asciidoc @@ -22,18 +22,17 @@ There is also an example of rendering dashboard container outside of dashboard a === Docs -link:./docs/README.md[Embeddable docs, guides & caveats] +link:https://github.com/elastic/kibana/blob/master/src/plugins/embeddable/docs/README.md[Embeddable docs, guides & caveats] === API docs -==== Server API -https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.md[Server Setup contract] -https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablestart.md[Server Start contract] - ===== Browser API https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablesetup.md[Browser Setup contract] https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md[Browser Start contract] +==== Server API +https://github.com/elastic/kibana/blob/master/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddablesetup.md[Server Setup contract] + === Testing Run unit tests diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts index b234b026a513e..7fe5c6f50d046 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts @@ -477,6 +477,29 @@ describe('', () => { component.update(); }); + test('serialization', async () => { + httpRequestsMockHelpers.setLoadPolicies([DEFAULT_POLICY]); + await act(async () => { + testBed = await setup(); + }); + const { component, actions } = testBed; + component.update(); + await actions.delete.enablePhase(); + await actions.setWaitForSnapshotPolicy('test'); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(entirePolicy.phases.delete).toEqual({ + min_age: '365d', + actions: { + delete: {}, + wait_for_snapshot: { + policy: 'test', + }, + }, + }); + }); + test('wait for snapshot policy field should correctly display snapshot policy name', () => { expect(testBed.find('snapshotPolicyCombobox').prop('data-currentvalue')).toEqual([ { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts index 600a660657863..65fc82b7ccc68 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts @@ -354,7 +354,7 @@ export const schema: FormSchema = { }, delete: { min_age: { - defaultValue: '0', + defaultValue: '365', validations: [ { validator: minAgeValidator, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx index d5c0b9ff64807..af5411dd4d3b0 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx @@ -11,9 +11,9 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { Ast } from '@kbn/interpreter/common'; import { i18n } from '@kbn/i18n'; import { + EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, - EuiIcon, EuiText, EuiButtonEmpty, EuiLink, @@ -389,72 +389,84 @@ export const InnerVisualizationWrapper = ({ if (localState.configurationValidationError?.length) { let showExtraErrors = null; + let showExtraErrorsAction = null; + if (localState.configurationValidationError.length > 1) { if (localState.expandError) { showExtraErrors = localState.configurationValidationError .slice(1) .map(({ longMessage }) => ( - {longMessage} - +

)); } else { - showExtraErrors = ( - - { - setLocalState((prevState: WorkspaceState) => ({ - ...prevState, - expandError: !prevState.expandError, - })); - }} - data-test-subj="configuration-failure-more-errors" - > - {i18n.translate('xpack.lens.editorFrame.configurationFailureMoreErrors', { - defaultMessage: ` +{errors} {errors, plural, one {error} other {errors}}`, - values: { errors: localState.configurationValidationError.length - 1 }, - })} - - + showExtraErrorsAction = ( + { + setLocalState((prevState: WorkspaceState) => ({ + ...prevState, + expandError: !prevState.expandError, + })); + }} + data-test-subj="configuration-failure-more-errors" + > + {i18n.translate('xpack.lens.editorFrame.configurationFailureMoreErrors', { + defaultMessage: ` +{errors} {errors, plural, one {error} other {errors}}`, + values: { errors: localState.configurationValidationError.length - 1 }, + })} + ); } } return ( - + - - - - {localState.configurationValidationError[0].longMessage} + +

+ {localState.configurationValidationError[0].longMessage} +

+ + {showExtraErrors} + + } + iconColor="danger" + iconType="alert" + />
- {showExtraErrors}
); } if (localState.expressionBuildError?.length) { return ( - + - - - - +

+ +

+ +

{localState.expressionBuildError[0].longMessage}

+ + } + iconColor="danger" + iconType="alert" />
- {localState.expressionBuildError[0].longMessage}
); } @@ -474,34 +486,43 @@ export const InnerVisualizationWrapper = ({ const visibleErrorMessage = getOriginalRequestErrorMessage(error) || errorMessage; return ( - + - - - - { + setLocalState((prevState: WorkspaceState) => ({ + ...prevState, + expandError: !prevState.expandError, + })); + }} + > + {i18n.translate('xpack.lens.editorFrame.expandRenderingErrorButton', { + defaultMessage: 'Show details of error', + })} + + ) : null + } + body={ + <> +

+ +

+ + {localState.expandError ? ( +

visibleErrorMessage

+ ) : null} + + } + iconColor="danger" + iconType="alert" />
- {visibleErrorMessage ? ( - - { - setLocalState((prevState: WorkspaceState) => ({ - ...prevState, - expandError: !prevState.expandError, - })); - }} - > - {i18n.translate('xpack.lens.editorFrame.expandRenderingErrorButton', { - defaultMessage: 'Show details of error', - })} - - - {localState.expandError ? visibleErrorMessage : null} - - ) : null}
); }} diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx index 740d127e1b08d..344464bfe9590 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx @@ -14,6 +14,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiFormRow, + EuiIconTip, EuiSelect, EuiSpacer, EuiSwitch, @@ -57,6 +58,24 @@ const TOGGLE_OFF = i18n.translate('xpack.ml.splom.toggleOff', { const sampleSizeOptions = [100, 1000, 10000].map((d) => ({ value: d, text: '' + d })); +interface OptionLabelWithIconTipProps { + label: string; + tooltip: string; +} + +const OptionLabelWithIconTip: FC = ({ label, tooltip }) => ( + <> + {label} + + +); + export interface ScatterplotMatrixProps { fields: string[]; index: string; @@ -252,9 +271,16 @@ export const ScatterplotMatrix: FC = ({ + } display="rowCompressed" fullWidth > @@ -276,9 +302,16 @@ export const ScatterplotMatrix: FC = ({ + } display="rowCompressed" fullWidth > @@ -292,9 +325,17 @@ export const ScatterplotMatrix: FC = ({ + } display="rowCompressed" fullWidth > @@ -310,9 +351,16 @@ export const ScatterplotMatrix: FC = ({ {resultsField !== undefined && legendType === undefined && ( + } display="rowCompressed" fullWidth > diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss index d946a0cf94032..65a72a1d4a48d 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss @@ -46,6 +46,7 @@ } .body { display: block; + height: 315px; } } & > li.has-body.active { diff --git a/x-pack/test/accessibility/apps/index_lifecycle_management.ts b/x-pack/test/accessibility/apps/index_lifecycle_management.ts index 43fd805a42d37..d6ba222e50eb4 100644 --- a/x-pack/test/accessibility/apps/index_lifecycle_management.ts +++ b/x-pack/test/accessibility/apps/index_lifecycle_management.ts @@ -28,7 +28,10 @@ const TEST_POLICY_ALL_PHASES = { }; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const { common } = getPageObjects(['common']); + const { common, indexLifecycleManagement } = getPageObjects([ + 'common', + 'indexLifecycleManagement', + ]); const retry = getService('retry'); const testSubjects = getService('testSubjects'); const esClient = getService('es'); @@ -55,6 +58,32 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await esClient.ilm.deleteLifecycle({ policy: TEST_POLICY_NAME }); }); + it('Create Policy Form', async () => { + await retry.waitFor('Index Lifecycle Policy create/edit view to be present', async () => { + return testSubjects.isDisplayed('createPolicyButton'); + }); + + // Navigate to create policy page and take snapshot + await testSubjects.click('createPolicyButton'); + await retry.waitFor('Index Lifecycle Policy create/edit view to be present', async () => { + return (await testSubjects.getVisibleText('policyTitle')) === 'Create policy'; + }); + + // Fill out form after enabling all phases and take snapshot. + await indexLifecycleManagement.fillNewPolicyForm('testPolicy', true, true, false); + await a11y.testAppSnapshot(); + }); + + it('Send Request Flyout on New Policy Page', async () => { + // Take snapshot of the show request panel + await testSubjects.click('requestButton'); + await a11y.testAppSnapshot(); + + // Close panel and save policy + await testSubjects.click('euiFlyoutCloseButton'); + await indexLifecycleManagement.saveNewPolicy(); + }); + it('List policies view', async () => { await retry.waitFor('Index Lifecycle Policy create/edit view to be present', async () => { await common.navigateToApp('indexLifecycleManagement'); diff --git a/x-pack/test/functional/page_objects/index_lifecycle_management_page.ts b/x-pack/test/functional/page_objects/index_lifecycle_management_page.ts index 04db9e4544c9a..ddf46926f122a 100644 --- a/x-pack/test/functional/page_objects/index_lifecycle_management_page.ts +++ b/x-pack/test/functional/page_objects/index_lifecycle_management_page.ts @@ -9,6 +9,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function IndexLifecycleManagementPageProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); + const retry = getService('retry'); return { async sectionHeadingText() { @@ -17,5 +18,40 @@ export function IndexLifecycleManagementPageProvider({ getService }: FtrProvider async createPolicyButton() { return await testSubjects.find('createPolicyButton'); }, + async fillNewPolicyForm( + policyName: string, + warmEnabled: boolean = false, + coldEnabled: boolean = false, + deletePhaseEnabled: boolean = false + ) { + await testSubjects.setValue('policyNameField', policyName); + if (warmEnabled) { + await retry.try(async () => { + await testSubjects.click('enablePhaseSwitch-warm'); + }); + } + if (coldEnabled) { + await retry.try(async () => { + await testSubjects.click('enablePhaseSwitch-cold'); + }); + } + if (deletePhaseEnabled) { + await retry.try(async () => { + await testSubjects.click('enableDeletePhaseButton'); + }); + } + }, + async saveNewPolicy() { + await testSubjects.click('savePolicyButton'); + }, + async createNewPolicyAndSave( + policyName: string, + warmEnabled: boolean = false, + coldEnabled: boolean = false, + deletePhaseEnabled: boolean = false + ) { + await this.fillNewPolicyForm(policyName, warmEnabled, coldEnabled, deletePhaseEnabled); + await this.saveNewPolicy(); + }, }; } diff --git a/yarn.lock b/yarn.lock index 776ad348020f5..6366d37eaf571 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19991,10 +19991,10 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.2.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.19, lodash@~4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.2.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.19, lodash@~4.17.20: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-ok@^0.1.1: version "0.1.1"