diff --git a/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.html b/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.html index bd5a3d946..af6d7582e 100644 --- a/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.html +++ b/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.html @@ -11,22 +11,31 @@ -
- - {{index === 0? 'To': 'From'}} - +
+ + {{ index === 0 ? "To" : "From" }} + - {{cys.subunitIndex}}_{{cys.residueIndex}} + {{ cys.subunitIndex }}_{{ cys.residueIndex }} - - {{site.subunitIndex}}_{{site.residueIndex}} + + {{ site.subunitIndex }}_{{ site.residueIndex }} - -
+
+
- - + diff --git a/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.ts b/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.ts index dbff377f7..ed21aac16 100644 --- a/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.ts +++ b/src/app/core/substance-form/disulfide-links/disulfide-links-form.component.ts @@ -1,34 +1,39 @@ -import {AfterViewInit, Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; -import {Link, Site} from '@gsrs-core/substance'; -import { SubstanceFormDisulfideLinksService } from './substance-form-disulfide-links.service'; -import {UtilsService} from '@gsrs-core/utils'; -import {ControlledVocabularyService} from '@gsrs-core/controlled-vocabulary'; -import {MatDialog} from '@angular/material/dialog'; -import {OverlayContainer} from '@angular/cdk/overlay'; -import {Subscription} from 'rxjs'; -import {SubstanceFormService} from '@gsrs-core/substance-form/substance-form.service'; -import {FormControl, FormGroup, Validators} from '@angular/forms'; -import {SubunitSelectorDialogComponent} from '@gsrs-core/substance-form/subunit-selector-dialog/subunit-selector-dialog.component'; +import { + AfterViewInit, + Component, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, +} from "@angular/core"; +import { Link, Site } from "@gsrs-core/substance"; +import { SubstanceFormDisulfideLinksService } from "./substance-form-disulfide-links.service"; +import { UtilsService } from "@gsrs-core/utils"; +import { ControlledVocabularyService } from "@gsrs-core/controlled-vocabulary"; +import { MatDialog } from "@angular/material/dialog"; +import { OverlayContainer } from "@angular/cdk/overlay"; +import { Subscription } from "rxjs"; +import { SubstanceFormService } from "@gsrs-core/substance-form/substance-form.service"; +import { FormControl, FormGroup, Validators } from "@angular/forms"; +import { SubunitSelectorDialogComponent } from "@gsrs-core/substance-form/subunit-selector-dialog/subunit-selector-dialog.component"; @Component({ - selector: 'app-disulfide-links-form', - templateUrl: './disulfide-links-form.component.html', - styleUrls: ['./disulfide-links-form.component.scss'], - standalone: false + selector: "app-disulfide-links-form", + templateUrl: "./disulfide-links-form.component.html", + styleUrls: ["./disulfide-links-form.component.scss"], + standalone: false, }) -export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDestroy { - +export class DisulfideLinksFormComponent + implements OnInit, AfterViewInit, OnDestroy +{ private privateLink: Link; public cysteine: Array = []; @Output() linkDeleted = new EventEmitter(); deleteTimer: any; testForm = new FormGroup({ - site0: new FormControl('', [ - Validators.required - ]), - site1: new FormControl('', [ - Validators.required - ]), + site0: new FormControl(null, [Validators.required]), + site1: new FormControl(null, [Validators.required]), }); private subscriptions: Array = []; private overlayContainer: HTMLElement; @@ -39,29 +44,32 @@ export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDes private utilsService: UtilsService, private overlayContainerService: OverlayContainer, private substanceFormService: SubstanceFormService, - private substanceFormDisulfideLinksService: SubstanceFormDisulfideLinksService - ) { } + private substanceFormDisulfideLinksService: SubstanceFormDisulfideLinksService, + ) {} ngOnInit() { if (this.privateLink.sites) { - this.testForm.controls['site0'].setValue(this.privateLink.sites[0].toString()); - this.testForm.controls['site1'].setValue(this.privateLink.sites[1].toString()); + this.testForm.controls["site0"].setValue(this.privateLink.sites[0]); + this.testForm.controls["site1"].setValue(this.privateLink.sites[1]); } else { this.privateLink.sites = [{}, {}]; } this.overlayContainer = this.overlayContainerService.getContainerElement(); } - ngAfterViewInit() { - setTimeout(() => { - const cysteineSubscription = this.substanceFormDisulfideLinksService.substanceCysteineSites.subscribe(cysteine => { - this.cysteine = cysteine; - }); - this.subscriptions.push(cysteineSubscription); - }); + ngAfterViewInit() { + setTimeout(() => { + const cysteineSubscription = + this.substanceFormDisulfideLinksService.substanceCysteineSites.subscribe( + (cysteine) => { + this.cysteine = cysteine; + }, + ); + this.subscriptions.push(cysteineSubscription); + }); } ngOnDestroy() { - this.subscriptions.forEach(subscription => { + this.subscriptions.forEach((subscription) => { subscription.unsubscribe(); }); } @@ -76,14 +84,14 @@ export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDes } deleteLink(): void { - if (confirm('Are you sure you want to delete links?')) { - this.privateLink.$$deletedCode = this.utilsService.newUUID(); - // if (!this.privateLink) { + if (confirm("Are you sure you want to delete links?")) { + this.privateLink.$$deletedCode = this.utilsService.newUUID(); + // if (!this.privateLink) { this.deleteTimer = setTimeout(() => { this.linkDeleted.emit(this.link); }, 1000); - // } - this.substanceFormDisulfideLinksService.emitDisulfideLinkUpdate(); + // } + this.substanceFormDisulfideLinksService.emitDisulfideLinkUpdate(); } } @@ -98,8 +106,11 @@ export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDes } updateSuggestions(value: Site, pos: number): void { - this.cysteine = this.cysteine.filter(function(r) { - return (r.residueIndex !== value.residueIndex) || (r.subunitIndex !== value.subunitIndex); + this.cysteine = this.cysteine.filter(function (r) { + return ( + r.residueIndex !== value.residueIndex || + r.subunitIndex !== value.subunitIndex + ); }); if (this.privateLink.sites[pos] !== value) { if (this.privateLink.sites[pos].residueIndex) { @@ -109,7 +120,7 @@ export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDes this.substanceFormDisulfideLinksService.updateCysteine(this.cysteine); } else { } - this.testForm.controls['site' + pos].setValue(value); + this.testForm.controls["site" + pos].setValue(value); } openDialog(): void { @@ -118,28 +129,28 @@ export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDes sentSites = []; } const dialogRef = this.dialog.open(SubunitSelectorDialogComponent, { - data: {'card': 'disulfide', 'link': sentSites}, - width: '1040px', - panelClass: 'subunit-dialog' + data: { card: "disulfide", link: sentSites }, + width: "1040px", + panelClass: "subunit-dialog", }); - this.overlayContainer.style.zIndex = '1002'; + this.overlayContainer.style.zIndex = "1002"; - const dialogSubscription = dialogRef.afterClosed().subscribe(newLinks => { + const dialogSubscription = dialogRef.afterClosed().subscribe((newLinks) => { this.overlayContainer.style.zIndex = null; if (newLinks) { if (newLinks[0] && newLinks[0].subunitIndex) { this.privateLink.sites[0] = newLinks[0]; - this.testForm.controls['site0'].setValue(this.privateLink.sites[0].toString()); + this.testForm.controls["site0"].setValue(this.privateLink.sites[0]); } else { this.privateLink.sites[0] = {}; - this.testForm.controls['site0'].reset(); + this.testForm.controls["site0"].reset(); } if (newLinks[1] && newLinks[1].subunitIndex) { this.privateLink.sites[1] = newLinks[1]; - this.testForm.controls['site1'].setValue(this.privateLink.sites[1].toString()); + this.testForm.controls["site1"].setValue(this.privateLink.sites[1]); } else { this.privateLink.sites[1] = {}; - this.testForm.controls['site1'].reset(); + this.testForm.controls["site1"].reset(); } } this.substanceFormDisulfideLinksService.emitDisulfideLinkUpdate(); @@ -147,4 +158,13 @@ export class DisulfideLinksFormComponent implements OnInit, AfterViewInit, OnDes this.subscriptions.push(dialogSubscription); } + compareSites = (a: Site | null, b: Site | null): boolean => { + if (!a || !b) { + return a === b; + } + + return ( + a.subunitIndex === b.subunitIndex && a.residueIndex === b.residueIndex + ); + }; } diff --git a/src/app/core/substance-form/disulfide-links/substance-form-disulfide-links-card.component.ts b/src/app/core/substance-form/disulfide-links/substance-form-disulfide-links-card.component.ts index 3d4a1b355..77a57d111 100644 --- a/src/app/core/substance-form/disulfide-links/substance-form-disulfide-links-card.component.ts +++ b/src/app/core/substance-form/disulfide-links/substance-form-disulfide-links-card.component.ts @@ -42,22 +42,28 @@ export class SubstanceFormDisulfideLinksCardComponent extends SubstanceCardBaseF } ngAfterViewInit() { - const disulfideLinksSubscription = this.substanceFormDisulfideLinksService.substanceDisulfideLinks.subscribe(disulfideLinks => { - this.disulfideLinks = disulfideLinks; - this.countCysteine(); - }); + // setTimeout defers subscriptions until after the service's unload/init setTimeout callbacks + // have fired. This prevents subscribing to a propertyEmitter that is about to be completed + // and replaced by unloadSubstance(), which would leave the component with a dead subscription. + setTimeout(() => { + const disulfideLinksSubscription = this.substanceFormDisulfideLinksService.substanceDisulfideLinks.subscribe(disulfideLinks => { + this.disulfideLinks = disulfideLinks; + this.countCysteine(); + }); + this.subscriptions.push(disulfideLinksSubscription); - this.subscriptions.push(disulfideLinksSubscription); - const subunitsSubscription = this.substanceFormService.substanceSubunits.subscribe(subunits => { - this.subunits = subunits; - this.countCysteine(); - }); - this.subscriptions.push(subunitsSubscription); - const cysteineSubscription = this.substanceFormDisulfideLinksService.substanceCysteineSites.subscribe(cysteine => { - this.cysteine = cysteine; - this.countCysteine(); + const subunitsSubscription = this.substanceFormService.substanceSubunits.subscribe(subunits => { + this.subunits = subunits; + this.countCysteine(); + }); + this.subscriptions.push(subunitsSubscription); + + const cysteineSubscription = this.substanceFormDisulfideLinksService.substanceCysteineSites.subscribe(cysteine => { + this.cysteine = cysteine; + this.countCysteine(); + }); + this.subscriptions.push(cysteineSubscription); }); - this.subscriptions.push(cysteineSubscription); } ngOnDestroy() { diff --git a/src/app/fda/substance-details/substance-products/substance-products.component.scss b/src/app/fda/substance-details/substance-products/substance-products.component.scss index ad142db50..7bc840da1 100644 --- a/src/app/fda/substance-details/substance-products/substance-products.component.scss +++ b/src/app/fda/substance-details/substance-products/substance-products.component.scss @@ -7,10 +7,16 @@ } .mat-tab-style { + :host ::ng-deep .mat-mdc-tab .mdc-tab__text-label, .mat-tab-labels, .mat-tab-label, .mat-tab-link { - color: var(--regular-blue-color); + color: var(--regular-blue-color); } +} +:host ::ng-deep .mat-mdc-tab-list .mat-mdc-tab, +:host ::ng-deep .mat-tab-list .mat-tab-label { + flex-grow: 0 !important; + flex-shrink: 0 !important; } .bordergray { diff --git a/src/styles/_material-overrides.scss b/src/styles/_material-overrides.scss index 6e549fb88..59a87649b 100644 --- a/src/styles/_material-overrides.scss +++ b/src/styles/_material-overrides.scss @@ -1332,10 +1332,12 @@ button.export-button { 0px 3px 14px 2px rgba(0, 0, 0, 0.12); } -// Override MDC ripple behavior if it interferes with existing styles +// Override MDC ripple behavior if it interferes with existing styles. +// NOTE: .mat-ripple is intentionally excluded — MatRipple directive adds that class +// to its HOST element (e.g. the pagination