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

new content for query building empty state #246

Merged
merged 9 commits into from
Jan 7, 2025
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
33 changes: 21 additions & 12 deletions query-connector/src/app/backend/dbCreation/db-creation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ async function insertSeedDbStructs(structType: string) {
/**
* Overall orchestration function that performs the scripted process of querying
* the eRSD, extracting OIDs, then inserting valuesets into the DB.
* @returns a { success: true/false reload: true/false } status dictionary for
* whether the creation failed / needs a reload on the frontend for display
*/
export async function createDibbsDB() {
// Check if the DB already contains valuesets
Expand All @@ -358,20 +360,27 @@ export async function createDibbsDB() {
console.error("Could not load eRSD, aborting DIBBs DB creation");
}

// Only run default and custom insertions if we're making the dump
// file for dev
// if (process.env.NODE_ENV !== "production") {
await insertSeedDbStructs("valuesets");
await insertSeedDbStructs("concepts");
await insertSeedDbStructs("valueset_to_concept");
await insertSeedDbStructs("conditions");
await insertSeedDbStructs("condition_to_valueset");
await insertSeedDbStructs("query");
await insertSeedDbStructs("category");
await executeCategoryUpdates();
try {
// Only run default and custom insertions if we're making the dump
// file for dev
// if (process.env.NODE_ENV !== "production") {
await insertSeedDbStructs("valuesets");
await insertSeedDbStructs("concepts");
await insertSeedDbStructs("valueset_to_concept");
await insertSeedDbStructs("conditions");
await insertSeedDbStructs("condition_to_valueset");
await insertSeedDbStructs("query");
await insertSeedDbStructs("category");
await executeCategoryUpdates();
return { success: false, reload: false };

// }
// }
} catch {
console.error("DB reload failed");
return { succes: false, reload: false };
}
} else {
console.log("Database already has data; skipping DIBBs DB creation.");
return { success: true, reload: false };
}
}
7 changes: 3 additions & 4 deletions query-connector/src/app/queryBuilding/QueryBuilding.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ describe("tests the query building steps", () => {

// Wait for the asynchronous data to resolve and the component to update
await waitFor(() => {
expect(screen.getByText("My queries")).toBeInTheDocument();
expect(
screen.getByText("No custom queries available"),
).toBeInTheDocument();
expect(screen.getByText("Start with Query Builder")).toBeInTheDocument();

expect(screen).toMatchSnapshot();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`tests the query building steps renders 1`] = `
{
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"logTestingPlaygroundURL": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ConditionSelection: React.FC<ConditionSelectionProps> = ({
)}
>
<div className="display-flex flex-justify flex-align-end margin-bottom-3 width-full">
<h2 className="margin-y-0-important">Select condition(s)</h2>
<h2 className="margin-y-0-important">Select condition template(s)</h2>
</div>
<div className={classNames(styles.conditionSelectionForm, "radius-lg")}>
<SearchField
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { Button, Icon } from "@trussworks/react-uswds";
import { Button } from "@trussworks/react-uswds";
import { useState } from "react";
import styles from "./querySelection.module.scss";
import classNames from "classnames";
import WorkSpaceSetUpView from "./WorkspaceSetUp";
import { createDibbsDB } from "@/app/backend/dbCreation/db-creation";

type EmptyQueryProps = {
goForward: () => void;
};
/**
* Empty-state component for query building
* @param root0 - params
* @param root0.goForward - navigation function to go to the next page
* @returns the EmptyQueriesDisplay to render the empty state status
*/
export const EmptyQueriesDisplay: React.FC = () => {
export const EmptyQueriesDisplay: React.FC<EmptyQueryProps> = ({
goForward,
}) => {
const [loading, setLoading] = useState(false);

const handleClick = async () => {
Expand All @@ -17,44 +25,55 @@ export const EmptyQueriesDisplay: React.FC = () => {
// DB Creation Function
console.log("Creating DB...");

await createDibbsDB();
const { reload } = await createDibbsDB();

// Stop loading and redirect once function is complete
setLoading(false);

// Refresh query building page to display the now seeded values
location.reload();
if (reload) {
// Refresh query building page to display the now seeded values
location.reload();
} else {
goForward();
}
};

if (loading) {
return <WorkSpaceSetUpView loading={loading} />;
return <WorkSpaceSetUpView />;
}

return (
<>
<div
className={classNames(
"bg-gray-5",
"display-flex",
"flex-align-center",
"flex-justify-center",
styles.emptyStateQueryContainer,
)}
>
<div className="display-flex flex-column flex-align-center">
<Icon.GridView
aria-label="Icon of four boxes in a grid to indicate empty query state"
className={styles.emptyQueryIcon}
></Icon.GridView>
<h2 className={styles.emptyQueryTitle}>
No custom queries available
</h2>
<h1 className={styles.queryTitle}>Query Library</h1>

<div className={classNames("bg-gray-5", styles.emptyStateQueryContainer)}>
<div className="display-flex flex-column flex-align-left">
<h2 className={styles.emptyQueryTitle}>Start with Query Builder</h2>
<h3 className={styles.emptyQuerySubtitle}>
Create custom queries that your staff can use to search for relevant
data
</h3>

<ul className={styles.emptyQueryExplainer}>
<li>
<strong>Leverage</strong> our pre-populated templates with public
health codes from LOINC, ICD-10, SNOMED, and more.
</li>
<li>
<strong>Decide</strong> which codes to include in each query.
</li>
<li>
<strong>Combine</strong> codes from different conditions.
</li>
</ul>
<Button
onClick={() => handleClick()}
onClick={async () => {
await handleClick();
}}
className={styles.createQueryButton}
type={"button"}
>
Create Query
Build your first query
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const MyQueriesDisplay: React.FC<UserQueriesDisplayProps> = ({
context,
)}
<div className="display-flex flex-justify-between flex-align-center width-full margin-bottom-4">
<h1 className="flex-align-center">My queries</h1>
<h1 className="flex-align-center">Query Library</h1>
<div className="margin-left-auto">
<Button
onClick={() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import {
} from "react";
import { ToastContainer } from "react-toastify";
import EmptyQueriesDisplay from "./EmptyQueriesDisplay";
import MyQueriesDisplay from "./MyQueries";
import MyQueriesDisplay from "./QueryLibrary";
import { SelectedQueryDetails, SelectedQueryState } from "./utils";
import styles from "./querySelection.module.scss";
import { BuildStep } from "@/app/constants";
import { DataContext } from "@/app/DataProvider";

Expand Down Expand Up @@ -70,9 +69,12 @@ const QuerySelection: React.FC<QuerySelectionProps> = ({
return (
<>
{queries.length === 0 ? (
<div className="main-container">
<h1 className={styles.queryTitle}>My queries</h1>
<EmptyQueriesDisplay />
<div className="main-container__wide">
<EmptyQueriesDisplay
goForward={() => {
setBuildStep("condition");
}}
/>
</div>
) : (
<div className="main-container__wide">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,34 @@ import classNames from "classnames";
import React from "react";
import styles from "./querySelection.module.scss";

interface LoadingViewProps {
loading: boolean;
}

/**
*
* @param root0 - Component for loading screen.
* @param root0.loading - Boolean to track loading state.
* @returns The LoadingView component.
*/
const WorkSpaceSetUpView: React.FC<LoadingViewProps> = ({ loading }) => {
if (loading) {
return (
<>
<div
className={classNames(
"bg-gray-5",
"display-flex",
"flex-align-center",
"flex-justify-center",
styles.emptyStateQueryContainer,
)}
>
<div className="display-flex flex-column flex-align-center">
<Icon.HourglassEmpty
aria-label="Icon of empty hourglass to indicate loading state"
className={styles.emptyQueryIcon}
></Icon.HourglassEmpty>
<h2 className={styles.emptyQueryTitle}>
Setting up your workspace...
</h2>
<p>This is a one-time setup that may take several minutes.</p>
<p> Please do not navigate away from page during setup.</p>
</div>
</div>
</>
);
} else {
return null;
}
const WorkSpaceSetUpView: React.FC = () => {
return (
<div
className={classNames(
"bg-gray-5",
"display-flex",
"flex-align-center",
"flex-justify-center",
styles.emptyStateQueryContainer,
)}
>
<div className="display-flex flex-column flex-align-center">
<Icon.HourglassEmpty
aria-label="Icon of empty hourglass to indicate loading state"
className={styles.emptyQueryIcon}
></Icon.HourglassEmpty>
<h2 className={styles.emptyQueryTitle}>Setting up your workspace...</h2>
<p>
This is a one-time setup that may take several minutes. Please do not
navigate away from page during setup.
</p>
</div>
</div>
);
};

export default WorkSpaceSetUpView;
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ $conditionColumnSpacing: 2fr 3fr 3fr;
}

.emptyStateQueryContainer {
height: 27.75rem;
padding: 2.5rem 5rem;
}

.emptyQueryTitle {
width: fit-content;
margin: 0.5rem 0 1.5rem 0;
font-family: $sans-serif-font;
margin: 0;
}

.emptyQuerySubtitle {
width: fit-content;
margin: 0.5rem 0;
}

.emptyQueryIcon {
Expand All @@ -40,6 +44,11 @@ $conditionColumnSpacing: 2fr 3fr 3fr;
color: $gray-20;
}

.emptyQueryExplainer {
padding-left: 1.5rem;
margin: 0 0 1.5rem 0;
}

.createQueryButton {
width: fit-content;
padding: 1rem !important;
Expand Down
Loading