kibana/x-pack/plugins/upgrade_assistant/public/application/components/tabs.tsx
Jean-Louis Leysens 899270a108
[Upgrade Assistant] Move out of legacy folder (#58034)
* Create x-pack/plugins skeleton for upgrade assistant

* Move public folder contents

Move the public folder of Upgrade Assistant and migrate public to use HttpSetup (remove axios)

* Include stylesheets in public

* Move server side out of legacy

Begin migration of Reindex worker to new platform

Move imports around so that it satsifies new platform constraints like not importing
server side code (even types) in client.

* Updated the routes with new dependencies and removed server shim

* Fix router unit tests

* Fix server lib tests

After changing function signatures for the reindex server factory (and others) all
of the tests needed to be revisited and brought in line with the new APIs.

Also used core/server mocks where appropriate

* Clean up types issues

* Fix setting credentials on request header

* Removed the security plugin from Upgrade Assistant

The security plugin is a potential future consumer of the Upgrade Assistant's deprecation feature
and we would therefore not want to create a circular depedency here. We pull in the licensing plugin
rather (as it is less likely that we will depend on that) and use it to determine whether security
is available and enabled.

* Migrate to config to new platform config

xpack.upgrade_assistant.enabled

* Remove unused types

* Fix import issue

* Move upgrade assistant back to Elasticsearch management section

* Update dotfiles

Added elasticsearch ui team as upgrade assistant code owner
Updated i18nrc.json path

* Alphabetical ordering in xpack/i18nrc.json

* Implemented PR feedback

Renamed callCluster -> callAsUser to be more consistent
with platform naming.

Added comment about why we are not using security plugin
directly inside of Upgrade Assistant.

Fixed long path imports and use 'src/core/..' throughout.

Fixed import ordering.

Renamed variables inside of telemetry lib.

* Revert to longer import path

In plugin.ts importing from 'kibana/server' or 'src/core/server'
results in a module not found error.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
2020-02-25 15:31:04 +01:00

253 lines
7.8 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { findIndex, get, set } from 'lodash';
import React from 'react';
import {
EuiEmptyPrompt,
EuiPageContent,
EuiPageContentBody,
EuiTabbedContent,
EuiTabbedContentTab,
} from '@elastic/eui';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import { HttpSetup } from 'src/core/public';
import { UpgradeAssistantStatus } from '../../../common/types';
import { LatestMinorBanner } from './latest_minor_banner';
import { CheckupTab } from './tabs/checkup';
import { OverviewTab } from './tabs/overview';
import { LoadingState, TelemetryState, UpgradeAssistantTabProps } from './types';
enum ClusterUpgradeState {
needsUpgrade,
partiallyUpgraded,
upgraded,
}
interface TabsState {
loadingState: LoadingState;
loadingError?: Error;
checkupData?: UpgradeAssistantStatus;
selectedTabIndex: number;
telemetryState: TelemetryState;
clusterUpgradeState: ClusterUpgradeState;
}
type Props = ReactIntl.InjectedIntlProps & { http: HttpSetup };
export class UpgradeAssistantTabsUI extends React.Component<Props, TabsState> {
constructor(props: Props) {
super(props);
this.state = {
loadingState: LoadingState.Loading,
clusterUpgradeState: ClusterUpgradeState.needsUpgrade,
selectedTabIndex: 0,
telemetryState: TelemetryState.Complete,
};
}
public async componentDidMount() {
await this.loadData();
// Send telemetry info about the default selected tab
this.sendTelemetryInfo(this.tabs[this.state.selectedTabIndex].id);
}
public render() {
const { selectedTabIndex, telemetryState, clusterUpgradeState } = this.state;
const tabs = this.tabs;
if (clusterUpgradeState === ClusterUpgradeState.partiallyUpgraded) {
return (
<EuiPageContent>
<EuiPageContentBody>
<EuiEmptyPrompt
iconType="logoElasticsearch"
title={
<h2>
<FormattedMessage
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradingTitle"
defaultMessage="Your cluster is upgrading"
/>
</h2>
}
body={
<p>
<FormattedMessage
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradingDescription"
defaultMessage="One or more Elasticsearch nodes have a newer version of
Elasticsearch than Kibana. Once all your nodes are upgraded, upgrade Kibana."
/>
</p>
}
/>
</EuiPageContentBody>
</EuiPageContent>
);
} else if (clusterUpgradeState === ClusterUpgradeState.upgraded) {
return (
<EuiPageContent>
<EuiPageContentBody>
<EuiEmptyPrompt
iconType="logoElasticsearch"
title={
<h2>
<FormattedMessage
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradeCompleteTitle"
defaultMessage="Your cluster has been upgraded"
/>
</h2>
}
body={
<p>
<FormattedMessage
id="xpack.upgradeAssistant.tabs.upgradingInterstitial.upgradeCompleteDescription"
defaultMessage="All Elasticsearch nodes have been upgraded. You may now upgrade Kibana."
/>
</p>
}
/>
</EuiPageContentBody>
</EuiPageContent>
);
}
return (
<EuiTabbedContent
data-test-subj={
telemetryState === TelemetryState.Running ? 'upgradeAssistantTelemetryRunning' : undefined
}
tabs={tabs}
onTabClick={this.onTabClick}
selectedTab={tabs[selectedTabIndex]}
/>
);
}
private onTabClick = (selectedTab: EuiTabbedContentTab) => {
const selectedTabIndex = findIndex(this.tabs, { id: selectedTab.id });
if (selectedTabIndex === -1) {
throw new Error(`Clicked tab did not exist in tabs array`);
}
// Send telemetry info about the current selected tab
// only in case the clicked tab id it's different from the
// current selected tab id
if (this.tabs[this.state.selectedTabIndex].id !== selectedTab.id) {
this.sendTelemetryInfo(selectedTab.id);
}
this.setSelectedTabIndex(selectedTabIndex);
};
private setSelectedTabIndex = (selectedTabIndex: number) => {
this.setState({ selectedTabIndex });
};
private loadData = async () => {
try {
this.setState({ loadingState: LoadingState.Loading });
const resp = await this.props.http.get('/api/upgrade_assistant/status');
this.setState({
loadingState: LoadingState.Success,
checkupData: resp,
});
} catch (e) {
if (get(e, 'response.status') === 426) {
this.setState({
loadingState: LoadingState.Success,
clusterUpgradeState: get(e, 'response.data.attributes.allNodesUpgraded', false)
? ClusterUpgradeState.upgraded
: ClusterUpgradeState.partiallyUpgraded,
});
} else {
this.setState({ loadingState: LoadingState.Error, loadingError: e });
}
}
};
private get tabs() {
const { intl } = this.props;
const { loadingError, loadingState, checkupData } = this.state;
const commonProps: UpgradeAssistantTabProps = {
loadingError,
loadingState,
refreshCheckupData: this.loadData,
setSelectedTabIndex: this.setSelectedTabIndex,
// Remove this in last minor of the current major (eg. 6.7)
alertBanner: <LatestMinorBanner />,
};
return [
{
id: 'overview',
name: intl.formatMessage({
id: 'xpack.upgradeAssistant.overviewTab.overviewTabTitle',
defaultMessage: 'Overview',
}),
content: <OverviewTab checkupData={checkupData} {...commonProps} />,
},
{
id: 'cluster',
name: intl.formatMessage({
id: 'xpack.upgradeAssistant.checkupTab.clusterTabLabel',
defaultMessage: 'Cluster',
}),
content: (
<CheckupTab
key="cluster"
deprecations={checkupData ? checkupData.cluster : undefined}
checkupLabel={intl.formatMessage({
id: 'xpack.upgradeAssistant.tabs.checkupTab.clusterLabel',
defaultMessage: 'cluster',
})}
{...commonProps}
/>
),
},
{
id: 'indices',
name: intl.formatMessage({
id: 'xpack.upgradeAssistant.checkupTab.indicesTabLabel',
defaultMessage: 'Indices',
}),
content: (
<CheckupTab
key="indices"
deprecations={checkupData ? checkupData.indices : undefined}
checkupLabel={intl.formatMessage({
id: 'xpack.upgradeAssistant.checkupTab.indexLabel',
defaultMessage: 'index',
})}
showBackupWarning
{...commonProps}
/>
),
},
];
}
private async sendTelemetryInfo(tabName: string) {
// In case we don't have any data yet, we wanna to ignore the
// telemetry info update
if (this.state.loadingState !== LoadingState.Success) {
return;
}
this.setState({ telemetryState: TelemetryState.Running });
await this.props.http.fetch('/api/upgrade_assistant/telemetry/ui_open', {
method: 'PUT',
body: JSON.stringify(set({}, tabName, true)),
});
this.setState({ telemetryState: TelemetryState.Complete });
}
}
export const UpgradeAssistantTabs = injectI18n(UpgradeAssistantTabsUI);