From c871d9cbafd9b5cc1eaf9e2415f03178aab87357 Mon Sep 17 00:00:00 2001 From: m-goggins Date: Wed, 6 Nov 2024 11:52:44 -0800 Subject: [PATCH 01/16] add button to "my queries" page to add eRSD data to the db --- .../queryBuilding/emptyState/EmptyQueriesDisplay.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index a73c1c12f..1a7bc3bac 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -17,10 +17,14 @@ export const EmptyQueriesDisplay: React.FC = () => {

No custom queries available

- - +
+ + +
From a509ace7e7a1209c087e82f1f5be0ad32f627126 Mon Sep 17 00:00:00 2001 From: m-goggins Date: Wed, 6 Nov 2024 13:40:56 -0800 Subject: [PATCH 02/16] add button for triggering data insertion --- query-connector/src/app/database-service.ts | 42 +++++++++---------- .../emptyState/EmptyQueriesDisplay.tsx | 6 ++- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/query-connector/src/app/database-service.ts b/query-connector/src/app/database-service.ts index f2bbee22c..e4f09d3e6 100644 --- a/query-connector/src/app/database-service.ts +++ b/query-connector/src/app/database-service.ts @@ -121,7 +121,7 @@ type ErsdOrVsacResponse = Bundle | OperationOutcome; * @returns The eRSD Specification as a FHIR Bundle or an OperationOutcome if an error occurs. */ export async function getERSD( - eRSDVersion: number = 3, + eRSDVersion: number = 3 ): Promise { const ERSD_API_KEY = process.env.ERSD_API_KEY; const eRSDUrl = `https://ersd.aimsplatform.org/api/ersd/v${eRSDVersion}specification?format=json&api-key=${ERSD_API_KEY}`; @@ -152,7 +152,7 @@ export async function getERSD( * @returns The value sets as a FHIR bundle, or an Operation Outcome if there is an error. */ export async function getVSACValueSet( - oid: string, + oid: string ): Promise { const username: string = "apikey"; const umlsKey: string = process.env.UMLS_API_KEY || ""; @@ -192,7 +192,7 @@ export async function getVSACValueSet( */ export async function translateVSACToInternalValueSet( fhirValueset: FhirValueSet, - ersdConceptType: ErsdConceptType, + ersdConceptType: ErsdConceptType ) { const oid = fhirValueset.id; const version = fhirValueset.version; @@ -233,7 +233,7 @@ export async function insertValueSet(vs: ValueSet) { await insertValueSetPromise; } catch (e) { console.error( - `ValueSet insertion for ${vs.valueSetId}_${vs.valueSetVersion} failed`, + `ValueSet insertion for ${vs.valueSetId}_${vs.valueSetVersion} failed` ); console.error(e); errorArray.push("Error occured in valuset insertion"); @@ -241,11 +241,11 @@ export async function insertValueSet(vs: ValueSet) { const insertConceptsPromiseArray = generateConceptSqlPromises(vs); const conceptInsertResults = await Promise.allSettled( - insertConceptsPromiseArray, + insertConceptsPromiseArray ); const allConceptInsertsSucceed = conceptInsertResults.every( - (r) => r.status === "fulfilled", + (r) => r.status === "fulfilled" ); if (!allConceptInsertsSucceed) { @@ -257,13 +257,13 @@ export async function insertValueSet(vs: ValueSet) { const joinInsertResults = await Promise.allSettled(joinInsertsPromiseArray); const allJoinInsertsSucceed = joinInsertResults.every( - (r) => r.status === "fulfilled", + (r) => r.status === "fulfilled" ); if (!allJoinInsertsSucceed) { logRejectedPromiseReasons( joinInsertResults, - "ValueSet <> concept join insert failed", + "ValueSet <> concept join insert failed" ); errorArray.push("Error occured in ValueSet <> concept join seeding"); } @@ -394,7 +394,7 @@ function stripProtocolAndTLDFromSystemUrl(systemURL: string) { function logRejectedPromiseReasons( resultsArray: PromiseSettledResult[], - errorMessageString: string, + errorMessageString: string ) { return resultsArray .filter((r): r is PromiseRejectedResult => r.status === "rejected") @@ -421,7 +421,7 @@ export async function insertQuery(input: QueryInput) { queryId = results.rows[0].id as unknown as UUID; } catch (e) { console.error( - `Error occured in user query insertion: insertion for ${input.queryName} failed`, + `Error occured in user query insertion: insertion for ${input.queryName} failed` ); console.error(e); errorArray.push("Error occured in user query insertion"); @@ -431,7 +431,7 @@ export async function insertQuery(input: QueryInput) { const insertJoinSqlArray = generateQueryToValueSetInsertionSql( input, - queryId as UUID, + queryId as UUID ); const joinPromises = insertJoinSqlArray.map((q) => { @@ -441,7 +441,7 @@ export async function insertQuery(input: QueryInput) { const joinInsertResults = await Promise.allSettled(joinPromises); const joinInsertsSucceeded = joinInsertResults.every( - (r) => r.status === "fulfilled", + (r) => r.status === "fulfilled" ); if (!joinInsertsSucceeded) { @@ -483,7 +483,7 @@ export async function checkValueSetInsertion(vs: ValueSet) { foundVS.author !== vs.author ) { console.error( - "Retrieved value set information differs from given value set", + "Retrieved value set information differs from given value set" ); missingData.missingValueSet = true; } @@ -511,18 +511,18 @@ export async function checkValueSetInsertion(vs: ValueSet) { console.error( "Retrieved concept " + conceptId + - " has different values than given concept", + " has different values than given concept" ); return conceptId; } } catch (error) { console.error( "Couldn't fetch concept with ID " + conceptId + ": ", - error, + error ); return conceptId; } - }), + }) ); missingData.missingConcepts = brokenConcepts.filter((bc) => bc !== undefined); @@ -539,18 +539,18 @@ export async function checkValueSetInsertion(vs: ValueSet) { const fIdx = rows.findIndex((r) => r["concept_id"] === conceptUniqueId); if (fIdx === -1) { console.error( - "Couldn't locate concept " + conceptUniqueId + " in fetched mappings", + "Couldn't locate concept " + conceptUniqueId + " in fetched mappings" ); return conceptUniqueId; } }); missingData.missingMappings = missingConceptsFromMappings.filter( - (item) => item !== undefined, + (item) => item !== undefined ); } catch (error) { console.error( "Couldn't fetch value set to concept mappings for this valueset: ", - error, + error ); const systemPrefix = stripProtocolAndTLDFromSystemUrl(vs.system); vs.concepts.forEach((c) => { @@ -588,7 +588,7 @@ export async function getConditionsData() { acc[category].push({ [id]: name }); return acc; }, - {} as Record>>, + {} as Record>> ); // 2. ID-Name mapping @@ -597,7 +597,7 @@ export async function getConditionsData() { acc[row.id] = row.name; return acc; }, - {} as Record, + {} as Record ); return { conditionCatergories, conditionLookup }; diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index 1a7bc3bac..8e82fe2d5 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -21,7 +21,11 @@ export const EmptyQueriesDisplay: React.FC = () => { - From 15f4cb77e980be9890e1373b340278629b8387ad Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:48:59 +0000 Subject: [PATCH 03/16] [pre-commit.ci] auto fixes from pre-commit hooks --- query-connector/src/app/database-service.ts | 42 ++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/query-connector/src/app/database-service.ts b/query-connector/src/app/database-service.ts index e4f09d3e6..f2bbee22c 100644 --- a/query-connector/src/app/database-service.ts +++ b/query-connector/src/app/database-service.ts @@ -121,7 +121,7 @@ type ErsdOrVsacResponse = Bundle | OperationOutcome; * @returns The eRSD Specification as a FHIR Bundle or an OperationOutcome if an error occurs. */ export async function getERSD( - eRSDVersion: number = 3 + eRSDVersion: number = 3, ): Promise { const ERSD_API_KEY = process.env.ERSD_API_KEY; const eRSDUrl = `https://ersd.aimsplatform.org/api/ersd/v${eRSDVersion}specification?format=json&api-key=${ERSD_API_KEY}`; @@ -152,7 +152,7 @@ export async function getERSD( * @returns The value sets as a FHIR bundle, or an Operation Outcome if there is an error. */ export async function getVSACValueSet( - oid: string + oid: string, ): Promise { const username: string = "apikey"; const umlsKey: string = process.env.UMLS_API_KEY || ""; @@ -192,7 +192,7 @@ export async function getVSACValueSet( */ export async function translateVSACToInternalValueSet( fhirValueset: FhirValueSet, - ersdConceptType: ErsdConceptType + ersdConceptType: ErsdConceptType, ) { const oid = fhirValueset.id; const version = fhirValueset.version; @@ -233,7 +233,7 @@ export async function insertValueSet(vs: ValueSet) { await insertValueSetPromise; } catch (e) { console.error( - `ValueSet insertion for ${vs.valueSetId}_${vs.valueSetVersion} failed` + `ValueSet insertion for ${vs.valueSetId}_${vs.valueSetVersion} failed`, ); console.error(e); errorArray.push("Error occured in valuset insertion"); @@ -241,11 +241,11 @@ export async function insertValueSet(vs: ValueSet) { const insertConceptsPromiseArray = generateConceptSqlPromises(vs); const conceptInsertResults = await Promise.allSettled( - insertConceptsPromiseArray + insertConceptsPromiseArray, ); const allConceptInsertsSucceed = conceptInsertResults.every( - (r) => r.status === "fulfilled" + (r) => r.status === "fulfilled", ); if (!allConceptInsertsSucceed) { @@ -257,13 +257,13 @@ export async function insertValueSet(vs: ValueSet) { const joinInsertResults = await Promise.allSettled(joinInsertsPromiseArray); const allJoinInsertsSucceed = joinInsertResults.every( - (r) => r.status === "fulfilled" + (r) => r.status === "fulfilled", ); if (!allJoinInsertsSucceed) { logRejectedPromiseReasons( joinInsertResults, - "ValueSet <> concept join insert failed" + "ValueSet <> concept join insert failed", ); errorArray.push("Error occured in ValueSet <> concept join seeding"); } @@ -394,7 +394,7 @@ function stripProtocolAndTLDFromSystemUrl(systemURL: string) { function logRejectedPromiseReasons( resultsArray: PromiseSettledResult[], - errorMessageString: string + errorMessageString: string, ) { return resultsArray .filter((r): r is PromiseRejectedResult => r.status === "rejected") @@ -421,7 +421,7 @@ export async function insertQuery(input: QueryInput) { queryId = results.rows[0].id as unknown as UUID; } catch (e) { console.error( - `Error occured in user query insertion: insertion for ${input.queryName} failed` + `Error occured in user query insertion: insertion for ${input.queryName} failed`, ); console.error(e); errorArray.push("Error occured in user query insertion"); @@ -431,7 +431,7 @@ export async function insertQuery(input: QueryInput) { const insertJoinSqlArray = generateQueryToValueSetInsertionSql( input, - queryId as UUID + queryId as UUID, ); const joinPromises = insertJoinSqlArray.map((q) => { @@ -441,7 +441,7 @@ export async function insertQuery(input: QueryInput) { const joinInsertResults = await Promise.allSettled(joinPromises); const joinInsertsSucceeded = joinInsertResults.every( - (r) => r.status === "fulfilled" + (r) => r.status === "fulfilled", ); if (!joinInsertsSucceeded) { @@ -483,7 +483,7 @@ export async function checkValueSetInsertion(vs: ValueSet) { foundVS.author !== vs.author ) { console.error( - "Retrieved value set information differs from given value set" + "Retrieved value set information differs from given value set", ); missingData.missingValueSet = true; } @@ -511,18 +511,18 @@ export async function checkValueSetInsertion(vs: ValueSet) { console.error( "Retrieved concept " + conceptId + - " has different values than given concept" + " has different values than given concept", ); return conceptId; } } catch (error) { console.error( "Couldn't fetch concept with ID " + conceptId + ": ", - error + error, ); return conceptId; } - }) + }), ); missingData.missingConcepts = brokenConcepts.filter((bc) => bc !== undefined); @@ -539,18 +539,18 @@ export async function checkValueSetInsertion(vs: ValueSet) { const fIdx = rows.findIndex((r) => r["concept_id"] === conceptUniqueId); if (fIdx === -1) { console.error( - "Couldn't locate concept " + conceptUniqueId + " in fetched mappings" + "Couldn't locate concept " + conceptUniqueId + " in fetched mappings", ); return conceptUniqueId; } }); missingData.missingMappings = missingConceptsFromMappings.filter( - (item) => item !== undefined + (item) => item !== undefined, ); } catch (error) { console.error( "Couldn't fetch value set to concept mappings for this valueset: ", - error + error, ); const systemPrefix = stripProtocolAndTLDFromSystemUrl(vs.system); vs.concepts.forEach((c) => { @@ -588,7 +588,7 @@ export async function getConditionsData() { acc[category].push({ [id]: name }); return acc; }, - {} as Record>> + {} as Record>>, ); // 2. ID-Name mapping @@ -597,7 +597,7 @@ export async function getConditionsData() { acc[row.id] = row.name; return acc; }, - {} as Record + {} as Record, ); return { conditionCatergories, conditionLookup }; From 4678f3cb8e718ef2f61c40f3e69e383d6b969910 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:30:28 +0000 Subject: [PATCH 04/16] [pre-commit.ci] auto fixes from pre-commit hooks --- .../src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index bc445146f..b59b1763e 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -18,7 +18,7 @@ export const EmptyQueriesDisplay: React.FC = () => { "display-flex", "flex-align-center", "flex-justify-center", - styles.emptyStateQueryContainer + styles.emptyStateQueryContainer, )} >
From 36a127d52049fb3ef33b0d5f383a203e10883e32 Mon Sep 17 00:00:00 2001 From: m-goggins Date: Fri, 8 Nov 2024 08:50:05 -0800 Subject: [PATCH 05/16] add to gear icon --- .../src/app/query/components/header/header.tsx | 14 +++++++++++--- .../emptyState/EmptyQueriesDisplay.tsx | 9 +-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/query-connector/src/app/query/components/header/header.tsx b/query-connector/src/app/query/components/header/header.tsx index 6b466ad25..73da1bb00 100644 --- a/query-connector/src/app/query/components/header/header.tsx +++ b/query-connector/src/app/query/components/header/header.tsx @@ -57,7 +57,7 @@ export default function HeaderComponent() {
@@ -77,7 +77,7 @@ export default function HeaderComponent() { className={classNames( "margin-left-auto", "display-flex", - "flex-align-center", + "flex-align-center" )} > {path != "/signin" && isClient && ( @@ -106,7 +106,7 @@ export default function HeaderComponent() { styles.menuButton, "usa-accordion__button", "usa-nav__link", - "usa-current", + "usa-current" )} aria-expanded="false" aria-controls="dropdown-menu" @@ -145,6 +145,14 @@ export default function HeaderComponent() { )} +
  • + + Add eRSD value sets + +
  • Log out diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index b59b1763e..394a67aa9 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -18,7 +18,7 @@ export const EmptyQueriesDisplay: React.FC = () => { "display-flex", "flex-align-center", "flex-justify-center", - styles.emptyStateQueryContainer, + styles.emptyStateQueryContainer )} >
    @@ -37,13 +37,6 @@ export const EmptyQueriesDisplay: React.FC = () => { > Create Query -
  • From 2a7a1a201aba9a6320688db351e7f1fc2d718db0 Mon Sep 17 00:00:00 2001 From: m-goggins Date: Fri, 8 Nov 2024 08:51:11 -0800 Subject: [PATCH 06/16] add advanced --- query-connector/src/app/query/components/header/header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query-connector/src/app/query/components/header/header.tsx b/query-connector/src/app/query/components/header/header.tsx index 73da1bb00..9fee40565 100644 --- a/query-connector/src/app/query/components/header/header.tsx +++ b/query-connector/src/app/query/components/header/header.tsx @@ -150,7 +150,7 @@ export default function HeaderComponent() { className={styles.menuItem} // onClick={function_for_inserting_data()} > - Add eRSD value sets + Add eRSD value sets (advanced)
  • From 7988bbcfb0e3caa929d24b9192c3e246d8a7af49 Mon Sep 17 00:00:00 2001 From: m-goggins Date: Fri, 8 Nov 2024 08:51:44 -0800 Subject: [PATCH 07/16] uppercase --- query-connector/src/app/query/components/header/header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query-connector/src/app/query/components/header/header.tsx b/query-connector/src/app/query/components/header/header.tsx index 9fee40565..d0d1c557a 100644 --- a/query-connector/src/app/query/components/header/header.tsx +++ b/query-connector/src/app/query/components/header/header.tsx @@ -150,7 +150,7 @@ export default function HeaderComponent() { className={styles.menuItem} // onClick={function_for_inserting_data()} > - Add eRSD value sets (advanced) + Add eRSD value sets (Advanced)
  • From 8f9dae07a160ff6af7e29dfcb6ad5b9c803a83af Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:52:30 +0000 Subject: [PATCH 08/16] [pre-commit.ci] auto fixes from pre-commit hooks --- query-connector/src/app/query/components/header/header.tsx | 6 +++--- .../app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/query-connector/src/app/query/components/header/header.tsx b/query-connector/src/app/query/components/header/header.tsx index d0d1c557a..0c17a16e8 100644 --- a/query-connector/src/app/query/components/header/header.tsx +++ b/query-connector/src/app/query/components/header/header.tsx @@ -57,7 +57,7 @@ export default function HeaderComponent() {
    @@ -77,7 +77,7 @@ export default function HeaderComponent() { className={classNames( "margin-left-auto", "display-flex", - "flex-align-center" + "flex-align-center", )} > {path != "/signin" && isClient && ( @@ -106,7 +106,7 @@ export default function HeaderComponent() { styles.menuButton, "usa-accordion__button", "usa-nav__link", - "usa-current" + "usa-current", )} aria-expanded="false" aria-controls="dropdown-menu" diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index 394a67aa9..a664f5cc1 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -18,7 +18,7 @@ export const EmptyQueriesDisplay: React.FC = () => { "display-flex", "flex-align-center", "flex-justify-center", - styles.emptyStateQueryContainer + styles.emptyStateQueryContainer, )} >
    From 0deac75aa385677c726cccac2904bf9014319165 Mon Sep 17 00:00:00 2001 From: m-goggins Date: Fri, 8 Nov 2024 08:57:55 -0800 Subject: [PATCH 09/16] bump width --- .../src/app/query/components/header/header.module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query-connector/src/app/query/components/header/header.module.scss b/query-connector/src/app/query/components/header/header.module.scss index 9441580cf..5c93a0bea 100644 --- a/query-connector/src/app/query/components/header/header.module.scss +++ b/query-connector/src/app/query/components/header/header.module.scss @@ -47,7 +47,7 @@ padding: 0.5rem !important; background: #ffffff !important; margin: 3.5rem 2rem 0rem 0rem !important; - width: 10rem !important; + width: 19rem !important; box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.16); } From 0d06b870ffcde79c3b3b4ff1aae3591e9edc258f Mon Sep 17 00:00:00 2001 From: m-goggins Date: Fri, 8 Nov 2024 10:53:51 -0800 Subject: [PATCH 10/16] export createDibbsDB --- query-connector/src/db-creation.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/query-connector/src/db-creation.ts b/query-connector/src/db-creation.ts index 6e573d801..dd0c9b580 100644 --- a/query-connector/src/db-creation.ts +++ b/query-connector/src/db-creation.ts @@ -40,7 +40,7 @@ async function getOidsFromErsd() { console.log("Fetching and parsing eRSD."); const ersd = await getERSD(); const valuesets = (ersd as unknown as Bundle)["entry"]?.filter( - (e) => e.resource?.resourceType === "ValueSet", + (e) => e.resource?.resourceType === "ValueSet" ); // Build up a mapping of OIDs to eRSD clinical types @@ -65,7 +65,7 @@ async function getOidsFromErsd() { // Make sure to take out the umbrella value sets from the ones we try to insert let oids = valuesets?.map((vs) => vs.resource?.id); oids = oids?.filter( - (oid) => !Object.keys(ersdToDibbsConceptMap).includes(oid || ""), + (oid) => !Object.keys(ersdToDibbsConceptMap).includes(oid || "") ); return { oids: oids, oidToErsdType: oidToErsdType } as OidData; } catch (error) { @@ -93,14 +93,14 @@ async function fetchBatchValueSetsFromVsac(oidData: OidData, batchSize = 100) { console.log( "Attempting fetches and inserts for", oidData.oids.length, - "value sets.", + "value sets." ); while (startIdx < oidData.oids.length) { console.log("Batching IDs", startIdx, "to", lastIdx); const oidsToFetch = oidData.oids.slice( startIdx, - Math.min(lastIdx, oidData.oids.length), + Math.min(lastIdx, oidData.oids.length) ); let valueSetPromises = await Promise.all( @@ -109,24 +109,24 @@ async function fetchBatchValueSetsFromVsac(oidData: OidData, batchSize = 100) { try { const vs = await getVSACValueSet(oid); const eRSDType: ErsdConceptType = oidData.oidToErsdType.get( - oid, + oid ) as ErsdConceptType; const internalValueSet = await translateVSACToInternalValueSet( vs as unknown as ValueSet, - eRSDType, + eRSDType ); return internalValueSet; } catch (error) { console.error(error); } - }), + }) ); // Next, in case we hit a value set that has a `retired` status and // a deprecated concept listing, we'll need to filter for only those // with defined Concepts valueSetPromises = valueSetPromises.filter( - (vsp) => vsp?.concepts !== undefined, + (vsp) => vsp?.concepts !== undefined ); // Then, we'll insert it into our database instance @@ -135,7 +135,7 @@ async function fetchBatchValueSetsFromVsac(oidData: OidData, batchSize = 100) { if (vs) { await insertValueSet(vs); } - }), + }) ); // // Finally, we verify that the insert was performed correctly @@ -152,7 +152,7 @@ async function fetchBatchValueSetsFromVsac(oidData: OidData, batchSize = 100) { ) { console.log( "Resolving missing values or errors for valueset", - vs.valueSetId, + vs.valueSetId ); await insertValueSet(vs); missingData = await checkValueSetInsertion(vs); @@ -175,7 +175,7 @@ async function fetchBatchValueSetsFromVsac(oidData: OidData, batchSize = 100) { * Overall orchestration function that performs the scripted process of querying * the eRSD, extracting OIDs, then inserting valuesets into the DB. */ -async function createDibbsDB() { +export async function createDibbsDB() { const ersdOidData = await getOidsFromErsd(); if (ersdOidData) { await fetchBatchValueSetsFromVsac(ersdOidData); From e7f2c4bc019132de9c19e9eca18e92a4293ce43c Mon Sep 17 00:00:00 2001 From: m-goggins Date: Fri, 8 Nov 2024 10:54:07 -0800 Subject: [PATCH 11/16] add loading page + state while inserting data --- query-connector/src/app/database-service.ts | 42 ++++++++-------- .../components/header/header.module.scss | 2 +- .../app/query/components/header/header.tsx | 14 ++---- .../emptyState/EmptyQueriesDisplay.tsx | 29 +++++++++-- .../loadingState/WorkspaceSetUp.tsx | 50 +++++++++++++++++++ 5 files changed, 102 insertions(+), 35 deletions(-) create mode 100644 query-connector/src/app/queryBuilding/loadingState/WorkspaceSetUp.tsx diff --git a/query-connector/src/app/database-service.ts b/query-connector/src/app/database-service.ts index ce2c677eb..8f8e348ee 100644 --- a/query-connector/src/app/database-service.ts +++ b/query-connector/src/app/database-service.ts @@ -125,9 +125,10 @@ type ErsdOrVsacResponse = Bundle | OperationOutcome; * @returns The eRSD Specification as a FHIR Bundle or an OperationOutcome if an error occurs. */ export async function getERSD( - eRSDVersion: number = 3, + eRSDVersion: number = 3 ): Promise { const ERSD_API_KEY = process.env.ERSD_API_KEY; + console.log("ERSD_API_KEY: ", ERSD_API_KEY); const eRSDUrl = `https://ersd.aimsplatform.org/api/ersd/v${eRSDVersion}specification?format=json&api-key=${ERSD_API_KEY}`; const response = await fetch(eRSDUrl); if (response.status === 200) { @@ -156,8 +157,9 @@ export async function getERSD( * @returns The value sets as a FHIR bundle, or an Operation Outcome if there is an error. */ export async function getVSACValueSet( - oid: string, + oid: string ): Promise { + console.log("UMLS_API_KEY: ", process.env.UMLS_API_KEY); const username: string = "apikey"; const umlsKey: string = process.env.UMLS_API_KEY || ""; const vsacUrl: string = `https://cts.nlm.nih.gov/fhir/ValueSet/${oid}`; @@ -196,7 +198,7 @@ export async function getVSACValueSet( */ export async function translateVSACToInternalValueSet( fhirValueset: FhirValueSet, - ersdConceptType: ErsdConceptType, + ersdConceptType: ErsdConceptType ) { const oid = fhirValueset.id; const version = fhirValueset.version; @@ -237,7 +239,7 @@ export async function insertValueSet(vs: ValueSet) { await insertValueSetPromise; } catch (e) { console.error( - `ValueSet insertion for ${vs.valueSetId}_${vs.valueSetVersion} failed`, + `ValueSet insertion for ${vs.valueSetId}_${vs.valueSetVersion} failed` ); console.error(e); errorArray.push("Error occured in valuset insertion"); @@ -245,11 +247,11 @@ export async function insertValueSet(vs: ValueSet) { const insertConceptsPromiseArray = generateConceptSqlPromises(vs); const conceptInsertResults = await Promise.allSettled( - insertConceptsPromiseArray, + insertConceptsPromiseArray ); const allConceptInsertsSucceed = conceptInsertResults.every( - (r) => r.status === "fulfilled", + (r) => r.status === "fulfilled" ); if (!allConceptInsertsSucceed) { @@ -261,13 +263,13 @@ export async function insertValueSet(vs: ValueSet) { const joinInsertResults = await Promise.allSettled(joinInsertsPromiseArray); const allJoinInsertsSucceed = joinInsertResults.every( - (r) => r.status === "fulfilled", + (r) => r.status === "fulfilled" ); if (!allJoinInsertsSucceed) { logRejectedPromiseReasons( joinInsertResults, - "ValueSet <> concept join insert failed", + "ValueSet <> concept join insert failed" ); errorArray.push("Error occured in ValueSet <> concept join seeding"); } @@ -398,7 +400,7 @@ function stripProtocolAndTLDFromSystemUrl(systemURL: string) { function logRejectedPromiseReasons( resultsArray: PromiseSettledResult[], - errorMessageString: string, + errorMessageString: string ) { return resultsArray .filter((r): r is PromiseRejectedResult => r.status === "rejected") @@ -425,7 +427,7 @@ export async function insertQuery(input: QueryInput) { queryId = results.rows[0].id as unknown as UUID; } catch (e) { console.error( - `Error occured in user query insertion: insertion for ${input.queryName} failed`, + `Error occured in user query insertion: insertion for ${input.queryName} failed` ); console.error(e); errorArray.push("Error occured in user query insertion"); @@ -435,7 +437,7 @@ export async function insertQuery(input: QueryInput) { const insertJoinSqlArray = generateQueryToValueSetInsertionSql( input, - queryId as UUID, + queryId as UUID ); const joinPromises = insertJoinSqlArray.map((q) => { @@ -445,7 +447,7 @@ export async function insertQuery(input: QueryInput) { const joinInsertResults = await Promise.allSettled(joinPromises); const joinInsertsSucceeded = joinInsertResults.every( - (r) => r.status === "fulfilled", + (r) => r.status === "fulfilled" ); if (!joinInsertsSucceeded) { @@ -487,7 +489,7 @@ export async function checkValueSetInsertion(vs: ValueSet) { foundVS.author !== vs.author ) { console.error( - "Retrieved value set information differs from given value set", + "Retrieved value set information differs from given value set" ); missingData.missingValueSet = true; } @@ -515,18 +517,18 @@ export async function checkValueSetInsertion(vs: ValueSet) { console.error( "Retrieved concept " + conceptId + - " has different values than given concept", + " has different values than given concept" ); return conceptId; } } catch (error) { console.error( "Couldn't fetch concept with ID " + conceptId + ": ", - error, + error ); return conceptId; } - }), + }) ); missingData.missingConcepts = brokenConcepts.filter((bc) => bc !== undefined); @@ -543,18 +545,18 @@ export async function checkValueSetInsertion(vs: ValueSet) { const fIdx = rows.findIndex((r) => r["concept_id"] === conceptUniqueId); if (fIdx === -1) { console.error( - "Couldn't locate concept " + conceptUniqueId + " in fetched mappings", + "Couldn't locate concept " + conceptUniqueId + " in fetched mappings" ); return conceptUniqueId; } }); missingData.missingMappings = missingConceptsFromMappings.filter( - (item) => item !== undefined, + (item) => item !== undefined ); } catch (error) { console.error( "Couldn't fetch value set to concept mappings for this valueset: ", - error, + error ); const systemPrefix = stripProtocolAndTLDFromSystemUrl(vs.system); vs.concepts.forEach((c) => { @@ -592,7 +594,7 @@ export async function getConditionsData() { acc[category].push({ [id]: name }); return acc; }, - {} as CategoryToConditionArrayMap, + {} as CategoryToConditionArrayMap ); // 2. ID-Name mapping diff --git a/query-connector/src/app/query/components/header/header.module.scss b/query-connector/src/app/query/components/header/header.module.scss index 5c93a0bea..9441580cf 100644 --- a/query-connector/src/app/query/components/header/header.module.scss +++ b/query-connector/src/app/query/components/header/header.module.scss @@ -47,7 +47,7 @@ padding: 0.5rem !important; background: #ffffff !important; margin: 3.5rem 2rem 0rem 0rem !important; - width: 19rem !important; + width: 10rem !important; box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.16); } diff --git a/query-connector/src/app/query/components/header/header.tsx b/query-connector/src/app/query/components/header/header.tsx index 0c17a16e8..12e01d923 100644 --- a/query-connector/src/app/query/components/header/header.tsx +++ b/query-connector/src/app/query/components/header/header.tsx @@ -57,7 +57,7 @@ export default function HeaderComponent() {
    @@ -77,7 +77,7 @@ export default function HeaderComponent() { className={classNames( "margin-left-auto", "display-flex", - "flex-align-center", + "flex-align-center" )} > {path != "/signin" && isClient && ( @@ -106,7 +106,7 @@ export default function HeaderComponent() { styles.menuButton, "usa-accordion__button", "usa-nav__link", - "usa-current", + "usa-current" )} aria-expanded="false" aria-controls="dropdown-menu" @@ -145,14 +145,6 @@ export default function HeaderComponent() {
  • )} -
  • - - Add eRSD value sets (Advanced) - -
  • Log out diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index a664f5cc1..9e2104d97 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -1,14 +1,37 @@ import { Button, Icon } from "@trussworks/react-uswds"; +import { useEffect, useState } from "react"; import styles from "../queryBuilding.module.scss"; import { useRouter } from "next/navigation"; import classNames from "classnames"; - +import WorkSpaceSetUpView from "../loadingState/WorkspaceSetUp"; +import { createDibbsDB } from "../../../db-creation"; /** * Empty-state component for query building * @returns the EmptyQueriesDisplay to render the empty state status */ export const EmptyQueriesDisplay: React.FC = () => { const router = useRouter(); + const [loading, setLoading] = useState(false); + + const handleClick = async () => { + setLoading(true); + + // DB Creation Function + console.log("Creating DB..."); + + await new Promise((r) => setTimeout(r, 5000)); //remove once DB creation is implemented + await createDibbsDB(); + + // Stop loading and redirect once function is complete + setLoading(false); + + // Redirect to query building page + // router.push("/queryBuilding/buildFromTemplates"); + }; + + if (loading) { + return ; + } return ( <> @@ -18,7 +41,7 @@ export const EmptyQueriesDisplay: React.FC = () => { "display-flex", "flex-align-center", "flex-justify-center", - styles.emptyStateQueryContainer, + styles.emptyStateQueryContainer )} >
    @@ -31,7 +54,7 @@ export const EmptyQueriesDisplay: React.FC = () => {
    -
    +
  • From db1eafdeca1a12e4406146a984cd59413dafc8ae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 19:14:38 +0000 Subject: [PATCH 16/16] [pre-commit.ci] auto fixes from pre-commit hooks --- .../src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx index 1b9c9b65c..4f1278963 100644 --- a/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx +++ b/query-connector/src/app/queryBuilding/emptyState/EmptyQueriesDisplay.tsx @@ -40,7 +40,7 @@ export const EmptyQueriesDisplay: React.FC = () => { "display-flex", "flex-align-center", "flex-justify-center", - styles.emptyStateQueryContainer + styles.emptyStateQueryContainer, )} >