diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js index c6da347ed8cf..4fe3d5c66696 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js @@ -253,6 +253,9 @@ describe('edit policy', () => { beforeEach(() => { server.respondImmediately = true; httpRequestsMockHelpers.setNodesListResponse({}); + httpRequestsMockHelpers.setNodesDetailsResponse('attribute:true', [ + { nodeId: 'testNodeId', stats: { name: 'testNodeName', host: 'testHost' } }, + ]); }); test('should show number required error when trying to save empty warm phase', async () => { @@ -395,7 +398,9 @@ describe('edit policy', () => { rendered.update(); const flyoutButton = findTestSubject(rendered, 'warm-viewNodeDetailsFlyoutButton'); expect(flyoutButton.exists()).toBeTruthy(); - flyoutButton.simulate('click'); + await act(async () => { + await flyoutButton.simulate('click'); + }); rendered.update(); expect(rendered.find('.euiFlyout').exists()).toBeTruthy(); }); @@ -404,6 +409,9 @@ describe('edit policy', () => { beforeEach(() => { server.respondImmediately = true; httpRequestsMockHelpers.setNodesListResponse({}); + httpRequestsMockHelpers.setNodesDetailsResponse('attribute:true', [ + { nodeId: 'testNodeId', stats: { name: 'testNodeName', host: 'testHost' } }, + ]); }); test('should allow 0 for phase timing', async () => { const rendered = mountWithIntl(component); @@ -470,7 +478,9 @@ describe('edit policy', () => { rendered.update(); const flyoutButton = findTestSubject(rendered, 'cold-viewNodeDetailsFlyoutButton'); expect(flyoutButton.exists()).toBeTruthy(); - flyoutButton.simulate('click'); + await act(async () => { + await flyoutButton.simulate('click'); + }); rendered.update(); expect(rendered.find('.euiFlyout').exists()).toBeTruthy(); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts b/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts index b5c941beef18..668cbedbf0c9 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/helpers/http_requests.ts @@ -25,9 +25,18 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setNodesDetailsResponse = (nodeAttributes: string, response: HttpResponse = []) => { + server.respondWith(`/api/index_lifecycle_management/nodes/${nodeAttributes}/details`, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(response), + ]); + }; + return { setPoliciesResponse, setNodesListResponse, + setNodesDetailsResponse, }; }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js index d5c0744e5eb0..200bf0e767d9 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js @@ -34,7 +34,6 @@ import { SetPriorityInput } from '../set_priority_input'; export class ColdPhase extends PureComponent { static propTypes = { setPhaseData: PropTypes.func.isRequired, - showNodeDetailsFlyout: PropTypes.func.isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, @@ -42,7 +41,6 @@ export class ColdPhase extends PureComponent { render() { const { setPhaseData, - showNodeDetailsFlyout, phaseData, errors, isShowingErrors, @@ -114,7 +112,6 @@ export class ColdPhase extends PureComponent { void; - showNodeDetailsFlyout: (nodeAttrs: any) => void; errors: any; phaseData: any; isShowingErrors: boolean; @@ -48,13 +48,16 @@ const learnMoreLink = ( export const NodeAllocation: React.FunctionComponent = ({ phase, setPhaseData, - showNodeDetailsFlyout, errors, phaseData, isShowingErrors, }) => { const { isLoading, data: nodes, error, sendRequest } = useLoadNodes(); + const [selectedNodeAttrsForDetails, setSelectedNodeAttrsForDetails] = useState( + null + ); + if (isLoading) { return ( @@ -162,7 +165,7 @@ export const NodeAllocation: React.FunctionComponent = ({ data-test-subj={`${phase}-viewNodeDetailsFlyoutButton`} flush="left" iconType="eye" - onClick={() => showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} + onClick={() => setSelectedNodeAttrsForDetails(phaseData[PHASE_NODE_ATTRS])} > = ({ ) : null} {learnMoreLink} + + {selectedNodeAttrsForDetails ? ( + setSelectedNodeAttrsForDetails(null)} + /> + ) : null} ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.ts similarity index 78% rename from x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.ts index 885e965c46c4..056d2f2f600f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { NodeAttrsDetails } from './node_attrs_details.container'; +export { NodeAttrsDetails } from './node_attrs_details'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js deleted file mode 100644 index ca7c310723b6..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; - -import { getNodeDetails } from '../../../../store/selectors'; -import { fetchNodeDetails } from '../../../../store/actions'; -import { NodeAttrsDetails as PresentationComponent } from './node_attrs_details'; - -export const NodeAttrsDetails = connect( - (state, ownProps) => ({ - details: getNodeDetails(state, ownProps.selectedNodeAttrs), - }), - { fetchNodeDetails } -)(PresentationComponent); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js deleted file mode 100644 index 67bc8f0386ab..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiFlyoutBody, - EuiFlyout, - EuiTitle, - EuiInMemoryTable, - EuiSpacer, - EuiPortal, -} from '@elastic/eui'; - -export class NodeAttrsDetails extends PureComponent { - static propTypes = { - fetchNodeDetails: PropTypes.func.isRequired, - close: PropTypes.func.isRequired, - - details: PropTypes.array, - selectedNodeAttrs: PropTypes.string.isRequired, - }; - - UNSAFE_componentWillMount() { - this.props.fetchNodeDetails(this.props.selectedNodeAttrs); - } - - render() { - const { selectedNodeAttrs, details, close } = this.props; - - return ( - - - - -

- -

-
- - -
-
-
- ); - } -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.tsx new file mode 100644 index 000000000000..6fcbd94dc5e9 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiFlyoutBody, + EuiFlyout, + EuiTitle, + EuiInMemoryTable, + EuiSpacer, + EuiPortal, + EuiLoadingContent, + EuiCallOut, + EuiButton, +} from '@elastic/eui'; + +import { useLoadNodeDetails } from '../../../../services/api'; + +interface Props { + close: () => void; + selectedNodeAttrs: string; +} + +export const NodeAttrsDetails: React.FunctionComponent = ({ close, selectedNodeAttrs }) => { + const { data, isLoading, error, sendRequest } = useLoadNodeDetails(selectedNodeAttrs); + let content; + if (isLoading) { + content = ; + } else if (error) { + const { statusCode, message } = error; + content = ( + + } + color="danger" + > +

+ {message} ({statusCode}) +

+ + + +
+ ); + } else { + content = ( + + ); + } + return ( + + + + +

+ +

+
+ + {content} +
+
+
+ ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js index 55aec88c8bca..60b5ab4781b6 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js @@ -38,7 +38,6 @@ import { MinAgeInput } from '../min_age_input'; export class WarmPhase extends PureComponent { static propTypes = { setPhaseData: PropTypes.func.isRequired, - showNodeDetailsFlyout: PropTypes.func.isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, @@ -47,7 +46,6 @@ export class WarmPhase extends PureComponent { render() { const { setPhaseData, - showNodeDetailsFlyout, phaseData, errors, isShowingErrors, @@ -152,7 +150,6 @@ export class WarmPhase extends PureComponent { { - this.setState({ isShowingNodeDetailsFlyout: true, selectedNodeAttrsForDetails }); - }; - togglePolicyJsonFlyout = () => { this.setState(({ isShowingPolicyJsonFlyout }) => ({ isShowingPolicyJsonFlyout: !isShowingPolicyJsonFlyout, @@ -291,7 +284,6 @@ export class EditPolicy extends Component { @@ -299,7 +291,6 @@ export class EditPolicy extends Component { @@ -370,13 +361,6 @@ export class EditPolicy extends Component { - {this.state.isShowingNodeDetailsFlyout ? ( - this.setState({ isShowingNodeDetailsFlyout: false })} - /> - ) : null} - {this.state.isShowingPolicyJsonFlyout ? ( { }); }; -export async function loadNodeDetails(selectedNodeAttrs: string) { - return await sendGet(`nodes/${selectedNodeAttrs}/details`); -} +export const useLoadNodeDetails = (selectedNodeAttrs: string) => { + return useRequest({ + path: `nodes/${selectedNodeAttrs}/details`, + method: 'get', + }); +}; export async function loadIndexTemplates() { return await sendGet(`templates`); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js index 0b4026f01921..3f1c00db621a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js @@ -3,33 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { createAction } from 'redux-actions'; -import { showApiError } from '../../services/api_errors'; -import { loadNodeDetails } from '../../services/api'; import { SET_SELECTED_NODE_ATTRS } from '../../constants'; export const setSelectedNodeAttrs = createAction(SET_SELECTED_NODE_ATTRS); export const setSelectedPrimaryShardCount = createAction('SET_SELECTED_PRIMARY_SHARED_COUNT'); export const setSelectedReplicaCount = createAction('SET_SELECTED_REPLICA_COUNT'); - -export const fetchedNodeDetails = createAction( - 'FETCHED_NODE_DETAILS', - (selectedNodeAttrs, details) => ({ - selectedNodeAttrs, - details, - }) -); -export const fetchNodeDetails = (selectedNodeAttrs) => async (dispatch) => { - let details; - try { - details = await loadNodeDetails(selectedNodeAttrs); - } catch (err) { - const title = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.nodeDetailErrorMessage', { - defaultMessage: 'Error loading node attribute details', - }); - showApiError(err, title); - return false; - } - dispatch(fetchedNodeDetails(selectedNodeAttrs, details)); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js index 06d173e9901f..383e61b5aacd 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js @@ -5,12 +5,7 @@ */ import { handleActions } from 'redux-actions'; -import { - setSelectedNodeAttrs, - setSelectedPrimaryShardCount, - setSelectedReplicaCount, - fetchedNodeDetails, -} from '../actions/nodes'; +import { setSelectedPrimaryShardCount, setSelectedReplicaCount } from '../actions'; const defaultState = { isLoading: false, @@ -23,22 +18,6 @@ const defaultState = { export const nodes = handleActions( { - [fetchedNodeDetails](state, { payload }) { - const { selectedNodeAttrs, details } = payload; - return { - ...state, - details: { - ...state.details, - [selectedNodeAttrs]: details, - }, - }; - }, - [setSelectedNodeAttrs](state, { payload: selectedNodeAttrs }) { - return { - ...state, - selectedNodeAttrs, - }; - }, [setSelectedPrimaryShardCount](state, { payload }) { let selectedPrimaryShardCount = parseInt(payload); if (isNaN(selectedPrimaryShardCount)) { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js index 561681bf7d93..72bfd4b15a78 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js @@ -10,17 +10,3 @@ export const getSelectedPrimaryShardCount = (state) => state.nodes.selectedPrima export const getSelectedReplicaCount = (state) => state.nodes.selectedReplicaCount !== undefined ? state.nodes.selectedReplicaCount : 1; - -export const getSelectedNodeAttrs = (state) => state.nodes.selectedNodeAttrs; - -export const getNodesFromSelectedNodeAttrs = (state) => { - const nodes = getNodes(state)[getSelectedNodeAttrs(state)]; - if (nodes) { - return nodes.length; - } - return null; -}; - -export const getNodeDetails = (state, selectedNodeAttrs) => { - return state.nodes.details[selectedNodeAttrs]; -}; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 05f709f04aa8..c796aacda10a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8206,7 +8206,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "シャードの割当をコントロールするノード属性を選択", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingDescription": "ノード属性なしではシャードの割り当てをコントロールできません。", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "elasticsearch.yml でノード属性が構成されていません", - "xpack.indexLifecycleMgmt.editPolicy.nodeDetailErrorMessage": "ノード属性の詳細の読み込み中にエラーが発生しました", "xpack.indexLifecycleMgmt.editPolicy.numberRequiredError": "数字が必要です。", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel": "コールドフェーズのタイミング", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel": "コールドフェーズのタイミングの単位", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index bd0066eeb419..4c48a66b3c3c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8208,7 +8208,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "选择节点属性来控制分片分配", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingDescription": "没有节点属性,将无法控制分片分配。", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "elasticsearch.yml 中未配置任何节点属性", - "xpack.indexLifecycleMgmt.editPolicy.nodeDetailErrorMessage": "加载节点属性详细信息时出错", "xpack.indexLifecycleMgmt.editPolicy.numberRequiredError": "数字必填。", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeLabel": "冷阶段计时", "xpack.indexLifecycleMgmt.editPolicy.phaseCold.minimumAgeUnitsAriaLabel": "冷阶段计时单位",