Skip to content

Commit

Permalink
fix: ORV2-1808 More sonarcloud fixes (#966)
Browse files Browse the repository at this point in the history
  • Loading branch information
krishnan-aot authored Dec 26, 2023
1 parent 67ffdbc commit 76aefc7
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 93 deletions.
8 changes: 7 additions & 1 deletion frontend/src/common/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ const Navbar = ({
*/
const NavButton = ({ toggleMenu }: { toggleMenu: () => void }) => (
<div className="other">
<a className="nav-btn" onClick={toggleMenu} onKeyDown={toggleMenu}>
<a
className="nav-btn"
role="link"
onClick={toggleMenu}
onKeyDown={toggleMenu}
tabIndex={0}
>
<FontAwesomeIcon id="menu" className="menu-icon" icon={faBars} />
</a>
</div>
Expand Down
59 changes: 57 additions & 2 deletions frontend/src/common/helpers/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ export const removeEmptyValues = (obj: object): object => {
*
* @see https://dev.to/typescripttv/what-is-the-difference-between-null-and-undefined-5h76
*/
export const replaceEmptyValuesWithNull = (obj: object): RequiredOrNull<object> => {
export const replaceEmptyValuesWithNull = (
obj: object,
): RequiredOrNull<object> => {
if (Array.isArray(obj)) {
return obj.map((item) => replaceEmptyValuesWithNull(item));
} else if (typeof obj === "object" && obj !== null) {
Expand Down Expand Up @@ -89,7 +91,7 @@ export const applyWhenNotNullable = <T>(
* @returns The first non-nullable value from defaultVals, or undefined if there are no non-nullable values.
*/
export const getDefaultNullableVal = <T>(
...defaultVals: (Nullable<T>)[]
...defaultVals: Nullable<T>[]
): Optional<T> => {
return defaultVals.find((val) => val != null) ?? undefined;
};
Expand Down Expand Up @@ -131,3 +133,56 @@ export const areValuesDifferent = <T>(

return false; // values are equal otherwise
};

/**
* Returns the file name for a file from API response.
* @param headers The collection of headers in an API response.
* @returns string | undefined.
*/
export const getFileNameFromHeaders = (
headers: Headers,
): string | undefined => {
const contentDisposition = headers.get("content-disposition");
if (!contentDisposition) return undefined;
const matchRegex = /filename=(.+)/;
const filenameMatch = matchRegex.exec(contentDisposition);
if (filenameMatch && filenameMatch.length > 1) {
return filenameMatch[1];
}
return undefined;
};

/**
* Downloads a file using stream.
* @param response The Axios response containing file details.
* @returns The file.
*/
export const streamDownloadFile = async (response: Response) => {
const filename = getFileNameFromHeaders(response.headers);
if (!filename) {
throw new Error("Unable to download pdf, file not available");
}
if (!response.body) {
throw new Error("Unable to download pdf, no response found");
}
const reader = response.body.getReader();
const stream = new ReadableStream({
start: (controller) => {
const processRead = async () => {
const { done, value } = await reader.read();
if (done) {
// When no more data needs to be consumed, close the stream
controller.close();
return;
}
// Enqueue the next data chunk into our target stream
controller.enqueue(value);
await processRead();
};
processRead();
},
});
const newRes = new Response(stream);
const blobObj = await newRes.blob();
return { blobObj, filename };
};
31 changes: 3 additions & 28 deletions frontend/src/features/idir/reporting/api/reports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { UseQueryResult, useQuery } from "@tanstack/react-query";

import { VEHICLES_URL } from "../../../../common/apiManager/endpoints/endpoints";
import { ONE_HOUR } from "../../../../common/constants/constants";
import { getFileNameFromHeaders } from "../../../permits/apiManager/permitsAPI";
import {
httpGETRequest,
httpPOSTRequestStream,
Expand All @@ -12,6 +11,7 @@ import {
PaymentAndRefundDetailRequest,
PaymentAndRefundSummaryRequest,
} from "../types/types";
import { streamDownloadFile } from "../../../../common/helpers/util";

/**
* Streams a file through a POST request.
Expand All @@ -29,33 +29,8 @@ const streamDownloadWithHTTPPost = async (
filename: string;
}> => {
const response = await httpPOSTRequestStream(url, requestBody);
const filename = getFileNameFromHeaders(response.headers);
if (!filename) {
throw new Error("Unable to download pdf, file not available");
}
if (!response.body) {
throw new Error("Unable to download pdf, no response found");
}
const reader = response.body.getReader();
const stream = new ReadableStream({
start: (controller) => {
const processRead = async () => {
const { done, value } = await reader.read();
if (done) {
// When no more data needs to be consumed, close the stream
controller.close();
return;
}
// Enqueue the next data chunk into our target stream
controller.enqueue(value);
await processRead();
};
processRead();
},
});
const newRes = new Response(stream);
const blobObj = await newRes.blob();
return { blobObj, filename };
const file = await streamDownloadFile(response);
return file;
};

/**
Expand Down
41 changes: 3 additions & 38 deletions frontend/src/features/permits/apiManager/permitsAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
applyWhenNotNullable,
getDefaultRequiredVal,
replaceEmptyValuesWithNull,
streamDownloadFile,
} from "../../../common/helpers/util";

import {
Expand Down Expand Up @@ -175,46 +176,10 @@ export const deleteApplications = async (applicationIds: Array<string>) => {
);
};

export const getFileNameFromHeaders = (headers: Headers) => {
const contentDisposition = headers.get("content-disposition");
if (!contentDisposition) return undefined;
const matchRegex = /filename=(.+)/;
const filenameMatch = matchRegex.exec(contentDisposition);
if (filenameMatch && filenameMatch.length > 1) {
return filenameMatch[1];
}
return undefined;
};

const streamDownload = async (url: string) => {
const response = await httpGETRequestStream(url);
const filename = getFileNameFromHeaders(response.headers);
if (!filename) {
throw new Error("Unable to download pdf, file not available");
}
if (!response.body) {
throw new Error("Unable to download pdf, no response found");
}
const reader = response.body.getReader();
const stream = new ReadableStream({
start: (controller) => {
const processRead = async () => {
const { done, value } = await reader.read();
if (done) {
// When no more data needs to be consumed, close the stream
controller.close();
return;
}
// Enqueue the next data chunk into our target stream
controller.enqueue(value);
await processRead();
};
processRead();
},
});
const newRes = new Response(stream);
const blobObj = await newRes.blob();
return { blobObj, filename };
const file = await streamDownloadFile(response);
return file;
};

/**
Expand Down
55 changes: 37 additions & 18 deletions frontend/src/features/permits/helpers/sorter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,36 @@ export const sortVehicleSubTypes = (
return sorted;
};

/**
* @param a Vehicle a
* @param b Vehicle b
* @returns 1 or -1 depending on whether a's plate > b's plate
*/
const sortByPlate = (a: Vehicle, b: Vehicle) => {
return a.plate > b.plate ? 1 : -1;
};

/**
* @param a Vehicle a
* @param b Vehicle b
* @returns 1 or -1 depending on whether a's unitNumber > b's unitNumber
*/
const sortByUnitNumber = (a: Vehicle, b: Vehicle) => {
return (a.unitNumber || -1) > (b.unitNumber || -1) ? 1 : -1;
};

/**
* @param a Vehicle a
* @param b Vehicle b
* @returns 1 or -1 depending on whether a's vehicleType > b's vehicleType
*/
const sortByVehicleType = (a: Vehicle, b: Vehicle) => {
if (a.vehicleType && b.vehicleType) {
return a.vehicleType > b.vehicleType ? 1 : -1;
}
return 0;
};

/**
* Sort Vehicles by Plates and Unit Number alphabetically and immutably
* @param vehicleType string, either plate or unitNumber
Expand All @@ -38,30 +68,19 @@ export const sortVehicles = (
) => {
if (!chooseFrom || !options) return [];

const sortByPlateOrUnitNumber = (a: Vehicle, b: Vehicle) => {
if (chooseFrom === "plate") {
return a.plate > b.plate ? 1 : -1;
}
return (a.unitNumber || -1) > (b.unitNumber || -1) ? 1 : -1;
};

const sortByVehicleType = (a: Vehicle, b: Vehicle) => {
if (a.vehicleType && b.vehicleType) {
return a.vehicleType > b.vehicleType ? 1 : -1;
}
return 0;
};

// We shouldn't change original array, but make an copy and sort on that instead
const sorted = [...options];
sorted.sort((a, b) => {
const sortedVehicles = [...options];
sortedVehicles.sort((a, b) => {
// If the vehicle types (powerUnit | trailer) are the same, sort by plate or unitnumber
if (a.vehicleType?.toLowerCase() === b.vehicleType?.toLowerCase()) {
return sortByPlateOrUnitNumber(a, b);
if (chooseFrom === "plate") {
return sortByPlate(a, b);
}
return sortByUnitNumber(a, b);
}
// else sort by vehicle type
return sortByVehicleType(a, b);
});

return sorted;
return sortedVehicles;
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { Box, Button, Typography } from "@mui/material";
import "./PermitPayFeeSummary.scss";
import { PermitType } from "../../../../types/PermitType";
import { FeeSummary } from "../../../../components/feeSummary/FeeSummary";
import { DEBOUNCE_TIMEOUT, PPC_EMAIL, TOLL_FREE_NUMBER } from "../../../../../../common/constants/constants";
import {
DEBOUNCE_TIMEOUT,
PPC_EMAIL,
TOLL_FREE_NUMBER,
} from "../../../../../../common/constants/constants";
import { useDebounce } from "@uidotdev/usehooks";
import { useEffect, useState } from "react";

Expand All @@ -23,8 +27,7 @@ export const PermitPayFeeSummary = ({
if (debouncedInputAction) {
onPay();
}

}, [debouncedInputAction])
}, [debouncedInputAction]);

return (
<Box className="permit-pay-fee-summary">
Expand All @@ -43,14 +46,13 @@ export const PermitPayFeeSummary = ({

<Typography className="permit-pay-fee-summary__contact" variant="h6">
Have questions? Please contact the Provincial Permit Centre. Toll-free:
{""}
<span className="pay-contact pay-contact--phone">
{" "}
{TOLL_FREE_NUMBER}
</span>{" "}
or Email:{" "}
<span className="pay-contact pay-contact--email">
{PPC_EMAIL}
</span>
<span className="pay-contact pay-contact--email">{PPC_EMAIL}</span>
</Typography>
</Box>
);
Expand Down

0 comments on commit 76aefc7

Please sign in to comment.