From c04413245bfe3e0165ad0b3e6865e17fa518cd2e Mon Sep 17 00:00:00 2001 From: SupaJoon Date: Wed, 7 Jun 2023 12:37:28 -0400 Subject: [PATCH] EVG-15463: Create the Patch Name Change Modal (#1871) --- .../integration/version/name_change_modal.ts | 37 ++++++++ src/components/PageTitle.tsx | 4 +- .../SpruceForm/Widgets/LeafyGreenWidgets.tsx | 25 +++++- src/components/SpruceForm/Widgets/types.ts | 7 +- src/gql/generated/types.ts | 25 ++++++ src/gql/mutations/index.ts | 6 +- .../update-patch-description.graphql | 10 +++ src/pages/Version.tsx | 7 +- .../version/NameChangeModal/getFormSchema.ts | 27 ++++++ src/pages/version/NameChangeModal/index.tsx | 86 +++++++++++++++++++ 10 files changed, 224 insertions(+), 10 deletions(-) create mode 100644 cypress/integration/version/name_change_modal.ts create mode 100644 src/gql/mutations/update-patch-description.graphql create mode 100644 src/pages/version/NameChangeModal/getFormSchema.ts create mode 100644 src/pages/version/NameChangeModal/index.tsx diff --git a/cypress/integration/version/name_change_modal.ts b/cypress/integration/version/name_change_modal.ts new file mode 100644 index 0000000000..4b372e95b8 --- /dev/null +++ b/cypress/integration/version/name_change_modal.ts @@ -0,0 +1,37 @@ +describe("Name change modal", () => { + beforeEach(() => { + cy.visit("version/5f74d99ab2373627c047c5e5"); + }); + + it("Use the name change modal to change the name of a patch", () => { + const originalName = "main: EVG-7823 add a commit queue message (#4048)"; + cy.contains(originalName); + cy.dataCy("name-change-modal-trigger").click(); + const newName = "a different name"; + cy.get("textarea").clear().type(newName); + cy.contains("Confirm").click(); + cy.get("textarea").should("not.exist"); + cy.contains(newName); + cy.validateToast("success", "Patch name was successfully updated.", true); + // revert name change + cy.dataCy("name-change-modal-trigger").click(); + cy.get("textarea").clear().type(originalName); + cy.contains("Confirm").click(); + cy.get("textarea").should("not.exist"); + cy.validateToast("success", "Patch name was successfully updated.", true); + cy.contains(originalName); + }); + + it("The confirm button is disabled when the text area value is empty or greater than 300 characters", () => { + cy.dataCy("name-change-modal-trigger").click(); + cy.get("textarea").clear(); + cy.contains("button", "Confirm").should("be.disabled"); + cy.get("textarea").type("lol"); + cy.contains("button", "Confirm").should("not.be.disabled"); + const over300Chars = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + cy.get("textarea").type(over300Chars); + cy.contains("button", "Confirm").should("be.disabled"); + cy.contains("should NOT be longer than 300 characters"); + }); +}); diff --git a/src/components/PageTitle.tsx b/src/components/PageTitle.tsx index 1295d5f72f..aca4d89ec9 100644 --- a/src/components/PageTitle.tsx +++ b/src/components/PageTitle.tsx @@ -32,7 +32,8 @@ const TitleTypography: React.VFC = ({ } }; -export const PageTitle: React.VFC = ({ +export const PageTitle: React.FC = ({ + children, loading, title, badge, @@ -54,6 +55,7 @@ export const PageTitle: React.VFC = ({ {title} + {children} {badge} diff --git a/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx b/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx index f1ca064e6e..021d809bc1 100644 --- a/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx +++ b/src/components/SpruceForm/Widgets/LeafyGreenWidgets.tsx @@ -1,3 +1,4 @@ +import { useEffect, useRef } from "react"; import styled from "@emotion/styled"; import Banner from "@leafygreen-ui/banner"; import Checkbox from "@leafygreen-ui/checkbox"; @@ -330,21 +331,39 @@ const StyledRadioBox = styled(RadioBox)` `; export const LeafyGreenTextArea: React.VFC = ({ - label, disabled, - value, + label, onChange, options, rawErrors, readonly, + value, }) => { - const { "data-cy": dataCy, emptyValue = "", elementWrapperCSS } = options; + const { + "data-cy": dataCy, + elementWrapperCSS, + emptyValue = "", + focusOnMount, + } = options; const { errors, hasError } = processErrors(rawErrors); + const el = useRef(); + + useEffect(() => { + if (focusOnMount) { + const textarea = el.current; + if (textarea) { + textarea.focus(); + textarea.selectionStart = textarea.value.length; + textarea.selectionEnd = textarea.value.length; + } + } + }, [focusOnMount]); return (