From 8385fc6449a76410bbea2e67f5f30214d6728fae Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 18 Aug 2021 13:59:20 -0400 Subject: [PATCH 1/2] wip - new kibana deprecations list design --- .../kibana_deprecations.tsx | 60 +++---- .../kibana_deprecations_table.tsx | 156 ++++++++++++++++++ .../public/application/lib/breadcrumbs.ts | 2 +- 3 files changed, 187 insertions(+), 31 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx 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 31b5c80d5b377..16545f55c6bab 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 @@ -8,27 +8,39 @@ import React, { useEffect, useState, useCallback } from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { EuiButtonEmpty, EuiPageContent, EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { EuiPageContent, EuiPageHeader, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import type { DomainDeprecationDetails } from 'kibana/public'; import { SectionLoading } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { NoDeprecationsPrompt } from '../shared'; -import { KibanaDeprecationList } from './deprecation_list'; +import { LEVEL_MAP } from '../constants'; import { StepsModal, StepsModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; import { ResolveDeprecationModal } from './resolve_deprecation_modal'; -import { LEVEL_MAP } from '../constants'; +import { KibanaDeprecationsTable } from './kibana_deprecations_table'; const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { - defaultMessage: 'Kibana', - }), - pageDescription: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageDescription', { - defaultMessage: - 'Review the issues listed here and make the necessary changes before upgrading. Critical issues must be resolved before you upgrade.', + defaultMessage: 'Kibana deprecation warnings', }), + pageDescription: ( + + {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.quickResolveText', { + defaultMessage: 'Quick Resolve', + })} + + ), + }} + /> + ), docLinkText: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.docLinkText', { defaultMessage: 'Documentation', }), @@ -64,7 +76,7 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent >(undefined); const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); - const { deprecations, breadcrumbs, docLinks, api, notifications } = useAppContext(); + const { deprecations, breadcrumbs, api, notifications } = useAppContext(); const getAllDeprecations = useCallback(async () => { setIsLoading(true); @@ -145,36 +157,22 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent {i18nTexts.isLoading} ); - } else if (kibanaDeprecations?.length) { + } + + if (kibanaDeprecations?.length) { return (
- {i18nTexts.docLinkText} - , - ]} /> - + - {stepsModalContent && ( + {/* {stepsModalContent && ( toggleStepsModal()} modalContent={stepsModalContent} /> )} @@ -185,10 +183,12 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent isResolvingDeprecation={isResolvingDeprecation} deprecation={resolveModalContent} /> - )} + )} */}
); - } else if (error) { + } + + if (error) { return ; } diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx new file mode 100644 index 0000000000000..b3b31c238c6d6 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx @@ -0,0 +1,156 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { + EuiInMemoryTable, + EuiBasicTableColumn, + EuiButton, + EuiLink, + EuiBadge, +} from '@elastic/eui'; + +import type { DomainDeprecationDetails } from 'kibana/public'; + +const i18nTexts = { + refreshButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.refreshButtonLabel', + { + defaultMessage: 'Refresh', + } + ), + statusColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.statusColumnTitle', + { + defaultMessage: 'Status', + } + ), + issueColumnTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.issueColumnTitle', + { + defaultMessage: 'Issue', + } + ), + getDeprecationIssue: (domainId: string) => { + return i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.table.issueCellDescription', { + defaultMessage: '{domainId} is using a deprecated feature', + values: { + domainId, + }, + }); + }, + criticalBadgeLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.criticalBadgeLabel', + { + defaultMessage: 'critical', + } + ), + searchPlaceholderLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.table.searchPlaceholderLabel', + { + defaultMessage: 'Filter', + } + ), +}; + +interface Props { + deprecations?: DomainDeprecationDetails[]; + reload: () => void; +} + +export const KibanaDeprecationsTable: React.FunctionComponent = ({ + deprecations, + reload, +}) => { + const columns: Array> = [ + { + field: 'level', + name: i18nTexts.statusColumnTitle, + width: '5%', + truncateText: true, + sortable: true, + render: (level: DomainDeprecationDetails['level']) => { + if (level === 'critical') { + return {i18nTexts.criticalBadgeLabel}; + } + + return <>{''}; + }, + }, + { + field: 'domainId', + width: '95%', + name: i18nTexts.issueColumnTitle, + truncateText: true, + sortable: true, + render: (domainId: DomainDeprecationDetails['domainId']) => { + // TODO update to handle opening flyout + return {i18nTexts.getDeprecationIssue(domainId)}; + }, + }, + ]; + + const pagination = { + initialPageSize: 50, + pageSizeOptions: [50, 100, 200], + }; + + const sorting = { + sort: { + field: 'level', + direction: 'asc', + }, + } as const; + + const searchConfig = { + // TODO fix + // query: {}, + filters: [ + { + type: 'is', + field: 'level', + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.isManagedFilterLabel', { + defaultMessage: 'Critical', + }), + }, + ], + box: { + incremental: true, + placeholder: i18nTexts.searchPlaceholderLabel, + }, + toolsRight: [ + + {i18nTexts.refreshButtonLabel} + , + ], + }; + + return ( + ({ + 'data-test-subj': 'row', + })} + cellProps={() => ({ + 'data-test-subj': 'cell', + })} + data-test-subj="kibanaDeprecationsTable" + tableLayout="auto" + /> + ); +}; 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 00359988d5e2a..5c989ad236805 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/breadcrumbs.ts @@ -21,7 +21,7 @@ const i18nTexts = { kibanaDeprecations: i18n.translate( 'xpack.upgradeAssistant.breadcrumb.kibanaDeprecationsLabel', { - defaultMessage: 'Kibana deprecations', + defaultMessage: 'Kibana deprecation warnings', } ), }, From 2ad2e204d616db00b0bbd89fc27fced9e8a681d2 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 18 Aug 2021 15:35:22 -0400 Subject: [PATCH 2/2] implement flyout --- .../public/application/app.tsx | 8 +- .../deprecation_details_flyout.tsx | 163 ++++++++++++++++++ .../kibana_deprecations.tsx | 113 ++++++------ .../kibana_deprecations_table.tsx | 7 +- .../public/shared_imports.ts | 1 + 5 files changed, 236 insertions(+), 56 deletions(-) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx index b1571b9e45461..f2c7cd0397b4a 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/app.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -10,6 +10,8 @@ import { Router, Switch, Route, Redirect } from 'react-router-dom'; import { I18nStart, ScopedHistory } from 'src/core/public'; import { ApplicationStart } from 'kibana/public'; +import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; +import { GlobalFlyout } from '../shared_imports'; import { KibanaContextProvider } from '../shared_imports'; import { AppServicesContext } from '../types'; import { AppContextProvider, ContextValue, useAppContext } from './app_context'; @@ -17,8 +19,8 @@ import { ComingSoonPrompt } from './components/coming_soon_prompt'; import { EsDeprecationsContent } from './components/es_deprecations'; import { KibanaDeprecationsContent } from './components/kibana_deprecations'; import { Overview } from './components/overview'; -import { RedirectAppLinks } from '../../../../../src/plugins/kibana_react/public'; +const { GlobalFlyoutProvider } = GlobalFlyout; export interface AppDependencies extends ContextValue { i18n: I18nStart; history: ScopedHistory; @@ -64,7 +66,9 @@ export const RootComponent = ({ - + + + diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx new file mode 100644 index 0000000000000..47f821cbfdf6b --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/deprecation_details_flyout.tsx @@ -0,0 +1,163 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiButtonEmpty, + EuiButton, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiText, + EuiCallOut, + EuiLink, + EuiSpacer, +} from '@elastic/eui'; + +import type { DomainDeprecationDetails } from 'kibana/public'; + +export interface DeprecationDetailsFlyoutProps { + deprecation: DomainDeprecationDetails; + closeFlyout: () => void; +} + +const i18nTexts = { + learnMoreLinkLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.learnMoreLinkLabel', + { + defaultMessage: 'Learn more about this deprecation', + } + ), + closeButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.closeButtonLabel', + { + defaultMessage: 'Close', + } + ), + quickResolveButtonLabel: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveButtonLabel', + { + defaultMessage: 'Quick resolve', + } + ), + quickResolveCalloutTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveCalloutTitle', + { + defaultMessage: 'Quick resolve action available', + } + ), + quickResolveCalloutDescription: ( + + {i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.flyout.quickResolveText', { + defaultMessage: 'Quick resolve', + })} + + ), + }} + /> + ), + manualFixTitle: i18n.translate( + 'xpack.upgradeAssistant.kibanaDeprecations.flyout.manualFixTitle', + { + defaultMessage: 'Fix manually', + } + ), +}; + +export const DeprecationDetailsFlyout = ({ + deprecation, + closeFlyout, +}: DeprecationDetailsFlyoutProps) => { + const { documentationUrl, message, correctiveActions } = deprecation; + + return ( + <> + + +

Deprecation title goes here...

+
+
+ + +

{message}

+ + {documentationUrl && ( +

+ + {i18nTexts.learnMoreLinkLabel} + +

+ )} +
+ + + + {correctiveActions.api && ( + <> + +

{i18nTexts.quickResolveCalloutDescription}

+
+ + + + )} + + +

{i18nTexts.manualFixTitle}

+
+ + + + +
    + {correctiveActions.manualSteps.map((step, stepIndex) => ( + // TODO temp inline style +
  1. + {step} +
  2. + ))} +
+
+
+ + + + + {i18nTexts.closeButtonLabel} + + + + {/* Only show the Quick resolve button if deprecation supports it */} + {correctiveActions.api && ( + + {/* TODO implement onClick */} + {}}> + {i18nTexts.quickResolveButtonLabel} + + + )} + + + + ); +}; 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 16545f55c6bab..ef31752b7c375 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 @@ -13,14 +13,17 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import type { DomainDeprecationDetails } from 'kibana/public'; -import { SectionLoading } from '../../../shared_imports'; +import { SectionLoading, GlobalFlyout } from '../../../shared_imports'; import { useAppContext } from '../../app_context'; import { NoDeprecationsPrompt } from '../shared'; -import { LEVEL_MAP } from '../constants'; -import { StepsModal, StepsModalContent } from './steps_modal'; import { KibanaDeprecationErrors } from './kibana_deprecation_errors'; -import { ResolveDeprecationModal } from './resolve_deprecation_modal'; import { KibanaDeprecationsTable } from './kibana_deprecations_table'; +import { + DeprecationDetailsFlyout, + DeprecationDetailsFlyoutProps, +} from './deprecation_details_flyout'; + +const { useGlobalFlyout } = GlobalFlyout; const i18nTexts = { pageTitle: i18n.translate('xpack.upgradeAssistant.kibanaDeprecations.pageTitle', { @@ -58,33 +61,25 @@ const i18nTexts = { }), }; -const sortByLevelDesc = (a: DomainDeprecationDetails, b: DomainDeprecationDetails) => { - return -1 * (LEVEL_MAP[a.level] - LEVEL_MAP[b.level]); -}; - export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponentProps) => { const [kibanaDeprecations, setKibanaDeprecations] = useState< DomainDeprecationDetails[] | undefined >(undefined); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(undefined); - const [stepsModalContent, setStepsModalContent] = useState( + const [flyoutContent, setFlyoutContent] = useState( undefined ); - const [resolveModalContent, setResolveModalContent] = useState< - undefined | DomainDeprecationDetails - >(undefined); - const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); + // const [isResolvingDeprecation, setIsResolvingDeprecation] = useState(false); - const { deprecations, breadcrumbs, api, notifications } = useAppContext(); + const { deprecations, breadcrumbs, api } = useAppContext(); const getAllDeprecations = useCallback(async () => { setIsLoading(true); try { const response = await deprecations.getAllDeprecations(); - const sortedDeprecations = response.sort(sortByLevelDesc); - setKibanaDeprecations(sortedDeprecations); + setKibanaDeprecations(response); } catch (e) { setError(e); } @@ -92,35 +87,60 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent setIsLoading(false); }, [deprecations]); - const toggleStepsModal = (newStepsModalContent?: StepsModalContent) => { - setStepsModalContent(newStepsModalContent); + const toggleFlyout = (newFlyoutContent?: DomainDeprecationDetails) => { + setFlyoutContent(newFlyoutContent); }; - const toggleResolveModal = (newResolveModalContent?: DomainDeprecationDetails) => { - setResolveModalContent(newResolveModalContent); - }; + const { + addContent: addContentToGlobalFlyout, + removeContent: removeContentFromGlobalFlyout, + } = useGlobalFlyout(); - const resolveDeprecation = async (deprecationDetails: DomainDeprecationDetails) => { - setIsResolvingDeprecation(true); + const closeFlyout = useCallback(() => { + toggleFlyout(); + removeContentFromGlobalFlyout('deprecationDetails'); + }, [removeContentFromGlobalFlyout]); - const response = await deprecations.resolveDeprecation(deprecationDetails); + useEffect(() => { + if (flyoutContent) { + addContentToGlobalFlyout({ + id: 'deprecationDetails', + Component: DeprecationDetailsFlyout, + props: { + deprecation: flyoutContent, + closeFlyout, + }, + flyoutProps: { + onClose: closeFlyout, + 'data-test-subj': 'kibanaDeprecationDetails', + 'aria-labelledby': 'kibanaDeprecationDetailsFlyoutTitle', + }, + }); + } + }, [addContentToGlobalFlyout, closeFlyout, flyoutContent]); - setIsResolvingDeprecation(false); - toggleResolveModal(); + // TODO finish implementing + // const resolveDeprecation = async (deprecationDetails: DomainDeprecationDetails) => { + // setIsResolvingDeprecation(true); - // Handle error case - if (response.status === 'fail') { - notifications.toasts.addError(new Error(response.reason), { - title: i18nTexts.errorMessage, - }); + // const response = await deprecations.resolveDeprecation(deprecationDetails); - return; - } + // setIsResolvingDeprecation(false); + // // toggleResolveModal(); - notifications.toasts.addSuccess(i18nTexts.successMessage); - // Refetch deprecations - getAllDeprecations(); - }; + // // 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 + // getAllDeprecations(); + // }; useEffect(() => { async function sendTelemetryData() { @@ -170,20 +190,11 @@ export const KibanaDeprecationsContent = withRouter(({ history }: RouteComponent - - - {/* {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/kibana_deprecations_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx index b3b31c238c6d6..b37c4b0725a52 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/kibana_deprecations/kibana_deprecations_table.tsx @@ -60,11 +60,13 @@ const i18nTexts = { interface Props { deprecations?: DomainDeprecationDetails[]; reload: () => void; + toggleFlyout: (newFlyoutContent?: DomainDeprecationDetails) => void; } export const KibanaDeprecationsTable: React.FunctionComponent = ({ deprecations, reload, + toggleFlyout }) => { const columns: Array> = [ { @@ -87,9 +89,8 @@ export const KibanaDeprecationsTable: React.FunctionComponent = ({ name: i18nTexts.issueColumnTitle, truncateText: true, sortable: true, - render: (domainId: DomainDeprecationDetails['domainId']) => { - // TODO update to handle opening flyout - return {i18nTexts.getDeprecationIssue(domainId)}; + render: (domainId: DomainDeprecationDetails['domainId'], deprecation: DomainDeprecationDetails) => { + return toggleFlyout(deprecation)}>{i18nTexts.getDeprecationIssue(domainId)}; }, }, ]; diff --git a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts index c3ffd44662ec2..64b52065f63e6 100644 --- a/x-pack/plugins/upgrade_assistant/public/shared_imports.ts +++ b/x-pack/plugins/upgrade_assistant/public/shared_imports.ts @@ -15,6 +15,7 @@ export { useRequest, UseRequestConfig, SectionLoading, + GlobalFlyout, } from '../../../../src/plugins/es_ui_shared/public/'; export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';