moved connected sources list to its own component.

adding medical sources filter component for left menu with pipe for code => category name.
filter component can exand and shrink wiht animations

TODO: clear checkbox list when query changes.
This commit is contained in:
Jason Kulatunga 2023-05-08 22:11:21 -07:00
parent 551c7cbd42
commit 4c680a6c42
16 changed files with 1821 additions and 1313 deletions

View File

@ -0,0 +1,57 @@
<h2 class="az-content-title">Connected Sources</h2>
<div *ngIf="!loading else isLoadingTemplate" class="row">
<div *ngFor="let sourceInfo of connectedSourceList" class="col-sm-3 mg-b-20 px-3">
<div class="card h-100 d-flex align-items-center justify-content-center mt-3 mt-3 rounded-0 cursor-pointer">
<div (click)="openModal(contentModalRef, sourceInfo)" class="card-body">
<div class="h-100 d-flex align-items-center">
<img [src]="'assets/sources/'+(sourceInfo.metadata.brand_logo ? sourceInfo.metadata.brand_logo : sourceInfo.metadata.source_type+'.png')" [alt]="sourceInfo?.metadata.display" class="img-fluid">
</div>
<div *ngIf="status[sourceInfo.metadata?.source_type]" class="progress">
<div [style.width]="status[sourceInfo?.metadata?.source_type] == 'authorize' ? '33%' : '66%'" class="bg-indigo progress-bar progress-bar-striped progress-bar-animated" role="progressbar"></div>
</div>
</div>
<div class="card-footer text-center p-1" style="width:100%">
<small class="tx-gray-700">
{{sourceInfo?.metadata.display}}
</small>
</div>
</div>
</div>
</div>
<ng-template #contentModalRef let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{modalSelectedSourceListItem?.metadata["display"]}}</h4>
<button type="button" class="btn btn-close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<h6>Manage Source</h6>
<p>Existing connections can be "Synced", "Reconnected" or "Deleted"</p>
<ul>
<li><p><strong>Sync</strong> - Download all resources from this healthcare provider, storing them securely in Fasten</p></li>
<li><p><strong>Reconnect</strong> - If your healthcare connection has expired, you can use this button to reconnect</p></li>
<li><p><strong>Delete</strong> - Delete all resources for this healthcare provider. This will ONLY effect data stored in Fasten</p></li>
</ul>
</div>
<div class="modal-footer">
<button (click)="sourceSyncHandler(modalSelectedSourceListItem.source)" type="button" class="btn btn-indigo">Sync</button>
<!-- <button (click)="connectHandler($event, modalSelectedSourceListItem.source['source_type'])" type="button" class="btn btn-outline-light">Reconnect</button>-->
<button type="button" class="btn btn-outline-danger">Delete</button>
<button (click)="modal.dismiss('Close click')" type="button" class="btn btn-outline-light">Close</button>
</div>
</ng-template>
<ng-template #isLoadingTemplate>
<div class="row">
<div class="col-12">
<app-loading-spinner [loadingTitle]="'Please wait, loading sources...'"></app-loading-spinner>
</div>
</div>
</ng-template>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MedicalSourcesConnectedComponent } from './medical-sources-connected.component';
describe('MedicalSourcesConnectedComponent', () => {
let component: MedicalSourcesConnectedComponent;
let fixture: ComponentFixture<MedicalSourcesConnectedComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MedicalSourcesConnectedComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(MedicalSourcesConnectedComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,89 @@
import {Component, Input, OnInit} from '@angular/core';
import {Source} from '../../models/fasten/source';
import {SourceListItem} from '../../pages/medical-sources/medical-sources.component';
import {ModalDismissReasons, NgbModal} from '@ng-bootstrap/ng-bootstrap';
import {FastenApiService} from '../../services/fasten-api.service';
import {forkJoin} from 'rxjs';
import {LighthouseService} from '../../services/lighthouse.service';
@Component({
selector: 'app-medical-sources-connected',
templateUrl: './medical-sources-connected.component.html',
styleUrls: ['./medical-sources-connected.component.scss']
})
export class MedicalSourcesConnectedComponent implements OnInit {
loading: boolean = false
status: { [name: string]: string } = {}
modalSelectedSourceListItem:SourceListItem = null;
modalCloseResult = '';
connectedSourceList: SourceListItem[] = [] //source's are populated for this list
constructor(
private lighthouseApi: LighthouseService,
private fastenApi: FastenApiService,
private modalService: NgbModal,
) { }
ngOnInit(): void {
this.loading = true
this.fastenApi.getSources().subscribe(results => {
this.loading = false
//handle connected sources sources
const connectedSources = results as Source[]
forkJoin(connectedSources.map((source) => this.lighthouseApi.getLighthouseSource(source.source_type))).subscribe((connectedMetadata) => {
for(const ndx in connectedSources){
this.connectedSourceList.push({source: connectedSources[ndx], metadata: connectedMetadata[ndx]})
}
})
})
}
public openModal(contentModalRef, sourceListItem: SourceListItem) {
if(this.status[sourceListItem.metadata.source_type] || !sourceListItem.source){
//if this source is currently "loading" dont open the modal window
return
}
this.modalSelectedSourceListItem = sourceListItem
this.modalService.open(contentModalRef, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
this.modalSelectedSourceListItem = null
this.modalCloseResult = `Closed with: ${result}`;
}, (reason) => {
this.modalSelectedSourceListItem = null
this.modalCloseResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
public sourceSyncHandler(source: Source){
this.status[source.source_type] = "authorize"
this.modalService.dismissAll()
this.fastenApi.syncSource(source.id).subscribe(
(respData) => {
delete this.status[source.source_type]
console.log("source sync response:", respData)
},
(err) => {
delete this.status[source.source_type]
console.log(err)
}
)
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
}

View File

@ -0,0 +1,8 @@
import { MedicalSourcesCategoryLookupPipe } from './medical-sources-category-lookup.pipe';
describe('MedicalSourcesCategoryLookupPipe', () => {
it('create an instance', () => {
const pipe = new MedicalSourcesCategoryLookupPipe();
expect(pipe).toBeTruthy();
});
});

View File

@ -0,0 +1,892 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'medicalSourcesCategoryLookup'
})
export class MedicalSourcesCategoryLookupPipe implements PipeTransform {
transform(categoryCode: string, ...args: unknown[]): string {
if (!categoryCode){
return null;
}
let lookupDescription = SOURCE_CATEGORY_CODE_LOOKUP[categoryCode];
if (!lookupDescription){
console.log("COULD NOT FIND CATEGORY CODE", categoryCode, "IN LOOKUP")
return categoryCode;
} else {
return lookupDescription;
}
}
}
const SOURCE_CATEGORY_CODE_LOOKUP = {
"101200000X": "Drama Therapist",
"101Y00000X": "Counselor",
"101YA0400X": "Addiction (Substance Use Disorder) Counselor",
"101YM0800X": "Mental Health Counselor",
"101YP1600X": "Pastoral Counselor",
"101YP2500X": "Professional Counselor",
"101YS0200X": "School Counselor",
"102L00000X": "Psychoanalyst",
"102X00000X": "Poetry Therapist",
"103G00000X": "Clinical Neuropsychologist",
"103GC0700X": "Deactivated - Clinical Neuropsychologist",
"103K00000X": "Behavioral Analyst",
"103T00000X": "Psychologist",
"103TA0400X": "Addiction (Substance Use Disorder) Psychologist",
"103TA0700X": "Adult Development & Aging Psychologist",
"103TB0200X": "Cognitive & Behavioral Psychologist",
"103TC0700X": "Clinical Psychologist",
"103TC1900X": "Counseling Psychologist",
"103TC2200X": "Clinical Child & Adolescent Psychologist",
"103TE1000X": "Deactivated - Psychologist",
"103TE1100X": "Exercise & Sports Psychologist",
"103TF0000X": "Family Psychologist",
"103TF0200X": "Forensic Psychologist",
"103TH0004X": "Health Psychologist",
"103TH0100X": "Health Service Psychologist",
"103TM1700X": "Deactivated - Psychologist Men & Masculinity",
"103TM1800X": "Intellectual & Developmental Disabilities Psychologist",
"103TP0016X": "Prescribing (Medical) Psychologist",
"103TP0814X": "Psychoanalysis Psychologist",
"103TP2700X": "Deactivated - Psychologist Psychotherapy",
"103TP2701X": "Group Psychotherapy Psychologist",
"103TR0400X": "Rehabilitation Psychologist",
"103TS0200X": "School Psychologist",
"103TW0100X": "Deactivated - Psychotherapy Women",
"104100000X": "Social Worker",
"1041C0700X": "Clinical Social Worker",
"1041S0200X": "School Social Worker",
"106E00000X": "Assistant Behavior Analyst",
"106H00000X": "Marriage & Family Therapist",
"106S00000X": "Behavior Technician",
"111N00000X": "Chiropractor",
"111NI0013X": "Independent Medical Examiner Chiropractor",
"111NI0900X": "Internist Chiropractor",
"111NN0400X": "Neurology Chiropractor",
"111NN1001X": "Nutrition Chiropractor",
"111NP0017X": "Pediatric Chiropractor",
"111NR0200X": "Radiology Chiropractor",
"111NR0400X": "Rehabilitation Chiropractor",
"111NS0005X": "Sports Physician Chiropractor",
"111NT0100X": "Thermography Chiropractor",
"111NX0100X": "Occupational Health Chiropractor",
"111NX0800X": "Orthopedic Chiropractor",
"122300000X": "Dentist",
"1223D0001X": "Public Health Dentist",
"1223D0004X": "Dentist Anesthesiologist",
"1223E0200X": "Endodontist",
"1223G0001X": "General Practice Dentistry",
"1223P0106X": "Oral and Maxillofacial Pathology Dentist",
"1223P0221X": "Pediatric Dentist",
"1223P0300X": "Periodontist",
"1223P0700X": "Prosthodontist",
"1223S0112X": "Oral and Maxillofacial Surgery (Dentist)",
"1223X0008X": "Oral and Maxillofacial Radiology Dentist",
"1223X0400X": "Orthodontics and Dentofacial Orthopedic Dentist",
"1223X2210X": "Orofacial Pain Dentist",
"122400000X": "Denturist",
"124Q00000X": "Dental Hygienist",
"125J00000X": "Dental Therapist",
"125K00000X": "Advanced Practice Dental Therapist",
"125Q00000X": "Oral Medicinist",
"126800000X": "Dental Assistant",
"126900000X": "Dental Laboratory Technician",
"132700000X": "Dietary Manager",
"133N00000X": "Nutritionist",
"133NN1002X": "Nutrition Education Nutritionist",
"133V00000X": "Registered Dietitian",
"133VN1004X": "Pediatric Nutrition Registered Dietitian",
"133VN1005X": "Renal Nutrition Registered Dietitian",
"133VN1006X": "Metabolic Nutrition Registered Dietitian",
"133VN1101X": "Gerontological Nutrition Registered Dietitian",
"133VN1201X": "Obesity and Weight Management Nutrition Registered Dietitian",
"133VN1301X": "Oncology Nutrition Registered Dietitian",
"133VN1401X": "Pediatric Critical Care Nutrition Registered Dietitian",
"133VN1501X": "Sports Dietetics Nutrition Registered Dietitian",
"136A00000X": "Registered Dietetic Technician",
"146D00000X": "Personal Emergency Response Attendant",
"146L00000X": "Paramedic",
"146M00000X": "Intermediate Emergency Medical Technician",
"146N00000X": "Basic Emergency Medical Technician",
"152W00000X": "Optometrist",
"152WC0802X": "Corneal and Contact Management Optometrist",
"152WL0500X": "Low Vision Rehabilitation Optometrist",
"152WP0200X": "Pediatric Optometrist",
"152WS0006X": "Sports Vision Optometrist",
"152WV0400X": "Vision Therapy Optometrist",
"152WX0102X": "Occupational Vision Optometrist",
"156F00000X": "Technician/Technologist",
"156FC0800X": "Contact Lens Technician/Technologist",
"156FC0801X": "Contact Lens Fitter",
"156FX1100X": "Ophthalmic Technician/Technologist",
"156FX1101X": "Ophthalmic Assistant",
"156FX1201X": "Optometric Assistant Technician",
"156FX1202X": "Optometric Technician",
"156FX1700X": "Ocularist",
"156FX1800X": "Optician",
"156FX1900X": "Orthoptist",
"163W00000X": "Registered Nurse",
"163WA0400X": "Addiction (Substance Use Disorder) Registered Nurse",
"163WA2000X": "Administrator Registered Nurse",
"163WC0200X": "Critical Care Medicine Registered Nurse",
"163WC0400X": "Case Management Registered Nurse",
"163WC1400X": "College Health Registered Nurse",
"163WC1500X": "Community Health Registered Nurse",
"163WC1600X": "Continuing Education/Staff Development Registered Nurse",
"163WC2100X": "Continence Care Registered Nurse",
"163WC3500X": "Cardiac Rehabilitation Registered Nurse",
"163WD0400X": "Diabetes Educator Registered Nurse",
"163WD1100X": "Peritoneal Dialysis Registered Nurse",
"163WE0003X": "Emergency Registered Nurse",
"163WE0900X": "Enterostomal Therapy Registered Nurse",
"163WF0300X": "Flight Registered Nurse",
"163WG0000X": "General Practice Registered Nurse",
"163WG0100X": "Gastroenterology Registered Nurse",
"163WG0600X": "Gerontology Registered Nurse",
"163WH0200X": "Home Health Registered Nurse",
"163WH0500X": "Hemodialysis Registered Nurse",
"163WH1000X": "Hospice Registered Nurse",
"163WI0500X": "Infusion Therapy Registered Nurse",
"163WI0600X": "Infection Control Registered Nurse",
"163WL0100X": "Lactation Consultant (Registered Nurse)",
"163WM0102X": "Maternal Newborn Registered Nurse",
"163WM0705X": "Medical-Surgical Registered Nurse",
"163WM1400X": "Nurse Massage Therapist (NMT)",
"163WN0002X": "Neonatal Intensive Care Registered Nurse",
"163WN0003X": "Low-Risk Neonatal Registered Nurse",
"163WN0300X": "Nephrology Registered Nurse",
"163WN0800X": "Neuroscience Registered Nurse",
"163WN1003X": "Nutrition Support Registered Nurse",
"163WP0000X": "Pain Management Registered Nurse",
"163WP0200X": "Pediatric Registered Nurse",
"163WP0218X": "Pediatric Oncology Registered Nurse",
"163WP0807X": "Child & Adolescent Psychiatric/Mental Health Registered Nurse",
"163WP0808X": "Psychiatric/Mental Health Registered Nurse",
"163WP0809X": "Adult Psychiatric/Mental Health Registered Nurse",
"163WP1700X": "Perinatal Registered Nurse",
"163WP2201X": "Ambulatory Care Registered Nurse",
"163WR0006X": "Registered Nurse First Assistant",
"163WR0400X": "Rehabilitation Registered Nurse",
"163WR1000X": "Reproductive Endocrinology/Infertility Registered Nurse",
"163WS0121X": "Plastic Surgery Registered Nurse",
"163WS0200X": "School Registered Nurse",
"163WU0100X": "Urology Registered Nurse",
"163WW0000X": "Wound Care Registered Nurse",
"163WW0101X": "Ambulatory Women's Health Care Registered Nurse",
"163WX0002X": "High-Risk Obstetric Registered Nurse",
"163WX0003X": "Inpatient Obstetric Registered Nurse",
"163WX0106X": "Occupational Health Registered Nurse",
"163WX0200X": "Oncology Registered Nurse",
"163WX0601X": "Otorhinolaryngology & Head-Neck Registered Nurse",
"163WX0800X": "Orthopedic Registered Nurse",
"163WX1100X": "Ophthalmic Registered Nurse",
"163WX1500X": "Ostomy Care Registered Nurse",
"164W00000X": "Licensed Practical Nurse",
"164X00000X": "Licensed Vocational Nurse",
"167G00000X": "Licensed Psychiatric Technician",
"170100000X": "Ph.D. Medical Genetics",
"170300000X": "Genetic Counselor (M.S.)",
"171000000X": "Military Health Care Provider",
"1710I1002X": "Independent Duty Corpsman",
"1710I1003X": "Independent Duty Medical Technicians",
"171100000X": "Acupuncturist",
"171400000X": "Health & Wellness Coach",
"171M00000X": "Case Manager/Care Coordinator",
"171R00000X": "Interpreter",
"171W00000X": "Contractor",
"171WH0202X": "Home Modifications Contractor",
"171WV0202X": "Vehicle Modifications Contractor",
"172A00000X": "Driver",
"172M00000X": "Mechanotherapist",
"172P00000X": "Naprapath",
"172V00000X": "Community Health Worker",
"173000000X": "Legal Medicine",
"173C00000X": "Reflexologist",
"173F00000X": "Sleep Specialist (PhD)",
"174200000X": "Meals Provider",
"174400000X": "Specialist",
"1744G0900X": "Graphics Designer",
"1744P3200X": "Prosthetics Case Management",
"1744R1102X": "Research Study Specialist",
"1744R1103X": "Research Study Abstracter/Coder",
"174H00000X": "Health Educator",
"174M00000X": "Veterinarian",
"174MM1900X": "Medical Research Veterinarian",
"174N00000X": "Lactation Consultant (Non-RN)",
"174V00000X": "Clinical Ethicist",
"175F00000X": "Naturopath",
"175L00000X": "Homeopath",
"175M00000X": "Lay Midwife",
"175T00000X": "Peer Specialist",
"176B00000X": "Midwife",
"176P00000X": "Funeral Director",
"177F00000X": "Lodging Provider",
"183500000X": "Pharmacist",
"1835C0205X": "Critical Care Pharmacist",
"1835G0000X": "Deactivated - Pharmacist",
"1835G0303X": "Geriatric Pharmacist",
"1835N0905X": "Nuclear Pharmacist",
"1835N1003X": "Nutrition Support Pharmacist",
"1835P0018X": "Pharmacist Clinician (PhC)/ Clinical Pharmacy Specialist",
"1835P0200X": "Pediatric Pharmacist",
"1835P1200X": "Pharmacotherapy Pharmacist",
"1835P1300X": "Psychiatric Pharmacist",
"1835P2201X": "Ambulatory Care Pharmacist",
"1835X0200X": "Oncology Pharmacist",
"183700000X": "Pharmacy Technician",
"193200000X": "Multi-Specialty Group",
"193400000X": "Single Specialty Group",
"202C00000X": "Independent Medical Examiner Physician",
"202D00000X": "Integrative Medicine",
"202K00000X": "Phlebology Physician",
"204C00000X": "Sports Medicine (Neuromusculoskeletal Medicine) Physician",
"204D00000X": "Neuromusculoskeletal Medicine & OMM Physician",
"204E00000X": "Oral & Maxillofacial Surgery (D.M.D.)",
"204F00000X": "Transplant Surgery Physician",
"204R00000X": "Electrodiagnostic Medicine Physician",
"207K00000X": "Allergy & Immunology Physician",
"207KA0200X": "Allergy Physician",
"207KI0005X": "Clinical & Laboratory Immunology (Allergy & Immunology) Physician",
"207L00000X": "Anesthesiology Physician",
"207LA0401X": "Addiction Medicine (Anesthesiology) Physician",
"207LC0200X": "Critical Care Medicine (Anesthesiology) Physician",
"207LH0002X": "Hospice and Palliative Medicine (Anesthesiology) Physician",
"207LP2900X": "Pain Medicine (Anesthesiology) Physician",
"207LP3000X": "Pediatric Anesthesiology Physician",
"207N00000X": "Dermatology Physician",
"207ND0101X": "MOHS-Micrographic Surgery Physician",
"207ND0900X": "Dermatopathology Physician",
"207NI0002X": "Clinical & Laboratory Dermatological Immunology Physician",
"207NP0225X": "Pediatric Dermatology Physician",
"207NS0135X": "Procedural Dermatology Physician",
"207P00000X": "Emergency Medicine Physician",
"207PE0004X": "Emergency Medical Services (Emergency Medicine) Physician",
"207PE0005X": "Undersea and Hyperbaric Medicine (Emergency Medicine) Physician",
"207PH0002X": "Hospice and Palliative Medicine (Emergency Medicine) Physician",
"207PP0204X": "Pediatric Emergency Medicine (Emergency Medicine) Physician",
"207PS0010X": "Sports Medicine (Emergency Medicine) Physician",
"207PT0002X": "Medical Toxicology (Emergency Medicine) Physician",
"207Q00000X": "Family Medicine Physician",
"207QA0000X": "Adolescent Medicine (Family Medicine) Physician",
"207QA0401X": "Addiction Medicine (Family Medicine) Physician",
"207QA0505X": "Adult Medicine Physician",
"207QB0002X": "Obesity Medicine (Family Medicine) Physician",
"207QG0300X": "Geriatric Medicine (Family Medicine) Physician",
"207QH0002X": "Hospice and Palliative Medicine (Family Medicine) Physician",
"207QS0010X": "Sports Medicine (Family Medicine) Physician",
"207QS1201X": "Sleep Medicine (Family Medicine) Physician",
"207R00000X": "Internal Medicine Physician",
"207RA0000X": "Adolescent Medicine (Internal Medicine) Physician",
"207RA0001X": "Advanced Heart Failure and Transplant Cardiology Physician",
"207RA0002X": "Adult Congenital Heart Disease Physician",
"207RA0201X": "Allergy & Immunology (Internal Medicine) Physician",
"207RA0401X": "Addiction Medicine (Internal Medicine) Physician",
"207RB0002X": "Obesity Medicine (Internal Medicine) Physician",
"207RC0000X": "Cardiovascular Disease Physician",
"207RC0001X": "Clinical Cardiac Electrophysiology Physician",
"207RC0200X": "Critical Care Medicine (Internal Medicine) Physician",
"207RE0101X": "Endocrinology, Diabetes & Metabolism Physician",
"207RG0100X": "Gastroenterology Physician",
"207RG0300X": "Geriatric Medicine (Internal Medicine) Physician",
"207RH0000X": "Hematology (Internal Medicine) Physician",
"207RH0002X": "Hospice and Palliative Medicine (Internal Medicine) Physician",
"207RH0003X": "Hematology & Oncology Physician",
"207RH0005X": "Hypertension Specialist Physician",
"207RI0001X": "Clinical & Laboratory Immunology (Internal Medicine) Physician",
"207RI0008X": "Hepatology Physician",
"207RI0011X": "Interventional Cardiology Physician",
"207RI0200X": "Infectious Disease Physician",
"207RM1200X": "Magnetic Resonance Imaging (MRI) Internal Medicine Physician",
"207RN0300X": "Nephrology Physician",
"207RP1001X": "Pulmonary Disease Physician",
"207RR0500X": "Rheumatology Physician",
"207RS0010X": "Sports Medicine (Internal Medicine) Physician",
"207RS0012X": "Sleep Medicine (Internal Medicine) Physician",
"207RT0003X": "Transplant Hepatology Physician",
"207RX0202X": "Medical Oncology Physician",
"207SC0300X": "Clinical Cytogenetics Physician",
"207SG0201X": "Clinical Genetics (M.D.) Physician",
"207SG0202X": "Clinical Biochemical Genetics Physician",
"207SG0203X": "Clinical Molecular Genetics Physician",
"207SG0205X": "Ph.D. Medical Genetics Physician",
"207SM0001X": "Molecular Genetic Pathology (Medical Genetics) Physician",
"207T00000X": "Neurological Surgery Physician",
"207U00000X": "Nuclear Medicine Physician",
"207UN0901X": "Nuclear Cardiology Physician",
"207UN0902X": "Nuclear Imaging & Therapy Physician",
"207UN0903X": "In Vivo & In Vitro Nuclear Medicine Physician",
"207V00000X": "Obstetrics & Gynecology Physician",
"207VB0002X": "Obesity Medicine (Obstetrics & Gynecology) Physician",
"207VC0200X": "Critical Care Medicine (Obstetrics & Gynecology) Physician",
"207VC0300X": "Complex Family Planning",
"207VE0102X": "Reproductive Endocrinology Physician",
"207VF0040X": "Female Pelvic Medicine and Reconstructive Surgery (Obstetrics & Gynecology) Physician",
"207VG0400X": "Gynecology Physician",
"207VH0002X": "Hospice and Palliative Medicine (Obstetrics & Gynecology) Physician",
"207VM0101X": "Maternal & Fetal Medicine Physician",
"207VX0000X": "Obstetrics Physician",
"207VX0201X": "Gynecologic Oncology Physician",
"207W00000X": "Ophthalmology Physician",
"207WX0009X": "Glaucoma Specialist (Ophthalmology) Physician",
"207WX0107X": "Retina Specialist (Ophthalmology) Physician",
"207WX0108X": "Uveitis and Ocular Inflammatory Disease (Ophthalmology) Physician",
"207WX0109X": "Neuro-ophthalmology Physician",
"207WX0110X": "Pediatric Ophthalmology and Strabismus Specialist Physician Physician",
"207WX0120X": "Cornea and External Diseases Specialist Physician",
"207WX0200X": "Ophthalmic Plastic and Reconstructive Surgery Physician",
"207X00000X": "Orthopaedic Surgery Physician",
"207XP3100X": "Pediatric Orthopaedic Surgery Physician",
"207XS0106X": "Orthopaedic Hand Surgery Physician",
"207XS0114X": "Adult Reconstructive Orthopaedic Surgery Physician",
"207XS0117X": "Orthopaedic Surgery of the Spine Physician",
"207XX0004X": "Orthopaedic Foot and Ankle Surgery Physician",
"207XX0005X": "Sports Medicine (Orthopaedic Surgery) Physician",
"207XX0801X": "Orthopaedic Trauma Physician",
"207Y00000X": "Otolaryngology Physician",
"207YP0228X": "Pediatric Otolaryngology Physician",
"207YS0012X": "Sleep Medicine (Otolaryngology) Physician",
"207YS0123X": "Facial Plastic Surgery Physician",
"207YX0007X": "Plastic Surgery within the Head & Neck (Otolaryngology) Physician",
"207YX0602X": "Otolaryngic Allergy Physician",
"207YX0901X": "Otology & Neurotology Physician",
"207YX0905X": "Otolaryngology/Facial Plastic Surgery Physician",
"207ZB0001X": "Blood Banking & Transfusion Medicine Physician",
"207ZC0006X": "Clinical Pathology Physician",
"207ZC0008X": "Clinical Informatics (Pathology) Physician",
"207ZC0500X": "Cytopathology Physician",
"207ZD0900X": "Dermatopathology (Pathology) Physician",
"207ZF0201X": "Forensic Pathology Physician",
"207ZH0000X": "Hematology (Pathology) Physician",
"207ZI0100X": "Immunopathology Physician",
"207ZM0300X": "Medical Microbiology Physician",
"207ZN0500X": "Neuropathology Physician",
"207ZP0007X": "Molecular Genetic Pathology (Pathology) Physician",
"207ZP0101X": "Anatomic Pathology Physician",
"207ZP0102X": "Anatomic Pathology & Clinical Pathology Physician",
"207ZP0104X": "Chemical Pathology Physician",
"207ZP0105X": "Clinical Pathology/Laboratory Medicine Physician",
"207ZP0213X": "Pediatric Pathology Physician",
"208000000X": "Pediatrics Physician",
"2080A0000X": "Pediatric Adolescent Medicine Physician",
"2080B0002X": "Pediatric Obesity Medicine Physician",
"2080C0008X": "Child Abuse Pediatrics Physician",
"2080H0002X": "Pediatric Hospice and Palliative Medicine Physician",
"2080I0007X": "Pediatric Clinical & Laboratory Immunology Physician",
"2080N0001X": "Neonatal-Perinatal Medicine Physician",
"2080P0006X": "Developmental - Behavioral Pediatrics Physician",
"2080P0008X": "Pediatric Neurodevelopmental Disabilities Physician",
"2080P0201X": "Pediatric Allergy/Immunology Physician",
"2080P0202X": "Pediatric Cardiology Physician",
"2080P0203X": "Pediatric Critical Care Medicine Physician",
"2080P0204X": "Pediatric Emergency Medicine (Pediatrics) Physician",
"2080P0205X": "Pediatric Endocrinology Physician",
"2080P0206X": "Pediatric Gastroenterology Physician",
"2080P0207X": "Pediatric Hematology & Oncology Physician",
"2080P0208X": "Pediatric Infectious Diseases Physician",
"2080P0210X": "Pediatric Nephrology Physician",
"2080P0214X": "Pediatric Pulmonology Physician",
"2080P0216X": "Pediatric Rheumatology Physician",
"2080S0010X": "Pediatric Sports Medicine Physician",
"2080S0012X": "Pediatric Sleep Medicine Physician",
"2080T0002X": "Pediatric Medical Toxicology Physician",
"2080T0004X": "Pediatric Transplant Hepatology Physician",
"208100000X": "Physical Medicine & Rehabilitation Physician",
"2081H0002X": "Hospice and Palliative Medicine (Physical Medicine & Rehabilitation) Physician",
"2081N0008X": "Neuromuscular Medicine (Physical Medicine & Rehabilitation) Physician",
"2081P0004X": "Spinal Cord Injury Medicine Physician",
"2081P0010X": "Pediatric Rehabilitation Medicine Physician",
"2081P0301X": "Brain Injury Medicine (Physical Medicine & Rehabilitation) Physician",
"2081P2900X": "Pain Medicine (Physical Medicine & Rehabilitation) Physician",
"2081S0010X": "Sports Medicine (Physical Medicine & Rehabilitation) Physician",
"208200000X": "Plastic Surgery Physician",
"2082S0099X": "Plastic Surgery Within the Head and Neck (Plastic Surgery) Physician",
"2082S0105X": "Surgery of the Hand (Plastic Surgery) Physician",
"2083A0100X": "Aerospace Medicine Physician",
"2083A0300X": "Addiction Medicine (Preventive Medicine) Physician",
"2083B0002X": "Obesity Medicine (Preventive Medicine) Physician",
"2083C0008X": "Clinical Informatics Physician",
"2083P0011X": "Undersea and Hyperbaric Medicine (Preventive Medicine) Physician",
"2083P0500X": "Preventive Medicine/Occupational Environmental Medicine Physician",
"2083P0901X": "Public Health & General Preventive Medicine Physician",
"2083S0010X": "Sports Medicine (Preventive Medicine) Physician",
"2083T0002X": "Medical Toxicology (Preventive Medicine) Physician",
"2083X0100X": "Occupational Medicine Physician",
"2084A0401X": "Addiction Medicine (Psychiatry & Neurology) Physician",
"2084A2900X": "Neurocritical Care Physician",
"2084B0002X": "Obesity Medicine (Psychiatry & Neurology) Physician",
"2084B0040X": "Behavioral Neurology & Neuropsychiatry Physician",
"2084D0003X": "Diagnostic Neuroimaging (Psychiatry & Neurology) Physician",
"2084E0001X": "Epilepsy Physician",
"2084F0202X": "Forensic Psychiatry Physician",
"2084H0002X": "Hospice and Palliative Medicine (Psychiatry & Neurology) Physician",
"2084N0008X": "Neuromuscular Medicine (Psychiatry & Neurology) Physician",
"2084N0400X": "Neurology Physician",
"2084N0402X": "Neurology with Special Qualifications in Child Neurology Physician",
"2084N0600X": "Clinical Neurophysiology Physician",
"2084P0005X": "Neurodevelopmental Disabilities Physician Physician",
"2084P0015X": "Psychosomatic Medicine Physician",
"2084P0301X": "Brain Injury Medicine (Psychiatry & Neurology) Physician",
"2084P0800X": "Psychiatry Physician",
"2084P0802X": "Addiction Psychiatry Physician",
"2084P0804X": "Child & Adolescent Psychiatry Physician",
"2084P0805X": "Geriatric Psychiatry Physician",
"2084P2900X": "Pain Medicine (Psychiatry & Neurology) Physician",
"2084S0010X": "Sports Medicine (Psychiatry & Neurology) Physician",
"2084S0012X": "Sleep Medicine (Psychiatry & Neurology) Physician",
"2084V0102X": "Vascular Neurology Physician",
"2085B0100X": "Body Imaging Physician",
"2085D0003X": "Diagnostic Neuroimaging (Radiology) Physician",
"2085H0002X": "Hospice and Palliative Medicine (Radiology) Physician",
"2085N0700X": "Neuroradiology Physician",
"2085N0904X": "Nuclear Radiology Physician",
"2085P0229X": "Pediatric Radiology Physician",
"2085R0001X": "Radiation Oncology Physician",
"2085R0202X": "Diagnostic Radiology Physician",
"2085R0203X": "Therapeutic Radiology Physician",
"2085R0204X": "Vascular & Interventional Radiology Physician",
"2085R0205X": "Radiological Physics Physician",
"2085U0001X": "Diagnostic Ultrasound Physician",
"208600000X": "Surgery Physician",
"2086H0002X": "Hospice and Palliative Medicine (Surgery) Physician",
"2086S0102X": "Surgical Critical Care Physician",
"2086S0105X": "Surgery of the Hand (Surgery) Physician",
"2086S0120X": "Pediatric Surgery Physician",
"2086S0122X": "Plastic and Reconstructive Surgery Physician",
"2086S0127X": "Trauma Surgery Physician",
"2086S0129X": "Vascular Surgery Physician",
"2086X0206X": "Surgical Oncology Physician",
"208800000X": "Urology Physician",
"2088F0040X": "Female Pelvic Medicine and Reconstructive Surgery (Urology) Physician",
"2088P0231X": "Pediatric Urology Physician",
"208C00000X": "Colon & Rectal Surgery Physician",
"208D00000X": "General Practice Physician",
"208G00000X": "Thoracic Surgery (Cardiothoracic Vascular Surgery) Physician",
"208M00000X": "Hospitalist Physician",
"208U00000X": "Clinical Pharmacology Physician",
"208VP0000X": "Pain Medicine Physician",
"208VP0014X": "Interventional Pain Medicine Physician",
"209800000X": "Legal Medicine (M.D./D.O.) Physician",
"211D00000X": "Podiatric Assistant",
"213E00000X": "Podiatrist",
"213EG0000X": "Deactivated - Podiatrist",
"213EP0504X": "Public Medicine Podiatrist",
"213EP1101X": "Primary Podiatric Medicine Podiatrist",
"213ER0200X": "Radiology Podiatrist",
"213ES0000X": "Sports Medicine Podiatrist",
"213ES0103X": "Foot & Ankle Surgery Podiatrist",
"213ES0131X": "Foot Surgery Podiatrist",
"221700000X": "Art Therapist",
"222Q00000X": "Developmental Therapist",
"222Z00000X": "Orthotist",
"224900000X": "Mastectomy Fitter",
"224L00000X": "Pedorthist",
"224P00000X": "Prosthetist",
"224Y00000X": "Clinical Exercise Physiologist",
"224Z00000X": "Occupational Therapy Assistant",
"224ZE0001X": "Environmental Modification Occupational Therapy Assistant",
"224ZF0002X": "Feeding, Eating & Swallowing Occupational Therapy Assistant",
"224ZL0004X": "Low Vision Occupational Therapy Assistant",
"224ZR0403X": "Driving and Community Mobility Occupational Therapy Assistant",
"225000000X": "Orthotic Fitter",
"225100000X": "Physical Therapist",
"2251C2600X": "Cardiopulmonary Physical Therapist",
"2251E1200X": "Ergonomics Physical Therapist",
"2251E1300X": "Clinical Electrophysiology Physical Therapist",
"2251G0304X": "Geriatric Physical Therapist",
"2251H1200X": "Hand Physical Therapist",
"2251H1300X": "Human Factors Physical Therapist",
"2251N0400X": "Neurology Physical Therapist",
"2251P0200X": "Pediatric Physical Therapist",
"2251S0007X": "Sports Physical Therapist",
"2251X0800X": "Orthopedic Physical Therapist",
"225200000X": "Physical Therapy Assistant",
"225400000X": "Rehabilitation Practitioner",
"225500000X": "Respiratory/Developmental/Rehabilitative Specialist/Technologist",
"2255A2300X": "Athletic Trainer",
"2255R0406X": "Blind Rehabilitation Specialist/Technologist",
"225600000X": "Dance Therapist",
"225700000X": "Massage Therapist",
"225800000X": "Recreation Therapist",
"225A00000X": "Music Therapist",
"225B00000X": "Pulmonary Function Technologist",
"225C00000X": "Rehabilitation Counselor",
"225CA2400X": "Assistive Technology Practitioner Rehabilitation Counselor",
"225CA2500X": "Assistive Technology Supplier Rehabilitation Counselor",
"225CX0006X": "Orientation and Mobility Training Rehabilitation Counselor",
"225X00000X": "Occupational Therapist",
"225XE0001X": "Environmental Modification Occupational Therapist",
"225XE1200X": "Ergonomics Occupational Therapist",
"225XF0002X": "Feeding, Eating & Swallowing Occupational Therapist",
"225XG0600X": "Gerontology Occupational Therapist",
"225XH1200X": "Hand Occupational Therapist",
"225XH1300X": "Human Factors Occupational Therapist",
"225XL0004X": "Low Vision Occupational Therapist",
"225XM0800X": "Mental Health Occupational Therapist",
"225XN1300X": "Neurorehabilitation Occupational Therapist",
"225XP0019X": "Physical Rehabilitation Occupational Therapist",
"225XP0200X": "Pediatric Occupational Therapist",
"225XR0403X": "Driving and Community Mobility Occupational Therapist",
"226000000X": "Recreational Therapist Assistant",
"226300000X": "Kinesiotherapist",
"227800000X": "Certified Respiratory Therapist",
"2278C0205X": "Critical Care Certified Respiratory Therapist",
"2278E0002X": "Emergency Care Certified Respiratory Therapist",
"2278E1000X": "Educational Certified Respiratory Therapist",
"2278G0305X": "Geriatric Care Certified Respiratory Therapist",
"2278G1100X": "General Care Certified Respiratory Therapist",
"2278H0200X": "Home Health Certified Respiratory Therapist",
"2278P1004X": "Pulmonary Diagnostics Certified Respiratory Therapist",
"2278P1005X": "Pulmonary Rehabilitation Certified Respiratory Therapist",
"2278P1006X": "Pulmonary Function Technologist Certified Respiratory Therapist",
"2278P3800X": "Palliative/Hospice Certified Respiratory Therapist",
"2278P3900X": "Neonatal/Pediatric Certified Respiratory Therapist",
"2278P4000X": "Patient Transport Certified Respiratory Therapist",
"2278S1500X": "SNF/Subacute Care Certified Respiratory Therapist",
"227900000X": "Registered Respiratory Therapist",
"2279C0205X": "Critical Care Registered Respiratory Therapist",
"2279E0002X": "Emergency Care Registered Respiratory Therapist",
"2279E1000X": "Educational Registered Respiratory Therapist",
"2279G0305X": "Geriatric Care Registered Respiratory Therapist",
"2279G1100X": "General Care Registered Respiratory Therapist",
"2279H0200X": "Home Health Registered Respiratory Therapist",
"2279P1004X": "Pulmonary Diagnostics Registered Respiratory Therapist",
"2279P1005X": "Pulmonary Rehabilitation Registered Respiratory Therapist",
"2279P1006X": "Pulmonary Function Technologist Registered Respiratory Therapist",
"2279P3800X": "Palliative/Hospice Registered Respiratory Therapist",
"2279P3900X": "Neonatal/Pediatric Registered Respiratory Therapist",
"2279P4000X": "Patient Transport Registered Respiratory Therapist",
"2279S1500X": "SNF/Subacute Care Registered Respiratory Therapist",
"229N00000X": "Anaplastologist",
"231H00000X": "Audiologist",
"231HA2400X": "Assistive Technology Practitioner Audiologist",
"231HA2500X": "Assistive Technology Supplier Audiologist",
"235500000X": "Speech/Language/Hearing Specialist/Technologist",
"2355A2700X": "Audiology Assistant",
"2355S0801X": "Speech-Language Assistant",
"235Z00000X": "Speech-Language Pathologist",
"237600000X": "Audiologist-Hearing Aid Fitter",
"237700000X": "Hearing Instrument Specialist",
"242T00000X": "Perfusionist",
"243U00000X": "Radiology Practitioner Assistant",
"246Q00000X": "Pathology Specialist/Technologist",
"246QB0000X": "Blood Banking Specialist/Technologist",
"246QC1000X": "Chemistry Pathology Specialist/Technologist",
"246QC2700X": "Cytotechnology Specialist/Technologist",
"246QH0000X": "Hematology Specialist/Technologist",
"246QH0401X": "Hemapheresis Practitioner",
"246QH0600X": "Histology Specialist/Technologist",
"246QI0000X": "Immunology Pathology Specialist/Technologist",
"246QL0900X": "Laboratory Management Specialist/Technologist",
"246QL0901X": "Diplomate Laboratory Management Specialist/Technologist",
"246QM0706X": "Medical Technologist",
"246QM0900X": "Microbiology Specialist/Technologist",
"246R00000X": "Pathology Technician",
"246RH0600X": "Histology Technician",
"246RM2200X": "Medical Laboratory Technician",
"246RP1900X": "Phlebotomy Technician",
"246W00000X": "Cardiology Technician",
"246X00000X": "Cardiovascular Specialist/Technologist",
"246XC2901X": "Cardiovascular Invasive Specialist/Technologist",
"246XC2903X": "Vascular Specialist/Technologist",
"246XS1301X": "Sonography Specialist/Technologist",
"246Y00000X": "Health Information Specialist/Technologist",
"246YC3301X": "Hospital Based Coding Specialist",
"246YC3302X": "Physician Office Based Coding Specialist",
"246YR1600X": "Registered Record Administrator",
"246Z00000X": "Other Specialist/Technologist",
"246ZA2600X": "Medical Art Specialist/Technologist",
"246ZB0301X": "Biomedical Engineer",
"246ZB0302X": "Biomedical Photographer",
"246ZB0500X": "Biochemist",
"246ZB0600X": "Biostatiscian",
"246ZC0007X": "Surgical Assistant",
"246ZE0500X": "EEG Specialist/Technologist",
"246ZE0600X": "Electroneurodiagnostic Specialist/Technologist",
"246ZG0701X": "Graphics Methods Specialist/Technologist",
"246ZG1000X": "Medical Geneticist (PhD) Specialist/Technologist",
"246ZI1000X": "Medical Illustrator",
"246ZN0300X": "Nephrology Specialist/Technologist",
"246ZS0410X": "Surgical Technologist",
"246ZX2200X": "Orthopedic Assistant",
"247000000X": "Health Information Technician",
"2470A2800X": "Assistant Health Information Record Technician",
"247100000X": "Radiologic Technologist",
"2471B0102X": "Bone Densitometry Radiologic Technologist",
"2471C1101X": "Cardiovascular-Interventional Technology Radiologic Technologist",
"2471C1106X": "Cardiac-Interventional Technology Radiologic Technologist",
"2471C3401X": "Computed Tomography Radiologic Technologist",
"2471C3402X": "Radiography Radiologic Technologist",
"2471M1202X": "Magnetic Resonance Imaging Radiologic Technologist",
"2471M2300X": "Mammography Radiologic Technologist",
"2471N0900X": "Nuclear Medicine Technology Radiologic Technologist",
"2471Q0001X": "Quality Management Radiologic Technologist",
"2471R0002X": "Radiation Therapy Radiologic Technologist",
"2471S1302X": "Sonography Radiologic Technologist",
"2471V0105X": "Vascular Sonography Radiologic Technologist",
"2471V0106X": "Vascular-Interventional Technology Radiologic Technologist",
"247200000X": "Other Technician",
"2472B0301X": "Biomedical Engineering Technician",
"2472D0500X": "Darkroom Technician",
"2472E0500X": "EEG Technician",
"2472R0900X": "Renal Dialysis Technician",
"2472V0600X": "Veterinary Technician",
"247ZC0005X": "Clinical Laboratory Director (Non-physician)",
"251300000X": "Local Education Agency (LEA)",
"251B00000X": "Case Management Agency",
"251C00000X": "Developmentally Disabled Services Day Training Agency",
"251E00000X": "Home Health Agency",
"251F00000X": "Home Infusion Agency",
"251G00000X": "Community Based Hospice Care Agency",
"251J00000X": "Nursing Care Agency",
"251K00000X": "Public Health or Welfare Agency",
"251S00000X": "Community/Behavioral Health Agency",
"251T00000X": "PACE Provider Organization",
"251V00000X": "Voluntary or Charitable Agency",
"251X00000X": "Supports Brokerage Agency",
"252Y00000X": "Early Intervention Provider Agency",
"253J00000X": "Foster Care Agency",
"253Z00000X": "In Home Supportive Care Agency",
"261Q00000X": "Clinic/Center",
"261QA0005X": "Ambulatory Family Planning Facility",
"261QA0006X": "Ambulatory Fertility Facility",
"261QA0600X": "Adult Day Care Clinic/Center",
"261QA0900X": "Amputee Clinic/Center",
"261QA1903X": "Ambulatory Surgical Clinic/Center",
"261QA3000X": "Augmentative Communication Clinic/Center",
"261QB0400X": "Birthing Clinic/Center",
"261QC0050X": "Critical Access Hospital Clinic/Center",
"261QC1500X": "Community Health Clinic/Center",
"261QC1800X": "Corporate Health Clinic/Center",
"261QD0000X": "Dental Clinic/Center",
"261QD1600X": "Developmental Disabilities Clinic/Center",
"261QE0002X": "Emergency Care Clinic/Center",
"261QE0700X": "End-Stage Renal Disease (ESRD) Treatment Clinic/Center",
"261QE0800X": "Endoscopy Clinic/Center",
"261QF0050X": "Non-Surgical Family Planning Clinic/Center",
"261QF0400X": "Federally Qualified Health Center (FQHC)",
"261QG0250X": "Genetics Clinic/Center",
"261QH0100X": "Health Service Clinic/Center",
"261QH0700X": "Hearing and Speech Clinic/Center",
"261QI0500X": "Infusion Therapy Clinic/Center",
"261QL0400X": "Lithotripsy Clinic/Center",
"261QM0801X": "Mental Health Clinic/Center (Including Community Mental Health Center)",
"261QM0850X": "Adult Mental Health Clinic/Center",
"261QM0855X": "Adolescent and Children Mental Health Clinic/Center",
"261QM1000X": "Migrant Health Clinic/Center",
"261QM1100X": "Military/U.S. Coast Guard Outpatient Clinic/Center",
"261QM1101X": "Military and U.S. Coast Guard Ambulatory Procedure Clinic/Center",
"261QM1102X": "Military Outpatient Operational (Transportable) Component Clinic/Center",
"261QM1103X": "Military Ambulatory Procedure Visits Operational (Transportable) Clinic/Center",
"261QM1200X": "Magnetic Resonance Imaging (MRI) Clinic/Center",
"261QM1300X": "Multi-Specialty Clinic/Center",
"261QM2500X": "Medical Specialty Clinic/Center",
"261QM2800X": "Methadone Clinic",
"261QM3000X": "Medically Fragile Infants and Children Day Care",
"261QP0904X": "Federal Public Health Clinic/Center",
"261QP0905X": "State or Local Public Health Clinic/Center",
"261QP1100X": "Podiatric Clinic/Center",
"261QP2000X": "Physical Therapy Clinic/Center",
"261QP2300X": "Primary Care Clinic/Center",
"261QP2400X": "Prison Health Clinic/Center",
"261QP3300X": "Pain Clinic/Center",
"261QR0200X": "Radiology Clinic/Center",
"261QR0206X": "Mammography Clinic/Center",
"261QR0207X": "Mobile Mammography Clinic/Center",
"261QR0208X": "Mobile Radiology Clinic/Center",
"261QR0400X": "Rehabilitation Clinic/Center",
"261QR0401X": "Comprehensive Outpatient Rehabilitation Facility (CORF)",
"261QR0404X": "Cardiac Rehabilitation Clinic/Center",
"261QR0405X": "Substance Use Disorder Rehabilitation Clinic/Center",
"261QR0800X": "Recovery Care Clinic/Center",
"261QR1100X": "Research Clinic/Center",
"261QR1300X": "Rural Health Clinic/Center",
"261QS0112X": "Oral and Maxillofacial Surgery Clinic/Center",
"261QS0132X": "Ophthalmologic Surgery Clinic/Center",
"261QS1000X": "Student Health Clinic/Center",
"261QS1200X": "Sleep Disorder Diagnostic Clinic/Center",
"261QU0200X": "Urgent Care Clinic/Center",
"261QV0200X": "VA Clinic/Center",
"261QX0100X": "Occupational Medicine Clinic/Center",
"261QX0200X": "Oncology Clinic/Center",
"261QX0203X": "Radiation Oncology Clinic/Center",
"273100000X": "Epilepsy Hospital Unit",
"273R00000X": "Psychiatric Hospital Unit",
"273Y00000X": "Rehabilitation Hospital Unit",
"275N00000X": "Medicare Defined Swing Bed Hospital Unit",
"276400000X": "Substance Use Disorder Rehabilitation Hospital Unit",
"281P00000X": "Chronic Disease Hospital",
"281PC2000X": "Children' s Chronic Disease Hospital",
"282E00000X": "Long Term Care Hospital",
"282J00000X": "Religious Nonmedical Health Care Institution",
"282N00000X": "General Acute Care Hospital",
"282NC0060X": "Critical Access Hospital",
"282NC2000X": "Children's Hospital",
"282NR1301X": "Rural Acute Care Hospital",
"282NW0100X": "Women's Hospital",
"283Q00000X": "Psychiatric Hospital",
"283X00000X": "Rehabilitation Hospital",
"283XC2000X": "Children's Rehabilitation Hospital",
"284300000X": "Special Hospital",
"286500000X": "Military Hospital",
"2865C1500X": "Deactivated - Military Hospital",
"2865M2000X": "Military General Acute Care Hospital",
"2865X1600X": "Operational (Transportable) Military General Acute Care Hospital",
"287300000X": "Deactivated - Christian Science Sanitorium",
"291900000X": "Military Clinical Medical Laboratory",
"291U00000X": "Clinical Medical Laboratory",
"292200000X": "Dental Laboratory",
"293D00000X": "Physiological Laboratory",
"302F00000X": "Exclusive Provider Organization",
"302R00000X": "Health Maintenance Organization",
"305R00000X": "Preferred Provider Organization",
"305S00000X": "Point of Service",
"310400000X": "Assisted Living Facility",
"3104A0625X": "Assisted Living Facility (Mental Illness)",
"3104A0630X": "Assisted Living Facility (Behavioral Disturbances)",
"310500000X": "Mental Illness Intermediate Care Facility",
"311500000X": "Alzheimer Center (Dementia Center)",
"311Z00000X": "Custodial Care Facility",
"311ZA0620X": "Adult Care Home Facility",
"313M00000X": "Nursing Facility/Intermediate Care Facility",
"314000000X": "Skilled Nursing Facility",
"3140N1450X": "Pediatric Skilled Nursing Facility",
"315D00000X": "Inpatient Hospice",
"315P00000X": "Intellectual Disabilities Intermediate Care Facility",
"317400000X": "Deactivated - Christian Science Facility",
"320600000X": "Intellectual and/or Developmental Disabilities Residential Treatment Facility",
"320700000X": "Physical Disabilities Residential Treatment Facility",
"320800000X": "Mental Illness Community Based Residential Treatment Facility",
"320900000X": "Intellectual and/or Developmental Disabilities Community Based Residential Treatment Facility",
"322D00000X": "Emotionally Disturbed Childrens' Residential Treatment Facility",
"323P00000X": "Psychiatric Residential Treatment Facility",
"324500000X": "Substance Abuse Rehabilitation Facility",
"3245S0500X": "Children's Substance Abuse Rehabilitation Facility",
"331L00000X": "Blood Bank",
"332000000X": "Military/U.S. Coast Guard Pharmacy",
"332100000X": "Department of Veterans Affairs (VA) Pharmacy",
"332800000X": "Indian Health Service/Tribal/Urban Indian Health (I/T/U) Pharmacy",
"332900000X": "Non-Pharmacy Dispensing Site",
"332B00000X": "Durable Medical Equipment & Medical Supplies",
"332BC3200X": "Customized Equipment (DME)",
"332BD1200X": "Dialysis Equipment & Supplies (DME)",
"332BN1400X": "Nursing Facility Supplies (DME)",
"332BP3500X": "Parenteral & Enteral Nutrition Supplies (DME)",
"332BX2000X": "Oxygen Equipment & Supplies (DME)",
"332G00000X": "Eye Bank",
"332H00000X": "Eyewear Supplier",
"332S00000X": "Hearing Aid Equipment",
"332U00000X": "Home Delivered Meals",
"333300000X": "Emergency Response System Companies",
"333600000X": "Pharmacy",
"3336C0002X": "Clinic Pharmacy",
"3336C0003X": "Community/Retail Pharmacy",
"3336C0004X": "Compounding Pharmacy",
"3336H0001X": "Home Infusion Therapy Pharmacy",
"3336I0012X": "Institutional Pharmacy",
"3336L0003X": "Long Term Care Pharmacy",
"3336M0002X": "Mail Order Pharmacy",
"3336M0003X": "Managed Care Organization Pharmacy",
"3336N0007X": "Nuclear Pharmacy",
"3336S0011X": "Specialty Pharmacy",
"335E00000X": "Prosthetic/Orthotic Supplier",
"335G00000X": "Medical Foods Supplier",
"335U00000X": "Organ Procurement Organization",
"335V00000X": "Portable X-ray and/or Other Portable Diagnostic Imaging Supplier",
"341600000X": "Ambulance",
"3416A0800X": "Air Ambulance",
"3416L0300X": "Land Ambulance",
"3416S0300X": "Water Ambulance",
"341800000X": "Military/U.S. Coast Guard Transport,",
"3418M1110X": "Military or U.S. Coast Guard Ground Transport Ambulance",
"3418M1120X": "Military or U.S. Coast Guard Air Transport Ambulance",
"3418M1130X": "Military or U.S. Coast Guard Water Transport Ambulance",
"342000000X": "Transportation Network Company",
"343800000X": "Secured Medical Transport (VAN)",
"343900000X": "Non-emergency Medical Transport (VAN)",
"344600000X": "Taxi",
"344800000X": "Air Carrier",
"347B00000X": "Bus",
"347C00000X": "Private Vehicle",
"347D00000X": "Train",
"347E00000X": "Transportation Broker",
"363A00000X": "Physician Assistant",
"363AM0700X": "Medical Physician Assistant",
"363AS0400X": "Surgical Physician Assistant",
"363L00000X": "Nurse Practitioner",
"363LA2100X": "Acute Care Nurse Practitioner",
"363LA2200X": "Adult Health Nurse Practitioner",
"363LC0200X": "Critical Care Medicine Nurse Practitioner",
"363LC1500X": "Community Health Nurse Practitioner",
"363LF0000X": "Family Nurse Practitioner",
"363LG0600X": "Gerontology Nurse Practitioner",
"363LN0000X": "Neonatal Nurse Practitioner",
"363LN0005X": "Critical Care Neonatal Nurse Practitioner",
"363LP0200X": "Pediatric Nurse Practitioner",
"363LP0222X": "Critical Care Pediatric Nurse Practitioner",
"363LP0808X": "Psychiatric/Mental Health Nurse Practitioner",
"363LP1700X": "Perinatal Nurse Practitioner",
"363LP2300X": "Primary Care Nurse Practitioner",
"363LS0200X": "School Nurse Practitioner",
"363LW0102X": "Women's Health Nurse Practitioner",
"363LX0001X": "Obstetrics & Gynecology Nurse Practitioner",
"363LX0106X": "Occupational Health Nurse Practitioner",
"364S00000X": "Clinical Nurse Specialist",
"364SA2100X": "Acute Care Clinical Nurse Specialist",
"364SA2200X": "Adult Health Clinical Nurse Specialist",
"364SC0200X": "Critical Care Medicine Clinical Nurse Specialist",
"364SC1501X": "Community Health/Public Health Clinical Nurse Specialist",
"364SC2300X": "Chronic Care Clinical Nurse Specialist",
"364SE0003X": "Emergency Clinical Nurse Specialist",
"364SE1400X": "Ethics Clinical Nurse Specialist",
"364SF0001X": "Family Health Clinical Nurse Specialist",
"364SG0600X": "Gerontology Clinical Nurse Specialist",
"364SH0200X": "Home Health Clinical Nurse Specialist",
"364SH1100X": "Holistic Clinical Nurse Specialist",
"364SI0800X": "Informatics Clinical Nurse Specialist",
"364SL0600X": "Long-Term Care Clinical Nurse Specialist",
"364SM0705X": "Medical-Surgical Clinical Nurse Specialist",
"364SN0000X": "Neonatal Clinical Nurse Specialist",
"364SN0800X": "Neuroscience Clinical Nurse Specialist",
"364SP0200X": "Pediatric Clinical Nurse Specialist",
"364SP0807X": "Child & Adolescent Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0808X": "Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0809X": "Adult Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0810X": "Child & Family Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0811X": "Chronically Ill Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0812X": "Community Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0813X": "Geropsychiatric Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP1700X": "Perinatal Clinical Nurse Specialist",
"364SP2800X": "Perioperative Clinical Nurse Specialist",
"364SR0400X": "Rehabilitation Clinical Nurse Specialist",
"364SS0200X": "School Clinical Nurse Specialist",
"364ST0500X": "Transplantation Clinical Nurse Specialist",
"364SW0102X": "Women's Health Clinical Nurse Specialist",
"364SX0106X": "Occupational Health Clinical Nurse Specialist",
"364SX0200X": "Oncology Clinical Nurse Specialist",
"364SX0204X": "Pediatric Oncology Clinical Nurse Specialist",
"367500000X": "Certified Registered Nurse Anesthetist",
"367A00000X": "Advanced Practice Midwife",
"367H00000X": "Anesthesiologist Assistant",
"372500000X": "Chore Provider",
"372600000X": "Adult Companion",
"373H00000X": "Day Training/Habilitation Specialist",
"374700000X": "Technician",
"3747A0650X": "Attendant Care Provider",
"3747P1801X": "Personal Care Attendant",
"374J00000X": "Doula",
"374K00000X": "Religious Nonmedical Practitioner",
"374T00000X": "Religious Nonmedical Nursing Personnel",
"374U00000X": "Home Health Aide",
"376G00000X": "Nursing Home Administrator",
"376J00000X": "Homemaker",
"376K00000X": "Nurse's Aide",
"385H00000X": "Respite Care",
"385HR2050X": "Respite Care Camp",
"385HR2055X": "Child Mental Illness Respite Care",
"385HR2060X": "Child Intellectual and/or Developmental Disabilities Respite Care",
"385HR2065X": "Child Physical Disabilities Respite Care",
"390200000X": "Student in an Organized Health Care Education/Training Program",
"405300000X": "Prevention Professional"
}

View File

@ -1,4 +1,4 @@
<div class="az-content-left az-content-left-components sticky-top" style="position:sticky;">
<div [formGroup]="filterService.filterForm" class="az-content-left az-content-left-components sticky-top" style="position:sticky;">
<div class="component-item">
<label>Connected</label>
<nav class="nav flex-column">
@ -6,12 +6,16 @@
<a ngbTooltip="not yet implemented" routerLinkActive="active" class="nav-link">Manual</a>
</nav>
<label>Categories</label>
<nav class="nav flex-column">
<a ngbTooltip="not yet implemented" routerLinkActive="active" class="nav-link">Hospital Networks/Clinics</a>
<a ngbTooltip="not yet implemented" routerLinkActive="active" class="nav-link">Pharmacies</a>
<a ngbTooltip="not yet implemented" routerLinkActive="active" class="nav-link">Insurers</a>
<a ngbTooltip="not yet implemented" routerLinkActive="active" class="nav-link">Laboratories</a>
<a ngbTooltip="not yet implemented" routerLinkActive="active" class="nav-link">Wearables</a>
<nav formGroupName="categories" class="nav flex-column">
<div *ngFor="let category of filterService.filterForm.get('categories').value | keyvalue " class="switch-container">
<label class="switch text-nowrap">
<input type="checkbox" [formControlName]="category.key" [value]="category.value">
<span class="switch-button"></span><span class="category-label truncate pl-1 pr-1">{{category.key | medicalSourcesCategoryLookup}}</span>
<span *ngIf="!filterService.filterForm.get('categories').get(category.key).value" class="badge badge-primary mr-1">{{bucketDocCount(categories, category.key)}}</span>
</label>
</div>
</nav>
<label>Industry</label>

View File

@ -1,4 +1,8 @@
import { Component, OnInit } from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';
import {
LighthouseSourceSearchAggregation,
} from '../../models/lighthouse/lighthouse-source-search';
import {MedicalSourcesFilterService} from '../../services/medical-sources-filter.service';
@Component({
selector: 'app-medical-sources-filter',
@ -7,9 +11,24 @@ import { Component, OnInit } from '@angular/core';
})
export class MedicalSourcesFilterComponent implements OnInit {
constructor() { }
@Input() categories: LighthouseSourceSearchAggregation = {buckets: [], sum_other_doc_count: 0}
@Input() platformTypes: LighthouseSourceSearchAggregation = {buckets: [], sum_other_doc_count: 0}
constructor(
public filterService: MedicalSourcesFilterService,
) { }
ngOnInit(): void {
}
categorySelected(category: string){
console.log("SELECTED CATEGORY", category)
this.filterService.filterForm.patchValue({'categories': {[category]: true}})
}
bucketDocCount(aggregationData: LighthouseSourceSearchAggregation, key): number {
return aggregationData?.buckets?.find(bucket => bucket.key === key)?.doc_count
}
}

View File

@ -72,6 +72,8 @@ import { ReportMedicalHistoryExplanationOfBenefitComponent } from './report-medi
import {GridstackComponent} from './gridstack/gridstack.component';
import {GridstackItemComponent} from './gridstack/gridstack-item.component';
import { MedicalSourcesFilterComponent } from './medical-sources-filter/medical-sources-filter.component';
import { MedicalSourcesConnectedComponent } from './medical-sources-connected/medical-sources-connected.component';
import { MedicalSourcesCategoryLookupPipe } from './medical-sources-filter/medical-sources-category-lookup.pipe';
@NgModule({
imports: [
@ -156,72 +158,75 @@ import { MedicalSourcesFilterComponent } from './medical-sources-filter/medical-
MediaComponent,
ReportMedicalHistoryExplanationOfBenefitComponent,
MedicalSourcesFilterComponent,
MedicalSourcesConnectedComponent,
MedicalSourcesCategoryLookupPipe,
],
exports: [
BinaryComponent,
ComponentsSidebarComponent,
DiagnosticReportComponent,
DocumentReferenceComponent,
FallbackComponent,
FhirResourceComponent,
FhirResourceOutletDirective,
ImmunizationComponent,
ListAdverseEventComponent,
ListAllergyIntoleranceComponent,
ListAppointmentComponent,
ListCarePlanComponent,
ListCommunicationComponent,
ListConditionComponent,
ListCoverageComponent,
ListDeviceComponent,
ListDeviceRequestComponent,
ListDiagnosticReportComponent,
ListDocumentReferenceComponent,
ListEncounterComponent,
ListGenericResourceComponent,
ListGoalComponent,
ListImmunizationComponent,
ListMedicationAdministrationComponent,
ListMedicationComponent,
ListMedicationDispenseComponent,
ListMedicationRequestComponent,
ListNutritionOrderComponent,
ListObservationComponent,
ListPatientComponent,
ListProcedureComponent,
ListServiceRequestComponent,
MedicalSourcesFilterComponent,
MedicationRequestComponent,
NlmTypeaheadComponent,
PractitionerComponent,
ProcedureComponent,
ReportHeaderComponent,
ReportLabsObservationComponent,
ReportMedicalHistoryConditionComponent,
ReportMedicalHistoryEditorComponent,
ReportMedicalHistoryExplanationOfBenefitComponent,
ResourceListComponent,
ResourceListOutletDirective,
ToastComponent,
UtilitiesSidebarComponent,
exports: [
BinaryComponent,
ComponentsSidebarComponent,
DiagnosticReportComponent,
DocumentReferenceComponent,
FallbackComponent,
FhirResourceComponent,
FhirResourceOutletDirective,
ImmunizationComponent,
ListAdverseEventComponent,
ListAllergyIntoleranceComponent,
ListAppointmentComponent,
ListCarePlanComponent,
ListCommunicationComponent,
ListConditionComponent,
ListCoverageComponent,
ListDeviceComponent,
ListDeviceRequestComponent,
ListDiagnosticReportComponent,
ListDocumentReferenceComponent,
ListEncounterComponent,
ListGenericResourceComponent,
ListGoalComponent,
ListImmunizationComponent,
ListMedicationAdministrationComponent,
ListMedicationComponent,
ListMedicationDispenseComponent,
ListMedicationRequestComponent,
ListNutritionOrderComponent,
ListObservationComponent,
ListPatientComponent,
ListProcedureComponent,
ListServiceRequestComponent,
MedicalSourcesFilterComponent,
MedicationRequestComponent,
NlmTypeaheadComponent,
PractitionerComponent,
ProcedureComponent,
ReportHeaderComponent,
ReportLabsObservationComponent,
ReportMedicalHistoryConditionComponent,
ReportMedicalHistoryEditorComponent,
ReportMedicalHistoryExplanationOfBenefitComponent,
ResourceListComponent,
ResourceListOutletDirective,
ToastComponent,
UtilitiesSidebarComponent,
//standalone components
BadgeComponent,
TableComponent,
CodingComponent,
LoadingSpinnerComponent,
GlossaryLookupComponent,
AllergyIntoleranceComponent,
MedicationComponent,
MedicationRequestComponent,
PractitionerComponent,
ProcedureComponent,
ImmunizationComponent,
BinaryComponent,
GridstackComponent,
GridstackItemComponent,
//standalone components
BadgeComponent,
TableComponent,
CodingComponent,
LoadingSpinnerComponent,
GlossaryLookupComponent,
AllergyIntoleranceComponent,
MedicationComponent,
MedicationRequestComponent,
PractitionerComponent,
ProcedureComponent,
ImmunizationComponent,
BinaryComponent,
GridstackComponent,
GridstackItemComponent,
MedicalSourcesConnectedComponent,
]
]
})
export class SharedModule { }

View File

@ -1,5 +1,22 @@
import {MetadataSource} from '../fasten/metadata-source';
export class LighthouseSourceSearchResult {
_index: string;
_type: string;
_id: string;
_score: number;
_source: MetadataSource;
sort: string[];
}
export class LighthouseSourceSearchAggregation {
sum_other_doc_count: number;
buckets: {
key: string;
doc_count: number;
}[]
}
export class LighthouseSourceSearch {
_scroll_id: string;
took: number;
@ -10,28 +27,10 @@ export class LighthouseSourceSearch {
relation: string;
};
max_score: number;
hits: {
_index: string;
_type: string;
_id: string;
_score: number;
_source: MetadataSource;
}[];
hits: LighthouseSourceSearchResult[];
};
aggregations: {
by_platform_type: {
sum_other_doc_count: number;
buckets: {
key: string;
doc_count: number;
}[]
},
by_category: {
sum_other_doc_count: number;
buckets: {
key: string;
doc_count: number;
}[]
}
}
by_platform_type: LighthouseSourceSearchAggregation
by_category: LighthouseSourceSearchAggregation
};
}

View File

@ -1,6 +1,6 @@
<div class="az-content">
<div class="container">
<app-medical-sources-filter></app-medical-sources-filter>
<app-medical-sources-filter [categories]="resultLimits.categoryBuckets" [platformTypes]="resultLimits.platformTypesBuckets"></app-medical-sources-filter>
<div class="az-content-body pd-lg-l-40 d-flex flex-column">
<div class="az-content-breadcrumb">
<span>Medical Sources</span>
@ -23,29 +23,8 @@
</span>
</div>
<app-medical-sources-connected></app-medical-sources-connected>
<h2 class="az-content-title">Connected Sources</h2>
<div *ngIf="!loading else isLoadingTemplate" class="row">
<div *ngFor="let sourceInfo of connectedSourceList" class="col-sm-3 mg-b-20 px-3">
<div class="card h-100 d-flex align-items-center justify-content-center mt-3 mt-3 rounded-0 cursor-pointer">
<div (click)="openModal(contentModalRef, sourceInfo)" class="card-body">
<div class="h-100 d-flex align-items-center">
<img [src]="'assets/sources/'+(sourceInfo.metadata.brand_logo ? sourceInfo.metadata.brand_logo : sourceInfo.metadata.source_type+'.png')" [alt]="sourceInfo?.metadata.display" class="img-fluid">
</div>
<div *ngIf="status[sourceInfo.metadata?.source_type]" class="progress">
<div [style.width]="status[sourceInfo?.metadata?.source_type] == 'authorize' ? '33%' : '66%'" class="bg-indigo progress-bar progress-bar-striped progress-bar-animated" role="progressbar"></div>
</div>
</div>
<div class="card-footer text-center p-1" style="width:100%">
<small class="tx-gray-700">
{{sourceInfo?.metadata.display}}
</small>
</div>
</div>
</div>
</div>
<h2 class="az-content-title mg-t-40">Medical Record Sources</h2>
@ -76,9 +55,9 @@
<div class="input-group-prepend">
<span class="input-group-text" id="search-prefix">Search</span>
</div>
<input (keyup)="searchTermUpdate.next($event.target.value)" type="text" class="form-control" placeholder="Search Term">
<input [ngModel]="searchTermUpdate | async" (keyup)="searchTermUpdate.next($event.target.value)" type="text" class="form-control" placeholder="Search Term">
<div class="input-group-append">
<span class="input-group-text">{{this.availableSourceList.length}} of {{this.totalAvailableSourceList}} results</span>
<span class="input-group-text">{{this.availableSourceList.length}} of {{this.resultLimits.totalItems}} results</span>
</div>
</div><!-- input-group -->
@ -86,7 +65,7 @@
</div>
<div *ngIf="!loading else isLoadingTemplate" class="row row-sm"
<div *ngIf="!loading || availableSourceList.length > 0 else isLoadingTemplate" class="row row-sm"
infiniteScroll
[infiniteScrollDistance]="2"
[infiniteScrollThrottle]="50"
@ -116,32 +95,6 @@
</div><!-- container -->
</div><!-- az-content -->
<ng-template #contentModalRef let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">{{modalSelectedSourceListItem?.metadata["display"]}}</h4>
<button type="button" class="btn btn-close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<h6>Manage Source</h6>
<p>Existing connections can be "Synced", "Reconnected" or "Deleted"</p>
<ul>
<li><p><strong>Sync</strong> - Download all resources from this healthcare provider, storing them securely in Fasten</p></li>
<li><p><strong>Reconnect</strong> - If your healthcare connection has expired, you can use this button to reconnect</p></li>
<li><p><strong>Delete</strong> - Delete all resources for this healthcare provider. This will ONLY effect data stored in Fasten</p></li>
</ul>
</div>
<div class="modal-footer">
<button (click)="sourceSyncHandler(modalSelectedSourceListItem.source)" type="button" class="btn btn-indigo">Sync</button>
<button (click)="connectHandler($event, modalSelectedSourceListItem.source['source_type'])" type="button" class="btn btn-outline-light">Reconnect</button>
<button type="button" class="btn btn-outline-danger">Delete</button>
<button (click)="modal.dismiss('Close click')" type="button" class="btn btn-outline-light">Close</button>
</div>
</ng-template>
<ng-template #isLoadingTemplate>
<div class="row">
<div class="col-12">

View File

@ -1,4 +1,4 @@
import {Component, OnInit} from '@angular/core';
import {Component, EventEmitter, OnInit, Optional, Output} from '@angular/core';
import {LighthouseService} from '../../services/lighthouse.service';
import {FastenApiService} from '../../services/fasten-api.service';
import {LighthouseSourceMetadata} from '../../models/lighthouse/lighthouse-source-metadata';
@ -10,9 +10,15 @@ import {Location} from '@angular/common';
import {ToastService} from '../../services/toast.service';
import {ToastNotification, ToastType} from '../../models/fasten/toast';
import {environment} from '../../../environments/environment';
import {BehaviorSubject, forkJoin, Subject} from 'rxjs';
import {LighthouseSourceSearch} from '../../models/lighthouse/lighthouse-source-search';
import {BehaviorSubject, forkJoin, Observable, Subject} from 'rxjs';
import {
LighthouseSourceSearch,
LighthouseSourceSearchAggregation,
LighthouseSourceSearchResult
} from '../../models/lighthouse/lighthouse-source-search';
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
import {MedicalSourcesFilter, MedicalSourcesFilterService} from '../../services/medical-sources-filter.service';
import {FormControl, FormGroup} from '@angular/forms';
// If you dont import this angular will import the wrong "Location"
export const sourceConnectWindowTimeout = 24*5000 //wait 2 minutes (5 * 24 = 120)
@ -31,78 +37,145 @@ export class MedicalSourcesComponent implements OnInit {
loading: boolean = false
environment_name = environment.environment_name
status: { [name: string]: string } = {}
connectedSourceList: SourceListItem[] = [] //source's are populated for this list
availableSourceList: SourceListItem[] = []
totalAvailableSourceList: number = 0
uploadedFile: File[] = []
closeResult = '';
modalSelectedSourceListItem:SourceListItem = null;
scrollId: string = ""
scrollComplete: boolean = false
availableSourceList: SourceListItem[] = []
searchTermUpdate = new BehaviorSubject<string>("");
showHidden: boolean = false
status: { [name: string]: string } = {}
//aggregation/filter data & limits
globalLimits: {
// aggregations: LighthouseSourceSearchAggregations | undefined,
} = {
// categories: [],
// aggregations: undefined,
}
//limits that are tied to the current result set.
resultLimits: {
totalItems: number,
scrollComplete: boolean,
platformTypesBuckets: LighthouseSourceSearchAggregation,
categoryBuckets: LighthouseSourceSearchAggregation,
} = {
totalItems: 0,
scrollComplete: false,
platformTypesBuckets: undefined,
categoryBuckets: undefined
}
//source of truth for current state
filterForm = this.filterService.filterForm;
constructor(
private lighthouseApi: LighthouseService,
private fastenApi: FastenApiService,
private modalService: NgbModal,
private route: ActivatedRoute,
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
private toastService: ToastService
private toastService: ToastService,
private filterService: MedicalSourcesFilterService,
) { }
ngOnInit(): void {
this.loading = true
forkJoin([this.lighthouseApi.findLighthouseSources("", "", this.showHidden), this.fastenApi.getSources()]).subscribe(results => {
this.loading = false
//handle connected sources sources
const connectedSources = results[1] as Source[]
forkJoin(connectedSources.map((source) => this.lighthouseApi.getLighthouseSource(source.source_type))).subscribe((connectedMetadata) => {
for(const ndx in connectedSources){
this.connectedSourceList.push({source: connectedSources[ndx], metadata: connectedMetadata[ndx]})
}
})
//changing the form, should change the URL, BUT NOT do a query
this.filterForm.valueChanges.pipe(debounceTime(100)).subscribe(val => {
console.log("FILTER FORM CHANGED:", val, this.filterService.toQueryParams())
//handle source metadata map response
this.populateAvailableSourceList(results[0] as LighthouseSourceSearch)
//check if we've just started connecting a "source_type"
const callbackSourceType = this.route.snapshot.paramMap.get('source_type')
if(callbackSourceType){
this.status[callbackSourceType] = "token"
//move this source from available to connected (with a progress bar)
//remove item from available sources list, add to connected sources.
let inProgressAvailableIndex = this.availableSourceList.findIndex((item) => item.metadata.source_type == callbackSourceType)
if(inProgressAvailableIndex > -1){
let sourcesInProgress = this.availableSourceList.splice(inProgressAvailableIndex, 1);
}
//the structure of "availableSourceList" vs "connectedSourceList" sources is slightly different,
//connectedSourceList contains a "source" field. The this.fastenApi.createSource() call in the callback function will set it.
this.lighthouseApi.getLighthouseSource(callbackSourceType)
.then((metadata) => {
this.connectedSourceList.push({metadata: metadata})
return this.callback(callbackSourceType)
})
.then(console.log)
}
}, err => {
this.loading = false
// change the browser url whenever the filter is updated.
this.updateBrowserUrl(this.filterService.toQueryParams())
})
//TODO: handle Callbacks from the source connect window
const callbackSourceType = this.activatedRoute.snapshot.paramMap.get('source_type')
if(callbackSourceType){
console.error("TODO! handle callback redirect from source")
} else {
//we're not in a callback redirect, lets load the sources
if(this.activatedRoute.snapshot.queryParams['query']){
this.searchTermUpdate.next(this.activatedRoute.snapshot.queryParams['query'])
}
//register a callback for when the search term changes
//changing the route should trigger a query
this.activatedRoute.queryParams
.subscribe(params => {
console.log("QUERY PARAMS CHANGED ON ROUTE", params); // {order: "popular"}
var updatedForm = this.filterService.parseQueryParams(params);
//this is a "breaking change" to the filter values, causing a reset and a new query
this.availableSourceList = []
this.resultLimits.totalItems = 0
this.resultLimits.scrollComplete = false
// this.filterService.filterForm.setControl("categories", this.{: {}}, { emitEvent: false})
//update the form with data from route (don't emit a new patch event), then submit query
var searchObservable = this.querySources(this.filterService.toMedicalSourcesFilter(updatedForm));
searchObservable.subscribe(null, null, () => {
this.filterForm.patchValue(updatedForm, { emitEvent: false});
})
});
}
/// OLD CODE - Should be refactored
// this.loading = true
// forkJoin([this.lighthouseApi.findLighthouseSources("", "", this.showHidden), this.fastenApi.getSources()]).subscribe(results => {
// this.loading = false
//
// //handle connected sources sources
// const connectedSources = results[1] as Source[]
// forkJoin(connectedSources.map((source) => this.lighthouseApi.getLighthouseSource(source.source_type))).subscribe((connectedMetadata) => {
// for(const ndx in connectedSources){
// this.connectedSourceList.push({source: connectedSources[ndx], metadata: connectedMetadata[ndx]})
// }
// })
//
//
// //handle source metadata map response
// this.populateAvailableSourceList(results[0] as LighthouseSourceSearch)
//
//
// //check if we've just started connecting a "source_type"
// const callbackSourceType = this.route.snapshot.paramMap.get('source_type')
// if(callbackSourceType){
// this.status[callbackSourceType] = "token"
//
// //move this source from available to connected (with a progress bar)
// //remove item from available sources list, add to connected sources.
// let inProgressAvailableIndex = this.availableSourceList.findIndex((item) => item.metadata.source_type == callbackSourceType)
// if(inProgressAvailableIndex > -1){
// let sourcesInProgress = this.availableSourceList.splice(inProgressAvailableIndex, 1);
//
// }
//
// //the structure of "availableSourceList" vs "connectedSourceList" sources is slightly different,
// //connectedSourceList contains a "source" field. The this.fastenApi.createSource() call in the callback function will set it.
// this.lighthouseApi.getLighthouseSource(callbackSourceType)
// .then((metadata) => {
// this.connectedSourceList.push({metadata: metadata})
// return this.callback(callbackSourceType)
// })
// .then(console.log)
// }
//
// }, err => {
// this.loading = false
// })
//
//
//register a callback for when the search box content changes
this.searchTermUpdate
.pipe(
debounceTime(200),
@ -110,215 +183,293 @@ export class MedicalSourcesComponent implements OnInit {
)
.subscribe(value => {
console.log("search term changed:", value)
//reset available sources
this.availableSourceList = []
this.scrollId = ""
this.scrollComplete = false
this.totalAvailableSourceList = 0
this.lighthouseApi.findLighthouseSources(value, this.scrollId, this.showHidden)
.subscribe((results) => {
this.populateAvailableSourceList(results)
})
let currentQuery = this.filterService.filterForm.value.query || ""
if(value != null && currentQuery != value){
this.filterService.filterForm.patchValue({query: value})
}
});
}
private populateAvailableSourceList(results: LighthouseSourceSearch): void {
this.totalAvailableSourceList = results.hits.total.value
if(results.hits.hits.length == 0){
this.scrollComplete = true
console.log("scroll complete")
updateBrowserUrl(queryParams: {[name: string]: string}){
console.log("update the browser url with query params data", queryParams)
this.router.navigate(['/sources'], { queryParams: queryParams })
}
private querySources(filter?: MedicalSourcesFilter): Observable<LighthouseSourceSearch> {
if(this.loading){
return
}
this.scrollId = results._scroll_id
this.availableSourceList = this.availableSourceList.concat(results.hits.hits.map((result) => {
return {metadata: result._source}
}).filter((item) => {
return !this.connectedSourceList.find((connectedItem) => connectedItem.metadata.source_type == item.metadata.source_type)
}))
}
//TODO: pass filter to function.
// this.location.replaceState('/dashboard','', this.filter)
public onScroll(): void {
if(this.scrollComplete){
return
if(!filter){
filter = this.filterService.toMedicalSourcesFilter(this.filterForm.value)
console.log("querySources() - no filter provided, using current form value", filter)
}
this.lighthouseApi.findLighthouseSources(this.searchTermUpdate.getValue(), this.scrollId, this.showHidden)
.subscribe((results) => {
this.populateAvailableSourceList(results)
})
}
/**
* after pressing the logo (connectHandler button), this function will generate an authorize url for this source, and redirec the user.
* @param $event
* @param sourceType
*/
public connectHandler($event: MouseEvent, sourceType: string):void {
($event.currentTarget as HTMLButtonElement).disabled = true;
this.status[sourceType] = "authorize"
filter.fields = ["*"];
this.loading = true
var searchObservable = this.lighthouseApi.searchLighthouseSources(filter);
searchObservable.subscribe(wrapper => {
console.log("search sources", wrapper);
// this.searchResults = wrapper.hits.hits;
this.resultLimits.totalItems = wrapper.hits.total.value;
this.lighthouseApi.getLighthouseSource(sourceType)
.then(async (sourceMetadata: LighthouseSourceMetadata) => {
console.log(sourceMetadata);
let authorizationUrl = await this.lighthouseApi.generateSourceAuthorizeUrl(sourceType, sourceMetadata)
this.availableSourceList = this.availableSourceList.concat(wrapper.hits.hits.map((result) => {
return {metadata: result._source}
}))
console.log('authorize url:', authorizationUrl.toString());
// redirect to lighthouse with uri's
this.lighthouseApi.redirectWithOriginAndDestination(authorizationUrl.toString(), sourceType, sourceMetadata.redirect_uri)
//change the current Page (but don't cause a new query)
if(wrapper.hits.hits.length == 0){
console.log("SCROLL_COMPLETE!@@@@@@@@")
this.resultLimits.scrollComplete = true;
} else {
console.log("SETTING NEXT SORT KEY:", wrapper.hits.hits[wrapper.hits.hits.length - 1].sort.join(','))
this.filterService.filterForm.patchValue({searchAfter: wrapper.hits.hits[wrapper.hits.hits.length - 1].sort.join(",")}, {emitEvent: false})
}
});
}
// .filter((item) => {
// return !this.connectedSourceList.find((connectedItem) => connectedItem.metadata.source_type == item.metadata.source_type)
// }))
/**
* if the user is redirected to this page from the lighthouse, we'll need to process the "code" to retrieve the access token & refresh token.
* @param sourceType
*/
public async callback(sourceType: string) {
//get the source metadata again
await this.lighthouseApi.getLighthouseSource(sourceType)
.then(async (sourceMetadata: LighthouseSourceMetadata) => {
//get required parameters from the URI and local storage
const callbackUrlParts = new URL(window.location.href)
const fragmentParams = new URLSearchParams(callbackUrlParts.hash.substring(1))
const callbackCode = callbackUrlParts.searchParams.get("code") || fragmentParams.get("code")
const callbackState = callbackUrlParts.searchParams.get("state") || fragmentParams.get("state")
const callbackError = callbackUrlParts.searchParams.get("error") || fragmentParams.get("error")
const callbackErrorDescription = callbackUrlParts.searchParams.get("error_description") || fragmentParams.get("error_description")
this.resultLimits.platformTypesBuckets = wrapper.aggregations.by_platform_type;
this.resultLimits.categoryBuckets = wrapper.aggregations.by_category;
//reset the url, removing the params and fragment from the current url.
const urlTree = this.router.createUrlTree(["/sources"],{
relativeTo: this.route,
});
this.location.replaceState(urlTree.toString());
const expectedSourceStateInfo = JSON.parse(localStorage.getItem(callbackState))
localStorage.removeItem(callbackState)
if(callbackError && !callbackCode){
//TOOD: print this message in the UI
let errMsg = "an error occurred while authenticating to this source. Please try again later"
console.error(errMsg, callbackErrorDescription)
throw new Error(errMsg)
}
console.log("callback code:", callbackCode)
this.status[sourceType] = "token"
let payload: any
payload = await this.lighthouseApi.swapOauthToken(sourceType, sourceMetadata,expectedSourceStateInfo, callbackCode)
if(!payload.access_token || payload.error){
//if the access token is not set, then something is wrong,
let errMsg = payload.error || "unable to retrieve access_token"
console.error(errMsg)
throw new Error(errMsg)
}
//If payload.patient is not set, make sure we extract the patient ID from the id_token or make an introspection req
if(!payload.patient && payload.id_token){
//
console.log("NO PATIENT ID present, decoding jwt to extract patient")
//const introspectionResp = await Oauth.introspectionRequest(as, client, payload.access_token)
//console.log(introspectionResp)
let decodedIdToken = this.jwtDecode(payload.id_token)
//nextGen uses fhirUser instead of profile.
payload.patient = decodedIdToken["profile"] || decodedIdToken["fhirUser"]
if(payload.patient){
payload.patient = payload.patient.replace(/^(Patient\/)/,'')
var currentCategories = this.filterForm.get('categories').value;
this.resultLimits.categoryBuckets.buckets.forEach((bucketData) => {
if(!currentCategories.hasOwnProperty(bucketData.key)){
(this.filterForm.get('categories') as FormGroup).addControl(bucketData.key, new FormControl(false))
}
}
//Create FHIR Client
const dbSourceCredential = new Source({
source_type: sourceType,
authorization_endpoint: sourceMetadata.authorization_endpoint,
token_endpoint: sourceMetadata.token_endpoint,
introspection_endpoint: sourceMetadata.introspection_endpoint,
userinfo_endpoint: sourceMetadata.userinfo_endpoint,
api_endpoint_base_url: sourceMetadata.api_endpoint_base_url,
client_id: sourceMetadata.client_id,
redirect_uri: sourceMetadata.redirect_uri,
scopes_supported: sourceMetadata.scopes_supported,
issuer: sourceMetadata.issuer,
grant_types_supported: sourceMetadata.grant_types_supported,
response_types_supported: sourceMetadata.response_types_supported,
aud: sourceMetadata.aud,
code_challenge_methods_supported: sourceMetadata.code_challenge_methods_supported,
confidential: sourceMetadata.confidential,
cors_relay_required: sourceMetadata.cors_relay_required,
patient: payload.patient,
access_token: payload.access_token,
refresh_token: payload.refresh_token,
id_token: payload.id_token,
// @ts-ignore - in some cases the getAccessTokenExpiration is a string, which cases failures to store Source in db.
expires_at: parseInt(this.getAccessTokenExpiration(payload)),
})
//
// this.resultLimits.categoryBuckets.forEach((bucketData) => {
// if(!this.globalLimits.categories.some((category) => { return category.id === bucketData.key})){
// this.globalLimits.categories.push({
// id: bucketData.key,
// name: bucketData.key,
// group: 'custom'
// })
// }
// })
this.fastenApi.createSource(dbSourceCredential)
.subscribe((resp) => {
// const sourceSyncMessage = JSON.parse(msg) as SourceSyncMessage
delete this.status[sourceType]
// window.location.reload();
// this.connectedSourceList.
//find the index of the "inprogress" source in the connected List, and then add this source to its source metadata.
let foundSource = this.connectedSourceList.findIndex((item) => item.metadata.source_type == sourceType)
this.connectedSourceList[foundSource].source = resp.source
console.log("source sync-all response:", resp.summary)
const toastNotification = new ToastNotification()
toastNotification.type = ToastType.Success
toastNotification.message = `Successfully connected ${sourceType}`
// const upsertSummary = sourceSyncMessage.response as UpsertSummary
// if(upsertSummary && upsertSummary.totalResources != upsertSummary.updatedResources.length){
// toastNotification.message += `\n (total: ${upsertSummary.totalResources}, updated: ${upsertSummary.updatedResources.length})`
// } else if(upsertSummary){
// toastNotification.message += `\n (total: ${upsertSummary.totalResources})`
// }
this.toastService.show(toastNotification)
},
(err) => {
delete this.status[sourceType]
// window.location.reload();
const toastNotification = new ToastNotification()
toastNotification.type = ToastType.Error
toastNotification.message = `An error occurred while accessing ${sourceType}: ${err}`
toastNotification.autohide = false
this.toastService.show(toastNotification)
console.error(err)
});
})
.catch((err) => {
delete this.status[sourceType]
// window.location.reload();
const toastNotification = new ToastNotification()
toastNotification.type = ToastType.Error
toastNotification.message = `An error occurred while accessing ${sourceType}: ${err}`
toastNotification.autohide = false
this.toastService.show(toastNotification)
console.error(err)
})
// const fileTypes = <FormGroup>this.filterForm.get('fileTypes');
// fileTypes.forEach((option: any) => {
// checkboxes.addControl(option.title, new FormControl(true));
// });
this.loading = false
},
error => {
this.loading = false
console.error("sources FAILED", error)
},
() => {
this.loading = false
console.log("sources finished")
}
);
return searchObservable;
}
//OLD FUNCTIONS
//
//
// private populateAvailableSourceList(results: LighthouseSourceSearch): void {
// console.log("AGGREGATIONS!!!!!", results.aggregations)
// this.totalAvailableSourceList = results.hits.total.value
// if(results.hits.hits.length == 0){
// this.scrollComplete = true
// console.log("scroll complete")
// return
// }
// this.scrollId = results._scroll_id
// this.availableSourceList = this.availableSourceList.concat(results.hits.hits.map((result) => {
// return {metadata: result._source}
// }).filter((item) => {
// return !this.connectedSourceList.find((connectedItem) => connectedItem.metadata.source_type == item.metadata.source_type)
// }))
// }
//
public onScroll(): void {
console.log("TODO: SCROLL, TRIGGER update")
this.querySources()
}
// /**
// * after pressing the logo (connectHandler button), this function will generate an authorize url for this source, and redirec the user.
// * @param $event
// * @param sourceType
// */
public connectHandler($event: MouseEvent, sourceType: string):void {
console.log("TODO: connect Handler")
// ($event.currentTarget as HTMLButtonElement).disabled = true;
// this.status[sourceType] = "authorize"
//
// this.lighthouseApi.getLighthouseSource(sourceType)
// .then(async (sourceMetadata: LighthouseSourceMetadata) => {
// console.log(sourceMetadata);
// let authorizationUrl = await this.lighthouseApi.generateSourceAuthorizeUrl(sourceType, sourceMetadata)
//
// console.log('authorize url:', authorizationUrl.toString());
// // redirect to lighthouse with uri's
// this.lighthouseApi.redirectWithOriginAndDestination(authorizationUrl.toString(), sourceType, sourceMetadata.redirect_uri)
//
// });
}
//
// /**
// * if the user is redirected to this page from the lighthouse, we'll need to process the "code" to retrieve the access token & refresh token.
// * @param sourceType
// */
// public async callback(sourceType: string) {
//
// //get the source metadata again
// await this.lighthouseApi.getLighthouseSource(sourceType)
// .then(async (sourceMetadata: LighthouseSourceMetadata) => {
//
// //get required parameters from the URI and local storage
// const callbackUrlParts = new URL(window.location.href)
// const fragmentParams = new URLSearchParams(callbackUrlParts.hash.substring(1))
// const callbackCode = callbackUrlParts.searchParams.get("code") || fragmentParams.get("code")
// const callbackState = callbackUrlParts.searchParams.get("state") || fragmentParams.get("state")
// const callbackError = callbackUrlParts.searchParams.get("error") || fragmentParams.get("error")
// const callbackErrorDescription = callbackUrlParts.searchParams.get("error_description") || fragmentParams.get("error_description")
//
// //reset the url, removing the params and fragment from the current url.
// const urlTree = this.router.createUrlTree(["/sources"],{
// relativeTo: this.route,
// });
// this.location.replaceState(urlTree.toString());
//
// const expectedSourceStateInfo = JSON.parse(localStorage.getItem(callbackState))
// localStorage.removeItem(callbackState)
//
// if(callbackError && !callbackCode){
// //TOOD: print this message in the UI
// let errMsg = "an error occurred while authenticating to this source. Please try again later"
// console.error(errMsg, callbackErrorDescription)
// throw new Error(errMsg)
// }
//
// console.log("callback code:", callbackCode)
// this.status[sourceType] = "token"
//
// let payload: any
// payload = await this.lighthouseApi.swapOauthToken(sourceType, sourceMetadata,expectedSourceStateInfo, callbackCode)
//
// if(!payload.access_token || payload.error){
// //if the access token is not set, then something is wrong,
// let errMsg = payload.error || "unable to retrieve access_token"
// console.error(errMsg)
// throw new Error(errMsg)
// }
//
// //If payload.patient is not set, make sure we extract the patient ID from the id_token or make an introspection req
// if(!payload.patient && payload.id_token){
// //
// console.log("NO PATIENT ID present, decoding jwt to extract patient")
// //const introspectionResp = await Oauth.introspectionRequest(as, client, payload.access_token)
// //console.log(introspectionResp)
// let decodedIdToken = this.jwtDecode(payload.id_token)
// //nextGen uses fhirUser instead of profile.
// payload.patient = decodedIdToken["profile"] || decodedIdToken["fhirUser"]
//
// if(payload.patient){
// payload.patient = payload.patient.replace(/^(Patient\/)/,'')
// }
//
// }
//
//
//
// //Create FHIR Client
//
// const dbSourceCredential = new Source({
// source_type: sourceType,
//
// authorization_endpoint: sourceMetadata.authorization_endpoint,
// token_endpoint: sourceMetadata.token_endpoint,
// introspection_endpoint: sourceMetadata.introspection_endpoint,
// userinfo_endpoint: sourceMetadata.userinfo_endpoint,
// api_endpoint_base_url: sourceMetadata.api_endpoint_base_url,
// client_id: sourceMetadata.client_id,
// redirect_uri: sourceMetadata.redirect_uri,
// scopes_supported: sourceMetadata.scopes_supported,
// issuer: sourceMetadata.issuer,
// grant_types_supported: sourceMetadata.grant_types_supported,
// response_types_supported: sourceMetadata.response_types_supported,
// aud: sourceMetadata.aud,
// code_challenge_methods_supported: sourceMetadata.code_challenge_methods_supported,
// confidential: sourceMetadata.confidential,
// cors_relay_required: sourceMetadata.cors_relay_required,
//
// patient: payload.patient,
// access_token: payload.access_token,
// refresh_token: payload.refresh_token,
// id_token: payload.id_token,
//
// // @ts-ignore - in some cases the getAccessTokenExpiration is a string, which cases failures to store Source in db.
// expires_at: parseInt(this.getAccessTokenExpiration(payload)),
// })
//
// this.fastenApi.createSource(dbSourceCredential)
// .subscribe((resp) => {
// // const sourceSyncMessage = JSON.parse(msg) as SourceSyncMessage
// delete this.status[sourceType]
// // window.location.reload();
// // this.connectedSourceList.
//
// //find the index of the "inprogress" source in the connected List, and then add this source to its source metadata.
// let foundSource = this.connectedSourceList.findIndex((item) => item.metadata.source_type == sourceType)
// this.connectedSourceList[foundSource].source = resp.source
//
// console.log("source sync-all response:", resp.summary)
//
// const toastNotification = new ToastNotification()
// toastNotification.type = ToastType.Success
// toastNotification.message = `Successfully connected ${sourceType}`
//
// // const upsertSummary = sourceSyncMessage.response as UpsertSummary
// // if(upsertSummary && upsertSummary.totalResources != upsertSummary.updatedResources.length){
// // toastNotification.message += `\n (total: ${upsertSummary.totalResources}, updated: ${upsertSummary.updatedResources.length})`
// // } else if(upsertSummary){
// // toastNotification.message += `\n (total: ${upsertSummary.totalResources})`
// // }
//
// this.toastService.show(toastNotification)
// },
// (err) => {
// delete this.status[sourceType]
// // window.location.reload();
//
// const toastNotification = new ToastNotification()
// toastNotification.type = ToastType.Error
// toastNotification.message = `An error occurred while accessing ${sourceType}: ${err}`
// toastNotification.autohide = false
// this.toastService.show(toastNotification)
// console.error(err)
// });
// })
// .catch((err) => {
// delete this.status[sourceType]
// // window.location.reload();
//
// const toastNotification = new ToastNotification()
// toastNotification.type = ToastType.Error
// toastNotification.message = `An error occurred while accessing ${sourceType}: ${err}`
// toastNotification.autohide = false
// this.toastService.show(toastNotification)
// console.error(err)
// })
// }
/**
* this function is used to process manually "uploaded" FHIR bundle files, adding them to the database.
* @param event
@ -337,52 +488,14 @@ export class MedicalSourcesComponent implements OnInit {
)
}
public openModal(contentModalRef, sourceListItem: SourceListItem) {
if(this.status[sourceListItem.metadata.source_type] || !sourceListItem.source){
//if this source is currently "loading" dont open the modal window
return
}
this.modalSelectedSourceListItem = sourceListItem
this.modalService.open(contentModalRef, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
this.modalSelectedSourceListItem = null
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.modalSelectedSourceListItem = null
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
public sourceSyncHandler(source: Source){
this.status[source.source_type] = "authorize"
this.modalService.dismissAll()
this.fastenApi.syncSource(source.id).subscribe(
(respData) => {
delete this.status[source.source_type]
console.log("source sync response:", respData)
},
(err) => {
delete this.status[source.source_type]
console.log(err)
}
)
}
///////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
/**

View File

@ -11,6 +11,7 @@ import {MetadataSource} from '../models/fasten/metadata-source';
import {uuidV4} from '../../lib/utils/uuid';
import {LighthouseSourceSearch} from '../models/lighthouse/lighthouse-source-search';
import {HTTP_CLIENT_TOKEN} from "../dependency-injection";
import {MedicalSourcesFilter} from './medical-sources-filter.service';
@Injectable({
providedIn: 'root'
@ -20,19 +21,14 @@ export class LighthouseService {
constructor(@Inject(HTTP_CLIENT_TOKEN) private _httpClient: HttpClient) {
}
public findLighthouseSources(searchTerm: string, scrollId= "", showHidden = false): Observable<LighthouseSourceSearch> {
const endpointUrl = new URL(`${environment.lighthouse_api_endpoint_base}/list/search`);
if(showHidden){
endpointUrl.searchParams.set('show_hidden', 'true');
public searchLighthouseSources(filter: MedicalSourcesFilter): Observable<LighthouseSourceSearch> {
if(filter.searchAfter){
filter.searchAfter = (filter.searchAfter as string).split(',')
} else {
filter.searchAfter = []
}
if(scrollId){
endpointUrl.searchParams.set('scroll_id', scrollId);
}
if(searchTerm){
endpointUrl.searchParams.set('query', searchTerm);
}
return this._httpClient.get<ResponseWrapper>(endpointUrl.toString())
const endpointUrl = new URL(`${environment.lighthouse_api_endpoint_base}/search`);
return this._httpClient.post<ResponseWrapper>(endpointUrl.toString(), filter)
.pipe(
map((response: ResponseWrapper) => {
console.log("Metadata RESPONSE", response)
@ -41,6 +37,28 @@ export class LighthouseService {
);
}
//deprecated
// public findLighthouseSources(searchTerm: string, scrollId= "", showHidden = false): Observable<LighthouseSourceSearch> {
// const endpointUrl = new URL(`${environment.lighthouse_api_endpoint_base}/list/search`);
// if(showHidden){
// endpointUrl.searchParams.set('show_hidden', 'true');
// }
// if(scrollId){
// endpointUrl.searchParams.set('scroll_id', scrollId);
// }
// if(searchTerm){
// endpointUrl.searchParams.set('query', searchTerm);
// }
//
// return this._httpClient.get<ResponseWrapper>(endpointUrl.toString())
// .pipe(
// map((response: ResponseWrapper) => {
// console.log("Metadata RESPONSE", response)
// return response.data as LighthouseSourceSearch
// })
// );
// }
public getLighthouseSourceMetadataMap(showHidden = false): Observable<{[name: string]: MetadataSource}> {
const endpointUrl = new URL(`${environment.lighthouse_api_endpoint_base}/list`);
if(showHidden){
@ -209,881 +227,5 @@ export class LighthouseService {
})
return parts.join(separator);
}
public categoryCodeLookup(code: string): string {
return SOURCE_CATEGORY_CODE_LOOKUP[code];
}
}
const SOURCE_CATEGORY_CODE_LOOKUP = {
"101200000X": "Drama Therapist",
"101Y00000X": "Counselor",
"101YA0400X": "Addiction (Substance Use Disorder) Counselor",
"101YM0800X": "Mental Health Counselor",
"101YP1600X": "Pastoral Counselor",
"101YP2500X": "Professional Counselor",
"101YS0200X": "School Counselor",
"102L00000X": "Psychoanalyst",
"102X00000X": "Poetry Therapist",
"103G00000X": "Clinical Neuropsychologist",
"103GC0700X": "Deactivated - Clinical Neuropsychologist",
"103K00000X": "Behavioral Analyst",
"103T00000X": "Psychologist",
"103TA0400X": "Addiction (Substance Use Disorder) Psychologist",
"103TA0700X": "Adult Development & Aging Psychologist",
"103TB0200X": "Cognitive & Behavioral Psychologist",
"103TC0700X": "Clinical Psychologist",
"103TC1900X": "Counseling Psychologist",
"103TC2200X": "Clinical Child & Adolescent Psychologist",
"103TE1000X": "Deactivated - Psychologist",
"103TE1100X": "Exercise & Sports Psychologist",
"103TF0000X": "Family Psychologist",
"103TF0200X": "Forensic Psychologist",
"103TH0004X": "Health Psychologist",
"103TH0100X": "Health Service Psychologist",
"103TM1700X": "Deactivated - Psychologist Men & Masculinity",
"103TM1800X": "Intellectual & Developmental Disabilities Psychologist",
"103TP0016X": "Prescribing (Medical) Psychologist",
"103TP0814X": "Psychoanalysis Psychologist",
"103TP2700X": "Deactivated - Psychologist Psychotherapy",
"103TP2701X": "Group Psychotherapy Psychologist",
"103TR0400X": "Rehabilitation Psychologist",
"103TS0200X": "School Psychologist",
"103TW0100X": "Deactivated - Psychotherapy Women",
"104100000X": "Social Worker",
"1041C0700X": "Clinical Social Worker",
"1041S0200X": "School Social Worker",
"106E00000X": "Assistant Behavior Analyst",
"106H00000X": "Marriage & Family Therapist",
"106S00000X": "Behavior Technician",
"111N00000X": "Chiropractor",
"111NI0013X": "Independent Medical Examiner Chiropractor",
"111NI0900X": "Internist Chiropractor",
"111NN0400X": "Neurology Chiropractor",
"111NN1001X": "Nutrition Chiropractor",
"111NP0017X": "Pediatric Chiropractor",
"111NR0200X": "Radiology Chiropractor",
"111NR0400X": "Rehabilitation Chiropractor",
"111NS0005X": "Sports Physician Chiropractor",
"111NT0100X": "Thermography Chiropractor",
"111NX0100X": "Occupational Health Chiropractor",
"111NX0800X": "Orthopedic Chiropractor",
"122300000X": "Dentist",
"1223D0001X": "Public Health Dentist",
"1223D0004X": "Dentist Anesthesiologist",
"1223E0200X": "Endodontist",
"1223G0001X": "General Practice Dentistry",
"1223P0106X": "Oral and Maxillofacial Pathology Dentist",
"1223P0221X": "Pediatric Dentist",
"1223P0300X": "Periodontist",
"1223P0700X": "Prosthodontist",
"1223S0112X": "Oral and Maxillofacial Surgery (Dentist)",
"1223X0008X": "Oral and Maxillofacial Radiology Dentist",
"1223X0400X": "Orthodontics and Dentofacial Orthopedic Dentist",
"1223X2210X": "Orofacial Pain Dentist",
"122400000X": "Denturist",
"124Q00000X": "Dental Hygienist",
"125J00000X": "Dental Therapist",
"125K00000X": "Advanced Practice Dental Therapist",
"125Q00000X": "Oral Medicinist",
"126800000X": "Dental Assistant",
"126900000X": "Dental Laboratory Technician",
"132700000X": "Dietary Manager",
"133N00000X": "Nutritionist",
"133NN1002X": "Nutrition Education Nutritionist",
"133V00000X": "Registered Dietitian",
"133VN1004X": "Pediatric Nutrition Registered Dietitian",
"133VN1005X": "Renal Nutrition Registered Dietitian",
"133VN1006X": "Metabolic Nutrition Registered Dietitian",
"133VN1101X": "Gerontological Nutrition Registered Dietitian",
"133VN1201X": "Obesity and Weight Management Nutrition Registered Dietitian",
"133VN1301X": "Oncology Nutrition Registered Dietitian",
"133VN1401X": "Pediatric Critical Care Nutrition Registered Dietitian",
"133VN1501X": "Sports Dietetics Nutrition Registered Dietitian",
"136A00000X": "Registered Dietetic Technician",
"146D00000X": "Personal Emergency Response Attendant",
"146L00000X": "Paramedic",
"146M00000X": "Intermediate Emergency Medical Technician",
"146N00000X": "Basic Emergency Medical Technician",
"152W00000X": "Optometrist",
"152WC0802X": "Corneal and Contact Management Optometrist",
"152WL0500X": "Low Vision Rehabilitation Optometrist",
"152WP0200X": "Pediatric Optometrist",
"152WS0006X": "Sports Vision Optometrist",
"152WV0400X": "Vision Therapy Optometrist",
"152WX0102X": "Occupational Vision Optometrist",
"156F00000X": "Technician/Technologist",
"156FC0800X": "Contact Lens Technician/Technologist",
"156FC0801X": "Contact Lens Fitter",
"156FX1100X": "Ophthalmic Technician/Technologist",
"156FX1101X": "Ophthalmic Assistant",
"156FX1201X": "Optometric Assistant Technician",
"156FX1202X": "Optometric Technician",
"156FX1700X": "Ocularist",
"156FX1800X": "Optician",
"156FX1900X": "Orthoptist",
"163W00000X": "Registered Nurse",
"163WA0400X": "Addiction (Substance Use Disorder) Registered Nurse",
"163WA2000X": "Administrator Registered Nurse",
"163WC0200X": "Critical Care Medicine Registered Nurse",
"163WC0400X": "Case Management Registered Nurse",
"163WC1400X": "College Health Registered Nurse",
"163WC1500X": "Community Health Registered Nurse",
"163WC1600X": "Continuing Education/Staff Development Registered Nurse",
"163WC2100X": "Continence Care Registered Nurse",
"163WC3500X": "Cardiac Rehabilitation Registered Nurse",
"163WD0400X": "Diabetes Educator Registered Nurse",
"163WD1100X": "Peritoneal Dialysis Registered Nurse",
"163WE0003X": "Emergency Registered Nurse",
"163WE0900X": "Enterostomal Therapy Registered Nurse",
"163WF0300X": "Flight Registered Nurse",
"163WG0000X": "General Practice Registered Nurse",
"163WG0100X": "Gastroenterology Registered Nurse",
"163WG0600X": "Gerontology Registered Nurse",
"163WH0200X": "Home Health Registered Nurse",
"163WH0500X": "Hemodialysis Registered Nurse",
"163WH1000X": "Hospice Registered Nurse",
"163WI0500X": "Infusion Therapy Registered Nurse",
"163WI0600X": "Infection Control Registered Nurse",
"163WL0100X": "Lactation Consultant (Registered Nurse)",
"163WM0102X": "Maternal Newborn Registered Nurse",
"163WM0705X": "Medical-Surgical Registered Nurse",
"163WM1400X": "Nurse Massage Therapist (NMT)",
"163WN0002X": "Neonatal Intensive Care Registered Nurse",
"163WN0003X": "Low-Risk Neonatal Registered Nurse",
"163WN0300X": "Nephrology Registered Nurse",
"163WN0800X": "Neuroscience Registered Nurse",
"163WN1003X": "Nutrition Support Registered Nurse",
"163WP0000X": "Pain Management Registered Nurse",
"163WP0200X": "Pediatric Registered Nurse",
"163WP0218X": "Pediatric Oncology Registered Nurse",
"163WP0807X": "Child & Adolescent Psychiatric/Mental Health Registered Nurse",
"163WP0808X": "Psychiatric/Mental Health Registered Nurse",
"163WP0809X": "Adult Psychiatric/Mental Health Registered Nurse",
"163WP1700X": "Perinatal Registered Nurse",
"163WP2201X": "Ambulatory Care Registered Nurse",
"163WR0006X": "Registered Nurse First Assistant",
"163WR0400X": "Rehabilitation Registered Nurse",
"163WR1000X": "Reproductive Endocrinology/Infertility Registered Nurse",
"163WS0121X": "Plastic Surgery Registered Nurse",
"163WS0200X": "School Registered Nurse",
"163WU0100X": "Urology Registered Nurse",
"163WW0000X": "Wound Care Registered Nurse",
"163WW0101X": "Ambulatory Women's Health Care Registered Nurse",
"163WX0002X": "High-Risk Obstetric Registered Nurse",
"163WX0003X": "Inpatient Obstetric Registered Nurse",
"163WX0106X": "Occupational Health Registered Nurse",
"163WX0200X": "Oncology Registered Nurse",
"163WX0601X": "Otorhinolaryngology & Head-Neck Registered Nurse",
"163WX0800X": "Orthopedic Registered Nurse",
"163WX1100X": "Ophthalmic Registered Nurse",
"163WX1500X": "Ostomy Care Registered Nurse",
"164W00000X": "Licensed Practical Nurse",
"164X00000X": "Licensed Vocational Nurse",
"167G00000X": "Licensed Psychiatric Technician",
"170100000X": "Ph.D. Medical Genetics",
"170300000X": "Genetic Counselor (M.S.)",
"171000000X": "Military Health Care Provider",
"1710I1002X": "Independent Duty Corpsman",
"1710I1003X": "Independent Duty Medical Technicians",
"171100000X": "Acupuncturist",
"171400000X": "Health & Wellness Coach",
"171M00000X": "Case Manager/Care Coordinator",
"171R00000X": "Interpreter",
"171W00000X": "Contractor",
"171WH0202X": "Home Modifications Contractor",
"171WV0202X": "Vehicle Modifications Contractor",
"172A00000X": "Driver",
"172M00000X": "Mechanotherapist",
"172P00000X": "Naprapath",
"172V00000X": "Community Health Worker",
"173000000X": "Legal Medicine",
"173C00000X": "Reflexologist",
"173F00000X": "Sleep Specialist (PhD)",
"174200000X": "Meals Provider",
"174400000X": "Specialist",
"1744G0900X": "Graphics Designer",
"1744P3200X": "Prosthetics Case Management",
"1744R1102X": "Research Study Specialist",
"1744R1103X": "Research Study Abstracter/Coder",
"174H00000X": "Health Educator",
"174M00000X": "Veterinarian",
"174MM1900X": "Medical Research Veterinarian",
"174N00000X": "Lactation Consultant (Non-RN)",
"174V00000X": "Clinical Ethicist",
"175F00000X": "Naturopath",
"175L00000X": "Homeopath",
"175M00000X": "Lay Midwife",
"175T00000X": "Peer Specialist",
"176B00000X": "Midwife",
"176P00000X": "Funeral Director",
"177F00000X": "Lodging Provider",
"183500000X": "Pharmacist",
"1835C0205X": "Critical Care Pharmacist",
"1835G0000X": "Deactivated - Pharmacist",
"1835G0303X": "Geriatric Pharmacist",
"1835N0905X": "Nuclear Pharmacist",
"1835N1003X": "Nutrition Support Pharmacist",
"1835P0018X": "Pharmacist Clinician (PhC)/ Clinical Pharmacy Specialist",
"1835P0200X": "Pediatric Pharmacist",
"1835P1200X": "Pharmacotherapy Pharmacist",
"1835P1300X": "Psychiatric Pharmacist",
"1835P2201X": "Ambulatory Care Pharmacist",
"1835X0200X": "Oncology Pharmacist",
"183700000X": "Pharmacy Technician",
"193200000X": "Multi-Specialty Group",
"193400000X": "Single Specialty Group",
"202C00000X": "Independent Medical Examiner Physician",
"202D00000X": "Integrative Medicine",
"202K00000X": "Phlebology Physician",
"204C00000X": "Sports Medicine (Neuromusculoskeletal Medicine) Physician",
"204D00000X": "Neuromusculoskeletal Medicine & OMM Physician",
"204E00000X": "Oral & Maxillofacial Surgery (D.M.D.)",
"204F00000X": "Transplant Surgery Physician",
"204R00000X": "Electrodiagnostic Medicine Physician",
"207K00000X": "Allergy & Immunology Physician",
"207KA0200X": "Allergy Physician",
"207KI0005X": "Clinical & Laboratory Immunology (Allergy & Immunology) Physician",
"207L00000X": "Anesthesiology Physician",
"207LA0401X": "Addiction Medicine (Anesthesiology) Physician",
"207LC0200X": "Critical Care Medicine (Anesthesiology) Physician",
"207LH0002X": "Hospice and Palliative Medicine (Anesthesiology) Physician",
"207LP2900X": "Pain Medicine (Anesthesiology) Physician",
"207LP3000X": "Pediatric Anesthesiology Physician",
"207N00000X": "Dermatology Physician",
"207ND0101X": "MOHS-Micrographic Surgery Physician",
"207ND0900X": "Dermatopathology Physician",
"207NI0002X": "Clinical & Laboratory Dermatological Immunology Physician",
"207NP0225X": "Pediatric Dermatology Physician",
"207NS0135X": "Procedural Dermatology Physician",
"207P00000X": "Emergency Medicine Physician",
"207PE0004X": "Emergency Medical Services (Emergency Medicine) Physician",
"207PE0005X": "Undersea and Hyperbaric Medicine (Emergency Medicine) Physician",
"207PH0002X": "Hospice and Palliative Medicine (Emergency Medicine) Physician",
"207PP0204X": "Pediatric Emergency Medicine (Emergency Medicine) Physician",
"207PS0010X": "Sports Medicine (Emergency Medicine) Physician",
"207PT0002X": "Medical Toxicology (Emergency Medicine) Physician",
"207Q00000X": "Family Medicine Physician",
"207QA0000X": "Adolescent Medicine (Family Medicine) Physician",
"207QA0401X": "Addiction Medicine (Family Medicine) Physician",
"207QA0505X": "Adult Medicine Physician",
"207QB0002X": "Obesity Medicine (Family Medicine) Physician",
"207QG0300X": "Geriatric Medicine (Family Medicine) Physician",
"207QH0002X": "Hospice and Palliative Medicine (Family Medicine) Physician",
"207QS0010X": "Sports Medicine (Family Medicine) Physician",
"207QS1201X": "Sleep Medicine (Family Medicine) Physician",
"207R00000X": "Internal Medicine Physician",
"207RA0000X": "Adolescent Medicine (Internal Medicine) Physician",
"207RA0001X": "Advanced Heart Failure and Transplant Cardiology Physician",
"207RA0002X": "Adult Congenital Heart Disease Physician",
"207RA0201X": "Allergy & Immunology (Internal Medicine) Physician",
"207RA0401X": "Addiction Medicine (Internal Medicine) Physician",
"207RB0002X": "Obesity Medicine (Internal Medicine) Physician",
"207RC0000X": "Cardiovascular Disease Physician",
"207RC0001X": "Clinical Cardiac Electrophysiology Physician",
"207RC0200X": "Critical Care Medicine (Internal Medicine) Physician",
"207RE0101X": "Endocrinology, Diabetes & Metabolism Physician",
"207RG0100X": "Gastroenterology Physician",
"207RG0300X": "Geriatric Medicine (Internal Medicine) Physician",
"207RH0000X": "Hematology (Internal Medicine) Physician",
"207RH0002X": "Hospice and Palliative Medicine (Internal Medicine) Physician",
"207RH0003X": "Hematology & Oncology Physician",
"207RH0005X": "Hypertension Specialist Physician",
"207RI0001X": "Clinical & Laboratory Immunology (Internal Medicine) Physician",
"207RI0008X": "Hepatology Physician",
"207RI0011X": "Interventional Cardiology Physician",
"207RI0200X": "Infectious Disease Physician",
"207RM1200X": "Magnetic Resonance Imaging (MRI) Internal Medicine Physician",
"207RN0300X": "Nephrology Physician",
"207RP1001X": "Pulmonary Disease Physician",
"207RR0500X": "Rheumatology Physician",
"207RS0010X": "Sports Medicine (Internal Medicine) Physician",
"207RS0012X": "Sleep Medicine (Internal Medicine) Physician",
"207RT0003X": "Transplant Hepatology Physician",
"207RX0202X": "Medical Oncology Physician",
"207SC0300X": "Clinical Cytogenetics Physician",
"207SG0201X": "Clinical Genetics (M.D.) Physician",
"207SG0202X": "Clinical Biochemical Genetics Physician",
"207SG0203X": "Clinical Molecular Genetics Physician",
"207SG0205X": "Ph.D. Medical Genetics Physician",
"207SM0001X": "Molecular Genetic Pathology (Medical Genetics) Physician",
"207T00000X": "Neurological Surgery Physician",
"207U00000X": "Nuclear Medicine Physician",
"207UN0901X": "Nuclear Cardiology Physician",
"207UN0902X": "Nuclear Imaging & Therapy Physician",
"207UN0903X": "In Vivo & In Vitro Nuclear Medicine Physician",
"207V00000X": "Obstetrics & Gynecology Physician",
"207VB0002X": "Obesity Medicine (Obstetrics & Gynecology) Physician",
"207VC0200X": "Critical Care Medicine (Obstetrics & Gynecology) Physician",
"207VC0300X": "Complex Family Planning",
"207VE0102X": "Reproductive Endocrinology Physician",
"207VF0040X": "Female Pelvic Medicine and Reconstructive Surgery (Obstetrics & Gynecology) Physician",
"207VG0400X": "Gynecology Physician",
"207VH0002X": "Hospice and Palliative Medicine (Obstetrics & Gynecology) Physician",
"207VM0101X": "Maternal & Fetal Medicine Physician",
"207VX0000X": "Obstetrics Physician",
"207VX0201X": "Gynecologic Oncology Physician",
"207W00000X": "Ophthalmology Physician",
"207WX0009X": "Glaucoma Specialist (Ophthalmology) Physician",
"207WX0107X": "Retina Specialist (Ophthalmology) Physician",
"207WX0108X": "Uveitis and Ocular Inflammatory Disease (Ophthalmology) Physician",
"207WX0109X": "Neuro-ophthalmology Physician",
"207WX0110X": "Pediatric Ophthalmology and Strabismus Specialist Physician Physician",
"207WX0120X": "Cornea and External Diseases Specialist Physician",
"207WX0200X": "Ophthalmic Plastic and Reconstructive Surgery Physician",
"207X00000X": "Orthopaedic Surgery Physician",
"207XP3100X": "Pediatric Orthopaedic Surgery Physician",
"207XS0106X": "Orthopaedic Hand Surgery Physician",
"207XS0114X": "Adult Reconstructive Orthopaedic Surgery Physician",
"207XS0117X": "Orthopaedic Surgery of the Spine Physician",
"207XX0004X": "Orthopaedic Foot and Ankle Surgery Physician",
"207XX0005X": "Sports Medicine (Orthopaedic Surgery) Physician",
"207XX0801X": "Orthopaedic Trauma Physician",
"207Y00000X": "Otolaryngology Physician",
"207YP0228X": "Pediatric Otolaryngology Physician",
"207YS0012X": "Sleep Medicine (Otolaryngology) Physician",
"207YS0123X": "Facial Plastic Surgery Physician",
"207YX0007X": "Plastic Surgery within the Head & Neck (Otolaryngology) Physician",
"207YX0602X": "Otolaryngic Allergy Physician",
"207YX0901X": "Otology & Neurotology Physician",
"207YX0905X": "Otolaryngology/Facial Plastic Surgery Physician",
"207ZB0001X": "Blood Banking & Transfusion Medicine Physician",
"207ZC0006X": "Clinical Pathology Physician",
"207ZC0008X": "Clinical Informatics (Pathology) Physician",
"207ZC0500X": "Cytopathology Physician",
"207ZD0900X": "Dermatopathology (Pathology) Physician",
"207ZF0201X": "Forensic Pathology Physician",
"207ZH0000X": "Hematology (Pathology) Physician",
"207ZI0100X": "Immunopathology Physician",
"207ZM0300X": "Medical Microbiology Physician",
"207ZN0500X": "Neuropathology Physician",
"207ZP0007X": "Molecular Genetic Pathology (Pathology) Physician",
"207ZP0101X": "Anatomic Pathology Physician",
"207ZP0102X": "Anatomic Pathology & Clinical Pathology Physician",
"207ZP0104X": "Chemical Pathology Physician",
"207ZP0105X": "Clinical Pathology/Laboratory Medicine Physician",
"207ZP0213X": "Pediatric Pathology Physician",
"208000000X": "Pediatrics Physician",
"2080A0000X": "Pediatric Adolescent Medicine Physician",
"2080B0002X": "Pediatric Obesity Medicine Physician",
"2080C0008X": "Child Abuse Pediatrics Physician",
"2080H0002X": "Pediatric Hospice and Palliative Medicine Physician",
"2080I0007X": "Pediatric Clinical & Laboratory Immunology Physician",
"2080N0001X": "Neonatal-Perinatal Medicine Physician",
"2080P0006X": "Developmental - Behavioral Pediatrics Physician",
"2080P0008X": "Pediatric Neurodevelopmental Disabilities Physician",
"2080P0201X": "Pediatric Allergy/Immunology Physician",
"2080P0202X": "Pediatric Cardiology Physician",
"2080P0203X": "Pediatric Critical Care Medicine Physician",
"2080P0204X": "Pediatric Emergency Medicine (Pediatrics) Physician",
"2080P0205X": "Pediatric Endocrinology Physician",
"2080P0206X": "Pediatric Gastroenterology Physician",
"2080P0207X": "Pediatric Hematology & Oncology Physician",
"2080P0208X": "Pediatric Infectious Diseases Physician",
"2080P0210X": "Pediatric Nephrology Physician",
"2080P0214X": "Pediatric Pulmonology Physician",
"2080P0216X": "Pediatric Rheumatology Physician",
"2080S0010X": "Pediatric Sports Medicine Physician",
"2080S0012X": "Pediatric Sleep Medicine Physician",
"2080T0002X": "Pediatric Medical Toxicology Physician",
"2080T0004X": "Pediatric Transplant Hepatology Physician",
"208100000X": "Physical Medicine & Rehabilitation Physician",
"2081H0002X": "Hospice and Palliative Medicine (Physical Medicine & Rehabilitation) Physician",
"2081N0008X": "Neuromuscular Medicine (Physical Medicine & Rehabilitation) Physician",
"2081P0004X": "Spinal Cord Injury Medicine Physician",
"2081P0010X": "Pediatric Rehabilitation Medicine Physician",
"2081P0301X": "Brain Injury Medicine (Physical Medicine & Rehabilitation) Physician",
"2081P2900X": "Pain Medicine (Physical Medicine & Rehabilitation) Physician",
"2081S0010X": "Sports Medicine (Physical Medicine & Rehabilitation) Physician",
"208200000X": "Plastic Surgery Physician",
"2082S0099X": "Plastic Surgery Within the Head and Neck (Plastic Surgery) Physician",
"2082S0105X": "Surgery of the Hand (Plastic Surgery) Physician",
"2083A0100X": "Aerospace Medicine Physician",
"2083A0300X": "Addiction Medicine (Preventive Medicine) Physician",
"2083B0002X": "Obesity Medicine (Preventive Medicine) Physician",
"2083C0008X": "Clinical Informatics Physician",
"2083P0011X": "Undersea and Hyperbaric Medicine (Preventive Medicine) Physician",
"2083P0500X": "Preventive Medicine/Occupational Environmental Medicine Physician",
"2083P0901X": "Public Health & General Preventive Medicine Physician",
"2083S0010X": "Sports Medicine (Preventive Medicine) Physician",
"2083T0002X": "Medical Toxicology (Preventive Medicine) Physician",
"2083X0100X": "Occupational Medicine Physician",
"2084A0401X": "Addiction Medicine (Psychiatry & Neurology) Physician",
"2084A2900X": "Neurocritical Care Physician",
"2084B0002X": "Obesity Medicine (Psychiatry & Neurology) Physician",
"2084B0040X": "Behavioral Neurology & Neuropsychiatry Physician",
"2084D0003X": "Diagnostic Neuroimaging (Psychiatry & Neurology) Physician",
"2084E0001X": "Epilepsy Physician",
"2084F0202X": "Forensic Psychiatry Physician",
"2084H0002X": "Hospice and Palliative Medicine (Psychiatry & Neurology) Physician",
"2084N0008X": "Neuromuscular Medicine (Psychiatry & Neurology) Physician",
"2084N0400X": "Neurology Physician",
"2084N0402X": "Neurology with Special Qualifications in Child Neurology Physician",
"2084N0600X": "Clinical Neurophysiology Physician",
"2084P0005X": "Neurodevelopmental Disabilities Physician Physician",
"2084P0015X": "Psychosomatic Medicine Physician",
"2084P0301X": "Brain Injury Medicine (Psychiatry & Neurology) Physician",
"2084P0800X": "Psychiatry Physician",
"2084P0802X": "Addiction Psychiatry Physician",
"2084P0804X": "Child & Adolescent Psychiatry Physician",
"2084P0805X": "Geriatric Psychiatry Physician",
"2084P2900X": "Pain Medicine (Psychiatry & Neurology) Physician",
"2084S0010X": "Sports Medicine (Psychiatry & Neurology) Physician",
"2084S0012X": "Sleep Medicine (Psychiatry & Neurology) Physician",
"2084V0102X": "Vascular Neurology Physician",
"2085B0100X": "Body Imaging Physician",
"2085D0003X": "Diagnostic Neuroimaging (Radiology) Physician",
"2085H0002X": "Hospice and Palliative Medicine (Radiology) Physician",
"2085N0700X": "Neuroradiology Physician",
"2085N0904X": "Nuclear Radiology Physician",
"2085P0229X": "Pediatric Radiology Physician",
"2085R0001X": "Radiation Oncology Physician",
"2085R0202X": "Diagnostic Radiology Physician",
"2085R0203X": "Therapeutic Radiology Physician",
"2085R0204X": "Vascular & Interventional Radiology Physician",
"2085R0205X": "Radiological Physics Physician",
"2085U0001X": "Diagnostic Ultrasound Physician",
"208600000X": "Surgery Physician",
"2086H0002X": "Hospice and Palliative Medicine (Surgery) Physician",
"2086S0102X": "Surgical Critical Care Physician",
"2086S0105X": "Surgery of the Hand (Surgery) Physician",
"2086S0120X": "Pediatric Surgery Physician",
"2086S0122X": "Plastic and Reconstructive Surgery Physician",
"2086S0127X": "Trauma Surgery Physician",
"2086S0129X": "Vascular Surgery Physician",
"2086X0206X": "Surgical Oncology Physician",
"208800000X": "Urology Physician",
"2088F0040X": "Female Pelvic Medicine and Reconstructive Surgery (Urology) Physician",
"2088P0231X": "Pediatric Urology Physician",
"208C00000X": "Colon & Rectal Surgery Physician",
"208D00000X": "General Practice Physician",
"208G00000X": "Thoracic Surgery (Cardiothoracic Vascular Surgery) Physician",
"208M00000X": "Hospitalist Physician",
"208U00000X": "Clinical Pharmacology Physician",
"208VP0000X": "Pain Medicine Physician",
"208VP0014X": "Interventional Pain Medicine Physician",
"209800000X": "Legal Medicine (M.D./D.O.) Physician",
"211D00000X": "Podiatric Assistant",
"213E00000X": "Podiatrist",
"213EG0000X": "Deactivated - Podiatrist",
"213EP0504X": "Public Medicine Podiatrist",
"213EP1101X": "Primary Podiatric Medicine Podiatrist",
"213ER0200X": "Radiology Podiatrist",
"213ES0000X": "Sports Medicine Podiatrist",
"213ES0103X": "Foot & Ankle Surgery Podiatrist",
"213ES0131X": "Foot Surgery Podiatrist",
"221700000X": "Art Therapist",
"222Q00000X": "Developmental Therapist",
"222Z00000X": "Orthotist",
"224900000X": "Mastectomy Fitter",
"224L00000X": "Pedorthist",
"224P00000X": "Prosthetist",
"224Y00000X": "Clinical Exercise Physiologist",
"224Z00000X": "Occupational Therapy Assistant",
"224ZE0001X": "Environmental Modification Occupational Therapy Assistant",
"224ZF0002X": "Feeding, Eating & Swallowing Occupational Therapy Assistant",
"224ZL0004X": "Low Vision Occupational Therapy Assistant",
"224ZR0403X": "Driving and Community Mobility Occupational Therapy Assistant",
"225000000X": "Orthotic Fitter",
"225100000X": "Physical Therapist",
"2251C2600X": "Cardiopulmonary Physical Therapist",
"2251E1200X": "Ergonomics Physical Therapist",
"2251E1300X": "Clinical Electrophysiology Physical Therapist",
"2251G0304X": "Geriatric Physical Therapist",
"2251H1200X": "Hand Physical Therapist",
"2251H1300X": "Human Factors Physical Therapist",
"2251N0400X": "Neurology Physical Therapist",
"2251P0200X": "Pediatric Physical Therapist",
"2251S0007X": "Sports Physical Therapist",
"2251X0800X": "Orthopedic Physical Therapist",
"225200000X": "Physical Therapy Assistant",
"225400000X": "Rehabilitation Practitioner",
"225500000X": "Respiratory/Developmental/Rehabilitative Specialist/Technologist",
"2255A2300X": "Athletic Trainer",
"2255R0406X": "Blind Rehabilitation Specialist/Technologist",
"225600000X": "Dance Therapist",
"225700000X": "Massage Therapist",
"225800000X": "Recreation Therapist",
"225A00000X": "Music Therapist",
"225B00000X": "Pulmonary Function Technologist",
"225C00000X": "Rehabilitation Counselor",
"225CA2400X": "Assistive Technology Practitioner Rehabilitation Counselor",
"225CA2500X": "Assistive Technology Supplier Rehabilitation Counselor",
"225CX0006X": "Orientation and Mobility Training Rehabilitation Counselor",
"225X00000X": "Occupational Therapist",
"225XE0001X": "Environmental Modification Occupational Therapist",
"225XE1200X": "Ergonomics Occupational Therapist",
"225XF0002X": "Feeding, Eating & Swallowing Occupational Therapist",
"225XG0600X": "Gerontology Occupational Therapist",
"225XH1200X": "Hand Occupational Therapist",
"225XH1300X": "Human Factors Occupational Therapist",
"225XL0004X": "Low Vision Occupational Therapist",
"225XM0800X": "Mental Health Occupational Therapist",
"225XN1300X": "Neurorehabilitation Occupational Therapist",
"225XP0019X": "Physical Rehabilitation Occupational Therapist",
"225XP0200X": "Pediatric Occupational Therapist",
"225XR0403X": "Driving and Community Mobility Occupational Therapist",
"226000000X": "Recreational Therapist Assistant",
"226300000X": "Kinesiotherapist",
"227800000X": "Certified Respiratory Therapist",
"2278C0205X": "Critical Care Certified Respiratory Therapist",
"2278E0002X": "Emergency Care Certified Respiratory Therapist",
"2278E1000X": "Educational Certified Respiratory Therapist",
"2278G0305X": "Geriatric Care Certified Respiratory Therapist",
"2278G1100X": "General Care Certified Respiratory Therapist",
"2278H0200X": "Home Health Certified Respiratory Therapist",
"2278P1004X": "Pulmonary Diagnostics Certified Respiratory Therapist",
"2278P1005X": "Pulmonary Rehabilitation Certified Respiratory Therapist",
"2278P1006X": "Pulmonary Function Technologist Certified Respiratory Therapist",
"2278P3800X": "Palliative/Hospice Certified Respiratory Therapist",
"2278P3900X": "Neonatal/Pediatric Certified Respiratory Therapist",
"2278P4000X": "Patient Transport Certified Respiratory Therapist",
"2278S1500X": "SNF/Subacute Care Certified Respiratory Therapist",
"227900000X": "Registered Respiratory Therapist",
"2279C0205X": "Critical Care Registered Respiratory Therapist",
"2279E0002X": "Emergency Care Registered Respiratory Therapist",
"2279E1000X": "Educational Registered Respiratory Therapist",
"2279G0305X": "Geriatric Care Registered Respiratory Therapist",
"2279G1100X": "General Care Registered Respiratory Therapist",
"2279H0200X": "Home Health Registered Respiratory Therapist",
"2279P1004X": "Pulmonary Diagnostics Registered Respiratory Therapist",
"2279P1005X": "Pulmonary Rehabilitation Registered Respiratory Therapist",
"2279P1006X": "Pulmonary Function Technologist Registered Respiratory Therapist",
"2279P3800X": "Palliative/Hospice Registered Respiratory Therapist",
"2279P3900X": "Neonatal/Pediatric Registered Respiratory Therapist",
"2279P4000X": "Patient Transport Registered Respiratory Therapist",
"2279S1500X": "SNF/Subacute Care Registered Respiratory Therapist",
"229N00000X": "Anaplastologist",
"231H00000X": "Audiologist",
"231HA2400X": "Assistive Technology Practitioner Audiologist",
"231HA2500X": "Assistive Technology Supplier Audiologist",
"235500000X": "Speech/Language/Hearing Specialist/Technologist",
"2355A2700X": "Audiology Assistant",
"2355S0801X": "Speech-Language Assistant",
"235Z00000X": "Speech-Language Pathologist",
"237600000X": "Audiologist-Hearing Aid Fitter",
"237700000X": "Hearing Instrument Specialist",
"242T00000X": "Perfusionist",
"243U00000X": "Radiology Practitioner Assistant",
"246Q00000X": "Pathology Specialist/Technologist",
"246QB0000X": "Blood Banking Specialist/Technologist",
"246QC1000X": "Chemistry Pathology Specialist/Technologist",
"246QC2700X": "Cytotechnology Specialist/Technologist",
"246QH0000X": "Hematology Specialist/Technologist",
"246QH0401X": "Hemapheresis Practitioner",
"246QH0600X": "Histology Specialist/Technologist",
"246QI0000X": "Immunology Pathology Specialist/Technologist",
"246QL0900X": "Laboratory Management Specialist/Technologist",
"246QL0901X": "Diplomate Laboratory Management Specialist/Technologist",
"246QM0706X": "Medical Technologist",
"246QM0900X": "Microbiology Specialist/Technologist",
"246R00000X": "Pathology Technician",
"246RH0600X": "Histology Technician",
"246RM2200X": "Medical Laboratory Technician",
"246RP1900X": "Phlebotomy Technician",
"246W00000X": "Cardiology Technician",
"246X00000X": "Cardiovascular Specialist/Technologist",
"246XC2901X": "Cardiovascular Invasive Specialist/Technologist",
"246XC2903X": "Vascular Specialist/Technologist",
"246XS1301X": "Sonography Specialist/Technologist",
"246Y00000X": "Health Information Specialist/Technologist",
"246YC3301X": "Hospital Based Coding Specialist",
"246YC3302X": "Physician Office Based Coding Specialist",
"246YR1600X": "Registered Record Administrator",
"246Z00000X": "Other Specialist/Technologist",
"246ZA2600X": "Medical Art Specialist/Technologist",
"246ZB0301X": "Biomedical Engineer",
"246ZB0302X": "Biomedical Photographer",
"246ZB0500X": "Biochemist",
"246ZB0600X": "Biostatiscian",
"246ZC0007X": "Surgical Assistant",
"246ZE0500X": "EEG Specialist/Technologist",
"246ZE0600X": "Electroneurodiagnostic Specialist/Technologist",
"246ZG0701X": "Graphics Methods Specialist/Technologist",
"246ZG1000X": "Medical Geneticist (PhD) Specialist/Technologist",
"246ZI1000X": "Medical Illustrator",
"246ZN0300X": "Nephrology Specialist/Technologist",
"246ZS0410X": "Surgical Technologist",
"246ZX2200X": "Orthopedic Assistant",
"247000000X": "Health Information Technician",
"2470A2800X": "Assistant Health Information Record Technician",
"247100000X": "Radiologic Technologist",
"2471B0102X": "Bone Densitometry Radiologic Technologist",
"2471C1101X": "Cardiovascular-Interventional Technology Radiologic Technologist",
"2471C1106X": "Cardiac-Interventional Technology Radiologic Technologist",
"2471C3401X": "Computed Tomography Radiologic Technologist",
"2471C3402X": "Radiography Radiologic Technologist",
"2471M1202X": "Magnetic Resonance Imaging Radiologic Technologist",
"2471M2300X": "Mammography Radiologic Technologist",
"2471N0900X": "Nuclear Medicine Technology Radiologic Technologist",
"2471Q0001X": "Quality Management Radiologic Technologist",
"2471R0002X": "Radiation Therapy Radiologic Technologist",
"2471S1302X": "Sonography Radiologic Technologist",
"2471V0105X": "Vascular Sonography Radiologic Technologist",
"2471V0106X": "Vascular-Interventional Technology Radiologic Technologist",
"247200000X": "Other Technician",
"2472B0301X": "Biomedical Engineering Technician",
"2472D0500X": "Darkroom Technician",
"2472E0500X": "EEG Technician",
"2472R0900X": "Renal Dialysis Technician",
"2472V0600X": "Veterinary Technician",
"247ZC0005X": "Clinical Laboratory Director (Non-physician)",
"251300000X": "Local Education Agency (LEA)",
"251B00000X": "Case Management Agency",
"251C00000X": "Developmentally Disabled Services Day Training Agency",
"251E00000X": "Home Health Agency",
"251F00000X": "Home Infusion Agency",
"251G00000X": "Community Based Hospice Care Agency",
"251J00000X": "Nursing Care Agency",
"251K00000X": "Public Health or Welfare Agency",
"251S00000X": "Community/Behavioral Health Agency",
"251T00000X": "PACE Provider Organization",
"251V00000X": "Voluntary or Charitable Agency",
"251X00000X": "Supports Brokerage Agency",
"252Y00000X": "Early Intervention Provider Agency",
"253J00000X": "Foster Care Agency",
"253Z00000X": "In Home Supportive Care Agency",
"261Q00000X": "Clinic/Center",
"261QA0005X": "Ambulatory Family Planning Facility",
"261QA0006X": "Ambulatory Fertility Facility",
"261QA0600X": "Adult Day Care Clinic/Center",
"261QA0900X": "Amputee Clinic/Center",
"261QA1903X": "Ambulatory Surgical Clinic/Center",
"261QA3000X": "Augmentative Communication Clinic/Center",
"261QB0400X": "Birthing Clinic/Center",
"261QC0050X": "Critical Access Hospital Clinic/Center",
"261QC1500X": "Community Health Clinic/Center",
"261QC1800X": "Corporate Health Clinic/Center",
"261QD0000X": "Dental Clinic/Center",
"261QD1600X": "Developmental Disabilities Clinic/Center",
"261QE0002X": "Emergency Care Clinic/Center",
"261QE0700X": "End-Stage Renal Disease (ESRD) Treatment Clinic/Center",
"261QE0800X": "Endoscopy Clinic/Center",
"261QF0050X": "Non-Surgical Family Planning Clinic/Center",
"261QF0400X": "Federally Qualified Health Center (FQHC)",
"261QG0250X": "Genetics Clinic/Center",
"261QH0100X": "Health Service Clinic/Center",
"261QH0700X": "Hearing and Speech Clinic/Center",
"261QI0500X": "Infusion Therapy Clinic/Center",
"261QL0400X": "Lithotripsy Clinic/Center",
"261QM0801X": "Mental Health Clinic/Center (Including Community Mental Health Center)",
"261QM0850X": "Adult Mental Health Clinic/Center",
"261QM0855X": "Adolescent and Children Mental Health Clinic/Center",
"261QM1000X": "Migrant Health Clinic/Center",
"261QM1100X": "Military/U.S. Coast Guard Outpatient Clinic/Center",
"261QM1101X": "Military and U.S. Coast Guard Ambulatory Procedure Clinic/Center",
"261QM1102X": "Military Outpatient Operational (Transportable) Component Clinic/Center",
"261QM1103X": "Military Ambulatory Procedure Visits Operational (Transportable) Clinic/Center",
"261QM1200X": "Magnetic Resonance Imaging (MRI) Clinic/Center",
"261QM1300X": "Multi-Specialty Clinic/Center",
"261QM2500X": "Medical Specialty Clinic/Center",
"261QM2800X": "Methadone Clinic",
"261QM3000X": "Medically Fragile Infants and Children Day Care",
"261QP0904X": "Federal Public Health Clinic/Center",
"261QP0905X": "State or Local Public Health Clinic/Center",
"261QP1100X": "Podiatric Clinic/Center",
"261QP2000X": "Physical Therapy Clinic/Center",
"261QP2300X": "Primary Care Clinic/Center",
"261QP2400X": "Prison Health Clinic/Center",
"261QP3300X": "Pain Clinic/Center",
"261QR0200X": "Radiology Clinic/Center",
"261QR0206X": "Mammography Clinic/Center",
"261QR0207X": "Mobile Mammography Clinic/Center",
"261QR0208X": "Mobile Radiology Clinic/Center",
"261QR0400X": "Rehabilitation Clinic/Center",
"261QR0401X": "Comprehensive Outpatient Rehabilitation Facility (CORF)",
"261QR0404X": "Cardiac Rehabilitation Clinic/Center",
"261QR0405X": "Substance Use Disorder Rehabilitation Clinic/Center",
"261QR0800X": "Recovery Care Clinic/Center",
"261QR1100X": "Research Clinic/Center",
"261QR1300X": "Rural Health Clinic/Center",
"261QS0112X": "Oral and Maxillofacial Surgery Clinic/Center",
"261QS0132X": "Ophthalmologic Surgery Clinic/Center",
"261QS1000X": "Student Health Clinic/Center",
"261QS1200X": "Sleep Disorder Diagnostic Clinic/Center",
"261QU0200X": "Urgent Care Clinic/Center",
"261QV0200X": "VA Clinic/Center",
"261QX0100X": "Occupational Medicine Clinic/Center",
"261QX0200X": "Oncology Clinic/Center",
"261QX0203X": "Radiation Oncology Clinic/Center",
"273100000X": "Epilepsy Hospital Unit",
"273R00000X": "Psychiatric Hospital Unit",
"273Y00000X": "Rehabilitation Hospital Unit",
"275N00000X": "Medicare Defined Swing Bed Hospital Unit",
"276400000X": "Substance Use Disorder Rehabilitation Hospital Unit",
"281P00000X": "Chronic Disease Hospital",
"281PC2000X": "Children' s Chronic Disease Hospital",
"282E00000X": "Long Term Care Hospital",
"282J00000X": "Religious Nonmedical Health Care Institution",
"282N00000X": "General Acute Care Hospital",
"282NC0060X": "Critical Access Hospital",
"282NC2000X": "Children's Hospital",
"282NR1301X": "Rural Acute Care Hospital",
"282NW0100X": "Women's Hospital",
"283Q00000X": "Psychiatric Hospital",
"283X00000X": "Rehabilitation Hospital",
"283XC2000X": "Children's Rehabilitation Hospital",
"284300000X": "Special Hospital",
"286500000X": "Military Hospital",
"2865C1500X": "Deactivated - Military Hospital",
"2865M2000X": "Military General Acute Care Hospital",
"2865X1600X": "Operational (Transportable) Military General Acute Care Hospital",
"287300000X": "Deactivated - Christian Science Sanitorium",
"291900000X": "Military Clinical Medical Laboratory",
"291U00000X": "Clinical Medical Laboratory",
"292200000X": "Dental Laboratory",
"293D00000X": "Physiological Laboratory",
"302F00000X": "Exclusive Provider Organization",
"302R00000X": "Health Maintenance Organization",
"305R00000X": "Preferred Provider Organization",
"305S00000X": "Point of Service",
"310400000X": "Assisted Living Facility",
"3104A0625X": "Assisted Living Facility (Mental Illness)",
"3104A0630X": "Assisted Living Facility (Behavioral Disturbances)",
"310500000X": "Mental Illness Intermediate Care Facility",
"311500000X": "Alzheimer Center (Dementia Center)",
"311Z00000X": "Custodial Care Facility",
"311ZA0620X": "Adult Care Home Facility",
"313M00000X": "Nursing Facility/Intermediate Care Facility",
"314000000X": "Skilled Nursing Facility",
"3140N1450X": "Pediatric Skilled Nursing Facility",
"315D00000X": "Inpatient Hospice",
"315P00000X": "Intellectual Disabilities Intermediate Care Facility",
"317400000X": "Deactivated - Christian Science Facility",
"320600000X": "Intellectual and/or Developmental Disabilities Residential Treatment Facility",
"320700000X": "Physical Disabilities Residential Treatment Facility",
"320800000X": "Mental Illness Community Based Residential Treatment Facility",
"320900000X": "Intellectual and/or Developmental Disabilities Community Based Residential Treatment Facility",
"322D00000X": "Emotionally Disturbed Childrens' Residential Treatment Facility",
"323P00000X": "Psychiatric Residential Treatment Facility",
"324500000X": "Substance Abuse Rehabilitation Facility",
"3245S0500X": "Children's Substance Abuse Rehabilitation Facility",
"331L00000X": "Blood Bank",
"332000000X": "Military/U.S. Coast Guard Pharmacy",
"332100000X": "Department of Veterans Affairs (VA) Pharmacy",
"332800000X": "Indian Health Service/Tribal/Urban Indian Health (I/T/U) Pharmacy",
"332900000X": "Non-Pharmacy Dispensing Site",
"332B00000X": "Durable Medical Equipment & Medical Supplies",
"332BC3200X": "Customized Equipment (DME)",
"332BD1200X": "Dialysis Equipment & Supplies (DME)",
"332BN1400X": "Nursing Facility Supplies (DME)",
"332BP3500X": "Parenteral & Enteral Nutrition Supplies (DME)",
"332BX2000X": "Oxygen Equipment & Supplies (DME)",
"332G00000X": "Eye Bank",
"332H00000X": "Eyewear Supplier",
"332S00000X": "Hearing Aid Equipment",
"332U00000X": "Home Delivered Meals",
"333300000X": "Emergency Response System Companies",
"333600000X": "Pharmacy",
"3336C0002X": "Clinic Pharmacy",
"3336C0003X": "Community/Retail Pharmacy",
"3336C0004X": "Compounding Pharmacy",
"3336H0001X": "Home Infusion Therapy Pharmacy",
"3336I0012X": "Institutional Pharmacy",
"3336L0003X": "Long Term Care Pharmacy",
"3336M0002X": "Mail Order Pharmacy",
"3336M0003X": "Managed Care Organization Pharmacy",
"3336N0007X": "Nuclear Pharmacy",
"3336S0011X": "Specialty Pharmacy",
"335E00000X": "Prosthetic/Orthotic Supplier",
"335G00000X": "Medical Foods Supplier",
"335U00000X": "Organ Procurement Organization",
"335V00000X": "Portable X-ray and/or Other Portable Diagnostic Imaging Supplier",
"341600000X": "Ambulance",
"3416A0800X": "Air Ambulance",
"3416L0300X": "Land Ambulance",
"3416S0300X": "Water Ambulance",
"341800000X": "Military/U.S. Coast Guard Transport,",
"3418M1110X": "Military or U.S. Coast Guard Ground Transport Ambulance",
"3418M1120X": "Military or U.S. Coast Guard Air Transport Ambulance",
"3418M1130X": "Military or U.S. Coast Guard Water Transport Ambulance",
"342000000X": "Transportation Network Company",
"343800000X": "Secured Medical Transport (VAN)",
"343900000X": "Non-emergency Medical Transport (VAN)",
"344600000X": "Taxi",
"344800000X": "Air Carrier",
"347B00000X": "Bus",
"347C00000X": "Private Vehicle",
"347D00000X": "Train",
"347E00000X": "Transportation Broker",
"363A00000X": "Physician Assistant",
"363AM0700X": "Medical Physician Assistant",
"363AS0400X": "Surgical Physician Assistant",
"363L00000X": "Nurse Practitioner",
"363LA2100X": "Acute Care Nurse Practitioner",
"363LA2200X": "Adult Health Nurse Practitioner",
"363LC0200X": "Critical Care Medicine Nurse Practitioner",
"363LC1500X": "Community Health Nurse Practitioner",
"363LF0000X": "Family Nurse Practitioner",
"363LG0600X": "Gerontology Nurse Practitioner",
"363LN0000X": "Neonatal Nurse Practitioner",
"363LN0005X": "Critical Care Neonatal Nurse Practitioner",
"363LP0200X": "Pediatric Nurse Practitioner",
"363LP0222X": "Critical Care Pediatric Nurse Practitioner",
"363LP0808X": "Psychiatric/Mental Health Nurse Practitioner",
"363LP1700X": "Perinatal Nurse Practitioner",
"363LP2300X": "Primary Care Nurse Practitioner",
"363LS0200X": "School Nurse Practitioner",
"363LW0102X": "Women's Health Nurse Practitioner",
"363LX0001X": "Obstetrics & Gynecology Nurse Practitioner",
"363LX0106X": "Occupational Health Nurse Practitioner",
"364S00000X": "Clinical Nurse Specialist",
"364SA2100X": "Acute Care Clinical Nurse Specialist",
"364SA2200X": "Adult Health Clinical Nurse Specialist",
"364SC0200X": "Critical Care Medicine Clinical Nurse Specialist",
"364SC1501X": "Community Health/Public Health Clinical Nurse Specialist",
"364SC2300X": "Chronic Care Clinical Nurse Specialist",
"364SE0003X": "Emergency Clinical Nurse Specialist",
"364SE1400X": "Ethics Clinical Nurse Specialist",
"364SF0001X": "Family Health Clinical Nurse Specialist",
"364SG0600X": "Gerontology Clinical Nurse Specialist",
"364SH0200X": "Home Health Clinical Nurse Specialist",
"364SH1100X": "Holistic Clinical Nurse Specialist",
"364SI0800X": "Informatics Clinical Nurse Specialist",
"364SL0600X": "Long-Term Care Clinical Nurse Specialist",
"364SM0705X": "Medical-Surgical Clinical Nurse Specialist",
"364SN0000X": "Neonatal Clinical Nurse Specialist",
"364SN0800X": "Neuroscience Clinical Nurse Specialist",
"364SP0200X": "Pediatric Clinical Nurse Specialist",
"364SP0807X": "Child & Adolescent Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0808X": "Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0809X": "Adult Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0810X": "Child & Family Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0811X": "Chronically Ill Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0812X": "Community Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP0813X": "Geropsychiatric Psychiatric/Mental Health Clinical Nurse Specialist",
"364SP1700X": "Perinatal Clinical Nurse Specialist",
"364SP2800X": "Perioperative Clinical Nurse Specialist",
"364SR0400X": "Rehabilitation Clinical Nurse Specialist",
"364SS0200X": "School Clinical Nurse Specialist",
"364ST0500X": "Transplantation Clinical Nurse Specialist",
"364SW0102X": "Women's Health Clinical Nurse Specialist",
"364SX0106X": "Occupational Health Clinical Nurse Specialist",
"364SX0200X": "Oncology Clinical Nurse Specialist",
"364SX0204X": "Pediatric Oncology Clinical Nurse Specialist",
"367500000X": "Certified Registered Nurse Anesthetist",
"367A00000X": "Advanced Practice Midwife",
"367H00000X": "Anesthesiologist Assistant",
"372500000X": "Chore Provider",
"372600000X": "Adult Companion",
"373H00000X": "Day Training/Habilitation Specialist",
"374700000X": "Technician",
"3747A0650X": "Attendant Care Provider",
"3747P1801X": "Personal Care Attendant",
"374J00000X": "Doula",
"374K00000X": "Religious Nonmedical Practitioner",
"374T00000X": "Religious Nonmedical Nursing Personnel",
"374U00000X": "Home Health Aide",
"376G00000X": "Nursing Home Administrator",
"376J00000X": "Homemaker",
"376K00000X": "Nurse's Aide",
"385H00000X": "Respite Care",
"385HR2050X": "Respite Care Camp",
"385HR2055X": "Child Mental Illness Respite Care",
"385HR2060X": "Child Intellectual and/or Developmental Disabilities Respite Care",
"385HR2065X": "Child Physical Disabilities Respite Care",
"390200000X": "Student in an Organized Health Care Education/Training Program",
"405300000X": "Prevention Professional"
}

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { MedicalSourcesFilterService } from './medical-sources-filter.service';
describe('MedicalSourcesFilterService', () => {
let service: MedicalSourcesFilterService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MedicalSourcesFilterService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,168 @@
import { Injectable } from '@angular/core';
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
export class MedicalSourcesFilter {
searchAfter: string | string[] = '';
query: string;
platformTypes: string[] = [];
categories: string[] = [];
showHidden: boolean = false;
fields: string[] = []; //specify the fields to return. if null or empty list, return all.
}
@Injectable({
providedIn: 'root'
})
export class MedicalSourcesFilterService {
filterForm = this.formBuilder.group({
searchAfter: [''],
query: [''],
platformTypes: this.formBuilder.group({}),
categories: this.formBuilder.group({}),
showHidden: [false],
})
constructor(private formBuilder: FormBuilder) { }
//parse angular query string parameters
parseQueryParams(queryParams: {[name:string]:string}){
var updateData: {
searchAfter?: string,
query?: string,
platformTypes?: {},
categories?: {},
showHidden?: boolean,
} = {};
if(queryParams['searchAfter']){
updateData.searchAfter = queryParams['searchAfter']
}
if(queryParams['query']){
updateData.query = queryParams['query']
}
if(queryParams['platformTypes']){
updateData.platformTypes = updateData.platformTypes ? updateData.platformTypes : {};
for(let platformType of queryParams['platformTypes']?.split(',')){
updateData.platformTypes[platformType] = true;
}
}
if(queryParams['categories']){
updateData.categories = updateData.categories ? updateData.categories : {};
for(let category of queryParams['categories']?.split(',')){
updateData.categories[category] = true;
}
}
if(queryParams['showHidden']){
updateData.showHidden = queryParams['showHidden'] == 'true';
}
//ensure that checkbox list values exist before trying to "patch" them in.
if(updateData.platformTypes){
var currentFileTypes = this.filterForm.get('platformTypes').value;
Object.keys(updateData.platformTypes).forEach((bucketKey) => {
if(!currentFileTypes.hasOwnProperty(bucketKey)){
(this.filterForm.get('platformTypes') as FormGroup).addControl(bucketKey, new FormControl(false))
}
})
}
if(updateData.categories){
Object.keys(updateData.categories).forEach((bucketKey) => {
if(!this.filterForm.get('categories').get(bucketKey)){
(this.filterForm.get('categories') as FormGroup).addControl(bucketKey, new FormControl(false))
}
})
}
return updateData;
}
toQueryParams() : {[name:string]:string} {
var form = this.filterForm.value;
var queryParams = {};
// if(form.searchAfter){
// var searchAfter = [];
// Object.keys(form.searchAfter).forEach((key) => {
// if (form.searchAfter[key]) {
// searchAfter.push(key);
// }
// })
//
// queryParams['searchAfter'] = searchAfter.join(',');
// }
if(form.query){
queryParams['query'] = form.query
}
if(form.platformTypes && Object.keys(form.platformTypes).length){
var platformTypes = [];
Object.keys(form.platformTypes).forEach((key) => {
if (form.platformTypes[key]) {
platformTypes.push(key);
}
})
queryParams['platformTypes'] = platformTypes.join(',');
}
if(form.categories && Object.keys(form.categories).length){
var categories = [];
Object.keys(form.categories).forEach((key) => {
if (form.categories[key]) {
categories.push(key);
}
})
queryParams['categories'] = categories.join(',');
}
if(form.showHidden){
queryParams['showHidden'] = form.showHidden.toString();
}
return queryParams;
}
toMedicalSourcesFilter(form): MedicalSourcesFilter {
var medicalSourcesFilter = new MedicalSourcesFilter();
if(form.searchAfter){
medicalSourcesFilter.searchAfter = form.searchAfter
}
if(form.query){
medicalSourcesFilter.query = form.query;
}
if(form.platformTypes){
medicalSourcesFilter.platformTypes = [];
Object.keys(form.platformTypes).forEach((key) => {
if (form.platformTypes[key]) {
medicalSourcesFilter.platformTypes.push(key);
}
})
}
if(form.categories){
medicalSourcesFilter.categories = [];
Object.keys(form.categories).forEach((key) => {
if (form.categories[key]) {
medicalSourcesFilter.categories.push(key);
}
})
}
if (form.showHidden) {
medicalSourcesFilter.showHidden = form.showHidden;
}
return medicalSourcesFilter
}
}

View File

@ -214,3 +214,23 @@ app-nlm-typeahead {
border-radius: 10px;
}
}
//Medical Source Filter
.category-label {
font-weight: 400
}
app-medical-sources-filter > .az-content-left-components {
overflow: hidden;
-webkit-transition: width 0.2s ease-in-out;
-moz-transition: width 0.2s ease-in-out;
-o-transition: width 0.2s ease-in-out;
transition: width 0.2s ease-in-out;
}
app-medical-sources-filter > .az-content-left-components:hover{
width: 100%;
-webkit-transition: width 0.2s ease-in-out;
-moz-transition: width 0.2s ease-in-out;
-o-transition: width 0.2s ease-in-out;
transition: width 0.2s ease-in-out;
}