import autobind from "autobind-decorator" ; import { action , computed , makeObservable , observable } from "mobx" ; import { observer } from "mobx-react" ; import React from "react" ; import { Button , Checkbox , FormControl , ListGroup , ListGroupItem , Modal , } from "react-bootstrap" ; import { EModalType , IDataTypeMetaData } from "../ui/react-pathway-mapper" ; import CBioPortalAccessor from "../utils/CBioPortalAccessor" ; interface IStudyModalProps { show : boolean ; loadFromCBio : Function ; handleClose : Function ; } @ observer export default class StudyModal extends React . Component < IStudyModalProps , { } > { @ observable dataTypes : { [ dataType ] : IDataTypeMetaData ; } = { } ; @ observable dataTypeFetchResultsReady : boolean = false ; currentlySelectedItemIndex = - 1 ; @ observable selectedStudies : { data : any [ ] ; dataTypes : { [ dataType ] : IDataTypeMetaData ; } ; } [ ] = [ ] ; checkboxModalPosition : { bottom : number ; } = { bottom : 0 , } ; @ observable selectedDataTypesPerStudy : string [ ] = [ ] ; @ observable itemArray : any [ ] = [ ] ; @ observable searchQuery : string = "" ; @ observable showDataTypeSelectionModal = false ; @ observable studyListItemCheckboxChecked : boolean [ ] = [ ] ; @ observable selectedStudyData : any [ ] ; @ observable portalAccessor : CBioPortalAccessor ; constructor ( props ) { super ( props ) ; makeObservable ( this ) ; this . selectedStudyData = [ ] ; this . portalAccessor = new CBioPortalAccessor ( ) ; this . fetchStudy ( ) ; } @ action . bound setDataTypeFetchResultsReady ( ready ) { this . dataTypeFetchResultsReady = ready ; } @ action . bound setItemArray ( itemArray ) { this . itemArray = itemArray ; } @ action . bound setSearchQuery ( query ) { this . searchQuery = query ; } @ action . bound setSelectedStudyData ( data ) { this . selectedStudyData = data ; } @ action . bound setDataTypeProperties ( dataType , properties ) { this . dataTypes [ dataType ] = properties ; } @ action . bound initStudyListItemCheckboxChecked ( studyCount ) { this . studyListItemCheckboxChecked = Array ( studyCount ) . fill ( false ) ; } @ action . bound initSelectedDataTypesPerStudy ( studyCount ) { this . selectedDataTypesPerStudy = Array ( studyCount ) . fill ( "" ) ; } @ action . bound toggleStudyListItemCheckboxChecked ( studyIndex ) { this . studyListItemCheckboxChecked [ studyIndex ] = ! this . studyListItemCheckboxChecked [ studyIndex ] ; } @ action . bound addSelectedStudy ( selectedStudy ) { this . selectedStudies . push ( selectedStudy ) ; } @ action . bound removeSelectedStudy ( selectedStudyData ) { this . selectedStudies = this . selectedStudies . filter ( ( study ) => study . data [ 0 ] != selectedStudyData [ 0 ] ) ; } @ action . bound clearSelectedStudies ( ) { this . selectedStudies = [ ] ; } @ action . bound setShowDataTypeSelectionModal ( show ) { this . showDataTypeSelectionModal = show ; } @ action . bound clearStudyCheckboxesChecked ( ) { const length = this . studyListItemCheckboxChecked . length ; this . studyListItemCheckboxChecked = Array ( length ) . fill ( false ) ; } @ action . bound clearSelectedDataTypesPerStudy ( ) { const length = this . studyListItemCheckboxChecked . length ; this . selectedDataTypesPerStudy = Array ( length ) . fill ( "" ) ; } @ action . bound unselectDataTypesForStudy ( index ) { this . selectedDataTypesPerStudy [ index ] = "" ; } preparePortalAccess ( studyId ) { this . setDataTypeFetchResultsReady ( false ) ; this . portalAccessor . getSupportedGeneticProfiles ( studyId , ( data ) => { this . disableAllDataTypes ( ) ; for ( const profile of Object . keys ( data ) ) { const type = CBioPortalAccessor . getDataType ( profile ) ; if ( type !== "" ) { this . setDataTypeProperties ( type , { ... this . dataTypes [ type ] , enabled : true , profile : profile , } ) ; setTimeout ( ( ) => this . setDataTypeFetchResultsReady ( true ) , 500 ) ; } } } ) ; } disableAllDataTypes ( ) { for ( const dataType of Object . keys ( this . dataTypes ) ) { this . setDataTypeProperties ( dataType , { enabled : false , checked : false , profile : undefined , } ) ; } } fetchStudy ( ) { this . portalAccessor . getDataTypes ( ) . forEach ( ( dataType ) => { this . setDataTypeProperties ( dataType , { enabled : false , checked : false , profile : undefined , } ) ; } ) ; this . portalAccessor . fetchCancerStudies ( ( cancerStudies ) => { let temp = [ ] ; for ( const studyTitle in cancerStudies ) { if ( ! cancerStudies . hasOwnProperty ( studyTitle ) ) { continue ; } const studyData = cancerStudies [ studyTitle ] ; temp . push ( studyData ) ; } const numOfStudies = temp . length ; this . initStudyListItemCheckboxChecked ( numOfStudies ) ; this . initSelectedDataTypesPerStudy ( numOfStudies ) ; this . setItemArray ( temp ) ; } ) ; } @ autobind resetModal ( ) { this . disableAllDataTypes ( ) ; this . setSelectedStudyData ( [ ] ) ; this . clearSelectedStudies ( ) ; this . clearStudyCheckboxesChecked ( ) ; this . clearSelectedDataTypesPerStudy ( ) ; this . currentlySelectedItemIndex = - 1 ; this . searchQuery = "" ; } @ autobind handleCheckboxClick ( dataType ) { this . setDataTypeProperties ( dataType , { ... this . dataTypes [ dataType ] , checked : ! this . dataTypes [ dataType ] . checked , } ) ; } @ computed get selectedStudyDataTitle ( ) { if ( this . selectedStudyData . length > 1 ) { return this . selectedStudyData [ 1 ] || "Choose study" ; } else { return "Choose study" ; } } render ( ) { return ( < Modal id = "cbioPortalModal" show = { this . props . show } onHide = { ( ) => { this . props . handleClose ( EModalType . STUDY ) ; this . resetModal ( ) ; } } > < Modal . Header closeButton > < Modal . Title > Profile Data from cBioPortal < /Modal.Title> < /Modal.Header> < Modal . Body > < div id = "cancerDropDown" style = { { textAlign : "left" , } } > < h4 > Select Cancer Study < /h4> < form > < FormControl type = "text" placeholder = "Search studies" onChange = { ( event ) => this . setSearchQuery ( event . target . value ) } /> < /form> < ListGroup style = { { maxHeight : "200px" , overflow : "auto" , marginTop : "10px" , border : "1px solid #ccc" , borderRadius : "4px" , } } > { this . itemArray . length < 1 ? ( < span > Fetching studies from cBioPortal ... < /span>) : (this.itemArray . map ( ( item , index ) => { return { item : item , index : index } ; } ) . filter ( ( obj ) => obj . item [ 1 ] . toLowerCase ( ) . includes ( this . searchQuery . toLowerCase ( ) ) ) . map ( ( obj ) => { const item = obj . item ; const index = obj . index ; const studyTitle = item [ 1 ] ; const studyId = item [ 0 ] ; return ( < ListGroupItem id = { "listgroupitem" + index } key = { studyId } style = { { padding : "5px 5px" , } } > < Checkbox checked = { this . studyListItemCheckboxChecked [ index ] } style = { { marginTop : "0px" , marginBottom : "0px" , } } onClick = { ( ) => { const boundingRect = document . getElementById ( "listgroupitem" + index ) . getBoundingClientRect ( ) ; const modalMargin = 30 ; this . checkboxModalPosition = { bottom : boundingRect . bottom - modalMargin , } ; this . setSelectedStudyData ( item ) ; this . preparePortalAccess ( studyId ) ; this . toggleStudyListItemCheckboxChecked ( index ) ; this . currentlySelectedItemIndex = index ; if ( this . studyListItemCheckboxChecked [ index ] ) { this . setShowDataTypeSelectionModal ( true ) ; } else { this . removeSelectedStudy ( item ) ; this . unselectDataTypesForStudy ( index ) ; } } } > { studyTitle } < /Checkbox> { this . selectedDataTypesPerStudy [ index ] != "" && ( < span style = { { fontSize : "12px" , marginLeft : "25px" , } } > { this . selectedDataTypesPerStudy [ index ] } < /span>)} < /ListGroupItem>); } ) ) } < /ListGroup> < /div> < div style = { { marginTop : "10px" } } > < p style = { { textAlign : "left" } } > < b > Warning : < /b> At most six different data sets will be overlayed on the genes. You can toggle which ones are to be displayed via "Alteration %" {">"} "View Settings" menu. < /p> < /div> < Modal style = { { position : "absolute" , top : this . checkboxModalPosition . bottom + "px" , } } dialogClassName = "fitContent" show = { this . showDataTypeSelectionModal } onHide = { ( ) => { this . setShowDataTypeSelectionModal ( false ) ; } } > < Modal . Body > { this . dataTypeFetchResultsReady === false ? ( < span > Fetching data types from cBioPortal ... < /span>) : (Object.keys(this.dataTypes).map((dataType) => { return ( < Checkbox inline key = { dataType } disabled = { ! this . dataTypes [ dataType ] . enabled } onClick = { ( ) => { this . handleCheckboxClick ( dataType ) ; } } checked = { this . dataTypes [ dataType ] . checked } > { dataType } < /Checkbox>); } ) ) } < /Modal.Body> < Modal . Footer > < Button onClick = { ( ) => { const currentDataTypes = { ... this . dataTypes } ; const selectedCount = Object . keys ( currentDataTypes ) . filter ( ( dataType ) => { return currentDataTypes [ dataType ] . checked ; } ) . length ; if ( selectedCount == 0 ) { this . studyListItemCheckboxChecked [ this . currentlySelectedItemIndex ] = false ; } this . setShowDataTypeSelectionModal ( false ) ; } } > Cancel < /Button> < Button onClick = { ( ) => { const currentDataTypes = { ... this . dataTypes } ; this . addSelectedStudy ( { data : this . selectedStudyData , dataTypes : currentDataTypes , } ) ; this . selectedDataTypesPerStudy [ this . currentlySelectedItemIndex ] = Object . keys ( currentDataTypes ) . filter ( ( dataType ) => { return currentDataTypes [ dataType ] . checked ; } ) . join ( ", " ) ; this . setShowDataTypeSelectionModal ( false ) ; } } > Add < /Button> < /Modal.Footer> < /Modal> < /Modal.Body> < Modal . Footer > < Button bsClass = "success" onClick = { ( ) => { this . selectedStudies . forEach ( ( study ) => { this . props . loadFromCBio ( study . dataTypes , study . data ) ; } ) ; this . props . handleClose ( EModalType . STUDY ) ; this . resetModal ( ) ; } } > Load Data < /Button> < /Modal.Footer> < /Modal>); } }