Skip to content
Open
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
38 changes: 16 additions & 22 deletions __tests__/Unit/Components/Tasks/TaskDetails.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import TaskDetails, { Button, Textarea } from '@/components/taskDetails';
import TaskDetails, {
Button,
EndsOnDetails,
Textarea,
} from '@/components/taskDetails';
import TaskContainer from '@/components/taskDetails/TaskContainer';
import task from '@/interfaces/task.type';
import { tasks } from '../../../../__mocks__/db/tasks';
Expand All @@ -15,7 +19,6 @@ import Details from '@/components/taskDetails/Details';
import { taskRequestErrorHandler } from '../../../../__mocks__/handlers/task-request.handler';
import { taskDetailsHandler } from '../../../../__mocks__/handlers/task-details.handler';
import { superUserSelfHandler } from '../../../../__mocks__/handlers/self.handler';
import DevFeature from '@/components/DevFeature';

const details = {
url: 'https://realdevsquad.com/tasks/6KhcLU3yr45dzjQIVm0J/details',
Expand Down Expand Up @@ -153,7 +156,7 @@ describe('TaskDetails Page', () => {
it('Renders N/A when link is empty or undefined', async () => {
const { getByText } = renderWithRouter(
<Provider store={store()}>
<Details detailType={'Link'} value={undefined} />
<Details detailType={'Link'}>{undefined}</Details>
</Provider>
);
await waitFor(() => {
Expand Down Expand Up @@ -194,10 +197,9 @@ describe('TaskDetails Page', () => {
it('Renders Task Started-on Date', async () => {
const { getByText } = renderWithRouter(
<Provider store={store()}>
<Details
detailType={'StartedOn'}
value={'3/30/2021, 12:00:00 AM'}
/>
<Details detailType={'StartedOn'}>
{'3/30/2021, 12:00:00 AM'}
</Details>
</Provider>
);
await waitFor(() => {
Expand All @@ -208,7 +210,7 @@ describe('TaskDetails Page', () => {
it('Renders N/A when started on is undefined', async () => {
const { getByText } = renderWithRouter(
<Provider store={store()}>
<Details detailType={'StartedOn'} value={undefined} />
<Details detailType={'StartedOn'}>{undefined}</Details>
</Provider>
);
await waitFor(() => {
Expand All @@ -219,10 +221,7 @@ describe('TaskDetails Page', () => {
it('Renders Task Ends-on Date', async () => {
const { getByText } = renderWithRouter(
<Provider store={store()}>
<Details
detailType={'EndsOn'}
value={'4/19/2021, 12:00:10 AM'}
/>
<EndsOnDetails endsOnDate="4/19/2021, 12:00:10 AM" />
</Provider>
);
await waitFor(() => {
Expand All @@ -233,10 +232,9 @@ describe('TaskDetails Page', () => {
it('Renders Extension Request icon', async () => {
const { getByText } = renderWithRouter(
<Provider store={store()}>
<Details
detailType={'Ends On'}
value={'4/19/2021, 12:00:10 AM'}
url={details.extension_request_url}
<EndsOnDetails
endsOnDate="4/19/2021, 12:00:10 AM"
extensionRequestURL={details.extension_request_url}
/>
</Provider>
);
Expand All @@ -251,14 +249,10 @@ describe('TaskDetails Page', () => {
});
});

it('Doesnot Renders Extension Request icon when url not available', async () => {
it('Does not Renders Extension Request icon when url not available', async () => {
const { getByText } = renderWithRouter(
<Provider store={store()}>
<Details
detailType={'Ends On'}
value={'4/19/2021, 12:00:10 AM'}
url={null}
/>
<EndsOnDetails endsOnDate="4/19/2021, 12:00:10 AM" />
</Provider>,
{
query: { dev: 'true' },
Expand Down
49 changes: 13 additions & 36 deletions src/components/taskDetails/Details.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,27 @@
import React, { FC } from 'react';
import setColor from './taskPriorityColors';
import styles from './task-details.module.scss';
import { TaskDetailsProps } from '@/interfaces/taskDetails.type';
import extractRepoName from '@/utils/extractRepoName';
import Link from 'next/link';
import { FaReceipt } from 'react-icons/fa6';
import DevFeature from '../DevFeature';

const Details: FC<TaskDetailsProps> = ({ detailType, value, url }) => {
const color = value ? setColor?.[value] : undefined;
const isGitHubLink = detailType === 'Link';
const gitHubIssueLink = isGitHubLink ? value : undefined;

const Details: FC<TaskDetailsProps> = ({
detailType,
children,
additionalChild,
color = 'black',
isUpperCase = false,
}) => {
return (
<div className={styles.detailsContainer}>
<span className={styles.detailType}>{detailType}:</span>
<span
className={styles.detailValue}
style={{ color: color ?? 'black' }}
style={{
color: color,
textTransform: isUpperCase ? 'uppercase' : 'none',
}}
>
{isGitHubLink && value ? (
<a
className={styles.gitLink}
href={gitHubIssueLink}
target="_blank"
rel="noopener noreferrer"
aria-label="Open GitHub Issue"
title={value}
>
{isGitHubLink ? `${extractRepoName(value)}` : value}
</a>
) : (
<>{isGitHubLink ? 'N/A' : value ?? 'N/A'}</>
)}
</span>
<span>
{detailType === 'Ends On' && url && (
<Link
href={url}
target="_blank"
data-testid="extension-request-icon"
>
<FaReceipt color="green" />
</Link>
)}
{children ?? 'N/A'}
</span>
{additionalChild && <span>{additionalChild}</span>}
</div>
);
};
Expand Down
156 changes: 107 additions & 49 deletions src/components/taskDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import React, { ChangeEvent, FC, useState, useEffect, useRef } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';

import TaskContainer from './TaskContainer';
import Details from './Details';
import { toast, ToastTypes } from '@/helperFunctions/toast';
import convertTimeStamp from '@/helperFunctions/convertTimeStamp';
import styles from './task-details.module.scss';
import { useRouter } from 'next/router';
import Layout from '@/components/Layout';
import TaskDependency from '@/components/taskDetails/taskDependency';
import Progress from '../ProgressCard';
import ProgressContainer from '../tasks/card/progressContainer';
import DevFeature from '../DevFeature';
import Suggestions from '../tasks/SuggestionBox/Suggestions';

import {
useGetExtensionRequestDetailsQuery,
useGetTaskDetailsQuery,
useUpdateTaskDetailsMutation,
} from '@/app/services/taskDetailsApi';

import { useGetProgressDetailsQuery } from '@/app/services/progressesApi';
import { toast, ToastTypes } from '@/helperFunctions/toast';
import convertTimeStamp from '@/helperFunctions/convertTimeStamp';
import useUserData from '@/hooks/useUserData';
import extractRepoName from '@/utils/extractRepoName';

import {
ButtonProps,
EndsOnDetailsProps,
TextAreaProps,
taskDetailsDataType,
} from '@/interfaces/taskDetails.type';
import Layout from '@/components/Layout';
import TaskDependency from '@/components/taskDetails/taskDependency';
import { useGetProgressDetailsQuery } from '@/app/services/progressesApi';
import { ProgressDetailsData } from '@/types/standup.type';
import Progress from '../ProgressCard';
import ProgressContainer from '../tasks/card/progressContainer';
import DevFeature from '../DevFeature';
import Suggestions from '../tasks/SuggestionBox/Suggestions';
import { BACKEND_TASK_STATUS } from '@/constants/task-status';
import task from '@/interfaces/task.type';

import { BACKEND_TASK_STATUS } from '@/constants/task-status';
import { TASK_EXTENSION_REQUEST_URL } from '@/constants/url';
import { TASK_PRIORITY_COLORS } from '@/constants/tasks';

import styles from './task-details.module.scss';
import { FaReceipt } from 'react-icons/fa6';

const taskStatus = Object.entries(BACKEND_TASK_STATUS);

Expand Down Expand Up @@ -58,6 +67,31 @@ export function Textarea(props: TextAreaProps) {
);
}

export function EndsOnDetails({
endsOnDate,
extensionRequestURL,
}: EndsOnDetailsProps) {
return (
<Details
detailType={'Ends On'}
isUpperCase={true}
additionalChild={
extensionRequestURL && (
<Link
href={extensionRequestURL}
target="_blank"
data-testid="extension-request-icon"
>
<FaReceipt color="green" />
</Link>
)
}
>
<span>{endsOnDate}</span>
</Details>
);
}

type Props = {
url?: string;
taskID: string;
Expand Down Expand Up @@ -220,6 +254,12 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
}
};

const taskIssueLink = taskDetailsData?.github?.issue?.html_url;
const extensionRequestURL = getExtensionRequestLink(
taskDetailsData.id,
isExtensionRequestPending
);

return (
<Layout hideHeader={true}>
{renderLoadingComponent()}
Expand Down Expand Up @@ -291,12 +331,21 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
>
<Details
detailType={'Type'}
value={taskDetailsData?.type}
/>
isUpperCase={true}
>
{taskDetailsData?.type}
</Details>
<Details
detailType={'Priority'}
value={taskDetailsData?.priority}
/>
isUpperCase={true}
color={
TASK_PRIORITY_COLORS[
taskDetailsData?.priority
]
}
>
{taskDetailsData?.priority}
</Details>
<DevFeature>
{isEditing && (
<label>
Expand Down Expand Up @@ -326,15 +375,30 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
</DevFeature>
<Details
detailType={'Status'}
value={taskDetailsData?.status}
/>
isUpperCase={true}
>
{taskDetailsData?.status}
</Details>
<Details
detailType={'Link'}
value={
taskDetailsData?.github?.issue
?.html_url
}
/>
isUpperCase={true}
>
<a
className={styles.gitLink}
href={taskIssueLink}
target="_blank"
rel="noopener noreferrer"
aria-label="Open GitHub Issue"
title={taskIssueLink}
>
{taskIssueLink
? `${extractRepoName(
taskIssueLink
)}
`
: 'N/A'}
</a>
</Details>
<DevFeature>
{isUserAuthorized && (
<ProgressContainer
Expand Down Expand Up @@ -367,16 +431,13 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
title="Participants"
hasImg={true}
>
<Details
detailType={'Assignee'}
value={
taskDetailsData?.type === 'feature'
? taskDetailsData?.assignee
: taskDetailsData?.participants?.join(
' , '
)
}
/>
<Details detailType={'Assignee'}>
{taskDetailsData?.type === 'feature'
? taskDetailsData?.assignee
: taskDetailsData?.participants?.join(
' , '
)}
</Details>
<DevFeature>
{isEditing && isUserAuthorized && (
<div
Expand All @@ -399,10 +460,9 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
</div>
)}
</DevFeature>
<Details
detailType={'Reporter'}
value={'Ankush'}
/>
<Details detailType={'Reporter'}>
{'Ankush'}
</Details>
</TaskContainer>
<TaskContainer
src="/calendar-icon.png"
Expand All @@ -411,24 +471,22 @@ const TaskDetails: FC<Props> = ({ taskID }) => {
>
<Details
detailType={'Started On'}
value={getStartedOn(
taskDetailsData?.startedOn
)}
/>
<Details
detailType={'Ends On'}
value={getEndsOn(taskDetailsData?.endsOn)}
url={getExtensionRequestLink(
taskDetailsData.id,
isExtensionRequestPending
isUpperCase={true}
>
{getStartedOn(taskDetailsData?.startedOn)}
</Details>
<EndsOnDetails
endsOnDate={getEndsOn(
taskDetailsData?.endsOn
)}
extensionRequestURL={extensionRequestURL}
/>

<DevFeature>
{isEditing && (
<>
<label htmlFor="endsOnTaskDetails">
Ends On:
New Ends On:
</label>
<input
id="endsOnTaskDetails"
Expand Down
Loading