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

componentize query page checkboxes #181

Merged
Show file tree
Hide file tree
Changes from 13 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
1 change: 1 addition & 0 deletions query-connector/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ AUTH_SECRET="ido5D/uybeAB3AmMQwn+ubw2zYC4t2h7RJlW2R79598="
AUTH_KEYCLOAK_ID=query-connector
AUTH_KEYCLOAK_SECRET=ZG3f7R1J3qIwBaw8QtttJnJMinpERQKs
AUTH_KEYCLOAK_ISSUER=http://localhost:8081/realms/master
E2E_LOCAL_FHIR_SERVER=http://localhost:8080/fhir
ERSD_API_KEY=
UMLS_API_KEY=
6 changes: 6 additions & 0 deletions query-connector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ If the above doesn't work, try replacing `localhost` with `0.0.0.0`.
4. Enter the DB password when prompted.
5. The extract file, `vs_dump.sql`, should now be created. It should automatically be located in `/query-connector`, but if it isn't, put `vs_dump.sql` there.

#### Running the e2e tests locally

Our e2e's are available locally via `npm run test:playright:local`. You'll need to have the app running locally at `localhost:3000` first (ie using `npm run dev`).

You'll need to set `E2E_LOCAL_FHIR_SERVER` in your local `.env` file first in order for the flows that use the local HAPI server to route correctly. This is pre-set for you in the `.env.sample` file.

### Architecture Diagram

```mermaid
Expand Down
9 changes: 4 additions & 5 deletions query-connector/e2e/customize_query.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,14 @@ test.describe("querying with the Query Connector", () => {
await page.getByRole("link", { name: "Medications" }).click();
await page.getByRole("button", { name: "Chlamydia Medication" }).click();
await page
.getByRole("row")
.filter({ hasText: "azithromycin 1000 MG" })
.getByRole("img")
.getByRole("row", { name: "azithromycin 1000 MG" })
.locator("label")
.click();
await expect(page.getByText("3 of 4 selected")).toBeVisible();
await page
.getByRole("row")
.filter({ hasText: "ceftriaxone 500 MG Injection" })
.getByRole("img")
.locator("label")
.click();
await expect(page.getByText("2 of 4 selected")).toBeVisible();
await page.getByRole("button", { name: "Apply changes" }).click();
Expand Down Expand Up @@ -124,7 +123,7 @@ test.describe("querying with the Query Connector", () => {
await page.getByRole("link", { name: "Medications" }).click();
await page
.getByRole("button", { name: "Chlamydia Medication" })
.getByRole("img")
.locator("label")
.click();
await expect(page.getByText("0 of 4 selected")).toBeVisible();

Expand Down
4 changes: 3 additions & 1 deletion query-connector/src/app/fhir-servers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ type FHIR_SERVER_CONFIG = {
/**
* The configurations for the FHIR servers currently supported.
*/
const localE2EFhirServer =
process.env.E2E_LOCAL_FHIR_SERVER ?? "http://hapi-fhir-server:8080/fhir";
fzhao99 marked this conversation as resolved.
Show resolved Hide resolved
export const fhirServers: Record<FHIR_SERVERS, FHIR_SERVER_CONFIG> = {
"HELIOS Meld: Direct": {
hostname: "https://gw.interop.community/HeliosConnectathonSa/open",
Expand All @@ -29,7 +31,7 @@ export const fhirServers: Record<FHIR_SERVERS, FHIR_SERVER_CONFIG> = {
init: {} as RequestInit,
},
"Local e2e HAPI Server: Direct": {
hostname: "http://hapi-fhir-server:8080/fhir",
hostname: localE2EFhirServer,
init: {} as RequestInit,
},
"OpenEpic: eHealthExchange": configureEHX("OpenEpic"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Icon } from "@trussworks/react-uswds";
import styles from "./customizeQuery.module.css";
import { GroupedValueSet } from "./customizeQueryUtils";
import Table from "../../designSystem/Table";
import CustomizeQueryCheckbox from "./vanityCheckbox/CustomizeQueryCheckbox";

type CustomizeQueryAccordionBodyProps = {
group: GroupedValueSet;
Expand Down Expand Up @@ -52,22 +52,14 @@ const CustomizeQueryAccordionBody: React.FC<
}, [] as ValueSetIndexedConcept[])
.map((item, conceptIndex) => (
<tr className={`${styles.customizeQueryGridRow}`} key={item.code}>
<td
className={`${styles.customizeQueryCheckbox}`}
onClick={(e) => {
e.stopPropagation();
toggleInclude(groupIndex, item.vsIndex, conceptIndex);
}}
>
{item.include && (
<Icon.Check
aria-label="Check icon indicating selection"
className="usa-icon"
style={{ backgroundColor: "white" }}
size={4}
color="#005EA2"
/>
)}
<td className={styles.noBorderNoBackgroundNoPadding}>
<CustomizeQueryCheckbox
id={item.code}
checked={item.include}
onChange={() => {
toggleInclude(groupIndex, item.vsIndex, conceptIndex);
}}
/>
</td>
<td className={styles.noBorderNoBackgroundNoPadding}>
{item.code}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Icon } from "@trussworks/react-uswds";
import styles from "./customizeQuery.module.css";
import { GroupedValueSet } from "./customizeQueryUtils";
import CustomizeQueryCheckbox from "./vanityCheckbox/CustomizeQueryCheckbox";

type CustomizeQueryAccordionProps = {
handleSelectAllChange: (groupIndex: string, checked: boolean) => void;
Expand Down Expand Up @@ -36,31 +36,14 @@ const CustomizeQueryAccordionHeader: React.FC<CustomizeQueryAccordionProps> = ({
<div
className={`${styles.accordionHeader} display-flex flex-no-wrap flex-align-start customize-query-header`}
>
<div
id="select-all"
className={`hide-checkbox-label ${styles.customizeQueryCheckbox}`}
onClick={(e) => {
e.stopPropagation();
<CustomizeQueryCheckbox
id={group.valueSetName}
checked={selectedCount === selectedTotal}
isHeader
onChange={() => {
handleSelectAllChange(groupIndex, selectedCount !== selectedTotal);
}}
>
{selectedCount === selectedTotal && (
<Icon.Check
className="usa-icon bg-base-lightest"
size={4}
color="#565C65"
aria-label="Checkmark icon indicating addition"
/>
)}
{selectedCount > 0 && selectedCount < selectedTotal && (
<Icon.Remove
className="usa-icon bg-base-lightest"
size={4}
color="#565C65"
aria-label="Minus icon indicating removal"
/>
)}
</div>
/>
<div className={`${styles.accordionButtonTitle}`}>
{`${group.valueSetName}`}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,26 +70,6 @@
padding: 0 !important;
}

.customizeQueryCheckbox {
width: 2.25rem;
height: 2.25rem;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
background-color: #fff;
border: 1px solid #a9aeb1 !important;
border-radius: 0.25rem;
margin: 0.5rem;
padding: 0 !important;
}

.customizeQueryCheckbox svg {
width: 100%;
height: 100%;
border-radius: inherit;
}

.accordionHeader {
display: flex;
width: 100%;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import classNames from "classnames";
import Checkbox, {
CheckboxProps,
} from "../../../designSystem/checkbox/Checkbox";
import styles from "./checkbox.module.css";

type VanityCheckboxProps = CheckboxProps & {
isHeader?: boolean;
};
/**
* Vanity component wrapper around the checkbox component for the query customization
* checkboxes
* @param root0 - params
* @param root0.id - ID for checkbox
* @param root0.checked - whether the checkbox is checked
* @param root0.onChange - handler for when the checkbox is clicked
* @param root0.isHeader - whether the checkbox is in the header
* @returns A checkbox for the customize query page
*/
const CustomizeQueryCheckbox: React.FC<VanityCheckboxProps> = ({
id,
checked,
onChange,
isHeader,
}) => {
return (
<Checkbox
id={id}
checked={checked}
onChange={onChange}
className={classNames(styles.vanity, isHeader ? styles.vanityHeader : "")}
/>
);
};

export default CustomizeQueryCheckbox;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.vanity {
background: inherit;
margin: 0.5rem;
}

.vanity label {
margin-top: 0;
padding-left: 0;
}

.vanity label::before {
width: 2.25rem;
height: 2.25rem;
background-color: #fff;
box-shadow: 0 0 0 1px #a9aeb1 !important;
border-radius: 0.25rem;
margin: 0;
padding: 0 !important;
position: relative !important;
}

.vanity input:checked + label::before {
background-color: #fff !important;
background-image: url("bodyCheckmark.svg") !important;
background-size: cover !important;
}

.vanityHeader input:checked + label::before {
background-image: url("headerCheckbox.svg") !important;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 9 additions & 4 deletions query-connector/src/app/query/designSystem/checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { Checkbox as TrussCheckbox } from "@trussworks/react-uswds";
import classNames from "classnames";
import styles from "./checkbox.module.css";

type CheckboxProps = {
export type CheckboxProps = {
id: string;
label: string;
label?: string;
className?: string;
onClick?: () => void;
checked: boolean;
onChange?: () => void;
checked?: boolean;
};

/**
Expand All @@ -18,13 +19,16 @@ type CheckboxProps = {
* @param root0.className Optional styling classes
* @param root0.onClick Event listener for checkbox click
* @param root0.checked Boolean indicating whether the checkbox is checked
* @param root0.onChange - Event listener for checkbox change. Use this one
* over onClick if the component is controlled (ie checked is passed in)
* @returns A checkbox styled according to our design system
*/
const Checkbox: React.FC<CheckboxProps> = ({
label,
id,
className,
onClick,
onChange,
checked,
}) => {
return (
Expand All @@ -34,7 +38,8 @@ const Checkbox: React.FC<CheckboxProps> = ({
name={id}
className={classNames(styles.checkbox, className)}
onClick={onClick}
defaultChecked={checked}
onChange={onChange}
checked={checked}
></TrussCheckbox>
);
};
Expand Down
Loading
Loading