From 6549f020d5f82151a16f54fea27c20142e715c97 Mon Sep 17 00:00:00 2001 From: nanders0 Date: Wed, 2 Jun 2021 22:22:21 -0400 Subject: [PATCH 01/15] public changes for _html property --- src/app/core/config/config.json | 2 +- .../core/facets-manager/facet-display.pipe.ts | 17 +++++++++++++++++ .../substance-details.component.html | 2 +- .../substance-form-definition.component.html | 2 +- .../core/substance-form/substance-form.model.ts | 1 + .../substance-form/substance-form.service.ts | 2 ++ .../substance-selector.component.html | 2 +- .../substance-summary-card.component.html | 4 ++-- .../substances-browse.component.html | 2 +- 9 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/app/core/config/config.json b/src/app/core/config/config.json index 6ca055140..c43ee1b41 100644 --- a/src/app/core/config/config.json +++ b/src/app/core/config/config.json @@ -1,5 +1,5 @@ { - "version": "2.6", + "version": "2.7.1", "substanceDetailsCards": [ { "card": "substance-overview", diff --git a/src/app/core/facets-manager/facet-display.pipe.ts b/src/app/core/facets-manager/facet-display.pipe.ts index b22be948c..1193ef667 100644 --- a/src/app/core/facets-manager/facet-display.pipe.ts +++ b/src/app/core/facets-manager/facet-display.pipe.ts @@ -1,9 +1,13 @@ import { Pipe, PipeTransform } from '@angular/core'; +import { ConfigService } from '@gsrs-core/config'; @Pipe({ name: 'facetDisplay' }) export class FacetDisplayPipe implements PipeTransform { + constructor(public configService: ConfigService) { + + } transform(name: any, args?: any): any { if (args) { @@ -27,6 +31,18 @@ export class FacetDisplayPipe implements PipeTransform { } } } + if(this.configService && this.configService.configData.facetDisplay) { + let returned = name; + this.configService.configData.facetDisplay.forEach(facet => { + if (name === facet.value) { + returned = facet.display; + return facet.display; + } + }); + if (returned !== name) { + return returned; + } + } if (name.toLowerCase() === 'substancestereochemistry') { return 'Stereochemistry'; } @@ -51,6 +67,7 @@ export class FacetDisplayPipe implements PipeTransform { if (name === 'GInAS Tag') { return 'Source Tag'; } + return name.trim(); } diff --git a/src/app/core/substance-details/substance-details.component.html b/src/app/core/substance-details/substance-details.component.html index f719655c8..17b3f18c1 100644 --- a/src/app/core/substance-details/substance-details.component.html +++ b/src/app/core/substance-details/substance-details.component.html @@ -17,7 +17,7 @@
-

{{substance._name}}

+

{{substance.approvalID}}
diff --git a/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html b/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html index d63d83a9e..2703f4631 100644 --- a/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html +++ b/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html @@ -6,7 +6,7 @@ {{definition.approvalID}}
-
Preferred Term: {{definition._name}}
+
Preferred Term:
diff --git a/src/app/core/substance-form/substance-form.model.ts b/src/app/core/substance-form/substance-form.model.ts index 766ae8fa0..a7d9f0fd2 100644 --- a/src/app/core/substance-form/substance-form.model.ts +++ b/src/app/core/substance-form/substance-form.model.ts @@ -15,6 +15,7 @@ export interface SubstanceFormDefinition { status?: string; approvalID?: string; _name?: string; + _name_html?: string; relationships?: Array; tags?: Array; } diff --git a/src/app/core/substance-form/substance-form.service.ts b/src/app/core/substance-form/substance-form.service.ts index 93dd4ef24..bb19c687c 100644 --- a/src/app/core/substance-form/substance-form.service.ts +++ b/src/app/core/substance-form/substance-form.service.ts @@ -491,6 +491,8 @@ export class SubstanceFormService implements OnDestroy { lastEdited: this.privateSubstance.lastEdited, lastEditedBy: this.privateSubstance.lastEditedBy, _name: this.privateSubstance._name, + _name_html: this.privateSubstance._name_html, + tags: this.privateSubstance.tags }; if (this.privateSubstance.status) { diff --git a/src/app/core/substance-selector/substance-selector.component.html b/src/app/core/substance-selector/substance-selector.component.html index 9148f57e8..9f79e3c9d 100644 --- a/src/app/core/substance-selector/substance-selector.component.html +++ b/src/app/core/substance-selector/substance-selector.component.html @@ -22,7 +22,7 @@
{{header}}
- {{selectedSubstance._name}} +
NOT IN DATABASE
diff --git a/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html b/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html index 67436de7f..6c4384c85 100644 --- a/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html +++ b/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html @@ -1,7 +1,7 @@ - - {{substance._name}} + + diff --git a/src/app/core/substances-browse/substances-browse.component.html b/src/app/core/substances-browse/substances-browse.component.html index 56e8e6f7e..1868c9a48 100644 --- a/src/app/core/substances-browse/substances-browse.component.html +++ b/src/app/core/substances-browse/substances-browse.component.html @@ -199,7 +199,7 @@ Name {{substance._name}} + [routerLink]="['/substances', substance.uuid]" [innerHTML] = "substance._name_html"> From 620871a680690248ab2e0a3e939acc3e8fcbadb7 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Fri, 16 Jul 2021 06:00:38 -0700 Subject: [PATCH 02/15] =?UTF-8?q?[PFDA-2527]=20precisionFDA=20toolbar=20-?= =?UTF-8?q?=20New=20config.json=20options:=20=20=20-=20customToolbarCompon?= =?UTF-8?q?ent:=20Only=20recognises=20=E2=80=98precisionFDA=E2=80=99=20for?= =?UTF-8?q?=20now=20=20=20-=20pfdaBaseUrl:=20base=20URL=20for=20the=20pfda?= =?UTF-8?q?=20site=20-=20Added=20config.pfda.json=20as=20the=20base=20conf?= =?UTF-8?q?ig=20for=20a=20precisionFDA=20deployment=20-=20Added=20PfdaTool?= =?UTF-8?q?barComponent=20which=20is=20used=20instead=20of=20the=20=20element=20in=20BaseComponent=20if=20the=20config=20set?= =?UTF-8?q?ting=20customToolbarComponent=20is=20=E2=80=98precisionFDA?= =?UTF-8?q?=E2=80=99=20-=20Added=20pFDA=20icons=20and=20images?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/core/app.component.ts | 17 + src/app/core/app.module.ts | 2 + .../assets/icons/pfda/gsrs-logo-round-bw.svg | 20 + src/app/core/assets/icons/pfda/home.svg | 13 + src/app/core/assets/icons/pfda/profile.svg | 10 + .../core/assets/icons/pfda/questionmark.svg | 11 + src/app/core/assets/icons/pfda/support.svg | 14 + src/app/core/assets/images/pfda/pfda-logo.png | Bin 0 -> 12080 bytes src/app/core/base/base.component.html | 5 +- src/app/core/base/base.component.ts | 2 + .../pfda-toolbar/pfda-toolbar.component.html | 83 +++ .../pfda-toolbar/pfda-toolbar.component.scss | 88 +++ .../pfda-toolbar.component.spec.ts | 25 + .../pfda-toolbar/pfda-toolbar.component.ts | 51 ++ src/app/core/config/config.model.ts | 2 + src/app/core/config/config.pfda.json | 536 ++++++++++++++++++ 16 files changed, 878 insertions(+), 1 deletion(-) create mode 100644 src/app/core/assets/icons/pfda/gsrs-logo-round-bw.svg create mode 100644 src/app/core/assets/icons/pfda/home.svg create mode 100644 src/app/core/assets/icons/pfda/profile.svg create mode 100644 src/app/core/assets/icons/pfda/questionmark.svg create mode 100644 src/app/core/assets/icons/pfda/support.svg create mode 100644 src/app/core/assets/images/pfda/pfda-logo.png create mode 100644 src/app/core/base/pfda-toolbar/pfda-toolbar.component.html create mode 100644 src/app/core/base/pfda-toolbar/pfda-toolbar.component.scss create mode 100644 src/app/core/base/pfda-toolbar/pfda-toolbar.component.spec.ts create mode 100644 src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts create mode 100644 src/app/core/config/config.pfda.json diff --git a/src/app/core/app.component.ts b/src/app/core/app.component.ts index 42a8159d5..b8e3f964a 100644 --- a/src/app/core/app.component.ts +++ b/src/app/core/app.component.ts @@ -181,6 +181,23 @@ export class AppComponent { iconRegistry.addSvgIcon( 'alarm-on', sanitizer.bypassSecurityTrustResourceUrl('assets/icons/baseline-alarm_on-24px.svg')); + + // precisionFDA Icons + iconRegistry.addSvgIcon( + 'pfda_home', + sanitizer.bypassSecurityTrustResourceUrl('assets/icons/pfda/home.svg')); + iconRegistry.addSvgIcon( + 'pfda_gsrs', + sanitizer.bypassSecurityTrustResourceUrl('assets/icons/pfda/gsrs-logo-round-bw.svg')); + iconRegistry.addSvgIcon( + 'pfda_support', + sanitizer.bypassSecurityTrustResourceUrl('assets/icons/pfda/support.svg')); + iconRegistry.addSvgIcon( + 'pfda_questionmark', + sanitizer.bypassSecurityTrustResourceUrl('assets/icons/pfda/questionmark.svg')); + iconRegistry.addSvgIcon( + 'pfda_profile', + sanitizer.bypassSecurityTrustResourceUrl('assets/icons/pfda/profile.svg')); } } diff --git a/src/app/core/app.module.ts b/src/app/core/app.module.ts index 52a9fe476..8c6864754 100644 --- a/src/app/core/app.module.ts +++ b/src/app/core/app.module.ts @@ -34,6 +34,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { BaseComponent } from './base/base.component'; +import { PfdaToolbarComponent } from './base/pfda-toolbar/pfda-toolbar.component'; import { HomeComponent } from './home/home.component'; import { SubstancesBrowseComponent } from './substances-browse/substances-browse.component'; import { configServiceFactory } from './config/config.factory'; @@ -86,6 +87,7 @@ import { GlobalErrorHandler } from '@gsrs-core/error-handler/error-handler'; AppComponent, PageNotFoundComponent, BaseComponent, + PfdaToolbarComponent, HomeComponent, SubstancesBrowseComponent, StructureSearchComponent, diff --git a/src/app/core/assets/icons/pfda/gsrs-logo-round-bw.svg b/src/app/core/assets/icons/pfda/gsrs-logo-round-bw.svg new file mode 100644 index 000000000..d33ecd415 --- /dev/null +++ b/src/app/core/assets/icons/pfda/gsrs-logo-round-bw.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/core/assets/icons/pfda/home.svg b/src/app/core/assets/icons/pfda/home.svg new file mode 100644 index 000000000..991b35a92 --- /dev/null +++ b/src/app/core/assets/icons/pfda/home.svg @@ -0,0 +1,13 @@ + diff --git a/src/app/core/assets/icons/pfda/profile.svg b/src/app/core/assets/icons/pfda/profile.svg new file mode 100644 index 000000000..3b6727689 --- /dev/null +++ b/src/app/core/assets/icons/pfda/profile.svg @@ -0,0 +1,10 @@ + + + diff --git a/src/app/core/assets/icons/pfda/questionmark.svg b/src/app/core/assets/icons/pfda/questionmark.svg new file mode 100644 index 000000000..52dafbde8 --- /dev/null +++ b/src/app/core/assets/icons/pfda/questionmark.svg @@ -0,0 +1,11 @@ + diff --git a/src/app/core/assets/icons/pfda/support.svg b/src/app/core/assets/icons/pfda/support.svg new file mode 100644 index 000000000..05368ee92 --- /dev/null +++ b/src/app/core/assets/icons/pfda/support.svg @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/src/app/core/assets/images/pfda/pfda-logo.png b/src/app/core/assets/images/pfda/pfda-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..980274504b091cd264c9b7c5951241a57ae5b7d7 GIT binary patch literal 12080 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 ec(_sWOP*F0pw0_w&$Yj0?0Q4>WB(V%sUfid literal 0 HcmV?d00001 diff --git a/src/app/core/base/base.component.html b/src/app/core/base/base.component.html index 8d719595d..0e98540d7 100644 --- a/src/app/core/base/base.component.html +++ b/src/app/core/base/base.component.html @@ -1,4 +1,4 @@ - + +
+ +
\ No newline at end of file diff --git a/src/app/core/base/base.component.ts b/src/app/core/base/base.component.ts index f8b7a361e..4c150354b 100644 --- a/src/app/core/base/base.component.ts +++ b/src/app/core/base/base.component.ts @@ -46,6 +46,7 @@ export class BaseComponent implements OnInit, OnDestroy { appId: string; clasicBaseHref: string; navItems: Array; + customToolbarComponent: string = ''; constructor( private router: Router, @@ -64,6 +65,7 @@ export class BaseComponent implements OnInit, OnDestroy { this.contactEmail = this.configService.configData.contactEmail; this.clasicBaseHref = this.configService.environment.clasicBaseHref; this.navItems = this.configService.configData.navItems; + this.customToolbarComponent = this.configService.configData.customToolbarComponent; } ngOnInit() { diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html new file mode 100644 index 000000000..d9dd4fc36 --- /dev/null +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html @@ -0,0 +1,83 @@ + +
+ +
+ + +
+ + +
Back Home
+
+
+ +
+ + +
+ +
GSRS
+
+
+ + + + +
+ +
Support
+
+
+ + +
+ +
Getting Started
+
+
+ + +
diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.scss b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.scss new file mode 100644 index 000000000..8a863ed32 --- /dev/null +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.scss @@ -0,0 +1,88 @@ +$pfda-padding-main: 32px; +$pfda-navbar-height: 64px; +$pfda-navbar-blue: #343E4D; +$pfda-navbar-active-blue: #2f5373; +$pfda-navbar-item-hover: #a0c2e0; +$pfda-navbar-spacer-colour: #5f768a; + +$screenSmall: 850px; +$screenMedium: 1045px; + + +.pfda-toolbar { + background-color: $pfda-navbar-blue; + color: white; + font-family: "Lato","Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 13px; + font-weight: 400; + line-height: 16px; + padding: 0 8px; + height: auto; + + a { + color: inherit; + text-decoration: none; + } + + @media(min-width: $screenSmall) { + padding: 0 $pfda-padding-main; + height: $pfda-navbar-height; + } +} + +.pfda-toolbar-inner { + display: flex; + align-items: center; +} + +.pfda-logo img { + width: 144px; + margin-top: 4px; +} + +.pfda-toolbar-button { + display: flex; + flex-flow: column nowrap; + align-self: flex-end; + align-items: center; + justify-content: center; + padding: 10px 6px; + + &:hover { + color: $pfda-navbar-item-hover; + } + + &.active { + color: white; + background-color: $pfda-navbar-active-blue; + } + + &-icon, .mat-icon { + display: flex; + align-items: flex-end; + height: 18px; + margin: 3px 0px 2px 0px; + } + + &-title { + display: none; + margin-top: 4px; + + @media(min-width: $screenSmall) { + display: inline; + } + } +} + +.pfda-toolbar-spacer { + border-right: 1px solid $pfda-navbar-spacer-colour; + width: 1px; + height: 38px; + margin: 0px 4px; +} + +.pfda-user-button { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.spec.ts b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.spec.ts new file mode 100644 index 000000000..59dc19d1f --- /dev/null +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { PfdaToolbarComponent } from './pfda-toolbar.component'; + +describe('PfdaToolbarComponent', () => { + let component: PfdaToolbarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ PfdaToolbarComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PfdaToolbarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts new file mode 100644 index 000000000..3fa3e97d9 --- /dev/null +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts @@ -0,0 +1,51 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { ConfigService } from '../../config/config.service'; +import { OverlayContainer } from '@angular/cdk/overlay'; +import { AuthService } from '../../auth/auth.service'; +import { Auth } from '../../auth/auth.model'; +import { Subscription } from 'rxjs'; + +@Component({ + selector: 'app-pfda-toolbar', + templateUrl: './pfda-toolbar.component.html', + styleUrls: ['./pfda-toolbar.component.scss'] +}) +export class PfdaToolbarComponent implements OnInit { + pfdaBaseUrl: string; + logoSrcPath: string; + homeIconPath: string; + auth?: Auth; + private overlayContainer: HTMLElement; + private subscriptions: Array = []; + + constructor( + private router: Router, + private configService: ConfigService, + private overlayContainerService: OverlayContainer, + public authService: AuthService, + ) { + const authSubscription = this.authService.getAuth().subscribe(auth => { + this.auth = auth; + }); + this.subscriptions.push(authSubscription); + } + + ngOnInit() { + this.pfdaBaseUrl = this.configService.configData.pfdaBaseUrl || '/'; + + const baseHref = this.configService.environment.baseHref || '/' + this.logoSrcPath = `${baseHref}assets/images/pfda/pfda-logo.png`; + this.homeIconPath = `${baseHref}assets/images/pfda/home.svg`; + + this.overlayContainer = this.overlayContainerService.getContainerElement(); + } + + increaseMenuZindex(): void { + this.overlayContainer.style.zIndex = '1001'; + } + + removeZindex(): void { + this.overlayContainer.style.zIndex = null; + } +} diff --git a/src/app/core/config/config.model.ts b/src/app/core/config/config.model.ts index 3aad993c4..82928bb78 100644 --- a/src/app/core/config/config.model.ts +++ b/src/app/core/config/config.model.ts @@ -24,6 +24,8 @@ export interface Config { adverseEventShinyAdverseEventURL?: string; facetDisplay?: Array; relationshipsVisualizationUri?: string; + customToolbarComponent?: string; + pfdaBaseUrl?: string; } export interface SubstanceDetailsCard { diff --git a/src/app/core/config/config.pfda.json b/src/app/core/config/config.pfda.json new file mode 100644 index 000000000..2a8af9c77 --- /dev/null +++ b/src/app/core/config/config.pfda.json @@ -0,0 +1,536 @@ +{ + "version": "2.7.1", + "substanceDetailsCards": [ + { + "card": "substance-overview", + "title": "overview" + }, + { + "card": "substance-primary-definition", + "title": "primary definition", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "definitionType", + "value": "ALTERNATIVE" + } + ] + }, + { + "card": "substance-alternative-definition", + "type": "SUBSTANCE->SUB_ALTERNATE", + "title": "variant concepts", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": "SUBSTANCE->SUB_ALTERNATE" + } + ] + }, + { + "card": "structure-details", + "title": "structure", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "chemical|polymer" + }, + { + "filterName": "exists", + "propertyToCheck": "structure" + } + ] + }, + { + "card": "substance-names", + "title": "names", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "names" + } + ] + }, + { + "card": "substance-codes", + "type": "classification", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "codes" + }, + { + "filterName": "substanceCodes", + "value": "classification" + } + ] + }, + { + "card": "substance-codes", + "type": "identifiers", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "codes" + }, + { + "filterName": "substanceCodes", + "value": "identifiers" + } + ] + }, + { + "card": "substance-subunits", + "title": "subunits", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "protein" + }, + { + "filterName": "exists", + "propertyToCheck": "protein.subunits" + } + ] + }, + { + "card": "substance-subunits", + "title": "subunits", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "nucleicAcid" + }, + { + "filterName": "exists", + "propertyToCheck": "nucleicAcid.subunits" + } + ] + }, + { + "card": "substance-glycosylation", + "title": "glycosylation", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "protein" + }, + { + "filterName": "anyExists", + "propertyToCheck": "protein.glycosylation.glycosylationType|protein.glycosylation.CGlycosylationSites|protein.glycosylation.NGlycosylationSites|protein.glycosylation.OGlycosylationSites" + } + ] + }, + { + "card": "substance-disulfide-links", + "title": "disulfide links", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "protein" + }, + { + "filterName": "exists", + "propertyToCheck": "protein.disulfideLinks" + } + ] + }, + { + "card": "substance-other-links", + "title": "other links", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "protein" + }, + { + "filterName": "exists", + "propertyToCheck": "protein.otherLinks" + } + ] + }, + { + "card": "substance-relationships", + "type": "IMPURITY", + "title": "impurities", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": "IMPURITY" + } + ] + }, + { + "card": "substance-relationships", + "type": "METABOLITE", + "title": "metabolites", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": "METABOLITE" + } + ] + }, + { + "card": "substance-relationships", + "type": "ACTIVE MOIETY", + "title": "active moiety", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": "ACTIVE MOIETY" + } + ] + }, + { + "card": "substance-relationships", + "type": "CONSTITUENT", + "title": "constituents", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": "CONSTITUENT" + } + ] + }, + { + "card": "substance-relationships", + "type": "SUB_CONCEPT->SUBSTANCE", + "title": "variant concepts", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": "SUB_CONCEPT->SUBSTANCE" + } + ] + }, + { + "card": "substance-relationships", + "type": "RELATIONSHIPS", + "title": "relationships", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "relationships" + }, + { + "filterName": "substanceRelationships", + "value": [ + "METABOLITE", + "IMPURITY", + "ACTIVE MOIETY", + "CONSTITUENT", + "SUB_CONCEPT->SUBSTANCE" + ] + } + ] + }, + { + "card": "substance-notes", + "title": "notes", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "notes" + } + ] + }, + { + "card": "substance-audit-info", + "title": "audit info" + }, + { + "card": "substance-references", + "title": "references", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "references" + } + ] + }, + { + "card": "substance-moieties", + "title": "moieties", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "chemical" + }, + { + "filterName": "exists", + "propertyToCheck": "moieties" + } + ] + }, + { + "card": "substance-concept-definition", + "title": "concept definition", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "concept" + } + ] + }, + { + "card": "substance-polymer-structure", + "title": "display structure", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "polymer" + } + ] + }, + { + "card": "substance-monomers", + "title": "monomers", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "polymer" + }, + { + "filterName": "exists", + "propertyToCheck": "polymer.monomers" + } + ] + }, + { + "card": "substance-structural-units", + "title": "Structural Units", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "polymer" + }, + { + "filterName": "exists", + "propertyToCheck": "polymer.structuralUnits" + } + ] + }, + { + "card": "substance-mixture-components", + "title": "mixture components", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "mixture" + }, + { + "filterName": "exists", + "propertyToCheck": "mixture.components" + } + ] + }, + { + "card": "substance-constituents", + "title": "specified substance constituents", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "specifiedSubstanceG1" + }, + { + "filterName": "exists", + "propertyToCheck": "specifiedSubstance.constituents" + } + ] + }, + { + "card": "substance-mixture-source", + "title": "mixture source", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "mixture" + }, + { + "filterName": "exists", + "propertyToCheck": "mixture.parentSubstance" + } + ] + }, + { + "card": "substance-modifications", + "title": "substance modifications", + "filters": [ + { + "filterName": "anyExists", + "propertyToCheck": "modifications.structuralModifications|modifications.physicalModifications|modifications.agentModifications" + } + ] + }, + { + "card": "substance-na-sugars", + "title": "sugars", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "nucleicAcid" + }, + { + "filterName": "exists", + "propertyToCheck": "nucleicAcid.sugars" + } + ] + }, + { + "card": "substance-na-linkages", + "title": "linkages", + "filters": [ + { + "filterName": "equals", + "propertyToCheck": "substanceClass", + "value": "nucleicAcid" + }, + { + "filterName": "exists", + "propertyToCheck": "nucleicAcid.linkages" + } + ] + }, + { + "card": "substance-properties", + "title": "characteristic attributes", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "properties" + } + ] + }, + { + "card": "substance-history", + "title": "history", + "filters": [ + { + "filterName": "hasCredentials", + "propertyToCheck": "admin" + } + ] + }, + { + "card": "substance-ssg-definition", + "title": "definition", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "specifiedSubstanceG3.definition" + } + ] + }, + { + "card": "substance-ssg-parent-substance", + "title": "parent substance", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "specifiedSubstanceG3.parentSubstance" + } + ] + }, + { + "card": "substance-ssg-grade", + "title": "grade", + "filters": [ + { + "filterName": "exists", + "propertyToCheck": "specifiedSubstanceG3.grade" + } + ] + } + ], + "facets": { + "substances": { + "default": [ + "Deprecated", + "Record Status", + "Substance Class", + "GInAS Tag", + "Code System", + "ATC Level 1", + "ATC Level 2", + "ATC Level 3", + "ATC Level 4", + "DME Reactions", + "Moiety Type", + "Molecular Weight", + "SubstanceStereochemistry", + "Relationships", + "Record Level Access", + "Display Name Level Access", + "Definition Level Access", + "Protein Type", + "Protein Subtype", + "modified" + ], + "admin": [ + "Record Created By", + "root_lastEdited", + "root_lastEditedBy", + "root_approved", + "Approved By", + "Material Type", + "Family", + "Parts" + ] + } + }, + "codeSystemOrder": [ + "BDNUM", + "CAS", + "WHO-ATC", + "EVMPD", + "NCI" + ], + "substanceSelectorProperties": [ + "root_names_name", + "root_approvalID", + "root_codes_BDNUM", + "root_codes_CAS", + "root_codes_ECHA\\ \\(EC\/EINECS\\)" + ], + "customToolbarComponent": "precisionFDA" +} \ No newline at end of file From 1f9d8623e7defbf6163cb700def3c8586e7820db Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Tue, 3 Aug 2021 11:55:14 -0700 Subject: [PATCH 03/15] [PFDA-2600] Disable Google Analytics via config.pfda.json - Also added contactEmail --- src/app/core/config/config.pfda.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/core/config/config.pfda.json b/src/app/core/config/config.pfda.json index 2a8af9c77..661c73b6e 100644 --- a/src/app/core/config/config.pfda.json +++ b/src/app/core/config/config.pfda.json @@ -532,5 +532,7 @@ "root_codes_CAS", "root_codes_ECHA\\ \\(EC\/EINECS\\)" ], + "contactEmail": "precisionfda-support@dnanexus.com", + "googleAnalyticsId": "", "customToolbarComponent": "precisionFDA" } \ No newline at end of file From 8aa02105dacd9d59750d14be3d4aae7af8d886c7 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Wed, 11 Aug 2021 06:02:48 -0700 Subject: [PATCH 04/15] [PFDA-2560] Session expiration warning dialog to warn users of pending expiration, allowing users to extend a session or upon expiration a button redirecting the user to the login page. - To enable this feature, add the following to config.json: "sessionExpirationWarning": { "extendSessionApiUrl": "/api/update_active", "maxSessionDurationMinutes": 30 }, - The endpoint at extendSessionApiUrl should respond to a GET request and return 200 if session is updated successfully - Note that the /login path may be outside of the Angular app (e.g. in the case of precisionFDA) --- src/app/core/auth/auth.module.ts | 8 ++ .../session-expiration-dialog.component.html | 11 ++ .../session-expiration-dialog.component.scss | 0 ...ession-expiration-dialog.component.spec.ts | 25 ++++ .../session-expiration-dialog.component.ts | 79 +++++++++++ .../session-expiration.component.html | 0 .../session-expiration.component.spec.ts | 25 ++++ .../session-expiration.component.ts | 130 ++++++++++++++++++ src/app/core/base/base.component.html | 1 + src/app/core/base/base.component.ts | 1 + src/app/core/config/config.model.ts | 6 + src/app/core/config/config.pfda.json | 4 + 12 files changed, 290 insertions(+) create mode 100644 src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.html create mode 100644 src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.scss create mode 100644 src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.spec.ts create mode 100644 src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts create mode 100644 src/app/core/auth/session-expiration/session-expiration.component.html create mode 100644 src/app/core/auth/session-expiration/session-expiration.component.spec.ts create mode 100644 src/app/core/auth/session-expiration/session-expiration.component.ts diff --git a/src/app/core/auth/auth.module.ts b/src/app/core/auth/auth.module.ts index 364614e00..0675167ca 100644 --- a/src/app/core/auth/auth.module.ts +++ b/src/app/core/auth/auth.module.ts @@ -15,6 +15,8 @@ import { RouterModule } from '@angular/router'; import { DecodeUriPipe } from '@gsrs-core/auth/user-downloads/download-monitor/decodeURI.pipe'; import { FileSizePipe } from '@gsrs-core/auth/user-downloads/download-monitor/fileSize.pipe'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { SessionExpirationComponent } from './session-expiration/session-expiration.component'; +import { SessionExpirationDialogComponent } from './session-expiration/session-expiration-dialog/session-expiration-dialog.component'; @NgModule({ imports: [ @@ -37,13 +39,19 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; UserProfileComponent, UserDownloadsComponent, DownloadMonitorComponent, + SessionExpirationComponent, + SessionExpirationDialogComponent, DecodeUriPipe, FileSizePipe ], + entryComponents: [ + SessionExpirationDialogComponent + ], exports: [ LoginComponent, UserProfileComponent, DownloadMonitorComponent, + SessionExpirationComponent, UserDownloadsComponent ] }) diff --git a/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.html b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.html new file mode 100644 index 000000000..c35a6869c --- /dev/null +++ b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.html @@ -0,0 +1,11 @@ +

+ {{dialogTitle}} +

+
+ {{dialogMessage}} +
+
+ + + +
diff --git a/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.scss b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.spec.ts b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.spec.ts new file mode 100644 index 000000000..b3156517c --- /dev/null +++ b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SessionExpirationDialogComponent } from './session-expiration-dialog.component'; + +describe('SessionExpirationDialogComponent', () => { + let component: SessionExpirationDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SessionExpirationDialogComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SessionExpirationDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts new file mode 100644 index 000000000..8063a6630 --- /dev/null +++ b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts @@ -0,0 +1,79 @@ +import { Component, OnInit, Inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { HttpClient } from '@angular/common/http'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { ConfigService, SessionExpirationWarning } from '@gsrs-core/config'; + +@Component({ + selector: 'app-session-expiration-dialog', + templateUrl: './session-expiration-dialog.component.html', + styleUrls: ['./session-expiration-dialog.component.scss'] +}) +export class SessionExpirationDialogComponent implements OnInit { + sessionExpirationWarning: SessionExpirationWarning = null; + sessionExpiringAt: number; + timeRemainingSeconds: number; + dialogTitle: string; + dialogMessage: string; + private updateDialogInterval: number; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + // N.B. injected services has to come after data + private router: Router, + private http: HttpClient + ) { + this.sessionExpirationWarning = data.sessionExpirationWarning; + this.sessionExpiringAt = data.sessionExpiringAt; + } + + ngOnInit() { + // If SessionExpirationWarning is not found in configData, the intervals are never set + // and this component is inert + this.updateDialogInterval = setInterval(() => { this.updateDialog(); }); + } + + ngOnDestroy() { + clearInterval(this.updateDialogInterval); + } + + getCurrentTime() { + return Math.floor((new Date()).getTime() / 1000); + } + + updateDialog() { + const currentTime = this.getCurrentTime() + this.timeRemainingSeconds = this.sessionExpiringAt - currentTime; + + if (this.timeRemainingSeconds > 0) { + const remainingMinutes = Math.floor(this.timeRemainingSeconds / 60); + const reminaingSeconds = String(this.timeRemainingSeconds % 60).padStart(2, '0'); + this.dialogTitle = "Session Ending Soon" + this.dialogMessage = `You will be logged out in ${remainingMinutes}:${reminaingSeconds}` + } + else { + this.dialogTitle = "Session Ended" + this.dialogMessage = "Your session has expired, please login again." + } + } + + closeDialog() { + this.dialogRef.close(false); + } + + extendSession() { + const url = this.sessionExpirationWarning.extendSessionApiUrl; + this.http.get(url).subscribe( + data => { + this.dialogRef.close(true); + }, + err => { console.log("Error extending session: ", err) }, + () => { } + ); + } + + login() { + window.location.assign('/login'); + } +} diff --git a/src/app/core/auth/session-expiration/session-expiration.component.html b/src/app/core/auth/session-expiration/session-expiration.component.html new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/core/auth/session-expiration/session-expiration.component.spec.ts b/src/app/core/auth/session-expiration/session-expiration.component.spec.ts new file mode 100644 index 000000000..ae9bf0c23 --- /dev/null +++ b/src/app/core/auth/session-expiration/session-expiration.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SessionExpirationComponent } from './session-expiration.component'; + +describe('SessionExpirationComponent', () => { + let component: SessionExpirationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SessionExpirationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SessionExpirationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/core/auth/session-expiration/session-expiration.component.ts b/src/app/core/auth/session-expiration/session-expiration.component.ts new file mode 100644 index 000000000..58c199f3b --- /dev/null +++ b/src/app/core/auth/session-expiration/session-expiration.component.ts @@ -0,0 +1,130 @@ +import { Router, Event as NavigationEvent, NavigationStart } from '@angular/router'; +import { Component, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material'; +import { OverlayContainer } from '@angular/cdk/overlay'; +import { HttpClient } from '@angular/common/http'; +import { ConfigService, SessionExpirationWarning } from '@gsrs-core/config'; +import { AuthService } from '../auth.service'; +import { SessionExpirationDialogComponent } from './session-expiration-dialog/session-expiration-dialog.component' +import { Subscription } from 'rxjs'; + +@Component({ + selector: 'app-session-expiration', + templateUrl: './session-expiration.component.html' +}) +export class SessionExpirationComponent implements OnInit { + sessionExpirationWarning: SessionExpirationWarning = null; + sessionExpiringAt: number; + private overlayContainer: HTMLElement; + private subscriptions: Array = []; + private expirationTimer: any; + + constructor( + private router: Router, + private configService: ConfigService, + private authService: AuthService, + private http: HttpClient, + private dialog: MatDialog, + private overlayContainerService: OverlayContainer + ) { + this.sessionExpirationWarning = configService.configData.sessionExpirationWarning; + this.overlayContainer = this.overlayContainerService.getContainerElement(); + } + + ngOnInit() { + // If SessionExpirationWarning is not found in configData, the intervals are never set + // and this component is inert + const authSubscription = this.authService.getAuth().subscribe(auth => { + if (this.sessionExpirationWarning) { + if (auth) { + this.resetExpirationTimer(); + } + else { + // User has logged out while timeout is active + this.clearExpirationTimer(); + } + } + }); + this.subscriptions.push(authSubscription); + + // This component seems to be destroyed and recreated on route change, so maybe + // the following isn't necessary: + // const routerSubscription = this.router.events.subscribe((event: NavigationEvent) => { + // if (event instanceof NavigationStart && this.expirationTimer) { + // this.extendSession(); + // } + // }); + // this.subscriptions.push(routerSubscription); + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => { + subscription.unsubscribe(); + }); + this.clearExpirationTimer(); + } + + getCurrentTime() { + return Math.floor((new Date()).getTime() / 1000); + } + + clearExpirationTimer() { + if (this.expirationTimer) { + clearTimeout(this.expirationTimer); + this.expirationTimer = null; + } + } + + resetExpirationTimer() { + this.clearExpirationTimer(); + + const currentTime = this.getCurrentTime() + this.sessionExpiringAt = currentTime + this.sessionExpirationWarning.maxSessionDurationMinutes * 60; + + const timeRemainingSeconds = this.sessionExpiringAt - currentTime; + const timeBeforeDisplayingDialogMs = (timeRemainingSeconds - 61) * 1000; + if (timeBeforeDisplayingDialogMs > 0) { + this.expirationTimer = setTimeout( () => { + this.openDialog(); + }, timeBeforeDisplayingDialogMs); + } + else { + this.login(); + } + } + + openDialog() { + const dialogRef = this.dialog.open(SessionExpirationDialogComponent, { + data: { + 'sessionExpirationWarning': this.sessionExpirationWarning, + 'sessionExpiringAt': this.sessionExpiringAt + }, + width: '650px', + autoFocus: false, + disableClose: true + }); + this.overlayContainer.style.zIndex = '1501'; + const dialogSubscription = dialogRef.afterClosed().subscribe(response => { + this.overlayContainer.style.zIndex = null; + if (response) { + // Session was extended + this.resetExpirationTimer(); + } + }); + } + + extendSession() { + const url = this.sessionExpirationWarning.extendSessionApiUrl; + this.http.get(url).subscribe( + data => { + this.resetExpirationTimer(); + }, + err => { console.log("Error extending session: ", err) }, + () => { } + ); + } + + login() { + window.location.assign('/login'); + } +} diff --git a/src/app/core/base/base.component.html b/src/app/core/base/base.component.html index 0e98540d7..387904ffc 100644 --- a/src/app/core/base/base.component.html +++ b/src/app/core/base/base.component.html @@ -109,5 +109,6 @@
+ \ No newline at end of file diff --git a/src/app/core/base/base.component.ts b/src/app/core/base/base.component.ts index 4c150354b..3b603ff72 100644 --- a/src/app/core/base/base.component.ts +++ b/src/app/core/base/base.component.ts @@ -3,6 +3,7 @@ import { Router, RouterEvent, NavigationEnd, NavigationExtras, ActivatedRoute, N import { Environment } from '../../../environments/environment.model'; import { AuthService } from '../auth/auth.service'; import { Auth } from '../auth/auth.model'; +import { SessionExpirationComponent } from '../auth/session-expiration/session-expiration.component' import { ConfigService } from '../config/config.service'; import { OverlayContainer } from '@angular/cdk/overlay'; import { LoadingService } from '../loading/loading.service'; diff --git a/src/app/core/config/config.model.ts b/src/app/core/config/config.model.ts index 82928bb78..b276cd991 100644 --- a/src/app/core/config/config.model.ts +++ b/src/app/core/config/config.model.ts @@ -25,6 +25,7 @@ export interface Config { facetDisplay?: Array; relationshipsVisualizationUri?: string; customToolbarComponent?: string; + sessionExpirationWarning?: SessionExpirationWarning; pfdaBaseUrl?: string; } @@ -51,3 +52,8 @@ export interface NavItem { order?: number; children?: Array; } + +export interface SessionExpirationWarning { + maxSessionDurationMinutes: number; + extendSessionApiUrl: string; +} diff --git a/src/app/core/config/config.pfda.json b/src/app/core/config/config.pfda.json index 661c73b6e..1e9e7297f 100644 --- a/src/app/core/config/config.pfda.json +++ b/src/app/core/config/config.pfda.json @@ -533,6 +533,10 @@ "root_codes_ECHA\\ \\(EC\/EINECS\\)" ], "contactEmail": "precisionfda-support@dnanexus.com", + "sessionExpirationWarning": { + "extendSessionApiUrl": "/api/update_active", + "maxSessionDurationMinutes": 30 + }, "googleAnalyticsId": "", "customToolbarComponent": "precisionFDA" } \ No newline at end of file From bb77d39ae9a03ab9a88e369e996a049a4ccd006c Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Tue, 17 Aug 2021 00:34:32 -0700 Subject: [PATCH 05/15] [PFDA-2564] Substance submission UI improvements - For pFDA a button takes the user to the file uploaded to his/her user space. This required a fileUrl attribute inserted into the SubstanceDetail payload - For GSRS in general the dialog message is now a little more descriptive --- .../submit-success-dialog.component.html | 8 +++++-- .../submit-success-dialog.component.ts | 21 +++++++++++++++++-- .../substance-form.component.ts | 16 ++++++++++---- .../substance-form/substance-form.model.ts | 1 + .../substance-form/substance-form.service.ts | 6 ++++++ src/app/core/substance/substance.model.ts | 1 + 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html index aabd188b0..cba1ef8e6 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html @@ -2,10 +2,14 @@

Success

- Update was performed. + {{dialogMessage}}
-
+
+
+
+ +
\ No newline at end of file diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts index b71c1ef2c..336ca8b13 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts @@ -7,16 +7,33 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; styleUrls: ['./submit-success-dialog.component.scss'] }) export class SubmitSuccessDialogComponent implements OnInit { + dialogMessage: string = "Update was performed."; + fileUrl: string = null; constructor( public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any - ) { } + ) { + switch (data.type) { + case 'submit': + this.dialogMessage = 'Substance was submitted successfully'; + break; + case 'approve': + this.dialogMessage = 'Substance was approved successfully'; + break; + } + + // If data.fileUrl is not null, this is assumed to be GSRS running within the precisionFDA + // whereby we display a button that reveals the substance file uploaded onto the pFDA environment + if (data.fileUrl) { + this.fileUrl = data.fileUrl; + } + } ngOnInit() { } - dismissDialog(action: 'continue'|'browse'|'view'): void { + dismissDialog(action: 'continue'|'browse'|'view'|'viewInPfda'): void { this.dialogRef.close(action); } diff --git a/src/app/core/substance-form/substance-form.component.ts b/src/app/core/substance-form/substance-form.component.ts index 2e249197d..bf2509ff2 100644 --- a/src/app/core/substance-form/substance-form.component.ts +++ b/src/app/core/substance-form/substance-form.component.ts @@ -569,7 +569,7 @@ export class SubstanceFormComponent implements OnInit, AfterViewInit, OnDestroy this.loadingService.setLoading(false); this.isLoading = false; this.validationMessages = null; - this.openSuccessDialog('approve'); + this.openSuccessDialog({ type: 'approve' }); this.submissionMessage = 'Substance was approved successfully'; this.showSubmissionMessages = true; this.validationResult = false; @@ -601,7 +601,7 @@ export class SubstanceFormComponent implements OnInit, AfterViewInit, OnDestroy if (!this.id) { this.id = response.uuid; } - this.openSuccessDialog(); + this.openSuccessDialog({ type: 'submit', fileUrl: response.fileUrl }); }, (error: SubstanceFormResults) => { this.showSubmissionMessages = true; this.loadingService.setLoading(false); @@ -798,8 +798,13 @@ export class SubstanceFormComponent implements OnInit, AfterViewInit, OnDestroy return old; } - openSuccessDialog(type?: string): void { - const dialogRef = this.dialog.open(SubmitSuccessDialogComponent, {}); + openSuccessDialog({ type, fileUrl }: { type?: 'submit'|'approve', fileUrl?: string }): void { + const dialogRef = this.dialog.open(SubmitSuccessDialogComponent, { + data: { + type: type, + fileUrl: fileUrl + } + }); this.overlayContainer.style.zIndex = '1002'; const dialogSubscription = dialogRef.afterClosed().pipe(take(1)).subscribe((response?: 'continue' | 'browse' | 'view') => { @@ -811,6 +816,9 @@ export class SubstanceFormComponent implements OnInit, AfterViewInit, OnDestroy this.router.navigate(['/browse-substance']); } else if (response === 'view') { this.router.navigate(['/substances', this.id]); + } else if (response === 'viewInPfda') { + // View the submitted substance file in the user's precisionFDA home + window.location.assign(fileUrl); } else { this.submissionMessage = 'Substance was saved successfully!'; if (type && type === 'approve') { diff --git a/src/app/core/substance-form/substance-form.model.ts b/src/app/core/substance-form/substance-form.model.ts index a7d9f0fd2..e2b2e984d 100644 --- a/src/app/core/substance-form/substance-form.model.ts +++ b/src/app/core/substance-form/substance-form.model.ts @@ -26,6 +26,7 @@ export interface SubstanceFormResults { valid?: boolean; validationMessages?: Array; serverError?: any; + fileUrl?: string; // For precisionFDA } export interface ValidationResults { diff --git a/src/app/core/substance-form/substance-form.service.ts b/src/app/core/substance-form/substance-form.service.ts index bb19c687c..82a3ff0a5 100644 --- a/src/app/core/substance-form/substance-form.service.ts +++ b/src/app/core/substance-form/substance-form.service.ts @@ -1385,6 +1385,12 @@ this.emitDisulfideLinkUpdate(); } else if (this.privateSubstance.substanceClass === 'mixture') { this.substanceSubunitsEmitter.next(this.privateSubstance.mixture.components); } + + // For precisionFDA + if (substance.fileUrl) { + results.fileUrl = substance.fileUrl; + } + this.substanceChangeReasonEmitter.next(this.privateSubstance.changeReason); this.substanceService.getSubstanceDetails(results.uuid).subscribe(resp => { this.privateSubstance = resp; diff --git a/src/app/core/substance/substance.model.ts b/src/app/core/substance/substance.model.ts index 8eba54e63..4e75027c1 100644 --- a/src/app/core/substance/substance.model.ts +++ b/src/app/core/substance/substance.model.ts @@ -63,6 +63,7 @@ export interface SubstanceDetail extends SubstanceBase, SubstanceBaseExtended { specifiedSubstance?: SpecifiedSubstance; specifiedSubstanceG3?: SpecifiedSubstanceG3; _matchContext?: MatchContext; + fileUrl?: string; // For precisionFDA } export interface StructurallyDiverse extends SubstanceBase { From b8b9d6165005afa85d950dd061efe8608e517f81 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Tue, 17 Aug 2021 09:49:52 -0700 Subject: [PATCH 06/15] [PFDA-2615] Disable the Upload Document button for a reference when "disableReferenceDocumentUpload" is true in config.json --- src/app/core/config/config.model.ts | 1 + src/app/core/config/config.pfda.json | 1 + .../substance-form/references/reference-form.component.html | 2 +- .../substance-form/references/reference-form.component.ts | 5 ++++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app/core/config/config.model.ts b/src/app/core/config/config.model.ts index b276cd991..53b5479b6 100644 --- a/src/app/core/config/config.model.ts +++ b/src/app/core/config/config.model.ts @@ -26,6 +26,7 @@ export interface Config { relationshipsVisualizationUri?: string; customToolbarComponent?: string; sessionExpirationWarning?: SessionExpirationWarning; + disableReferenceDocumentUpload?: boolean; pfdaBaseUrl?: string; } diff --git a/src/app/core/config/config.pfda.json b/src/app/core/config/config.pfda.json index 1e9e7297f..412f83bc1 100644 --- a/src/app/core/config/config.pfda.json +++ b/src/app/core/config/config.pfda.json @@ -537,6 +537,7 @@ "extendSessionApiUrl": "/api/update_active", "maxSessionDurationMinutes": 30 }, + "disableReferenceDocumentUpload": true, "googleAnalyticsId": "", "customToolbarComponent": "precisionFDA" } \ No newline at end of file diff --git a/src/app/core/substance-form/references/reference-form.component.html b/src/app/core/substance-form/references/reference-form.component.html index e4d0eb084..f5c02ff93 100644 --- a/src/app/core/substance-form/references/reference-form.component.html +++ b/src/app/core/substance-form/references/reference-form.component.html @@ -40,7 +40,7 @@
-
+
+ +
diff --git a/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.scss b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.scss new file mode 100644 index 000000000..af8ab23c1 --- /dev/null +++ b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.scss @@ -0,0 +1,16 @@ +.dialog-title { + margin-top: 12px; +} + +.dialog-actions { + margin-top: 12px; + + button { + margin-left: 12px; + } +} + +.dialog-checkbox { + font-size: 14px; + margin: 12px; +} diff --git a/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.spec.ts b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.spec.ts new file mode 100644 index 000000000..705322fcd --- /dev/null +++ b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExternalSiteWarningDialogComponent } from './external-site-warning-dialog.component'; + +describe('ExternalSiteWarningDialogComponent', () => { + let component: ExternalSiteWarningDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ExternalSiteWarningDialogComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExternalSiteWarningDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts new file mode 100644 index 000000000..cd513ad17 --- /dev/null +++ b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { ConfigService, ExternalSiteWarning } from '@gsrs-core/config'; + +@Component({ + selector: 'app-external-site-warning-dialog', + templateUrl: './external-site-warning-dialog.component.html', + styleUrls: ['./external-site-warning-dialog.component.scss'] +}) +export class ExternalSiteWarningDialogComponent implements OnInit { + externalSiteWarning: ExternalSiteWarning; + dontAskAgain: boolean; + + constructor( + public dialogRef: MatDialogRef, + private configService: ConfigService + ) { } + + ngOnInit() { + this.externalSiteWarning = this.configService.configData.externalSiteWarning; + this.dontAskAgain = localStorage.getItem('externalSiteWarningDontAskAgain') === 'true'; + } + + acceptDialog() { + localStorage.setItem('externalSiteWarningDontAskAgain', this.dontAskAgain.toString()); + + this.dialogRef.close(true); + } + + cancelDialog() { + this.dialogRef.close(false); + } +} diff --git a/src/app/core/name-resolver/name-resolver.component.ts b/src/app/core/name-resolver/name-resolver.component.ts index 2696ae0f1..485728e98 100644 --- a/src/app/core/name-resolver/name-resolver.component.ts +++ b/src/app/core/name-resolver/name-resolver.component.ts @@ -8,6 +8,11 @@ import { ResolverResponse } from '../structure/structure-post-response.model'; import { SubstanceService } from '../substance/substance.service'; import { StructureService } from '../structure/structure.service'; import {SafeUrl} from '@angular/platform-browser'; +import { ConfigService, ExternalSiteWarning } from '@gsrs-core/config'; +import { THIS_EXPR } from '@angular/compiler/src/output/output_ast'; +import { MatDialog } from '@angular/material'; +import { OverlayContainer } from '@angular/cdk/overlay'; +import { ExternalSiteWarningDialogComponent } from './external-site-warning-dialog/external-site-warning-dialog.component'; @Component({ selector: 'app-name-resolver', @@ -22,14 +27,23 @@ export class NameResolverComponent implements OnInit { matchedNames: PagingResponse; @Output() structureSelected = new EventEmitter(); @Input() startingName?: string; + // External site warning dialog for precisionFDA + externalSiteWarning: ExternalSiteWarning; + private overlayContainer: HTMLElement; constructor( + private configService: ConfigService, private loadingService: LoadingService, private substanceService: SubstanceService, - private structureService: StructureService - ) { } + private structureService: StructureService, + private dialog: MatDialog, + private overlayContainerService: OverlayContainer + ) { } ngOnInit() { + this.externalSiteWarning = this.configService.configData.externalSiteWarning; + this.overlayContainer = this.overlayContainerService.getContainerElement(); + if (this.startingName) { this.resolverControl.setValue(this.startingName); setTimeout( () => { @@ -45,6 +59,15 @@ export class NameResolverComponent implements OnInit { } resolveName(name: string): void { + if (this.shouldShowExternalSiteWarningDialog() === true) { + this.showExternalSiteWarningDialog(); + return; + } + + this.resolveNameInternal(name); + } + + resolveNameInternal(name: string): void { this.errorMessage = ''; this.resolvedNames = []; this.matchedNames = null; @@ -71,4 +94,24 @@ export class NameResolverComponent implements OnInit { this.structureSelected.emit(molfile); } + shouldShowExternalSiteWarningDialog(): boolean { + if (!this.externalSiteWarning || !this.externalSiteWarning.enabled) { + return false; + } + return localStorage.getItem('externalSiteWarningDontAskAgain') != 'true'; + } + + showExternalSiteWarningDialog(): void { + const dialogRef = this.dialog.open(ExternalSiteWarningDialogComponent, { + width: '800px', + autoFocus: false + }); + this.overlayContainer.style.zIndex = '1002'; + const dialogSubscription = dialogRef.afterClosed().subscribe(response => { + this.overlayContainer.style.zIndex = null; + if (response) { + this.resolveNameInternal(this.resolverControl.value); + } + }); + } } diff --git a/src/app/core/name-resolver/name-resolver.module.ts b/src/app/core/name-resolver/name-resolver.module.ts index 7f0cce2a0..458e7372a 100644 --- a/src/app/core/name-resolver/name-resolver.module.ts +++ b/src/app/core/name-resolver/name-resolver.module.ts @@ -4,10 +4,12 @@ import { NameResolverComponent } from './name-resolver.component'; import { ReactiveFormsModule, FormsModule } from '@angular/forms'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; +import { MatCheckboxModule } from '@angular/material'; import { MatIconModule } from '@angular/material/icon'; import { RouterModule } from '@angular/router'; import { LoadingModule } from '../loading/loading.module'; import { NameResolverDialogComponent } from './name-resolver-dialog.component'; +import { ExternalSiteWarningDialogComponent } from './external-site-warning-dialog/external-site-warning-dialog.component'; import { SubstanceImageModule } from '@gsrs-core/substance/substance-image.module'; @NgModule({ @@ -17,6 +19,7 @@ import { SubstanceImageModule } from '@gsrs-core/substance/substance-image.modul FormsModule, MatInputModule, MatButtonModule, + MatCheckboxModule, MatIconModule, RouterModule, LoadingModule, @@ -24,14 +27,16 @@ import { SubstanceImageModule } from '@gsrs-core/substance/substance-image.modul ], declarations: [ NameResolverComponent, - NameResolverDialogComponent + NameResolverDialogComponent, + ExternalSiteWarningDialogComponent ], exports: [ NameResolverComponent, NameResolverDialogComponent ], entryComponents: [ - NameResolverDialogComponent + NameResolverDialogComponent, + ExternalSiteWarningDialogComponent ] }) export class NameResolverModule { } From 19fe6207ca30895434a5ec26e4608f481008c9e8 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Wed, 13 Oct 2021 20:32:50 +0100 Subject: [PATCH 09/15] =?UTF-8?q?[PFDA-2687]=20Refined=20submissions=20suc?= =?UTF-8?q?cess=20dialog=20=20-=20Better=20messaging=20for=20the=20PFDA=20?= =?UTF-8?q?case=20=20-=20Disallow=20closing=20by=20clicking=20outside=20th?= =?UTF-8?q?e=20dialog=20=20-=20Added=20=E2=80=9CGo=20to=20Browse=E2=80=9D?= =?UTF-8?q?=20button=20as=20an=20option=20to=20stay=20within=20the=20GSRS?= =?UTF-8?q?=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../submit-success-dialog.component.html | 3 ++- .../submit-success-dialog/submit-success-dialog.component.ts | 5 +++++ src/app/core/substance-form/substance-form.component.ts | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html index cba1ef8e6..a4a8de821 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html @@ -1,5 +1,5 @@

- Success + {{dialogTitle}}

{{dialogMessage}} @@ -11,5 +11,6 @@

+
\ No newline at end of file diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts index 336ca8b13..a19f93d48 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts @@ -7,6 +7,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; styleUrls: ['./submit-success-dialog.component.scss'] }) export class SubmitSuccessDialogComponent implements OnInit { + dialogTitle: string; dialogMessage: string = "Update was performed."; fileUrl: string = null; @@ -16,9 +17,11 @@ export class SubmitSuccessDialogComponent implements OnInit { ) { switch (data.type) { case 'submit': + this.dialogTitle = 'Submission Success'; this.dialogMessage = 'Substance was submitted successfully'; break; case 'approve': + this.dialogTitle = 'Submission Approved'; this.dialogMessage = 'Substance was approved successfully'; break; } @@ -27,6 +30,8 @@ export class SubmitSuccessDialogComponent implements OnInit { // whereby we display a button that reveals the substance file uploaded onto the pFDA environment if (data.fileUrl) { this.fileUrl = data.fileUrl; + this.dialogTitle = 'Substance Saved'; + this.dialogMessage = 'The substance was saved successfully your pFDA Home'; } } diff --git a/src/app/core/substance-form/substance-form.component.ts b/src/app/core/substance-form/substance-form.component.ts index bf2509ff2..8b7d72e62 100644 --- a/src/app/core/substance-form/substance-form.component.ts +++ b/src/app/core/substance-form/substance-form.component.ts @@ -803,7 +803,8 @@ export class SubstanceFormComponent implements OnInit, AfterViewInit, OnDestroy data: { type: type, fileUrl: fileUrl - } + }, + disableClose: true }); this.overlayContainer.style.zIndex = '1002'; From eb427885c2623ee2dbbf75125fc6212b36d7eadc Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Tue, 19 Oct 2021 09:51:44 +0100 Subject: [PATCH 10/15] [PFDA-2711] Added substance search bar to pFDA toolbar --- .../pfda-toolbar/pfda-toolbar.component.html | 5 +++ .../pfda-toolbar/pfda-toolbar.component.ts | 36 +++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html index d9dd4fc36..3ce0bde53 100644 --- a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html @@ -26,6 +26,11 @@ + + +
diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts index 3fa3e97d9..1bc5a3ab2 100644 --- a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.ts @@ -1,8 +1,9 @@ import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; +import { Router, ActivatedRoute, NavigationExtras } from '@angular/router'; import { ConfigService } from '../../config/config.service'; import { OverlayContainer } from '@angular/cdk/overlay'; import { AuthService } from '../../auth/auth.service'; +import { SubstanceTextSearchService } from '@gsrs-core/substance-text-search/substance-text-search.service'; import { Auth } from '../../auth/auth.model'; import { Subscription } from 'rxjs'; @@ -16,14 +17,17 @@ export class PfdaToolbarComponent implements OnInit { logoSrcPath: string; homeIconPath: string; auth?: Auth; + searchValue: string; private overlayContainer: HTMLElement; private subscriptions: Array = []; constructor( private router: Router, + private activatedRoute: ActivatedRoute, private configService: ConfigService, private overlayContainerService: OverlayContainer, - public authService: AuthService, + private substanceTextSearchService: SubstanceTextSearchService, + public authService: AuthService ) { const authSubscription = this.authService.getAuth().subscribe(auth => { this.auth = auth; @@ -39,6 +43,34 @@ export class PfdaToolbarComponent implements OnInit { this.homeIconPath = `${baseHref}assets/images/pfda/home.svg`; this.overlayContainer = this.overlayContainerService.getContainerElement(); + + if (this.activatedRoute.snapshot.queryParamMap.has('search')) { + this.searchValue = this.activatedRoute.snapshot.queryParamMap.get('search'); + } + + const paramsSubscription = this.activatedRoute.queryParamMap.subscribe(params => { + this.searchValue = params.get('search'); + }); + this.subscriptions.push(paramsSubscription); + + this.substanceTextSearchService.registerSearchComponent('main-substance-search'); + const cleanSearchSubscription = this.substanceTextSearchService.setSearchComponentValueEvent('main-substance-search') + .subscribe(value => { + this.searchValue = value; + }); + this.subscriptions.push(cleanSearchSubscription); + } + + processSubstanceSearch(searchValue: string) { + this.navigateToSearchResults(searchValue); + } + + navigateToSearchResults(searchTerm: string) { + const navigationExtras: NavigationExtras = { + queryParams: searchTerm ? { 'search': searchTerm } : null + }; + + this.router.navigate(['/browse-substance'], navigationExtras); } increaseMenuZindex(): void { From 1e3db165de30729b79d3a9b4cd76e6cba04b53c3 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Tue, 19 Oct 2021 14:39:50 +0200 Subject: [PATCH 11/15] =?UTF-8?q?[PFDA-2671]=20Fixed=20substance=20name=20?= =?UTF-8?q?not=20appearing=20in=20various=20places.=20This=20is=20a=20temp?= =?UTF-8?q?orary=20measure=20and=20should=20be=20reverted=20once=20we=20up?= =?UTF-8?q?grade=20to=203.0,=20short=20explanation=20is=20that=20the=20two?= =?UTF-8?q?=202.7.1=20branches=20used=20for=20frontend=20and=20backend=20w?= =?UTF-8?q?e=20used=20don=E2=80=99t=20actually=20match=20with=20respect=20?= =?UTF-8?q?to=20the=20name=20property=20for=20substances.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/core/substance-details/substance-details.component.html | 2 +- .../substance-form-definition.component.html | 2 +- .../core/substance-selector/substance-selector.component.html | 2 +- .../substance-summary-card.component.html | 2 +- src/app/core/substances-browse/substances-browse.component.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/core/substance-details/substance-details.component.html b/src/app/core/substance-details/substance-details.component.html index 17b3f18c1..04b1e1f86 100644 --- a/src/app/core/substance-details/substance-details.component.html +++ b/src/app/core/substance-details/substance-details.component.html @@ -17,7 +17,7 @@
-

+

{{substance.approvalID}}
diff --git a/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html b/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html index 2703f4631..1959792dc 100644 --- a/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html +++ b/src/app/core/substance-form/substance-form-definition/substance-form-definition.component.html @@ -6,7 +6,7 @@ {{definition.approvalID}}
-
Preferred Term:
+
Preferred Term:
diff --git a/src/app/core/substance-selector/substance-selector.component.html b/src/app/core/substance-selector/substance-selector.component.html index 9f79e3c9d..18963fb54 100644 --- a/src/app/core/substance-selector/substance-selector.component.html +++ b/src/app/core/substance-selector/substance-selector.component.html @@ -22,7 +22,7 @@
{{header}}
- +
NOT IN DATABASE
diff --git a/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html b/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html index 6c4384c85..0d692af2e 100644 --- a/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html +++ b/src/app/core/substances-browse/substance-summary-card/substance-summary-card.component.html @@ -1,7 +1,7 @@
- + diff --git a/src/app/core/substances-browse/substances-browse.component.html b/src/app/core/substances-browse/substances-browse.component.html index 1868c9a48..941fbdc7f 100644 --- a/src/app/core/substances-browse/substances-browse.component.html +++ b/src/app/core/substances-browse/substances-browse.component.html @@ -199,7 +199,7 @@ Name + [routerLink]="['/substances', substance.uuid]" [innerHTML] = "substance._name"> From 64822cd25b61d53f76dbb7d5849ec23b0c8cc432 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Tue, 19 Oct 2021 21:06:07 +0200 Subject: [PATCH 12/15] [PFDA-2728] Update JSDraw license --- src/app/core/assets/jsdraw/Scilligence.JSDraw2.Pro.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core/assets/jsdraw/Scilligence.JSDraw2.Pro.js b/src/app/core/assets/jsdraw/Scilligence.JSDraw2.Pro.js index 84297890d..7c77cf6b6 100644 --- a/src/app/core/assets/jsdraw/Scilligence.JSDraw2.Pro.js +++ b/src/app/core/assets/jsdraw/Scilligence.JSDraw2.Pro.js @@ -25,8 +25,8 @@ JSDraw2.password = { encrypt: true, key: null, iv: null }; // Place the license code below // Licensed to: FDA // Product: JSDraw -// Expiration Date: 2020-Jul-01 -JSDraw2.licensecode='405565434916781761723242424242424131213141512181'; +// Expiration Date: 2022-Jul-30 +JSDraw2.licensecode='405562533916781761723242424242424131213141512181'; From 4fd1b9d3bf4792ff0dcc981ffc37ebc7d2d0e2d3 Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Wed, 20 Oct 2021 18:20:26 +0200 Subject: [PATCH 13/15] [PFDA-2687] Tweak to substance submission success dialog message - Also increased spacing between dialog message and action buttons --- .../submit-success-dialog.component.html | 4 ++-- .../submit-success-dialog.component.scss | 3 +++ .../submit-success-dialog/submit-success-dialog.component.ts | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html index a4a8de821..262c8ac5e 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.html @@ -4,12 +4,12 @@

{{dialogMessage}}
-
+
-
+
diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.scss b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.scss index e69de29bb..6c4b2ba41 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.scss +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.scss @@ -0,0 +1,3 @@ +.dialog-actions { + margin-top: 12px; +} diff --git a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts index a19f93d48..98a1f0faa 100644 --- a/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts +++ b/src/app/core/substance-form/submit-success-dialog/submit-success-dialog.component.ts @@ -31,7 +31,7 @@ export class SubmitSuccessDialogComponent implements OnInit { if (data.fileUrl) { this.fileUrl = data.fileUrl; this.dialogTitle = 'Substance Saved'; - this.dialogMessage = 'The substance was saved successfully your pFDA Home'; + this.dialogMessage = 'The substance was saved successfully as a file in your pFDA My Home area.'; } } From d3f5514857cd342a09bf7d097bcb96c329d69afb Mon Sep 17 00:00:00 2001 From: Zai Chang Date: Thu, 28 Oct 2021 22:15:01 +0200 Subject: [PATCH 14/15] [PFDA-2781] Add User Downloads menu item --- src/app/core/base/pfda-toolbar/pfda-toolbar.component.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html index 3ce0bde53..63df8dd5b 100644 --- a/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html +++ b/src/app/core/base/pfda-toolbar/pfda-toolbar.component.html @@ -66,6 +66,9 @@ + + User Downloads + Manage Licenses From dd52d6e8642d4baa5bd1d21ab3b17b1717fb157b Mon Sep 17 00:00:00 2001 From: NikoAnderson Date: Tue, 19 Dec 2023 12:22:03 -0500 Subject: [PATCH 15/15] compile fixes --- .../session-expiration-dialog.component.ts | 4 ++-- .../auth/session-expiration/session-expiration.component.ts | 3 ++- .../external-site-warning-dialog.component.ts | 2 +- src/app/core/name-resolver/name-resolver.component.ts | 3 +-- src/app/core/name-resolver/name-resolver.module.ts | 2 +- src/app/core/substance-form/substance-form.component.ts | 4 ++-- src/app/core/substance-form/substance-form.service.ts | 2 -- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts index 8063a6630..434d87a4f 100644 --- a/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts +++ b/src/app/core/auth/session-expiration/session-expiration-dialog/session-expiration-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Inject } from '@angular/core'; import { Router } from '@angular/router'; import { HttpClient } from '@angular/common/http'; -import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { ConfigService, SessionExpirationWarning } from '@gsrs-core/config'; @Component({ @@ -15,7 +15,7 @@ export class SessionExpirationDialogComponent implements OnInit { timeRemainingSeconds: number; dialogTitle: string; dialogMessage: string; - private updateDialogInterval: number; + private updateDialogInterval: any; constructor( public dialogRef: MatDialogRef, diff --git a/src/app/core/auth/session-expiration/session-expiration.component.ts b/src/app/core/auth/session-expiration/session-expiration.component.ts index 58c199f3b..75d5d929a 100644 --- a/src/app/core/auth/session-expiration/session-expiration.component.ts +++ b/src/app/core/auth/session-expiration/session-expiration.component.ts @@ -1,6 +1,7 @@ import { Router, Event as NavigationEvent, NavigationStart } from '@angular/router'; import { Component, OnInit } from '@angular/core'; -import { MatDialog } from '@angular/material'; +import { MatDialog} from '@angular/material/dialog'; + import { OverlayContainer } from '@angular/cdk/overlay'; import { HttpClient } from '@angular/common/http'; import { ConfigService, SessionExpirationWarning } from '@gsrs-core/config'; diff --git a/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts index cd513ad17..fcd877e8c 100644 --- a/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts +++ b/src/app/core/name-resolver/external-site-warning-dialog/external-site-warning-dialog.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; +import { MatDialogRef} from '@angular/material/dialog'; import { ConfigService, ExternalSiteWarning } from '@gsrs-core/config'; @Component({ diff --git a/src/app/core/name-resolver/name-resolver.component.ts b/src/app/core/name-resolver/name-resolver.component.ts index 485728e98..41913222e 100644 --- a/src/app/core/name-resolver/name-resolver.component.ts +++ b/src/app/core/name-resolver/name-resolver.component.ts @@ -9,8 +9,7 @@ import { SubstanceService } from '../substance/substance.service'; import { StructureService } from '../structure/structure.service'; import {SafeUrl} from '@angular/platform-browser'; import { ConfigService, ExternalSiteWarning } from '@gsrs-core/config'; -import { THIS_EXPR } from '@angular/compiler/src/output/output_ast'; -import { MatDialog } from '@angular/material'; +import { MatDialog } from '@angular/material/dialog'; import { OverlayContainer } from '@angular/cdk/overlay'; import { ExternalSiteWarningDialogComponent } from './external-site-warning-dialog/external-site-warning-dialog.component'; diff --git a/src/app/core/name-resolver/name-resolver.module.ts b/src/app/core/name-resolver/name-resolver.module.ts index 458e7372a..57cc89b1d 100644 --- a/src/app/core/name-resolver/name-resolver.module.ts +++ b/src/app/core/name-resolver/name-resolver.module.ts @@ -4,7 +4,7 @@ import { NameResolverComponent } from './name-resolver.component'; import { ReactiveFormsModule, FormsModule } from '@angular/forms'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material'; +import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatIconModule } from '@angular/material/icon'; import { RouterModule } from '@angular/router'; import { LoadingModule } from '../loading/loading.module'; diff --git a/src/app/core/substance-form/substance-form.component.ts b/src/app/core/substance-form/substance-form.component.ts index 1acbb90ea..680df4298 100644 --- a/src/app/core/substance-form/substance-form.component.ts +++ b/src/app/core/substance-form/substance-form.component.ts @@ -923,7 +923,7 @@ getDrafts() { if (!this.id) { this.id = response.uuid; } - this.openSuccessDialog('staging'); + this.openSuccessDialog({ type: 'staging' }); }) } @@ -1153,7 +1153,7 @@ getDrafts() { const dialogRef = this.dialog.open(SubmitSuccessDialogComponent, { data: { type: type, - fileUrl: fileUrl + fileUrl: fileUrl ? fileUrl : null }, disableClose: true }); diff --git a/src/app/core/substance-form/substance-form.service.ts b/src/app/core/substance-form/substance-form.service.ts index ee1037077..180639ed2 100644 --- a/src/app/core/substance-form/substance-form.service.ts +++ b/src/app/core/substance-form/substance-form.service.ts @@ -618,8 +618,6 @@ export class SubstanceFormService implements OnDestroy { lastEdited: this.privateSubstance.lastEdited, lastEditedBy: this.privateSubstance.lastEditedBy, _name: this.privateSubstance._name, - _name_html: this.privateSubstance._name_html, - tags: this.privateSubstance.tags }; if (this.privateSubstance.status) {