From 55d2cf1f10f0af816e0a2464993b6987fb5c486a Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Fri, 6 May 2022 12:31:11 -0400 Subject: [PATCH] Integrations Page: Remove edit integration from UI, Render duplicate error message, Unique integration naming convention (#5577) --- changes/issue-5565-sunset-edit-integration | 1 + .../integration/all/app/settingsflow.spec.ts | 74 ------------------- .../IntegrationsPage/IntegrationsPage.tsx | 68 ++++++++++++++--- .../IntegrationsTableConfig.tsx | 5 -- .../DeleteIntegrationModal.tsx | 7 +- 5 files changed, 64 insertions(+), 91 deletions(-) create mode 100644 changes/issue-5565-sunset-edit-integration diff --git a/changes/issue-5565-sunset-edit-integration b/changes/issue-5565-sunset-edit-integration new file mode 100644 index 0000000000..47b13500f9 --- /dev/null +++ b/changes/issue-5565-sunset-edit-integration @@ -0,0 +1 @@ +* Remove the ability to edit a Jira integration as integrations fields are unique to each integration \ No newline at end of file diff --git a/cypress/integration/all/app/settingsflow.spec.ts b/cypress/integration/all/app/settingsflow.spec.ts index b96ef2fe17..758b2a6503 100644 --- a/cypress/integration/all/app/settingsflow.spec.ts +++ b/cypress/integration/all/app/settingsflow.spec.ts @@ -174,35 +174,6 @@ const createConfig = { }, }; -const editConfig = { - ...getConfig, - integrations: { - jira: [ - { - url: "https://fleetdm.atlassian.com", - username: "jira1@example.com", - api_token: "jira123", - project_key: "PROJECT 1", - enable_software_vulnerabilities: false, - }, - { - url: "https://fleetdm.atlassian.com", - username: "jira0@example.com", - api_token: "jira0123", - project_key: "PROJECT 0", - enable_software_vulnerabilities: false, - }, - { - url: "https://fleetdm.atlassian.com", - username: "jira3@example.com", - api_token: "jira123", - project_key: "PROJECT 3", - enable_software_vulnerabilities: false, - }, - ], - }, -}; - const deleteConfig = { ...getConfig, integrations: { @@ -564,51 +535,6 @@ describe("App settings flow", () => { console.log(JSON.stringify(configStub)); }); }); - it("edits jira integration", () => { - cy.getAttached("tbody>tr") - .should("have.length", 3) - .eq(1) - .within(() => { - cy.findByText(/action/i).click(); - cy.findByText(/edit/i).click(); - }); - cy.findByLabelText(/jira site url/i) - .clear() - .type("https://fleetdm.atlassian.com"); - cy.findByLabelText(/jira username/i) - .clear() - .type("jira0@example.com"); - cy.findByLabelText(/jira api token/i) - .clear() - .type("jira0123"); - cy.findByLabelText(/jira project key/i) - .clear() - .type("PROJECT 0"); - cy.intercept("PATCH", "/api/latest/fleet/config", editConfig).as( - "editIntegration" - ); - cy.intercept("GET", "/api/latest/fleet/config", editConfig).as( - "editedIntegration" - ); - cy.getAttached(".integration-form__btn-wrap") - .contains("button", /save/i) - .click(); - cy.wait("@editIntegration").then((configStub) => { - cy.log(JSON.stringify(configStub)); - console.log(JSON.stringify(configStub)); - }); - cy.wait("@editedIntegration").then((configStub) => { - cy.log(JSON.stringify(configStub)); - console.log(JSON.stringify(configStub)); - cy.findByText(/successfully edited/i).should("exist"); - cy.getAttached("tbody>tr") - .should("have.length", 3) - .eq(0) - .within(() => { - cy.findByText(/fleetdm.atlassian.com - project 0/i).should("exist"); - }); - }); - }); it("deletes jira integration", () => { cy.getAttached("tbody>tr") .eq(1) diff --git a/frontend/pages/admin/IntegrationsPage/IntegrationsPage.tsx b/frontend/pages/admin/IntegrationsPage/IntegrationsPage.tsx index f55652a279..d9e57f11f4 100644 --- a/frontend/pages/admin/IntegrationsPage/IntegrationsPage.tsx +++ b/frontend/pages/admin/IntegrationsPage/IntegrationsPage.tsx @@ -143,6 +143,12 @@ const IntegrationsPage = (): JSX.Element => { jiraIntegrationSubmitData[ jiraIntegrationSubmitData.length - 1 ].url + }{" "} + -{" "} + { + jiraIntegrationSubmitData[ + jiraIntegrationSubmitData.length - 1 + ].project_key } @@ -154,11 +160,36 @@ const IntegrationsPage = (): JSX.Element => { .catch((createError: { data: IApiError }) => { if (createError.data.message.includes("Validation Failed")) { renderFlash("error", VALIDATION_FAILED_ERROR); - } - if (createError.data.message.includes("Bad request")) { - renderFlash("error", BAD_REQUEST_ERROR); - } - if (createError.data.message.includes("Unknown Error")) { + } else if (createError.data.message.includes("Bad request")) { + if ( + createError.data.errors[0].reason.includes( + "duplicate Jira integration for project key" + ) + ) { + renderFlash( + "error", + <> + Could not add add{" "} + + { + jiraIntegrationSubmitData[ + jiraIntegrationSubmitData.length - 1 + ].url + }{" "} + -{" "} + { + jiraIntegrationSubmitData[ + jiraIntegrationSubmitData.length - 1 + ].project_key + } + + . This integration already exists + + ); + } else { + renderFlash("error", BAD_REQUEST_ERROR); + } + } else if (createError.data.message.includes("Unknown Error")) { renderFlash("error", UNKNOWN_ERROR); } else { renderFlash( @@ -194,7 +225,10 @@ const IntegrationsPage = (): JSX.Element => { renderFlash( "success", <> - Successfully deleted {integrationEditing.url} + Successfully deleted{" "} + + {integrationEditing.url} - {integrationEditing.project_key} + ); refetchIntegrations(); @@ -203,8 +237,11 @@ const IntegrationsPage = (): JSX.Element => { renderFlash( "error", <> - Could not delete {integrationEditing.url}. Please try - again. + Could not delete{" "} + + {integrationEditing.url} - {integrationEditing.project_key} + + . Please try again. ); }) @@ -226,7 +263,11 @@ const IntegrationsPage = (): JSX.Element => { <> Successfully edited{" "} - {jiraIntegrationSubmitData[integrationEditing?.index].url} + {jiraIntegrationSubmitData[integrationEditing?.index].url} -{" "} + { + jiraIntegrationSubmitData[integrationEditing?.index] + .project_key + } ); @@ -248,8 +289,12 @@ const IntegrationsPage = (): JSX.Element => { renderFlash( "error", <> - Could not edit {integrationEditing?.url}. Please try - again. + Could not edit{" "} + + {integrationEditing?.url} -{" "} + {integrationEditing?.project_key} + + . Please try again. ); } @@ -356,6 +401,7 @@ const IntegrationsPage = (): JSX.Element => { onCancel={toggleDeleteIntegrationModal} onSubmit={onDeleteSubmit} url={integrationEditing?.url || ""} + projectKey={integrationEditing?.project_key || ""} /> )} {showEditIntegrationModal && ( diff --git a/frontend/pages/admin/IntegrationsPage/IntegrationsTableConfig.tsx b/frontend/pages/admin/IntegrationsPage/IntegrationsTableConfig.tsx index 3015b8f0cc..0206c18173 100644 --- a/frontend/pages/admin/IntegrationsPage/IntegrationsTableConfig.tsx +++ b/frontend/pages/admin/IntegrationsPage/IntegrationsTableConfig.tsx @@ -100,11 +100,6 @@ const generateTableHeaders = ( // NOTE: may need current user ID later for permission on actions. const generateActionDropdownOptions = (): IDropdownOption[] => { return [ - { - label: "Edit", - disabled: false, - value: "edit", - }, { label: "Delete", disabled: false, diff --git a/frontend/pages/admin/IntegrationsPage/components/DeleteIntegrationModal/DeleteIntegrationModal.tsx b/frontend/pages/admin/IntegrationsPage/components/DeleteIntegrationModal/DeleteIntegrationModal.tsx index 03bdc7f884..93d2682666 100644 --- a/frontend/pages/admin/IntegrationsPage/components/DeleteIntegrationModal/DeleteIntegrationModal.tsx +++ b/frontend/pages/admin/IntegrationsPage/components/DeleteIntegrationModal/DeleteIntegrationModal.tsx @@ -7,12 +7,14 @@ const baseClass = "delete-integration-modal"; interface IDeleteIntegrationModalProps { url: string; + projectKey: string; onSubmit: () => void; onCancel: () => void; } const DeleteIntegrationModal = ({ url, + projectKey, onSubmit, onCancel, }: IDeleteIntegrationModalProps): JSX.Element => { @@ -34,7 +36,10 @@ const DeleteIntegrationModal = ({

This action will delete the{" "} - {url} integration. + + {url} - {projectKey} + {" "} + integration.

The automations that use this integration will be turned off.