diff --git a/web/build.gradle b/web/build.gradle index 2b0e6968..656fefe2 100644 --- a/web/build.gradle +++ b/web/build.gradle @@ -77,6 +77,7 @@ dependencies { implementation 'org.springframework:spring-web:6.1.13' // Updated version implementation 'org.springframework:spring-webmvc:6.1.13' // Updated version // fixes netty resolver error for macos + implementation 'io.netty:netty-common:4.1.115.Final' implementation 'io.netty:netty-resolver-dns-native-macos' testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/web/frontend/package-lock.json b/web/frontend/package-lock.json index 9af1b4dd..cd87e9a9 100644 --- a/web/frontend/package-lock.json +++ b/web/frontend/package-lock.json @@ -25,6 +25,7 @@ "braces": "^3.0.3", "chart.js": "^2.9.4", "cookie": "^0.4.1", + "cross-spawn": "^7.0.6", "eventsource": "^1.1.1", "file-saver": "^2.0.5", "follow-redirects": "^1.14.8", @@ -5581,10 +5582,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5598,7 +5598,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6168,9 +6167,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -6178,7 +6177,7 @@ "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -6197,6 +6196,15 @@ "node": ">=10.0.0" } }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -6489,7 +6497,7 @@ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.6", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", @@ -6522,9 +6530,9 @@ "dev": true }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, "dependencies": { "accepts": "~1.3.8", @@ -6532,7 +6540,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -6564,9 +6572,9 @@ } }, "node_modules/express/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, "engines": { "node": ">= 0.6" @@ -6860,7 +6868,7 @@ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -7493,9 +7501,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "dev": true, "dependencies": { "@types/http-proxy": "^1.17.8", @@ -8125,8 +8133,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isobject": { "version": "3.0.1", @@ -11101,7 +11108,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.3", + "version": "7.0.6", "inBundle": true, "license": "MIT", "dependencies": { @@ -11233,7 +11240,7 @@ "inBundle": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -13794,7 +13801,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -15603,7 +15609,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -15615,7 +15620,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -15755,16 +15759,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, diff --git a/web/frontend/package.json b/web/frontend/package.json index cb58f19b..93533793 100644 --- a/web/frontend/package.json +++ b/web/frontend/package.json @@ -30,6 +30,7 @@ "braces": "^3.0.3", "chart.js": "^2.9.4", "cookie": "^0.4.1", + "cross-spawn": "^7.0.6", "eventsource": "^1.1.1", "file-saver": "^2.0.5", "follow-redirects": "^1.14.8", diff --git a/web/frontend/src/app/component/subset-details/subset-details.component.html b/web/frontend/src/app/component/subset-details/subset-details.component.html index b4b1939e..dfb7f6b4 100644 --- a/web/frontend/src/app/component/subset-details/subset-details.component.html +++ b/web/frontend/src/app/component/subset-details/subset-details.component.html @@ -25,7 +25,7 @@

-
+
Subset Download Link: {{ subsetLink }}

diff --git a/web/frontend/src/app/component/subset-details/subset-details.component.ts b/web/frontend/src/app/component/subset-details/subset-details.component.ts index b8612433..b10d6bd7 100644 --- a/web/frontend/src/app/component/subset-details/subset-details.component.ts +++ b/web/frontend/src/app/component/subset-details/subset-details.component.ts @@ -81,8 +81,10 @@ export class SubsetDetailsComponent implements OnInit { this.subsetCodes = {}; this.subsets.unshift(this.selectedSubset); this.subsets.forEach((c) => { - synonymMap.push(this.getSynonymSources(c['synonyms'])); - if (c.inverseAssociations?.find((assoc) => assoc.type == 'Concept_In_Subset')) { + if (c && c['synonyms'].length > 0) { + synonymMap.push(this.getSynonymSources(c['synonyms'])); + } + if (c && c['inverseAssociations'].length > 0 && c['inverseAssociations'].find((assoc) => assoc.type == 'Concept_In_Subset')) { this.subsetCodes[c.code] = 1; } }); @@ -401,16 +403,25 @@ export class SubsetDetailsComponent implements OnInit { getCdiscSubmissionValue(concept: Concept): string { // If a single CDISC/PT, return it const matchingSynonyms = concept.synonyms.filter((sy) => sy.source === 'CDISC' && sy.termType === 'PT'); - if (matchingSynonyms.length==1) { + if (matchingSynonyms.length===1) { return matchingSynonyms[0].name; } - // Otherwise, find the one matching the sumissionValueCode + // Otherwise, find the one matching the submissionValueCode const matchingSynonym = matchingSynonyms.find((sy) => sy.code === this.submissionValueCode); if (matchingSynonym) { return matchingSynonym.name; } // can't figure it out, just return the first again - return matchingSynonyms[0].name; + if(matchingSynonyms.length > 0) + return matchingSynonyms[0].name; + + // if we get all the way here there isn't one + return null; + + } + linkNotInDescription() { + const desc = this.selectedSubset.properties.find((item) => item.type === "Term_Browser_Value_Set_Description"); + return (this.selectedSubset.subsetLink !== undefined && desc !== undefined && !desc.value.includes(this.selectedSubset.subsetLink)); } } diff --git a/web/frontend/src/app/component/welcome/welcome.component.ts b/web/frontend/src/app/component/welcome/welcome.component.ts index bb8b1204..cb508ae7 100644 --- a/web/frontend/src/app/component/welcome/welcome.component.ts +++ b/web/frontend/src/app/component/welcome/welcome.component.ts @@ -18,7 +18,7 @@ export class WelcomeComponent implements OnInit, OnDestroy, AfterViewInit { welcomeText: any = null; boilerPlateWelcomeText: any = 'Loading welcome text for ' + this.configService.getTerminologyName() + ' ...'; allTerminologies: any = null; - selectedMultiTerminologies = new Set(); + selectedMultiTerminologies = new Set(); checkboxStates: { [key: string]: boolean } = {}; // track the state of the checkbox based on terminology private subscription = null; @@ -37,23 +37,27 @@ export class WelcomeComponent implements OnInit, OnDestroy, AfterViewInit { ngOnInit(): void { this.route.queryParams .subscribe(params => { - if (Object.keys(params).length > 0 && params.terminology !== 'multi' && !params.terminology.includes(',')) { - this.setWelcomeText(params.terminology != undefined ? params.terminology : 'ncit'); + if (Object.keys(params).length > 0 && params.terminology !== 'multi' && params.terminology !== undefined && !params.terminology.includes(',')) { + this.setWelcomeText(params.terminology !== undefined ? params.terminology : 'ncit'); this.configService.setMultiSearch(false); } else if (Object.keys(params).length > 0) { - if (params.terminology.includes(',')) { + if (params.terminology !== undefined && params.terminology.includes(',')) { // populating saved terminologies in url params.terminology.split(',').forEach(term => { this.selectedMultiTerminologies.add(term); }); - + this.configService.setMultiSearch(true); + } else if (params.terminology === "multi") { + this.configService.setMultiSearch(true); + } + else { + this.setWelcomeText(params.terminology !== undefined ? params.terminology : 'ncit'); + this.configService.setMultiSearch(false); } - this.configService.setMultiSearch(true); } this.allTerminologies = this.configService.getTerminologies().map((terminology) => { // initialize checkboxStates for each terminology - const normalizedTerm = terminology.metadata.uiLabel.replace(/\:.*/, '').toLowerCase(); - this.checkboxStates[normalizedTerm] = false; + this.checkboxStates[terminology.terminology] = this.selectedMultiTerminologies.has(terminology.terminology); // set the checkbox state based on the selected terminologies return { label: terminology.metadata.uiLabel.replace(/\:.*/, ''),