From aad5d4ee89d1cd2a339f622a625dca24b4c6fb16 Mon Sep 17 00:00:00 2001 From: Newatia Date: Wed, 14 Aug 2024 16:42:55 -0400 Subject: [PATCH 1/2] updated product, application, ivp, impurities --- .../core/assets/data/product_dictionary.json | 8 +- ...tance-form-ssg4m-process-card.component.ts | 6 + .../service/advanced-search.service.ts | 10 +- .../application-form.component.ts | 9 +- .../ingredient-form.component.html | 26 +- .../ingredient-form.component.ts | 158 +- src/app/fda/application/application.module.ts | 5 - src/app/fda/config/config.json | 1 + .../impurities-form.component.ts | 9 +- ...harmacology-assay-data-import.component.ts | 8 +- .../invitro-pharmacology-details.component.ts | 7 +- ...vitro-pharmacology-assay-form.component.ts | 9 +- ...ro-pharmacology-assayset-form.component.ts | 1 - .../invitro-pharmacology-form.component.html | 2 +- .../invitro-pharmacology-form.component.ts | 573 +++- ...tro-pharmacology-summary-form.component.ts | 15 +- ...acology-screening-data-import.component.ts | 12 +- .../invitro-pharmacology.component.ts | 13 - .../json-dialog-fda.component.html | 2 +- .../json-dialog-fda.component.ts | 13 +- src/app/fda/product/model/product.model.ts | 35 +- .../product-details-base.component.ts | 223 +- .../product-details.component.html | 2754 ++++++++++------- .../product-details.component.scss | 206 +- .../product-details.component.ts | 12 +- .../product-elist-details.component.ts | 6 +- .../product-component-form.component.ts | 1 - .../product-form/product-form.component.html | 22 +- .../product-form/product-form.component.ts | 29 +- .../product-ingredient-form.component.ts | 1 - .../product-lot-form.component.ts | 1 - src/app/fda/product/product.module.ts | 1 - .../products-browse.component.html | 236 +- .../products-browse.component.ts | 5 +- .../fda/product/service/product.service.ts | 2 +- src/styles/_styles.scss | 1 + 36 files changed, 2651 insertions(+), 1771 deletions(-) diff --git a/src/app/core/assets/data/product_dictionary.json b/src/app/core/assets/data/product_dictionary.json index 8c189a667..37d178942 100644 --- a/src/app/core/assets/data/product_dictionary.json +++ b/src/app/core/assets/data/product_dictionary.json @@ -1,9 +1,9 @@ { - "Administravail Pharmacedical Dosage Form":{ - "lucenePath":"root_pharmacedicalDosageForm", - "description":"Pharmaceutical Form of the product", + "Administered Pharmaceutical Dosage Form":{ + "lucenePath":"root_pharmaceuticalDosageForm", + "description":"Administered Pharmaceutical Dosage Form of the product", "type":"string", - "cvDomain":"PROD_PHARMACEDICAL_DOSAGE_FORM", + "cvDomain":"DOSAGE_FORM", "priority":null, "suggest":null }, diff --git a/src/app/core/substance-ssg4m/ssg4m-process/substance-form-ssg4m-process-card.component.ts b/src/app/core/substance-ssg4m/ssg4m-process/substance-form-ssg4m-process-card.component.ts index edd3d1d05..e02869c6a 100644 --- a/src/app/core/substance-ssg4m/ssg4m-process/substance-form-ssg4m-process-card.component.ts +++ b/src/app/core/substance-ssg4m/ssg4m-process/substance-form-ssg4m-process-card.component.ts @@ -62,6 +62,12 @@ export class SubstanceFormSsg4mProcessCardComponent extends SubstanceCardBaseFil //TODO: make more configurable and standardized console.log("About to configure the scheme view"); window['schemeUtil'].debug = false; + + window['schemeUtil'].maxContinuousSteps = 1; + window['schemeUtil'].maxTextLen = 19; + window['schemeUtil'].BREAK_GAP = 300; + window['schemeUtil'].maxTitleTextLen = 100; + const url = `${(this.configService.configData && this.configService.configData.apiBaseUrl) || '/'}api/v1/`; const httpp = this.http; window['schemeUtil'].apiBaseURL = url; diff --git a/src/app/fda/advanced-search/service/advanced-search.service.ts b/src/app/fda/advanced-search/service/advanced-search.service.ts index 8643d7fa7..a1983be7d 100644 --- a/src/app/fda/advanced-search/service/advanced-search.service.ts +++ b/src/app/fda/advanced-search/service/advanced-search.service.ts @@ -6,11 +6,9 @@ import { BaseHttpService } from '@gsrs-core/base'; import { PagingResponse } from '@gsrs-core/utils'; import { FacetParam, FacetHttpParams, FacetQueryResponse } from '@gsrs-core/facets-manager'; import { SubstanceDetail, SubstanceName, SubstanceCode } from '@gsrs-core/substance/substance.model'; -import { ProductAll } from '../../product/model/product.model'; -import { ClinicalTrial } from '../../clinical-trials/clinical-trial/clinical-trial.model'; -// import { map, switchMap, tap } from 'rxjs/operators'; -// import { Facet } from '@gsrs-core/facets-manager'; +import { Product } from '../../product/model/product.model' import { Application, ApplicationIngredient } from '../../application/model/application.model'; +import { ClinicalTrial } from '../../clinical-trials/clinical-trial/clinical-trial.model'; @Injectable( { providedIn: 'root' } @@ -119,7 +117,7 @@ export class AdvancedSearchService extends BaseHttpService { pageSize: number = 10, searchTerm?: string, facets?: FacetParam - ): Observable> { + ): Observable> { let params = new FacetHttpParams(); params = params.append('skip', skip.toString()); params = params.append('top', '1'); // setting top=1, faster result, no content @@ -134,7 +132,7 @@ export class AdvancedSearchService extends BaseHttpService { params: params }; - return this.http.get>(url, options); + return this.http.get>(url, options); } getClinicalTrials( diff --git a/src/app/fda/application/application-form/application-form.component.ts b/src/app/fda/application/application-form/application-form.component.ts index 8cff542af..39347dcdc 100644 --- a/src/app/fda/application/application-form/application-form.component.ts +++ b/src/app/fda/application/application-form/application-form.component.ts @@ -11,6 +11,7 @@ import { ControlledVocabularyService } from '../../../core/controlled-vocabulary import { VocabularyTerm } from '../../../core/controlled-vocabulary/vocabulary.model'; import { Application, ValidationMessage } from '../model/application.model'; import { Subscription } from 'rxjs'; +import * as moment from 'moment'; import { Title } from '@angular/platform-browser'; import { take } from 'rxjs/operators'; import { MatDialog } from '@angular/material/dialog'; @@ -455,11 +456,17 @@ export class ApplicationFormComponent implements OnInit, AfterViewInit, OnDestro } showJSON(): void { + const date = new Date(); + let jsonFilename = 'application_' + moment(date).format('MMM-DD-YYYY_H-mm-ss'); + let cleanApplication = this.cleanApplication(); + + let data = {jsonData: cleanApplication, jsonFilename: jsonFilename}; + const dialogRef = this.dialog.open(JsonDialogFdaComponent, { width: '90%', height: '90%', - data: cleanApplication + data: data }); // this.overlayContainer.style.zIndex = '1002'; diff --git a/src/app/fda/application/application-form/ingredient-form/ingredient-form.component.html b/src/app/fda/application/application-form/ingredient-form/ingredient-form.component.html index 00afa7526..9d8e45154 100644 --- a/src/app/fda/application/application-form/ingredient-form/ingredient-form.component.html +++ b/src/app/fda/application/application-form/ingredient-form/ingredient-form.component.html @@ -44,8 +44,8 @@ - -
+
Product Summaries - - - PRODUCT OVERVIEW - - - -
-
-
- Administravail Pharmacedical Dosage Form: -
-
- {{product.pharmacedicalDosageForm}} -
-
-
-
- Route of Administration: -
-
- {{product.routeAdmin}} -
-
-
+     -
-
-
- Effective Date: -
-
- {{product.effectiveDate}} -
-
-
-
- Unit of Presentation: -
-
- {{product.unitPresentation}} -
-
-
+ + Show + Hide + -
-
-
- End Date: -
-
- {{product.endDate}} -
-
-
-
- Country Code: -
-
- {{product.countryCode}} -
-
-
+
+
-
-
-
- Shelf Life: -
-
- {{product.shelfLife}} -
-
+
+
-
-
- Language: -
-
- {{product.language}} -
-
-
+ + + -
-
-
- Storage Conditions: -
-
- {{product.storageConditions}} -
-
-
-
- Manufacturer Code: -
-
- {{product.manufacturerCode}} -
-
-
+ + + -
-
-
- Number of Manufacture Item: -
-
- {{product.numberOfManufactureItem}} -
-
-
-
- Manufacturer Code Type: -
-
- {{product.manufacturerCodeType}} -
-
-
+ -
-
-
- Manufacturer Name: -
-
- {{product.manufacturerName}} -
-
-
- - - -
- - - - -
- - - PRODUCT PROVENANCE ({{product.productProvenances.length}}) - -
- -
- -
-
- Provenance {{(i+1)}} of {{product.productProvenances.length}} -
-

+ + Provenance:  + + {{prodProv.provenance}} + + +
-
-
- Provenance: -
-
- {{ x.provenance }} -
-
-
-
- Product Status: -
-
- {{x.productStatus}} -
-
-
-
-
-
- Product Type: -
-
- {{ x.productType }} -
-
-
-
- Public Domain: -
-
- {{x.publicDomain}} +
+
+ Product Names:
-
-
+
+
+
+
+
{{prodName.productName}} -
-
-
- Application Type: -
-
- {{ x.applicationType }} + +  ({{prodName.productNameType}}) + + +
+ +
+   + check +
+
+
+
+ + (No Product Name) +
-
-
- Is Listed: + +
+
+ Marketing Status:
-
- {{x.isListed}} +
+ {{prodProv.productStatus}}
-
+
+
-
-
- Application Number: +
+
+ Product Code:
-
- {{x.applicationNumber}} +
+ +
+ {{prodCode.productCode}} +  ({{prodCode.productCodeType}}) + + + +     + + + + + + +
-
-
- Marketing Category Name: + +
+
+ Product Type:
-
- {{x.marketingCategoryName}} +
+ {{prodProv.productType}}
-
+ +
+
-
-
- Control Substance Code: +
+
+ Labeler Name:
-
- {{x.controlSubstanceCode}} +
+
+ {{prodComp.companyName}} +
+ {{prodCompCode.productCode}} +
+
-
-
- Marketing Category Code: +
+
+ Labeler Code:
-
- {{x.marketingCategoryCode}} +
+ {{product.manufacturerCode}} + +  ({{product.manufacturerCodeType}}) +
-
+
+
-
-
- Control Substance Source: +
+
+ Country:
-
- {{x.controlSubstanceSource}} +
+ {{product.countryCode}}
-
-
- Control Substance Class: +
+
+ Application Type Number:
-
- {{x.controlSubstanceClass}} +
+ + {{prodProv.applicationType}} + + + {{prodProv.applicationNumber}} +
-
-
-
-
- Jurisdictions: -
-
- {{ x.jurisdictions }} -
-
-
-
- Product URL: -
-
- {{ x.productUrl }} -
+
+
+ + + + +
+ +
+
+
+ Dosage Form: +
+
+
+ | + {{prodManuItem.dosageForm}}
- - - - -

- - - PRODUCT NAME ({{x.productNames.length}}) - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
#Product NameProduct TypeLanguageTerm and Term Part
{{indexName + 1}} -
-
- {{ prodName.productName }} -
+
+
+
+ Route of Administration: +
+
+ {{product.routeAdmin}} +
+
+ -
-   - check -
- -
{{ prodName.productNameType }}{{ prodName.language }} -
- Term: {{prodPart.productTerm}} - Term Part:  {{prodPart.productTermPart}}

-
-
- No Product Name Available -
-
-
-
- - - - -
- - - PRODUCT CODE ({{x.productCodes.length}}) - -
- - - - - - - - - - - - - - - - -
#Product CodeProduct Code Type
{{i + 1}}{{ prodCode.productCode }}{{ prodCode.productCodeType }}
-
-
-
+ + +
+
+
+ Substance Name +
(Active):  + ({{product._activeIngredients.length}})
- - - - -
- - - PRODUCT COMPANY ({{x.productCompanies.length}}) - -
- -
- -
- Company {{(i+1)}} of {{x.productCompanies.length}} -
-

-
-
-
- Company Name: -
-
- {{prodComp.companyName}} -
-
-
-
- Company Role: -
-
- {{ prodComp.companyRole }} -
-
-
-
-
-
- Company Address: -
-
- {{ prodComp.companyAddress }} -
-
-
-
- City: -
-
- {{ prodComp.companyCity }} -
-
-
+
-
-
-
- State: -
-
- {{ prodComp.companyState }} -
-
-
-
- Zip: -
-
- {{ prodComp.companyZip }} -
-
-
+ +
    -
    -
    -
    - Company GPS Latitude: -
    -
    - {{ prodComp.companyGpsLatitude }} -
    -
    -
    -
    - Company Country: -
    -
    - {{ prodComp.companyCountry }} -
    -
    -
    +
    +
    -
    -
    -
    - Company GPS Longitude: -
    -
    - {{ prodComp.companyGpsLongitude }} -
    -
    -
    -
    - Company GPS Elevation: -
    -
    - {{ prodComp.companyGpsElevation }} -
    -
    -
    + + +
    + + Show More + Show Less + +
    +
    -
    -
    -
    - Start Marketing Date: -
    -
    - {{ prodComp.startMarketingDate }} -
    -
    -
    -
    - Company Public Domain: -
    -
    - {{ prodComp.companyPublicDomain }} -
    -
    -
    +
    +
    -
    -
    -
    - End Marketing Date: -
    -
    - {{ prodComp.endMarketingDate }} -
    -
    -
    -
    - Company Product ID: -
    -
    - {{ prodComp.companyProductId }} -
    -
    -
    +
  1. +
    -
    -
    -
    - Company Document ID: + -
    - {{ prodComp.companyDocumentId }} + + {{prodIngred._ingredientName}} + + +
    +
    + +
    + + +
    + Average: + {{prodIngred.average}} {{prodIngred.unit}} + +
    -
    -
    - Provenance Document ID: + +
    + +
    + + Numerator: + {{ prodIngred.originalNumeratorNumber }} {{ prodIngred.originalNumeratorUnit + }} + + +
    -
    - {{ prodComp.provenanceDocumentId }} + + +
    + + Denominator: + {{ prodIngred.originalDenominatorNumber }} {{ + prodIngred.originalDenominatorUnit + }} + + +
    +
    + + +
    + ({{ prodIngred.ingredientType }})
    -
    +
  2. + +
    + +
    + + (No Substance Name) + +
    + +
- -
- - - Company Code ({{prodComp.productCompanyCodes.length}}) - -
- - - - - - - - - - - - - - - - -
#Company CodeCompany Code Type
{{ compCodeIndex + 1}}{{ compCode.companyCode }}{{ compCode.companyCodeType }}
-
-
-
-
- -

-
-
- -
-
- - - - -
- - - PRODUCT DOCUMENTATION IDs ({{x.productDocumentations.length}}) - -
- - - - - - - - - - - - - - - - - - - - - - -
#Document IDProduct Document TypeSet Id VersionEffective TimeJurisdictions
{{i + 1}}{{ prodDoc.documentId }}{{ prodDoc.documentType }}{{ prodDoc.setIdVersion }}{{ prodDoc.effectiveTime }}{{ prodDoc.jurisdictions }}
-
-
-
+
+ + + +
+
+ Substance Name +
(Inactive/Other):  + ({{product._otherIngredients.length}})
- - - - -
- - - PRODUCT INDICATION ({{x.productIndications.length}}) - -
- -
- -
- Indication {{(i+1)}} of {{x.productIndications.length}} -
-

- -
-
-
- Indication: + +
+ + +
    + +
    +
    + + + +
    + + Show More + Show Less + +
    +
    + +
    +
    + +
  1. +
    + + -
    - {{ prodInd.indication }} + + {{prodIngred._ingredientName}} + + +
    +
    +
    -
    -
    - Indication Text: -
    -
    - {{ prodInd.indicationText }} -
    + + +
    + Average: + {{prodIngred.average}} {{prodIngred.unit}} + +
    -
    -
    -
    -
    - Indication Code: +
    + +
    + + Numerator: + {{ prodIngred.originalNumeratorNumber }} {{ prodIngred.originalNumeratorUnit + }} + + +
    -
    - {{ prodInd.indicationCode }} + + +
    + + Denominator: + {{ prodIngred.originalDenominatorNumber }} {{ + prodIngred.originalDenominatorUnit + }} + + +
    -
    -
    -
    - Indication Code Type: -
    -
    - {{ prodInd.indicationCodeType }} -
    -
    -
    -
    -
    -
    - Indication Group: -
    -
    - {{ prodInd.indicationGroup }} -
    -
    -
    -
    - Indication Source: -
    -
    - {{ prodInd.indicationSource }} -
    -
    -
    +
    -
    -
    -
    - Indication Source Type: -
    -
    - {{ prodInd.indicationSourceType }} -
    -
    -
    -
    - Indication Source URL: -
    -
    - {{ prodInd.indicationSourceUrl }} -
    + +
    + ({{ prodIngred.ingredientType }})
    -
    -
    - -
    - + +
  2. + +
    + +
    + + (No Substance Name) + +
    + +
+
- +
+
+
-
-
-
-
-
- - - - -
- - - MANUFACTURE ITEM ({{product.productManufactureItems.length}}) - -
- -
- - - - - - -
-
-
-
- Dosage Form: -
-
- {{ prodComp.dosageForm }} -
-
-
-
- Amount: -
-
- {{prodComp.amount}} -
-
-
+
+
-
-
-
- Dosage Form Code: -
-
- {{prodComp.dosageFormCode}} -
-
-
-
- Unit: -
-
- {{prodComp.unit}} -
-
-
-
-
-
- Dosage Form Code Type: -
-
- {{prodComp.dosageFormCodeType}} -
-
-
-
- Scoring: -
-
- {{prodComp.charNumFragments}} -
-
-
+ +
Product Full Details -
-
-
- Flavor Name: -
-
- {{prodComp.charFlavor}} -
-
-
-
- Size: -
-
- {{prodComp.charSize}} -
-
-
+     -
-
-
- Color Name: -
-
- {{prodComp.charColor}} -
-
-
-
- Imprint Text: -
-
- {{prodComp.charImprintText}} -
-
-
+ + Show + Hide + -
-
-
- Shape Name: -
-
- {{prodComp.charShape}} -
-
-
-
- Route of Administration: -
-
- {{prodComp.routeOfAdministration}} -
-
-
+
+
-
-
-
- Dosage Form Note: -
-
- {{prodComp.dosageFormNote}} -
-
-
-
- Composition Note: -
-
- {{prodComp.compositionNote}} -
-
-
+
-
-
-
- Provenance Manufacture Item ID: -
-
- {{prodComp.provenanceManufactureItemId}} -
-
-
- + + +
- - - - MANUFACTURER ITEM CODE ({{prodComp.productManufacturers.length}}) - -
- -
-
-
-
-
- Manufacturer Name: -
-
- {{ prodManu.manufacturerName }} -
+ + + + +
MANUFACTURE ITEM ({{product.productManufactureItems.length}})
+
+ + +
+ +
+ + + + + + + + +
+
 
+
 
+ +
+ +
+ +
+
+
+ Dosage Form:
-
-
- Manufacturer Role: -
-
- {{ prodManu.manufacturerRole }} -
+
+ {{ prodComp.dosageForm }}
- -
-
-
- Manufacturer Code: -
-
- {{ prodManu.manufacturerCode }} -
+
+
+ Amount:
-
-
- Manufacturer Code Type: -
-
- {{ prodManu.manufacturerCodeType }} -
+
+ {{prodComp.amount}}
+
-
-
-
- Manufactured Item Code: -
-
- {{ prodManu.manufacturedItemCode }} -
+
+
+
+ Dosage Form Code:
-
-
- Manufactured Item Code Type -
-
- {{ prodManu.manufacturedItemCodeType }} -
+
+ {{prodComp.dosageFormCode}}
-
-
-
- -
- - - - - -

- - -
-
-
+
+
+
+ Unit: +
+
+ {{prodComp.unit}} +
+
+
-
- LOT {{indexLot + 1}} +
+
+
+ Dosage Form Code Type: +
+
+ {{prodComp.dosageFormCodeType}} +
+
+
+
+ Scoring: +
+
+ {{prodComp.charNumFragments}} +
+
+
- Lot Type: + Flavor Name: +
+
+ {{prodComp.charFlavor}} +
+
+
+
+ Size:
- {{ lot.lotType }} + {{prodComp.charSize}}
@@ -1048,18 +603,18 @@
- Lot Number: + Color Name:
- {{ lot.lotNo }} + {{prodComp.charColor}}
- Lot Size: + Imprint Text:
- {{ lot.lotSize }} + {{prodComp.charImprintText}}
@@ -1067,297 +622,1232 @@
- Expiry Date: + Shape Name:
- {{ lot.expiryDate }} + {{prodComp.charShape}}
- Manufacture Date: + Route of Administration:
- {{ lot.manufactureDate }} + {{prodComp.routeOfAdministration}}
- +
+
+
+ Dosage Form Note: +
+
+ {{prodComp.dosageFormNote}} +
+
+
+
+ Composition Note: +
+
+ {{prodComp.compositionNote}} +
+
+
- -
- - - - INGREDIENTS - ({{lot.productIngredients.length}}) - - - -
-
+
+
+
+ Provenance Manufacture Item ID: +
+
+ {{prodComp.provenanceManufactureItemId}} +
+
+
+ -
- Ingredient {{(indexIng+1)}} of {{lot.productIngredients.length}} -
-

-
-
-
- Applicant Ingredient Name: -
-
- {{ingred.applicantIngredName}} -
-
-
-
- Ingredient Type: + + + + MANUFACTURER ITEM CODE ({{prodComp.productManufacturers.length}}) + +
+ +
+
+
+
+
+ Manufacturer Name: +
+
+ {{ prodManu.manufacturerName }} +
-
- {{ ingred.ingredientType }} +
+
+ Manufacturer Role: +
+
+ {{ prodManu.manufacturerRole }} +
-
-
-
-
- Ingredient Name: -
-
-
- {{ingred._ingredientName}} +
+
+
+ Manufacturer Code:
- - -
- {{active}} -  (Active Moiety) +
+ {{ prodManu.manufacturerCode }}
-
-
-
-
- Ingredient Function: -
-
- {{ ingred.ingredientFunction }} +
+
+ Manufacturer Code Type: +
+
+ {{ prodManu.manufacturerCodeType }} +
-
-
-
-
- Basis Of Strength: +
+
+
+ Manufactured Item Code: +
+
+ {{ prodManu.manufacturedItemCode }} +
-
-
- {{ingred._basisOfStrengthIngredientName}} +
+
+ Manufactured Item Code Type:
- - -
- {{active}} -  (Active Moiety) +
+ {{ prodManu.manufacturedItemCodeType }}
-
-
+
+
+
+ +
+ + -
-
- Ingredient Location: -
-
- {{ ingred.ingredientLocation }} - - ({{ingred.ingredientLocationText}}) - -
-
-
+
-
-
-
- Average: -
-
- {{ ingred.average }} -
-
-
-
- Low: -
-
- {{ ingred.low }} -
-
-
+ + + +
+
+
-
-
-
- Unit: -
-
- {{ ingred.unit }} -
-
-
-
- High: -
-
- {{ ingred.high }} -
-
-
+
-
-
-
- Original Numerator Number: -
-
- {{ ingred.originalNumeratorNumber }} -
+
+ LOT {{indexLot + 1}} +
+ +
+
+
+ Lot Type:
-
-
- Original Denominator Number: -
-
- {{ ingred.originalDenominatorNumber }} -
+
+ {{ lot.lotType }}
+
-
-
-
- Original Numerator Unit: -
-
- {{ ingred.originalNumeratorUnit }} -
+
+
+
+ Lot Number:
-
-
- Original Denominator Unit: -
-
- {{ ingred.originalDenominatorUnit }} -
+
+ {{ lot.lotNo }}
- -
-
-
- Manufacturer: -
-
- {{ ingred.manufacturer }} -
+
+
+ Lot Size:
-
-
- Lot No: -
-
- {{ ingred.ingredLotNo }} -
+
+ {{ lot.lotSize }}
+
-
-
-
- Manufacture Ingredient Catalog ID: -
-
- {{ ingred.manufactureIngredientCatalogId }} -
+
+
+
+ Expiry Date:
-
-
- Manufacture Ingredient URL: -
-
- {{ ingred.manufactureIngredientUrl }} -
+
+ {{ lot.expiryDate }}
- -
-
-
- Grade: -
-
- {{ ingred.grade }} -
+
+
+ Manufacture Date:
-
-
- Release Characteristics: -
-
- {{ ingred.releaseCharacteristic }} -
+
+ {{ lot.manufactureDate }}
+
+ +
-
-
-
- Confidentiality Code: -
-
- {{ ingred.confidentialityCode }} -
-
-
-
- Notes: -
-
- {{ ingred.notes }} + + + + + + + INGREDIENTS + ({{lot.productIngredients.length}}) + + + + +
+ +
+ +
 
+ +
+ Ingredient + {{(indexIng+1)}}  +   of {{lot.productIngredients.length}} +
-
-
-
-
- - - -
+
+ +
+
+
+ Applicant Ingredient Name: +
+
+ {{ingred.applicantIngredName}} +
+
+
+
+ Ingredient Type: +
+
+ {{ ingred.ingredientType }} +
+
+
-
- - +
+
+
+ Ingredient Name: +
+
+ + + +
+ {{active}} +  (Active Moiety) +
+ +
+
+
+
+ Ingredient Function: +
+
+ {{ ingred.ingredientFunction }} +
+
+
+ +
+
+
+ Basis Of Strength: +
+
+ + + +
+ {{active}} +  (Active Moiety) +
+ +
+
+ +
+
+ Ingredient Location: +
+
+ {{ ingred.ingredientLocation }} + + ({{ingred.ingredientLocationText}}) + +
+
+
- - - +
+
+
+ Average: +
+
+ {{ ingred.average }} +
+
+
+
+ Low: +
+
+ {{ ingred.low }} +
+
+
- - - -
- -
+
+
+
+ Unit: +
+
+ {{ ingred.unit }} +
+
+
+
+ High: +
+
+ {{ ingred.high }} +
+
+
+ +
+
+
+ Original Numerator Number: +
+
+ {{ ingred.originalNumeratorNumber }} +
+
+
+
+ Original Denominator Number: +
+
+ {{ ingred.originalDenominatorNumber }} +
+
+
+ +
+
+
+ Original Numerator Unit: +
+
+ {{ ingred.originalNumeratorUnit }} +
+
+
+
+ Original Denominator Unit: +
+
+ {{ ingred.originalDenominatorUnit }} +
+
+
+ +
+
+
+ Manufacturer: +
+
+ {{ ingred.manufacturer }} +
+
+
+
+ Manufacturer Lot No: +
+
+ {{ ingred.ingredLotNo }} +
+
+
+ +
+
+
+ Manufacture Ingredient Catalog ID: +
+
+ {{ ingred.manufactureIngredientCatalogId }} +
+
+
+
+ Manufacture Ingredient URL: +
+
+ {{ ingred.manufactureIngredientUrl }} +
+
+
+ +
+
+
+ Grade: +
+
+ {{ ingred.grade }} +
+
+
+
+ Release Characteristics: +
+
+ {{ ingred.releaseCharacteristic }} +
+
+
+ +
+
+
+ Confidentiality Code: +
+
+ {{ ingred.confidentialityCode }} +
+
+
+
+ Notes: +
+
+ {{ ingred.notes }} +
+
+
+
+ +
+
+ + + + +
+ +
+ + + + + + + + + + +
+ + +
+ + + +
+ + + + + +
PRODUCT PROVENANCE ({{product.productProvenances.length}})
+
+ + +
+ +
+
+ +
+
+ Provenance {{(i+1)}} of {{product.productProvenances.length}} +
+
+ +
+
+
+ Provenance: +
+
+ {{ x.provenance }} +
+
+
+
+ Product Status: +
+
+ {{x.productStatus}} +
+
+
+ +
+
+
+ Product Type: +
+
+ {{ x.productType }} +
+
+
+
+ Public Domain: +
+
+ {{x.publicDomain}} +
+
+
+ +
+
+
+ Application Type: +
+
+ {{ x.applicationType }} +
+
+
+
+ Is Listed: +
+
+ {{x.isListed}} +
+
+
+ +
+
+
+ Application Number: +
+
+ {{x.applicationNumber}} +
+
+
+
+ Marketing Category Name: +
+
+ {{x.marketingCategoryName}} +
+
+
+ +
+
+
+ Control Substance Code: +
+
+ {{x.controlSubstanceCode}} +
+
+
+
+ Marketing Category Code: +
+
+ {{x.marketingCategoryCode}} +
+
+
+ +
+
+
+ Control Substance Source: +
+
+ {{x.controlSubstanceSource}} +
+
+
+
+ Control Substance Class: +
+
+ {{x.controlSubstanceClass}} +
+
+
+ +
+
+
+ Jurisdictions: +
+
+ {{ x.jurisdictions }} +
+
+
+
+ Product URL: +
+ +
+
+ + + + +

+ + + PRODUCT NAME ({{x.productNames.length}}) + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
#Product NameProduct TypeLanguageTerm and Term Part
{{indexName + 1}} +
+
+ {{ prodName.productName }} +
+ +
+   + check +
+
+
{{ prodName.productNameType }}{{ prodName.language }} +
+ Term: {{prodPart.productTerm}} + Term Part:  {{prodPart.productTermPart}}

+
+
+ No Product Name Available +
+
+
+
+ + + + +
+ + + PRODUCT CODE ({{x.productCodes.length}}) + +
+ + + + + + + + + + + + + + + + +
#Product CodeProduct Code Type
{{i + 1}}{{ prodCode.productCode }}{{ prodCode.productCodeType }}
+
+
+
+
+ + + + +
+ + + PRODUCT COMPANY ({{x.productCompanies.length}}) + +
+ +
+ +
+ Company {{(i+1)}} of {{x.productCompanies.length}} +
+
+ +
+
+
+ Company Name: +
+
+ {{prodComp.companyName}} +
+
+
+
+ Company Role: +
+
+ {{ prodComp.companyRole }} +
+
+
+ +
+
+
+ Company Address: +
+
+ {{ prodComp.companyAddress }} +
+
+
+
+ City: +
+
+ {{ prodComp.companyCity }} +
+
+
+ +
+
+
+ State: +
+
+ {{ prodComp.companyState }} +
+
+
+
+ Zip: +
+
+ {{ prodComp.companyZip }} +
+
+
+ +
+
+
+ Company GPS Latitude: +
+
+ {{ prodComp.companyGpsLatitude }} +
+
+
+
+ Company Country: +
+
+ {{ prodComp.companyCountry }} +
+
+
+ +
+
+
+ Company GPS Longitude: +
+
+ {{ prodComp.companyGpsLongitude }} +
+
+
+
+ Company GPS Elevation: +
+
+ {{ prodComp.companyGpsElevation }} +
+
+
+ +
+
+
+ Start Marketing Date: +
+
+ {{ prodComp.startMarketingDate }} +
+
+
+
+ Company Public Domain: +
+
+ {{ prodComp.companyPublicDomain }} +
+
+
+ +
+
+
+ End Marketing Date: +
+
+ {{ prodComp.endMarketingDate }} +
+
+
+
+ Company Product ID: +
+
+ {{ prodComp.companyProductId }} +
+
+
+ +
+
+
+ Company Document ID: +
+
+ {{ prodComp.companyDocumentId }} +
+
+
+
+ Provenance Document ID: +
+
+ {{ prodComp.provenanceDocumentId }} +
+
+
+ + +
+ + + Company Code ({{prodComp.productCompanyCodes.length}}) + +
+ + + + + + + + + + + + + + + + +
#Company CodeCompany Code Type
{{ compCodeIndex + 1}}{{ compCode.companyCode }}{{ compCode.companyCodeType }}
+
+
+
+
+ +
+
+
+
+
+
+
+ + + + +
+ + + PRODUCT DOCUMENTATION IDs ({{x.productDocumentations.length}}) + +
+ + + + + + + + + + + + + + + + + + + + + + +
#Document IDProduct Document TypeSet Id VersionEffective TimeJurisdictions
{{i + 1}}{{ prodDoc.documentId }}{{ prodDoc.documentType }}{{ prodDoc.setIdVersion }}{{ prodDoc.effectiveTime }}{{ prodDoc.jurisdictions }}
+
+
+
+
+ + + + +
+ + + PRODUCT INDICATION ({{x.productIndications.length}}) + +
+ +
+ +
+ Indication {{(i+1)}} of {{x.productIndications.length}} +
+

+ +
+
+
+ Indication: +
+
+ {{ prodInd.indication }} +
+
+
+
+ Indication Text: +
+
+ {{ prodInd.indicationText }} +
+
+
+ +
+
+
+ Indication Code: +
+
+ {{ prodInd.indicationCode }} +
+
+
+
+ Indication Code Type: +
+
+ {{ prodInd.indicationCodeType }} +
+
+
+ +
+
+
+ Indication Group: +
+
+ {{ prodInd.indicationGroup }} +
+
+
+
+ Indication Source: +
+
+ {{ prodInd.indicationSource }} +
+
+
+ +
+
+
+ Indication Source Type: +
+
+ {{ prodInd.indicationSourceType }} +
+
+
+
+ Indication Source URL: +
+
+ {{ prodInd.indicationSourceUrl }} +
+
+
+
+
+
+
+
+ + +
+ + +
+ +
+ +
+ + + + +
+ + + + + +
PRODUCT OVERVIEW
+
+ + +
+ +
+
+
+ Product Container: +
+
+ {{product.productContainer}} +
+
+
+
+ Route of Administration: +
+
+ {{product.routeAdmin}} +
+
+
+ +
+
+
+ Effective Date: +
+
+ {{product.effectiveDate}} +
+
+
+
+ Unit of Presentation: +
+
+ {{product.unitPresentation}} +
+
+
+ +
+
+
+ End Date: +
+
+ {{product.endDate}} +
+
+
+
+ Country: +
+
+ {{product.countryCode}} +
+
+
+ +
+
+
+ Shelf Life: +
+
+ {{product.shelfLife}} +
+
+ +
+
+ Language: +
+
+ {{product.language}} +
+
+
+ +
+
+
+ Storage Conditions: +
+
+ {{product.storageConditions}} +
+
+
+
+ Manufacturer Code: +
+
+ {{product.manufacturerCode}} +
+
+
+ +
+
+
+ Number of Manufacture Item: +
+
+ {{product.numberOfManufactureItem}} +
+
+
+
+ Manufacturer Code Type: +
+
+ {{product.manufacturerCodeType}} +
+
+
+ +
+
+
+ Manufacturer Name: +
+
+ {{product.manufacturerName}} +
+
+
+ + +
+ +
+ + +
+ +

+ +
\ No newline at end of file diff --git a/src/app/fda/product/product-details/product-details/product-details.component.scss b/src/app/fda/product/product-details/product-details/product-details.component.scss index 8a9171cbe..72f3a36ba 100644 --- a/src/app/fda/product/product-details/product-details/product-details.component.scss +++ b/src/app/fda/product/product-details/product-details/product-details.component.scss @@ -1,5 +1,6 @@ .details-container { width: 100%; + max-width: 100%; display: flex; align-items: center; justify-content: center; @@ -42,10 +43,9 @@ } .mat-card { + /* min-width: 1028px;*/ max-width: 1028px; width: 100%; - /*box-sizing: border-box;*/ - /*margin-bottom: 20px;*/ } .mat-card-title { @@ -92,10 +92,30 @@ .row-property-2 { display: flex; - width: 100%; + width: 50%; } .row-property-key-2 { + min-width: 35%; + max-width: 35%; + padding: 9px; + font-size: 13px; + font-weight: 600; +} + +.row-property-value-2 { + min-width: 65%; + max-width: 65%; + padding: 9px; + font-size: 13px; +} + +.row-property-3 { + display: flex; + width: 33%; +} + +.row-property-key-3 { min-width: 50%; max-width: 50%; padding: 9px; @@ -103,7 +123,7 @@ font-weight: 600; } -.row-property-value-2 { +.row-property-value-3 { min-width: 50%; max-width: 50%; padding: 9px; @@ -130,6 +150,7 @@ font-size: 12px; } + .title { font-size: 26px; font-weight: bold; @@ -144,7 +165,8 @@ display: flex; box-sizing: border-box; width: 100%; - margin-bottom: 20px; + margin-top: 10px; + margin-bottom: 10px; flex-direction: row; align-items: center; white-space: nowrap; @@ -163,10 +185,34 @@ margin-top: -10px; } +.margintopneg15 { + margin-top: -15px; +} + +.margintopneg20px { + margin-top: -20px; +} + +.margintopneg30px { + margin-top: -30px; +} + +.margintop5px { + margin-top: 5px; +} + .margintop10px { margin-top: 10px; } +.margintop12px { + margin-top: 12px; +} + +.margintop15px { + margin-top: 15px; +} + .margintop20px { margin-top: 20px; } @@ -183,6 +229,10 @@ margin-top: 100px; } +.marginbottom10px { + margin-bottom: 10px; +} + .marginbottom20px { margin-bottom: 20px; } @@ -191,10 +241,18 @@ margin-bottom: 60px; } +.marginleft5px { + margin-left: 5px; +} + .marginleft50px { margin-left: 50px; } +.padtopneg20px { + padding-top: -20px; +} + .padtop17px { padding-top: 17px; } @@ -203,6 +261,10 @@ padding-top: 50px; } +.padleft10px { + padding-left: 10px; +} + .padleft20px { padding-left: 20px; } @@ -235,6 +297,10 @@ font-size: 14px; } +.font15px { + font-size: 15px; +} + .font16px { font-size: 16px; } @@ -251,6 +317,14 @@ color: var(--regular-black-color); } +.colorwhite { + color: var(--regular-white-color); +} + +.coloroffwhite { + color: var(--light-yellow-color-2); +} + .colorred { color: var(--regular-red-color); } @@ -267,6 +341,10 @@ color: var(--regular-blue-color); } +.colorlightblue { + color: var(--blue-color); +} + .colorgreen { color: var(--regular-green-color); } @@ -275,6 +353,18 @@ border: 1px solid var(--regular-grey-color); } +.bordergreen { + border: 1px solid var(--regular-green-color); +} + +.bordertopnone { + border-top: none; +} + +.borderbottomnone { + border-bottom: none; +} + .colororange { color: var(--orange-color); } @@ -288,6 +378,11 @@ max-width: 650px; } +.width1028px { + min-width: 1028px; + max-width: 1028px; +} + .width45percent { width: 45%; } @@ -318,6 +413,59 @@ hr { height: 5px; } +.wordwrap { + word-wrap: break-word; +} + +.middle-fill { + flex: 1 1 auto; +} + +.olstyle { + /* list-style-position: inside;*/ + padding-left: 0px; + margin-top: 0px; + } + +.badge-one { + background-color: green; + color: white; + padding: 3px 3px; + text-align: center; + border-radius: 5px; + margin-left: 7px; + margin-top: -15px; + min-width: 10px; + max-height: 10px; + border: 1px solid gray; + font-size: 12px; + font-weight: 700; + line-height: 1px; +} + +.badge-two { + background-color: rgb(113, 94, 2); + color: white; + padding: 6px 6px; + text-align: center; + border-radius: 10px; + margin-left: 7px; + margin-top: -15px; + min-width: 10px; + font-size: 12px; + font-weight: 700; + line-height: 1px; +} + +.ingredienttitle { + width: 190px; + height: 40px; + background-color: var(--legend-bg-color); + border-radius: 10px 10px 0px 0px; + border: 1px solid gray; + border-bottom: none; +} + table.blueTable { font-family: Roboto, "Helvetica Neue", sans-serif; /*font-family: Verdana, Geneva, sans-serif;*/ @@ -353,7 +501,6 @@ table.blueTable thead th { font-weight: 700; color: var(--table-th-color); border-left: 1px solid var(--table-th-border-color-2); - /*border: 1px solid rgb(249, 249, 247);*/ padding: 10px 10px; } @@ -391,27 +538,50 @@ table.blueTable tfoot .links a{ padding-left: 5px; } -/* label style */ -.mat-tab-label{ - background: var(--pale-border-color-rgb-3); - color: var(--red-label-color); - min-width: 60px!important; +/* TABS Style */ +.tab-style { + border-width: 9px; + border-style: solid; + border-color: red; +} +/* TAB STYLE BEGIN */ +:host ::ng-deep .mat-tab-list .mat-tab-label { + min-width: 200px; + max-width: 2000px; + height: 35px; + padding-top: 5px; + margin-right: 7px; + text-align: top; + color: #393939; + opacity: 1 !important; + border-radius: 10px 10px 0px 0px; + background-color: var(--regular-lightgray-color-2); + padding-top: -10px; } -:host ::ng-deep .mat-tab-label-active { - color: var(--regular-white-color); +:host ::ng-deep .mat-tab-label-content { + margin-top: -5px; +} + +:host ::ng-deep .mat-tab-header { + margin-top: -10px; /* tab margin*/ + border-bottom: 1px solid rgb(205, 201, 201); +} + +:host ::ng-deep .mat-tab-list .mat-tab-labels .mat-tab-label-active { + background-color: var(--tabstyle-bg-color-7); + color: #FFFFFF; font-weight: bold; - /*background-color: var(--pale-border-color-rgb-3);*/ - background-color: var(--orange-color-rgb); - border-radius: 5px; + padding-top: -10px; } :host ::ng-deep .mat-ink-bar { - background-color: var(--primary-color, --orange-color-rgb) !important; - height: 2px; + display: none !important; } +/* TAB STYLE END */ + @media(max-width: 700px) { .mat-card-title { flex-direction: column; diff --git a/src/app/fda/product/product-details/product-details/product-details.component.ts b/src/app/fda/product/product-details/product-details/product-details.component.ts index aa34168d4..db8d44e0f 100644 --- a/src/app/fda/product/product-details/product-details/product-details.component.ts +++ b/src/app/fda/product/product-details/product-details/product-details.component.ts @@ -1,7 +1,8 @@ import { Component, OnInit, AfterViewInit } from '@angular/core'; -import { ProductService } from '../../service/product.service'; +import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute, Router } from '@angular/router'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; +import { OverlayContainer } from '@angular/cdk/overlay'; import { LoadingService } from '@gsrs-core/loading'; import { Title } from '@angular/platform-browser'; import { MainNotificationService } from '@gsrs-core/main-notification'; @@ -9,9 +10,11 @@ import { AppNotification, NotificationType } from '@gsrs-core/main-notification' import { GoogleAnalyticsService } from '@gsrs-core/google-analytics'; import { ControlledVocabularyService } from '@gsrs-core/controlled-vocabulary/controlled-vocabulary.service'; import { UtilsService } from '../../../../core/utils/utils.service'; +import { ConfigService } from '@gsrs-core/config'; import { ProductDetailsBaseComponent } from '../product-details-base.component'; import { GeneralService } from '../../../service/general.service'; import { AuthService } from '@gsrs-core/auth/auth.service'; +import { ProductService } from '../../service/product.service'; @Component({ selector: 'app-product-details', @@ -30,16 +33,19 @@ export class ProductDetailsComponent extends ProductDetailsBaseComponent impleme gaService: GoogleAnalyticsService, utilsService: UtilsService, cvService: ControlledVocabularyService, + public configService: ConfigService, public authService: AuthService, titleService: Title, + overlayContainerService: OverlayContainer, + dialog: MatDialog, public sanitizer: DomSanitizer ) { super(productService, generalService, activatedRoute, loadingService, mainNotificationService, - router, gaService, utilsService, cvService, titleService, sanitizer); + router, gaService, utilsService, cvService, configService, titleService, overlayContainerService, dialog, sanitizer); } ngOnInit() { - this.authService.hasAnyRolesAsync('Admin', 'Updater', 'SuperUpdater').subscribe(response => { + this.authService.hasAnyRolesAsync('Admin', ', Updater', 'SuperUpdater').subscribe(response => { this.isAdmin = response; }); diff --git a/src/app/fda/product/product-details/product-elist-details/product-elist-details.component.ts b/src/app/fda/product/product-details/product-elist-details/product-elist-details.component.ts index 4912bfc7c..63e01b739 100644 --- a/src/app/fda/product/product-details/product-elist-details/product-elist-details.component.ts +++ b/src/app/fda/product/product-details/product-elist-details/product-elist-details.component.ts @@ -1,7 +1,9 @@ import { Component, OnInit, AfterViewInit, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; +import { MatDialog } from '@angular/material/dialog'; import { ProductService } from '../../service/product.service'; import { ActivatedRoute, Router } from '@angular/router'; +import { OverlayContainer } from '@angular/cdk/overlay'; import { LoadingService } from '@gsrs-core/loading'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser'; @@ -39,10 +41,12 @@ export class ProductElistDetailsComponent extends ProductDetailsBaseComponent im public cvService: ControlledVocabularyService, public configService: ConfigService, titleService: Title, + public overlayContainerService: OverlayContainer, + dialog: MatDialog, public sanitizer: DomSanitizer ) { super(producService, generalService, activatedRoute, loadingService, mainNotificationService, - router, gaService, utilsService, cvService, titleService, sanitizer); + router, gaService, utilsService, cvService, configService, titleService, overlayContainerService, dialog, sanitizer); } ngOnInit() { diff --git a/src/app/fda/product/product-form/product-component/product-component-form.component.ts b/src/app/fda/product/product-form/product-component/product-component-form.component.ts index 488a44966..d0d0441b7 100644 --- a/src/app/fda/product/product-form/product-component/product-component-form.component.ts +++ b/src/app/fda/product/product-form/product-component/product-component-form.component.ts @@ -14,7 +14,6 @@ import { Subscription } from 'rxjs'; import { take } from 'rxjs/operators'; import { MatDialog } from '@angular/material/dialog'; import { OverlayContainer } from '@angular/cdk/overlay'; -import { JsonDialogFdaComponent } from '../../../json-dialog-fda/json-dialog-fda.component'; import { ConfirmDialogComponent } from '../../../confirm-dialog/confirm-dialog.component'; @Component({ diff --git a/src/app/fda/product/product-form/product-form.component.html b/src/app/fda/product/product-form/product-form.component.html index ae0fe1c09..5f0d38f4b 100644 --- a/src/app/fda/product/product-form/product-form.component.html +++ b/src/app/fda/product/product-form/product-form.component.html @@ -157,9 +157,9 @@
- + - + - - - + + - +
diff --git a/src/app/fda/product/product-form/product-form.component.ts b/src/app/fda/product/product-form/product-form.component.ts index 48e71fffe..d57cae9e4 100644 --- a/src/app/fda/product/product-form/product-form.component.ts +++ b/src/app/fda/product/product-form/product-form.component.ts @@ -44,6 +44,7 @@ export class ProductFormComponent implements OnInit, AfterViewInit, OnDestroy { username = null; title = null; isAdmin = false; + disableMarketingCategoryCode = true; expiryDateMessage = ''; manufactureDateMessage = ''; viewProductUrl = ''; @@ -491,11 +492,17 @@ export class ProductFormComponent implements OnInit, AfterViewInit, OnDestroy { } showJSON(): void { + const date = new Date(); + let jsonFilename = 'product_' + moment(date).format('MMM-DD-YYYY_H-mm-ss'); + let cleanProduct = this.cleanProduct(); + + let data = {jsonData: cleanProduct, jsonFilename: jsonFilename}; + const dialogRef = this.dialog.open(JsonDialogFdaComponent, { width: '90%', height: '90%', - data: cleanProduct + data: data }); // this.overlayContainer.style.zIndex = '1002'; @@ -794,6 +801,26 @@ export class ProductFormComponent implements OnInit, AfterViewInit, OnDestroy { return this.productService.getViewProductUrl(this.id); } + updateMarketingCategoryName(event: any, prodProvIndex: number) { + + this.product.productProvenances[prodProvIndex].marketingCategoryName = event; + + const cvSubscription = this.cvService.getDomainVocabulary('PROD_MARKETING_CATEGORY_NAME').subscribe(response => { + const marketingCatNameVocabulary = response['PROD_MARKETING_CATEGORY_NAME'].dictionary; + + if (marketingCatNameVocabulary) { + if (event) { + if (marketingCatNameVocabulary[event]) { + if (marketingCatNameVocabulary[event].description) { + this.product.productProvenances[prodProvIndex].marketingCategoryCode = marketingCatNameVocabulary[event].description; + } + } + } + } + }); + this.subscriptions.push(cvSubscription); + } + scrub(oldraw: any): any { const old = oldraw; const idHolders = defiant.json.search(old, '//*[id]'); diff --git a/src/app/fda/product/product-form/product-ingredient-form/product-ingredient-form.component.ts b/src/app/fda/product/product-form/product-ingredient-form/product-ingredient-form.component.ts index 21e093be8..55f6b7a21 100644 --- a/src/app/fda/product/product-form/product-ingredient-form/product-ingredient-form.component.ts +++ b/src/app/fda/product/product-form/product-ingredient-form/product-ingredient-form.component.ts @@ -15,7 +15,6 @@ import { Subscription } from 'rxjs'; import { take } from 'rxjs/operators'; import { MatDialog } from '@angular/material/dialog'; import { OverlayContainer } from '@angular/cdk/overlay'; -import { JsonDialogFdaComponent } from '../../../json-dialog-fda/json-dialog-fda.component'; import { ConfirmDialogComponent } from '../../../confirm-dialog/confirm-dialog.component'; import { SubstanceSearchSelectorComponent } from '../../../substance-search-select/substance-search-selector.component'; import { SubstanceRelated, SubstanceSummary } from '@gsrs-core/substance'; diff --git a/src/app/fda/product/product-form/product-lot-form/product-lot-form.component.ts b/src/app/fda/product/product-form/product-lot-form/product-lot-form.component.ts index 3fd840ab5..d6ac00dff 100644 --- a/src/app/fda/product/product-form/product-lot-form/product-lot-form.component.ts +++ b/src/app/fda/product/product-form/product-lot-form/product-lot-form.component.ts @@ -14,7 +14,6 @@ import { Subscription } from 'rxjs'; import { take } from 'rxjs/operators'; import { MatDialog } from '@angular/material/dialog'; import { OverlayContainer } from '@angular/cdk/overlay'; -import { JsonDialogFdaComponent } from '../../../json-dialog-fda/json-dialog-fda.component'; import { ConfirmDialogComponent } from '../../../confirm-dialog/confirm-dialog.component'; @Component({ diff --git a/src/app/fda/product/product.module.ts b/src/app/fda/product/product.module.ts index b4c57db15..7e4ddf936 100644 --- a/src/app/fda/product/product.module.ts +++ b/src/app/fda/product/product.module.ts @@ -35,7 +35,6 @@ import { SubstanceSearchSelectorModule } from '../substance-search-select/substa import { SubstanceImageModule } from '@gsrs-core/substance/substance-image.module'; import { SubstanceFormModule } from '../../core/substance-form/substance-form.module'; import { FacetsManagerModule } from '@gsrs-core/facets-manager'; -import { JsonDialogFdaComponent } from '../json-dialog-fda/json-dialog-fda.component'; /* GSRS Product Imports */ import { ProductTextSearchModule } from './product-text-search/product-text-search.module'; diff --git a/src/app/fda/product/products-browse/products-browse.component.html b/src/app/fda/product/products-browse/products-browse.component.html index c848275b4..325eee944 100644 --- a/src/app/fda/product/products-browse/products-browse.component.html +++ b/src/app/fda/product/products-browse/products-browse.component.html @@ -219,63 +219,9 @@ - - - - - - - - @@ -300,7 +246,8 @@
- +
  • @@ -341,27 +288,6 @@
  • - @@ -390,11 +316,6 @@ Country -
    {{prodComp.companyCity}} @@ -408,7 +329,7 @@ - Product Status + Marketing Status
    {{prodProv.productStatus}} @@ -425,23 +346,6 @@ - - Application Number @@ -464,18 +368,6 @@ --> - @@ -564,83 +456,6 @@ - - - -
    @@ -699,22 +514,9 @@ title="Go to DailyMed website"> - + - -
    @@ -734,46 +536,22 @@ Labeler Name:
    -
    {{prodComp.companyName}} -
    -
    Application Type Number:
    - {{prodProv.applicationType}} {{prodProv.applicationNumber}} -
    @@ -805,14 +583,8 @@
    - - - diff --git a/src/app/fda/product/products-browse/products-browse.component.ts b/src/app/fda/product/products-browse/products-browse.component.ts index 2b9c36143..6f29e20ae 100644 --- a/src/app/fda/product/products-browse/products-browse.component.ts +++ b/src/app/fda/product/products-browse/products-browse.component.ts @@ -498,13 +498,13 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy // if Ingredient Type exists if (elementIngred.ingredientType) { + // Active Ingredient Count if (elementIngred.ingredientType == this.ACTIVE_INGREDIENT_UPPERCASE || elementIngred.ingredientType == this.ACTIVE_INGREDIENT_LOWERCASE) { // Store Active Ingredient in an Array product._activeIngredients.push(elementIngred); - } // Inactive and Other Ingredient Count else if (elementIngred.ingredientType != this.ACTIVE_INGREDIENT_UPPERCASE @@ -512,10 +512,10 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy // Store Active Ingredient in an Array product._otherIngredients.push(elementIngred); - } } // if Ingredient Type exists + /* // Get Substance Details, uuid, approval_id, substance name if (elementIngred.substanceKey) { @@ -540,6 +540,7 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy }); }); */ + } // response }); this.subscriptions.push(substanceSubscription); diff --git a/src/app/fda/product/service/product.service.ts b/src/app/fda/product/service/product.service.ts index ce6d66791..17f72a5ae 100644 --- a/src/app/fda/product/service/product.service.ts +++ b/src/app/fda/product/service/product.service.ts @@ -8,7 +8,7 @@ import { PagingResponse } from '@gsrs-core/utils'; import { UtilsService } from '@gsrs-core/utils/utils.service'; import { Facet } from '@gsrs-core/facets-manager'; import { FacetParam, FacetHttpParams, FacetQueryResponse } from '@gsrs-core/facets-manager'; -import { Product, ProductProvenance, ProductName, ProductTermAndPart, ProductCode, ProductAll, ProductDocumentation } from '../model/product.model'; +import { Product, ProductProvenance, ProductName, ProductTermAndPart, ProductCode, ProductDocumentation } from '../model/product.model'; import { ProductCompany, ProductCompanyCode, ProductIndication, ProductManufactureItem, ProductManufacturer, ProductLot, ProductIngredient } from '../model/product.model'; import { ValidationResults } from '../model/product.model'; import { SubstanceSuggestionsGroup } from '@gsrs-core/utils/substance-suggestions-group.model'; diff --git a/src/styles/_styles.scss b/src/styles/_styles.scss index d9c627e53..3cb6122bd 100644 --- a/src/styles/_styles.scss +++ b/src/styles/_styles.scss @@ -11,6 +11,7 @@ --regular-white-color: white; --regular-offwhite-color: rgb(242, 242, 242); --regular-lightgray-color: lightgray; + --regular-lightgray-color-2: rgb(232, 232, 232); --regular-gainsboro-color: gainsboro; --regular-grey-color: grey; --regular-transparent-color: transparent; From 9bd39826101c8dde8c06d63d629cc77f2f6e6568 Mon Sep 17 00:00:00 2001 From: Newatia Date: Tue, 20 Aug 2024 11:20:32 -0400 Subject: [PATCH 2/2] updated product application ivp --- .../core/assets/data/product_dictionary.json | 8 +- .../core/facets-manager/facet-display.pipe.ts | 8 +- src/app/fda/config/config.json | 5 +- .../invitro-pharmacology-form.component.html | 69 +- .../invitro-pharmacology-form.component.ts | 734 +++++++----------- .../model/invitro-pharmacology.model.ts | 4 +- .../service/invitro-pharmacology.service.ts | 3 +- .../product-details-base.component.ts | 6 +- .../product-details.component.html | 8 +- .../product-text-search.component.ts | 51 +- .../products-browse.component.html | 211 +++-- .../products-browse.component.scss | 4 + .../products-browse.component.ts | 100 ++- src/app/fda/service/general.service.ts | 7 +- 14 files changed, 610 insertions(+), 608 deletions(-) diff --git a/src/app/core/assets/data/product_dictionary.json b/src/app/core/assets/data/product_dictionary.json index 37d178942..263fe500f 100644 --- a/src/app/core/assets/data/product_dictionary.json +++ b/src/app/core/assets/data/product_dictionary.json @@ -1,9 +1,9 @@ { - "Administered Pharmaceutical Dosage Form":{ - "lucenePath":"root_pharmaceuticalDosageForm", - "description":"Administered Pharmaceutical Dosage Form of the product", + "Product Container":{ + "lucenePath":"root_productContainer", + "description":"Product Container of the product", "type":"string", - "cvDomain":"DOSAGE_FORM", + "cvDomain":"PROD_CONTAINER", "priority":null, "suggest":null }, diff --git a/src/app/core/facets-manager/facet-display.pipe.ts b/src/app/core/facets-manager/facet-display.pipe.ts index cf14e66e8..ed384b5eb 100644 --- a/src/app/core/facets-manager/facet-display.pipe.ts +++ b/src/app/core/facets-manager/facet-display.pipe.ts @@ -16,8 +16,6 @@ export class FacetDisplayPipe implements PipeTransform { codeTerm = this.configService.configData.approvalCodeName; } - - if (args) { if (args === 'userList') { if (name.includes(':')){ @@ -98,6 +96,12 @@ export class FacetDisplayPipe implements PipeTransform { if (name === 'root_submitDate') { return 'Submit Date'; } + if (name === 'root_creationDate') { + return 'Record Create Date'; + } + if (name === 'root_lastModifiedDate') { + return 'Record Last Edited'; + } return name.trim(); } diff --git a/src/app/fda/config/config.json b/src/app/fda/config/config.json index c4a10ed3e..a16732a6c 100644 --- a/src/app/fda/config/config.json +++ b/src/app/fda/config/config.json @@ -969,7 +969,6 @@ ] }, "applications": { - "default": [ "Application Type", "Center", @@ -1039,8 +1038,8 @@ "admin": [ "Record Created By", "Record Last Edited By", - "Record Create Date", - "Record Last Edited" + "root_creationDate", + "root_lastModifiedDate" ] }, "ctclinicaltrial": { diff --git a/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.html b/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.html index ead1d29d4..66eb23d96 100644 --- a/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.html +++ b/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.html @@ -72,7 +72,7 @@
    - @@ -138,52 +138,43 @@ - - - + + - - +
    +
    + Saving Screening Records ... +
    - - + + -
    Screening {{(screeningIndex+1)}} of - {{assay.invitroAssayScreenings.length}} -      + + - - -
    -
    - --> + + + - - - call_end - - - forum - - - -
    @@ -1205,7 +1195,7 @@
    - @@ -1311,12 +1301,11 @@
    -
    Plasma Protein + [(ngModel)]="screening.invitroAssayResult.plasmaProteinAdded" + (change)="setPlasmaProteinCheckBox($event, screeningIndex)">Plasma Protein Added? diff --git a/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.ts b/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.ts index e6c1c95dc..eef4f328f 100644 --- a/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.ts +++ b/src/app/fda/invitro-pharmacology/invitro-pharmacology-form/invitro-pharmacology-form.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit, OnDestroy, ViewChild, TemplateRef } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { HttpClient, HttpParams } from '@angular/common/http'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; @@ -46,20 +46,27 @@ import { }) export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { + @ViewChild('saveTemplate', { static: false }) private saveTemplate; + substanceKeyTypeForInvitroPharmacologyConfig = null; assay: InvitroAssayInformation; - assayTemp: InvitroAssayInformation; firstAssayToSave: InvitroAssayInformation; - originalAssayFromDb: Array = []; + originalAssaysFromDb: Array = []; + assaysToSave: Array = []; - firstAssaySavedResultInfo: InvitroAssayResultInformation; originalAssayResultInfoFromDb: InvitroAssayResultInformation; assayResultInfo: InvitroAssayResultInformation = {}; + assayToSaveApiUrlList: Array = []; + id?: number; totalAssayToSave = 0; - assaySavedCounter = 0; + totalRecordSavedInDatabase = 0; + + numberOfRecordToSaveParallel = 1; + numberOfRecordToSaveEndIndex = 1; + numberOfRecordToSaveStartIndex = 0; // Form Control existingAssayControl = new FormControl(); @@ -243,6 +250,10 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { }, 600); } + ngAfterViewInit(changes: any) { + //this.openModalSave(this.saveTemplate); + } + ngOnDestroy(): void { this.subscriptions.forEach(subscription => { subscription.unsubscribe(); @@ -259,7 +270,7 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { this.existingAssaysByAssaySetList = response; // Copy original records in the variable - this.originalAssayFromDb = _.cloneDeep(response); + this.originalAssaysFromDb = _.cloneDeep(response); // Loop through Assays and find result information id where same as url id this.existingAssaysByAssaySetList.forEach(assay => { @@ -365,9 +376,6 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { // Push new screening record in existing Assay assay.invitroAssayScreenings.push(newInvitroAssayScreening); - // Delete Assay Set Object - // delete assay.invitroAssaySets; - }); // LOOP: assay } else { @@ -725,323 +733,237 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { }); // LOOP: assay } - createFirstAssayToSave() { - // Using this assay list in the form - if (this.existingAssaysByAssaySetList.length > 0) { - - // Get the first Assay from the list - this.firstAssayToSave = this.existingAssaysByAssaySetList[0]; + openModalSave(template: TemplateRef) { + const dialogRef = this.dialog.open(template, { + minWidth: '50%', + maxWidth: '50%' + }); - // copy the Result Information on the last screening or where _show == true - // call copy, THIS LINE MUST be before deleteing the _show field in the next code - this.firstAssayToSave.invitroAssayScreenings.forEach(screening => { - if (screening) { - if (screening._show == true) { - screening.invitroAssayResultInformation = this.assayResultInfo; - } - } - }); + this.overlayContainer.style.zIndex = '1002'; - // delete _show field before saving - this.firstAssayToSave.invitroAssayScreenings.forEach(screening => { - if (screening) { - if (screening._show) { - delete screening._show; - } - } - }); + dialogRef.afterClosed().subscribe(result => { + this.overlayContainer.style.zIndex = null; + }); + } - // Assign assay to Servive assay - this.invitroPharmacologyService.assay = this.firstAssayToSave; - } + close() { + this.dialog.closeAll(); } - saveFirstNewAssay() { - this.loadingService.setLoading(true); - this.isLoading = true; + /************************************************************************************************** */ + /****************************************************************************************************/ + /* SAVING ASSAY/SCREEING FUNCTIONS BEGIN */ + /************************************************************************************************** */ - this.isSavedSuccessfullyMessage = []; + saveAssays() { - // If saving Assays for existing Result - if (this.id) { - this.saveRemainingAssays(false); - } else { + this.openModalSave(this.saveTemplate); - // Registering NEW Screening, Saving the FIRST Assay - // Create First Assay To Save - if (this.firstAssayToSave == null) { - this.createFirstAssayToSave(); - } + // Create new Summary Record from Screening/Result record + this.createNewSummary(); - // Create Summary Object to copy Result data - this.createNewSummary(); + // Copy the Assays/Screening to new variable + this.assaysToSave = _.cloneDeep(this.existingAssaysByAssaySetList); - const saveFirstAssaySubscribe = this.invitroPharmacologyService.saveAssay().subscribe(response => { + this.generateAssayToSave(); + } - //Add a counter for each assay get saved - this.assaySavedCounter = this.assaySavedCounter + 1; + generateAssayToSave() { + let isAssaySame = false; + let assayToSaveApiUrlList: Array = []; - if (response) { - // Clear validation and submission message - //this.loadingService.setLoading(false); - //this.isLoading = false; - this.validationMessages = null; - this.showSubmissionMessages = false; - this.submissionMessage = ''; - - if (response.id) { - if (response.invitroAssayScreenings.length > 0) { - - // Store in the list if this record was stored into the database successfully or not - this.isSavedSuccessfullyMessage.push(this.assaySavedCounter + '|' + response.id + '|' + 'true'); - - // Get the last screening from the returned/saved Assay - let screening = response.invitroAssayScreenings[response.invitroAssayScreenings.length - 1]; - - // Get the saved result information from the database - // set invitroAssayResultInformation to local variable - if (screening.invitroAssayResultInformation) { - this.firstAssaySavedResultInfo = screening.invitroAssayResultInformation; - - // if ** ONLY ONE ** record exists, go to edit page, otherwise save rest of the assays - if (this.existingAssaysByAssaySetList.length == 1) { - - this.isLoading = false; - this.loadingService.setLoading(this.isLoading); - - this.submissionMessage = 'In-vitro Pharmacology Assay Screening data was saved successfully!'; - this.showSubmissionMessages = true; - - setTimeout(() => { - this.showSubmissionMessages = false; - this.submissionMessage = ''; - if (response.id) { - this.invitroPharmacologyService.bypassUpdateCheck(); - const id = response.id; - this.router.routeReuseStrategy.shouldReuseRoute = () => false; - this.router.onSameUrlNavigation = 'reload'; - this.router.navigate(['/invitro-pharm/', this.firstAssaySavedResultInfo.id, 'edit']); - } - }, 4000); - } else { - - // remove the first screening, save the remaining screeing into the database - // this.existingAssaysByAssaySetList.splice(0, 1); - - // Save remaining assays - this.saveRemainingAssays(true); - } + let endIndex = this.numberOfRecordToSaveEndIndex * this.numberOfRecordToSaveParallel; - } // if invitroAssayResultInformation exists + while (this.numberOfRecordToSaveStartIndex < endIndex && this.numberOfRecordToSaveStartIndex < this.assaysToSave.length) { - } // if responseAssay.invitroAssayScreenings.length > 0 - } // if response.id // if saved successfully - } // if response + // Get Assay + let assay = this.assaysToSave[this.numberOfRecordToSaveStartIndex]; - }, (error: SubstanceFormResults) => { - this.showSubmissionMessages = true; - this.loadingService.setLoading(false); - this.isLoading = false; - this.submissionMessage = null; - if (error.validationMessages && error.validationMessages.length) { - this.validationResult = error.isSuccessfull; - this.validationMessages = error.validationMessages - .filter(message => message.messageType.toUpperCase() === 'ERROR' || message.messageType.toUpperCase() === 'WARNING'); - this.showSubmissionMessages = true; - } else { - this.submissionMessage = 'There was a problem with your submission'; - this.addServerError(error.serverError); - setTimeout(() => { - this.showSubmissionMessages = false; - this.submissionMessage = null; - }, 8000); - } - } - ); + // copy the Result Information on the last screening or where _show == true + // call copy, THIS LINE MUST be before deleteing the _show field in the next code - //); // save one Assay record first - this.subscriptions.push(saveFirstAssaySubscribe); - } // else + // if REGISTERING New Screeing record + if (!this.id) { - } + // if saving FIRST record, copy the form Assay Result Information + if (this.numberOfRecordToSaveStartIndex == 0) { - saveRemainingAssays(skipFirstRecord?: boolean) { + if (assay.invitroAssayScreenings.length > 0) { - let assayApiUrlList: any = []; + assay.invitroAssayScreenings.forEach(screening => { + if (screening) { + if (screening._show == true) { + // Set result information from the FORM for the first Assay Record + screening.invitroAssayResultInformation = this.assayResultInfo; + } + } + }); - const params = new HttpParams(); - const options = { - params: params, - type: 'JSON', - headers: { - 'Content-type': 'application/json' - } - }; + // delete _show field before saving + this.scrubShowFieldsSingle(assay); - const url = this.invitroPharmacologyService.apiBaseUrlWithInvitroPharmEntityUrl; + } // invitroAssayScreenings.length > 0 - // Check if the JSON same as original. If same json for invitroAssayResultInformation are not same - let isResultInfoSame = this.isJsonSame(this.originalAssayResultInfoFromDb, this.assayResultInfo); - if (isResultInfoSame == false) { - this.copyResultInfoForSaving(true); - } + } else { + // NOT FIRST Record in the list when REGISTERING NEW SCREENING + if (assay.invitroAssayScreenings.length > 0) { + + assay.invitroAssayScreenings.forEach(screening => { + if (screening) { + if (screening._show == true) { + // Set result information from the saved record. + if (this.originalAssayResultInfoFromDb) { + screening.invitroAssayResultInformation = this.originalAssayResultInfoFromDb; + } + } + } + }); - // Copy the screening to new variable - let remainingAssays = _.cloneDeep(this.existingAssaysByAssaySetList); + // delete _show field before saving + this.scrubShowFieldsSingle(assay); - // Remove extra fields before saving - this.scrubExtraFields(remainingAssays); + } // invitroAssayScreenings.length > 0 + } // else + } // if (!this.id) // Registering New Screeing + else { + // UPDATING the existing Screening Records - remainingAssays.forEach((assay, indexAssay) => { - if (assay) { + // Check if the JSON same as original. If same json for invitroAssayResultInformation do not save + let isResultInfoSame = this.isJsonSame(this.originalAssayResultInfoFromDb, this.assayResultInfo); - let isAssaySame = false; - this.originalAssayFromDb.forEach(originalAssay => { - if (originalAssay) { - if (originalAssay.id) { - if (originalAssay.id == assay.id) { - isAssaySame = this.isJsonSame(originalAssay, assay); - } - } - } - }); + // Not Same, or record has been changed in the form + if (isResultInfoSame == false) { - // Only save to Database if the Assay record has changed otherwise will get server error "No Change Detected" - if (isAssaySame == false) { - // if registering new record, and invitroAssayResultInformation is null, assign the existing invitroAssayResultInformation - if (assay.invitroAssayScreenings[assay.invitroAssayScreenings.length - 1].invitroAssayResultInformation == null) { - assay.invitroAssayScreenings[assay.invitroAssayScreenings.length - 1].invitroAssayResultInformation = this.firstAssaySavedResultInfo; - } else { - // If No id found for invitroAssayResultInformation, copy the saved record - if (!assay.invitroAssayScreenings[assay.invitroAssayScreenings.length - 1].invitroAssayResultInformation.id) { - assay.invitroAssayScreenings[assay.invitroAssayScreenings.length - 1].invitroAssayResultInformation = this.firstAssaySavedResultInfo; + assay.invitroAssayScreenings.forEach((screening, indexScreening) => { + // copy this Result Reference, Lab, Sponsor, Test Agent Info to assay object + if (screening._show == true) { + screening.invitroAssayResultInformation = this.assayResultInfo; } - } + }); + } - // Create API Url List to save into the database - if (skipFirstRecord == true && indexAssay == 0) { - // Do not save the first assay record - } else { + // delete _show field before saving + this.scrubShowFieldsSingle(assay); - // make 5 Rest Api calls one at a time - const apiUrl = this.http.put(url, assay, options) - .pipe( - //mergeMap((apiCall) => res, 5)) - shareReplay(1), catchError(error => { throw error; })); + if (assay) { + // Check if existing Assay has been updated. + this.originalAssaysFromDb.forEach(originalAssay => { + if (originalAssay) { + if (originalAssay.id) { + if (originalAssay.id == assay.id) { + isAssaySame = this.isJsonSame(originalAssay, assay); + } + } + } + }); + } // if assay - assayApiUrlList.push(apiUrl); + } // else if updating - } - } + // Create REST API Url for the assay + let apiUrl = this.createAssayApiUrl(assay); + assayToSaveApiUrlList.push(apiUrl); - } // if assay - }); // FOR LOOP: Assay to Save + this.numberOfRecordToSaveEndIndex++; + this.numberOfRecordToSaveStartIndex++; - let savedCount = 0; + } // while loop - // Save Assays into the database - forkJoin(assayApiUrlList).subscribe( - results => { - let resultList: any = []; - resultList = results; - // return list of array of the result - resultList.forEach(result => { - if (result.id) { - savedCount = savedCount + 1; - } - }); + // Save the record into the database if Assay/screening record has changed + this.saveRecordForkJoin(assayToSaveApiUrlList, isAssaySame); - // if all the records are saved, refresh the page - if (savedCount == assayApiUrlList.length) { - - this.reloadPageAfterSave(); + } - /* - this.validationMessages = null; - this.submissionMessage = 'In-vitro Pharmacology Assay Screening data was saved successfully!'; - this.showSubmissionMessages = true; - this.validationResult = false; + createAssayApiUrl(assay: any): any { + let apiUrl = null; - let forwardId = null; - if (this.firstAssaySavedResultInfo) { - if (this.firstAssaySavedResultInfo.id) { - forwardId = this.firstAssaySavedResultInfo.id; - } - } else if (this.id) { - forwardId = this.id; - } + const params = new HttpParams(); + const options = { + params: params, + type: 'JSON', + headers: { + 'Content-type': 'application/json' + } + }; - setTimeout(() => { - if (forwardId) { - this.invitroPharmacologyService.bypassUpdateCheck(); - //const id = response.id; - this.router.routeReuseStrategy.shouldReuseRoute = () => false; - this.router.onSameUrlNavigation = 'reload'; - this.router.navigate(['/invitro-pharm/', forwardId, 'edit']); - } else { - alert("Something went wrong while retrieving the In-vitro Pharmacology Screening data"); - } - }, 4000); */ - } - }, - ) // forkJoin + const url = this.invitroPharmacologyService.apiBaseUrlWithInvitroPharmEntityUrl; + // Rest Api calls + apiUrl = this.http.put(url, assay, options) + .pipe( + shareReplay(1), catchError(error => { throw error; })); - if (assayApiUrlList.length == 0) { - this.reloadPageAfterSave(); - } + return apiUrl; + } - /* - // Assign the assay to service assay - this.invitroPharmacologyService.assay = assay; + saveRecordForkJoin(assayApiUrlList: any, isSameAssay: boolean) { - // Increment counter by 1 - this.assaySavedCounter = this.assaySavedCounter + 1; + let copyAssayApiUrlList = _.cloneDeep(assayApiUrlList); - const saveSubscribe = this.invitroPharmacologyService.saveAssay().subscribe(response => { + // Save Assays into the database + let savedCount = 0; - if (response) { + // Only save to Database if the Assay record has changed otherwise will get server error "No Change Detected" + if (isSameAssay == false) { + forkJoin(copyAssayApiUrlList).subscribe( + results => { + let resultList: any = []; + resultList = results; - // Get the last screening from the returned/saved Assay - // let screening = response.invitroAssayScreenings[response.invitroAssayScreenings.length - 1]; + // return list of array of the result + resultList.forEach(result => { + if (result.id) { + savedCount = savedCount + 1; + this.totalRecordSavedInDatabase = this.totalRecordSavedInDatabase + 1; - // Get the saved result information from the database - // set invitroAssayResultInformation to local variable - // if (screening.invitroAssayResultInformation) { - // this.firstAssaySavedResultInfo = screening.invitroAssayResultInformation; + if (result.invitroAssayScreenings.length > 0) { + // Get the last screening from the returned/saved Assay + let screening = result.invitroAssayScreenings[result.invitroAssayScreenings.length - 1]; - // Store in the list if this record was stored into the database successfully or not - this.isSavedSuccessfullyMessage.push(this.assaySavedCounter + '|' + response.id + '|' + 'true'); + // Get the saved result information from the database + // set invitroAssayResultInformation to local variable + if (screening.invitroAssayResultInformation) { - this.loadingService.setLoading(false); - this.isLoading = false; + // copy the Database/Original invitroAssayResultInformation in variable + this.originalAssayResultInfoFromDb = _.cloneDeep(screening.invitroAssayResultInformation); + } + } // invitroAssayScreenings.length > 0 - this.validationMessages = null; - this.submissionMessage = 'In-vitro Pharmacology Assay Screening data was saved successfully!'; - this.showSubmissionMessages = true; - this.validationResult = false; + } // if result.id + }); - setTimeout(() => { - // // this.showSubmissionMessages = false; - // this.submissionMessage = ''; - if (response.id) { - this.invitroPharmacologyService.bypassUpdateCheck(); - //const id = response.id; - this.router.routeReuseStrategy.shouldReuseRoute = () => false; - this.router.onSameUrlNavigation = 'reload'; - this.router.navigate(['/invitro-pharm/', this.id, 'edit']); + // if all the records are saved + if (savedCount == copyAssayApiUrlList.length) { + this.assayToSaveCallBack(); } - }, 4000); - } // if response remaining assays - }); - this.subscriptions.push(saveSubscribe); - */ + } // results + ); // forkJoin + } else { + // Do not save record into the database if Assay/Screening record has not been changed. + // increment count + this.totalRecordSavedInDatabase++; + this.assayToSaveCallBack(); + } } + assayToSaveCallBack() { + if (this.totalRecordSavedInDatabase != this.assaysToSave.length) { + // Save More Records + this.generateAssayToSave(); + } else { + // close the popup dialog + setTimeout(() => { + this.close(); + }, 4000); + + this.reloadPageAfterSave(); + } + } + reloadPageAfterSave() { this.validationMessages = null; this.submissionMessage = 'In-vitro Pharmacology Assay Screening data was saved successfully!'; @@ -1049,12 +971,13 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { this.validationResult = false; let forwardId = null; - if (this.firstAssaySavedResultInfo) { - if (this.firstAssaySavedResultInfo.id) { - forwardId = this.firstAssaySavedResultInfo.id; - } - } else if (this.id) { + + if (this.id) { forwardId = this.id; + } else if (this.originalAssayResultInfoFromDb) { + if (this.originalAssayResultInfoFromDb.id) { + forwardId = this.originalAssayResultInfoFromDb.id; + } } setTimeout(() => { @@ -1072,144 +995,10 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { this.loadingService.setLoading(false); }, 4000); - } - - /* - saveBulkAssays(skipFirstRecord?: boolean) { - let assayApiUrlList: any = []; - - const params = new HttpParams(); - const options = { - params: params, - type: 'JSON', - headers: { - 'Content-type': 'application/json' - } - }; - - const url = this.invitroPharmacologyService.apiBaseUrlWithInvitroPharmEntityUrl; - - // Create API Url List to save into the database - this.assaysToSave.forEach((assay, indexAssay) => { - if (skipFirstRecord == true && indexAssay == 0) { - // Do not save the first assay record - } else { - const apiUrl = this.http.put(url, assay, options).pipe( - catchError(error => { throw error; })); - - assayApiUrlList.push(apiUrl); - } - }); - - let savedCount = 0; - - // Save Assays into the database - forkJoin(assayApiUrlList).subscribe( - results => { - let resultList: any = []; - resultList = results; - // return list of array of the result - resultList.forEach(result => { - if (result.id) { - savedCount = savedCount + 1; - } - }); - // if all the records are saved, refresh the page - if (savedCount == assayApiUrlList.length) { - this.validationMessages = null; - this.submissionMessage = 'In-vitro Pharmacology Assay data was saved successfully!'; - this.showSubmissionMessages = true; - this.validationResult = false; - - setTimeout(() => { - this.showSubmissionMessages = false; - this.submissionMessage = ''; - this.invitroPharmacologyService.bypassUpdateCheck(); - this.router.routeReuseStrategy.shouldReuseRoute = () => false; - this.router.onSameUrlNavigation = 'reload'; - this.router.navigateByUrl('/invitro-pharm/assaySetBuilder?assaySet=' + this.selectedAssaySet); - }, 4000); - } - - this.isLoading = false; - this.loadingService.setLoading(false); - }, - ) } - */ - - submit(): void { - this.isLoading = true; - this.loadingService.setLoading(true); - - // Copy this when registering - // call copy, THIS LINE MUST be before this.scrubExtraFields() call - // if (!this.id) { - this.copyResultInfoForSaving(); - // } - // Remove extra fields before saving - this.scrubExtraFields(this.existingAssaysByAssaySetList); - - /* - this.invitroPharmacologyService.saveBulkAssays(this.existingAssaysByAssaySetList).subscribe(response => { - - this.loadingService.setLoading(false); - this.isLoading = false; - this.validationMessages = null; - this.submissionMessage = 'In-vitro Pharmacology Assay Screening data was saved successfully!'; - this.showSubmissionMessages = true; - this.validationResult = false; - setTimeout(() => { - this.showSubmissionMessages = false; - this.submissionMessage = ''; - - let id = null; - if (response) { - if (response[0].invitroAssayScreenings.length > 0) { - let indexScreeing = response[0].invitroAssayScreenings.length - 1; - - if (response[0].invitroAssayScreenings[indexScreeing].invitroAssayResultInformation) { - - if (response[0].invitroAssayScreenings[indexScreeing].invitroAssayResultInformation.id) { - - id = response[0].invitroAssayScreenings[indexScreeing].invitroAssayResultInformation.id; - if (id) { - // Saved Successfully, reload this update page - this.invitroPharmacologyService.bypassUpdateCheck(); - this.router.routeReuseStrategy.shouldReuseRoute = () => false; - this.router.onSameUrlNavigation = 'reload'; - this.router.navigate(['/invitro-pharm/', id, 'edit']); - } - } - } - } - } // response - }, 4000); - } */ - /* - , (error: SubstanceFormResults) => { - this.showSubmissionMessages = true; - this.loadingService.setLoading(false); - this.isLoading = false; - this.submissionMessage = null; - if (error.validationMessages && error.validationMessages.length) { - this.validationResult = error.isSuccessfull; - this.validationMessages = error.validationMessages - .filter(message => message.messageType.toUpperCase() === 'ERROR' || message.messageType.toUpperCase() === 'WARNING'); - this.showSubmissionMessages = true; - } else { - this.submissionMessage = 'There was a problem with your submission'; - this.addServerError(error.serverError); - setTimeout(() => { - this.showSubmissionMessages = false; - this.submissionMessage = null; - }, 8000); - } - }*/ - // ); - } + /* ******************* SAVING SCREEING FUNCTIONS END *************************************************/ showJSON(): void { const date = new Date(); @@ -1220,9 +1009,10 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { this.copyResultInfoForSaving(); } - let json = this.existingAssaysByAssaySetList; + let copyJson = _.cloneDeep(this.existingAssaysByAssaySetList); + let cleanJson = this.scrubShowFieldsMultiple(copyJson); - let data = {jsonData: json, jsonFilename: jsonFilename}; + let data = { jsonData: cleanJson, jsonFilename: jsonFilename }; const dialogRef = this.dialog.open(JsonDialogFdaComponent, { width: '90%', @@ -1318,11 +1108,39 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { }); } - addNewScreening(event: Event) { - this.invitroPharmacologyService.addNewScreening(); + createFirstAssayToSave() { + // Using this assay list in the form + if (this.existingAssaysByAssaySetList.length > 0) { + + // Get the first Assay from the list + this.firstAssayToSave = this.existingAssaysByAssaySetList[0]; + + // copy the Result Information on the last screening or where _show == true + // call copy, THIS LINE MUST be before deleteing the _show field in the next code + this.firstAssayToSave.invitroAssayScreenings.forEach(screening => { + if (screening) { + if (screening._show == true) { + screening.invitroAssayResultInformation = this.assayResultInfo; + } + } + }); + + // delete _show field before saving + this.firstAssayToSave.invitroAssayScreenings.forEach(screening => { + if (screening) { + if (screening._show) { + delete screening._show; + } + } + }); + + // Assign assay to Servive assay + this.invitroPharmacologyService.assay = this.firstAssayToSave; + } } createNewSummary() { + // Loop through each Assay this.existingAssaysByAssaySetList.forEach(assay => { @@ -1493,8 +1311,6 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { selectionChangeExistingReference(event) { if (event) { let reference = (event.split('||')); - // this.assay.invitroAssayScreenings[0].invitroReference.referenceSourceType = reference[0]; - // this.assay.invitroAssayScreenings[0].invitroReference.referenceSource = reference[1]; this.referenceMessage = ""; } @@ -1602,6 +1418,23 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { if (assay.invitroAssayScreenings[indexScreening].invitroAssayResult.testDate) { assay.invitroAssayScreenings[indexScreening].invitroAssayResult.testDate = ''; } + + if (assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinAdded) { + assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinAdded = false; + } + + if (assay.invitroAssayScreenings[indexScreening].invitroAssayResult.protein) { + assay.invitroAssayScreenings[indexScreening].invitroAssayResult.protein = ''; + } + + if (assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinConcentration) { + assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinConcentration = null; + } + + if (assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinConcentrationUnits) { + assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinConcentrationUnits = ''; + } + }); } @@ -1639,8 +1472,8 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinAdded = this.existingAssaysByAssaySetList[indexAssay].invitroAssayScreenings[indexFirstAssayScreening].invitroAssayResult.plasmaProteinAdded; } - if (!assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProtein) { - assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProtein = this.existingAssaysByAssaySetList[indexAssay].invitroAssayScreenings[indexFirstAssayScreening].invitroAssayResult.plasmaProtein; + if (!assay.invitroAssayScreenings[indexScreening].invitroAssayResult.protein) { + assay.invitroAssayScreenings[indexScreening].invitroAssayResult.protein = this.existingAssaysByAssaySetList[indexAssay].invitroAssayScreenings[indexFirstAssayScreening].invitroAssayResult.protein; } if (!assay.invitroAssayScreenings[indexScreening].invitroAssayResult.plasmaProteinConcentration) { @@ -1655,19 +1488,44 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { // } } - copyAssaySummaryRow(indexAssay: number) { - let indexAssayScreening = this.existingAssaysByAssaySetList[indexAssay].invitroAssayScreenings.length - 1; + copyAssayResultRow(indexCopyFromAssay: number) { + //let indexCopyAssayScreening = this.existingAssaysByAssaySetList[indexCopyFromAssay].invitroAssayScreenings.length - 1; + + let copyAssay = this.existingAssaysByAssaySetList[indexCopyFromAssay]; + + let newScreening = null; + this.existingAssaysByAssaySetList[indexCopyFromAssay].invitroAssayScreenings.forEach(copyFromScreening => { + if (copyFromScreening) { + if (copyFromScreening._show) { + let screen = _.cloneDeep(copyFromScreening); + + // remove the ids, create date, etc. + newScreening = this.scrub(screen); + newScreening._show = true; + } + } + }); - // Remove extra fields before saving - // this.scrubExtraFields(); + /* + const newInvitroAssayScreening: InvitroAssayScreening = + { + invitroAssayResultInformation: { invitroReferences: [], invitroLaboratory: {}, invitroSponsor: {}, invitroSponsorReport: { invitroSponsorSubmitters: [] }, invitroTestAgent: {} }, + invitroAssayResult: {}, + invitroControls: [{}], + invitroSummary: {} + }; + */ // Copy the assay to new variable - let copyAssay = _.cloneDeep(this.existingAssaysByAssaySetList[indexAssay]); - this.existingAssaysByAssaySetList.splice(indexAssay + 1, 0, copyAssay); + // let copyAssay = _.cloneDeep(this.existingAssaysByAssaySetList[indexCopyFromAssay]); + + copyAssay.invitroAssayScreenings.push(newScreening); + + // this.existingAssaysByAssaySetList.splice(indexCopyFromAssay + 1, 0, copyAssay); } - setPlasmaProteinCheckBox(checkBoxValue: any, screeningIndex: number): void { - this.assay.invitroAssayScreenings[screeningIndex].invitroAssayResult.plasmaProteinAdded = checkBoxValue; + setPlasmaProteinCheckBox($event, screeningIndex: number): void { + this.assay.invitroAssayScreenings[screeningIndex].invitroAssayResult.plasmaProteinAdded = $event.checked; } confirmDeleteSubmitter(indexSubmitter: number) { @@ -1721,10 +1579,6 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { isJsonSame(sourceJson: any, destinationJson: any) { let jsonSame = false; - console.log("SOURCE SOURCE: " + JSON.stringify(sourceJson)); - console.log("DESTIONATION " + JSON.stringify(destinationJson)); - - if ((sourceJson) && (destinationJson)) { if (JSON.stringify(sourceJson) == JSON.stringify(destinationJson)) { jsonSame = true; @@ -1733,8 +1587,18 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { return jsonSame; } - scrubExtraFields(assayToScrub) { - assayToScrub.forEach(assay => { + scrubShowFieldsSingle(assay) { + assay.invitroAssayScreenings.forEach(screening => { + if (screening) { + if (screening._show) { + delete screening._show; + } + } + }); + } + + scrubShowFieldsMultiple(assayArray): any { + assayArray.forEach(assay => { if (assay) { assay.invitroAssayScreenings.forEach(screening => { if (screening) { @@ -1745,6 +1609,8 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { }); } }); + return assayArray; + } scrub(oldraw: any): any { @@ -1761,7 +1627,7 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { delete showHolders[i]._show; } - const createHolders = defiant.json.search(old, '//*[creationDate]'); + const createHolders = defiant.json.search(old, '//*[createdDate]'); for (let i = 0; i < createHolders.length; i++) { delete createHolders[i].creationDate; } @@ -1771,7 +1637,7 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { delete createdByHolders[i].createdBy; } - const modifyHolders = defiant.json.search(old, '//*[lastModifiedDate]'); + const modifyHolders = defiant.json.search(old, '//*[modifiedDate]'); for (let i = 0; i < modifyHolders.length; i++) { delete modifyHolders[i].lastModifiedDate; } @@ -1786,10 +1652,10 @@ export class InvitroPharmacologyFormComponent implements OnInit, OnDestroy { delete intVersionHolders[i].internalVersion; } - delete old['creationDate']; + delete old['createdDate']; delete old['createdBy']; delete old['modifiedBy']; - delete old['lastModifiedDate']; + delete old['modifiedDate']; delete old['internalVersion']; delete old['$$update']; delete old['_self']; diff --git a/src/app/fda/invitro-pharmacology/model/invitro-pharmacology.model.ts b/src/app/fda/invitro-pharmacology/model/invitro-pharmacology.model.ts index 0c9d3900b..88728cee8 100644 --- a/src/app/fda/invitro-pharmacology/model/invitro-pharmacology.model.ts +++ b/src/app/fda/invitro-pharmacology/model/invitro-pharmacology.model.ts @@ -219,8 +219,8 @@ export interface InvitroAssayResult { resultValueUnits?: string; ligandSubstrateConcentration?: number; ligandSubstrateConcentrationUnits?: string; - plasmaProteinAdded?: string; - plasmaProtein?: string; + plasmaProteinAdded?: boolean; + protein?: string; plasmaProteinConcentration?: number; plasmaProteinConcentrationUnits?: string; batchNumber?: string; diff --git a/src/app/fda/invitro-pharmacology/service/invitro-pharmacology.service.ts b/src/app/fda/invitro-pharmacology/service/invitro-pharmacology.service.ts index 41ffc16ed..c9f8c5047 100644 --- a/src/app/fda/invitro-pharmacology/service/invitro-pharmacology.service.ts +++ b/src/app/fda/invitro-pharmacology/service/invitro-pharmacology.service.ts @@ -493,7 +493,7 @@ export class InvitroPharmacologyService extends BaseHttpService { addNewScreening(): void { const newInvitroAssayScreening: InvitroAssayScreening = { - invitroAssayResultInformation: { invitroReferences: [], invitroLaboratory: {}, invitroSponsor: {}, invitroSponsorReport: {invitroSponsorSubmitters: []}, invitroTestAgent: {}}, + invitroAssayResultInformation: { invitroReferences: [], invitroLaboratory: {}, invitroSponsor: {}, invitroSponsorReport: { invitroSponsorSubmitters: [] }, invitroTestAgent: {} }, invitroAssayResult: {}, invitroControls: [{}], invitroSummary: {} @@ -555,4 +555,5 @@ export class InvitroPharmacologyService extends BaseHttpService { return referenceSourceTypeAndId; } + } \ No newline at end of file diff --git a/src/app/fda/product/product-details/product-details-base.component.ts b/src/app/fda/product/product-details/product-details-base.component.ts index ccdb66ce5..daacfd47c 100644 --- a/src/app/fda/product/product-details/product-details-base.component.ts +++ b/src/app/fda/product/product-details/product-details-base.component.ts @@ -353,7 +353,7 @@ export class ProductDetailsBaseComponent implements OnInit, AfterViewInit, OnDes const dialogRef = this.dialog.open(StructureImageModalComponent, { height: '90%', - width: '680px', + width: '650px', panelClass: 'structure-image-panel', data: data }); @@ -361,10 +361,10 @@ export class ProductDetailsBaseComponent implements OnInit, AfterViewInit, OnDes this.overlayContainer.style.zIndex = '1002'; const subscription = dialogRef.afterClosed().subscribe(() => { - this.overlayContainer.style.zIndex = '1002'; + this.overlayContainer.style.zIndex = null; subscription.unsubscribe(); }, () => { - this.overlayContainer.style.zIndex = '1002'; + this.overlayContainer.style.zIndex = null; subscription.unsubscribe(); }); } diff --git a/src/app/fda/product/product-details/product-details/product-details.component.html b/src/app/fda/product/product-details/product-details/product-details.component.html index e02c87f49..30b6d1003 100644 --- a/src/app/fda/product/product-details/product-details/product-details.component.html +++ b/src/app/fda/product/product-details/product-details/product-details.component.html @@ -26,7 +26,7 @@ + download="{{jsonFilename}}.json" matTooltip='Download JSON'>   @@ -329,7 +329,7 @@
    - Denominator: +  Denominator: {{ prodIngred.originalDenominatorNumber }} {{ prodIngred.originalDenominatorUnit }} @@ -408,7 +408,7 @@
    -
    +
    @@ -433,7 +433,7 @@
    - Denominator: +  Denominator: {{ prodIngred.originalDenominatorNumber }} {{ prodIngred.originalDenominatorUnit }} diff --git a/src/app/fda/product/product-text-search/product-text-search.component.ts b/src/app/fda/product/product-text-search/product-text-search.component.ts index db14b7189..49fd502d2 100644 --- a/src/app/fda/product/product-text-search/product-text-search.component.ts +++ b/src/app/fda/product/product-text-search/product-text-search.component.ts @@ -58,43 +58,56 @@ export class ProductTextSearchComponent implements OnInit, AfterViewInit, OnDest }) ).subscribe((response: SubstanceSuggestionsGroup) => { this.substanceSuggestionsGroup = response; - let showTypes = ['Active_Moiety', 'Dosage_Form_Name', 'Marketing_Category_Name', 'Ingredient_Approval_ID', 'Product_Name', 'Ingredient_Type', 'Company_Country', 'Route_of_Admin', 'Labeler_Name', 'Application_Type_Number', 'Ingredient_Name', 'Nonproprietary_Name', 'Product_Type']; - /* if(this.configService && this.configService.configData && this.configService.configData.typeaheadFields) { - showTypes = this.configService.configData.typeaheadFields; - } */ + let showTypes = ['Active_Moiety', 'Product_Name', 'Product_Type', 'Dosage_Form_Name', 'Marketing_Category_Name', + 'Marketing_Category_Code', 'Ingredient_Name', 'Ingredient_Name_(Preferred)', 'Ingredient_Type', + 'Route_of_Administration', 'Labeler_Name', 'Labeler_Code', 'Labeler_State', 'Company_Role', 'Company_Country', + 'Manufacturer_Name', 'Manufacturer_Role', 'Application_Type', 'Application_Number', 'Application_Type_Number']; + this.suggestionsFields = Object.keys(this.substanceSuggestionsGroup).filter(function (item) { return showTypes.indexOf(item) > -1; }); - // this.suggestionsFields.sort(function (x, y) { return x === 'Display_Name' ? -1 : y === 'Display_Name' ? 1 : 0; }); + this.suggestionsFields.forEach((value, index) => { if (value === 'Active_Moiety') { this.suggestionsFields[index] = { value: 'Active_Moiety', display: 'Active Moiety' }; + } else if (value === 'Product_Name') { + this.suggestionsFields[index] = { value: 'Product_Name', display: 'Product Name' }; + } else if (value === 'Product_Type') { + this.suggestionsFields[index] = { value: 'Product_Type', display: 'Product Type' }; } else if (value === 'Dosage_Form_Name') { this.suggestionsFields[index] = { value: 'Dosage_Form_Name', display: 'Dosage Form Name' }; } else if (value === 'Marketing_Category_Name') { this.suggestionsFields[index] = { value: 'Marketing_Category_Name', display: 'Marketing Category Name' }; + } else if (value === ' Marketing_Category_Code') { + this.suggestionsFields[index] = { value: 'Marketing_Category_Code', display: 'Marketing Category Code' }; } else if (value === 'Ingredient_Name') { this.suggestionsFields[index] = { value: 'Ingredient_Name', display: 'Ingredient Name' }; - } else if (value === 'Ingredient_Approval_ID') { - this.suggestionsFields[index] = { value: 'Ingredient_Approval_ID', display: 'Ingredient Approval ID' }; - } else if (value === 'Product_Name') { - this.suggestionsFields[index] = { value: 'Product_Name', display: 'Product Name' }; + } else if (value === 'Ingredient_Name_(Preferred)') { + this.suggestionsFields[index] = { value: 'Ingredient_Name_(Preferred)', display: 'Ingredient Name (Preferred)' }; } else if (value === 'Ingredient_Type') { this.suggestionsFields[index] = { value: 'Ingredient_Type', display: 'Ingredient Type' }; - } else if (value === 'Company_Country') { - this.suggestionsFields[index] = { value: 'Company_Country', display: 'Company Country' }; - } else if (value === 'Route_of_Admin') { - this.suggestionsFields[index] = { value: 'Route_of_Admin', display: 'Route of Administration' }; + } else if (value === 'Route_of_Administration') { + this.suggestionsFields[index] = { value: 'Route_of_Administration', display: 'Route of Administration' }; } else if (value === 'Labeler_Name') { this.suggestionsFields[index] = { value: 'Labeler_Name', display: 'Labeler Name' }; + } else if (value === 'Labeler_Code') { + this.suggestionsFields[index] = { value: 'Labeler_Code', display: 'Labeler Code' }; + } else if (value === 'Labeler_State') { + this.suggestionsFields[index] = { value: 'Labeler_State', display: 'Labeler State' }; + } else if (value === 'Company_Role') { + this.suggestionsFields[index] = { value: 'Company_Role', display: 'Company Role' }; + } else if (value === 'Company_Country') { + this.suggestionsFields[index] = { value: 'Company_Country', display: 'Company Country' }; + } else if (value === 'Manufacturer_Name') { + this.suggestionsFields[index] = { value: 'Manufacturer_Name', display: 'Manufacturer Name' }; + } else if (value === 'Manufacturer_Role') { + this.suggestionsFields[index] = { value: 'Manufacturer_Role', display: 'Manufacturer Role' }; + } else if (value === 'Application_Type') { + this.suggestionsFields[index] = { value: 'Application_Type', display: 'Application Type' }; + } else if (value === 'Application_Number') { + this.suggestionsFields[index] = { value: 'Application_Number', display: 'Application Number' }; } else if (value === 'Application_Type_Number') { this.suggestionsFields[index] = { value: 'Application_Type_Number', display: 'Application Type Number' }; - } else if (value === 'Ingredient_Name') { - this.suggestionsFields[index] = { value: 'Ingredient_Name', display: 'Ingredient Name' }; - } else if (value === 'Nonproprietary_Name') { - this.suggestionsFields[index] = { value: 'Nonproprietary_Name', display: 'Nonproprietary Name' }; - } else if (value === 'Product_Type') { - this.suggestionsFields[index] = { value: 'Product_Type', display: 'Product Type' }; } else { this.suggestionsFields[index] = { value: value, display: value }; } diff --git a/src/app/fda/product/products-browse/products-browse.component.html b/src/app/fda/product/products-browse/products-browse.component.html index 325eee944..7e40da575 100644 --- a/src/app/fda/product/products-browse/products-browse.component.html +++ b/src/app/fda/product/products-browse/products-browse.component.html @@ -130,15 +130,6 @@ - -
    @@ -198,26 +189,39 @@ + + + + + @@ -294,11 +302,6 @@ + + + + +
    Product Code + + + + View + + + +   + + + + + Product Code - - - - - {{prodCode.productCode}} - - (NO ID) - + - - - - + +

    + {{prodCode.productCode}} +
    + (NO ID)
    @@ -228,11 +232,15 @@
    Product Name -
    -
    - {{prodName.productName}} +
      +
      +
      +
    1. + {{prodName.productName}} +
    2. +
      -
    +
    Labeler Name {{product.labelerName}} -
    {{prodComp.companyName}} @@ -313,6 +316,19 @@
    Provenance +
      +
      +
    1. + {{prodProv.provenance}} +
    2. +
      +
    +
    Country @@ -411,10 +427,19 @@ +
    + + + + article +   + +
    +
    - @@ -435,7 +460,8 @@
    - + + @@ -605,7 +631,7 @@
    - Route of Admin: + Route of Administration:
    {{product.routeAdmin}} @@ -722,18 +748,41 @@
    - - + + +
    + Average: + {{prodIngred.average}} {{prodIngred.unit}} + +
    - --> -
    +
    + +
    + + Numerator: + {{ prodIngred.originalNumeratorNumber }} {{ + prodIngred.originalNumeratorUnit + }} + + + +
    + + +
    + +   Denominator: + {{ prodIngred.originalDenominatorNumber }} {{ + prodIngred.originalDenominatorUnit + }} + + + +
    +
    @@ -804,53 +853,48 @@
    - - - + + +
    + Average: + {{prodIngred.average}} {{prodIngred.unit}} + +
    - --> - +
    + +
    + + Numerator: + {{ prodIngred.originalNumeratorNumber }} {{ + prodIngred.originalNumeratorUnit + }} + + + +
    + + +
    + +   Denominator: + {{ prodIngred.originalDenominatorNumber }} {{ + prodIngred.originalDenominatorUnit + }} + + + +
    + +
    ({{ prodIngred.ingredientType }})
    - - - @@ -861,7 +905,6 @@ - diff --git a/src/app/fda/product/products-browse/products-browse.component.scss b/src/app/fda/product/products-browse/products-browse.component.scss index f270191ba..35a29d790 100644 --- a/src/app/fda/product/products-browse/products-browse.component.scss +++ b/src/app/fda/product/products-browse/products-browse.component.scss @@ -1004,6 +1004,10 @@ width:150px; padding-bottom: 7px; } +.width100px { + width: 100px; +} + .width120px { width: 120px; } diff --git a/src/app/fda/product/products-browse/products-browse.component.ts b/src/app/fda/product/products-browse/products-browse.component.ts index 6f29e20ae..ba28854da 100644 --- a/src/app/fda/product/products-browse/products-browse.component.ts +++ b/src/app/fda/product/products-browse/products-browse.component.ts @@ -5,6 +5,7 @@ import { MatDialog } from '@angular/material/dialog'; import { DomSanitizer } from '@angular/platform-browser'; import { Location, LocationStrategy } from '@angular/common'; import { OverlayContainer } from '@angular/cdk/overlay'; +import * as defiant from '@gsrs-core/../../../node_modules/defiant.js/dist/defiant.min.js'; import * as _ from 'lodash'; import * as moment from 'moment'; import { Sort } from '@angular/material/sort'; @@ -28,6 +29,7 @@ import { Facet, FacetParam, FacetsManagerService, FacetUpdateEvent } from '@gsrs import { DisplayFacet } from '@gsrs-core/facets-manager/display-facet'; import { ExportDialogComponent } from '@gsrs-core/substances-browse/export-dialog/export-dialog.component'; import { StructureImageModalComponent, StructureService } from '@gsrs-core/structure'; +import { JsonDialogFdaComponent } from '../../json-dialog-fda/json-dialog-fda.component'; /* GSRS Product Imports */ import { GeneralService } from '../../service/general.service'; @@ -95,10 +97,12 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy ascDescDir = 'desc'; public displayedColumns: string[] = [ + 'viewDetails', 'productCode', 'productName', 'ingredientName', 'labelerName', + 'provenance', 'country', 'status', 'productNameType', @@ -350,7 +354,6 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy if (sort.active) { const orderIndex = this.displayedColumns.indexOf(sort.active).toString(); this.ascDescDir = sort.direction; - alert("AAAAAAAAAAAAAA" + this.ascDescDir); this.sortValues.forEach(sortValue => { if (sortValue.displayedColumns && sortValue.direction) { if (this.displayedColumns[orderIndex] === sortValue.displayedColumns && this.ascDescDir === sortValue.direction) { @@ -540,7 +543,7 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy }); }); */ - + } // response }); this.subscriptions.push(substanceSubscription); @@ -641,18 +644,18 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy const dialogRef = this.dialog.open(StructureImageModalComponent, { height: '90%', - width: '680px', + width: '650px', panelClass: 'structure-image-panel', data: data }); - this.overlayContainer.style.zIndex = '1001'; + this.overlayContainer.style.zIndex = '1002'; const subscription = dialogRef.afterClosed().subscribe(() => { - this.overlayContainer.style.zIndex = '1001'; + this.overlayContainer.style.zIndex = null; subscription.unsubscribe(); }, () => { - this.overlayContainer.style.zIndex = '1001'; + this.overlayContainer.style.zIndex = null; subscription.unsubscribe(); }); } @@ -676,9 +679,31 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy }); } - saveJSON(productId: number): void { - let json = this.products[productId]; - const uri = this.sanitizer.bypassSecurityTrustUrl('data:text/json;charset=UTF-8,' + encodeURIComponent(JSON.stringify(json))); + showJSON(productIndex: number): void { + const date = new Date(); + let jsonFilename = 'product_' + moment(date).format('MMM-DD-YYYY_H-mm-ss'); + + const copyProd = _.cloneDeep(this.products[productIndex]); + let cleanProduct = this.scrub(copyProd); + + let data = {jsonData: cleanProduct, jsonFilename: jsonFilename}; + + const dialogRef = this.dialog.open(JsonDialogFdaComponent, { + width: '90%', + height: '90%', + data: data + }); + + const dialogSubscription = dialogRef.afterClosed().subscribe(response => { + }); + this.subscriptions.push(dialogSubscription); + } + + saveJSON(productIndex: number): void { + const copyProd = _.cloneDeep(this.products[productIndex]); + let cleanProduct = this.scrub(copyProd); + + const uri = this.sanitizer.bypassSecurityTrustUrl('data:text/json;charset=UTF-8,' + encodeURIComponent(JSON.stringify(cleanProduct))); this.downloadJsonHref = uri; const date = new Date(); @@ -707,4 +732,61 @@ export class ProductsBrowseComponent implements OnInit, AfterViewInit, OnDestroy this.showMoreLessOtherIngredArray[indexProd] = !this.showMoreLessOtherIngredArray[indexProd]; } + scrub(oldraw: any): any { + const old = oldraw; + + const activeMoietyHolders = defiant.json.search(old, '//*[_ingredientNameActiveMoieties]'); + for (let i = 0; i < activeMoietyHolders.length; i++) { + if (activeMoietyHolders[i]._ingredientNameActiveMoieties) { + delete activeMoietyHolders[i]._ingredientNameActiveMoieties; + } + } + + const basisOfStrenghActiveMoietyHolders = defiant.json.search(old, '//*[_basisOfStrengthActiveMoieties]'); + for (let i = 0; i < basisOfStrenghActiveMoietyHolders.length; i++) { + if (basisOfStrenghActiveMoietyHolders[i]._basisOfStrengthActiveMoieties) { + delete basisOfStrenghActiveMoietyHolders[i]._basisOfStrengthActiveMoieties; + } + } + + const basisOfStrengthSubUuidHolders = defiant.json.search(old, '//*[_basisOfStrengthSubstanceUuid]'); + for (let i = 0; i < basisOfStrengthSubUuidHolders.length; i++) { + if (basisOfStrengthSubUuidHolders[i]._basisOfStrengthSubstanceUuid) { + delete basisOfStrengthSubUuidHolders[i]._basisOfStrengthSubstanceUuid; + } + } + + const basisOfStrengthIngNameHolders = defiant.json.search(old, '//*[_basisOfStrengthIngredientName]'); + for (let i = 0; i < basisOfStrengthIngNameHolders.length; i++) { + if (basisOfStrengthIngNameHolders[i]._basisOfStrengthIngredientName) { + delete basisOfStrengthIngNameHolders[i]._basisOfStrengthIngredientName; + } + } + + const substanceUuidHolders = defiant.json.search(old, '//*[_substanceUuid]'); + for (let i = 0; i < substanceUuidHolders.length; i++) { + if (substanceUuidHolders[i]._substanceUuid) { + delete substanceUuidHolders[i]._substanceUuid; + } + } + + const ingredientNameHolders = defiant.json.search(old, '//*[_ingredientName]'); + for (let i = 0; i < ingredientNameHolders.length; i++) { + if (ingredientNameHolders[i]._ingredientName) { + delete ingredientNameHolders[i]._ingredientName; + } + } + + const approvalIdHolders = defiant.json.search(old, '//*[_approvalId]'); + for (let i = 0; i < approvalIdHolders.length; i++) { + if (approvalIdHolders[i]._approvalId) { + delete approvalIdHolders[i]._approvalId; + } + } + + delete old['_activeIngredients']; + delete old['_otherIngredients']; + + return old; + } } diff --git a/src/app/fda/service/general.service.ts b/src/app/fda/service/general.service.ts index d8fb51fa0..8fa0d3bc4 100644 --- a/src/app/fda/service/general.service.ts +++ b/src/app/fda/service/general.service.ts @@ -88,9 +88,10 @@ export class GeneralService extends BaseHttpService { if (results) { results.forEach((codeObj, index) => { if (codeObj) { - - if ((codeObj.codeSystem) && ((codeObj.codeSystem === 'BDNUM') && (codeObj.type === 'PRIMARY'))) { - substanceKey = codeObj.code; + if ((codeObj.codeSystem) && (codeObj.codeSystem === 'BDNUM')) { + if (codeObj.type === 'PRIMARY') { + substanceKey = codeObj.code; + } } } });