From 00d2955b565b62420bd8dc7cef1978785490129b Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 2 Jul 2020 08:52:49 +0200 Subject: [PATCH 01/11] [ML] Refactor list action buttons so modals won't unmount after button click. --- .../transform_list/action_clone.tsx | 16 +- .../transform_list/action_delete.tsx | 201 ++++++++++++------ .../components/transform_list/action_edit.tsx | 50 +++-- .../transform_list/action_start.tsx | 110 ++++++---- .../components/transform_list/action_stop.tsx | 20 +- .../transform_list/actions.test.tsx | 21 -- .../components/transform_list/actions.tsx | 105 ++++++--- .../components/transform_list/columns.tsx | 8 +- .../transform_list/transform_list.tsx | 48 ++++- 9 files changed, 370 insertions(+), 209 deletions(-) delete mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx index aa78dfb4315f9..4686ede7bc2c2 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx @@ -7,7 +7,7 @@ import React, { FC, useContext } from 'react'; import { useHistory } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; -import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; import { createCapabilityFailureMessage, @@ -20,7 +20,7 @@ interface CloneActionProps { itemId: string; } -export const CloneAction: FC = ({ itemId }) => { +export const CloneButton: FC = ({ itemId }) => { const history = useHistory(); const { canCreateTransform } = useContext(AuthorizationContext).capabilities; @@ -34,17 +34,15 @@ export const CloneAction: FC = ({ itemId }) => { } const cloneButton = ( - - {buttonCloneText} - + {buttonCloneText} + ); if (!canCreateTransform) { diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx index 79a9e45e317e5..6fc1cbd26fd6e 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx @@ -4,14 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, Fragment, useContext, useMemo, useState } from 'react'; +import React, { FC, useContext, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EUI_MODAL_CONFIRM_BUTTON, - EuiButtonEmpty, EuiConfirmModal, EuiFlexGroup, EuiFlexItem, + EuiIcon, + EuiLink, EuiOverlayMask, EuiSpacer, EuiSwitch, @@ -26,50 +27,20 @@ import { } from '../../../../lib/authorization'; import { TransformListRow } from '../../../../common'; -interface DeleteActionProps { +interface DeleteButtonProps { items: TransformListRow[]; forceDisable?: boolean; + onClick: (items: TransformListRow[]) => void; } const transformCanNotBeDeleted = (i: TransformListRow) => ![TRANSFORM_STATE.STOPPED, TRANSFORM_STATE.FAILED].includes(i.stats.state); -export const DeleteAction: FC = ({ items, forceDisable }) => { +export const DeleteButton: FC = ({ items, forceDisable, onClick }) => { const isBulkAction = items.length > 1; const disabled = items.some(transformCanNotBeDeleted); - const shouldForceDelete = useMemo( - () => items.some((i: TransformListRow) => i.stats.state === TRANSFORM_STATE.FAILED), - [items] - ); const { canDeleteTransform } = useContext(AuthorizationContext).capabilities; - const deleteTransforms = useDeleteTransforms(); - const { - userCanDeleteIndex, - deleteDestIndex, - indexPatternExists, - deleteIndexPattern, - toggleDeleteIndex, - toggleDeleteIndexPattern, - } = useDeleteIndexAndTargetIndex(items); - - const [isModalVisible, setModalVisible] = useState(false); - - const closeModal = () => setModalVisible(false); - const deleteAndCloseModal = () => { - setModalVisible(false); - - const shouldDeleteDestIndex = userCanDeleteIndex && deleteDestIndex; - const shouldDeleteDestIndexPattern = - userCanDeleteIndex && indexPatternExists && deleteIndexPattern; - // if we are deleting multiple transforms, then force delete all if at least one item has failed - // else, force delete only when the item user picks has failed - const forceDelete = isBulkAction - ? shouldForceDelete - : items[0] && items[0] && items[0].stats.state === TRANSFORM_STATE.FAILED; - deleteTransforms(items, shouldDeleteDestIndex, shouldDeleteDestIndexPattern, forceDelete); - }; - const openModal = () => setModalVisible(true); const buttonDeleteText = i18n.translate('xpack.transform.transformList.deleteActionName', { defaultMessage: 'Delete', @@ -86,6 +57,67 @@ export const DeleteAction: FC = ({ items, forceDisable }) => defaultMessage: 'Stop the transform in order to delete it.', } ); + + const buttonDisabled = forceDisable === true || disabled || !canDeleteTransform; + let deleteButton = ( + onClick(items)} + aria-label={buttonDeleteText} + > + {buttonDeleteText} + + ); + + if (disabled || !canDeleteTransform) { + let content; + if (disabled) { + content = isBulkAction ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; + } else { + content = createCapabilityFailureMessage('canDeleteTransform'); + } + + deleteButton = ( + + {deleteButton} + + ); + } + + return deleteButton; +}; + +type DeleteButtonModalProps = Pick< + DeleteAction, + | 'closeModal' + | 'deleteAndCloseModal' + | 'deleteDestIndex' + | 'deleteIndexPattern' + | 'indexPatternExists' + | 'isModalVisible' + | 'items' + | 'shouldForceDelete' + | 'toggleDeleteIndex' + | 'toggleDeleteIndexPattern' + | 'userCanDeleteIndex' +>; +export const DeleteButtonModal: FC = ({ + closeModal, + deleteAndCloseModal, + deleteDestIndex, + deleteIndexPattern, + indexPatternExists, + isModalVisible, + items, + shouldForceDelete, + toggleDeleteIndex, + toggleDeleteIndexPattern, + userCanDeleteIndex, +}) => { + const isBulkAction = items.length > 1; + const bulkDeleteModalTitle = i18n.translate( 'xpack.transform.transformList.bulkDeleteModalTitle', { @@ -203,42 +235,12 @@ export const DeleteAction: FC = ({ items, forceDisable }) => ); - let deleteButton = ( - - {buttonDeleteText} - - ); - - if (disabled || !canDeleteTransform) { - let content; - if (disabled) { - content = isBulkAction ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; - } else { - content = createCapabilityFailureMessage('canDeleteTransform'); - } - - deleteButton = ( - - {deleteButton} - - ); - } - return ( - - {deleteButton} + <> {isModalVisible && ( = ({ items, forceDisable }) => )} - + ); }; + +type DeleteAction = ReturnType; +export const useDeleteAction = () => { + const deleteTransforms = useDeleteTransforms(); + + const [isModalVisible, setModalVisible] = useState(false); + const [items, setItems] = useState([]); + + const isBulkAction = items.length > 1; + const shouldForceDelete = useMemo( + () => items.some((i: TransformListRow) => i.stats.state === TRANSFORM_STATE.FAILED), + [items] + ); + + const closeModal = () => setModalVisible(false); + + const { + userCanDeleteIndex, + deleteDestIndex, + indexPatternExists, + deleteIndexPattern, + toggleDeleteIndex, + toggleDeleteIndexPattern, + } = useDeleteIndexAndTargetIndex(items); + + const deleteAndCloseModal = () => { + setModalVisible(false); + + const shouldDeleteDestIndex = userCanDeleteIndex && deleteDestIndex; + const shouldDeleteDestIndexPattern = + userCanDeleteIndex && indexPatternExists && deleteIndexPattern; + // if we are deleting multiple transforms, then force delete all if at least one item has failed + // else, force delete only when the item user picks has failed + const forceDelete = isBulkAction + ? shouldForceDelete + : items[0] && items[0] && items[0].stats.state === TRANSFORM_STATE.FAILED; + deleteTransforms(items, shouldDeleteDestIndex, shouldDeleteDestIndexPattern, forceDelete); + }; + + const openModal = (newItems: TransformListRow[]) => { + // EUI issue: Might trigger twice, one time as an array, + // one time as a single object. See https://github.com/elastic/eui/issues/3679 + if (Array.isArray(newItems)) { + setItems(newItems); + setModalVisible(true); + } + }; + + return { + closeModal, + deleteAndCloseModal, + deleteDestIndex, + deleteIndexPattern, + indexPatternExists, + isModalVisible, + items, + openModal, + shouldForceDelete, + toggleDeleteIndex, + toggleDeleteIndexPattern, + userCanDeleteIndex, + }; +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx index dfb4cd443e904..e094a582a73ba 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx @@ -8,7 +8,7 @@ import React, { useContext, useState, FC } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; import { TransformPivotConfig } from '../../../../common'; import { @@ -16,35 +16,27 @@ import { AuthorizationContext, } from '../../../../lib/authorization'; -import { EditTransformFlyout } from '../edit_transform_flyout'; - -interface EditActionProps { +interface EditButtonProps { config: TransformPivotConfig; + onClick: (config: TransformPivotConfig) => void; } - -export const EditAction: FC = ({ config }) => { +export const EditButton: FC = ({ config, onClick }) => { const { canCreateTransform } = useContext(AuthorizationContext).capabilities; - const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); - const closeFlyout = () => setIsFlyoutVisible(false); - const showFlyout = () => setIsFlyoutVisible(true); - const buttonEditText = i18n.translate('xpack.transform.transformList.editActionName', { defaultMessage: 'Edit', }); const editButton = ( - onClick(config)} aria-label={buttonEditText} > - {buttonEditText} - + {buttonEditText} + ); if (!canCreateTransform) { @@ -57,10 +49,22 @@ export const EditAction: FC = ({ config }) => { ); } - return ( - <> - {editButton} - {isFlyoutVisible && } - - ); + return editButton; +}; + +export const useEditAction = () => { + const [config, setConfig] = useState(); + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + const closeFlyout = () => setIsFlyoutVisible(false); + const showFlyout = (newConfig: TransformPivotConfig) => { + setConfig(newConfig); + setIsFlyoutVisible(true); + }; + + return { + config, + closeFlyout, + isFlyoutVisible, + showFlyout, + }; }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx index 9edfe7fab70a0..7bfd3d5db80bd 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, FC, useContext, useState } from 'react'; +import React, { FC, useContext, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiButtonEmpty, EuiConfirmModal, + EuiIcon, + EuiLink, EuiOverlayMask, EuiToolTip, EUI_MODAL_CONFIRM_BUTTON, @@ -23,24 +24,14 @@ import { } from '../../../../lib/authorization'; import { TransformListRow, isCompletedBatchTransform } from '../../../../common'; -interface StartActionProps { +interface StartButtonProps { items: TransformListRow[]; forceDisable?: boolean; + onClick: (items: TransformListRow[]) => void; } - -export const StartAction: FC = ({ items, forceDisable }) => { - const isBulkAction = items.length > 1; +export const StartButton: FC = ({ items, forceDisable, onClick }) => { const { canStartStopTransform } = useContext(AuthorizationContext).capabilities; - const startTransforms = useStartTransforms(); - - const [isModalVisible, setModalVisible] = useState(false); - - const closeModal = () => setModalVisible(false); - const startAndCloseModal = () => { - setModalVisible(false); - startTransforms(items); - }; - const openModal = () => setModalVisible(true); + const isBulkAction = items.length > 1; const buttonStartText = i18n.translate('xpack.transform.transformList.startActionName', { defaultMessage: 'Start', @@ -87,24 +78,11 @@ export const StartAction: FC = ({ items, forceDisable }) => { ); } - const actionIsDisabled = !canStartStopTransform || completedBatchTransform || startedTransform; - - let startButton = ( - - {buttonStartText} - - ); + const actionIsDisabled = + !canStartStopTransform || completedBatchTransform || startedTransform || items.length === 0; - if (actionIsDisabled) { - let content; + let content: string | undefined; + if (actionIsDisabled && items.length > 0) { if (!canStartStopTransform) { content = createCapabilityFailureMessage('canStartStopTransform'); } else if (completedBatchTransform) { @@ -112,13 +90,40 @@ export const StartAction: FC = ({ items, forceDisable }) => { } else if (startedTransform) { content = startedTransformMessage; } + } + + const disabled = forceDisable === true || actionIsDisabled; - startButton = ( + const startButton = ( + onClick(items)} + > + {buttonStartText} + + ); + if (disabled && content !== undefined) { + return ( {startButton} ); } + return startButton; +}; + +type StartButtonModalProps = Pick< + StartAction, + 'closeModal' | 'isModalVisible' | 'items' | 'startAndCloseModal' +>; +export const StartButtonModal: FC = ({ + closeModal, + isModalVisible, + items, + startAndCloseModal, +}) => { + const isBulkAction = items.length > 1; const bulkStartModalTitle = i18n.translate('xpack.transform.transformList.bulkStartModalTitle', { defaultMessage: 'Start {count} {count, plural, one {transform} other {transforms}}?', @@ -130,8 +135,7 @@ export const StartAction: FC = ({ items, forceDisable }) => { }); return ( - - {startButton} + <> {isModalVisible && ( = ({ items, forceDisable }) => { )} - + ); }; + +type StartAction = ReturnType; +export const useStartAction = () => { + const startTransforms = useStartTransforms(); + + const [isModalVisible, setModalVisible] = useState(false); + const [items, setItems] = useState([]); + + const closeModal = () => setModalVisible(false); + + const startAndCloseModal = () => { + setModalVisible(false); + startTransforms(items); + }; + + const openModal = (newItems: TransformListRow[]) => { + // EUI issue: Might trigger twice, one time as an array, + // one time as a single object. See https://github.com/elastic/eui/issues/3679 + if (Array.isArray(newItems)) { + setItems(newItems); + setModalVisible(true); + } + }; + + return { + closeModal, + isModalVisible, + items, + openModal, + startAndCloseModal, + }; +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.tsx index 3f35bef458951..2c67ea3e83ecc 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.tsx @@ -6,7 +6,7 @@ import React, { FC, useContext } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; import { TRANSFORM_STATE } from '../../../../../../common'; @@ -17,12 +17,11 @@ import { } from '../../../../lib/authorization'; import { useStopTransforms } from '../../../../hooks'; -interface StopActionProps { +interface StopButtonProps { items: TransformListRow[]; forceDisable?: boolean; } - -export const StopAction: FC = ({ items, forceDisable }) => { +export const StopButton: FC = ({ items, forceDisable }) => { const isBulkAction = items.length > 1; const { canStartStopTransform } = useContext(AuthorizationContext).capabilities; const stopTransforms = useStopTransforms(); @@ -57,18 +56,17 @@ export const StopAction: FC = ({ items, forceDisable }) => { stopTransforms(items); }; + const disabled = forceDisable === true || !canStartStopTransform || stoppedTransform === true; + const stopButton = ( - - {buttonStopText} - + {buttonStopText} + ); if (!canStartStopTransform || stoppedTransform) { return ( diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx deleted file mode 100644 index 18d324c8767c7..0000000000000 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx +++ /dev/null @@ -1,21 +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 { getActions } from './actions'; - -jest.mock('../../../../../shared_imports'); - -describe('Transform: Transform List Actions', () => { - test('getActions()', () => { - const actions = getActions({ forceDisable: false }); - - expect(actions).toHaveLength(4); - expect(typeof actions[0].render).toBe('function'); - expect(typeof actions[1].render).toBe('function'); - expect(typeof actions[2].render).toBe('function'); - expect(typeof actions[3].render).toBe('function'); - }); -}); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx index 343b5e4db67e3..cc732060081aa 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx @@ -5,41 +5,92 @@ */ import React from 'react'; +import { pick } from 'lodash'; + +import { EuiTableActionsColumnType } from '@elastic/eui'; import { TRANSFORM_STATE } from '../../../../../../common'; import { TransformListRow } from '../../../../common'; -import { CloneAction } from './action_clone'; -import { DeleteAction } from './action_delete'; -import { EditAction } from './action_edit'; -import { StartAction } from './action_start'; -import { StopAction } from './action_stop'; +import { CloneButton } from './action_clone'; +import { useDeleteAction, DeleteButton, DeleteButtonModal } from './action_delete'; +import { EditTransformFlyout } from '../edit_transform_flyout'; +import { useEditAction, EditButton } from './action_edit'; +import { useStartAction, StartButton, StartButtonModal } from './action_start'; +import { StopButton } from './action_stop'; + +export const useActions = ({ + forceDisable, +}: { + forceDisable: boolean; +}): { actions: EuiTableActionsColumnType['actions']; modals: JSX.Element } => { + const deleteAction = useDeleteAction(); + const editAction = useEditAction(); + const startAction = useStartAction(); -export const getActions = ({ forceDisable }: { forceDisable: boolean }) => { - return [ - { - render: (item: TransformListRow) => { - if (item.stats.state === TRANSFORM_STATE.STOPPED) { - return ; - } - return ; + return { + modals: ( + <> + + {editAction.config && editAction.isFlyoutVisible && ( + + )} + + + ), + actions: [ + { + render: (item: TransformListRow) => { + if (item.stats.state === TRANSFORM_STATE.STOPPED) { + return ( + + ); + } + return ; + }, }, - }, - { - render: (item: TransformListRow) => { - return ; + { + render: (item: TransformListRow) => { + return ; + }, }, - }, - { - render: (item: TransformListRow) => { - return ; + { + render: (item: TransformListRow) => { + return ; + }, }, - }, - { - render: (item: TransformListRow) => { - return ; + { + render: (item: TransformListRow) => { + return ( + + ); + }, }, - }, - ]; + ], + }; }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx index 5ed2566e8a194..ee577d71095d7 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx @@ -30,7 +30,7 @@ import { TransformStats, TRANSFORM_LIST_COLUMN, } from '../../../../common'; -import { getActions } from './actions'; +import { useActions } from './actions'; enum STATE_COLOR { aborting = 'warning', @@ -64,12 +64,12 @@ export const getTaskStateBadge = ( ); }; -export const getColumns = ( +export const useColumns = ( expandedRowItemIds: TransformId[], setExpandedRowItemIds: React.Dispatch>, transformSelection: TransformListRow[] ) => { - const actions = getActions({ forceDisable: transformSelection.length > 0 }); + const { actions, modals } = useActions({ forceDisable: transformSelection.length > 0 }); function toggleDetails(item: TransformListRow) { const index = expandedRowItemIds.indexOf(item.config.id); @@ -228,5 +228,5 @@ export const getColumns = ( }, ]; - return columns; + return { columns, modals }; }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx index b1eea4a09fca3..12f253afe89f3 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx @@ -5,6 +5,7 @@ */ import React, { MouseEventHandler, FC, useContext, useState } from 'react'; +import { pick } from 'lodash'; import { i18n } from '@kbn/i18n'; @@ -36,12 +37,12 @@ import { AuthorizationContext } from '../../../../lib/authorization'; import { CreateTransformButton } from '../create_transform_button'; import { RefreshTransformListButton } from '../refresh_transform_list_button'; import { getTaskStateBadge } from './columns'; -import { DeleteAction } from './action_delete'; -import { StartAction } from './action_start'; -import { StopAction } from './action_stop'; +import { useDeleteAction, DeleteButton, DeleteButtonModal } from './action_delete'; +import { useStartAction, StartButton, StartButtonModal } from './action_start'; +import { StopButton } from './action_stop'; import { ItemIdToExpandedRowMap, Clause, TermClause, FieldClause, Value } from './common'; -import { getColumns } from './columns'; +import { useColumns } from './columns'; import { ExpandedRow } from './expanded_row'; function getItemIdToExpandedRowMap( @@ -90,6 +91,8 @@ export const TransformList: FC = ({ const [transformSelection, setTransformSelection] = useState([]); const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(false); + const bulkStartAction = useStartAction(); + const bulkDeleteAction = useDeleteAction(); const [searchError, setSearchError] = useState(undefined); @@ -185,6 +188,12 @@ export const TransformList: FC = ({ setIsLoading(false); }; + const { columns, modals: singleActionModals } = useColumns( + expandedRowItemIds, + setExpandedRowItemIds, + transformSelection + ); + // Before the transforms have been loaded for the first time, display the loading indicator only. // Otherwise a user would see 'No transforms found' during the initial loading. if (!isInitialized) { @@ -231,8 +240,6 @@ export const TransformList: FC = ({ ); } - const columns = getColumns(expandedRowItemIds, setExpandedRowItemIds, transformSelection); - const sorting = { sort: { field: sortField, @@ -252,13 +259,13 @@ export const TransformList: FC = ({ const bulkActionMenuItems = [
- +
,
- +
,
- +
, ]; @@ -375,6 +382,29 @@ export const TransformList: FC = ({ return (
+ {/* Bulk Action Modals */} + + + + {/* Single Action Modals */} + {singleActionModals} + Date: Thu, 2 Jul 2020 16:40:55 +0200 Subject: [PATCH 02/11] [ML] Update tests. --- .../components/transform_list/action_delete.test.tsx | 12 ++++++------ .../components/transform_list/action_start.test.tsx | 12 ++++++------ .../components/transform_list/action_stop.test.tsx | 11 +++++------ .../components/transform_list/columns.test.tsx | 9 ++++++--- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx index fdd0b821f54fd..1d69791b923e0 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx @@ -5,10 +5,10 @@ */ import { shallow } from 'enzyme'; -import React from 'react'; +import React, { ComponentProps } from 'react'; import { TransformListRow } from '../../../../common'; -import { DeleteAction } from './action_delete'; +import { DeleteButton } from './action_delete'; import transformListRow from '../../../../common/__mocks__/transform_list_row.json'; @@ -18,13 +18,13 @@ jest.mock('../../../../../app/app_dependencies'); describe('Transform: Transform List Actions ', () => { test('Minimal initialization', () => { const item: TransformListRow = transformListRow; - const props = { - disabled: false, + const props: ComponentProps = { + forceDisable: false, items: [item], - deleteTransform(d: TransformListRow) {}, + onClick: () => {}, }; - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx index 2de115236c4dc..33d7ca7d97602 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx @@ -5,10 +5,10 @@ */ import { shallow } from 'enzyme'; -import React from 'react'; +import React, { ComponentProps } from 'react'; import { TransformListRow } from '../../../../common'; -import { StartAction } from './action_start'; +import { StartButton } from './action_start'; import transformListRow from '../../../../common/__mocks__/transform_list_row.json'; @@ -18,13 +18,13 @@ jest.mock('../../../../../app/app_dependencies'); describe('Transform: Transform List Actions ', () => { test('Minimal initialization', () => { const item: TransformListRow = transformListRow; - const props = { - disabled: false, + const props: ComponentProps = { + forceDisable: false, items: [item], - startTransform(d: TransformListRow) {}, + onClick: () => {}, }; - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx index a97097d909848..8803c8aefa622 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx @@ -5,10 +5,10 @@ */ import { shallow } from 'enzyme'; -import React from 'react'; +import React, { ComponentProps } from 'react'; import { TransformListRow } from '../../../../common'; -import { StopAction } from './action_stop'; +import { StopButton } from './action_stop'; import transformListRow from '../../../../common/__mocks__/transform_list_row.json'; @@ -18,13 +18,12 @@ jest.mock('../../../../../app/app_dependencies'); describe('Transform: Transform List Actions ', () => { test('Minimal initialization', () => { const item: TransformListRow = transformListRow; - const props = { - disabled: false, + const props: ComponentProps = { + forceDisable: false, items: [item], - stopTransform(d: TransformListRow) {}, }; - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx index 3c75c33caf840..964ee3f517876 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx @@ -4,13 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getColumns } from './columns'; +import { renderHook } from '@testing-library/react-hooks'; + +import { useColumns } from './columns'; jest.mock('../../../../../shared_imports'); describe('Transform: Job List Columns', () => { - test('getColumns()', () => { - const columns = getColumns([], () => {}, []); + test('useColumns()', () => { + const { result } = renderHook(() => useColumns([], () => {}, [])); + const columns: ReturnType['columns'] = result.current.columns; expect(columns).toHaveLength(7); expect(columns[0].isExpander).toBeTruthy(); From 1b72310f957542e5b2286e11c1d27fad0ad5b62f Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 2 Jul 2020 17:29:03 +0200 Subject: [PATCH 03/11] [ML] Rename hook files. --- .../transform_list/use_actions.test.tsx | 24 +++++++++++++++++++ .../{actions.tsx => use_actions.tsx} | 4 ++-- ...{columns.test.tsx => use_columns.test.tsx} | 2 +- .../{columns.tsx => use_columns.tsx} | 4 ++-- 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx rename x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/{actions.tsx => use_actions.tsx} (94%) rename x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/{columns.test.tsx => use_columns.test.tsx} (95%) rename x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/{columns.tsx => use_columns.tsx} (98%) diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx new file mode 100644 index 0000000000000..5c5d3017ac871 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { renderHook } from '@testing-library/react-hooks'; + +import { useActions } from './use_actions'; + +jest.mock('../../../../../shared_imports'); + +describe('Transform: Transform List Actions', () => { + test('useActions()', () => { + const { result } = renderHook(() => useActions({ forceDisable: false })); + const actions: ReturnType['actions'] = result.current.actions; + + expect(actions).toHaveLength(4); + expect(typeof actions[0].render).toBe('function'); + expect(typeof actions[1].render).toBe('function'); + expect(typeof actions[2].render).toBe('function'); + expect(typeof actions[3].render).toBe('function'); + }); +}); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx similarity index 94% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx index cc732060081aa..2b97b2367c64e 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { pick } from 'lodash'; -import { EuiTableActionsColumnType } from '@elastic/eui'; +import { EuiTableComputedColumnType } from '@elastic/eui'; import { TRANSFORM_STATE } from '../../../../../../common'; @@ -24,7 +24,7 @@ export const useActions = ({ forceDisable, }: { forceDisable: boolean; -}): { actions: EuiTableActionsColumnType['actions']; modals: JSX.Element } => { +}): { actions: Array>; modals: JSX.Element } => { const deleteAction = useDeleteAction(); const editAction = useEditAction(); const startAction = useStartAction(); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx similarity index 95% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx index 964ee3f517876..1f57e6e377798 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx @@ -6,7 +6,7 @@ import { renderHook } from '@testing-library/react-hooks'; -import { useColumns } from './columns'; +import { useColumns } from './use_columns'; jest.mock('../../../../../shared_imports'); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.tsx similarity index 98% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.tsx index ee577d71095d7..d2d8c7084941d 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.tsx @@ -30,7 +30,7 @@ import { TransformStats, TRANSFORM_LIST_COLUMN, } from '../../../../common'; -import { useActions } from './actions'; +import { useActions } from './use_actions'; enum STATE_COLOR { aborting = 'warning', @@ -223,7 +223,7 @@ export const useColumns = ( }, { name: i18n.translate('xpack.transform.tableActionLabel', { defaultMessage: 'Actions' }), - actions, + actions: actions as EuiTableActionsColumnType['actions'], width: '80px', }, ]; From bb91e7dba18bdc53c9c8119c50c467010caed0b0 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 2 Jul 2020 18:00:51 +0200 Subject: [PATCH 04/11] [ML] Updated file structure. --- .../clone_button.tsx} | 0 .../components/action_clone/index.ts | 7 + .../delete_button.test.tsx} | 2 +- .../action_delete/delete_button.tsx | 77 ++++++++++ .../delete_button_modal.tsx} | 136 +----------------- .../components/action_delete/index.ts | 9 ++ .../action_delete/use_delete_action.ts | 75 ++++++++++ .../edit_button.tsx} | 19 +-- .../components/action_edit/index.ts | 8 ++ .../components/action_edit/use_edit_action.ts | 26 ++++ .../components/action_start/index.ts | 9 ++ .../start_button.test.tsx} | 2 +- .../start_button.tsx} | 102 +------------ .../action_start/start_button_modal.tsx | 69 +++++++++ .../action_start/use_start_action.ts | 42 ++++++ .../components/action_stop/index.ts | 7 + .../stop_button.test.tsx} | 2 +- .../stop_button.tsx} | 0 .../transform_list/transform_list.tsx | 9 +- .../components/transform_list/use_actions.tsx | 10 +- 20 files changed, 346 insertions(+), 265 deletions(-) rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_clone.tsx => action_clone/clone_button.tsx} (100%) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/index.ts rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_delete.test.tsx => action_delete/delete_button.test.tsx} (95%) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_delete.tsx => action_delete/delete_button_modal.tsx} (60%) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/index.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/use_delete_action.ts rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_edit.tsx => action_edit/edit_button.tsx} (75%) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/index.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/use_edit_action.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/index.ts rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_start.test.tsx => action_start/start_button.test.tsx} (95%) rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_start.tsx => action_start/start_button.tsx} (52%) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/use_start_action.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/index.ts rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_stop.test.tsx => action_stop/stop_button.test.tsx} (95%) rename x-pack/plugins/transform/public/app/sections/transform_management/components/{transform_list/action_stop.tsx => action_stop/stop_button.tsx} (100%) diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/clone_button.tsx similarity index 100% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_clone.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/clone_button.tsx diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/index.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/index.ts new file mode 100644 index 0000000000000..727cc87c70f2c --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_clone/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { CloneButton } from './clone_button'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.test.tsx similarity index 95% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.test.tsx index 1d69791b923e0..63f8243b403d3 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.test.tsx @@ -8,7 +8,7 @@ import { shallow } from 'enzyme'; import React, { ComponentProps } from 'react'; import { TransformListRow } from '../../../../common'; -import { DeleteButton } from './action_delete'; +import { DeleteButton } from './delete_button'; import transformListRow from '../../../../common/__mocks__/transform_list_row.json'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx new file mode 100644 index 0000000000000..b81c3ebc34ca0 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button.tsx @@ -0,0 +1,77 @@ +/* + * 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, { FC, useContext } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; +import { TRANSFORM_STATE } from '../../../../../../common'; +import { + AuthorizationContext, + createCapabilityFailureMessage, +} from '../../../../lib/authorization'; +import { TransformListRow } from '../../../../common'; + +interface DeleteButtonProps { + items: TransformListRow[]; + forceDisable?: boolean; + onClick: (items: TransformListRow[]) => void; +} + +const transformCanNotBeDeleted = (i: TransformListRow) => + ![TRANSFORM_STATE.STOPPED, TRANSFORM_STATE.FAILED].includes(i.stats.state); + +export const DeleteButton: FC = ({ items, forceDisable, onClick }) => { + const isBulkAction = items.length > 1; + + const disabled = items.some(transformCanNotBeDeleted); + const { canDeleteTransform } = useContext(AuthorizationContext).capabilities; + + const buttonDeleteText = i18n.translate('xpack.transform.transformList.deleteActionName', { + defaultMessage: 'Delete', + }); + const bulkDeleteButtonDisabledText = i18n.translate( + 'xpack.transform.transformList.deleteBulkActionDisabledToolTipContent', + { + defaultMessage: 'One or more selected transforms must be stopped in order to be deleted.', + } + ); + const deleteButtonDisabledText = i18n.translate( + 'xpack.transform.transformList.deleteActionDisabledToolTipContent', + { + defaultMessage: 'Stop the transform in order to delete it.', + } + ); + + const buttonDisabled = forceDisable === true || disabled || !canDeleteTransform; + let deleteButton = ( + onClick(items)} + aria-label={buttonDeleteText} + > + {buttonDeleteText} + + ); + + if (disabled || !canDeleteTransform) { + let content; + if (disabled) { + content = isBulkAction ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; + } else { + content = createCapabilityFailureMessage('canDeleteTransform'); + } + + deleteButton = ( + + {deleteButton} + + ); + } + + return deleteButton; +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx similarity index 60% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx index 6fc1cbd26fd6e..89c1e759c10de 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx @@ -4,90 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, useContext, useMemo, useState } from 'react'; +import React, { FC } from 'react'; import { i18n } from '@kbn/i18n'; import { EUI_MODAL_CONFIRM_BUTTON, EuiConfirmModal, EuiFlexGroup, EuiFlexItem, - EuiIcon, - EuiLink, EuiOverlayMask, EuiSpacer, EuiSwitch, - EuiToolTip, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { TRANSFORM_STATE } from '../../../../../../common'; -import { useDeleteIndexAndTargetIndex, useDeleteTransforms } from '../../../../hooks'; -import { - AuthorizationContext, - createCapabilityFailureMessage, -} from '../../../../lib/authorization'; -import { TransformListRow } from '../../../../common'; - -interface DeleteButtonProps { - items: TransformListRow[]; - forceDisable?: boolean; - onClick: (items: TransformListRow[]) => void; -} - -const transformCanNotBeDeleted = (i: TransformListRow) => - ![TRANSFORM_STATE.STOPPED, TRANSFORM_STATE.FAILED].includes(i.stats.state); - -export const DeleteButton: FC = ({ items, forceDisable, onClick }) => { - const isBulkAction = items.length > 1; - const disabled = items.some(transformCanNotBeDeleted); - const { canDeleteTransform } = useContext(AuthorizationContext).capabilities; - - const buttonDeleteText = i18n.translate('xpack.transform.transformList.deleteActionName', { - defaultMessage: 'Delete', - }); - const bulkDeleteButtonDisabledText = i18n.translate( - 'xpack.transform.transformList.deleteBulkActionDisabledToolTipContent', - { - defaultMessage: 'One or more selected transforms must be stopped in order to be deleted.', - } - ); - const deleteButtonDisabledText = i18n.translate( - 'xpack.transform.transformList.deleteActionDisabledToolTipContent', - { - defaultMessage: 'Stop the transform in order to delete it.', - } - ); - - const buttonDisabled = forceDisable === true || disabled || !canDeleteTransform; - let deleteButton = ( - onClick(items)} - aria-label={buttonDeleteText} - > - {buttonDeleteText} - - ); - - if (disabled || !canDeleteTransform) { - let content; - if (disabled) { - content = isBulkAction ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; - } else { - content = createCapabilityFailureMessage('canDeleteTransform'); - } - - deleteButton = ( - - {deleteButton} - - ); - } - - return deleteButton; -}; +import { DeleteAction } from './use_delete_action'; type DeleteButtonModalProps = Pick< DeleteAction, @@ -265,66 +196,3 @@ export const DeleteButtonModal: FC = ({ ); }; - -type DeleteAction = ReturnType; -export const useDeleteAction = () => { - const deleteTransforms = useDeleteTransforms(); - - const [isModalVisible, setModalVisible] = useState(false); - const [items, setItems] = useState([]); - - const isBulkAction = items.length > 1; - const shouldForceDelete = useMemo( - () => items.some((i: TransformListRow) => i.stats.state === TRANSFORM_STATE.FAILED), - [items] - ); - - const closeModal = () => setModalVisible(false); - - const { - userCanDeleteIndex, - deleteDestIndex, - indexPatternExists, - deleteIndexPattern, - toggleDeleteIndex, - toggleDeleteIndexPattern, - } = useDeleteIndexAndTargetIndex(items); - - const deleteAndCloseModal = () => { - setModalVisible(false); - - const shouldDeleteDestIndex = userCanDeleteIndex && deleteDestIndex; - const shouldDeleteDestIndexPattern = - userCanDeleteIndex && indexPatternExists && deleteIndexPattern; - // if we are deleting multiple transforms, then force delete all if at least one item has failed - // else, force delete only when the item user picks has failed - const forceDelete = isBulkAction - ? shouldForceDelete - : items[0] && items[0] && items[0].stats.state === TRANSFORM_STATE.FAILED; - deleteTransforms(items, shouldDeleteDestIndex, shouldDeleteDestIndexPattern, forceDelete); - }; - - const openModal = (newItems: TransformListRow[]) => { - // EUI issue: Might trigger twice, one time as an array, - // one time as a single object. See https://github.com/elastic/eui/issues/3679 - if (Array.isArray(newItems)) { - setItems(newItems); - setModalVisible(true); - } - }; - - return { - closeModal, - deleteAndCloseModal, - deleteDestIndex, - deleteIndexPattern, - indexPatternExists, - isModalVisible, - items, - openModal, - shouldForceDelete, - toggleDeleteIndex, - toggleDeleteIndexPattern, - userCanDeleteIndex, - }; -}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/index.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/index.ts new file mode 100644 index 0000000000000..ef891d7c4a128 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { DeleteButton } from './delete_button'; +export { DeleteButtonModal } from './delete_button_modal'; +export { useDeleteAction } from './use_delete_action'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/use_delete_action.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/use_delete_action.ts new file mode 100644 index 0000000000000..d76eebe954d7b --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/use_delete_action.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useMemo, useState } from 'react'; + +import { TRANSFORM_STATE } from '../../../../../../common'; + +import { TransformListRow } from '../../../../common'; +import { useDeleteIndexAndTargetIndex, useDeleteTransforms } from '../../../../hooks'; + +export type DeleteAction = ReturnType; +export const useDeleteAction = () => { + const deleteTransforms = useDeleteTransforms(); + + const [isModalVisible, setModalVisible] = useState(false); + const [items, setItems] = useState([]); + + const isBulkAction = items.length > 1; + const shouldForceDelete = useMemo( + () => items.some((i: TransformListRow) => i.stats.state === TRANSFORM_STATE.FAILED), + [items] + ); + + const closeModal = () => setModalVisible(false); + + const { + userCanDeleteIndex, + deleteDestIndex, + indexPatternExists, + deleteIndexPattern, + toggleDeleteIndex, + toggleDeleteIndexPattern, + } = useDeleteIndexAndTargetIndex(items); + + const deleteAndCloseModal = () => { + setModalVisible(false); + + const shouldDeleteDestIndex = userCanDeleteIndex && deleteDestIndex; + const shouldDeleteDestIndexPattern = + userCanDeleteIndex && indexPatternExists && deleteIndexPattern; + // if we are deleting multiple transforms, then force delete all if at least one item has failed + // else, force delete only when the item user picks has failed + const forceDelete = isBulkAction + ? shouldForceDelete + : items[0] && items[0] && items[0].stats.state === TRANSFORM_STATE.FAILED; + deleteTransforms(items, shouldDeleteDestIndex, shouldDeleteDestIndexPattern, forceDelete); + }; + + const openModal = (newItems: TransformListRow[]) => { + // EUI issue: Might trigger twice, one time as an array, + // one time as a single object. See https://github.com/elastic/eui/issues/3679 + if (Array.isArray(newItems)) { + setItems(newItems); + setModalVisible(true); + } + }; + + return { + closeModal, + deleteAndCloseModal, + deleteDestIndex, + deleteIndexPattern, + indexPatternExists, + isModalVisible, + items, + openModal, + shouldForceDelete, + toggleDeleteIndex, + toggleDeleteIndexPattern, + userCanDeleteIndex, + }; +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx similarity index 75% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx index e094a582a73ba..b418690b83171 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext, useState, FC } from 'react'; +import React, { useContext, FC } from 'react'; import { i18n } from '@kbn/i18n'; @@ -51,20 +51,3 @@ export const EditButton: FC = ({ config, onClick }) => { return editButton; }; - -export const useEditAction = () => { - const [config, setConfig] = useState(); - const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); - const closeFlyout = () => setIsFlyoutVisible(false); - const showFlyout = (newConfig: TransformPivotConfig) => { - setConfig(newConfig); - setIsFlyoutVisible(true); - }; - - return { - config, - closeFlyout, - isFlyoutVisible, - showFlyout, - }; -}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/index.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/index.ts new file mode 100644 index 0000000000000..17a2ad9444f8d --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { EditButton } from './edit_button'; +export { useEditAction } from './use_edit_action'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/use_edit_action.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/use_edit_action.ts new file mode 100644 index 0000000000000..ace3ec8f636e6 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/use_edit_action.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useState } from 'react'; + +import { TransformPivotConfig } from '../../../../common'; + +export const useEditAction = () => { + const [config, setConfig] = useState(); + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + const closeFlyout = () => setIsFlyoutVisible(false); + const showFlyout = (newConfig: TransformPivotConfig) => { + setConfig(newConfig); + setIsFlyoutVisible(true); + }; + + return { + config, + closeFlyout, + isFlyoutVisible, + showFlyout, + }; +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/index.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/index.ts new file mode 100644 index 0000000000000..df6bbb7c61908 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { StartButton } from './start_button'; +export { StartButtonModal } from './start_button_modal'; +export { useStartAction } from './use_start_action'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.test.tsx similarity index 95% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.test.tsx index 33d7ca7d97602..b88e1257f56ad 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.test.tsx @@ -8,7 +8,7 @@ import { shallow } from 'enzyme'; import React, { ComponentProps } from 'react'; import { TransformListRow } from '../../../../common'; -import { StartButton } from './action_start'; +import { StartButton } from './start_button'; import transformListRow from '../../../../common/__mocks__/transform_list_row.json'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx similarity index 52% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx index 7bfd3d5db80bd..a0fe1bfbb9544 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_start.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button.tsx @@ -4,20 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC, useContext, useState } from 'react'; +import React, { FC, useContext } from 'react'; import { i18n } from '@kbn/i18n'; -import { - EuiConfirmModal, - EuiIcon, - EuiLink, - EuiOverlayMask, - EuiToolTip, - EUI_MODAL_CONFIRM_BUTTON, -} from '@elastic/eui'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; import { TRANSFORM_STATE } from '../../../../../../common'; -import { useStartTransforms } from '../../../../hooks'; import { createCapabilityFailureMessage, AuthorizationContext, @@ -112,93 +104,3 @@ export const StartButton: FC = ({ items, forceDisable, onClick } return startButton; }; - -type StartButtonModalProps = Pick< - StartAction, - 'closeModal' | 'isModalVisible' | 'items' | 'startAndCloseModal' ->; -export const StartButtonModal: FC = ({ - closeModal, - isModalVisible, - items, - startAndCloseModal, -}) => { - const isBulkAction = items.length > 1; - - const bulkStartModalTitle = i18n.translate('xpack.transform.transformList.bulkStartModalTitle', { - defaultMessage: 'Start {count} {count, plural, one {transform} other {transforms}}?', - values: { count: items && items.length }, - }); - const startModalTitle = i18n.translate('xpack.transform.transformList.startModalTitle', { - defaultMessage: 'Start {transformId}', - values: { transformId: items[0] && items[0].config.id }, - }); - - return ( - <> - {isModalVisible && ( - - -

- {i18n.translate('xpack.transform.transformList.startModalBody', { - defaultMessage: - 'A transform will increase search and indexing load in your cluster. Please stop the transform if excessive load is experienced. Are you sure you want to start {count, plural, one {this} other {these}} {count} {count, plural, one {transform} other {transforms}}?', - values: { count: items.length }, - })} -

-
-
- )} - - ); -}; - -type StartAction = ReturnType; -export const useStartAction = () => { - const startTransforms = useStartTransforms(); - - const [isModalVisible, setModalVisible] = useState(false); - const [items, setItems] = useState([]); - - const closeModal = () => setModalVisible(false); - - const startAndCloseModal = () => { - setModalVisible(false); - startTransforms(items); - }; - - const openModal = (newItems: TransformListRow[]) => { - // EUI issue: Might trigger twice, one time as an array, - // one time as a single object. See https://github.com/elastic/eui/issues/3679 - if (Array.isArray(newItems)) { - setItems(newItems); - setModalVisible(true); - } - }; - - return { - closeModal, - isModalVisible, - items, - openModal, - startAndCloseModal, - }; -}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx new file mode 100644 index 0000000000000..95eecc2d0c657 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiConfirmModal, EuiOverlayMask, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui'; + +import { StartAction } from './use_start_action'; + +type StartButtonModalProps = Pick< + StartAction, + 'closeModal' | 'isModalVisible' | 'items' | 'startAndCloseModal' +>; +export const StartButtonModal: FC = ({ + closeModal, + isModalVisible, + items, + startAndCloseModal, +}) => { + const isBulkAction = items.length > 1; + + const bulkStartModalTitle = i18n.translate('xpack.transform.transformList.bulkStartModalTitle', { + defaultMessage: 'Start {count} {count, plural, one {transform} other {transforms}}?', + values: { count: items && items.length }, + }); + const startModalTitle = i18n.translate('xpack.transform.transformList.startModalTitle', { + defaultMessage: 'Start {transformId}', + values: { transformId: items[0] && items[0].config.id }, + }); + + return ( + <> + {isModalVisible && ( + + +

+ {i18n.translate('xpack.transform.transformList.startModalBody', { + defaultMessage: + 'A transform will increase search and indexing load in your cluster. Please stop the transform if excessive load is experienced. Are you sure you want to start {count, plural, one {this} other {these}} {count} {count, plural, one {transform} other {transforms}}?', + values: { count: items.length }, + })} +

+
+
+ )} + + ); +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/use_start_action.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/use_start_action.ts new file mode 100644 index 0000000000000..32d2dc6dabf86 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/use_start_action.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useState } from 'react'; + +import { TransformListRow } from '../../../../common'; +import { useStartTransforms } from '../../../../hooks'; + +export type StartAction = ReturnType; +export const useStartAction = () => { + const startTransforms = useStartTransforms(); + + const [isModalVisible, setModalVisible] = useState(false); + const [items, setItems] = useState([]); + + const closeModal = () => setModalVisible(false); + + const startAndCloseModal = () => { + setModalVisible(false); + startTransforms(items); + }; + + const openModal = (newItems: TransformListRow[]) => { + // EUI issue: Might trigger twice, one time as an array, + // one time as a single object. See https://github.com/elastic/eui/issues/3679 + if (Array.isArray(newItems)) { + setItems(newItems); + setModalVisible(true); + } + }; + + return { + closeModal, + isModalVisible, + items, + openModal, + startAndCloseModal, + }; +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/index.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/index.ts new file mode 100644 index 0000000000000..858b6c70501b3 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { StopButton } from './stop_button'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.test.tsx similarity index 95% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.test.tsx index 8803c8aefa622..d9c07a9dccc8f 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.test.tsx @@ -8,7 +8,7 @@ import { shallow } from 'enzyme'; import React, { ComponentProps } from 'react'; import { TransformListRow } from '../../../../common'; -import { StopButton } from './action_stop'; +import { StopButton } from './stop_button'; import transformListRow from '../../../../common/__mocks__/transform_list_row.json'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.tsx similarity index 100% rename from x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_stop.tsx rename to x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/stop_button.tsx diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx index 12f253afe89f3..a2dcd54c6677e 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx @@ -36,13 +36,12 @@ import { AuthorizationContext } from '../../../../lib/authorization'; import { CreateTransformButton } from '../create_transform_button'; import { RefreshTransformListButton } from '../refresh_transform_list_button'; -import { getTaskStateBadge } from './columns'; -import { useDeleteAction, DeleteButton, DeleteButtonModal } from './action_delete'; -import { useStartAction, StartButton, StartButtonModal } from './action_start'; -import { StopButton } from './action_stop'; +import { useDeleteAction, DeleteButton, DeleteButtonModal } from '../action_delete'; +import { useStartAction, StartButton, StartButtonModal } from '../action_start'; +import { StopButton } from '../action_stop'; import { ItemIdToExpandedRowMap, Clause, TermClause, FieldClause, Value } from './common'; -import { useColumns } from './columns'; +import { getTaskStateBadge, useColumns } from './use_columns'; import { ExpandedRow } from './expanded_row'; function getItemIdToExpandedRowMap( diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx index 2b97b2367c64e..bce4a3113c356 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx @@ -13,12 +13,12 @@ import { TRANSFORM_STATE } from '../../../../../../common'; import { TransformListRow } from '../../../../common'; -import { CloneButton } from './action_clone'; -import { useDeleteAction, DeleteButton, DeleteButtonModal } from './action_delete'; +import { CloneButton } from '../action_clone'; +import { useDeleteAction, DeleteButton, DeleteButtonModal } from '../action_delete'; import { EditTransformFlyout } from '../edit_transform_flyout'; -import { useEditAction, EditButton } from './action_edit'; -import { useStartAction, StartButton, StartButtonModal } from './action_start'; -import { StopButton } from './action_stop'; +import { useEditAction, EditButton } from '../action_edit'; +import { useStartAction, StartButton, StartButtonModal } from '../action_start'; +import { StopButton } from '../action_stop'; export const useActions = ({ forceDisable, From 996e15126cf0463ed33e7ee7dbc26767c7c5e081 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 3 Jul 2020 11:57:41 +0200 Subject: [PATCH 05/11] [ML] Refactor analytics list actions. --- .../clone_button.test.ts} | 2 +- .../clone_button.tsx} | 6 +- .../components/action_clone/index.ts | 7 + .../action_delete.test.tsx | 15 +- .../action_delete/delete_button.tsx | 64 +++++ .../action_delete/delete_button_modal.tsx | 126 +++++++++ .../components/action_delete/index.ts | 9 + .../action_delete/use_delete_action.ts | 140 ++++++++++ .../components/action_start/index.ts | 9 + .../components/action_start/start_button.tsx | 66 +++++ .../action_start/start_button_modal.tsx | 60 +++++ .../action_start/use_start_action.ts | 38 +++ .../components/action_stop/index.ts | 7 + .../components/action_stop/stop_button.tsx | 57 ++++ .../action_view/get_view_action.tsx | 22 ++ .../components/action_view/index.ts | 8 + .../components/action_view/view_button.tsx | 61 +++++ .../analytics_list/action_delete.tsx | 248 ------------------ .../analytics_list/action_start.tsx | 120 --------- .../components/analytics_list/actions.tsx | 151 ----------- .../analytics_list/analytics_list.tsx | 54 ++-- .../components/analytics_list/use_actions.tsx | 84 ++++++ .../{columns.tsx => use_columns.tsx} | 22 +- 23 files changed, 793 insertions(+), 583 deletions(-) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/{analytics_list/action_clone.test.ts => action_clone/clone_button.test.ts} (99%) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/{analytics_list/action_clone.tsx => action_clone/clone_button.tsx} (98%) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/{analytics_list => action_delete}/action_delete.test.tsx (89%) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/index.ts create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.ts create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/index.ts create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/use_start_action.ts create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/index.ts create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_action.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/index.ts create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_start.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_actions.tsx rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/{columns.tsx => use_columns.tsx} (93%) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts similarity index 99% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts index 01d92d8e192c1..a4e47822d7bd5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isAdvancedConfig } from './action_clone'; +import { isAdvancedConfig } from './clone_button'; describe('Analytics job clone action', () => { describe('isAdvancedConfig', () => { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx similarity index 98% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx index f184c7c5d874e..84cb4701c275d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_button.tsx @@ -19,7 +19,7 @@ import { DEFAULT_NUM_TOP_FEATURE_IMPORTANCE_VALUES, } from '../../hooks/use_create_analytics_form'; import { State } from '../../hooks/use_create_analytics_form/state'; -import { DataFrameAnalyticsListRow } from './common'; +import { DataFrameAnalyticsListRow } from '../analytics_list/common'; import { checkPermission } from '../../../../../capabilities/check_capabilities'; import { extractErrorMessage } from '../../../../../../../common/util/errors'; @@ -343,7 +343,7 @@ export function getCloneAction(createAnalyticsForm: CreateAnalyticsFormProps) { }; } -interface CloneActionProps { +interface CloneButtonProps { item: DataFrameAnalyticsListRow; createAnalyticsForm: CreateAnalyticsFormProps; } @@ -353,7 +353,7 @@ interface CloneActionProps { * Replace with {@link getCloneAction} as soon as all the actions are refactored * to support EuiContext with a valid DOM structure without nested buttons. */ -export const CloneAction: FC = ({ createAnalyticsForm, item }) => { +export const CloneButton: FC = ({ createAnalyticsForm, item }) => { const canCreateDataFrameAnalytics: boolean = checkPermission('canCreateDataFrameAnalytics'); const buttonText = i18n.translate('xpack.ml.dataframe.analyticsList.cloneJobButtonLabel', { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts new file mode 100644 index 0000000000000..727cc87c70f2c --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { CloneButton } from './clone_button'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx similarity index 89% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.test.tsx rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx index 33217f127f998..4ce5893d19b10 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { fireEvent, render } from '@testing-library/react'; import * as CheckPrivilige from '../../../../../capabilities/check_capabilities'; import mockAnalyticsListItem from './__mocks__/analytics_list_item.json'; -import { DeleteAction } from './action_delete'; +import { DeleteButton } from './delete_button'; import { I18nProvider } from '@kbn/i18n/react'; import { coreMock as mockCoreServices, @@ -41,14 +41,18 @@ describe('DeleteAction', () => { }); test('When canDeleteDataFrameAnalytics permission is false, button should be disabled.', () => { - const { getByTestId } = render(); + const { getByTestId } = render( + {}} /> + ); expect(getByTestId('mlAnalyticsJobDeleteButton')).toHaveAttribute('disabled'); }); test('When canDeleteDataFrameAnalytics permission is true, button should not be disabled.', () => { const mock = jest.spyOn(CheckPrivilige, 'checkPermission'); mock.mockImplementation((p) => p === 'canDeleteDataFrameAnalytics'); - const { getByTestId } = render(); + const { getByTestId } = render( + {}} /> + ); expect(getByTestId('mlAnalyticsJobDeleteButton')).not.toHaveAttribute('disabled'); @@ -57,11 +61,12 @@ describe('DeleteAction', () => { test('When job is running, delete button should be disabled.', () => { const { getByTestId } = render( - {}} /> ); @@ -74,7 +79,7 @@ describe('DeleteAction', () => { mock.mockImplementation((p) => p === 'canDeleteDataFrameAnalytics'); const { getByTestId, queryByTestId } = render( - + {}} /> ); const deleteButton = getByTestId('mlAnalyticsJobDeleteButton'); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx new file mode 100644 index 0000000000000..ff2f405775db3 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; +import { + checkPermission, + createPermissionFailureMessage, +} from '../../../../../capabilities/check_capabilities'; +import { isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from '../analytics_list/common'; + +interface DeleteButtonProps { + item: DataFrameAnalyticsListRow; + onClick: (item: DataFrameAnalyticsListRow) => void; +} + +export const DeleteButton: FC = ({ item, onClick }) => { + const disabled = isDataFrameAnalyticsRunning(item.stats.state); + const canDeleteDataFrameAnalytics: boolean = checkPermission('canDeleteDataFrameAnalytics'); + + const buttonDeleteText = i18n.translate('xpack.ml.dataframe.analyticsList.deleteActionName', { + defaultMessage: 'Delete', + }); + + const buttonDisabled = disabled || !canDeleteDataFrameAnalytics; + let deleteButton = ( + onClick(item)} + aria-label={buttonDeleteText} + style={{ padding: 0 }} + > + {buttonDeleteText} + + ); + + if (disabled || !canDeleteDataFrameAnalytics) { + deleteButton = ( + + {deleteButton} + + ); + } + + return deleteButton; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx new file mode 100644 index 0000000000000..7fca76c4aebc8 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx @@ -0,0 +1,126 @@ +/* + * 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, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiConfirmModal, + EuiOverlayMask, + EuiSwitch, + EuiFlexGroup, + EuiFlexItem, + EUI_MODAL_CONFIRM_BUTTON, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { DeleteAction } from './use_delete_action'; + +type DeleteButtonModalProps = Pick< + DeleteAction, + | 'closeModal' + | 'deleteAndCloseModal' + | 'deleteTargetIndex' + | 'deleteIndexPattern' + | 'indexPatternExists' + | 'isModalVisible' + | 'item' + | 'toggleDeleteIndex' + | 'toggleDeleteIndexPattern' + | 'userCanDeleteIndex' +>; +export const DeleteButtonModal: FC = ({ + closeModal, + deleteAndCloseModal, + deleteTargetIndex, + deleteIndexPattern, + indexPatternExists, + isModalVisible, + item, + toggleDeleteIndex, + toggleDeleteIndexPattern, + userCanDeleteIndex, +}) => { + if (item === undefined) { + return null; + } + + const indexName = item.config.dest.index; + + return ( + <> + {isModalVisible && ( + + +

+ +

+ + + + {userCanDeleteIndex && ( + + )} + + + {userCanDeleteIndex && indexPatternExists && ( + + )} + + +
+
+ )} + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/index.ts new file mode 100644 index 0000000000000..ef891d7c4a128 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { DeleteButton } from './delete_button'; +export { DeleteButtonModal } from './delete_button_modal'; +export { useDeleteAction } from './use_delete_action'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.ts new file mode 100644 index 0000000000000..f924cf3afcba5 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/use_delete_action.ts @@ -0,0 +1,140 @@ +/* + * 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 { useEffect, useState } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { IIndexPattern } from 'src/plugins/data/common'; + +import { extractErrorMessage } from '../../../../../../../common/util/errors'; + +import { useMlKibana } from '../../../../../contexts/kibana'; + +import { + deleteAnalytics, + deleteAnalyticsAndDestIndex, + canDeleteIndex, +} from '../../services/analytics_service'; + +import { DataFrameAnalyticsListRow } from '../analytics_list/common'; + +export type DeleteAction = ReturnType; +export const useDeleteAction = () => { + const [item, setItem] = useState(); + + const [isModalVisible, setModalVisible] = useState(false); + const [deleteTargetIndex, setDeleteTargetIndex] = useState(true); + const [deleteIndexPattern, setDeleteIndexPattern] = useState(true); + const [userCanDeleteIndex, setUserCanDeleteIndex] = useState(false); + const [indexPatternExists, setIndexPatternExists] = useState(false); + + const { savedObjects, notifications } = useMlKibana().services; + const savedObjectsClient = savedObjects.client; + + const indexName = item?.config.dest.index ?? ''; + + const checkIndexPatternExists = async () => { + try { + const response = await savedObjectsClient.find({ + type: 'index-pattern', + perPage: 10, + search: `"${indexName}"`, + searchFields: ['title'], + fields: ['title'], + }); + const ip = response.savedObjects.find( + (obj) => obj.attributes.title.toLowerCase() === indexName.toLowerCase() + ); + if (ip !== undefined) { + setIndexPatternExists(true); + } + } catch (e) { + const { toasts } = notifications; + const error = extractErrorMessage(e); + + toasts.addDanger( + i18n.translate( + 'xpack.ml.dataframe.analyticsList.errorWithCheckingIfIndexPatternExistsNotificationErrorMessage', + { + defaultMessage: + 'An error occurred checking if index pattern {indexPattern} exists: {error}', + values: { indexPattern: indexName, error }, + } + ) + ); + } + }; + const checkUserIndexPermission = () => { + try { + const userCanDelete = canDeleteIndex(indexName); + if (userCanDelete) { + setUserCanDeleteIndex(true); + } + } catch (e) { + const { toasts } = notifications; + const error = extractErrorMessage(e); + + toasts.addDanger( + i18n.translate( + 'xpack.ml.dataframe.analyticsList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage', + { + defaultMessage: + 'An error occurred checking if user can delete {destinationIndex}: {error}', + values: { destinationIndex: indexName, error }, + } + ) + ); + } + }; + + useEffect(() => { + // Check if an index pattern exists corresponding to current DFA job + // if pattern does exist, show it to user + checkIndexPatternExists(); + + // Check if an user has permission to delete the index & index pattern + checkUserIndexPermission(); + }, []); + + const closeModal = () => setModalVisible(false); + const deleteAndCloseModal = () => { + setModalVisible(false); + + if (item !== undefined) { + if ((userCanDeleteIndex && deleteTargetIndex) || (userCanDeleteIndex && deleteIndexPattern)) { + deleteAnalyticsAndDestIndex( + item, + deleteTargetIndex, + indexPatternExists && deleteIndexPattern + ); + } else { + deleteAnalytics(item); + } + } + }; + const toggleDeleteIndex = () => setDeleteTargetIndex(!deleteTargetIndex); + const toggleDeleteIndexPattern = () => setDeleteIndexPattern(!deleteIndexPattern); + + const openModal = (newItem: DataFrameAnalyticsListRow) => { + setItem(newItem); + setModalVisible(true); + }; + + return { + closeModal, + deleteAndCloseModal, + deleteTargetIndex, + deleteIndexPattern, + indexPatternExists, + isModalVisible, + item, + openModal, + toggleDeleteIndex, + toggleDeleteIndexPattern, + userCanDeleteIndex, + }; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/index.ts new file mode 100644 index 0000000000000..df6bbb7c61908 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { StartButton } from './start_button'; +export { StartButtonModal } from './start_button_modal'; +export { useStartAction } from './use_start_action'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.tsx new file mode 100644 index 0000000000000..279a335de8f42 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; + +import { + checkPermission, + createPermissionFailureMessage, +} from '../../../../../capabilities/check_capabilities'; + +import { DataFrameAnalyticsListRow, isCompletedAnalyticsJob } from '../analytics_list/common'; + +interface StartButtonProps { + item: DataFrameAnalyticsListRow; + onClick: (item: DataFrameAnalyticsListRow) => void; +} + +export const StartButton: FC = ({ item, onClick }) => { + const canStartStopDataFrameAnalytics: boolean = checkPermission('canStartStopDataFrameAnalytics'); + + const buttonStartText = i18n.translate('xpack.ml.dataframe.analyticsList.startActionName', { + defaultMessage: 'Start', + }); + + // Disable start for analytics jobs which have completed. + const completeAnalytics = isCompletedAnalyticsJob(item.stats); + + const disabled = !canStartStopDataFrameAnalytics || completeAnalytics; + + let startButton = ( + onClick(item)} + aria-label={buttonStartText} + data-test-subj="mlAnalyticsJobStartButton" + > + {buttonStartText} + + ); + + if (!canStartStopDataFrameAnalytics || completeAnalytics) { + startButton = ( + + {startButton} + + ); + } + + return startButton; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx new file mode 100644 index 0000000000000..bf3505f3a26ea --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx @@ -0,0 +1,60 @@ +/* + * 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, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiConfirmModal, EuiOverlayMask, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui'; + +import { StartAction } from './use_start_action'; + +type StartButtonModalProps = Pick< + StartAction, + 'closeModal' | 'isModalVisible' | 'item' | 'startAndCloseModal' +>; +export const StartButtonModal: FC = ({ + closeModal, + isModalVisible, + item, + startAndCloseModal, +}) => { + return ( + <> + {isModalVisible && item !== undefined && ( + + +

+ {i18n.translate('xpack.ml.dataframe.analyticsList.startModalBody', { + defaultMessage: + 'A data frame analytics job will increase search and indexing load in your cluster. Please stop the analytics job if excessive load is experienced. Are you sure you want to start this analytics job?', + })} +

+
+
+ )} + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/use_start_action.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/use_start_action.ts new file mode 100644 index 0000000000000..8eb6b990827ac --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/use_start_action.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useState } from 'react'; + +import { DataFrameAnalyticsListRow } from '../analytics_list/common'; +import { startAnalytics } from '../../services/analytics_service'; + +export type StartAction = ReturnType; +export const useStartAction = () => { + const [isModalVisible, setModalVisible] = useState(false); + + const [item, setItem] = useState(); + + const closeModal = () => setModalVisible(false); + const startAndCloseModal = () => { + if (item !== undefined) { + setModalVisible(false); + startAnalytics(item); + } + }; + + const openModal = (newItem: DataFrameAnalyticsListRow) => { + setItem(newItem); + setModalVisible(true); + }; + + return { + closeModal, + isModalVisible, + item, + openModal, + startAndCloseModal, + }; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/index.ts new file mode 100644 index 0000000000000..858b6c70501b3 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { StopButton } from './stop_button'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx new file mode 100644 index 0000000000000..b8395f2f7c2a0 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/stop_button.tsx @@ -0,0 +1,57 @@ +/* + * 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, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; + +import { + checkPermission, + createPermissionFailureMessage, +} from '../../../../../capabilities/check_capabilities'; + +import { stopAnalytics } from '../../services/analytics_service'; + +import { DataFrameAnalyticsListRow } from '../analytics_list/common'; + +const buttonStopText = i18n.translate('xpack.ml.dataframe.analyticsList.stopActionName', { + defaultMessage: 'Stop', +}); + +interface StopButtonProps { + item: DataFrameAnalyticsListRow; +} + +export const StopButton: FC = ({ item }) => { + const canStartStopDataFrameAnalytics: boolean = checkPermission('canStartStopDataFrameAnalytics'); + + const stopButton = ( + stopAnalytics(item)} + aria-label={buttonStopText} + data-test-subj="mlAnalyticsJobStopButton" + > + {buttonStopText} + + ); + if (!canStartStopDataFrameAnalytics) { + return ( + + {stopButton} + + ); + } + + return stopButton; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_action.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_action.tsx new file mode 100644 index 0000000000000..e31670ea42ceb --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/get_view_action.tsx @@ -0,0 +1,22 @@ +/* + * 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 { EuiTableActionsColumnType } from '@elastic/eui'; + +import { DataFrameAnalyticsListRow } from '../analytics_list/common'; + +import { ViewButton } from './view_button'; + +export const getViewAction = ( + isManagementTable: boolean = false +): EuiTableActionsColumnType['actions'][number] => ({ + isPrimary: true, + render: (item: DataFrameAnalyticsListRow) => ( + + ), +}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/index.ts new file mode 100644 index 0000000000000..5ac12c12071fd --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { getViewAction } from './get_view_action'; +export { ViewButton } from './view_button'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx new file mode 100644 index 0000000000000..17a18c374dfa6 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/view_button.tsx @@ -0,0 +1,61 @@ +/* + * 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, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButtonEmpty } from '@elastic/eui'; + +import { + getAnalysisType, + isRegressionAnalysis, + isOutlierAnalysis, + isClassificationAnalysis, +} from '../../../../common/analytics'; +import { useMlKibana } from '../../../../../contexts/kibana'; + +import { getResultsUrl, DataFrameAnalyticsListRow } from '../analytics_list/common'; + +interface ViewButtonProps { + item: DataFrameAnalyticsListRow; + isManagementTable: boolean; +} + +export const ViewButton: FC = ({ item, isManagementTable }) => { + const { + services: { + application: { navigateToUrl, navigateToApp }, + }, + } = useMlKibana(); + + const analysisType = getAnalysisType(item.config.analysis); + const isDisabled = + !isRegressionAnalysis(item.config.analysis) && + !isOutlierAnalysis(item.config.analysis) && + !isClassificationAnalysis(item.config.analysis); + + const url = getResultsUrl(item.id, analysisType); + const navigator = isManagementTable + ? () => navigateToApp('ml', { path: url }) + : () => navigateToUrl(url); + + return ( + + {i18n.translate('xpack.ml.dataframe.analyticsList.viewActionName', { + defaultMessage: 'View', + })} + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx deleted file mode 100644 index 38ef00914e8fb..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx +++ /dev/null @@ -1,248 +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, { Fragment, FC, useState, useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiButtonEmpty, - EuiConfirmModal, - EuiOverlayMask, - EuiToolTip, - EuiSwitch, - EuiFlexGroup, - EuiFlexItem, - EUI_MODAL_CONFIRM_BUTTON, -} from '@elastic/eui'; -import { IIndexPattern } from 'src/plugins/data/common'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { extractErrorMessage } from '../../../../../../../common/util/errors'; -import { - deleteAnalytics, - deleteAnalyticsAndDestIndex, - canDeleteIndex, -} from '../../services/analytics_service'; -import { - checkPermission, - createPermissionFailureMessage, -} from '../../../../../capabilities/check_capabilities'; -import { useMlKibana } from '../../../../../contexts/kibana'; -import { isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common'; - -interface DeleteActionProps { - item: DataFrameAnalyticsListRow; -} - -export const DeleteAction: FC = ({ item }) => { - const disabled = isDataFrameAnalyticsRunning(item.stats.state); - const canDeleteDataFrameAnalytics: boolean = checkPermission('canDeleteDataFrameAnalytics'); - - const [isModalVisible, setModalVisible] = useState(false); - const [deleteTargetIndex, setDeleteTargetIndex] = useState(true); - const [deleteIndexPattern, setDeleteIndexPattern] = useState(true); - const [userCanDeleteIndex, setUserCanDeleteIndex] = useState(false); - const [indexPatternExists, setIndexPatternExists] = useState(false); - - const { savedObjects, notifications } = useMlKibana().services; - const savedObjectsClient = savedObjects.client; - - const indexName = item.config.dest.index; - - const checkIndexPatternExists = async () => { - try { - const response = await savedObjectsClient.find({ - type: 'index-pattern', - perPage: 10, - search: `"${indexName}"`, - searchFields: ['title'], - fields: ['title'], - }); - const ip = response.savedObjects.find( - (obj) => obj.attributes.title.toLowerCase() === indexName.toLowerCase() - ); - if (ip !== undefined) { - setIndexPatternExists(true); - } - } catch (e) { - const { toasts } = notifications; - const error = extractErrorMessage(e); - - toasts.addDanger( - i18n.translate( - 'xpack.ml.dataframe.analyticsList.errorWithCheckingIfIndexPatternExistsNotificationErrorMessage', - { - defaultMessage: - 'An error occurred checking if index pattern {indexPattern} exists: {error}', - values: { indexPattern: indexName, error }, - } - ) - ); - } - }; - const checkUserIndexPermission = () => { - try { - const userCanDelete = canDeleteIndex(indexName); - if (userCanDelete) { - setUserCanDeleteIndex(true); - } - } catch (e) { - const { toasts } = notifications; - const error = extractErrorMessage(e); - - toasts.addDanger( - i18n.translate( - 'xpack.ml.dataframe.analyticsList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage', - { - defaultMessage: - 'An error occurred checking if user can delete {destinationIndex}: {error}', - values: { destinationIndex: indexName, error }, - } - ) - ); - } - }; - - useEffect(() => { - // Check if an index pattern exists corresponding to current DFA job - // if pattern does exist, show it to user - checkIndexPatternExists(); - - // Check if an user has permission to delete the index & index pattern - checkUserIndexPermission(); - }, []); - - const closeModal = () => setModalVisible(false); - const deleteAndCloseModal = () => { - setModalVisible(false); - - if ((userCanDeleteIndex && deleteTargetIndex) || (userCanDeleteIndex && deleteIndexPattern)) { - deleteAnalyticsAndDestIndex( - item, - deleteTargetIndex, - indexPatternExists && deleteIndexPattern - ); - } else { - deleteAnalytics(item); - } - }; - const openModal = () => setModalVisible(true); - const toggleDeleteIndex = () => setDeleteTargetIndex(!deleteTargetIndex); - const toggleDeleteIndexPattern = () => setDeleteIndexPattern(!deleteIndexPattern); - - const buttonDeleteText = i18n.translate('xpack.ml.dataframe.analyticsList.deleteActionName', { - defaultMessage: 'Delete', - }); - - let deleteButton = ( - - {buttonDeleteText} - - ); - - if (disabled || !canDeleteDataFrameAnalytics) { - deleteButton = ( - - {deleteButton} - - ); - } - - return ( - - {deleteButton} - {isModalVisible && ( - - -

- -

- - - - {userCanDeleteIndex && ( - - )} - - - {userCanDeleteIndex && indexPatternExists && ( - - )} - - -
-
- )} -
- ); -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_start.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_start.tsx deleted file mode 100644 index 74eb1d0b02782..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_start.tsx +++ /dev/null @@ -1,120 +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, { Fragment, FC, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { - EuiButtonEmpty, - EuiConfirmModal, - EuiOverlayMask, - EuiToolTip, - EUI_MODAL_CONFIRM_BUTTON, -} from '@elastic/eui'; - -import { startAnalytics } from '../../services/analytics_service'; - -import { - checkPermission, - createPermissionFailureMessage, -} from '../../../../../capabilities/check_capabilities'; - -import { DataFrameAnalyticsListRow, isCompletedAnalyticsJob } from './common'; - -interface StartActionProps { - item: DataFrameAnalyticsListRow; -} - -export const StartAction: FC = ({ item }) => { - const canStartStopDataFrameAnalytics: boolean = checkPermission('canStartStopDataFrameAnalytics'); - - const [isModalVisible, setModalVisible] = useState(false); - - const closeModal = () => setModalVisible(false); - const startAndCloseModal = () => { - setModalVisible(false); - startAnalytics(item); - }; - const openModal = () => setModalVisible(true); - - const buttonStartText = i18n.translate('xpack.ml.dataframe.analyticsList.startActionName', { - defaultMessage: 'Start', - }); - - // Disable start for analytics jobs which have completed. - const completeAnalytics = isCompletedAnalyticsJob(item.stats); - - let startButton = ( - - {buttonStartText} - - ); - - if (!canStartStopDataFrameAnalytics || completeAnalytics) { - startButton = ( - - {startButton} - - ); - } - - return ( - - {startButton} - {isModalVisible && ( - - -

- {i18n.translate('xpack.ml.dataframe.analyticsList.startModalBody', { - defaultMessage: - 'A data frame analytics job will increase search and indexing load in your cluster. Please stop the analytics job if excessive load is experienced. Are you sure you want to start this analytics job?', - })} -

-
-
- )} -
- ); -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx deleted file mode 100644 index b47b23f668530..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx +++ /dev/null @@ -1,151 +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, { FC } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; - -import { - checkPermission, - createPermissionFailureMessage, -} from '../../../../../capabilities/check_capabilities'; - -import { - getAnalysisType, - isRegressionAnalysis, - isOutlierAnalysis, - isClassificationAnalysis, -} from '../../../../common/analytics'; -import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; -import { useMlKibana } from '../../../../../contexts/kibana'; -import { CloneAction } from './action_clone'; - -import { getResultsUrl, isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common'; -import { stopAnalytics } from '../../services/analytics_service'; - -import { StartAction } from './action_start'; -import { DeleteAction } from './action_delete'; - -interface Props { - item: DataFrameAnalyticsListRow; - isManagementTable: boolean; -} - -const AnalyticsViewButton: FC = ({ item, isManagementTable }) => { - const { - services: { - application: { navigateToUrl, navigateToApp }, - }, - } = useMlKibana(); - - const analysisType = getAnalysisType(item.config.analysis); - const isDisabled = - !isRegressionAnalysis(item.config.analysis) && - !isOutlierAnalysis(item.config.analysis) && - !isClassificationAnalysis(item.config.analysis); - - const url = getResultsUrl(item.id, analysisType); - const navigator = isManagementTable - ? () => navigateToApp('ml', { path: url }) - : () => navigateToUrl(url); - - return ( - - {i18n.translate('xpack.ml.dataframe.analyticsList.viewActionName', { - defaultMessage: 'View', - })} - - ); -}; - -interface Action { - isPrimary?: boolean; - render: (item: DataFrameAnalyticsListRow) => any; -} - -export const getAnalyticsViewAction = (isManagementTable: boolean = false): Action => ({ - isPrimary: true, - render: (item: DataFrameAnalyticsListRow) => ( - - ), -}); - -export const getActions = ( - createAnalyticsForm: CreateAnalyticsFormProps, - isManagementTable: boolean -) => { - const canStartStopDataFrameAnalytics: boolean = checkPermission('canStartStopDataFrameAnalytics'); - const actions: Action[] = [getAnalyticsViewAction(isManagementTable)]; - - if (isManagementTable === false) { - actions.push( - ...[ - { - render: (item: DataFrameAnalyticsListRow) => { - if (!isDataFrameAnalyticsRunning(item.stats.state)) { - return ; - } - - const buttonStopText = i18n.translate( - 'xpack.ml.dataframe.analyticsList.stopActionName', - { - defaultMessage: 'Stop', - } - ); - - const stopButton = ( - stopAnalytics(item)} - aria-label={buttonStopText} - data-test-subj="mlAnalyticsJobStopButton" - > - {buttonStopText} - - ); - if (!canStartStopDataFrameAnalytics) { - return ( - - {stopButton} - - ); - } - - return stopButton; - }, - }, - { - render: (item: DataFrameAnalyticsListRow) => { - return ; - }, - }, - { - render: (item: DataFrameAnalyticsListRow) => { - return ; - }, - }, - ] - ); - } - - return actions; -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx index dac0de4c7a533..405231aef5774 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, FC, useState, useEffect } from 'react'; +import React, { FC, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; @@ -25,7 +25,6 @@ import { ANALYSIS_CONFIG_TYPE, } from '../../../../common'; import { checkPermission } from '../../../../../capabilities/check_capabilities'; -import { getTaskStateBadge, getJobTypeBadge } from './columns'; import { DataFrameAnalyticsListColumn, @@ -38,7 +37,7 @@ import { FieldClause, } from './common'; import { getAnalyticsFactory } from '../../services/analytics_service'; -import { getColumns } from './columns'; +import { getTaskStateBadge, getJobTypeBadge, useColumns } from './use_columns'; import { ExpandedRow } from './expanded_row'; import { ProgressBar, @@ -232,6 +231,14 @@ export const DataFrameAnalyticsList: FC = ({ setIsLoading(false); }; + const { columns, modals } = useColumns( + expandedRowItemIds, + setExpandedRowItemIds, + isManagementTable, + isMlEnabledInSpace, + createAnalyticsForm + ); + // Before the analytics have been loaded for the first time, display the loading indicator only. // Otherwise a user would see 'No data frame analytics found' during the initial loading. if (!isInitialized) { @@ -240,7 +247,7 @@ export const DataFrameAnalyticsList: FC = ({ if (typeof errorMessage !== 'undefined') { return ( - + <> = ({ >
{JSON.stringify(errorMessage)}
-
+ ); } if (analytics.length === 0) { return ( - + <> = ({ {isSourceIndexModalVisible === true && ( setIsSourceIndexModalVisible(false)} /> )} - + ); } - const columns = getColumns( - expandedRowItemIds, - setExpandedRowItemIds, - isManagementTable, - isMlEnabledInSpace, - createAnalyticsForm - ); - const sorting = { sort: { field: sortField, @@ -349,26 +348,6 @@ export const DataFrameAnalyticsList: FC = ({ view: getTaskStateBadge(val), })), }, - // For now analytics jobs are batch only - /* - { - type: 'field_value_selection', - field: 'mode', - name: i18n.translate('xpack.ml.dataframe.analyticsList.modeFilter', { - defaultMessage: 'Mode', - }), - multiSelect: false, - options: Object.values(DATA_FRAME_MODE).map(val => ({ - value: val, - name: val, - view: ( - - {val} - - ), - })), - }, - */ ], }; @@ -386,7 +365,8 @@ export const DataFrameAnalyticsList: FC = ({ }; return ( - + <> + {modals} {analyticsStats && ( @@ -435,6 +415,6 @@ export const DataFrameAnalyticsList: FC = ({ {isSourceIndexModalVisible === true && ( setIsSourceIndexModalVisible(false)} /> )} - + ); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_actions.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_actions.tsx new file mode 100644 index 0000000000000..34bb60a71164f --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_actions.tsx @@ -0,0 +1,84 @@ +/* + * 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 { pick } from 'lodash'; + +import { EuiTableActionsColumnType } from '@elastic/eui'; + +import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; +import { CloneButton } from '../action_clone'; +import { useDeleteAction, DeleteButton, DeleteButtonModal } from '../action_delete'; +import { useStartAction, StartButton, StartButtonModal } from '../action_start'; +import { StopButton } from '../action_stop'; +import { getViewAction } from '../action_view'; + +import { isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common'; + +export const useActions = ( + createAnalyticsForm: CreateAnalyticsFormProps, + isManagementTable: boolean +): { + actions: EuiTableActionsColumnType['actions']; + modals: JSX.Element | null; +} => { + const deleteAction = useDeleteAction(); + const startAction = useStartAction(); + + let modals: JSX.Element | null = null; + + const actions: EuiTableActionsColumnType['actions'] = [ + getViewAction(isManagementTable), + ]; + + if (isManagementTable === false) { + modals = ( + <> + + + + ); + actions.push( + ...[ + { + render: (item: DataFrameAnalyticsListRow) => { + if (!isDataFrameAnalyticsRunning(item.stats.state)) { + return ; + } + return ; + }, + }, + { + render: (item: DataFrameAnalyticsListRow) => { + return ; + }, + }, + { + render: (item: DataFrameAnalyticsListRow) => { + return ; + }, + }, + ] + ); + } + + return { actions, modals }; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx similarity index 93% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx index a3d2e65386c19..fa88396461cd7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns.tsx @@ -33,7 +33,7 @@ import { DataFrameAnalyticsListRow, DataFrameAnalyticsStats, } from './common'; -import { getActions } from './actions'; +import { useActions } from './use_actions'; enum TASK_STATE_COLOR { analyzing = 'primary', @@ -141,14 +141,14 @@ export const getDFAnalyticsJobIdLink = (item: DataFrameAnalyticsListRow) => ( {item.id} ); -export const getColumns = ( +export const useColumns = ( expandedRowItemIds: DataFrameAnalyticsId[], setExpandedRowItemIds: React.Dispatch>, isManagementTable: boolean = false, isMlEnabledInSpace: boolean = true, createAnalyticsForm?: CreateAnalyticsFormProps ) => { - const actions = getActions(createAnalyticsForm!, isManagementTable); + const { actions, modals } = useActions(createAnalyticsForm!, isManagementTable); function toggleDetails(item: DataFrameAnalyticsListRow) { const index = expandedRowItemIds.indexOf(item.config.id); @@ -253,20 +253,6 @@ export const getColumns = ( width: '100px', 'data-test-subj': 'mlAnalyticsTableColumnStatus', }, - // For now there is batch mode only so we hide this column for now. - /* - { - name: i18n.translate('xpack.ml.dataframe.analyticsList.mode', { defaultMessage: 'Mode' }), - sortable: (item: DataFrameAnalyticsListRow) => item.mode, - truncateText: true, - render(item: DataFrameAnalyticsListRow) { - const mode = item.mode; - const color = 'hollow'; - return {mode}; - }, - width: '100px', - }, - */ progressColumn, { name: i18n.translate('xpack.ml.dataframe.analyticsList.tableActionLabel', { @@ -293,5 +279,5 @@ export const getColumns = ( } } - return columns; + return { columns, modals }; }; From f4186e7d807ab31303d9bd7f4da8d82d39437f55 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 6 Jul 2020 11:41:23 +0200 Subject: [PATCH 06/11] [ML] Text tweak. --- .../components/action_delete/delete_button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx index ff2f405775db3..7da3bced48576 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button.tsx @@ -49,7 +49,7 @@ export const DeleteButton: FC = ({ item, onClick }) => { ? i18n.translate( 'xpack.ml.dataframe.analyticsList.deleteActionDisabledToolTipContent', { - defaultMessage: 'Stop the data frame analytics in order to delete it.', + defaultMessage: 'Stop the data frame analytics job in order to delete it.', } ) : createPermissionFailureMessage('canStartStopDataFrameAnalytics') From 4382fee77b3f69cfc99f2ab061b3fabcc987044f Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 6 Jul 2020 11:43:09 +0200 Subject: [PATCH 07/11] [ML] Simplify props. --- .../action_delete/delete_button_modal.tsx | 150 ++++++++---------- .../action_start/start_button_modal.tsx | 13 +- .../components/analytics_list/use_actions.tsx | 20 +-- .../action_delete/delete_button_modal.tsx | 61 +++---- .../action_start/start_button_modal.tsx | 62 +++----- .../transform_list/transform_list.tsx | 21 +-- .../components/transform_list/use_actions.tsx | 21 +-- 7 files changed, 116 insertions(+), 232 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx index 7fca76c4aebc8..f94dccee479bd 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/delete_button_modal.tsx @@ -18,26 +18,12 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { DeleteAction } from './use_delete_action'; -type DeleteButtonModalProps = Pick< - DeleteAction, - | 'closeModal' - | 'deleteAndCloseModal' - | 'deleteTargetIndex' - | 'deleteIndexPattern' - | 'indexPatternExists' - | 'isModalVisible' - | 'item' - | 'toggleDeleteIndex' - | 'toggleDeleteIndexPattern' - | 'userCanDeleteIndex' ->; -export const DeleteButtonModal: FC = ({ +export const DeleteButtonModal: FC = ({ closeModal, deleteAndCloseModal, deleteTargetIndex, deleteIndexPattern, indexPatternExists, - isModalVisible, item, toggleDeleteIndex, toggleDeleteIndexPattern, @@ -50,77 +36,73 @@ export const DeleteButtonModal: FC = ({ const indexName = item.config.dest.index; return ( - <> - {isModalVisible && ( - - -

- -

+ + +

+ +

- - - {userCanDeleteIndex && ( - + + + {userCanDeleteIndex && ( + - - {userCanDeleteIndex && indexPatternExists && ( - + checked={deleteTargetIndex} + onChange={toggleDeleteIndex} + /> + )} + + + {userCanDeleteIndex && indexPatternExists && ( + - -
-
- )} - + checked={deleteIndexPattern} + onChange={toggleDeleteIndexPattern} + /> + )} + + +
+
); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx index bf3505f3a26ea..664dbe5c62b2f 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_start/start_button_modal.tsx @@ -10,19 +10,10 @@ import { EuiConfirmModal, EuiOverlayMask, EUI_MODAL_CONFIRM_BUTTON } from '@elas import { StartAction } from './use_start_action'; -type StartButtonModalProps = Pick< - StartAction, - 'closeModal' | 'isModalVisible' | 'item' | 'startAndCloseModal' ->; -export const StartButtonModal: FC = ({ - closeModal, - isModalVisible, - item, - startAndCloseModal, -}) => { +export const StartButtonModal: FC = ({ closeModal, item, startAndCloseModal }) => { return ( <> - {isModalVisible && item !== undefined && ( + {item !== undefined && ( - - + {startAction.isModalVisible && } + {deleteAction.isModalVisible && } ); actions.push( diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx index 89c1e759c10de..668e535198649 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/delete_button_modal.tsx @@ -20,27 +20,12 @@ import { TRANSFORM_STATE } from '../../../../../../common'; import { DeleteAction } from './use_delete_action'; -type DeleteButtonModalProps = Pick< - DeleteAction, - | 'closeModal' - | 'deleteAndCloseModal' - | 'deleteDestIndex' - | 'deleteIndexPattern' - | 'indexPatternExists' - | 'isModalVisible' - | 'items' - | 'shouldForceDelete' - | 'toggleDeleteIndex' - | 'toggleDeleteIndexPattern' - | 'userCanDeleteIndex' ->; -export const DeleteButtonModal: FC = ({ +export const DeleteButtonModal: FC = ({ closeModal, deleteAndCloseModal, deleteDestIndex, deleteIndexPattern, indexPatternExists, - isModalVisible, items, shouldForceDelete, toggleDeleteIndex, @@ -167,32 +152,22 @@ export const DeleteButtonModal: FC = ({ ); return ( - <> - {isModalVisible && ( - - - {isBulkAction ? bulkDeleteModalContent : deleteModalContent} - - - )} - + + + {isBulkAction ? bulkDeleteModalContent : deleteModalContent} + + ); }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx index 95eecc2d0c657..2ef0d20c45116 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/start_button_modal.tsx @@ -10,11 +10,7 @@ import { EuiConfirmModal, EuiOverlayMask, EUI_MODAL_CONFIRM_BUTTON } from '@elas import { StartAction } from './use_start_action'; -type StartButtonModalProps = Pick< - StartAction, - 'closeModal' | 'isModalVisible' | 'items' | 'startAndCloseModal' ->; -export const StartButtonModal: FC = ({ +export const StartButtonModal: FC = ({ closeModal, isModalVisible, items, @@ -32,38 +28,28 @@ export const StartButtonModal: FC = ({ }); return ( - <> - {isModalVisible && ( - - -

- {i18n.translate('xpack.transform.transformList.startModalBody', { - defaultMessage: - 'A transform will increase search and indexing load in your cluster. Please stop the transform if excessive load is experienced. Are you sure you want to start {count, plural, one {this} other {these}} {count} {count, plural, one {transform} other {transforms}}?', - values: { count: items.length }, - })} -

-
-
- )} - + + +

+ {i18n.translate('xpack.transform.transformList.startModalBody', { + defaultMessage: + 'A transform will increase search and indexing load in your cluster. Please stop the transform if excessive load is experienced. Are you sure you want to start {count, plural, one {this} other {these}} {count} {count, plural, one {transform} other {transforms}}?', + values: { count: items.length }, + })} +

+
+
); }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx index a2dcd54c6677e..9df4113fa9a8b 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx @@ -5,7 +5,6 @@ */ import React, { MouseEventHandler, FC, useContext, useState } from 'react'; -import { pick } from 'lodash'; import { i18n } from '@kbn/i18n'; @@ -382,24 +381,8 @@ export const TransformList: FC = ({ return (
{/* Bulk Action Modals */} - - + {bulkStartAction.isModalVisible && } + {bulkDeleteAction.isModalVisible && } {/* Single Action Modals */} {singleActionModals} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx index bce4a3113c356..8938ff288075f 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; -import { pick } from 'lodash'; import { EuiTableComputedColumnType } from '@elastic/eui'; @@ -32,27 +31,11 @@ export const useActions = ({ return { modals: ( <> - + {startAction.isModalVisible && } {editAction.config && editAction.isFlyoutVisible && ( )} - + {deleteAction.isModalVisible && } ), actions: [ From e47755be48e17356f9dbf0209f5725c00666dcab Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 6 Jul 2020 13:10:49 +0200 Subject: [PATCH 08/11] [ML] Fix imports and types. --- .../classification_exploration/evaluate_panel.tsx | 2 +- .../exploration_results_table.tsx | 2 +- .../components/outlier_exploration/outlier_exploration.tsx | 2 +- .../components/regression_exploration/evaluate_panel.tsx | 2 +- .../analytics_management/components/action_clone/index.ts | 7 ++++++- .../components/analytics_list/expanded_row.tsx | 2 +- .../hooks/use_create_analytics_form/state.ts | 2 +- .../use_create_analytics_form/use_create_analytics_form.ts | 5 +---- .../overview/components/analytics_panel/table.tsx | 6 +++--- 9 files changed, 16 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx index 45f883c4ccd94..86e2c5fd2fb94 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx @@ -30,7 +30,7 @@ import { DataFrameAnalyticsConfig, } from '../../../../common'; import { isKeywordAndTextType } from '../../../../common/fields'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; +import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; import { isResultsSearchBoolQuery, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx index 941fbefd78084..2b36d04c44baf 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/exploration_results_table.tsx @@ -29,7 +29,7 @@ import { SEARCH_SIZE, defaultSearchQuery, } from '../../../../common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; +import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; import { ExplorationTitle } from '../exploration_title'; import { ExplorationQueryBar } from '../exploration_query_bar'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx index 0b29b7f43bfc8..eb193b6f37ab4 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/outlier_exploration.tsx @@ -29,7 +29,7 @@ import { getToastNotifications } from '../../../../../util/dependency_cache'; import { defaultSearchQuery, useResultsViewConfig, INDEX_STATUS } from '../../../../common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; +import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; import { ExplorationQueryBar } from '../exploration_query_bar'; import { ExplorationTitle } from '../exploration_title'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx index f6e8e0047671f..d31b7734f9969 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/evaluate_panel.tsx @@ -27,7 +27,7 @@ import { Eval, DataFrameAnalyticsConfig, } from '../../../../common'; -import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; +import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/use_columns'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; import { EvaluateStat } from './evaluate_stat'; import { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts index 727cc87c70f2c..b3d7189ff8cda 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/index.ts @@ -4,4 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -export { CloneButton } from './clone_button'; +export { + extractCloningConfig, + isAdvancedConfig, + CloneButton, + CloneDataFrameAnalyticsConfig, +} from './clone_button'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx index 0ee57fe5be141..4d029ff1d9546 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx @@ -24,7 +24,7 @@ import { loadEvalData, Eval, } from '../../../../common'; -import { getTaskStateBadge } from './columns'; +import { getTaskStateBadge } from './use_columns'; import { getDataFrameAnalyticsProgressPhase, isCompletedAnalyticsJob } from './common'; import { isRegressionAnalysis, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index 241866b56c5c8..9cc46eb9723a9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -16,7 +16,7 @@ import { DataFrameAnalyticsConfig, ANALYSIS_CONFIG_TYPE, } from '../../../../common/analytics'; -import { CloneDataFrameAnalyticsConfig } from '../../components/analytics_list/action_clone'; +import { CloneDataFrameAnalyticsConfig } from '../../components/action_clone'; export enum DEFAULT_MODEL_MEMORY_LIMIT { regression = '100mb', diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts index f95d2f572a406..4c312be26613c 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts @@ -18,10 +18,7 @@ import { DataFrameAnalyticsId, DataFrameAnalyticsConfig, } from '../../../../common'; -import { - extractCloningConfig, - isAdvancedConfig, -} from '../../components/analytics_list/action_clone'; +import { extractCloningConfig, isAdvancedConfig } from '../../components/action_clone'; import { ActionDispatchers, ACTION } from './actions'; import { reducer } from './reducer'; diff --git a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/table.tsx b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/table.tsx index f2e6ff7885b16..1eeff6287867d 100644 --- a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/table.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/table.tsx @@ -22,8 +22,8 @@ import { import { getTaskStateBadge, progressColumn, -} from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/columns'; -import { getAnalyticsViewAction } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/actions'; +} from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/use_columns'; +import { getViewAction } from '../../../data_frame_analytics/pages/analytics_management/components/action_view'; import { formatHumanReadableDateTimeSeconds } from '../../../util/date_utils'; const MlInMemoryTable = mlInMemoryTableFactory(); @@ -82,7 +82,7 @@ export const AnalyticsTable: FC = ({ items }) => { name: i18n.translate('xpack.ml.overview.analyticsList.tableActionLabel', { defaultMessage: 'Actions', }), - actions: [getAnalyticsViewAction()], + actions: [getViewAction()], width: '100px', }, ]; From d7cf5797912bc83e14d63132bc049952001eb7ff Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 7 Jul 2020 09:43:01 +0200 Subject: [PATCH 09/11] [ML] Update tests to reflect new required component structure. --- .../action_delete/action_delete.test.tsx | 21 ++++++++++++++--- .../__snapshots__/action_delete.test.tsx.snap | 23 ------------------- .../__snapshots__/action_start.test.tsx.snap | 23 ------------------- .../__snapshots__/action_stop.test.tsx.snap | 21 ----------------- 4 files changed, 18 insertions(+), 70 deletions(-) delete mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_delete.test.tsx.snap delete mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_start.test.tsx.snap delete mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_stop.test.tsx.snap diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx index 4ce5893d19b10..8d6272c5df860 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_delete/action_delete.test.tsx @@ -7,14 +7,17 @@ import React from 'react'; import { fireEvent, render } from '@testing-library/react'; import * as CheckPrivilige from '../../../../../capabilities/check_capabilities'; -import mockAnalyticsListItem from './__mocks__/analytics_list_item.json'; -import { DeleteButton } from './delete_button'; +import mockAnalyticsListItem from '../analytics_list/__mocks__/analytics_list_item.json'; import { I18nProvider } from '@kbn/i18n/react'; import { coreMock as mockCoreServices, i18nServiceMock, } from '../../../../../../../../../../src/core/public/mocks'; +import { DeleteButton } from './delete_button'; +import { DeleteButtonModal } from './delete_button_modal'; +import { useDeleteAction } from './use_delete_action'; + jest.mock('../../../../../capabilities/check_capabilities', () => ({ checkPermission: jest.fn(() => false), createPermissionFailureMessage: jest.fn(), @@ -77,9 +80,21 @@ describe('DeleteAction', () => { test('should allow to delete target index by default.', () => { const mock = jest.spyOn(CheckPrivilige, 'checkPermission'); mock.mockImplementation((p) => p === 'canDeleteDataFrameAnalytics'); + + const TestComponent = () => { + const deleteAction = useDeleteAction(); + + return ( + <> + {deleteAction.isModalVisible && } + + + ); + }; + const { getByTestId, queryByTestId } = render( - {}} /> + ); const deleteButton = getByTestId('mlAnalyticsJobDeleteButton'); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_delete.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_delete.test.tsx.snap deleted file mode 100644 index da5ad27c9d6b1..0000000000000 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_delete.test.tsx.snap +++ /dev/null @@ -1,23 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Transform: Transform List Actions Minimal initialization 1`] = ` - - - - Delete - - - -`; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_start.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_start.test.tsx.snap deleted file mode 100644 index d534f05d3be96..0000000000000 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_start.test.tsx.snap +++ /dev/null @@ -1,23 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Transform: Transform List Actions Minimal initialization 1`] = ` - - - - Start - - - -`; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_stop.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_stop.test.tsx.snap deleted file mode 100644 index 97d393bc8128b..0000000000000 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/action_stop.test.tsx.snap +++ /dev/null @@ -1,21 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Transform: Transform List Actions Minimal initialization 1`] = ` - - - Stop - - -`; From 1c42f67ce8ae506f358a91428b276587ff4127e2 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 7 Jul 2020 12:01:05 +0200 Subject: [PATCH 10/11] [ML] Update tests to reflect new required component structure. --- .../__snapshots__/delete_button.test.tsx.snap | 22 +++++++++++++++++++ .../__snapshots__/start_button.test.tsx.snap | 20 +++++++++++++++++ .../__snapshots__/stop_button.test.tsx.snap | 22 +++++++++++++++++++ .../transform_list/transform_list.test.tsx | 1 + .../transform_list/use_actions.test.tsx | 1 + .../transform_list/use_columns.test.tsx | 1 + 6 files changed, 67 insertions(+) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap new file mode 100644 index 0000000000000..3980cc5d5a1ae --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_delete/__snapshots__/delete_button.test.tsx.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Transform: Transform List Actions Minimal initialization 1`] = ` + + + + + Delete + + +`; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap new file mode 100644 index 0000000000000..231a1f30f2c31 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_start/__snapshots__/start_button.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Transform: Transform List Actions Minimal initialization 1`] = ` + + + + + Start + + +`; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap new file mode 100644 index 0000000000000..dd81bf34bf582 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_stop/__snapshots__/stop_button.test.tsx.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Transform: Transform List Actions Minimal initialization 1`] = ` + + + + + Stop + + +`; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.test.tsx index 5e0363d0a7a15..70b3dc7c2bffe 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.test.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { TransformList } from './transform_list'; jest.mock('../../../../../shared_imports'); +jest.mock('../../../../../app/app_dependencies'); describe('Transform: Transform List ', () => { test('Minimal initialization', () => { diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx index 5c5d3017ac871..e58d5ed572667 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.test.tsx @@ -9,6 +9,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { useActions } from './use_actions'; jest.mock('../../../../../shared_imports'); +jest.mock('../../../../../app/app_dependencies'); describe('Transform: Transform List Actions', () => { test('useActions()', () => { diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx index 1f57e6e377798..94d3e5322a2e8 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_columns.test.tsx @@ -9,6 +9,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { useColumns } from './use_columns'; jest.mock('../../../../../shared_imports'); +jest.mock('../../../../../app/app_dependencies'); describe('Transform: Job List Columns', () => { test('useColumns()', () => { From 5de8ec35ad6ccce808b06edea76fe2a6c2b6827e Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 7 Jul 2020 13:51:25 +0200 Subject: [PATCH 11/11] [ML] Fix transform edit button setup. --- .../components/action_edit/edit_button.tsx | 8 +++----- .../components/transform_list/use_actions.tsx | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx index b418690b83171..6ba8e7aeba20f 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/action_edit/edit_button.tsx @@ -10,17 +10,15 @@ import { i18n } from '@kbn/i18n'; import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; -import { TransformPivotConfig } from '../../../../common'; import { createCapabilityFailureMessage, AuthorizationContext, } from '../../../../lib/authorization'; interface EditButtonProps { - config: TransformPivotConfig; - onClick: (config: TransformPivotConfig) => void; + onClick: () => void; } -export const EditButton: FC = ({ config, onClick }) => { +export const EditButton: FC = ({ onClick }) => { const { canCreateTransform } = useContext(AuthorizationContext).capabilities; const buttonEditText = i18n.translate('xpack.transform.transformList.editActionName', { @@ -32,7 +30,7 @@ export const EditButton: FC = ({ config, onClick }) => { data-test-subj="transformActionEdit" color={!canCreateTransform ? 'subdued' : 'text'} disabled={!canCreateTransform} - onClick={!canCreateTransform ? undefined : () => onClick(config)} + onClick={!canCreateTransform ? undefined : onClick} aria-label={buttonEditText} > {buttonEditText} diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx index 8938ff288075f..a6b1aa1a1b5c5 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/use_actions.tsx @@ -55,7 +55,7 @@ export const useActions = ({ }, { render: (item: TransformListRow) => { - return ; + return editAction.showFlyout(item.config)} />; }, }, {