Skip to content

Commit e855cae

Browse files
authored
Merge branch 'develop' into #1388-ArinjaySingh-credits
2 parents 0aeb276 + 919d5e1 commit e855cae

12 files changed

Lines changed: 63 additions & 40 deletions

File tree

src/backend/src/services/work-packages.services.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ export default class WorkPackagesService {
154154
throw new HttpException(400, 'A Work Package cannot have its own project as a blocker');
155155
}
156156

157+
blockedBy.forEach((dep: WbsNumber) => {
158+
if (dep.workPackageNumber === 0) {
159+
throw new HttpException(400, 'A Project cannot be a Blocker');
160+
}
161+
});
162+
157163
const wbsElem = await prisma.wBS_Element.findUnique({
158164
where: {
159165
wbsNumber: {
@@ -287,6 +293,12 @@ export default class WorkPackagesService {
287293
// verify user is allowed to edit work packages
288294
if (isGuest(user.role)) throw new AccessDeniedGuestException('edit work packages');
289295

296+
blockedBy.forEach((dep: WbsNumber) => {
297+
if (dep.workPackageNumber === 0) {
298+
throw new HttpException(400, 'A Project cannot be a Blocker');
299+
}
300+
});
301+
290302
const { userId } = user;
291303

292304
// get the original work package so we can compare things

src/frontend/src/hooks/work-packages.hooks.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,6 @@ export const useSingleWorkPackage = (wbsNum: WbsNumber) => {
3737
});
3838
};
3939

40-
/**
41-
* Custom React Hook to supply multiple work packages
42-
*
43-
* @param wbsNums WBS numbers of the requested work packages
44-
*/
45-
export const useManyWorkPackages = (wbsNums: WbsNumber[]) => {
46-
return useQuery<WorkPackage[], Error>(['work packages', wbsNums], async () => {
47-
const workPackagePromises = wbsNums.map(async (wbsNum) => {
48-
const { data } = await getSingleWorkPackage(wbsNum);
49-
return data;
50-
});
51-
const workPackages = await Promise.all(workPackagePromises);
52-
return workPackages;
53-
});
54-
};
55-
5640
/**
5741
* Custom React Hook to create a new work package.
5842
*

src/frontend/src/pages/CreditsPage/CreditsPage.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const CreditsPage: React.FC = () => {
8484
{ name: 'Yechan Na', color: '#C2B078' },
8585
{ name: 'Liam Kosar', color: '#eb66ff' },
8686
{ name: 'Daniel Yu', color: '#bdc0c7' },
87+
{ name: 'Jake Wu-Chen', color: '#bdc0c7' },
8788
{ name: 'William Seward', color: '#e53774' },
8889
{
8990
name: 'Zach Norman',
@@ -95,6 +96,7 @@ const CreditsPage: React.FC = () => {
9596
},
9697
{ name: 'Ethan Mouri', color: '#00bbff' },
9798
{ name: 'Laith Taher', color: '#000080' },
99+
{ name: 'Teera Tesharojanasup', color: '#DC143C', sx: { px: 1, backgroundColor: '#E8D8CC', borderRadius: 10 } },
98100
{ name: 'Griffin Cooper', color: '#02d69a' },
99101
{ name: 'Amani Scarborough', color: '#e34db6' },
100102
{ name: 'Peter Moise', color: '#FF0000' },
@@ -103,9 +105,26 @@ const CreditsPage: React.FC = () => {
103105
{ name: 'Waasif Mahmood', color: '#114a13' },
104106
{ name: 'Matthew Wang', color: '#c657f2' },
105107
{ name: 'Sharon Yang', color: '#ed8a5f' },
108+
{ name: 'Samantha Moy', color: '#d287fa' },
109+
{ name: 'Benjamin Zhu', color: '#ccccff' },
110+
{ name: 'Stephanie Xu', color: '#ffcd42' },
106111
{ name: 'Hareg Aderie', color: '#34b46c' },
112+
{ name: 'Arinjay Singh', color: '#7bb5dc' },
113+
{ name: 'Aarav Shyamkumar', color: '#FF0000' },
114+
{ name: 'Raghav Mathur', color: '#009933' },
115+
{ name: 'Anika Sharma', color: '#ff0000' },
116+
{
117+
name: 'Kaan Tural',
118+
color: 'transparent',
119+
sx: {
120+
background: 'linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(0,128,255,1) 100%)',
121+
'-webkit-background-clip': 'text',
122+
textShadow: '0 0 5px rgba(255,0,0,1), 0 0 10px rgba(0,128,255,1)'
123+
}
124+
},
107125
{ name: 'Kevin Polackal', color: '#800080' },
108-
{ name: 'Arinjay Singh', color: '#7bb5dc' }
126+
{ name: 'Lily Shiomitsu', color: '#008080' },
127+
{ name: 'Kevin Yang', color: '#0000FF' }
109128
];
110129

111130
const snark = ['Add your name!', "Shouldn't you do it yourself?", 'Seriously', 'go', 'do', 'it'];

src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/ReimbursementRequestDetailsView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* See the LICENSE file in the repository root folder for details.
44
*/
55

6+
import { expenseTypePipe } from '../../../utils/pipes';
67
import { Edit } from '@mui/icons-material';
78
import CheckIcon from '@mui/icons-material/Check';
89
import ConfirmationNumberIcon from '@mui/icons-material/ConfirmationNumber';
@@ -118,7 +119,7 @@ const ReimbursementRequestDetailsView: React.FC<ReimbursementRequestDetailsViewP
118119
<VerticalDetailDisplay label="Refund Source" content={`${reimbursementRequest.account}`} />
119120
</Grid>
120121
<Grid item sm={6} xs={12}>
121-
<VerticalDetailDisplay label="Expense Type" content={`${reimbursementRequest.expenseType.name}`} />
122+
<VerticalDetailDisplay label="Expense Type" content={expenseTypePipe(reimbursementRequest.expenseType)} />
122123
</Grid>
123124
<Grid item sm={6} xs={12}>
124125
<VerticalDetailDisplay label="Date Delivered" content={dateUndefinedPipe(reimbursementRequest.dateDelivered)} />

src/frontend/src/pages/FinancePage/ReimbursementRequestForm/ReimbursementFormView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import NERSuccessButton from '../../../components/NERSuccessButton';
2929
import { ReimbursementRequestFormInput } from './ReimbursementRequestForm';
3030
import { useState } from 'react';
3131
import { useToast } from '../../../hooks/toasts.hooks';
32+
import { expenseTypePipe } from '../../../utils/pipes';
3233

3334
interface ReimbursementRequestFormViewProps {
3435
allVendors: Vendor[];
@@ -195,7 +196,7 @@ const ReimbursementRequestFormView: React.FC<ReimbursementRequestFormViewProps>
195196
>
196197
{allExpenseTypes.map((expenseType) => (
197198
<MenuItem key={expenseType.expenseTypeId} value={expenseType.expenseTypeId}>
198-
{expenseType.name}
199+
{expenseTypePipe(expenseType)}
199200
</MenuItem>
200201
))}
201202
</Select>

src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/WorkPackageSummary.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Grid from '@mui/material/Grid';
1818
import { useTheme } from '@mui/material';
1919
import DetailDisplay from '../../../components/DetailDisplay';
2020
import WorkPackageStageChip from '../../../components/WorkPackageStageChip';
21-
import { useManyWorkPackages } from '../../../hooks/work-packages.hooks';
21+
import { useGetBlockingWorkPackages } from '../../../hooks/work-packages.hooks';
2222
import LoadingIndicator from '../../../components/LoadingIndicator';
2323
import ErrorPage from '../../ErrorPage';
2424

@@ -37,7 +37,7 @@ const WorkPackageSummary: React.FC<WorkPackageSummaryProps> = ({ workPackage })
3737
</ul>
3838
);
3939

40-
const { data: dependencies, isError, isLoading, error } = useManyWorkPackages(workPackage.blockedBy);
40+
const { data: dependencies, isError, isLoading, error } = useGetBlockingWorkPackages(workPackage.wbsNum);
4141
const theme = useTheme();
4242

4343
if (!dependencies || isLoading) return <LoadingIndicator />;

src/frontend/src/pages/WorkPackageDetailPage/WorkPackageViewContainer/WorkPackageViewContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import KeyboardDoubleArrowUpIcon from '@mui/icons-material/KeyboardDoubleArrowUp
2222
import DoneOutlineIcon from '@mui/icons-material/DoneOutline';
2323
import Delete from '@mui/icons-material/Delete';
2424
import DeleteWorkPackage from '../DeleteWorkPackageModalContainer/DeleteWorkPackage';
25-
import { useManyWorkPackages } from '../../../hooks/work-packages.hooks';
25+
import { useGetBlockingWorkPackages } from '../../../hooks/work-packages.hooks';
2626
import PageLayout from '../../../components/PageLayout';
2727
import LoadingIndicator from '../../../components/LoadingIndicator';
2828
import ErrorPage from '../../ErrorPage';
@@ -52,7 +52,7 @@ const WorkPackageViewContainer: React.FC<WorkPackageViewContainerProps> = ({
5252
const [showStageGateModal, setShowStageGateModal] = useState<boolean>(false);
5353
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);
5454
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
55-
const { data: dependencies, isError, isLoading, error } = useManyWorkPackages(workPackage.blockedBy);
55+
const { data: dependencies, isError, isLoading, error } = useGetBlockingWorkPackages(workPackage.wbsNum);
5656
const dropdownOpen = Boolean(anchorEl);
5757
const wbsNum = wbsPipe(workPackage.wbsNum);
5858

src/frontend/src/tests/pages/ProjectDetailPage/ProjectViewContainer.test.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { WorkPackageStage } from 'shared/src/types/work-package-types';
1212
import * as userHooks from '../../../hooks/users.hooks';
1313
import * as authHooks from '../../../hooks/auth.hooks';
1414
import * as wpHooks from '../../../hooks/work-packages.hooks';
15-
import { mockUseManyWorkPackagesReturnValue, mockUseUsersFavoriteProjects } from '../../test-support/mock-hooks';
15+
import { mockUseGetBlockingWorkPackagesReturnValue, mockUseUsersFavoriteProjects } from '../../test-support/mock-hooks';
1616
import { exampleAllWorkPackages } from '../../test-support/test-data/work-packages.stub';
1717

1818
vi.mock('../../../utils/axios');
@@ -33,7 +33,9 @@ describe('Rendering Project View Container', () => {
3333
vi.spyOn(authHooks, 'useAuth').mockReturnValue(mockAuth(false, exampleAdminUser));
3434
vi.spyOn(userHooks, 'useCurrentUser').mockReturnValue(exampleAdminUser);
3535
vi.spyOn(userHooks, 'useUsersFavoriteProjects').mockReturnValue(mockUseUsersFavoriteProjects());
36-
vi.spyOn(wpHooks, 'useManyWorkPackages').mockReturnValue(mockUseManyWorkPackagesReturnValue(exampleAllWorkPackages));
36+
vi.spyOn(wpHooks, 'useGetBlockingWorkPackages').mockReturnValue(
37+
mockUseGetBlockingWorkPackagesReturnValue(exampleAllWorkPackages)
38+
);
3739
renderComponent();
3840
});
3941

src/frontend/src/tests/pages/WorkPackageDetailPage/WorkPackagePage.test.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { UseQueryResult } from 'react-query';
77
import { AuthenticatedUser, WorkPackage } from 'shared';
88
import { render, screen, routerWrapperBuilder, act, fireEvent } from '../../test-support/test-utils';
99
import { Auth } from '../../../utils/types';
10-
import { useManyWorkPackages, useSingleWorkPackage } from '../../../hooks/work-packages.hooks';
10+
import { useGetBlockingWorkPackages, useSingleWorkPackage } from '../../../hooks/work-packages.hooks';
1111
import { useAuth } from '../../../hooks/auth.hooks';
1212
import { mockAuth, mockUseQueryResult } from '../../test-support/test-data/test-utils.stub';
1313
import { exampleDesignWorkPackage, exampleResearchWorkPackage } from '../../test-support/test-data/work-packages.stub';
@@ -25,10 +25,10 @@ const mockSingleWPHook = (isLoading: boolean, isError: boolean, data?: WorkPacka
2525
mockedUseSingleWorkPackage.mockReturnValue(mockUseQueryResult<WorkPackage>(isLoading, isError, data, error));
2626
};
2727

28-
const mockedUseManyWorkPackages = useManyWorkPackages as jest.Mock<UseQueryResult<WorkPackage[]>>;
28+
const mockedGetBlockingWorkPackages = useGetBlockingWorkPackages as jest.Mock<UseQueryResult<WorkPackage[]>>;
2929

30-
const mockManyWorkPackagesHook = (isLoading: boolean, isError: boolean, data?: WorkPackage[], error?: Error) => {
31-
mockedUseManyWorkPackages.mockReturnValue(mockUseQueryResult<WorkPackage[]>(isLoading, isError, data, error));
30+
const mockGetBlockingWorkPackagesHook = (isLoading: boolean, isError: boolean, data?: WorkPackage[], error?: Error) => {
31+
mockedGetBlockingWorkPackages.mockReturnValue(mockUseQueryResult<WorkPackage[]>(isLoading, isError, data, error));
3232
};
3333

3434
vi.mock('../../../hooks/auth.hooks');
@@ -63,7 +63,7 @@ describe('work package container', () => {
6363
mockSingleWPHook(true, false);
6464
mockAuthHook();
6565
mockCurrentUserHook();
66-
mockManyWorkPackagesHook(true, false);
66+
mockGetBlockingWorkPackagesHook(true, false);
6767
renderComponent();
6868

6969
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
@@ -74,7 +74,7 @@ describe('work package container', () => {
7474
mockSingleWPHook(false, false, exampleResearchWorkPackage);
7575
mockAuthHook();
7676
mockCurrentUserHook();
77-
mockManyWorkPackagesHook(false, false, [exampleDesignWorkPackage]);
77+
mockGetBlockingWorkPackagesHook(false, false, [exampleDesignWorkPackage]);
7878
renderComponent();
7979

8080
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
@@ -87,7 +87,7 @@ describe('work package container', () => {
8787
mockSingleWPHook(false, true, undefined, new Error('404 could not find the requested work package'));
8888
mockAuthHook();
8989
mockCurrentUserHook();
90-
mockManyWorkPackagesHook(false, false);
90+
mockGetBlockingWorkPackagesHook(false, false);
9191
renderComponent();
9292

9393
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
@@ -99,7 +99,7 @@ describe('work package container', () => {
9999
mockSingleWPHook(false, true);
100100
mockAuthHook();
101101
mockCurrentUserHook();
102-
mockManyWorkPackagesHook(false, false);
102+
mockGetBlockingWorkPackagesHook(false, false);
103103
renderComponent();
104104

105105
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
@@ -111,7 +111,7 @@ describe('work package container', () => {
111111
mockSingleWPHook(false, false, exampleResearchWorkPackage);
112112
mockAuthHook(exampleAdminUser);
113113
mockCurrentUserHook();
114-
mockManyWorkPackagesHook(false, false, [exampleDesignWorkPackage]);
114+
mockGetBlockingWorkPackagesHook(false, false, [exampleDesignWorkPackage]);
115115
renderComponent();
116116

117117
act(() => {
@@ -124,7 +124,7 @@ describe('work package container', () => {
124124
mockSingleWPHook(false, false, exampleResearchWorkPackage);
125125
mockAuthHook(exampleGuestUser);
126126
mockCurrentUserHook(exampleGuestUser);
127-
mockManyWorkPackagesHook(false, false, [exampleDesignWorkPackage]);
127+
mockGetBlockingWorkPackagesHook(false, false, [exampleDesignWorkPackage]);
128128
renderComponent();
129129

130130
act(() => {

src/frontend/src/tests/pages/WorkPackageDetailPage/WorkPackageViewContainer/WorkPackageViewContainer.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as wpHooks from '../../../../hooks/work-packages.hooks';
1010
import { exampleAdminUser } from '../../../test-support/test-data/users.stub';
1111
import AppContextUser from '../../../../app/AppContextUser';
1212
import * as userHooks from '../../../../hooks/users.hooks';
13-
import { mockUseManyWorkPackagesReturnValue } from '../../../test-support/mock-hooks';
13+
import { mockUseGetBlockingWorkPackagesReturnValue } from '../../../test-support/mock-hooks';
1414

1515
// Sets up the component under test with the desired values and renders it.
1616
const renderComponent = (
@@ -42,8 +42,8 @@ const renderComponent = (
4242
describe.skip('work package container view', () => {
4343
beforeEach(() => {
4444
vi.spyOn(userHooks, 'useCurrentUser').mockReturnValue(exampleAdminUser);
45-
vi.spyOn(wpHooks, 'useManyWorkPackages').mockReturnValue(
46-
mockUseManyWorkPackagesReturnValue([exampleResearchWorkPackage])
45+
vi.spyOn(wpHooks, 'useGetBlockingWorkPackages').mockReturnValue(
46+
mockUseGetBlockingWorkPackagesReturnValue([exampleResearchWorkPackage])
4747
);
4848
});
4949

0 commit comments

Comments
 (0)