-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ML] Transforms: Adds _schedule_now
action to transform list.
#153545
Changes from 4 commits
8f1fadd
f991e5a
0ca8fbe
69df7c2
967f452
bdff00b
ca7197e
02b902b
f4898da
f0ed391
a92b1ae
24ba764
3563f14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import { TypeOf } from '@kbn/config-schema'; | ||
|
||
import { transformIdsSchema, CommonResponseStatusSchema } from './common'; | ||
|
||
export const scheduleNowTransformsRequestSchema = transformIdsSchema; | ||
export type ScheduleNowTransformsRequestSchema = TypeOf<typeof scheduleNowTransformsRequestSchema>; | ||
export type ScheduleNowTransformsResponseSchema = CommonResponseStatusSchema; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,81 @@ | ||||||
/* | ||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||||||
* or more contributor license agreements. Licensed under the Elastic License | ||||||
* 2.0; you may not use this file except in compliance with the Elastic License | ||||||
* 2.0. | ||||||
*/ | ||||||
|
||||||
import React from 'react'; | ||||||
|
||||||
import { i18n } from '@kbn/i18n'; | ||||||
|
||||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public'; | ||||||
|
||||||
import type { ScheduleNowTransformsRequestSchema } from '../../../common/api_schemas/schedule_now_transforms'; | ||||||
import { isScheduleNowTransformsResponseSchema } from '../../../common/api_schemas/type_guards'; | ||||||
|
||||||
import { getErrorMessage } from '../../../common/utils/errors'; | ||||||
|
||||||
import { useAppDependencies, useToastNotifications } from '../app_dependencies'; | ||||||
import { refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common'; | ||||||
import { ToastNotificationText } from '../components'; | ||||||
|
||||||
import { useApi } from './use_api'; | ||||||
|
||||||
export const useScheduleNowTransforms = () => { | ||||||
const { overlays, theme } = useAppDependencies(); | ||||||
const toastNotifications = useToastNotifications(); | ||||||
const api = useApi(); | ||||||
|
||||||
return async (transformsInfo: ScheduleNowTransformsRequestSchema) => { | ||||||
const results = await api.scheduleNowTransforms(transformsInfo); | ||||||
|
||||||
if (!isScheduleNowTransformsResponseSchema(results)) { | ||||||
toastNotifications.addDanger({ | ||||||
title: i18n.translate( | ||||||
'xpack.transform.stepCreateForm.scheduleNowTransformResponseSchemaErrorMessage', | ||||||
{ | ||||||
defaultMessage: 'An error occurred calling the schedule now transforms request.', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
), | ||||||
text: toMountPoint( | ||||||
<ToastNotificationText | ||||||
overlays={overlays} | ||||||
theme={theme} | ||||||
text={getErrorMessage(results)} | ||||||
/>, | ||||||
{ theme$: theme.theme$ } | ||||||
), | ||||||
}); | ||||||
return; | ||||||
} | ||||||
|
||||||
for (const transformId in results) { | ||||||
// hasOwnProperty check to ensure only properties on object itself, and not its prototypes | ||||||
if (results.hasOwnProperty(transformId)) { | ||||||
const result = results[transformId]; | ||||||
if (result.success === true) { | ||||||
toastNotifications.addSuccess( | ||||||
i18n.translate('xpack.transform.transformList.scheduleNowTransformSuccessMessage', { | ||||||
defaultMessage: 'Request to schedule now transform {transformId} acknowledged.', | ||||||
values: { transformId }, | ||||||
}) | ||||||
); | ||||||
} else { | ||||||
toastNotifications.addError(new Error(JSON.stringify(result.error!.caused_by, null, 2)), { | ||||||
title: i18n.translate( | ||||||
'xpack.transform.transformList.scheduleNowTransformErrorMessage', | ||||||
{ | ||||||
defaultMessage: 'An error occurred to schedule the transform {transformId} now', | ||||||
qn895 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
values: { transformId }, | ||||||
} | ||||||
), | ||||||
toastMessage: result.error!.reason, | ||||||
}); | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
refreshTransformList$.next(REFRESH_TRANSFORM_LIST_STATE.REFRESH); | ||||||
}; | ||||||
}; |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -15,6 +15,7 @@ export interface Capabilities { | |||||||||
canDeleteTransform: boolean; | ||||||||||
canPreviewTransform: boolean; | ||||||||||
canCreateTransform: boolean; | ||||||||||
canScheduleNowTransform: boolean; | ||||||||||
canStartStopTransform: boolean; | ||||||||||
canCreateTransformAlerts: boolean; | ||||||||||
canUseTransformAlerts: boolean; | ||||||||||
|
@@ -78,6 +79,14 @@ export function createCapabilityFailureMessage( | |||||||||
} | ||||||||||
); | ||||||||||
break; | ||||||||||
case 'canScheduleNowTransform': | ||||||||||
message = i18n.translate( | ||||||||||
'xpack.transform.capability.noPermission.scheduleNowTransformTooltip', | ||||||||||
{ | ||||||||||
defaultMessage: 'You do not have permission to schedule transforms now.', | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you need the word There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
} | ||||||||||
); | ||||||||||
break; | ||||||||||
case 'canStartStopTransform': | ||||||||||
message = i18n.translate( | ||||||||||
'xpack.transform.capability.noPermission.startOrStopTransformTooltip', | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
export { useScheduleNowAction } from './use_schedule_now_action'; | ||
export { ScheduleNowActionModal } from './schedule_now_action_modal'; | ||
export { isScheduleNowActionDisabled, ScheduleNowActionName } from './schedule_now_action_name'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
import React, { FC } from 'react'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { EuiConfirmModal, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui'; | ||
import { ScheduleNowAction } from './use_schedule_now_action'; | ||
|
||
export const ScheduleNowActionModal: FC<ScheduleNowAction> = ({ | ||
closeModal, | ||
items, | ||
scheduleNowAndCloseModal, | ||
}) => { | ||
const isBulkAction = items.length > 1; | ||
|
||
const bulkScheduleNowModalTitle = i18n.translate( | ||
'xpack.transform.transformList.bulkScheduleNowModalTitle', | ||
{ | ||
defaultMessage: 'Schedule {count} {count, plural, one {transform} other {transforms}} now?', | ||
values: { count: items && items.length }, | ||
} | ||
); | ||
const scheduleNowModalTitle = i18n.translate( | ||
'xpack.transform.transformList.scheduleNowModalTitle', | ||
{ | ||
defaultMessage: 'Schedule {transformId} now?', | ||
values: { transformId: items[0] && items[0].config.id }, | ||
} | ||
); | ||
|
||
return ( | ||
<EuiConfirmModal | ||
data-test-subj="transformScheduleNowModal" | ||
title={isBulkAction === true ? bulkScheduleNowModalTitle : scheduleNowModalTitle} | ||
onCancel={closeModal} | ||
onConfirm={scheduleNowAndCloseModal} | ||
cancelButtonText={i18n.translate( | ||
'xpack.transform.transformList.scheduleNowModalCancelButton', | ||
{ | ||
defaultMessage: 'Cancel', | ||
} | ||
)} | ||
confirmButtonText={i18n.translate( | ||
'xpack.transform.transformList.scheduleNowModalScheduleNowButton', | ||
{ | ||
defaultMessage: 'Schedule now', | ||
} | ||
)} | ||
defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} | ||
buttonColor="primary" | ||
> | ||
<p> | ||
{i18n.translate('xpack.transform.transformList.scheduleNowModalBody', { | ||
defaultMessage: | ||
'A transform increases search and indexing load in your cluster. If excessive load is experienced, stop the transform.', | ||
})} | ||
</p> | ||
</EuiConfirmModal> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,101 @@ | ||||||
/* | ||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||||||
* or more contributor license agreements. Licensed under the Elastic License | ||||||
* 2.0; you may not use this file except in compliance with the Elastic License | ||||||
* 2.0. | ||||||
*/ | ||||||
|
||||||
import React, { FC, useContext } from 'react'; | ||||||
import { i18n } from '@kbn/i18n'; | ||||||
import { EuiToolTip } from '@elastic/eui'; | ||||||
|
||||||
import { | ||||||
createCapabilityFailureMessage, | ||||||
AuthorizationContext, | ||||||
} from '../../../../lib/authorization'; | ||||||
import { TransformListRow, isCompletedBatchTransform } from '../../../../common'; | ||||||
|
||||||
export const scheduleNowActionNameText = i18n.translate( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a tooltip to this button to provide clarification as to what this action does as @qn895 suggested? Something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a tooltip in a92b1ae. |
||||||
'xpack.transform.transformList.scheduleNowActionNameText', | ||||||
{ | ||||||
defaultMessage: 'Schedule now', | ||||||
} | ||||||
); | ||||||
|
||||||
export const isScheduleNowActionDisabled = ( | ||||||
items: TransformListRow[], | ||||||
canScheduleNowTransform: boolean, | ||||||
transformNodes: number | ||||||
) => { | ||||||
// Disable schedule-now for batch transforms which have completed. | ||||||
const completedBatchTransform = items.some((i: TransformListRow) => isCompletedBatchTransform(i)); | ||||||
|
||||||
return ( | ||||||
!canScheduleNowTransform || | ||||||
completedBatchTransform || | ||||||
items.length === 0 || | ||||||
transformNodes === 0 | ||||||
); | ||||||
}; | ||||||
|
||||||
export interface ScheduleNowActionNameProps { | ||||||
items: TransformListRow[]; | ||||||
forceDisable?: boolean; | ||||||
transformNodes: number; | ||||||
} | ||||||
export const ScheduleNowActionName: FC<ScheduleNowActionNameProps> = ({ | ||||||
items, | ||||||
forceDisable, | ||||||
transformNodes, | ||||||
}) => { | ||||||
const { canScheduleNowTransform } = useContext(AuthorizationContext).capabilities; | ||||||
const isBulkAction = items.length > 1; | ||||||
|
||||||
// Disable schedule-now for batch transforms which have completed. | ||||||
const completedBatchTransform = items.some((i: TransformListRow) => isCompletedBatchTransform(i)); | ||||||
|
||||||
let completedBatchTransformMessage; | ||||||
|
||||||
if (isBulkAction === true) { | ||||||
completedBatchTransformMessage = i18n.translate( | ||||||
'xpack.transform.transformList.cannotScheduleNowCompleteBatchTransformBulkActionToolTip', | ||||||
{ | ||||||
defaultMessage: | ||||||
'One or more transforms are completed batch transforms and cannot be scheduled now.', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
); | ||||||
} else { | ||||||
completedBatchTransformMessage = i18n.translate( | ||||||
'xpack.transform.transformList.cannotScheduleNowCompleteBatchTransformToolTip', | ||||||
{ | ||||||
defaultMessage: '{transformId} is a completed batch transform and cannot be scheduled now.', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
values: { transformId: items[0] && items[0].config.id }, | ||||||
} | ||||||
); | ||||||
} | ||||||
|
||||||
const actionIsDisabled = isScheduleNowActionDisabled( | ||||||
items, | ||||||
canScheduleNowTransform, | ||||||
transformNodes | ||||||
); | ||||||
|
||||||
let content: string | undefined; | ||||||
if (actionIsDisabled && items.length > 0) { | ||||||
if (!canScheduleNowTransform) { | ||||||
content = createCapabilityFailureMessage('canScheduleNowTransform'); | ||||||
} else if (completedBatchTransform) { | ||||||
content = completedBatchTransformMessage; | ||||||
} | ||||||
} | ||||||
|
||||||
if ((forceDisable === true || actionIsDisabled) && content !== undefined) { | ||||||
return ( | ||||||
<EuiToolTip position="top" content={content}> | ||||||
<>{scheduleNowActionNameText}</> | ||||||
</EuiToolTip> | ||||||
); | ||||||
} | ||||||
|
||||||
return <>{scheduleNowActionNameText}</>; | ||||||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
An error occurred calling the request to schedule the transform.
?