Skip to content
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

[Alerting UI] Disable "Save" button for Alerts with broken Connectors #80579

Merged
merged 4 commits into from
Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe('action_form', () => {
describe('action_form in alert', () => {
let wrapper: ReactWrapper<any>;

async function setup() {
async function setup(customActions?: AlertAction[]) {
const { loadAllActions } = jest.requireMock('../../lib/action_connector_api');
loadAllActions.mockResolvedValueOnce([
{
Expand Down Expand Up @@ -177,6 +177,7 @@ describe('action_form', () => {
show: true,
},
},
setHasActionsWithBrokenConnector: jest.fn(),
actionTypeRegistry: actionTypeRegistry as any,
docLinks: { ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' },
};
Expand All @@ -198,16 +199,18 @@ describe('action_form', () => {
schedule: {
interval: '1m',
},
actions: [
{
group: 'default',
id: 'test',
actionTypeId: actionType.id,
params: {
message: '',
},
},
],
actions: customActions
? customActions
: [
{
group: 'default',
id: 'test',
actionTypeId: actionType.id,
params: {
message: '',
},
},
],
tags: [],
muteAll: false,
enabled: false,
Expand All @@ -229,6 +232,7 @@ describe('action_form', () => {
setActionParamsProperty={(key: string, value: any, index: number) =>
(initialAlert.actions[index] = { ...initialAlert.actions[index], [key]: value })
}
setHasActionsWithBrokenConnector={deps!.setHasActionsWithBrokenConnector}
http={deps!.http}
actionTypeRegistry={deps!.actionTypeRegistry}
defaultActionMessage={'Alert [{{ctx.metadata.name}}] has exceeded the threshold'}
Expand Down Expand Up @@ -306,6 +310,7 @@ describe('action_form', () => {
.find(`EuiToolTip [data-test-subj="${actionType.id}-ActionTypeSelectOption"]`)
.exists()
).toBeFalsy();
expect(deps.setHasActionsWithBrokenConnector).toHaveBeenLastCalledWith(false);
});

it('does not render action types disabled by config', async () => {
Expand Down Expand Up @@ -392,5 +397,27 @@ describe('action_form', () => {
);
expect(actionOption.exists()).toBeFalsy();
});

it('recognizes actions with broken connectors', async () => {
await setup([
{
group: 'default',
id: 'test',
actionTypeId: actionType.id,
params: {
message: '',
},
},
{
group: 'default',
id: 'connector-doesnt-exist',
actionTypeId: actionType.id,
params: {
message: 'broken',
},
},
]);
expect(deps.setHasActionsWithBrokenConnector).toHaveBeenLastCalledWith(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ interface ActionAccordionFormProps {
messageVariables?: ActionVariable[];
defaultActionMessage?: string;
setHasActionsDisabled?: (value: boolean) => void;
setHasActionsWithBrokenConnector?: (value: boolean) => void;
capabilities: ApplicationStart['capabilities'];
}

Expand All @@ -83,6 +84,7 @@ export const ActionForm = ({
defaultActionMessage,
toastNotifications,
setHasActionsDisabled,
setHasActionsWithBrokenConnector,
capabilities,
docLinks,
}: ActionAccordionFormProps) => {
Expand Down Expand Up @@ -171,6 +173,16 @@ export const ActionForm = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [connectors, actionTypesIndex]);

useEffect(() => {
const hasActionWithBrokenConnector = actions.some(
(action) => !connectors.find((connector) => connector.id === action.id)
);
if (setHasActionsWithBrokenConnector) {
setHasActionsWithBrokenConnector(hasActionWithBrokenConnector);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [actions, connectors]);

const preconfiguredMessage = i18n.translate(
'xpack.triggersActionsUI.sections.actionForm.preconfiguredTitleMessage',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ export const AlertEdit = ({ initialAlert, onClose }: AlertEditProps) => {
const [{ alert }, dispatch] = useReducer(alertReducer, { alert: initialAlert });
const [isSaving, setIsSaving] = useState<boolean>(false);
const [hasActionsDisabled, setHasActionsDisabled] = useState<boolean>(false);
const [hasActionsWithBrokenConnector, setHasActionsWithBrokenConnector] = useState<boolean>(
false
);
const setAlert = (key: string, value: any) => {
dispatch({ command: { type: 'setAlert' }, payload: { key, value } });
};
Expand Down Expand Up @@ -155,6 +158,7 @@ export const AlertEdit = ({ initialAlert, onClose }: AlertEditProps) => {
errors={errors}
canChangeTrigger={false}
setHasActionsDisabled={setHasActionsDisabled}
setHasActionsWithBrokenConnector={setHasActionsWithBrokenConnector}
operation="i18n.translate('xpack.triggersActionsUI.sections.alertEdit.operationName', {
defaultMessage: 'edit',
})"
Expand All @@ -176,7 +180,7 @@ export const AlertEdit = ({ initialAlert, onClose }: AlertEditProps) => {
data-test-subj="saveEditedAlertButton"
type="submit"
iconType="check"
isDisabled={hasErrors || hasActionErrors}
isDisabled={hasErrors || hasActionErrors || hasActionsWithBrokenConnector}
isLoading={isSaving}
onClick={async () => {
setIsSaving(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ interface AlertFormProps {
errors: IErrorObject;
canChangeTrigger?: boolean; // to hide Change trigger button
setHasActionsDisabled?: (value: boolean) => void;
setHasActionsWithBrokenConnector?: (value: boolean) => void;
operation: string;
}

Expand All @@ -90,6 +91,7 @@ export const AlertForm = ({
dispatch,
errors,
setHasActionsDisabled,
setHasActionsWithBrokenConnector,
operation,
}: AlertFormProps) => {
const alertsContext = useAlertsContext();
Expand Down Expand Up @@ -260,6 +262,7 @@ export const AlertForm = ({
<ActionForm
actions={alert.actions}
setHasActionsDisabled={setHasActionsDisabled}
setHasActionsWithBrokenConnector={setHasActionsWithBrokenConnector}
messageVariables={
alertTypesIndex && alertTypesIndex.has(alert.alertTypeId)
? actionVariablesFromAlertType(alertTypesIndex.get(alert.alertTypeId)!).sort((a, b) =>
Expand Down