Skip to content

Commit

Permalink
Merge branch 'main' into josh/refactor/annotation-over-assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
JNygaard-Skylight authored Jan 3, 2025
2 parents edc318e + 6f59c59 commit 9bd215d
Show file tree
Hide file tree
Showing 41 changed files with 297 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
*.sh text eol=lf
*.md text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.csv text eol=lf

File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion containers/ecr-viewer/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.next
.github
.env
docker-compose.yml
docker-compose.yaml
Dockerfile
node_modules
seed-scripts
Expand Down
2 changes: 1 addition & 1 deletion containers/ecr-viewer/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ help:
@echo "\033[1;36mmake lint\033[0m \033[0;33m- Runs next lint\033[0m"
@echo "\033[1;36mmake test\033[0m \033[0;33m- Runs TZ=America/New_York jest\033[0m"
@echo "\033[1;36mmake test-watch\033[0m \033[0;33m- Runs TZ=America/New_York jest --watch\033[0m"
@echo "\033[1;36mmake convert-seed-data\033[0m \033[0;33m- Runs docker compose -f ./seed-scripts/docker-compose.yml up --abort-on-container-exit\033[0m"
@echo "\033[1;36mmake convert-seed-data\033[0m \033[0;33m- Runs docker compose -f ./seed-scripts/docker-compose.yaml up --abort-on-container-exit\033[0m"
@echo "\033[1;36mmake cypress-open\033[0m \033[0;33m- Opens Cypress\033[0m"
@echo "\033[1;36mmake cypress-run\033[0m \033[0;33m- Runs Cypress tests\033[0m"
@echo "\033[1;36mmake cypress-run-local\033[0m \033[0;33m- Runs Cypress tests in local environment\033[0m"
Expand Down
2 changes: 1 addition & 1 deletion containers/ecr-viewer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The eCR Viewer is primailly deveoped on Mac silicon machines, See this [integrea

Sample eICRs are included in `containers/ecr-viewer/seed-scripts/baseECR/`. If you ever need to update the eCRs or add new eCRs you can regenerate the data by:

1. Delete the current volume used by your DB: `docker compose -f ./docker-compose.yml --profile "*" down -v`
1. Delete the current volume used by your DB: `docker compose -f ./docker-compose.yaml --profile "*" down -v`
2. Run `npm run convert-seed-data` to re-run the FHIR conversion of the seed eCRs
3. Run `npm run local-dev` to re-run the eCR Viewer with the newly converted data.

Expand Down
2 changes: 1 addition & 1 deletion containers/ecr-viewer/design-review/design-review.sh
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,4 @@ open $URL

# Prompt to end review session
read -p "Press enter to end review"
docker compose -f ./docker-compose.yml --profile "*" down
docker compose -f ./docker-compose.yaml --profile "*" down
File renamed without changes.
16 changes: 8 additions & 8 deletions containers/ecr-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@
"private": true,
"scripts": {
"dev": "next dev",
"local-dev": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./docker-compose.yml --profile ${CONFIG_NAME} up -d && npm run dev'",
"local-docker": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./docker-compose.yml --profile ${CONFIG_NAME} --profile ecr-viewer up'",
"local-docker:build": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./docker-compose.yml --profile ${CONFIG_NAME} --profile ecr-viewer up --build'",
"local-dev": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./docker-compose.yaml --profile ${CONFIG_NAME} up -d && npm run dev'",
"local-docker": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./docker-compose.yaml --profile ${CONFIG_NAME} --profile ecr-viewer up'",
"local-docker:build": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./docker-compose.yaml --profile ${CONFIG_NAME} --profile ecr-viewer up --build'",
"setup-local-env": "./setup-env.sh",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "TZ=America/New_York jest",
"test:watch": "TZ=America/New_York jest --watch",
"clear-local": "docker compose -f ./seed-scripts/docker-compose-seed.yml --profile \"*\" down -v",
"convert-seed-data": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./seed-scripts/docker-compose-seed.yml --profile ${CONFIG_NAME} --profile ecr-viewer up --abort-on-container-exit'",
"convert-seed-data:build": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./seed-scripts/docker-compose-seed.yml --profile ${CONFIG_NAME} --profile ecr-viewer up --abort-on-container-exit --build'",
"update-cypress-data": "docker compose -f ./seed-scripts/docker-compose-create-sql.yml up --build --abort-on-container-exit",
"clear-local": "docker compose -f ./seed-scripts/docker-compose-seed.yaml --profile \"*\" down -v",
"convert-seed-data": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./seed-scripts/docker-compose-seed.yaml --profile ${CONFIG_NAME} --profile ecr-viewer up --abort-on-container-exit'",
"convert-seed-data:build": "npx @dotenvx/dotenvx run -f .env.local -- sh -c 'docker compose -f ./seed-scripts/docker-compose-seed.yaml --profile ${CONFIG_NAME} --profile ecr-viewer up --abort-on-container-exit --build'",
"update-cypress-data": "docker compose -f ./seed-scripts/docker-compose-create-sql.yaml up --build --abort-on-container-exit",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"cypress:run-local": "docker compose -f cypress/docker-compose.yml --env-file .env.test up postgres -d && concurrently --kill-others 'npm run dev' 'npx wait-on http://localhost:3000 && NODE_ENV=dev cypress run ; docker compose down'",
"cypress:run-local": "docker compose -f cypress/docker-compose.yaml --env-file .env.test up postgres -d && concurrently --kill-others 'npm run dev' 'npx wait-on http://localhost:3000 && NODE_ENV=dev cypress run ; docker compose down'",
"cypress:run-prod": "NODE_ENV=production cypress run"
},
"dependencies": {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: ecr-viewer

include:
- ../docker-compose.yml
- ../docker-compose.yaml
services:
fhir-converter-service:
platform: linux/amd64
Expand Down
2 changes: 1 addition & 1 deletion containers/ecr-viewer/src/app/api/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const AZURE_SOURCE = "azure";
* @returns An object representing the path mappings defined in the YAML configuration file.
*/
export function loadYamlConfig(): PathMappings {
const filePath = path.join(process.cwd(), "src/app/api/fhirPath.yml");
const filePath = path.join(process.cwd(), "src/app/api/fhirPath.yaml");
const fileContents = fs.readFileSync(filePath, "utf8");
return <PathMappings>yaml.load(fileContents);
}
Expand Down
43 changes: 35 additions & 8 deletions containers/ecr-viewer/src/app/components/BaseFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import React, { ComponentType, ReactNode, useCallback, useState } from "react";
import React, {
ComponentType,
ReactNode,
useCallback,
useContext,
useEffect,
useRef,
} from "react";
import { Button } from "@trussworks/react-uswds";
import { useRouter, usePathname, useSearchParams } from "next/navigation";
import { FILTER_CLOSED, FILTER_SUBMITTED, FilterOpenContext } from "./Filters";

/**
* Custom hook to manage query parameters in the URL (set, delete, and update). Hook always resets page back to 1.
Expand Down Expand Up @@ -94,21 +102,40 @@ export const Filter = ({
submitHandler: () => void;
children: ReactNode;
}) => {
const [isFilterBoxOpen, setIsFilterBoxOpen] = useState(false);
const openBtnRef = React.useRef<HTMLElement | null>(null);
const { filterBoxOpen, setFilterBoxOpen, lastOpenButtonRef } =
useContext(FilterOpenContext);
const openBtnRef = useRef<HTMLElement | null>(null);

const isFilterBoxOpen = filterBoxOpen === type;
const setIsFilterBoxOpen = useCallback((open: boolean) => {
if (open) {
setFilterBoxOpen(type);
// Set the last open button to this button when we open it
lastOpenButtonRef.current = openBtnRef.current?.parentElement || null;
} else {
setFilterBoxOpen(FILTER_CLOSED);
}
openBtnRef?.current?.parentElement?.focus();
}, []);

// This filter has closed. We need the special submitted case to prevent
// a race condition with submitting and resetting if we try to do a reset
// just after submitting.
useEffect(() => {
if (filterBoxOpen !== FILTER_SUBMITTED && filterBoxOpen !== type) {
resetHandler();
}
}, [filterBoxOpen]);

return (
<div>
<div onClick={(e) => e.stopPropagation()}>
<div className="position-relative display-flex flex-column">
<Button
className={`margin-right-0 ${isActive ? "filters-applied" : "filter-button"}`}
aria-label={`Filter by ${type}`}
aria-haspopup="listbox"
aria-expanded={isFilterBoxOpen}
onClick={() => {
if (isFilterBoxOpen) {
resetHandler();
}
setIsFilterBoxOpen(!isFilterBoxOpen);
}}
type="button"
Expand All @@ -133,7 +160,7 @@ export const Filter = ({
onSubmit={(e) => {
e.preventDefault();
submitHandler();
setIsFilterBoxOpen(false);
setFilterBoxOpen(FILTER_SUBMITTED);
openBtnRef?.current?.parentElement?.focus();
}}
>
Expand Down
69 changes: 66 additions & 3 deletions containers/ecr-viewer/src/app/components/Filters.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
"use client";

import React, { useEffect, useState } from "react";
import React, {
createContext,
useCallback,
useEffect,
useRef,
useState,
} from "react";
import { Icon } from "@trussworks/react-uswds";
import { useQueryParam, Filter } from "./BaseFilter";
import {
Expand All @@ -9,19 +15,76 @@ import {
dateRangeLabels,
} from "@/app/view-data/utils/date-utils";

// We use a context to communicate between the overall <Filters /> component
// and the `<Filter />` component to avoid prop drilling
type FilterOpenContextValue = {
filterBoxOpen: string;
setFilterBoxOpen: (v: string) => void;
lastOpenButtonRef: { current: HTMLElement | null };
};
// We need the submitted case to differentiate from closing and prevent
// a race condition with submitting and resetting if we try to do a reset
// just after submitting.
export const FILTER_SUBMITTED = "__submitted__";
export const FILTER_CLOSED = "__closed__";

export const FilterOpenContext = createContext<FilterOpenContextValue>({
filterBoxOpen: FILTER_CLOSED,
setFilterBoxOpen: () => {},
lastOpenButtonRef: { current: null },
});

/**
* Functional component that renders Filters section in eCR Library.
* Includes Filter component for reportable conditions.
* @returns The rendered Filters component.
*/
const Filters = () => {
const [filterBoxOpen, setFilterBoxOpen] = useState<string>(FILTER_CLOSED);
const lastOpenButtonRef = useRef<HTMLElement | null>(null);

const filterOpenContextValue = {
filterBoxOpen,
setFilterBoxOpen,
lastOpenButtonRef,
};

const resetFilters = useCallback(() => {
setFilterBoxOpen(FILTER_CLOSED);
}, []);

// When a filter is open, close it if the escape key is hit or a click happens
// outside the <Filter /> component (implemented by stopping click propogation on <Filter />)
useEffect(() => {
if (filterBoxOpen !== FILTER_CLOSED && filterBoxOpen !== FILTER_SUBMITTED) {
const handleEscapeFilters = (event: KeyboardEvent) => {
if (event.code === "Escape") {
resetFilters();

// Return focus to the most recently selected open button
lastOpenButtonRef.current?.focus();
lastOpenButtonRef.current = null;
}
};

window.addEventListener("keydown", handleEscapeFilters);
window.addEventListener("click", resetFilters);
return () => {
window.removeEventListener("keydown", handleEscapeFilters);
window.removeEventListener("click", resetFilters);
};
}
}, [filterBoxOpen]);

return (
<div>
<div className="border-top border-base-lighter"></div>
<div className="margin-x-3 margin-y-105 display-flex flex-align-center gap-105">
<span className="line-height-sans-6">FILTERS:</span>
<FilterByDate />
<FilterReportableConditions />
<FilterOpenContext.Provider value={filterOpenContextValue}>
<FilterByDate />
<FilterReportableConditions />
</FilterOpenContext.Provider>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("Active Problems Table", () => {
let container: HTMLElement;
beforeEach(() => {
const fhirPathFile = fs
.readFileSync("./src/app/api/fhirPath.yml", "utf8")
.readFileSync("./src/app/api/fhirPath.yaml", "utf8")
.toString();
const fhirPathMappings = YAML.load(fhirPathFile) as PathMappings;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe("Snapshot test for Procedures (Treatment Details)", () => {
] as unknown as Procedure[];

const fhirPathFile = fs
.readFileSync("./src/app/api/fhirPath.yml", "utf8")
.readFileSync("./src/app/api/fhirPath.yaml", "utf8")
.toString();
const mappings = YAML.load(fhirPathFile) as PathMappings;
const treatmentData = [
Expand Down
Loading

0 comments on commit 9bd215d

Please sign in to comment.