From a0b787c39a7eab88c2de3a64aa872779b94abe39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Fri, 15 Jan 2021 08:13:15 -0500 Subject: [PATCH 01/33] Fix flaky test for legacy authorization (#87642) * Unskip test * Increase attempts to 2 for retryIfConflicts * Cleanup authorization for updateApiKey --- .../plugins/alerts/server/alerts_client/alerts_client.ts | 5 +---- .../server/authorization/alerts_authorization.mock.ts | 1 - .../alerts/server/authorization/alerts_authorization.ts | 7 +------ x-pack/plugins/alerts/server/lib/retry_if_conflicts.ts | 4 +--- .../security_and_spaces/tests/alerting/rbac_legacy.ts | 2 +- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts b/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts index b6606d9d7fe578..457079229de94d 100644 --- a/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts +++ b/x-pack/plugins/alerts/server/alerts_client/alerts_client.ts @@ -817,10 +817,7 @@ export class AlertsClient { attributes.consumer, WriteOperations.UpdateApiKey ); - if ( - attributes.actions.length && - !this.authorization.shouldUseLegacyAuthorization(attributes) - ) { + if (attributes.actions.length) { await this.actionsAuthorization.ensureAuthorized('execute'); } } catch (error) { diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts index 171e3978d0d0d2..30de2c79732ced 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts @@ -14,7 +14,6 @@ const createAlertsAuthorizationMock = () => { ensureAuthorized: jest.fn(), filterByAlertTypeAuthorization: jest.fn(), getFindAuthorizationFilter: jest.fn(), - shouldUseLegacyAuthorization: jest.fn(), }; return mocked; }; diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts index 6814e4ac1cc1bf..29f2078bc61e41 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.ts @@ -8,13 +8,12 @@ import Boom from '@hapi/boom'; import { map, mapValues, fromPairs, has } from 'lodash'; import { KibanaRequest } from 'src/core/server'; import { ALERTS_FEATURE_ID } from '../../common'; -import { AlertTypeRegistry, RawAlert } from '../types'; +import { AlertTypeRegistry } from '../types'; import { SecurityPluginSetup } from '../../../security/server'; import { RegistryAlertType } from '../alert_type_registry'; import { PluginStartContract as FeaturesPluginStart } from '../../../features/server'; import { AlertsAuthorizationAuditLogger, ScopeType } from './audit_logger'; import { Space } from '../../../spaces/server'; -import { LEGACY_LAST_MODIFIED_VERSION } from '../saved_objects/migrations'; import { asFiltersByAlertTypeAndConsumer } from './alerts_authorization_kuery'; import { KueryNode } from '../../../../../src/plugins/data/server'; @@ -112,10 +111,6 @@ export class AlertsAuthorization { ); } - public shouldUseLegacyAuthorization(alert: RawAlert): boolean { - return alert.meta?.versionApiKeyLastmodified === LEGACY_LAST_MODIFIED_VERSION; - } - private shouldCheckAuthorization(): boolean { return this.authorization?.mode?.useRbacForRequest(this.request) ?? false; } diff --git a/x-pack/plugins/alerts/server/lib/retry_if_conflicts.ts b/x-pack/plugins/alerts/server/lib/retry_if_conflicts.ts index 9cb1d7975855c2..59ecc59ab57f8c 100644 --- a/x-pack/plugins/alerts/server/lib/retry_if_conflicts.ts +++ b/x-pack/plugins/alerts/server/lib/retry_if_conflicts.ts @@ -15,9 +15,7 @@ import { Logger, SavedObjectsErrorHelpers } from '../../../../../src/core/server type RetryableForConflicts = () => Promise; // number of times to retry when conflicts occur -// note: it seems unlikely that we'd need more than one retry, but leaving -// this statically configurable in case we DO need > 1 -export const RetryForConflictsAttempts = 1; +export const RetryForConflictsAttempts = 2; // milliseconds to wait before retrying when conflicts occur // note: we considered making this random, to help avoid a stampede, but diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts index 992d9210b9761b..2b25c82cc92e5b 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts @@ -62,7 +62,7 @@ export default function alertTests({ getService }: FtrProviderContext) { }); }); - it.skip('should schedule actions on legacy alerts', async () => { + it('should schedule actions on legacy alerts', async () => { const reference = `alert:migrated-to-7.10:${user.username}`; const migratedAlertId = MIGRATED_ALERT_ID[user.username]; From 5fd0027ba279fcc57f827d3580317c31f3c038dd Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 15 Jan 2021 16:45:26 +0300 Subject: [PATCH 02/33] use the same defaults as Lens (#87991) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/components/xy_settings.tsx | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/plugins/vis_type_xy/public/components/xy_settings.tsx b/src/plugins/vis_type_xy/public/components/xy_settings.tsx index 3682fdf3350b04..18099173c56a9d 100644 --- a/src/plugins/vis_type_xy/public/components/xy_settings.tsx +++ b/src/plugins/vis_type_xy/public/components/xy_settings.tsx @@ -32,6 +32,8 @@ import { LegendColorPicker, TooltipProps, TickFormatter, + VerticalAlignment, + HorizontalAlignment, } from '@elastic/charts'; import { renderEndzoneTooltip } from '../../../charts/public'; @@ -70,6 +72,27 @@ type XYSettingsProps = Pick< legendPosition: Position; }; +function getValueLabelsStyling(isHorizontal: boolean) { + const VALUE_LABELS_MAX_FONTSIZE = 15; + const VALUE_LABELS_MIN_FONTSIZE = 10; + const VALUE_LABELS_VERTICAL_OFFSET = -10; + const VALUE_LABELS_HORIZONTAL_OFFSET = 10; + + return { + displayValue: { + fontSize: { min: VALUE_LABELS_MIN_FONTSIZE, max: VALUE_LABELS_MAX_FONTSIZE }, + fill: { textInverted: true, textBorder: 2 }, + alignment: isHorizontal + ? { + vertical: VerticalAlignment.Middle, + } + : { horizontal: HorizontalAlignment.Center }, + offsetX: isHorizontal ? VALUE_LABELS_HORIZONTAL_OFFSET : 0, + offsetY: isHorizontal ? 0 : VALUE_LABELS_VERTICAL_OFFSET, + }, + }; +} + export const XYSettings: FC = ({ markSizeRatio, rotation, @@ -92,10 +115,7 @@ export const XYSettings: FC = ({ const theme = themeService.useChartsTheme(); const baseTheme = themeService.useChartsBaseTheme(); const dimmingOpacity = getUISettings().get('visualization:dimmingOpacity'); - const fontSize = - typeof theme.barSeriesStyle?.displayValue?.fontSize === 'number' - ? { min: theme.barSeriesStyle?.displayValue?.fontSize } - : theme.barSeriesStyle?.displayValue?.fontSize ?? { min: 8 }; + const valueLabelsStyling = getValueLabelsStyling(rotation === 90 || rotation === -90); const themeOverrides: PartialTheme = { markSizeRatio, @@ -105,13 +125,7 @@ export const XYSettings: FC = ({ }, }, barSeriesStyle: { - displayValue: { - fontSize, - alignment: { - horizontal: 'center', - vertical: 'middle', - }, - }, + ...valueLabelsStyling, }, axes: { axisTitle: { From 1bd408603243e80e5d8ed042505c4c87a140ffb8 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Fri, 15 Jan 2021 14:55:53 +0100 Subject: [PATCH 03/33] Move Spaces, Security and EncryptedSavedObjects plugins to separate TS projects (#88365) --- .../encrypted_saved_objects/tsconfig.json | 14 ++++++ .../common/model/authenticated_user.ts | 2 +- x-pack/plugins/security/tsconfig.json | 24 +++++++++ .../public/management/components/index.ts | 1 - .../components/secure_space_message/index.ts | 7 --- .../secure_space_message.tsx | 49 ------------------- .../enabled_features.test.tsx.snap | 20 -------- .../enabled_features.test.tsx | 8 --- .../enabled_features/enabled_features.tsx | 24 +-------- .../edit_space/manage_space_page.test.tsx | 5 -- .../edit_space/manage_space_page.tsx | 12 +---- .../public/management/management_service.tsx | 6 +-- .../spaces_grid_pages.test.tsx.snap | 3 -- .../spaces_grid/spaces_grid_page.tsx | 10 +--- .../spaces_grid/spaces_grid_pages.test.tsx | 4 -- .../management/spaces_management_app.test.tsx | 15 ++---- .../management/spaces_management_app.tsx | 7 +-- x-pack/plugins/spaces/public/plugin.tsx | 4 -- x-pack/plugins/spaces/tsconfig.json | 22 +++++++++ .../translations/translations/ja-JP.json | 7 +-- .../translations/translations/zh-CN.json | 7 +-- x-pack/test/tsconfig.json | 3 ++ x-pack/tsconfig.json | 6 +++ x-pack/tsconfig.refs.json | 3 ++ 24 files changed, 85 insertions(+), 178 deletions(-) create mode 100644 x-pack/plugins/encrypted_saved_objects/tsconfig.json create mode 100644 x-pack/plugins/security/tsconfig.json delete mode 100644 x-pack/plugins/spaces/public/management/components/secure_space_message/index.ts delete mode 100644 x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx create mode 100644 x-pack/plugins/spaces/tsconfig.json diff --git a/x-pack/plugins/encrypted_saved_objects/tsconfig.json b/x-pack/plugins/encrypted_saved_objects/tsconfig.json new file mode 100644 index 00000000000000..2b51b313d34fcb --- /dev/null +++ b/x-pack/plugins/encrypted_saved_objects/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["server/**/*"], + "references": [ + { "path": "../security/tsconfig.json" }, + ] +} diff --git a/x-pack/plugins/security/common/model/authenticated_user.ts b/x-pack/plugins/security/common/model/authenticated_user.ts index 491ceb6845e28a..5513fa27fa1784 100644 --- a/x-pack/plugins/security/common/model/authenticated_user.ts +++ b/x-pack/plugins/security/common/model/authenticated_user.ts @@ -8,7 +8,7 @@ import type { AuthenticationProvider, User } from '.'; const REALMS_ELIGIBLE_FOR_PASSWORD_CHANGE = ['reserved', 'native']; -interface UserRealm { +export interface UserRealm { name: string; type: string; } diff --git a/x-pack/plugins/security/tsconfig.json b/x-pack/plugins/security/tsconfig.json new file mode 100644 index 00000000000000..6c3fd1851a8cbe --- /dev/null +++ b/x-pack/plugins/security/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*"], + "references": [ + { "path": "../features/tsconfig.json" }, + { "path": "../licensing/tsconfig.json" }, + { "path": "../spaces/tsconfig.json" }, + { "path": "../task_manager/tsconfig.json" }, + { "path": "../../../src/plugins/data/tsconfig.json" }, + { "path": "../../../src/plugins/es_ui_shared/tsconfig.json" }, + { "path": "../../../src/plugins/home/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" }, + { "path": "../../../src/plugins/security_oss/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" } + ] +} diff --git a/x-pack/plugins/spaces/public/management/components/index.ts b/x-pack/plugins/spaces/public/management/components/index.ts index 7f9f80f470d12a..91f4964e1da068 100644 --- a/x-pack/plugins/spaces/public/management/components/index.ts +++ b/x-pack/plugins/spaces/public/management/components/index.ts @@ -6,4 +6,3 @@ export { ConfirmDeleteModal } from './confirm_delete_modal'; export { UnauthorizedPrompt } from './unauthorized_prompt'; -export { SecureSpaceMessage } from './secure_space_message'; diff --git a/x-pack/plugins/spaces/public/management/components/secure_space_message/index.ts b/x-pack/plugins/spaces/public/management/components/secure_space_message/index.ts deleted file mode 100644 index 4526dc791a224d..00000000000000 --- a/x-pack/plugins/spaces/public/management/components/secure_space_message/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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 { SecureSpaceMessage } from './secure_space_message'; diff --git a/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx b/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx deleted file mode 100644 index 9500810a395f87..00000000000000 --- a/x-pack/plugins/spaces/public/management/components/secure_space_message/secure_space_message.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import React, { Fragment } from 'react'; -import { ApplicationStart } from 'kibana/public'; - -interface SecureSpaceMessageProps { - getUrlForApp: ApplicationStart['getUrlForApp']; -} - -export const SecureSpaceMessage = (props: SecureSpaceMessageProps) => { - const rolesLinkTextAriaLabel = i18n.translate( - 'xpack.spaces.management.secureSpaceMessage.rolesLinkTextAriaLabel', - { defaultMessage: 'Roles management page' } - ); - return ( - - - -

- - - - ), - }} - /> -

-
-
- ); -}; diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap index 28aa8750beddd8..c22a25ef60c313 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap @@ -59,26 +59,6 @@ exports[`EnabledFeatures renders as expected 1`] = ` values={Object {}} />

-

- - - , - } - } - /> -

diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx index aa47e439af95fe..b84b1cc699d5f5 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx @@ -42,7 +42,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: ['feature-1', 'feature-2'], }} - securityEnabled={true} onChange={jest.fn()} getUrlForApp={getUrlForApp} /> @@ -61,7 +60,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: ['feature-1', 'feature-2'], }} - securityEnabled={true} onChange={changeHandler} getUrlForApp={getUrlForApp} /> @@ -96,7 +94,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: [], }} - securityEnabled={true} onChange={changeHandler} getUrlForApp={getUrlForApp} /> @@ -134,7 +131,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: [], }} - securityEnabled={true} onChange={changeHandler} getUrlForApp={getUrlForApp} /> @@ -165,7 +161,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: ['feature-1', 'feature-2'], }} - securityEnabled={true} onChange={changeHandler} getUrlForApp={getUrlForApp} /> @@ -194,7 +189,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: ['feature-1'], }} - securityEnabled={true} onChange={jest.fn()} getUrlForApp={getUrlForApp} /> @@ -214,7 +208,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: [], }} - securityEnabled={true} onChange={changeHandler} getUrlForApp={getUrlForApp} /> @@ -243,7 +236,6 @@ describe('EnabledFeatures', () => { name: 'my space', disabledFeatures: [], }} - securityEnabled={true} onChange={changeHandler} getUrlForApp={getUrlForApp} /> diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx index 9429472d9e3424..41cdef94fa3151 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { Component, Fragment, ReactNode } from 'react'; @@ -18,7 +18,6 @@ import { FeatureTable } from './feature_table'; interface Props { space: Partial; features: KibanaFeatureConfig[]; - securityEnabled: boolean; onChange: (space: Partial) => void; getUrlForApp: ApplicationStart['getUrlForApp']; } @@ -129,27 +128,6 @@ export class EnabledFeatures extends Component { defaultMessage="The feature is hidden in the UI, but is not disabled." />

- {this.props.securityEnabled && ( -

- - - - ), - }} - /> -

- )} ); diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx index bc26d6f1325224..50e40ca75e0dc9 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.test.tsx @@ -58,7 +58,6 @@ describe('ManageSpacePage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -120,7 +119,6 @@ describe('ManageSpacePage', () => { onLoadSpace={onLoadSpace} getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -173,7 +171,6 @@ describe('ManageSpacePage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={() => Promise.reject(error)} notifications={notifications} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -211,7 +208,6 @@ describe('ManageSpacePage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -273,7 +269,6 @@ describe('ManageSpacePage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ diff --git a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx index 285dd6a1134ecb..b954b314c8854e 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/manage_space_page.tsx @@ -23,7 +23,7 @@ import { Space } from '../../../../../../src/plugins/spaces_oss/common'; import { KibanaFeature, FeaturesPluginStart } from '../../../../features/public'; import { isReservedSpace } from '../../../common'; import { SpacesManager } from '../../spaces_manager'; -import { SecureSpaceMessage, UnauthorizedPrompt } from '../components'; +import { UnauthorizedPrompt } from '../components'; import { toSpaceIdentifier } from '../lib'; import { SpaceValidator } from '../lib/validate_space'; import { ConfirmAlterActiveSpaceModal } from './confirm_alter_active_space_modal'; @@ -39,7 +39,6 @@ interface Props { spaceId?: string; onLoadSpace?: (space: Space) => void; capabilities: Capabilities; - securityEnabled: boolean; history: ScopedHistory; getUrlForApp: ApplicationStart['getUrlForApp']; } @@ -107,7 +106,6 @@ export class ManageSpacePage extends Component { return ( {content} - {this.maybeGetSecureSpacesMessage()} ); } @@ -157,7 +155,6 @@ export class ManageSpacePage extends Component { features={this.state.features} onChange={this.onSpaceChange} getUrlForApp={this.props.getUrlForApp} - securityEnabled={this.props.securityEnabled} /> @@ -201,13 +198,6 @@ export class ManageSpacePage extends Component { ); }; - public maybeGetSecureSpacesMessage = () => { - if (this.editingExistingSpace() && this.props.securityEnabled) { - return ; - } - return null; - }; - public getFormButtons = () => { const createSpaceText = i18n.translate( 'xpack.spaces.management.manageSpacePage.createSpaceButton', diff --git a/x-pack/plugins/spaces/public/management/management_service.tsx b/x-pack/plugins/spaces/public/management/management_service.tsx index 11853e5f1abdd3..aa4cc51726a4e5 100644 --- a/x-pack/plugins/spaces/public/management/management_service.tsx +++ b/x-pack/plugins/spaces/public/management/management_service.tsx @@ -6,7 +6,6 @@ import { StartServicesAccessor } from 'src/core/public'; import { ManagementSetup, ManagementApp } from '../../../../../src/plugins/management/public'; -import { SecurityLicense } from '../../../security/public'; import { SpacesManager } from '../spaces_manager'; import { PluginsStart } from '../plugin'; import { spacesManagementApp } from './spaces_management_app'; @@ -15,15 +14,14 @@ interface SetupDeps { management: ManagementSetup; getStartServices: StartServicesAccessor; spacesManager: SpacesManager; - securityLicense?: SecurityLicense; } export class ManagementService { private registeredSpacesManagementApp?: ManagementApp; - public setup({ getStartServices, management, spacesManager, securityLicense }: SetupDeps) { + public setup({ getStartServices, management, spacesManager }: SetupDeps) { this.registeredSpacesManagementApp = management.sections.section.kibana.registerApp( - spacesManagementApp.create({ getStartServices, spacesManager, securityLicense }) + spacesManagementApp.create({ getStartServices, spacesManager }) ); } diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap b/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap index 497b13642b81b5..3b67cceb1c8690 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/spaces_grid/__snapshots__/spaces_grid_pages.test.tsx.snap @@ -125,9 +125,6 @@ exports[`SpacesGridPage renders as expected 1`] = ` tableLayout="fixed" /> - `; diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx index ae93ae80c7cd25..f75bc1d084cd8c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx @@ -27,10 +27,8 @@ import { isReservedSpace } from '../../../common'; import { DEFAULT_SPACE_ID } from '../../../common/constants'; import { SpaceAvatar } from '../../space_avatar'; import { getSpacesFeatureDescription } from '../../constants'; -import { SpacesManager } from '../..//spaces_manager'; -import { ConfirmDeleteModal } from '../components/confirm_delete_modal'; -import { SecureSpaceMessage } from '../components/secure_space_message'; -import { UnauthorizedPrompt } from '../components/unauthorized_prompt'; +import { SpacesManager } from '../../spaces_manager'; +import { ConfirmDeleteModal, UnauthorizedPrompt } from '../components'; import { getEnabledFeatures } from '../lib/feature_utils'; import { reactRouterNavigate } from '../../../../../../src/plugins/kibana_react/public'; @@ -39,7 +37,6 @@ interface Props { notifications: NotificationsStart; getFeatures: FeaturesPluginStart['getFeatures']; capabilities: Capabilities; - securityEnabled: boolean; history: ScopedHistory; getUrlForApp: ApplicationStart['getUrlForApp']; } @@ -74,9 +71,6 @@ export class SpacesGridPage extends Component { return (
{this.getPageContent()} - {this.props.securityEnabled && ( - - )} {this.getConfirmDeleteModal()}
); diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx index 606bb5cfbdcc99..945e3298f46a5c 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_pages.test.tsx @@ -65,7 +65,6 @@ describe('SpacesGridPage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -88,7 +87,6 @@ describe('SpacesGridPage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={featuresStart.getFeatures} notifications={notificationServiceMock.createStartContract()} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -122,7 +120,6 @@ describe('SpacesGridPage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={featuresStart.getFeatures} notifications={notifications} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ @@ -157,7 +154,6 @@ describe('SpacesGridPage', () => { spacesManager={(spacesManager as unknown) as SpacesManager} getFeatures={() => Promise.reject(error)} notifications={notifications} - securityEnabled={true} getUrlForApp={getUrlForApp} history={history} capabilities={{ diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index e345657a785c12..fc824bec6e2cef 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -20,9 +20,7 @@ jest.mock('./edit_space', () => ({ import { spacesManagementApp } from './spaces_management_app'; import { coreMock, scopedHistoryMock } from '../../../../../src/core/public/mocks'; -import { securityMock } from '../../../security/public/mocks'; import { spacesManagerMock } from '../spaces_manager/mocks'; -import { SecurityLicenseFeatures } from '../../../security/public'; import { featuresPluginMock } from '../../../features/public/mocks'; import { PluginsStart } from '../plugin'; @@ -39,18 +37,12 @@ async function mountApp(basePath: string, pathname: string, spaceId?: string) { }); } - const securityLicense = securityMock.createSetup().license; - securityLicense.getFeatures.mockReturnValue({ - showLinks: true, - } as SecurityLicenseFeatures); - const [coreStart, pluginsStart] = await coreMock.createSetup().getStartServices(); (pluginsStart as PluginsStart).features = featuresPluginMock.createStart(); const unmount = await spacesManagementApp .create({ spacesManager, - securityLicense, getStartServices: async () => [coreStart, pluginsStart as PluginsStart, {}], }) .mount({ @@ -68,7 +60,6 @@ describe('spacesManagementApp', () => { expect( spacesManagementApp.create({ spacesManager: spacesManagerMock.create(), - securityLicense: securityMock.createSetup().license, getStartServices: coreMock.createSetup().getStartServices as any, }) ).toMatchInlineSnapshot(` @@ -91,7 +82,7 @@ describe('spacesManagementApp', () => { `); @@ -114,7 +105,7 @@ describe('spacesManagementApp', () => { `); @@ -139,7 +130,7 @@ describe('spacesManagementApp', () => { `); diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx index a328c50af4e7a6..9c2584dfcee67d 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.tsx @@ -10,7 +10,6 @@ import { Router, Route, Switch, useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { StartServicesAccessor } from 'src/core/public'; import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; -import { SecurityLicense } from '../../../security/public'; import { RegisterManagementAppArgs } from '../../../../../src/plugins/management/public'; import { PluginsStart } from '../plugin'; import { SpacesManager } from '../spaces_manager'; @@ -21,12 +20,11 @@ import { Space } from '..'; interface CreateParams { getStartServices: StartServicesAccessor; spacesManager: SpacesManager; - securityLicense?: SecurityLicense; } export const spacesManagementApp = Object.freeze({ id: 'spaces', - create({ getStartServices, spacesManager, securityLicense }: CreateParams) { + create({ getStartServices, spacesManager }: CreateParams) { return { id: this.id, order: 2, @@ -58,7 +56,6 @@ export const spacesManagementApp = Object.freeze({ spacesManager={spacesManager} history={history} getUrlForApp={application.getUrlForApp} - securityEnabled={securityLicense?.getFeatures().showLinks ?? false} /> ); }; @@ -81,7 +78,6 @@ export const spacesManagementApp = Object.freeze({ spacesManager={spacesManager} history={history} getUrlForApp={application.getUrlForApp} - securityEnabled={securityLicense?.getFeatures().showLinks ?? false} /> ); }; @@ -109,7 +105,6 @@ export const spacesManagementApp = Object.freeze({ onLoadSpace={onLoadSpace} history={history} getUrlForApp={application.getUrlForApp} - securityEnabled={securityLicense?.getFeatures().showLinks ?? false} /> ); }; diff --git a/x-pack/plugins/spaces/public/plugin.tsx b/x-pack/plugins/spaces/public/plugin.tsx index c479c01991e31f..43888c7b5758b6 100644 --- a/x-pack/plugins/spaces/public/plugin.tsx +++ b/x-pack/plugins/spaces/public/plugin.tsx @@ -11,7 +11,6 @@ import { SavedObjectsManagementPluginSetup } from 'src/plugins/saved_objects_man import { ManagementStart, ManagementSetup } from 'src/plugins/management/public'; import { AdvancedSettingsSetup } from 'src/plugins/advanced_settings/public'; import { FeaturesPluginStart } from '../../features/public'; -import { SecurityPluginStart, SecurityPluginSetup } from '../../security/public'; import { SpacesManager } from './spaces_manager'; import { initSpacesNavControl } from './nav_control'; import { createSpacesFeatureCatalogueEntry } from './create_feature_catalogue_entry'; @@ -26,14 +25,12 @@ export interface PluginsSetup { advancedSettings?: AdvancedSettingsSetup; home?: HomePublicPluginSetup; management?: ManagementSetup; - security?: SecurityPluginSetup; savedObjectsManagement?: SavedObjectsManagementPluginSetup; } export interface PluginsStart { features: FeaturesPluginStart; management?: ManagementStart; - security?: SecurityPluginStart; } export type SpacesPluginSetup = ReturnType; @@ -57,7 +54,6 @@ export class SpacesPlugin implements Plugin, spacesManager: this.spacesManager, - securityLicense: plugins.security?.license, }); } diff --git a/x-pack/plugins/spaces/tsconfig.json b/x-pack/plugins/spaces/tsconfig.json new file mode 100644 index 00000000000000..95fbecaa909366 --- /dev/null +++ b/x-pack/plugins/spaces/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*"], + "references": [ + { "path": "../features/tsconfig.json" }, + { "path": "../licensing/tsconfig.json" }, + { "path": "../../../src/plugins/advanced_settings/tsconfig.json" }, + { "path": "../../../src/plugins/home/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" }, + { "path": "../../../src/plugins/saved_objects_management/tsconfig.json" }, + { "path": "../../../src/plugins/spaces_oss/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" } + ] +} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 67c307dbf56ccf..f479b3a521185d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -20772,10 +20772,8 @@ "xpack.spaces.management.enabledSpaceFeatures.allFeaturesEnabledMessage": "(表示されているすべての機能)", "xpack.spaces.management.enabledSpaceFeatures.enabledFeaturesSectionMessage": "機能", "xpack.spaces.management.enabledSpaceFeatures.enableFeaturesInSpaceMessage": "このスペースの機能の表示を設定", - "xpack.spaces.management.enabledSpaceFeatures.goToRolesLink": "機能へのアクセスを保護する場合は、{manageSecurityRoles}してください。", "xpack.spaces.management.enabledSpaceFeatures.noFeaturesEnabledMessage": "(表示されている機能がありません)", "xpack.spaces.management.enabledSpaceFeatures.notASecurityMechanismMessage": "この機能は UI で非表示になっていますが、無効ではありません。", - "xpack.spaces.management.enabledSpaceFeatures.rolesLinkText": "セキュリティロールを管理", "xpack.spaces.management.enabledSpaceFeatures.someFeaturesEnabledMessage": "({featureCount} 件中 {enabledCount} 件の機能を表示中)", "xpack.spaces.management.featureAccordionSwitchLabel": "{featureCount}件中{enabledCount}件の機能を表示中", "xpack.spaces.management.featureVisibilityTitle": "機能の表示", @@ -20802,9 +20800,6 @@ "xpack.spaces.management.manageSpacePage.spaceSuccessfullySavedNotificationMessage": "スペース {name} が保存されました。", "xpack.spaces.management.manageSpacePage.updateSpaceButton": "スペースを更新", "xpack.spaces.management.reversedSpaceBadge.reversedSpacesCanBePartiallyModifiedTooltip": "リザーブされたスペースはビルトインのため、部分的な変更しかできません。", - "xpack.spaces.management.secureSpaceMessage.howToAssignRoleToSpaceDescription": "スペースへのロールの割り当てをご希望ですか?{rolesLink} に移動してください。", - "xpack.spaces.management.secureSpaceMessage.rolesLinkText": "ロール", - "xpack.spaces.management.secureSpaceMessage.rolesLinkTextAriaLabel": "ロール管理ページ", "xpack.spaces.management.selectAllFeaturesLink": "すべて選択", "xpack.spaces.management.shareToSpace.actionDescription": "この保存されたオブジェクトを1つ以上のスペースと共有します。", "xpack.spaces.management.shareToSpace.actionTitle": "スペースと共有", @@ -22782,4 +22777,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9746c8b9ca8068..a661537e6e2886 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -20820,10 +20820,8 @@ "xpack.spaces.management.enabledSpaceFeatures.allFeaturesEnabledMessage": "(所有可见功能)", "xpack.spaces.management.enabledSpaceFeatures.enabledFeaturesSectionMessage": "功能", "xpack.spaces.management.enabledSpaceFeatures.enableFeaturesInSpaceMessage": "为此工作区设置功能可见性", - "xpack.spaces.management.enabledSpaceFeatures.goToRolesLink": "如果您希望保护对功能的访问,请{manageSecurityRoles}。", "xpack.spaces.management.enabledSpaceFeatures.noFeaturesEnabledMessage": "(没有可见功能)", "xpack.spaces.management.enabledSpaceFeatures.notASecurityMechanismMessage": "该功能在 UI 中已隐藏,但未禁用。", - "xpack.spaces.management.enabledSpaceFeatures.rolesLinkText": "管理安全角色", "xpack.spaces.management.enabledSpaceFeatures.someFeaturesEnabledMessage": "({enabledCount} / {featureCount} 个功能可见)", "xpack.spaces.management.featureAccordionSwitchLabel": "{enabledCount} / {featureCount} 个功能可见", "xpack.spaces.management.featureVisibilityTitle": "功能可见性", @@ -20850,9 +20848,6 @@ "xpack.spaces.management.manageSpacePage.spaceSuccessfullySavedNotificationMessage": "空间 “{name}” 已保存。", "xpack.spaces.management.manageSpacePage.updateSpaceButton": "更新工作区", "xpack.spaces.management.reversedSpaceBadge.reversedSpacesCanBePartiallyModifiedTooltip": "保留的空间是内置的,只能进行部分修改。", - "xpack.spaces.management.secureSpaceMessage.howToAssignRoleToSpaceDescription": "想要为工作区分配角色?前往{rolesLink}。", - "xpack.spaces.management.secureSpaceMessage.rolesLinkText": "角色", - "xpack.spaces.management.secureSpaceMessage.rolesLinkTextAriaLabel": "角色管理页面", "xpack.spaces.management.selectAllFeaturesLink": "全选", "xpack.spaces.management.shareToSpace.actionDescription": "将此已保存对象共享到一个或多个工作区", "xpack.spaces.management.shareToSpace.actionTitle": "共享到工作区", @@ -22833,4 +22828,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +} diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index a0a94f91a1ddbb..0fbb16c0e8c872 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -46,5 +46,8 @@ { "path": "../plugins/task_manager/tsconfig.json" }, { "path": "../plugins/telemetry_collection_xpack/tsconfig.json" }, { "path": "../plugins/ui_actions_enhanced/tsconfig.json" }, + { "path": "../plugins/spaces/tsconfig.json" }, + { "path": "../plugins/security/tsconfig.json" }, + { "path": "../plugins/encrypted_saved_objects/tsconfig.json" } ] } diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index dc720fced30632..01d9bcf9537ecd 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -21,6 +21,9 @@ "plugins/translations/**/*", "plugins/ui_actions_enhanced/**/*", "plugins/vis_type_timeseries_enhanced/**/*", + "plugins/spaces/**/*", + "plugins/security/**/*", + "plugins/encrypted_saved_objects/**/*", "test/**/*" ], "compilerOptions": { @@ -77,5 +80,8 @@ { "path": "./plugins/ui_actions_enhanced/tsconfig.json" }, { "path": "./plugins/vis_type_timeseries_enhanced/tsconfig.json" }, { "path": "./plugins/translations/tsconfig.json" }, + { "path": "./plugins/spaces/tsconfig.json" }, + { "path": "./plugins/security/tsconfig.json" }, + { "path": "./plugins/encrypted_saved_objects/tsconfig.json" } ] } diff --git a/x-pack/tsconfig.refs.json b/x-pack/tsconfig.refs.json index 08c81d5f3b8021..4352d2993002a4 100644 --- a/x-pack/tsconfig.refs.json +++ b/x-pack/tsconfig.refs.json @@ -17,5 +17,8 @@ { "path": "./plugins/ui_actions_enhanced/tsconfig.json" }, { "path": "./plugins/vis_type_timeseries_enhanced/tsconfig.json" }, { "path": "./plugins/translations/tsconfig.json" }, + { "path": "./plugins/spaces/tsconfig.json" }, + { "path": "./plugins/security/tsconfig.json" }, + { "path": "./plugins/encrypted_saved_objects/tsconfig.json" } ] } From 11d4457d9714df83d0029d55c87bffb3b339add3 Mon Sep 17 00:00:00 2001 From: John Schulz Date: Fri, 15 Jan 2021 09:33:19 -0500 Subject: [PATCH 04/33] Don't retry if icon isn't in initial response (#88403) --- .../create_package_policy_page/step_select_package.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_package.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_package.tsx index 3bcafaecbf8d93..ef8dba4447c318 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_package.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/step_select_package.tsx @@ -141,15 +141,7 @@ export const StepSelectPackage: React.FunctionComponent<{ return { label: title || name, key: pkgkey, - prepend: ( - - ), + prepend: , checked: selectedPkgKey === pkgkey ? 'on' : undefined, }; })} From 31a481a9dda7e2b9028b9aad9e8b4e71804832cd Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Fri, 15 Jan 2021 08:44:28 -0600 Subject: [PATCH 05/33] Remove dependency between alerts and infra (#88342) The alerts plugin was importing `JsonObject` from the infra plugin. The infra plugin imported `JsonObject`, `JsonValue`, and `JsonArray` from kibanaUtils and then re-exported them. Remove the re-export from the infra plugin and instead always import these types from kibanaUtils. --- x-pack/plugins/alerts/common/alert_navigation.ts | 3 ++- x-pack/plugins/alerts/kibana.json | 10 +++++++++- .../alerts/public/alert_navigation_registry/types.ts | 2 +- x-pack/plugins/infra/common/typed_json.ts | 2 -- .../infra/public/components/log_stream/index.tsx | 2 +- .../components/logging/log_text_stream/field_value.tsx | 2 +- .../logging/log_text_stream/log_entry_field_column.tsx | 2 +- .../public/utils/log_column_render_configuration.tsx | 2 +- .../server/lib/adapters/framework/adapter_types.ts | 2 +- .../adapters/log_entries/kibana_log_entries_adapter.ts | 2 +- .../domains/log_entries_domain/log_entries_domain.ts | 2 +- .../server/lib/domains/log_entries_domain/message.ts | 2 +- .../lib/domains/log_entries_domain/rule_types.ts | 2 +- .../routes/snapshot/lib/get_metrics_aggregations.ts | 2 +- x-pack/plugins/infra/server/utils/serialized_query.ts | 2 +- .../infra/server/utils/typed_search_strategy.ts | 3 ++- x-pack/plugins/infra/types/eui.d.ts | 3 --- .../plugins/security_solution/server/endpoint/types.ts | 2 +- 18 files changed, 26 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/alerts/common/alert_navigation.ts b/x-pack/plugins/alerts/common/alert_navigation.ts index 188764069e84f3..b04278b6517c8a 100644 --- a/x-pack/plugins/alerts/common/alert_navigation.ts +++ b/x-pack/plugins/alerts/common/alert_navigation.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { JsonObject } from '../../infra/common/typed_json'; +import { JsonObject } from '../../../../src/plugins/kibana_utils/common'; + export interface AlertUrlNavigation { path: string; } diff --git a/x-pack/plugins/alerts/kibana.json b/x-pack/plugins/alerts/kibana.json index c0ab2428314283..a2cb237467f112 100644 --- a/x-pack/plugins/alerts/kibana.json +++ b/x-pack/plugins/alerts/kibana.json @@ -5,7 +5,15 @@ "version": "8.0.0", "kibanaVersion": "kibana", "configPath": ["xpack", "alerts"], - "requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "actions", "eventLog", "features"], + "requiredPlugins": [ + "actions", + "encryptedSavedObjects", + "eventLog", + "features", + "kibanaUtils", + "licensing", + "taskManager" + ], "optionalPlugins": ["usageCollection", "spaces", "security"], "extraPublicDirs": ["common", "common/parse_duration"] } diff --git a/x-pack/plugins/alerts/public/alert_navigation_registry/types.ts b/x-pack/plugins/alerts/public/alert_navigation_registry/types.ts index 0038652f47f129..e0ab2dcf405f33 100644 --- a/x-pack/plugins/alerts/public/alert_navigation_registry/types.ts +++ b/x-pack/plugins/alerts/public/alert_navigation_registry/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { JsonObject } from '../../../infra/common/typed_json'; +import { JsonObject } from '../../../../../src/plugins/kibana_utils/common'; import { AlertType, SanitizedAlert } from '../../common'; export type AlertNavigationHandler = ( diff --git a/x-pack/plugins/infra/common/typed_json.ts b/x-pack/plugins/infra/common/typed_json.ts index 0ff9e42942ef20..f3e7608910e095 100644 --- a/x-pack/plugins/infra/common/typed_json.ts +++ b/x-pack/plugins/infra/common/typed_json.ts @@ -20,5 +20,3 @@ export const jsonArrayRT: rt.Type = rt.recursion('JsonArray', () => export const jsonObjectRT: rt.Type = rt.recursion('JsonObject', () => rt.record(rt.string, jsonValueRT) ); - -export { JsonValue, JsonArray, JsonObject }; diff --git a/x-pack/plugins/infra/public/components/log_stream/index.tsx b/x-pack/plugins/infra/public/components/log_stream/index.tsx index 997f81583fb645..3d69b6a0229870 100644 --- a/x-pack/plugins/infra/public/components/log_stream/index.tsx +++ b/x-pack/plugins/infra/public/components/log_stream/index.tsx @@ -16,7 +16,7 @@ import { useLogStream } from '../../containers/logs/log_stream'; import { ScrollableLogTextStreamView } from '../logging/log_text_stream'; import { LogColumnRenderConfiguration } from '../../utils/log_column_render_configuration'; -import { JsonValue } from '../../../common/typed_json'; +import { JsonValue } from '../../../../../../src/plugins/kibana_utils/common'; const PAGE_THRESHOLD = 2; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx index 4047e80846ca67..b13e3569c1e5b5 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx @@ -7,7 +7,7 @@ import stringify from 'json-stable-stringify'; import React from 'react'; import { euiStyled } from '../../../../../observability/public'; -import { JsonArray, JsonValue } from '../../../../common/typed_json'; +import { JsonArray, JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; import { ActiveHighlightMarker, highlightFieldValue, HighlightMarker } from './highlighting'; export const FieldValue: React.FC<{ diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx index a8165463d7ee6b..fe5e7f305f60c7 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { JsonValue } from '../../../../common/typed_json'; +import { JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; import { euiStyled } from '../../../../../observability/public'; import { LogColumn } from '../../../../common/http_api'; import { isFieldColumn, isHighlightFieldColumn } from '../../../utils/log_entry'; diff --git a/x-pack/plugins/infra/public/utils/log_column_render_configuration.tsx b/x-pack/plugins/infra/public/utils/log_column_render_configuration.tsx index 7ffbfcace88cef..95ebe37b64c972 100644 --- a/x-pack/plugins/infra/public/utils/log_column_render_configuration.tsx +++ b/x-pack/plugins/infra/public/utils/log_column_render_configuration.tsx @@ -5,7 +5,7 @@ */ import { ReactNode } from 'react'; -import { JsonValue } from '../../common/typed_json'; +import { JsonValue } from '../../../../../src/plugins/kibana_utils/common'; /** * Interface for common configuration properties, regardless of the column type. diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts index 93a7bc9a0830b2..705d7bf34c1c66 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts @@ -19,7 +19,7 @@ import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../pl import { SpacesPluginSetup } from '../../../../../../plugins/spaces/server'; import { PluginSetupContract as AlertingPluginContract } from '../../../../../alerts/server'; import { MlPluginSetup } from '../../../../../ml/server'; -import { JsonArray, JsonValue } from '../../../../common/typed_json'; +import { JsonArray, JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; export interface InfraServerPluginSetupDeps { data: DataPluginSetup; diff --git a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts index 4637f3ab41782a..98c42ab7d98ab6 100644 --- a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts @@ -11,7 +11,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import * as runtimeTypes from 'io-ts'; import { compact } from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; -import { JsonArray } from '../../../../common/typed_json'; +import { JsonArray } from '../../../../../../../src/plugins/kibana_utils/common'; import { LogEntriesAdapter, LogEntriesParams, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts index 52cf6f46716b35..d9f125908b32db 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -5,7 +5,7 @@ */ import { RequestHandlerContext } from 'src/core/server'; -import { JsonObject } from '../../../../common/typed_json'; +import { JsonObject } from '../../../../../../../src/plugins/kibana_utils/common'; import { LogEntriesSummaryBucket, LogEntriesSummaryHighlightsBucket, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts index f9775e127088a9..19ab82c9c5ac11 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts @@ -5,7 +5,7 @@ */ import { LogMessagePart } from '../../../../common/http_api/log_entries'; -import { JsonArray, JsonValue } from '../../../../common/typed_json'; +import { JsonArray, JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; import { LogMessageFormattingCondition, LogMessageFormattingFieldValueConditionValue, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts index 4569f4b8e8a916..e2368d7475d480 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { JsonValue } from '../../../../common/typed_json'; +import { JsonValue } from '../../../../../../../src/plugins/kibana_utils/common'; export interface LogMessageFormattingRule { when: LogMessageFormattingCondition; diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts index 2421469eb1bddb..578ebaffc8369b 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { JsonObject } from '../../../../common/typed_json'; +import { JsonObject } from '../../../../../../../src/plugins/kibana_utils/common'; import { InventoryItemType, MetricsUIAggregation, diff --git a/x-pack/plugins/infra/server/utils/serialized_query.ts b/x-pack/plugins/infra/server/utils/serialized_query.ts index 932df847e65d08..8dfe00fcd380ef 100644 --- a/x-pack/plugins/infra/server/utils/serialized_query.ts +++ b/x-pack/plugins/infra/server/utils/serialized_query.ts @@ -6,7 +6,7 @@ import { UserInputError } from 'apollo-server-errors'; -import { JsonObject } from '../../common/typed_json'; +import { JsonObject } from '../../../../../src/plugins/kibana_utils/common'; export const parseFilterQuery = ( filterQuery: string | null | undefined diff --git a/x-pack/plugins/infra/server/utils/typed_search_strategy.ts b/x-pack/plugins/infra/server/utils/typed_search_strategy.ts index 1234aea507f3fb..b7132fa5dc3aa8 100644 --- a/x-pack/plugins/infra/server/utils/typed_search_strategy.ts +++ b/x-pack/plugins/infra/server/utils/typed_search_strategy.ts @@ -6,7 +6,8 @@ import * as rt from 'io-ts'; import stringify from 'json-stable-stringify'; -import { JsonValue, jsonValueRT } from '../../common/typed_json'; +import { JsonValue } from '../../../../../src/plugins/kibana_utils/common'; +import { jsonValueRT } from '../../common/typed_json'; import { SearchStrategyError } from '../../common/search_strategies/common/errors'; import { ShardFailure } from './elasticsearch_runtime_types'; diff --git a/x-pack/plugins/infra/types/eui.d.ts b/x-pack/plugins/infra/types/eui.d.ts index 802e11dd8fc84d..e3009820d1624b 100644 --- a/x-pack/plugins/infra/types/eui.d.ts +++ b/x-pack/plugins/infra/types/eui.d.ts @@ -11,9 +11,6 @@ import { IconType, ToolTipPositions } from '@elastic/eui'; import { CommonProps } from '@elastic/eui/src/components/common'; -import moment from 'moment'; -import { MouseEventHandler, ReactType, Ref } from 'react'; -import { JsonObject } from '../common/typed_json'; declare module '@elastic/eui' { interface EuiFormControlLayoutIconProps { diff --git a/x-pack/plugins/security_solution/server/endpoint/types.ts b/x-pack/plugins/security_solution/server/endpoint/types.ts index 2328c86f78a353..0e4f03c56b9f0b 100644 --- a/x-pack/plugins/security_solution/server/endpoint/types.ts +++ b/x-pack/plugins/security_solution/server/endpoint/types.ts @@ -7,7 +7,7 @@ import { LoggerFactory } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; import { ConfigType } from '../config'; import { EndpointAppContextService } from './endpoint_app_context_services'; -import { JsonObject } from '../../../infra/common/typed_json'; +import { JsonObject } from '../../../../../src/plugins/kibana_utils/common'; import { HostMetadata, HostMetadataDetails, From 9b22789c3ce570a90f84c34d786c66f24b080b89 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Fri, 15 Jan 2021 14:47:35 +0000 Subject: [PATCH 06/33] [Discover] Use fields API to retrieve fields (#83891) * Add search source to example plugin. * Add uiSetting for fields API. * Update SearchSource to support fields API. * [PoC] reading from the fields API in Discover * Add N fields as a default column * Make fields column non-removeable * Do not add 'fields' to state * Remove fields from app state and read from source when needed * Remove fields column if a new column is added * Add search source to example plugin. * Add uiSetting for fields API. * Update SearchSource to support fields API. * Improve error handling in search examples plugin. * Add unit tests for legacy behavior. * Remove uiSettings feature flag; add fieldsFromSource config. * Rewrite flatten() based on final API design. * Update example app based on final API design. * Update maps app to use legacy fieldsFromSource. * Update Discover to use legacy fieldsFromSource. * Rename source filters to field filters. * Address feedback. * Update generated docs. * Update maps functional test. * Formatting fields column similar to _source * Moving logic for using search API to updating search source * Fix small merge error * Move useSource switch to Discover section of advanced settings * Do not use fields and source at the same time * Remove unmapped fields switch * Add basic support for grouping multifields * Remove output.txt * Fix some merge leftovers * Fix some merge leftovers * Fix merge errors * Fix typescript errors and update nested fields logic * Add a unit test * Fixing field formats * Fix multifield selection logic * Request all fields from source * Fix eslint * Fix default columns when switching between _source and fields * More unit tests * Update API changes * Add unit test for discover field details footer * Remove unused file * Remove fields formatting from index pattern * Remove unnecessary check * Addressing design comments * Fixing fields column display and renaming it to Document * Adding more unit tests * Adding a missing check for useNewFieldsAPI; minor fixes * Fixing typescript error * Remove unnecessary console statement * Add missing prop * Fixing import order * Adding functional test to test fields API * [Functional test] Clean up in after * Fixing context app * Addressing PR comments * Updating failed snapshot * Addressing PR comments * Fixing i18n translations, updating type * Addressing PR comments * Updating a functional test * Add a separate functional test for fields API * Read fields from source in a functional test * Skip buggy test * Use default behavior in functional tests * Fixing remaining failing tests * Fixing date-nanos test * Updating FLS test * Fixing yet another functional test * Skipping non-relevant tests * Fixing more tests * Update stub import in test * Fix import * Fix invalid import Co-authored-by: Luke Elmers Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/discover/common/index.ts | 1 + .../stubbed_saved_object_index_pattern.ts | 2 +- .../application/angular/context/api/_stubs.js | 1 + .../application/angular/context/api/anchor.js | 7 +- .../angular/context/api/anchor.test.js | 25 + .../context/api/context.predecessors.test.js | 77 ++ .../context/api/context.successors.test.js | 77 ++ .../angular/context/api/context.ts | 15 +- .../api/utils/get_es_query_search_after.ts | 20 +- .../angular/context/query/actions.js | 12 +- .../application/angular/context_app.html | 1 + .../public/application/angular/context_app.js | 13 +- .../public/application/angular/discover.js | 46 +- .../application/angular/discover_legacy.html | 1 + .../angular/doc_table/actions/columns.ts | 16 +- .../components/table_header/helpers.tsx | 39 +- .../angular/doc_table/components/table_row.ts | 30 +- .../doc_table/components/table_row/_cell.scss | 6 +- .../components/table_row/details.html | 2 +- .../doc_table/create_doc_table_react.tsx | 2 + .../angular/doc_table/doc_table.html | 2 + .../angular/doc_table/doc_table.ts | 1 + .../application/angular/helpers/index.ts | 1 + .../angular/helpers/row_formatter.test.ts | 69 ++ .../angular/helpers/row_formatter.ts | 47 ++ .../context_app/context_app_legacy.tsx | 12 +- .../context_app_legacy_directive.ts | 1 + .../create_discover_legacy_directive.ts | 1 + .../components/discover_legacy.tsx | 17 +- ...iscover_field_details_footer.test.tsx.snap | 704 ++++++++++++++++++ .../components/sidebar/discover_field.scss | 10 +- .../sidebar/discover_field.test.tsx | 2 +- .../components/sidebar/discover_field.tsx | 217 ++++-- .../sidebar/discover_field_details.test.tsx | 2 +- .../sidebar/discover_field_details.tsx | 33 +- .../discover_field_details_footer.test.tsx | 82 ++ .../sidebar/discover_field_details_footer.tsx | 70 ++ .../components/sidebar/discover_sidebar.tsx | 41 +- .../sidebar/discover_sidebar_responsive.tsx | 4 + .../sidebar/lib/group_fields.test.ts | 83 ++- .../components/sidebar/lib/group_fields.tsx | 12 +- .../application/components/sidebar/types.ts | 2 +- .../get_switch_index_pattern_app_state.ts | 7 +- .../helpers/persist_saved_search.ts | 2 + .../helpers/update_search_source.test.ts | 29 + .../helpers/update_search_source.ts | 12 + src/plugins/discover/server/ui_settings.ts | 8 + .../context/_date_nanos_custom_timestamp.js | 1 + .../discover/_data_grid_doc_navigation.ts | 3 +- .../apps/discover/_data_grid_field_data.ts | 2 +- .../apps/discover/_discover_fields_api.ts | 71 ++ .../apps/discover/_doc_navigation.ts | 3 +- test/functional/apps/discover/_field_data.ts | 1 + .../discover/_field_data_with_fields_api.ts | 105 +++ .../functional/apps/discover/_large_string.ts | 3 +- .../functional/apps/discover/_shared_links.ts | 2 +- .../apps/discover/_source_filters.ts | 4 + .../apps/discover/ftr_provider_context.d.ts | 23 + test/functional/apps/discover/index.ts | 2 + .../es_archiver/date_nanos/mappings.json | 3 +- .../date_nanos_mixed/mappings.json | 3 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../apps/security/doc_level_security_roles.js | 2 +- .../apps/security/field_level_security.js | 4 +- .../security/flstest/data/mappings.json | 6 +- 66 files changed, 1920 insertions(+), 186 deletions(-) rename src/{fixtures => plugins/discover/public/__mocks__}/stubbed_saved_object_index_pattern.ts (94%) create mode 100644 src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts create mode 100644 src/plugins/discover/public/application/angular/helpers/row_formatter.ts create mode 100644 src/plugins/discover/public/application/components/sidebar/__snapshots__/discover_field_details_footer.test.tsx.snap create mode 100644 src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.test.tsx create mode 100644 src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.tsx create mode 100644 test/functional/apps/discover/_discover_fields_api.ts create mode 100644 test/functional/apps/discover/_field_data_with_fields_api.ts create mode 100644 test/functional/apps/discover/ftr_provider_context.d.ts diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts index 321a102e8d7827..b721c9157fe168 100644 --- a/src/plugins/discover/common/index.ts +++ b/src/plugins/discover/common/index.ts @@ -29,3 +29,4 @@ export const CONTEXT_STEP_SETTING = 'context:step'; export const CONTEXT_TIE_BREAKER_FIELDS_SETTING = 'context:tieBreakerFields'; export const DOC_TABLE_LEGACY = 'doc_table:legacy'; export const MODIFY_COLUMNS_ON_SWITCH = 'discover:modifyColumnsOnSwitch'; +export const SEARCH_FIELDS_FROM_SOURCE = 'discover:searchFieldsFromSource'; diff --git a/src/fixtures/stubbed_saved_object_index_pattern.ts b/src/plugins/discover/public/__mocks__/stubbed_saved_object_index_pattern.ts similarity index 94% rename from src/fixtures/stubbed_saved_object_index_pattern.ts rename to src/plugins/discover/public/__mocks__/stubbed_saved_object_index_pattern.ts index 261e451db5452e..a85734edba2742 100644 --- a/src/fixtures/stubbed_saved_object_index_pattern.ts +++ b/src/plugins/discover/public/__mocks__/stubbed_saved_object_index_pattern.ts @@ -18,7 +18,7 @@ */ // @ts-expect-error -import stubbedLogstashFields from './logstash_fields'; +import stubbedLogstashFields from '../../../../fixtures/logstash_fields'; const mockLogstashFields = stubbedLogstashFields(); diff --git a/src/plugins/discover/public/application/angular/context/api/_stubs.js b/src/plugins/discover/public/application/angular/context/api/_stubs.js index d82189db609356..17d45756af1483 100644 --- a/src/plugins/discover/public/application/angular/context/api/_stubs.js +++ b/src/plugins/discover/public/application/angular/context/api/_stubs.js @@ -47,6 +47,7 @@ export function createSearchSourceStub(hits, timeField) { searchSourceStub.setParent = sinon.spy(() => searchSourceStub); searchSourceStub.setField = sinon.spy(() => searchSourceStub); + searchSourceStub.removeField = sinon.spy(() => searchSourceStub); searchSourceStub.getField = sinon.spy((key) => { const previousSetCall = searchSourceStub.setField.withArgs(key).lastCall; diff --git a/src/plugins/discover/public/application/angular/context/api/anchor.js b/src/plugins/discover/public/application/angular/context/api/anchor.js index 4df5ba989f7985..31c106b95cbe58 100644 --- a/src/plugins/discover/public/application/angular/context/api/anchor.js +++ b/src/plugins/discover/public/application/angular/context/api/anchor.js @@ -20,7 +20,7 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -export function fetchAnchorProvider(indexPatterns, searchSource) { +export function fetchAnchorProvider(indexPatterns, searchSource, useNewFieldsApi = false) { return async function fetchAnchor(indexPatternId, anchorId, sort) { const indexPattern = await indexPatterns.get(indexPatternId); searchSource @@ -41,7 +41,10 @@ export function fetchAnchorProvider(indexPatterns, searchSource) { language: 'lucene', }) .setField('sort', sort); - + if (useNewFieldsApi) { + searchSource.removeField('fieldsFromSource'); + searchSource.setField('fields', ['*']); + } const response = await searchSource.fetch(); if (_.get(response, ['hits', 'total'], 0) < 1) { diff --git a/src/plugins/discover/public/application/angular/context/api/anchor.test.js b/src/plugins/discover/public/application/angular/context/api/anchor.test.js index 993aefc4f59e34..d54b38c466a5c5 100644 --- a/src/plugins/discover/public/application/angular/context/api/anchor.test.js +++ b/src/plugins/discover/public/application/angular/context/api/anchor.test.js @@ -144,4 +144,29 @@ describe('context app', function () { }); }); }); + + describe('useNewFields API', () => { + let fetchAnchor; + let searchSourceStub; + + beforeEach(() => { + searchSourceStub = createSearchSourceStub([{ _id: 'hit1' }]); + fetchAnchor = fetchAnchorProvider(createIndexPatternsStub(), searchSourceStub, true); + }); + + it('should request fields if useNewFieldsApi set', function () { + searchSourceStub._stubHits = [{ property1: 'value1' }, { property2: 'value2' }]; + + return fetchAnchor('INDEX_PATTERN_ID', 'id', [ + { '@timestamp': 'desc' }, + { _doc: 'desc' }, + ]).then(() => { + const setFieldsSpy = searchSourceStub.setField.withArgs('fields'); + const removeFieldsSpy = searchSourceStub.removeField.withArgs('fieldsFromSource'); + expect(setFieldsSpy.calledOnce).toBe(true); + expect(removeFieldsSpy.calledOnce).toBe(true); + expect(setFieldsSpy.firstCall.args[1]).toEqual(['*']); + }); + }); + }); }); diff --git a/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js b/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js index 4c0515906a4947..ea181782470faa 100644 --- a/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js +++ b/src/plugins/discover/public/application/angular/context/api/context.predecessors.test.js @@ -227,4 +227,81 @@ describe('context app', function () { }); }); }); + + describe('function fetchPredecessors with useNewFieldsApi set', function () { + let fetchPredecessors; + let mockSearchSource; + + beforeEach(() => { + mockSearchSource = createContextSearchSourceStub([], '@timestamp', MS_PER_DAY * 8); + + setServices({ + data: { + search: { + searchSource: { + create: jest.fn().mockImplementation(() => mockSearchSource), + }, + }, + }, + }); + + fetchPredecessors = ( + indexPatternId, + timeField, + sortDir, + timeValIso, + timeValNr, + tieBreakerField, + tieBreakerValue, + size + ) => { + const anchor = { + _source: { + [timeField]: timeValIso, + }, + sort: [timeValNr, tieBreakerValue], + }; + + return fetchContextProvider(createIndexPatternsStub(), true).fetchSurroundingDocs( + 'predecessors', + indexPatternId, + anchor, + timeField, + tieBreakerField, + sortDir, + size, + [] + ); + }; + }); + + it('should perform exactly one query when enough hits are returned', function () { + mockSearchSource._stubHits = [ + mockSearchSource._createStubHit(MS_PER_DAY * 3000 + 2), + mockSearchSource._createStubHit(MS_PER_DAY * 3000 + 1), + mockSearchSource._createStubHit(MS_PER_DAY * 3000), + mockSearchSource._createStubHit(MS_PER_DAY * 2000), + mockSearchSource._createStubHit(MS_PER_DAY * 1000), + ]; + + return fetchPredecessors( + 'INDEX_PATTERN_ID', + '@timestamp', + 'desc', + ANCHOR_TIMESTAMP_3000, + MS_PER_DAY * 3000, + '_doc', + 0, + 3, + [] + ).then((hits) => { + const setFieldsSpy = mockSearchSource.setField.withArgs('fields'); + const removeFieldsSpy = mockSearchSource.removeField.withArgs('fieldsFromSource'); + expect(mockSearchSource.fetch.calledOnce).toBe(true); + expect(removeFieldsSpy.calledOnce).toBe(true); + expect(setFieldsSpy.calledOnce).toBe(true); + expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3)); + }); + }); + }); }); diff --git a/src/plugins/discover/public/application/angular/context/api/context.successors.test.js b/src/plugins/discover/public/application/angular/context/api/context.successors.test.js index 285d39cd4d8a44..2c54de946c8d42 100644 --- a/src/plugins/discover/public/application/angular/context/api/context.successors.test.js +++ b/src/plugins/discover/public/application/angular/context/api/context.successors.test.js @@ -231,4 +231,81 @@ describe('context app', function () { }); }); }); + + describe('function fetchSuccessors with useNewFieldsApi set', function () { + let fetchSuccessors; + let mockSearchSource; + + beforeEach(() => { + mockSearchSource = createContextSearchSourceStub([], '@timestamp'); + + setServices({ + data: { + search: { + searchSource: { + create: jest.fn().mockImplementation(() => mockSearchSource), + }, + }, + }, + }); + + fetchSuccessors = ( + indexPatternId, + timeField, + sortDir, + timeValIso, + timeValNr, + tieBreakerField, + tieBreakerValue, + size + ) => { + const anchor = { + _source: { + [timeField]: timeValIso, + }, + sort: [timeValNr, tieBreakerValue], + }; + + return fetchContextProvider(createIndexPatternsStub(), true).fetchSurroundingDocs( + 'successors', + indexPatternId, + anchor, + timeField, + tieBreakerField, + sortDir, + size, + [] + ); + }; + }); + + it('should perform exactly one query when enough hits are returned', function () { + mockSearchSource._stubHits = [ + mockSearchSource._createStubHit(MS_PER_DAY * 5000), + mockSearchSource._createStubHit(MS_PER_DAY * 4000), + mockSearchSource._createStubHit(MS_PER_DAY * 3000), + mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 1), + mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 2), + ]; + + return fetchSuccessors( + 'INDEX_PATTERN_ID', + '@timestamp', + 'desc', + ANCHOR_TIMESTAMP_3000, + MS_PER_DAY * 3000, + '_doc', + 0, + 3, + [] + ).then((hits) => { + expect(mockSearchSource.fetch.calledOnce).toBe(true); + expect(hits).toEqual(mockSearchSource._stubHits.slice(-3)); + const setFieldsSpy = mockSearchSource.setField.withArgs('fields'); + const removeFieldsSpy = mockSearchSource.removeField.withArgs('fieldsFromSource'); + expect(removeFieldsSpy.calledOnce).toBe(true); + expect(setFieldsSpy.calledOnce).toBe(true); + }); + }); + }); }); diff --git a/src/plugins/discover/public/application/angular/context/api/context.ts b/src/plugins/discover/public/application/angular/context/api/context.ts index ba8cffd1d7558f..903e4e0f1b4853 100644 --- a/src/plugins/discover/public/application/angular/context/api/context.ts +++ b/src/plugins/discover/public/application/angular/context/api/context.ts @@ -40,7 +40,7 @@ const DAY_MILLIS = 24 * 60 * 60 * 1000; // look from 1 day up to 10000 days into the past and future const LOOKUP_OFFSETS = [0, 1, 7, 30, 365, 10000].map((days) => days * DAY_MILLIS); -function fetchContextProvider(indexPatterns: IndexPatternsContract) { +function fetchContextProvider(indexPatterns: IndexPatternsContract, useNewFieldsApi?: boolean) { return { fetchSurroundingDocs, }; @@ -89,7 +89,14 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract) { break; } - const searchAfter = getEsQuerySearchAfter(type, documents, timeField, anchor, nanos); + const searchAfter = getEsQuerySearchAfter( + type, + documents, + timeField, + anchor, + nanos, + useNewFieldsApi + ); const sort = getEsQuerySort(timeField, tieBreakerField, sortDirToApply); @@ -116,6 +123,10 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract) { const { data } = getServices(); const searchSource = await data.search.searchSource.create(); + if (useNewFieldsApi) { + searchSource.removeField('fieldsFromSource'); + searchSource.setField('fields', ['*']); + } return searchSource .setParent(undefined) .setField('index', indexPattern) diff --git a/src/plugins/discover/public/application/angular/context/api/utils/get_es_query_search_after.ts b/src/plugins/discover/public/application/angular/context/api/utils/get_es_query_search_after.ts index 24ac19a7e3bc3f..348a0c04a84adc 100644 --- a/src/plugins/discover/public/application/angular/context/api/utils/get_es_query_search_after.ts +++ b/src/plugins/discover/public/application/angular/context/api/utils/get_es_query_search_after.ts @@ -31,16 +31,30 @@ export function getEsQuerySearchAfter( documents: EsHitRecordList, timeFieldName: string, anchor: EsHitRecord, - nanoSeconds: string + nanoSeconds: string, + useNewFieldsApi?: boolean ): EsQuerySearchAfter { if (documents.length) { // already surrounding docs -> first or last record is used const afterTimeRecIdx = type === 'successors' && documents.length ? documents.length - 1 : 0; const afterTimeDoc = documents[afterTimeRecIdx]; - const afterTimeValue = nanoSeconds ? afterTimeDoc._source[timeFieldName] : afterTimeDoc.sort[0]; + let afterTimeValue = afterTimeDoc.sort[0]; + if (nanoSeconds) { + afterTimeValue = useNewFieldsApi + ? afterTimeDoc.fields[timeFieldName][0] + : afterTimeDoc._source[timeFieldName]; + } return [afterTimeValue, afterTimeDoc.sort[1]]; } // if data_nanos adapt timestamp value for sorting, since numeric value was rounded by browser // ES search_after also works when number is provided as string - return [nanoSeconds ? anchor._source[timeFieldName] : anchor.sort[0], anchor.sort[1]]; + const searchAfter = new Array(2) as EsQuerySearchAfter; + searchAfter[0] = anchor.sort[0]; + if (nanoSeconds) { + searchAfter[0] = useNewFieldsApi + ? anchor.fields[timeFieldName][0] + : anchor._source[timeFieldName]; + } + searchAfter[1] = anchor.sort[1]; + return searchAfter; } diff --git a/src/plugins/discover/public/application/angular/context/query/actions.js b/src/plugins/discover/public/application/angular/context/query/actions.js index d5c72d34006e2e..42638cd90a1bb6 100644 --- a/src/plugins/discover/public/application/angular/context/query/actions.js +++ b/src/plugins/discover/public/application/angular/context/query/actions.js @@ -27,11 +27,17 @@ import { fetchContextProvider } from '../api/context'; import { getQueryParameterActions } from '../query_parameters'; import { FAILURE_REASONS, LOADING_STATUS } from './index'; import { MarkdownSimple } from '../../../../../../kibana_react/public'; +import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../../common'; export function QueryActionsProvider(Promise) { - const { filterManager, indexPatterns, data } = getServices(); - const fetchAnchor = fetchAnchorProvider(indexPatterns, data.search.searchSource.createEmpty()); - const { fetchSurroundingDocs } = fetchContextProvider(indexPatterns); + const { filterManager, indexPatterns, data, uiSettings } = getServices(); + const useNewFieldsApi = !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE); + const fetchAnchor = fetchAnchorProvider( + indexPatterns, + data.search.searchSource.createEmpty(), + useNewFieldsApi + ); + const { fetchSurroundingDocs } = fetchContextProvider(indexPatterns, useNewFieldsApi); const { setPredecessorCount, setQueryParameters, setSuccessorCount } = getQueryParameterActions( filterManager, indexPatterns diff --git a/src/plugins/discover/public/application/angular/context_app.html b/src/plugins/discover/public/application/angular/context_app.html index 8dc3e5c87e5045..3d731459ad8d72 100644 --- a/src/plugins/discover/public/application/angular/context_app.html +++ b/src/plugins/discover/public/application/angular/context_app.html @@ -17,5 +17,6 @@ successor-available="contextApp.state.rows.successors.length" successor-status="contextApp.state.loadingStatus.successors.status" on-change-successor-count="contextApp.actions.fetchGivenSuccessorRows" + use-new-fields-api="contextApp.state.useNewFieldsApi" top-nav-menu="contextApp.topNavMenu" > diff --git a/src/plugins/discover/public/application/angular/context_app.js b/src/plugins/discover/public/application/angular/context_app.js index d9e2452eb8bd6d..f18389df6d12de 100644 --- a/src/plugins/discover/public/application/angular/context_app.js +++ b/src/plugins/discover/public/application/angular/context_app.js @@ -18,7 +18,11 @@ */ import _ from 'lodash'; -import { CONTEXT_STEP_SETTING, CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '../../../common'; +import { + CONTEXT_STEP_SETTING, + CONTEXT_TIE_BREAKER_FIELDS_SETTING, + SEARCH_FIELDS_FROM_SOURCE, +} from '../../../common'; import { getAngularModule, getServices } from '../../kibana_services'; import contextAppTemplate from './context_app.html'; import './context/components/action_bar'; @@ -59,9 +63,11 @@ function ContextAppController($scope, Private) { const { filterManager, indexPatterns, uiSettings, navigation } = getServices(); const queryParameterActions = getQueryParameterActions(filterManager, indexPatterns); const queryActions = Private(QueryActionsProvider); + const useNewFieldsApi = !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE); this.state = createInitialState( parseInt(uiSettings.get(CONTEXT_STEP_SETTING), 10), - getFirstSortableField(this.indexPattern, uiSettings.get(CONTEXT_TIE_BREAKER_FIELDS_SETTING)) + getFirstSortableField(this.indexPattern, uiSettings.get(CONTEXT_TIE_BREAKER_FIELDS_SETTING)), + useNewFieldsApi ); this.topNavMenu = navigation.ui.TopNavMenu; @@ -127,7 +133,7 @@ function ContextAppController($scope, Private) { ); } -function createInitialState(defaultStepSize, tieBreakerField) { +function createInitialState(defaultStepSize, tieBreakerField, useNewFieldsApi) { return { queryParameters: createInitialQueryParametersState(defaultStepSize, tieBreakerField), rows: { @@ -137,5 +143,6 @@ function createInitialState(defaultStepSize, tieBreakerField) { successors: [], }, loadingStatus: createInitialLoadingStatusState(), + useNewFieldsApi, }; } diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index de3b7c6c1a326d..6b552d92df0f0e 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -64,6 +64,7 @@ import { DEFAULT_COLUMNS_SETTING, MODIFY_COLUMNS_ON_SWITCH, SAMPLE_SIZE_SETTING, + SEARCH_FIELDS_FROM_SOURCE, SEARCH_ON_PAGE_LOAD_SETTING, SORT_DEFAULT_ORDER_SETTING, } from '../../../common'; @@ -197,6 +198,8 @@ function discoverController($element, $route, $scope, $timeout, Promise) { $scope.searchSource, toastNotifications ); + $scope.useNewFieldsApi = !config.get(SEARCH_FIELDS_FROM_SOURCE); + //used for functional testing $scope.fetchCounter = 0; @@ -308,7 +311,8 @@ function discoverController($element, $route, $scope, $timeout, Promise) { nextIndexPattern, $scope.state.columns, $scope.state.sort, - config.get(MODIFY_COLUMNS_ON_SWITCH) + config.get(MODIFY_COLUMNS_ON_SWITCH), + $scope.useNewFieldsApi ); await setAppState(nextAppState); } @@ -415,19 +419,33 @@ function discoverController($element, $route, $scope, $timeout, Promise) { setBreadcrumbsTitle(savedSearch, chrome); + function removeSourceFromColumns(columns) { + return columns.filter((col) => col !== '_source'); + } + + function getDefaultColumns() { + const columns = [...savedSearch.columns]; + + if ($scope.useNewFieldsApi) { + return removeSourceFromColumns(columns); + } + if (columns.length > 0) { + return columns; + } + return [...config.get(DEFAULT_COLUMNS_SETTING)]; + } + function getStateDefaults() { const query = $scope.searchSource.getField('query') || data.query.queryString.getDefaultQuery(); const sort = getSortArray(savedSearch.sort, $scope.indexPattern); + const columns = getDefaultColumns(); const defaultState = { query, sort: !sort.length ? getDefaultSort($scope.indexPattern, config.get(SORT_DEFAULT_ORDER_SETTING, 'desc')) : sort, - columns: - savedSearch.columns.length > 0 - ? savedSearch.columns - : config.get(DEFAULT_COLUMNS_SETTING).slice(), + columns, index: $scope.indexPattern.id, interval: 'auto', filters: _.cloneDeep($scope.searchSource.getOwnField('filter')), @@ -739,10 +757,14 @@ function discoverController($element, $route, $scope, $timeout, Promise) { }; $scope.updateDataSource = () => { - updateSearchSource($scope.searchSource, { - indexPattern: $scope.indexPattern, + const { indexPattern, searchSource, useNewFieldsApi } = $scope; + const { columns, sort } = $scope.state; + updateSearchSource(searchSource, { + indexPattern, services, - sort: $scope.state.sort, + sort, + columns, + useNewFieldsApi, }); return Promise.resolve(); }; @@ -770,20 +792,20 @@ function discoverController($element, $route, $scope, $timeout, Promise) { }; $scope.addColumn = function addColumn(columnName) { + const { indexPattern, useNewFieldsApi } = $scope; if (capabilities.discover.save) { - const { indexPattern } = $scope; popularizeField(indexPattern, columnName, indexPatterns); } - const columns = columnActions.addColumn($scope.state.columns, columnName); + const columns = columnActions.addColumn($scope.state.columns, columnName, useNewFieldsApi); setAppState({ columns }); }; $scope.removeColumn = function removeColumn(columnName) { + const { indexPattern, useNewFieldsApi } = $scope; if (capabilities.discover.save) { - const { indexPattern } = $scope; popularizeField(indexPattern, columnName, indexPatterns); } - const columns = columnActions.removeColumn($scope.state.columns, columnName); + const columns = columnActions.removeColumn($scope.state.columns, columnName, useNewFieldsApi); // The state's sort property is an array of [sortByColumn,sortDirection] const sort = $scope.state.sort.length ? $scope.state.sort.filter((subArr) => subArr[0] !== columnName) diff --git a/src/plugins/discover/public/application/angular/discover_legacy.html b/src/plugins/discover/public/application/angular/discover_legacy.html index 3596c0a2519ed0..9383980fd9fd6f 100644 --- a/src/plugins/discover/public/application/angular/discover_legacy.html +++ b/src/plugins/discover/public/application/angular/discover_legacy.html @@ -29,6 +29,7 @@ top-nav-menu="topNavMenu" update-query="handleRefresh" update-saved-query-id="updateSavedQueryId" + use-new-fields-api="useNewFieldsApi" > diff --git a/src/plugins/discover/public/application/angular/doc_table/actions/columns.ts b/src/plugins/discover/public/application/angular/doc_table/actions/columns.ts index 8257c79af7e8af..1b6d8fcbc25441 100644 --- a/src/plugins/discover/public/application/angular/doc_table/actions/columns.ts +++ b/src/plugins/discover/public/application/angular/doc_table/actions/columns.ts @@ -21,28 +21,32 @@ * Helper function to provide a fallback to a single _source column if the given array of columns * is empty, and removes _source if there are more than 1 columns given * @param columns + * @param useNewFieldsApi should a new fields API be used */ -function buildColumns(columns: string[]) { +function buildColumns(columns: string[], useNewFieldsApi = false) { if (columns.length > 1 && columns.indexOf('_source') !== -1) { return columns.filter((col) => col !== '_source'); } else if (columns.length !== 0) { return columns; } - return ['_source']; + return useNewFieldsApi ? [] : ['_source']; } -export function addColumn(columns: string[], columnName: string) { +export function addColumn(columns: string[], columnName: string, useNewFieldsApi?: boolean) { if (columns.includes(columnName)) { return columns; } - return buildColumns([...columns, columnName]); + return buildColumns([...columns, columnName], useNewFieldsApi); } -export function removeColumn(columns: string[], columnName: string) { +export function removeColumn(columns: string[], columnName: string, useNewFieldsApi?: boolean) { if (!columns.includes(columnName)) { return columns; } - return buildColumns(columns.filter((col) => col !== columnName)); + return buildColumns( + columns.filter((col) => col !== columnName), + useNewFieldsApi + ); } export function moveColumn(columns: string[], columnName: string, newIndex: number) { diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_header/helpers.tsx b/src/plugins/discover/public/application/angular/doc_table/components/table_header/helpers.tsx index b456fa0773b855..bb855373c910f3 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_header/helpers.tsx +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_header/helpers.tsx @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { i18n } from '@kbn/i18n'; import { IndexPattern } from '../../../../../kibana_services'; export type SortOrder = [string, string]; @@ -62,17 +63,33 @@ export function getDisplayedColumns( if (!Array.isArray(columns) || typeof indexPattern !== 'object' || !indexPattern.getFieldByName) { return []; } - const columnProps = columns.map((column, idx) => { - const field = indexPattern.getFieldByName(column); - return { - name: column, - displayName: field ? field.displayName : column, - isSortable: field && field.sortable ? true : false, - isRemoveable: column !== '_source' || columns.length > 1, - colLeftIdx: idx - 1 < 0 ? -1 : idx - 1, - colRightIdx: idx + 1 >= columns.length ? -1 : idx + 1, - }; - }); + + const columnProps = + columns.length === 0 + ? [ + { + name: '__document__', + displayName: i18n.translate('discover.docTable.tableHeader.documentHeader', { + defaultMessage: 'Document', + }), + isSortable: false, + isRemoveable: false, + colLeftIdx: -1, + colRightIdx: -1, + }, + ] + : columns.map((column, idx) => { + const field = indexPattern.getFieldByName(column); + return { + name: column, + displayName: field?.displayName ?? column, + isSortable: !!(field && field.sortable), + isRemoveable: column !== '_source' || columns.length > 1, + colLeftIdx: idx - 1 < 0 ? -1 : idx - 1, + colRightIdx: idx + 1 >= columns.length ? -1 : idx + 1, + }; + }); + return !hideTimeField && indexPattern.timeFieldName ? [getTimeColumn(indexPattern.timeFieldName), ...columnProps] : columnProps; diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts b/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts index e45f18606e3fc4..75206d6bf2e846 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row.ts @@ -27,6 +27,7 @@ import cellTemplateHtml from '../components/table_row/cell.html'; import truncateByHeightTemplateHtml from '../components/table_row/truncate_by_height.html'; import { getServices } from '../../../../kibana_services'; import { getContextUrl } from '../../../helpers/get_context_url'; +import { formatRow } from '../../helpers'; const TAGS_WITH_WS = />\s+ { $el.after(''); @@ -139,19 +141,33 @@ export function createTableRowDirective($compile: ng.ICompileService) { ); } - $scope.columns.forEach(function (column: any) { - const isFilterable = mapping(column) && mapping(column).filterable && $scope.filter; + if ($scope.columns.length === 0 && $scope.useNewFieldsApi) { + const formatted = formatRow(row, indexPattern); newHtmls.push( cellTemplate({ timefield: false, - sourcefield: column === '_source', - formatted: _displayField(row, column, true), - filterable: isFilterable, - column, + sourcefield: true, + formatted, + filterable: false, + column: '__document__', }) ); - }); + } else { + $scope.columns.forEach(function (column: string) { + const isFilterable = mapping(column) && mapping(column).filterable && $scope.filter; + + newHtmls.push( + cellTemplate({ + timefield: false, + sourcefield: column === '_source', + formatted: _displayField(row, column, true), + filterable: isFilterable, + column, + }) + ); + }); + } let $cells = $el.children(); newHtmls.forEach(function (html, i) { diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row/_cell.scss b/src/plugins/discover/public/application/angular/doc_table/components/table_row/_cell.scss index b73a2598070b50..22b6e0f29268ba 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row/_cell.scss +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row/_cell.scss @@ -1,9 +1,5 @@ -.kbnDocTableCell__dataField { - white-space: pre-wrap; -} - .kbnDocTableCell__toggleDetails { - padding: 4px 0 0 0!important; + padding: $euiSizeXS 0 0 0!important; } .kbnDocTableCell__filter { diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row/details.html b/src/plugins/discover/public/application/angular/doc_table/components/table_row/details.html index fd20bea8fb3dfc..bb443b880e2171 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row/details.html +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row/details.html @@ -1,4 +1,4 @@ - +
diff --git a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx index f191fa2dc89e84..0a162673eec82c 100644 --- a/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx +++ b/src/plugins/discover/public/application/angular/doc_table/create_doc_table_react.tsx @@ -97,6 +97,7 @@ export interface DocTableLegacyProps { onMoveColumn?: (columns: string, newIdx: number) => void; onRemoveColumn?: (column: string) => void; sort?: string[][]; + useNewFieldsApi?: boolean; } export function DocTableLegacy(renderProps: DocTableLegacyProps) { @@ -118,6 +119,7 @@ export function DocTableLegacy(renderProps: DocTableLegacyProps) { on-move-column="onMoveColumn" on-remove-column="onRemoveColumn" render-complete + use-new-fields-api="useNewFieldsApi" sorting="sort">`, }, () => getServices().getEmbeddableInjector() diff --git a/src/plugins/discover/public/application/angular/doc_table/doc_table.html b/src/plugins/discover/public/application/angular/doc_table/doc_table.html index bb8cc4b9ee4c2f..427893bd3e6fe8 100644 --- a/src/plugins/discover/public/application/angular/doc_table/doc_table.html +++ b/src/plugins/discover/public/application/angular/doc_table/doc_table.html @@ -46,6 +46,7 @@ class="kbnDocTable__row" on-add-column="onAddColumn" on-remove-column="onRemoveColumn" + use-new-fields-api="useNewFieldsApi" > @@ -97,6 +98,7 @@ data-test-subj="docTableRow{{ row['$$_isAnchor'] ? ' docTableAnchorRow' : ''}}" on-add-column="onAddColumn" on-remove-column="onRemoveColumn" + use-new-fields-api="useNewFieldsApi" > diff --git a/src/plugins/discover/public/application/angular/doc_table/doc_table.ts b/src/plugins/discover/public/application/angular/doc_table/doc_table.ts index 735ee9f555740e..2baf010b47c785 100644 --- a/src/plugins/discover/public/application/angular/doc_table/doc_table.ts +++ b/src/plugins/discover/public/application/angular/doc_table/doc_table.ts @@ -48,6 +48,7 @@ export function createDocTableDirective(pagerFactory: any, $filter: any) { onMoveColumn: '=?', onRemoveColumn: '=?', inspectorAdapters: '=?', + useNewFieldsApi: '<', }, link: ($scope: LazyScope, $el: JQuery) => { $scope.persist = { diff --git a/src/plugins/discover/public/application/angular/helpers/index.ts b/src/plugins/discover/public/application/angular/helpers/index.ts index 9bfba4de966be4..cba50dfa58751a 100644 --- a/src/plugins/discover/public/application/angular/helpers/index.ts +++ b/src/plugins/discover/public/application/angular/helpers/index.ts @@ -18,3 +18,4 @@ */ export { buildPointSeriesData } from './point_series'; +export { formatRow } from './row_formatter'; diff --git a/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts b/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts new file mode 100644 index 00000000000000..60ee1e4c2b68b3 --- /dev/null +++ b/src/plugins/discover/public/application/angular/helpers/row_formatter.test.ts @@ -0,0 +1,69 @@ +/* + * 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 { formatRow } from './row_formatter'; +import { stubbedSavedObjectIndexPattern } from '../../../__mocks__/stubbed_saved_object_index_pattern'; +import { IndexPattern } from '../../../../../data/common/index_patterns/index_patterns'; +import { fieldFormatsMock } from '../../../../../data/common/field_formats/mocks'; + +describe('Row formatter', () => { + const hit = { + foo: 'bar', + number: 42, + hello: '

World

', + also: 'with "quotes" or \'single quotes\'', + }; + + const createIndexPattern = () => { + const id = 'my-index'; + const { + type, + version, + attributes: { timeFieldName, fields, title }, + } = stubbedSavedObjectIndexPattern(id); + + return new IndexPattern({ + spec: { id, type, version, timeFieldName, fields, title }, + fieldFormats: fieldFormatsMock, + shortDotsEnable: false, + metaFields: [], + }); + }; + + const indexPattern = createIndexPattern(); + + const formatHitReturnValue = { + also: 'with \\"quotes\\" or 'single qoutes'', + number: '42', + foo: 'bar', + hello: '<h1>World</h1>', + }; + const formatHitMock = jest.fn().mockReturnValueOnce(formatHitReturnValue); + + beforeEach(() => { + // @ts-ignore + indexPattern.formatHit = formatHitMock; + }); + + it('formats document properly', () => { + expect(formatRow(hit, indexPattern).trim()).toBe( + '
also:
with \\"quotes\\" or 'single qoutes'
number:
42
foo:
bar
hello:
<h1>World</h1>
' + ); + }); +}); diff --git a/src/plugins/discover/public/application/angular/helpers/row_formatter.ts b/src/plugins/discover/public/application/angular/helpers/row_formatter.ts new file mode 100644 index 00000000000000..4ad50ef7621c57 --- /dev/null +++ b/src/plugins/discover/public/application/angular/helpers/row_formatter.ts @@ -0,0 +1,47 @@ +/* + * 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 { template } from 'lodash'; +import { IndexPattern } from '../../../kibana_services'; + +function noWhiteSpace(html: string) { + const TAGS_WITH_WS = />\s+<'); +} + +const templateHtml = ` +
+ <% defPairs.forEach(function (def) { %> +
<%- def[0] %>:
+
<%= def[1] %>
+ <%= ' ' %> + <% }); %> +
`; +export const doTemplate = template(noWhiteSpace(templateHtml)); + +export const formatRow = (hit: Record, indexPattern: IndexPattern) => { + const highlights = hit?.highlight ?? {}; + const formatted = indexPattern.formatHit(hit); + const highlightPairs: Array<[string, unknown]> = []; + const sourcePairs: Array<[string, unknown]> = []; + Object.entries(formatted).forEach(([key, val]) => { + const pairs = highlights[key] ? highlightPairs : sourcePairs; + pairs.push([key, val]); + }); + return doTemplate({ defPairs: [...highlightPairs, ...sourcePairs] }); +}; diff --git a/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx b/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx index f519df8a0b80db..4ace823471c457 100644 --- a/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx +++ b/src/plugins/discover/public/application/components/context_app/context_app_legacy.tsx @@ -48,6 +48,7 @@ export interface ContextAppProps { onChangeSuccessorCount: (count: number) => void; predecessorStatus: string; successorStatus: string; + useNewFieldsApi?: boolean; } const PREDECESSOR_TYPE = 'predecessors'; @@ -87,7 +88,15 @@ export function ContextAppLegacy(renderProps: ContextAppProps) { }; const docTableProps = () => { - const { hits, filter, sorting, columns, indexPattern, minimumVisibleRows } = renderProps; + const { + hits, + filter, + sorting, + columns, + indexPattern, + minimumVisibleRows, + useNewFieldsApi, + } = renderProps; return { columns, indexPattern, @@ -95,6 +104,7 @@ export function ContextAppLegacy(renderProps: ContextAppProps) { rows: hits, onFilter: filter, sort: sorting.map((el) => [el]), + useNewFieldsApi, } as DocTableLegacyProps; }; diff --git a/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts b/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts index dfb5d90c2befe7..e52226bee3785e 100644 --- a/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts +++ b/src/plugins/discover/public/application/components/context_app/context_app_legacy_directive.ts @@ -37,6 +37,7 @@ export function createContextAppLegacy(reactDirective: any) { ['successorAvailable', { watchDepth: 'reference' }], ['successorStatus', { watchDepth: 'reference' }], ['onChangeSuccessorCount', { watchDepth: 'reference' }], + ['useNewFieldsApi', { watchDepth: 'reference' }], ['topNavMenu', { watchDepth: 'reference' }], ]); } diff --git a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts b/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts index 6e5d47be987d80..fc877cab00e0b5 100644 --- a/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts +++ b/src/plugins/discover/public/application/components/create_discover_legacy_directive.ts @@ -51,5 +51,6 @@ export function createDiscoverLegacyDirective(reactDirective: any) { ['topNavMenu', { watchDepth: 'reference' }], ['updateQuery', { watchDepth: 'reference' }], ['updateSavedQueryId', { watchDepth: 'reference' }], + ['useNewFieldsApi', { watchDepth: 'reference' }], ]); } diff --git a/src/plugins/discover/public/application/components/discover_legacy.tsx b/src/plugins/discover/public/application/components/discover_legacy.tsx index 436a145024437c..402e686979d67f 100644 --- a/src/plugins/discover/public/application/components/discover_legacy.tsx +++ b/src/plugins/discover/public/application/components/discover_legacy.tsx @@ -219,6 +219,7 @@ export interface DiscoverProps { * Function to update the actual savedQuery id */ updateSavedQueryId: (savedQueryId?: string) => void; + useNewFieldsApi?: boolean; } export const DocTableLegacyMemoized = React.memo((props: DocTableLegacyProps) => ( @@ -257,6 +258,7 @@ export function DiscoverLegacy({ topNavMenu, updateQuery, updateSavedQueryId, + useNewFieldsApi, }: DiscoverProps) { const scrollableDesktop = useRef(null); const collapseIcon = useRef(null); @@ -278,6 +280,17 @@ export function DiscoverLegacy({ : undefined; const contentCentered = resultState === 'uninitialized'; + const getDisplayColumns = () => { + if (!state.columns) { + return []; + } + const columns = [...state.columns]; + if (useNewFieldsApi) { + return columns.filter((column) => column !== '_source'); + } + return columns.length === 0 ? ['_source'] : columns; + }; + return ( @@ -315,6 +328,7 @@ export function DiscoverLegacy({ setIndexPattern={setIndexPattern} isClosed={isSidebarClosed} trackUiMetric={trackUiMetric} + useNewFieldsApi={useNewFieldsApi} /> @@ -445,7 +459,7 @@ export function DiscoverLegacy({ {rows && rows.length && (
{rows.length === opts.sampleSize ? (
+ +
+ +
+ +
+ + + +
+
+
+
+
+
+ +`; diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.scss b/src/plugins/discover/public/application/components/sidebar/discover_field.scss index 8e1dd41f66ab1d..40bc58cef70238 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.scss +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.scss @@ -1,4 +1,10 @@ .dscSidebarItem__fieldPopoverPanel { - min-width: 260px; - max-width: 300px; + min-width: $euiSizeXXL * 6.5; + max-width: $euiSizeXXL * 7.5; +} + +.dscSidebarItem--multi { + .kbnFieldButton__button { + padding-left: 0; + } } diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx index 0957ee101bd270..d22ef7cdcc28c8 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.test.tsx @@ -82,7 +82,7 @@ function getComponent({ const props = { indexPattern, field: finalField, - getDetails: jest.fn(() => ({ buckets: [], error: '', exists: 1, total: true, columns: [] })), + getDetails: jest.fn(() => ({ buckets: [], error: '', exists: 1, total: 2, columns: [] })), onAddFilter: jest.fn(), onAddField: jest.fn(), onRemoveField: jest.fn(), diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field.tsx index f95e512dfb66e5..b885bdab316b53 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field.tsx @@ -19,7 +19,7 @@ import './discover_field.scss'; import React, { useState } from 'react'; -import { EuiPopover, EuiPopoverTitle, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; +import { EuiPopover, EuiPopoverTitle, EuiButtonIcon, EuiToolTip, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { UiCounterMetricType } from '@kbn/analytics'; import classNames from 'classnames'; @@ -28,6 +28,7 @@ import { FieldIcon, FieldButton } from '../../../../../kibana_react/public'; import { FieldDetails } from './types'; import { IndexPatternField, IndexPattern } from '../../../../../data/public'; import { getFieldTypeName } from './lib/get_field_type_name'; +import { DiscoverFieldDetailsFooter } from './discover_field_details_footer'; export interface DiscoverFieldProps { /** @@ -69,6 +70,8 @@ export interface DiscoverFieldProps { * @param eventName */ trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; + + multiFields?: Array<{ field: IndexPatternField; isSelected: boolean }>; } export function DiscoverField({ @@ -81,6 +84,7 @@ export function DiscoverField({ getDetails, selected, trackUiMetric, + multiFields, }: DiscoverFieldProps) { const addLabelAria = i18n.translate('discover.fieldChooser.discoverField.addButtonAriaLabel', { defaultMessage: 'Add {field} to table', @@ -96,8 +100,8 @@ export function DiscoverField({ const [infoIsOpen, setOpen] = useState(false); - const toggleDisplay = (f: IndexPatternField) => { - if (selected) { + const toggleDisplay = (f: IndexPatternField, isSelected: boolean) => { + if (isSelected) { onRemoveField(f.name); } else { onAddField(f.name); @@ -115,72 +119,100 @@ export function DiscoverField({ return str ? str.replace(/\./g, '.\u200B') : ''; } - const dscFieldIcon = ( - - ); + const getDscFieldIcon = (indexPatternField: IndexPatternField) => { + return ( + + ); + }; - const title = - field.displayName !== field.name ? `${field.name} (${field.displayName} )` : field.displayName; + const dscFieldIcon = getDscFieldIcon(field); + + const getTitle = (indexPatternField: IndexPatternField) => { + return indexPatternField.displayName !== indexPatternField.name + ? i18n.translate('discover.field.title', { + defaultMessage: '{fieldName} ({fieldDisplayName})', + values: { + fieldName: indexPatternField.name, + fieldDisplayName: indexPatternField.displayName, + }, + }) + : indexPatternField.displayName; + }; + + const getFieldName = (indexPatternField: IndexPatternField) => { + return ( + + {wrapOnDot(indexPatternField.displayName)} + + ); + }; + const fieldName = getFieldName(field); - const fieldName = ( - - {wrapOnDot(field.displayName)} - - ); const actionBtnClassName = classNames('dscSidebarItem__action', { ['dscSidebarItem__mobile']: alwaysShowActionButton, }); - let actionButton; - if (field.name !== '_source' && !selected) { - actionButton = ( - - ) => { - if (ev.type === 'click') { - ev.currentTarget.focus(); - } - ev.preventDefault(); - ev.stopPropagation(); - toggleDisplay(field); - }} - data-test-subj={`fieldToggle-${field.name}`} - aria-label={addLabelAria} - /> - - ); - } else if (field.name !== '_source' && selected) { - actionButton = ( - - ) => { - if (ev.type === 'click') { - ev.currentTarget.focus(); - } - ev.preventDefault(); - ev.stopPropagation(); - toggleDisplay(field); - }} - data-test-subj={`fieldToggle-${field.name}`} - aria-label={removeLabelAria} - /> - - ); - } + const getActionButton = (f: IndexPatternField, isSelected?: boolean) => { + if (f.name !== '_source' && !isSelected) { + return ( + + ) => { + if (ev.type === 'click') { + ev.currentTarget.focus(); + } + ev.preventDefault(); + ev.stopPropagation(); + toggleDisplay(f, false); + }} + data-test-subj={`fieldToggle-${f.name}`} + aria-label={addLabelAria} + /> + + ); + } else if (f.name !== '_source' && isSelected) { + return ( + + ) => { + if (ev.type === 'click') { + ev.currentTarget.focus(); + } + ev.preventDefault(); + ev.stopPropagation(); + toggleDisplay(f, isSelected); + }} + data-test-subj={`fieldToggle-${f.name}`} + aria-label={removeLabelAria} + /> + + ); + } + }; + + const actionButton = getActionButton(field, selected); if (field.type === '_source') { return ( @@ -195,6 +227,37 @@ export function DiscoverField({ ); } + const shouldRenderMultiFields = !!multiFields; + const renderMultiFields = () => { + if (!multiFields) { + return null; + } + return ( + + +
+ {i18n.translate('discover.fieldChooser.discoverField.multiFields', { + defaultMessage: 'Multi fields', + })} +
+
+ {multiFields.map((entry) => ( + {}} + dataTestSubj={`field-${entry.field.name}-showDetails`} + fieldIcon={getDscFieldIcon(entry.field)} + fieldAction={getActionButton(entry.field, entry.isSelected)} + fieldName={getFieldName(entry.field)} + key={entry.field.name} + /> + ))} +
+ ); + }; + return ( - - {' '} - {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { - defaultMessage: 'Top 5 values', - })} - + {field.displayName} + +
+ {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { + defaultMessage: 'Top 5 values', + })} +
+
{infoIsOpen && ( )} + {shouldRenderMultiFields ? ( + <> + {renderMultiFields()} + + + ) : null}
); } diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field_details.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field_details.test.tsx index 0618e53d15dbb5..8444f11ac912cc 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field_details.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field_details.test.tsx @@ -38,7 +38,7 @@ const indexPattern = getStubIndexPattern( describe('discover sidebar field details', function () { const defaultProps = { indexPattern, - details: { buckets: [], error: '', exists: 1, total: true, columns: [] }, + details: { buckets: [], error: '', exists: 1, total: 2, columns: [] }, onAddFilter: jest.fn(), }; diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field_details.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field_details.tsx index 740de54ae0cf32..bf24337543037d 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_field_details.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_field_details.tsx @@ -17,7 +17,7 @@ * under the License. */ import React, { useState, useEffect } from 'react'; -import { EuiLink, EuiIconTip, EuiText, EuiPopoverFooter, EuiButton, EuiSpacer } from '@elastic/eui'; +import { EuiIconTip, EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics'; import { DiscoverFieldBucket } from './discover_field_bucket'; @@ -30,6 +30,7 @@ import { import { Bucket, FieldDetails } from './types'; import { IndexPatternField, IndexPattern } from '../../../../../data/public'; import './discover_field_details.scss'; +import { DiscoverFieldDetailsFooter } from './discover_field_details_footer'; interface DiscoverFieldDetailsProps { field: IndexPatternField; @@ -37,6 +38,7 @@ interface DiscoverFieldDetailsProps { details: FieldDetails; onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; + showFooter?: boolean; } export function DiscoverFieldDetails({ @@ -45,6 +47,7 @@ export function DiscoverFieldDetails({ details, onAddFilter, trackUiMetric, + showFooter = true, }: DiscoverFieldDetailsProps) { const warnings = getWarnings(field); const [showVisualizeLink, setShowVisualizeLink] = useState(false); @@ -118,27 +121,13 @@ export function DiscoverFieldDetails({ )}
- {!details.error && ( - - - {!indexPattern.metaFields.includes(field.name) && !field.scripted ? ( - onAddFilter('_exists_', field.name, '+')}> - {' '} - {details.exists} - - ) : ( - {details.exists} - )}{' '} - / {details.total}{' '} - - - + {!details.error && showFooter && ( + )} ); diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.test.tsx new file mode 100644 index 00000000000000..028187569e977d --- /dev/null +++ b/src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.test.tsx @@ -0,0 +1,82 @@ +/* + * 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 React from 'react'; +import { findTestSubject } from '@elastic/eui/lib/test'; +// @ts-ignore +import stubbedLogstashFields from 'fixtures/logstash_fields'; +import { mountWithIntl } from '@kbn/test/jest'; +import { coreMock } from '../../../../../../core/public/mocks'; +import { IndexPatternField } from '../../../../../data/public'; +import { getStubIndexPattern } from '../../../../../data/public/test_utils'; +import { DiscoverFieldDetailsFooter } from './discover_field_details_footer'; + +const indexPattern = getStubIndexPattern( + 'logstash-*', + (cfg: any) => cfg, + 'time', + stubbedLogstashFields(), + coreMock.createSetup() +); + +describe('discover sidebar field details footer', function () { + const onAddFilter = jest.fn(); + const defaultProps = { + indexPattern, + details: { buckets: [], error: '', exists: 1, total: 2, columns: [] }, + onAddFilter, + }; + + function mountComponent(field: IndexPatternField) { + const compProps = { ...defaultProps, field }; + return mountWithIntl(); + } + + it('renders properly', function () { + const visualizableField = new IndexPatternField({ + name: 'bytes', + type: 'number', + esTypes: ['long'], + count: 10, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }); + const component = mountComponent(visualizableField); + expect(component).toMatchSnapshot(); + }); + + it('click on addFilter calls the function', function () { + const visualizableField = new IndexPatternField({ + name: 'bytes', + type: 'number', + esTypes: ['long'], + count: 10, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }); + const component = mountComponent(visualizableField); + const onAddButton = findTestSubject(component, 'onAddFilterButton'); + onAddButton.simulate('click'); + expect(onAddFilter).toHaveBeenCalledWith('_exists_', visualizableField.name, '+'); + }); +}); diff --git a/src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.tsx b/src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.tsx new file mode 100644 index 00000000000000..58e91c85913a1b --- /dev/null +++ b/src/plugins/discover/public/application/components/sidebar/discover_field_details_footer.tsx @@ -0,0 +1,70 @@ +/* + * 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 React from 'react'; +import { EuiLink, EuiPopoverFooter, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { IndexPatternField } from '../../../../../data/common/index_patterns/fields'; +import { IndexPattern } from '../../../../../data/common/index_patterns/index_patterns'; +import { FieldDetails } from './types'; + +interface DiscoverFieldDetailsFooterProps { + field: IndexPatternField; + indexPattern: IndexPattern; + details: FieldDetails; + onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; +} + +export function DiscoverFieldDetailsFooter({ + field, + indexPattern, + details, + onAddFilter, +}: DiscoverFieldDetailsFooterProps) { + return ( + + + {!indexPattern.metaFields.includes(field.name) && !field.scripted ? ( + onAddFilter('_exists_', field.name, '+')} + data-test-subj="onAddFilterButton" + > + + + ) : ( + + )} + + + ); +} diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx index 57cc45b3c3e9f5..6c312924fb7b71 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx @@ -100,6 +100,10 @@ export interface DiscoverSidebarProps { * Callback function to select another index pattern */ setIndexPattern: (id: string) => void; + /** + * If on, fields are read from the fields API, not from source + */ + useNewFieldsApi?: boolean; /** * Metric tracking function * @param metricType @@ -127,9 +131,11 @@ export function DiscoverSidebar({ setFieldFilter, setIndexPattern, trackUiMetric, + useNewFieldsApi = false, useFlyout = false, }: DiscoverSidebarProps) { const [fields, setFields] = useState(null); + useEffect(() => { const newFields = getIndexPatternFieldList(selectedIndexPattern, fieldCounts); setFields(newFields); @@ -154,13 +160,10 @@ export function DiscoverSidebar({ selected: selectedFields, popular: popularFields, unpopular: unpopularFields, - } = useMemo(() => groupFields(fields, columns, popularLimit, fieldCounts, fieldFilter), [ - fields, - columns, - popularLimit, - fieldCounts, - fieldFilter, - ]); + } = useMemo( + () => groupFields(fields, columns, popularLimit, fieldCounts, fieldFilter, useNewFieldsApi), + [fields, columns, popularLimit, fieldCounts, fieldFilter, useNewFieldsApi] + ); const fieldTypes = useMemo(() => { const result = ['any']; @@ -174,6 +177,27 @@ export function DiscoverSidebar({ return result; }, [fields]); + const multiFields = useMemo(() => { + if (!useNewFieldsApi || !fields) { + return undefined; + } + const map = new Map>(); + fields.forEach((field) => { + const parent = field.spec?.subType?.multi?.parent; + if (!parent) { + return; + } + const multiField = { + field, + isSelected: selectedFields.includes(field), + }; + const value = map.get(parent) ?? []; + value.push(multiField); + map.set(parent, value); + }); + return map; + }, [fields, useNewFieldsApi, selectedFields]); + if (!selectedIndexPattern || !fields) { return null; } @@ -278,6 +302,7 @@ export function DiscoverSidebar({ getDetails={getDetailsByField} selected={true} trackUiMetric={trackUiMetric} + multiFields={multiFields?.get(field.name)} /> ); @@ -338,6 +363,7 @@ export function DiscoverSidebar({ onAddFilter={onAddFilter} getDetails={getDetailsByField} trackUiMetric={trackUiMetric} + multiFields={multiFields?.get(field.name)} /> ); @@ -366,6 +392,7 @@ export function DiscoverSidebar({ onAddFilter={onAddFilter} getDetails={getDetailsByField} trackUiMetric={trackUiMetric} + multiFields={multiFields?.get(field.name)} /> ); diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx index 0413ebd17d71b3..3000291fc23bb3 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx @@ -103,6 +103,10 @@ export interface DiscoverSidebarResponsiveProps { * Shows index pattern and a button that displays the sidebar in a flyout */ useFlyout?: boolean; + /** + * Read from the Fields API + */ + useNewFieldsApi?: boolean; } /** 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 22cacae4c3b45b..6cbfa03a070dbf 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 @@ -69,7 +69,8 @@ describe('group_fields', function () { ['currency'], 5, fieldCounts, - fieldFilterState + fieldFilterState, + false ); expect(actual).toMatchInlineSnapshot(` Object { @@ -118,6 +119,80 @@ describe('group_fields', function () { } `); }); + it('should group fields in selected, popular, unpopular group if they contain multifields', function () { + const category = { + name: 'category', + type: 'string', + esTypes: ['text'], + count: 1, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }; + const currency = { + name: 'currency', + displayName: 'currency', + kbnFieldType: { + esTypes: ['string', 'text', 'keyword', '_type', '_id'], + filterable: true, + name: 'string', + sortable: true, + }, + spec: { + esTypes: ['text'], + name: 'category', + }, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + }; + const currencyKeyword = { + name: 'currency.keyword', + displayName: 'currency.keyword', + type: 'string', + esTypes: ['keyword'], + kbnFieldType: { + esTypes: ['string', 'text', 'keyword', '_type', '_id'], + filterable: true, + name: 'string', + sortable: true, + }, + spec: { + aggregatable: true, + esTypes: ['keyword'], + name: 'category.keyword', + readFromDocValues: true, + searchable: true, + shortDotsEnable: false, + subType: { + multi: { + parent: 'currency', + }, + }, + }, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, + }; + const fieldsToGroup = [category, currency, currencyKeyword]; + + const fieldFilterState = getDefaultFieldFilter(); + + const actual = groupFields( + fieldsToGroup as any, + ['currency'], + 5, + fieldCounts, + fieldFilterState, + true + ); + expect(actual.popular).toEqual([category]); + expect(actual.selected).toEqual([currency]); + expect(actual.unpopular).toEqual([]); + }); it('should sort selected fields by columns order ', function () { const fieldFilterState = getDefaultFieldFilter(); @@ -127,7 +202,8 @@ describe('group_fields', function () { ['customer_birth_date', 'currency', 'unknown'], 5, fieldCounts, - fieldFilterState + fieldFilterState, + false ); expect(actual1.selected.map((field) => field.name)).toEqual([ 'customer_birth_date', @@ -140,7 +216,8 @@ describe('group_fields', function () { ['currency', 'customer_birth_date', 'unknown'], 5, fieldCounts, - fieldFilterState + fieldFilterState, + false ); expect(actual2.selected.map((field) => field.name)).toEqual([ 'currency', 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 c34becc97cb93f..e6c3d0fe3ea423 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 @@ -33,7 +33,8 @@ export function groupFields( columns: string[], popularLimit: number, fieldCounts: Record, - fieldFilterState: FieldFilterState + fieldFilterState: FieldFilterState, + useNewFieldsApi: boolean ): GroupedFields { const result: GroupedFields = { selected: [], @@ -62,12 +63,17 @@ export function groupFields( if (!isFieldFiltered(field, fieldFilterState, fieldCounts)) { continue; } + const isSubfield = useNewFieldsApi && field.spec?.subType?.multi?.parent; if (columns.includes(field.name)) { result.selected.push(field); } else if (popular.includes(field.name) && field.type !== '_source') { - result.popular.push(field); + if (!isSubfield) { + result.popular.push(field); + } } else if (field.type !== '_source') { - result.unpopular.push(field); + if (!isSubfield) { + result.unpopular.push(field); + } } } // add columns, that are not part of the index pattern, to be removeable diff --git a/src/plugins/discover/public/application/components/sidebar/types.ts b/src/plugins/discover/public/application/components/sidebar/types.ts index d80662b65cc7b9..4ec731e852ce3a 100644 --- a/src/plugins/discover/public/application/components/sidebar/types.ts +++ b/src/plugins/discover/public/application/components/sidebar/types.ts @@ -25,7 +25,7 @@ export interface IndexPatternRef { export interface FieldDetails { error: string; exists: number; - total: boolean; + total: number; buckets: Bucket[]; columns: string[]; } diff --git a/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts b/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts index 458b9b7e066fdb..5af4449a63e0b5 100644 --- a/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts +++ b/src/plugins/discover/public/application/helpers/get_switch_index_pattern_app_state.ts @@ -29,7 +29,8 @@ export function getSwitchIndexPatternAppState( nextIndexPattern: IndexPattern, currentColumns: string[], currentSort: SortPairArr[], - modifyColumns: boolean = true + modifyColumns: boolean = true, + useNewFieldsApi: boolean = false ) { const nextColumns = modifyColumns ? currentColumns.filter( @@ -38,9 +39,11 @@ export function getSwitchIndexPatternAppState( ) : currentColumns; const nextSort = getSortArray(currentSort, nextIndexPattern); + const defaultColumns = useNewFieldsApi ? [] : ['_source']; + const columns = nextColumns.length ? nextColumns : defaultColumns; return { index: nextIndexPattern.id, - columns: nextColumns.length ? nextColumns : ['_source'], + columns, sort: nextSort, }; } diff --git a/src/plugins/discover/public/application/helpers/persist_saved_search.ts b/src/plugins/discover/public/application/helpers/persist_saved_search.ts index 8ec2012b5843e7..2f373c34eb17dc 100644 --- a/src/plugins/discover/public/application/helpers/persist_saved_search.ts +++ b/src/plugins/discover/public/application/helpers/persist_saved_search.ts @@ -49,6 +49,8 @@ export async function persistSavedSearch( indexPattern, services, sort: state.sort as SortOrder[], + columns: state.columns || [], + useNewFieldsApi: false, }); savedSearch.columns = state.columns || []; diff --git a/src/plugins/discover/public/application/helpers/update_search_source.test.ts b/src/plugins/discover/public/application/helpers/update_search_source.test.ts index 91832325432ef3..615a414680469e 100644 --- a/src/plugins/discover/public/application/helpers/update_search_source.test.ts +++ b/src/plugins/discover/public/application/helpers/update_search_source.test.ts @@ -44,8 +44,37 @@ describe('updateSearchSource', () => { } as unknown) as IUiSettingsClient, } as unknown) as DiscoverServices, sort: [] as SortOrder[], + columns: [], + useNewFieldsApi: false, }); expect(result.getField('index')).toEqual(indexPatternMock); expect(result.getField('size')).toEqual(sampleSize); + expect(result.getField('fields')).toBe(undefined); + }); + + test('updates a given search source with the usage of the new fields api', async () => { + const searchSourceMock = createSearchSourceMock({}); + const sampleSize = 250; + const result = updateSearchSource(searchSourceMock, { + indexPattern: indexPatternMock, + services: ({ + data: dataPluginMock.createStartContract(), + uiSettings: ({ + get: (key: string) => { + if (key === SAMPLE_SIZE_SETTING) { + return sampleSize; + } + return false; + }, + } as unknown) as IUiSettingsClient, + } as unknown) as DiscoverServices, + sort: [] as SortOrder[], + columns: [], + useNewFieldsApi: true, + }); + expect(result.getField('index')).toEqual(indexPatternMock); + expect(result.getField('size')).toEqual(sampleSize); + expect(result.getField('fields')).toEqual(['*']); + expect(result.getField('fieldsFromSource')).toBe(undefined); }); }); diff --git a/src/plugins/discover/public/application/helpers/update_search_source.ts b/src/plugins/discover/public/application/helpers/update_search_source.ts index 324dc8a48457a5..46f1c9f6260540 100644 --- a/src/plugins/discover/public/application/helpers/update_search_source.ts +++ b/src/plugins/discover/public/application/helpers/update_search_source.ts @@ -31,10 +31,14 @@ export function updateSearchSource( indexPattern, services, sort, + columns, + useNewFieldsApi, }: { indexPattern: IndexPattern; services: DiscoverServices; sort: SortOrder[]; + columns: string[]; + useNewFieldsApi: boolean; } ) { const { uiSettings, data } = services; @@ -50,5 +54,13 @@ export function updateSearchSource( .setField('sort', usedSort) .setField('query', data.query.queryString.getQuery() || null) .setField('filter', data.query.filterManager.getFilters()); + if (useNewFieldsApi) { + searchSource.removeField('fieldsFromSource'); + searchSource.setField('fields', ['*']); + } else { + searchSource.removeField('fields'); + const fieldNames = indexPattern.fields.map((field) => field.name); + searchSource.setField('fieldsFromSource', fieldNames); + } return searchSource; } diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index 425928385e64a6..673f55c78a506b 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -35,6 +35,7 @@ import { CONTEXT_TIE_BREAKER_FIELDS_SETTING, DOC_TABLE_LEGACY, MODIFY_COLUMNS_ON_SWITCH, + SEARCH_FIELDS_FROM_SOURCE, } from '../common'; export const uiSettings: Record = { @@ -198,4 +199,11 @@ export const uiSettings: Record = { name: 'discover:modifyColumnsOnSwitchTitle', }, }, + [SEARCH_FIELDS_FROM_SOURCE]: { + name: 'Read fields from _source', + description: `When enabled will load documents directly from \`_source\`. This is soon going to be deprecated. When disabled, will retrieve fields via the new Fields API in the high-level search service.`, + value: false, + category: ['discover'], + schema: schema.boolean(), + }, }; diff --git a/test/functional/apps/context/_date_nanos_custom_timestamp.js b/test/functional/apps/context/_date_nanos_custom_timestamp.js index 8fe08d13af0aa7..8772b10a4b8c8b 100644 --- a/test/functional/apps/context/_date_nanos_custom_timestamp.js +++ b/test/functional/apps/context/_date_nanos_custom_timestamp.js @@ -38,6 +38,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.update({ 'context:defaultSize': `${TEST_DEFAULT_CONTEXT_SIZE}`, 'context:step': `${TEST_STEP_SIZE}`, + 'discover:searchFieldsFromSource': true, }); }); diff --git a/test/functional/apps/discover/_data_grid_doc_navigation.ts b/test/functional/apps/discover/_data_grid_doc_navigation.ts index 92d9893cab0b60..97b8eb564a2567 100644 --- a/test/functional/apps/discover/_data_grid_doc_navigation.ts +++ b/test/functional/apps/discover/_data_grid_doc_navigation.ts @@ -56,7 +56,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(hasDocHit).to.be(true); }); - it('add filter should create an exists filter if value is null (#7189)', async function () { + // no longer relevant as null field won't be returned in the Fields API response + xit('add filter should create an exists filter if value is null (#7189)', async function () { await PageObjects.discover.waitUntilSearchingHasFinished(); // Filter special document await filterBar.addFilter('agent', 'is', 'Missing/Fields'); diff --git a/test/functional/apps/discover/_data_grid_field_data.ts b/test/functional/apps/discover/_data_grid_field_data.ts index 8224f59f7fabf8..137c19149d274c 100644 --- a/test/functional/apps/discover/_data_grid_field_data.ts +++ b/test/functional/apps/discover/_data_grid_field_data.ts @@ -53,7 +53,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('the search term should be highlighted in the field data', async function () { // marks is the style that highlights the text in yellow const marks = await PageObjects.discover.getMarks(); - expect(marks.length).to.be(25); + expect(marks.length).to.be(50); expect(marks.indexOf('php')).to.be(0); }); diff --git a/test/functional/apps/discover/_discover_fields_api.ts b/test/functional/apps/discover/_discover_fields_api.ts new file mode 100644 index 00000000000000..94cb4ed5fa52ef --- /dev/null +++ b/test/functional/apps/discover/_discover_fields_api.ts @@ -0,0 +1,71 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from './ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const log = getService('log'); + const retry = getService('retry'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + const defaultSettings = { + defaultIndex: 'logstash-*', + 'discover:searchFieldsFromSource': false, + }; + describe('discover uses fields API test', function describeIndexTests() { + before(async function () { + log.debug('load kibana index with default index pattern'); + await esArchiver.load('discover'); + await esArchiver.loadIfNeeded('logstash_functional'); + await kibanaServer.uiSettings.replace(defaultSettings); + log.debug('discover'); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + }); + + after(async () => { + await kibanaServer.uiSettings.replace({ 'discover:searchFieldsFromSource': true }); + }); + + it('should correctly display documents', async function () { + log.debug('check if Document title exists in the grid'); + expect(await PageObjects.discover.getDocHeader()).to.have.string('Document'); + const rowData = await PageObjects.discover.getDocTableIndex(1); + log.debug('check the newest doc timestamp in UTC (check diff timezone in last test)'); + expect(rowData.startsWith('Sep 22, 2015 @ 23:50:13.253')).to.be.ok(); + const expectedHitCount = '14,004'; + await retry.try(async function () { + expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount); + }); + }); + + it('adding a column removes a default column', async function () { + await PageObjects.discover.clickFieldListItemAdd('_score'); + expect(await PageObjects.discover.getDocHeader()).to.have.string('_score'); + expect(await PageObjects.discover.getDocHeader()).not.to.have.string('Document'); + }); + + it('removing a column adds a default column', async function () { + await PageObjects.discover.clickFieldListItemRemove('_score'); + expect(await PageObjects.discover.getDocHeader()).not.to.have.string('_score'); + expect(await PageObjects.discover.getDocHeader()).to.have.string('Document'); + }); + }); +} diff --git a/test/functional/apps/discover/_doc_navigation.ts b/test/functional/apps/discover/_doc_navigation.ts index 76612b255ac232..79632942cf04af 100644 --- a/test/functional/apps/discover/_doc_navigation.ts +++ b/test/functional/apps/discover/_doc_navigation.ts @@ -55,7 +55,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(hasDocHit).to.be(true); }); - it('add filter should create an exists filter if value is null (#7189)', async function () { + // no longer relevant as null field won't be returned in the Fields API response + xit('add filter should create an exists filter if value is null (#7189)', async function () { await PageObjects.discover.waitUntilSearchingHasFinished(); // Filter special document await filterBar.addFilter('agent', 'is', 'Missing/Fields'); diff --git a/test/functional/apps/discover/_field_data.ts b/test/functional/apps/discover/_field_data.ts index e08325a81a3e80..3811cde8a6367c 100644 --- a/test/functional/apps/discover/_field_data.ts +++ b/test/functional/apps/discover/_field_data.ts @@ -36,6 +36,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await esArchiver.load('discover'); await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*', + 'discover:searchFieldsFromSource': true, }); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); diff --git a/test/functional/apps/discover/_field_data_with_fields_api.ts b/test/functional/apps/discover/_field_data_with_fields_api.ts new file mode 100644 index 00000000000000..923a021f5fad6c --- /dev/null +++ b/test/functional/apps/discover/_field_data_with_fields_api.ts @@ -0,0 +1,105 @@ +/* + * 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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const toasts = getService('toasts'); + const queryBar = getService('queryBar'); + const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']); + + describe('discover tab with new fields API', function describeIndexTests() { + this.tags('includeFirefox'); + before(async function () { + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.load('discover'); + await kibanaServer.uiSettings.replace({ + defaultIndex: 'logstash-*', + 'discover:searchFieldsFromSource': false, + }); + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await PageObjects.common.navigateToApp('discover'); + }); + describe('field data', function () { + it('search php should show the correct hit count', async function () { + const expectedHitCount = '445'; + await retry.try(async function () { + await queryBar.setQuery('php'); + await queryBar.submitQuery(); + const hitCount = await PageObjects.discover.getHitCount(); + expect(hitCount).to.be(expectedHitCount); + }); + }); + + it('the search term should be highlighted in the field data', async function () { + // marks is the style that highlights the text in yellow + const marks = await PageObjects.discover.getMarks(); + expect(marks.length).to.be(100); + expect(marks.indexOf('php')).to.be(0); + }); + + it('search type:apache should show the correct hit count', async function () { + const expectedHitCount = '11,156'; + await queryBar.setQuery('type:apache'); + await queryBar.submitQuery(); + await retry.try(async function tryingForTime() { + const hitCount = await PageObjects.discover.getHitCount(); + expect(hitCount).to.be(expectedHitCount); + }); + }); + + it('doc view should show Time and Document columns', async function () { + const expectedHeader = 'Time Document'; + const Docheader = await PageObjects.discover.getDocHeader(); + expect(Docheader).to.be(expectedHeader); + }); + + it('doc view should sort ascending', async function () { + const expectedTimeStamp = 'Sep 20, 2015 @ 00:00:00.000'; + await PageObjects.discover.clickDocSortDown(); + + // we don't technically need this sleep here because the tryForTime will retry and the + // results will match on the 2nd or 3rd attempt, but that debug output is huge in this + // case and it can be avoided with just a few seconds sleep. + await PageObjects.common.sleep(2000); + await retry.try(async function tryingForTime() { + const rowData = await PageObjects.discover.getDocTableIndex(1); + + expect(rowData.startsWith(expectedTimeStamp)).to.be.ok(); + }); + }); + + it('a bad syntax query should show an error message', async function () { + const expectedError = + 'Expected ":", "<", "<=", ">", ">=", AND, OR, end of input, ' + + 'whitespace but "(" found.'; + await queryBar.setQuery('xxx(yyy))'); + await queryBar.submitQuery(); + const { message } = await toasts.getErrorToast(); + expect(message).to.contain(expectedError); + await toasts.dismissToast(); + }); + }); + }); +} diff --git a/test/functional/apps/discover/_large_string.ts b/test/functional/apps/discover/_large_string.ts index fe5613a4e3f195..e8ad6131bcc212 100644 --- a/test/functional/apps/discover/_large_string.ts +++ b/test/functional/apps/discover/_large_string.ts @@ -40,7 +40,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('verify the large string book present', async function () { const ExpectedDoc = - 'mybook:Project Gutenberg EBook of Hamlet, by William Shakespeare' + + '_id:1 _type: - _index:testlargestring _score:0' + + ' mybook:Project Gutenberg EBook of Hamlet, by William Shakespeare' + ' This eBook is for the use of anyone anywhere in the United States' + ' and most other parts of the world at no cost and with almost no restrictions whatsoever.' + ' You may copy it, give it away or re-use it under the terms of the' + diff --git a/test/functional/apps/discover/_shared_links.ts b/test/functional/apps/discover/_shared_links.ts index 51ea5f997e859d..b15f5b0aae39f5 100644 --- a/test/functional/apps/discover/_shared_links.ts +++ b/test/functional/apps/discover/_shared_links.ts @@ -88,7 +88,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { '/app/discover?_t=1453775307251#' + '/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time' + ":(from:'2015-09-19T06:31:44.000Z',to:'2015-09" + - "-23T18:31:44.000Z'))&_a=(columns:!(_source),filters:!(),index:'logstash-" + + "-23T18:31:44.000Z'))&_a=(columns:!(),filters:!(),index:'logstash-" + "*',interval:auto,query:(language:kuery,query:'')" + ",sort:!(!('@timestamp',desc)))"; const actualUrl = await PageObjects.share.getSharedUrl(); diff --git a/test/functional/apps/discover/_source_filters.ts b/test/functional/apps/discover/_source_filters.ts index 0af7c0ade79ba7..d2ae02ef25de4d 100644 --- a/test/functional/apps/discover/_source_filters.ts +++ b/test/functional/apps/discover/_source_filters.ts @@ -40,6 +40,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // and load a set of makelogs data await esArchiver.loadIfNeeded('logstash_functional'); + await kibanaServer.uiSettings.update({ + 'discover:searchFieldsFromSource': true, + }); + log.debug('discover'); await PageObjects.common.navigateToApp('discover'); diff --git a/test/functional/apps/discover/ftr_provider_context.d.ts b/test/functional/apps/discover/ftr_provider_context.d.ts new file mode 100644 index 00000000000000..a4894e024b6125 --- /dev/null +++ b/test/functional/apps/discover/ftr_provider_context.d.ts @@ -0,0 +1,23 @@ +/* + * 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 { GenericFtrProviderContext } from '@kbn/test/types/ftr'; +import { services } from '../../services'; +import { pageObjects } from '../../page_objects'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/test/functional/apps/discover/index.ts b/test/functional/apps/discover/index.ts index 450049af66abfa..5fd49a1d352166 100644 --- a/test/functional/apps/discover/index.ts +++ b/test/functional/apps/discover/index.ts @@ -42,6 +42,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_filter_editor')); loadTestFile(require.resolve('./_errors')); loadTestFile(require.resolve('./_field_data')); + loadTestFile(require.resolve('./_field_data_with_fields_api')); loadTestFile(require.resolve('./_shared_links')); loadTestFile(require.resolve('./_sidebar')); loadTestFile(require.resolve('./_source_filters')); @@ -51,6 +52,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_date_nanos')); loadTestFile(require.resolve('./_date_nanos_mixed')); loadTestFile(require.resolve('./_indexpattern_without_timefield')); + loadTestFile(require.resolve('./_discover_fields_api')); loadTestFile(require.resolve('./_data_grid')); loadTestFile(require.resolve('./_data_grid_context')); loadTestFile(require.resolve('./_data_grid_field_data')); diff --git a/test/functional/fixtures/es_archiver/date_nanos/mappings.json b/test/functional/fixtures/es_archiver/date_nanos/mappings.json index bea82767f6cbb0..f9ef429a0f97cc 100644 --- a/test/functional/fixtures/es_archiver/date_nanos/mappings.json +++ b/test/functional/fixtures/es_archiver/date_nanos/mappings.json @@ -5,7 +5,8 @@ "mappings": { "properties": { "@timestamp": { - "type": "date_nanos" + "type": "date_nanos", + "format": "strict_date_optional_time_nanos" } } }, diff --git a/test/functional/fixtures/es_archiver/date_nanos_mixed/mappings.json b/test/functional/fixtures/es_archiver/date_nanos_mixed/mappings.json index c62918abced58a..b29f6b111b06d9 100644 --- a/test/functional/fixtures/es_archiver/date_nanos_mixed/mappings.json +++ b/test/functional/fixtures/es_archiver/date_nanos_mixed/mappings.json @@ -29,7 +29,8 @@ "mappings": { "properties": { "timestamp": { - "type": "date_nanos" + "type": "date_nanos", + "format": "strict_date_optional_time_nanos" } } }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f479b3a521185d..999da541615c16 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1510,10 +1510,8 @@ "discover.embeddable.inspectorRequestDescription": "このリクエストはElasticsearchにクエリをかけ、検索データを取得します。", "discover.embeddable.search.displayName": "検索", "discover.fieldChooser.detailViews.emptyStringText": "空の文字列", - "discover.fieldChooser.detailViews.existsText": "存在する", "discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel": "{field}を除外:\"{value}\"", "discover.fieldChooser.detailViews.filterValueButtonAriaLabel": "{field}を除外:\"{value}\"", - "discover.fieldChooser.detailViews.recordsText": "記録", "discover.fieldChooser.detailViews.visualizeLinkText": "可視化", "discover.fieldChooser.discoverField.addButtonAriaLabel": "{field}を表に追加", "discover.fieldChooser.discoverField.addFieldTooltip": "フィールドを列として追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a661537e6e2886..d92a2ba94ff34a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1510,10 +1510,8 @@ "discover.embeddable.inspectorRequestDescription": "此请求将查询 Elasticsearch 以获取搜索的数据。", "discover.embeddable.search.displayName": "搜索", "discover.fieldChooser.detailViews.emptyStringText": "空字符串", - "discover.fieldChooser.detailViews.existsText": "存在于", "discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel": "筛除 {field}:“{value}”", "discover.fieldChooser.detailViews.filterValueButtonAriaLabel": "筛留 {field}:“{value}”", - "discover.fieldChooser.detailViews.recordsText": "个记录", "discover.fieldChooser.detailViews.visualizeLinkText": "可视化", "discover.fieldChooser.discoverField.addButtonAriaLabel": "将 {field} 添加到表中", "discover.fieldChooser.discoverField.addFieldTooltip": "将字段添加为列", diff --git a/x-pack/test/functional/apps/security/doc_level_security_roles.js b/x-pack/test/functional/apps/security/doc_level_security_roles.js index 72f463be48fd53..0595322ad2d219 100644 --- a/x-pack/test/functional/apps/security/doc_level_security_roles.js +++ b/x-pack/test/functional/apps/security/doc_level_security_roles.js @@ -77,7 +77,7 @@ export default function ({ getService, getPageObjects }) { }); const rowData = await PageObjects.discover.getDocTableIndex(1); expect(rowData).to.be( - 'name:ABC Company region:EAST _id:doc1 _type: - _index:dlstest _score:0' + '_id:doc1 _type: - _index:dlstest _score:0 region.keyword:EAST name:ABC Company name.keyword:ABC Company region:EAST' ); }); after('logout', async () => { diff --git a/x-pack/test/functional/apps/security/field_level_security.js b/x-pack/test/functional/apps/security/field_level_security.js index 7b22d72885c9d2..3f3984dd05a942 100644 --- a/x-pack/test/functional/apps/security/field_level_security.js +++ b/x-pack/test/functional/apps/security/field_level_security.js @@ -112,7 +112,7 @@ export default function ({ getService, getPageObjects }) { }); const rowData = await PageObjects.discover.getDocTableIndex(1); expect(rowData).to.be( - 'customer_ssn:444.555.6666 customer_name:ABC Company customer_region:WEST _id:2 _type: - _index:flstest _score:0' + '_id:2 _type: - _index:flstest _score:0 customer_name.keyword:ABC Company customer_ssn:444.555.6666 customer_region.keyword:WEST runtime_customer_ssn:444.555.6666 calculated at runtime customer_region:WEST customer_name:ABC Company customer_ssn.keyword:444.555.6666' ); }); @@ -126,7 +126,7 @@ export default function ({ getService, getPageObjects }) { }); const rowData = await PageObjects.discover.getDocTableIndex(1); expect(rowData).to.be( - 'customer_name:ABC Company customer_region:WEST _id:2 _type: - _index:flstest _score:0' + '_id:2 _type: - _index:flstest _score:0 customer_name.keyword:ABC Company customer_region.keyword:WEST customer_region:WEST customer_name:ABC Company' ); }); diff --git a/x-pack/test/functional/es_archives/security/flstest/data/mappings.json b/x-pack/test/functional/es_archives/security/flstest/data/mappings.json index 4f419e4b6ade47..0b970d5a3c1dfd 100644 --- a/x-pack/test/functional/es_archives/security/flstest/data/mappings.json +++ b/x-pack/test/functional/es_archives/security/flstest/data/mappings.json @@ -7,7 +7,8 @@ "runtime_customer_ssn": { "type": "keyword", "script": { - "source": "emit(doc['customer_ssn'].value + ' calculated at runtime')" + "lang": "painless", + "source": "if (doc['customer_ssn'].size() !== 0) { return emit(doc['customer_ssn'].value + ' calculated at runtime') }" } } }, @@ -37,7 +38,8 @@ "type": "keyword" } }, - "type": "text" + "type": "text", + "fielddata": true } } }, From fc370b74eb2f5efc0fe58ef587371fc276d54bd6 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 15 Jan 2021 10:25:06 -0500 Subject: [PATCH 07/33] [Uptime] Unskip "Observer location" test block (#87571) * Unskip "Observer location" test block. * Commit temp "describe.only" to make flaky test runner go faster. * Add optional chain for some potentially-null props. * Make overview filters type partial. * Repair broken types. * Remove \`only\` call from test. --- .../overview_filters/overview_filters.ts | 2 +- .../alerts_containers/alert_monitor_status.tsx | 2 +- .../overview/filter_group/filter_group.tsx | 18 +++++++++++------- .../test/functional/apps/uptime/locations.ts | 3 +-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/uptime/common/runtime_types/overview_filters/overview_filters.ts b/x-pack/plugins/uptime/common/runtime_types/overview_filters/overview_filters.ts index 9b9241494f0012..854b4b6b6e9b8e 100644 --- a/x-pack/plugins/uptime/common/runtime_types/overview_filters/overview_filters.ts +++ b/x-pack/plugins/uptime/common/runtime_types/overview_filters/overview_filters.ts @@ -6,7 +6,7 @@ import * as t from 'io-ts'; -export const OverviewFiltersType = t.type({ +export const OverviewFiltersType = t.partial({ locations: t.array(t.string), ports: t.array(t.number), schemes: t.array(t.string), diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx index 50b6fe2aa0ef17..1c1deb21049705 100644 --- a/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx +++ b/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx @@ -122,7 +122,7 @@ export const AlertMonitorStatus: React.FC = ({ enabled={enabled} hasFilters={!!overviewFilters?.filters} isOldAlert={isOldAlert} - locations={locations} + locations={locations || []} numTimes={numTimes} setAlertParams={setAlertParams} shouldUpdateUrl={shouldUpdateUrl} diff --git a/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx b/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx index 45268977a543f8..a5256ee1e26262 100644 --- a/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx +++ b/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx @@ -24,6 +24,10 @@ const Container = styled(EuiFilterGroup)` margin-bottom: 10px; `; +function isDisabled(array?: T[]) { + return array ? array.length === 0 : true; +} + export const FilterGroupComponent: React.FC = ({ overviewFilters, loading, @@ -51,7 +55,7 @@ export const FilterGroupComponent: React.FC = ({ onFilterFieldChange, fieldName: 'observer.geo.name', id: 'location', - items: locations, + items: locations || [], selectedItems: selectedLocations, title: filterLabels.LOCATION, }, @@ -63,8 +67,8 @@ export const FilterGroupComponent: React.FC = ({ onFilterFieldChange, fieldName: 'url.port', id: 'port', - disabled: ports.length === 0, - items: ports.map((p: number) => p.toString()), + disabled: isDisabled(ports), + items: ports?.map((p: number) => p.toString()) ?? [], selectedItems: selectedPorts, title: filterLabels.PORT, }, @@ -73,8 +77,8 @@ export const FilterGroupComponent: React.FC = ({ onFilterFieldChange, fieldName: 'monitor.type', id: 'scheme', - disabled: schemes.length === 0, - items: schemes, + disabled: isDisabled(schemes), + items: schemes ?? [], selectedItems: selectedSchemes, title: filterLabels.SCHEME, }, @@ -83,8 +87,8 @@ export const FilterGroupComponent: React.FC = ({ onFilterFieldChange, fieldName: 'tags', id: 'tags', - disabled: tags.length === 0, - items: tags, + disabled: isDisabled(tags), + items: tags ?? [], selectedItems: selectedTags, title: filterLabels.TAGS, }, diff --git a/x-pack/test/functional/apps/uptime/locations.ts b/x-pack/test/functional/apps/uptime/locations.ts index eb5a642c8d69dc..6bfa19c6ef578c 100644 --- a/x-pack/test/functional/apps/uptime/locations.ts +++ b/x-pack/test/functional/apps/uptime/locations.ts @@ -38,8 +38,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await makeChecksWithStatus(es, LessAvailMonitor, 5, 2, 10000, {}, 'down'); }; - // FLAKY: https://github.com/elastic/kibana/issues/85208 - describe.skip('Observer location', () => { + describe('Observer location', () => { const start = '~ 15 minutes ago'; const end = 'now'; From e2fc156bc55b9be2ccfa8715b4637ef8401fb4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 15 Jan 2021 17:03:56 +0100 Subject: [PATCH 08/33] [APM] Extracting custom link flaky test. (#88455) * extracting the flaky test to another file * extracting the flaky test to another file --- .../DeleteButton.test.tsx | 29 +++++++++++++++++ .../CustomizeUI/CustomLink/index.test.tsx | 32 +------------------ 2 files changed, 30 insertions(+), 31 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/DeleteButton.test.tsx diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/DeleteButton.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/DeleteButton.test.tsx new file mode 100644 index 00000000000000..1dda204c8d6bc0 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/DeleteButton.test.tsx @@ -0,0 +1,29 @@ +/* + * 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 { fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { MockApmPluginContextWrapper } from '../../../../../../context/apm_plugin/mock_apm_plugin_context'; +import * as apmApi from '../../../../../../services/rest/createCallApmApi'; +import { DeleteButton } from './DeleteButton'; + +describe('Delete custom link', () => { + beforeAll(() => { + jest.spyOn(apmApi, 'callApmApi').mockResolvedValue({}); + }); + it('deletes a custom link', async () => { + const onDeleteMock = jest.fn(); + const { getByText } = render( + + + + ); + await act(async () => { + fireEvent.click(getByText('Delete')); + }); + expect(onDeleteMock).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx index 63dd4865441248..c476686595b392 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx @@ -4,12 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - fireEvent, - render, - RenderResult, - waitFor, -} from '@testing-library/react'; +import { fireEvent, render, RenderResult } from '@testing-library/react'; import React from 'react'; import { act } from 'react-dom/test-utils'; import { CustomLinkOverview } from '.'; @@ -219,31 +214,6 @@ describe('CustomLink', () => { expect(saveCustomLinkSpy).toHaveBeenCalledTimes(1); }); - // FLAKY: https://github.com/elastic/kibana/issues/75106 - it.skip('deletes a custom link', async () => { - const mockContext = getMockAPMContext({ canSave: true }); - const component = render( - - - - - - ); - expect(component.queryByText('Create link')).not.toBeInTheDocument(); - const editButtons = component.getAllByLabelText('Edit'); - expect(editButtons.length).toEqual(2); - act(() => { - fireEvent.click(editButtons[0]); - }); - await waitFor(() => - expect(component.queryByText('Create link')).toBeInTheDocument() - ); - await act(async () => { - fireEvent.click(component.getByText('Delete')); - }); - expect(refetch).toHaveBeenCalled(); - }); - describe('Filters', () => { const addFilterField = (component: RenderResult, amount: number) => { for (let i = 1; i <= amount; i++) { From 329a5a3f21e8f6ef86e0139baf090f6ddc8834b4 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Fri, 15 Jan 2021 11:45:24 -0500 Subject: [PATCH 09/33] [App Search] Add configurable Filter and Sort modal to Documents View (#88066) --- .../__mocks__/shallow_useeffect.mock.ts | 13 +- .../customization_callout.test.tsx | 30 ++++ .../customization_callout.tsx | 48 ++++++ .../customization_modal.test.tsx | 75 +++++++++ .../search_experience/customization_modal.tsx | 156 ++++++++++++++++++ .../search_experience/search_experience.scss | 5 + .../search_experience.test.tsx | 51 ++++++ .../search_experience/search_experience.tsx | 30 +++- .../shared/use_local_storage/index.ts | 7 + .../use_local_storage.test.tsx | 69 ++++++++ .../use_local_storage/use_local_storage.ts | 56 +++++++ 11 files changed, 534 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/index.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_useeffect.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_useeffect.mock.ts index 1e3a45a83853ca..ce4ec39505732c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_useeffect.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_useeffect.mock.ts @@ -4,15 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ +// Helper for calling the returned useEffect unmount handler +let mockUnmountHandler: () => void; +export const unmountHandler = () => mockUnmountHandler(); + jest.mock('react', () => ({ ...(jest.requireActual('react') as object), - useEffect: jest.fn((fn) => fn()), // Calls on mount/every update - use mount for more complex behavior + useEffect: jest.fn((fn) => { + mockUnmountHandler = fn(); + return mockUnmountHandler; + }), // Calls on mount/every update - use mount for more complex behavior })); -// Helper for calling the returned useEffect unmount handler -import { useEffect } from 'react'; -export const unmountHandler = () => (useEffect as jest.Mock).mock.calls[0][0]()(); - /** * Example usage within a component test using shallow(): * diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx new file mode 100644 index 00000000000000..7864a6411ffa60 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.test.tsx @@ -0,0 +1,30 @@ +/* + * 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 React from 'react'; + +import { shallow, ShallowWrapper } from 'enzyme'; +import { EuiButton } from '@elastic/eui'; + +import { CustomizationCallout } from './customization_callout'; + +describe('CustomizationCallout', () => { + let wrapper: ShallowWrapper; + const onClick = jest.fn(); + + beforeAll(() => { + wrapper = shallow(); + }); + + it('renders', () => { + expect(wrapper.isEmptyRender()).toBe(false); + }); + + it('calls onClick param when the Customize button is clicked', () => { + wrapper.find(EuiButton).simulate('click'); + expect(onClick).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx new file mode 100644 index 00000000000000..a9bec6ced828fd --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_callout.tsx @@ -0,0 +1,48 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; + +import { EuiButton, EuiFlexGroup, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; + +interface Props { + onClick(): void; +} + +export const CustomizationCallout: React.FC = ({ onClick }) => { + return ( + + + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.documents.search.customizationCallout.message', + { + defaultMessage: + 'Did you know that you can customize your document search experience? Click "Customize" below to get started.', + } + )} + + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.documents.search.customizationCallout.button', + { + defaultMessage: 'Customize', + } + )} + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx new file mode 100644 index 00000000000000..94b2ab7cf3f044 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.test.tsx @@ -0,0 +1,75 @@ +/* + * 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 { setMockValues, setMockActions } from '../../../../__mocks__'; + +import React from 'react'; +import { shallow } from 'enzyme'; +import { EuiButton, EuiButtonEmpty } from '@elastic/eui'; + +import { CustomizationModal } from './customization_modal'; + +describe('CustomizationModal', () => { + const props = { + filterFields: ['field1', 'field2'], + sortFields: ['sortField1', 'sortField2'], + onClose: jest.fn(), + onSave: jest.fn(), + }; + + const values = { + engine: { + name: 'some-engine', + apiKey: '1234', + }, + }; + + const actions = { + setEngine: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + setMockValues(values); + setMockActions(actions); + }); + + it('renders', () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBe(false); + }); + + it('when save is clicked, it calls onSave prop with selected filter and sort fields', () => { + const wrapper = shallow(); + wrapper.find(EuiButton).simulate('click'); + expect(props.onSave).toHaveBeenCalledWith({ + filterFields: ['field1', 'field2'], + sortFields: ['sortField1', 'sortField2'], + }); + }); + + it('when save is clicked, it calls onSave prop when with updated selections', () => { + const wrapper = shallow(); + + const sortFieldsDropdown = wrapper.find('[data-test-subj="sortFieldsDropdown"]'); + sortFieldsDropdown.simulate('change', [{ label: 'newSort1' }]); + + const filterFieldsDropdown = wrapper.find('[data-test-subj="filterFieldsDropdown"]'); + filterFieldsDropdown.simulate('change', [{ label: 'newField1' }]); + + wrapper.find(EuiButton).simulate('click'); + expect(props.onSave).toHaveBeenCalledWith({ + filterFields: ['newField1'], + sortFields: ['newSort1'], + }); + }); + + it('calls onClose when cancel is clicked', () => { + const wrapper = shallow(); + wrapper.find(EuiButtonEmpty).simulate('click'); + expect(props.onClose).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx new file mode 100644 index 00000000000000..2b05ed7e78f641 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/customization_modal.tsx @@ -0,0 +1,156 @@ +/* + * 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 React, { useState, useMemo } from 'react'; + +import { + EuiButton, + EuiButtonEmpty, + EuiComboBox, + EuiForm, + EuiFormRow, + EuiModal, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiOverlayMask, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useValues } from 'kea'; + +import { EngineLogic } from '../../engine'; + +interface Props { + filterFields: string[]; + sortFields: string[]; + onClose(): void; + onSave({ sortFields, filterFields }: { sortFields: string[]; filterFields: string[] }): void; +} + +const fieldNameToComboBoxOption = (fieldName: string) => ({ label: fieldName }); +const comboBoxOptionToFieldName = ({ label }: { label: string }) => label; + +export const CustomizationModal: React.FC = ({ + filterFields, + onClose, + onSave, + sortFields, +}) => { + const { engine } = useValues(EngineLogic); + + const [selectedFilterFields, setSelectedFilterFields] = useState( + filterFields.map(fieldNameToComboBoxOption) + ); + const [selectedSortFields, setSelectedSortFields] = useState( + sortFields.map(fieldNameToComboBoxOption) + ); + + const engineSchema = engine.schema || {}; + const selectableFilterFields = useMemo( + () => Object.keys(engineSchema).map(fieldNameToComboBoxOption), + [engineSchema] + ); + const selectableSortFields = useMemo( + () => Object.keys(engineSchema).map(fieldNameToComboBoxOption), + [engineSchema] + ); + + return ( + + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.documents.search.customizationModal.title', + { + defaultMessage: 'Customize document search', + } + )} + + + + + + + + + + + + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.documents.search.customizationModal.cancel', + { + defaultMessage: 'Cancel', + } + )} + + { + onSave({ + filterFields: selectedFilterFields.map(comboBoxOptionToFieldName), + sortFields: selectedSortFields.map(comboBoxOptionToFieldName), + }); + }} + > + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.documents.search.customizationModal.save', + { + defaultMessage: 'Save', + } + )} + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.scss index 868a561a278739..ba9931dc90fdc3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.scss @@ -20,4 +20,9 @@ .documentsSearchExperience__pagingInfo { flex-grow: 0; } + + .customizationCallout { + background-color: $euiPageBackgroundColor; + padding: $euiSizeL; + } } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx index 750d00311255ce..250cd00943d7e4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx @@ -7,11 +7,26 @@ import '../../../../__mocks__/kea.mock'; import { setMockValues } from '../../../../__mocks__'; import '../../../../__mocks__/enterprise_search_url.mock'; +const mockSetFields = jest.fn(); + +jest.mock('../../../../shared/use_local_storage', () => ({ + useLocalStorage: jest.fn(() => [ + { + filterFields: ['a', 'b', 'c'], + sortFields: ['d', 'c'], + }, + mockSetFields, + ]), +})); + import React from 'react'; // @ts-expect-error types are not available for this package yet import { SearchProvider } from '@elastic/react-search-ui'; import { shallow } from 'enzyme'; +import { CustomizationCallout } from './customization_callout'; +import { CustomizationModal } from './customization_modal'; + import { SearchExperience } from './search_experience'; describe('SearchExperience', () => { @@ -31,4 +46,40 @@ describe('SearchExperience', () => { const wrapper = shallow(); expect(wrapper.find(SearchProvider).length).toBe(1); }); + + describe('customization modal', () => { + it('has a customization modal which can be opened and closed', () => { + const wrapper = shallow(); + expect(wrapper.find(CustomizationModal).exists()).toBe(false); + + wrapper.find(CustomizationCallout).simulate('click'); + expect(wrapper.find(CustomizationModal).exists()).toBe(true); + + wrapper.find(CustomizationModal).prop('onClose')(); + expect(wrapper.find(CustomizationModal).exists()).toBe(false); + }); + + it('passes values from localStorage to the customization modal', () => { + const wrapper = shallow(); + wrapper.find(CustomizationCallout).simulate('click'); + expect(wrapper.find(CustomizationModal).prop('filterFields')).toEqual(['a', 'b', 'c']); + expect(wrapper.find(CustomizationModal).prop('sortFields')).toEqual(['d', 'c']); + }); + + it('updates selected fields in localStorage and closes modal on save', () => { + const wrapper = shallow(); + wrapper.find(CustomizationCallout).simulate('click'); + wrapper.find(CustomizationModal).prop('onSave')({ + filterFields: ['new', 'filters'], + sortFields: ['new', 'sorts'], + }); + + expect(mockSetFields).toHaveBeenCalledWith({ + filterFields: ['new', 'filters'], + sortFields: ['new', 'sorts'], + }); + + expect(wrapper.find(CustomizationModal).exists()).toBe(false); + }); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx index 1501efc589fc08..e80ab2e18b2d3b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; import { useValues } from 'kea'; @@ -17,10 +17,13 @@ import './search_experience.scss'; import { EngineLogic } from '../../engine'; import { externalUrl } from '../../../../shared/enterprise_search_url'; +import { useLocalStorage } from '../../../../shared/use_local_storage'; import { SearchBoxView, SortingView } from './views'; import { SearchExperienceContent } from './search_experience_content'; import { buildSearchUIConfig } from './build_search_ui_config'; +import { CustomizationCallout } from './customization_callout'; +import { CustomizationModal } from './customization_modal'; const DEFAULT_SORT_OPTIONS = [ { @@ -43,6 +46,18 @@ export const SearchExperience: React.FC = () => { const { engine } = useValues(EngineLogic); const endpointBase = externalUrl.enterpriseSearchUrl; + const [showCustomizationModal, setShowCustomizationModal] = useState(false); + const openCustomizationModal = () => setShowCustomizationModal(true); + const closeCustomizationModal = () => setShowCustomizationModal(false); + + const [fields, setFields] = useLocalStorage( + `documents-search-experience-customization--${engine.name}`, + { + filterFields: [] as string[], + sortFields: [] as string[], + } + ); + // TODO const sortFieldsOptions = _flatten(fields.sortFields.map(fieldNameToSortOptions)) // we need to flatten this array since fieldNameToSortOptions returns an array of two sorting options const sortingOptions = [...DEFAULT_SORT_OPTIONS /* TODO ...sortFieldsOptions*/]; @@ -85,12 +100,25 @@ export const SearchExperience: React.FC = () => { sortOptions={sortingOptions} view={SortingView} /> + + + {showCustomizationModal && ( + { + setFields({ filterFields, sortFields }); + closeCustomizationModal(); + }} + /> + )}
); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/index.ts new file mode 100644 index 00000000000000..8c75ca9ae43c84 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/index.ts @@ -0,0 +1,7 @@ +/* + * 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 { useLocalStorage } from './use_local_storage'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.test.tsx new file mode 100644 index 00000000000000..0b0edcdf86f6ad --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.test.tsx @@ -0,0 +1,69 @@ +/* + * 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 React from 'react'; + +import { shallow } from 'enzyme'; + +import { useLocalStorage } from './use_local_storage'; + +describe('useLocalStorage', () => { + const KEY = 'fields'; + + const TestComponent = () => { + const [fields, setFields] = useLocalStorage(KEY, { + options: ['foo', 'bar', 'baz'], + }); + return ( +
+
+ ); + }; + + beforeEach(() => { + global.localStorage.clear(); + jest.clearAllMocks(); + }); + + it('will read state from localStorage on init if values already exist', () => { + global.localStorage.setItem( + KEY, + JSON.stringify({ + options: ['some', 'old', 'values'], + }) + ); + const wrapper = shallow(); + expect(wrapper.text()).toBe('some, old, values'); + }); + + it('will ignore non-JSON values in localStorage', () => { + global.localStorage.setItem(KEY, 'blah blah blah'); + const wrapper = shallow(); + expect(wrapper.text()).toBe('foo, bar, baz'); + expect(global.localStorage.getItem(KEY)).toBe('{"options":["foo","bar","baz"]}'); + }); + + it('if will use provided default values if state does not already exist in localStorage', () => { + const wrapper = shallow(); + expect(wrapper.text()).toBe('foo, bar, baz'); + expect(global.localStorage.getItem(KEY)).toBe('{"options":["foo","bar","baz"]}'); + }); + + it('state can be updated with new values', () => { + const wrapper = shallow(); + wrapper.find('#change').simulate('click'); + expect(wrapper.text()).toBe('big, new, values'); + expect(global.localStorage.getItem(KEY)).toBe('{"options":["big","new","values"]}'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.ts b/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.ts new file mode 100644 index 00000000000000..11f5fdb5aa1d22 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/use_local_storage/use_local_storage.ts @@ -0,0 +1,56 @@ +/* + * 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 { useState } from 'react'; + +/** + * A hook that works like `useState`, but persisted to localStorage. + * + * example: + * + * const [foo, setFoo] = useLocalStorage("foo", "bar"); + * + * console.log(foo) // "bar" + * setFoo("baz") + * console.log(foo) // "baz" + * + * // Navigate away from page and return + * + * const [foo, setFoo] = useLocalStorage("foo", "bar"); + * console.log(foo) // "baz" + */ +export const useLocalStorage = (key: string, defaultValue: Value): [Value, Function] => { + const saveToStorage = (value: Value) => window.localStorage.setItem(key, JSON.stringify(value)); + const removeFromStorage = () => window.localStorage.removeItem(key); + const getFromStorage = (): Value | undefined => { + const storedItem = window.localStorage.getItem(key); + if (!storedItem) return; + + let parsedItem; + try { + return JSON.parse(storedItem) as Value; + } catch (e) { + removeFromStorage(); + } + + return parsedItem; + }; + + const storedItem = getFromStorage(); + if (!storedItem) { + saveToStorage(defaultValue); + } + const toStore = storedItem || defaultValue; + + const [item, setItem] = useState(toStore); + + const saveItem = (value: Value) => { + saveToStorage(value); + setItem(value); + }; + + return [item, saveItem]; +}; From b36273693a928a9d4ab013f851d9a7ccbe963c78 Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Fri, 15 Jan 2021 17:58:33 +0100 Subject: [PATCH 10/33] Functional tests - stabilize reporting API network policy test for cloud (#88456) This PR fixes a reporting API network policy test failure that occurred during cloud execution. --- .../reporting_and_security/network_policy.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/network_policy.ts b/x-pack/test/reporting_api_integration/reporting_and_security/network_policy.ts index a9a1b31072e7ee..a4b2c005aa908b 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/network_policy.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/network_policy.ts @@ -5,14 +5,13 @@ */ import expect from '@kbn/expect'; -import * as Rx from 'rxjs'; -import { filter, first, map, switchMap, timeout } from 'rxjs/operators'; import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const reportingAPI = getService('reportingAPI'); + const retry = getService('retry'); const supertest = getService('supertest'); const archive = 'reporting/canvas_disallowed_url'; @@ -35,17 +34,10 @@ export default function ({ getService }: FtrProviderContext) { ); // Retry the download URL until a "failed" response status is returned - const fails$: Rx.Observable = Rx.interval(100).pipe( - switchMap(() => supertest.get(downloadPath).then((response) => response.body)), - filter(({ statusCode }) => statusCode === 500), - map(({ message }) => message), - first(), - timeout(120000) - ); - - const reportFailed = await fails$.toPromise(); - - expect(reportFailed).to.match(/Reporting generation failed: Error:/); + await retry.tryForTime(120000, async () => { + const { body } = await supertest.get(downloadPath).expect(500); + expect(body.message).to.match(/Reporting generation failed: Error:/); + }); }); }); } From c0a833d8ea1957d260e33e5047ca85104a571a3a Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Fri, 15 Jan 2021 16:59:31 +0000 Subject: [PATCH 11/33] [ML] Adds a11y tests for ML plugin (#88323) * [ML] Adds a11y tests for ML plugin * [ML] Edits to a11y tests following review --- .../components/data_grid/data_grid.tsx | 2 +- .../multi_select_picker.tsx | 2 +- .../additional_section/additional_section.tsx | 2 +- x-pack/plugins/ml/readme.md | 81 ++-- x-pack/test/accessibility/apps/ml.ts | 351 ++++++++++++++++++ x-pack/test/accessibility/config.ts | 1 + .../ml/data_frame_analytics_creation.ts | 2 +- .../functional/services/transform/wizard.ts | 2 +- 8 files changed, 401 insertions(+), 42 deletions(-) create mode 100644 x-pack/test/accessibility/apps/ml.ts diff --git a/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx b/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx index f18610561ad2c3..c499d1153a238c 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx +++ b/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx @@ -309,7 +309,7 @@ export const DataGrid: FC = memo( })} > = ({ additionalExpanded, setAdditional { + const esArchiver = getService('esArchiver'); + + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + }); + + describe('for user with full ML access', function () { + before(async () => { + await ml.securityUI.loginAsMlPowerUser(); + await ml.api.cleanMlIndices(); + }); + + after(async () => { + await ml.securityUI.logout(); + }); + + describe('with no data loaded', function () { + it('overview page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToOverview(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection page', async () => { + await ml.navigation.navigateToAnomalyDetection(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics page', async () => { + await ml.navigation.navigateToDataFrameAnalytics(); + await a11y.testAppSnapshot(); + }); + + it('settings page', async () => { + await ml.navigation.navigateToSettings(); + await a11y.testAppSnapshot(); + }); + }); + + describe('with data loaded', function () { + const adJobId = 'fq_single_a11y'; + const dfaOutlierJobId = 'iph_outlier_a11y'; + const calendarId = 'calendar_a11y'; + const eventDescription = 'calendar_event_a11y'; + const filterId = 'filter_a11y'; + const filterItems = ['filter_item_a11y']; + const fqIndexPattern = 'ft_farequote'; + const ecIndexPattern = 'ft_module_sample_ecommerce'; + const ihpIndexPattern = 'ft_ihp_outlier'; + const ecExpectedTotalCount = '287'; + + const adJobAggAndFieldIdentifier = 'Mean(responsetime)'; + const adJobBucketSpan = '30m'; + const adSingleMetricJobId = `fq_single_a11y_${Date.now()}`; + + const dfaJobType = 'outlier_detection'; + const dfaJobId = `ihp_ally_${Date.now()}`; + + const uploadFilePath = path.join( + __dirname, + '..', + '..', + 'functional', + 'apps', + 'ml', + 'data_visualizer', + 'files_to_import', + 'artificial_server_log' + ); + + before(async () => { + await esArchiver.loadIfNeeded('ml/farequote'); + await esArchiver.loadIfNeeded('ml/ihp_outlier'); + await esArchiver.loadIfNeeded('ml/module_sample_ecommerce'); + await ml.testResources.createIndexPatternIfNeeded(fqIndexPattern, '@timestamp'); + await ml.testResources.createIndexPatternIfNeeded(ihpIndexPattern, '@timestamp'); + await ml.testResources.createIndexPatternIfNeeded(ecIndexPattern, 'order_date'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createAndRunAnomalyDetectionLookbackJob( + ml.commonConfig.getADFqMultiMetricJobConfig(adJobId), + ml.commonConfig.getADFqDatafeedConfig(adJobId) + ); + + await ml.api.createAndRunDFAJob( + ml.commonConfig.getDFAIhpOutlierDetectionJobConfig(dfaOutlierJobId) + ); + + await ml.api.createCalendar(calendarId, { + calendar_id: calendarId, + job_ids: [], + description: 'Test calendar', + }); + await ml.api.createCalendarEvents(calendarId, [ + { + description: eventDescription, + start_time: 1513641600000, + end_time: 1513728000000, + }, + ]); + + await ml.api.createFilter(filterId, { + description: 'Test filter list', + items: filterItems, + }); + }); + + after(async () => { + await ml.api.cleanMlIndices(); + await ml.api.deleteIndices(`user-${dfaOutlierJobId}`); + await ml.api.deleteCalendar(calendarId); + await ml.api.deleteFilter(filterId); + + await ml.testResources.deleteIndexPatternByTitle(fqIndexPattern); + await ml.testResources.deleteIndexPatternByTitle(ihpIndexPattern); + await ml.testResources.deleteIndexPatternByTitle(ecIndexPattern); + await esArchiver.unload('ml/farequote'); + await esArchiver.unload('ml/ihp_outlier'); + await esArchiver.unload('ml/module_sample_ecommerce'); + await ml.testResources.resetKibanaTimeZone(); + }); + + it('overview page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToOverview(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection jobs list page', async () => { + await ml.navigation.navigateToAnomalyDetection(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create job select index pattern page', async () => { + await ml.jobManagement.navigateToNewJobSourceSelection(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create job select type page', async () => { + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob(fqIndexPattern); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create single metric job time range step', async () => { + await ml.jobTypeSelection.selectSingleMetricJob(); + await ml.testExecution.logTestStep('job creation set the time range'); + await ml.jobWizardCommon.clickUseFullDataButton( + 'Feb 7, 2016 @ 00:00:00.000', + 'Feb 11, 2016 @ 23:59:54.000' + ); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create single metric job pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + await ml.testExecution.logTestStep('job creation selects field and aggregation'); + await ml.jobWizardCommon.selectAggAndField(adJobAggAndFieldIdentifier, true); + await ml.testExecution.logTestStep('job creation inputs the bucket span'); + await ml.jobWizardCommon.setBucketSpan(adJobBucketSpan); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create single metric job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + await ml.testExecution.logTestStep('job creation inputs the job id'); + await ml.jobWizardCommon.setJobId(adSingleMetricJobId); + await ml.testExecution.logTestStep('job creation opens the additional settings section'); + await ml.jobWizardCommon.ensureAdditionalSettingsSectionOpen(); + await ml.testExecution.logTestStep('job creation opens the advanced section'); + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create single metric job validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection create single metric job summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + await a11y.testAppSnapshot(); + }); + + it('anomaly detection Single Metric Viewer page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToAnomalyDetection(); + await ml.jobTable.clickOpenJobInSingleMetricViewerButton(adJobId); + await ml.commonUI.waitForMlLoadingIndicatorToDisappear(); + + await ml.testExecution.logTestStep('should input the airline entity value'); + await ml.singleMetricViewer.assertEntityInputExist('airline'); + await ml.singleMetricViewer.assertEntityInputSelection('airline', []); + await ml.singleMetricViewer.selectEntityValue('airline', 'AAL'); + + await a11y.testAppSnapshot(); + }); + + it.skip('anomaly detection Anomaly Explorer page', async () => { + // Skip test until the dots used in the Elastic chart legend no longer have duplicate ids + // see https://github.com/elastic/elastic-charts/issues/970 + await ml.singleMetricViewer.openAnomalyExplorer(); + await ml.commonUI.waitForMlLoadingIndicatorToDisappear(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics page', async () => { + await ml.navigation.navigateToDataFrameAnalytics(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics outlier job exploration page', async () => { + await ml.dataFrameAnalyticsTable.openResultsView(dfaOutlierJobId); + await ml.dataFrameAnalyticsResults.assertOutlierTablePanelExists(); + await ml.dataFrameAnalyticsResults.assertResultsTableExists(); + await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics create job select index pattern modal', async () => { + await ml.navigation.navigateToDataFrameAnalytics(); + await ml.dataFrameAnalytics.startAnalyticsCreation(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics create job configuration step', async () => { + await ml.testExecution.logTestStep( + 'job creation selects the source data and loads the DFA job wizard page' + ); + await ml.jobSourceSelection.selectSourceForAnalyticsJob(ihpIndexPattern); + await ml.dataFrameAnalyticsCreation.assertConfigurationStepActive(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics create job configuration step for outlier job', async () => { + await ml.testExecution.logTestStep('selects the outlier job type'); + await ml.dataFrameAnalyticsCreation.assertJobTypeSelectExists(); + await ml.dataFrameAnalyticsCreation.selectJobType(dfaJobType); + await ml.testExecution.logTestStep('displays the source data preview'); + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); + await ml.testExecution.logTestStep('enables the source data preview histogram charts'); + await ml.dataFrameAnalyticsCreation.enableSourceDataPreviewHistogramCharts(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics create job additional options step for outlier job', async () => { + await ml.dataFrameAnalyticsCreation.continueToAdditionalOptionsStep(); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics create job additional options step for outlier job', async () => { + await ml.dataFrameAnalyticsCreation.continueToDetailsStep(); + await ml.dataFrameAnalyticsCreation.setJobId(dfaJobId); + await a11y.testAppSnapshot(); + }); + + it('data frame analytics create job create step for outlier job', async () => { + await ml.dataFrameAnalyticsCreation.continueToCreateStep(); + await a11y.testAppSnapshot(); + }); + + it('settings page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToSettings(); + await a11y.testAppSnapshot(); + }); + + it('calendar management page', async () => { + await ml.settings.navigateToCalendarManagement(); + await a11y.testAppSnapshot(); + }); + + it('edit calendar page', async () => { + await ml.settingsCalendar.openCalendarEditForm(calendarId); + await a11y.testAppSnapshot(); + }); + + it('filter list management page', async () => { + await ml.navigation.navigateToSettings(); + await ml.settings.navigateToFilterListsManagement(); + await a11y.testAppSnapshot(); + }); + + it('edit filter list page', async () => { + await ml.settingsFilterList.openFilterListEditForm(filterId); + await a11y.testAppSnapshot(); + }); + + it('data visualizer selector page', async () => { + await ml.navigation.navigateToDataVisualizer(); + await a11y.testAppSnapshot(); + }); + + it('index data visualizer select index pattern page', async () => { + await ml.dataVisualizer.navigateToIndexPatternSelection(); + await a11y.testAppSnapshot(); + }); + + it('index data visualizer page for selected index', async () => { + await ml.jobSourceSelection.selectSourceForIndexBasedDataVisualizer(ecIndexPattern); + + await ml.testExecution.logTestStep('should display the time range step'); + await ml.dataVisualizerIndexBased.assertTimeRangeSelectorSectionExists(); + + await ml.testExecution.logTestStep('should load data for full time range'); + await ml.dataVisualizerIndexBased.clickUseFullDataButton(ecExpectedTotalCount); + await a11y.testAppSnapshot(); + }); + + it('file data visualizer select file page', async () => { + await ml.navigation.navigateToDataVisualizer(); + await ml.dataVisualizer.navigateToFileUpload(); + await a11y.testAppSnapshot(); + }); + + it('file data visualizer file details page', async () => { + await ml.testExecution.logTestStep( + 'should select a file and load visualizer result page' + ); + await ml.dataVisualizerFileBased.selectFile(uploadFilePath); + await a11y.testAppSnapshot(); + }); + + it('file data visualizer import data page', async () => { + await ml.dataVisualizerFileBased.navigateToFileImport(); + await a11y.testAppSnapshot(); + }); + }); + }); + }); +} diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index 40acd461ab6a18..070e2c3a61f2bd 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -27,6 +27,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('./apps/roles'), require.resolve('./apps/kibana_overview'), require.resolve('./apps/ingest_node_pipelines'), + require.resolve('./apps/ml'), ], pageObjects, diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts index 71d68b16c4037b..062d3140841123 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts @@ -125,7 +125,7 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( const actualCheckState = (await testSubjects.getAttribute( 'mlAnalyticsCreationDataGridHistogramButton', - 'aria-checked' + 'aria-pressed' )) === 'true'; expect(actualCheckState).to.eql( expectedCheckState, diff --git a/x-pack/test/functional/services/transform/wizard.ts b/x-pack/test/functional/services/transform/wizard.ts index 1bfe3284c90450..97ed179d3ee94c 100644 --- a/x-pack/test/functional/services/transform/wizard.ts +++ b/x-pack/test/functional/services/transform/wizard.ts @@ -175,7 +175,7 @@ export function TransformWizardProvider({ getService }: FtrProviderContext) { const actualCheckState = (await testSubjects.getAttribute( 'transformIndexPreviewHistogramButton', - 'aria-checked' + 'aria-pressed' )) === 'true'; expect(actualCheckState).to.eql( expectedCheckState, From d2de5d03835b5b257aada5f111a9bae14d59479f Mon Sep 17 00:00:00 2001 From: Constance Date: Fri, 15 Jan 2021 09:26:07 -0800 Subject: [PATCH 12/33] [Enterprise Search] Small test helper for expected async errors (#88422) * Add small helper to reduce boilerplate on async tests expected to throw - Also hopefully a bit more descriptive on what's happening * Update all test files using the previous try/catch do nothing blocks to use new helper --- .../__mocks__/expected_async_error.ts | 20 ++++++ .../public/applications/__mocks__/index.ts | 2 + .../analytics/analytics_logic.test.ts | 18 ++--- .../credentials/credentials_logic.test.ts | 35 ++++----- .../documents/document_detail_logic.test.ts | 21 ++---- .../components/engine/engine_logic.test.ts | 12 ++-- .../engine_overview_logic.test.ts | 12 ++-- .../log_retention/log_retention_logic.test.ts | 15 +--- .../indexing_status_logic.test.ts | 9 ++- .../add_source/add_source_logic.test.ts | 46 ++++-------- .../views/groups/group_logic.test.ts | 72 ++++++++----------- .../views/groups/groups_logic.test.ts | 37 ++++------ 12 files changed, 121 insertions(+), 178 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/__mocks__/expected_async_error.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/expected_async_error.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/expected_async_error.ts new file mode 100644 index 00000000000000..e8fc8ef0c15065 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/expected_async_error.ts @@ -0,0 +1,20 @@ +/* + * 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 expectedAsyncError = async (promise: Promise) => { + let expectedError: unknown; + + try { + await promise; + } catch (e) { + // Silence expected errors from being reported by tests + + // Pass back expected error to optionally assert on + expectedError = e; + } + + return expectedError; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts index 57f4a9f66b987c..85b2821cd40eeb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts @@ -23,3 +23,5 @@ export { mountWithIntl } from './mount_with_i18n.mock'; export { shallowWithIntl } from './shallow_with_i18n.mock'; export { rerender } from './enzyme_rerender.mock'; // Note: shallow_useeffect must be imported directly as a file + +export { expectedAsyncError } from './expected_async_error'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts index 62e241df013617..7be811b7b27db4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, expectedAsyncError } from '../../../__mocks__'; jest.mock('../../../shared/kibana', () => ({ KibanaLogic: { values: { history: { location: { search: '' } } } }, @@ -215,12 +215,8 @@ describe('AnalyticsLogic', () => { mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsUnavailable'); - try { - AnalyticsLogic.actions.loadAnalyticsData(); - await promise; - } catch { - // Do nothing - } + AnalyticsLogic.actions.loadAnalyticsData(); + await expectedAsyncError(promise); expect(flashAPIErrors).toHaveBeenCalledWith('error'); expect(AnalyticsLogic.actions.onAnalyticsUnavailable).toHaveBeenCalled(); @@ -293,12 +289,8 @@ describe('AnalyticsLogic', () => { mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsUnavailable'); - try { - AnalyticsLogic.actions.loadQueryData('some-query'); - await promise; - } catch { - // Do nothing - } + AnalyticsLogic.actions.loadQueryData('some-query'); + await expectedAsyncError(promise); expect(flashAPIErrors).toHaveBeenCalledWith('error'); expect(AnalyticsLogic.actions.onAnalyticsUnavailable).toHaveBeenCalled(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts index 48be2b0ae8dfd7..b33d1eba572ec2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; -import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ HttpLogic: { values: mockHttpValues }, })); @@ -1093,11 +1092,9 @@ describe('CredentialsLogic', () => { http.get.mockReturnValue(promise); CredentialsLogic.actions.fetchCredentials(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); }); }); @@ -1124,11 +1121,9 @@ describe('CredentialsLogic', () => { http.get.mockReturnValue(promise); CredentialsLogic.actions.fetchDetails(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); }); }); @@ -1154,11 +1149,9 @@ describe('CredentialsLogic', () => { http.delete.mockReturnValue(promise); CredentialsLogic.actions.deleteApiKey(tokenName); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); }); }); @@ -1218,11 +1211,9 @@ describe('CredentialsLogic', () => { http.post.mockReturnValue(promise); CredentialsLogic.actions.onApiTokenChange(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); }); describe('token type data', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts index fe735f70247c62..015a9abd5405cd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; -import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ HttpLogic: { values: mockHttpValues }, })); @@ -81,12 +80,9 @@ describe('DocumentDetailLogic', () => { const promise = Promise.reject('An error occurred'); http.get.mockReturnValue(promise); - try { - DocumentDetailLogic.actions.getDocumentDetails('1'); - await promise; - } catch { - // Do nothing - } + DocumentDetailLogic.actions.getDocumentDetails('1'); + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('An error occurred', { isQueued: true }); expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith('/engines/engine1/documents'); }); @@ -134,12 +130,9 @@ describe('DocumentDetailLogic', () => { promise = Promise.reject('An error occured'); http.delete.mockReturnValue(promise); - try { - DocumentDetailLogic.actions.deleteDocument('1'); - await promise; - } catch { - // Do nothing - } + DocumentDetailLogic.actions.deleteDocument('1'); + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts index 094260b6df0958..8d855bebdb20f7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; -import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ HttpLogic: { values: mockHttpValues }, })); @@ -193,12 +192,9 @@ describe('EngineLogic', () => { const promise = Promise.reject('An error occured'); http.get.mockReturnValue(promise); - try { - EngineLogic.actions.initializeEngine(); - await promise; - } catch { - // Do nothing - } + EngineLogic.actions.initializeEngine(); + await expectedAsyncError(promise); + expect(EngineLogic.actions.setEngineNotFound).toHaveBeenCalledWith(true); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts index 61319245bba032..46d5a7b6608a52 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; -import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ HttpLogic: { values: mockHttpValues }, })); @@ -106,12 +105,9 @@ describe('EngineOverviewLogic', () => { const promise = Promise.reject('An error occurred'); http.get.mockReturnValue(promise); - try { - EngineOverviewLogic.actions.pollForOverviewMetrics(); - await promise; - } catch { - // Do nothing - } + EngineOverviewLogic.actions.pollForOverviewMetrics(); + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('An error occurred'); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts index 004e5e9752d97b..b1920b6ddea8a7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; -import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ HttpLogic: { values: mockHttpValues }, })); @@ -232,12 +231,8 @@ describe('LogRetentionLogic', () => { http.put.mockReturnValue(promise); LogRetentionLogic.actions.saveLogRetention(LogRetentionOptions.Analytics, true); + await expectedAsyncError(promise); - try { - await promise; - } catch { - // Do nothing - } expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); }); @@ -305,12 +300,8 @@ describe('LogRetentionLogic', () => { http.get.mockReturnValue(promise); LogRetentionLogic.actions.fetchLogRetention(); + await expectedAsyncError(promise); - try { - await promise; - } catch { - // Do nothing - } expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts index 9fa5fe0f84babf..abddb96275c6f2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts @@ -6,6 +6,8 @@ import { resetContext } from 'kea'; +import { expectedAsyncError } from '../../__mocks__'; + jest.mock('../http', () => ({ HttpLogic: { values: { http: { get: jest.fn() } }, @@ -82,11 +84,8 @@ describe('IndexingStatusLogic', () => { IndexingStatusLogic.actions.fetchIndexingStatus({ statusPath, onComplete }); jest.advanceTimersByTime(TIMEOUT); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts index 084c3d1fb9c4f1..97f08e294be274 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts @@ -5,7 +5,9 @@ */ import { resetContext } from 'kea'; -import { mockHttpValues } from '../../../../../__mocks__'; + +import { mockHttpValues, expectedAsyncError } from '../../../../../__mocks__'; + jest.mock('../../../../../shared/http', () => ({ HttpLogic: { values: { http: mockHttpValues.http }, @@ -296,11 +298,8 @@ describe('AddSourceLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); AddSourceLogic.actions.getSourceConfigData('github'); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -345,11 +344,8 @@ describe('AddSourceLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); AddSourceLogic.actions.getSourceConnectData('github', successCallback); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -377,11 +373,8 @@ describe('AddSourceLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); AddSourceLogic.actions.getSourceReConnectData('github'); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -409,11 +402,8 @@ describe('AddSourceLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); AddSourceLogic.actions.getPreContentSourceConfigData('123'); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -485,11 +475,8 @@ describe('AddSourceLogic', () => { (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); AddSourceLogic.actions.saveSourceConfig(true); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -550,11 +537,8 @@ describe('AddSourceLogic', () => { (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); AddSourceLogic.actions.createContentSource(serviceType, successCallback, errorCallback); - try { - await promise; - } catch { - // Do nothing - } + await expectedAsyncError(promise); + expect(errorCallback).toHaveBeenCalled(); expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts index b4724c8ed3f0ec..4de524fd9ac8ed 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts @@ -6,6 +6,8 @@ import { resetContext } from 'kea'; +import { expectedAsyncError } from '../../../__mocks__'; + jest.mock('../../../shared/http', () => ({ HttpLogic: { values: { http: { get: jest.fn(), post: jest.fn(), put: jest.fn(), delete: jest.fn() } }, @@ -253,16 +255,13 @@ describe('GroupLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); GroupLogic.actions.initializeGroup(sourceIds[0]); + await expectedAsyncError(promise); - try { - await promise; - } catch { - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); - expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith({ - type: 'error', - message: 'Unable to find group with ID: "123".', - }); - } + expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); + expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith({ + type: 'error', + message: 'Unable to find group with ID: "123".', + }); }); it('handles non-404 error', async () => { @@ -270,16 +269,13 @@ describe('GroupLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); GroupLogic.actions.initializeGroup(sourceIds[0]); + await expectedAsyncError(promise); - try { - await promise; - } catch { - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); - expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith({ - type: 'error', - message: 'this is an error', - }); - } + expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); + expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith({ + type: 'error', + message: 'this is an error', + }); }); }); @@ -308,11 +304,9 @@ describe('GroupLogic', () => { (HttpLogic.values.http.delete as jest.Mock).mockReturnValue(promise); GroupLogic.actions.deleteGroup(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -343,11 +337,9 @@ describe('GroupLogic', () => { (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); GroupLogic.actions.updateGroupName(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -381,11 +373,9 @@ describe('GroupLogic', () => { (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); GroupLogic.actions.saveGroupSources(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -418,11 +408,9 @@ describe('GroupLogic', () => { (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); GroupLogic.actions.saveGroupUsers(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -463,11 +451,9 @@ describe('GroupLogic', () => { (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); GroupLogic.actions.saveGroupSourcePrioritization(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts index 18206573a3978e..d046863fd388ca 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts @@ -6,6 +6,8 @@ import { resetContext } from 'kea'; +import { expectedAsyncError } from '../../../__mocks__'; + jest.mock('../../../shared/http', () => ({ HttpLogic: { values: { http: { get: jest.fn(), post: jest.fn() } }, @@ -240,11 +242,9 @@ describe('GroupsLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); GroupsLogic.actions.initializeGroups(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -304,13 +304,10 @@ describe('GroupsLogic', () => { (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); GroupsLogic.actions.getSearchResults(); - try { - await promise; - } catch { - // Account for `breakpoint` that debounces filter value. - await delay(); - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + await delay(); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -333,11 +330,9 @@ describe('GroupsLogic', () => { (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); GroupsLogic.actions.fetchGroupUsers('123'); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); @@ -363,11 +358,9 @@ describe('GroupsLogic', () => { (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); GroupsLogic.actions.saveNewGroup(); - try { - await promise; - } catch { - expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); - } + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith('this is an error'); }); }); From 51ba94d3e5616d86a21128088ba9cbfa20e5162d Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Fri, 15 Jan 2021 11:52:29 -0600 Subject: [PATCH 13/33] [dev] Replace sass-lint with stylelint (#86177) Co-authored-by: Tyler Smalley Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Dave Snider --- .../checks/{sasslint.sh => stylelint.sh} | 4 +- .prettierignore | 2 + .sass-lint.yml | 87 -- .stylelintignore | 3 + .stylelintrc | 84 ++ .teamcity/src/builds/Lint.kt | 6 +- package.json | 7 +- .../mock_repo/plugins/bar/public/index.scss | 1 + .../bar/public/legacy/_other_styles.scss | 1 + .../plugins/bar/public/legacy/styles.scss | 2 +- .../basic_optimization.test.ts.snap | 2 +- scripts/{sasslint.js => stylelint.js} | 2 +- src/core/public/core_app/styles/_mixins.scss | 6 +- src/dev/run_precommit_hook.js | 4 +- src/dev/{run_sasslint.js => run_stylelint.js} | 16 +- src/dev/{sasslint => stylelint}/index.js | 0 src/dev/{sasslint => stylelint}/lint_files.js | 41 +- .../pick_files_to_lint.js | 10 +- .../management_app/_advanced_settings.scss | 8 +- .../static/components/legend_toggle.scss | 1 - .../embeddable/grid/_dashboard_grid.scss | 4 +- .../embeddable/panel/_dashboard_panel.scss | 2 +- .../top_nav/panel_toolbar/panel_toolbar.scss | 2 +- .../ui/filter_bar/_global_filter_group.scss | 2 +- .../ui/filter_bar/_global_filter_item.scss | 2 +- .../_shard_failure_modal.scss | 48 +- .../angular/doc_table/_doc_table.scss | 7 +- .../components/table_row/_details.scss | 1 - .../doc_table/components/table_row/_open.scss | 2 +- .../application/components/discover.scss | 2 +- .../components/doc_viewer/doc_viewer.scss | 2 +- .../public/lib/panel/_embeddable_panel.scss | 4 +- .../ace/_ui_ace_keyboard_mode.scss | 2 +- .../components/_solutions_section.scss | 7 +- .../public/font_awesome/font_awesome.scss | 16 +- .../public/paginate/_paginate.scss | 3 +- .../public/markdown/_markdown.scss | 28 +- .../public/map/_leaflet_overrides.scss | 13 +- src/plugins/navigation/public/index.scss | 2 +- src/plugins/timelion/public/_base.scss | 1 - .../timelion/public/directives/_form.scss | 3 +- .../timelion/public/directives/_index.scss | 1 - .../directives/_saved_object_finder.scss | 1 - .../public/directives/cells/_cells.scss | 1 - .../vis_default_editor/public/_default.scss | 2 +- .../vis_default_editor/public/_sidebar.scss | 6 +- .../vis_default_editor/public/index.scss | 2 +- .../public/markdown_vis.scss | 2 +- .../public/legacy/_table_vis.scss | 2 +- .../public/legacy/agg_table/_agg_table.scss | 2 +- .../public/application/_tvb_editor.scss | 1 - .../components/vis_types/_vis_types.scss | 4 +- .../vis_types/markdown/_markdown.scss | 2 - .../visualizations/views/_top_n.scss | 1 - .../public/components/vega_vis.scss | 2 +- .../public/vislib/lib/_index.scss | 1 - .../public/vislib/lib/layout/_layout.scss | 232 +++-- .../public/components/_visualization.scss | 8 +- .../public/embeddable/_embeddables.scss | 19 +- .../components/visualize_editor.scss | 4 +- .../components/visualize_listing.scss | 2 +- test/scripts/jenkins_unit.sh | 2 +- test/scripts/lint/sasslint.sh | 6 - test/scripts/lint/stylelint.sh | 6 + vars/tasks.groovy | 2 +- .../components/element_card/element_card.scss | 2 +- .../components/fullscreen/fullscreen.scss | 3 +- .../public/components/toolbar/tray/tray.scss | 1 - .../public/components/workpad/workpad.scss | 2 +- .../workpad_dropzone/workpad_dropzone.scss | 2 +- x-pack/plugins/canvas/public/style/main.scss | 1 - .../components/footer/footer.module.scss | 2 +- .../components/footer/scrubber.module.scss | 2 +- .../components/result/result_field.scss | 2 +- .../components/product_card/product_card.scss | 2 +- .../applications/shared/layout/layout.scss | 4 +- .../applications/shared/layout/side_nav.scss | 2 +- .../shared/truncate/truncated_content.scss | 2 +- .../shared/license_badge/license_badge.scss | 6 +- .../shared/user_icon/user_icon.scss | 10 +- .../display_settings/display_settings.scss | 16 +- .../workplace_search/views/groups/groups.scss | 2 +- .../views/overview/recent_activity.scss | 4 +- x-pack/plugins/graph/public/_main.scss | 2 +- .../public/angular/templates/_graph.scss | 13 +- .../public/angular/templates/_sidebar.scss | 4 +- .../field_manager/_field_editor.scss | 2 +- .../_graph_visualization.scss | 8 +- .../components/legacy_icon/_legacy_icon.scss | 2 +- .../venn_diagram/_venn_diagram.scss | 4 +- .../component_templates.scss | 1 - .../component_templates_list_item.scss | 4 +- .../component_templates_selector.scss | 8 +- .../components/mappings_editor/_index.scss | 88 +- .../fields/_field_list_item.scss | 2 +- .../index_management/public/index.scss | 2 +- x-pack/plugins/infra/public/index.scss | 1 - .../processors_tree/processors_tree.scss | 2 +- x-pack/plugins/lens/public/_mixins.scss | 8 +- .../workspace_panel/chart_switch.scss | 2 +- .../indexpattern_datasource/datapanel.scss | 2 - .../vector/components/color/_color_stops.scss | 1 - .../components/legend/_vector_legend.scss | 2 +- .../widget_overlay/_mixins.scss | 14 +- .../layer_toc/toc_entry/_toc_entry.scss | 1 - .../ml/public/application/_variables.scss | 10 +- .../anomalies_table/_anomalies_table.scss | 9 +- .../chart_tooltip/_chart_tooltip.scss | 2 +- .../components/controls/_controls.scss | 2 +- .../components/data_grid/column_chart.scss | 2 +- .../components/data_grid/data_grid.scss | 1 - .../components/entity_cell/entity_cell.scss | 2 +- .../influencers_list/_influencers_list.scss | 2 +- .../job_selector/_job_selector.scss | 22 +- .../components/rule_editor/_rule_editor.scss | 6 +- .../_classification_exploration.scss | 2 +- .../expanded_row_messages_pane.scss | 1 - .../_experimental_badge.scss | 2 +- .../fields_stats/_field_stats_card.scss | 6 +- .../fields_stats/_fields_stats.scss | 2 - .../results_view/_results_view.scss | 4 +- .../field_data_card/_field_data_card.scss | 2 +- .../datavisualizer/stats_datagrid/_index.scss | 13 +- .../field_data_expanded_row/_index.scss | 2 +- .../_number_content.scss | 1 - .../application/explorer/_explorer.scss | 2 +- .../explorer_charts/_explorer_chart.scss | 32 +- .../_explorer_charts_container.scss | 4 +- .../edit_job_flyout/_edit_job_flyout.scss | 2 +- .../components/job_details/_job_details.scss | 6 +- .../job_filter_bar/_job_filter_bar.scss | 2 +- .../components/job_group/_job_group.scss | 2 +- .../components/jobs_list/_jobs_list.scss | 12 +- .../multi_job_actions/_multi_job_actions.scss | 7 +- .../group_list/_group_list.scss | 14 +- .../new_group_input/_new_group_input.scss | 2 +- .../_time_range_selector.scss | 9 +- .../components/jobs_list_page/_buttons.scss | 4 +- .../jobs_list_page/_expanded_row.scss | 6 +- .../components/jobs_list_page/_stats_bar.scss | 1 - .../settings/calendars/edit/_edit.scss | 2 +- .../settings/filter_lists/_filter_lists.scss | 1 - .../settings/filter_lists/edit/_edit.scss | 2 +- .../_timeseriesexplorer.scss | 47 +- .../_timeseriesexplorer_annotations.scss | 6 +- .../components/app/news_feed/index.scss | 2 +- .../public/application/_hacks.scss | 2 +- .../public/application/_app.scss | 23 +- .../application/sections/home/_home.scss | 12 +- .../components/wizard/_wizard.scss | 2 +- yarn.lock | 857 +++++++++--------- 151 files changed, 1068 insertions(+), 1075 deletions(-) rename .ci/teamcity/checks/{sasslint.sh => stylelint.sh} (50%) create mode 100644 .prettierignore delete mode 100644 .sass-lint.yml create mode 100644 .stylelintignore create mode 100644 .stylelintrc rename scripts/{sasslint.js => stylelint.js} (95%) rename src/dev/{run_sasslint.js => run_stylelint.js} (66%) rename src/dev/{sasslint => stylelint}/index.js (100%) rename src/dev/{sasslint => stylelint}/lint_files.js (59%) rename src/dev/{sasslint => stylelint}/pick_files_to_lint.js (75%) delete mode 100755 test/scripts/lint/sasslint.sh create mode 100755 test/scripts/lint/stylelint.sh diff --git a/.ci/teamcity/checks/sasslint.sh b/.ci/teamcity/checks/stylelint.sh similarity index 50% rename from .ci/teamcity/checks/sasslint.sh rename to .ci/teamcity/checks/stylelint.sh index 45b90f6a8034e9..f4e1da50273466 100755 --- a/.ci/teamcity/checks/sasslint.sh +++ b/.ci/teamcity/checks/stylelint.sh @@ -4,5 +4,5 @@ set -euo pipefail source "$(dirname "${0}")/../util.sh" -checks-reporter-with-killswitch "Lint: sasslint" \ - node scripts/sasslint +checks-reporter-with-killswitch "Lint: stylelint" \ + node scripts/stylelint diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000000000..3802245b91e812 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +# use stylelint +*.scss \ No newline at end of file diff --git a/.sass-lint.yml b/.sass-lint.yml deleted file mode 100644 index 85599750b0cb8d..00000000000000 --- a/.sass-lint.yml +++ /dev/null @@ -1,87 +0,0 @@ -files: - include: - - 'src/legacy/core_plugins/metrics/**/*.s+(a|c)ss' - - 'src/plugins/index_pattern_management/**/*.s+(a|c)ss' - - 'src/plugins/timelion/**/*.s+(a|c)ss' - - 'src/plugins/vis_type_vislib/**/*.s+(a|c)ss' - - 'src/plugins/vis_type_vega/**/*.s+(a|c)ss' - - 'src/plugins/vis_type_xy/**/*.s+(a|c)ss' - - 'src/plugins/visualizations/public/wizard/**/*.s+(a|c)ss' - - 'x-pack/plugins/canvas/**/*.s+(a|c)ss' - - 'x-pack/plugins/triggers_actions_ui/**/*.s+(a|c)ss' - - 'x-pack/plugins/lens/**/*.s+(a|c)ss' - - 'x-pack/plugins/cross_cluster_replication/**/*.s+(a|c)ss' - - 'x-pack/legacy/plugins/maps/**/*.s+(a|c)ss' - - 'x-pack/plugins/maps/**/*.s+(a|c)ss' - - 'x-pack/plugins/spaces/**/*.s+(a|c)ss' - - 'x-pack/plugins/security/**/*.s+(a|c)ss' - - 'x-pack/plugins/monitoring/**/*.s+(a|c)ss' - ignore: - - 'x-pack/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss' -rules: - quotes: - - 2 - - style: 'single' - # } else { style on one line, like our JS - brace-style: - - 2 - - style: '1tbs' - variable-name-format: - - 2 - - convention: 'camelcase' - # Needs regex, right now we ignore - class-name-format: 0 - # Order how you please - property-sort-order: 0 - hex-notation: - - 2 - - style: 'uppercase' - mixin-name-format: - - 2 - - allow-leading-underscore: false - convention: 'camelcase' - # Use none instead of 0 for no border - border-zero: - - 2 - - convention: 'none' - force-element-nesting: 0 - # something { not something{ - space-before-brace: - - 2 - force-pseudo-nesting: 0 - # 2 spaces for indentation - indentation: 2 - function-name-format: - - 2 - - allow-leading-underscore: false - convention: 'camelcase' - # This removes the need for ::hover - pseudo-element: 0 - # ($var / 2) rather than ($var/2) - space-around-operator: 2 - # We minify css, so this doesn't apply - no-css-comments: 0 - # We use _ (underscores) for import path that don't directly compile - clean-import-paths: 0 - # Allows input[type=search] - force-attribute-nesting: 0 - no-qualifying-elements: - - 2 - - # Allows input[type=search] - allow-element-with-attribute: 1 - # Files can end without a newline - final-newline: 0 - # We use some rare duplicate property values for browser variance - no-duplicate-properties: - - 2 - - exclude: - - 'font-size' - - 'word-break' - # Put a line-break between sections of CSS, but allow quicky one-liners for legibility - empty-line-between-blocks: - - 2 - - allow-single-line-rulesets: 1 - # Warns are nice for deprecations and development - no-warn: 0 - # Transition all is useful in certain situations and there's no recent info to suggest slowdown - no-transition-all: 0 diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 00000000000000..a48b3adfa36321 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,3 @@ +x-pack/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss +build +target diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 00000000000000..29c1f4b552b48a --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,84 @@ +plugins: + - stylelint-scss +rules: + color-no-invalid-hex: true + function-calc-no-invalid: true + string-no-newline: true + unit-no-unknown: true + property-no-unknown: + - true + # Used in css modules + - ignoreProperties: + - composes + block-no-empty: true + selector-pseudo-class-no-unknown: + - true + # Used in css modules + - ignorePseudoClasses: + - local + - global + selector-pseudo-element-no-unknown: true + media-feature-name-no-unknown: true + at-rule-no-unknown: + - true + # Sass related mixins + - ignoreAtRules: + - include + - mixin + - if + - else + - each + - extend + - function + - return + - for + comment-no-empty: true + no-duplicate-at-import-rules: true + no-duplicate-selectors: true + no-extra-semicolons: true + alpha-value-notation: number + color-named: never + length-zero-no-unit: true + no-eol-whitespace: true + max-empty-lines: 1 + # no-descending-specificity: true + number-leading-zero: never + color-hex-case: upper + string-quotes: single + indentation: 2 + declaration-block-no-duplicate-properties: + - true + # We use some rare duplicate property values for browser variance + - ignoreProperties: + - font-size + - word-break + - composes + - filter + - background + - width + - transition + - display + + # ($var / 2) rather than ($var/2) + function-calc-no-unspaced-operator: true + + # something { not something{ + block-opening-brace-space-before: always + + # TODO: # Allows input[type=search] + selector-no-qualifying-type: + - true + - ignore: + - attribute + + # Put a line-break between sections of CSS, but allow quicky one-liners for legibility + block-closing-brace-newline-after: + - always-multi-line + - ignoreAtRules: + - if + - else + + # camelCase mixin, function, and variable names + scss/at-mixin-pattern: "^[a-z][a-zA-Z0-9]+$" + scss/at-function-pattern: "^[a-z][a-zA-Z0-9]+$" + scss/dollar-variable-pattern: "^[a-z][a-zA-Z0-9]+$" diff --git a/.teamcity/src/builds/Lint.kt b/.teamcity/src/builds/Lint.kt index d02f1c9038acad..4a4bb8651a7c0b 100644 --- a/.teamcity/src/builds/Lint.kt +++ b/.teamcity/src/builds/Lint.kt @@ -6,18 +6,18 @@ import kibanaAgent object Lint : BuildType({ name = "Lint" - description = "Executes Linting, such as eslint and sasslint" + description = "Executes Linting, such as eslint and stylelint" kibanaAgent(2) steps { script { - name = "Sasslint" + name = "Stylelint" scriptContent = """ #!/bin/bash - ./.ci/teamcity/checks/sasslint.sh + ./.ci/teamcity/checks/stylelint.sh """.trimIndent() } diff --git a/package.json b/package.json index 07984e5a237b0a..7effbd0a5550a3 100644 --- a/package.json +++ b/package.json @@ -51,9 +51,9 @@ "start": "node scripts/kibana --dev", "debug": "node --nolazy --inspect scripts/kibana --dev", "debug-break": "node --nolazy --inspect-brk scripts/kibana --dev", - "lint": "yarn run lint:es && yarn run lint:sass", + "lint": "yarn run lint:es && yarn run lint:style", "lint:es": "node scripts/eslint", - "lint:sass": "node scripts/sasslint", + "lint:style": "node scripts/stylelint", "makelogs": "node scripts/makelogs", "kbn:watch": "node scripts/kibana --dev --logging.json=false", "build:types": "rm -rf ./target/types && tsc --p tsconfig.types.json", @@ -793,7 +793,6 @@ "resize-observer-polyfill": "^1.5.0", "resolve": "^1.7.1", "rxjs-marbles": "^5.0.6", - "sass-lint": "^1.12.1", "sass-loader": "^8.0.2", "sass-resources-loader": "^2.0.1", "selenium-webdriver": "^4.0.0-alpha.7", @@ -805,6 +804,8 @@ "string-replace-loader": "^2.2.0", "strong-log-transformer": "^2.1.0", "style-loader": "^1.1.3", + "stylelint": "13.8.0", + "stylelint-scss": "^3.18.0", "superagent": "^3.8.2", "supertest": "^3.1.0", "supertest-as-promised": "^4.0.2", diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/index.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/index.scss index 563d20e99ce82c..9603185daf4109 100644 --- a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/index.scss +++ b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/index.scss @@ -1,3 +1,4 @@ body { + /* stylelint-disable-next-line color-named */ color: green; } diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/_other_styles.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/_other_styles.scss index 2c1b9562b9567e..fae6b1e6276617 100644 --- a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/_other_styles.scss +++ b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/_other_styles.scss @@ -1,3 +1,4 @@ p { + /* stylelint-disable-next-line color-named */ background-color: rebeccapurple; } diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/styles.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/styles.scss index 7fa8383ec239c3..89c5d0d7d98c1f 100644 --- a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/styles.scss +++ b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/bar/public/legacy/styles.scss @@ -1,4 +1,4 @@ -@import "./other_styles.scss"; +@import './other_styles.scss'; body { width: $globalStyleConstant; diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index ddb19c8cdc3d75..4681057ad09980 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -99,7 +99,7 @@ OptimizerConfig { } `; -exports[`prepares assets for distribution: bar bundle 1`] = `"(function(modules){var installedModules={};function __webpack_require__(moduleId){if(installedModules[moduleId]){return installedModules[moduleId].exports}var module=installedModules[moduleId]={i:moduleId,l:false,exports:{}};modules[moduleId].call(module.exports,module,module.exports,__webpack_require__);module.l=true;return module.exports}__webpack_require__.m=modules;__webpack_require__.c=installedModules;__webpack_require__.d=function(exports,name,getter){if(!__webpack_require__.o(exports,name)){Object.defineProperty(exports,name,{enumerable:true,get:getter})}};__webpack_require__.r=function(exports){if(typeof Symbol!==\\"undefined\\"&&Symbol.toStringTag){Object.defineProperty(exports,Symbol.toStringTag,{value:\\"Module\\"})}Object.defineProperty(exports,\\"__esModule\\",{value:true})};__webpack_require__.t=function(value,mode){if(mode&1)value=__webpack_require__(value);if(mode&8)return value;if(mode&4&&typeof value===\\"object\\"&&value&&value.__esModule)return value;var ns=Object.create(null);__webpack_require__.r(ns);Object.defineProperty(ns,\\"default\\",{enumerable:true,value:value});if(mode&2&&typeof value!=\\"string\\")for(var key in value)__webpack_require__.d(ns,key,function(key){return value[key]}.bind(null,key));return ns};__webpack_require__.n=function(module){var getter=module&&module.__esModule?function getDefault(){return module[\\"default\\"]}:function getModuleExports(){return module};__webpack_require__.d(getter,\\"a\\",getter);return getter};__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)};__webpack_require__.p=\\"\\";return __webpack_require__(__webpack_require__.s=3)})([function(module,exports,__webpack_require__){\\"use strict\\";var isOldIE=function isOldIE(){var memo;return function memorize(){if(typeof memo===\\"undefined\\"){memo=Boolean(window&&document&&document.all&&!window.atob)}return memo}}();var getTarget=function getTarget(){var memo={};return function memorize(target){if(typeof memo[target]===\\"undefined\\"){var styleTarget=document.querySelector(target);if(window.HTMLIFrameElement&&styleTarget instanceof window.HTMLIFrameElement){try{styleTarget=styleTarget.contentDocument.head}catch(e){styleTarget=null}}memo[target]=styleTarget}return memo[target]}}();var stylesInDom=[];function getIndexByIdentifier(identifier){var result=-1;for(var i=0;i 0) { try { diff --git a/src/dev/run_sasslint.js b/src/dev/run_stylelint.js similarity index 66% rename from src/dev/run_sasslint.js rename to src/dev/run_stylelint.js index 8ee5c4d7a956db..060b322c12a227 100644 --- a/src/dev/run_sasslint.js +++ b/src/dev/run_stylelint.js @@ -18,11 +18,19 @@ */ import { resolve } from 'path'; +import { buildCLI } from 'stylelint/lib/cli'; -process.argv.push('--no-exit'); // don't exit after encountering a rule error -process.argv.push('--verbose'); // print results +const options = buildCLI(process.argv.slice(2)); + +const stylelintConfigPath = resolve(__dirname, '..', '..', '.stylelintrc'); +const stylelintIgnorePath = resolve(__dirname, '..', '..', '.stylelintignore'); + +if (!options.input.length) { + process.argv.push('**/*.s+(a|c)ss'); +} process.argv.push('--max-warnings', '0'); // return nonzero exit code on any warnings -process.argv.push('--config', resolve(__dirname, '..', '..', '.sass-lint.yml')); // configuration file +process.argv.push('--config', stylelintConfigPath); // configuration file +process.argv.push('--ignore-path', stylelintIgnorePath); // ignore file // common-js is required so that logic before this executes before loading sass-lint -require('sass-lint/bin/sass-lint'); +require('stylelint/bin/stylelint'); diff --git a/src/dev/sasslint/index.js b/src/dev/stylelint/index.js similarity index 100% rename from src/dev/sasslint/index.js rename to src/dev/stylelint/index.js diff --git a/src/dev/sasslint/lint_files.js b/src/dev/stylelint/lint_files.js similarity index 59% rename from src/dev/sasslint/lint_files.js rename to src/dev/stylelint/lint_files.js index 3a560b4a6ea1a6..415cd8650c8f82 100644 --- a/src/dev/sasslint/lint_files.js +++ b/src/dev/stylelint/lint_files.js @@ -17,10 +17,16 @@ * under the License. */ -import sassLint from 'sass-lint'; +import stylelint from 'stylelint'; import path from 'path'; +import { safeLoad } from 'js-yaml'; +import fs from 'fs'; import { createFailError } from '@kbn/dev-utils'; +// load the include globs from .stylelintrc and convert them to regular expressions for filtering files +const stylelintPath = path.resolve(__dirname, '..', '..', '..', '.stylelintrc'); +const styleLintConfig = safeLoad(fs.readFileSync(stylelintPath)); + /** * Lints a list of files with eslint. eslint reports are written to the log * and a FailError is thrown when linting errors occur. @@ -29,28 +35,21 @@ import { createFailError } from '@kbn/dev-utils'; * @param {Array} files * @return {undefined} */ -export function lintFiles(log, files) { +export async function lintFiles(log, files) { const paths = files.map((file) => file.getRelativePath()); - const report = sassLint.lintFiles( - paths.join(', '), - {}, - path.resolve(__dirname, '..', '..', '..', '.sass-lint.yml') - ); - - const failTypes = Object.keys( - report.reduce((failTypes, reportEntry) => { - if (reportEntry.warningCount > 0) failTypes.warning = true; - if (reportEntry.errorCount > 0) failTypes.errors = true; - return failTypes; - }, {}) - ); + const options = { + files: paths, + config: styleLintConfig, + formatter: 'string', + ignorePath: path.resolve(__dirname, '..', '..', '..', '.stylelintignore'), + }; - if (!failTypes.length) { - log.success('[sasslint] %d files linted successfully', files.length); - return; + const report = await stylelint.lint(options); + if (report.errored) { + log.error(report.output); + throw createFailError('[stylelint] errors'); + } else { + log.success('[stylelint] %d files linted successfully', files.length); } - - log.error(sassLint.format(report)); - throw createFailError(`[sasslint] ${failTypes.join(' & ')}`); } diff --git a/src/dev/sasslint/pick_files_to_lint.js b/src/dev/stylelint/pick_files_to_lint.js similarity index 75% rename from src/dev/sasslint/pick_files_to_lint.js rename to src/dev/stylelint/pick_files_to_lint.js index 57c38d0069e065..77274763fa600b 100644 --- a/src/dev/sasslint/pick_files_to_lint.js +++ b/src/dev/stylelint/pick_files_to_lint.js @@ -17,17 +17,9 @@ * under the License. */ -import fs from 'fs'; -import { safeLoad } from 'js-yaml'; import { makeRe } from 'minimatch'; -import path from 'path'; -// load the include globs from .sass-lint.yml and convert them to regular expressions for filtering files -const sassLintPath = path.resolve(__dirname, '..', '..', '..', '.sass-lint.yml'); -const sassLintConfig = safeLoad(fs.readFileSync(sassLintPath)); -const { - files: { include: includeGlobs }, -} = sassLintConfig; +const includeGlobs = ['**/*.s+(a|c)ss']; const includeRegex = includeGlobs.map((glob) => makeRe(glob)); function matchesInclude(file) { diff --git a/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss b/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss index fd26677e938942..76c181a9ec256f 100644 --- a/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss +++ b/src/plugins/advanced_settings/public/management_app/_advanced_settings.scss @@ -17,7 +17,7 @@ * under the License. */ - .mgtAdvancedSettings__field { +.mgtAdvancedSettings__field { + * { margin-top: $euiSize; } @@ -29,11 +29,11 @@ &--unsaved .mgtAdvancedSettings__fieldTitle { // Simulates a left side border without shifting content - box-shadow: -$euiSizeXS 0px $euiColorWarning; + box-shadow: -$euiSizeXS 0 $euiColorWarning; } &--invalid .mgtAdvancedSettings__fieldTitle { // Simulates a left side border without shifting content - box-shadow: -$euiSizeXS 0px $euiColorDanger; + box-shadow: -$euiSizeXS 0 $euiColorDanger; } @include internetExplorerOnly { @@ -57,7 +57,7 @@ .mgtAdvancedSettingsForm__unsavedCountMessage { // Simulates a left side border without shifting content - box-shadow: -$euiSizeXS 0px $euiColorWarning; + box-shadow: -$euiSizeXS 0 $euiColorWarning; padding-left: $euiSizeS; } diff --git a/src/plugins/charts/public/static/components/legend_toggle.scss b/src/plugins/charts/public/static/components/legend_toggle.scss index 7eb85a5e08ec05..3df799d4bcda48 100644 --- a/src/plugins/charts/public/static/components/legend_toggle.scss +++ b/src/plugins/charts/public/static/components/legend_toggle.scss @@ -17,4 +17,3 @@ top: 0; } } - diff --git a/src/plugins/dashboard/public/application/embeddable/grid/_dashboard_grid.scss b/src/plugins/dashboard/public/application/embeddable/grid/_dashboard_grid.scss index a205e611531b69..bf593bd89b42b6 100644 --- a/src/plugins/dashboard/public/application/embeddable/grid/_dashboard_grid.scss +++ b/src/plugins/dashboard/public/application/embeddable/grid/_dashboard_grid.scss @@ -31,7 +31,7 @@ * 1. Need to override the react grid layout height when a single panel is expanded. Important is required because * otherwise the height is set inline. */ - .dshLayout-isMaximizedPanel { +.dshLayout-isMaximizedPanel { height: 100% !important; /* 1. */ width: 100%; position: absolute !important; /* 1 */ @@ -66,7 +66,7 @@ /** * Disable transitions from the library on each grid element. */ - transition: none; + transition: none; /** * Copy over and overwrite the fill color with EUI color mixin (for theming) */ diff --git a/src/plugins/dashboard/public/application/embeddable/panel/_dashboard_panel.scss b/src/plugins/dashboard/public/application/embeddable/panel/_dashboard_panel.scss index 48961110db48b1..f2d017e54dc7b1 100644 --- a/src/plugins/dashboard/public/application/embeddable/panel/_dashboard_panel.scss +++ b/src/plugins/dashboard/public/application/embeddable/panel/_dashboard_panel.scss @@ -8,7 +8,7 @@ // Adjust borders/etc... for non-spaced out and expanded panels .dshLayout-withoutMargins, -.dshDashboardGrid__item--expanded { +.dshDashboardGrid__item--expanded { .embPanel { box-shadow: none; border-radius: 0; diff --git a/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.scss b/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.scss index 196ae68e3ed178..9ad6a5257df3ea 100644 --- a/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.scss +++ b/src/plugins/dashboard/public/application/top_nav/panel_toolbar/panel_toolbar.scss @@ -6,7 +6,7 @@ .panelToolbarButton { line-height: $euiButtonHeight; // Keeps alignment of text and chart icon background-color: $euiColorEmptyShade; - + // Lighten the border color for all states border-color: $euiBorderColor !important; // sass-lint:disable-line no-important } diff --git a/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss b/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss index 731c9f4d7f18d8..d45f7040e5739a 100644 --- a/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss +++ b/src/plugins/data/public/ui/filter_bar/_global_filter_group.scss @@ -1,6 +1,6 @@ // SASSTODO: Probably not the right file for this selector, but temporary until the files get re-organized .globalQueryBar { - padding: 0px $euiSizeS $euiSizeS $euiSizeS; + padding: 0 $euiSizeS $euiSizeS $euiSizeS; } .globalQueryBar:first-child { diff --git a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss index b79b7c038f9cc4..652c8b0b35b42e 100644 --- a/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss +++ b/src/plugins/data/public/ui/filter_bar/_global_filter_item.scss @@ -26,7 +26,7 @@ .globalFilterItem-isDisabled { color: $euiColorDarkShade; - background-color: transparentize($euiColorLightShade, 0.5); + background-color: transparentize($euiColorLightShade, .5); text-decoration: line-through; font-weight: $euiFontWeightRegular; font-style: italic; diff --git a/src/plugins/data/public/ui/shard_failure_modal/_shard_failure_modal.scss b/src/plugins/data/public/ui/shard_failure_modal/_shard_failure_modal.scss index 6527289f8021ff..ee3912098afae9 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/_shard_failure_modal.scss +++ b/src/plugins/data/public/ui/shard_failure_modal/_shard_failure_modal.scss @@ -1,41 +1,41 @@ // set width and height to fixed values to prevent resizing when you switch tabs .shardFailureModal { - min-height: 75vh; - width: 768px; + min-height: 75vh; + width: 768px; } .shardFailureModal__desc { - // set for IE11, since without it depending on the content the width of the list - // could be much higher than the available screenspace - max-width: 686px; + // set for IE11, since without it depending on the content the width of the list + // could be much higher than the available screenspace + max-width: 686px; } .shardFailureModal__descTitle { - width: 20% !important; - margin-top: $euiSizeS; + width: 20% !important; + margin-top: $euiSizeS; } .shardFailureModal__descValue { - width: 80% !important; - margin-top: $euiSizeS; + width: 80% !important; + margin-top: $euiSizeS; } .shardFailureModal__keyValueTitle { - padding-right: $euiSizeS; + padding-right: $euiSizeS; } @include euiBreakpoint('xs','s') { - .shardFailureModal__keyValueTitle { - display: block; - width: 100%; - } - - .shardFailureModal__descTitle { - display: block; - width: 100% !important; - } - - .shardFailureModal__descValue { - display: block; - width: 100% !important; - } + .shardFailureModal__keyValueTitle { + display: block; + width: 100%; + } + + .shardFailureModal__descTitle { + display: block; + width: 100% !important; + } + + .shardFailureModal__descValue { + display: block; + width: 100% !important; + } } \ No newline at end of file diff --git a/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss b/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss index 7d05171622e7bd..c4bba1a8bbf2bd 100644 --- a/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss +++ b/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss @@ -1,6 +1,7 @@ /** * 1. Stack content vertically so the table can scroll when its constrained by a fixed container height. */ +// stylelint-disable selector-no-qualifying-type doc-table { @include euiScrollBar; overflow: auto; @@ -18,12 +19,12 @@ doc-table { left: 0; right: 0; z-index: $euiZLevel1; - opacity: 0.5; + opacity: .5; } } .kbnDocTable__container.loading { - opacity: 0.5; + opacity: .5; } .kbnDocTable { @@ -58,7 +59,7 @@ doc-table { } dt { - background-color: transparentize(shade($euiColorPrimary, 20%), 0.9); + background-color: transparentize(shade($euiColorPrimary, 20%), .9); color: $euiTextColor; padding: ($euiSizeXS / 2) $euiSizeXS; margin-right: $euiSizeXS; diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row/_details.scss b/src/plugins/discover/public/application/angular/doc_table/components/table_row/_details.scss index 75d4789de929a5..cc6ccfe9fd29f3 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row/_details.scss +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row/_details.scss @@ -22,4 +22,3 @@ border-top: none !important; } } - diff --git a/src/plugins/discover/public/application/angular/doc_table/components/table_row/_open.scss b/src/plugins/discover/public/application/angular/doc_table/components/table_row/_open.scss index 96a2f2e0843cc6..659481e0968b59 100644 --- a/src/plugins/discover/public/application/angular/doc_table/components/table_row/_open.scss +++ b/src/plugins/discover/public/application/angular/doc_table/components/table_row/_open.scss @@ -4,7 +4,7 @@ * re-render which is SLOW. */ - .kbnDocTableOpen__button { +.kbnDocTableOpen__button { appearance: none; background-color: transparent; padding: 0; diff --git a/src/plugins/discover/public/application/components/discover.scss b/src/plugins/discover/public/application/components/discover.scss index 665bd98c232a5b..90bfd84c4d54e5 100644 --- a/src/plugins/discover/public/application/components/discover.scss +++ b/src/plugins/discover/public/application/components/discover.scss @@ -70,7 +70,7 @@ discover-app { // SASSTODO: the visualizing component should have an option or a modifier .series > rect { - fill-opacity: 0.5; + fill-opacity: .5; stroke-width: 1; } } diff --git a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss index fba26f5fa46860..5bae3d64a6b695 100644 --- a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss +++ b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss @@ -13,7 +13,7 @@ white-space: pre-wrap; color: $euiColorFullShade; vertical-align: top; - padding-top: $euiSizeXS * 0.5; + padding-top: $euiSizeXS * .5; } .kbnDocViewer__field { padding-top: $euiSizeS; diff --git a/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss b/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss index 6b8654f6c3528b..d21911f10f82e9 100644 --- a/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss +++ b/src/plugins/embeddable/public/lib/panel/_embeddable_panel.scss @@ -94,7 +94,7 @@ */ .embPanel__optionsMenuButton { - background-color: transparentize($euiColorDarkestShade, 0.9); + background-color: transparentize($euiColorDarkestShade, .9); border-bottom-right-radius: 0; border-top-left-radius: 0; @@ -156,7 +156,6 @@ justify-content: center; flex-direction: column; overflow: auto; - text-align: center; padding: $euiSizeS; } @@ -169,5 +168,6 @@ .embPanel__content[data-loading] { pointer-events: none; filter: grayscale(100%); + /* stylelint-disable-next-line color-named */ filter: gray; } diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/ace/_ui_ace_keyboard_mode.scss b/src/plugins/es_ui_shared/__packages_do_not_import__/ace/_ui_ace_keyboard_mode.scss index 5b637224c1784e..2ad92f3506b202 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/ace/_ui_ace_keyboard_mode.scss +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/ace/_ui_ace_keyboard_mode.scss @@ -4,7 +4,7 @@ bottom: 0; right: 0; left: 0; - background: transparentize($euiColorEmptyShade, 0.3); + background: transparentize($euiColorEmptyShade, .3); display: flex; flex-direction: column; justify-content: center; diff --git a/src/plugins/home/public/application/components/_solutions_section.scss b/src/plugins/home/public/application/components/_solutions_section.scss index 53c5678ff0b09b..86c111ee1a0adf 100644 --- a/src/plugins/home/public/application/components/_solutions_section.scss +++ b/src/plugins/home/public/application/components/_solutions_section.scss @@ -66,11 +66,6 @@ overflow: hidden; } -.homSolutionPanel__header { - color: $euiColorEmptyShade; - padding: $euiSize; -} - .homSolutionPanel__icon { background-color: $euiColorEmptyShade !important; box-shadow: none !important; @@ -93,6 +88,8 @@ } .homSolutionPanel__header { + color: $euiColorEmptyShade; + padding: $euiSize; background-color: $euiColorPrimary; background-image: url('data:image/png;base64,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'), url('data:image/png;base64,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'); diff --git a/src/plugins/kibana_legacy/public/font_awesome/font_awesome.scss b/src/plugins/kibana_legacy/public/font_awesome/font_awesome.scss index 876a920269c499..e641965fabd518 100644 --- a/src/plugins/kibana_legacy/public/font_awesome/font_awesome.scss +++ b/src/plugins/kibana_legacy/public/font_awesome/font_awesome.scss @@ -2,21 +2,21 @@ font-family: 'FontAwesome'; src: url('~font-awesome/fonts/fontawesome-webfont.eot?v=4.7.0'); src: url('~font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), - url('~font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), - url('~font-awesome/fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), - url('~font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), - url('~font-awesome/fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + url('~font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), + url('~font-awesome/fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), + url('~font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), + url('~font-awesome/fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } -@import "font-awesome/scss/variables"; -@import "font-awesome/scss/core"; -@import "font-awesome/scss/icons"; +@import 'font-awesome/scss/variables'; +@import 'font-awesome/scss/core'; +@import 'font-awesome/scss/icons'; // new file icon .#{$fa-css-prefix}-file-new-o:before { content: $fa-var-file-o; } -.#{$fa-css-prefix}-file-new-o:after { content: $fa-var-plus; position: relative; margin-left: -1.0em; font-size: 0.5em; } +.#{$fa-css-prefix}-file-new-o:after { content: $fa-var-plus; position: relative; margin-left: -1.0em; font-size: .5em; } // alias for alert types - allows class="fa fa-{{alertType}}" .fa-success:before { content: $fa-var-check; } diff --git a/src/plugins/kibana_legacy/public/paginate/_paginate.scss b/src/plugins/kibana_legacy/public/paginate/_paginate.scss index e9c1acaf9ee0d6..9824ff2d8dff36 100644 --- a/src/plugins/kibana_legacy/public/paginate/_paginate.scss +++ b/src/plugins/kibana_legacy/public/paginate/_paginate.scss @@ -36,7 +36,7 @@ paginate { text-decoration: underline; } - &.active a { + &.active a { // stylelint-disable-line selector-no-qualifying-type text-decoration: none !important; font-weight: $euiFontWeightBold; color: $euiColorDarkShade; @@ -54,4 +54,3 @@ paginate { } } } - diff --git a/src/plugins/kibana_react/public/markdown/_markdown.scss b/src/plugins/kibana_react/public/markdown/_markdown.scss index 515a301e648c2b..3c9b1cd165bab6 100644 --- a/src/plugins/kibana_react/public/markdown/_markdown.scss +++ b/src/plugins/kibana_react/public/markdown/_markdown.scss @@ -18,7 +18,6 @@ $kbnDefaultFontSize: 14px; } .kbnMarkdown__body { - // Font size variables $kbnMarkdownFontSizeS: canvasToEm(12px); $kbnMarkdownFontSize: canvasToEm(14px); @@ -34,14 +33,14 @@ $kbnDefaultFontSize: 14px; $kbnMarkdownSizeXXS: canvasToEm(4px); // Grayscale variables - $kbnMarkdownAlphaLightestShade: rgba($euiColorFullShade,.05); - $kbnMarkdownAlphaLightShade: rgba($euiColorFullShade,.15); - $kbnMarkdownAlphaDarkShade: rgba($euiColorFullShade,.65); + $kbnMarkdownAlphaLightestShade: rgba($euiColorFullShade, .05); + $kbnMarkdownAlphaLightShade: rgba($euiColorFullShade, .15); + $kbnMarkdownAlphaDarkShade: rgba($euiColorFullShade, .65); // Reverse grayscale for opposite of theme - $kbnMarkdownAlphaLightestShadeReversed: rgba($euiColorEmptyShade,.05); - $kbnMarkdownAlphaLightShadeReversed: rgba($euiColorEmptyShade,.15); - $kbnMarkdownAlphaDarkShadeReversed: rgba($euiColorEmptyShade,.65); + $kbnMarkdownAlphaLightestShadeReversed: rgba($euiColorEmptyShade, .05); + $kbnMarkdownAlphaLightShadeReversed: rgba($euiColorEmptyShade, .15); + $kbnMarkdownAlphaDarkShadeReversed: rgba($euiColorEmptyShade, .65); &--reversed { color: $euiColorLightestShade; @@ -171,19 +170,19 @@ $kbnDefaultFontSize: 14px; hr::before { display: table; - content: ""; + content: ''; } hr::after { display: table; clear: both; - content: ""; + content: ''; } // 6. Lists ul, ol { - padding-left: 0; + padding-left: $kbnMarkdownSizeL; margin-top: 0; margin-bottom: $kbnMarkdownSize; } @@ -215,11 +214,6 @@ $kbnDefaultFontSize: 14px; margin-left: 0; } - ul, - ol { - padding-left: $kbnMarkdownSizeL; - } - ul ul, ul ol, ol ol, @@ -297,8 +291,8 @@ $kbnDefaultFontSize: 14px; code::before, code::after { - letter-spacing: -0.2em; - content: "\00a0"; + letter-spacing: -.2em; + content: '\00a0'; } pre { diff --git a/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss b/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss index 3235bb63ca22d8..c688a8c9b518cb 100644 --- a/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss +++ b/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss @@ -1,7 +1,8 @@ +// stylelint-disable selector-no-qualifying-type // SASSTODO: Create these tooltip variables in EUI // And/Or create a tooltip mixin -$temp-euiTooltipBackground: tintOrShade($euiColorFullShade, 25%, 90%); -$temp-euiTooltipText: $euiColorGhost; +$tempEUITooltipBackground: tintOrShade($euiColorFullShade, 25%, 90%); +$tempEUITooltipText: $euiColorGhost; // Converted leaflet icon sprite into background svg for custom coloring (dark mode) $visMapLeafletSprite: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 60' height='60' width='600'%3E%3Cg fill='#{hexToRGB($euiTextColor)}'%3E%3Cg%3E%3Cpath d='M18 36v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M36 18v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M23.142 39.145l-2.285-2.29 16-15.998 2.285 2.285z'/%3E%3C/g%3E%3Cpath d='M100 24.565l-2.096 14.83L83.07 42 76 28.773 86.463 18z'/%3E%3Cpath d='M140 20h20v20h-20z'/%3E%3Cpath d='M221 30c0 6.078-4.926 11-11 11s-11-4.922-11-11c0-6.074 4.926-11 11-11s11 4.926 11 11z'/%3E%3Cpath d='M270,19c-4.971,0-9,4.029-9,9c0,4.971,5.001,12,9,14c4.001-2,9-9.029,9-14C279,23.029,274.971,19,270,19z M270,31.5c-2.484,0-4.5-2.014-4.5-4.5c0-2.484,2.016-4.5,4.5-4.5c2.485,0,4.5,2.016,4.5,4.5C274.5,29.486,272.485,31.5,270,31.5z'/%3E%3Cg%3E%3Cpath d='M337,30.156v0.407v5.604c0,1.658-1.344,3-3,3h-10c-1.655,0-3-1.342-3-3v-10c0-1.657,1.345-3,3-3h6.345 l3.19-3.17H324c-3.313,0-6,2.687-6,6v10c0,3.313,2.687,6,6,6h10c3.314,0,6-2.687,6-6v-8.809L337,30.156'/%3E%3Cpath d='M338.72 24.637l-8.892 8.892H327V30.7l8.89-8.89z'/%3E%3Cpath d='M338.697 17.826h4v4h-4z' transform='rotate(-134.99 340.703 19.817)'/%3E%3C/g%3E%3Cg%3E%3Cpath d='M381 42h18V24h-18v18zm14-16h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26z'/%3E%3Cpath d='M395 20v-4h-10v4h-6v2h22v-2h-6zm-2 0h-6v-2h6v2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A"; @@ -23,7 +24,7 @@ $visMapLeafletSprite: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/s .leaflet-clickable { &:hover { stroke-width: $euiSizeS; - stroke-opacity: 0.8; + stroke-opacity: .8; } } @@ -78,8 +79,8 @@ $visMapLeafletSprite: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/s .leaflet-popup-content-wrapper { margin: 0; padding: 0; - background: $temp-euiTooltipBackground; - color: $temp-euiTooltipText; + background: $tempEUITooltipBackground; + color: $tempEUITooltipText; border-radius: $euiBorderRadius !important; // Override all positions the popup might be at } @@ -146,7 +147,7 @@ $visMapLeafletSprite: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/s img.leaflet-tile { @if (lightness($euiTextColor) < 50) { - filter: brightness(1.03) grayscale(0.73); + filter: brightness(1.03) grayscale(.73); } @else { filter: invert(1) brightness(1.75) grayscale(1); } diff --git a/src/plugins/navigation/public/index.scss b/src/plugins/navigation/public/index.scss index 4734a2915c6208..760f3dfcddbbf9 100644 --- a/src/plugins/navigation/public/index.scss +++ b/src/plugins/navigation/public/index.scss @@ -1 +1 @@ -@import "top_nav_menu/index"; +@import 'top_nav_menu/index'; diff --git a/src/plugins/timelion/public/_base.scss b/src/plugins/timelion/public/_base.scss index 616ac9b3486e7c..e71196a2e6df99 100644 --- a/src/plugins/timelion/public/_base.scss +++ b/src/plugins/timelion/public/_base.scss @@ -16,4 +16,3 @@ input[type='checkbox'], opacity: .8; } } - diff --git a/src/plugins/timelion/public/directives/_form.scss b/src/plugins/timelion/public/directives/_form.scss index 370dd25f8263f7..37a0cc4c0f3e57 100644 --- a/src/plugins/timelion/public/directives/_form.scss +++ b/src/plugins/timelion/public/directives/_form.scss @@ -21,8 +21,7 @@ } } -// sass-lint:disable-block no-qualifying-elements -select.form-control { +select.form-control { // stylelint-disable-line selector-no-qualifying-type // Makes the select arrow similar to EUI's arrowDown icon background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"%3E%3Cpath fill="#{hexToRGB($euiTextColor)}" d="M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z"/%3E%3C/svg%3E'); background-size: $euiSize; diff --git a/src/plugins/timelion/public/directives/_index.scss b/src/plugins/timelion/public/directives/_index.scss index a407c1dfabdeb9..2a015711062a68 100644 --- a/src/plugins/timelion/public/directives/_index.scss +++ b/src/plugins/timelion/public/directives/_index.scss @@ -5,4 +5,3 @@ @import './timelion_interval/index'; @import './saved_object_finder'; @import './form'; - diff --git a/src/plugins/timelion/public/directives/_saved_object_finder.scss b/src/plugins/timelion/public/directives/_saved_object_finder.scss index 3a2489afb57211..55882fe78e99e3 100644 --- a/src/plugins/timelion/public/directives/_saved_object_finder.scss +++ b/src/plugins/timelion/public/directives/_saved_object_finder.scss @@ -24,7 +24,6 @@ } } - saved-object-finder { .timSearchBar { diff --git a/src/plugins/timelion/public/directives/cells/_cells.scss b/src/plugins/timelion/public/directives/cells/_cells.scss index 6cd71378a81de3..d1e5e976fc8d24 100644 --- a/src/plugins/timelion/public/directives/cells/_cells.scss +++ b/src/plugins/timelion/public/directives/cells/_cells.scss @@ -18,7 +18,6 @@ opacity: .5; } - .timCell__actions { position: absolute; bottom: $euiSizeXS; diff --git a/src/plugins/vis_default_editor/public/_default.scss b/src/plugins/vis_default_editor/public/_default.scss index f189b1c9e64a1f..985f2c73f6efea 100644 --- a/src/plugins/vis_default_editor/public/_default.scss +++ b/src/plugins/vis_default_editor/public/_default.scss @@ -13,7 +13,7 @@ .visEditor__collapsibleSidebar { background: $euiColorLightestShade; - min-width: $vis-editor-sidebar-min-width; + min-width: $visEditorSidebarMinWidth; max-width: 100%; position: relative; flex-shrink: 0; diff --git a/src/plugins/vis_default_editor/public/_sidebar.scss b/src/plugins/vis_default_editor/public/_sidebar.scss index 42f7c4e6a892ce..23241abcff770e 100644 --- a/src/plugins/vis_default_editor/public/_sidebar.scss +++ b/src/plugins/vis_default_editor/public/_sidebar.scss @@ -3,7 +3,7 @@ // .visEditorSidebar { - min-width: $vis-editor-sidebar-min-width; + min-width: $visEditorSidebarMinWidth; // a hack for IE, issue: https://github.com/elastic/kibana/issues/66586 > .visEditorSidebar__formWrapper { @@ -12,7 +12,7 @@ } .visEditorSidebar__form { - @include flex-parent(1, 1, auto); + @include flexParent(1, 1, auto); max-width: 100%; } @@ -24,7 +24,7 @@ } @include euiBreakpoint('l', 'xl') { - @include flex-parent(1, 1, 1px); + @include flexParent(1, 1, 1px); @include euiScrollBar; overflow: auto; } diff --git a/src/plugins/vis_default_editor/public/index.scss b/src/plugins/vis_default_editor/public/index.scss index 6abb45dc546a30..8f2675c1ba374c 100644 --- a/src/plugins/vis_default_editor/public/index.scss +++ b/src/plugins/vis_default_editor/public/index.scss @@ -1,4 +1,4 @@ -$vis-editor-sidebar-min-width: 350px; +$visEditorSidebarMinWidth: 350px; // Main layout @import './default'; diff --git a/src/plugins/vis_type_markdown/public/markdown_vis.scss b/src/plugins/vis_type_markdown/public/markdown_vis.scss index 2356562a86ed0a..97cfc4b151c77e 100644 --- a/src/plugins/vis_type_markdown/public/markdown_vis.scss +++ b/src/plugins/vis_type_markdown/public/markdown_vis.scss @@ -12,7 +12,7 @@ .visEditor--markdown { .visEditorSidebar__config > *, - .visEditor--markdown__textarea { + .visEditor--markdown__textarea { flex-grow: 1; } diff --git a/src/plugins/vis_type_table/public/legacy/_table_vis.scss b/src/plugins/vis_type_table/public/legacy/_table_vis.scss index fa12ef9a1cf39e..6ae3ddcca81a9f 100644 --- a/src/plugins/vis_type_table/public/legacy/_table_vis.scss +++ b/src/plugins/vis_type_table/public/legacy/_table_vis.scss @@ -12,7 +12,7 @@ .table-vis-container { kbn-agg-table-group > .table > tbody > tr > td { - border-top: 0px; + border-top: 0; } .pagination-other-pages { diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss b/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss index 4bbc4eb034f8da..89c7f6664c2fa7 100644 --- a/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss +++ b/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss @@ -38,5 +38,5 @@ kbn-agg-table-group { } .small { - font-size: 0.9em !important; + font-size: .9em !important; } diff --git a/src/plugins/vis_type_timeseries/public/application/_tvb_editor.scss b/src/plugins/vis_type_timeseries/public/application/_tvb_editor.scss index 9864c72b766285..73ef76931ff125 100644 --- a/src/plugins/vis_type_timeseries/public/application/_tvb_editor.scss +++ b/src/plugins/vis_type_timeseries/public/application/_tvb_editor.scss @@ -2,4 +2,3 @@ overflow-y: auto; overflow-x: hidden; } - diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/_vis_types.scss b/src/plugins/vis_type_timeseries/public/application/components/vis_types/_vis_types.scss index 9585711c73dd2a..9c07721fa00b36 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/_vis_types.scss +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/_vis_types.scss @@ -8,10 +8,10 @@ } .tvbVisTimeSeriesDark { .echReactiveChart_unavailable { - color: #dfe5ef; + color: #DFE5EF; } .echLegendItem { - color: #dfe5ef; + color: #DFE5EF; } } .tvbVisTimeSeriesLight { diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/_markdown.scss b/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/_markdown.scss index 92037c80e71763..ec16404df8e7f2 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/_markdown.scss +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/_markdown.scss @@ -29,5 +29,3 @@ overflow: auto; } } - - diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/_top_n.scss b/src/plugins/vis_type_timeseries/public/application/visualizations/views/_top_n.scss index fb6be95dba2a20..27ccb6227666dc 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/_top_n.scss +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/_top_n.scss @@ -1,5 +1,4 @@ - .tvbVisTopN { position: relative; overflow: auto; diff --git a/src/plugins/vis_type_vega/public/components/vega_vis.scss b/src/plugins/vis_type_vega/public/components/vega_vis.scss index 004eed5a3972b6..f0062869e00469 100644 --- a/src/plugins/vis_type_vega/public/components/vega_vis.scss +++ b/src/plugins/vis_type_vega/public/components/vega_vis.scss @@ -1,3 +1,4 @@ +// stylelint-disable selector-no-qualifying-type .vgaVis__wrapper { @include euiScrollBar; @@ -109,7 +110,6 @@ color: makeHighContrastColor($euiColorDanger, $calculateBackgroundColor); } - // Style tooltip popup (gets created dynamically at the top level if dashboard has a Vega vis) // Adapted from https://github.com/vega/vega-tooltip diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss b/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss index 6751e9f28a8ee4..6ab284fd8d122d 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss +++ b/src/plugins/vis_type_vislib/public/vislib/lib/_index.scss @@ -1,3 +1,2 @@ @import './alerts'; @import './layout/index'; - diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/layout/_layout.scss b/src/plugins/vis_type_vislib/public/vislib/lib/layout/_layout.scss index b3fdf654f8ab71..a6896a9181b4ec 100644 --- a/src/plugins/vis_type_vislib/public/vislib/lib/layout/_layout.scss +++ b/src/plugins/vis_type_vislib/public/vislib/lib/layout/_layout.scss @@ -25,123 +25,6 @@ // Numbers in here are brittle // -.visWrapper { - display: flex; - flex: 1 1 100%; - flex-direction: row; - min-height: 0; - min-width: 0; - overflow: hidden; - padding: $euiSizeS 0; -} - -.visWrapper__column { - display: flex; - flex: 1 0 0; - flex-direction: column; - min-height: 0; - min-width: 0; -} - -.visWrapper__splitCharts--column { - display: flex; - flex: 1 0 20px; - flex-direction: row; - min-height: 0; - min-width: 0; - - .visWrapper__chart { - margin-top: 0; - margin-bottom: 0; - } -} - -.visWrapper__splitCharts--row { - display: flex; - flex-direction: column; - flex: 1 1 100%; - min-height: 0; - min-width: 0; - - .visWrapper__chart { - margin-left: 0; - margin-right: 0; - } -} - -.visWrapper__chart { - display: flex; - flex: 1 0 0; - overflow: visible; - margin: 5px; - min-height: 0; - min-width: 0; -} - -.visWrapper__alerts { - position: relative; -} - -// General Axes - -.visAxis__column--top .axis-div svg { - margin-bottom: -5px; -} - -// Y Axes - -.visAxis--x, -.visAxis--y { - display: flex; - flex-direction: column; - min-height: 0; - min-width: 0; -} - -.visAxis--x { - overflow: visible; -} - -.visAxis__spacer--y { - min-height: 0; -} - -.visAxis__column--y { - display: flex; - flex-direction: row; - flex: 1 0 ($euiSizeXL + $euiSizeXS); - min-height: 0; - min-width: 0; -} - -.visAxis__splitTitles--y { - display: flex; - flex-direction: column; - min-height: $euiSizeM; - min-width: 0; -} - -.visAxis__splitTitles--x { - display: flex; - flex-direction: row; - min-height: 1px; - max-height: $euiSize; - min-width: $euiSize; -} - -.visAxis__splitAxes--x, -.visAxis__splitAxes--y { - display: flex; - flex-direction: column; - min-height: ($euiSize + $euiSizeXS); - min-width: 0; -} - -.visAxis__splitAxes--x { - flex-direction: row; - min-height: 0; -} - // // STYLE // @@ -155,6 +38,14 @@ // sass-lint:disable-block no-mergeable-selectors // Keep SVG and non-renamable selectors separately .visWrapper { + display: flex; + flex: 1 1 100%; + flex-direction: row; + min-height: 0; + min-width: 0; + overflow: hidden; + padding: $euiSizeS 0; + svg { overflow: visible; } @@ -340,3 +231,110 @@ fill: $visHoverBackgroundColor; } } + +.visWrapper__column { + display: flex; + flex: 1 0 0; + flex-direction: column; + min-height: 0; + min-width: 0; +} + +.visWrapper__splitCharts--column { + display: flex; + flex: 1 0 20px; + flex-direction: row; + min-height: 0; + min-width: 0; + + .visWrapper__chart { + margin-top: 0; + margin-bottom: 0; + } +} + +.visWrapper__splitCharts--row { + display: flex; + flex-direction: column; + flex: 1 1 100%; + min-height: 0; + min-width: 0; + + .visWrapper__chart { + margin-left: 0; + margin-right: 0; + } +} + +.visWrapper__chart { + display: flex; + flex: 1 0 0; + overflow: visible; + margin: 5px; + min-height: 0; + min-width: 0; +} + +.visWrapper__alerts { + position: relative; +} + +// General Axes + +.visAxis__column--top .axis-div svg { + margin-bottom: -5px; +} + +// Y Axes + +.visAxis--x, +.visAxis--y { + display: flex; + flex-direction: column; + min-height: 0; + min-width: 0; +} + +.visAxis--x { + overflow: visible; +} + +.visAxis__spacer--y { + min-height: 0; +} + +.visAxis__column--y { + display: flex; + flex-direction: row; + flex: 1 0 ($euiSizeXL + $euiSizeXS); + min-height: 0; + min-width: 0; +} + +.visAxis__splitTitles--y { + display: flex; + flex-direction: column; + min-height: $euiSizeM; + min-width: 0; +} + +.visAxis__splitTitles--x { + display: flex; + flex-direction: row; + min-height: 1px; + max-height: $euiSize; + min-width: $euiSize; +} + +.visAxis__splitAxes--x, +.visAxis__splitAxes--y { + display: flex; + flex-direction: column; + min-height: ($euiSize + $euiSizeXS); + min-width: 0; +} + +.visAxis__splitAxes--x { + flex-direction: row; + min-height: 0; +} diff --git a/src/plugins/visualizations/public/components/_visualization.scss b/src/plugins/visualizations/public/components/_visualization.scss index bde9621fd70b8e..e8d4c5c6db4452 100644 --- a/src/plugins/visualizations/public/components/_visualization.scss +++ b/src/plugins/visualizations/public/components/_visualization.scss @@ -27,14 +27,14 @@ display: flex; flex-direction: row; overflow: auto; - transition: opacity 0.01s; + transition: opacity .01s; // IE11 Hack // // Normally we would just set flex: 1 1 0%, which works as expected in IE11. // Unfortunately, a recent bug in Firefox causes this rule to be ignored, so we // have to use an IE-specific hack instead. - @include internetExplorerOnly(){ + @include internetExplorerOnly() { flex: 1 0; } @@ -45,7 +45,7 @@ // SASSTODO: Can't find exact usage .loading { - opacity: 0.5; + opacity: .5; } // SASSTODO: Can't find exact usage @@ -55,7 +55,7 @@ left: 0; right: 0; z-index: 20; - opacity: 0.5; + opacity: .5; } } diff --git a/src/plugins/visualizations/public/embeddable/_embeddables.scss b/src/plugins/visualizations/public/embeddable/_embeddables.scss index 23d3e189767d7a..f0ec8479489d26 100644 --- a/src/plugins/visualizations/public/embeddable/_embeddables.scss +++ b/src/plugins/visualizations/public/embeddable/_embeddables.scss @@ -15,6 +15,11 @@ .visLegend__toggle { border-bottom-right-radius: 0; border-top-left-radius: 0; + opacity: 0; /* 1 */ + + &:focus { + opacity: 1; /* 2 */ + } } } @@ -26,23 +31,15 @@ * 3. Always show in editing mode */ -.embPanel_optionsMenuPopover[class*="-isOpen"], -.embPanel:hover { +.embPanel_optionsMenuPopover[class*='-isOpen'], +.embPanel:hover { .visLegend__toggle { opacity: 1; } } -.embPanel .visLegend__toggle { - opacity: 0; /* 1 */ - - &:focus { - opacity: 1; /* 2 */ - } -} - .embPanel--editing { .visLegend__toggle { opacity: 1; /* 3 */ } -} \ No newline at end of file +} diff --git a/src/plugins/visualize/public/application/components/visualize_editor.scss b/src/plugins/visualize/public/application/components/visualize_editor.scss index 3a542cacc44be2..6ddf3c1264bff4 100644 --- a/src/plugins/visualize/public/application/components/visualize_editor.scss +++ b/src/plugins/visualize/public/application/components/visualize_editor.scss @@ -1,5 +1,5 @@ .visEditor { - @include flex-parent(); + @include flexParent(); height: 100%; @@ -23,7 +23,7 @@ a tilemap in an iframe: https://github.com/elastic/kibana/issues/16457 */ } .visEditor__content { - @include flex-parent(); + @include flexParent(); width: 100%; z-index: 0; } diff --git a/src/plugins/visualize/public/application/components/visualize_listing.scss b/src/plugins/visualize/public/application/components/visualize_listing.scss index e1777112cdb3a0..8eb2a8911ee02d 100644 --- a/src/plugins/visualize/public/application/components/visualize_listing.scss +++ b/src/plugins/visualize/public/application/components/visualize_listing.scss @@ -12,7 +12,7 @@ .visListingTable__experimentalIcon { width: $euiSizeL; vertical-align: baseline; - padding: 0 $euiSizeS; + padding: 0 $euiSizeS; margin-left: $euiSizeS; } diff --git a/test/scripts/jenkins_unit.sh b/test/scripts/jenkins_unit.sh index 2edd66579f72f4..00fd378b348a08 100755 --- a/test/scripts/jenkins_unit.sh +++ b/test/scripts/jenkins_unit.sh @@ -11,7 +11,7 @@ rename_coverage_file() { if [[ -z "$CODE_COVERAGE" ]] ; then # Lint ./test/scripts/lint/eslint.sh - ./test/scripts/lint/sasslint.sh + ./test/scripts/lint/stylelint.sh # Test ./test/scripts/test/jest_integration.sh diff --git a/test/scripts/lint/sasslint.sh b/test/scripts/lint/sasslint.sh deleted file mode 100755 index 72e341cdcda16a..00000000000000 --- a/test/scripts/lint/sasslint.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -source src/dev/ci_setup/setup_env.sh - -checks-reporter-with-killswitch "Lint: sasslint" \ - node scripts/sasslint diff --git a/test/scripts/lint/stylelint.sh b/test/scripts/lint/stylelint.sh new file mode 100755 index 00000000000000..3dcb682c40f0ca --- /dev/null +++ b/test/scripts/lint/stylelint.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +source src/dev/ci_setup/setup_env.sh + +checks-reporter-with-killswitch "Lint: stylelint" \ + node scripts/stylelint diff --git a/vars/tasks.groovy b/vars/tasks.groovy index 18be6e69a2637d..ec2af87caba567 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -24,7 +24,7 @@ def check() { def lint() { tasks([ kibanaPipeline.scriptTask('Lint: eslint', 'test/scripts/lint/eslint.sh'), - kibanaPipeline.scriptTask('Lint: sasslint', 'test/scripts/lint/sasslint.sh'), + kibanaPipeline.scriptTask('Lint: stylelint', 'test/scripts/lint/stylelint.sh'), ]) } diff --git a/x-pack/plugins/canvas/public/components/element_card/element_card.scss b/x-pack/plugins/canvas/public/components/element_card/element_card.scss index 87dc59edba2999..e6a308cc6af488 100644 --- a/x-pack/plugins/canvas/public/components/element_card/element_card.scss +++ b/x-pack/plugins/canvas/public/components/element_card/element_card.scss @@ -25,7 +25,7 @@ .canvasElementCard { .euiCard__top { text-align: center; - width: calc(100% + #{$euiSize}* 2); + width: calc(100% + #{$euiSize} * 2); height: 85px; margin: calc(-1 * #{$euiSize}) calc(-1 * #{$euiSize}) 0; } diff --git a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss index edd681a2c33e8e..3ab04e31eb9c19 100644 --- a/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss +++ b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss @@ -1,4 +1,5 @@ -body.canvas-isFullscreen { // sass-lint:disable-line no-qualifying-elements +/* stylelint-disable selector-no-qualifying-type */ +body.canvas-isFullscreen { // following two rules are for overriding the header bar padding &.euiBody--headerIsFixed { padding-top: 0; diff --git a/x-pack/plugins/canvas/public/components/toolbar/tray/tray.scss b/x-pack/plugins/canvas/public/components/toolbar/tray/tray.scss index 0ed47a761cd4fb..69c4329ecedafc 100644 --- a/x-pack/plugins/canvas/public/components/toolbar/tray/tray.scss +++ b/x-pack/plugins/canvas/public/components/toolbar/tray/tray.scss @@ -7,4 +7,3 @@ background-color: $euiFormBackgroundColor; border-radius: 0; } - diff --git a/x-pack/plugins/canvas/public/components/workpad/workpad.scss b/x-pack/plugins/canvas/public/components/workpad/workpad.scss index 2aa69fb1193175..b7c84507df61eb 100644 --- a/x-pack/plugins/canvas/public/components/workpad/workpad.scss +++ b/x-pack/plugins/canvas/public/components/workpad/workpad.scss @@ -12,7 +12,7 @@ user-select: none; pointer-events: none; background-image: linear-gradient(to right, $euiColorMediumShade 1px, transparent 1px), - linear-gradient(to bottom, $euiColorMediumShade 1px, transparent 1px); + linear-gradient(to bottom, $euiColorMediumShade 1px, transparent 1px); background-size: 50px 50px; top: 0; } diff --git a/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss index 0392e1983df578..ac6838da97fbd1 100644 --- a/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss +++ b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss @@ -19,4 +19,4 @@ .euiHealth { width: 100%; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/x-pack/plugins/canvas/public/style/main.scss b/x-pack/plugins/canvas/public/style/main.scss index 4387557cbc9f25..4f293e9072e4f7 100644 --- a/x-pack/plugins/canvas/public/style/main.scss +++ b/x-pack/plugins/canvas/public/style/main.scss @@ -3,7 +3,6 @@ */ $canvasElementCardWidth: 210px; - .canvas.canvasContainerWrapper { display: flex; flex-grow: 1; diff --git a/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.module.scss index d7a38d0fc59160..54f5983bd2e5a0 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.module.scss +++ b/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.module.scss @@ -10,7 +10,7 @@ } :global .kbnCanvas :local .bar { - transition: bottom 0.25s; + transition: bottom .25s; padding: $euiSizeM; } diff --git a/x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss index ce857f37b904a7..a8b602d40e8cd8 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss +++ b/x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss @@ -9,7 +9,7 @@ left: 0; right: 0; padding: $euiSizeS 0 ($euiSizeL * 2) 0; - transition: bottom 0.25s; + transition: bottom .25s; height: 172px; } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss index 15509b98d465be..80d60e2de67e2f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.scss @@ -2,7 +2,7 @@ font-size: $euiFontSizeS; line-height: $euiLineHeight; display: grid; - grid-template-columns: 0.85fr $euiSizeXL 1fr; + grid-template-columns: .85fr $euiSizeXL 1fr; grid-gap: $euiSizeXS; &__separator { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.scss b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.scss index d6b6bd34425906..71f16a830e5f84 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.scss +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.scss @@ -10,7 +10,7 @@ &__imageContainer { max-height: 115px; overflow: hidden; - background-color: #0076cc; + background-color: #0076CC; @include euiBreakpoint('s', 'm', 'l', 'xl') { max-height: none; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss index e867e9cf5a445b..d46696d9f978c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/layout.scss @@ -32,7 +32,7 @@ position: absolute; right: $euiSize; top: $sideBarMobileHeight / 2; - transform: translateY(-50%) scale(0.9); + transform: translateY(-50%) scale(.9); .euiButton { min-width: 0; @@ -52,7 +52,7 @@ width: $sideBarWidth; background-color: $euiColorLightestShade; - box-shadow: inset (-1 * $euiSizeXS) 0 $euiSizeS (-1 * $euiSizeXS) rgba($euiShadowColor, 0.25); + box-shadow: inset (-1 * $euiSizeXS) 0 $euiSizeS (-1 * $euiSizeXS) rgba($euiShadowColor, .25); @include euiBreakpoint('xs', 's', 'm') { position: relative; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss index 79cd7634cfaa02..84b5c8cdd40f7c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/side_nav.scss @@ -52,7 +52,7 @@ $euiSizeML: $euiSize * 1.25; // 20px - between medium and large ¯\_(ツ)_/¯ font-weight: $euiFontWeightMedium; line-height: $euiFontSizeM; - $activeBgColor: rgba($euiColorFullShade, 0.05); + $activeBgColor: rgba($euiColorFullShade, .05); &--isActive { background-color: $activeBgColor; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncated_content.scss b/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncated_content.scss index 701834acfed9dd..890d7a331cc5b1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncated_content.scss +++ b/x-pack/plugins/enterprise_search/public/applications/shared/truncate/truncated_content.scss @@ -23,7 +23,7 @@ padding: 0 2px; display: none; align-items: center; - box-shadow: 0 1px 3px rgba(black, 0.1); + box-shadow: 0 1px 3px $euiColorInk; border: 1px solid $euiBorderColor; width: auto; white-space: nowrap; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.scss b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.scss index f295194b7a130a..4cc9263d1747cf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.scss +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/license_badge/license_badge.scss @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -.wsLicenseBadge { - &__text { - color: white; - } +.wsLicenseBadge__text { + color: $euiColorGhost; } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.scss b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.scss index a47abba723fc81..bd061d6d00760a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.scss +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/user_icon/user_icon.scss @@ -24,7 +24,7 @@ } &__text { - text-shadow: 0 1px 2px rgba(black, 0.08); + text-shadow: 0 1px 2px rgba($euiColorInk, .08); justify-content: center; align-items: center; font-size: 1.125rem; @@ -81,7 +81,7 @@ font-weight: 500; color: $euiColorEmptyShade; font-size: .875rem; - text-shadow: 0 1px 2px rgba(black, 0.08); + text-shadow: 0 1px 2px rgba($euiColorInk, .08); } &__image { @@ -105,8 +105,8 @@ display: flex; flex-direction: column; align-items: flex-start; - box-shadow: 0px 0px 12px rgba(black, 0.15); - background: white; + box-shadow: 0 0 12px rgba($euiColorInk, .15); + background: $euiColorGhost; text-align: left; text-overflow: ellipsis; min-width: 125px; @@ -130,7 +130,7 @@ position:absolute; border-left: 6px solid transparent; border-right: 6px solid transparent; - border-bottom: 6px solid white; + border-bottom: 6px solid $euiColorGhost; top: -6px; left: 16px; } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss index 27935104f4ef64..af8c850f275b61 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings.scss @@ -8,16 +8,16 @@ // Custom Source display settings // -------------------------------------------------- -@mixin source_name { +@mixin sourceName { font-size: .6875em; text-transform: uppercase; font-weight: 600; - letter-spacing: 0.06em; + letter-spacing: .06em; } -@mixin example_result_box_shadow { +@mixin exampleResultBoxShadow { box-shadow: - 0 1px 3px rgba(black, 0.1), + 0 1px 3px rgba($euiColorInk, .1), 0 0 20px $euiColorLightestShade; } @@ -82,7 +82,7 @@ .example-standout-result { border-radius: 4px; overflow: hidden; - @include example_result_box_shadow; + @include exampleResultBoxShadow; &__header, &__content { @@ -97,7 +97,7 @@ &__source-name { line-height: 34px; - @include source_name; + @include sourceName; } } @@ -116,7 +116,7 @@ &__source-name { line-height: 1.75em; - @include source_name; + @include sourceName; } &__content { @@ -171,7 +171,7 @@ } .example-result-detail-card { - @include example_result_box_shadow; + @include exampleResultBoxShadow; &__header { position: relative; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.scss b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.scss index fbd4e6f87d19be..d8c70e45112c12 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.scss +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.scss @@ -35,7 +35,7 @@ color: $euiColorFullShade; box-shadow: inset 0 0 0 1px $euiColorLightShade, - 0 2px 4px rgba(black, .05); + 0 2px 4px rgba($euiColorInk, .05); } &:after { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.scss b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.scss index 2d1e474c03faaa..36016d8da93ba7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.scss +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/recent_activity.scss @@ -13,13 +13,13 @@ &--error { font-weight: $euiFontWeightSemiBold; color: $euiColorDanger; - background: rgba($euiColorDanger, 0.1); + background: rgba($euiColorDanger, .1); &__label { margin-left: $euiSizeS * 1.75; font-weight: $euiFontWeightRegular; text-decoration: underline; - opacity: 0.7; + opacity: .7; } } diff --git a/x-pack/plugins/graph/public/_main.scss b/x-pack/plugins/graph/public/_main.scss index 0d17015385292c..6b32de32c06d00 100644 --- a/x-pack/plugins/graph/public/_main.scss +++ b/x-pack/plugins/graph/public/_main.scss @@ -20,7 +20,7 @@ * Utilities */ -.gphNoUserSelect{ +.gphNoUserSelect { user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; diff --git a/x-pack/plugins/graph/public/angular/templates/_graph.scss b/x-pack/plugins/graph/public/angular/templates/_graph.scss index 4ba65e7ec6b96a..5c2f5d5f7a8814 100644 --- a/x-pack/plugins/graph/public/angular/templates/_graph.scss +++ b/x-pack/plugins/graph/public/angular/templates/_graph.scss @@ -11,13 +11,12 @@ * 1. Calculated px values come from the open/closed state of the global nav sidebar */ - - #graphBasic { - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; - } +#graphBasic { + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; +} .gphGraph__container { display: flex; diff --git a/x-pack/plugins/graph/public/angular/templates/_sidebar.scss b/x-pack/plugins/graph/public/angular/templates/_sidebar.scss index e54158e2ad8ce3..e784649b250fa9 100644 --- a/x-pack/plugins/graph/public/angular/templates/_sidebar.scss +++ b/x-pack/plugins/graph/public/angular/templates/_sidebar.scss @@ -17,7 +17,7 @@ } } -.gphSidebar__header{ +.gphSidebar__header { margin-top: $euiSizeS; color: $euiColorEmptyShade; background-color: $euiColorDarkShade; @@ -26,7 +26,7 @@ margin-bottom: $euiSizeXS; } -.gphSidebar__panel{ +.gphSidebar__panel { max-height: $euiSizeL * 10; overflow-y: hidden auto; } diff --git a/x-pack/plugins/graph/public/components/field_manager/_field_editor.scss b/x-pack/plugins/graph/public/components/field_manager/_field_editor.scss index 381d4778cf13b9..20773d98ce9c31 100644 --- a/x-pack/plugins/graph/public/components/field_manager/_field_editor.scss +++ b/x-pack/plugins/graph/public/components/field_manager/_field_editor.scss @@ -4,7 +4,7 @@ .gphFieldEditor__badge--disabled, .gphFieldEditor__badge--disabled:focus { - opacity: 0.7; + opacity: .7; text-decoration: line-through; } diff --git a/x-pack/plugins/graph/public/components/graph_visualization/_graph_visualization.scss b/x-pack/plugins/graph/public/components/graph_visualization/_graph_visualization.scss index 975e4e84d6b0da..caef2b6987dddd 100644 --- a/x-pack/plugins/graph/public/components/graph_visualization/_graph_visualization.scss +++ b/x-pack/plugins/graph/public/components/graph_visualization/_graph_visualization.scss @@ -13,16 +13,16 @@ fill: $euiColorMediumShade; stroke: $euiColorMediumShade; stroke-width: 2; - stroke-opacity: 0.5; + stroke-opacity: .5; &:hover { - stroke-opacity: 0.95; + stroke-opacity: .95; cursor: pointer; } &--selected { stroke: $euiColorDarkShade; - stroke-opacity: 0.95; + stroke-opacity: .95; } } @@ -54,7 +54,7 @@ fill: $euiColorMediumShade; &--selected { stroke-width: $euiSizeXS; - stroke: transparentize($euiColorPrimary, 0.25); + stroke: transparentize($euiColorPrimary, .25); } } diff --git a/x-pack/plugins/graph/public/components/legacy_icon/_legacy_icon.scss b/x-pack/plugins/graph/public/components/legacy_icon/_legacy_icon.scss index 56fc1b31a9ffaf..6e443d7105c53e 100644 --- a/x-pack/plugins/graph/public/components/legacy_icon/_legacy_icon.scss +++ b/x-pack/plugins/graph/public/components/legacy_icon/_legacy_icon.scss @@ -8,7 +8,7 @@ &--pickable { margin: $euiSizeXS; cursor: pointer; - opacity: 0.7; + opacity: .7; } &--pickable:hover, diff --git a/x-pack/plugins/graph/public/components/venn_diagram/_venn_diagram.scss b/x-pack/plugins/graph/public/components/venn_diagram/_venn_diagram.scss index 98b11112099e05..755eaca75664ac 100644 --- a/x-pack/plugins/graph/public/components/venn_diagram/_venn_diagram.scss +++ b/x-pack/plugins/graph/public/components/venn_diagram/_venn_diagram.scss @@ -1,9 +1,9 @@ .gphVennDiagram__left { fill: $euiColorDanger; - fill-opacity: 0.5; + fill-opacity: .5; } .gphVennDiagram__right { fill: $euiColorPrimary; - fill-opacity: 0.5; + fill-opacity: .5; } diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss index 8e196936e40732..c603224394919b 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates.scss @@ -1,5 +1,4 @@ - /** * [1] Will center vertically the empty search result */ diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.scss b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.scss index b454d8697c5fce..44ba20eed44aee 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.scss +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_list_item.scss @@ -1,5 +1,5 @@ .componentTemplatesListItem { - background-color: white; + background-color: $euiColorGhost; padding: $euiSizeM; border-bottom: $euiBorderThin; position: relative; @@ -8,7 +8,7 @@ &--selected { &::before { content: ''; - background-color: rgba(255, 255, 255, 0.7); + background-color: rgba(255, 255, 255, .7); height: 100%; left: 0; position: absolute; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss index aeccc6a513fe29..db16b14071aea4 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_selector/component_templates_selector.scss @@ -32,10 +32,10 @@ &__count { font-weight: 600; } - } + } - &__content { - mask-image: none; - } + &__content { + mask-image: none; + } } } diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/_index.scss b/x-pack/plugins/index_management/public/application/components/mappings_editor/_index.scss index f8c1b5e0869934..8e8ca5c5718609 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/_index.scss +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/_index.scss @@ -49,67 +49,67 @@ .mappingsEditor__fieldsList { .mappingsEditor__fieldsList .mappingsEditor__fieldsListItem__content, .mappingsEditor__createFieldContent { - &::before { - border-bottom: 1px solid $euiColorMediumShade; - content: ''; - left: $euiSize; - position: absolute; - top: 50%; - width: $euiSizeS; - } - &::after { - border-left: 1px solid $euiColorMediumShade; - content: ''; - left: $euiSize; - position: absolute; - top: calc(50% - #{$euiSizeS}); - height: $euiSizeS; - } + &::before { + border-bottom: 1px solid $euiColorMediumShade; + content: ''; + left: $euiSize; + position: absolute; + top: 50%; + width: $euiSizeS; } - - .mappingsEditor__createFieldContent { - padding-left: $euiSizeXXL - $euiSizeXS; // [1] + &::after { + border-left: 1px solid $euiColorMediumShade; + content: ''; + left: $euiSize; + position: absolute; + top: calc(50% - #{$euiSizeS}); + height: $euiSizeS; } + } - .mappingsEditor__createFieldWrapper { - &--multiField { - .mappingsEditor__createFieldContent { - padding-left: $euiSize; - } + .mappingsEditor__createFieldContent { + padding-left: $euiSizeXXL - $euiSizeXS; // [1] + } - .mappingsEditor__createFieldContent { - &::before, &::after { - content: none; - } - } - } + .mappingsEditor__createFieldWrapper { + &--multiField { - &--toggle { - .mappingsEditor__createFieldContent { - padding-left: $euiSizeXXL - $euiSizeXS; // [1] - } - } - } - - .mappingsEditor__fieldsList .mappingsEditor__fieldsListItem__content { - padding-left: $euiSizeXL; // [2] + .mappingsEditor__createFieldContent { + padding-left: $euiSize; - &--toggle, &--multiField { &::before, &::after { content: none; } } + } - &--toggle { - padding-left: 0; + &--toggle { + .mappingsEditor__createFieldContent { + padding-left: $euiSizeXXL - $euiSizeXS; // [1] } + } + } - &--multiField { - padding-left: $euiSizeS; + .mappingsEditor__fieldsList .mappingsEditor__fieldsListItem__content { + padding-left: $euiSizeXL; // [2] + + &--toggle, &--multiField { + &::before, &::after { + content: none; } } + + &--toggle { + padding-left: 0; + } + + &--multiField { + padding-left: $euiSizeS; + } + } } +// stylelint-disable selector-no-qualifying-type ul.esUiTree { padding: 0; margin: 0; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss index e117271dba309b..cc733972808e3e 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss @@ -29,7 +29,7 @@ } .mappingsEditor__fieldsListItem__field--dim { - opacity: 0.3; + opacity: .3; &:hover { background-color: initial; diff --git a/x-pack/plugins/index_management/public/index.scss b/x-pack/plugins/index_management/public/index.scss index 02686c4f7d6f34..11074af372f8c1 100644 --- a/x-pack/plugins/index_management/public/index.scss +++ b/x-pack/plugins/index_management/public/index.scss @@ -11,7 +11,7 @@ .indTable { // The index table is a bespoke table and can't make use of EuiBasicTable's width settings - thead th.indTable__header--name { + thead th.indTable__header--name { // stylelint-disable-line selector-no-qualifying-type width: 25%; } diff --git a/x-pack/plugins/infra/public/index.scss b/x-pack/plugins/infra/public/index.scss index a3d74e3afebe39..990092c792b145 100644 --- a/x-pack/plugins/infra/public/index.scss +++ b/x-pack/plugins/infra/public/index.scss @@ -14,4 +14,3 @@ display: flex; flex-direction: column; } - diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss index f1e399428cdf29..b04020cb59c696 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss @@ -31,7 +31,7 @@ } } $dropZoneButtonHeight: 60px; - $dropZoneButtonOffsetY: $dropZoneButtonHeight * 0.5; + $dropZoneButtonOffsetY: $dropZoneButtonHeight * .5; &__dropZoneButton { position: absolute; diff --git a/x-pack/plugins/lens/public/_mixins.scss b/x-pack/plugins/lens/public/_mixins.scss index 0db72d118cef14..f9b8ce466040e5 100644 --- a/x-pack/plugins/lens/public/_mixins.scss +++ b/x-pack/plugins/lens/public/_mixins.scss @@ -5,10 +5,10 @@ $hideHeight: $euiScrollBarCorner * 1.25; mask-image: linear-gradient( to right, - transparentize(red, .9) 0%, - transparentize(red, 0) $hideHeight, - transparentize(red, 0) calc(100% - #{$hideHeight}), - transparentize(red, .9) 100% + transparentize($euiColorDanger, .9) 0%, + transparentize($euiColorDanger, 0) $hideHeight, + transparentize($euiColorDanger, 0) calc(100% - #{$hideHeight}), + transparentize($euiColorDanger, .9) 100% ); } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss index e0031d051df819..0a4f7b0debf22b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss @@ -12,7 +12,7 @@ } // Targeting img as this won't target normal EuiIcon's only the custom svgs's -img.lnsChartSwitch__chartIcon { // sass-lint:disable-line no-qualifying-elements +img.lnsChartSwitch__chartIcon { // stylelint-disable-line selector-no-qualifying-type // The large icons aren't square so max out the width to fill the height width: 100%; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss index 15464bb204f17e..715d15e99ec201 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss @@ -38,5 +38,3 @@ margin-right: $euiSizeS; } } - - diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/color/_color_stops.scss b/x-pack/plugins/maps/public/classes/styles/vector/components/color/_color_stops.scss index 09a9ad59bce3c9..e927894957dd84 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/color/_color_stops.scss +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/color/_color_stops.scss @@ -5,4 +5,3 @@ margin-top: $euiSizeS; } } - diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss index d260f6effb2cb3..2d6d1837cfb0bd 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss @@ -1,4 +1,4 @@ -.vectorStyleLegendSpacer { +.vectorStyleLegendSpacer { &:not(:last-child) { margin-bottom: $euiSizeS; } diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/_mixins.scss b/x-pack/plugins/maps/public/connected_components/widget_overlay/_mixins.scss index 88ae78fde6ace4..97557f1312e861 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/_mixins.scss +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/_mixins.scss @@ -1,12 +1,8 @@ @mixin mapOverlayIsTextOnly { text-shadow: - 0 0 2px $euiColorEmptyShade, - // Multiple shadows helps turn it into an outline since - // text shadows have no spread value - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade, - 0 0 1px $euiColorEmptyShade; + 0 0 2px $euiColorEmptyShade, + 0 0 1px $euiColorEmptyShade, + 0 0 1px $euiColorEmptyShade, + 0 0 1px $euiColorEmptyShade, + 0 0 1px $euiColorEmptyShade 0 0 1px $euiColorEmptyShade 0 0 1px $euiColorEmptyShade; } diff --git a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/_toc_entry.scss b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/_toc_entry.scss index 764bf841f62072..53e5d2e0bb6b64 100644 --- a/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/_toc_entry.scss +++ b/x-pack/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/toc_entry/_toc_entry.scss @@ -45,7 +45,6 @@ background-color: tintOrShade($euiColorLightShade, 60%, 20%); } - .mapTocEntry-visible, .mapTocEntry-notVisible { display: flex; diff --git a/x-pack/plugins/ml/public/application/_variables.scss b/x-pack/plugins/ml/public/application/_variables.scss index 159a1ffd45dd50..761b266cac189d 100644 --- a/x-pack/plugins/ml/public/application/_variables.scss +++ b/x-pack/plugins/ml/public/application/_variables.scss @@ -1,8 +1,8 @@ -$mlColorCritical: #fe5050; -$mlColorMajor: #fba740; -$mlColorMinor: #fdec25; -$mlColorWarning: #8bc8fb; -$mlColorUnknown: #c0c0c0; +$mlColorCritical: #FE5050; +$mlColorMajor: #FBA740; +$mlColorMinor: #FDEC25; +$mlColorWarning: #8BC8FB; +$mlColorUnknown: #C0C0C0; $mlColorCriticalText: makeHighContrastColor($mlColorCritical, $euiColorEmptyShade); $mlColorMajorText: makeHighContrastColor($mlColorMajor, $euiColorEmptyShade); diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss b/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss index e95eabdf510ad9..813fbdcbe6f1f6 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss @@ -1,4 +1,4 @@ - // SASSTODO: This file has several direct EUI overwrites that need to be removed +// SASSTODO: This file has several direct EUI overwrites that need to be removed .ml-anomalies-table { .ml-icon-severity-critical, .ml-icon-severity-major, @@ -53,7 +53,7 @@ .detector-rules-icon { margin-left: $euiSizeXS; - opacity: 0.5; + opacity: .5; } } @@ -98,7 +98,7 @@ .anomaly-description-list { .euiDescriptionList__title { - margin-top: 0px; + margin-top: 0; flex-basis: 15%; font-size: inherit; line-height: 1.5rem; @@ -106,7 +106,7 @@ } .euiDescriptionList__description { - margin-top: 0px; + margin-top: 0; flex-basis: 85%; font-size: inherit; line-height: 1.5rem; @@ -116,4 +116,3 @@ } } - diff --git a/x-pack/plugins/ml/public/application/components/chart_tooltip/_chart_tooltip.scss b/x-pack/plugins/ml/public/application/components/chart_tooltip/_chart_tooltip.scss index 25be39f3ea2d75..4e04edd2e8e73a 100644 --- a/x-pack/plugins/ml/public/application/components/chart_tooltip/_chart_tooltip.scss +++ b/x-pack/plugins/ml/public/application/components/chart_tooltip/_chart_tooltip.scss @@ -35,7 +35,7 @@ } &__rowHighlighted { - background-color: transparentize($euiColorGhost, 0.9); + background-color: transparentize($euiColorGhost, .9); } &--hidden { diff --git a/x-pack/plugins/ml/public/application/components/controls/_controls.scss b/x-pack/plugins/ml/public/application/components/controls/_controls.scss index 2b46e2d2cd35d3..d491e88dffa240 100644 --- a/x-pack/plugins/ml/public/application/components/controls/_controls.scss +++ b/x-pack/plugins/ml/public/application/components/controls/_controls.scss @@ -1,7 +1,7 @@ .ml-table-controls { label { font-size: $euiFontSizeXS; - padding: 0px 0px $euiSizeXS $euiSizeXS; + padding: 0 0 $euiSizeXS $euiSizeXS; } .ml-table-controls-element { diff --git a/x-pack/plugins/ml/public/application/components/data_grid/column_chart.scss b/x-pack/plugins/ml/public/application/components/data_grid/column_chart.scss index 37d8871ab3562f..e07c8a7b81692d 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/column_chart.scss +++ b/x-pack/plugins/ml/public/application/components/data_grid/column_chart.scss @@ -10,7 +10,7 @@ color: $euiColorMediumShade; display: block; overflow-x: hidden; - margin: $euiSizeXS 0px 0px 0px; + margin: $euiSizeXS 0 0 0; font-style: italic; font-weight: normal; text-align: left; diff --git a/x-pack/plugins/ml/public/application/components/data_grid/data_grid.scss b/x-pack/plugins/ml/public/application/components/data_grid/data_grid.scss index 2e2f4e7af0a258..f6958ef66770e7 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/data_grid.scss +++ b/x-pack/plugins/ml/public/application/components/data_grid/data_grid.scss @@ -3,4 +3,3 @@ text-transform: none; } } - diff --git a/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.scss b/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.scss index 34b181723df107..60c1a0820fbc90 100644 --- a/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.scss +++ b/x-pack/plugins/ml/public/application/components/entity_cell/entity_cell.scss @@ -9,7 +9,7 @@ } .filter-button { - opacity: 0.3; + opacity: .3; min-width: 14px; -webkit-transform: translateY(-1px); transform: translateY(-1px); diff --git a/x-pack/plugins/ml/public/application/components/influencers_list/_influencers_list.scss b/x-pack/plugins/ml/public/application/components/influencers_list/_influencers_list.scss index e4bb9c22fda82b..d2d57544de41a8 100644 --- a/x-pack/plugins/ml/public/application/components/influencers_list/_influencers_list.scss +++ b/x-pack/plugins/ml/public/application/components/influencers_list/_influencers_list.scss @@ -19,7 +19,7 @@ width: calc(100% - 34px); // SASSTODO: Calc proper value height: 22px; min-width: 70px; - margin-bottom: 0px; + margin-bottom: 0; color: $euiColorDarkShade; background-color: transparent; diff --git a/x-pack/plugins/ml/public/application/components/job_selector/_job_selector.scss b/x-pack/plugins/ml/public/application/components/job_selector/_job_selector.scss index d8d0f87a589a0b..5cf57358b57ea9 100644 --- a/x-pack/plugins/ml/public/application/components/job_selector/_job_selector.scss +++ b/x-pack/plugins/ml/public/application/components/job_selector/_job_selector.scss @@ -7,33 +7,33 @@ } .mlJobSelector__ganttBar { - background-color: #79adda; + background-color: #79ADDA; height: $euiSizeM; border-radius: 2px; } .mlJobSelector__ganttBarBackEdge { height: $euiSize; - border-left: 1px solid #d6d6d6; - border-right: 1px solid #d6d6d6; + border-left: 1px solid #D6D6D6; + border-right: 1px solid #D6D6D6; margin-bottom: -14px; padding-top: $euiSizeS; } .mlJobSelector__ganttBarDashed { height: 1px; - border-top: 1px dashed #d6d6d6; + border-top: 1px dashed #D6D6D6; } .mlJobSelector__ganttBarRunning { background-image: linear-gradient(45deg, - rgba(255, 255, 255, 0.15) 25%, - transparent 25%, - transparent 50%, - rgba(255, 255, 255, 0.15) 50%, - rgba(255, 255, 255, 0.15) 75%, - transparent 75%, - transparent); + rgba(255, 255, 255, .15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, .15) 50%, + rgba(255, 255, 255, .15) 75%, + transparent 75%, + transparent); background-size: $euiSizeXXL $euiSizeXXL; animation: progress-bar-stripes 2s linear infinite; } diff --git a/x-pack/plugins/ml/public/application/components/rule_editor/_rule_editor.scss b/x-pack/plugins/ml/public/application/components/rule_editor/_rule_editor.scss index d033a255a3d16f..26767dd1e24dba 100644 --- a/x-pack/plugins/ml/public/application/components/rule_editor/_rule_editor.scss +++ b/x-pack/plugins/ml/public/application/components/rule_editor/_rule_editor.scss @@ -7,13 +7,13 @@ } .select-rule-action-panel { - padding: $euiSizeS 0px; + padding: $euiSizeS 0; // SASSTODO: Dangerous EUI overwrite .euiDescriptionList { .euiDescriptionList__title { flex-basis: 15%; - padding: 0px $euiSize; + padding: 0 $euiSize; } .euiDescriptionList__description { @@ -70,7 +70,7 @@ .condition-edit-value-field { width: 170px; height: 28px; - margin: 0px 2px; + margin: 0 2px; input { height: 28px; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss index 83d48c452d927b..d1c507c5241d5f 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/_classification_exploration.scss @@ -15,7 +15,7 @@ and just uses a legacy approach for a two column layout so we don't break IE11. */ .mlDataFrameAnalyticsClassification__confusionMatrix:after { - content: ""; + content: ''; display: table; clear: both; } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_messages_pane.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_messages_pane.scss index 5a4d1b3190402d..9a169f6856f397 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_messages_pane.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_messages_pane.scss @@ -6,4 +6,3 @@ .mlExpandedRowJobMessages .euiTable, .mlExpandedRowJobMessages .euiTableRowCell { background-color: transparent !important; } - diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/experimental_badge/_experimental_badge.scss b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/experimental_badge/_experimental_badge.scss index 4c90d6beed51ae..016d5cd579e3fc 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/experimental_badge/_experimental_badge.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/experimental_badge/_experimental_badge.scss @@ -2,6 +2,6 @@ font-size: 10px; vertical-align: middle; margin-bottom: 5px; - padding: 0px 20px; + padding: 0 20px; line-height: 20px; } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss index f6851fcb8eca4c..d0af6d3f01d2f2 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss @@ -1,7 +1,7 @@ .card-container { display: inline-grid; display: -ms-inline-grid; - padding: 0px 10px 10px 0px; + padding: 0 10px 10px 0; } .ml-field-data-card { @@ -70,7 +70,7 @@ } .stat.heading { - padding-bottom: 0px; + padding-bottom: 0; } .stat.min, @@ -92,7 +92,7 @@ } .not-exist-message { - padding: 50px 30px 0px 30px; + padding: 50px 30px 0 30px; text-align: center; } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_fields_stats.scss b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_fields_stats.scss index ac04fad0ef3e33..5decacfe1b7b87 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_fields_stats.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_fields_stats.scss @@ -4,5 +4,3 @@ .field { margin-bottom: 10px; } - - diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_view/_results_view.scss b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_view/_results_view.scss index 6f5c2826515e63..1c5ea1dd26fd73 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_view/_results_view.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_view/_results_view.scss @@ -1,10 +1,10 @@ .results { - .euiDescriptionList{ + .euiDescriptionList { dd, dt { margin-top: 5px; } dd:nth-child(1), dt:nth-child(1), { - margin-top: 0px; + margin-top: 0; } } } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss index 45c0937b6723a1..2ab26f1564a1fc 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss @@ -61,7 +61,7 @@ } .mlFieldDataCard__stats { - padding: $euiSizeS $euiSizeS 0px $euiSizeS; + padding: $euiSizeS $euiSizeS 0 $euiSizeS; text-align: center; } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/_index.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/_index.scss index 64545c886a112a..e9ecfc8b19100a 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/_index.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/_index.scss @@ -1,4 +1,4 @@ -@import "components/field_data_expanded_row/number_content"; +@import 'components/field_data_expanded_row/number_content'; .mlDataVisualizerFieldExpandedRow { padding-left: $euiSize * 4; @@ -19,15 +19,15 @@ .mlDataVisualizer { .euiTableRow > .euiTableRowCell { - border-bottom: 0px; + border-bottom: 0; border-top: $euiBorderThin; } .euiTableRow-isExpandedRow { - .euiTableRowCell{ + .euiTableRowCell { background-color: $euiColorEmptyShade !important; - border-top: 0px; + border-top: 0; border-bottom: $euiBorderThin; &:hover { background-color: $euiColorEmptyShade !important; @@ -35,12 +35,11 @@ } } .mlDataVisualizerSummaryTable { - .euiTableRow > .euiTableRowCell{ - border-bottom: 0px; + .euiTableRow > .euiTableRowCell { + border-bottom: 0; } .euiTableHeaderCell { display: none; } } } - diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_index.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_index.scss index 54fa24604f8f89..fdc591a140fea9 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_index.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_index.scss @@ -1 +1 @@ -@import "number_content"; +@import 'number_content'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_number_content.scss b/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_number_content.scss index 4b1da4b414045c..066f405b39cd68 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_number_content.scss +++ b/x-pack/plugins/ml/public/application/datavisualizer/stats_datagrid/components/field_data_expanded_row/_number_content.scss @@ -2,4 +2,3 @@ padding-top: $euiSizeXS; width: 100%; } - diff --git a/x-pack/plugins/ml/public/application/explorer/_explorer.scss b/x-pack/plugins/ml/public/application/explorer/_explorer.scss index d16a84a23c8135..c08020325428dd 100644 --- a/x-pack/plugins/ml/public/application/explorer/_explorer.scss +++ b/x-pack/plugins/ml/public/application/explorer/_explorer.scss @@ -11,7 +11,7 @@ $borderRadius: $euiBorderRadius / 2; } .results-container { - padding: 0px 0px $euiSize 0px; + padding: 0 0 $euiSize 0; // SASSTODO: Overwrite of bootstrap .col-xs-12 { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_chart.scss b/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_chart.scss index 32d589581929d5..c89c91b744cddd 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_chart.scss +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_chart.scss @@ -1,3 +1,4 @@ +// stylelint-disable selector-no-qualifying-type .ml-explorer-chart-container { overflow: hidden; @@ -12,10 +13,10 @@ } rect.selected-interval { - fill: rgba(200, 200, 200, 0.1); + fill: rgba(200, 200, 200, .1); stroke: $euiColorDarkShade; stroke-width: $euiSizeXS / 2; - stroke-opacity: 0.8; + stroke-opacity: .8; } rect.scheduled-event-marker { @@ -34,7 +35,7 @@ } .axis .tick line.ml-tick-emphasis { - stroke: rgba(0, 0, 0, 0.2); + stroke: rgba(0, 0, 0, .2); } .axis text { @@ -42,46 +43,41 @@ } .axis .tick line { - stroke: rgba(0, 0, 0, 0.05); + stroke: rgba(0, 0, 0, .05); stroke-width: 1px; } .values-line { fill: none; - stroke: #32a7c2; + stroke: #32A7C2; stroke-width: 2; } .values-dots circle, .values-dots-circle { - fill: #32a7c2; + fill: #32A7C2; stroke-width: 0; } .values-dots circle.values-dots-circle-blur { - fill: #aaa; - } - - .metric-value { - opacity: 1; - fill: #32a7c2; + fill: #AAA; } .metric-value { opacity: 1; fill: transparent; - stroke: #32a7c2; - stroke-width: 0px; + stroke: #32A7C2; + stroke-width: 0; } .anomaly-marker { stroke-width: 1px; - stroke: #aaaaaa; + stroke: #AAAAAA; } .anomaly-marker:hover { stroke-width: 6px; - stroke: #32a7c2; + stroke: #32A7C2; } .anomaly-marker.critical { @@ -101,13 +97,13 @@ } .anomaly-marker.low { - fill: #d2e9f7; + fill: #D2E9F7; } .metric-value:hover, .anomaly-marker:hover { stroke-width: 6px; - stroke-opacity: 0.65; + stroke-opacity: .65; } } diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_charts_container.scss b/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_charts_container.scss index 13eb6da97131a0..cc94e122254e3e 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_charts_container.scss +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/_explorer_charts_container.scss @@ -16,7 +16,7 @@ .chart-controls { label { - padding: 0px 0px 10px 0px; + padding: 0 0 10px 0; } } @@ -37,7 +37,7 @@ font-size: $euiFontSizeXS; td { - padding: 0px 0px 2px 0px; + padding: 0 0 2px 0; } table tr > td:first-child { diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss index a625b1274c9b42..7018a991ce1dca 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss @@ -3,6 +3,6 @@ position: relative; float: right; top: -$euiSizeXS; - right: 0px; + right: 0; } } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss index 1f68ec67ded471..fe61be550ecace 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss @@ -22,20 +22,20 @@ background-color: $euiColorLightestShade; border: 1px solid $euiColorLightShade; border-radius: $euiBorderRadius; - margin: $euiSizeXS 0px; + margin: $euiSizeXS 0; .euiTable { background-color: transparent; .euiTableRow:first-child { .euiTableRowCell { - border-top: 0px; + border-top: 0; } } .euiTableRow:last-child { .euiTableRowCell { - border-bottom: 0px; + border-bottom: 0; } } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss index 92c3ae53cbeee0..ecea309314dced 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss @@ -15,7 +15,7 @@ text-decoration: none; .inline-group { border: 1px solid $euiColorDarkShade; - box-shadow: 0px 1px 2px $euiColorMediumShade; + box-shadow: 0 1px 2px $euiColorMediumShade; } } } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss index 665f0a746e4a2d..fc5bce54afb6a8 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss @@ -4,7 +4,7 @@ padding: 2px 5px; border-radius: 2px; display: inline-block; - margin: 0px 3px; + margin: 0 3px; color: $euiColorEmptyShade; vertical-align: text-top; } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/_jobs_list.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/_jobs_list.scss index 421aa28cb9bf9d..28b1a4259406af 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/_jobs_list.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/_jobs_list.scss @@ -45,7 +45,7 @@ & > tbody { td:nth-child(4) .euiTableCellContent { - padding: 0px; + padding: 0; } td:nth-child(10) { @@ -68,10 +68,10 @@ } .euiContextMenuPanel { - .euiContextMenuItem { - white-space: nowrap; - } - .euiContextMenuItem:last-child:not(.euiContextMenuItem-isDisabled) { + .euiContextMenuItem { + white-space: nowrap; + } + .euiContextMenuItem:last-child:not(.euiContextMenuItem-isDisabled) { color: $euiColorDanger; } } @@ -94,7 +94,7 @@ width: 1px; display: inline-block; vertical-align: middle; - margin: 0px $euiSizeXS; + margin: 0 $euiSizeXS; } .job-description { diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/_multi_job_actions.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/_multi_job_actions.scss index 4298ce2691b688..131e4ea12ce50f 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/_multi_job_actions.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/_multi_job_actions.scss @@ -1,4 +1,4 @@ - // SASSTODO: This looks like it needs some rewriting for all the pixel values +// SASSTODO: This looks like it needs some rewriting for all the pixel values .multi-select-actions { padding-right: $euiSizeS; padding-bottom: $euiSizeM; @@ -11,15 +11,14 @@ width: 1px; display: inline-block; vertical-align: middle; - margin: 0px 5px; + margin: 0 5px; } .actions-border-large { height: 35px; - margin: 0px 15px; + margin: 0 15px; margin-top: -5px; } - .results-button { margin-right: 5px; } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/group_list/_group_list.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/group_list/_group_list.scss index a0d4ed68fa3230..b4fd5786fa2d9b 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/group_list/_group_list.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/group_list/_group_list.scss @@ -1,21 +1,21 @@ - // SASSTODO: proper calcs all through this. Replace shadows +// SASSTODO: proper calcs all through this. Replace shadows .group-list { max-height: 350px; overflow: auto; .group-item { line-height: 18px; - padding: 6px 0px; + padding: 6px 0; border-bottom: $euiBorderThin; cursor: pointer; &:focus { - background-color: #eef6f9; + background-color: #EEF6F9; box-shadow: none; } .check { - // SASSTODO: proper calc + // SASSTODO: proper calc width: 20px; display: inline-block; } @@ -28,13 +28,13 @@ .group-item:hover { .inline-group { border: 1px solid $euiColorDarkShade; - // SASSTODO: Replace with eui shadow mixin - box-shadow: 0px 1px 2px $euiColorMediumShade; + // SASSTODO: Replace with eui shadow mixin + box-shadow: 0 1px 2px $euiColorMediumShade; } } .group-item:last-child { - margin-bottom: 0px; + margin-bottom: 0; border-bottom: none; } } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/new_group_input/_new_group_input.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/new_group_input/_new_group_input.scss index 943fc78a9d0faf..1c5a66d049e0ee 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/new_group_input/_new_group_input.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/new_group_input/_new_group_input.scss @@ -1,3 +1,3 @@ .new-group-input { - padding-bottom: 0px; + padding-bottom: 0; } \ No newline at end of file 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 ac20a6abcc6949..d946a0cf940320 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 @@ -1,3 +1,4 @@ +// stylelint-disable selector-no-qualifying-type // SASSTODO: Looks like this could use a rewrite. Needs selectors .time-range-selector { .time-range-section-container { @@ -9,7 +10,7 @@ } .time-range-section { flex: 50%; - padding: 0px $euiSizeS; + padding: 0 $euiSizeS; border-right: $euiBorderThin; } @@ -47,12 +48,12 @@ display: block; } } - & > li.has-body.active { + & > li.has-body.active { & > a { - border-radius: $euiBorderRadius $euiBorderRadius 0px 0px; + border-radius: $euiBorderRadius $euiBorderRadius 0 0; } .react-datepicker { - border-radius: 0px 0px $euiBorderRadius $euiBorderRadius; + border-radius: 0 0 $euiBorderRadius $euiBorderRadius; border-top: none; } } diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_buttons.scss b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_buttons.scss index d235c832ffaf1e..584d8ca5bdb371 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_buttons.scss +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_buttons.scss @@ -1,8 +1,6 @@ // Refresh button style -.managementJobsList{ +.managementJobsList { clear: both; } - - diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_expanded_row.scss b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_expanded_row.scss index aeddbbd1a51082..1909b597dfe9c8 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_expanded_row.scss +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_expanded_row.scss @@ -23,20 +23,20 @@ background-color: $euiColorLightestShade; border: 1px solid $euiColorLightShade; border-radius: $euiBorderRadius; - margin: $euiSizeXS 0px; + margin: $euiSizeXS 0; .euiTable { background-color: transparent; .euiTableRow:first-child { .euiTableRowCell { - border-top: 0px; + border-top: 0; } } .euiTableRow:last-child { .euiTableRowCell { - border-bottom: 0px; + border-bottom: 0; } } diff --git a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_stats_bar.scss b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_stats_bar.scss index 05315fb4148deb..b35f9afb42fdf4 100644 --- a/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_stats_bar.scss +++ b/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/_stats_bar.scss @@ -14,4 +14,3 @@ padding: 14px; background-color: $euiColorLightestShade; } - diff --git a/x-pack/plugins/ml/public/application/settings/calendars/edit/_edit.scss b/x-pack/plugins/ml/public/application/settings/calendars/edit/_edit.scss index 4027f519bc9153..087b8e4638aed8 100644 --- a/x-pack/plugins/ml/public/application/settings/calendars/edit/_edit.scss +++ b/x-pack/plugins/ml/public/application/settings/calendars/edit/_edit.scss @@ -3,6 +3,6 @@ max-width: map-get($euiBreakpoints, 'xl'); width: 100%; margin-top: $euiSize; - margin-bottom: $euiSize; + margin-bottom: $euiSize; } } diff --git a/x-pack/plugins/ml/public/application/settings/filter_lists/_filter_lists.scss b/x-pack/plugins/ml/public/application/settings/filter_lists/_filter_lists.scss index c1d52875755780..8afa0fed51890d 100644 --- a/x-pack/plugins/ml/public/application/settings/filter_lists/_filter_lists.scss +++ b/x-pack/plugins/ml/public/application/settings/filter_lists/_filter_lists.scss @@ -13,4 +13,3 @@ } } - diff --git a/x-pack/plugins/ml/public/application/settings/filter_lists/edit/_edit.scss b/x-pack/plugins/ml/public/application/settings/filter_lists/edit/_edit.scss index 55978f1fb704a1..484dcb4f06b5a9 100644 --- a/x-pack/plugins/ml/public/application/settings/filter_lists/edit/_edit.scss +++ b/x-pack/plugins/ml/public/application/settings/filter_lists/edit/_edit.scss @@ -16,7 +16,7 @@ } .euiButtonEmpty .euiButtonEmpty__content { - padding: 0px $euiSizeXS; + padding: 0 $euiSizeXS; } } } diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss index 48774b98182265..af40e69af4124b 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss @@ -1,3 +1,4 @@ +// stylelint-disable selector-no-qualifying-type .ml-time-series-explorer { color: $euiColorDarkShade; @@ -64,7 +65,7 @@ } .axis .tick line { - stroke: rgba(0, 0, 0, 0.1); + stroke: rgba(0, 0, 0, .1); } .chart-border { @@ -88,24 +89,24 @@ } .area.bounds { - fill: rgba(50, 167, 194, 0.25); // Needs variable + fill: rgba(50, 167, 194, .25); // Needs variable pointer-events: none; } .values-line { fill: none; - stroke: #32a7c2; // Needs variable + stroke: #32A7C2; // Needs variable stroke-width: 2; pointer-events: none; } .values-line.forecast { - stroke: #cca300; // Needs variable + stroke: #CCA300; // Needs variable pointer-events: none; } .values-dots circle { - fill: #32a7c2; // Needs variable + fill: #32A7C2; // Needs variable stroke-width: 0; } @@ -114,20 +115,20 @@ } .area.forecast { - fill: rgba(204, 163, 0, 0.25); // Needs variable + fill: rgba(204, 163, 0, .25); // Needs variable pointer-events: none; } .metric-value { opacity: 1; fill: transparent; - stroke: #32a7c2; - stroke-width: 0px; + stroke: #32A7C2; + stroke-width: 0; } .anomaly-marker { stroke-width: 1px; - stroke: #aaaaaa; // Needs variable + stroke: #AAAAAA; // Needs variable } .anomaly-marker.critical { @@ -147,15 +148,15 @@ } .anomaly-marker.low { - fill: #d2e9f7; // Needs variable + fill: #D2E9F7; // Needs variable } .metric-value:hover, .anomaly-marker:hover, .anomaly-marker.highlighted { stroke-width: 6px; - stroke-opacity: 0.65; - stroke: #32a7c2; + stroke-opacity: .65; + stroke: #32A7C2; } rect.scheduled-event-marker { @@ -168,7 +169,7 @@ .forecast { .metric-value, .metric-value:hover { - stroke: #cca300; + stroke: #CCA300; } } @@ -214,7 +215,7 @@ } .area.context { - fill: rgba(50, 167, 194, 0.25); // Needs variable + fill: rgba(50, 167, 194, .25); // Needs variable } .values-line { @@ -222,25 +223,25 @@ } .area.context.forecast { - fill: rgba(204, 163, 0, 0.25); // Needs variable + fill: rgba(204, 163, 0, .25); // Needs variable } .mask { polygon { - fill-opacity: 0.1; + fill-opacity: .1; } .area.bounds { - fill: #d6d6d6; + fill: #D6D6D6; } .values-line { stroke-width: 1; - stroke: #b8b8b8; + stroke: #B8B8B8; } .values-dots circle { - fill: #b8b8b8; + fill: #B8B8B8; stroke-width: 0; } } @@ -255,12 +256,8 @@ } .brush .extent { - stroke: #aaaaaa; fill-opacity: 0; shape-rendering: crispEdges; - } - - .brush .extent { stroke: $euiColorDarkShade; stroke-width: 2; cursor: move; @@ -292,11 +289,11 @@ } div.brush-handle-inner-left { - border-radius: $euiBorderRadius 0px 0px $euiBorderRadius; + border-radius: $euiBorderRadius 0 0 $euiBorderRadius; } div.brush-handle-inner-right { - border-radius: 0px $euiBorderRadius $euiBorderRadius 0px; + border-radius: 0 $euiBorderRadius $euiBorderRadius 0; } rect.brush-handle { diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer_annotations.scss b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer_annotations.scss index 0c38d8e7ca1718..8c2d1391576026 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer_annotations.scss +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer_annotations.scss @@ -15,8 +15,8 @@ $mlAnnotationBorderWidth: 2px; // Instead of different EUI colors we use opacity settings // here to avoid opaque layers on top of existing chart elements. -$mlAnnotationRectDefaultStrokeOpacity: 0.2; -$mlAnnotationRectDefaultFillOpacity: 0.05; +$mlAnnotationRectDefaultStrokeOpacity: .2; +$mlAnnotationRectDefaultFillOpacity: .05; .mlAnnotationRect { stroke: $euiColorFullShade; @@ -32,7 +32,7 @@ $mlAnnotationRectDefaultFillOpacity: 0.05; } .mlAnnotationRect-isHighlight { - stroke-opacity: $mlAnnotationRectDefaultStrokeOpacity * 2;; + stroke-opacity: $mlAnnotationRectDefaultStrokeOpacity * 2; transition: stroke-opacity $euiAnimSpeedFast; fill-opacity: $mlAnnotationRectDefaultFillOpacity * 2; diff --git a/x-pack/plugins/observability/public/components/app/news_feed/index.scss b/x-pack/plugins/observability/public/components/app/news_feed/index.scss index 1222fe489c7329..82b1c88dc40386 100644 --- a/x-pack/plugins/observability/public/components/app/news_feed/index.scss +++ b/x-pack/plugins/observability/public/components/app/news_feed/index.scss @@ -1,3 +1,3 @@ -.obsNewsFeed__itemImg{ +.obsNewsFeed__itemImg { @include euiBottomShadowSmall; } \ No newline at end of file diff --git a/x-pack/plugins/remote_clusters/public/application/_hacks.scss b/x-pack/plugins/remote_clusters/public/application/_hacks.scss index b7d81885e716d0..fd974400a7936f 100644 --- a/x-pack/plugins/remote_clusters/public/application/_hacks.scss +++ b/x-pack/plugins/remote_clusters/public/application/_hacks.scss @@ -20,6 +20,6 @@ /** * 1. Prevent inherited flexbox layout from compressing this element on IE. */ - .remoteClustersConnectionStatus__message { +.remoteClustersConnectionStatus__message { flex-basis: auto !important; /* 1 */ } diff --git a/x-pack/plugins/searchprofiler/public/application/_app.scss b/x-pack/plugins/searchprofiler/public/application/_app.scss index dc48db9a8e751b..6a2d1eb5e2189c 100644 --- a/x-pack/plugins/searchprofiler/public/application/_app.scss +++ b/x-pack/plugins/searchprofiler/public/application/_app.scss @@ -37,19 +37,19 @@ $headerHeightOffset: $euiHeaderHeightCompensation * 3; flex-shrink: 1; } - .prfDevTool__main { - height: 100%; - order: 2; - margin-left: $euiSize; - display: flex; - overflow: hidden; - flex-direction: column; +.prfDevTool__main { + height: 100%; + order: 2; + margin-left: $euiSize; + display: flex; + overflow: hidden; + flex-direction: column; - // Make only the tab content scroll - .search-profiler-tabs { - flex-shrink: 0; - } + // Make only the tab content scroll + .search-profiler-tabs { + flex-shrink: 0; } +} @include euiPanel('.prfDevTool__main'); @@ -63,4 +63,3 @@ $headerHeightOffset: $euiHeaderHeightCompensation * 3; margin: $euiSize 0; } } - diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/_home.scss b/x-pack/plugins/snapshot_restore/public/application/sections/home/_home.scss index 741ee76985937e..468ada5c2712ad 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/_home.scss +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/_home.scss @@ -36,11 +36,11 @@ .snapshotRestorePolicyTableSnapshotFailureContainer { max-width: 200px; > .euiFlexItem:last-child { - min-width: 0; - .euiText { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } + min-width: 0; + .euiText { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } } } diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss b/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss index b235e9ebf7c21d..1b493e9e744907 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss @@ -4,7 +4,7 @@ .transform__steps { .euiStep__content { - padding-right: 0px; + padding-right: 0; } } diff --git a/yarn.lock b/yarn.lock index 8595ed43bf6d07..d8ea1d34b193ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,7 +83,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.7.5", "@babel/core@^7.9.0": +"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.7.5", "@babel/core@^7.9.0": version "7.11.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== @@ -4170,6 +4170,21 @@ resolve-from "^5.0.0" store2 "^2.7.1" +"@stylelint/postcss-css-in-js@^0.37.2": + version "0.37.2" + resolved "https://registry.yarnpkg.com/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz#7e5a84ad181f4234a2480803422a47b8749af3d2" + integrity sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA== + dependencies: + "@babel/core" ">=7.9.0" + +"@stylelint/postcss-markdown@^0.36.2": + version "0.36.2" + resolved "https://registry.yarnpkg.com/@stylelint/postcss-markdown/-/postcss-markdown-0.36.2.tgz#0a540c4692f8dcdfc13c8e352c17e7bfee2bb391" + integrity sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ== + dependencies: + remark "^13.0.0" + unist-util-find-all-after "^3.0.2" + "@svgr/babel-plugin-add-jsx-attribute@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" @@ -6446,13 +6461,6 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= - dependencies: - acorn "^3.0.4" - acorn-jsx@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" @@ -6477,16 +6485,11 @@ acorn-walk@^7.0.0, acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@5.X, acorn@^5.0.3, acorn@^5.5.0: +acorn@5.X, acorn@^5.0.3: version "5.7.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - acorn@^6.0.1, acorn@^6.0.4, acorn@^6.4.1: version "6.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" @@ -6598,24 +6601,11 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59" integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk= -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= - ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@^4.7.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.5.5, ajv@^6.9.1: version "6.12.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" @@ -6716,11 +6706,6 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= - ansi-escapes@^3.0.0, ansi-escapes@^3.1.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -7376,7 +7361,7 @@ array.prototype.map@^1.0.1: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.4" -arrify@^1.0.0, arrify@^1.0.1: +arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= @@ -7485,6 +7470,11 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async-cache@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/async-cache/-/async-cache-1.1.0.tgz#4a9a5a89d065ec5d8e5254bd9ee96ba76c532b5a" @@ -7597,7 +7587,7 @@ autobind-decorator@^1.3.4: resolved "https://registry.yarnpkg.com/autobind-decorator/-/autobind-decorator-1.4.3.tgz#4c96ffa77b10622ede24f110f5dbbf56691417d1" integrity sha1-TJb/p3sQYi7eJPEQ9du/VmkUF9E= -autoprefixer@^9.6.1: +autoprefixer@^9.6.1, autoprefixer@^9.8.6: version "9.8.6" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== @@ -9020,13 +9010,6 @@ caller-callsite@^2.0.0: dependencies: callsites "^2.0.0" -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= - dependencies: - callsites "^0.2.0" - caller-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" @@ -9034,11 +9017,6 @@ caller-path@^2.0.0: dependencies: caller-callsite "^2.0.0" -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= - callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -9441,11 +9419,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== - cjs-module-lexer@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" @@ -9497,7 +9470,7 @@ cli-boxes@^2.2.0: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== -cli-cursor@^1.0.1, cli-cursor@^1.0.2: +cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= @@ -9664,6 +9637,13 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone-regexp@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" + integrity sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q== + dependencies: + is-regexp "^2.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -9895,7 +9875,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@2, commander@^2.11.0, commander@^2.19.0, commander@^2.20.0, commander@^2.7.1, commander@^2.8.1, commander@^2.9.0: +commander@2, commander@^2.11.0, commander@^2.19.0, commander@^2.20.0, commander@^2.7.1, commander@^2.9.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -10001,7 +9981,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@^1.6.2, concat-stream@~1.6.0: +concat-stream@1.6.2, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@^1.6.2, concat-stream@~1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -10315,6 +10295,17 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" +cosmiconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" + integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + cp-file@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" @@ -11234,7 +11225,7 @@ debug-fabulous@1.X: memoizee "0.4.X" object-assign "4.X" -debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -11269,6 +11260,13 @@ debug@4.1.0: dependencies: ms "^2.1.1" +debug@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -11478,19 +11476,6 @@ del-cli@^3.0.1: del "^5.1.0" meow "^6.1.1" -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag= - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - del@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" @@ -11819,7 +11804,7 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -doctrine@1.5.0, doctrine@^1.2.2: +doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= @@ -12583,7 +12568,7 @@ es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-map@^0.1.3, es6-map@^0.1.5: +es6-map@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= @@ -12707,16 +12692,6 @@ escodegen@~1.2.0: optionalDependencies: source-map "~0.1.30" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-config-prettier@^6.15.0: version "6.15.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" @@ -12959,45 +12934,6 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^2.7.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11" - integrity sha1-5MyPoPAJ+4KaquI4VaKTYL4fbBE= - dependencies: - chalk "^1.1.3" - concat-stream "^1.4.6" - debug "^2.1.1" - doctrine "^1.2.2" - es6-map "^0.1.3" - escope "^3.6.0" - espree "^3.1.6" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^1.1.1" - glob "^7.0.3" - globals "^9.2.0" - ignore "^3.1.2" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - optionator "^0.8.1" - path-is-absolute "^1.0.0" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.6.0" - strip-json-comments "~1.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" - eslint@^6.8.0: version "6.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" @@ -13041,14 +12977,6 @@ eslint@^6.8.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^3.1.6: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - espree@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" @@ -13208,6 +13136,13 @@ execa@^4.0.0, execa@^4.0.2: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execall@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" + integrity sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow== + dependencies: + clone-regexp "^2.1.0" + executable@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" @@ -13461,6 +13396,18 @@ fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.2: micromatch "^4.0.2" picomatch "^2.2.1" +fast-glob@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-parse@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" @@ -13498,6 +13445,11 @@ fast-stream-to-buffer@^1.0.0: dependencies: end-of-stream "^1.4.1" +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + fastest-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028" @@ -13591,7 +13543,7 @@ figures@2.0.0, figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^1.3.5, figures@^1.7.0: +figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= @@ -13606,14 +13558,6 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^1.1.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" - integrity sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g= - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -13621,6 +13565,13 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== + dependencies: + flat-cache "^3.0.4" + file-loader@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.2.0.tgz#5fb124d2369d7075d70a9a5abecd12e60a95215e" @@ -13822,16 +13773,6 @@ flagged-respawn@^1.0.0: resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" integrity sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c= -flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" - integrity sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE= - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -13841,6 +13782,14 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + flat@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" @@ -13853,6 +13802,11 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== +flatted@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" + integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== + flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" @@ -14119,13 +14073,6 @@ fromentries@^1.2.0: resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== -front-matter@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.1.2.tgz#f75983b9f2f413be658c93dfd7bd8ce4078f5cdb" - integrity sha1-91mDufL0E75ljJPf172M5AePXNs= - dependencies: - js-yaml "^3.4.6" - fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -14152,15 +14099,6 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" - integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - fs-extra@^7.0.0, fs-extra@^7.0.1, fs-extra@~7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -14312,20 +14250,6 @@ geckodriver@^1.21.0: https-proxy-agent "5.0.0" tar "6.0.2" -generate-function@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - generic-pool@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.7.1.tgz#36fe5bb83e7e0e032e5d32cd05dc00f5ff119aa8" @@ -14406,6 +14330,11 @@ get-stdin@^6.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== +get-stdin@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== + get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -14713,7 +14642,7 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globals@^9.18.0, globals@^9.2.0: +globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== @@ -14764,18 +14693,6 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0= - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -14801,6 +14718,11 @@ globby@^9.2.0: pify "^4.0.1" slash "^2.0.0" +globjoin@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= + globule@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" @@ -14817,12 +14739,12 @@ glogg@^1.0.0: dependencies: sparkles "^1.0.0" -gonzales-pe-sl@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/gonzales-pe-sl/-/gonzales-pe-sl-4.2.3.tgz#6a868bc380645f141feeb042c6f97fcc71b59fe6" - integrity sha1-aoaLw4BkXxQf7rBCxvl/zHG1n+Y= +gonzales-pe@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.3.0.tgz#fe9dec5f3c557eead09ff868c65826be54d067b3" + integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== dependencies: - minimist "1.1.x" + minimist "^1.2.5" good-listener@^1.2.2: version "1.2.2" @@ -15732,6 +15654,13 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" integrity sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg== +hosted-git-info@^3.0.6: + version "3.0.7" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.7.tgz#a30727385ea85acfcee94e0aad9e368c792e036c" + integrity sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ== + dependencies: + lru-cache "^6.0.0" + hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" @@ -16097,7 +16026,7 @@ ignore-by-default@^1.0.1: resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= -ignore@^3.1.2, ignore@^3.3.5: +ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== @@ -16107,7 +16036,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.5, ignore@^5.1.1, ignore@^5.1.4: +ignore@^5.0.5, ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -16154,7 +16083,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.0.0, import-fresh@^3.1.0: +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== @@ -16174,6 +16103,11 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= +import-lazy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -16333,25 +16267,6 @@ inquirer@7.0.4: strip-ansi "^5.1.0" through "^2.3.6" -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^7.0.0, inquirer@^7.3.3: version "7.3.3" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" @@ -16814,22 +16729,6 @@ is-map@^2.0.1: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== - -is-my-json-valid@^2.10.0: - version "2.20.5" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.5.tgz#5eca6a8232a687f68869b7361be1612e7512e5df" - integrity sha512-VTPuvvGQtxvCeghwspQu1rBgjYUT6FGxPlvFKbYuFtgc4ADsX3U5ihZOYN0qyU6u+d4X9xXb0IT5O6QpXKt87A== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - is-native@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-native/-/is-native-1.0.1.tgz#cd18cc162e8450d683b5babe79ac99c145449675" @@ -16909,23 +16808,11 @@ is-odd@^2.0.0: dependencies: is-number "^4.0.0" -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= - is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== -is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - integrity sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw= - dependencies: - is-path-inside "^1.0.0" - is-path-in-cwd@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" @@ -16933,13 +16820,6 @@ is-path-in-cwd@^2.0.0: dependencies: is-path-inside "^2.1.0" -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= - dependencies: - path-is-inside "^1.0.1" - is-path-inside@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" @@ -16991,11 +16871,6 @@ is-promise@^2.1, is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= -is-property@^1.0.0, is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -17008,6 +16883,11 @@ is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.1: dependencies: has-symbols "^1.0.1" +is-regexp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" + integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA== + is-relative@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" @@ -17015,11 +16895,6 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -18058,7 +17933,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4, js-yaml@^3.9.0, js-yaml@~3.13.1: +js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.9.0, js-yaml@~3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -18266,13 +18141,6 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" - integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY= - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -18307,11 +18175,6 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= -jsonpointer@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.1.0.tgz#501fb89986a2389765ba09e6053299ceb4f2c2cc" - integrity sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg== - jsonwebtoken@^8.3.0, jsonwebtoken@^8.5.1: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" @@ -18497,10 +18360,10 @@ kleur@^3.0.2: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.2.tgz#83c7ec858a41098b613d5998a7b653962b504f68" integrity sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q== -known-css-properties@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.3.0.tgz#a3d135bbfc60ee8c6eacf2f7e7e6f2d4755e49a4" - integrity sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ== +known-css-properties@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.20.0.tgz#0570831661b47dd835293218381166090ff60e96" + integrity sha512-URvsjaA9ypfreqJ2/ylDr5MUERhJZ+DhguoWRr2xgS5C7aGCalXo+ewL+GixgKBfhT2vuL02nbIgNGqVWgTOYw== knuth-shuffle-seeded@^1.0.6: version "1.0.6" @@ -18980,11 +18843,6 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= -lodash.capitalize@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9" - integrity sha1-+CbJtOKoUR2E46yinbBeGk87cqk= - lodash.clone@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" @@ -19105,11 +18963,6 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= -lodash.kebabcase@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" - integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= - lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" @@ -19200,7 +19053,7 @@ 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.3.0, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.19, lodash@~4.17.20: +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== @@ -19291,6 +19144,11 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +longest-streak@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -19546,6 +19404,11 @@ material-colors@^1.2.1: resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1" integrity sha1-UpJZPmdUyxvMK5gDDk4Najr8nqE= +mathml-tag-names@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" + integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== + md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -19598,6 +19461,17 @@ mdast-util-definitions@^4.0.0: dependencies: unist-util-visit "^2.0.0" +mdast-util-from-markdown@^0.8.0: + version "0.8.4" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.4.tgz#2882100c1b9fc967d3f83806802f303666682d32" + integrity sha512-jj891B5pV2r63n2kBTFh8cRI2uR9LQHsXG1zSDqfhXkIlDzrTcIlbB5+5aaYEkl8vOPIOPLf8VT7Ere1wWTMdw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-string "^2.0.0" + micromark "~2.11.0" + parse-entities "^2.0.0" + unist-util-stringify-position "^2.0.0" + mdast-util-to-hast@9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-9.1.0.tgz#6ef121dd3cd3b006bf8650b1b9454da0faf79ffe" @@ -19629,11 +19503,28 @@ mdast-util-to-hast@^10.0.0: unist-util-position "^3.0.0" unist-util-visit "^2.0.0" +mdast-util-to-markdown@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.1.tgz#0e07d3f871e056bffc38a0cf50c7298b56d9e0d6" + integrity sha512-4qJtZ0qdyYeexAXoOZiU0uHIFVncJAmCkHkSluAsvDaVWODtPyNEo9I1ns0T4ulxu2EHRH5u/bt1cV0pdHCX+A== + dependencies: + "@types/unist" "^2.0.0" + longest-streak "^2.0.0" + mdast-util-to-string "^2.0.0" + parse-entities "^2.0.0" + repeat-string "^1.0.0" + zwitch "^1.0.0" + mdast-util-to-string@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz#27055500103f51637bd07d01da01eb1967a43527" integrity sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A== +mdast-util-to-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" + integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== + mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" @@ -19766,6 +19657,23 @@ meow@^7.0.1: type-fest "^0.13.1" yargs-parser "^18.1.3" +meow@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-8.0.0.tgz#1aa10ee61046719e334ffdc038bb5069250ec99a" + integrity sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-deep@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/merge-deep/-/merge-deep-3.0.2.tgz#f39fa100a4f1bd34ff29f7d2bf4508fbb8d83ad2" @@ -19797,11 +19705,6 @@ merge2@^1.2.3, merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -merge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== - methods@^1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -19812,6 +19715,14 @@ microevent.ts@~0.1.1: resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== +micromark@~2.11.0: + version "2.11.2" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.2.tgz#e8b6a05f54697d2d3d27fc89600c6bc40dd05f35" + integrity sha512-IXuP76p2uj8uMg4FQc1cRE7lPCLsfAXuEfdjtdO55VRiFO1asrCSQ5g43NmPqFtRwzEnEhafRVzn2jg0UiKArQ== + dependencies: + debug "^4.0.0" + parse-entities "^2.0.0" + micromatch@3.1.10, micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -19941,7 +19852,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimist-options@^4.0.2: +minimist-options@4.1.0, minimist-options@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== @@ -19950,7 +19861,7 @@ minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@0.0.8, minimist@1.1.x, minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.0: +minimist@0.0.8, minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.0: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -20283,6 +20194,11 @@ ms@2.1.1, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + msgpackr-extract@^0.3.5, msgpackr-extract@^0.3.6: version "0.3.6" resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-0.3.6.tgz#f20c0a278e44377471b1fa2a3a75a32c87693755" @@ -20372,11 +20288,6 @@ mute-stdout@^1.0.0: resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= - mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -20840,6 +20751,16 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-package-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.0.tgz#1f8a7c423b3d2e85eb36985eaf81de381d01301a" + integrity sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw== + dependencies: + hosted-git-info "^3.0.6" + resolve "^1.17.0" + semver "^7.3.2" + validate-npm-package-license "^3.0.1" + normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -20857,6 +20778,11 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= +normalize-selector@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" + integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= + normalize-url@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" @@ -21891,7 +21817,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= @@ -22182,11 +22108,6 @@ pluralize@3.1.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-3.1.0.tgz#84213d0a12356069daa84060c559242633161368" integrity sha1-hCE9ChI1YGnaqEBgxVkkJjMWE2g= -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" - integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= - pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -22257,6 +22178,20 @@ postcss-flexbugs-fixes@^4.1.0: dependencies: postcss "^7.0.0" +postcss-html@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" + integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== + dependencies: + htmlparser2 "^3.10.0" + +postcss-less@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad" + integrity sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA== + dependencies: + postcss "^7.0.14" + postcss-load-config@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" @@ -22275,6 +22210,11 @@ postcss-loader@^3.0.0: postcss-load-config "^2.0.0" schema-utils "^1.0.0" +postcss-media-query-parser@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= + postcss-modules-extract-imports@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" @@ -22315,6 +22255,33 @@ postcss-prefix-selector@^1.7.2: dependencies: postcss "^7.0.0" +postcss-resolve-nested-selector@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" + integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= + +postcss-safe-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" + integrity sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g== + dependencies: + postcss "^7.0.26" + +postcss-sass@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.4.4.tgz#91f0f3447b45ce373227a98b61f8d8f0785285a3" + integrity sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg== + dependencies: + gonzales-pe "^4.3.0" + postcss "^7.0.21" + +postcss-scss@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.1.1.tgz#ec3a75fa29a55e016b90bf3269026c53c1d2b383" + integrity sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA== + dependencies: + postcss "^7.0.6" + postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" @@ -22324,12 +22291,27 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: indexes-of "^1.0.1" uniq "^1.0.1" +postcss-selector-parser@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + util-deprecate "^1.0.2" + +postcss-syntax@^0.36.2: + version "0.36.2" + resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" + integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== + postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: +postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: version "7.0.32" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== @@ -22338,6 +22320,15 @@ postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.32, postcss@^7.0. source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.35: + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + potpack@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.1.tgz#d1b1afd89e4c8f7762865ec30bd112ab767e2ebf" @@ -23844,15 +23835,6 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - realpath-native@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" @@ -24270,6 +24252,13 @@ remark-parse@^5.0.0: vfile-location "^2.0.0" xtend "^4.0.1" +remark-parse@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" + integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== + dependencies: + mdast-util-from-markdown "^0.8.0" + remark-rehype@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-8.0.0.tgz#5a8afc8262a59d205fba21dafb27a673fb3b92fa" @@ -24293,6 +24282,22 @@ remark-squeeze-paragraphs@4.0.0: dependencies: mdast-squeeze-paragraphs "^4.0.0" +remark-stringify@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-9.0.1.tgz#576d06e910548b0a7191a71f27b33f1218862894" + integrity sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg== + dependencies: + mdast-util-to-markdown "^0.6.0" + +remark@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/remark/-/remark-13.0.0.tgz#d15d9bf71a402f40287ebe36067b66d54868e425" + integrity sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA== + dependencies: + remark-parse "^9.0.0" + remark-stringify "^9.0.0" + unified "^9.1.0" + remedial@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" @@ -24341,7 +24346,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= -repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.0.0, repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -24474,14 +24479,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -require-uncached@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - requirefresh@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/requirefresh/-/requirefresh-2.2.0.tgz#68298ae66af9da3d6843375adf8351dd29d73789" @@ -24536,11 +24533,6 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: expand-tilde "^2.0.0" global-modules "^1.0.0" -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= - resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -24805,13 +24797,6 @@ rtl-css-js@^1.9.0: dependencies: "@babel/runtime" "^7.1.2" -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= - dependencies: - once "^1.3.0" - run-async@^2.2.0, run-async@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" @@ -24841,11 +24826,6 @@ rw@~0.1.4: resolved "https://registry.yarnpkg.com/rw/-/rw-0.1.4.tgz#4903cbd80248ae0ede685bf58fd236a7a9b29a3e" integrity sha1-SQPL2AJIrg7eaFv1j9I2p6mymj4= -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" - integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= - rxjs-marbles@^5.0.6: version "5.0.6" resolved "https://registry.yarnpkg.com/rxjs-marbles/-/rxjs-marbles-5.0.6.tgz#e8e71df3b82b49603555f017f2fd3d8c359c4c24" @@ -24920,26 +24900,6 @@ sass-graph@2.2.5: scss-tokenizer "^0.2.3" yargs "^13.3.2" -sass-lint@^1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/sass-lint/-/sass-lint-1.12.1.tgz#630f69c216aa206b8232fb2aa907bdf3336b6d83" - integrity sha1-Yw9pwhaqIGuCMvsqqQe98zNrbYM= - dependencies: - commander "^2.8.1" - eslint "^2.7.0" - front-matter "2.1.2" - fs-extra "^3.0.1" - glob "^7.0.0" - globule "^1.0.0" - gonzales-pe-sl "^4.2.3" - js-yaml "^3.5.4" - known-css-properties "^0.3.0" - lodash.capitalize "^4.1.0" - lodash.kebabcase "^4.0.0" - merge "^1.2.0" - path-is-absolute "^1.0.0" - util "^0.10.3" - sass-loader@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" @@ -25376,11 +25336,6 @@ shell-quote@1.7.2, shell-quote@^1.4.2, shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== -shelljs@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" - integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg= - shelljs@^0.8.3, shelljs@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" @@ -25479,6 +25434,15 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slide@^1.1.5, slide@~1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -25802,6 +25766,11 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" +specificity@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" + integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== + split-on-first@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" @@ -26374,11 +26343,6 @@ strip-json-comments@^3.0.1, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" - integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= - strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -26403,6 +26367,11 @@ style-loader@^1.1.3, style-loader@^1.2.1: loader-utils "^2.0.0" schema-utils "^2.6.6" +style-search@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" + integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= + style-to-object@0.3.0, style-to-object@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" @@ -26426,6 +26395,71 @@ styled-components@^5.1.0: shallowequal "^1.1.0" supports-color "^5.5.0" +stylelint-scss@^3.18.0: + version "3.18.0" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-3.18.0.tgz#8f06371c223909bf3f62e839548af1badeed31e9" + integrity sha512-LD7+hv/6/ApNGt7+nR/50ft7cezKP2HM5rI8avIdGaUWre3xlHfV4jKO/DRZhscfuN+Ewy9FMhcTq0CcS0C/SA== + dependencies: + lodash "^4.17.15" + postcss-media-query-parser "^0.2.3" + postcss-resolve-nested-selector "^0.1.1" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +stylelint@13.8.0: + version "13.8.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.8.0.tgz#446765dbe25e3617f819a0165956faf2563ddc23" + integrity sha512-iHH3dv3UI23SLDrH4zMQDjLT9/dDIz/IpoFeuNxZmEx86KtfpjDOscxLTFioQyv+2vQjPlRZnK0UoJtfxLICXQ== + dependencies: + "@stylelint/postcss-css-in-js" "^0.37.2" + "@stylelint/postcss-markdown" "^0.36.2" + autoprefixer "^9.8.6" + balanced-match "^1.0.0" + chalk "^4.1.0" + cosmiconfig "^7.0.0" + debug "^4.2.0" + execall "^2.0.0" + fast-glob "^3.2.4" + fastest-levenshtein "^1.0.12" + file-entry-cache "^6.0.0" + get-stdin "^8.0.0" + global-modules "^2.0.0" + globby "^11.0.1" + globjoin "^0.1.4" + html-tags "^3.1.0" + ignore "^5.1.8" + import-lazy "^4.0.0" + imurmurhash "^0.1.4" + known-css-properties "^0.20.0" + lodash "^4.17.20" + log-symbols "^4.0.0" + mathml-tag-names "^2.1.3" + meow "^8.0.0" + micromatch "^4.0.2" + normalize-selector "^0.2.0" + postcss "^7.0.35" + postcss-html "^0.36.0" + postcss-less "^3.1.4" + postcss-media-query-parser "^0.2.3" + postcss-resolve-nested-selector "^0.1.1" + postcss-safe-parser "^4.0.2" + postcss-sass "^0.4.4" + postcss-scss "^2.1.1" + postcss-selector-parser "^6.0.4" + postcss-syntax "^0.36.2" + postcss-value-parser "^4.1.0" + resolve-from "^5.0.0" + slash "^3.0.0" + specificity "^0.4.1" + string-width "^4.2.0" + strip-ansi "^6.0.0" + style-search "^0.1.0" + sugarss "^2.0.0" + svg-tags "^1.0.0" + table "^6.0.3" + v8-compile-cache "^2.2.0" + write-file-atomic "^3.0.3" + stylis-rule-sheet@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" @@ -26453,6 +26487,13 @@ success-symbol@^0.1.0: resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" integrity sha1-JAIuSG878c3KCUKDt2nEctO3KJc= +sugarss@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" + integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ== + dependencies: + postcss "^7.0.2" + superagent@3.8.2: version "3.8.2" resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.2.tgz#e4a11b9d047f7d3efeb3bbe536d9ec0021d16403" @@ -26589,6 +26630,11 @@ svg-parser@^2.0.2: resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== +svg-tags@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= + svg-to-pdfkit@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/svg-to-pdfkit/-/svg-to-pdfkit-0.1.8.tgz#5921765922044843f0c1a5b25ec1ef8a4a33b8af" @@ -26657,18 +26703,6 @@ tabbable@^3.0.0: resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2" integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ== -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" - integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" - table@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" @@ -26679,6 +26713,16 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" +table@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d" + integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw== + dependencies: + ajv "^6.12.4" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" + tapable@^0.1.8: version "0.1.10" resolved "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" @@ -26941,7 +26985,7 @@ text-hex@1.0.x: resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== -text-table@0.2.0, text-table@^0.2.0, text-table@~0.2.0: +text-table@0.2.0, text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= @@ -27543,6 +27587,11 @@ type-fest@^0.13.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + type-fest@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -27864,7 +27913,7 @@ unified@^6.1.5: x-is-function "^1.0.4" x-is-string "^0.1.0" -unified@^9.2.0: +unified@^9.1.0, unified@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== @@ -27932,6 +27981,13 @@ unist-builder@2.0.3, unist-builder@^2.0.0: resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== +unist-util-find-all-after@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz#fdfecd14c5b7aea5e9ef38d5e0d5f774eeb561f6" + integrity sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ== + dependencies: + unist-util-is "^4.0.0" + unist-util-generated@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.5.tgz#1e903e68467931ebfaea386dae9ea253628acd42" @@ -28286,13 +28342,6 @@ use@^2.0.0: isobject "^3.0.0" lazy-cache "^2.0.2" -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= - dependencies: - os-homedir "^1.0.0" - utif@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/utif/-/utif-2.0.1.tgz#9e1582d9bbd20011a6588548ed3266298e711759" @@ -28333,7 +28382,7 @@ util.promisify@^1.0.0: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.0" -util@0.10.3, util@^0.10.3: +util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= @@ -28399,7 +28448,7 @@ uuid@^8.0.0, uuid@^8.3.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== -v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: +v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1, v8-compile-cache@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== @@ -29638,7 +29687,7 @@ write-file-atomic@^2.4.2: imurmurhash "^0.1.4" signal-exit "^3.0.2" -write-file-atomic@^3.0.0: +write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== @@ -29676,13 +29725,6 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= - dependencies: - mkdirp "^0.5.1" - ws@^6.1.2, ws@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" @@ -29826,7 +29868,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.7.2: +yaml@^1.10.0, yaml@^1.7.2: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== @@ -29860,6 +29902,11 @@ yargs-parser@^20.0.0, yargs-parser@^20.2.2: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.2.tgz#84562c6b1c41ccec2f13d346c7dd83f8d1a0dc70" integrity sha512-XmrpXaTl6noDsf1dKpBuUNCOHqjs0g3jRMXf/ztRxdOmb+er8kE5z5b55Lz3p5u2T8KJ59ENBnASS8/iapVJ5g== +yargs-parser@^20.2.3: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs-unparser@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" From 7845e61438d0477e9d6f49ae120acbb7d714a042 Mon Sep 17 00:00:00 2001 From: Devon Thomson Date: Fri, 15 Jan 2021 12:55:45 -0500 Subject: [PATCH 14/33] fix copy (#88481) --- src/plugins/dashboard/public/dashboard_strings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/dashboard/public/dashboard_strings.ts b/src/plugins/dashboard/public/dashboard_strings.ts index 9bede02c75b943..5747a383b4bcd0 100644 --- a/src/plugins/dashboard/public/dashboard_strings.ts +++ b/src/plugins/dashboard/public/dashboard_strings.ts @@ -92,7 +92,7 @@ export const dashboardFeatureCatalog = { export const dashboardAddToLibraryAction = { getDisplayName: () => i18n.translate('dashboard.panel.AddToLibrary', { - defaultMessage: 'Add to library', + defaultMessage: 'Save to library', }), getSuccessMessage: (panelTitle: string) => i18n.translate('dashboard.panel.addToLibrary.successMessage', { From 9eb993aaef03302c0b876a2a15b6101b5b5b7e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Fri, 15 Jan 2021 19:33:38 +0100 Subject: [PATCH 15/33] [APM] Consistent terminology for latency and throughput (#88452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Casper Hübertz --- x-pack/plugins/apm/common/alert_types.ts | 4 ++-- x-pack/plugins/apm/e2e/cypress/integration/apm.feature | 2 +- .../application/action_menu/alerting_popover_flyout.tsx | 4 ++-- .../public/components/alerting/register_apm_alerts.ts | 9 ++++----- .../app/ServiceMap/Popover/ServiceStatsList.tsx | 4 ++-- .../components/app/Settings/anomaly_detection/index.tsx | 2 +- .../public/components/app/TraceOverview/TraceList.tsx | 4 ++-- .../app/TransactionDetails/Distribution/index.tsx | 2 +- .../Waterfall/waterfall_helpers/waterfall_helpers.ts | 4 ++-- .../app/transaction_overview/TransactionList/index.tsx | 2 +- .../shared/charts/transaction_charts/ml_header.tsx | 2 +- .../lib/transactions/get_throughput_charts/transform.ts | 2 +- 12 files changed, 20 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/apm/common/alert_types.ts b/x-pack/plugins/apm/common/alert_types.ts index bb42c8acd167af..57236ea58063ca 100644 --- a/x-pack/plugins/apm/common/alert_types.ts +++ b/x-pack/plugins/apm/common/alert_types.ts @@ -46,7 +46,7 @@ export const ALERT_TYPES_CONFIG: Record< }, [AlertType.TransactionDuration]: { name: i18n.translate('xpack.apm.transactionDurationAlert.name', { - defaultMessage: 'Transaction duration threshold', + defaultMessage: 'Latency threshold', }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: THRESHOLD_MET_GROUP_ID, @@ -55,7 +55,7 @@ export const ALERT_TYPES_CONFIG: Record< }, [AlertType.TransactionDurationAnomaly]: { name: i18n.translate('xpack.apm.transactionDurationAnomalyAlert.name', { - defaultMessage: 'Transaction duration anomaly', + defaultMessage: 'Latency anomaly', }), actionGroups: [THRESHOLD_MET_GROUP], defaultActionGroupId: THRESHOLD_MET_GROUP_ID, diff --git a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature index 72c060c48f7551..0cc8f00d48dfd2 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/apm.feature +++ b/x-pack/plugins/apm/e2e/cypress/integration/apm.feature @@ -1,6 +1,6 @@ Feature: APM - Scenario: Transaction duration charts + Scenario: Transaction latency charts Given a user browses the APM UI application When the user inspects the opbeans-node service Then should redirect to correct path diff --git a/x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx b/x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx index 395233735a9d54..3204f4b183b4f8 100644 --- a/x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx +++ b/x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx @@ -21,7 +21,7 @@ const alertLabel = i18n.translate('xpack.apm.home.alertsMenu.alerts', { }); const transactionDurationLabel = i18n.translate( 'xpack.apm.home.alertsMenu.transactionDuration', - { defaultMessage: 'Transaction duration' } + { defaultMessage: 'Latency' } ); const transactionErrorRateLabel = i18n.translate( 'xpack.apm.home.alertsMenu.transactionErrorRate', @@ -112,7 +112,7 @@ export function AlertingPopoverAndFlyout({ ], }, - // transaction duration panel + // latency panel { id: CREATE_TRANSACTION_DURATION_ALERT_PANEL_ID, title: transactionDurationLabel, diff --git a/x-pack/plugins/apm/public/components/alerting/register_apm_alerts.ts b/x-pack/plugins/apm/public/components/alerting/register_apm_alerts.ts index 78d771aec13e04..1e35b10d83b7c9 100644 --- a/x-pack/plugins/apm/public/components/alerting/register_apm_alerts.ts +++ b/x-pack/plugins/apm/public/components/alerting/register_apm_alerts.ts @@ -46,7 +46,7 @@ export function registerApmAlerts( 'xpack.apm.alertTypes.transactionDuration.description', { defaultMessage: - 'Alert when the duration of a specific transaction type in a service exceeds a defined threshold.', + 'Alert when the latency of a specific transaction type in a service exceeds a defined threshold.', } ), iconClass: 'bell', @@ -68,8 +68,8 @@ export function registerApmAlerts( - Service name: \\{\\{context.serviceName\\}\\} - Type: \\{\\{context.transactionType\\}\\} - Environment: \\{\\{context.environment\\}\\} -- Threshold: \\{\\{context.threshold\\}\\}ms -- Triggered value: \\{\\{context.triggerValue\\}\\} over the last \\{\\{context.interval\\}\\}`, +- Latency threshold: \\{\\{context.threshold\\}\\}ms +- Latency observed: \\{\\{context.triggerValue\\}\\} over the last \\{\\{context.interval\\}\\}`, } ), }); @@ -113,8 +113,7 @@ export function registerApmAlerts( description: i18n.translate( 'xpack.apm.alertTypes.transactionDurationAnomaly.description', { - defaultMessage: - 'Alert when the overall transaction duration of a service is considered anomalous.', + defaultMessage: 'Alert when the latency of a service is abnormal.', } ), iconClass: 'bell', diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx index cc41c254ffb507..377496cf2ac9ba 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx @@ -41,7 +41,7 @@ export function ServiceStatsList({ title: i18n.translate( 'xpack.apm.serviceMap.avgTransDurationPopoverStat', { - defaultMessage: 'Trans. duration (avg.)', + defaultMessage: 'Latency (avg.)', } ), description: isNumber(transactionStats.avgTransactionDuration) @@ -52,7 +52,7 @@ export function ServiceStatsList({ title: i18n.translate( 'xpack.apm.serviceMap.avgReqPerMinutePopoverMetric', { - defaultMessage: 'Req. per minute (avg.)', + defaultMessage: 'Throughput (avg.)', } ), description: asTransactionRate(transactionStats.avgRequestsPerMinute), diff --git a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx index addfd64a9ef624..01544901f3849e 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx @@ -75,7 +75,7 @@ export function AnomalyDetection() { {i18n.translate('xpack.apm.settings.anomalyDetection.descriptionText', { - defaultMessage: `Machine Learning's anomaly detection integration enables application health status indicators for services in each configured environment by identifying transaction duration anomalies.`, + defaultMessage: `Machine Learning's anomaly detection integration enables application health status indicators for services in each configured environment by identifying anomalies in latency.`, })} diff --git a/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx b/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx index b216ab5498cf6d..a2ab8a365c7116 100644 --- a/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx +++ b/x-pack/plugins/apm/public/components/app/TraceOverview/TraceList.tsx @@ -68,7 +68,7 @@ const traceListColumns: Array> = [ { field: 'averageResponseTime', name: i18n.translate('xpack.apm.tracesTable.avgResponseTimeColumnLabel', { - defaultMessage: 'Avg. response time', + defaultMessage: 'Latency (avg.)', }), sortable: true, dataType: 'number', @@ -91,7 +91,7 @@ const traceListColumns: Array> = [ 'xpack.apm.tracesTable.impactColumnDescription', { defaultMessage: - "The most used and slowest endpoints in your service. It's calculated by taking the relative average duration times the number of transactions per minute.", + 'The most used and slowest endpoints in your service. It is the result of multiplying latency and throughput', } )} > diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx index 8ab09eccd9bdbc..a94c48f02c1017 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.tsx @@ -162,7 +162,7 @@ export function TransactionDistribution({ {i18n.translate( 'xpack.apm.transactionDetails.transactionsDurationDistributionChartTitle', { - defaultMessage: 'Transactions duration distribution', + defaultMessage: 'Latency distribution', } )}{' '} { parentId?: string; /** - * Duration in us + * Latency in us */ duration: number; diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx index d2a3dc54c2a487..877a4d22aa6281 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/TransactionList/index.tsx @@ -126,7 +126,7 @@ export function TransactionList({ items, isLoading }: Props) { 'xpack.apm.transactionsTable.impactColumnDescription', { defaultMessage: - "The most used and slowest endpoints in your service. It's calculated by taking the relative average duration times the number of transactions per minute.", + 'The most used and slowest endpoints in your service. It is the result of multiplying latency and throughput', } )} /> diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/ml_header.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/ml_header.tsx index 33dcbf02ccda7c..89bf370c90ad64 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/ml_header.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/ml_header.tsx @@ -62,7 +62,7 @@ export function MLHeader({ hasValidMlLicense, mlJobId }: Props) { 'xpack.apm.metrics.transactionChart.machineLearningTooltip', { defaultMessage: - 'The stream around the average duration shows the expected bounds. An annotation is shown for anomaly scores ≥ 75.', + 'The stream displays the expected bounds of the average latency. A red vertical annotation indicates anomalies with an anomaly score of 75 or above.', } )} /> diff --git a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts index 0ebf1446265fde..a12e36c0e9de45 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_throughput_charts/transform.ts @@ -37,7 +37,7 @@ export function getThroughputBuckets({ .map((bucket) => bucket.count.value) .reduce((a, b) => a + b, 0); - // calculate request/minute + // calculate average throughput const avg = docCountTotal / durationAsMinutes; return { key, dataPoints, avg }; From 73cd1a088cc2589f1164bf6959be352af2a7412d Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Fri, 15 Jan 2021 13:37:30 -0500 Subject: [PATCH 16/33] [Uptime] clear ping state when PingList component in unmounted (#88321) * clear ping state when PingList component in unmounted * update ping list content Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__snapshots__/ping_list.test.tsx.snap | 114 ----------------- .../monitor/ping_list/ping_list.test.tsx | 117 +++++++++++------- .../monitor/ping_list/ping_list.tsx | 16 +++ .../uptime/public/lib/helper/test_helpers.ts | 4 + .../uptime/public/state/actions/ping.ts | 2 + .../uptime/public/state/reducers/ping_list.ts | 6 +- 6 files changed, 98 insertions(+), 161 deletions(-) delete mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_list.test.tsx.snap diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_list.test.tsx.snap deleted file mode 100644 index 7d7da0b7dd74c7..00000000000000 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_list.test.tsx.snap +++ /dev/null @@ -1,114 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`PingList component renders sorted list without errors 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.test.tsx index d0fac09f683fcf..60e65580027a3d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.test.tsx @@ -5,58 +5,58 @@ */ import React from 'react'; -import { shallowWithIntl } from '@kbn/test/jest'; import { PingList } from './ping_list'; import { Ping, PingsResponse } from '../../../../common/runtime_types'; import { ExpandedRowMap } from '../../overview/monitor_list/types'; import { rowShouldExpand, toggleDetails } from './columns/expand_row'; import * as pingListHook from './use_pings'; -import { mockReduxHooks } from '../../../lib/helper/test_helpers'; +import { mockDispatch } from '../../../lib/helper/test_helpers'; +import { render } from '../../../lib/helper/rtl_helpers'; -mockReduxHooks(); +mockDispatch(); describe('PingList component', () => { - let response: PingsResponse; + const defaultPings = [ + { + docId: 'fewjio21', + timestamp: '2019-01-28T17:47:08.078Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1430 }, + id: 'auto-tcp-0X81440A68E839814F', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewjoo21', + timestamp: '2019-01-28T17:47:09.075Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1370 }, + id: 'auto-tcp-0X81440A68E839814D', + ip: '255.255.255.0', + name: '', + status: 'down', + type: 'tcp', + }, + }, + ]; - beforeAll(() => { - response = { - total: 9231, - pings: [ - { - docId: 'fewjio21', - timestamp: '2019-01-28T17:47:08.078Z', - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1430 }, - id: 'auto-tcp-0X81440A68E839814F', - ip: '127.0.0.1', - name: '', - status: 'down', - type: 'tcp', - }, - }, - { - docId: 'fewjoo21', - timestamp: '2019-01-28T17:47:09.075Z', - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1370 }, - id: 'auto-tcp-0X81440A68E839814D', - ip: '127.0.0.1', - name: '', - status: 'down', - type: 'tcp', - }, - }, - ], - }; + const response: PingsResponse = { + total: 9231, + pings: defaultPings, + }; + beforeEach(() => { jest.spyOn(pingListHook, 'usePingsList').mockReturnValue({ ...response, error: undefined, @@ -65,9 +65,34 @@ describe('PingList component', () => { }); }); - it('renders sorted list without errors', () => { - const component = shallowWithIntl(); - expect(component).toMatchSnapshot(); + it('renders loading state when pings are loading', () => { + jest.spyOn(pingListHook, 'usePingsList').mockReturnValue({ + pings: [], + total: 0, + error: undefined, + loading: true, + failedSteps: { steps: [], checkGroup: '1-f-4d-4f' }, + }); + const { getByText } = render(); + expect(getByText('Loading history...')).toBeInTheDocument(); + }); + + it('renders no pings state when pings are not found', () => { + jest.spyOn(pingListHook, 'usePingsList').mockReturnValue({ + pings: [], + total: 0, + error: undefined, + loading: false, + failedSteps: { steps: [], checkGroup: '1-f-4d-4f' }, + }); + const { getByText } = render(); + expect(getByText('No history found')).toBeInTheDocument(); + }); + + it('renders list without errors', () => { + const { getByText } = render(); + expect(getByText(`${response.pings[0].monitor.ip}`)).toBeInTheDocument(); + expect(getByText(`${response.pings[1].monitor.ip}`)).toBeInTheDocument(); }); describe('toggleDetails', () => { @@ -139,7 +164,7 @@ describe('PingList component', () => { "us": 1370, }, "id": "auto-tcp-0X81440A68E839814D", - "ip": "127.0.0.1", + "ip": "255.255.255.0", "name": "", "status": "down", "type": "tcp", diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx index 75f261f1e42fa0..3da788cc23a7ae 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx @@ -25,6 +25,7 @@ import { PingTimestamp } from './columns/ping_timestamp'; import { FailedStep } from './columns/failed_step'; import { usePingsList } from './use_pings'; import { PingListHeader } from './ping_list_header'; +import { clearPings } from '../../../state/actions'; export const SpanWithMargin = styled.span` margin-right: 16px; @@ -54,6 +55,12 @@ export const PingList = () => { Object.keys(expandedRows).filter((e) => !pings.some(({ docId }) => docId === e)) ); + useEffect(() => { + return () => { + dispatch(clearPings()); + }; + }, [dispatch]); + useEffect(() => { const parsed = JSON.parse(expandedIdsToRemove); if (parsed.length) { @@ -200,6 +207,15 @@ export const PingList = () => { itemId="docId" itemIdToExpandedRowMap={expandedRows} pagination={pagination} + noItemsMessage={ + loading + ? i18n.translate('xpack.uptime.pingList.pingsLoadingMesssage', { + defaultMessage: 'Loading history...', + }) + : i18n.translate('xpack.uptime.pingList.pingsUnavailableMessage', { + defaultMessage: 'No history found', + }) + } onChange={(criteria: any) => { setPageSize(criteria.page!.size); setPageIndex(criteria.page!.index); diff --git a/x-pack/plugins/uptime/public/lib/helper/test_helpers.ts b/x-pack/plugins/uptime/public/lib/helper/test_helpers.ts index b56b55f9146aec..ad842e7f34d1fb 100644 --- a/x-pack/plugins/uptime/public/lib/helper/test_helpers.ts +++ b/x-pack/plugins/uptime/public/lib/helper/test_helpers.ts @@ -62,6 +62,10 @@ export function mockReduxHooks(response?: any) { jest.spyOn(redux, 'useSelector').mockReturnValue(response); } +export function mockDispatch() { + jest.spyOn(redux, 'useDispatch').mockReturnValue(jest.fn()); +} + export function mockReactRouterDomHooks({ useParamsResponse }: { useParamsResponse: any }) { jest.spyOn(reactRouterDom, 'useParams').mockReturnValue(useParamsResponse); } diff --git a/x-pack/plugins/uptime/public/state/actions/ping.ts b/x-pack/plugins/uptime/public/state/actions/ping.ts index 70918a4cc70e56..af940ea00f3a29 100644 --- a/x-pack/plugins/uptime/public/state/actions/ping.ts +++ b/x-pack/plugins/uptime/public/state/actions/ping.ts @@ -12,6 +12,8 @@ import { GetPingsParams, } from '../../../common/runtime_types'; +export const clearPings = createAction('CLEAR PINGS'); + export const getPingHistogram = createAction('GET_PING_HISTOGRAM'); export const getPingHistogramSuccess = createAction('GET_PING_HISTOGRAM_SUCCESS'); export const getPingHistogramFail = createAction('GET_PING_HISTOGRAM_FAIL'); diff --git a/x-pack/plugins/uptime/public/state/reducers/ping_list.ts b/x-pack/plugins/uptime/public/state/reducers/ping_list.ts index 1fbdc6302f1137..da05a3ed3a036d 100644 --- a/x-pack/plugins/uptime/public/state/reducers/ping_list.ts +++ b/x-pack/plugins/uptime/public/state/reducers/ping_list.ts @@ -6,7 +6,7 @@ import { handleActions, Action } from 'redux-actions'; import { PingsResponse } from '../../../common/runtime_types'; -import { getPings, getPingsSuccess, getPingsFail } from '../actions'; +import { clearPings, getPings, getPingsSuccess, getPingsFail } from '../actions'; export interface PingListState { pingList: PingsResponse; @@ -26,6 +26,10 @@ type PingListPayload = PingsResponse & Error; export const pingListReducer = handleActions( { + [String(clearPings)]: (state) => ({ + ...state, + ...initialState, + }), [String(getPings)]: (state) => ({ ...state, loading: true, From 68288ebfdb31fadaff79c0ebceab0fd8eafbeb83 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Fri, 15 Jan 2021 13:43:27 -0500 Subject: [PATCH 17/33] [Monitoring] Change cloud messaging on no data page (#88375) * WIP * Update tests * Update copy * Fix translations and update copy * Fix tests and update copy --- .../no_data/blurbs/cloud_deployment.js | 64 +++++++++---------- .../__snapshots__/exporters.test.js.snap | 35 ++++++---- .../public/components/no_data/no_data.js | 49 +++++++++++++- .../__snapshots__/reason_found.test.js.snap | 35 ++++++---- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 6 files changed, 124 insertions(+), 63 deletions(-) diff --git a/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js b/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js index 073c84ee382aa1..c01243fdeec473 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js +++ b/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js @@ -4,45 +4,41 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment } from 'react'; -import { EuiTitle, EuiText, EuiTextColor, EuiLink, EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { EuiText, EuiTextColor, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; export const CloudDeployment = () => { return ( - - -

+ + +

-

-
- - - -

- - - cloud dashboard. - {' '} - - - the documentation. - -

-
-
-
+ + Elasticsearch Service Console + {' '} + + + Logs and metrics + {' '} + + + the documentation page. + +

+ + ); }; diff --git a/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap index ed45933fa94715..99f5a979c812be 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap @@ -87,29 +87,40 @@ Array [ exports[`ExplainExportersCloud should explain about xpack.monitoring.exporters setting in a cloud environment 1`] = ` Array [ -

- Your monitoring data is not available here. -

, -

- Please return to your + Configure monitoring through + + Elasticsearch Service Console + + + (opens in a new tab or window) + + + Go to - cloud dashboard. + Logs and metrics - For more information on Monitoring in Elastic Cloud, please see + section for a deployment to configure monitoring. For more information visit - the documentation. + the documentation page. + +

+ +

+ + + + + + +

+ +

+
+ + +

+ +

+
+
+ + +
+
+ + ); + } + if (useInternalCollection) { return ( diff --git a/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap index 9e3b7c0e25d5df..e3d25f97c9f783 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap @@ -162,29 +162,40 @@ Array [ exports[`ReasonFound should load ExplainExportersCloud component 1`] = ` Array [ -

- Your monitoring data is not available here. -

, -

- Please return to your + Configure monitoring through + + Elasticsearch Service Console + + + (opens in a new tab or window) + + + Go to - cloud dashboard. + Logs and metrics - For more information on Monitoring in Elastic Cloud, please see + section for a deployment to configure monitoring. For more information visit - the documentation. + the documentation page. Date: Fri, 15 Jan 2021 11:45:04 -0700 Subject: [PATCH 18/33] Change DELETE to POST for _bulk_delete to avoid incompatibility issues (#87914) ## Summary Changes `DELETE` to `POST` for _bulk_delete on the client only for a variety of reasons. According to the RFC, not all servers and proxies need to honor DELETE having a body. From: https://tools.ietf.org/html/rfc7231 ``` A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request. ``` Within at least one proxy, h2o2, we have found that it does indeed change request headers which will cause NodeJS to not attach the body of a `DELETE`: https://github.com/hapijs/h2o2/issues/124 Also from other communities such as OpenAPI where they debated this, they allow it but discourage it for reasons outlined there that I will not repeat here: https://github.com/OAI/OpenAPI-Specification/pull/1937 Elastic Search API's and other Kibana API's use `POST` rather than `DELETE` for their bodies that are attached to `DELETE`: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html We still support bodies in `DELETE` and `POST` but are just changing the web client to utilize `POST` moving forward. ### Checklist Reviewed and we already have unit tests and end to end tests for these use cases so we are good with just updating them. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../detections/containers/detection_engine/rules/api.test.ts | 2 +- .../public/detections/containers/detection_engine/rules/api.ts | 2 +- .../server/lib/detection_engine/scripts/delete_bulk.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts index e94cc8845c5a58..fce9974b458c5c 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts @@ -377,7 +377,7 @@ describe('Detections Rules API', () => { await deleteRules({ ids: ['mySuperRuleId', 'mySuperRuleId_II'] }); expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_bulk_delete', { body: '[{"id":"mySuperRuleId"},{"id":"mySuperRuleId_II"}]', - method: 'DELETE', + method: 'POST', }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts index a5dddd6d9afd39..da33b7841c7a90 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts @@ -205,7 +205,7 @@ export const enableRules = async ({ ids, enabled }: EnableRulesProps): Promise => KibanaServices.get().http.fetch(`${DETECTION_ENGINE_RULES_URL}/_bulk_delete`, { - method: 'DELETE', + method: 'POST', body: JSON.stringify(ids.map((id) => ({ id }))), }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/delete_bulk.sh b/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/delete_bulk.sh index 8f540e14ecdf18..6264a8e017ce32 100755 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/delete_bulk.sh +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/delete_bulk.sh @@ -17,6 +17,6 @@ curl -s -k \ -H 'Content-Type: application/json' \ -H 'kbn-xsrf: 123' \ -u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \ - -X DELETE ${KIBANA_URL}${SPACE_URL}/api/detection_engine/rules/_bulk_delete \ + -X POST ${KIBANA_URL}${SPACE_URL}/api/detection_engine/rules/_bulk_delete \ -d @${RULES} \ | jq .; From 208c76889de705770ede2d2b976d63e2ffc4657e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Fri, 15 Jan 2021 20:00:32 +0100 Subject: [PATCH 19/33] [Security Solution] Fix Timeline event details layout (#88377) --- .../timelines/components/timeline/expandable_event/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx index 27d28aa525d566..9a15d5dadcc94d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/expandable_event/index.tsx @@ -58,7 +58,10 @@ const StyledFlexGroup = styled(EuiFlexGroup)` `; const StyledEuiFlexItem = styled(EuiFlexItem)` - overflow: hidden; + &.euiFlexItem { + flex: 1 0 0; + overflow: hidden; + } `; export const ExpandableEventTitle = React.memo( From 039b2ff05223ea93d9a43eaecdd17e43a3d442a7 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 15 Jan 2021 12:45:51 -0700 Subject: [PATCH 20/33] [Docs] clean-up vega map reference documenation (#88487) * [Docs] clean-up vega map reference documenation * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> --- docs/user/dashboard/vega-reference.asciidoc | 58 ++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/user/dashboard/vega-reference.asciidoc b/docs/user/dashboard/vega-reference.asciidoc index d6593143e4f6df..f05d58918a2ebe 100644 --- a/docs/user/dashboard/vega-reference.asciidoc +++ b/docs/user/dashboard/vega-reference.asciidoc @@ -216,24 +216,8 @@ on the currently picked range: `"interval": {"%autointerval%": 10}` will try to get about 10-15 data points (buckets). [float] -[[vega-esmfiles]] -=== Access Elastic Map Service files - -experimental[] Access the Elastic Map Service files via the same mechanism: - -[source,yaml] ----- -url: { - // "type" defaults to "elasticsearch" otherwise - type: emsfile - // Name of the file, exactly as in the Region map visualization - name: World Countries -} -// The result is a geojson file, get its features to use -// this data source with the "shape" marks -// https://vega.github.io/vega/docs/marks/shape/ -format: {property: "features"} ----- +[[vega-with-a-map]] +=== Vega with a Map To enable Maps, the graph must specify `type=map` in the host configuration: @@ -282,6 +266,22 @@ Additionally, you can use `latitude`, `longitude`, and `zoom` signals. These signals can be used in the graph, or can be updated to modify the position of the map. +experimental[] You can use Vega's https://vega.github.io/vega/docs/data/[data] element to access https://www.elastic.co/elastic-maps-service[Elastic Maps Service (EMS)] vector shapes of administrative boundaries in your Vega map by setting `url.data` to `emsFile`: + +[source,yaml] +---- +url: { + // "type" defaults to "elasticsearch" otherwise + type: emsfile + // Name of the file, exactly as in the Region map visualization + name: World Countries +} +// The result is a geojson file, get its features to use +// this data source with the "shape" marks +// https://vega.github.io/vega/docs/marks/shape/ +format: {property: "features"} +---- + [float] [[vega-tooltip]] ==== Additional tooltip styling @@ -308,22 +308,22 @@ a configuration option for changing the tooltip position and padding: [[vega-url-loading]] ==== Advanced setting to enable URL loading from any domain -Vega can load data from any URL, but this is disabled by default in {kib}. +Vega can load data from any URL, but this is disabled by default in {kib}. To change this, set `vis_type_vega.enableExternalUrls: true` in `kibana.yml`, then restart {kib}. [float] [[vega-inspector]] ==== Vega Inspector -Use the contextual *Inspect* tool to gain insights into different elements. +Use the contextual *Inspect* tool to gain insights into different elements. For Vega visualizations, there are two different views: *Request* and *Vega debug*. [float] [[inspect-elasticsearch-requests]] ===== Inspect {es} requests -Vega uses the {ref}/search-search.html[{es} search API] to get documents and aggregation -results from {es}. To troubleshoot these requests, click *Inspect*, which shows the most recent requests. +Vega uses the {ref}/search-search.html[{es} search API] to get documents and aggregation +results from {es}. To troubleshoot these requests, click *Inspect*, which shows the most recent requests. In case your specification has more than one request, you can switch between the views using the *View* dropdown. [role="screenshot"] @@ -333,10 +333,10 @@ image::visualize/images/vega_tutorial_inspect_requests.png[] [[vega-debugging]] ===== Vega debugging -With the *Vega debug* view, you can inspect the *Data sets* and *Signal Values* runtime data. - -The runtime data is read from the -https://vega.github.io/vega/docs/api/debugging/#scope[runtime scope]. +With the *Vega debug* view, you can inspect the *Data sets* and *Signal Values* runtime data. + +The runtime data is read from the +https://vega.github.io/vega/docs/api/debugging/#scope[runtime scope]. [role="screenshot"] image::visualize/images/vega_tutorial_inspect_data_sets.png[] @@ -348,15 +348,15 @@ the <>. [[asking-for-help-with-a-vega-spec]] ===== Asking for help with a Vega spec -Because of the dynamic nature of the data in {es}, it is hard to help you with +Because of the dynamic nature of the data in {es}, it is hard to help you with Vega specs unless you can share a dataset. To do this, click *Inspect*, select the *Vega debug* view, then select the *Spec* tab: [role="screenshot"] image::visualize/images/vega_tutorial_getting_help.png[] -To copy the response, click *Copy to clipboard*. Paste the copied data to -https://gist.github.com/[gist.github.com], possibly with a .json extension. Use the [raw] button, +To copy the response, click *Copy to clipboard*. Paste the copied data to +https://gist.github.com/[gist.github.com], possibly with a .json extension. Use the [raw] button, and share that when asking for help. [float] From b9106282ec2a6fd5891d32a9113f713841b33f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 15 Jan 2021 21:01:53 +0100 Subject: [PATCH 21/33] [APM] Disable Create custom link button on Transaction details page for read-only users --- .../plugins/apm/common/custom_link/index.ts | 8 +++++ .../CustomLink/CreateCustomLinkButton.tsx | 14 ++------- .../CustomLinkToolbar.test.tsx | 20 ++++++++++-- .../CustomLinkToolbar.tsx | 30 +++++++++++------- .../CustomLinkMenuSection/index.tsx | 31 +++++++++++++------ .../TransactionActionMenu.test.tsx | 20 ++++++++++-- 6 files changed, 86 insertions(+), 37 deletions(-) diff --git a/x-pack/plugins/apm/common/custom_link/index.ts b/x-pack/plugins/apm/common/custom_link/index.ts index bc0ffefd79c4da..00162f50d889a7 100644 --- a/x-pack/plugins/apm/common/custom_link/index.ts +++ b/x-pack/plugins/apm/common/custom_link/index.ts @@ -12,3 +12,11 @@ export const INVALID_LICENSE = i18n.translate( "To create custom links, you must be subscribed to an Elastic Gold license or above. With it, you'll have the ability to create custom links to improve your workflow when analyzing your services.", } ); + +export const NO_PERMISSION_LABEL = i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.noPermissionTooltipLabel', + { + defaultMessage: + "Your user role doesn't have permissions to create custom links", + } +); diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx index 3b4c127aab1e5c..0a3d8f8b1e510d 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx @@ -6,24 +6,14 @@ import { EuiButton, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { NO_PERMISSION_LABEL } from '../../../../../../common/custom_link'; import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context'; export function CreateCustomLinkButton({ onClick }: { onClick: () => void }) { const { core } = useApmPluginContext(); const canSave = core.application.capabilities.apm.save; return ( - + - {children} + + {children} + ); } diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx index 36b370b4069aea..0fe3c461a49372 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/CustomLinkToolbar.tsx @@ -12,6 +12,8 @@ import { EuiIcon, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { NO_PERMISSION_LABEL } from '../../../../../common/custom_link'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { APMLink } from '../../Links/apm/APMLink'; export function CustomLinkToolbar({ @@ -21,6 +23,9 @@ export function CustomLinkToolbar({ onClickCreate: () => void; showCreateButton?: boolean; }) { + const { core } = useApmPluginContext(); + const canSave = !!core.application.capabilities.apm.save; + return ( @@ -42,17 +47,20 @@ export function CustomLinkToolbar({ {showCreateButton && ( - - - {i18n.translate('xpack.apm.customLink.buttom.create.title', { - defaultMessage: 'Create', - })} - - + + + + {i18n.translate('xpack.apm.customLink.buttom.create.title', { + defaultMessage: 'Create', + })} + + + )} diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx index a32302d2464234..ae22718af8b571 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/CustomLinkMenuSection/index.tsx @@ -13,6 +13,9 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; +import { EuiToolTip } from '@elastic/eui'; +import { NO_PERMISSION_LABEL } from '../../../../../common/custom_link'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { ActionMenuDivider, Section, @@ -147,6 +150,9 @@ function BottomSection({ toggleShowAll: () => void; onClickCreate: () => void; }) { + const { core } = useApmPluginContext(); + const canSave = !!core.application.capabilities.apm.save; + if (status === FETCH_STATUS.LOADING) { return ; } @@ -154,7 +160,7 @@ function BottomSection({ // render empty prompt if there are no custom links if (isEmpty(customLinks)) { return ( - + {i18n.translate('xpack.apm.customLink.empty', { @@ -163,15 +169,20 @@ function BottomSection({ })} - - {i18n.translate('xpack.apm.customLink.buttom.create', { - defaultMessage: 'Create custom link', - })} - + + + + + {i18n.translate('xpack.apm.customLink.buttom.create', { + defaultMessage: 'Create custom link', + })} + + ); diff --git a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx index 6ff395db594f13..48c863b4604820 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.test.tsx @@ -9,7 +9,11 @@ import React from 'react'; import { MemoryRouter } from 'react-router-dom'; import { License } from '../../../../../licensing/common/license'; import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; -import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; +import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; +import { + mockApmPluginContextValue, + MockApmPluginContextWrapper, +} from '../../../context/apm_plugin/mock_apm_plugin_context'; import { LicenseContext } from '../../../context/license/license_context'; import * as hooks from '../../../hooks/use_fetcher'; import * as apmApi from '../../../services/rest/createCallApmApi'; @@ -20,10 +24,22 @@ import { import { TransactionActionMenu } from './TransactionActionMenu'; import * as Transactions from './__fixtures__/mockData'; +function getMockAPMContext({ canSave }: { canSave: boolean }) { + return ({ + ...mockApmPluginContextValue, + core: { + ...mockApmPluginContextValue.core, + application: { capabilities: { apm: { save: canSave }, ml: {} } }, + }, + } as unknown) as ApmPluginContextValue; +} + function Wrapper({ children }: { children?: React.ReactNode }) { return ( - {children} + + {children} + ); } From 5b38816a97b4f2bdd43700b46a94a5371cfc90ae Mon Sep 17 00:00:00 2001 From: Constance Date: Fri, 15 Jan 2021 12:39:26 -0800 Subject: [PATCH 22/33] [Enterprise Search] Automatically mock shared logic files (#88494) * Update shared logic mocks to automatically mock their exports * Update FlashMessages to also mock its helper fns * Fix tests that were relying on component exports from shared logic files * Fix broken flash_messages tests - Caused by leaking auto mocks - work around this by importing from files directly and not from index.ts - Also clean up / use new auto mocks (e.g. for kibana) - Convert old instances of useValues mock to setMockValues * [AS] Update AnalyticsLogic test to use new auto mockers + move LogicMounter and destructured mock values to top of describe block * [AS] Update CredentialsLogic + udpate to use new clearFlashMessages helper * [AS] Update documents logic tests * [AS] Update engines logic tests * [AS] Update log retention logic test * [Shared] Update IndexingStatus tests + update to use LogicMounter * [Shared] Update telemetry logic test * [WS] Update AddSourceLogic + update to use new clearFlashMessages helper * [WS] Update groups logic files + update to use new flash message helpers * [WS] Update OverviewLogic test * [WS] Update AddSource component test + consolidate mocks imports * [Shared] Clean up KibanaLogic imports - all jest.mocks come along from the ride when the __mocks__ folder is imported, so HttpLogic is now automatically already mocked * [AS] Update EngineRouter test --- .../__mocks__/flash_messages_logic.mock.ts | 18 +++ .../applications/__mocks__/http_logic.mock.ts | 4 + .../public/applications/__mocks__/index.ts | 6 +- .../__mocks__/kibana_logic.mock.ts | 4 + .../__mocks__/licensing_logic.mock.ts | 4 + .../__mocks__/telemetry_logic.mock.ts | 5 + .../analytics/analytics_logic.test.ts | 62 ++++---- .../credentials/credentials_logic.test.ts | 29 ++-- .../credentials/credentials_logic.ts | 4 +- .../document_creation_logic.test.ts | 26 +--- .../documents/document_detail_logic.test.ts | 35 ++--- .../components/engine/engine_logic.test.ts | 10 +- .../components/engine/engine_router.test.tsx | 8 +- .../engine_overview_logic.test.ts | 23 ++- .../components/engines/engines_logic.test.ts | 20 ++- .../log_retention/log_retention_logic.test.ts | 23 ++- .../flash_messages/flash_messages.test.tsx | 11 +- .../flash_messages_logic.test.ts | 14 +- .../flash_messages/handle_api_errors.test.ts | 14 +- .../flash_messages/handle_api_errors.ts | 2 +- .../set_message_helpers.test.ts | 12 +- .../flash_messages/set_message_helpers.ts | 2 +- .../indexing_status_logic.test.ts | 36 ++--- .../shared/kibana/kibana_logic.test.ts | 5 +- .../shared/telemetry/telemetry_logic.test.ts | 11 +- .../components/add_source/add_source.test.tsx | 21 +-- .../add_source/add_source_logic.test.ts | 107 ++++++-------- .../components/add_source/add_source_logic.ts | 8 +- .../views/groups/group_logic.test.ts | 136 +++++++----------- .../views/groups/group_logic.ts | 18 ++- .../views/groups/groups_logic.test.ts | 66 +++------ .../views/groups/groups_logic.ts | 10 +- .../views/overview/overview_logic.test.ts | 7 +- 33 files changed, 318 insertions(+), 443 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/flash_messages_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/flash_messages_logic.mock.ts index a610ea0238ac00..f36a565ac54160 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/flash_messages_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/flash_messages_logic.mock.ts @@ -15,3 +15,21 @@ export const mockFlashMessagesActions = { setQueuedMessages: jest.fn(), clearQueuedMessages: jest.fn(), }; + +export const mockFlashMessageHelpers = { + flashAPIErrors: jest.fn(), + setSuccessMessage: jest.fn(), + setErrorMessage: jest.fn(), + setQueuedSuccessMessage: jest.fn(), + setQueuedErrorMessage: jest.fn(), + clearFlashMessages: jest.fn(), +}; + +jest.mock('../shared/flash_messages', () => ({ + ...(jest.requireActual('../shared/flash_messages') as object), + ...mockFlashMessageHelpers, + FlashMessagesLogic: { + values: mockFlashMessagesValues, + actions: mockFlashMessagesActions, + }, +})); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/http_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/http_logic.mock.ts index e77863c70c23a9..4b151d86767348 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/http_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/http_logic.mock.ts @@ -11,3 +11,7 @@ export const mockHttpValues = { errorConnecting: false, readOnlyMode: false, }; + +jest.mock('../shared/http', () => ({ + HttpLogic: { values: mockHttpValues }, +})); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts index 85b2821cd40eeb..f4e13eca11a5ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts @@ -9,7 +9,11 @@ export { mockKibanaValues } from './kibana_logic.mock'; export { mockLicensingValues } from './licensing_logic.mock'; export { mockHttpValues } from './http_logic.mock'; export { mockTelemetryActions } from './telemetry_logic.mock'; -export { mockFlashMessagesValues, mockFlashMessagesActions } from './flash_messages_logic.mock'; +export { + mockFlashMessagesValues, + mockFlashMessagesActions, + mockFlashMessageHelpers, +} from './flash_messages_logic.mock'; export { mockAllValues, mockAllActions, diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts index e1e20adbe5759b..15870001d9e44e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kibana_logic.mock.ts @@ -20,3 +20,7 @@ export const mockKibanaValues = { setDocTitle: jest.fn(), renderHeaderActions: jest.fn(), }; + +jest.mock('../shared/kibana', () => ({ + KibanaLogic: { values: mockKibanaValues }, +})); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts index 51b32e7a877b26..0cdba1d33c5c2e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/licensing_logic.mock.ts @@ -11,3 +11,7 @@ export const mockLicensingValues = { hasPlatinumLicense: false, hasGoldLicense: false, }; + +jest.mock('../shared/licensing', () => ({ + LicensingLogic: { values: mockLicensingValues }, +})); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/telemetry_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/telemetry_logic.mock.ts index 437e920ef008c0..4f915ce4d9ceab 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/telemetry_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/telemetry_logic.mock.ts @@ -10,3 +10,8 @@ export const mockTelemetryActions = { sendAppSearchTelemetry: jest.fn(), sendWorkplaceSearchTelemetry: jest.fn(), }; + +jest.mock('../shared/telemetry', () => ({ + ...(jest.requireActual('../shared/telemetry') as object), + TelemetryLogic: { actions: mockTelemetryActions }, +})); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts index 7be811b7b27db4..9d1c6bf09fc219 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_logic.test.ts @@ -4,22 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter, expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/kibana', () => ({ - KibanaLogic: { values: { history: { location: { search: '' } } } }, -})); -import { KibanaLogic } from '../../../shared/kibana'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: { http: { get: jest.fn() } } }, -})); -import { HttpLogic } from '../../../shared/http'; - -jest.mock('../../../shared/flash_messages', () => ({ - flashAPIErrors: jest.fn(), -})); -import { flashAPIErrors } from '../../../shared/flash_messages'; +import { + LogicMounter, + mockKibanaValues, + mockHttpValues, + mockFlashMessageHelpers, + expectedAsyncError, +} from '../../../__mocks__'; jest.mock('../engine', () => ({ EngineLogic: { values: { engineName: 'test-engine' } }, @@ -28,6 +19,11 @@ jest.mock('../engine', () => ({ import { AnalyticsLogic } from './'; describe('AnalyticsLogic', () => { + const { mount } = new LogicMounter(AnalyticsLogic); + const { history } = mockKibanaValues; + const { http } = mockHttpValues; + const { flashAPIErrors } = mockFlashMessageHelpers; + const DEFAULT_VALUES = { dataLoading: true, analyticsUnavailable: false, @@ -88,11 +84,9 @@ describe('AnalyticsLogic', () => { topClicksForQuery: MOCK_TOP_CLICKS, }; - const { mount } = new LogicMounter(AnalyticsLogic); - beforeEach(() => { jest.clearAllMocks(); - KibanaLogic.values.history.location.search = ''; + history.location.search = ''; }); it('has expected default values', () => { @@ -158,14 +152,14 @@ describe('AnalyticsLogic', () => { it('should make an API call and set state based on the response', async () => { const promise = Promise.resolve(MOCK_ANALYTICS_RESPONSE); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsDataLoad'); AnalyticsLogic.actions.loadAnalyticsData(); await promise; - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/app_search/engines/test-engine/analytics/queries', { query: { size: 20 }, @@ -177,14 +171,13 @@ describe('AnalyticsLogic', () => { }); it('parses and passes the current search query string', async () => { - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce({}); - KibanaLogic.values.history.location.search = - '?start=1970-01-01&end=1970-01-02&&tag=some_tag'; + (http.get as jest.Mock).mockReturnValueOnce({}); + history.location.search = '?start=1970-01-01&end=1970-01-02&&tag=some_tag'; mount(); AnalyticsLogic.actions.loadAnalyticsData(); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/app_search/engines/test-engine/analytics/queries', { query: { @@ -199,7 +192,7 @@ describe('AnalyticsLogic', () => { it('calls onAnalyticsUnavailable if analyticsUnavailable is in response', async () => { const promise = Promise.resolve({ analyticsUnavailable: true }); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsUnavailable'); @@ -211,7 +204,7 @@ describe('AnalyticsLogic', () => { it('handles errors', async () => { const promise = Promise.reject('error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsUnavailable'); @@ -237,14 +230,14 @@ describe('AnalyticsLogic', () => { it('should make an API call and set state based on the response', async () => { const promise = Promise.resolve(MOCK_QUERY_RESPONSE); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount(); jest.spyOn(AnalyticsLogic.actions, 'onQueryDataLoad'); AnalyticsLogic.actions.loadQueryData('some-query'); await promise; - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/app_search/engines/test-engine/analytics/queries/some-query', expect.any(Object) // empty query obj ); @@ -252,14 +245,13 @@ describe('AnalyticsLogic', () => { }); it('parses and passes the current search query string', async () => { - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce({}); - KibanaLogic.values.history.location.search = - '?start=1970-12-30&end=1970-12-31&&tag=another_tag'; + (http.get as jest.Mock).mockReturnValueOnce({}); + history.location.search = '?start=1970-12-30&end=1970-12-31&&tag=another_tag'; mount(); AnalyticsLogic.actions.loadQueryData('some-query'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/app_search/engines/test-engine/analytics/queries/some-query', { query: { @@ -273,7 +265,7 @@ describe('AnalyticsLogic', () => { it('calls onAnalyticsUnavailable if analyticsUnavailable is in response', async () => { const promise = Promise.resolve({ analyticsUnavailable: true }); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsUnavailable'); @@ -285,7 +277,7 @@ describe('AnalyticsLogic', () => { it('handles errors', async () => { const promise = Promise.reject('error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount(); jest.spyOn(AnalyticsLogic.actions, 'onAnalyticsUnavailable'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts index b33d1eba572ec2..cdd055fd367efe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts @@ -4,23 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: mockHttpValues }, -})); -const { http } = mockHttpValues; - -jest.mock('../../../shared/flash_messages', () => ({ - FlashMessagesLogic: { actions: { clearFlashMessages: jest.fn() } }, - setSuccessMessage: jest.fn(), - flashAPIErrors: jest.fn(), -})); import { - FlashMessagesLogic, - setSuccessMessage, - flashAPIErrors, -} from '../../../shared/flash_messages'; + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, + expectedAsyncError, +} from '../../../__mocks__'; jest.mock('../../app_logic', () => ({ AppLogic: { @@ -34,6 +23,10 @@ import { ApiTokenTypes } from './constants'; import { CredentialsLogic } from './credentials_logic'; describe('CredentialsLogic', () => { + const { mount } = new LogicMounter(CredentialsLogic); + const { http } = mockHttpValues; + const { clearFlashMessages, setSuccessMessage, flashAPIErrors } = mockFlashMessageHelpers; + const DEFAULT_VALUES = { activeApiToken: { name: '', @@ -56,8 +49,6 @@ describe('CredentialsLogic', () => { fullEngineAccessChecked: false, }; - const { mount } = new LogicMounter(CredentialsLogic); - const newToken = { id: 1, name: 'myToken', @@ -955,7 +946,7 @@ describe('CredentialsLogic', () => { describe('listener side-effects', () => { it('should clear flashMessages whenever the credentials form flyout is opened', () => { CredentialsLogic.actions.showCredentialsForm(); - expect(FlashMessagesLogic.actions.clearFlashMessages).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts index 166cbae9a45129..8afb7696ec1668 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.ts @@ -11,7 +11,7 @@ import { ApiTokenTypes, CREATE_MESSAGE, UPDATE_MESSAGE, DELETE_MESSAGE } from '. import { HttpLogic } from '../../../shared/http'; import { - FlashMessagesLogic, + clearFlashMessages, setSuccessMessage, flashAPIErrors, } from '../../../shared/flash_messages'; @@ -227,7 +227,7 @@ export const CredentialsLogic = kea({ }), listeners: ({ actions, values }) => ({ showCredentialsForm: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, initializeCredentialsData: () => { actions.fetchCredentials(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts index c2a0d29cc1f405..2256d5ae7946a3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; +import { LogicMounter, mockHttpValues } from '../../../__mocks__'; import dedent from 'dedent'; @@ -13,11 +13,6 @@ jest.mock('./utils', () => ({ })); import { readUploadedFileAsText } from './utils'; -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: { http: { post: jest.fn() } } }, -})); -import { HttpLogic } from '../../../shared/http'; - jest.mock('../engine', () => ({ EngineLogic: { values: { engineName: 'test-engine' } }, })); @@ -27,6 +22,9 @@ import { DocumentCreationStep } from './types'; import { DocumentCreationLogic } from './'; describe('DocumentCreationLogic', () => { + const { mount } = new LogicMounter(DocumentCreationLogic); + const { http } = mockHttpValues; + const DEFAULT_VALUES = { isDocumentCreationOpen: false, creationMode: 'text', @@ -40,8 +38,6 @@ describe('DocumentCreationLogic', () => { }; const mockFile = new File(['mockFile'], 'mockFile.json'); - const { mount } = new LogicMounter(DocumentCreationLogic); - beforeEach(() => { jest.clearAllMocks(); }); @@ -447,10 +443,7 @@ describe('DocumentCreationLogic', () => { }); it('should set and show summary from the returned response', async () => { - const { http } = HttpLogic.values; - const promise = (http.post as jest.Mock).mockReturnValueOnce( - Promise.resolve(mockValidResponse) - ); + const promise = http.post.mockReturnValueOnce(Promise.resolve(mockValidResponse)); await DocumentCreationLogic.actions.uploadDocuments({ documents: mockValidDocuments }); await promise; @@ -469,8 +462,7 @@ describe('DocumentCreationLogic', () => { }); it('handles API errors', async () => { - const { http } = HttpLogic.values; - const promise = (http.post as jest.Mock).mockReturnValueOnce( + const promise = http.post.mockReturnValueOnce( Promise.reject({ body: { statusCode: 400, @@ -489,7 +481,6 @@ describe('DocumentCreationLogic', () => { }); it('handles client-side errors', async () => { - const { http } = HttpLogic.values; const promise = (http.post as jest.Mock).mockReturnValueOnce(new Error()); await DocumentCreationLogic.actions.uploadDocuments({ documents: [{}] }); @@ -502,8 +493,7 @@ describe('DocumentCreationLogic', () => { // NOTE: I can't seem to reproduce this in a production setting. it('handles errors returned from the API', async () => { - const { http } = HttpLogic.values; - const promise = (http.post as jest.Mock).mockReturnValueOnce( + const promise = http.post.mockReturnValueOnce( Promise.resolve({ errors: ['JSON cannot be empty'], }) @@ -546,7 +536,6 @@ describe('DocumentCreationLogic', () => { }); it('should correctly merge multiple API calls into a single summary obj', async () => { - const { http } = HttpLogic.values; const promise = (http.post as jest.Mock) .mockReturnValueOnce(mockFirstResponse) .mockReturnValueOnce(mockSecondResponse); @@ -573,7 +562,6 @@ describe('DocumentCreationLogic', () => { }); it('should correctly merge response errors', async () => { - const { http } = HttpLogic.values; const promise = (http.post as jest.Mock) .mockReturnValueOnce({ ...mockFirstResponse, errors: ['JSON cannot be empty'] }) .mockReturnValueOnce({ ...mockSecondResponse, errors: ['Too large to render'] }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts index 015a9abd5405cd..f7476083009df0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts @@ -4,39 +4,32 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: mockHttpValues }, -})); -const { http } = mockHttpValues; +import { + LogicMounter, + mockHttpValues, + mockKibanaValues, + mockFlashMessageHelpers, + expectedAsyncError, +} from '../../../__mocks__'; jest.mock('../engine', () => ({ EngineLogic: { values: { engineName: 'engine1' } }, })); -jest.mock('../../../shared/kibana', () => ({ - KibanaLogic: { values: { navigateToUrl: jest.fn() } }, -})); -import { KibanaLogic } from '../../../shared/kibana'; - -jest.mock('../../../shared/flash_messages', () => ({ - setQueuedSuccessMessage: jest.fn(), - flashAPIErrors: jest.fn(), -})); -import { setQueuedSuccessMessage, flashAPIErrors } from '../../../shared/flash_messages'; - import { DocumentDetailLogic } from './document_detail_logic'; import { InternalSchemaTypes } from '../../../shared/types'; describe('DocumentDetailLogic', () => { + const { mount } = new LogicMounter(DocumentDetailLogic); + const { http } = mockHttpValues; + const { navigateToUrl } = mockKibanaValues; + const { setQueuedSuccessMessage, flashAPIErrors } = mockFlashMessageHelpers; + const DEFAULT_VALUES = { dataLoading: true, fields: [], }; - const { mount } = new LogicMounter(DocumentDetailLogic); - beforeEach(() => { jest.clearAllMocks(); }); @@ -84,7 +77,7 @@ describe('DocumentDetailLogic', () => { await expectedAsyncError(promise); expect(flashAPIErrors).toHaveBeenCalledWith('An error occurred', { isQueued: true }); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith('/engines/engine1/documents'); + expect(navigateToUrl).toHaveBeenCalledWith('/engines/engine1/documents'); }); }); @@ -112,7 +105,7 @@ describe('DocumentDetailLogic', () => { expect(setQueuedSuccessMessage).toHaveBeenCalledWith( 'Successfully marked document for deletion. It will be deleted momentarily.' ); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith('/engines/engine1/documents'); + expect(navigateToUrl).toHaveBeenCalledWith('/engines/engine1/documents'); }); it('will do nothing if not confirmed', async () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts index 8d855bebdb20f7..62f444cf8f6ab8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts @@ -6,14 +6,12 @@ import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: mockHttpValues }, -})); -const { http } = mockHttpValues; - import { EngineLogic } from './'; describe('EngineLogic', () => { + const { mount } = new LogicMounter(EngineLogic); + const { http } = mockHttpValues; + const mockEngineData = { name: 'some-engine', type: 'default', @@ -45,8 +43,6 @@ describe('EngineLogic', () => { engineNotFound: false, }; - const { mount } = new LogicMounter(EngineLogic); - beforeEach(() => { jest.clearAllMocks(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx index 26c7b3f677fc1a..362454c31f0d96 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.test.tsx @@ -6,17 +6,12 @@ import '../../../__mocks__/react_router_history.mock'; import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; -import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; +import { mockFlashMessageHelpers, setMockValues, setMockActions } from '../../../__mocks__'; import React from 'react'; import { shallow } from 'enzyme'; import { Switch, Redirect, useParams } from 'react-router-dom'; -jest.mock('../../../shared/flash_messages', () => ({ - setQueuedErrorMessage: jest.fn(), -})); -import { setQueuedErrorMessage } from '../../../shared/flash_messages'; - import { Loading } from '../../../shared/loading'; import { EngineOverview } from '../engine_overview'; import { AnalyticsRouter } from '../analytics'; @@ -58,6 +53,7 @@ describe('EngineRouter', () => { }); it('redirects to engines list and flashes an error if the engine param was not found', () => { + const { setQueuedErrorMessage } = mockFlashMessageHelpers; setMockValues({ ...values, engineNotFound: true, engineName: '404-engine' }); const wrapper = shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts index 46d5a7b6608a52..b6620756699d51 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts @@ -4,17 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: mockHttpValues }, -})); -const { http } = mockHttpValues; - -jest.mock('../../../shared/flash_messages', () => ({ - flashAPIErrors: jest.fn(), -})); -import { flashAPIErrors } from '../../../shared/flash_messages'; +import { + LogicMounter, + mockHttpValues, + mockFlashMessageHelpers, + expectedAsyncError, +} from '../../../__mocks__'; jest.mock('../engine', () => ({ EngineLogic: { values: { engineName: 'some-engine' } }, @@ -23,6 +18,10 @@ jest.mock('../engine', () => ({ import { EngineOverviewLogic } from './'; describe('EngineOverviewLogic', () => { + const { mount, unmount } = new LogicMounter(EngineOverviewLogic); + const { http } = mockHttpValues; + const { flashAPIErrors } = mockFlashMessageHelpers; + const mockEngineMetrics = { apiLogsUnavailable: true, documentCount: 10, @@ -45,8 +44,6 @@ describe('EngineOverviewLogic', () => { timeoutId: null, }; - const { mount, unmount } = new LogicMounter(EngineOverviewLogic); - beforeEach(() => { jest.clearAllMocks(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts index 157ae396319ac6..5a83717aa00301 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_logic.test.ts @@ -4,17 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter } from '../../../__mocks__/kea.mock'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: { http: { get: jest.fn() } } }, -})); -import { HttpLogic } from '../../../shared/http'; +import { LogicMounter, mockHttpValues } from '../../../__mocks__'; import { EngineDetails } from '../engine/types'; import { EnginesLogic } from './'; describe('EnginesLogic', () => { + const { mount } = new LogicMounter(EnginesLogic); + const { http } = mockHttpValues; + const DEFAULT_VALUES = { dataLoading: true, engines: [], @@ -43,8 +41,6 @@ describe('EnginesLogic', () => { }, }; - const { mount } = new LogicMounter(EnginesLogic); - beforeEach(() => { jest.clearAllMocks(); }); @@ -129,14 +125,14 @@ describe('EnginesLogic', () => { describe('loadEngines', () => { it('should call the engines API endpoint and set state based on the results', async () => { const promise = Promise.resolve(MOCK_ENGINES_API_RESPONSE); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount({ enginesPage: 10 }); jest.spyOn(EnginesLogic.actions, 'onEnginesLoad'); EnginesLogic.actions.loadEngines(); await promise; - expect(HttpLogic.values.http.get).toHaveBeenCalledWith('/api/app_search/engines', { + expect(http.get).toHaveBeenCalledWith('/api/app_search/engines', { query: { type: 'indexed', pageIndex: 10 }, }); expect(EnginesLogic.actions.onEnginesLoad).toHaveBeenCalledWith({ @@ -149,14 +145,14 @@ describe('EnginesLogic', () => { describe('loadMetaEngines', () => { it('should call the engines API endpoint and set state based on the results', async () => { const promise = Promise.resolve(MOCK_ENGINES_API_RESPONSE); - (HttpLogic.values.http.get as jest.Mock).mockReturnValueOnce(promise); + http.get.mockReturnValueOnce(promise); mount({ metaEnginesPage: 99 }); jest.spyOn(EnginesLogic.actions, 'onMetaEnginesLoad'); EnginesLogic.actions.loadMetaEngines(); await promise; - expect(HttpLogic.values.http.get).toHaveBeenCalledWith('/api/app_search/engines', { + expect(http.get).toHaveBeenCalledWith('/api/app_search/engines', { query: { type: 'meta', pageIndex: 99 }, }); expect(EnginesLogic.actions.onMetaEnginesLoad).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts index b1920b6ddea8a7..bfdca6791edc13 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts @@ -4,22 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LogicMounter, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { values: mockHttpValues }, -})); -const { http } = mockHttpValues; - -jest.mock('../../../shared/flash_messages', () => ({ - flashAPIErrors: jest.fn(), -})); -import { flashAPIErrors } from '../../../shared/flash_messages'; +import { + LogicMounter, + mockHttpValues, + mockFlashMessageHelpers, + expectedAsyncError, +} from '../../../__mocks__'; import { LogRetentionOptions } from './types'; import { LogRetentionLogic } from './log_retention_logic'; describe('LogRetentionLogic', () => { + const { mount } = new LogicMounter(LogRetentionLogic); + const { http } = mockHttpValues; + const { flashAPIErrors } = mockFlashMessageHelpers; + const TYPICAL_SERVER_LOG_RETENTION = { analytics: { disabled_at: null, @@ -52,8 +51,6 @@ describe('LogRetentionLogic', () => { isLogRetentionUpdating: false, }; - const { mount } = new LogicMounter(LogRetentionLogic); - beforeEach(() => { jest.clearAllMocks(); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx index 59bb7ee5b96252..746ac20016cc4e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages.test.tsx @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../__mocks__/kea.mock'; +import { setMockValues } from '../../__mocks__/kea.mock'; -import { useValues } from 'kea'; import React from 'react'; import { shallow } from 'enzyme'; import { EuiCallOut } from '@elastic/eui'; -import { FlashMessages } from './'; +import { FlashMessages } from './flash_messages'; describe('FlashMessages', () => { beforeEach(() => { @@ -19,7 +18,7 @@ describe('FlashMessages', () => { }); it('does not render if no messages exist', () => { - (useValues as jest.Mock).mockImplementationOnce(() => ({ messages: [] })); + setMockValues({ messages: [] }); const wrapper = shallow(); @@ -38,7 +37,7 @@ describe('FlashMessages', () => { { type: 'warning', message: 'Uh oh' }, { type: 'info', message: 'Testing multiples of same type' }, ]; - (useValues as jest.Mock).mockImplementationOnce(() => ({ messages: mockMessages })); + setMockValues({ messages: mockMessages }); const wrapper = shallow(); @@ -49,7 +48,7 @@ describe('FlashMessages', () => { }); it('renders any children', () => { - (useValues as jest.Mock).mockImplementationOnce(() => ({ messages: [{ type: 'success' }] })); + setMockValues({ messages: [{ type: 'success' }] }); const wrapper = shallow( diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts index ff1ec7428e8289..029c89340ca8b4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/flash_messages_logic.test.ts @@ -6,12 +6,10 @@ import { resetContext } from 'kea'; -import { mockHistory } from '../../__mocks__'; -jest.mock('../kibana', () => ({ - KibanaLogic: { values: { history: mockHistory } }, -})); +import { mockKibanaValues } from '../../__mocks__/kibana_logic.mock'; +const { history } = mockKibanaValues; -import { FlashMessagesLogic, mountFlashMessagesLogic, IFlashMessage } from './'; +import { FlashMessagesLogic, mountFlashMessagesLogic, IFlashMessage } from './flash_messages_logic'; describe('FlashMessagesLogic', () => { const mount = () => mountFlashMessagesLogic(); @@ -98,7 +96,7 @@ describe('FlashMessagesLogic', () => { describe('on mount', () => { it('listens for history changes and clears messages on change', () => { mount(); - expect(mockHistory.listen).toHaveBeenCalled(); + expect(history.listen).toHaveBeenCalled(); FlashMessagesLogic.actions.setQueuedMessages(['queuedMessages'] as any); jest.spyOn(FlashMessagesLogic.actions, 'clearFlashMessages'); @@ -106,7 +104,7 @@ describe('FlashMessagesLogic', () => { jest.spyOn(FlashMessagesLogic.actions, 'clearQueuedMessages'); jest.spyOn(FlashMessagesLogic.actions, 'setHistoryListener'); - const mockHistoryChange = (mockHistory.listen.mock.calls[0] as any)[0]; + const mockHistoryChange = (history.listen.mock.calls[0] as any)[0]; mockHistoryChange(); expect(FlashMessagesLogic.actions.clearFlashMessages).toHaveBeenCalled(); expect(FlashMessagesLogic.actions.setFlashMessages).toHaveBeenCalledWith([ @@ -119,7 +117,7 @@ describe('FlashMessagesLogic', () => { describe('on unmount', () => { it('removes history listener', () => { const mockUnlistener = jest.fn(); - mockHistory.listen.mockReturnValueOnce(mockUnlistener); + history.listen.mockReturnValueOnce(mockUnlistener); const unmount = mount(); unmount(); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts index c30631329b79d9..fbdb38937cc714 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.test.ts @@ -4,16 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('./', () => ({ - FlashMessagesLogic: { - actions: { - setFlashMessages: jest.fn(), - setQueuedMessages: jest.fn(), - }, - }, -})); -import { FlashMessagesLogic } from './'; +import '../../__mocks__/kibana_logic.mock'; +import { FlashMessagesLogic } from './flash_messages_logic'; import { flashAPIErrors } from './handle_api_errors'; describe('flashAPIErrors', () => { @@ -30,6 +23,9 @@ describe('flashAPIErrors', () => { beforeEach(() => { jest.clearAllMocks(); + FlashMessagesLogic.mount(); + jest.spyOn(FlashMessagesLogic.actions, 'setFlashMessages'); + jest.spyOn(FlashMessagesLogic.actions, 'setQueuedMessages'); }); it('converts API errors into flash messages', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts index c4b287ee08354f..783a61296cac89 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/handle_api_errors.ts @@ -6,7 +6,7 @@ import { HttpResponse } from 'src/core/public'; -import { FlashMessagesLogic, IFlashMessage } from './'; +import { FlashMessagesLogic, IFlashMessage } from './flash_messages_logic'; /** * The API errors we are handling can come from one of two ways: diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts index 4a5a4bb6be1f3d..5de16bde98926f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.test.ts @@ -4,26 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import { mockHistory } from '../../__mocks__'; -jest.mock('../kibana', () => ({ - KibanaLogic: { values: { history: mockHistory } }, -})); +import '../../__mocks__/kibana_logic.mock'; +import { FlashMessagesLogic } from './flash_messages_logic'; import { - FlashMessagesLogic, - mountFlashMessagesLogic, setSuccessMessage, setErrorMessage, setQueuedSuccessMessage, setQueuedErrorMessage, clearFlashMessages, -} from './'; +} from './set_message_helpers'; describe('Flash Message Helpers', () => { const message = 'I am a message'; beforeEach(() => { - mountFlashMessagesLogic(); + FlashMessagesLogic.mount(); }); it('setSuccessMessage()', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.ts b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.ts index e054ff6e2fd5a3..15ee890aaf2e40 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/flash_messages/set_message_helpers.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FlashMessagesLogic } from './'; +import { FlashMessagesLogic } from './flash_messages_logic'; export const setSuccessMessage = (message: string) => { FlashMessagesLogic.actions.setFlashMessages({ diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts index abddb96275c6f2..558271a8fbdc61 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status_logic.test.ts @@ -4,26 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; - -import { expectedAsyncError } from '../../__mocks__'; - -jest.mock('../http', () => ({ - HttpLogic: { - values: { http: { get: jest.fn() } }, - }, -})); -import { HttpLogic } from '../http'; - -jest.mock('../flash_messages', () => ({ - flashAPIErrors: jest.fn(), -})); -import { flashAPIErrors } from '../flash_messages'; +import { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, + expectedAsyncError, +} from '../../__mocks__'; import { IndexingStatusLogic } from './indexing_status_logic'; describe('IndexingStatusLogic', () => { - let unmount: any; + const { mount, unmount } = new LogicMounter(IndexingStatusLogic); + const { http } = mockHttpValues; + const { flashAPIErrors } = mockFlashMessageHelpers; const mockStatusResponse = { percentageComplete: 50, @@ -33,8 +26,7 @@ describe('IndexingStatusLogic', () => { beforeEach(() => { jest.clearAllMocks(); - resetContext({}); - unmount = IndexingStatusLogic.mount(); + mount(); }); it('has expected default values', () => { @@ -66,12 +58,12 @@ describe('IndexingStatusLogic', () => { it('calls API and sets values', async () => { const setIndexingStatusSpy = jest.spyOn(IndexingStatusLogic.actions, 'setIndexingStatus'); const promise = Promise.resolve(mockStatusResponse); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); IndexingStatusLogic.actions.fetchIndexingStatus({ statusPath, onComplete }); jest.advanceTimersByTime(TIMEOUT); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith(statusPath); + expect(http.get).toHaveBeenCalledWith(statusPath); await promise; expect(setIndexingStatusSpy).toHaveBeenCalledWith(mockStatusResponse); @@ -79,7 +71,7 @@ describe('IndexingStatusLogic', () => { it('handles error', async () => { const promise = Promise.reject('An error occured'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); IndexingStatusLogic.actions.fetchIndexingStatus({ statusPath, onComplete }); jest.advanceTimersByTime(TIMEOUT); @@ -91,7 +83,7 @@ describe('IndexingStatusLogic', () => { it('handles indexing complete state', async () => { const promise = Promise.resolve({ ...mockStatusResponse, percentageComplete: 100 }); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); IndexingStatusLogic.actions.fetchIndexingStatus({ statusPath, onComplete }); jest.advanceTimersByTime(TIMEOUT); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts index 3115e233a6058b..0fed5820dbff91 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.test.ts @@ -6,10 +6,7 @@ import { resetContext } from 'kea'; -import { mockKibanaValues, mockHttpValues } from '../../__mocks__'; -jest.mock('../http', () => ({ - HttpLogic: { values: { http: mockHttpValues.http } }, -})); +import { mockKibanaValues } from '../../__mocks__'; import { KibanaLogic, mountKibanaLogic } from './kibana_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts index 420d3a5dd4dede..6d4e4f4fe649cc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/telemetry/telemetry_logic.test.ts @@ -7,14 +7,13 @@ import { resetContext } from 'kea'; import { JSON_HEADER as headers } from '../../../../common/constants'; -import { mockHttpValues } from '../../__mocks__'; -jest.mock('../http', () => ({ - HttpLogic: { values: { http: mockHttpValues.http } }, -})); +import { mockHttpValues } from '../../__mocks__/http_logic.mock'; import { TelemetryLogic } from './'; describe('Telemetry logic', () => { + const { http } = mockHttpValues; + beforeEach(() => { jest.clearAllMocks(); resetContext({}); @@ -29,14 +28,14 @@ describe('Telemetry logic', () => { product: 'enterprise_search', }); - expect(mockHttpValues.http.put).toHaveBeenCalledWith('/api/enterprise_search/stats', { + expect(http.put).toHaveBeenCalledWith('/api/enterprise_search/stats', { headers, body: '{"product":"enterprise_search","action":"viewed","metric":"setup_guide"}', }); }); it('throws an error if the telemetry endpoint fails', async () => { - mockHttpValues.http.put.mockImplementationOnce(() => Promise.reject()); + http.put.mockImplementationOnce(() => Promise.reject()); // To capture thrown errors, we have to call the listener fn directly // instead of using `TelemetryLogic.actions.sendTelemetry` - this is diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx index a45094ac55ba0a..9ab50000ba1a5c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx @@ -4,17 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; +import { mockKibanaValues, setMockActions, setMockValues } from '../../../../../__mocks__'; -import { setMockActions, setMockValues } from '../../../../../__mocks__'; import { sourceConfigData } from '../../../../__mocks__/content_sources.mock'; -jest.mock('../../../../../shared/kibana', () => ({ - KibanaLogic: { values: { navigateToUrl: jest.fn() } }, -})); -import { KibanaLogic } from '../../../../../shared/kibana'; - import React from 'react'; import { shallow } from 'enzyme'; @@ -32,6 +26,7 @@ import { SaveConfig } from './save_config'; import { SaveCustom } from './save_custom'; describe('AddSourceList', () => { + const { navigateToUrl } = mockKibanaValues; const initializeAddSource = jest.fn(); const setAddSourceStep = jest.fn(); const saveSourceConfig = jest.fn((_, setConfigCompletedStep) => { @@ -83,9 +78,7 @@ describe('AddSourceList', () => { const wrapper = shallow(); wrapper.find(ConfigCompleted).prop('advanceStep')(); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith( - '/sources/add/confluence_cloud/connect' - ); + expect(navigateToUrl).toHaveBeenCalledWith('/sources/add/confluence_cloud/connect'); expect(setAddSourceStep).toHaveBeenCalledWith(AddSourceSteps.ConnectInstanceStep); }); @@ -112,9 +105,7 @@ describe('AddSourceList', () => { const wrapper = shallow(); wrapper.find(ConnectInstance).prop('onFormCreated')('foo'); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith( - '/sources/add/confluence_cloud/connect' - ); + expect(navigateToUrl).toHaveBeenCalledWith('/sources/add/confluence_cloud/connect'); }); it('renders Configure Custom step', () => { @@ -137,9 +128,7 @@ describe('AddSourceList', () => { wrapper.find(ConfigureOauth).prop('onFormCreated')('foo'); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith( - '/sources/add/confluence_cloud/connect' - ); + expect(navigateToUrl).toHaveBeenCalledWith('/sources/add/confluence_cloud/connect'); }); it('renders Save Custom step', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts index 97f08e294be274..1cd7da56dbe73d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts @@ -6,22 +6,11 @@ import { resetContext } from 'kea'; -import { mockHttpValues, expectedAsyncError } from '../../../../../__mocks__'; - -jest.mock('../../../../../shared/http', () => ({ - HttpLogic: { - values: { http: mockHttpValues.http }, - }, -})); -import { HttpLogic } from '../../../../../shared/http'; - -jest.mock('../../../../../shared/flash_messages', () => ({ - FlashMessagesLogic: { actions: { clearFlashMessages: jest.fn(), setQueuedMessages: jest.fn() } }, - flashAPIErrors: jest.fn(), - setSuccessMessage: jest.fn(), - setQueuedSuccessMessage: jest.fn(), -})); -import { FlashMessagesLogic, flashAPIErrors } from '../../../../../shared/flash_messages'; +import { + mockFlashMessageHelpers, + mockHttpValues, + expectedAsyncError, +} from '../../../../../__mocks__'; import { AppLogic } from '../../../../app_logic'; jest.mock('../../../../app_logic', () => ({ @@ -41,6 +30,9 @@ import { } from './add_source_logic'; describe('AddSourceLogic', () => { + const { http } = mockHttpValues; + const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; + const defaultValues = { addSourceCurrentStep: AddSourceSteps.ConfigIntroStep, addSourceProps: {}, @@ -77,8 +69,6 @@ describe('AddSourceLogic', () => { const CUSTOM_SERVICE_TYPE_INDEX = 17; - const clearFlashMessagesSpy = jest.spyOn(FlashMessagesLogic.actions, 'clearFlashMessages'); - beforeEach(() => { jest.clearAllMocks(); resetContext({}); @@ -283,10 +273,10 @@ describe('AddSourceLogic', () => { it('calls API and sets values', async () => { const setSourceConfigDataSpy = jest.spyOn(AddSourceLogic.actions, 'setSourceConfigData'); const promise = Promise.resolve(sourceConfigData); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getSourceConfigData('github'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/workplace_search/org/settings/connectors/github' ); await promise; @@ -295,7 +285,7 @@ describe('AddSourceLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getSourceConfigData('github'); await expectedAsyncError(promise); @@ -314,15 +304,13 @@ describe('AddSourceLogic', () => { 'setSourceConnectData' ); const promise = Promise.resolve(sourceConnectData); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getSourceConnectData('github', successCallback); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); expect(AddSourceLogic.values.buttonLoading).toEqual(true); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( - '/api/workplace_search/org/sources/github/prepare' - ); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/sources/github/prepare'); await promise; expect(setSourceConnectDataSpy).toHaveBeenCalledWith(sourceConnectData); expect(successCallback).toHaveBeenCalledWith(sourceConnectData.oauthUrl); @@ -334,14 +322,14 @@ describe('AddSourceLogic', () => { AddSourceLogic.actions.setSourceIndexPermissionsValue(true); AddSourceLogic.actions.getSourceConnectData('github', successCallback); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/workplace_search/org/sources/github/prepare?subdomain=subdomain&index_permissions=true' ); }); it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getSourceConnectData('github', successCallback); await expectedAsyncError(promise); @@ -357,11 +345,11 @@ describe('AddSourceLogic', () => { 'setSourceConnectData' ); const promise = Promise.resolve(sourceConnectData); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getSourceReConnectData('github'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/workplace_search/org/sources/github/reauth_prepare' ); await promise; @@ -370,7 +358,7 @@ describe('AddSourceLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getSourceReConnectData('github'); await expectedAsyncError(promise); @@ -386,20 +374,18 @@ describe('AddSourceLogic', () => { 'setPreContentSourceConfigData' ); const promise = Promise.resolve(config); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getPreContentSourceConfigData('123'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( - '/api/workplace_search/org/pre_sources/123' - ); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/pre_sources/123'); await promise; expect(setPreContentSourceConfigDataSpy).toHaveBeenCalledWith(config); }); it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); AddSourceLogic.actions.getPreContentSourceConfigData('123'); await expectedAsyncError(promise); @@ -430,14 +416,14 @@ describe('AddSourceLogic', () => { const setButtonNotLoadingSpy = jest.spyOn(AddSourceLogic.actions, 'setButtonNotLoading'); const setSourceConfigDataSpy = jest.spyOn(AddSourceLogic.actions, 'setSourceConfigData'); const promise = Promise.resolve({ sourceConfigData }); - (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); + http.put.mockReturnValue(promise); AddSourceLogic.actions.saveSourceConfig(true, successCallback); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); expect(AddSourceLogic.values.buttonLoading).toEqual(true); expect( - HttpLogic.values.http.put + http.put ).toHaveBeenCalledWith( `/api/workplace_search/org/settings/connectors/${sourceConfigData.serviceType}`, { body: JSON.stringify({ params }) } @@ -462,17 +448,14 @@ describe('AddSourceLogic', () => { consumer_key: sourceConfigData.configuredFields?.consumerKey, }; - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/org/settings/connectors', - { - body: JSON.stringify({ params: createParams }), - } - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/org/settings/connectors', { + body: JSON.stringify({ params: createParams }), + }); }); it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); + http.put.mockReturnValue(promise); AddSourceLogic.actions.saveSourceConfig(true); await expectedAsyncError(promise); @@ -514,18 +497,15 @@ describe('AddSourceLogic', () => { const setButtonNotLoadingSpy = jest.spyOn(AddSourceLogic.actions, 'setButtonNotLoading'); const setCustomSourceDataSpy = jest.spyOn(AddSourceLogic.actions, 'setCustomSourceData'); const promise = Promise.resolve({ sourceConfigData }); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); AddSourceLogic.actions.createContentSource(serviceType, successCallback, errorCallback); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); expect(AddSourceLogic.values.buttonLoading).toEqual(true); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/org/create_source', - { - body: JSON.stringify({ ...params }), - } - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/org/create_source', { + body: JSON.stringify({ ...params }), + }); await promise; expect(setCustomSourceDataSpy).toHaveBeenCalledWith({ sourceConfigData }); expect(successCallback).toHaveBeenCalled(); @@ -534,7 +514,7 @@ describe('AddSourceLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); AddSourceLogic.actions.createContentSource(serviceType, successCallback, errorCallback); await expectedAsyncError(promise); @@ -553,7 +533,7 @@ describe('AddSourceLogic', () => { it('getSourceConnectData', () => { AddSourceLogic.actions.getSourceConnectData('github', jest.fn()); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/workplace_search/account/sources/github/prepare' ); }); @@ -561,7 +541,7 @@ describe('AddSourceLogic', () => { it('getSourceReConnectData', () => { AddSourceLogic.actions.getSourceReConnectData('123'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( + expect(http.get).toHaveBeenCalledWith( '/api/workplace_search/account/sources/123/reauth_prepare' ); }); @@ -569,20 +549,15 @@ describe('AddSourceLogic', () => { it('getPreContentSourceConfigData', () => { AddSourceLogic.actions.getPreContentSourceConfigData('123'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( - '/api/workplace_search/account/pre_sources/123' - ); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/account/pre_sources/123'); }); it('createContentSource', () => { AddSourceLogic.actions.createContentSource('github', jest.fn()); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/account/create_source', - { - body: JSON.stringify({ service_type: 'github' }), - } - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/account/create_source', { + body: JSON.stringify({ service_type: 'github' }), + }); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts index ec5cf541c2316e..a328cbe222afb8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.ts @@ -15,7 +15,7 @@ import { HttpLogic } from '../../../../../shared/http'; import { flashAPIErrors, setSuccessMessage, - FlashMessagesLogic, + clearFlashMessages, } from '../../../../../shared/flash_messages'; import { staticSourceData } from '../../source_data'; @@ -348,7 +348,7 @@ export const AddSourceLogic = kea { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); const { isOrganization } = AppLogic.values; const { subdomainValue: subdomain, indexPermissionsValue: indexPermissions } = values; @@ -399,7 +399,7 @@ export const AddSourceLogic = kea { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); const { sourceConfigData: { serviceType }, baseUrlValue, @@ -447,7 +447,7 @@ export const AddSourceLogic = kea { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); const { isOrganization } = AppLogic.values; const route = isOrganization ? '/api/workplace_search/org/create_source' diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts index 4de524fd9ac8ed..cfd4c279c6f8c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts @@ -6,32 +6,12 @@ import { resetContext } from 'kea'; -import { expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { - values: { http: { get: jest.fn(), post: jest.fn(), put: jest.fn(), delete: jest.fn() } }, - }, -})); -import { HttpLogic } from '../../../shared/http'; - -jest.mock('../../../shared/flash_messages', () => ({ - FlashMessagesLogic: { actions: { clearFlashMessages: jest.fn(), setQueuedMessages: jest.fn() } }, - flashAPIErrors: jest.fn(), - setSuccessMessage: jest.fn(), - setQueuedSuccessMessage: jest.fn(), -})); import { - FlashMessagesLogic, - flashAPIErrors, - setSuccessMessage, - setQueuedSuccessMessage, -} from '../../../shared/flash_messages'; - -jest.mock('../../../shared/kibana', () => ({ - KibanaLogic: { values: { navigateToUrl: jest.fn() } }, -})); -import { KibanaLogic } from '../../../shared/kibana'; + mockKibanaValues, + mockFlashMessageHelpers, + mockHttpValues, + expectedAsyncError, +} from '../../../__mocks__'; import { groups } from '../../__mocks__/groups.mock'; import { mockGroupValues } from './__mocks__/group_logic.mock'; @@ -40,11 +20,20 @@ import { GroupLogic } from './group_logic'; import { GROUPS_PATH } from '../../routes'; describe('GroupLogic', () => { + const { http } = mockHttpValues; + const { navigateToUrl } = mockKibanaValues; + const { + clearFlashMessages, + flashAPIErrors, + setSuccessMessage, + setQueuedSuccessMessage, + setQueuedErrorMessage, + } = mockFlashMessageHelpers; + const group = groups[0]; const sourceIds = ['123', '124']; const userIds = ['1z1z']; const sourcePriorities = { [sourceIds[0]]: 1, [sourceIds[1]]: 0.5 }; - const clearFlashMessagesSpy = jest.spyOn(FlashMessagesLogic.actions, 'clearFlashMessages'); beforeEach(() => { jest.clearAllMocks(); @@ -242,40 +231,34 @@ describe('GroupLogic', () => { it('calls API and sets values', async () => { const onInitializeGroupSpy = jest.spyOn(GroupLogic.actions, 'onInitializeGroup'); const promise = Promise.resolve(group); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupLogic.actions.initializeGroup(sourceIds[0]); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith('/api/workplace_search/groups/123'); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/groups/123'); await promise; expect(onInitializeGroupSpy).toHaveBeenCalledWith(group); }); it('handles 404 error', async () => { const promise = Promise.reject({ response: { status: 404 } }); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupLogic.actions.initializeGroup(sourceIds[0]); await expectedAsyncError(promise); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); - expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith({ - type: 'error', - message: 'Unable to find group with ID: "123".', - }); + expect(navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); + expect(setQueuedErrorMessage).toHaveBeenCalledWith('Unable to find group with ID: "123".'); }); it('handles non-404 error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupLogic.actions.initializeGroup(sourceIds[0]); await expectedAsyncError(promise); - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); - expect(FlashMessagesLogic.actions.setQueuedMessages).toHaveBeenCalledWith({ - type: 'error', - message: 'this is an error', - }); + expect(navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); + expect(setQueuedErrorMessage).toHaveBeenCalledWith('this is an error'); }); }); @@ -285,15 +268,13 @@ describe('GroupLogic', () => { }); it('deletes a group', async () => { const promise = Promise.resolve(true); - (HttpLogic.values.http.delete as jest.Mock).mockReturnValue(promise); + http.delete.mockReturnValue(promise); GroupLogic.actions.deleteGroup(); - expect(HttpLogic.values.http.delete).toHaveBeenCalledWith( - '/api/workplace_search/groups/123' - ); + expect(http.delete).toHaveBeenCalledWith('/api/workplace_search/groups/123'); await promise; - expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); + expect(navigateToUrl).toHaveBeenCalledWith(GROUPS_PATH); expect(setQueuedSuccessMessage).toHaveBeenCalledWith( 'Group "group" was successfully deleted.' ); @@ -301,7 +282,7 @@ describe('GroupLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.delete as jest.Mock).mockReturnValue(promise); + http.delete.mockReturnValue(promise); GroupLogic.actions.deleteGroup(); await expectedAsyncError(promise); @@ -318,10 +299,10 @@ describe('GroupLogic', () => { it('updates name', async () => { const onGroupNameChangedSpy = jest.spyOn(GroupLogic.actions, 'onGroupNameChanged'); const promise = Promise.resolve(group); - (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); + http.put.mockReturnValue(promise); GroupLogic.actions.updateGroupName(); - expect(HttpLogic.values.http.put).toHaveBeenCalledWith('/api/workplace_search/groups/123', { + expect(http.put).toHaveBeenCalledWith('/api/workplace_search/groups/123', { body: JSON.stringify({ group: { name: 'new name' } }), }); @@ -334,7 +315,7 @@ describe('GroupLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); + http.put.mockReturnValue(promise); GroupLogic.actions.updateGroupName(); await expectedAsyncError(promise); @@ -351,15 +332,12 @@ describe('GroupLogic', () => { it('updates name', async () => { const onGroupSourcesSavedSpy = jest.spyOn(GroupLogic.actions, 'onGroupSourcesSaved'); const promise = Promise.resolve(group); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupLogic.actions.saveGroupSources(); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/groups/123/share', - { - body: JSON.stringify({ content_source_ids: sourceIds }), - } - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/groups/123/share', { + body: JSON.stringify({ content_source_ids: sourceIds }), + }); await promise; expect(onGroupSourcesSavedSpy).toHaveBeenCalledWith(group); @@ -370,7 +348,7 @@ describe('GroupLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupLogic.actions.saveGroupSources(); await expectedAsyncError(promise); @@ -386,15 +364,12 @@ describe('GroupLogic', () => { it('updates name', async () => { const onGroupUsersSavedSpy = jest.spyOn(GroupLogic.actions, 'onGroupUsersSaved'); const promise = Promise.resolve(group); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupLogic.actions.saveGroupUsers(); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/groups/123/assign', - { - body: JSON.stringify({ user_ids: userIds }), - } - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/groups/123/assign', { + body: JSON.stringify({ user_ids: userIds }), + }); await promise; expect(onGroupUsersSavedSpy).toHaveBeenCalledWith(group); @@ -405,7 +380,7 @@ describe('GroupLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupLogic.actions.saveGroupUsers(); await expectedAsyncError(promise); @@ -424,20 +399,17 @@ describe('GroupLogic', () => { 'onGroupPrioritiesChanged' ); const promise = Promise.resolve(group); - (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); + http.put.mockReturnValue(promise); GroupLogic.actions.saveGroupSourcePrioritization(); - expect(HttpLogic.values.http.put).toHaveBeenCalledWith( - '/api/workplace_search/groups/123/boosts', - { - body: JSON.stringify({ - content_source_boosts: [ - [sourceIds[0], 1], - [sourceIds[1], 0.5], - ], - }), - } - ); + expect(http.put).toHaveBeenCalledWith('/api/workplace_search/groups/123/boosts', { + body: JSON.stringify({ + content_source_boosts: [ + [sourceIds[0], 1], + [sourceIds[1], 0.5], + ], + }), + }); await promise; expect(setSuccessMessage).toHaveBeenCalledWith( @@ -448,7 +420,7 @@ describe('GroupLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.put as jest.Mock).mockReturnValue(promise); + http.put.mockReturnValue(promise); GroupLogic.actions.saveGroupSourcePrioritization(); await expectedAsyncError(promise); @@ -462,7 +434,7 @@ describe('GroupLogic', () => { GroupLogic.actions.showConfirmDeleteModal(); expect(GroupLogic.values.confirmDeleteModalVisible).toEqual(true); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); @@ -471,7 +443,7 @@ describe('GroupLogic', () => { GroupLogic.actions.showSharedSourcesModal(); expect(GroupLogic.values.sharedSourcesModalVisible).toEqual(true); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); @@ -480,7 +452,7 @@ describe('GroupLogic', () => { GroupLogic.actions.showManageUsersModal(); expect(GroupLogic.values.manageUsersModalVisible).toEqual(true); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); @@ -488,7 +460,7 @@ describe('GroupLogic', () => { it('clears flash messages', () => { GroupLogic.actions.resetFlashMessages(); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts index 357f0553c69e15..6d9c2d5d8233f2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.ts @@ -10,13 +10,14 @@ import { i18n } from '@kbn/i18n'; import { HttpLogic } from '../../../shared/http'; import { KibanaLogic } from '../../../shared/kibana'; - import { - FlashMessagesLogic, + clearFlashMessages, flashAPIErrors, setSuccessMessage, setQueuedSuccessMessage, + setQueuedErrorMessage, } from '../../../shared/flash_messages'; + import { GROUPS_PATH } from '../../routes'; import { ContentSourceDetails, GroupDetails, User, SourcePriority } from '../../types'; @@ -223,10 +224,7 @@ export const GroupLogic = kea>({ ); const error = e.response?.status === 404 ? NOT_FOUND_MESSAGE : e; - FlashMessagesLogic.actions.setQueuedMessages({ - type: 'error', - message: error, - }); + setQueuedErrorMessage(error); KibanaLogic.values.navigateToUrl(GROUPS_PATH); } @@ -360,16 +358,16 @@ export const GroupLogic = kea>({ } }, showConfirmDeleteModal: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, showManageUsersModal: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, showSharedSourcesModal: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, resetFlashMessages: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts index d046863fd388ca..bbeded9207d019 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts @@ -6,23 +6,7 @@ import { resetContext } from 'kea'; -import { expectedAsyncError } from '../../../__mocks__'; - -jest.mock('../../../shared/http', () => ({ - HttpLogic: { - values: { http: { get: jest.fn(), post: jest.fn() } }, - }, -})); -import { HttpLogic } from '../../../shared/http'; - -jest.mock('../../../shared/flash_messages', () => ({ - FlashMessagesLogic: { actions: { clearFlashMessages: jest.fn(), setQueuedMessages: jest.fn() } }, - flashAPIErrors: jest.fn(), - setSuccessMessage: jest.fn(), - setQueuedSuccessMessage: jest.fn(), -})); -import { FlashMessagesLogic, flashAPIErrors } from '../../../shared/flash_messages'; - +import { mockFlashMessageHelpers, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; import { DEFAULT_META } from '../../../shared/constants'; import { JSON_HEADER as headers } from '../../../../../common/constants'; @@ -37,7 +21,9 @@ const TIMEOUT = 400; const delay = () => new Promise((resolve) => setTimeout(resolve, TIMEOUT)); describe('GroupsLogic', () => { - const clearFlashMessagesSpy = jest.spyOn(FlashMessagesLogic.actions, 'clearFlashMessages'); + const { http } = mockHttpValues; + const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; + const groupsResponse = { results: groups, meta: DEFAULT_META, @@ -229,17 +215,17 @@ describe('GroupsLogic', () => { it('calls API and sets values', async () => { const onInitializeGroupsSpy = jest.spyOn(GroupsLogic.actions, 'onInitializeGroups'); const promise = Promise.resolve(groupsResponse); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupsLogic.actions.initializeGroups(); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith('/api/workplace_search/groups'); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/groups'); await promise; expect(onInitializeGroupsSpy).toHaveBeenCalledWith(groupsResponse); }); it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupsLogic.actions.initializeGroups(); await expectedAsyncError(promise); @@ -269,14 +255,11 @@ describe('GroupsLogic', () => { it('calls API and sets values', async () => { const setSearchResultsSpy = jest.spyOn(GroupsLogic.actions, 'setSearchResults'); const promise = Promise.resolve(groups); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupsLogic.actions.getSearchResults(); await delay(); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/groups/search', - payload - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/groups/search', payload); await promise; expect(setSearchResultsSpy).toHaveBeenCalledWith(groups); }); @@ -286,22 +269,19 @@ describe('GroupsLogic', () => { GroupsLogic.actions.setActivePage(2); const setSearchResultsSpy = jest.spyOn(GroupsLogic.actions, 'setSearchResults'); const promise = Promise.resolve(groups); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupsLogic.actions.getSearchResults(true); // Account for `breakpoint` that debounces filter value. await delay(); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith( - '/api/workplace_search/groups/search', - payload - ); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/groups/search', payload); await promise; expect(setSearchResultsSpy).toHaveBeenCalledWith(groups); }); it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupsLogic.actions.getSearchResults(); await expectedAsyncError(promise); @@ -315,19 +295,17 @@ describe('GroupsLogic', () => { it('calls API and sets values', async () => { const setGroupUsersSpy = jest.spyOn(GroupsLogic.actions, 'setGroupUsers'); const promise = Promise.resolve(users); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupsLogic.actions.fetchGroupUsers('123'); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith( - '/api/workplace_search/groups/123/group_users' - ); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/groups/123/group_users'); await promise; expect(setGroupUsersSpy).toHaveBeenCalledWith(users); }); it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.get as jest.Mock).mockReturnValue(promise); + http.get.mockReturnValue(promise); GroupsLogic.actions.fetchGroupUsers('123'); await expectedAsyncError(promise); @@ -342,10 +320,10 @@ describe('GroupsLogic', () => { GroupsLogic.actions.setNewGroupName(GROUP_NAME); const setNewGroupSpy = jest.spyOn(GroupsLogic.actions, 'setNewGroup'); const promise = Promise.resolve(groups[0]); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupsLogic.actions.saveNewGroup(); - expect(HttpLogic.values.http.post).toHaveBeenCalledWith('/api/workplace_search/groups', { + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/groups', { body: JSON.stringify({ group_name: GROUP_NAME }), headers, }); @@ -355,7 +333,7 @@ describe('GroupsLogic', () => { it('handles error', async () => { const promise = Promise.reject('this is an error'); - (HttpLogic.values.http.post as jest.Mock).mockReturnValue(promise); + http.post.mockReturnValue(promise); GroupsLogic.actions.saveNewGroup(); await expectedAsyncError(promise); @@ -388,7 +366,7 @@ describe('GroupsLogic', () => { expect(GroupsLogic.values.newGroupModalOpen).toEqual(true); expect(GroupsLogic.values.newGroup).toEqual(null); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); @@ -400,7 +378,7 @@ describe('GroupsLogic', () => { expect(GroupsLogic.values.filteredUsers).toEqual([]); expect(GroupsLogic.values.filterValue).toEqual(''); expect(GroupsLogic.values.groupsMeta).toEqual(DEFAULT_META); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); @@ -409,7 +387,7 @@ describe('GroupsLogic', () => { GroupsLogic.actions.toggleFilterSourcesDropdown(); expect(GroupsLogic.values.filterSourcesDropdownOpen).toEqual(true); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); @@ -418,7 +396,7 @@ describe('GroupsLogic', () => { GroupsLogic.actions.toggleFilterUsersDropdown(); expect(GroupsLogic.values.filterUsersDropdownOpen).toEqual(true); - expect(clearFlashMessagesSpy).toHaveBeenCalled(); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts index 618ca84f825c9b..3957f2ea7a124d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { HttpLogic } from '../../../shared/http'; import { - FlashMessagesLogic, + clearFlashMessages, flashAPIErrors, setSuccessMessage, } from '../../../shared/flash_messages'; @@ -339,16 +339,16 @@ export const GroupsLogic = kea>({ actions.getSearchResults(); }, openNewGroupModal: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, resetGroupsFilters: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, toggleFilterSourcesDropdown: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, toggleFilterUsersDropdown: () => { - FlashMessagesLogic.actions.clearFlashMessages(); + clearFlashMessages(); }, }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts index 1ec770e9defcee..fb55d11be1f0fc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts @@ -6,13 +6,14 @@ import { resetContext } from 'kea'; -jest.mock('../../../shared/http', () => ({ HttpLogic: { values: { http: { get: jest.fn() } } } })); -import { HttpLogic } from '../../../shared/http'; +import { mockHttpValues } from '../../../__mocks__'; import { mockOverviewValues } from './__mocks__'; import { OverviewLogic } from './overview_logic'; describe('OverviewLogic', () => { + const { http } = mockHttpValues; + beforeEach(() => { jest.clearAllMocks(); resetContext({}); @@ -65,7 +66,7 @@ describe('OverviewLogic', () => { await OverviewLogic.actions.initializeOverview(); - expect(HttpLogic.values.http.get).toHaveBeenCalledWith('/api/workplace_search/overview'); + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/overview'); expect(setServerDataSpy).toHaveBeenCalled(); }); }); From bb70c6a82abbd1769af498de12142f685fb25f21 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Fri, 15 Jan 2021 12:41:16 -0800 Subject: [PATCH 23/33] [APM] Only display relevant sections for rum agent in service overview (#88410) * [APM] Only display relevent sections for rum agent in service overview (#85546) * call `isRumAgentName` once * User experience callout links to the selected service --- .../components/app/service_overview/index.tsx | 37 ++++++++++++------- .../app/transaction_overview/index.tsx | 2 +- .../user_experience_callout.tsx | 9 ++++- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx index 2e04cce5ff6704..f7720589359c84 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx @@ -16,6 +16,7 @@ import { LatencyChart } from '../../shared/charts/latency_chart'; import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart'; import { TransactionErrorRateChart } from '../../shared/charts/transaction_error_rate_chart'; import { SearchBar } from '../../shared/search_bar'; +import { UserExperienceCallout } from '../transaction_overview/user_experience_callout'; import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table'; import { ServiceOverviewErrorsTable } from './service_overview_errors_table'; import { ServiceOverviewInstancesTable } from './service_overview_instances_table'; @@ -51,6 +52,7 @@ export function ServiceOverview({ 'xpack.apm.serviceOverview.searchBar.transactionTypeLabel', { defaultMessage: 'Type: {transactionType}', values: { transactionType } } ); + const isRumAgent = isRumAgentName(agentName); return ( @@ -58,6 +60,11 @@ export function ServiceOverview({ + {isRumAgent && ( + + + + )} @@ -87,7 +94,7 @@ export function ServiceOverview({ gutterSize="s" responsive={false} > - {!isRumAgentName(agentName) && ( + {!isRumAgent && ( - - - - - + {!isRumAgent && ( + + + + + + )} - - - - - + {!isRumAgent && ( + + + + + + )} diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx index 948facae222e7b..30fbfe9cc87082 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx @@ -123,7 +123,7 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) { {transactionType === TRANSACTION_PAGE_LOAD && ( <> - + )} diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/user_experience_callout.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/user_experience_callout.tsx index 6e1154a458d6e9..95f4fcaab63eb9 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/user_experience_callout.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/user_experience_callout.tsx @@ -9,9 +9,14 @@ import { EuiButton, EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; -export function UserExperienceCallout() { +interface Props { + serviceName: string; +} +export function UserExperienceCallout({ serviceName }: Props) { const { core } = useApmPluginContext(); - const userExperienceHref = core.http.basePath.prepend(`/app/ux`); + const userExperienceHref = core.http.basePath.prepend( + `/app/ux?serviceName=${serviceName}` + ); return ( Date: Fri, 15 Jan 2021 21:17:25 +0000 Subject: [PATCH 24/33] chore(NA): remove mocha junit ci integrations (#88129) * chore(NA): remove mocha junit ci integrations * chore(NA): remove mocha script from xpack * chore(NA): single rule exclusion on eslint config for mocha * chore(NA): remove unused custom mocha integration code from kbn/test * chore(NA): rewording packages readme * docs(NA): remoe mocha mention from development-unit-tests --- .ci/Jenkinsfile_flaky | 29 ++---- .ci/teamcity/tests/mocha.sh | 8 -- .eslintrc.js | 12 +-- .teamcity/src/builds/test/QuickTests.kt | 1 - .../contributing/development-tests.asciidoc | 6 -- .../development-unit-tests.asciidoc | 34 +------ .../interpreting-ci-failures.asciidoc | 2 +- package.json | 1 - packages/README.md | 16 +-- packages/kbn-plugin-generator/README.md | 4 - packages/kbn-test/src/index.ts | 7 +- .../kbn-test/src/mocha/auto_junit_reporter.js | 37 ------- packages/kbn-test/src/mocha/index.ts | 4 - packages/kbn-test/src/mocha/run_mocha_cli.js | 99 ------------------- .../src/mocha/server_junit_reporter.js | 25 ----- scripts/mocha.js | 21 ---- src/dev/index.js | 2 +- test/scripts/jenkins_unit.sh | 1 - test/scripts/test/mocha.sh | 7 -- test/tsconfig.json | 2 +- vars/tasks.groovy | 1 - x-pack/package.json | 3 +- .../canvas/storybook/webpack.dll.config.js | 1 - x-pack/scripts/mocha.js | 7 -- x-pack/test/tsconfig.json | 2 +- 25 files changed, 26 insertions(+), 306 deletions(-) delete mode 100755 .ci/teamcity/tests/mocha.sh delete mode 100644 packages/kbn-test/src/mocha/auto_junit_reporter.js delete mode 100644 packages/kbn-test/src/mocha/run_mocha_cli.js delete mode 100644 packages/kbn-test/src/mocha/server_junit_reporter.js delete mode 100644 scripts/mocha.js delete mode 100755 test/scripts/test/mocha.sh delete mode 100644 x-pack/scripts/mocha.js diff --git a/.ci/Jenkinsfile_flaky b/.ci/Jenkinsfile_flaky index 2f496329dfd8ec..33204d73964616 100644 --- a/.ci/Jenkinsfile_flaky +++ b/.ci/Jenkinsfile_flaky @@ -5,11 +5,10 @@ kibanaLibrary.load() def CI_GROUP_PARAM = params.CI_GROUP -// Looks like 'oss:ciGroup:1', 'oss:firefoxSmoke', or 'all:serverMocha' +// Looks like 'oss:ciGroup:1', 'oss:firefoxSmoke' def JOB_PARTS = CI_GROUP_PARAM.split(':') def IS_XPACK = JOB_PARTS[0] == 'xpack' def JOB = JOB_PARTS[1] -def NEED_BUILD = JOB != 'serverMocha' def CI_GROUP = JOB_PARTS.size() > 2 ? JOB_PARTS[2] : '' def EXECUTIONS = params.NUMBER_EXECUTIONS.toInteger() def AGENT_COUNT = getAgentCount(EXECUTIONS) @@ -31,15 +30,13 @@ kibanaPipeline(timeoutMinutes: 180) { print "Agent ${agentNumberInside} - ${agentExecutions} executions" workers.functional('flaky-test-runner', { - if (NEED_BUILD) { - if (!IS_XPACK) { - kibanaPipeline.buildOss() - if (CI_GROUP == '1') { - runbld("./test/scripts/jenkins_build_kbn_sample_panel_action.sh", "Build kbn tp sample panel action for ciGroup1") - } - } else { - kibanaPipeline.buildXpack() + if (!IS_XPACK) { + kibanaPipeline.buildOss() + if (CI_GROUP == '1') { + runbld("./test/scripts/jenkins_build_kbn_sample_panel_action.sh", "Build kbn tp sample panel action for ciGroup1") } + } else { + kibanaPipeline.buildXpack() } }, getWorkerMap(agentNumberInside, agentExecutions, worker, workerFailures))() } @@ -60,17 +57,7 @@ kibanaPipeline(timeoutMinutes: 180) { def getWorkerFromParams(isXpack, job, ciGroup) { if (!isXpack) { - if (job == 'serverMocha') { - return kibanaPipeline.functionalTestProcess('serverMocha', { - kibanaPipeline.bash( - """ - source src/dev/ci_setup/setup_env.sh - node scripts/mocha - """, - "run `node scripts/mocha`" - ) - }) - } else if (job == 'accessibility') { + if (job == 'accessibility') { return kibanaPipeline.functionalTestProcess('kibana-accessibility', './test/scripts/jenkins_accessibility.sh') } else if (job == 'firefoxSmoke') { return kibanaPipeline.functionalTestProcess('firefoxSmoke', './test/scripts/jenkins_firefox_smoke.sh') diff --git a/.ci/teamcity/tests/mocha.sh b/.ci/teamcity/tests/mocha.sh deleted file mode 100755 index acb088220fa786..00000000000000 --- a/.ci/teamcity/tests/mocha.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source "$(dirname "${0}")/../util.sh" - -checks-reporter-with-killswitch "Mocha Tests" \ - node scripts/mocha diff --git a/.eslintrc.js b/.eslintrc.js index 82275d9441cc24..db5d36d1168dfd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -71,11 +71,6 @@ const SAFER_LODASH_SET_DEFINITELYTYPED_HEADER = ` */ `; -const allMochaRulesOff = {}; -Object.keys(require('eslint-plugin-mocha').rules).forEach((k) => { - allMochaRulesOff['mocha/' + k] = 'off'; -}); - module.exports = { root: true, @@ -542,7 +537,6 @@ module.exports = { 'packages/kbn-eslint-import-resolver-kibana/**/*.js', 'packages/kbn-eslint-plugin-eslint/**/*', 'x-pack/gulpfile.js', - 'x-pack/dev-tools/mocha/setup_mocha.js', 'x-pack/scripts/*.js', ], excludedFiles: ['**/integration_tests/**/*'], @@ -574,7 +568,9 @@ module.exports = { */ { files: ['test/harden/*.js', 'packages/elastic-safer-lodash-set/test/*.js'], - rules: allMochaRulesOff, + rules: { + 'mocha/handle-done-callback': 'off', + }, }, { files: ['**/*.{js,mjs,ts,tsx}'], @@ -794,7 +790,6 @@ module.exports = { files: ['x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}'], plugins: ['eslint-plugin-node', 'react'], env: { - mocha: true, jest: true, }, rules: { @@ -930,7 +925,6 @@ module.exports = { files: ['x-pack/plugins/lists/**/*.{js,mjs,ts,tsx}'], plugins: ['eslint-plugin-node'], env: { - mocha: true, jest: true, }, rules: { diff --git a/.teamcity/src/builds/test/QuickTests.kt b/.teamcity/src/builds/test/QuickTests.kt index a294fce9599c36..086f65e4ee26b8 100644 --- a/.teamcity/src/builds/test/QuickTests.kt +++ b/.teamcity/src/builds/test/QuickTests.kt @@ -14,7 +14,6 @@ object QuickTests : BuildType({ val testScripts = mapOf( "Test Hardening" to ".ci/teamcity/checks/test_hardening.sh", "Test Projects" to ".ci/teamcity/tests/test_projects.sh", - "Mocha Tests" to ".ci/teamcity/tests/mocha.sh" ) steps { diff --git a/docs/developer/contributing/development-tests.asciidoc b/docs/developer/contributing/development-tests.asciidoc index 647dc8b3f3b263..7aabc480cdaa29 100644 --- a/docs/developer/contributing/development-tests.asciidoc +++ b/docs/developer/contributing/development-tests.asciidoc @@ -17,10 +17,6 @@ root) |Jest (integration) |`**/integration_tests/**/*.test.{js,mjs,ts,tsx}` |`yarn test:jest_integration [test path]` -|Mocha -|`**/__tests__/**/*.js` -|`node scripts/mocha --grep=regexp [test path]` - |Functional |`test/**/config.js` `x-pack/test/**/config.js` |`node scripts/functional_tests_server --config [directory]/config.js``node scripts/functional_test_runner_ --config [directory]/config.js --grep=regexp` @@ -60,8 +56,6 @@ kibana/src/plugins/dashboard/server$ yarn test:jest --coverage yarn jest --coverage --verbose --config /home/tyler/elastic/kibana/src/plugins/dashboard/jest.config.js server ---- -NOTE: There are still a handful of legacy tests that use the Mocha test runner. For those tests, use `node scripts/mocha --grep=regexp [test path]`. Tests using Mocha are located within `__tests__` directories. - [discrete] === Running browser automation tests diff --git a/docs/developer/contributing/development-unit-tests.asciidoc b/docs/developer/contributing/development-unit-tests.asciidoc index d5f5bc76b3302f..72edaf1241bc67 100644 --- a/docs/developer/contributing/development-unit-tests.asciidoc +++ b/docs/developer/contributing/development-unit-tests.asciidoc @@ -1,20 +1,7 @@ [[development-unit-tests]] == Unit testing frameworks -{kib} is migrating unit testing from `Mocha` to `Jest`. Legacy unit tests -still exist in Mocha but all new unit tests should be written in Jest. - -[discrete] -=== Mocha (legacy) - -Mocha tests are contained in `__tests__` directories. - -*Running Mocha Unit Tests* - -["source","shell"] ------------ -yarn test:mocha ------------ +{kib} is doing unit testing doing `Jest`. [discrete] == Jest @@ -92,23 +79,10 @@ the `--debug-brk` flag. You’ll need to connect a remote debugger such as https://github.com/node-inspector/node-inspector[`node-inspector`] to proceed in this mode. -[source,bash] ----- -node scripts/mocha --debug ----- - [discrete] === Unit Testing Plugins -This should work super if you’re using the +Even when using https://github.com/elastic/kibana/tree/master/packages/kbn-plugin-generator[Kibana -plugin generator]. If you’re not using the generator, well, you’re on -your own. We suggest you look at how the generator works. - -To run the tests for just your particular plugin run the following -command from your plugin: - -[source,bash] ----- -yarn test:mocha ----- \ No newline at end of file +plugin generator] we do not enforce a way for unit testing your plugin. Please setup and you use +the tools of your choice. If the plugin will live inside the Kibana repo `Jest` must be used. \ No newline at end of file diff --git a/docs/developer/contributing/interpreting-ci-failures.asciidoc b/docs/developer/contributing/interpreting-ci-failures.asciidoc index bb623bc7a541ca..38609b2be5c8cd 100644 --- a/docs/developer/contributing/interpreting-ci-failures.asciidoc +++ b/docs/developer/contributing/interpreting-ci-failures.asciidoc @@ -27,7 +27,7 @@ image::images/job_view.png[] [discrete] === Viewing ciGroup/test Logs -To view the logs for a failed specific ciGroup, jest, mocha, type checkers, linters, etc., click on the *Pipeline Steps* link in from the Job page. +To view the logs for a failed specific ciGroup, jest, type checkers, linters, etc., click on the *Pipeline Steps* link in from the Job page. image::images/pipeline_steps_view.png[] diff --git a/package.json b/package.json index 7effbd0a5550a3..053b2060dc4d3d 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "es": "node scripts/es", "test:jest": "node scripts/jest", "test:jest_integration": "node scripts/jest_integration", - "test:mocha": "node scripts/mocha", "test:ftr": "node scripts/functional_tests", "test:ftr:server": "node scripts/functional_tests_server", "test:ftr:runner": "node scripts/functional_test_runner", diff --git a/packages/README.md b/packages/README.md index 9d9cd4ed7b6e55..a328fe70e201fb 100644 --- a/packages/README.md +++ b/packages/README.md @@ -44,23 +44,17 @@ All new packages should use the `@kbn` namespace, and should be marked with ## Unit tests for a package -Currently there are two patterns used to test packages, one using Mocha and one using Jest. These patterns emerged out of convention and we'd like to make them more similar to each other in the near future. +Currently there is only one tool being used in order to test packages which is Jest. Below we will explain how it should be done. -### 1. Mocha -Today a package can follow the pattern of having a `__tests__` directory in each source code directory of a package which contains the tests for that module. These are usually run by Mocha. - -If a package's tests should be run with Mocha, you'll have to opt-in to run them by appending the package's test file pattern(s) to Kibana's `src/dev/mocha/run_mocha_cli.js` file. These will then be run by the unit test runner. - -* `yarn test` or `yarn grunt test` runs all unit tests. -* `node scripts/mocha` runs all Mocha tests. - -### 2. Jest -A package can also follow the pattern of having `.test.js` files as siblings of the source code files, and these run by Jest. +### Jest +A package should follow the pattern of having `.test.js` files as siblings of the source code files, and these run by Jest. A package using the `.test.js` naming convention will have those tests automatically picked up by Jest and run by the unit test runner, currently mapped to the Kibana `test` script in the root `package.json`. * `yarn test` or `yarn grunt test` runs all unit tests. * `yarn jest` runs all Jest tests in Kibana. +In order for the plugin or package to use Jest, a jest.config.js file must be present in it's root. However, there are safeguards for this in CI should a test file be added without a corresponding config file. + ---- Each package can also specify its own `test` script in the package's `package.json`, for cases where you'd prefer to run the tests from the local package directory. diff --git a/packages/kbn-plugin-generator/README.md b/packages/kbn-plugin-generator/README.md index bee8e6c2ca783b..4603c9ed7b1ba6 100644 --- a/packages/kbn-plugin-generator/README.md +++ b/packages/kbn-plugin-generator/README.md @@ -63,10 +63,6 @@ Generated plugins receive a handful of scripts that can be used during developme Build a distributable archive of your plugin. - - `yarn test:mocha` - - Run the server tests using mocha. - To start kibana run the following command from Kibana root. diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index a88820eb281ccf..fa7124a5b042d1 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -46,12 +46,7 @@ export { readConfigFile } from './functional_test_runner/lib/config/read_config_ export { runFtrCli } from './functional_test_runner/cli'; -export { - createAutoJUnitReporter, - runMochaCli, - setupJUnitReportGeneration, - escapeCdata, -} from './mocha'; +export { setupJUnitReportGeneration, escapeCdata } from './mocha'; export { runFailedTestsReporterCli } from './failed_tests_reporter'; diff --git a/packages/kbn-test/src/mocha/auto_junit_reporter.js b/packages/kbn-test/src/mocha/auto_junit_reporter.js deleted file mode 100644 index b6e79616e1cde0..00000000000000 --- a/packages/kbn-test/src/mocha/auto_junit_reporter.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 mocha from 'mocha'; -import { setupJUnitReportGeneration } from './junit_report_generation'; - -const MochaSpecReporter = mocha.reporters.spec; - -export function createAutoJUnitReporter(junitReportOptions) { - return class AutoJUnitReporter { - constructor(runner, options) { - // setup a spec reporter for console output - new MochaSpecReporter(runner, options); - - // in CI we also setup the JUnit reporter - if (process.env.CI && !process.env.DISABLE_JUNIT_REPORTER) { - setupJUnitReportGeneration(runner, junitReportOptions); - } - } - }; -} diff --git a/packages/kbn-test/src/mocha/index.ts b/packages/kbn-test/src/mocha/index.ts index 99c0f6f4230b7a..aadf1b7f16a19d 100644 --- a/packages/kbn-test/src/mocha/index.ts +++ b/packages/kbn-test/src/mocha/index.ts @@ -17,13 +17,9 @@ * under the License. */ -// @ts-ignore not typed yet -export { createAutoJUnitReporter } from './auto_junit_reporter'; // @ts-ignore not typed yet export { setupJUnitReportGeneration } from './junit_report_generation'; // @ts-ignore not typed yet -export { runMochaCli } from './run_mocha_cli'; -// @ts-ignore not typed yet export { recordLog, snapshotLogsForRunnable } from './log_cache'; // @ts-ignore not typed yet export { escapeCdata } from './xml'; diff --git a/packages/kbn-test/src/mocha/run_mocha_cli.js b/packages/kbn-test/src/mocha/run_mocha_cli.js deleted file mode 100644 index f61b3096103416..00000000000000 --- a/packages/kbn-test/src/mocha/run_mocha_cli.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 { REPO_ROOT } from '@kbn/utils'; -import getopts from 'getopts'; -import globby from 'globby'; - -export function runMochaCli() { - const opts = getopts(process.argv.slice(2), { - alias: { - t: 'timeout', - }, - boolean: ['no-timeouts'], - }); - - const runInBand = - process.execArgv.includes('--inspect') || process.execArgv.includes('--inspect-brk'); - - // ensure that mocha exits when test have completed - process.argv.push('--exit'); - - // check that we aren't leaking any globals - process.argv.push('--check-leaks'); - // prevent globals injected from canvas plugins from triggering leak check - process.argv.push('--globals', '__core-js_shared__,core,_, '); - - // set default test timeout - if (opts.timeout == null && !opts['no-timeouts']) { - if (runInBand) { - process.argv.push('--no-timeouts'); - } else { - process.argv.push('--timeout', '10000'); - } - } - - // set default slow timeout - if (opts.slow == null) { - process.argv.push('--slow', '5000'); - } - - // set default reporter - if (opts.reporter == null) { - process.argv.push('--reporter', require.resolve('./server_junit_reporter')); - } - - // set default test files - if (!opts._.length) { - globby - .sync( - [ - 'src/**/__tests__/**/*.{js,ts,tsx}', - 'packages/**/__tests__/**/*.{js,ts,tsx}', - 'tasks/**/__tests__/**/*.{js,ts,tsx}', - 'x-pack/common/**/__tests__/**/*.{js,ts,tsx}', - 'x-pack/server/**/__tests__/**/*.{js,ts,tsx}', - `x-pack/legacy/plugins/*/__tests__/**/*.{js,ts,tsx}`, - `x-pack/legacy/plugins/*/common/**/__tests__/**/*.{js,ts,tsx}`, - `x-pack/legacy/plugins/*/**/server/**/__tests__/**/*.{js,ts,tsx}`, - ], - { - cwd: REPO_ROOT, - onlyFiles: true, - absolute: true, - ignore: [ - '**/__tests__/fixtures/**', - 'src/**/public/**', - '**/_*.{js,ts,tsx}', - '**/*.test.*', - 'packages/**/target/**', - ], - } - ) - .forEach((file) => { - process.argv.push(file); - }); - } - - if (runInBand) { - require('mocha/bin/_mocha'); - } else { - require('mocha/bin/mocha'); - } -} diff --git a/packages/kbn-test/src/mocha/server_junit_reporter.js b/packages/kbn-test/src/mocha/server_junit_reporter.js deleted file mode 100644 index c629f401d05809..00000000000000 --- a/packages/kbn-test/src/mocha/server_junit_reporter.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -// when the reporter is loaded by mocha in child process it might be before setup_node_env -require('../../../../src/setup_node_env'); - -module.exports = require('./auto_junit_reporter').createAutoJUnitReporter({ - reportName: 'Server Mocha Tests', -}); diff --git a/scripts/mocha.js b/scripts/mocha.js deleted file mode 100644 index 8d25d18a594ccf..00000000000000 --- a/scripts/mocha.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ - -require('../src/setup_node_env'); -require('@kbn/test').runMochaCli(); diff --git a/src/dev/index.js b/src/dev/index.js index f24eee040c8671..d9d0cec0f15737 100644 --- a/src/dev/index.js +++ b/src/dev/index.js @@ -17,6 +17,6 @@ * under the License. */ -export { createAutoJUnitReporter, setupJUnitReportGeneration } from '@kbn/test'; +export { setupJUnitReportGeneration } from '@kbn/test'; export { generateNoticeFromSource } from './notice'; diff --git a/test/scripts/jenkins_unit.sh b/test/scripts/jenkins_unit.sh index 00fd378b348a08..6e28f9c3ef56ab 100755 --- a/test/scripts/jenkins_unit.sh +++ b/test/scripts/jenkins_unit.sh @@ -15,7 +15,6 @@ if [[ -z "$CODE_COVERAGE" ]] ; then # Test ./test/scripts/test/jest_integration.sh - ./test/scripts/test/mocha.sh ./test/scripts/test/jest_unit.sh ./test/scripts/test/api_integration.sh diff --git a/test/scripts/test/mocha.sh b/test/scripts/test/mocha.sh deleted file mode 100755 index 5e005c89330ca7..00000000000000 --- a/test/scripts/test/mocha.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -source src/dev/ci_setup/setup_env.sh - -# TODO: will remove mocha in another PR -# checks-reporter-with-killswitch "Mocha Tests" \ -# node scripts/mocha diff --git a/test/tsconfig.json b/test/tsconfig.json index 684efc145e4d07..c8e6e69586ca0e 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../tsconfig.base.json", "compilerOptions": { "incremental": false, - "types": ["node", "mocha", "flot"] + "types": ["node", "flot"] }, "include": ["**/*", "../typings/elastic__node_crypto.d.ts", "typings/**/*", "../packages/kbn-test/types/ftr_globals/**/*"], "exclude": ["plugin_functional/plugins/**/*", "interpreter_functional/plugins/**/*"], diff --git a/vars/tasks.groovy b/vars/tasks.groovy index ec2af87caba567..68a6d4b32618c7 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -32,7 +32,6 @@ def test() { tasks([ // These 2 tasks require isolation because of hard-coded, conflicting ports and such, so let's use Docker here kibanaPipeline.scriptTaskDocker('Jest Integration Tests', 'test/scripts/test/jest_integration.sh'), - kibanaPipeline.scriptTaskDocker('Mocha Tests', 'test/scripts/test/mocha.sh'), kibanaPipeline.scriptTask('Jest Unit Tests', 'test/scripts/test/jest_unit.sh'), kibanaPipeline.scriptTask('API Integration Tests', 'test/scripts/test/api_integration.sh'), diff --git a/x-pack/package.json b/x-pack/package.json index 34ef8bb589b44c..97fe5144f135a4 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -12,8 +12,7 @@ "build": "../node_modules/.bin/gulp build", "testonly": "echo 'Deprecated, use `yarn test`'", "test": "../node_modules/.bin/gulp test", - "test:jest": "node ../scripts/jest", - "test:mocha": "node scripts/mocha" + "test:jest": "node ../scripts/jest" }, "kibana": { "build": { diff --git a/x-pack/plugins/canvas/storybook/webpack.dll.config.js b/x-pack/plugins/canvas/storybook/webpack.dll.config.js index b830f72692eded..2fa31235ac0bb1 100644 --- a/x-pack/plugins/canvas/storybook/webpack.dll.config.js +++ b/x-pack/plugins/canvas/storybook/webpack.dll.config.js @@ -39,7 +39,6 @@ module.exports = { 'jquery', 'lodash', 'markdown-it', - 'mocha', 'monaco-editor', 'prop-types', 'react-ace', diff --git a/x-pack/scripts/mocha.js b/x-pack/scripts/mocha.js deleted file mode 100644 index cc0f94a2a760e0..00000000000000 --- a/x-pack/scripts/mocha.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -require('../../scripts/mocha'); diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 0fbb16c0e8c872..eac9d928840281 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { // overhead is too significant "incremental": false, - "types": ["mocha", "node", "flot"] + "types": ["node", "flot"] }, "include": ["**/*", "../typings/**/*", "../../packages/kbn-test/types/ftr_globals/**/*"], "exclude": ["../typings/jest.d.ts"], From f5ec1dc3525a2234d6e6fa34e0dd98647a45c51d Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Fri, 15 Jan 2021 22:34:54 +0100 Subject: [PATCH 25/33] [APM] Explicitly set environment for cross-service links (#87481) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apm/common/environment_filter_values.ts | 24 +++++++++++++++++++ .../MaybeViewTraceLink.tsx | 10 +++++++- .../Waterfall/FlyoutTopLevelProperties.tsx | 10 +++++++- .../SpanFlyout/StickySpanProperties.tsx | 11 ++++++++- .../index.tsx | 21 +++++++++++----- .../components/shared/Links/apm/APMLink.tsx | 20 +++++++++++----- .../shared/Links/apm/ErrorOverviewLink.tsx | 5 +++- .../shared/Links/apm/MetricOverviewLink.tsx | 5 +++- .../shared/Links/apm/ServiceMapLink.tsx | 4 ++-- .../Links/apm/ServiceNodeOverviewLink.tsx | 5 +++- .../shared/Links/apm/TraceOverviewLink.tsx | 2 +- .../Links/apm/service_inventory_link.tsx | 2 +- .../Links/apm/service_overview_link.tsx | 20 +++++++++++++--- .../service_transactions_overview_link.tsx | 16 ++++++++++--- .../Links/apm/transaction_detail_link.tsx | 5 +++- .../apm/typings/es_schemas/raw/span_raw.ts | 1 + 16 files changed, 132 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/apm/common/environment_filter_values.ts b/x-pack/plugins/apm/common/environment_filter_values.ts index e231f37a170ed9..8f5b6456b8c928 100644 --- a/x-pack/plugins/apm/common/environment_filter_values.ts +++ b/x-pack/plugins/apm/common/environment_filter_values.ts @@ -33,3 +33,27 @@ export const ENVIRONMENT_NOT_DEFINED = { export function getEnvironmentLabel(environment: string) { return environmentLabels[environment] || environment; } + +// returns the environment url param that should be used +// based on the requested environment. If the requested +// environment is different from the URL parameter, we'll +// return ENVIRONMENT_ALL. If it's not, we'll just return +// the current environment URL param +export function getNextEnvironmentUrlParam({ + requestedEnvironment, + currentEnvironmentUrlParam, +}: { + requestedEnvironment?: string; + currentEnvironmentUrlParam?: string; +}) { + const normalizedRequestedEnvironment = + requestedEnvironment || ENVIRONMENT_NOT_DEFINED.value; + const normalizedQueryEnvironment = + currentEnvironmentUrlParam || ENVIRONMENT_ALL.value; + + if (normalizedRequestedEnvironment === normalizedQueryEnvironment) { + return currentEnvironmentUrlParam; + } + + return ENVIRONMENT_ALL.value; +} diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx index 49a016f338888a..fec14ccf76c938 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/MaybeViewTraceLink.tsx @@ -7,6 +7,7 @@ import { EuiButton, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { getNextEnvironmentUrlParam } from '../../../../../common/environment_filter_values'; import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/transaction'; import { TransactionDetailLink } from '../../../shared/Links/apm/transaction_detail_link'; @@ -20,8 +21,9 @@ export const MaybeViewTraceLink = ({ waterfall: IWaterfall; }) => { const { - urlParams: { latencyAggregationType }, + urlParams: { environment, latencyAggregationType }, } = useUrlParams(); + const viewFullTraceButtonLabel = i18n.translate( 'xpack.apm.transactionDetails.viewFullTraceButtonLabel', { @@ -73,6 +75,11 @@ export const MaybeViewTraceLink = ({ // the user is viewing a zoomed in version of the trace. Link to the full trace } else { + const nextEnvironment = getNextEnvironmentUrlParam({ + requestedEnvironment: rootTransaction?.service.environment, + currentEnvironmentUrlParam: environment, + }); + return ( {viewFullTraceButtonLabel} diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx index a67ec0a69ed879..6b6d54b6cbad69 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useUrlParams } from '../../../../../../context/url_params_context/use_url_params'; +import { getNextEnvironmentUrlParam } from '../../../../../../../common/environment_filter_values'; import { SERVICE_NAME, TRANSACTION_NAME, @@ -22,13 +23,18 @@ interface Props { export function FlyoutTopLevelProperties({ transaction }: Props) { const { - urlParams: { latencyAggregationType }, + urlParams: { environment, latencyAggregationType }, } = useUrlParams(); if (!transaction) { return null; } + const nextEnvironment = getNextEnvironmentUrlParam({ + requestedEnvironment: transaction.service.environment, + currentEnvironmentUrlParam: environment, + }); + const stickyProperties = [ { label: i18n.translate('xpack.apm.transactionDetails.serviceLabel', { @@ -38,6 +44,7 @@ export function FlyoutTopLevelProperties({ transaction }: Props) { val: ( {transaction.service.name} @@ -56,6 +63,7 @@ export function FlyoutTopLevelProperties({ transaction }: Props) { traceId={transaction.trace.id} transactionName={transaction.transaction.name} transactionType={transaction.transaction.type} + environment={nextEnvironment} latencyAggregationType={latencyAggregationType} > {transaction.transaction.name} diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx index 5a1f6e3d2a24dd..82b43b3dce99af 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/SpanFlyout/StickySpanProperties.tsx @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useUrlParams } from '../../../../../../../context/url_params_context/use_url_params'; +import { getNextEnvironmentUrlParam } from '../../../../../../../../common/environment_filter_values'; import { SERVICE_NAME, SPAN_NAME, @@ -26,8 +27,14 @@ interface Props { export function StickySpanProperties({ span, transaction }: Props) { const { - urlParams: { latencyAggregationType }, + urlParams: { environment, latencyAggregationType }, } = useUrlParams(); + + const nextEnvironment = getNextEnvironmentUrlParam({ + requestedEnvironment: transaction?.service.environment, + currentEnvironmentUrlParam: environment, + }); + const spanName = span.span.name; const transactionStickyProperties = transaction ? [ @@ -39,6 +46,7 @@ export function StickySpanProperties({ span, transaction }: Props) { val: ( {transaction.service.name} @@ -60,6 +68,7 @@ export function StickySpanProperties({ span, transaction }: Props) { traceId={transaction.trace.id} transactionName={transaction.transaction.name} transactionType={transaction.transaction.type} + environment={nextEnvironment} latencyAggregationType={latencyAggregationType} > {transaction.transaction.name} diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx index 079c599f8f7baf..1bd7310e3251df 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx @@ -13,7 +13,10 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; +import { + ENVIRONMENT_ALL, + getNextEnvironmentUrlParam, +} from '../../../../../common/environment_filter_values'; import { asMillisecondDuration, asPercent, @@ -40,6 +43,10 @@ interface Props { } export function ServiceOverviewDependenciesTable({ serviceName }: Props) { + const { + urlParams: { start, end, environment }, + } = useUrlParams(); + const columns: Array> = [ { field: 'name', @@ -64,7 +71,13 @@ export function ServiceOverviewDependenciesTable({ serviceName }: Props) { {item.type === 'service' ? ( - + {item.name} ) : ( @@ -154,10 +167,6 @@ export function ServiceOverviewDependenciesTable({ serviceName }: Props) { }, ]; - const { - urlParams: { start, end, environment }, - } = useUrlParams(); - const { data = [], status } = useFetcher(() => { if (!start || !end) { return; diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx index 7acc2542a65f3f..fe5bfc6c4679b8 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx @@ -36,16 +36,24 @@ export const PERSISTENT_APM_PARAMS: Array = [ /** * Hook to get a link for a path with persisted filters */ -export function useAPMHref( - path: string, - persistentFilters: Array = [] -) { +export function useAPMHref({ + path, + persistedFilters, + query, +}: { + path: string; + persistedFilters?: Array; + query?: APMQueryParams; +}) { const { urlParams } = useUrlParams(); const { basePath } = useApmPluginContext().core.http; const { search } = useLocation(); - const query = pickKeys(urlParams as APMQueryParams, ...persistentFilters); + const nextQuery = { + ...pickKeys(urlParams as APMQueryParams, ...(persistedFilters ?? [])), + ...query, + }; - return getAPMHref({ basePath, path, query, search }); + return getAPMHref({ basePath, path, query: nextQuery, search }); } /** diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx index dcf21de7dca8df..506787c0fe62f2 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx @@ -17,7 +17,10 @@ const persistedFilters: Array = [ ]; export function useErrorOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/errors`, persistedFilters); + return useAPMHref({ + path: `/services/${serviceName}/errors`, + persistedFilters, + }); } interface Props extends APMLinkExtendProps { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx index 8031b6088d420d..e369e920a4b82e 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx @@ -16,7 +16,10 @@ const persistedFilters: Array = [ ]; export function useMetricOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/metrics`, persistedFilters); + return useAPMHref({ + path: `/services/${serviceName}/metrics`, + persistedFilters, + }); } interface Props extends APMLinkExtendProps { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx index 670b7137219e17..b5b74f06d65ba6 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceMapLink.tsx @@ -8,10 +8,10 @@ import React from 'react'; import { APMLinkExtendProps, useAPMHref } from './APMLink'; export function useServiceMapHref(serviceName?: string) { - const pathFor = serviceName + const path = serviceName ? `/services/${serviceName}/service-map` : '/service-map'; - return useAPMHref(pathFor); + return useAPMHref({ path }); } interface ServiceMapLinkProps extends APMLinkExtendProps { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx index 279c038d95a80c..b2382ef99e9820 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ServiceNodeOverviewLink.tsx @@ -14,5 +14,8 @@ const persistedFilters: Array = [ ]; export function useServiceNodeOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/nodes`, persistedFilters); + return useAPMHref({ + path: `/services/${serviceName}/nodes`, + persistedFilters, + }); } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx index 3cb0009a12c945..a5f7b3f2b28e43 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx @@ -20,5 +20,5 @@ const persistedFilters: Array = [ ]; export function useTraceOverviewHref() { - return useAPMHref('/traces', persistedFilters); + return useAPMHref({ path: '/traces', persistedFilters }); } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx index c3b80cbeb701b8..1d879f86dff3d6 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/service_inventory_link.tsx @@ -15,5 +15,5 @@ import { useAPMHref } from './APMLink'; const persistedFilters: Array = ['host', 'agentName']; export function useServiceInventoryHref() { - return useAPMHref('/services', persistedFilters); + return useAPMHref({ path: '/services', persistedFilters }); } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx index ba53243a6bc750..31ce04cf23fbc5 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/service_overview_link.tsx @@ -15,20 +15,34 @@ import { APMLinkExtendProps, useAPMHref } from './APMLink'; interface ServiceOverviewLinkProps extends APMLinkExtendProps { serviceName: string; + environment?: string; } const persistedFilters: Array = [ 'latencyAggregationType', ]; -export function useServiceOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}/overview`, persistedFilters); +export function useServiceOverviewHref( + serviceName: string, + environment?: string +) { + const query = environment + ? { + environment, + } + : {}; + return useAPMHref({ + path: `/services/${serviceName}/overview`, + persistedFilters, + query, + }); } export function ServiceOverviewLink({ serviceName, + environment, ...rest }: ServiceOverviewLinkProps) { - const href = useServiceOverviewHref(serviceName); + const href = useServiceOverviewHref(serviceName, environment); return ; } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx index 8b96ba8ab233a2..c4ea99030d87c3 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/service_transactions_overview_link.tsx @@ -17,18 +17,28 @@ const persistedFilters: Array = [ 'latencyAggregationType', ]; -export function useServiceOrTransactionsOverviewHref(serviceName: string) { - return useAPMHref(`/services/${serviceName}`, persistedFilters); +export function useServiceOrTransactionsOverviewHref( + serviceName: string, + environment?: string +) { + const query = environment ? { environment } : {}; + return useAPMHref({ + path: `/services/${serviceName}`, + persistedFilters, + query, + }); } interface Props extends APMLinkExtendProps { serviceName: string; + environment?: string; } export function ServiceOrTransactionsOverviewLink({ serviceName, + environment, ...rest }: Props) { - const href = useServiceOrTransactionsOverviewHref(serviceName); + const href = useServiceOrTransactionsOverviewHref(serviceName, environment); return ; } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx index 8108dcf41321f4..a97d860d99798a 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; import { EuiLink } from '@elastic/eui'; +import { pickBy, identity } from 'lodash'; import { getAPMHref, APMLinkExtendProps } from './APMLink'; import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { pickKeys } from '../../../../../common/utils/pick_keys'; @@ -20,6 +21,7 @@ interface Props extends APMLinkExtendProps { transactionName: string; transactionType: string; latencyAggregationType?: string; + environment?: string; } const persistedFilters: Array = [ @@ -34,6 +36,7 @@ export function TransactionDetailLink({ transactionName, transactionType, latencyAggregationType, + environment, ...rest }: Props) { const { urlParams } = useUrlParams(); @@ -47,8 +50,8 @@ export function TransactionDetailLink({ transactionId, transactionName, transactionType, - ...(latencyAggregationType ? { latencyAggregationType } : {}), ...pickKeys(urlParams as APMQueryParams, ...persistedFilters), + ...pickBy({ latencyAggregationType, environment }, identity), }, search: location.search, }); diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts b/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts index e152ed23af1b39..3938a9b54d913a 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/span_raw.ts @@ -18,6 +18,7 @@ export interface SpanRaw extends APMBaseDoc { trace: { id: string }; // trace is required service: { name: string; + environment?: string; }; span: { destination?: { From fbb8238f5747e967d14246b3f527fe334091f4de Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Fri, 15 Jan 2021 18:04:45 -0400 Subject: [PATCH 26/33] Porting fixes 1 (#88477) * Remove Manage button from Source overview page * Replace empty select option with "Leave unassigned" * Replace content source key with id * Update Google icons * Replace anchor with EuiLink * Add Folders as one of the synced items for Box * Add DLP feature UI to Jira and Confluence cloud pages * Fix the "Fix" link path Also updated TS types to match ent-search * Fix copy and button color on "Content source is disabled" callout * Remove incorrect copy from Private sources empty state * Move constants from logic file to a separate file, rename a constant * Fix i18n path to not include file name Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../shared/assets/source_icons/gmail.svg | 2 +- .../assets/source_icons/google_drive.svg | 2 +- .../assets/sources_full_bleed/gmail.svg | 2 +- .../sources_full_bleed/google_drive.svg | 2 +- .../shared/source_row/source_row.tsx | 14 +++++++-- .../workplace_search/constants.ts | 3 ++ .../applications/workplace_search/routes.ts | 2 +- .../applications/workplace_search/types.ts | 2 -- .../components/add_source/constants.ts | 6 ++-- .../components/add_source/save_custom.tsx | 12 +++----- .../components/display_settings/constants.ts | 21 +++++++++++++ .../display_settings_logic.ts | 9 +++--- .../display_settings/search_results.tsx | 11 ++++--- .../content_sources/components/overview.tsx | 30 ++++--------------- .../views/content_sources/private_sources.tsx | 11 +------ .../views/content_sources/source_data.tsx | 4 ++- .../views/content_sources/source_router.tsx | 11 +++---- .../views/setup_guide/setup_guide.tsx | 6 ++-- 18 files changed, 79 insertions(+), 71 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/constants.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/gmail.svg b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/gmail.svg index ee824f730aca67..ae068feb7133d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/gmail.svg +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/gmail.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/google_drive.svg b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/google_drive.svg index 59469d814e35fd..c684cecb712352 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/google_drive.svg +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/source_icons/google_drive.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/gmail.svg b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/gmail.svg index 98d418244c22f3..31fe60c6a63f9f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/gmail.svg +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/gmail.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/google_drive.svg b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/google_drive.svg index 6541b3f9e753ff..f3fe82cd3cd983 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/google_drive.svg +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/assets/sources_full_bleed/google_drive.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx index 818d06c55dd12a..2080f454596b57 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/shared/source_row/source_row.tsx @@ -26,7 +26,12 @@ import { import { EuiLinkTo } from '../../../../shared/react_router_helpers'; import { SOURCE_STATUSES as statuses } from '../../../constants'; import { ContentSourceDetails } from '../../../types'; -import { ADD_SOURCE_PATH, SOURCE_DETAILS_PATH, getContentSourcePath } from '../../../routes'; +import { + ADD_SOURCE_PATH, + SOURCE_DETAILS_PATH, + getContentSourcePath, + getSourcesPath, +} from '../../../routes'; import { SourceIcon } from '../source_icon'; @@ -77,7 +82,12 @@ export const SourceRow: React.FC = ({ const imageClass = classNames('source-row__icon', { 'source-row__icon--loading': isIndexing }); const fixLink = ( - + Fix ); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts index 74e0682db89b5a..4ca256ac91a3f1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts @@ -136,6 +136,9 @@ export const SOURCE_NAMES = { }; export const SOURCE_OBJ_TYPES = { + FOLDERS: i18n.translate('xpack.enterpriseSearch.workplaceSearch.sources.objTypes.folders', { + defaultMessage: 'Folders', + }), PAGES: i18n.translate('xpack.enterpriseSearch.workplaceSearch.sources.objTypes.pages', { defaultMessage: 'Pages', }), diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts index 868d76f7d09c51..1e4b51e157724a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts @@ -124,7 +124,7 @@ export const getContentSourcePath = ( export const getGroupPath = (groupId: string): string => generatePath(GROUP_PATH, { groupId }); export const getGroupSourcePrioritizationPath = (groupId: string): string => `${GROUPS_PATH}/${groupId}/source_prioritization`; -export const getSourcesPath = (path: string, isOrganization: boolean): string => +export const getSourcesPath = (path: string, isOrganization?: boolean): string => isOrganization ? path : `${PERSONAL_PATH}${path}`; export const getReindexJobRoute = ( sourceId: string, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts index 9bda686ebbf00b..ed4946a019bb05 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts @@ -130,7 +130,6 @@ export interface ContentSourceFullData extends ContentSourceDetails { groups: Group[]; custom: boolean; accessToken: string; - key: string; urlField: string; titleField: string; licenseSupportsPermissions: boolean; @@ -177,7 +176,6 @@ export enum FeatureIds { export interface CustomSource { accessToken: string; - key: string; name: string; id: string; } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/constants.ts index 09a9d22461e145..7d891953e618bd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/constants.ts @@ -299,10 +299,10 @@ export const SAVE_CUSTOM_ACCESS_TOKEN_LABEL = i18n.translate( } ); -export const SAVE_CUSTOM_API_KEY_LABEL = i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.contentSource.saveCustom.apiKey.label', +export const SAVE_CUSTOM_ID_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.contentSource.saveCustom.id.label', { - defaultMessage: 'Key', + defaultMessage: 'ID', } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx index 59d691023f413c..28aeaec2b47dfb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_custom.tsx @@ -43,7 +43,7 @@ import { SAVE_CUSTOM_API_KEYS_TITLE, SAVE_CUSTOM_API_KEYS_BODY, SAVE_CUSTOM_ACCESS_TOKEN_LABEL, - SAVE_CUSTOM_API_KEY_LABEL, + SAVE_CUSTOM_ID_LABEL, SAVE_CUSTOM_VISUAL_WALKTHROUGH_TITLE, SAVE_CUSTOM_STYLING_RESULTS_TITLE, SAVE_CUSTOM_DOC_PERMISSIONS_TITLE, @@ -59,7 +59,7 @@ interface SaveCustomProps { export const SaveCustom: React.FC = ({ documentationUrl, - newCustomSource: { key, id, accessToken, name }, + newCustomSource: { id, accessToken, name }, isOrganization, header, }) => ( @@ -109,17 +109,13 @@ export const SaveCustom: React.FC = ({

{SAVE_CUSTOM_API_KEYS_BODY}

+ + - - diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/constants.ts new file mode 100644 index 00000000000000..0e6cbb25601285 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/constants.ts @@ -0,0 +1,21 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const LEAVE_UNASSIGNED_FIELD = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.contentSources.displaySettings.leaveUnassignedField', + { + defaultMessage: 'Leave unassigned', + } +); + +export const SUCCESS_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.contentSources.displaySettings.successMessage', + { + defaultMessage: 'Display Settings have been successfuly updated.', + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts index c52665524f5666..a8636b4a34da18 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/display_settings_logic.ts @@ -20,10 +20,8 @@ import { import { AppLogic } from '../../../../app_logic'; import { SourceLogic } from '../../source_logic'; -const SUCCESS_MESSAGE = 'Display Settings have been successfuly updated.'; - import { DetailField, SearchResultConfig, OptionValue, Result } from '../../../../types'; - +import { LEAVE_UNASSIGNED_FIELD, SUCCESS_MESSAGE } from './constants'; export interface DisplaySettingsResponseProps { sourceName: string; searchResultConfig: SearchResultConfig; @@ -271,7 +269,10 @@ export const DisplaySettingsLogic = kea< () => [selectors.fieldOptions], (fieldOptions) => { const optionalFieldOptions = cloneDeep(fieldOptions); - optionalFieldOptions.unshift({ value: '', text: '' }); + optionalFieldOptions.unshift({ + value: LEAVE_UNASSIGNED_FIELD, + text: LEAVE_UNASSIGNED_FIELD, + }); return optionalFieldOptions; }, ], diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx index cfe0ddb1533ecc..96b7a6fbe14b50 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/search_results.tsx @@ -21,6 +21,7 @@ import { } from '@elastic/eui'; import { DisplaySettingsLogic } from './display_settings_logic'; +import { LEAVE_UNASSIGNED_FIELD } from './constants'; import { ExampleSearchResultGroup } from './example_search_result_group'; import { ExampleStandoutResult } from './example_standout_result'; @@ -104,8 +105,10 @@ export const SearchResults: React.FC = () => { className="field-selector" hasNoInitialSelection={true} data-test-subj="SubtitleFieldSelect" - value={subtitleField || ''} - onChange={({ target: { value } }) => setSubtitleField(value === '' ? null : value)} + value={subtitleField || LEAVE_UNASSIGNED_FIELD} + onChange={({ target: { value } }) => + setSubtitleField(value === LEAVE_UNASSIGNED_FIELD ? null : value) + } /> { className="field-selector" hasNoInitialSelection={true} data-test-subj="DescriptionFieldSelect" - value={descriptionField || ''} + value={descriptionField || LEAVE_UNASSIGNED_FIELD} onChange={({ target: { value } }) => - setDescriptionField(value === '' ? null : value) + setDescriptionField(value === LEAVE_UNASSIGNED_FIELD ? null : value) } /> diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx index 8d6e421005df71..71d79b4b2a0827 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/overview.tsx @@ -33,8 +33,6 @@ import { DOCUMENT_PERMISSIONS_DOCS_URL, ENT_SEARCH_LICENSE_MANAGEMENT, EXTERNAL_IDENTITIES_DOCS_URL, - SOURCE_CONTENT_PATH, - getContentSourcePath, getGroupPath, } from '../../../routes'; @@ -45,7 +43,7 @@ import { CredentialItem } from '../../../components/shared/credential_item'; import { ViewContentHeader } from '../../../components/shared/view_content_header'; import { LicenseBadge } from '../../../components/shared/license_badge'; import { Loading } from '../../../../shared/loading'; -import { EuiButtonEmptyTo, EuiPanelTo } from '../../../../shared/react_router_helpers'; +import { EuiPanelTo } from '../../../../shared/react_router_helpers'; import aclImage from '../../../assets/supports_acl.svg'; import { SourceLogic } from '../source_logic'; @@ -63,7 +61,6 @@ export const Overview: React.FC = () => { details, custom, accessToken, - key, licenseSupportsPermissions, serviceTypeSupportsPermissions, indexPermissions, @@ -105,24 +102,9 @@ export const Overview: React.FC = () => { return (
- - - -

Content summary

-
-
- {totalDocuments > 0 && ( - - - Manage - - - )} -
+ +

Content summary

+
{!summary && } @@ -388,9 +370,9 @@ export const Overview: React.FC = () => { - + - + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx index 0f5f4ffb9e0daf..a1a76c678866c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources.tsx @@ -107,16 +107,7 @@ export const PrivateSources: React.FC = () => { - You have no private sources} - body={ -

- Select from the content sources below to create a private source, available only to - you -

- } - /> + You have no private sources} />
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx index 882c3861922e71..8aebbf721f8fc3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx @@ -106,7 +106,7 @@ export const staticSourceData = [ } ), connectStepDescription: connectStepDescription.files, - objTypes: [SOURCE_OBJ_TYPES.ALL_FILES], + objTypes: [SOURCE_OBJ_TYPES.FOLDERS, SOURCE_OBJ_TYPES.ALL_FILES], features: { basicOrgContext: [ FeatureIds.SyncFrequency, @@ -156,6 +156,7 @@ export const staticSourceData = [ FeatureIds.SyncedItems, FeatureIds.GlobalAccessPermissions, ], + basicOrgContextExcludedFeatures: [FeatureIds.DocumentLevelPermissions], platinumOrgContext: [FeatureIds.SyncFrequency, FeatureIds.SyncedItems], platinumPrivateContext: [ FeatureIds.Private, @@ -435,6 +436,7 @@ export const staticSourceData = [ FeatureIds.SyncedItems, FeatureIds.GlobalAccessPermissions, ], + basicOrgContextExcludedFeatures: [FeatureIds.DocumentLevelPermissions], platinumOrgContext: [FeatureIds.SyncFrequency, FeatureIds.SyncedItems], platinumPrivateContext: [ FeatureIds.Private, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx index 7244ff21e3b388..089ef0cd46a008 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx @@ -84,12 +84,13 @@ export const SourceRouter: React.FC = () => { <>

- Your organization's license level changed and no longer supports document-level - permissions.{' '} + Your organization’s license level has changed. Your data is safe, but document-level + permissions are no longer supported and searching of this source has been disabled. + Upgrade to a Platinum license to re-enable this source.

-

Don't worry: your data is safe. Search has been disabled.

-

Upgrade to a Platinum license to re-enable this source.

- Explore Platinum license + + Explore Platinum license +
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx index 3b91c4e84d02f7..8fefe3bac2a12c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/setup_guide/setup_guide.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { EuiSpacer, EuiTitle, EuiText, EuiButton } from '@elastic/eui'; +import { EuiSpacer, EuiTitle, EuiText, EuiButton, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -30,7 +30,7 @@ export const SetupGuide: React.FC = () => { -
+ { width="1280" height-="720" /> - +

From c66c9424d9109e6de2406786a2ec2b9921a98244 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 15 Jan 2021 19:05:45 -0700 Subject: [PATCH 27/33] [Maps] fix zooming while drawing shape filter logs errors in console (#88413) * [Maps] fix zooming while drawing shape filter logs errors in console * add unit test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../connected_components/mb_map/mb.utils.test.js | 12 ++++++++++++ .../maps/public/connected_components/mb_map/utils.js | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb.utils.test.js b/x-pack/plugins/maps/public/connected_components/mb_map/mb.utils.test.js index a28cc75f6d89d1..2d6cba84e17e5c 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb.utils.test.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb.utils.test.js @@ -185,4 +185,16 @@ describe('removeOrphanedSourcesAndLayers', () => { removeOrphanedSourcesAndLayers(mockMbMap, [], spatialFilterLayer); expect(mockMbMap.getStyle()).toEqual(styleWithSpatialFilters); }); + + test('should not remove mapbox gl draw layers and sources', async () => { + const fooLayer = makeMultiSourceMockLayer('foo'); + const layerList = [fooLayer]; + + const currentStyle = getMockStyle(layerList); + currentStyle.layers.push({ id: 'gl-draw-points' }); + const mockMbMap = new MockMbMap(currentStyle); + + removeOrphanedSourcesAndLayers(mockMbMap, layerList, spatialFilterLayer); + expect(mockMbMap.getStyle()).toEqual(currentStyle); + }); }); diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/utils.js b/x-pack/plugins/maps/public/connected_components/mb_map/utils.js index e5801afd5b601a..f12f34061756fa 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/utils.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/utils.js @@ -16,6 +16,11 @@ export function removeOrphanedSourcesAndLayers(mbMap, layerList, spatialFilterLa return; } + // ignore gl-draw layers + if (mbLayer.id.startsWith('gl-draw')) { + return; + } + const layer = layerList.find((layer) => { return layer.ownsMbLayerId(mbLayer.id); }); From 5c112b8b5a89c9ea5ae88f018cf985329c3afe31 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Fri, 15 Jan 2021 19:07:45 -0800 Subject: [PATCH 28/33] [Alerting] Migrate Event Log plugin to TS project references (#81557) * [Alerting] Migrate Event Log plugin to TS project references * fixed faling typechecks * fixed path to spaces plugin ts file * fixed missing include * added fix for mapping.json * replaced package.json get version with kibanaVersion from plugin initial context * fixed build * fixed typechecks * fixed tests --- .../event_log/server/es/context.test.ts | 5 +++++ x-pack/plugins/event_log/server/es/context.ts | 3 ++- .../event_log/server/es/documents.test.ts | 3 ++- .../plugins/event_log/server/es/names.test.ts | 16 ++++++++------ x-pack/plugins/event_log/server/es/names.ts | 6 ++--- x-pack/plugins/event_log/server/plugin.ts | 3 +++ x-pack/plugins/event_log/tsconfig.json | 22 +++++++++++++++++++ x-pack/test/tsconfig.json | 1 + x-pack/tsconfig.json | 2 ++ x-pack/tsconfig.refs.json | 1 + 10 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 x-pack/plugins/event_log/tsconfig.json diff --git a/x-pack/plugins/event_log/server/es/context.test.ts b/x-pack/plugins/event_log/server/es/context.test.ts index f30b71c99a0432..5f26399618e38f 100644 --- a/x-pack/plugins/event_log/server/es/context.test.ts +++ b/x-pack/plugins/event_log/server/es/context.test.ts @@ -25,6 +25,7 @@ describe('createEsContext', () => { logger, clusterClientPromise: Promise.resolve(clusterClient), indexNameRoot: 'test0', + kibanaVersion: '1.2.3', }); expect(context.initialized).toBeFalsy(); @@ -38,6 +39,7 @@ describe('createEsContext', () => { logger, clusterClientPromise: Promise.resolve(clusterClient), indexNameRoot: 'test-index', + kibanaVersion: '1.2.3', }); const esNames = context.esNames; @@ -57,6 +59,7 @@ describe('createEsContext', () => { logger, clusterClientPromise: Promise.resolve(clusterClient), indexNameRoot: 'test1', + kibanaVersion: '1.2.3', }); clusterClient.callAsInternalUser.mockResolvedValue(false); @@ -74,6 +77,7 @@ describe('createEsContext', () => { logger, clusterClientPromise: Promise.resolve(clusterClient), indexNameRoot: 'test2', + kibanaVersion: '1.2.3', }); clusterClient.callAsInternalUser.mockResolvedValue(true); context.initialize(); @@ -98,6 +102,7 @@ describe('createEsContext', () => { logger, clusterClientPromise: Promise.resolve(clusterClient), indexNameRoot: 'test2', + kibanaVersion: '1.2.3', }); context.initialize(); const success = await context.waitTillReady(); diff --git a/x-pack/plugins/event_log/server/es/context.ts b/x-pack/plugins/event_log/server/es/context.ts index d7f67620e7968d..c1777d6979c5c0 100644 --- a/x-pack/plugins/event_log/server/es/context.ts +++ b/x-pack/plugins/event_log/server/es/context.ts @@ -36,6 +36,7 @@ export interface EsContextCtorParams { logger: Logger; clusterClientPromise: Promise; indexNameRoot: string; + kibanaVersion: string; } class EsContextImpl implements EsContext { @@ -47,7 +48,7 @@ class EsContextImpl implements EsContext { constructor(params: EsContextCtorParams) { this.logger = params.logger; - this.esNames = getEsNames(params.indexNameRoot); + this.esNames = getEsNames(params.indexNameRoot, params.kibanaVersion); this.readySignal = createReadySignal(); this.initialized = false; this.esAdapter = new ClusterClientAdapter({ diff --git a/x-pack/plugins/event_log/server/es/documents.test.ts b/x-pack/plugins/event_log/server/es/documents.test.ts index 2feb6e3b84f915..df0689ba0b63c2 100644 --- a/x-pack/plugins/event_log/server/es/documents.test.ts +++ b/x-pack/plugins/event_log/server/es/documents.test.ts @@ -18,7 +18,8 @@ describe('getIlmPolicy()', () => { }); describe('getIndexTemplate()', () => { - const esNames = getEsNames('XYZ'); + const kibanaVersion = '1.2.3'; + const esNames = getEsNames('XYZ', kibanaVersion); test('returns the correct details of the index template', () => { const indexTemplate = getIndexTemplate(esNames); diff --git a/x-pack/plugins/event_log/server/es/names.test.ts b/x-pack/plugins/event_log/server/es/names.test.ts index bc6a4c9a52fac4..b77ab30c754b74 100644 --- a/x-pack/plugins/event_log/server/es/names.test.ts +++ b/x-pack/plugins/event_log/server/es/names.test.ts @@ -13,20 +13,22 @@ jest.mock('../lib/../../../../package.json', () => ({ describe('getEsNames()', () => { test('works as expected', () => { const base = 'XYZ'; - const version = '1.2.3'; - const esNames = getEsNames(base); + const kibanaVersion = '1.2.3'; + const esNames = getEsNames(base, kibanaVersion); expect(esNames.base).toEqual(base); - expect(esNames.alias).toEqual(`${base}-event-log-${version}`); + expect(esNames.alias).toEqual(`${base}-event-log-${kibanaVersion}`); expect(esNames.ilmPolicy).toEqual(`${base}-event-log-policy`); expect(esNames.indexPattern).toEqual(`${base}-event-log-*`); - expect(esNames.indexPatternWithVersion).toEqual(`${base}-event-log-${version}-*`); - expect(esNames.initialIndex).toEqual(`${base}-event-log-${version}-000001`); - expect(esNames.indexTemplate).toEqual(`${base}-event-log-${version}-template`); + expect(esNames.indexPatternWithVersion).toEqual(`${base}-event-log-${kibanaVersion}-*`); + expect(esNames.initialIndex).toEqual(`${base}-event-log-${kibanaVersion}-000001`); + expect(esNames.indexTemplate).toEqual(`${base}-event-log-${kibanaVersion}-template`); }); test('ilm policy name does not contain dot prefix', () => { const base = '.XYZ'; - const esNames = getEsNames(base); + const kibanaVersion = '1.2.3'; + + const esNames = getEsNames(base, kibanaVersion); expect(esNames.ilmPolicy).toEqual('XYZ-event-log-policy'); }); }); diff --git a/x-pack/plugins/event_log/server/es/names.ts b/x-pack/plugins/event_log/server/es/names.ts index 8cd56a89d3fbec..363b67814efe70 100644 --- a/x-pack/plugins/event_log/server/es/names.ts +++ b/x-pack/plugins/event_log/server/es/names.ts @@ -4,10 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import xPackage from '../../../../package.json'; - const EVENT_LOG_NAME_SUFFIX = `-event-log`; -const EVENT_LOG_VERSION_SUFFIX = `-${xPackage.version}`; export interface EsNames { base: string; @@ -19,7 +16,8 @@ export interface EsNames { indexTemplate: string; } -export function getEsNames(baseName: string): EsNames { +export function getEsNames(baseName: string, kibanaVersion: string): EsNames { + const EVENT_LOG_VERSION_SUFFIX = `-${kibanaVersion.toLocaleLowerCase()}`; const eventLogName = `${baseName}${EVENT_LOG_NAME_SUFFIX}`; const eventLogNameWithVersion = `${eventLogName}${EVENT_LOG_VERSION_SUFFIX}`; const eventLogPolicyName = `${ diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index 6471db7d5dd691..03125f3005c3d2 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -55,12 +55,14 @@ export class Plugin implements CorePlugin; private eventLogClientService?: EventLogClientService; private savedObjectProviderRegistry: SavedObjectProviderRegistry; + private kibanaVersion: PluginInitializerContext['env']['packageInfo']['version']; constructor(private readonly context: PluginInitializerContext) { this.systemLogger = this.context.logger.get(); this.config$ = this.context.config.create(); this.globalConfig$ = this.context.config.legacy.globalConfig$; this.savedObjectProviderRegistry = new SavedObjectProviderRegistry(); + this.kibanaVersion = this.context.env.packageInfo.version; } async setup(core: CoreSetup): Promise { @@ -78,6 +80,7 @@ export class Plugin implements CorePlugin elasticsearch.legacy.client), + kibanaVersion: this.kibanaVersion, }); this.eventLogService = new EventLogService({ diff --git a/x-pack/plugins/event_log/tsconfig.json b/x-pack/plugins/event_log/tsconfig.json new file mode 100644 index 00000000000000..9b7cde10da3d60 --- /dev/null +++ b/x-pack/plugins/event_log/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "server/**/*", + "scripts/**/*", + "generated/*", + // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636 + "generated/*.json", + "common/*" + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + { "path": "../spaces/tsconfig.json" } + ] +} diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index eac9d928840281..d977730181e890 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -42,6 +42,7 @@ { "path": "../plugins/global_search_providers/tsconfig.json" }, { "path": "../plugins/features/tsconfig.json" }, { "path": "../plugins/embeddable_enhanced/tsconfig.json" }, + { "path": "../plugins/event_log/tsconfig.json"}, { "path": "../plugins/licensing/tsconfig.json" }, { "path": "../plugins/task_manager/tsconfig.json" }, { "path": "../plugins/telemetry_collection_xpack/tsconfig.json" }, diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index 01d9bcf9537ecd..56444ed80bc903 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -13,6 +13,7 @@ "plugins/graph/**/*", "plugins/features/**/*", "plugins/embeddable_enhanced/**/*", + "plugins/event_log/**/*", "plugins/licensing/**/*", "plugins/searchprofiler/**/*", "plugins/security_solution/cypress/**/*", @@ -73,6 +74,7 @@ { "path": "./plugins/features/tsconfig.json" }, { "path": "./plugins/graph/tsconfig.json" }, { "path": "./plugins/embeddable_enhanced/tsconfig.json" }, + { "path": "./plugins/event_log/tsconfig.json"}, { "path": "./plugins/licensing/tsconfig.json" }, { "path": "./plugins/searchprofiler/tsconfig.json" }, { "path": "./plugins/task_manager/tsconfig.json" }, diff --git a/x-pack/tsconfig.refs.json b/x-pack/tsconfig.refs.json index 4352d2993002a4..a0a9eda0aaf23f 100644 --- a/x-pack/tsconfig.refs.json +++ b/x-pack/tsconfig.refs.json @@ -8,6 +8,7 @@ { "path": "./plugins/data_enhanced/tsconfig.json" }, { "path": "./plugins/global_search/tsconfig.json" }, { "path": "./plugins/global_search_providers/tsconfig.json" }, + { "path": "./plugins/event_log/tsconfig.json"}, { "path": "./plugins/features/tsconfig.json" }, { "path": "./plugins/graph/tsconfig.json" }, { "path": "./plugins/embeddable_enhanced/tsconfig.json" }, From 273ad4e50517bac13a36bab0768b57d11e3b822a Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Fri, 15 Jan 2021 22:31:44 -0500 Subject: [PATCH 29/33] removing kibana-core-ui from codeowners (#88111) --- .github/CODEOWNERS | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5c768dccaf2742..b47d78ea6d691a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -98,18 +98,6 @@ #CC# /x-pack/legacy/plugins/canvas/ @elastic/kibana-presentation #CC# /x-pack/plugins/dashboard_mode @elastic/kibana-presentation -# Core UI -# Exclude tutorials folder for now because they are not owned by Kibana app and most will move out soon -/src/plugins/home/public @elastic/kibana-core-ui -/src/plugins/home/server/*.ts @elastic/kibana-core-ui -/src/plugins/home/server/services/ @elastic/kibana-core-ui -/src/plugins/kibana_overview/ @elastic/kibana-core-ui -/x-pack/plugins/global_search_bar/ @elastic/kibana-core-ui -#CC# /src/plugins/newsfeed @elastic/kibana-core-ui -#CC# /src/plugins/home/public @elastic/kibana-core-ui -#CC# /src/plugins/home/server/services/ @elastic/kibana-core-ui -#CC# /src/plugins/home/ @elastic/kibana-core-ui -#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core-ui # Observability UIs /x-pack/plugins/infra/ @elastic/logs-metrics-ui @@ -138,10 +126,6 @@ /x-pack/test/functional/apps/maps/ @elastic/kibana-gis /x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis /x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis -/x-pack/plugins/stack_alerts/server/alert_types/geo_containment @elastic/kibana-gis -/x-pack/plugins/stack_alerts/public/alert_types/geo_containment @elastic/kibana-gis -/x-pack/plugins/stack_alerts/server/alert_types/geo_threshold @elastic/kibana-gis -/x-pack/plugins/stack_alerts/public/alert_types/geo_threshold @elastic/kibana-gis #CC# /src/plugins/maps_legacy/ @elastic/kibana-gis #CC# /src/plugins/maps_oss/ @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis @@ -200,6 +184,11 @@ /src/plugins/status_page/ @elastic/kibana-core /src/plugins/saved_objects_management/ @elastic/kibana-core /src/dev/run_check_published_api_changes.ts @elastic/kibana-core +/src/plugins/home/public @elastic/kibana-core +/src/plugins/home/server/*.ts @elastic/kibana-core +/src/plugins/home/server/services/ @elastic/kibana-core +/src/plugins/kibana_overview/ @elastic/kibana-core +/x-pack/plugins/global_search_bar/ @elastic/kibana-core #CC# /src/core/server/csp/ @elastic/kibana-core #CC# /src/legacy/server/config/ @elastic/kibana-core #CC# /src/legacy/server/http/ @elastic/kibana-core @@ -210,6 +199,11 @@ #CC# /x-pack/plugins/cloud/ @elastic/kibana-core #CC# /x-pack/plugins/features/ @elastic/kibana-core #CC# /x-pack/plugins/global_search/ @elastic/kibana-core +#CC# /src/plugins/newsfeed @elastic/kibana-core +#CC# /src/plugins/home/public @elastic/kibana-core +#CC# /src/plugins/home/server/services/ @elastic/kibana-core +#CC# /src/plugins/home/ @elastic/kibana-core +#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core # Kibana Telemetry /packages/kbn-analytics/ @elastic/kibana-core @@ -236,7 +230,6 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib # Security /src/core/server/csp/ @elastic/kibana-security @elastic/kibana-core /src/plugins/security_oss/ @elastic/kibana-security -/src/plugins/spaces_oss/ @elastic/kibana-security /test/security_functional/ @elastic/kibana-security /x-pack/plugins/spaces/ @elastic/kibana-security /x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security @@ -263,7 +256,7 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib /x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services /docs/user/alerting/ @elastic/kibana-alerting-services /docs/management/alerting/ @elastic/kibana-alerting-services -#CC# /x-pack/plugins/stack_alerts/ @elastic/kibana-alerting-services +#CC# /x-pack/plugins/stack_alerts @elastic/kibana-alerting-services # Enterprise Search # Shared From abffb198899a61d6b05dcca3137bafce9a633e57 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Fri, 15 Jan 2021 22:05:14 -0700 Subject: [PATCH 30/33] [Test] Add tag cloud visualization to dashboard in functional test for reporting (#87600) * add tag cloud to dashboard in kibana archive * add pdf snapshot testing to downloaded pdfs * update png baseline image * remove pdf snapshot testing * rename mislabeled variable * fix test comparison * remove unnecessary pdf utf8 checks * Update screenshots.ts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../baseline/dashboard_preserve_layout.png | Bin 631719 -> 754042 bytes .../apps/dashboard/reporting/screenshots.ts | 28 +- .../functional/apps/visualize/reporting.ts | 2 +- .../reporting/ecommerce_kibana/data.json.gz | Bin 4219 -> 4526 bytes .../reporting/ecommerce_kibana/mappings.json | 3024 ++++++++--------- 5 files changed, 1371 insertions(+), 1683 deletions(-) diff --git a/x-pack/test/functional/apps/dashboard/reporting/reports/baseline/dashboard_preserve_layout.png b/x-pack/test/functional/apps/dashboard/reporting/reports/baseline/dashboard_preserve_layout.png index 1eb5f29d212c230c984be34e4aec189dbd2aa751..1832f3dc03d5291ec40cd10e827a1ebf31102584 100644 GIT binary patch literal 754042 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 z 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 -7SmLc--NveKN(5nSC@Kgo&T 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
M;81<5FG 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