Skip to content

Commit

Permalink
Merge pull request #2851 from Northeastern-Electric-Racing/merge-Deve…
Browse files Browse the repository at this point in the history
…lopToHomepageRedesign

Merge develop to homepage redesign
  • Loading branch information
walker-sean authored Sep 25, 2024
2 parents 2940bb6 + 96d5b62 commit 7247442
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 6 deletions.
9 changes: 9 additions & 0 deletions src/backend/src/controllers/organizations.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import OrganizationsService from '../services/organizations.services';
import { HttpException } from '../utils/errors.utils';

export default class OrganizationsController {
static async getCurrentOrganization(req: Request, res: Response, next: NextFunction) {
try {
const organization = await OrganizationsService.getCurrentOrganization(req.organization.organizationId);
return res.status(200).json(organization);
} catch (error: unknown) {
return next(error);
}
}

static async setUsefulLinks(req: Request, res: Response, next: NextFunction) {
try {
const { links } = req.body;
Expand Down
1 change: 1 addition & 0 deletions src/backend/src/routes/organizations.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { body } from 'express-validator';
const organizationRouter = express.Router();
const upload = multer({ limits: { fileSize: 30000000 }, storage: memoryStorage() });

organizationRouter.get('/current', OrganizationsController.getCurrentOrganization);
organizationRouter.post('/useful-links/set', ...linkValidators, validateInputs, OrganizationsController.setUsefulLinks);
organizationRouter.get('/useful-links', OrganizationsController.getAllUsefulLinks);
organizationRouter.post(
Expand Down
22 changes: 21 additions & 1 deletion src/backend/src/services/organizations.services.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Organization, User } from '@prisma/client';
import { LinkCreateArgs, isAdmin } from 'shared';
import prisma from '../prisma/prisma';
import { AccessDeniedAdminOnlyException, HttpException, NotFoundException } from '../utils/errors.utils';
import { AccessDeniedAdminOnlyException, HttpException, DeletedException, NotFoundException } from '../utils/errors.utils';
import { userHasPermission } from '../utils/users.utils';
import { createUsefulLinks } from '../utils/organizations.utils';
import { linkTransformer } from '../transformers/links.transformer';
Expand All @@ -10,6 +10,26 @@ import { uploadFile } from '../utils/google-integration.utils';
import { getProjects } from '../utils/projects.utils';

export default class OrganizationsService {
/**
* Gets the current organization
* @param organizationId the organizationId to be fetched
*/
static async getCurrentOrganization(organizationId: string) {
const organization = await prisma.organization.findUnique({
where: { organizationId }
});

if (!organization) {
throw new NotFoundException('Organization', organizationId);
}

if (organization.dateDeleted) {
throw new DeletedException('Organization', organizationId);
}

return organization;
}

/**
* sets an organizations useful links
* @param submitter the user who is setting the links
Expand Down
18 changes: 17 additions & 1 deletion src/backend/tests/unmocked/organization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ vi.mock('../../src/utils/google-integration.utils', () => ({
uploadFile: vi.fn()
}));

describe('Team Type Tests', () => {
describe('Organization Tests', () => {
let orgId: string;
let organization: Organization;

Expand All @@ -26,6 +26,22 @@ describe('Team Type Tests', () => {
await resetUsers();
});

describe('Get Current Organization', () => {
it('Fails if organization does not exist', async () => {
await expect(async () => await OrganizationsService.getCurrentOrganization('1')).rejects.toThrow(
new NotFoundException('Organization', '1')
);
});

it('Succeeds and gets the organization', async () => {
const org = await OrganizationsService.getCurrentOrganization(orgId);

expect(org).not.toBeNull();
expect(org.organizationId).toBe(orgId);
expect(org.name).toBe(organization.name);
});
});

describe('Set Images', () => {
const file1 = { originalname: 'image1.png' } as Express.Multer.File;
const file2 = { originalname: 'image2.png' } as Express.Multer.File;
Expand Down
13 changes: 13 additions & 0 deletions src/frontend/src/apis/organizations.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import axios from '../utils/axios';
import { Organization } from 'shared';
import { apiUrls } from '../utils/urls';

/**
* Create a design review
* @param payload all info needed to create a design review
*/
export const getCurrentOrganization = async () => {
return axios.get<Organization>(apiUrls.currentOrganization(), {
transformResponse: (data) => JSON.parse(data)
});
};
2 changes: 1 addition & 1 deletion src/frontend/src/app/AppOrganizationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createContext } from 'react';
import { useProvideOrganization } from '../hooks/organization.hooks';
import { useProvideOrganization } from '../hooks/organizations.hooks';

export interface Organization {
organizationId: string;
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/app/AppPublic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Login from '../pages/LoginPage/Login';
import AppAuthenticated from './AppAuthenticated';
import { useProvideThemeToggle } from '../hooks/theme.hooks';
import LoadingIndicator from '../components/LoadingIndicator';
import { useOrganization } from '../hooks/organization.hooks';
import { useOrganization } from '../hooks/organizations.hooks';
import Organizations from '../pages/OrganizationPage/Organizations';

const AppPublic: React.FC = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useContext, useState } from 'react';
import { OrganizationContext } from '../app/AppOrganizationContext';
import { useQuery } from 'react-query';
import { Organization } from 'shared';
import { getCurrentOrganization } from '../apis/organizations.api';

interface OrganizationProvider {
organizationId: string;
Expand All @@ -20,6 +23,13 @@ export const useProvideOrganization = (): OrganizationProvider => {
};
};

export const useCurrentOrganization = () => {
return useQuery<Organization, Error>(['organizations'], async () => {
const { data } = await getCurrentOrganization();
return data;
});
};

// Hook for child components to get the auth object
export const useOrganization = () => {
const context = useContext(OrganizationContext);
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/pages/LoginPage/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import LoginPage from './LoginPage';
import LoadingIndicator from '../../components/LoadingIndicator';
import { useQuery } from '../../hooks/utils.hooks';
import { GoogleLoginResponse, GoogleLoginResponseOffline } from 'react-google-login';
import { useOrganization } from '../../hooks/organization.hooks';
import { useOrganization } from '../../hooks/organizations.hooks';

/**
* Page for unauthenticated users to do login.
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/src/utils/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const workPackageTemplateDelete = (workPackageTemplateId: string) =>

/******************* Organizations Endpoints ********************/
const organizations = () => `${API_URL}/organizations`;
const currentOrganization = () => `${organizations()}/current`;
const organizationsUsefulLinks = () => `${organizations()}/useful-links`;
const organizationsSetUsefulLinks = () => `${organizationsUsefulLinks()}/set`;

Expand Down Expand Up @@ -324,6 +325,7 @@ export const apiUrls = {
workPackageTemplatesCreate,
workPackageTemplateDelete,

currentOrganization,
organizationsUsefulLinks,
organizationsSetUsefulLinks,

Expand Down
11 changes: 10 additions & 1 deletion src/frontend/src/utils/work-package.utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { WbsElement, wbsPipe } from 'shared';
import { WbsElement, WbsElementStatus, wbsPipe, WorkPackage } from 'shared';
import { WPFormType } from './form';

export const getTitleFromFormType = (formType: WPFormType, wbsElement: WbsElement): string => {
Expand All @@ -11,3 +11,12 @@ export const getTitleFromFormType = (formType: WPFormType, wbsElement: WbsElemen
return `${wbsPipe(wbsElement.wbsNum)} - ${wbsElement.name}`;
}
};

/**
* Given a list of work packages, return the work packages that are overdue.
* @param wpList a list of work packages.
* @returns a list of work packages that are overdue.
*/
export const getOverdueWorkPackages = (wpList: WorkPackage[]): WorkPackage[] => {
return wpList.filter((wp) => wp.status !== WbsElementStatus.Complete && wp.endDate < new Date());
};

0 comments on commit 7247442

Please sign in to comment.