Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ECR Library sorting #2812

Merged
merged 29 commits into from
Nov 5, 2024
Merged
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
14 changes: 14 additions & 0 deletions containers/ecr-viewer/jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,22 @@ import "@testing-library/jest-dom";
import { toHaveNoViolations } from "jest-axe";
import * as matchers from "jest-extended";
import { TextEncoder } from "util";
import router from "next-router-mock";

global.TextEncoder = TextEncoder;

expect.extend(toHaveNoViolations);
expect.extend(matchers);

// Mocking `next/navigation` hooks
jest.mock("next/navigation", () => ({
useRouter: () => router,
usePathname: () => router.pathname,
useSearchParams: () => {
const params = new URLSearchParams(router.asPath.split("?")[1]);
return {
get: params.get.bind(params),
toString: () => params.toString(),
};
},
}));
1 change: 1 addition & 0 deletions containers/ecr-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"mssql": "^11.0.1",
"next": "^14.2.14",
"next-auth": "^4.24.7",
"next-router-mock": "^0.9.13",
"pg-promise": "^11.6.0",
"react": "^18",
"react-dom": "^18",
Expand Down
45 changes: 44 additions & 1 deletion containers/ecr-viewer/src/app/api/services/listEcrDataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,25 @@ export type EcrDisplay = {
/**
* @param startIndex - The index of the first item to fetch
* @param itemsPerPage - The number of items to fetch
* @param sortColumn - The column to sort by
* @param sortDirection - The direction to sort by
* @param searchTerm - The search term to use
* @returns A promise resolving to a list of eCR metadata
*/
export async function listEcrData(
startIndex: number,
itemsPerPage: number,
sortColumn: string,
sortDirection: string,
searchTerm?: string,
): Promise<EcrDisplay[]> {
const list = await database.manyOrNone<EcrMetadataModel>(
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] order by ed.report_date DESC OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] $[sortStatement] OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
{
whereClause: generateSearchStatement(searchTerm),
startIndex,
itemsPerPage,
sortStatement: generateSortStatement(sortColumn, sortDirection),
},
);
return processMetadata(list);
Expand Down Expand Up @@ -121,3 +126,41 @@ export const generateSearchStatement = (searchTerm?: string) => ({
.join(" OR ");
},
});

/**
* A custom type format for sort statement
* @param columnName - The column to sort by
* @param direction - The direction to sort by
* @returns custom type format object for use by pg-promise
*/
export const generateSortStatement = (
lina-roth marked this conversation as resolved.
Show resolved Hide resolved
columnName: string,
direction: string,
) => ({
rawType: true,
toPostgres: () => {
// Valid columns and directions
const validColumns = ["patient", "date_created", "report_date"];
const validDirections = ["ASC", "DESC"];

// Validation check
if (!validColumns.includes(columnName)) {
columnName = "date_created";
}
if (!validDirections.includes(direction)) {
direction = "DESC";
}

if (columnName === "patient") {
return pgPromise.as.format(
`ORDER BY ed.patient_name_last ${direction}, ed.patient_name_first ${direction}`,
{ direction },
);
}

// Default case for other columns
return pgPromise.as.format(`ORDER BY $[columnName:raw] ${direction}`, {
columnName,
});
},
});
62 changes: 52 additions & 10 deletions containers/ecr-viewer/src/app/api/tests/listEcrDataService.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,23 @@ describe("listEcrDataService", () => {
it("should return empty array when no data is found", async () => {
let startIndex = 0;
let itemsPerPage = 25;
let columnName = "date_created";
let direction = "DESC";
database.manyOrNone = jest.fn(() => Promise.resolve([]));
const actual = await listEcrData(startIndex, itemsPerPage);
const actual = await listEcrData(
startIndex,
itemsPerPage,
columnName,
direction,
);
expect(database.manyOrNone).toHaveBeenCalledOnce();
expect(database.manyOrNone).toHaveBeenCalledWith(
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] order by ed.report_date DESC OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] $[sortStatement] OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
{
whereClause: expect.any(Object),
startIndex,
itemsPerPage,
sortStatement: expect.any(Object),
},
);
expect(actual).toBeEmpty();
Expand All @@ -137,15 +145,23 @@ describe("listEcrDataService", () => {

let startIndex = 0;
let itemsPerPage = 25;
const actual: EcrDisplay[] = await listEcrData(startIndex, itemsPerPage);
let columnName = "date_created";
let direction = "DESC";
const actual: EcrDisplay[] = await listEcrData(
startIndex,
itemsPerPage,
columnName,
direction,
);

expect(database.manyOrNone).toHaveBeenCalledOnce();
expect(database.manyOrNone).toHaveBeenCalledWith(
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] order by ed.report_date DESC OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] $[sortStatement] OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
{
whereClause: expect.any(Object),
startIndex,
itemsPerPage,
sortStatement: expect.any(Object),
},
);
expect(actual).toEqual([
Expand Down Expand Up @@ -183,14 +199,22 @@ describe("listEcrDataService", () => {

let startIndex = 0;
let itemsPerPage = 25;
const actual: EcrDisplay[] = await listEcrData(startIndex, itemsPerPage);
let columnName = "date_created";
let direction = "DESC";
const actual: EcrDisplay[] = await listEcrData(
startIndex,
itemsPerPage,
columnName,
direction,
);
expect(database.manyOrNone).toHaveBeenCalledOnce();
expect(database.manyOrNone).toHaveBeenCalledWith(
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] order by ed.report_date DESC OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] $[sortStatement] OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
{
whereClause: expect.any(Object),
startIndex,
itemsPerPage,
sortStatement: expect.any(Object),
},
);
expect(actual).toEqual([
Expand All @@ -211,15 +235,24 @@ describe("listEcrDataService", () => {
database.manyOrNone = jest.fn(() => Promise.resolve([]));
let startIndex = 0;
let itemsPerPage = 25;
let columnName = "date_created";
let direction = "DESC";
let searchTerm = "abc";
await listEcrData(startIndex, itemsPerPage, searchTerm);
await listEcrData(
startIndex,
itemsPerPage,
columnName,
direction,
searchTerm,
);
expect(database.manyOrNone).toHaveBeenCalledOnce();
expect(database.manyOrNone).toHaveBeenCalledWith(
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] order by ed.report_date DESC OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] $[sortStatement] OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
{
whereClause: expect.any(Object),
startIndex,
itemsPerPage,
sortStatement: expect.any(Object),
},
);
});
Expand All @@ -229,14 +262,23 @@ describe("listEcrDataService", () => {
let startIndex = 0;
let itemsPerPage = 25;
let searchTerm = "O'Riley";
await listEcrData(startIndex, itemsPerPage, searchTerm);
let columnName = "date_created";
let direction = "DESC";
await listEcrData(
startIndex,
itemsPerPage,
searchTerm,
columnName,
direction,
);
expect(database.manyOrNone).toHaveBeenCalledOnce();
expect(database.manyOrNone).toHaveBeenCalledWith(
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] order by ed.report_date DESC OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
"SELECT ed.eICR_ID, ed.patient_name_first, ed.patient_name_last, ed.patient_birth_date, ed.date_created, ed.report_date, erc.condition, ers.rule_summary, ed.report_date FROM ecr_data ed LEFT JOIN ecr_rr_conditions erc ON ed.eICR_ID = erc.eICR_ID LEFT JOIN ecr_rr_rule_summaries ers ON erc.uuid = ers.ecr_rr_conditions_id where $[whereClause] $[sortStatement] OFFSET $[startIndex] ROWS FETCH NEXT $[itemsPerPage] ROWS ONLY",
{
whereClause: expect.any(Object),
startIndex,
itemsPerPage,
sortStatement: expect.any(Object),
},
);
});
Expand Down
Loading
Loading