diff --git a/cypress/integration/task/annotations.ts b/cypress/integration/task/annotations.ts index b29f471a6f..f52e02922b 100644 --- a/cypress/integration/task/annotations.ts +++ b/cypress/integration/task/annotations.ts @@ -2,19 +2,20 @@ const taskWithAnnotations = "evergreen_ubuntu1604_test_annotations_b_5e4ff3abe3c3317e352062e4_20_02_21_15_13_48"; const taskRoute = `/task/${taskWithAnnotations}/annotations`; -const suspectedIssuesTable = - "[data-test-id=suspected-issues-table] tr td:first-child"; -const issuesTable = "[data-test-id=issues-table] tr td:first-child"; - describe("Task Annotation Tab", () => { beforeEach(() => { cy.visit(taskRoute); + cy.dataCy("loading-annotation-ticket").should("not.exist"); + const rowSelector = "[data-cy='annotation-ticket-row']"; + cy.dataCy("issues-list").find(rowSelector).as("issueRows"); + cy.dataCy("suspected-issues-list").find(rowSelector).as("susIssueRows"); }); it("annotations can be moved between lists", () => { - cy.get(issuesTable).should("have.length", 1); - cy.get(suspectedIssuesTable).should("have.length", 3); - cy.dataCy("loading-annotation-ticket").should("have.length", 0); + cy.dataCy("loading-annotation-ticket").should("not.exist"); + + cy.get("@issueRows").should("have.length", 1); + cy.get("@susIssueRows").should("have.length", 3); // move from suspectedIssues to Issues cy.dataCy("move-btn-AnotherOne").click(); @@ -22,8 +23,8 @@ describe("Task Annotation Tab", () => { .should("be.visible") .should("not.have.attr", "aria-disabled", "true"); cy.contains("button", "Yes").click(); - cy.get(issuesTable).should("have.length", 2); - cy.get(suspectedIssuesTable).should("have.length", 2); + cy.get("@issueRows").should("have.length", 2); + cy.get("@susIssueRows").should("have.length", 2); cy.validateToast("success", "Successfully moved suspected issue to issues"); // move from Issues to suspectedIssues @@ -32,22 +33,24 @@ describe("Task Annotation Tab", () => { .should("be.visible") .should("not.have.attr", "aria-disabled", "true"); cy.contains("button", "Yes").click(); - cy.get(issuesTable).should("have.length", 1); - cy.get(suspectedIssuesTable).should("have.length", 3); + cy.get("@issueRows").should("have.length", 1); + cy.get("@susIssueRows").should("have.length", 3); + cy.validateToast("success", "Successfully moved issue to suspected issues"); }); it("annotations add and delete correctly", () => { - cy.get(issuesTable).should("have.length", 1); - cy.get(suspectedIssuesTable).should("have.length", 3); + cy.get("@issueRows").should("have.length", 1); + cy.get("@susIssueRows").should("have.length", 3); + cy.dataCy("loading-annotation-ticket").should("have.length", 0); // add a ticket cy.dataCy("add-suspected-issue-button").click(); cy.dataCy("issue-url").type("https://jira.example.com/browse/SERVER-1234"); cy.contains("Add suspected issue").click(); - cy.get(issuesTable).should("have.length", 1); - cy.get(suspectedIssuesTable).should("have.length", 4); + cy.get("@issueRows").should("have.length", 1); + cy.get("@susIssueRows").should("have.length", 4); cy.validateToast("success", "Successfully added suspected issue"); // delete the added ticket @@ -56,8 +59,8 @@ describe("Task Annotation Tab", () => { .should("be.visible") .should("not.have.attr", "aria-disabled", "true"); cy.contains("button", "Yes").click(); - cy.get(issuesTable).should("have.length", 1); - cy.get(suspectedIssuesTable).should("have.length", 3); + cy.get("@issueRows").should("have.length", 1); + cy.get("@susIssueRows").should("have.length", 3); cy.validateToast("success", "Successfully removed suspected issue"); }); }); diff --git a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/AnnotationTicketRow.stories.tsx b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/AnnotationTicketRow.stories.tsx similarity index 93% rename from src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/AnnotationTicketRow.stories.tsx rename to src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/AnnotationTicketRow.stories.tsx index 644a5e856e..d78a9af141 100644 --- a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/AnnotationTicketRow.stories.tsx +++ b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/AnnotationTicketRow.stories.tsx @@ -1,5 +1,5 @@ import { CustomStoryObj, CustomMeta } from "test_utils/types"; -import { AnnotationTicketRow } from "./AnnotationTicketRow"; +import AnnotationTicketRow from "."; export default { component: AnnotationTicketRow, @@ -29,6 +29,7 @@ export const Default: CustomStoryObj = { ), args: { confidenceScore: 0.5, + loading: false, }, argTypes: { confidenceScore: { diff --git a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/__snapshots__/AnnotationTicketRow.stories.storyshot b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/__snapshots__/AnnotationTicketRow.stories.storyshot similarity index 100% rename from src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/__snapshots__/AnnotationTicketRow.stories.storyshot rename to src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/__snapshots__/AnnotationTicketRow.stories.storyshot diff --git a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/AnnotationTicketRow.tsx b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/index.tsx similarity index 75% rename from src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/AnnotationTicketRow.tsx rename to src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/index.tsx index 57564548b8..0846c5148f 100644 --- a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsTable/AnnotationTicketRow.tsx +++ b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRow/index.tsx @@ -1,7 +1,7 @@ import styled from "@emotion/styled"; import Badge from "@leafygreen-ui/badge"; +import { Skeleton } from "@leafygreen-ui/skeleton-loader"; import { Disclaimer } from "@leafygreen-ui/typography"; -import { Skeleton } from "antd"; import { useAnnotationAnalytics } from "analytics"; import { StyledLink } from "components/styles"; import { size } from "constants/tokens"; @@ -12,14 +12,14 @@ import { numbers } from "utils"; const { roundDecimal, toPercent } = numbers; interface AnnotationTicketRowProps { - issueKey: string; - url: string; + issueKey?: string; + url?: string; jiraTicket?: JiraTicket; loading?: boolean; confidenceScore?: number; } -export const AnnotationTicketRow: React.FC = ({ +const AnnotationTicketRow: React.FC = ({ confidenceScore, issueKey, jiraTicket, @@ -38,27 +38,31 @@ export const AnnotationTicketRow: React.FC = ({ updated, } = fields ?? {}; + const jiraLink = ( + + annotationAnalytics.sendEvent({ + name: "Click Annotation Ticket Link", + }) + } + > + {issueKey} + {summary && `: ${summary}`} + + ); return ( -
- - annotationAnalytics.sendEvent({ - name: "Click Annotation Ticket Link", - }) - } - > - {issueKey} - {summary && `: ${summary}`} - + {loading ? ( - - - + <> + {jiraLink} + + ) : ( <> + {jiraLink} {jiraTicket && ( {status.name} @@ -95,12 +99,11 @@ export const AnnotationTicketRow: React.FC = ({ )} -
+ ); }; - -const LoadingWrapper = styled.div` - margin-top: ${size.xs}; +const Container = styled.div` + width: 100%; `; const JiraSummaryLink = styled(StyledLink)` @@ -118,3 +121,6 @@ const BottomMetaDataWrapper = styled.div` margin-top: ${size.xs}; width: 80%; `; + +export default AnnotationTicketRow; +export type { AnnotationTicketRowProps }; diff --git a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRowWithActions/AnnotationTicketRowWithAction.stories.tsx b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRowWithActions/AnnotationTicketRowWithAction.stories.tsx new file mode 100644 index 0000000000..c1d971496d --- /dev/null +++ b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRowWithActions/AnnotationTicketRowWithAction.stories.tsx @@ -0,0 +1,35 @@ +import { CustomMeta, CustomStoryObj } from "test_utils/types"; +import AnnotationTicketRowWithActionProps from "."; + +export default { + component: AnnotationTicketRowWithActionProps, +} satisfies CustomMeta; + +export const Default: CustomStoryObj< + typeof AnnotationTicketRowWithActionProps +> = { + render: (args) => , + argTypes: {}, + args: { + issueKey: "EVG-123", + url: "https://www.google.com", + jiraTicket: { + key: "key", + fields: { + summary: "summary", + status: { + name: "status", + id: "id", + }, + created: "2020-01-02", + updated: "2020-01-02", + assigneeDisplayName: "mohamed.khelif", + assignedTeam: "evg-ui", + }, + }, + confidenceScore: 0.5, + loading: false, + userCanModify: true, + isIssue: true, + }, +}; diff --git a/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRowWithActions/index.tsx b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRowWithActions/index.tsx new file mode 100644 index 0000000000..1e6d6b87f1 --- /dev/null +++ b/src/pages/task/taskTabs/buildBaronAndAnnotations/AnnotationTicketsList/AnnotationTicketRowWithActions/index.tsx @@ -0,0 +1,135 @@ +import { forwardRef } from "react"; +import styled from "@emotion/styled"; +import Button, { Size } from "@leafygreen-ui/button"; +import { palette } from "@leafygreen-ui/palette"; +import Tooltip from "@leafygreen-ui/tooltip"; +import { ConditionalWrapper } from "components/ConditionalWrapper"; +import Icon from "components/Icon"; +import Popconfirm from "components/Popconfirm"; +import { size } from "constants/tokens"; +import AnnotationTicketRow, { + AnnotationTicketRowProps, +} from "../AnnotationTicketRow"; + +const { gray } = palette; +interface AnnotationTicketRowWithActionsProps extends AnnotationTicketRowProps { + onRemove: (url: string, issueKey: string) => void; + userCanModify: boolean; + onMove: ({ + confidenceScore, + issueKey, + url, + }: { + url: string; + issueKey?: string; + confidenceScore?: number; + }) => void; + issueString: string; + isIssue: boolean; + selected: boolean; +} + +const AnnotationTicketRowWithActions = forwardRef< + HTMLDivElement, + AnnotationTicketRowWithActionsProps +>( + ( + { + isIssue, + issueString, + onMove, + onRemove, + selected, + userCanModify, + ...rest + }, + ref + ) => { + const { confidenceScore, issueKey, loading, url } = rest; + return ( + + + {!loading && ( + + {ConditionalWrapper({ + condition: userCanModify, + wrapper: (children: JSX.Element) => ( + { + onMove({ url, issueKey, confidenceScore }); + }} + trigger={children} + > + Do you want to move this {issueString} to{" "} + {isIssue ? "suspected issues" : "issues"}? + + ), + altWrapper: (children: JSX.Element) => ( + + You are not authorized to edit failure details + + ), + children: ( + + ), + })} + {ConditionalWrapper({ + condition: userCanModify, + wrapper: (children: JSX.Element) => ( + { + onRemove(url, issueKey); + }} + trigger={children} + > + Do you want to delete this {issueString}? + + ), + altWrapper: (children: JSX.Element) => ( + + You are not authorized to edit failure details + + ), + children: ( + - ), - })} - {ConditionalWrapper({ - condition: userCanModify, - wrapper: (children: JSX.Element) => ( - { - handleRemove(url, issueKey); - }} - trigger={children} - > - Do you want to delete this {issueString}? - - ), - altWrapper: (children: JSX.Element) => ( - - You are not authorized to edit failure details - - ), - children: ( -