From 8fe94fba4b03592d38d804416a7ab3297f9c80ac Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 14 Apr 2021 08:49:26 -0400 Subject: [PATCH 01/18] add support for kibana deprecations --- .../upgrade_assistant/common/constants.ts | 2 +- .../plugins/upgrade_assistant/common/types.ts | 5 +- .../public/application/app.tsx | 2 + .../public/application/app_context.tsx | 9 +- .../{es_deprecations => }/constants.tsx | 4 +- .../__snapshots__/group_by_bar.test.tsx.snap | 24 -- .../components/es_deprecations/controls.tsx | 108 -------- .../deprecation_tab_content.tsx | 229 +++++++++++---- .../deprecations/_deprecations.scss | 18 -- .../es_deprecations/deprecations/_index.scss | 1 - .../es_deprecations/deprecations/cell.tsx | 23 +- .../deprecations/deprecation_group_item.tsx | 75 +++++ .../deprecations/grouped.test.tsx | 215 --------------- .../es_deprecations/deprecations/grouped.tsx | 261 ------------------ .../es_deprecations/deprecations/list.tsx | 12 +- .../kibana_deprecations/deprecation_item.tsx | 105 +++++++ .../kibana_deprecations/deprecation_list.tsx | 160 +++++++++++ .../components/kibana_deprecations/index.ts | 8 + .../kibana_deprecation_errors.tsx | 49 ++++ .../kibana_deprecations.tsx | 159 +++++++++++ .../kibana_deprecations/steps_flyout.tsx | 89 ++++++ .../components/overview/kibana_stats.tsx | 119 ++++++++ .../components/overview/overview.tsx | 7 +- .../deprecation_list_bar}/count_summary.tsx | 20 +- .../deprecation_list_bar.tsx | 69 +++++ .../shared/deprecation_list_bar/index.ts | 8 + .../shared/deprecation_pagination.tsx | 24 ++ .../deprecations => shared}/health.tsx | 16 +- .../application/components/shared/index.ts | 12 + .../components/shared/no_deprecations.tsx | 66 +++++ .../__snapshots__/level_filter.test.tsx.snap} | 5 +- .../search_bar/group_by_filter.test.tsx} | 10 +- .../search_bar/group_by_filter.tsx} | 6 +- .../components/shared/search_bar/index.ts | 8 + .../search_bar/level_filter.test.tsx} | 19 +- .../search_bar/level_filter.tsx} | 25 +- .../shared/search_bar/search_bar.tsx | 142 ++++++++++ .../public/application/lib/breadcrumbs.ts | 17 +- .../application/mount_management_section.ts | 6 +- .../server/lib/es_migration_apis.ts | 103 ++++++- .../server/lib/telemetry/es_ui_open_apis.ts | 6 + .../server/routes/telemetry.ts | 4 +- .../telemetry_saved_object_type.ts | 4 + 43 files changed, 1486 insertions(+), 768 deletions(-) rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations => }/constants.tsx (87%) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/group_by_bar.test.tsx.snap delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/controls.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_deprecations.scss create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/deprecation_group_item.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.test.tsx delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/deprecations => shared/deprecation_list_bar}/count_summary.tsx (68%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/deprecations => shared}/health.tsx (86%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/__snapshots__/filter_bar.test.tsx.snap => shared/search_bar/__snapshots__/level_filter.test.tsx.snap} (85%) rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/group_by_bar.test.tsx => shared/search_bar/group_by_filter.test.tsx} (75%) rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/group_by_bar.tsx => shared/search_bar/group_by_filter.tsx} (90%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/filter_bar.test.tsx => shared/search_bar/level_filter.test.tsx} (63%) rename x-pack/plugins/upgrade_assistant/public/application/components/{es_deprecations/filter_bar.tsx => shared/search_bar/level_filter.tsx} (75%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index 29253d3c373d6..aec52f0913238 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -19,7 +19,7 @@ export const mockKibanaSemverVersion = new SemVer(mockKibanaVersion); * In readonly mode, the user will not be able to perform any actions in the UI * and will be presented with a message indicating as such. */ -export const UA_READONLY_MODE = true; +export const UA_READONLY_MODE = false; /* * Map of 7.0 --> 8.0 index setting deprecation log messages and associated settings diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index b8a5a7c1ab8cc..0471fc30f28ea 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -117,13 +117,14 @@ export enum IndexGroup { // Telemetry types export const UPGRADE_ASSISTANT_TYPE = 'upgrade-assistant-telemetry'; export const UPGRADE_ASSISTANT_DOC_ID = 'upgrade-assistant-telemetry'; -export type UIOpenOption = 'overview' | 'cluster' | 'indices'; +export type UIOpenOption = 'overview' | 'cluster' | 'indices' | 'kibana'; export type UIReindexOption = 'close' | 'open' | 'start' | 'stop'; export interface UIOpen { overview: boolean; cluster: boolean; indices: boolean; + kibana: boolean; } export interface UIReindex { @@ -138,6 +139,7 @@ export interface UpgradeAssistantTelemetrySavedObject { overview: number; cluster: number; indices: number; + kibana: number; }; ui_reindex: { close: number; @@ -152,6 +154,7 @@ export interface UpgradeAssistantTelemetry { overview: number; cluster: number; indices: number; + kibana: number; }; ui_reindex: { close: number; diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index 7be723e335e8b..8086d3322c0e9 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -11,6 +11,7 @@ import { I18nStart, ScopedHistory } from 'src/core/public'; import { AppContextProvider, ContextValue, useAppContext } from './app_context'; import { ComingSoonPrompt } from './components/coming_soon_prompt'; import { EsDeprecationsContent } from './components/es_deprecations'; +import { KibanaDeprecationsContent } from './components/kibana_deprecations'; import { DeprecationsOverview } from './components/overview'; export interface AppDependencies extends ContextValue { @@ -30,6 +31,7 @@ const App: React.FunctionComponent = () => { + ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx index 18df47d4cbd4a..049318f5b78d9 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx @@ -5,7 +5,13 @@ * 2.0. */ -import { CoreStart, DocLinksStart, HttpSetup, NotificationsStart } from 'src/core/public'; +import { + CoreStart, + DeprecationsServiceStart, + DocLinksStart, + HttpSetup, + NotificationsStart, +} from 'src/core/public'; import React, { createContext, useContext } from 'react'; import { ApiService } from './lib/api'; import { BreadcrumbService } from './lib/breadcrumbs'; @@ -26,6 +32,7 @@ export interface ContextValue { api: ApiService; breadcrumbs: BreadcrumbService; getUrlForApp: CoreStart['application']['getUrlForApp']; + deprecations: DeprecationsServiceStart; } export const AppContext = createContext({} as any); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/constants.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx similarity index 87% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/constants.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx index feff6010efe38..7b4bee75bc757 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/constants.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/constants.tsx @@ -7,7 +7,7 @@ import { IconColor } from '@elastic/eui'; import { invert } from 'lodash'; -import { DeprecationInfo } from '../../../../common/types'; +import { DeprecationInfo } from '../../../common/types'; export const LEVEL_MAP: { [level: string]: number } = { warning: 0, @@ -24,3 +24,5 @@ export const COLOR_MAP: { [level: string]: IconColor } = { warning: 'default', critical: 'danger', }; + +export const DEPRECATIONS_PER_PAGE = 25; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/group_by_bar.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/group_by_bar.test.tsx.snap deleted file mode 100644 index dfc69c57cfff6..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/group_by_bar.test.tsx.snap +++ /dev/null @@ -1,24 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`GroupByBar renders 1`] = ` - - - - by issue - - - by index - - - -`; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/controls.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/controls.tsx deleted file mode 100644 index 7212c2db4c6b4..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/controls.tsx +++ /dev/null @@ -1,108 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiButton, EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { DeprecationInfo } from '../../../../common/types'; -import { validateRegExpString } from '../../lib/utils'; -import { GroupByOption, LevelFilterOption } from '../types'; -import { FilterBar } from './filter_bar'; -import { GroupByBar } from './group_by_bar'; - -interface CheckupControlsProps { - allDeprecations?: DeprecationInfo[]; - isLoading: boolean; - loadData: () => void; - currentFilter: LevelFilterOption; - onFilterChange: (filter: LevelFilterOption) => void; - onSearchChange: (filter: string) => void; - availableGroupByOptions: GroupByOption[]; - currentGroupBy: GroupByOption; - onGroupByChange: (groupBy: GroupByOption) => void; -} - -export const CheckupControls: FunctionComponent = ({ - allDeprecations, - isLoading, - loadData, - currentFilter, - onFilterChange, - onSearchChange, - availableGroupByOptions, - currentGroupBy, - onGroupByChange, -}) => { - const [searchTermError, setSearchTermError] = useState(null); - const filterInvalid = Boolean(searchTermError); - return ( - - - - - { - const string = e.target.value; - const errorMessage = validateRegExpString(string); - if (errorMessage) { - // Emit an empty search term to listeners if search term is invalid. - onSearchChange(''); - setSearchTermError(errorMessage); - } else { - onSearchChange(e.target.value); - if (searchTermError) { - setSearchTermError(null); - } - } - }} - /> - - - {/* These two components provide their own EuiFlexItem wrappers */} - - - - - - - - - - - {filterInvalid && ( - - - - )} - - ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx index 9e8678fea0eb9..cb11a45e66f18 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx @@ -5,18 +5,24 @@ * 2.0. */ -import { find } from 'lodash'; -import React, { FunctionComponent, useState } from 'react'; - -import { EuiEmptyPrompt, EuiLink, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; +import { find, groupBy } from 'lodash'; +import React, { FunctionComponent, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; +import { EuiSpacer, EuiHorizontalRule } from '@elastic/eui'; + +import { EnrichedDeprecationInfo } from '../../../../common/types'; import { SectionLoading } from '../../../shared_imports'; import { GroupByOption, LevelFilterOption, UpgradeAssistantTabProps } from '../types'; -import { CheckupControls } from './controls'; -import { GroupedDeprecations } from './deprecations/grouped'; +import { + NoDeprecationsPrompt, + SearchBar, + DeprecationPagination, + DeprecationListBar, +} from '../shared'; +import { DEPRECATIONS_PER_PAGE } from '../constants'; import { EsDeprecationErrors } from './es_deprecation_errors'; +import { EsDeprecationAccordion } from './deprecations/deprecation_group_item'; const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { @@ -28,6 +34,63 @@ export interface CheckupTabProps extends UpgradeAssistantTabProps { checkupLabel: string; } +export const filterDeps = (level: LevelFilterOption, search: string = '') => { + const conditions: Array<(dep: EnrichedDeprecationInfo) => boolean> = []; + + if (level !== LevelFilterOption.all) { + conditions.push((dep: EnrichedDeprecationInfo) => dep.level === level); + } + + if (search.length > 0) { + // Change everything to lower case for a case-insensitive comparison + conditions.push((dep) => { + try { + const searchReg = new RegExp(search.toLowerCase()); + return Boolean(dep.message.toLowerCase().match(searchReg)); + } catch (e) { + // ignore any regexp errors. + return true; + } + }); + } + + // Return true if every condition function returns true (boolean AND) + return (dep: EnrichedDeprecationInfo) => conditions.map((c) => c(dep)).every((t) => t); +}; + +/** + * Collection of calculated fields based on props, extracted for reuse in + * `render` and `getDerivedStateFromProps`. + */ +const CalcFields = { + filteredDeprecations(props: { + deprecations: EnrichedDeprecationInfo[]; + currentFilter: LevelFilterOption; + search: string; + }) { + const { deprecations = [], currentFilter, search } = props; + return deprecations.filter(filterDeps(currentFilter, search)); + }, + + groups(props: { + deprecations: EnrichedDeprecationInfo[]; + currentFilter: LevelFilterOption; + search: string; + currentGroupBy: GroupByOption; + }) { + return groupBy(CalcFields.filteredDeprecations(props), props.currentGroupBy); + }, + + numPages(props: { + deprecations: EnrichedDeprecationInfo[]; + currentFilter: LevelFilterOption; + search: string; + currentGroupBy: GroupByOption; + }) { + return Math.ceil(Object.keys(CalcFields.groups(props)).length / DEPRECATIONS_PER_PAGE); + }, +}; + /** * Displays a list of deprecations that are filterable and groupable. Can be used for cluster, * nodes, or indices deprecations. @@ -43,8 +106,13 @@ export const DeprecationTabContent: FunctionComponent = ({ const [currentFilter, setCurrentFilter] = useState(LevelFilterOption.all); const [search, setSearch] = useState(''); const [currentGroupBy, setCurrentGroupBy] = useState(GroupByOption.message); + const [expandState, setExpandState] = useState({ + forceExpand: false, + expandNumber: 0, + }); + const [currentPage, setCurrentPage] = useState(0); - const availableGroupByOptions = () => { + const getAvailableGroupByOptions = () => { if (!deprecations) { return []; } @@ -52,45 +120,30 @@ export const DeprecationTabContent: FunctionComponent = ({ return Object.keys(GroupByOption).filter((opt) => find(deprecations, opt)) as GroupByOption[]; }; + const setExpandAll = (expandAll: boolean) => { + setExpandState({ forceExpand: expandAll, expandNumber: expandState.expandNumber + 1 }); + }; + + useEffect(() => { + if (deprecations) { + const pageCount = CalcFields.numPages({ + deprecations, + currentFilter, + search, + currentGroupBy, + }); + + if (currentPage >= pageCount) { + setCurrentPage(0); + } + } + }, [currentPage, deprecations, currentFilter, search, currentGroupBy]); + if (deprecations && deprecations.length === 0) { return ( - - - - } - body={ - <> -

- -

-

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

- - } + ); } @@ -100,28 +153,92 @@ export const DeprecationTabContent: FunctionComponent = ({ if (isLoading) { content = {i18nTexts.isLoading}; } else if (deprecations?.length) { + const levelGroups = groupBy(deprecations, 'level'); + const deprecationLevelsCount = Object.keys(levelGroups).reduce((counts, level) => { + counts[level] = levelGroups[level].length; + return counts; + }, {} as { [level: string]: number }); + + const filteredDeprecations = CalcFields.filteredDeprecations({ + deprecations, + currentFilter, + search, + }); + + const groups = CalcFields.groups({ + deprecations, + currentFilter, + search, + currentGroupBy, + }); + content = (
- - - - + + + + <> + {Object.keys(groups) + .sort() + // Apply pagination + .slice(currentPage * DEPRECATIONS_PER_PAGE, (currentPage + 1) * DEPRECATIONS_PER_PAGE) + .map((groupName, index) => [ +
+ + +
, + , + ])} + + {/* Only show pagination if we have more than DEPRECATIONS_PER_PAGE. */} + {Object.keys(groups).length > DEPRECATIONS_PER_PAGE && ( + <> + + + + + )} +
); } else if (error) { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_deprecations.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_deprecations.scss deleted file mode 100644 index 445ef6269afb9..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_deprecations.scss +++ /dev/null @@ -1,18 +0,0 @@ -.upgDeprecations { - // Pull the container through the padding of EuiPageContent - margin-left: -$euiSizeL; - margin-right: -$euiSizeL; -} - -.upgDeprecations__item { - padding: $euiSize $euiSizeL; - border-top: $euiBorderThin; - - &:last-of-type { - margin-bottom: -$euiSizeL; - } -} - -.upgDeprecations__itemName { - font-weight: $euiFontWeightMedium; -} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_index.scss index 55aff6b379db5..1f4f0352e7939 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_index.scss +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/_index.scss @@ -1,3 +1,2 @@ @import 'cell'; -@import 'deprecations'; @import 'reindex/index'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx index 5f960bd09d286..f587b1507c205 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx @@ -61,26 +61,25 @@ export const DeprecationCell: FunctionComponent = ({ )} + {items.map((item) => ( + + {item.title &&
{item.title}
} +

{item.body}

+
+ ))} + {docUrl && ( -
+ <> + + - -
+ )} - - {items.map((item) => ( -
- - {item.title &&
{item.title}
} -

{item.body}

-
-
- ))} {reindexIndexName && ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/deprecation_group_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/deprecation_group_item.tsx new file mode 100644 index 0000000000000..66e2a5d25998b --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/deprecation_group_item.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { FunctionComponent } from 'react'; +import { EuiAccordion, EuiBadge } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { EnrichedDeprecationInfo } from '../../../../../common/types'; +import { DeprecationHealth } from '../../shared'; +import { GroupByOption } from '../../types'; +import { EsDeprecationList } from './list'; +import { LEVEL_MAP } from '../../constants'; + +export interface Props { + id: string; + deprecations: EnrichedDeprecationInfo[]; + title: string; + currentGroupBy: GroupByOption; + forceExpand: boolean; + dataTestSubj: string; +} + +/** + * A single accordion item for a grouped deprecation item. + */ +export const EsDeprecationAccordion: FunctionComponent = ({ + id, + deprecations, + title, + currentGroupBy, + forceExpand, + dataTestSubj, +}) => { + const hasIndices = Boolean( + currentGroupBy === GroupByOption.message && + (deprecations as EnrichedDeprecationInfo[]).filter((d) => d.index).length + ); + const numIndices = hasIndices ? deprecations.length : null; + + return ( + + {hasIndices && ( + <> + + {numIndices}{' '} + + +   + + )} + LEVEL_MAP[d.level])} + /> + + } + > + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.test.tsx deleted file mode 100644 index 00059fe0456ce..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.test.tsx +++ /dev/null @@ -1,215 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { range } from 'lodash'; -import React from 'react'; -import { mountWithIntl, shallowWithIntl } from '@kbn/test/jest'; -import { EuiBadge, EuiPagination } from '@elastic/eui'; - -import { DeprecationInfo, EnrichedDeprecationInfo } from '../../../../../common/types'; -import { GroupByOption, LevelFilterOption } from '../../types'; -import { DeprecationAccordion, filterDeps, GroupedDeprecations } from './grouped'; - -describe('filterDeps', () => { - test('filters on levels', () => { - const fd = filterDeps(LevelFilterOption.critical); - expect(fd({ level: 'critical' } as DeprecationInfo)).toBe(true); - expect(fd({ level: 'warning' } as DeprecationInfo)).toBe(false); - }); - - test('filters on title search', () => { - const fd = filterDeps(LevelFilterOption.critical, 'wow'); - expect(fd({ level: 'critical', message: 'the wow error' } as DeprecationInfo)).toBe(true); - expect(fd({ level: 'critical', message: 'other error' } as DeprecationInfo)).toBe(false); - }); - - test('filters on index search', () => { - const fd = filterDeps(LevelFilterOption.critical, 'myIndex'); - expect( - fd({ - level: 'critical', - message: 'the wow error', - index: 'myIndex-2', - } as EnrichedDeprecationInfo) - ).toBe(true); - expect( - fd({ - level: 'critical', - message: 'other error', - index: 'notIndex', - } as EnrichedDeprecationInfo) - ).toBe(false); - }); - - test('filters on node search', () => { - const fd = filterDeps(LevelFilterOption.critical, 'myNode'); - expect( - fd({ - level: 'critical', - message: 'the wow error', - index: 'myNode-123', - } as EnrichedDeprecationInfo) - ).toBe(true); - expect( - fd({ - level: 'critical', - message: 'other error', - index: 'notNode', - } as EnrichedDeprecationInfo) - ).toBe(false); - }); -}); - -describe('GroupedDeprecations', () => { - const defaultProps = { - currentFilter: LevelFilterOption.all, - search: '', - currentGroupBy: GroupByOption.message, - allDeprecations: [ - { message: 'Cluster error 1', url: '', level: 'warning' }, - { message: 'Cluster error 2', url: '', level: 'critical' }, - ] as EnrichedDeprecationInfo[], - }; - - describe('expand + collapse all', () => { - const expectNumOpen = (wrapper: any, numExpected: number) => - expect(wrapper.find('div.euiAccordion-isOpen')).toHaveLength(numExpected); - - test('clicking opens and closes panels', () => { - const wrapper = mountWithIntl(); - expectNumOpen(wrapper, 0); - - // Test expand all - wrapper.find('button[data-test-subj="expandAll"]').simulate('click'); - expectNumOpen(wrapper, 2); - - // Test collapse all - wrapper.find('button[data-test-subj="collapseAll"]').simulate('click'); - expectNumOpen(wrapper, 0); - }); - - test('clicking overrides current state when some are open', () => { - const wrapper = mountWithIntl(); - - // Open a single deprecation - wrapper.find('button.euiAccordion__button').first().simulate('click'); - expectNumOpen(wrapper, 1); - - // Test expand all - wrapper.find('button[data-test-subj="expandAll"]').simulate('click'); - expectNumOpen(wrapper, 2); - - // Close a single deprecation - wrapper.find('button.euiAccordion__button').first().simulate('click'); - expectNumOpen(wrapper, 1); - - // Test collapse all - wrapper.find('button[data-test-subj="collapseAll"]').simulate('click'); - expectNumOpen(wrapper, 0); - }); - }); - - describe('pagination', () => { - const paginationProps = { - ...defaultProps, - allDeprecations: range(0, 40).map((i) => ({ - message: `Message ${i}`, - level: 'warning', - })) as DeprecationInfo[], - }; - - test('it only displays 25 items', () => { - const wrapper = shallowWithIntl(); - expect(wrapper.find(DeprecationAccordion)).toHaveLength(25); - }); - - test('it displays pagination', () => { - const wrapper = shallowWithIntl(); - expect(wrapper.find(EuiPagination).exists()).toBe(true); - }); - - test('shows next page on click', () => { - const wrapper = mountWithIntl(); - wrapper.find('button[data-test-subj="pagination-button-next"]').simulate('click'); - expect(wrapper.find(DeprecationAccordion)).toHaveLength(15); // 40 total - 25 first page = 15 second page - }); - }); - - describe('grouping', () => { - test('group by message', () => { - const wrapper = shallowWithIntl( - - ); - - // Only 2 groups should exist b/c there are only 2 unique messages - expect(wrapper.find(DeprecationAccordion)).toHaveLength(2); - }); - - test('group by index', () => { - const wrapper = shallowWithIntl( - - ); - - // Only 3 groups should exist b/c there are only 3 unique indexes - expect(wrapper.find(DeprecationAccordion)).toHaveLength(3); - }); - }); -}); - -describe('DeprecationAccordion', () => { - const defaultProps = { - id: 'x', - dataTestSubj: 'data-test-subj', - title: 'Issue 1', - currentGroupBy: GroupByOption.message, - forceExpand: false, - deprecations: [{ index: 'index1' }, { index: 'index2' }] as EnrichedDeprecationInfo[], - }; - - test('shows indices count badge', () => { - const wrapper = mountWithIntl(); - expect(wrapper.find(EuiBadge).find('[data-test-subj="indexCount"]').text()).toEqual('2'); - }); -}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.tsx deleted file mode 100644 index 9879b977f1cfd..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/grouped.tsx +++ /dev/null @@ -1,261 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { groupBy } from 'lodash'; -import React, { Fragment, FunctionComponent } from 'react'; - -import { - EuiAccordion, - EuiBadge, - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiPagination, - EuiSpacer, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { DeprecationInfo, EnrichedDeprecationInfo } from '../../../../../common/types'; -import { GroupByOption, LevelFilterOption } from '../../types'; - -import { DeprecationCountSummary } from './count_summary'; -import { DeprecationHealth } from './health'; -import { DeprecationList } from './list'; - -// exported only for testing -export const filterDeps = (level: LevelFilterOption, search: string = '') => { - const conditions: Array<(dep: EnrichedDeprecationInfo) => boolean> = []; - - if (level !== LevelFilterOption.all) { - conditions.push((dep: DeprecationInfo) => dep.level === level); - } - - if (search.length > 0) { - // Change everything to lower case for a case-insensitive comparison - conditions.push((dep) => { - try { - const searchReg = new RegExp(search.toLowerCase()); - return Boolean( - dep.message.toLowerCase().match(searchReg) || - (dep.details && dep.details.toLowerCase().match(searchReg)) || - (dep.index && dep.index.toLowerCase().match(searchReg)) || - (dep.node && dep.node.toLowerCase().match(searchReg)) - ); - } catch (e) { - // ignore any regexp errors. - return true; - } - }); - } - - // Return true if every condition function returns true (boolean AND) - return (dep: EnrichedDeprecationInfo) => conditions.map((c) => c(dep)).every((t) => t); -}; - -/** - * A single accordion item for a grouped deprecation item. - */ -export const DeprecationAccordion: FunctionComponent<{ - id: string; - deprecations: EnrichedDeprecationInfo[]; - title: string; - currentGroupBy: GroupByOption; - forceExpand: boolean; - dataTestSubj: string; -}> = ({ id, deprecations, title, currentGroupBy, forceExpand, dataTestSubj }) => { - const hasIndices = Boolean( - currentGroupBy === GroupByOption.message && deprecations.filter((d) => d.index).length - ); - const numIndices = hasIndices ? deprecations.length : null; - - return ( - {title}} - extraAction={ -
- {hasIndices && ( - - - {numIndices}{' '} - - -   - - )} - -
- } - > - -
- ); -}; - -interface GroupedDeprecationsProps { - currentFilter: LevelFilterOption; - search: string; - currentGroupBy: GroupByOption; - allDeprecations?: EnrichedDeprecationInfo[]; -} - -interface GroupedDeprecationsState { - forceExpand: true | false | null; - expandNumber: number; - currentPage: number; -} - -const PER_PAGE = 25; - -/** - * Collection of calculated fields based on props, extracted for reuse in - * `render` and `getDerivedStateFromProps`. - */ -const CalcFields = { - filteredDeprecations(props: GroupedDeprecationsProps) { - const { allDeprecations = [], currentFilter, search } = props; - return allDeprecations.filter(filterDeps(currentFilter, search)); - }, - - groups(props: GroupedDeprecationsProps) { - const { currentGroupBy } = props; - return groupBy(CalcFields.filteredDeprecations(props), currentGroupBy); - }, - - numPages(props: GroupedDeprecationsProps) { - return Math.ceil(Object.keys(CalcFields.groups(props)).length / PER_PAGE); - }, -}; - -/** - * Displays groups of deprecation messages in an accordion. - */ -export class GroupedDeprecations extends React.Component< - GroupedDeprecationsProps, - GroupedDeprecationsState -> { - public static getDerivedStateFromProps( - nextProps: GroupedDeprecationsProps, - { currentPage }: GroupedDeprecationsState - ) { - // If filters change and the currentPage is now bigger than the num of pages we're going to show, - // reset the current page to 0. - if (currentPage >= CalcFields.numPages(nextProps)) { - return { currentPage: 0 }; - } else { - return null; - } - } - - public state = { - forceExpand: false, - // `expandNumber` is used as workaround to force EuiAccordion to re-render by - // incrementing this number (used as a key) when expand all or collapse all is clicked. - expandNumber: 0, - currentPage: 0, - }; - - public render() { - const { currentGroupBy, allDeprecations = [] } = this.props; - const { forceExpand, expandNumber, currentPage } = this.state; - - const filteredDeprecations = CalcFields.filteredDeprecations(this.props); - const groups = CalcFields.groups(this.props); - - return ( - - - - this.setExpand(true)} - data-test-subj="expandAll" - > - - - - - this.setExpand(false)} - data-test-subj="collapseAll" - > - - - - - - - - - - - -
- {Object.keys(groups) - .sort() - // Apply pagination - .slice(currentPage * PER_PAGE, (currentPage + 1) * PER_PAGE) - .map((groupName) => [ - , - ])} - - {/* Only show pagination if we have more than PER_PAGE. */} - {Object.keys(groups).length > PER_PAGE && ( - - - - - - - - - - )} -
-
- ); - } - - private setExpand = (forceExpand: boolean) => { - this.setState({ forceExpand, expandNumber: this.state.expandNumber + 1 }); - }; - - private setPage = (currentPage: number) => this.setState({ currentPage }); -} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.tsx index 65b878fe36a86..cb9f238d0e4dd 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.tsx @@ -10,7 +10,7 @@ import React, { FunctionComponent } from 'react'; import { DeprecationInfo, EnrichedDeprecationInfo } from '../../../../../common/types'; import { GroupByOption } from '../../types'; -import { COLOR_MAP, LEVEL_MAP } from '../constants'; +import { COLOR_MAP, LEVEL_MAP } from '../../constants'; import { DeprecationCell } from './cell'; import { IndexDeprecationDetails, IndexDeprecationTable } from './index_table'; @@ -85,7 +85,7 @@ const IndexDeprecation: FunctionComponent = ({ deprecatio * A list of deprecations that is either shown as individual deprecation cells or as a * deprecation summary for a list of indices. */ -export const DeprecationList: FunctionComponent<{ +export const EsDeprecationList: FunctionComponent<{ deprecations: EnrichedDeprecationInfo[]; currentGroupBy: GroupByOption; }> = ({ deprecations, currentGroupBy }) => { @@ -105,16 +105,16 @@ export const DeprecationList: FunctionComponent<{ } else if (currentGroupBy === GroupByOption.index) { return (
- {deprecations.sort(sortByLevelDesc).map((dep) => ( - + {deprecations.sort(sortByLevelDesc).map((dep, index) => ( + ))}
); } else { return (
- {deprecations.sort(sortByLevelDesc).map((dep) => ( - + {deprecations.sort(sortByLevelDesc).map((dep, index) => ( + ))}
); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx new file mode 100644 index 0000000000000..ebccd11857438 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { FunctionComponent } from 'react'; +import { + EuiAccordion, + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiText, + EuiCallOut, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { DomainDeprecationDetails } from 'src/core/server/types'; +import { DeprecationHealth } from '../shared'; +import { LEVEL_MAP } from '../constants'; +import { FlyoutContent } from './steps_flyout'; + +const i18nTexts = { + getDeprecationTitle: (domainId: string) => { + return i18n.translate('xpack.upgradeAssistant.deprecationGroupItemTitle', { + defaultMessage: `"${domainId}" is using a deprecated feature`, + }); + }, + docLinkText: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.docLinkText', { + defaultMessage: 'Documentation', + }), + fixButtonLabel: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel', { + defaultMessage: 'Fix', + }), +}; + +export interface Props { + deprecation: DomainDeprecationDetails; + index: number; + forceExpand: boolean; + showFlyout: (flyoutContent: FlyoutContent) => void; +} + +/** + * A single accordion item for a grouped deprecation item. + */ +export const KibanaDeprecationAccordion: FunctionComponent = ({ + deprecation, + forceExpand, + index, + showFlyout, +}) => { + const { domainId, level, message, documentationUrl, correctiveActions } = deprecation; + + return ( + } + > + + + + {level === 'fetch_error' ? ( + + ) : ( + <> +

{message}

+ {documentationUrl && ( +

+ + {i18nTexts.docLinkText} + +

+ )} + + )} +
+
+ + {correctiveActions?.manualSteps && ( + + showFlyout({ domainId, steps: correctiveActions.manualSteps! })} + > + {i18nTexts.fixButtonLabel} + + + )} +
+
+ ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx new file mode 100644 index 0000000000000..df9940801edbf --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useState, useEffect } from 'react'; +import { groupBy } from 'lodash'; +import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { DomainDeprecationDetails } from 'src/core/server/types'; + +import { LevelFilterOption } from '../types'; +import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; +import { LEVEL_MAP, DEPRECATIONS_PER_PAGE } from '../constants'; +import { KibanaDeprecationAccordion } from './deprecation_item'; +import { FlyoutContent } from './steps_flyout'; +import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; + +interface Props { + deprecations: DomainDeprecationDetails[]; + showFlyout: (newFlyoutContent: FlyoutContent) => void; + reloadDeprecations: () => Promise; + isLoading: boolean; +} + +const getFilteredDeprecations = ( + deprecations: DomainDeprecationDetails[], + level: string, + search: string +) => { + return deprecations + .filter((deprecation) => { + return level === 'all' ? true : deprecation.level === level; + }) + .filter((filteredDep) => { + if (search.length > 0) { + try { + const searchReg = new RegExp(search.toLowerCase()); + return Boolean(filteredDep.message.toLowerCase().match(searchReg)); + } catch (e) { + // ignore any regexp errors + return true; + } + } + return true; + }); +}; + +const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetails) => { + return -1 * (LEVEL_MAP[a.level] - LEVEL_MAP[b.level]); +}; + +export const KibanaDeprecationList: FunctionComponent = ({ + deprecations, + showFlyout, + reloadDeprecations, + isLoading, +}) => { + const [currentFilter, setCurrentFilter] = useState(LevelFilterOption.all); + const [search, setSearch] = useState(''); + const [expandState, setExpandState] = useState({ + forceExpand: false, + expandNumber: 0, + }); + const [currentPage, setCurrentPage] = useState(0); + + const changeFilter = (filter: LevelFilterOption) => { + setCurrentFilter(filter); + }; + + const changeSearch = (newSearch: string) => { + setSearch(newSearch); + }; + + const setExpandAll = (expandAll: boolean) => { + setExpandState({ forceExpand: expandAll, expandNumber: expandState.expandNumber + 1 }); + }; + + const levelGroups = groupBy(deprecations, 'level'); + const deprecationLevelsCount = Object.keys(levelGroups).reduce((counts, level) => { + counts[level] = levelGroups[level].length; + return counts; + }, {} as { [level: string]: number }); + + const filteredDeprecations = getFilteredDeprecations(deprecations, currentFilter, search); + + const deprecationsWithErrors = deprecations.filter((dep) => dep.level === 'fetch_error'); + + useEffect(() => { + const pageCount = Math.ceil(filteredDeprecations.length / DEPRECATIONS_PER_PAGE); + if (currentPage >= pageCount) { + setCurrentPage(0); + } + }, [filteredDeprecations, currentPage]); + + return ( + <> + + + {deprecationsWithErrors.length > 0 && ( + <> + + + + )} + + + + + + <> + {filteredDeprecations + .slice(currentPage * DEPRECATIONS_PER_PAGE, (currentPage + 1) * DEPRECATIONS_PER_PAGE) + .sort(sortByLevelDesc) + .map((deprecation, index) => [ +
+ + +
, + ])} + + {/* Only show pagination if we have more than DEPRECATIONS_PER_PAGE */} + {filteredDeprecations.length > DEPRECATIONS_PER_PAGE && ( + <> + + + + + )} + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts new file mode 100644 index 0000000000000..84d2b88757188 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { KibanaDeprecationsContent } from './kibana_deprecations'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx new file mode 100644 index 0000000000000..480c3ed92b4eb --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiCallOut } from '@elastic/eui'; + +interface Props { + errorType: 'pluginError' | 'requestError'; +} + +const i18nTexts = { + pluginError: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationErrors.pluginErrorMessage', { + defaultMessage: + 'Not all Kibana deprecations were retrieved successfully. This list may be incomplete.', + }), + loadingError: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorMessage', + { + defaultMessage: 'An error occurred while retrieving Kibana deprecations.', + } + ), +}; + +export const KibanaDeprecationErrors: React.FunctionComponent = ({ errorType }) => { + if (errorType === 'pluginError') { + return ( + + ); + } + + return ( + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx new file mode 100644 index 0000000000000..d88b5e1427a86 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState, useCallback } from 'react'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; + +import { + EuiButtonEmpty, + EuiPageBody, + EuiPageHeader, + EuiPageContent, + EuiPageContentBody, + EuiSpacer, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { DomainDeprecationDetails } from 'src/core/server/types'; + +import { SectionLoading } from '../../../shared_imports'; +import { useAppContext } from '../../app_context'; +import { NoDeprecationsPrompt } from '../shared'; +import { KibanaDeprecationList } from './deprecation_list'; +import { StepsFlyout, FlyoutContent } from './steps_flyout'; +import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; + +const i18nTexts = { + pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { + defaultMessage: 'Kibana', + }), + pageDescription: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageDescription', { + defaultMessage: 'Some Kibana issues may require your attention. Resolve them before upgrading.', + }), + docLinkText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.docLinkText', { + defaultMessage: 'Documentation', + }), + deprecationLabel: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.deprecationLabel', { + defaultMessage: 'Kibana', + }), + isLoading: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.loadingText', { + defaultMessage: 'Loading deprecations…', + }), +}; + +export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponentProps) => { + const [kibanaDeprecations, setKibanaDeprecations] = useState< + DomainDeprecationDetails[] | undefined + >(undefined); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(undefined); + const [flyoutContent, setFlyoutContent] = useState(undefined); + + const { deprecations, breadcrumbs, docLinks, api } = useAppContext(); + + const getAllDeprecations = useCallback(async () => { + setIsLoading(true); + + try { + const response = await deprecations.getAllDeprecations(); + setKibanaDeprecations(response); + } catch (e) { + setError(e); + } + + setIsLoading(false); + }, [deprecations]); + + const toggleFlyout = (newFlyoutContent?: FlyoutContent) => { + if (typeof newFlyoutContent === 'undefined') { + setFlyoutContent(undefined); + } + + setFlyoutContent(newFlyoutContent); + }; + + useEffect(() => { + async function sendTelemetryData() { + await api.sendTelemetryData({ + kibana: true, + }); + } + + sendTelemetryData(); + }, [api]); + + useEffect(() => { + breadcrumbs.setBreadcrumbs('kibanaDeprecations'); + }, [breadcrumbs]); + + useEffect(() => { + getAllDeprecations(); + }, [deprecations, getAllDeprecations]); + + const getPageContent = () => { + if (kibanaDeprecations && kibanaDeprecations.length === 0) { + return ( + history.push('/overview')} + /> + ); + } + + let content: React.ReactNode; + + if (isLoading) { + content = {i18nTexts.isLoading}; + } else if (kibanaDeprecations?.length) { + content = ( + + ); + } else if (error) { + content = ; + } + return ( +
+ + {content} +
+ ); + }; + + return ( + + + + {i18nTexts.docLinkText} + , + ]} + /> + + + {getPageContent()} + {flyoutContent && ( + toggleFlyout()} flyoutContent={flyoutContent} /> + )} + + + + ); +}); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx new file mode 100644 index 0000000000000..3867a1d6013b4 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { + EuiFlyout, + EuiFlyoutHeader, + EuiFlyoutBody, + EuiTitle, + EuiText, + EuiSteps, + EuiSpacer, +} from '@elastic/eui'; + +export interface FlyoutContent { + domainId: string; + steps: string[]; +} + +interface Props { + closeFlyout: () => void; + flyoutContent: FlyoutContent; +} + +const i18nTexts = { + getFlyoutTitle: (domainId: string) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsFlyout.flyoutTitle', { + defaultMessage: `Fix '${domainId}' deprecation`, + values: { + domainId, + }, + }), + getStepTitle: (step: number) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsFlyout.stepTitle', { + defaultMessage: 'Step {step}', + values: { + step, + }, + }), + flyoutDescription: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.stepsFlyout.flyoutDescription', + { + defaultMessage: 'Follow the steps below to address this deprecation.', + } + ), +}; + +export const StepsFlyout: FunctionComponent = ({ closeFlyout, flyoutContent }) => { + const { domainId, steps } = flyoutContent; + + return ( + + + +

{i18nTexts.getFlyoutTitle(domainId)}

+
+
+ + <> + +

{i18nTexts.flyoutDescription}

+
+ + + + { + return { + title: i18nTexts.getStepTitle(index + 1), + children: ( + +

{step}

+
+ ), + }; + })} + /> + +
+
+ ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx new file mode 100644 index 0000000000000..658c84d016faa --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useEffect, useState } from 'react'; + +import { + EuiLink, + EuiPanel, + EuiStat, + EuiTitle, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { RouteComponentProps } from 'react-router-dom'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { DomainDeprecationDetails } from 'src/core/server/types'; +import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; +import { useAppContext } from '../../app_context'; + +const i18nTexts = { + statsTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.statsTitle', { + defaultMessage: 'Kibana', + }), + totalDeprecationsTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationStats.totalDeprecationsTitle', + { + defaultMessage: 'Deprecations', + } + ), + criticalDeprecationsTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsTitle', + { + defaultMessage: 'Critical', + } + ), +}; + +interface Props { + history: RouteComponentProps['history']; +} + +export const KibanaDeprecationStats: FunctionComponent = ({ history }) => { + const { deprecations } = useAppContext(); + + const [kibanaDeprecations, setKibanaDeprecations] = useState< + DomainDeprecationDetails[] | undefined + >(undefined); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(undefined); + + useEffect(() => { + async function getAllDeprecations() { + setIsLoading(true); + + try { + const response = await deprecations.getAllDeprecations(); + setKibanaDeprecations(response); + } catch (e) { + setError(e); + } + + setIsLoading(false); + } + + getAllDeprecations(); + }, [deprecations]); + + return ( + + +

+ + {i18nTexts.statsTitle} + +

+
+ + + + + + + + + + deprecation.level === 'critical') + ?.length ?? '0' + : '--' + } + description={i18nTexts.criticalDeprecationsTitle} + titleColor="danger" + isLoading={isLoading} + > + {/* {error && } */} + + + +
+ ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 0784fbc102805..0a91a24cd9798 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -27,6 +27,7 @@ import { RouteComponentProps } from 'react-router-dom'; import { useAppContext } from '../../app_context'; import { LatestMinorBanner } from '../latest_minor_banner'; import { ESDeprecationStats } from './es_stats'; +import { KibanaDeprecationStats } from './kibana_stats'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; const i18nTexts = { @@ -114,7 +115,7 @@ export const DeprecationsOverview: FunctionComponent = ({ history }) => { - + @@ -128,6 +129,10 @@ export const DeprecationsOverview: FunctionComponent = ({ history }) => { + + + + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/count_summary.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx similarity index 68% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/count_summary.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx index db176ba43d8ed..709ef7224870e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/count_summary.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/count_summary.tsx @@ -5,23 +5,21 @@ * 2.0. */ -import React, { Fragment, FunctionComponent } from 'react'; +import React, { FunctionComponent } from 'react'; import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EnrichedDeprecationInfo } from '../../../../../common/types'; - export const DeprecationCountSummary: FunctionComponent<{ - deprecations: EnrichedDeprecationInfo[]; - allDeprecations: EnrichedDeprecationInfo[]; -}> = ({ deprecations, allDeprecations }) => ( + allDeprecationsCount: number; + filteredDeprecationsCount: number; +}> = ({ filteredDeprecationsCount, allDeprecationsCount }) => ( - {allDeprecations.length ? ( + {allDeprecationsCount > 0 ? ( ) : ( )} - {deprecations.length !== allDeprecations.length && ( - + {filteredDeprecationsCount !== allDeprecationsCount && ( + <> {'. '} - + )} ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.tsx new file mode 100644 index 0000000000000..6cb5ae3675c44 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/deprecation_list_bar.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { DeprecationCountSummary } from './count_summary'; + +const i18nTexts = { + expandAllButton: i18n.translate( + 'xpack.upgradeAssistant.deprecationListBar.expandAllButtonLabel', + { + defaultMessage: 'Expand all', + } + ), + collapseAllButton: i18n.translate( + 'xpack.upgradeAssistant.deprecationListBar.collapseAllButtonLabel', + { + defaultMessage: 'Collapse all', + } + ), +}; + +export const DeprecationListBar: FunctionComponent<{ + allDeprecationsCount: number; + filteredDeprecationsCount: number; + setExpandAll: (shouldExpandAll: boolean) => void; +}> = ({ allDeprecationsCount, filteredDeprecationsCount, setExpandAll }) => { + return ( + + + + + + + + + setExpandAll(true)} + data-test-subj="expandAll" + > + {i18nTexts.expandAllButton} + + + + setExpandAll(false)} + data-test-subj="collapseAll" + > + {i18nTexts.collapseAllButton} + + + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts new file mode 100644 index 0000000000000..cbc04fd86bfbd --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_list_bar/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { DeprecationListBar } from './deprecation_list_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx new file mode 100644 index 0000000000000..ae2c0ba1c4877 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/deprecation_pagination.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; + +import { EuiFlexGroup, EuiFlexItem, EuiPagination } from '@elastic/eui'; + +export const DeprecationPagination: FunctionComponent<{ + pageCount: number; + activePage: number; + setPage: (page: number) => void; +}> = ({ pageCount, activePage, setPage }) => { + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/health.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx similarity index 86% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/health.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx index c489824b1059d..362b2af684e27 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/health.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/health.tsx @@ -11,8 +11,8 @@ import React, { FunctionComponent } from 'react'; import { EuiBadge, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DeprecationInfo } from '../../../../../common/types'; -import { COLOR_MAP, LEVEL_MAP, REVERSE_LEVEL_MAP } from '../constants'; +import { DeprecationInfo } from '../../../../common/types'; +import { COLOR_MAP, REVERSE_LEVEL_MAP } from '../constants'; const LocalizedLevels: { [level: string]: string } = { warning: i18n.translate('xpack.upgradeAssistant.checkupTab.deprecations.warningLabel', { @@ -33,7 +33,7 @@ export const LocalizedActions: { [level: string]: string } = { }; interface DeprecationHealthProps { - deprecations: DeprecationInfo[]; + deprecationLevels: number[]; single?: boolean; } @@ -54,23 +54,21 @@ const SingleHealth: FunctionComponent<{ level: DeprecationInfo['level']; label: * deprecations in the list. */ export const DeprecationHealth: FunctionComponent = ({ - deprecations, + deprecationLevels, single = false, }) => { - if (deprecations.length === 0) { + if (deprecationLevels.length === 0) { return ; } - const levels = deprecations.map((d) => LEVEL_MAP[d.level]); - if (single) { - const highest = Math.max(...levels); + const highest = Math.max(...deprecationLevels); const highestLevel = REVERSE_LEVEL_MAP[highest]; return ; } - const countByLevel = countBy(levels); + const countByLevel = countBy(deprecationLevels); return ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts new file mode 100644 index 0000000000000..c79d8247a93f1 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { NoDeprecationsPrompt } from './no_deprecations'; +export { DeprecationHealth } from './health'; +export { SearchBar } from './search_bar'; +export { DeprecationPagination } from './deprecation_pagination'; +export { DeprecationListBar } from './deprecation_list_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx new file mode 100644 index 0000000000000..2d2f1e5fe93cf --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; + +import { EuiLink, EuiEmptyPrompt } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +const i18nTexts = { + emptyPromptTitle: i18n.translate('xpack.upgradeAssistant.noDeprecationsPrompt.title', { + defaultMessage: 'All clear!', + }), + getEmptyPromptDescription: (deprecationType: string) => + i18n.translate('xpack.upgradeAssistant.noDeprecationsPrompt.description', { + defaultMessage: 'You have no {deprecationType} issues.', + values: { + deprecationType, + }, + }), + getEmptyPromptNextStepsDescription: (navigateToOverviewPage: () => void) => ( + + {i18n.translate('xpack.upgradeAssistant.noDeprecationsPrompt.overviewLinkText', { + defaultMessage: 'Overview page', + })} + + ), + }} + /> + ), +}; + +interface Props { + deprecationType: string; + navigateToOverviewPage: () => void; +} + +export const NoDeprecationsPrompt: FunctionComponent = ({ + deprecationType, + navigateToOverviewPage, +}) => { + return ( + {i18nTexts.emptyPromptTitle}} + body={ + <> +

+ {i18nTexts.getEmptyPromptDescription(deprecationType)} +

+

{i18nTexts.getEmptyPromptNextStepsDescription(navigateToOverviewPage)}

+ + } + /> + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/filter_bar.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap similarity index 85% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/filter_bar.test.tsx.snap rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap index b88886b364165..9712a647744da 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/__snapshots__/filter_bar.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FilterBar renders 1`] = ` +exports[`DeprecationLevelFilter renders 1`] = ` @@ -9,7 +9,7 @@ exports[`FilterBar renders 1`] = ` data-test-subj="criticalLevelFilter" hasActiveFilters={false} key="critical" - numFilters={2} + numFilters={1} onClick={[Function]} withNext={true} > @@ -19,6 +19,7 @@ exports[`FilterBar renders 1`] = ` data-test-subj="warningLevelFilter" hasActiveFilters={false} key="warning" + numFilters={4} onClick={[Function]} > warning diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/group_by_bar.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx similarity index 75% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/group_by_bar.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx index 53f76d6d0f981..fa863e4935c09 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/group_by_bar.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.test.tsx @@ -8,8 +8,8 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; -import { GroupByOption } from '../types'; -import { GroupByBar } from './group_by_bar'; +import { GroupByOption } from '../../types'; +import { GroupByFilter } from './group_by_filter'; const defaultProps = { availableGroupByOptions: [GroupByOption.message, GroupByOption.index], @@ -17,13 +17,13 @@ const defaultProps = { onGroupByChange: jest.fn(), }; -describe('GroupByBar', () => { +describe('GroupByFilter', () => { test('renders', () => { - expect(shallow()).toMatchSnapshot(); + expect(shallow()).toMatchSnapshot(); }); test('clicking button calls onGroupByChange', () => { - const wrapper = mount(); + const wrapper = mount(); wrapper.find('button.euiFilterButton-hasActiveFilters').simulate('click'); expect(defaultProps.onGroupByChange).toHaveBeenCalledTimes(1); expect(defaultProps.onGroupByChange.mock.calls[0][0]).toEqual(GroupByOption.message); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/group_by_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx similarity index 90% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/group_by_bar.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx index a80fe664ced2e..d6a3cab9ba160 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/group_by_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/group_by_filter.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { GroupByOption } from '../types'; +import { GroupByOption } from '../../types'; const LocalizedOptions: { [option: string]: string } = { message: i18n.translate('xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel', { @@ -21,13 +21,13 @@ const LocalizedOptions: { [option: string]: string } = { }), }; -interface GroupByBarProps { +interface GroupByFilterProps { availableGroupByOptions: GroupByOption[]; currentGroupBy: GroupByOption; onGroupByChange: (groupBy: GroupByOption) => void; } -export const GroupByBar: React.FunctionComponent = ({ +export const GroupByFilter: React.FunctionComponent = ({ availableGroupByOptions, currentGroupBy, onGroupByChange, diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts new file mode 100644 index 0000000000000..31ad78cf572fe --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { SearchBar } from './search_bar'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/filter_bar.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx similarity index 63% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/filter_bar.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx index 4888efda97bd0..f64b099993899 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/filter_bar.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx @@ -7,27 +7,26 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; -import { DeprecationInfo } from '../../../../common/types'; -import { LevelFilterOption } from '../types'; -import { FilterBar } from './filter_bar'; +import { LevelFilterOption } from '../../types'; +import { DeprecationLevelFilter } from './level_filter'; const defaultProps = { - allDeprecations: [ - { level: LevelFilterOption.critical }, - { level: LevelFilterOption.critical }, - ] as DeprecationInfo[], + levelsCount: { + warning: 4, + critical: 1, + }, currentFilter: LevelFilterOption.all, onFilterChange: jest.fn(), }; -describe('FilterBar', () => { +describe('DeprecationLevelFilter', () => { test('renders', () => { - expect(shallow()).toMatchSnapshot(); + expect(shallow()).toMatchSnapshot(); }); test('clicking button calls onFilterChange', () => { - const wrapper = mount(); + const wrapper = mount(); wrapper.find('button[data-test-subj="criticalLevelFilter"]').simulate('click'); expect(defaultProps.onFilterChange).toHaveBeenCalledTimes(1); expect(defaultProps.onFilterChange.mock.calls[0][0]).toEqual(LevelFilterOption.critical); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/filter_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx similarity index 75% rename from x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/filter_bar.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx index 848ac3b14a817..7c814f320c879 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/filter_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx @@ -5,14 +5,12 @@ * 2.0. */ -import { groupBy } from 'lodash'; import React from 'react'; import { EuiFilterButton, EuiFilterGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DeprecationInfo } from '../../../../common/types'; -import { LevelFilterOption } from '../types'; +import { LevelFilterOption } from '../../types'; const LocalizedOptions: { [option: string]: string } = { warning: i18n.translate( @@ -26,24 +24,19 @@ const LocalizedOptions: { [option: string]: string } = { { defaultMessage: 'critical' } ), }; - -interface FilterBarProps { - allDeprecations?: DeprecationInfo[]; +interface DeprecationLevelProps { + levelsCount: { + [key: string]: number; + }; currentFilter: LevelFilterOption; onFilterChange(level: LevelFilterOption): void; } -export const FilterBar: React.FunctionComponent = ({ - allDeprecations = [], +export const DeprecationLevelFilter: React.FunctionComponent = ({ + levelsCount, currentFilter, onFilterChange, }) => { - const levelGroups = groupBy(allDeprecations, 'level'); - const levelCounts = Object.keys(levelGroups).reduce((counts, level) => { - counts[level] = levelGroups[level].length; - return counts; - }, {} as { [level: string]: number }); - return ( @@ -58,7 +51,7 @@ export const FilterBar: React.FunctionComponent = ({ ); }} hasActiveFilters={currentFilter === LevelFilterOption.critical} - numFilters={levelCounts[LevelFilterOption.critical] || undefined} + numFilters={levelsCount[LevelFilterOption.critical] || undefined} data-test-subj="criticalLevelFilter" > {LocalizedOptions[LevelFilterOption.critical]} @@ -73,7 +66,7 @@ export const FilterBar: React.FunctionComponent = ({ ); }} hasActiveFilters={currentFilter === LevelFilterOption.warning} - numFilters={levelCounts[LevelFilterOption.warning] || undefined} + numFilters={levelsCount[LevelFilterOption.warning] || undefined} data-test-subj="warningLevelFilter" > {LocalizedOptions[LevelFilterOption.warning]} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx new file mode 100644 index 0000000000000..ee77fd6a1bc5d --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiButtonEmpty, + EuiFieldSearch, + EuiFlexGroup, + EuiFlexItem, + EuiCallOut, + EuiSpacer, + EuiHorizontalRule, +} from '@elastic/eui'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { DomainDeprecationDetails } from 'src/core/server/types'; +import { DeprecationInfo } from '../../../../../common/types'; +import { validateRegExpString } from '../../../lib/utils'; +import { GroupByOption, LevelFilterOption } from '../../types'; +import { DeprecationLevelFilter } from './level_filter'; +import { GroupByFilter } from './group_by_filter'; + +interface SearchBarProps { + allDeprecations?: DeprecationInfo[] | DomainDeprecationDetails; + isLoading: boolean; + loadData: () => void; + currentFilter: LevelFilterOption; + onFilterChange: (filter: LevelFilterOption) => void; + onSearchChange: (filter: string) => void; + totalDeprecationsCount: number; + deprecationLevelsCount: { + [key: string]: number; + }; + groupByFilterProps?: { + availableGroupByOptions: GroupByOption[]; + currentGroupBy: GroupByOption; + onGroupByChange: (groupBy: GroupByOption) => void; + }; +} + +const i18nTexts = { + searchAriaLabel: i18n.translate( + 'xpack.upgradeAssistant.deprecationListSearchBar.placeholderAriaLabel', + { defaultMessage: 'Filter' } + ), + searchPlaceholderLabel: i18n.translate( + 'xpack.upgradeAssistant.deprecationListSearchBar.placeholderLabel', + { + defaultMessage: 'Filter', + } + ), + reloadButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.deprecationListSearchBar.reloadButtonLabel', + { + defaultMessage: 'Reload', + } + ), + getInvalidSearchMessage: (searchTermError: string) => + i18n.translate('xpack.upgradeAssistant.deprecationListSearchBar.filterErrorMessageLabel', { + defaultMessage: 'Filter invalid: {searchTermError}', + values: { searchTermError }, + }), +}; + +export const SearchBar: FunctionComponent = ({ + totalDeprecationsCount, + deprecationLevelsCount, + isLoading, + loadData, + currentFilter, + onFilterChange, + onSearchChange, + groupByFilterProps, +}) => { + const [searchTermError, setSearchTermError] = useState(null); + const filterInvalid = Boolean(searchTermError); + return ( + <> + + + + + { + const string = e.target.value; + const errorMessage = validateRegExpString(string); + if (errorMessage) { + // Emit an empty search term to listeners if search term is invalid. + onSearchChange(''); + setSearchTermError(errorMessage); + } else { + onSearchChange(e.target.value); + if (searchTermError) { + setSearchTermError(null); + } + } + }} + /> + + + {/* These two components provide their own EuiFlexItem wrappers */} + + {groupByFilterProps && } + + + + + {i18nTexts.reloadButtonLabel} + + + + + {filterInvalid && ( + <> + + + + + )} + + + + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts index 3f2ee4fa33657..00359988d5e2a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts @@ -18,6 +18,12 @@ const i18nTexts = { esDeprecations: i18n.translate('xpack.upgradeAssistant.breadcrumb.esDeprecationsLabel', { defaultMessage: 'Elasticsearch deprecations', }), + kibanaDeprecations: i18n.translate( + 'xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel', + { + defaultMessage: 'Kibana deprecations', + } + ), }, }; @@ -42,6 +48,15 @@ export class BreadcrumbService { text: i18nTexts.breadcrumbs.esDeprecations, }, ], + kibanaDeprecations: [ + { + text: i18nTexts.breadcrumbs.overview, + href: '/', + }, + { + text: i18nTexts.breadcrumbs.kibanaDeprecations, + }, + ], }; private setBreadcrumbsHandler?: SetBreadcrumbs; @@ -50,7 +65,7 @@ export class BreadcrumbService { this.setBreadcrumbsHandler = setBreadcrumbsHandler; } - public setBreadcrumbs(type: 'overview' | 'esDeprecations'): void { + public setBreadcrumbs(type: 'overview' | 'esDeprecations' | 'kibanaDeprecations'): void { if (!this.setBreadcrumbsHandler) { throw new Error('Breadcrumb service has not been initialized'); } diff --git a/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.ts b/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.ts index 575c85bb33ec0..b17c1301f83f3 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/mount_management_section.ts @@ -19,7 +19,10 @@ export async function mountManagementSection( params: ManagementAppMountParams, kibanaVersionInfo: KibanaVersionContext ) { - const [{ i18n, docLinks, notifications, application }] = await coreSetup.getStartServices(); + const [ + { i18n, docLinks, notifications, application, deprecations }, + ] = await coreSetup.getStartServices(); + const { element, history, setBreadcrumbs } = params; const { http } = coreSetup; @@ -39,5 +42,6 @@ export async function mountManagementSection( api: apiService, breadcrumbs: breadcrumbService, getUrlForApp: application.getUrlForApp, + deprecations, }); } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts index e775190d426df..35a70fb8740ab 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts @@ -40,9 +40,106 @@ export async function getUpgradeAssistantStatus( const criticalWarnings = cluster.concat(indices).filter((d) => d.level === 'critical'); return { - readyForUpgrade: criticalWarnings.length === 0, - cluster, - indices, + readyForUpgrade: false, + cluster: [ + { + level: 'critical', + message: 'Index Lifecycle Management poll interval is set too low', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#ilm-poll-interval-limit', + details: + 'The Index Lifecycle Management poll interval setting [indices.lifecycle.poll_interval] is currently set to [500ms], but must be 1s or greater', + }, + { + level: 'warning', + message: 'Index templates contain _field_names settings.', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#fieldnames-enabling', + details: + 'Index templates [field_names_enabled] use the deprecated `enable` setting for the `_field_names` field. Using this setting in new index mappings will throw an error in the next major version and needs to be removed from existing mappings and templates.', + }, + ], + indices: [ + { + level: 'warning', + message: 'translog retention settings are ignored', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', + details: + 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', + index: 'deprecated_settings', + reindex: false, + }, + { + level: 'warning', + message: 'translog retention settings are ignored', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', + details: + 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', + index: 'settings', + reindex: false, + }, + { + level: 'warning', + message: 'Multi-fields within multi-fields', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#_defining_multi_fields_within_multi_fields', + details: + 'The names of fields that contain chained multi-fields: [[type: _doc, field: text]]', + index: 'nested_multi_fields', + reindex: false, + }, + { + level: 'critical', + message: 'Index created before 7.0', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html', + details: 'This index was created using version: 6.8.13', + index: 'test2', + reindex: true, + }, + { + level: 'warning', + message: 'Multi-fields within multi-fields', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#_defining_multi_fields_within_multi_fields', + details: + 'The names of fields that contain chained multi-fields: [[type: _doc, field: test]]', + index: 'foo', + reindex: false, + }, + { + level: 'warning', + message: 'Index mapping contains explicit `_field_names` enabling settings.', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#fieldnames-enabling', + details: + 'The index mapping contains a deprecated `enabled` setting for `_field_names` that should be removed moving foward.', + index: 'field_names_enabled', + reindex: false, + }, + { + level: 'warning', + message: 'Index mapping contains explicit `_field_names` enabling settings.', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#fieldnames-enabling', + details: + 'The index mapping contains a deprecated `enabled` setting for `_field_names` that should be removed moving foward.', + index: 'tweets', + reindex: false, + }, + { + level: 'warning', + message: 'translog retention settings are ignored', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', + details: + 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', + index: 'translog_settings', + reindex: false, + }, + ], }; } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts index 19f4641b2136d..ab876828a343c 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts @@ -36,6 +36,7 @@ export async function upsertUIOpenOption({ cluster, indices, savedObjects, + kibana, }: UpsertUIOpenOptionDependencies): Promise { if (overview) { await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'overview' }); @@ -49,9 +50,14 @@ export async function upsertUIOpenOption({ await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'indices' }); } + if (kibana) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'kibana' }); + } + return { overview, cluster, indices, + kibana, }; } diff --git a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts index 040e54bb9f06a..4e9b4b9a472a9 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts @@ -20,17 +20,19 @@ export function registerTelemetryRoutes({ router, getSavedObjectsService }: Rout overview: schema.boolean({ defaultValue: false }), cluster: schema.boolean({ defaultValue: false }), indices: schema.boolean({ defaultValue: false }), + kibana: schema.boolean({ defaultValue: false }), }), }, }, async (ctx, request, response) => { - const { cluster, indices, overview } = request.body; + const { cluster, indices, overview, kibana } = request.body; return response.ok({ body: await upsertUIOpenOption({ savedObjects: getSavedObjectsService(), cluster, indices, overview, + kibana, }), }); } diff --git a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts index 4bb690b318242..f76c07da678da 100644 --- a/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts +++ b/x-pack/plugins/upgrade_assistant/server/saved_object_types/telemetry_saved_object_type.ts @@ -29,6 +29,10 @@ export const telemetrySavedObjectType: SavedObjectsType = { type: 'long', null_value: 0, }, + kibana: { + type: 'long', + null_value: 0, + }, }, }, ui_reindex: { From 16ba626ec841b1cdb0435c1ede61749e5a3dce12 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 14 Apr 2021 13:16:15 -0400 Subject: [PATCH 02/18] design fixes --- .../kibana_deprecations/deprecation_item.tsx | 8 +- .../kibana_deprecations/deprecation_list.tsx | 8 +- .../kibana_deprecations.tsx | 18 +-- .../kibana_deprecations/steps_flyout.tsx | 89 -------------- .../kibana_deprecations/steps_modal.tsx | 115 ++++++++++++++++++ .../components/overview/kibana_stats.tsx | 23 +++- .../components/overview/overview.tsx | 22 ++-- .../shared/search_bar/search_bar.tsx | 10 +- 8 files changed, 165 insertions(+), 128 deletions(-) delete mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx index ebccd11857438..1736040c20cd7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { DomainDeprecationDetails } from 'src/core/server/types'; import { DeprecationHealth } from '../shared'; import { LEVEL_MAP } from '../constants'; -import { FlyoutContent } from './steps_flyout'; +import { ModalContent } from './steps_modal'; const i18nTexts = { getDeprecationTitle: (domainId: string) => { @@ -40,7 +40,7 @@ export interface Props { deprecation: DomainDeprecationDetails; index: number; forceExpand: boolean; - showFlyout: (flyoutContent: FlyoutContent) => void; + showModal: (modalContent: ModalContent) => void; } /** @@ -50,7 +50,7 @@ export const KibanaDeprecationAccordion: FunctionComponent = ({ deprecation, forceExpand, index, - showFlyout, + showModal, }) => { const { domainId, level, message, documentationUrl, correctiveActions } = deprecation; @@ -93,7 +93,7 @@ export const KibanaDeprecationAccordion: FunctionComponent = ({ showFlyout({ domainId, steps: correctiveActions.manualSteps! })} + onClick={() => showModal({ domainId, steps: correctiveActions.manualSteps! })} > {i18nTexts.fixButtonLabel} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx index df9940801edbf..845c84ad37696 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx @@ -16,12 +16,12 @@ import { LevelFilterOption } from '../types'; import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; import { LEVEL_MAP, DEPRECATIONS_PER_PAGE } from '../constants'; import { KibanaDeprecationAccordion } from './deprecation_item'; -import { FlyoutContent } from './steps_flyout'; +import { ModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; interface Props { deprecations: DomainDeprecationDetails[]; - showFlyout: (newFlyoutContent: FlyoutContent) => void; + showModal: (newModalContent: ModalContent) => void; reloadDeprecations: () => Promise; isLoading: boolean; } @@ -55,7 +55,7 @@ const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetail export const KibanaDeprecationList: FunctionComponent = ({ deprecations, - showFlyout, + showModal, reloadDeprecations, isLoading, }) => { @@ -135,7 +135,7 @@ export const KibanaDeprecationList: FunctionComponent = ({ index, deprecation, forceExpand: expandState.forceExpand, - showFlyout, + showModal, }} /> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index d88b5e1427a86..578b92731952e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -25,7 +25,7 @@ import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { NoDeprecationsPrompt } from '../shared'; import { KibanaDeprecationList } from './deprecation_list'; -import { StepsFlyout, FlyoutContent } from './steps_flyout'; +import { StepsModal, ModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; const i18nTexts = { @@ -52,7 +52,7 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent >(undefined); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(undefined); - const [flyoutContent, setFlyoutContent] = useState(undefined); + const [modalContent, setModalContent] = useState(undefined); const { deprecations, breadcrumbs, docLinks, api } = useAppContext(); @@ -69,12 +69,12 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent setIsLoading(false); }, [deprecations]); - const toggleFlyout = (newFlyoutContent?: FlyoutContent) => { - if (typeof newFlyoutContent === 'undefined') { - setFlyoutContent(undefined); + const toggleModal = (newModalContent?: ModalContent) => { + if (typeof newModalContent === 'undefined') { + setModalContent(undefined); } - setFlyoutContent(newFlyoutContent); + setModalContent(newModalContent); }; useEffect(() => { @@ -113,7 +113,7 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent content = ( @@ -149,8 +149,8 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent {getPageContent()} - {flyoutContent && ( - toggleFlyout()} flyoutContent={flyoutContent} /> + {modalContent && ( + toggleModal()} modalContent={modalContent} /> )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx deleted file mode 100644 index 3867a1d6013b4..0000000000000 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_flyout.tsx +++ /dev/null @@ -1,89 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { - EuiFlyout, - EuiFlyoutHeader, - EuiFlyoutBody, - EuiTitle, - EuiText, - EuiSteps, - EuiSpacer, -} from '@elastic/eui'; - -export interface FlyoutContent { - domainId: string; - steps: string[]; -} - -interface Props { - closeFlyout: () => void; - flyoutContent: FlyoutContent; -} - -const i18nTexts = { - getFlyoutTitle: (domainId: string) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsFlyout.flyoutTitle', { - defaultMessage: `Fix '${domainId}' deprecation`, - values: { - domainId, - }, - }), - getStepTitle: (step: number) => - i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsFlyout.stepTitle', { - defaultMessage: 'Step {step}', - values: { - step, - }, - }), - flyoutDescription: i18n.translate( - 'xpack.upgradeAssistant.kibanaDeprecations.stepsFlyout.flyoutDescription', - { - defaultMessage: 'Follow the steps below to address this deprecation.', - } - ), -}; - -export const StepsFlyout: FunctionComponent = ({ closeFlyout, flyoutContent }) => { - const { domainId, steps } = flyoutContent; - - return ( - - - -

{i18nTexts.getFlyoutTitle(domainId)}

-
-
- - <> - -

{i18nTexts.flyoutDescription}

-
- - - - { - return { - title: i18nTexts.getStepTitle(index + 1), - children: ( - -

{step}

-
- ), - }; - })} - /> - -
-
- ); -}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx new file mode 100644 index 0000000000000..c3cbbcd6b5de3 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { + EuiText, + EuiSteps, + EuiSpacer, + EuiButton, + EuiModal, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiTitle, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; + +export interface ModalContent { + domainId: string; + steps: string[]; +} + +interface Props { + closeModal: () => void; + modalContent: ModalContent; +} + +const i18nTexts = { + getModalTitle: (domainId: string) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle', { + defaultMessage: `Fix '${domainId}'`, + values: { + domainId, + }, + }), + getStepTitle: (step: number) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.stepTitle', { + defaultMessage: 'Step {step}', + values: { + step, + }, + }), + modalDescription: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalDescription', + { + defaultMessage: 'Follow the steps below to address this deprecation.', + } + ), +}; + +export const StepsModal: FunctionComponent = ({ closeModal, modalContent }) => { + const { domainId, steps } = modalContent; + + return ( + + + + +

{i18nTexts.getModalTitle(domainId)}

+
+
+
+ + + <> + +

{i18nTexts.modalDescription}

+
+ + + + { + return { + title: i18nTexts.getStepTitle(index + 1), + children: ( + +

{step}

+
+ ), + }; + })} + /> + +
+ + + + + {/* TODO i18n and href */} + + View documentation + + + + {/* TODO i18n */} + + Close window + + + + +
+ ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx index 658c84d016faa..72525cd59978a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx @@ -40,6 +40,12 @@ const i18nTexts = { defaultMessage: 'Critical', } ), + viewDeprecationsLink: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationStats.viewDeprecationsLinkText', + { + defaultMessage: 'View deprecations', + } + ), }; interface Props { @@ -73,17 +79,22 @@ export const KibanaDeprecationStats: FunctionComponent = ({ history }) => }, [deprecations]); return ( - - -

+ + + + +

{i18nTexts.statsTitle}

+
+
+ - {i18nTexts.statsTitle} + {i18nTexts.viewDeprecationsLink} -

-
+
+ diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx index 0a91a24cd9798..b346d918f212a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/overview.tsx @@ -117,23 +117,23 @@ export const DeprecationsOverview: FunctionComponent = ({ history }) => { - - - - - - + + + + + + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx index ee77fd6a1bc5d..b04895d81555b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx @@ -8,14 +8,14 @@ import React, { FunctionComponent, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiButtonEmpty, + EuiButton, EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiCallOut, EuiSpacer, - EuiHorizontalRule, } from '@elastic/eui'; + // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { DomainDeprecationDetails } from 'src/core/server/types'; import { DeprecationInfo } from '../../../../../common/types'; @@ -118,9 +118,9 @@ export const SearchBar: FunctionComponent = ({
- + {i18nTexts.reloadButtonLabel} - + @@ -136,7 +136,7 @@ export const SearchBar: FunctionComponent = ({ )} - + ); }; From e68a6a0a886a66fc1bbe214843ad60acf68f15f7 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 14 Apr 2021 14:22:35 -0400 Subject: [PATCH 03/18] fix build errors --- .../schema/xpack_plugins.json | 3 + .../translations/translations/ja-JP.json | 9 -- .../translations/translations/zh-CN.json | 9 -- .../upgrade_assistant/common/constants.ts | 2 +- .../deprecations/list.test.tsx | 18 +-- .../kibana_deprecations/deprecation_item.tsx | 15 +-- .../kibana_deprecations/deprecation_list.tsx | 15 +-- .../kibana_deprecations.tsx | 4 +- .../kibana_deprecations/steps_modal.tsx | 34 ++++-- .../components/overview/kibana_stats.tsx | 3 +- .../components/shared/no_deprecations.tsx | 9 +- .../shared/search_bar/search_bar.tsx | 3 +- .../server/lib/es_migration_apis.ts | 103 +----------------- .../lib/telemetry/es_ui_open_apis.test.ts | 14 ++- .../lib/telemetry/usage_collector.test.ts | 2 + .../server/lib/telemetry/usage_collector.ts | 3 + .../helpers/setup_environment.tsx | 7 +- 17 files changed, 78 insertions(+), 175 deletions(-) diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 3d302aa12832e..208cf994afc03 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -4210,6 +4210,9 @@ }, "overview": { "type": "long" + }, + "kibana": { + "type": "long" } } }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 933bf512bdda0..462467801d18f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -22594,15 +22594,9 @@ "xpack.uiActionsEnhanced.drilldowns.urlDrilldownValidation.urlFormatGeneralErrorMessage": "無効なフォーマット。例:{exampleUrl}", "xpack.upgradeAssistant.appTitle": "{version} アップグレードアシスタント", "xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "より多く表示させるにはフィルターを変更します。", - "xpack.upgradeAssistant.checkupTab.controls.collapseAllButtonLabel": "すべて縮小", - "xpack.upgradeAssistant.checkupTab.controls.expandAllButtonLabel": "すべて拡張", "xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "致命的", - "xpack.upgradeAssistant.checkupTab.controls.filterErrorMessageLabel": "フィルター無効:{searchTermError}", "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "インデックス別", "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "問題別", - "xpack.upgradeAssistant.checkupTab.controls.refreshButtonLabel": "更新", - "xpack.upgradeAssistant.checkupTab.controls.searchBarPlaceholder": "フィルター", - "xpack.upgradeAssistant.checkupTab.controls.searchBarPlaceholderAriaLabel": "フィルター", "xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "アップグレード前にこの問題を解決してください。", "xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel": "致命的", "xpack.upgradeAssistant.checkupTab.deprecations.documentationButtonLabel": "ドキュメント", @@ -22611,9 +22605,6 @@ "xpack.upgradeAssistant.checkupTab.deprecations.warningActionTooltip": "アップグレード前にこの問題を解決することをお勧めしますが、必須ではありません。", "xpack.upgradeAssistant.checkupTab.deprecations.warningLabel": "警告", "xpack.upgradeAssistant.checkupTab.noDeprecationsLabel": "説明がありません", - "xpack.upgradeAssistant.checkupTab.noIssues.nextStepsDetail": "{overviewTabButton} で次のステップを確認してください。", - "xpack.upgradeAssistant.checkupTab.noIssues.nextStepsDetail.overviewTabButtonLabel": "概要タブ", - "xpack.upgradeAssistant.checkupTab.noIssues.noIssuesTitle": "完璧です!", "xpack.upgradeAssistant.checkupTab.numDeprecationsShownLabel": "{total} 件中 {numShown} 件を表示中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.cancelButtonLabel": "キャンセル", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.closeButtonLabel": "閉じる", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 917c68913d462..dde014dac6708 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -22951,15 +22951,9 @@ "xpack.uiActionsEnhanced.drilldowns.urlDrilldownValidation.urlFormatGeneralErrorMessage": "格式无效。例如:{exampleUrl}", "xpack.upgradeAssistant.appTitle": "{version} 升级助手", "xpack.upgradeAssistant.checkupTab.changeFiltersShowMoreLabel": "更改筛选以显示更多内容。", - "xpack.upgradeAssistant.checkupTab.controls.collapseAllButtonLabel": "折叠全部", - "xpack.upgradeAssistant.checkupTab.controls.expandAllButtonLabel": "展开全部", "xpack.upgradeAssistant.checkupTab.controls.filterBar.criticalButtonLabel": "紧急", - "xpack.upgradeAssistant.checkupTab.controls.filterErrorMessageLabel": "筛选无效:{searchTermError}", "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIndexLabel": "按索引", "xpack.upgradeAssistant.checkupTab.controls.groupByBar.byIssueLabel": "按问题", - "xpack.upgradeAssistant.checkupTab.controls.refreshButtonLabel": "刷新", - "xpack.upgradeAssistant.checkupTab.controls.searchBarPlaceholder": "筛选", - "xpack.upgradeAssistant.checkupTab.controls.searchBarPlaceholderAriaLabel": "筛选", "xpack.upgradeAssistant.checkupTab.deprecations.criticalActionTooltip": "请解决此问题后再升级。", "xpack.upgradeAssistant.checkupTab.deprecations.criticalLabel": "紧急", "xpack.upgradeAssistant.checkupTab.deprecations.documentationButtonLabel": "文档", @@ -22969,9 +22963,6 @@ "xpack.upgradeAssistant.checkupTab.deprecations.warningLabel": "警告", "xpack.upgradeAssistant.checkupTab.indicesBadgeLabel": "{numIndices, plural, other { 个索引}}", "xpack.upgradeAssistant.checkupTab.noDeprecationsLabel": "无弃用内容", - "xpack.upgradeAssistant.checkupTab.noIssues.nextStepsDetail": "选中 {overviewTabButton} 以执行后续步骤。", - "xpack.upgradeAssistant.checkupTab.noIssues.nextStepsDetail.overviewTabButtonLabel": "“概述”选项卡", - "xpack.upgradeAssistant.checkupTab.noIssues.noIssuesTitle": "全部清除!", "xpack.upgradeAssistant.checkupTab.numDeprecationsShownLabel": "显示 {numShown} 个,共 {total} 个", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.cancelButtonLabel": "取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.closeButtonLabel": "关闭", diff --git a/x-pack/plugins/upgrade_assistant/common/constants.ts b/x-pack/plugins/upgrade_assistant/common/constants.ts index aec52f0913238..29253d3c373d6 100644 --- a/x-pack/plugins/upgrade_assistant/common/constants.ts +++ b/x-pack/plugins/upgrade_assistant/common/constants.ts @@ -19,7 +19,7 @@ export const mockKibanaSemverVersion = new SemVer(mockKibanaVersion); * In readonly mode, the user will not be able to perform any actions in the UI * and will be presented with a message indicating as such. */ -export const UA_READONLY_MODE = false; +export const UA_READONLY_MODE = true; /* * Map of 7.0 --> 8.0 index setting deprecation log messages and associated settings diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.test.tsx index c1b6357d504eb..579cf1f4a55bb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/list.test.tsx @@ -10,9 +10,9 @@ import React from 'react'; import { EnrichedDeprecationInfo } from '../../../../../common/types'; import { GroupByOption } from '../../types'; -import { DeprecationList } from './list'; +import { EsDeprecationList } from './list'; -describe('DeprecationList', () => { +describe('EsDeprecationList', () => { describe('group by message', () => { const defaultProps = { deprecations: [ @@ -23,7 +23,7 @@ describe('DeprecationList', () => { }; test('shows simple messages when index field is not present', () => { - expect(shallow()).toMatchInlineSnapshot(` + expect(shallow()).toMatchInlineSnapshot(`
{ "url": "", } } - key="Issue 1" + key="Issue 1-0" /> { "url": "", } } - key="Issue 1" + key="Issue 1-1" />
`); @@ -58,7 +58,7 @@ describe('DeprecationList', () => { index: index.toString(), })), }; - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchInlineSnapshot(` { }; test('shows detailed messages', () => { - expect(shallow()).toMatchInlineSnapshot(` + expect(shallow()).toMatchInlineSnapshot(`
{ "url": "", } } - key="Issue 1" + key="Issue 1-0" /> { "url": "", } } - key="Issue 2" + key="Issue 2-1" />
`); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx index 1736040c20cd7..9c54a4f26db44 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx @@ -16,8 +16,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { DomainDeprecationDetails } from 'src/core/server/types'; +import { DomainDeprecationDetails } from 'kibana/public'; import { DeprecationHealth } from '../shared'; import { LEVEL_MAP } from '../constants'; import { ModalContent } from './steps_modal'; @@ -25,7 +24,10 @@ import { ModalContent } from './steps_modal'; const i18nTexts = { getDeprecationTitle: (domainId: string) => { return i18n.translate('xpack.upgradeAssistant.deprecationGroupItemTitle', { - defaultMessage: `"${domainId}" is using a deprecated feature`, + defaultMessage: "'{domainId}' is using a deprecated feature", + values: { + domainId, + }, }); }, docLinkText: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.docLinkText', { @@ -43,9 +45,6 @@ export interface Props { showModal: (modalContent: ModalContent) => void; } -/** - * A single accordion item for a grouped deprecation item. - */ export const KibanaDeprecationAccordion: FunctionComponent = ({ deprecation, forceExpand, @@ -93,7 +92,9 @@ export const KibanaDeprecationAccordion: FunctionComponent = ({ showModal({ domainId, steps: correctiveActions.manualSteps! })} + onClick={() => + showModal({ domainId, steps: correctiveActions.manualSteps!, documentationUrl }) + } > {i18nTexts.fixButtonLabel} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx index 845c84ad37696..05effa3bb14d2 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx @@ -9,8 +9,7 @@ import React, { FunctionComponent, useState, useEffect } from 'react'; import { groupBy } from 'lodash'; import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { DomainDeprecationDetails } from 'src/core/server/types'; +import { DomainDeprecationDetails } from 'kibana/public'; import { LevelFilterOption } from '../types'; import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; @@ -67,14 +66,6 @@ export const KibanaDeprecationList: FunctionComponent = ({ }); const [currentPage, setCurrentPage] = useState(0); - const changeFilter = (filter: LevelFilterOption) => { - setCurrentFilter(filter); - }; - - const changeSearch = (newSearch: string) => { - setSearch(newSearch); - }; - const setExpandAll = (expandAll: boolean) => { setExpandState({ forceExpand: expandAll, expandNumber: expandState.expandNumber + 1 }); }; @@ -102,8 +93,8 @@ export const KibanaDeprecationList: FunctionComponent = ({ isLoading={isLoading} loadData={reloadDeprecations} currentFilter={currentFilter} - onFilterChange={changeFilter} - onSearchChange={changeSearch} + onFilterChange={setCurrentFilter} + onSearchChange={setSearch} totalDeprecationsCount={deprecations.length} deprecationLevelsCount={deprecationLevelsCount} /> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 578b92731952e..2b06da84b1dcb 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -18,9 +18,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { DomainDeprecationDetails } from 'src/core/server/types'; - +import { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { NoDeprecationsPrompt } from '../shared'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx index c3cbbcd6b5de3..953b0e051dc35 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx @@ -27,6 +27,7 @@ import { export interface ModalContent { domainId: string; steps: string[]; + documentationUrl?: string; } interface Props { @@ -37,7 +38,7 @@ interface Props { const i18nTexts = { getModalTitle: (domainId: string) => i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.stepsModal.modalTitle', { - defaultMessage: `Fix '${domainId}'`, + defaultMessage: "Fix '{domainId}'", values: { domainId, }, @@ -55,10 +56,22 @@ const i18nTexts = { defaultMessage: 'Follow the steps below to address this deprecation.', } ), + docLinkLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.docLinkLabel', + { + defaultMessage: 'View documentation', + } + ), + closeButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.stepsModal.closeButtonLabel', + { + defaultMessage: 'Close', + } + ), }; export const StepsModal: FunctionComponent = ({ closeModal, modalContent }) => { - const { domainId, steps } = modalContent; + const { domainId, steps, documentationUrl } = modalContent; return ( @@ -96,16 +109,17 @@ export const StepsModal: FunctionComponent = ({ closeModal, modalContent + {documentationUrl && ( + + + {i18nTexts.docLinkLabel} + + + )} + - {/* TODO i18n and href */} - - View documentation - - - - {/* TODO i18n */} - Close window + {i18nTexts.closeButtonLabel} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx index 72525cd59978a..b2fefc57e9f5e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx @@ -19,8 +19,7 @@ import { import { i18n } from '@kbn/i18n'; import { RouteComponentProps } from 'react-router-dom'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { DomainDeprecationDetails } from 'src/core/server/types'; +import { DomainDeprecationDetails } from 'kibana/public'; import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; import { useAppContext } from '../../app_context'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx index 2d2f1e5fe93cf..3626151b63bbf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/no_deprecations.tsx @@ -13,19 +13,16 @@ import { FormattedMessage } from '@kbn/i18n/react'; const i18nTexts = { emptyPromptTitle: i18n.translate('xpack.upgradeAssistant.noDeprecationsPrompt.title', { - defaultMessage: 'All clear!', + defaultMessage: 'Ready to upgrade!', }), getEmptyPromptDescription: (deprecationType: string) => i18n.translate('xpack.upgradeAssistant.noDeprecationsPrompt.description', { - defaultMessage: 'You have no {deprecationType} issues.', - values: { - deprecationType, - }, + defaultMessage: 'Your configuration is up to date.', }), getEmptyPromptNextStepsDescription: (navigateToOverviewPage: () => void) => ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx index b04895d81555b..1b00b904db596 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx @@ -16,8 +16,7 @@ import { EuiSpacer, } from '@elastic/eui'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { DomainDeprecationDetails } from 'src/core/server/types'; +import { DomainDeprecationDetails } from 'kibana/public'; import { DeprecationInfo } from '../../../../../common/types'; import { validateRegExpString } from '../../../lib/utils'; import { GroupByOption, LevelFilterOption } from '../../types'; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts index 35a70fb8740ab..e775190d426df 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts @@ -40,106 +40,9 @@ export async function getUpgradeAssistantStatus( const criticalWarnings = cluster.concat(indices).filter((d) => d.level === 'critical'); return { - readyForUpgrade: false, - cluster: [ - { - level: 'critical', - message: 'Index Lifecycle Management poll interval is set too low', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#ilm-poll-interval-limit', - details: - 'The Index Lifecycle Management poll interval setting [indices.lifecycle.poll_interval] is currently set to [500ms], but must be 1s or greater', - }, - { - level: 'warning', - message: 'Index templates contain _field_names settings.', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#fieldnames-enabling', - details: - 'Index templates [field_names_enabled] use the deprecated `enable` setting for the `_field_names` field. Using this setting in new index mappings will throw an error in the next major version and needs to be removed from existing mappings and templates.', - }, - ], - indices: [ - { - level: 'warning', - message: 'translog retention settings are ignored', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', - details: - 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', - index: 'deprecated_settings', - reindex: false, - }, - { - level: 'warning', - message: 'translog retention settings are ignored', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', - details: - 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', - index: 'settings', - reindex: false, - }, - { - level: 'warning', - message: 'Multi-fields within multi-fields', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#_defining_multi_fields_within_multi_fields', - details: - 'The names of fields that contain chained multi-fields: [[type: _doc, field: text]]', - index: 'nested_multi_fields', - reindex: false, - }, - { - level: 'critical', - message: 'Index created before 7.0', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html', - details: 'This index was created using version: 6.8.13', - index: 'test2', - reindex: true, - }, - { - level: 'warning', - message: 'Multi-fields within multi-fields', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#_defining_multi_fields_within_multi_fields', - details: - 'The names of fields that contain chained multi-fields: [[type: _doc, field: test]]', - index: 'foo', - reindex: false, - }, - { - level: 'warning', - message: 'Index mapping contains explicit `_field_names` enabling settings.', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#fieldnames-enabling', - details: - 'The index mapping contains a deprecated `enabled` setting for `_field_names` that should be removed moving foward.', - index: 'field_names_enabled', - reindex: false, - }, - { - level: 'warning', - message: 'Index mapping contains explicit `_field_names` enabling settings.', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#fieldnames-enabling', - details: - 'The index mapping contains a deprecated `enabled` setting for `_field_names` that should be removed moving foward.', - index: 'tweets', - reindex: false, - }, - { - level: 'warning', - message: 'translog retention settings are ignored', - url: - 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', - details: - 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', - index: 'translog_settings', - reindex: false, - }, - ], + readyForUpgrade: criticalWarnings.length === 0, + cluster, + indices, }; } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts index 05db5ebdaa54d..a911c5810dd0a 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts @@ -24,24 +24,30 @@ describe('Upgrade Assistant Telemetry SavedObject UIOpen', () => { overview: true, cluster: true, indices: true, + kibana: true, savedObjects: { createInternalRepository: () => internalRepo } as any, }); - expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(3); + expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(4); expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, - [`ui_open.overview`] + ['ui_open.overview'] ); expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, - [`ui_open.cluster`] + ['ui_open.cluster'] ); expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, - [`ui_open.indices`] + ['ui_open.indices'] + ); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + ['ui_open.kibana'] ); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index 46208a6a2c7bb..30195f6652fb2 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -51,6 +51,7 @@ describe('Upgrade Assistant Usage Collector', () => { 'ui_open.overview': 10, 'ui_open.cluster': 20, 'ui_open.indices': 30, + 'ui_open.kibana': 15, 'ui_reindex.close': 1, 'ui_reindex.open': 4, 'ui_reindex.start': 2, @@ -90,6 +91,7 @@ describe('Upgrade Assistant Usage Collector', () => { overview: 10, cluster: 20, indices: 30, + kibana: 15, }, ui_reindex: { close: 1, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index 9d4889bb7bcea..a03931780d51f 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -73,6 +73,7 @@ export async function fetchUpgradeAssistantMetrics( overview: 0, cluster: 0, indices: 0, + kibana: 0, }, ui_reindex: { close: 0, @@ -91,6 +92,7 @@ export async function fetchUpgradeAssistantMetrics( overview: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.overview', 0), cluster: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.cluster', 0), indices: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.indices', 0), + kibana: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_open.kibana', 0), }, ui_reindex: { close: get(upgradeAssistantTelemetrySavedObjectAttrs, 'ui_reindex.close', 0), @@ -136,6 +138,7 @@ export function registerUpgradeAssistantUsageCollector({ cluster: { type: 'long' }, indices: { type: 'long' }, overview: { type: 'long' }, + kibana: { type: 'long' }, }, ui_reindex: { close: { type: 'long' }, diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/setup_environment.tsx b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/setup_environment.tsx index 7ee6114cd86a8..9ea5c15e9d031 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/setup_environment.tsx @@ -10,7 +10,11 @@ import axios from 'axios'; // @ts-ignore import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import { docLinksServiceMock, notificationServiceMock } from '../../../../../src/core/public/mocks'; +import { + deprecationsServiceMock, + docLinksServiceMock, + notificationServiceMock, +} from '../../../../../src/core/public/mocks'; import { HttpSetup } from '../../../../../src/core/public'; import { mockKibanaSemverVersion, UA_READONLY_MODE } from '../../common/constants'; @@ -41,6 +45,7 @@ export const WithAppDependencies = (Comp: any, overrides: Record '', + deprecations: deprecationsServiceMock.createStartContract(), }; return ( From 98a8c30710b8849b32a38220af51fbf1dc84a9cb Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 14 Apr 2021 15:45:25 -0400 Subject: [PATCH 04/18] update overview tests --- .../deprecation_tab_content.tsx | 2 +- .../es_deprecations/deprecations/index.tsx | 2 +- .../components/overview/kibana_stats.tsx | 23 +- .../helpers/http_requests.ts | 7 +- .../helpers/overview.helpers.ts | 3 + .../tests_client_integration/indices.test.ts | 12 +- .../tests_client_integration/overview.test.ts | 197 ++++++++++++------ 7 files changed, 171 insertions(+), 75 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx index cb11a45e66f18..41cd48e5d401f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx @@ -22,7 +22,7 @@ import { } from '../shared'; import { DEPRECATIONS_PER_PAGE } from '../constants'; import { EsDeprecationErrors } from './es_deprecation_errors'; -import { EsDeprecationAccordion } from './deprecations/deprecation_group_item'; +import { EsDeprecationAccordion } from './deprecations'; const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.esDeprecations.loadingText', { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/index.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/index.tsx index e361e98beffb7..a4152e52a35b7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/index.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/index.tsx @@ -5,4 +5,4 @@ * 2.0. */ -export { GroupedDeprecations } from './grouped'; +export { EsDeprecationAccordion } from './deprecation_group_item'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx index b2fefc57e9f5e..f120c73dea44c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx @@ -15,6 +15,7 @@ import { EuiSpacer, EuiFlexGroup, EuiFlexItem, + EuiIconTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -45,6 +46,12 @@ const i18nTexts = { defaultMessage: 'View deprecations', } ), + loadingError: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecationStats.loadingErrorMessage', + { + defaultMessage: 'An error occurred while retrieving Kibana deprecations.', + } + ), }; interface Props { @@ -120,7 +127,21 @@ export const KibanaDeprecationStats: FunctionComponent = ({ history }) => titleColor="danger" isLoading={isLoading} > - {/* {error && } */} + {error && ( + <> + + + + + )} diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/http_requests.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/http_requests.ts index 76ed94c7bf684..9abd981bd85c8 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/http_requests.ts @@ -12,7 +12,10 @@ import { ResponseError } from '../../public/application/lib/api'; // Register helpers to mock HTTP Requests const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { - const setLoadStatusResponse = (response?: UpgradeAssistantStatus, error?: ResponseError) => { + const setLoadEsDeprecationsResponse = ( + response?: UpgradeAssistantStatus, + error?: ResponseError + ) => { const status = error ? error.statusCode || 400 : 200; const body = error ? error : response; @@ -60,7 +63,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { }; return { - setLoadStatusResponse, + setLoadEsDeprecationsResponse, setLoadDeprecationLoggingResponse, setUpdateDeprecationLoggingResponse, setUpdateIndexSettingsResponse, diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/overview.helpers.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/overview.helpers.ts index 161364f6d45ce..52346c94ef46b 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/overview.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/overview.helpers.ts @@ -34,6 +34,9 @@ export type OverviewTestSubjects = | 'esStatsPanel' | 'esStatsPanel.totalDeprecations' | 'esStatsPanel.criticalDeprecations' + | 'kibanaStatsPanel' + | 'kibanaStatsPanel.totalDeprecations' + | 'kibanaStatsPanel.criticalDeprecations' | 'deprecationLoggingFormRow' | 'requestErrorIconTip' | 'partiallyUpgradedErrorIconTip' diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/indices.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/indices.test.ts index 6363e57903c27..51526698effc5 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/indices.test.ts @@ -35,7 +35,7 @@ describe('Indices tab', () => { }; beforeEach(async () => { - httpRequestsMockHelpers.setLoadStatusResponse(upgradeStatusMockResponse); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(upgradeStatusMockResponse); httpRequestsMockHelpers.setLoadDeprecationLoggingResponse({ isEnabled: true }); await act(async () => { @@ -118,7 +118,7 @@ describe('Indices tab', () => { indices: [], }; - httpRequestsMockHelpers.setLoadStatusResponse(noDeprecationsResponse); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(noDeprecationsResponse); await act(async () => { testBed = await setupIndicesPage({ isReadOnlyMode: false }); @@ -144,7 +144,7 @@ describe('Indices tab', () => { message: 'Forbidden', }; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); await act(async () => { testBed = await setupIndicesPage({ isReadOnlyMode: false }); @@ -170,7 +170,7 @@ describe('Indices tab', () => { }, }; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); await act(async () => { testBed = await setupIndicesPage({ isReadOnlyMode: false }); @@ -196,7 +196,7 @@ describe('Indices tab', () => { }, }; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); await act(async () => { testBed = await setupIndicesPage({ isReadOnlyMode: false }); @@ -219,7 +219,7 @@ describe('Indices tab', () => { message: 'Internal server error', }; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); await act(async () => { testBed = await setupIndicesPage({ isReadOnlyMode: false }); diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts index cdbbd0a36cbdd..a94a943188c25 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts @@ -5,7 +5,10 @@ * 2.0. */ +import { DomainDeprecationDetails } from 'kibana/public'; import { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; +import { UpgradeAssistantStatus } from '../common/types'; import { OverviewTestBed, setupOverviewPage, setupEnvironment } from './helpers'; @@ -14,17 +17,54 @@ describe('Overview page', () => { const { server, httpRequestsMockHelpers } = setupEnvironment(); beforeEach(async () => { - const upgradeStatusMockResponse = { + const esDeprecationsMockResponse: UpgradeAssistantStatus = { readyForUpgrade: false, - cluster: [], - indices: [], + cluster: [ + { + level: 'critical', + message: 'Index Lifecycle Management poll interval is set too low', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-8.0.html#ilm-poll-interval-limit', + details: + 'The Index Lifecycle Management poll interval setting [indices.lifecycle.poll_interval] is currently set to [500ms], but must be 1s or greater', + }, + ], + indices: [ + { + level: 'warning', + message: 'translog retention settings are ignored', + url: + 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-translog.html', + details: + 'translog retention settings [index.translog.retention.size] and [index.translog.retention.age] are ignored because translog is no longer used in peer recoveries with soft-deletes enabled (default in 7.0 or later)', + index: 'settings', + reindex: false, + }, + ], }; - httpRequestsMockHelpers.setLoadStatusResponse(upgradeStatusMockResponse); + const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ + { + correctiveActions: {}, + domainId: 'xpack.spaces', + level: 'critical', + message: + 'Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)', + }, + ]; + + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(esDeprecationsMockResponse); httpRequestsMockHelpers.setLoadDeprecationLoggingResponse({ isEnabled: true }); await act(async () => { - testBed = await setupOverviewPage(); + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupOverviewPage({ + deprecations: deprecationService, + }); }); const { component } = testBed; @@ -39,10 +79,16 @@ describe('Overview page', () => { const { exists, find } = testBed; expect(exists('overviewPageContent')).toBe(true); + // Verify ES stats expect(exists('esStatsPanel')).toBe(true); - expect(find('esStatsPanel.totalDeprecations').text()).toContain('0'); - expect(find('esStatsPanel.criticalDeprecations').text()).toContain('0'); + expect(find('esStatsPanel.totalDeprecations').text()).toContain('2'); + expect(find('esStatsPanel.criticalDeprecations').text()).toContain('1'); + + // Verify Kibana stats + expect(exists('kibanaStatsPanel')).toBe(true); + expect(find('kibanaStatsPanel.totalDeprecations').text()).toContain('1'); + expect(find('kibanaStatsPanel.criticalDeprecations').text()).toContain('1'); }); describe('Deprecation logging', () => { @@ -96,90 +142,113 @@ describe('Overview page', () => { }); describe('Error handling', () => { - test('handles network failure', async () => { - const error = { - statusCode: 500, - error: 'Internal server error', - message: 'Internal server error', - }; + describe('Kibana deprecations', () => { + test('handles network failure', async () => { + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest + .fn() + .mockRejectedValue(new Error('Internal Server Error')); - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + testBed = await setupOverviewPage({ + deprecations: deprecationService, + }); + }); - await act(async () => { - testBed = await setupOverviewPage(); + const { component, exists } = testBed; + + component.update(); + + expect(exists('requestErrorIconTip')).toBe(true); }); + }); - const { component, exists } = testBed; + describe('Elasticsearch deprecations', () => { + test('handles network failure', async () => { + const error = { + statusCode: 500, + error: 'Internal server error', + message: 'Internal server error', + }; - component.update(); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - expect(exists('requestErrorIconTip')).toBe(true); - }); + await act(async () => { + testBed = await setupOverviewPage(); + }); - test('handles unauthorized error', async () => { - const error = { - statusCode: 403, - error: 'Forbidden', - message: 'Forbidden', - }; + const { component, exists } = testBed; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + component.update(); - await act(async () => { - testBed = await setupOverviewPage(); + expect(exists('requestErrorIconTip')).toBe(true); }); - const { component, exists } = testBed; + test('handles unauthorized error', async () => { + const error = { + statusCode: 403, + error: 'Forbidden', + message: 'Forbidden', + }; - component.update(); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - expect(exists('unauthorizedErrorIconTip')).toBe(true); - }); + await act(async () => { + testBed = await setupOverviewPage(); + }); - test('handles partially upgraded error', async () => { - const error = { - statusCode: 426, - error: 'Upgrade required', - message: 'There are some nodes running a different version of Elasticsearch', - attributes: { - allNodesUpgraded: false, - }, - }; + const { component, exists } = testBed; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + component.update(); - await act(async () => { - testBed = await setupOverviewPage({ isReadOnlyMode: false }); + expect(exists('unauthorizedErrorIconTip')).toBe(true); }); - const { component, exists } = testBed; + test('handles partially upgraded error', async () => { + const error = { + statusCode: 426, + error: 'Upgrade required', + message: 'There are some nodes running a different version of Elasticsearch', + attributes: { + allNodesUpgraded: false, + }, + }; - component.update(); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - expect(exists('partiallyUpgradedErrorIconTip')).toBe(true); - }); + await act(async () => { + testBed = await setupOverviewPage({ isReadOnlyMode: false }); + }); - test('handles upgrade error', async () => { - const error = { - statusCode: 426, - error: 'Upgrade required', - message: 'There are some nodes running a different version of Elasticsearch', - attributes: { - allNodesUpgraded: true, - }, - }; + const { component, exists } = testBed; - httpRequestsMockHelpers.setLoadStatusResponse(undefined, error); + component.update(); - await act(async () => { - testBed = await setupOverviewPage({ isReadOnlyMode: false }); + expect(exists('partiallyUpgradedErrorIconTip')).toBe(true); }); - const { component, exists } = testBed; + test('handles upgrade error', async () => { + const error = { + statusCode: 426, + error: 'Upgrade required', + message: 'There are some nodes running a different version of Elasticsearch', + attributes: { + allNodesUpgraded: true, + }, + }; - component.update(); + httpRequestsMockHelpers.setLoadEsDeprecationsResponse(undefined, error); - expect(exists('upgradedErrorIconTip')).toBe(true); + await act(async () => { + testBed = await setupOverviewPage({ isReadOnlyMode: false }); + }); + + const { component, exists } = testBed; + + component.update(); + + expect(exists('upgradedErrorIconTip')).toBe(true); + }); }); }); }); From a0376ea344e17437d39d2d3534aef0562fc24f7a Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 14 Apr 2021 21:02:17 -0400 Subject: [PATCH 05/18] add tests for kibana deprecations --- .../kibana_deprecations/deprecation_list.tsx | 2 +- .../kibana_deprecation_errors.tsx | 2 +- .../group_by_filter.test.tsx.snap | 24 +++++ .../tests_client_integration/helpers/index.ts | 1 + .../helpers/kibana.helpers.ts | 58 ++++++++++++ .../tests_client_integration/kibana.test.ts | 94 +++++++++++++++++++ 6 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/group_by_filter.test.tsx.snap create mode 100644 x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts create mode 100644 x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx index 05effa3bb14d2..3f7bc96172a1c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx @@ -119,7 +119,7 @@ export const KibanaDeprecationList: FunctionComponent = ({ .slice(currentPage * DEPRECATIONS_PER_PAGE, (currentPage + 1) * DEPRECATIONS_PER_PAGE) .sort(sortByLevelDesc) .map((deprecation, index) => [ -
+
+ + + by issue + + + by index + + + +`; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/index.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/index.ts index 74aa173866b7a..ddf5787af1037 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/index.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/index.ts @@ -7,5 +7,6 @@ export { setup as setupOverviewPage, OverviewTestBed } from './overview.helpers'; export { setup as setupIndicesPage, IndicesTestBed } from './indices.helpers'; +export { setup as setupKibanaPage, KibanaTestBed } from './kibana.helpers'; export { setupEnvironment } from './setup_environment'; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts new file mode 100644 index 0000000000000..ef2af9d6a0dd0 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest'; +import { KibanaDeprecationsContent } from '../../public/application/components/kibana_deprecations'; +import { WithAppDependencies } from './setup_environment'; + +const testBedConfig: TestBedConfig = { + memoryRouter: { + initialEntries: ['/kibana_deprecations'], + componentRoutePath: '/kibana_deprecations', + }, + doMountAsync: true, +}; + +export type KibanaTestBed = TestBed & { + actions: ReturnType; +}; + +const createActions = (testBed: TestBed) => { + /** + * User Actions + */ + + const clickExpandAll = () => { + const { find } = testBed; + find('expandAll').simulate('click'); + }; + + return { + clickExpandAll, + }; +}; + +export const setup = async (overrides?: Record): Promise => { + const initTestBed = registerTestBed( + WithAppDependencies(KibanaDeprecationsContent, overrides), + testBedConfig + ); + const testBed = await initTestBed(); + + return { + ...testBed, + actions: createActions(testBed), + }; +}; + +export type KibanaTestSubjects = + | 'expandAll' + | 'noDeprecationsPrompt' + | 'kibanaPluginError' + | 'kibanaDeprecationsContent' + | 'kibanaDeprecationItem' + | 'kibanaRequestError'; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts new file mode 100644 index 0000000000000..a6192a5e42b51 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { DomainDeprecationDetails } from 'kibana/public'; +import { act } from 'react-dom/test-utils'; +import { deprecationsServiceMock } from 'src/core/public/mocks'; + +import { KibanaTestBed, setupKibanaPage, setupEnvironment } from './helpers'; + +describe('Kibana deprecations', () => { + let testBed: KibanaTestBed; + const { server } = setupEnvironment(); + + afterAll(() => { + server.restore(); + }); + + describe('With deprecations', () => { + const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ + { + correctiveActions: {}, + domainId: 'xpack.spaces', + level: 'critical', + message: + 'Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)', + }, + ]; + + beforeEach(async () => { + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupKibanaPage({ + deprecations: deprecationService, + }); + }); + }); + + test('renders deprecations', () => { + const { exists, find } = testBed; + expect(exists('kibanaDeprecationsContent')).toBe(true); + expect(find('kibanaDeprecationItem').length).toEqual(1); + }); + }); + + describe('No deprecations', () => { + beforeEach(async () => { + await act(async () => { + testBed = await setupKibanaPage({ isReadOnlyMode: false }); + }); + + const { component } = testBed; + + component.update(); + }); + + test('renders prompt', () => { + const { exists, find } = testBed; + expect(exists('noDeprecationsPrompt')).toBe(true); + expect(find('noDeprecationsPrompt').text()).toContain('Ready to upgrade!'); + }); + }); + + describe('Error handling', () => { + test('handles request error', async () => { + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest + .fn() + .mockRejectedValue(new Error('Internal Server Error')); + + testBed = await setupKibanaPage({ + deprecations: deprecationService, + }); + }); + + const { component, exists, find } = testBed; + + component.update(); + + expect(exists('kibanaRequestError')).toBe(true); + expect(find('kibanaRequestError').text()).toContain( + 'Could not retrieve Kibana deprecations.' + ); + }); + }); +}); From cbc289c5edfd7828b29f4a5e0c0500b1efe9bbe0 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 21 Apr 2021 15:02:17 -0400 Subject: [PATCH 06/18] address design feedback --- .../kibana_deprecations/deprecation_item.tsx | 58 ++++++++++++------- .../shared/search_bar/level_filter.tsx | 16 ----- .../public/application/components/types.ts | 1 - 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx index 9c54a4f26db44..3f99050a33321 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx @@ -10,7 +10,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem, - EuiLink, + EuiButtonEmpty, EuiText, EuiCallOut, } from '@elastic/eui'; @@ -31,10 +31,10 @@ const i18nTexts = { }); }, docLinkText: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.docLinkText', { - defaultMessage: 'Documentation', + defaultMessage: 'View documentation', }), fixButtonLabel: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel', { - defaultMessage: 'Fix', + defaultMessage: 'Show steps to fix', }), }; @@ -76,30 +76,44 @@ export const KibanaDeprecationAccordion: FunctionComponent = ({ ) : ( <>

{message}

- {documentationUrl && ( -

- - {i18nTexts.docLinkText} - -

+ + {(documentationUrl || correctiveActions?.manualSteps) && ( + + {correctiveActions?.manualSteps && ( + + + showModal({ + domainId, + steps: correctiveActions.manualSteps!, + documentationUrl, + }) + } + > + {i18nTexts.fixButtonLabel} + + + )} + + {documentationUrl && ( + + + {i18nTexts.docLinkText} + + + )} + )} )} - - {correctiveActions?.manualSteps && ( - - - showModal({ domainId, steps: correctiveActions.manualSteps!, documentationUrl }) - } - > - {i18nTexts.fixButtonLabel} - - - )} ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx index 7c814f320c879..f149accf04540 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx @@ -41,7 +41,6 @@ export const DeprecationLevelFilter: React.FunctionComponent { onFilterChange( @@ -56,21 +55,6 @@ export const DeprecationLevelFilter: React.FunctionComponent {LocalizedOptions[LevelFilterOption.critical]} - { - onFilterChange( - currentFilter !== LevelFilterOption.warning - ? LevelFilterOption.warning - : LevelFilterOption.all - ); - }} - hasActiveFilters={currentFilter === LevelFilterOption.warning} - numFilters={levelsCount[LevelFilterOption.warning] || undefined} - data-test-subj="warningLevelFilter" - > - {LocalizedOptions[LevelFilterOption.warning]} - ); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts index d82b779110a89..c26f8be9f9372 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -35,7 +35,6 @@ export enum LoadingState { export enum LevelFilterOption { all = 'all', critical = 'critical', - warning = 'warning', } export enum GroupByOption { From 975515323fd4b38766ca3ce05a6e68ba6dea59e2 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 22 Apr 2021 14:14:05 -0400 Subject: [PATCH 07/18] support for auto resolving kibana deprecations --- .../kibana_deprecations/deprecation_item.tsx | 41 +++++-- .../kibana_deprecations/deprecation_list.tsx | 11 +- .../kibana_deprecations.tsx | 75 +++++++++++-- .../resolve_deprecation_modal.tsx | 64 +++++++++++ .../kibana_deprecations/steps_modal.tsx | 9 +- .../__snapshots__/level_filter.test.tsx.snap | 10 -- .../helpers/kibana.helpers.ts | 3 +- .../tests_client_integration/kibana.test.ts | 104 +++++++++++++++++- 8 files changed, 276 insertions(+), 41 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx index 3f99050a33321..43f47cebfa01e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_item.tsx @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { DomainDeprecationDetails } from 'kibana/public'; import { DeprecationHealth } from '../shared'; import { LEVEL_MAP } from '../constants'; -import { ModalContent } from './steps_modal'; +import { StepsModalContent } from './steps_modal'; const i18nTexts = { getDeprecationTitle: (domainId: string) => { @@ -33,23 +33,34 @@ const i18nTexts = { docLinkText: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.docLinkText', { defaultMessage: 'View documentation', }), - fixButtonLabel: i18n.translate('xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel', { - defaultMessage: 'Show steps to fix', - }), + manualFixButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.deprecationGroupItem.fixButtonLabel', + { + defaultMessage: 'Show steps to fix', + } + ), + resolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.deprecationGroupItem.resolveButtonLabel', + { + defaultMessage: 'Quick resolve', + } + ), }; export interface Props { deprecation: DomainDeprecationDetails; index: number; forceExpand: boolean; - showModal: (modalContent: ModalContent) => void; + showStepsModal: (modalContent: StepsModalContent) => void; + showResolveModal: (deprecation: DomainDeprecationDetails) => void; } export const KibanaDeprecationAccordion: FunctionComponent = ({ deprecation, forceExpand, index, - showModal, + showStepsModal, + showResolveModal, }) => { const { domainId, level, message, documentationUrl, correctiveActions } = deprecation; @@ -79,19 +90,33 @@ export const KibanaDeprecationAccordion: FunctionComponent = ({ {(documentationUrl || correctiveActions?.manualSteps) && ( + {correctiveActions?.api && ( + + showResolveModal(deprecation)} + > + {i18nTexts.resolveButtonLabel} + + + )} + {correctiveActions?.manualSteps && ( - showModal({ + showStepsModal({ domainId, steps: correctiveActions.manualSteps!, documentationUrl, }) } > - {i18nTexts.fixButtonLabel} + {i18nTexts.manualFixButtonLabel} )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx index 3f7bc96172a1c..212a7ab933524 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx @@ -15,12 +15,13 @@ import { LevelFilterOption } from '../types'; import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; import { LEVEL_MAP, DEPRECATIONS_PER_PAGE } from '../constants'; import { KibanaDeprecationAccordion } from './deprecation_item'; -import { ModalContent } from './steps_modal'; +import { StepsModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; interface Props { deprecations: DomainDeprecationDetails[]; - showModal: (newModalContent: ModalContent) => void; + showStepsModal: (newStepsModalContent: StepsModalContent) => void; + showResolveModal: (deprecation: DomainDeprecationDetails) => void; reloadDeprecations: () => Promise; isLoading: boolean; } @@ -54,7 +55,8 @@ const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetail export const KibanaDeprecationList: FunctionComponent = ({ deprecations, - showModal, + showStepsModal, + showResolveModal, reloadDeprecations, isLoading, }) => { @@ -126,7 +128,8 @@ export const KibanaDeprecationList: FunctionComponent = ({ index, deprecation, forceExpand: expandState.forceExpand, - showModal, + showStepsModal, + showResolveModal, }} /> diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 2b06da84b1dcb..458ffc3814a5f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -23,8 +23,9 @@ import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { NoDeprecationsPrompt } from '../shared'; import { KibanaDeprecationList } from './deprecation_list'; -import { StepsModal, ModalContent } from './steps_modal'; +import { StepsModal, StepsModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; +import { ResolveDeprecationModal } from './resolve_deprecation_modal'; const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { @@ -42,6 +43,12 @@ const i18nTexts = { isLoading: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.loadingText', { defaultMessage: 'Loading deprecations…', }), + successMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.successMessage', { + defaultMessage: 'Kibana deprecation resolved', + }), + errorMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.errorMessage', { + defaultMessage: 'Error resolving deprecation', + }), }; export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponentProps) => { @@ -50,9 +57,15 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent >(undefined); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(undefined); - const [modalContent, setModalContent] = useState(undefined); + const [stepsModalContent, setStepsModalContent] = useState( + undefined + ); + const [resolveModalContent, setResolveModalContent] = useState< + undefined | DomainDeprecationDetails + >(undefined); + const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); - const { deprecations, breadcrumbs, docLinks, api } = useAppContext(); + const { deprecations, breadcrumbs, docLinks, api, notifications } = useAppContext(); const getAllDeprecations = useCallback(async () => { setIsLoading(true); @@ -67,12 +80,42 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent setIsLoading(false); }, [deprecations]); - const toggleModal = (newModalContent?: ModalContent) => { - if (typeof newModalContent === 'undefined') { - setModalContent(undefined); + const toggleStepsModal = (newStepsModalContent?: StepsModalContent) => { + if (typeof newStepsModalContent === 'undefined') { + setStepsModalContent(undefined); } - setModalContent(newModalContent); + setStepsModalContent(newStepsModalContent); + }; + + const toggleResolveModal = (newResolveModalContent?: DomainDeprecationDetails) => { + if (typeof newResolveModalContent === 'undefined') { + setResolveModalContent(undefined); + } + + setResolveModalContent(newResolveModalContent); + }; + + const resolveDeprecation = async (deprecationDetails: DomainDeprecationDetails) => { + setIsResolvingDeprecation(true); + + const response = await deprecations.resolveDeprecation(deprecationDetails); + + setIsResolvingDeprecation(false); + toggleResolveModal(); + + // Handle error case + if (response.status === 'fail') { + notifications.toasts.addError(new Error(response.reason), { + title: i18nTexts.errorMessage, + }); + + return; + } + + notifications.toasts.addSuccess(i18nTexts.successMessage); + // Refetch deprecations + await getAllDeprecations(); }; useEffect(() => { @@ -111,7 +154,8 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent content = ( @@ -119,6 +163,7 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent } else if (error) { content = ; } + return (
@@ -147,8 +192,18 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent {getPageContent()} - {modalContent && ( - toggleModal()} modalContent={modalContent} /> + + {stepsModalContent && ( + toggleStepsModal()} modalContent={stepsModalContent} /> + )} + + {resolveModalContent && ( + toggleResolveModal()} + resolveDeprecation={resolveDeprecation} + isResolvingDeprecation={isResolvingDeprecation} + deprecation={resolveModalContent} + /> )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx new file mode 100644 index 0000000000000..c4bf7c0b05125 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { EuiConfirmModal } from '@elastic/eui'; +import { DomainDeprecationDetails } from 'kibana/public'; + +interface Props { + closeModal: () => void; + deprecation: DomainDeprecationDetails; + isResolvingDeprecation: boolean; + resolveDeprecation: (deprecationDetails: DomainDeprecationDetails) => Promise; +} + +const i18nTexts = { + getModalTitle: (domainId: string) => + i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.modalTitle', + { + defaultMessage: "Resolve '{domainId}'?", + values: { + domainId, + }, + } + ), + cancelButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.cancelButtonLabel', + { + defaultMessage: 'Cancel', + } + ), + resolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.resolveConfirmationModal.resolveButtonLabel', + { + defaultMessage: 'Resolve', + } + ), +}; + +export const ResolveDeprecationModal: FunctionComponent = ({ + closeModal, + deprecation, + isResolvingDeprecation, + resolveDeprecation, +}) => { + return ( + resolveDeprecation(deprecation)} + cancelButtonText={i18nTexts.cancelButtonLabel} + confirmButtonText={i18nTexts.resolveButtonLabel} + defaultFocusedButton="confirm" + isLoading={isResolvingDeprecation} + /> + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx index 953b0e051dc35..7646fcba6ad3c 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/steps_modal.tsx @@ -24,7 +24,7 @@ import { EuiFlexItem, } from '@elastic/eui'; -export interface ModalContent { +export interface StepsModalContent { domainId: string; steps: string[]; documentationUrl?: string; @@ -32,7 +32,7 @@ export interface ModalContent { interface Props { closeModal: () => void; - modalContent: ModalContent; + modalContent: StepsModalContent; } const i18nTexts = { @@ -74,7 +74,7 @@ export const StepsModal: FunctionComponent = ({ closeModal, modalContent const { domainId, steps, documentationUrl } = modalContent; return ( - + @@ -93,6 +93,7 @@ export const StepsModal: FunctionComponent = ({ closeModal, modalContent { return { title: i18nTexts.getStepTitle(index + 1), @@ -118,7 +119,7 @@ export const StepsModal: FunctionComponent = ({ closeModal, modalContent )} - + {i18nTexts.closeButtonLabel} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap index 9712a647744da..4865c5fa8eb55 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/__snapshots__/level_filter.test.tsx.snap @@ -11,19 +11,9 @@ exports[`DeprecationLevelFilter renders 1`] = ` key="critical" numFilters={1} onClick={[Function]} - withNext={true} > critical - - warning - `; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts index ef2af9d6a0dd0..0a800771e2656 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/helpers/kibana.helpers.ts @@ -55,4 +55,5 @@ export type KibanaTestSubjects = | 'kibanaPluginError' | 'kibanaDeprecationsContent' | 'kibanaDeprecationItem' - | 'kibanaRequestError'; + | 'kibanaRequestError' + | string; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts index a6192a5e42b51..a251dd9221991 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts @@ -22,11 +22,16 @@ describe('Kibana deprecations', () => { describe('With deprecations', () => { const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ { - correctiveActions: {}, - domainId: 'xpack.spaces', + correctiveActions: { + manualSteps: ['Step 1', 'Step 2', 'Step 3'], + api: { + method: 'POST', + path: '/test', + }, + }, + domainId: 'test_domain', level: 'critical', - message: - 'Disabling the spaces plugin (xpack.spaces.enabled) will not be supported in the next major version (8.0)', + message: 'Test deprecation message', }, ]; @@ -41,6 +46,8 @@ describe('Kibana deprecations', () => { deprecations: deprecationService, }); }); + + testBed.component.update(); }); test('renders deprecations', () => { @@ -48,6 +55,95 @@ describe('Kibana deprecations', () => { expect(exists('kibanaDeprecationsContent')).toBe(true); expect(find('kibanaDeprecationItem').length).toEqual(1); }); + + describe('manual steps modal', () => { + test('renders modal with a list of steps to fix a deprecation', async () => { + const { component, actions, exists, find } = testBed; + const deprecation = kibanaDeprecationsMockResponse[0]; + + expect(exists('kibanaDeprecationsContent')).toBe(true); + + // Open all deprecations + actions.clickExpandAll(); + + const accordionTestSubj = `${deprecation.domainId}Deprecation`; + + await act(async () => { + find(`${accordionTestSubj}.stepsButton`).simulate('click'); + }); + + component.update(); + + // We need to read the document "body" as the modal is added there and not inside + // the component DOM tree. + let modal = document.body.querySelector('[data-test-subj="stepsModal"]'); + + expect(modal).not.toBe(null); + expect(modal!.textContent).toContain(`Fix '${deprecation.domainId}'`); + + const steps: NodeListOf | null = modal!.querySelectorAll( + '[data-test-subj="fixDeprecationSteps"] .euiStep' + ); + + expect(steps).not.toBe(null); + expect(steps.length).toEqual(deprecation!.correctiveActions!.manualSteps!.length); + + await act(async () => { + const closeButton: HTMLButtonElement | null = modal!.querySelector( + '[data-test-subj="closeButton"]' + ); + + closeButton!.click(); + }); + + component.update(); + + // Confirm modal closed and no longer appears in the DOM + modal = document.body.querySelector('[data-test-subj="stepsModal"]'); + expect(modal).toBe(null); + }); + }); + + describe('resolve modal', () => { + test('renders confirmation modal to resolve a deprecation', async () => { + const { component, actions, exists, find } = testBed; + const deprecation = kibanaDeprecationsMockResponse[0]; + + expect(exists('kibanaDeprecationsContent')).toBe(true); + + // Open all deprecations + actions.clickExpandAll(); + + const accordionTestSubj = `${deprecation.domainId}Deprecation`; + + await act(async () => { + find(`${accordionTestSubj}.resolveButton`).simulate('click'); + }); + + component.update(); + + // We need to read the document "body" as the modal is added there and not inside + // the component DOM tree. + let modal = document.body.querySelector('[data-test-subj="resolveModal"]'); + + expect(modal).not.toBe(null); + expect(modal!.textContent).toContain(`Resolve '${deprecation.domainId}'`); + + const confirmButton: HTMLButtonElement | null = modal!.querySelector( + '[data-test-subj="confirmModalConfirmButton"]' + ); + + await act(async () => { + confirmButton!.click(); + }); + + component.update(); + + // Confirm modal should close and no longer appears in the DOM + modal = document.body.querySelector('[data-test-subj="resolveModal"]'); + expect(modal).toBe(null); + }); + }); }); describe('No deprecations', () => { From edbc2a4b320e30c29c89bb560f1534ec4a48e79b Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 22 Apr 2021 16:22:22 -0400 Subject: [PATCH 08/18] add test for error condition --- .../kibana_deprecations.tsx | 2 +- .../tests_client_integration/kibana.test.ts | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index 458ffc3814a5f..b2d018ca4544f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -44,7 +44,7 @@ const i18nTexts = { defaultMessage: 'Loading deprecations…', }), successMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.successMessage', { - defaultMessage: 'Kibana deprecation resolved', + defaultMessage: 'Deprecation resolved', }), errorMessage: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.errorMessage', { defaultMessage: 'Error resolving deprecation', diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts index a251dd9221991..16e182a7f2c06 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts @@ -186,5 +186,45 @@ describe('Kibana deprecations', () => { 'Could not retrieve Kibana deprecations.' ); }); + + test('handles deprecation service error', async () => { + const domainId = 'test'; + const kibanaDeprecationsMockResponse: DomainDeprecationDetails[] = [ + { + domainId, + message: `Failed to get deprecations info for plugin "${domainId}".`, + level: 'fetch_error', + correctiveActions: { + manualSteps: ['Check Kibana server logs for error message.'], + }, + }, + ]; + + await act(async () => { + const deprecationService = deprecationsServiceMock.createStartContract(); + deprecationService.getAllDeprecations = jest + .fn() + .mockReturnValue(kibanaDeprecationsMockResponse); + + testBed = await setupKibanaPage({ + deprecations: deprecationService, + }); + }); + + const { component, exists, find, actions } = testBed; + component.update(); + + // Verify top-level callout renders + expect(exists('kibanaPluginError')).toBe(true); + expect(find('kibanaPluginError').text()).toContain( + 'Not all Kibana deprecations were retrieved successfully.' + ); + + // Open all deprecations + actions.clickExpandAll(); + + // Verify callout also displays for deprecation with error + expect(exists(`${domainId}Error`)).toBe(true); + }); }); }); From 480b6cd300975cb988478948de1bc49ab61a7033 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 22 Apr 2021 16:23:44 -0400 Subject: [PATCH 09/18] TEMP commit: test Kibana API action --- src/plugins/timelion/server/deprecations.ts | 4 +++ .../upgrade_assistant/server/plugin.ts | 2 ++ .../upgrade_assistant/server/routes/test.ts | 35 +++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/test.ts diff --git a/src/plugins/timelion/server/deprecations.ts b/src/plugins/timelion/server/deprecations.ts index 3d4e687f154cf..9c68520f5c6e2 100644 --- a/src/plugins/timelion/server/deprecations.ts +++ b/src/plugins/timelion/server/deprecations.ts @@ -62,6 +62,10 @@ export async function getDeprecations({ 'In the toolbar, click Save.', 'On the Save visualization window, enter the visualization Title, then click Save and return.', ], + api: { + method: 'POST', + path: '/api/upgrade_assistant/test', + }, }, }); } diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index ae5975c2bc8a7..59b8ea54614c0 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -31,6 +31,7 @@ import { registerReindexIndicesRoutes, createReindexWorker } from './routes/rein import { registerTelemetryRoutes } from './routes/telemetry'; import { registerUpdateSettingsRoute } from './routes/update_index_settings'; import { telemetrySavedObjectType, reindexOperationSavedObjectType } from './saved_object_types'; +import { registerTestRoutes } from './routes/test'; import { RouteDependencies } from './types'; @@ -113,6 +114,7 @@ export class UpgradeAssistantServerPlugin implements Plugin { // Bootstrap the needed routes and the collector for the telemetry registerTelemetryRoutes(dependencies); registerUpdateSettingsRoute(dependencies); + registerTestRoutes(dependencies); if (usageCollection) { getStartServices().then(([{ savedObjects: savedObjectsService, elasticsearch }]) => { diff --git a/x-pack/plugins/upgrade_assistant/server/routes/test.ts b/x-pack/plugins/upgrade_assistant/server/routes/test.ts new file mode 100644 index 0000000000000..d87f549eeea19 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { API_BASE_PATH } from '../../common/constants'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { RouteDependencies } from '../types'; + +export function registerTestRoutes({ router }: RouteDependencies) { + router.post( + { + path: `${API_BASE_PATH}/test`, + validate: false, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + savedObjects: { client: savedObjectsClient }, + elasticsearch: { client }, + }, + }, + request, + response + ) => { + return response.ok({ + body: {}, + }); + } + ) + ); +} From 68cff12e0cf5c30da27ea150ba32c5088b78ddbd Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 22 Apr 2021 16:23:56 -0400 Subject: [PATCH 10/18] Revert "TEMP commit: test Kibana API action" This reverts commit 480b6cd300975cb988478948de1bc49ab61a7033. --- src/plugins/timelion/server/deprecations.ts | 4 --- .../upgrade_assistant/server/plugin.ts | 2 -- .../upgrade_assistant/server/routes/test.ts | 35 ------------------- 3 files changed, 41 deletions(-) delete mode 100644 x-pack/plugins/upgrade_assistant/server/routes/test.ts diff --git a/src/plugins/timelion/server/deprecations.ts b/src/plugins/timelion/server/deprecations.ts index 9c68520f5c6e2..3d4e687f154cf 100644 --- a/src/plugins/timelion/server/deprecations.ts +++ b/src/plugins/timelion/server/deprecations.ts @@ -62,10 +62,6 @@ export async function getDeprecations({ 'In the toolbar, click Save.', 'On the Save visualization window, enter the visualization Title, then click Save and return.', ], - api: { - method: 'POST', - path: '/api/upgrade_assistant/test', - }, }, }); } diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts index 59b8ea54614c0..ae5975c2bc8a7 100644 --- a/x-pack/plugins/upgrade_assistant/server/plugin.ts +++ b/x-pack/plugins/upgrade_assistant/server/plugin.ts @@ -31,7 +31,6 @@ import { registerReindexIndicesRoutes, createReindexWorker } from './routes/rein import { registerTelemetryRoutes } from './routes/telemetry'; import { registerUpdateSettingsRoute } from './routes/update_index_settings'; import { telemetrySavedObjectType, reindexOperationSavedObjectType } from './saved_object_types'; -import { registerTestRoutes } from './routes/test'; import { RouteDependencies } from './types'; @@ -114,7 +113,6 @@ export class UpgradeAssistantServerPlugin implements Plugin { // Bootstrap the needed routes and the collector for the telemetry registerTelemetryRoutes(dependencies); registerUpdateSettingsRoute(dependencies); - registerTestRoutes(dependencies); if (usageCollection) { getStartServices().then(([{ savedObjects: savedObjectsService, elasticsearch }]) => { diff --git a/x-pack/plugins/upgrade_assistant/server/routes/test.ts b/x-pack/plugins/upgrade_assistant/server/routes/test.ts deleted file mode 100644 index d87f549eeea19..0000000000000 --- a/x-pack/plugins/upgrade_assistant/server/routes/test.ts +++ /dev/null @@ -1,35 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { API_BASE_PATH } from '../../common/constants'; -import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; -import { RouteDependencies } from '../types'; - -export function registerTestRoutes({ router }: RouteDependencies) { - router.post( - { - path: `${API_BASE_PATH}/test`, - validate: false, - }, - versionCheckHandlerWrapper( - async ( - { - core: { - savedObjects: { client: savedObjectsClient }, - elasticsearch: { client }, - }, - }, - request, - response - ) => { - return response.ok({ - body: {}, - }); - } - ) - ); -} From b6f83b60a3bc7ea453281428c9b84cded8dec035 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Fri, 23 Apr 2021 11:39:59 -0400 Subject: [PATCH 11/18] update a11y tests and fix issue --- .../deprecation_tab_content.tsx | 10 ++-- .../components/overview/es_stats.tsx | 39 ++++++++++++++- .../components/overview/kibana_stats.tsx | 46 ++++++++++++++++- .../accessibility/apps/upgrade_assistant.ts | 50 ++++++++++++++++--- 4 files changed, 133 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx index 41cd48e5d401f..a83a26325eb26 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx @@ -141,10 +141,12 @@ export const DeprecationTabContent: FunctionComponent = ({ if (deprecations && deprecations.length === 0) { return ( - +
+ +
); } diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/es_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/es_stats.tsx index 51a66bdd35395..3152639d3f10d 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/es_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/es_stats.tsx @@ -16,6 +16,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIconTip, + EuiScreenReaderOnly, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -46,6 +47,16 @@ const i18nTexts = { defaultMessage: 'View deprecations', } ), + loadingText: i18n.translate('xpack.upgradeAssistant.esDeprecationStats.loadingText', { + defaultMessage: 'Loading Elasticsearch deprecation stats…', + }), + getCriticalDeprecationsMessage: (criticalDeprecations: number) => + i18n.translate('xpack.upgradeAssistant.esDeprecationStats.criticalDeprecationsLabel', { + defaultMessage: 'This cluster has {criticalDeprecations} critical deprecations', + values: { + criticalDeprecations, + }, + }), getTotalDeprecationsTooltip: (clusterCount: number, indexCount: number) => i18n.translate('xpack.upgradeAssistant.esDeprecationStats.totalDeprecationsTooltip', { defaultMessage: @@ -105,11 +116,27 @@ export const ESDeprecationStats: FunctionComponent = ({ history }) => { esDeprecations?.indices.length ?? 0 )} position="right" + iconProps={{ + tabIndex: -1, + }} /> } isLoading={isLoading} - /> + > + {error === null && ( + +

+ {isLoading + ? i18nTexts.loadingText + : i18nTexts.getTotalDeprecationsTooltip( + esDeprecations?.cluster.length ?? 0, + esDeprecations?.indices.length ?? 0 + )} +

+
+ )} + @@ -120,6 +147,16 @@ export const ESDeprecationStats: FunctionComponent = ({ history }) => { titleColor="danger" isLoading={isLoading} > + {error === null && ( + +

+ {isLoading + ? i18nTexts.loadingText + : i18nTexts.getCriticalDeprecationsMessage(criticalDeprecations.length)} +

+
+ )} + {error && }
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx index f120c73dea44c..6b4746e371dde 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx @@ -16,6 +16,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIconTip, + EuiScreenReaderOnly, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -52,6 +53,23 @@ const i18nTexts = { defaultMessage: 'An error occurred while retrieving Kibana deprecations.', } ), + loadingText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.loadingText', { + defaultMessage: 'Loading Kibana deprecation stats…', + }), + getCriticalDeprecationsMessage: (criticalDeprecations: number) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.criticalDeprecationsLabel', { + defaultMessage: 'Kibana has {criticalDeprecations} critical deprecations', + values: { + criticalDeprecations, + }, + }), + getTotalDeprecationsMessage: (totalDeprecations: number) => + i18n.translate('xpack.upgradeAssistant.kibanaDeprecationStats.totalDeprecationsLabel', { + defaultMessage: 'Kibana has {totalDeprecations} total deprecations', + values: { + totalDeprecations, + }, + }), }; interface Props { @@ -111,7 +129,17 @@ export const KibanaDeprecationStats: FunctionComponent = ({ history }) => title={error ? '--' : kibanaDeprecations?.length ?? '0'} description={i18nTexts.totalDeprecationsTitle} isLoading={isLoading} - /> + > + {error === undefined && ( + +

+ {isLoading + ? i18nTexts.loadingText + : i18nTexts.getTotalDeprecationsMessage(kibanaDeprecations?.length ?? 0)} +

+
+ )} + @@ -127,6 +155,22 @@ export const KibanaDeprecationStats: FunctionComponent = ({ history }) => titleColor="danger" isLoading={isLoading} > + {error === undefined && ( + +

+ {isLoading + ? i18nTexts.loadingText + : i18nTexts.getCriticalDeprecationsMessage( + kibanaDeprecations + ? kibanaDeprecations.filter( + (deprecation) => deprecation.level === 'critical' + )?.length ?? 0 + : 0 + )} +

+
+ )} + {error && ( <> diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 8d2774c000b29..c96b21ba21820 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -34,19 +34,57 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it('Elasticsearch cluster tab', async () => { - await testSubjects.click('esDeprecationsLink'); - await retry.waitFor('Upgrade Assistant Cluster tab to be visible', async () => { + it('Elasticsearch cluster deprecations', async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/es_deprecations/cluster', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); + + await retry.waitFor('Cluster tab to be visible', async () => { return testSubjects.exists('clusterTabContent'); }); + await a11y.testAppSnapshot(); }); - it('Elasticsearch indices tab', async () => { - await testSubjects.click('upgradeAssistantIndicesTab'); - await retry.waitFor('Upgrade Assistant Indices tab to be visible', async () => { + it('Elasticsearch index deprecations', async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/es_deprecations/indices', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); + + await retry.waitFor('Indices tab to be visible', async () => { return testSubjects.exists('indexTabContent'); }); + + await a11y.testAppSnapshot(); + }); + + it('Kibana deprecations', async () => { + await PageObjects.common.navigateToUrl( + 'management', + 'stack/upgrade_assistant/kibana_deprecations', + { + ensureCurrentUrl: false, + shouldLoginIfPrompted: false, + shouldUseHashForSubUrl: false, + } + ); + + await retry.waitFor('Kibana deprecations to be visible', async () => { + return testSubjects.exists('kibanaDeprecationsContent'); + }); + await a11y.testAppSnapshot(); }); }); From 67bd3093641ca13221f43387477c78901017b4e7 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Mon, 26 Apr 2021 10:42:05 -0400 Subject: [PATCH 12/18] add descriptions to telemetry --- .../server/lib/telemetry/usage_collector.ts | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index a03931780d51f..9bec1bf888d1e 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -131,14 +131,41 @@ export function registerUpgradeAssistantUsageCollector({ schema: { features: { deprecation_logging: { - enabled: { type: 'boolean' }, + enabled: { + type: 'boolean', + _meta: { + description: 'Whether user has enabled Elasticsearch deprecation logging', + }, + }, }, }, ui_open: { - cluster: { type: 'long' }, - indices: { type: 'long' }, - overview: { type: 'long' }, - kibana: { type: 'long' }, + cluster: { + type: 'long', + _meta: { + description: + 'Number of times a user opened the Elasticsearch cluster deprecations page', + }, + }, + indices: { + type: 'long', + _meta: { + description: + 'Number of times a user opened the Elasticsearch index deprecations page', + }, + }, + overview: { + type: 'long', + _meta: { + description: 'Number of times a user opened the overview page', + }, + }, + kibana: { + type: 'long', + _meta: { + description: 'Number of times a user opened the Kibana deprecations page', + }, + }, }, ui_reindex: { close: { type: 'long' }, From 0aa953e2e5af43c873e6a72e3f82f46c70a4f6bc Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Mon, 26 Apr 2021 12:51:41 -0400 Subject: [PATCH 13/18] update xpack_plugins.json --- .../schema/xpack_plugins.json | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 9b307002dd2df..7bd62b1a8e3ed 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -5314,7 +5314,10 @@ "deprecation_logging": { "properties": { "enabled": { - "type": "boolean" + "type": "boolean", + "_meta": { + "description": "Whether user has enabled Elasticsearch deprecation logging" + } } } } @@ -5323,16 +5326,28 @@ "ui_open": { "properties": { "cluster": { - "type": "long" + "type": "long", + "_meta": { + "description": "Number of times a user opened the Elasticsearch cluster deprecations page" + } }, "indices": { - "type": "long" + "type": "long", + "_meta": { + "description": "Number of times a user opened the Elasticsearch index deprecations page" + } }, "overview": { - "type": "long" + "type": "long", + "_meta": { + "description": "Number of times a user opened the overview page" + } }, "kibana": { - "type": "long" + "type": "long", + "_meta": { + "description": "Number of times a user opened the Kibana deprecations page" + } } } }, From 0f227f9fefbbb6f43d68846e7dc49841675cf7ec Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 27 Apr 2021 11:56:28 -0400 Subject: [PATCH 14/18] address review feedback --- .../deprecation_tab_content.tsx | 23 +++++++++---------- .../kibana_deprecations/deprecation_item.tsx | 2 +- .../kibana_deprecations/deprecation_list.tsx | 8 +++---- .../kibana_deprecations.tsx | 2 +- .../resolve_deprecation_modal.tsx | 2 +- .../components/overview/kibana_stats.tsx | 2 +- .../shared/search_bar/search_bar.tsx | 2 +- .../tests_client_integration/kibana.test.ts | 2 +- .../tests_client_integration/overview.test.ts | 2 +- 9 files changed, 22 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx index a83a26325eb26..a67949299750e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx @@ -45,8 +45,8 @@ export const filterDeps = (level: LevelFilterOption, search: string = '') => { // Change everything to lower case for a case-insensitive comparison conditions.push((dep) => { try { - const searchReg = new RegExp(search.toLowerCase()); - return Boolean(dep.message.toLowerCase().match(searchReg)); + const searchReg = new RegExp(search, 'i'); + return searchReg.test(dep.message); } catch (e) { // ignore any regexp errors. return true; @@ -59,10 +59,9 @@ export const filterDeps = (level: LevelFilterOption, search: string = '') => { }; /** - * Collection of calculated fields based on props, extracted for reuse in - * `render` and `getDerivedStateFromProps`. + * Collection of calculated fields based on props */ -const CalcFields = { +const calcFields = { filteredDeprecations(props: { deprecations: EnrichedDeprecationInfo[]; currentFilter: LevelFilterOption; @@ -78,7 +77,7 @@ const CalcFields = { search: string; currentGroupBy: GroupByOption; }) { - return groupBy(CalcFields.filteredDeprecations(props), props.currentGroupBy); + return groupBy(calcFields.filteredDeprecations(props), props.currentGroupBy); }, numPages(props: { @@ -87,7 +86,7 @@ const CalcFields = { search: string; currentGroupBy: GroupByOption; }) { - return Math.ceil(Object.keys(CalcFields.groups(props)).length / DEPRECATIONS_PER_PAGE); + return Math.ceil(Object.keys(calcFields.groups(props)).length / DEPRECATIONS_PER_PAGE); }, }; @@ -126,7 +125,7 @@ export const DeprecationTabContent: FunctionComponent = ({ useEffect(() => { if (deprecations) { - const pageCount = CalcFields.numPages({ + const pageCount = calcFields.numPages({ deprecations, currentFilter, search, @@ -159,15 +158,15 @@ export const DeprecationTabContent: FunctionComponent = ({ const deprecationLevelsCount = Object.keys(levelGroups).reduce((counts, level) => { counts[level] = levelGroups[level].length; return counts; - }, {} as { [level: string]: number }); + }, {} as Record); - const filteredDeprecations = CalcFields.filteredDeprecations({ + const filteredDeprecations = calcFields.filteredDeprecations({ deprecations, currentFilter, search, }); - const groups = CalcFields.groups({ + const groups = calcFields.groups({ deprecations, currentFilter, search, @@ -229,7 +228,7 @@ export const DeprecationTabContent: FunctionComponent = ({ { return deprecations .filter((deprecation) => { - return level === 'all' ? true : deprecation.level === level; + return level === 'all' || deprecation.level === level; }) .filter((filteredDep) => { if (search.length > 0) { try { - const searchReg = new RegExp(search.toLowerCase()); - return Boolean(filteredDep.message.toLowerCase().match(searchReg)); + const searchReg = new RegExp(search, 'i'); + return searchReg.test(filteredDep.message); } catch (e) { // ignore any regexp errors return true; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx index b2d018ca4544f..8abc22dc0b80a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DomainDeprecationDetails } from 'kibana/public'; +import type { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { NoDeprecationsPrompt } from '../shared'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx index c4bf7c0b05125..dd78c3513f973 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/resolve_deprecation_modal.tsx @@ -9,7 +9,7 @@ import React, { FunctionComponent } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiConfirmModal } from '@elastic/eui'; -import { DomainDeprecationDetails } from 'kibana/public'; +import type { DomainDeprecationDetails } from 'kibana/public'; interface Props { closeModal: () => void; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx index 6b4746e371dde..28941d1305adf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/kibana_stats.tsx @@ -21,7 +21,7 @@ import { import { i18n } from '@kbn/i18n'; import { RouteComponentProps } from 'react-router-dom'; -import { DomainDeprecationDetails } from 'kibana/public'; +import type { DomainDeprecationDetails } from 'kibana/public'; import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public'; import { useAppContext } from '../../app_context'; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx index 1b00b904db596..9dee354a53958 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx @@ -16,7 +16,7 @@ import { EuiSpacer, } from '@elastic/eui'; -import { DomainDeprecationDetails } from 'kibana/public'; +import type { DomainDeprecationDetails } from 'kibana/public'; import { DeprecationInfo } from '../../../../../common/types'; import { validateRegExpString } from '../../../lib/utils'; import { GroupByOption, LevelFilterOption } from '../../types'; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts index 16e182a7f2c06..fef0fedf4cce6 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/kibana.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DomainDeprecationDetails } from 'kibana/public'; +import type { DomainDeprecationDetails } from 'kibana/public'; import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; diff --git a/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts b/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts index a94a943188c25..5459fb4945026 100644 --- a/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts +++ b/x-pack/plugins/upgrade_assistant/tests_client_integration/overview.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DomainDeprecationDetails } from 'kibana/public'; +import type { DomainDeprecationDetails } from 'kibana/public'; import { act } from 'react-dom/test-utils'; import { deprecationsServiceMock } from 'src/core/public/mocks'; import { UpgradeAssistantStatus } from '../common/types'; From 138cd0753972b6f662402b3dcde02ca27ddf46e6 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 27 Apr 2021 12:00:51 -0400 Subject: [PATCH 15/18] remove unnecessary code comment --- .../components/es_deprecations/deprecation_tab_content.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx index a67949299750e..57429ce96068e 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx @@ -42,7 +42,6 @@ export const filterDeps = (level: LevelFilterOption, search: string = '') => { } if (search.length > 0) { - // Change everything to lower case for a case-insensitive comparison conditions.push((dep) => { try { const searchReg = new RegExp(search, 'i'); From 52fe1fdaed1f6c47e39cfbc201b14316bde538b4 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 28 Apr 2021 09:37:41 -0400 Subject: [PATCH 16/18] address review feedback --- .../deprecation_tab_content.tsx | 93 +++++++------------ .../es_deprecations/deprecations/cell.tsx | 4 +- .../kibana_deprecations/deprecation_list.tsx | 16 ++-- .../kibana_deprecation_errors.tsx | 2 +- .../kibana_deprecations.tsx | 18 ++-- .../shared/search_bar/level_filter.test.tsx | 6 +- .../shared/search_bar/level_filter.tsx | 14 +-- .../shared/search_bar/search_bar.tsx | 6 +- .../public/application/components/types.ts | 5 +- .../server/lib/telemetry/usage_collector.ts | 8 +- 10 files changed, 66 insertions(+), 106 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx index 57429ce96068e..8be407371f038 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_tab_content.tsx @@ -34,16 +34,17 @@ export interface CheckupTabProps extends UpgradeAssistantTabProps { checkupLabel: string; } -export const filterDeps = (level: LevelFilterOption, search: string = '') => { +export const createDependenciesFilter = (level: LevelFilterOption, search: string = '') => { const conditions: Array<(dep: EnrichedDeprecationInfo) => boolean> = []; - if (level !== LevelFilterOption.all) { + if (level !== 'all') { conditions.push((dep: EnrichedDeprecationInfo) => dep.level === level); } if (search.length > 0) { conditions.push((dep) => { try { + // 'i' is used for case-insensitive matching const searchReg = new RegExp(search, 'i'); return searchReg.test(dep.message); } catch (e) { @@ -57,37 +58,29 @@ export const filterDeps = (level: LevelFilterOption, search: string = '') => { return (dep: EnrichedDeprecationInfo) => conditions.map((c) => c(dep)).every((t) => t); }; -/** - * Collection of calculated fields based on props - */ -const calcFields = { - filteredDeprecations(props: { - deprecations: EnrichedDeprecationInfo[]; - currentFilter: LevelFilterOption; - search: string; - }) { - const { deprecations = [], currentFilter, search } = props; - return deprecations.filter(filterDeps(currentFilter, search)); - }, - - groups(props: { - deprecations: EnrichedDeprecationInfo[]; - currentFilter: LevelFilterOption; - search: string; - currentGroupBy: GroupByOption; - }) { - return groupBy(calcFields.filteredDeprecations(props), props.currentGroupBy); - }, - - numPages(props: { - deprecations: EnrichedDeprecationInfo[]; - currentFilter: LevelFilterOption; - search: string; - currentGroupBy: GroupByOption; - }) { - return Math.ceil(Object.keys(calcFields.groups(props)).length / DEPRECATIONS_PER_PAGE); - }, -}; +const filterDeprecations = ( + deprecations: EnrichedDeprecationInfo[] = [], + currentFilter: LevelFilterOption, + search: string +) => deprecations.filter(createDependenciesFilter(currentFilter, search)); + +const groupDeprecations = ( + deprecations: EnrichedDeprecationInfo[], + currentFilter: LevelFilterOption, + search: string, + currentGroupBy: GroupByOption +) => groupBy(filterDeprecations(deprecations, currentFilter, search), currentGroupBy); + +const getPageCount = ( + deprecations: EnrichedDeprecationInfo[], + currentFilter: LevelFilterOption, + search: string, + currentGroupBy: GroupByOption +) => + Math.ceil( + Object.keys(groupDeprecations(deprecations, currentFilter, search, currentGroupBy)).length / + DEPRECATIONS_PER_PAGE + ); /** * Displays a list of deprecations that are filterable and groupable. Can be used for cluster, @@ -101,7 +94,7 @@ export const DeprecationTabContent: FunctionComponent = ({ refreshCheckupData, navigateToOverviewPage, }) => { - const [currentFilter, setCurrentFilter] = useState(LevelFilterOption.all); + const [currentFilter, setCurrentFilter] = useState('all'); const [search, setSearch] = useState(''); const [currentGroupBy, setCurrentGroupBy] = useState(GroupByOption.message); const [expandState, setExpandState] = useState({ @@ -124,12 +117,7 @@ export const DeprecationTabContent: FunctionComponent = ({ useEffect(() => { if (deprecations) { - const pageCount = calcFields.numPages({ - deprecations, - currentFilter, - search, - currentGroupBy, - }); + const pageCount = getPageCount(deprecations, currentFilter, search, currentGroupBy); if (currentPage >= pageCount) { setCurrentPage(0); @@ -154,23 +142,14 @@ export const DeprecationTabContent: FunctionComponent = ({ content = {i18nTexts.isLoading}; } else if (deprecations?.length) { const levelGroups = groupBy(deprecations, 'level'); - const deprecationLevelsCount = Object.keys(levelGroups).reduce((counts, level) => { + const levelToDeprecationCountMap = Object.keys(levelGroups).reduce((counts, level) => { counts[level] = levelGroups[level].length; return counts; }, {} as Record); - const filteredDeprecations = calcFields.filteredDeprecations({ - deprecations, - currentFilter, - search, - }); + const filteredDeprecations = filterDeprecations(deprecations, currentFilter, search); - const groups = calcFields.groups({ - deprecations, - currentFilter, - search, - currentGroupBy, - }); + const groups = groupDeprecations(deprecations, currentFilter, search, currentGroupBy); content = (
@@ -182,7 +161,7 @@ export const DeprecationTabContent: FunctionComponent = ({ onFilterChange={setCurrentFilter} onSearchChange={setSearch} totalDeprecationsCount={deprecations.length} - deprecationLevelsCount={deprecationLevelsCount} + levelToDeprecationCountMap={levelToDeprecationCountMap} groupByFilterProps={{ availableGroupByOptions: getAvailableGroupByOptions(), currentGroupBy, @@ -218,7 +197,6 @@ export const DeprecationTabContent: FunctionComponent = ({ />
, - , ])} {/* Only show pagination if we have more than DEPRECATIONS_PER_PAGE. */} @@ -227,12 +205,7 @@ export const DeprecationTabContent: FunctionComponent = ({ diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx index f587b1507c205..b7d3247ffbf21 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecations/cell.tsx @@ -61,8 +61,8 @@ export const DeprecationCell: FunctionComponent = ({
)} - {items.map((item) => ( - + {items.map((item, index) => ( + {item.title &&
{item.title}
}

{item.body}

diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx index 3d269f2888d7e..fb61efc373acf 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_list.tsx @@ -13,7 +13,7 @@ import type { DomainDeprecationDetails } from 'kibana/public'; import { LevelFilterOption } from '../types'; import { SearchBar, DeprecationListBar, DeprecationPagination } from '../shared'; -import { LEVEL_MAP, DEPRECATIONS_PER_PAGE } from '../constants'; +import { DEPRECATIONS_PER_PAGE } from '../constants'; import { KibanaDeprecationAccordion } from './deprecation_item'; import { StepsModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; @@ -28,7 +28,7 @@ interface Props { const getFilteredDeprecations = ( deprecations: DomainDeprecationDetails[], - level: string, + level: LevelFilterOption, search: string ) => { return deprecations @@ -38,6 +38,7 @@ const getFilteredDeprecations = ( .filter((filteredDep) => { if (search.length > 0) { try { + // 'i' is used for case-insensitive matching const searchReg = new RegExp(search, 'i'); return searchReg.test(filteredDep.message); } catch (e) { @@ -49,10 +50,6 @@ const getFilteredDeprecations = ( }); }; -const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetails) => { - return -1 * (LEVEL_MAP[a.level] - LEVEL_MAP[b.level]); -}; - export const KibanaDeprecationList: FunctionComponent = ({ deprecations, showStepsModal, @@ -60,7 +57,7 @@ export const KibanaDeprecationList: FunctionComponent = ({ reloadDeprecations, isLoading, }) => { - const [currentFilter, setCurrentFilter] = useState(LevelFilterOption.all); + const [currentFilter, setCurrentFilter] = useState('all'); const [search, setSearch] = useState(''); const [expandState, setExpandState] = useState({ forceExpand: false, @@ -73,7 +70,7 @@ export const KibanaDeprecationList: FunctionComponent = ({ }; const levelGroups = groupBy(deprecations, 'level'); - const deprecationLevelsCount = Object.keys(levelGroups).reduce((counts, level) => { + const levelToDeprecationCountMap = Object.keys(levelGroups).reduce((counts, level) => { counts[level] = levelGroups[level].length; return counts; }, {} as { [level: string]: number }); @@ -98,7 +95,7 @@ export const KibanaDeprecationList: FunctionComponent = ({ onFilterChange={setCurrentFilter} onSearchChange={setSearch} totalDeprecationsCount={deprecations.length} - deprecationLevelsCount={deprecationLevelsCount} + levelToDeprecationCountMap={levelToDeprecationCountMap} /> {deprecationsWithErrors.length > 0 && ( @@ -119,7 +116,6 @@ export const KibanaDeprecationList: FunctionComponent = ({ <> {filteredDeprecations .slice(currentPage * DEPRECATIONS_PER_PAGE, (currentPage + 1) * DEPRECATIONS_PER_PAGE) - .sort(sortByLevelDesc) .map((deprecation, index) => [
{ + return -1 * (LEVEL_MAP[a.level] - LEVEL_MAP[b.level]); +}; + export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponentProps) => { const [kibanaDeprecations, setKibanaDeprecations] = useState< DomainDeprecationDetails[] | undefined @@ -72,7 +77,8 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent try { const response = await deprecations.getAllDeprecations(); - setKibanaDeprecations(response); + const sortedDeprecations = response.sort(sortByLevelDesc); + setKibanaDeprecations(sortedDeprecations); } catch (e) { setError(e); } @@ -81,18 +87,10 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent }, [deprecations]); const toggleStepsModal = (newStepsModalContent?: StepsModalContent) => { - if (typeof newStepsModalContent === 'undefined') { - setStepsModalContent(undefined); - } - setStepsModalContent(newStepsModalContent); }; const toggleResolveModal = (newResolveModalContent?: DomainDeprecationDetails) => { - if (typeof newResolveModalContent === 'undefined') { - setResolveModalContent(undefined); - } - setResolveModalContent(newResolveModalContent); }; @@ -115,7 +113,7 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent notifications.toasts.addSuccess(i18nTexts.successMessage); // Refetch deprecations - await getAllDeprecations(); + getAllDeprecations(); }; useEffect(() => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx index f64b099993899..c778e56e8df11 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.test.tsx @@ -7,8 +7,8 @@ import { mount, shallow } from 'enzyme'; import React from 'react'; - import { LevelFilterOption } from '../../types'; + import { DeprecationLevelFilter } from './level_filter'; const defaultProps = { @@ -16,7 +16,7 @@ const defaultProps = { warning: 4, critical: 1, }, - currentFilter: LevelFilterOption.all, + currentFilter: 'all' as LevelFilterOption, onFilterChange: jest.fn(), }; @@ -29,6 +29,6 @@ describe('DeprecationLevelFilter', () => { const wrapper = mount(); wrapper.find('button[data-test-subj="criticalLevelFilter"]').simulate('click'); expect(defaultProps.onFilterChange).toHaveBeenCalledTimes(1); - expect(defaultProps.onFilterChange.mock.calls[0][0]).toEqual(LevelFilterOption.critical); + expect(defaultProps.onFilterChange.mock.calls[0][0]).toEqual('critical'); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx index f149accf04540..108087e2ae992 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/level_filter.tsx @@ -41,19 +41,15 @@ export const DeprecationLevelFilter: React.FunctionComponent { - onFilterChange( - currentFilter !== LevelFilterOption.critical - ? LevelFilterOption.critical - : LevelFilterOption.all - ); + onFilterChange(currentFilter !== 'critical' ? 'critical' : 'all'); }} - hasActiveFilters={currentFilter === LevelFilterOption.critical} - numFilters={levelsCount[LevelFilterOption.critical] || undefined} + hasActiveFilters={currentFilter === 'critical'} + numFilters={levelsCount.critical || undefined} data-test-subj="criticalLevelFilter" > - {LocalizedOptions[LevelFilterOption.critical]} + {LocalizedOptions.critical} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx index 9dee354a53958..7c805398a6b47 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/shared/search_bar/search_bar.tsx @@ -31,7 +31,7 @@ interface SearchBarProps { onFilterChange: (filter: LevelFilterOption) => void; onSearchChange: (filter: string) => void; totalDeprecationsCount: number; - deprecationLevelsCount: { + levelToDeprecationCountMap: { [key: string]: number; }; groupByFilterProps?: { @@ -67,7 +67,7 @@ const i18nTexts = { export const SearchBar: FunctionComponent = ({ totalDeprecationsCount, - deprecationLevelsCount, + levelToDeprecationCountMap, isLoading, loadData, currentFilter, @@ -108,7 +108,7 @@ export const SearchBar: FunctionComponent = ({ Date: Wed, 28 Apr 2021 09:52:31 -0400 Subject: [PATCH 17/18] fix telemetry --- .../telemetry_collection_xpack/schema/xpack_plugins.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 7bd62b1a8e3ed..d2fbbf147efd5 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -5328,25 +5328,25 @@ "cluster": { "type": "long", "_meta": { - "description": "Number of times a user opened the Elasticsearch cluster deprecations page" + "description": "Number of times a user viewed the list of Elasticsearch cluster deprecations." } }, "indices": { "type": "long", "_meta": { - "description": "Number of times a user opened the Elasticsearch index deprecations page" + "description": "Number of times a user viewed the list of Elasticsearch index deprecations." } }, "overview": { "type": "long", "_meta": { - "description": "Number of times a user opened the overview page" + "description": "Number of times a user viewed the Overview page." } }, "kibana": { "type": "long", "_meta": { - "description": "Number of times a user opened the Kibana deprecations page" + "description": "Number of times a user viewed the list of Kibana deprecations" } } } From 59412ce74c55897802153b94afc017c7c7a08794 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 28 Apr 2021 10:00:22 -0400 Subject: [PATCH 18/18] update copy --- .../kibana_deprecations/kibana_deprecation_errors.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx index 8484ddb74fec5..e6ba83919c31b 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecation_errors.tsx @@ -21,7 +21,8 @@ const i18nTexts = { loadingError: i18n.translate( 'xpack.upgradeAssistant.kibanaDeprecationErrors.loadingErrorMessage', { - defaultMessage: 'Could not retrieve Kibana deprecations.', + defaultMessage: + 'Could not retrieve Kibana deprecations. Check the Kibana server logs for errors.', } ), };