Skip to content
This repository has been archived by the owner on Jul 2, 2024. It is now read-only.

Commit

Permalink
DEVPROD-1968 Convert AnnotationTicketsTable into a list (#2180)
Browse files Browse the repository at this point in the history
  • Loading branch information
khelif96 authored Dec 15, 2023
1 parent 5e05f71 commit 3ab4a87
Show file tree
Hide file tree
Showing 14 changed files with 425 additions and 290 deletions.
37 changes: 20 additions & 17 deletions cypress/integration/task/annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,29 @@ 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();
cy.contains("button", "Yes")
.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
Expand All @@ -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
Expand All @@ -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");
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CustomStoryObj, CustomMeta } from "test_utils/types";
import { AnnotationTicketRow } from "./AnnotationTicketRow";
import AnnotationTicketRow from ".";

export default {
component: AnnotationTicketRow,
Expand Down Expand Up @@ -29,6 +29,7 @@ export const Default: CustomStoryObj<typeof AnnotationTicketRow> = {
),
args: {
confidenceScore: 0.5,
loading: false,
},
argTypes: {
confidenceScore: {
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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<AnnotationTicketRowProps> = ({
const AnnotationTicketRow: React.FC<AnnotationTicketRowProps> = ({
confidenceScore,
issueKey,
jiraTicket,
Expand All @@ -38,27 +38,31 @@ export const AnnotationTicketRow: React.FC<AnnotationTicketRowProps> = ({
updated,
} = fields ?? {};

const jiraLink = (
<JiraSummaryLink
href={url}
target="_blank"
data-cy={issueKey}
onClick={() =>
annotationAnalytics.sendEvent({
name: "Click Annotation Ticket Link",
})
}
>
{issueKey}
{summary && `: ${summary}`}
</JiraSummaryLink>
);
return (
<div data-cy="annotation-ticket-row">
<JiraSummaryLink
href={url}
target="_blank"
data-cy={issueKey}
onClick={() =>
annotationAnalytics.sendEvent({
name: "Click Annotation Ticket Link",
})
}
>
{issueKey}
{summary && `: ${summary}`}
</JiraSummaryLink>
<Container data-cy="annotation-ticket-row">
{loading ? (
<LoadingWrapper data-cy="loading-annotation-ticket">
<Skeleton active title={false} />
</LoadingWrapper>
<>
{jiraLink}
<Skeleton data-cy="loading-annotation-ticket" />
</>
) : (
<>
{jiraLink}
{jiraTicket && (
<StyledBadge data-cy={`${issueKey}-badge`} variant="lightgray">
{status.name}
Expand Down Expand Up @@ -95,12 +99,11 @@ export const AnnotationTicketRow: React.FC<AnnotationTicketRowProps> = ({
</BottomMetaDataWrapper>
</>
)}
</div>
</Container>
);
};

const LoadingWrapper = styled.div`
margin-top: ${size.xs};
const Container = styled.div`
width: 100%;
`;

const JiraSummaryLink = styled(StyledLink)`
Expand All @@ -118,3 +121,6 @@ const BottomMetaDataWrapper = styled.div`
margin-top: ${size.xs};
width: 80%;
`;

export default AnnotationTicketRow;
export type { AnnotationTicketRowProps };
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CustomMeta, CustomStoryObj } from "test_utils/types";
import AnnotationTicketRowWithActionProps from ".";

export default {
component: AnnotationTicketRowWithActionProps,
} satisfies CustomMeta<typeof AnnotationTicketRowWithActionProps>;

export const Default: CustomStoryObj<
typeof AnnotationTicketRowWithActionProps
> = {
render: (args) => <AnnotationTicketRowWithActionProps {...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,
},
};
Original file line number Diff line number Diff line change
@@ -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 (
<Container selected={selected} ref={ref}>
<AnnotationTicketRow {...rest} />
{!loading && (
<ButtonContainer>
{ConditionalWrapper({
condition: userCanModify,
wrapper: (children: JSX.Element) => (
<Popconfirm
align="right"
onConfirm={() => {
onMove({ url, issueKey, confidenceScore });
}}
trigger={children}
>
Do you want to move this {issueString} to{" "}
{isIssue ? "suspected issues" : "issues"}?
</Popconfirm>
),
altWrapper: (children: JSX.Element) => (
<Tooltip trigger={children}>
You are not authorized to edit failure details
</Tooltip>
),
children: (
<Button
size={Size.Small}
data-cy={`move-btn-${issueKey}`}
disabled={!userCanModify}
leftGlyph={<Icon glyph={isIssue ? "ArrowDown" : "ArrowUp"} />}
>
Move to {isIssue ? "suspected issues" : "issues"}
</Button>
),
})}
{ConditionalWrapper({
condition: userCanModify,
wrapper: (children: JSX.Element) => (
<Popconfirm
align="right"
onConfirm={() => {
onRemove(url, issueKey);
}}
trigger={children}
>
Do you want to delete this {issueString}?
</Popconfirm>
),
altWrapper: (children: JSX.Element) => (
<Tooltip trigger={children}>
You are not authorized to edit failure details
</Tooltip>
),
children: (
<Button
size="small"
data-cy={`${issueKey}-delete-btn`}
leftGlyph={<Icon glyph="Trash" />}
disabled={!userCanModify}
/>
),
})}
</ButtonContainer>
)}
</Container>
);
}
);

const ButtonContainer = styled.div`
display: flex;
justify-content: space-between;
gap: ${size.xs};
`;

const Container = styled.div`
display: flex;
justify-content: space-between;
padding: ${size.xs};
${({ selected }: { selected?: boolean }) =>
selected &&
`
background-color: ${gray.light2};
`}
`;

export default AnnotationTicketRowWithActions;
Loading

0 comments on commit 3ab4a87

Please sign in to comment.