-
Notifications
You must be signed in to change notification settings - Fork 0
/
ViewerLocalFileData.bundle.ee5ee9351a4db3e8d0b3.js.map
1 lines (1 loc) · 102 KB
/
ViewerLocalFileData.bundle.ee5ee9351a4db3e8d0b3.js.map
1
{"version":3,"sources":["webpack:///./connectedComponents/ConnectedCineDialog.js","webpack:///./connectedComponents/ConnectedLayoutButton.js","webpack:///./connectedComponents/ToolbarRow.js","webpack:///./connectedComponents/ConnectedStudyBrowser.js","webpack:///./connectedComponents/findDisplaySetByUID.js","webpack:///./components/ViewportGrid/ViewportPane.js","webpack:///./components/ViewportGrid/ViewportGrid.js","webpack:///./components/ViewportGrid/DefaultViewport.js","webpack:///./components/ViewportGrid/ConnectedViewportGrid.js","webpack:///./connectedComponents/ViewerMain.js","webpack:///./connectedComponents/ConnectedViewerMain.js","webpack:///./components/SidePanel.js","webpack:///./components/ErrorBoundaryDialog/ErrorBoundaryDialog.js","webpack:///./components/ErrorBoundaryDialog/index.js","webpack:///./connectedComponents/Viewer.js","webpack:///./connectedComponents/ConnectedViewer.js","webpack:///./lib/localFileLoaders/fileLoader.js","webpack:///./lib/localFileLoaders/pdfFileLoader.js","webpack:///./lib/localFileLoaders/dicomFileLoader.js","webpack:///./lib/localFileLoaders/fileLoaderService.js","webpack:///./lib/filesToStudies.js","webpack:///./connectedComponents/ViewerLocalFileData.js"],"names":["scrollToIndex","toolImport","csTools","import","setViewportSpecificData","OHIF","redux","actions","ConnectedCineDialog","connect","state","viewports","cine","viewportSpecificData","activeViewportIndex","activeEnabledElement","commandsManager","runCommand","activeViewportCineData","isPlaying","cineFrameRate","dispatch","dispatchSetViewportSpecificData","viewportIndex","data","propsFromState","propsFromDispatch","ownProps","onPlayPauseChanged","cloneDeep","onFrameRateChanged","frameRate","onClickNextButton","stackData","getToolState","length","currentImageIdIndex","imageIds","onClickBackButton","onClickSkipToStart","onClickSkipToEnd","lastIndex","CineDialog","setLayout","setViewportActive","ConnectedLayoutButton","currentLayout","layout","onChange","selectedCell","numRows","row","numColumns","col","numViewports","i","viewport","plugin","vtk","push","onChangeFromDispatch","LayoutButton","ToolbarRow","props","dialog","dialogId","activeButtons","toolbarButtons","find","button","options","behavior","dismiss","id","filter","setState","toolbarButtonDefinitions","_getVisibleToolbarButtons","call","seriesPerStudyCount","_handleBuiltIn","bind","_onDerivedDisplaySetsLoadedAndCached","updateButtonGroups","panelModules","extensionManager","modules","MODULE_TYPES","PANEL","this","buttonGroups","left","right","forEach","panelExtension","panelModule","module","defaultContexts","Array","from","defaultContext","menuOptions","menuOption","contexts","context","hasActiveContext","activeContexts","some","actx","includes","isDisabled","studies","activeViewport","menuOptionEntry","value","target","icon","bottomLabel","label","unshift","t","document","addEventListener","removeEventListener","prevProps","activeContextsChanged","prevStudies","prevActiveViewport","shouldUpdate","series","closeCineDialogIfNotApplicable","buttonComponents","_getButtonComponents","onPress","side","handleSidePanelChange","onPressLeft","onPressRight","className","style","padding","selectedLeftSidePanel","onValueChanged","marginLeft","selectedRightSidePanel","Component","_getCustomButtonComponent","CustomComponent","activeButtonsIds","map","isActive","parentContext","toolbarClickCallback","_handleToolbarButtonClick","key","_getExpandableButtonComponent","activeCommand","childButtons","buttons","childButton","onClick","indexOf","_getDefaultButtonComponent","_this","hasCustomComponent","hasNestedButtonDefinitions","evt","commandName","Object","assign","commandOptions","type","toggables","togglable","toolbarModules","TOOLBAR","extension","definitions","definition","querySelector","getBoundingClientRect","x","y","newDialogId","create","content","defaultPosition","title","isLeftSidePanelOpen","PropTypes","bool","isRequired","isRightSidePanelOpen","string","func","arrayOf","array","any","modal","withTranslation","withModal","withDialog","withAppContext","utils","studyMetadataManager","setActiveViewportSpecificData","ConnectedStudyBrowser","stackLoadingProgressMap","loading","progress","studiesWithLoadingData","study","thumbnails","displaySetInstanceUID","stackId","stackProgressData","stackPercentComplete","percentComplete","onThumbnailClick","displaySet","studyMetadata","isArray","reduce","all","current","currentDisplaySet","displaySets","concat","ds","findDisplaySetByUID","isDerived","Modality","getSourceDisplaySet","Error","StudyBrowser","ViewportPane","children","onDrop","propClassName","useDrop","accept","drop","droppedItem","monitor","canDrop","isOver","StudyInstanceUID","collect","highlighted","hovered","classNames","ref","data-cy","propTypes","node","number","loadAndCacheDerivedDisplaySets","ViewportGrid","availablePlugins","defaultPluginName","defaultPlugin","setViewportData","viewportData","isStudyLoaded","rowSize","colSize","snackbar","useSnackbarContext","logger","useLogger","useEffect","promise","catch","error","message","show","autoClose","ViewportPanes","React","useMemo","pluginName","ViewportComponent","JSON","stringify","_getViewportComponent","active","display","gridTemplateRows","gridTemplateColumns","height","width","supportsDrop","object","defaultProps","DefaultViewport","getAvailableViewportModules","memoize","viewportModules","availableViewportModules","moduleDefinition","extensionId","ConnectedViewportGrid","VIEWPORT","values","_values","ViewerMain","dirtyViewportPanes","viewportPane","foundDisplaySet","v","vp","findDisplaySet","dSet","getDisplaySets","fillEmptyViewportPanes","prevViewportAmount","viewportAmount","isVtk","keys","clearViewportSpecificData","ConnectedViewerMain","SidePanel","isOpen","fromSideClass","styles","maxWidth","marginRight","Number","parseInt","UIModalService","servicesManager","services","ErrorBoundaryDialog","fallbackComponent","role","onError","componentStack","useState","open","setOpen","s","name","classnames","opened","Viewer","log","info","earliestDate","Date","toISOString","latestDate","StudyDate","moment","Promise","resolve","timepointType","timepointId","studyInstanceUIDs","PatientID","isLocked","timepointData","query","timepointIds","timepoints","onTimepointsUpdated","measurements","onMeasurementsUpdated","activeServer","server","MeasurementApi","setConfiguration","dataExchange","retrieve","DICOMSR","retrieveMeasurements","store","storeMeasurements","TimepointApi","retrieveTimepoints","storeTimepoints","remove","removeTimepoint","update","updateTimepoint","disassociate","disassociateStudy","_getActiveViewport","dismissAll","timepointApi","measurementApi","currentTimepointId","_mapStudiesToThumbnails","VisiblePanelLeft","VisiblePanelRight","panelExt","components","comp","component","WhiteLabelingContext","Consumer","whiteLabeling","UserManagerContext","userManager","AppContext","appContext","ConnectedHeader","linkText","appConfig","showStudyList","undefined","linkPath","createLogoComponentFn","isDerivedDisplaySetsLoaded","selectedPanel","sideClicked","toUpperCase","slice","openKey","selectedKey","updatedState","prevSelectedPanel","isSameSelectedPanel","activeIndex","getActiveViewport","shape","SeriesDescription","SeriesNumber","InstanceNumber","numImageFrames","images","getImageId","wadoRoot","_checkForSeriesInconsistencesWarnings","warningsList","warningIssues","warning","ReconstructionIssues","DATASET_4D","VARYING_IMAGESDIMENSIONS","VARYING_IMAGESCOMPONENTS","VARYING_IMAGESORIENTATION","IRREGULAR_SPACING","MULTIFFRAMES","missingFrames","warn","imageId","altImageText","imageIndex","Math","floor","hasWarnings","setTimepoints","setMeasurements","getActiveServer","servers","a","ConnectedViewer","FileLoader","file","image","dataset","PDFFileLoader","cornerstoneWADOImageLoader","wadouri","loadFileRequest","getDefaultStudy","StudyTime","AccessionNumber","ReferringPhysicianName","PatientName","PatientBirthdate","PatientSex","StudyId","StudyDescription","SeriesInstanceUID","instances","metadata","SOPInstanceUID","SOPClassUID","Rows","Columns","NumberOfFrames","isLocalFile","metadataProvider","cornerstone","DICOMFileLoader","dicomData","dcmjs","DicomMessage","readFile","DicomMetaDictionary","naturalizeDataset","dict","addInstance","_meta","namifyDataset","meta","e","console","getStudyFromDataset","PatientBirthDate","StudyID","instance","url","FileLoaderService","fileType","loader","getLoader","groupBy","list","groupByKey","listKey","nonKeyCounter","acc","obj","studyGroup","seriesGrouped","fileManager","add","loadFile","getDataset","getStudies","processFile","fileLoaderService","addFile","filesToStudies","files","processFilesPromises","groupSeries","flat","OHIFStudyMetadata","dropZoneLinkDialog","i18n","dir","noDrag","getRootProps","getInputProps","webkitdirectory","mozdirectory","ViewerLocalFileData","purge","updatedStudies","sopClassHandlerModules","createDisplaySets","forEachDisplaySet","displayset","localFile","acceptedFiles","updateStudies","noClick","linksDialogMessage"],"mappings":"gRAUMA,GAAgBC,EADHC,IAAQC,QACM,sBACzBC,EAA4BC,IAAKC,MAAMC,QAAvCH,wBA4FOI,EANaC,aAjFJ,SAAAC,GAAS,MAEuBA,EAAMC,UACpDC,GAHuB,EAEvBC,qBAFuB,EAEDC,sBACgC,IAAtDF,KASR,MAAO,CACLG,qBATUC,IAAgBC,WAAW,mCAUrCC,uBAReN,GAAQ,CACvBO,WAAW,EACXC,cAAe,IAOfN,oBAAqBJ,EAAMC,UAAUG,wBAId,SAAAO,GACzB,MAAO,CACLC,gCAAiC,SAACC,EAAeC,GAC/CH,EAASjB,EAAwBmB,EAAeC,SAKnC,SAACC,EAAgBC,EAAmBC,GAAa,IAEhEZ,EAGEU,EAHFV,qBACAG,EAEEO,EAFFP,uBACAJ,EACEW,EADFX,oBAGF,MAAO,CACLM,cAAeF,EAAuBE,cACtCD,UAAWD,EAAuBC,UAClCS,mBAAoB,SAAAT,GAClB,IAAMP,EAAOiB,IAAUX,GACvBN,EAAKO,WAAaP,EAAKO,UAEvBO,EAAkBJ,gCAAgCR,EAAqB,CACrEF,UAGJkB,mBAAoB,SAAAC,GAClB,IAAMnB,EAAOiB,IAAUX,GACvBN,EAAKQ,cAAgBW,EAErBL,EAAkBJ,gCAAgCR,EAAqB,CACrEF,UAGJoB,kBAAmB,WACjB,IAAMC,EAAY/B,IAAQgC,aAAanB,EAAsB,SAC7D,GAAKkB,GAAcA,EAAUT,MAASS,EAAUT,KAAKW,OAArD,CAFuB,MAGmBF,EAAUT,KAAK,GAAjDY,EAHe,EAGfA,oBACJA,GAJmB,EAGMC,SACOF,OAAS,GAC7CnC,EAAce,EAAsBqB,EAAsB,KAE5DE,kBAAmB,WACjB,IAAML,EAAY/B,IAAQgC,aAAanB,EAAsB,SAC7D,GAAKkB,GAAcA,EAAUT,MAASS,EAAUT,KAAKW,OAArD,CAFuB,IAGfC,EAAwBH,EAAUT,KAAK,GAAvCY,oBACoB,IAAxBA,GACJpC,EAAce,EAAsBqB,EAAsB,KAE5DG,mBAAoB,WAClB,IAAMN,EAAY/B,IAAQgC,aAAanB,EAAsB,SACxDkB,GAAcA,EAAUT,MAASS,EAAUT,KAAKW,QACrDnC,EAAce,EAAsB,IAEtCyB,iBAAkB,WAChB,IAAMP,EAAY/B,IAAQgC,aAAanB,EAAsB,SAC7D,GAAKkB,GAAcA,EAAUT,MAASS,EAAUT,KAAKW,OAArD,CACA,IAAMM,EAAYR,EAAUT,KAAK,GAAGa,SAASF,OAAS,EACtDnC,EAAce,EAAsB0B,QAKdhC,CAI1BiC,K,ECjGuCrC,IAAKC,MAAMC,QAA5CoC,E,EAAAA,UAAWC,E,EAAAA,kBA8DJC,EANepC,aAtDN,SAAAC,GACtB,MAAO,CACLoC,cAAepC,EAAMC,UAAUoC,OAC/BjC,oBAAqBJ,EAAMC,UAAUG,wBAId,SAAAO,GACzB,MAAO,CAEL2B,SAAU,SAACC,EAAcH,EAAehC,GAMtC,IALA,IAAMH,EAAY,GACZuC,EAAUD,EAAaE,IAAM,EAC7BC,EAAaH,EAAaI,IAAM,EAChCC,EAAeJ,EAAUE,EAEtBG,EAAI,EAAGA,EAAID,EAAcC,IAAK,CAErC,IAAMC,EAAWV,EAAcnC,UAAU4C,GACrCE,EAASD,GAAYA,EAASC,OAC9BD,GAAYA,EAASE,MACvBD,EAAS,eAGX9C,EAAUgD,KAAK,CACbF,WAGJ,IAAMV,EAAS,CACbG,UACAE,aACAzC,aAIEG,EADmBwC,EAAe,GAEpCjC,EAASuB,EAAkB,IAG7BvB,EAASsB,EAAUI,SAKN,SAACtB,EAAgBC,GAClC,IAAMkC,EAAuBlC,EAAkBsB,SACvCF,EAAuCrB,EAAvCqB,cAAehC,EAAwBW,EAAxBX,oBAEvB,MAAO,CACLkC,SAAU,SAAAC,GAAY,OACpBW,EAAqBX,EAAcH,EAAehC,OAI1BL,CAI5BoD,K,4rCC5CIC,E,YAqBJ,WAAYC,GAAO,M,iGAAA,S,EACjB,K,EAAA,eAAMA,GAAN,G,gDADiB,yCA6Ic,WAAM,IAC7BC,EAAW,EAAKD,MAAhBC,OAD6B,EAEa,EAAKtD,MAAjDuD,EAF+B,EAE/BA,SAAUC,EAFqB,EAErBA,cAAeC,EAFM,EAENA,eAC3BF,IACwBE,EAAeC,MACvC,SAAAC,GAAM,OAAIA,EAAOC,SAAuC,SAA5BD,EAAOC,QAAQC,cAG3CP,EAAOQ,QAAQ,CAAEC,GAAIR,IACrBC,EAAgBA,EAAcQ,QAC5B,SAAAL,GAAM,OAAIA,EAAOC,SAAuC,SAA5BD,EAAOC,QAAQC,YAE7C,EAAKI,SAAS,CAAEV,SAAU,KAAMC,uBAtJpC,IAAMU,EAA2BC,EAA0BC,KAA1B,MAHhB,OAYjB,EAAKpE,MAAQ,CACXyD,eAAgBS,EAChBV,cAAe,IAGjB,EAAKa,oBAAsB,GAE3B,EAAKC,eAAiBA,EAAeC,KAAf,MACtB,EAAKC,qCAAuC,EAAKA,qCAAqCD,KAA1C,MAI5C,EAAKE,qBAxBY,E,4SA2BE,WACbC,EAAeC,IAAiBC,QAAQC,IAAaC,OAE3DC,KAAKC,aAAe,CAClBC,KAAM,GACNC,MAAO,IAITR,EAAaS,SAAQ,SAAAC,GACnB,IAAMC,EAAcD,EAAeE,OAC7BC,EAAkBC,MAAMC,KAAKJ,EAAYK,gBAE/CL,EAAYM,YAAYR,SAAQ,SAAAS,GAC9B,IAAMC,EAAWL,MAAMC,KAAKG,EAAWE,SAAWP,GAC5CQ,EAAmB,EAAK1C,MAAM2C,eAAeC,MAAK,SAAAC,GAAI,OAC1DL,EAASM,SAASD,MAKdE,EAC6B,mBAA1BR,EAAWQ,YAClBR,EAAWQ,WAAW,EAAK/C,MAAMgD,QAAS,EAAKhD,MAAMiD,gBAEvD,GAAIP,IAAqBK,EAAY,CACnC,IAAMG,EAAkB,CACtBC,MAAOZ,EAAWa,OAClBC,KAAMd,EAAWc,KACjBC,YAAaf,EAAWgB,OAEpBnB,EAAOG,EAAWH,MAAQ,QAEhC,EAAKT,aAAaS,GAAMxC,KAAKsD,UAMnCxB,KAAKC,aAAaC,KAAK4B,QAAQ,CAC7BL,MAAO,UACPE,KAAM,WACNC,YAAa5B,KAAK1B,MAAMyD,EAAE,c,0CAU5BC,SAASC,iBACP,oCACAjC,KAAKP,wC,6CAKPuC,SAASE,oBACP,oCACAlC,KAAKP,wC,6DAKPO,KAAKN,qBACLM,KAAKd,SAAS,CACZR,eAAgBU,EAA0BC,KAAKW,U,yCAIhCmC,GACjB,IAAMC,EACJD,EAAUlB,iBAAmBjB,KAAK1B,MAAM2C,eAEpCoB,EAAcF,EAAUb,QACxBgB,EAAqBH,EAAUZ,eAC/BA,EAAiBvB,KAAK1B,MAAMiD,eAC5BD,EAAUtB,KAAK1B,MAAMgD,QACrBhC,EAAsBU,KAAKV,oBAE7BiD,GAAe,EAEnB,GACEF,EAAY3F,SAAW4E,EAAQ5E,QAC/B4F,IAAuBf,EAEvBgB,GAAe,OAEf,IAAK,IAAIzE,EAAI,EAAGA,EAAIwD,EAAQ5E,OAAQoB,IAClC,GAAIwD,EAAQxD,GAAG0E,OAAO9F,SAAW4C,EAAoBxB,GAAI,CACvDwB,EAAoBxB,GAAKwD,EAAQxD,GAAG0E,OAAO9F,OAE3C6F,GAAe,EACf,MAKFA,GACFvC,KAAKN,qBAGH0C,GACFpC,KAAKd,SACH,CACER,eAAgBU,EAA0BC,KAAKW,OAEjDA,KAAKyC,kC,+BAsBF,WACDC,EAAmBC,EAAqBtD,KAC5CW,KACAA,KAAK/E,MAAMyD,eACXsB,KAAK/E,MAAMwD,eAGPmE,EAAU,SAACC,EAAMpB,GACrB,EAAKnD,MAAMwE,sBAAsBD,EAAMpB,IAEnCsB,EAAcH,EAAQpD,KAAKQ,KAAM,QACjCgD,EAAeJ,EAAQpD,KAAKQ,KAAM,SAExC,OACE,oCACE,yBAAKiD,UAAU,cACb,yBAAKA,UAAU,wBAAwBC,MAAO,CAAEC,QAAS,SACvD,kBAAC,IAAD,CACEtE,QAASmB,KAAKC,aAAaC,KAC3BuB,MAAOzB,KAAK1B,MAAM8E,uBAAyB,GAC3CC,eAAgBN,KAGnBL,EACD,kBAAC,EAAD,MACA,yBACEO,UAAU,0BACVC,MAAO,CAAEI,WAAY,SAEpBtD,KAAKC,aAAaE,MAAMzD,QACvB,kBAAC,IAAD,CACEmC,QAASmB,KAAKC,aAAaE,MAC3BsB,MAAOzB,KAAK1B,MAAMiF,wBAA0B,GAC5CF,eAAgBL,Y,8BApNPQ,aA8NzB,SAASC,EAA0B7E,EAAQH,GACzC,IAAMiF,EAAkB9E,EAAO8E,gBAI/B,GAHoD,mBAApBA,EAGV,CACpB,IACMC,EAAmBlF,EAAcmF,KAAI,SAAAhF,GAAM,OAAIA,EAAOI,MACtD6E,EAAWF,EAAiBvC,SAASxC,EAAOI,IAElD,OACE,kBAAC0E,EAAD,CACEI,cANkB9D,KAOlB+D,qBAAsBC,EAA0BxE,KAAKQ,MACrDpB,OAAQA,EACRqF,IAAKrF,EAAOI,GACZP,cAAekF,EACfE,SAAUA,KAMlB,SAASK,EAA8BtF,EAAQH,GAAe,IAExD0F,EAFwD,OAGtDC,EAAexF,EAAOyF,QAAQT,KAAI,SAAAU,GAOtC,OANAA,EAAYC,QAAUP,EAA0BxE,KAAK,EAAM8E,GAEvD7F,EAAcmF,KAAI,SAAAhF,GAAM,OAAIA,EAAOI,MAAIwF,QAAQF,EAAYtF,KAAO,IACpEmF,EAAgBG,EAAYtF,IAGvBsF,KAGT,OACE,kBAAC,IAAD,CACEL,IAAKrF,EAAOI,GACZ6C,MAAOjD,EAAOiD,MACdF,KAAM/C,EAAO+C,KACb0C,QAASD,EACTD,cAAeA,IAKrB,SAASM,EAA2B7F,EAAQH,GAC1C,OACE,kBAAC,IAAD,CACEwF,IAAKrF,EAAOI,GACZ6C,MAAOjD,EAAOiD,MACdF,KAAM/C,EAAO+C,KACb4C,QAASP,EAA0BxE,KAAKQ,KAAMpB,GAC9CiF,SAAUpF,EAAcmF,KAAI,SAAAhF,GAAM,OAAIA,EAAOI,MAAIoC,SAASxC,EAAOI,MAQvE,SAAS2D,EAAqBjE,EAAgBD,GAC5C,IAAMiG,EAAQ1E,KACd,OAAOtB,EAAekF,KAAI,SAAAhF,GACxB,IAAM+F,EAAqB/F,EAAO8E,gBAC5BkB,EAA6BhG,EAAOyF,SAAWzF,EAAOyF,QAAQ3H,OAEpE,OAAIiI,EACKlB,EAA0BpE,KAAKqF,EAAO9F,EAAQH,GAGnDmG,EACKV,EAA8B7E,KAAKqF,EAAO9F,EAAQH,GAGpDgG,EAA2BpF,KAAKqF,EAAO9F,EAAQH,MAgB1D,SAASuF,EAA0BpF,EAAQiG,EAAKvG,GAAO,IAC7CG,EAAkBuB,KAAK/E,MAAvBwD,cAER,GAAIG,EAAOkG,YAAa,CACtB,IAAMjG,EAAUkG,OAAOC,OAAO,CAAEH,OAAOjG,EAAOqG,gBAC9C1J,IAAgBC,WAAWoD,EAAOkG,YAAajG,GAMjD,GAAoB,kBAAhBD,EAAOsG,KAA0B,CACnC,IAAMC,EAAY1G,EAAcQ,QAC9B,gBAAGJ,EAAH,EAAGA,QAAH,OAAiBA,IAAYA,EAAQuG,aAEvCpF,KAAKd,SAAS,CAAET,cAAe,GAAF,SAAM0G,GAAN,CAAiBvG,UACrB,YAAhBA,EAAOsG,MAChBlF,KAAKT,eAAeX,GAOxB,SAASQ,IAA4B,WAC7BiG,EAAiBzF,IAAiBC,QAAQC,IAAawF,SACvDnG,EAA2B,GAajC,OAXAkG,EAAejF,SAAQ,SAAAmF,GAAa,MACMA,EAAUhF,OAA1CiF,EAD0B,EAC1BA,YAAa7E,EADa,EACbA,eACrB6E,EAAYpF,SAAQ,SAAAqF,GAClB,IAAM1E,EAAU0E,EAAW1E,SAAWJ,EAElC,EAAKrC,MAAM2C,eAAeG,SAASL,IACrC5B,EAAyBjB,KAAKuH,SAK7BtG,EAGT,SAASI,EAAeX,GAAQ,MAERoB,KAAK1B,MAAnBC,EAFsB,EAEtBA,OAAQwD,EAFc,EAEdA,EACRvD,EAAawB,KAAK/E,MAAlBuD,SACAQ,EAAgBJ,EAAhBI,GAAIH,EAAYD,EAAZC,QAEZ,GAAyB,SAArBA,EAAQC,SACV,GAAIN,EACFD,EAAOQ,QAAQ,CAAEC,GAAIR,IACrBwB,KAAKd,UAAS,SAAAjE,GAAK,MAAK,CACtBuD,SAAU,KACVC,cAAe,EACVxD,EAAMwD,cAAcQ,QAAO,SAAAL,GAAM,OAAIA,EAAOI,KAAOA,cAGrD,CACL,IADK,EAEYgD,SACd0D,cADc,eAEdC,wBAFKC,EAFH,EAEGA,EAAGC,EAFN,EAEMA,EAGLC,EAAcvH,EAAOwH,OAAO,CAChCC,QAASjL,EACTkL,gBAAiB,CACfL,EAAGA,EAPS,IAOM,EAClBC,EAAGA,EARS,IAQM,KAGtB7F,KAAKd,UAAS,SAAAjE,GAAK,MAAK,CACtBuD,SAAUsH,EACVrH,cAAe,GAAF,SAAMxD,EAAMwD,eAAZ,CAA2BG,QAKrB,yBAArBC,EAAQC,UACVvD,IAAgBC,WAAW,4BAA6B,CACtD0K,MAAOnE,EAAE,iC,EAxYT1D,E,YAGe,CACjB8H,oBAAqBC,IAAUC,KAAKC,WACpCC,qBAAsBH,IAAUC,KAAKC,WACrClD,sBAAuBgD,IAAUI,OAAOF,WACxC/C,uBAAwB6C,IAAUI,OAAOF,WACzCxD,sBAAuBsD,IAAUK,KAAKH,WACtCrF,eAAgBmF,IAAUM,QAAQN,IAAUI,QAAQF,WACpDhF,QAAS8E,IAAUO,MACnB5E,EAAGqE,IAAUK,KAAKH,WAElB/H,OAAQ6H,IAAUQ,IAClBC,MAAOT,IAAUQ,M,EAdfvI,E,eAiBkB,CACpBiD,QAAS,KA2XEwF,kBAAgB,CAAC,SAAU,wBAA3BA,CACbC,YAAUC,YAAWC,YAAe5I,MC5ZLzD,IAAKsM,MAA9BC,qB,IAEAC,EAAkCxM,IAAKC,MAAMC,QAA7CsM,8BAkEOC,EALerM,aAxDN,SAACC,EAAOiB,GAI9B,IAAMoL,EAA0BrM,EAAMsM,QAAQC,SACxCC,EAAyBrL,IAAUF,EAASoF,SAiBlD,OAfAmG,EAAuBrH,SAAQ,SAAAsH,GAC7BA,EAAMC,WAAWvH,SAAQ,SAAArE,GAAQ,IACvB6L,EAA0B7L,EAA1B6L,sBACFC,EAAU,iBAAH,OAAoBD,GAC3BE,EAAoBR,EAAwBO,GAE9CE,EAAuB,EACvBD,IACFC,EAAuBD,EAAkBE,iBAG3CjM,EAAKgM,qBAAuBA,QAIzB,CACLzG,QAASmG,MAIc,SAAC7L,EAAUM,GACpC,MAAO,CACL+L,iBAAkB,SAAAL,GAChB,IAAIM,ECtCK,SACbC,EACAP,GAEA,OAAKnH,MAAM2H,QAAQD,IAEIA,EAAcE,QAAO,SAACC,EAAKC,GAChD,IAAIC,EAAoB,GAIxB,OAHID,GAAW9H,MAAM2H,QAAQG,EAAQE,eACnCD,EAAoBD,EAAQE,aAEvBH,EAAII,OAAOF,KACjB,IAK+B7J,MAHT,SAAAgK,GAAE,OACzBA,EAAGf,wBAA0BA,MAXW,KDkCrBgB,CACf1M,EAASiM,cACTP,GAGF,GAAIM,EAAWW,UAAW,KAChBC,EAAaZ,EAAbY,SAIR,KAFAZ,EAAaA,EAAWa,oBAAoB7M,EAASiM,gBAGnD,MAAM,IAAIa,MAAJ,gCACqBF,EADrB,0BAKR,IAAKZ,EACH,MAAM,IAAIc,MAAM,2BAIpBpN,EAASwL,EAA8Bc,QAKflN,CAG5BiO,K,kiBElEF,IAAMC,EAAe,SAAU5K,GAAO,IAC5B6K,EAA8D7K,EAA9D6K,SAAUC,EAAoD9K,EAApD8K,OAAQtN,EAA4CwC,EAA5CxC,cAA0BuN,EAAkB/K,EAA7B2E,UADL,IAEKqG,YAAQ,CAC/CC,OAAQ,YACRC,KAAM,SAACC,EAAaC,GAClB,IAAMC,EAAUD,EAAQC,UAClBC,EAASF,EAAQE,SAEvB,GAAID,GAAWC,GAAUR,EAAQ,KACvBS,EAA4CJ,EAA5CI,iBAAkBjC,EAA0B6B,EAA1B7B,sBAE1BwB,EAAO,CAAEtN,gBAAe+N,mBAAkBjC,4BAK9CkC,QAAS,SAAAJ,GAAO,MAAK,CACnBK,YAAaL,EAAQC,UACrBK,QAASN,EAAQE,aAlBe,UAE3BI,EAF2B,EAE3BA,QAASD,EAFkB,EAElBA,YAAeP,EAFG,KAsBpC,OACE,yBACEvG,UAAWgH,IACT,uBACA,CAAED,QAASA,GACX,CAAED,YAAaA,GACfV,GAEFa,IAAKV,EACLW,UAAA,6BAA+BrO,IAE9BqN,IAKPD,EAAakB,UAAY,CACvBjB,SAAU/C,IAAUiE,KAAK/D,WACzBxK,cAAesK,IAAUkE,OAAOhE,WAChC8C,OAAQhD,IAAUK,KAAKH,WACvBrD,UAAWmD,IAAUI,QAGR0C,Q,0BCvCPqB,GAAmCrD,IAAnCqD,+BAEFC,GAAe,SAASlM,GAAO,IAEjCjD,EAWEiD,EAXFjD,oBACAoP,EAUEnM,EAVFmM,iBACeC,EASbpM,EATFqM,cACArN,EAQEgB,EARFhB,OACAG,EAOEa,EAPFb,QACAE,EAMEW,EANFX,WACAiN,EAKEtM,EALFsM,gBACAtJ,EAIEhD,EAJFgD,QACAuJ,EAGEvM,EAHFuM,aACA1B,EAEE7K,EAFF6K,SACA2B,EACExM,EADFwM,cAGIC,EAAU,IAAMtN,EAChBuN,EAAU,IAAMrN,EAGtB,IAAKkN,IAAiBA,EAAanO,OACjC,OAAO,KAGT,IAAMuO,EAAWC,cACXC,EAASC,cAEfC,qBAAU,WACJP,GACFD,EAAazK,SAAQ,SAAA8H,GACFqC,GAA+BrC,EAAY5G,GACnDlB,SAAQ,SAAAkL,GACfA,EAAQC,OAAM,SAAAC,GACZL,EAAOK,MAAM,CAAEA,QAAOC,QAASD,EAAMC,UACrCR,EAASS,KAAK,CACZxF,MAAO,qCACPuF,QAASD,EAAMC,QACfvG,KAAM,QACNsG,QACAG,WAAW,eAMpB,CAACrK,EAASuJ,EAAcC,EAAeG,IAE1C,IAqDMW,EAAgBC,IAAMC,SArDH,kBACvBxO,EAAOpC,UAAU0I,KAAI,SAACtG,EAAQxB,GAC5B,IAAMoM,EAAa2C,EAAa/O,GAEhC,IAAKoM,EACH,OAAO,KAGT,IAAMnM,EAAO,CACXmM,aACA5G,WAeIyK,GACHzO,EAAOU,QAAUkK,GAAcA,EAAWlK,OACvCkK,EAAWlK,OACXV,EAAOU,OAEPgO,EAwFZ,SACEnB,EACA/O,EACAqN,EACAsB,EACAsB,EACArB,GAEA,GAAIG,EAAa3C,WAAY,CAE3B,IAAM8D,EAAoBvB,EAD1BsB,EAAaA,GAAcrB,GAG3B,IAAKsB,EACH,MAAM,IAAIhD,MAAJ,mDACwC+C,EADxC,0CAEkBE,KAAKC,UAAUzB,KAIzC,OACE,kBAACuB,EAAD,CACEnB,aAAcA,EACd/O,cAAeA,EACfqN,SAAU,CAACA,KAKjB,OAAO,kBAAC,KAAD,MApHuBgD,CACxBpQ,EACAD,EACAqN,EACAsB,EACAsB,EACArB,GAGF,OACE,kBAAC,EAAD,CACEtB,OAAQwB,EACR9O,cAAeA,EACfmH,UAAWgH,IAAW,qBAAsB,CAC1CmC,OAAQ/Q,IAAwBS,IAElCmI,IAAKnI,GAEJkQ,QAK6C,CACpD1O,EACAuN,EACAvJ,EACA6H,EACAsB,EACAC,EACAE,EACAvP,IAGF,OACE,yBACE8O,UAAQ,eACRjH,MAAO,CACLmJ,QAAS,OACTC,iBAAkB,UAAF,OAAY7O,EAAZ,aAAwBsN,EAAxB,MAChBwB,oBAAqB,UAAF,OAAY5O,EAAZ,aAA2BqN,EAA3B,MACnBwB,OAAQ,OACRC,MAAO,SAGRb,IAKPpB,GAAaJ,UAAY,CACvBS,aAAczE,IAAUO,MAAML,WAC9BoG,aAActG,IAAUC,KAAKC,WAC7BjL,oBAAqB+K,IAAUkE,OAAOhE,WACtChJ,OAAQ8I,IAAUuG,OAAOrG,WACzBmE,iBAAkBrE,IAAUuG,OAAOrG,WACnCsE,gBAAiBxE,IAAUK,KAAKH,WAChChF,QAAS8E,IAAUO,MACnBwC,SAAU/C,IAAUiE,KACpBM,cAAevE,IAAUI,OACzB/I,QAAS2I,IAAUkE,OAAOhE,WAC1B3I,WAAYyI,IAAUkE,OAAOhE,YAG/BkE,GAAaoC,aAAe,CAC1B/B,aAAc,GACdpN,QAAS,EACTE,WAAY,EACZL,OAAQ,CACNpC,UAAW,CAAC,KAEdG,oBAAqB,EACrBqR,cAAc,EACdjC,iBAAkB,CAChBoC,gBC7JW,SAAyBvO,GACtC,OAAO,+BAAM2N,KAAKC,UAAU5N,MD8J5BqM,cAAe,yBA2CFH,U,qBE3MTsC,GAA8BC,MAAQ,SAAAC,GAC1C,IAAMC,EAA2B,GAKjC,OAJAD,EAAgB5M,SAAQ,SAAA8M,GACtBD,EAAyBC,EAAiBC,aACxCD,EAAiB3M,UAEd0M,KAgCMG,GALepS,aAxBN,SAAAC,GACtB,IAII0P,EAJEqC,EAAkBpN,IAAiBC,QAAQC,IAAauN,UACxDJ,EAA2BH,GAA4BE,GAIzDA,EAAgBtQ,SAClBiO,EAAgBqC,EAAgB,GAAGG,aAPN,MAU8BlS,EAAMC,UAEnE,MAAO,CACLuC,QAb6B,EAUvBA,QAINE,WAd6B,EAUdA,WAKfL,OAf6B,EAUFA,OAM3BjC,oBAhB6B,EAUMA,oBAQnCoP,iBAAkBwC,EAElBtC,mBAMF,KAF4B3P,CAG5BwP,I,03BCjCF,IAAI8C,GAASP,KAAQQ,MAEfC,G,YAUJ,WAAYlP,GAAO,M,IAAA,O,4FAAA,S,EACjB,K,EAAA,gBAAMA,GAAN,G,kDADiB,mCA6DM,WAEvB,IAAMmP,EAAqB,GAFE,EAGY,EAAKnP,MAAtChB,EAHqB,EAGrBA,OAAQlC,EAHa,EAGbA,qBACRqN,EAAgB,EAAKxN,MAArBwN,YAER,GAAKA,GAAgBA,EAAY/L,OAAjC,CAIA,IAAK,IAAIoB,EAAI,EAAGA,EAAIR,EAAOpC,UAAUwB,OAAQoB,IAAK,CAChD,IAAM4P,EAAetS,EAAqB0C,GAM1C,GAJE4P,GACAA,EAAa7D,kBACb6D,EAAa9F,sBAGb6F,EAAmBvP,KAAK,CACtB2L,iBAAkB6D,EAAa7D,iBAC/BjC,sBAAuB8F,EAAa9F,4BAHxC,CASA,IAAM+F,EACJlF,EAAY9J,MACV,SAAAgK,GAAE,OACC8E,EAAmBvM,MAClB,SAAA0M,GAAC,OAAIA,EAAEhG,wBAA0Be,EAAGf,6BAErCa,EAAYA,EAAY/L,OAAS,GAExC+Q,EAAmBvP,KAAKyP,IAG1BF,EAAmBrN,SAAQ,SAACyN,EAAI/P,GAC1B+P,GAAMA,EAAGhE,kBACX,EAAKe,gBAAgB,CACnB9O,cAAegC,EACf+L,iBAAkBgE,EAAGhE,iBACrBjC,sBAAuBiG,EAAGjG,+BAvGf,4BA6GD,YAIZ,IAHJ9L,EAGI,EAHJA,cACA+N,EAEI,EAFJA,iBACAjC,EACI,EADJA,sBAEIM,EAAa,EAAK4F,eACpB,EAAKxP,MAAMgD,QACXuI,EACAjC,GAGF,GAAIM,EAAWW,UAAW,KAChBC,EAAaZ,EAAbY,SAGR,KAFAZ,EAAaA,EAAWa,oBAAoB,EAAKzK,MAAMgD,UAGrD,MAAM,IAAI0H,MAAJ,gCACqBF,EADrB,0BAMV,EAAKxK,MAAM3D,wBAAwBmB,EAAeoM,MAhIlD,EAAKjN,MAAQ,CACXwN,YAAa,IAJE,E,uSAQJnH,GACb,IAAMmH,EAAc,GAUpB,OATAnH,EAAQlB,SAAQ,SAAAsH,GACdA,EAAMe,YAAYrI,SAAQ,SAAA2N,GACnBA,EAAK/P,SACR+P,EAAK/P,OAAS,eAEhByK,EAAYvK,KAAK6P,SAIdtF,I,qCAGMnH,EAASuI,EAAkBjC,GACxC,IAAMF,EAAQpG,EAAQ3C,MAAK,SAAA+I,GACzB,OAAOA,EAAMmC,mBAAqBA,KAGpC,GAAKnC,EAIL,OAAOA,EAAMe,YAAY9J,MAAK,SAAAuJ,GAC5B,OAAOA,EAAWN,wBAA0BA,O,0CAS9C,GAAI5H,KAAK1B,MAAMgD,QAAS,CACtB,IAAMmH,EAAczI,KAAKgO,eAAehO,KAAK1B,MAAMgD,SACnDtB,KAAKd,SAAS,CAAEuJ,eAAezI,KAAKiO,2B,yCAIrB9L,GACjB,IAAM+L,EAAqB/L,EAAU7E,OAAOpC,UAAUwB,OAChDyR,EAAiBnO,KAAK1B,MAAMhB,OAAOpC,UAAUwB,OAC7C0R,EAAQpO,KAAK1B,MAAMhB,OAAOpC,UAAUgG,MAAK,SAAA2M,GAAE,QAAMA,EAAG5P,OAE1D,GACE+B,KAAK1B,MAAMgD,UAAYa,EAAUb,SAChC6M,IAAmBD,IAAuBE,EAC3C,CACA,IAAM3F,EAAczI,KAAKgO,eAAehO,KAAK1B,MAAMgD,SACnDtB,KAAKd,SAAS,CAAEuJ,eAAezI,KAAKiO,2B,+BA6E/B,IACC7S,EAAyB4E,KAAK1B,MAA9BlD,qBACFyP,EAAeyC,GAAOlS,GAE5B,OACE,yBAAK6H,UAAU,cACZjD,KAAK/E,MAAMwN,YAAY/L,QACtB,kBAAC,GAAD,CACEoO,cAAe9K,KAAK1B,MAAMwM,cAC1BxJ,QAAStB,KAAK1B,MAAMgD,QACpBuJ,aAAcA,EACdD,gBAAiB5K,KAAK4K,qB,6CAST,WAEbxP,EAAyB4E,KAAK1B,MAA9BlD,qBACR2J,OAAOsJ,KAAKjT,GAAsBgF,SAAQ,SAAAtE,GACxC,EAAKwC,MAAMgQ,0BAA0BxS,W,gCAxKlB0H,a,GAAnBgK,G,YACe,CACjBnS,oBAAqB+K,IAAUkE,OAAOhE,WACtChF,QAAS8E,IAAUO,MACnBvL,qBAAsBgL,IAAUuG,OAAOrG,WACvChJ,OAAQ8I,IAAUuG,OAAOrG,WACzB3L,wBAAyByL,IAAUK,KAAKH,WACxCgI,0BAA2BlI,IAAUK,KAAKH,aAyL/BkH,U,GCpMX5S,IAAKC,MAAMC,QAFbH,G,GAAAA,wBACA2T,G,GAAAA,0BA8BaC,GALavT,aAtBJ,SAAAC,GAAS,MAC+BA,EAAMC,UAEpE,MAAO,CACLG,oBAJ6B,EACvBA,oBAINiC,OAL6B,EACFA,OAK3BlC,qBAN6B,EACMA,qBAMnCF,UAAWD,EAAMC,cAIM,SAAAU,GACzB,MAAO,CACLjB,wBAAyB,SAACmB,EAAeC,GACvCH,EAASjB,GAAwBmB,EAAeC,KAElDuS,0BAA2B,WACzB1S,EAAS0S,UAKatT,CAG1BwS,IC5BIgB,I,QAAY,SAAC,GAAsC,IAApC9N,EAAoC,EAApCA,KAAM+N,EAA8B,EAA9BA,OAAQtF,EAAsB,EAAtBA,SAAUsD,EAAY,EAAZA,MACrCiC,EAAyB,UAAThO,EAAmB,aAAe,YAElDiO,EAASlC,EACX,CACEmC,SAAUnC,EACVoC,YAAaJ,EAAS,KAAgC,EAA1BK,OAAOC,SAAStC,IAE9C,GAEJ,OACE,6BACEvJ,MAAOyL,EACP1L,UAAWgH,IAAW,YAAayE,EAAe,CAChD,UAAWD,KAGZtF,KAKPqF,GAAUpE,UAAY,CACpB1J,KAAM0F,IAAUI,OAAOF,WACvBmI,OAAQrI,IAAUC,KAAKC,WACvB6C,SAAU/C,IAAUiE,KACpBoC,MAAOrG,IAAUI,QAGJgI,U,mgBC3BPQ,GAAmBC,IAAgBC,SAAnCF,eAEFG,GAAsB,SAAC,GAA0B,IAAxBpO,EAAwB,EAAxBA,QAASoI,EAAe,EAAfA,SA6CtC,OACE,kBAAC,IAAD,CACEiG,kBAXsB,kBACxB,yBAAKnM,UAAU,gBAAgBoM,KAAK,SAClC,8CACmBtO,EADnB,KAC6B,6BAD7B,kDAUAA,QAASA,EACTuO,QAhDkB,SAAC9D,EAAO+D,GA6B5BP,GAAetD,KAAK,CAClB1F,QA7BkB,WAAM,SACAwJ,oBAAS,GADT,GACjBC,EADiB,KACXC,EADW,KAGxB,OACE,yBAAKzM,UAAU,gBAAgBoM,KAAK,SAClC,yBAAKpM,UAAU,uBACb,wBAAIA,UAAU,4BACXlC,EADH,KACa,8BAAOyK,EAAMC,WAG5B,4BACExI,UAAU,mDACVsB,QAAS,kBAAMmL,GAAQ,SAAAC,GAAC,OAAKA,OAE7B,kBAAC,IAAD,CACEC,KAAK,eACL3M,UAAW4M,IAAW,0BAA2B,CAC/CC,OAAQL,MAPd,eAaCA,GAAQ,6BAAMF,KAOnBrJ,MAAO,2BAAF,OAA6BnF,OAmBjCoI,IAKPgG,GAAoB/E,UAAY,CAC9BrJ,QAASqF,IAAUI,OAAOF,WAC1B6C,SAAU/C,IAAUiE,KAAK/D,YAGZ6I,ICrEAA,GDqEAA,G,+gCE/CTY,G,YAuCJ,WAAYzR,GAAO,M,iGAAA,S,EACjB,K,EAAA,gBAAMA,GAAN,G,kDADiB,iBA2BX,CACN6H,qBAAqB,EACrBI,sBAAsB,EACtBhD,uBAAwB,GACxBH,sBAAuB,UACvBuE,WAAY,KAhCK,+BAyCE,SAAA1I,GACnBrE,IAAKoV,IAAIC,KAAK,sBAGd,IAAIC,GAAe,IAAIC,MAAOC,cAC1BC,GAAa,IAAIF,MAAOC,cAe5B,OAdI,EAAK9R,MAAMgD,UACb+O,EAAa,IAAIF,KAAK,cAAcC,cACpC,EAAK9R,MAAMgD,QAAQlB,SAAQ,SAAAsH,GACzB,IAAM4I,EAAYC,IAAO7I,EAAM4I,UAAW,YAAYF,cAClDE,EAAYJ,IACdA,EAAeI,GAEbA,EAAYD,IACdA,EAAaC,OAMZE,QAAQC,QAAQ,CACrB,CACEC,cAAe,WACfC,YAAa,cACbC,kBAAmB,EAAKtS,MAAMsS,kBAC9BC,UAAW5R,EAAO4R,UAClBX,eACAG,aACAS,UAAU,QArEG,4BA0ED,SAAAC,GAEhB,OADAnW,IAAKoV,IAAIC,KAAK,mBACPO,QAAQC,aA5EE,4BA+ED,SAACM,EAAeC,GAEhC,OADApW,IAAKoV,IAAIC,KAAK,mBACPO,QAAQC,aAjFE,4BAoFD,SAAAE,GAEhB,OADA/V,IAAKoV,IAAIC,KAAK,mBACPO,QAAQC,aAtFE,8BAyFC,SAACQ,EAAcpH,GAEjC,OADAjP,IAAKoV,IAAIC,KAAK,qBACPO,QAAQC,aA3FE,gCA8FG,SAAAS,GAChB,EAAK5S,MAAM6S,qBACb,EAAK7S,MAAM6S,oBAAoBD,MAhGhB,kCAoGK,SAAAE,GAClB,EAAK9S,MAAM+S,uBACb,EAAK/S,MAAM+S,sBAAsBD,MAtGlB,IAGTE,EAAiB,EAAKhT,MAAtBgT,aACFC,EAASxM,OAAOC,OAAO,GAAIsM,GAJhB,OAMjB1W,IAAKwW,aAAaI,eAAeC,iBAAiB,CAChDC,aAAc,CACZC,SAAUC,IAAQC,qBAClBC,MAAOF,IAAQG,mBAEjBR,WAGF3W,IAAKwW,aAAaY,aAAaP,iBAAiB,CAC9CC,aAAc,CACZC,SAAU,EAAKM,mBACfH,MAAO,EAAKI,gBACZC,OAAQ,EAAKC,gBACbC,OAAQ,EAAKC,gBACbC,aAAc,EAAKC,qBAIvB,EAAKC,mBAAqB,EAAKA,mBAAmBjT,KAAxB,OAxBT,E,+SAoCbQ,KAAK1B,MAAMC,QACbyB,KAAK1B,MAAMC,OAAOmU,e,0CAqEF,MACiB1S,KAAK1B,MAAhCgD,EADU,EACVA,QAASwJ,EADC,EACDA,cADC,EAEuBlQ,IAAKwW,aAAtCY,EAFU,EAEVA,aAAcR,EAFJ,EAEIA,eAGhBmB,EAAe,IAAIX,EAFE,cAE+B,CACxDb,oBAAqBnR,KAAKmR,sBAGtByB,EAAiB,IAAIpB,EAAemB,EAAc,CACtDtB,sBAAuBrR,KAAKqR,wBAO9B,GAJArR,KAAK6S,mBAVsB,cAW3B7S,KAAK2S,aAAeA,EACpB3S,KAAK4S,eAAiBA,EAElBtR,EAAS,CACX,IAAMuP,EAAYvP,EAAQ,IAAMA,EAAQ,GAAGuP,UAE3C8B,EAAaV,mBAAmB,CAAEpB,cAC9B/F,GACF9K,KAAK4S,eAAef,qBAAqBhB,EAAW,CAnB7B,gBAwBzB7Q,KAAKd,SAAS,CACZyI,WAAYmL,GAAwBxR,Q,yCAKvBa,GAAW,MACOnC,KAAK1B,MAAhCgD,EADoB,EACpBA,QAASwJ,EADW,EACXA,cAOjB,GALIxJ,IAAYa,EAAUb,SACxBtB,KAAKd,SAAS,CACZyI,WAAYmL,GAAwBxR,KAGpCwJ,GAAiBA,IAAkB3I,EAAU2I,cAAe,CAC9D,IAAM+F,EAAYvP,EAAQ,IAAMA,EAAQ,GAAGuP,UACnCgC,EAAuB7S,KAAvB6S,mBAER7S,KAAK2S,aAAaV,mBAAmB,CAAEpB,cACvC7Q,KAAK4S,eAAef,qBAAqBhB,EAAW,CAACgC,O,2CAKvD,OAAO7S,KAAK1B,MAAMpD,UAAU8E,KAAK1B,MAAMjD,uB,+BAGhC,IACH0X,EAAkBC,EADf,OAcP,OAZwBpT,IAAiBC,QAAQC,IAAaC,OAE9CK,SAAQ,SAAA6S,GACtBA,EAAS1S,OAAO2S,WAAW9S,SAAQ,SAAA+S,GAC7BA,EAAKnU,KAAO,EAAK/D,MAAMsI,uBACzByP,EAAoBG,EAAKC,UAChBD,EAAKnU,KAAO,EAAK/D,MAAMmI,wBAChC2P,EAAmBI,EAAKC,iBAM5B,oCAEE,kBAACC,GAAA,EAAqBC,SAAtB,MACG,SAAAC,GAAa,OACZ,kBAACC,GAAA,EAAmBF,SAApB,MACG,SAAAG,GAAW,OACV,kBAACC,EAAA,EAAWJ,SAAZ,MACG,SAAAK,GAAU,OACT,kBAACC,EAAA,EAAD,CACEC,SACEF,EAAWG,UAAUC,cACjB,kBACAC,EAENC,SACEN,EAAWG,UAAUC,cAAgB,SAAMC,EAE7CP,YAAaA,GAEZF,GACCA,EAAcW,uBACdX,EAAcW,sBAAsBrI,eAUpD,kBAAC,GAAD,CAAqB9K,QAAQ,cAC3B,kBAAC,EAAD,CACEQ,eACEvB,KAAK1B,MAAMpD,UAAU8E,KAAK1B,MAAMjD,qBAElC8Y,2BAA4BnU,KAAK1B,MAAM6V,2BACvChO,oBAAqBnG,KAAK/E,MAAMkL,oBAChCI,qBAAsBvG,KAAK/E,MAAMsL,qBACjCnD,sBACEpD,KAAK/E,MAAMkL,oBACPnG,KAAK/E,MAAMmI,sBACX,GAENG,uBACEvD,KAAK/E,MAAMsL,qBACPvG,KAAK/E,MAAMsI,uBACX,GAENT,sBAAuB,SAACD,EAAMuR,GAC5B,IAAMC,EAAcxR,GAAQA,EAAK,GAAGyR,cAAgBzR,EAAK0R,MAAM,GACzDC,EAAU,KAAH,OAAQH,EAAR,iBACPI,EAAc,WAAH,OAAcJ,EAAd,aACXK,EAAe3P,OAAOC,OAAO,GAAI,EAAK/J,OAEtCwT,EAASiG,EAAaF,GACtBG,EAAoBD,EAAaD,GAEjCG,EACJD,IAAsBP,GAAmC,OAAlBA,EAEzCM,EAAaD,GAAeL,GAAiBO,IAEdlG,GAAUmG,KAEvCF,EAAaF,IAAYE,EAAaF,IAGxC,EAAKtV,SAASwV,IAEhBpT,QAAStB,KAAK1B,MAAMgD,WAQxB,yBAAK2B,UAAU,iBAEb,kBAAC,GAAD,CAAqBlC,QAAQ,iBAC3B,kBAAC,GAAD,CAAWL,KAAK,OAAO+N,OAAQzO,KAAK/E,MAAMkL,qBACvC4M,EACC,kBAACA,EAAD,CACE7X,UAAW8E,KAAK1B,MAAMpD,UACtBoG,QAAStB,KAAK1B,MAAMgD,QACpBuT,YAAa7U,KAAK1B,MAAMjD,sBAG1B,kBAAC,EAAD,CACEiG,QAAStB,KAAK/E,MAAM0M,WACpBQ,cAAenI,KAAK1B,MAAMgD,YAOlC,yBAAK2B,UAAWgH,IAAW,iBACzB,kBAAC,GAAD,CAAqBlJ,QAAQ,cAC3B,kBAAC,GAAD,CACEO,QAAStB,KAAK1B,MAAMgD,QACpBwJ,cAAe9K,KAAK1B,MAAMwM,kBAMhC,kBAAC,GAAD,CAAqB/J,QAAQ,kBAC3B,kBAAC,GAAD,CAAWL,KAAK,QAAQ+N,OAAQzO,KAAK/E,MAAMsL,sBACxCyM,GACC,kBAACA,EAAD,CACEvE,OAAQzO,KAAK/E,MAAMsL,qBACnBrL,UAAW8E,KAAK1B,MAAMpD,UACtBoG,QAAStB,KAAK1B,MAAMgD,QACpBuT,YAAa7U,KAAK1B,MAAMjD,oBACxBkG,eACEvB,KAAK1B,MAAMpD,UAAU8E,KAAK1B,MAAMjD,qBAElCyZ,kBAAmB9U,KAAKyS,8B,gCA7UrBjP,a,GAAfuM,G,YACe,CACjBzO,QAAS8E,IAAUM,QACjBN,IAAU2O,MAAM,CACdlL,iBAAkBzD,IAAUI,OAAOF,WACnCgK,UAAWlK,IAAUI,OACrBqK,UAAWzK,IAAUI,OACrBiC,YAAarC,IAAUM,QACrBN,IAAU2O,MAAM,CACdnN,sBAAuBxB,IAAUI,OAAOF,WACxC0O,kBAAmB5O,IAAUI,OAC7ByO,aAAc7O,IAAUkE,OACxB4K,eAAgB9O,IAAUkE,OAC1B6K,eAAgB/O,IAAUkE,OAC1BxB,SAAU1C,IAAUI,OAAOF,WAC3B8O,OAAQhP,IAAUM,QAChBN,IAAU2O,MAAM,CACdM,WAAYjP,IAAUK,KAAKH,oBAOvCsK,kBAAmBxK,IAAUO,MAC7B2K,aAAclL,IAAU2O,MAAM,CAC5B7P,KAAMkB,IAAUI,OAChB8O,SAAUlP,IAAUI,SAEtB2K,oBAAqB/K,IAAUK,KAC/B4K,sBAAuBjL,IAAUK,KAEjCvL,UAAWkL,IAAUuG,OAAOrG,WAE5BjL,oBAAqB+K,IAAUkE,OAAOhE,WACtCwE,cAAe1E,IAAUC,KACzB9H,OAAQ6H,IAAUuG,SAoTP3F,mBAAW+I,IAepBwF,GAAqC,e,EAAA,G,EAAA,yBAAG,WAAgBrN,GAAhB,6FAKtCsN,EAAe,GACjBtN,EAAWuN,eAAqD,IAApCvN,EAAWuN,cAAc/Y,SACvDwL,EAAWuN,cAAcrV,SAAQ,SAAAsV,GAC/B,OAAQA,GACN,KAAKC,KAAqBC,WACxBJ,EAAatX,KAAK,sBAClB,MACF,KAAKyX,KAAqBE,yBACxBL,EAAatX,KAAK,iEAClB,MACF,KAAKyX,KAAqBG,yBACxBN,EAAatX,KAAK,oEAClB,MACF,KAAKyX,KAAqBI,0BACxBP,EAAatX,KAAK,kDAClB,MACF,KAAKyX,KAAqBK,kBACxBR,EAAatX,KAAK,oDAClB,MACF,KAAKyX,KAAqBM,aACxBT,EAAatX,KAAK,qCAMtBsX,EAAatX,KAAK,gFAGlBgK,EAAWgO,iBACXhO,EAAWuN,eACVvN,EAAWuN,gBAAkBvN,EAAWuN,cAAc9W,MAAK,SAAAwX,GAAI,OAAIA,IAASR,KAAqBC,gBACpGJ,EAAatX,KAAK,mCAAqCgK,EAAWgO,cAAgB,KArCxC,kBAwCrCV,GAxCqC,0C,iLAAH,sDAqDrC1C,GAA0B,SAASxR,GACvC,OAAOA,EAAQsC,KAAI,SAAA8D,GA0CjB,MAAO,CACLmC,iBA1C2BnC,EAArBmC,iBA2CNlC,WAzCiBD,EAAMe,YAAY7E,KAAI,SAAAsE,GAAc,IASjDkO,EACAC,EARFzO,EAKEM,EALFN,sBACAoN,EAIE9M,EAJF8M,kBACAE,EAGEhN,EAHFgN,eACAC,EAEEjN,EAFFiN,eACAF,EACE/M,EADF+M,aAMF,GAAI/M,EAAWY,UAAoC,QAAxBZ,EAAWY,SAIpCuN,EAAe,WACV,GAAInO,EAAWkN,QAAUlN,EAAWkN,OAAO1Y,OAAQ,CACxD,IAAM4Z,EAAaC,KAAKC,MAAMtO,EAAWkN,OAAO1Y,OAAS,GAEzD0Z,EAAUlO,EAAWkN,OAAOkB,GAAYjB,kBAExCgB,EAAenO,EAAWY,SAAWZ,EAAWY,SAAW,KAK7D,MAAO,CACLsN,UACAC,eACAzO,wBACAoN,oBACAE,iBACAC,iBACAF,eACAwB,YAVkBlB,GAAsCrN,Y,GC7crBtN,IAAKC,MAAMC,QAA9C4b,G,GAAAA,cAAeC,G,GAAAA,gBAEjBC,GAAkB,SAAAC,GAEtB,OAAOA,EAAQA,QAAQlY,MADN,SAAAmY,GAAC,OAAiB,IAAbA,EAAE1K,WAwBpB2K,GAAkB/b,aApBA,SAAAC,GAAS,IACvBC,EAAuBD,EAAvBC,UAAW2b,EAAY5b,EAAZ4b,QACnB,MAAO,CACL3b,UAAWA,EAAUE,qBACrBC,oBAAqBH,EAAUG,oBAC/BiW,aAAcsF,GAAgBC,OAIP,SAAAjb,GACzB,MAAO,CACLuV,oBAAqB,SAAAD,GACnBtV,EAAS8a,GAAcxF,KAEzBG,sBAAuB,SAAAD,GACrBxV,EAAS+a,GAAgBvF,QAKPpW,CAGtB+U,IAEagH,Q,uZCpCMC,E,wTAEVC,EAAMb,M,iCACJc,EAAOd,M,iCACPe,EAASf,S,mwBCDtB,IAwDegB,EAxDO,qC,uGAAA,wF,EAAA,S,GAAA,yC,+CAAA,K,EACT,mB,EADS,c,wFAAA,E,UAAA,O,kOAAA,M,EAAA,G,EAAA,gCAEXH,EAAMb,GACb,OAAOiB,IAA2BC,QAAQC,gBAAgBnB,KAHxC,iCAMTc,EAAOd,GAChB,IAAMe,EAAU,GAEhB,OADAA,EAAQf,QAAUc,EAAMd,SAAWA,EAC5Be,IATW,iCAYTA,EAASf,GAClB,OAAOpW,KAAKwX,gBAAgBpB,KAbV,sCAgBJA,GAoCd,MAnCc,CACZvM,iBAAkB,GAClByG,UAAW,GACXmH,UAAW,GACXC,gBAAiB,GACjBC,uBAAwB,GACxBC,YAAa,GACb/G,UAAW,GACXgH,iBAAkB,GAClBC,WAAY,GACZC,QAAS,GACTC,iBAAkB,GAClBxV,OAAQ,CACN,CACEyV,kBAAmB,GACnBjD,kBAAmB,GACnBC,aAAc,GACdiD,UAAW,CACT,CACEC,SAAU,CACRC,eAAgB,GAChBC,YAAa,gCACbC,KAAM,GACNC,QAAS,GACTC,eAAgB,EAChBtD,eAAgB,GAElBG,WAAY,kBAAMe,GAClBqC,aAAa,Y,2BA7CL,GAAmBzB,I,2uBCEzC,IAAM0B,E,MAAmB9d,EAAK+d,YAAYD,iBA6F3BE,EA3FS,qC,uGAAA,wF,EAAA,S,GAAA,yC,+CAAA,K,EACX,qB,EADW,c,wFAAA,E,UAAA,O,kOAAA,M,EAAA,G,EAAA,gCAEb3B,EAAMb,GACb,OAAOiB,IAA2BC,QAAQC,gBAAgBnB,KAHtC,iCAMXc,EAAOd,GAChB,IAAIe,EAAU,GACd,IACE,IAAM0B,EAAYC,IAAM/c,KAAKgd,aAAaC,SAAS9B,GAEnDC,EAAU2B,IAAM/c,KAAKkd,oBAAoBC,kBACvCL,EAAUM,MAGZT,EAAiBU,YAAYjC,GAE7BA,EAAQkC,MAAQP,IAAM/c,KAAKkd,oBAAoBK,cAC7CT,EAAUU,MAEZ,MAAOC,GACPC,QAAQjO,MAAM,2BAA4BgO,GAK5C,OAFArC,EAAQf,QAAUA,EAEXe,IA1Ba,iCA6BXA,EAASf,GAClB,OAAOpW,KAAK0Z,oBAAoBvC,KA9BZ,4CAiCY,IAAdA,EAAc,uDAAJ,GAE1BtN,EAeEsN,EAfFtN,iBACAyG,EAcE6G,EAdF7G,UACAmH,EAaEN,EAbFM,UACAC,EAYEP,EAZFO,gBACAC,EAWER,EAXFQ,uBACAC,EAUET,EAVFS,YACA/G,EASEsG,EATFtG,UACA8I,EAQExC,EARFwC,iBACA7B,EAOEX,EAPFW,WACA8B,EAMEzC,EANFyC,QACA5B,EAKEb,EALFa,iBACAC,EAIEd,EAJFc,kBACAjD,EAGEmC,EAHFnC,kBACAC,EAEEkC,EAFFlC,aACAmB,EACEe,EADFf,QAGIyD,EAAW,CACf1B,SAAUhB,EACV2C,IAAK1D,GAGD5T,EAAS,CACbyV,kBAAmBA,EACnBjD,kBAAmBA,EACnBC,aAAcA,EACdiD,UAAW,CAAC2B,IAGRnS,EAAQ,CACZmC,mBACAyG,YACAmH,YACAC,kBACAC,yBACAC,cACA/G,YACA8I,mBACA7B,aACA8B,UACA5B,mBASAxV,OAAQ,CAACA,IAGX,OAAOkF,O,2BAvFa,GAAmBsP,I,k5CC0E5B+C,E,YAzEb,WAAY9C,GAAM,M,iGAAA,S,EAChB,S,EAAA,kB,6CADgB,kDAEhB,IAAM+C,EAAW/C,GAAQA,EAAK/R,KAFd,OAGhB,EAAK+U,OAAS,EAAKC,UAAUF,GAC7B,EAAKA,SAAW,EAAKC,OAAOD,SAJZ,E,kSAOC1Y,GACjB,IAAM6Y,EAAU,SAACC,EAAMC,EAAYC,GACjC,IAAIC,EAAgB,EAEpB,OAAOH,EAAK/R,QAAO,SAACmS,EAAKC,GAAQ,MAC3BxW,EAAMwW,EAAIJ,GACRD,EAAOK,EAAIH,GAYjB,OAPKE,EAFLvW,EAAQA,GAAY,GAAKsW,OAGvBC,EAAIvW,G,+UAAJ,IAAgBwW,GAChBD,EAAIvW,GAAKqW,GAAW,KAGtB,EAAAE,EAAIvW,GAAKqW,IAASpc,KAAlB,UAA0Bkc,IAEnBI,IACN,KAkBL,OAfuBzV,OAAOuI,OAC5B6M,EAAQ7Y,EAAS,mBAAoB,WAGTsC,KAAI,SAAA8W,GAChC,IAAMC,EAAgBR,EACpBO,EAAWlY,OACX,oBACA,aAIF,OAFAkY,EAAWlY,OAASuC,OAAOuI,OAAOqN,GAE3BD,S,iCAMHzD,GACN,OAAOI,IAA2BC,QAAQsD,YAAYC,IAAI5D,K,+BAGnDA,EAAMb,GACb,OAAOpW,KAAKia,OAAOa,SAAS7D,EAAMb,K,iCAGzBc,EAAOd,GAChB,OAAOpW,KAAKia,OAAOc,WAAW7D,EAAOd,K,iCAG5Be,EAASf,GAClB,OAAOpW,KAAKia,OAAOe,WAAW7D,EAASf,K,gCAG/B4D,GACR,MAAiB,oBAAbA,EACK5C,EAGAwB,O,8BAvEmB5B,G,8VCHhC,IAAMiE,EAAW,4CAAG,WAAMhE,GAAN,8GAEViE,EAAoB,IAAInB,EAAkB9C,GAC1Cb,EAAU8E,EAAkBC,QAAQlE,GAH1B,SAIIiE,EAAkBJ,SAAS7D,EAAMb,GAJrC,cAIVc,EAJU,gBAKMgE,EAAkBH,WAAW7D,EAAOd,GAL1C,cAKVe,EALU,iBAMM+D,EAAkBF,WAAW7D,EAASf,GAN5C,eAMV9U,EANU,yBAQTA,GARS,kCAUhBmY,QAAQzJ,IACN,KAAMJ,KACN,sDACA,KAAMnE,SAbQ,0DAAH,sDAkBF,SAAe2P,EAA9B,kC,iDAAe,WAA8BC,GAA9B,+FACPC,EAAuBD,EAAMzX,IAAIqX,GAD1B,SAESzK,QAAQlI,IAAIgT,GAFrB,cAEPha,EAFO,yBAINyY,EAAkBwB,YAAYja,EAAQka,SAJhC,4C,s5CCTPC,EAAsBtD,IAAtBsD,kBACAtU,EAAyBD,IAAzBC,qBAEFuU,EAAqB,SAACtS,EAAQuS,EAAMC,GACxC,OACE,kBAAC,IAAD,CAAUxS,OAAQA,EAAQyS,QAAM,IAC7B,gBAAGC,EAAH,EAAGA,aAAcC,EAAjB,EAAiBA,cAAjB,OACC,8BAAUD,IAAV,CAA0B7Y,UAAU,gBACjC2Y,EACC,8BACGD,EAAK,gBACN,+BACMI,IADN,CAEEC,gBAAgB,OAChBC,aAAa,WAIjB,8BACGN,EAAK,cACN,0BAAWI,WAqBnBG,E,6UAKI,CACN5a,QAAS,KACTiG,SAAS,EACTiE,MAAO,O,wBAGO,SAAAlK,GAEd6F,EAAqBgV,QAGrB,IAAMC,EAAiB9a,EAAQsC,KAAI,SAAA8D,GACjC,IAAMS,EAAgB,IAAIsT,EACxB/T,EACAA,EAAMmC,kBAEFwS,EACJzc,IAAiBC,QAAjB,sBAYF,OAVA6H,EAAMe,YACJf,EAAMe,aACNN,EAAcmU,kBAAkBD,GAElClU,EAAcoU,mBAAkB,SAAAC,GAC9BA,EAAWC,WAAY,KAGzBtV,EAAqB0T,IAAI1S,GAElBT,KAGT,EAAKxI,SAAS,CACZoC,QAAS8a,O,kSAIJ,WACDhT,EAAM,e,EAAA,G,EAAA,yBAAG,WAAMsT,GAAN,+FACb,EAAKxd,SAAS,CAAEqI,SAAS,IADZ,SAGS6T,YAAesB,GAHxB,UAGPpb,EAHO,OAIP8a,EAAiB,EAAKO,cAAcrb,GAJ7B,iDAUb,EAAKpC,SAAS,CAAEoC,QAAS8a,EAAgB7U,SAAS,IAVrC,0C,+KAAH,sDAaZ,OAAIvH,KAAK/E,MAAMuQ,MACN,uCAAaS,KAAKC,UAAUlM,KAAK/E,MAAMuQ,QAI9C,kBAAC,IAAD,CAAUpC,OAAQA,EAAQwT,SAAO,IAC9B,gBAAGd,EAAH,EAAGA,aAAH,SAAiBC,cAChB,6BAASD,IAAT,CAAyB5Y,MAAO,CAAEuJ,MAAO,OAAQD,OAAQ,UACtD,EAAKvR,MAAMqG,QACV,kBAAC,IAAD,CACEA,QAAS,EAAKrG,MAAMqG,QACpBsP,kBACE,EAAK3V,MAAMqG,SACX,EAAKrG,MAAMqG,QAAQsC,KAAI,SAAAkT,GAAC,OAAIA,EAAEjN,sBAIlC,yBAAK5G,UAAW,0BACd,yBAAKA,UAAW,sBACb,EAAKhI,MAAMsM,QACV,4BAAK,EAAKjJ,MAAMyD,EAAE,eAElB,oCACE,4BACG,EAAKzD,MAAMyD,EACV,8DAGJ,4BAhGK,SAACqH,EAAQuS,GAClC,OACE,oCACGA,EAAK,gBACLD,EAAmBtS,EAAQuS,GAC3BA,EAAK,QACLD,EAAmBtS,EAAQuS,GAAM,GACjCA,EAAK,iBAyFekB,CAAmBzT,EAAQ,EAAK9K,MAAMyD,gB,8BApF/ByB,a,EAA5B0Y,E,YACe,CACjB5a,QAAS8E,IAAUO,QA+FRG,sBAAgB,SAAhBA,CAA0BoV","file":"ViewerLocalFileData.bundle.ee5ee9351a4db3e8d0b3.js","sourcesContent":["import { connect } from 'react-redux';\nimport { CineDialog } from '@ohif/ui';\nimport OHIF from '@ohif/core';\nimport csTools from 'cornerstone-tools';\nimport { commandsManager } from './../App.js';\n// Our target output kills the `as` and \"import\" throws a keyword error\n// import { import as toolImport, getToolState } from 'cornerstone-tools';\nimport cloneDeep from 'lodash.clonedeep';\n\nconst toolImport = csTools.import;\nconst scrollToIndex = toolImport('util/scrollToIndex');\nconst { setViewportSpecificData } = OHIF.redux.actions;\n\n// Why do I need or care about any of this info?\n// A dispatch action should be able to pull this at the time of an event?\n// `isPlaying` and `cineFrameRate` might matter, but I think we can prop pass for those.\nconst mapStateToProps = state => {\n // Get activeViewport's `cine` and `stack`\n const { viewportSpecificData, activeViewportIndex } = state.viewports;\n const { cine } = viewportSpecificData[activeViewportIndex] || {};\n const dom = commandsManager.runCommand('getActiveViewportEnabledElement');\n\n const cineData = cine || {\n isPlaying: false,\n cineFrameRate: 24,\n };\n\n // New props we're creating?\n return {\n activeEnabledElement: dom,\n activeViewportCineData: cineData,\n activeViewportIndex: state.viewports.activeViewportIndex,\n };\n};\n\nconst mapDispatchToProps = dispatch => {\n return {\n dispatchSetViewportSpecificData: (viewportIndex, data) => {\n dispatch(setViewportSpecificData(viewportIndex, data));\n },\n };\n};\n\nconst mergeProps = (propsFromState, propsFromDispatch, ownProps) => {\n const {\n activeEnabledElement,\n activeViewportCineData,\n activeViewportIndex,\n } = propsFromState;\n\n return {\n cineFrameRate: activeViewportCineData.cineFrameRate,\n isPlaying: activeViewportCineData.isPlaying,\n onPlayPauseChanged: isPlaying => {\n const cine = cloneDeep(activeViewportCineData);\n cine.isPlaying = !cine.isPlaying;\n\n propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, {\n cine,\n });\n },\n onFrameRateChanged: frameRate => {\n const cine = cloneDeep(activeViewportCineData);\n cine.cineFrameRate = frameRate;\n\n propsFromDispatch.dispatchSetViewportSpecificData(activeViewportIndex, {\n cine,\n });\n },\n onClickNextButton: () => {\n const stackData = csTools.getToolState(activeEnabledElement, 'stack');\n if (!stackData || !stackData.data || !stackData.data.length) return;\n const { currentImageIdIndex, imageIds } = stackData.data[0];\n if (currentImageIdIndex >= imageIds.length - 1) return;\n scrollToIndex(activeEnabledElement, currentImageIdIndex + 1);\n },\n onClickBackButton: () => {\n const stackData = csTools.getToolState(activeEnabledElement, 'stack');\n if (!stackData || !stackData.data || !stackData.data.length) return;\n const { currentImageIdIndex } = stackData.data[0];\n if (currentImageIdIndex === 0) return;\n scrollToIndex(activeEnabledElement, currentImageIdIndex - 1);\n },\n onClickSkipToStart: () => {\n const stackData = csTools.getToolState(activeEnabledElement, 'stack');\n if (!stackData || !stackData.data || !stackData.data.length) return;\n scrollToIndex(activeEnabledElement, 0);\n },\n onClickSkipToEnd: () => {\n const stackData = csTools.getToolState(activeEnabledElement, 'stack');\n if (!stackData || !stackData.data || !stackData.data.length) return;\n const lastIndex = stackData.data[0].imageIds.length - 1;\n scrollToIndex(activeEnabledElement, lastIndex);\n },\n };\n};\n\nconst ConnectedCineDialog = connect(\n mapStateToProps,\n mapDispatchToProps,\n mergeProps\n)(CineDialog);\n\nexport default ConnectedCineDialog;\n","import { LayoutButton } from '@ohif/ui';\nimport OHIF from '@ohif/core';\nimport { connect } from 'react-redux';\n\nconst { setLayout, setViewportActive } = OHIF.redux.actions;\n\nconst mapStateToProps = state => {\n return {\n currentLayout: state.viewports.layout,\n activeViewportIndex: state.viewports.activeViewportIndex,\n };\n};\n\nconst mapDispatchToProps = dispatch => {\n return {\n // TODO: Change if layout switched becomes more complex\n onChange: (selectedCell, currentLayout, activeViewportIndex) => {\n const viewports = [];\n const numRows = selectedCell.row + 1;\n const numColumns = selectedCell.col + 1;\n const numViewports = numRows * numColumns;\n\n for (let i = 0; i < numViewports; i++) {\n // Hacky way to allow users to exit MPR \"mode\"\n const viewport = currentLayout.viewports[i];\n let plugin = viewport && viewport.plugin;\n if (viewport && viewport.vtk) {\n plugin = 'cornerstone';\n }\n\n viewports.push({\n plugin,\n });\n }\n const layout = {\n numRows,\n numColumns,\n viewports,\n };\n\n const maxActiveIndex = numViewports - 1;\n if (activeViewportIndex > maxActiveIndex) {\n dispatch(setViewportActive(0));\n }\n\n dispatch(setLayout(layout));\n },\n };\n};\n\nconst mergeProps = (propsFromState, propsFromDispatch) => {\n const onChangeFromDispatch = propsFromDispatch.onChange;\n const { currentLayout, activeViewportIndex } = propsFromState;\n\n return {\n onChange: selectedCell =>\n onChangeFromDispatch(selectedCell, currentLayout, activeViewportIndex),\n };\n};\n\nconst ConnectedLayoutButton = connect(\n mapStateToProps,\n mapDispatchToProps,\n mergeProps\n)(LayoutButton);\n\nexport default ConnectedLayoutButton;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { withTranslation } from 'react-i18next';\n\nimport { MODULE_TYPES } from '@ohif/core';\nimport {\n ExpandableToolMenu,\n RoundedButtonGroup,\n ToolbarButton,\n withModal,\n withDialog,\n} from '@ohif/ui';\n\nimport './ToolbarRow.css';\nimport { commandsManager, extensionManager } from './../App.js';\n\nimport ConnectedCineDialog from './ConnectedCineDialog';\nimport ConnectedLayoutButton from './ConnectedLayoutButton';\nimport { withAppContext } from '../context/AppContext';\n\nclass ToolbarRow extends Component {\n // TODO: Simplify these? isOpen can be computed if we say \"any\" value for selected,\n // closed if selected is null/undefined\n static propTypes = {\n isLeftSidePanelOpen: PropTypes.bool.isRequired,\n isRightSidePanelOpen: PropTypes.bool.isRequired,\n selectedLeftSidePanel: PropTypes.string.isRequired,\n selectedRightSidePanel: PropTypes.string.isRequired,\n handleSidePanelChange: PropTypes.func.isRequired,\n activeContexts: PropTypes.arrayOf(PropTypes.string).isRequired,\n studies: PropTypes.array,\n t: PropTypes.func.isRequired,\n // NOTE: withDialog, withModal HOCs\n dialog: PropTypes.any,\n modal: PropTypes.any,\n };\n\n static defaultProps = {\n studies: [],\n };\n\n constructor(props) {\n super(props);\n\n const toolbarButtonDefinitions = _getVisibleToolbarButtons.call(this);\n // TODO:\n // If it's a tool that can be active... Mark it as active?\n // - Tools that are on/off?\n // - Tools that can be bound to multiple buttons?\n\n // Normal ToolbarButtons...\n // Just how high do we need to hoist this state?\n // Why ToolbarRow instead of just Toolbar? Do we have any others?\n this.state = {\n toolbarButtons: toolbarButtonDefinitions,\n activeButtons: [],\n };\n\n this.seriesPerStudyCount = [];\n\n this._handleBuiltIn = _handleBuiltIn.bind(this);\n this._onDerivedDisplaySetsLoadedAndCached = this._onDerivedDisplaySetsLoadedAndCached.bind(\n this\n );\n\n this.updateButtonGroups();\n }\n\n updateButtonGroups() {\n const panelModules = extensionManager.modules[MODULE_TYPES.PANEL];\n\n this.buttonGroups = {\n left: [],\n right: [],\n };\n\n // ~ FIND MENU OPTIONS\n panelModules.forEach(panelExtension => {\n const panelModule = panelExtension.module;\n const defaultContexts = Array.from(panelModule.defaultContext);\n\n panelModule.menuOptions.forEach(menuOption => {\n const contexts = Array.from(menuOption.context || defaultContexts);\n const hasActiveContext = this.props.activeContexts.some(actx =>\n contexts.includes(actx)\n );\n\n // It's a bit beefy to pass studies; probably only need to be reactive on `studyInstanceUIDs` and activeViewport?\n // Note: This does not cleanly handle `studies` prop updating with panel open\n const isDisabled =\n typeof menuOption.isDisabled === 'function' &&\n menuOption.isDisabled(this.props.studies, this.props.activeViewport);\n\n if (hasActiveContext && !isDisabled) {\n const menuOptionEntry = {\n value: menuOption.target,\n icon: menuOption.icon,\n bottomLabel: menuOption.label,\n };\n const from = menuOption.from || 'right';\n\n this.buttonGroups[from].push(menuOptionEntry);\n }\n });\n });\n\n // TODO: This should come from extensions, instead of being baked in\n this.buttonGroups.left.unshift({\n value: 'studies',\n icon: 'th-large',\n bottomLabel: this.props.t('Series'),\n });\n }\n\n componentDidMount() {\n /*\n * TODO: Improve the way we notify parts of the app\n * that depends on derived display sets to be loaded.\n * (Implement pubsub for better tracking of derived display sets)\n */\n document.addEventListener(\n 'deriveddisplaysetsloadedandcached',\n this._onDerivedDisplaySetsLoadedAndCached\n );\n }\n\n componentWillUnmount() {\n document.removeEventListener(\n 'deriveddisplaysetsloadedandcached',\n this._onDerivedDisplaySetsLoadedAndCached\n );\n }\n\n _onDerivedDisplaySetsLoadedAndCached() {\n this.updateButtonGroups();\n this.setState({\n toolbarButtons: _getVisibleToolbarButtons.call(this),\n });\n }\n\n componentDidUpdate(prevProps) {\n const activeContextsChanged =\n prevProps.activeContexts !== this.props.activeContexts;\n\n const prevStudies = prevProps.studies;\n const prevActiveViewport = prevProps.activeViewport;\n const activeViewport = this.props.activeViewport;\n const studies = this.props.studies;\n const seriesPerStudyCount = this.seriesPerStudyCount;\n\n let shouldUpdate = false;\n\n if (\n prevStudies.length !== studies.length ||\n prevActiveViewport !== activeViewport\n ) {\n shouldUpdate = true;\n } else {\n for (let i = 0; i < studies.length; i++) {\n if (studies[i].series.length !== seriesPerStudyCount[i]) {\n seriesPerStudyCount[i] = studies[i].series.length;\n\n shouldUpdate = true;\n break;\n }\n }\n }\n\n if (shouldUpdate) {\n this.updateButtonGroups();\n }\n\n if (activeContextsChanged) {\n this.setState(\n {\n toolbarButtons: _getVisibleToolbarButtons.call(this),\n },\n this.closeCineDialogIfNotApplicable\n );\n }\n }\n\n closeCineDialogIfNotApplicable = () => {\n const { dialog } = this.props;\n let { dialogId, activeButtons, toolbarButtons } = this.state;\n if (dialogId) {\n const cineButtonPresent = toolbarButtons.find(\n button => button.options && button.options.behavior === 'CINE'\n );\n if (!cineButtonPresent) {\n dialog.dismiss({ id: dialogId });\n activeButtons = activeButtons.filter(\n button => button.options && button.options.behavior !== 'CINE'\n );\n this.setState({ dialogId: null, activeButtons });\n }\n }\n };\n\n render() {\n const buttonComponents = _getButtonComponents.call(\n this,\n this.state.toolbarButtons,\n this.state.activeButtons\n );\n\n const onPress = (side, value) => {\n this.props.handleSidePanelChange(side, value);\n };\n const onPressLeft = onPress.bind(this, 'left');\n const onPressRight = onPress.bind(this, 'right');\n\n return (\n <>\n <div className=\"ToolbarRow\">\n <div className=\"pull-left m-t-1 p-y-1\" style={{ padding: '10px' }}>\n <RoundedButtonGroup\n options={this.buttonGroups.left}\n value={this.props.selectedLeftSidePanel || ''}\n onValueChanged={onPressLeft}\n />\n </div>\n {buttonComponents}\n <ConnectedLayoutButton />\n <div\n className=\"pull-right m-t-1 rm-x-1\"\n style={{ marginLeft: 'auto' }}\n >\n {this.buttonGroups.right.length && (\n <RoundedButtonGroup\n options={this.buttonGroups.right}\n value={this.props.selectedRightSidePanel || ''}\n onValueChanged={onPressRight}\n />\n )}\n </div>\n </div>\n </>\n );\n }\n}\n\nfunction _getCustomButtonComponent(button, activeButtons) {\n const CustomComponent = button.CustomComponent;\n const isValidComponent = typeof CustomComponent === 'function';\n\n // Check if its a valid customComponent. Later on an CustomToolbarComponent interface could be implemented.\n if (isValidComponent) {\n const parentContext = this;\n const activeButtonsIds = activeButtons.map(button => button.id);\n const isActive = activeButtonsIds.includes(button.id);\n\n return (\n <CustomComponent\n parentContext={parentContext}\n toolbarClickCallback={_handleToolbarButtonClick.bind(this)}\n button={button}\n key={button.id}\n activeButtons={activeButtonsIds}\n isActive={isActive}\n />\n );\n }\n}\n\nfunction _getExpandableButtonComponent(button, activeButtons) {\n // Iterate over button definitions and update `onClick` behavior\n let activeCommand;\n const childButtons = button.buttons.map(childButton => {\n childButton.onClick = _handleToolbarButtonClick.bind(this, childButton);\n\n if (activeButtons.map(button => button.id).indexOf(childButton.id) > -1) {\n activeCommand = childButton.id;\n }\n\n return childButton;\n });\n\n return (\n <ExpandableToolMenu\n key={button.id}\n label={button.label}\n icon={button.icon}\n buttons={childButtons}\n activeCommand={activeCommand}\n />\n );\n}\n\nfunction _getDefaultButtonComponent(button, activeButtons) {\n return (\n <ToolbarButton\n key={button.id}\n label={button.label}\n icon={button.icon}\n onClick={_handleToolbarButtonClick.bind(this, button)}\n isActive={activeButtons.map(button => button.id).includes(button.id)}\n />\n );\n}\n/**\n * Determine which extension buttons should be showing, if they're\n * active, and what their onClick behavior should be.\n */\nfunction _getButtonComponents(toolbarButtons, activeButtons) {\n const _this = this;\n return toolbarButtons.map(button => {\n const hasCustomComponent = button.CustomComponent;\n const hasNestedButtonDefinitions = button.buttons && button.buttons.length;\n\n if (hasCustomComponent) {\n return _getCustomButtonComponent.call(_this, button, activeButtons);\n }\n\n if (hasNestedButtonDefinitions) {\n return _getExpandableButtonComponent.call(_this, button, activeButtons);\n }\n\n return _getDefaultButtonComponent.call(_this, button, activeButtons);\n });\n}\n\n/**\n * TODO: DEPRECATE\n * This is used exclusively in `extensions/cornerstone/src`\n * We have better ways with new UI Services to trigger \"builtin\" behaviors\n *\n * A handy way for us to handle different button types. IE. firing commands for\n * buttons, or initiation built in behavior.\n *\n * @param {*} button\n * @param {*} evt\n * @param {*} props\n */\nfunction _handleToolbarButtonClick(button, evt, props) {\n const { activeButtons } = this.state;\n\n if (button.commandName) {\n const options = Object.assign({ evt }, button.commandOptions);\n commandsManager.runCommand(button.commandName, options);\n }\n\n // TODO: Use Types ENUM\n // TODO: We can update this to be a `getter` on the extension to query\n // For the active tools after we apply our updates?\n if (button.type === 'setToolActive') {\n const toggables = activeButtons.filter(\n ({ options }) => options && !options.togglable\n );\n this.setState({ activeButtons: [...toggables, button] });\n } else if (button.type === 'builtIn') {\n this._handleBuiltIn(button);\n }\n}\n\n/**\n *\n */\nfunction _getVisibleToolbarButtons() {\n const toolbarModules = extensionManager.modules[MODULE_TYPES.TOOLBAR];\n const toolbarButtonDefinitions = [];\n\n toolbarModules.forEach(extension => {\n const { definitions, defaultContext } = extension.module;\n definitions.forEach(definition => {\n const context = definition.context || defaultContext;\n\n if (this.props.activeContexts.includes(context)) {\n toolbarButtonDefinitions.push(definition);\n }\n });\n });\n\n return toolbarButtonDefinitions;\n}\n\nfunction _handleBuiltIn(button) {\n /* TODO: Keep cine button active until its unselected. */\n const { dialog, t } = this.props;\n const { dialogId } = this.state;\n const { id, options } = button;\n\n if (options.behavior === 'CINE') {\n if (dialogId) {\n dialog.dismiss({ id: dialogId });\n this.setState(state => ({\n dialogId: null,\n activeButtons: [\n ...state.activeButtons.filter(button => button.id !== id),\n ],\n }));\n } else {\n const spacing = 20;\n const { x, y } = document\n .querySelector(`.ViewerMain`)\n .getBoundingClientRect();\n const newDialogId = dialog.create({\n content: ConnectedCineDialog,\n defaultPosition: {\n x: x + spacing || 0,\n y: y + spacing || 0,\n },\n });\n this.setState(state => ({\n dialogId: newDialogId,\n activeButtons: [...state.activeButtons, button],\n }));\n }\n }\n\n if (options.behavior === 'DOWNLOAD_SCREEN_SHOT') {\n commandsManager.runCommand('showDownloadViewportModal', {\n title: t('Download High Quality Image'),\n });\n }\n}\n\nexport default withTranslation(['Common', 'ViewportDownloadForm'])(\n withModal(withDialog(withAppContext(ToolbarRow)))\n);\n","import OHIF from '@ohif/core';\nimport { connect } from 'react-redux';\nimport { StudyBrowser } from '@ohif/ui';\nimport cloneDeep from 'lodash.clonedeep';\nimport findDisplaySetByUID from './findDisplaySetByUID';\n\nconst { studyMetadataManager } = OHIF.utils;\n\nconst { setActiveViewportSpecificData } = OHIF.redux.actions;\n\n// TODO\n// - Determine in which display set is active from Redux (activeViewportIndex and layout viewportData)\n// - Pass in errors and stack loading progress from Redux\nconst mapStateToProps = (state, ownProps) => {\n // If we know that the stack loading progress details have changed,\n // we can try to update the component state so that the thumbnail\n // progress bar is updated\n const stackLoadingProgressMap = state.loading.progress;\n const studiesWithLoadingData = cloneDeep(ownProps.studies);\n\n studiesWithLoadingData.forEach(study => {\n study.thumbnails.forEach(data => {\n const { displaySetInstanceUID } = data;\n const stackId = `StackProgress:${displaySetInstanceUID}`;\n const stackProgressData = stackLoadingProgressMap[stackId];\n\n let stackPercentComplete = 0;\n if (stackProgressData) {\n stackPercentComplete = stackProgressData.percentComplete;\n }\n\n data.stackPercentComplete = stackPercentComplete;\n });\n });\n\n return {\n studies: studiesWithLoadingData,\n };\n};\n\nconst mapDispatchToProps = (dispatch, ownProps) => {\n return {\n onThumbnailClick: displaySetInstanceUID => {\n let displaySet = findDisplaySetByUID(\n ownProps.studyMetadata,\n displaySetInstanceUID\n );\n\n if (displaySet.isDerived) {\n const { Modality } = displaySet;\n\n displaySet = displaySet.getSourceDisplaySet(ownProps.studyMetadata);\n\n if (!displaySet) {\n throw new Error(\n `Referenced series for ${Modality} dataset not present.`\n );\n }\n\n if (!displaySet) {\n throw new Error('Source data not present');\n }\n }\n\n dispatch(setActiveViewportSpecificData(displaySet));\n },\n };\n};\n\nconst ConnectedStudyBrowser = connect(\n mapStateToProps,\n mapDispatchToProps\n)(StudyBrowser);\n\nexport default ConnectedStudyBrowser;\n","/**\n * Finds displaySet by UID across all displaySets inside studyMetadata\n * @param {Array} studyMetadata\n * @param {string} displaySetInstanceUID\n */\nexport default function findDisplaySetByUID(\n studyMetadata,\n displaySetInstanceUID\n) {\n if (!Array.isArray(studyMetadata)) return null;\n\n const allDisplaySets = studyMetadata.reduce((all, current) => {\n let currentDisplaySet = [];\n if (current && Array.isArray(current.displaySets)) {\n currentDisplaySet = current.displaySets;\n }\n return all.concat(currentDisplaySet);\n }, []);\n\n const bySetInstanceUID = ds =>\n ds.displaySetInstanceUID === displaySetInstanceUID;\n\n const displaySet = allDisplaySets.find(bySetInstanceUID);\n return displaySet || null;\n}\n","import React from 'react';\nimport { useDrop } from 'react-dnd';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport './ViewportPane.css';\n\nconst ViewportPane = function (props) {\n const { children, onDrop, viewportIndex, className: propClassName } = props;\n const [{ hovered, highlighted }, drop] = useDrop({\n accept: 'thumbnail',\n drop: (droppedItem, monitor) => {\n const canDrop = monitor.canDrop();\n const isOver = monitor.isOver();\n\n if (canDrop && isOver && onDrop) {\n const { StudyInstanceUID, displaySetInstanceUID } = droppedItem;\n\n onDrop({ viewportIndex, StudyInstanceUID, displaySetInstanceUID });\n }\n },\n // Monitor, and collect props.\n // Returned as values by `useDrop`\n collect: monitor => ({\n highlighted: monitor.canDrop(),\n hovered: monitor.isOver(),\n }),\n });\n\n return (\n <div\n className={classNames(\n 'viewport-drop-target',\n { hovered: hovered },\n { highlighted: highlighted },\n propClassName\n )}\n ref={drop}\n data-cy={`viewport-container-${viewportIndex}`}\n >\n {children}\n </div>\n );\n};\n\nViewportPane.propTypes = {\n children: PropTypes.node.isRequired,\n viewportIndex: PropTypes.number.isRequired,\n onDrop: PropTypes.func.isRequired,\n className: PropTypes.string,\n};\n\nexport default ViewportPane;\n","import './ViewportGrid.css';\n\nimport React, { useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport { utils } from '@ohif/core';\nimport { useSnackbarContext, useLogger } from '@ohif/ui';\n//\nimport ViewportPane from './ViewportPane.js';\nimport DefaultViewport from './DefaultViewport.js';\nimport EmptyViewport from './EmptyViewport.js';\n\nconst { loadAndCacheDerivedDisplaySets } = utils;\n\nconst ViewportGrid = function(props) {\n const {\n activeViewportIndex,\n availablePlugins,\n defaultPlugin: defaultPluginName,\n layout,\n numRows,\n numColumns,\n setViewportData,\n studies,\n viewportData,\n children,\n isStudyLoaded,\n } = props;\n\n const rowSize = 100 / numRows;\n const colSize = 100 / numColumns;\n\n // http://grid.malven.co/\n if (!viewportData || !viewportData.length) {\n return null;\n }\n\n const snackbar = useSnackbarContext();\n const logger = useLogger();\n\n useEffect(() => {\n if (isStudyLoaded) {\n viewportData.forEach(displaySet => {\n const promises = loadAndCacheDerivedDisplaySets(displaySet, studies);\n promises.forEach(promise => {\n promise.catch(error => {\n logger.error({ error, message: error.message });\n snackbar.show({\n title: 'Error loading derived display set:',\n message: error.message,\n type: 'error',\n error,\n autoClose: false,\n });\n });\n });\n });\n }\n }, [studies, viewportData, isStudyLoaded, snackbar]);\n\n const getViewportPanes = () =>\n layout.viewports.map((layout, viewportIndex) => {\n const displaySet = viewportData[viewportIndex];\n\n if (!displaySet) {\n return null;\n }\n\n const data = {\n displaySet,\n studies,\n };\n\n // JAMES TODO:\n\n // Use whichever plugin is currently in use in the panel\n // unless nothing is specified. If nothing is specified\n // and the display set has a plugin specified, use that.\n //\n // TODO: Change this logic to:\n // - Plugins define how capable they are of displaying a SopClass\n // - When updating a panel, ensure that the currently enabled plugin\n // in the viewport is capable of rendering this display set. If not\n // then use the most capable available plugin\n\n const pluginName =\n !layout.plugin && displaySet && displaySet.plugin\n ? displaySet.plugin\n : layout.plugin;\n\n const ViewportComponent = _getViewportComponent(\n data, // Why do we pass this as `ViewportData`, when that's not really what it is?\n viewportIndex,\n children,\n availablePlugins,\n pluginName,\n defaultPluginName\n );\n\n return (\n <ViewportPane\n onDrop={setViewportData}\n viewportIndex={viewportIndex} // Needed by `setViewportData`\n className={classNames('viewport-container', {\n active: activeViewportIndex === viewportIndex,\n })}\n key={viewportIndex}\n >\n {ViewportComponent}\n </ViewportPane>\n );\n });\n\n const ViewportPanes = React.useMemo(getViewportPanes, [\n layout,\n viewportData,\n studies,\n children,\n availablePlugins,\n defaultPluginName,\n setViewportData,\n activeViewportIndex,\n ]);\n\n return (\n <div\n data-cy=\"viewprt-grid\"\n style={{\n display: 'grid',\n gridTemplateRows: `repeat(${numRows}, ${rowSize}%)`,\n gridTemplateColumns: `repeat(${numColumns}, ${colSize}%)`,\n height: '100%',\n width: '100%',\n }}\n >\n {ViewportPanes}\n </div>\n );\n};\n\nViewportGrid.propTypes = {\n viewportData: PropTypes.array.isRequired,\n supportsDrop: PropTypes.bool.isRequired,\n activeViewportIndex: PropTypes.number.isRequired,\n layout: PropTypes.object.isRequired,\n availablePlugins: PropTypes.object.isRequired,\n setViewportData: PropTypes.func.isRequired,\n studies: PropTypes.array,\n children: PropTypes.node,\n defaultPlugin: PropTypes.string,\n numRows: PropTypes.number.isRequired,\n numColumns: PropTypes.number.isRequired,\n};\n\nViewportGrid.defaultProps = {\n viewportData: [],\n numRows: 1,\n numColumns: 1,\n layout: {\n viewports: [{}],\n },\n activeViewportIndex: 0,\n supportsDrop: true,\n availablePlugins: {\n DefaultViewport,\n },\n defaultPlugin: 'defaultViewportPlugin',\n};\n\n/**\n *\n *\n * @param {*} plugin\n * @param {*} viewportData\n * @param {*} viewportIndex\n * @param {*} children\n * @returns\n */\nfunction _getViewportComponent(\n viewportData,\n viewportIndex,\n children,\n availablePlugins,\n pluginName,\n defaultPluginName\n) {\n if (viewportData.displaySet) {\n pluginName = pluginName || defaultPluginName;\n const ViewportComponent = availablePlugins[pluginName];\n\n if (!ViewportComponent) {\n throw new Error(\n `No Viewport Component available for name ${pluginName}.\n Available plugins: ${JSON.stringify(availablePlugins)}`\n );\n }\n\n return (\n <ViewportComponent\n viewportData={viewportData}\n viewportIndex={viewportIndex}\n children={[children]}\n />\n );\n }\n\n return <EmptyViewport />;\n}\n\nexport default ViewportGrid;\n","/**\n *\n *\n * @export\n * @param {*} props\n * @returns\n */\nexport default function DefaultViewport(props) {\n return <div>{JSON.stringify(props)}</div>;\n}\n","import ViewportGrid from './ViewportGrid.js';\nimport { MODULE_TYPES } from '@ohif/core';\nimport { connect } from 'react-redux';\nimport { extensionManager } from './../../App.js';\nimport memoize from 'lodash/memoize';\n\nconst getAvailableViewportModules = memoize(viewportModules => {\n const availableViewportModules = {};\n viewportModules.forEach(moduleDefinition => {\n availableViewportModules[moduleDefinition.extensionId] =\n moduleDefinition.module;\n });\n return availableViewportModules;\n});\n\nconst mapStateToProps = state => {\n const viewportModules = extensionManager.modules[MODULE_TYPES.VIEWPORT];\n const availableViewportModules = getAvailableViewportModules(viewportModules);\n\n // TODO: Use something like state.plugins.defaultPlugin[MODULE_TYPES.VIEWPORT]\n let defaultPlugin;\n if (viewportModules.length) {\n defaultPlugin = viewportModules[0].extensionId;\n }\n\n const { numRows, numColumns, layout, activeViewportIndex } = state.viewports;\n\n return {\n numRows,\n numColumns,\n layout,\n activeViewportIndex,\n // TODO: rename `availableViewportModules`\n availablePlugins: availableViewportModules,\n // TODO: rename `defaultViewportModule`\n defaultPlugin,\n };\n};\n\nconst ConnectedViewportGrid = connect(\n mapStateToProps,\n null\n)(ViewportGrid);\n\nexport default ConnectedViewportGrid;\n","import './ViewerMain.css';\n\nimport { Component } from 'react';\nimport { ConnectedViewportGrid } from './../components/ViewportGrid/index.js';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport memoize from 'lodash/memoize';\nimport _values from 'lodash/values';\n\nvar values = memoize(_values);\n\nclass ViewerMain extends Component {\n static propTypes = {\n activeViewportIndex: PropTypes.number.isRequired,\n studies: PropTypes.array,\n viewportSpecificData: PropTypes.object.isRequired,\n layout: PropTypes.object.isRequired,\n setViewportSpecificData: PropTypes.func.isRequired,\n clearViewportSpecificData: PropTypes.func.isRequired,\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n displaySets: [],\n };\n }\n\n getDisplaySets(studies) {\n const displaySets = [];\n studies.forEach(study => {\n study.displaySets.forEach(dSet => {\n if (!dSet.plugin) {\n dSet.plugin = 'cornerstone';\n }\n displaySets.push(dSet);\n });\n });\n\n return displaySets;\n }\n\n findDisplaySet(studies, StudyInstanceUID, displaySetInstanceUID) {\n const study = studies.find(study => {\n return study.StudyInstanceUID === StudyInstanceUID;\n });\n\n if (!study) {\n return;\n }\n\n return study.displaySets.find(displaySet => {\n return displaySet.displaySetInstanceUID === displaySetInstanceUID;\n });\n }\n\n componentDidMount() {\n // Add beforeUnload event handler to check for unsaved changes\n //window.addEventListener('beforeunload', unloadHandlers.beforeUnload);\n\n // Get all the display sets for the viewer studies\n if (this.props.studies) {\n const displaySets = this.getDisplaySets(this.props.studies);\n this.setState({ displaySets }, this.fillEmptyViewportPanes);\n }\n }\n\n componentDidUpdate(prevProps) {\n const prevViewportAmount = prevProps.layout.viewports.length;\n const viewportAmount = this.props.layout.viewports.length;\n const isVtk = this.props.layout.viewports.some(vp => !!vp.vtk);\n\n if (\n this.props.studies !== prevProps.studies ||\n (viewportAmount !== prevViewportAmount && !isVtk)\n ) {\n const displaySets = this.getDisplaySets(this.props.studies);\n this.setState({ displaySets }, this.fillEmptyViewportPanes);\n }\n }\n\n fillEmptyViewportPanes = () => {\n // TODO: Here is the entry point for filling viewports on load.\n const dirtyViewportPanes = [];\n const { layout, viewportSpecificData } = this.props;\n const { displaySets } = this.state;\n\n if (!displaySets || !displaySets.length) {\n return;\n }\n\n for (let i = 0; i < layout.viewports.length; i++) {\n const viewportPane = viewportSpecificData[i];\n const isNonEmptyViewport =\n viewportPane &&\n viewportPane.StudyInstanceUID &&\n viewportPane.displaySetInstanceUID;\n\n if (isNonEmptyViewport) {\n dirtyViewportPanes.push({\n StudyInstanceUID: viewportPane.StudyInstanceUID,\n displaySetInstanceUID: viewportPane.displaySetInstanceUID,\n });\n\n continue;\n }\n\n const foundDisplaySet =\n displaySets.find(\n ds =>\n !dirtyViewportPanes.some(\n v => v.displaySetInstanceUID === ds.displaySetInstanceUID\n )\n ) || displaySets[displaySets.length - 1];\n\n dirtyViewportPanes.push(foundDisplaySet);\n }\n\n dirtyViewportPanes.forEach((vp, i) => {\n if (vp && vp.StudyInstanceUID) {\n this.setViewportData({\n viewportIndex: i,\n StudyInstanceUID: vp.StudyInstanceUID,\n displaySetInstanceUID: vp.displaySetInstanceUID,\n });\n }\n });\n };\n\n setViewportData = ({\n viewportIndex,\n StudyInstanceUID,\n displaySetInstanceUID,\n }) => {\n let displaySet = this.findDisplaySet(\n this.props.studies,\n StudyInstanceUID,\n displaySetInstanceUID\n );\n\n if (displaySet.isDerived) {\n const { Modality } = displaySet;\n displaySet = displaySet.getSourceDisplaySet(this.props.studies);\n\n if (!displaySet) {\n throw new Error(\n `Referenced series for ${Modality} dataset not present.`\n );\n }\n }\n\n this.props.setViewportSpecificData(viewportIndex, displaySet);\n };\n\n render() {\n const { viewportSpecificData } = this.props;\n const viewportData = values(viewportSpecificData);\n\n return (\n <div className=\"ViewerMain\">\n {this.state.displaySets.length && (\n <ConnectedViewportGrid\n isStudyLoaded={this.props.isStudyLoaded}\n studies={this.props.studies}\n viewportData={viewportData}\n setViewportData={this.setViewportData}\n >\n {/* Children to add to each viewport that support children */}\n </ConnectedViewportGrid>\n )}\n </div>\n );\n }\n\n componentWillUnmount() {\n // Clear the entire viewport specific data\n const { viewportSpecificData } = this.props;\n Object.keys(viewportSpecificData).forEach(viewportIndex => {\n this.props.clearViewportSpecificData(viewportIndex);\n });\n\n // TODO: These don't have to be viewer specific?\n // Could qualify for other routes?\n // hotkeys.destroy();\n\n // Remove beforeUnload event handler...\n //window.removeEventListener('beforeunload', unloadHandlers.beforeUnload);\n // Destroy the synchronizer used to update reference lines\n //OHIF.viewer.updateImageSynchronizer.destroy();\n // TODO: Instruct all plugins to clean up themselves\n //\n // Clear references to all stacks in the StackManager\n //StackManager.clearStacks();\n // @TypeSafeStudies\n // Clears OHIF.viewer.Studies collection\n //OHIF.viewer.Studies.removeAll();\n // @TypeSafeStudies\n // Clears OHIF.viewer.StudyMetadataList collection\n //OHIF.viewer.StudyMetadataList.removeAll();\n }\n}\n\nexport default ViewerMain;\n","import OHIF from '@ohif/core';\nimport ViewerMain from './ViewerMain';\nimport { connect } from 'react-redux';\n\nconst {\n setViewportSpecificData,\n clearViewportSpecificData,\n} = OHIF.redux.actions;\n\nconst mapStateToProps = state => {\n const { activeViewportIndex, layout, viewportSpecificData } = state.viewports;\n\n return {\n activeViewportIndex,\n layout,\n viewportSpecificData,\n viewports: state.viewports,\n };\n};\n\nconst mapDispatchToProps = dispatch => {\n return {\n setViewportSpecificData: (viewportIndex, data) => {\n dispatch(setViewportSpecificData(viewportIndex, data));\n },\n clearViewportSpecificData: () => {\n dispatch(clearViewportSpecificData());\n },\n };\n};\n\nconst ConnectedViewerMain = connect(\n mapStateToProps,\n mapDispatchToProps\n)(ViewerMain);\n\nexport default ConnectedViewerMain;\n","import './SidePanel.css';\n\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nconst SidePanel = ({ from, isOpen, children, width }) => {\n const fromSideClass = from === 'right' ? 'from-right' : 'from-left';\n\n const styles = width\n ? {\n maxWidth: width,\n marginRight: isOpen ? '0' : Number.parseInt(width) * -1,\n }\n : {};\n\n return (\n <section\n style={styles}\n className={classNames('sidepanel', fromSideClass, {\n 'is-open': isOpen,\n })}\n >\n {children}\n </section>\n );\n};\n\nSidePanel.propTypes = {\n from: PropTypes.string.isRequired,\n isOpen: PropTypes.bool.isRequired,\n children: PropTypes.node,\n width: PropTypes.string,\n};\n\nexport default SidePanel;\n","import React, { useState } from 'react';\nimport classnames from 'classnames';\nimport PropTypes from 'prop-types';\nimport { ErrorBoundary, Icon } from '@ohif/ui';\nimport { servicesManager } from './../../App';\n\nimport './ErrorBoundaryDialog.css';\n\nconst { UIModalService } = servicesManager.services;\n\nconst ErrorBoundaryDialog = ({ context, children }) => {\n const handleOnError = (error, componentStack) => {\n const ErrorDialog = () => {\n const [open, setOpen] = useState(false);\n\n return (\n <div className=\"ErrorFallback\" role=\"alert\">\n <div className=\"ErrorBoundaryDialog\">\n <h3 className=\"ErrorBoundaryDialogTitle\">\n {context}: <span>{error.message}</span>\n </h3>\n </div>\n <button\n className=\"btn btn-primary btn-sm ErrorBoundaryDialogButton\"\n onClick={() => setOpen(s => !s)}\n >\n <Icon\n name=\"chevron-down\"\n className={classnames('ErrorBoundaryDialogIcon', {\n opened: open,\n })}\n />\n Stack Trace\n </button>\n\n {open && <pre>{componentStack}</pre>}\n </div>\n );\n };\n\n UIModalService.show({\n content: ErrorDialog,\n title: `Something went wrong in ${context}`,\n });\n };\n\n const fallbackComponent = () => (\n <div className=\"ErrorFallback\" role=\"alert\">\n <p>\n Error rendering {context}. <br /> Check the browser console for more\n details.\n </p>\n </div>\n );\n\n return (\n <ErrorBoundary\n fallbackComponent={fallbackComponent}\n context={context}\n onError={handleOnError}\n >\n {children}\n </ErrorBoundary>\n );\n};\n\nErrorBoundaryDialog.propTypes = {\n context: PropTypes.string.isRequired,\n children: PropTypes.node.isRequired,\n};\n\nexport default ErrorBoundaryDialog;\n","import ErrorBoundaryDialog from './ErrorBoundaryDialog';\n\nexport default ErrorBoundaryDialog;\n","import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nimport OHIF, { MODULE_TYPES, DICOMSR } from '@ohif/core';\nimport { withDialog } from '@ohif/ui';\nimport moment from 'moment';\nimport ConnectedHeader from './ConnectedHeader.js';\nimport ToolbarRow from './ToolbarRow.js';\nimport ConnectedStudyBrowser from './ConnectedStudyBrowser.js';\nimport ConnectedViewerMain from './ConnectedViewerMain.js';\nimport SidePanel from './../components/SidePanel.js';\nimport ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';\nimport { extensionManager } from './../App.js';\nimport { ReconstructionIssues } from './../../../core/src/enums.js';\n\n// Contexts\nimport WhiteLabelingContext from '../context/WhiteLabelingContext.js';\nimport UserManagerContext from '../context/UserManagerContext';\nimport AppContext from '../context/AppContext';\n\nimport './Viewer.css';\nimport { finished } from 'stream';\n\nclass Viewer extends Component {\n static propTypes = {\n studies: PropTypes.arrayOf(\n PropTypes.shape({\n StudyInstanceUID: PropTypes.string.isRequired,\n StudyDate: PropTypes.string,\n PatientID: PropTypes.string,\n displaySets: PropTypes.arrayOf(\n PropTypes.shape({\n displaySetInstanceUID: PropTypes.string.isRequired,\n SeriesDescription: PropTypes.string,\n SeriesNumber: PropTypes.number,\n InstanceNumber: PropTypes.number,\n numImageFrames: PropTypes.number,\n Modality: PropTypes.string.isRequired,\n images: PropTypes.arrayOf(\n PropTypes.shape({\n getImageId: PropTypes.func.isRequired,\n })\n ),\n })\n ),\n })\n ),\n studyInstanceUIDs: PropTypes.array,\n activeServer: PropTypes.shape({\n type: PropTypes.string,\n wadoRoot: PropTypes.string,\n }),\n onTimepointsUpdated: PropTypes.func,\n onMeasurementsUpdated: PropTypes.func,\n // window.store.getState().viewports.viewportSpecificData\n viewports: PropTypes.object.isRequired,\n // window.store.getState().viewports.activeViewportIndex\n activeViewportIndex: PropTypes.number.isRequired,\n isStudyLoaded: PropTypes.bool,\n dialog: PropTypes.object,\n };\n\n constructor(props) {\n super(props);\n\n const { activeServer } = this.props;\n const server = Object.assign({}, activeServer);\n\n OHIF.measurements.MeasurementApi.setConfiguration({\n dataExchange: {\n retrieve: DICOMSR.retrieveMeasurements,\n store: DICOMSR.storeMeasurements,\n },\n server,\n });\n\n OHIF.measurements.TimepointApi.setConfiguration({\n dataExchange: {\n retrieve: this.retrieveTimepoints,\n store: this.storeTimepoints,\n remove: this.removeTimepoint,\n update: this.updateTimepoint,\n disassociate: this.disassociateStudy,\n },\n });\n\n this._getActiveViewport = this._getActiveViewport.bind(this);\n }\n\n state = {\n isLeftSidePanelOpen: true,\n isRightSidePanelOpen: false,\n selectedRightSidePanel: '',\n selectedLeftSidePanel: 'studies', // TODO: Don't hardcode this\n thumbnails: [],\n };\n\n componentWillUnmount() {\n if (this.props.dialog) {\n this.props.dialog.dismissAll();\n }\n }\n\n retrieveTimepoints = filter => {\n OHIF.log.info('retrieveTimepoints');\n\n // Get the earliest and latest study date\n let earliestDate = new Date().toISOString();\n let latestDate = new Date().toISOString();\n if (this.props.studies) {\n latestDate = new Date('1000-01-01').toISOString();\n this.props.studies.forEach(study => {\n const StudyDate = moment(study.StudyDate, 'YYYYMMDD').toISOString();\n if (StudyDate < earliestDate) {\n earliestDate = StudyDate;\n }\n if (StudyDate > latestDate) {\n latestDate = StudyDate;\n }\n });\n }\n\n // Return a generic timepoint\n return Promise.resolve([\n {\n timepointType: 'baseline',\n timepointId: 'TimepointId',\n studyInstanceUIDs: this.props.studyInstanceUIDs,\n PatientID: filter.PatientID,\n earliestDate,\n latestDate,\n isLocked: false,\n },\n ]);\n };\n\n storeTimepoints = timepointData => {\n OHIF.log.info('storeTimepoints');\n return Promise.resolve();\n };\n\n updateTimepoint = (timepointData, query) => {\n OHIF.log.info('updateTimepoint');\n return Promise.resolve();\n };\n\n removeTimepoint = timepointId => {\n OHIF.log.info('removeTimepoint');\n return Promise.resolve();\n };\n\n disassociateStudy = (timepointIds, StudyInstanceUID) => {\n OHIF.log.info('disassociateStudy');\n return Promise.resolve();\n };\n\n onTimepointsUpdated = timepoints => {\n if (this.props.onTimepointsUpdated) {\n this.props.onTimepointsUpdated(timepoints);\n }\n };\n\n onMeasurementsUpdated = measurements => {\n if (this.props.onMeasurementsUpdated) {\n this.props.onMeasurementsUpdated(measurements);\n }\n };\n\n componentDidMount() {\n const { studies, isStudyLoaded } = this.props;\n const { TimepointApi, MeasurementApi } = OHIF.measurements;\n const currentTimepointId = 'TimepointId';\n\n const timepointApi = new TimepointApi(currentTimepointId, {\n onTimepointsUpdated: this.onTimepointsUpdated,\n });\n\n const measurementApi = new MeasurementApi(timepointApi, {\n onMeasurementsUpdated: this.onMeasurementsUpdated,\n });\n\n this.currentTimepointId = currentTimepointId;\n this.timepointApi = timepointApi;\n this.measurementApi = measurementApi;\n\n if (studies) {\n const PatientID = studies[0] && studies[0].PatientID;\n\n timepointApi.retrieveTimepoints({ PatientID });\n if (isStudyLoaded) {\n this.measurementApi.retrieveMeasurements(PatientID, [\n currentTimepointId,\n ]);\n }\n\n this.setState({\n thumbnails: _mapStudiesToThumbnails(studies),\n });\n }\n }\n\n componentDidUpdate(prevProps) {\n const { studies, isStudyLoaded } = this.props;\n\n if (studies !== prevProps.studies) {\n this.setState({\n thumbnails: _mapStudiesToThumbnails(studies),\n });\n }\n if (isStudyLoaded && isStudyLoaded !== prevProps.isStudyLoaded) {\n const PatientID = studies[0] && studies[0].PatientID;\n const { currentTimepointId } = this;\n\n this.timepointApi.retrieveTimepoints({ PatientID });\n this.measurementApi.retrieveMeasurements(PatientID, [currentTimepointId]);\n }\n }\n\n _getActiveViewport() {\n return this.props.viewports[this.props.activeViewportIndex];\n }\n\n render() {\n let VisiblePanelLeft, VisiblePanelRight;\n const panelExtensions = extensionManager.modules[MODULE_TYPES.PANEL];\n\n panelExtensions.forEach(panelExt => {\n panelExt.module.components.forEach(comp => {\n if (comp.id === this.state.selectedRightSidePanel) {\n VisiblePanelRight = comp.component;\n } else if (comp.id === this.state.selectedLeftSidePanel) {\n VisiblePanelLeft = comp.component;\n }\n });\n });\n\n return (\n <>\n {/* HEADER */}\n <WhiteLabelingContext.Consumer>\n {whiteLabeling => (\n <UserManagerContext.Consumer>\n {userManager => (\n <AppContext.Consumer>\n {appContext => (\n <ConnectedHeader\n linkText={\n appContext.appConfig.showStudyList\n ? 'Study List'\n : undefined\n }\n linkPath={\n appContext.appConfig.showStudyList ? '/' : undefined\n }\n userManager={userManager}\n >\n {whiteLabeling &&\n whiteLabeling.createLogoComponentFn &&\n whiteLabeling.createLogoComponentFn(React)}\n </ConnectedHeader>\n )}\n </AppContext.Consumer>\n )}\n </UserManagerContext.Consumer>\n )}\n </WhiteLabelingContext.Consumer>\n\n {/* TOOLBAR */}\n <ErrorBoundaryDialog context=\"ToolbarRow\">\n <ToolbarRow\n activeViewport={\n this.props.viewports[this.props.activeViewportIndex]\n }\n isDerivedDisplaySetsLoaded={this.props.isDerivedDisplaySetsLoaded}\n isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}\n isRightSidePanelOpen={this.state.isRightSidePanelOpen}\n selectedLeftSidePanel={\n this.state.isLeftSidePanelOpen\n ? this.state.selectedLeftSidePanel\n : ''\n }\n selectedRightSidePanel={\n this.state.isRightSidePanelOpen\n ? this.state.selectedRightSidePanel\n : ''\n }\n handleSidePanelChange={(side, selectedPanel) => {\n const sideClicked = side && side[0].toUpperCase() + side.slice(1);\n const openKey = `is${sideClicked}SidePanelOpen`;\n const selectedKey = `selected${sideClicked}SidePanel`;\n const updatedState = Object.assign({}, this.state);\n\n const isOpen = updatedState[openKey];\n const prevSelectedPanel = updatedState[selectedKey];\n // RoundedButtonGroup returns `null` if selected button is clicked\n const isSameSelectedPanel =\n prevSelectedPanel === selectedPanel || selectedPanel === null;\n\n updatedState[selectedKey] = selectedPanel || prevSelectedPanel;\n\n const isClosedOrShouldClose = !isOpen || isSameSelectedPanel;\n if (isClosedOrShouldClose) {\n updatedState[openKey] = !updatedState[openKey];\n }\n\n this.setState(updatedState);\n }}\n studies={this.props.studies}\n />\n </ErrorBoundaryDialog>\n\n {/*<ConnectedStudyLoadingMonitor studies={this.props.studies} />*/}\n {/*<StudyPrefetcher studies={this.props.studies} />*/}\n\n {/* VIEWPORTS + SIDEPANELS */}\n <div className=\"FlexboxLayout\">\n {/* LEFT */}\n <ErrorBoundaryDialog context=\"LeftSidePanel\">\n <SidePanel from=\"left\" isOpen={this.state.isLeftSidePanelOpen}>\n {VisiblePanelLeft ? (\n <VisiblePanelLeft\n viewports={this.props.viewports}\n studies={this.props.studies}\n activeIndex={this.props.activeViewportIndex}\n />\n ) : (\n <ConnectedStudyBrowser\n studies={this.state.thumbnails}\n studyMetadata={this.props.studies}\n />\n )}\n </SidePanel>\n </ErrorBoundaryDialog>\n\n {/* MAIN */}\n <div className={classNames('main-content')}>\n <ErrorBoundaryDialog context=\"ViewerMain\">\n <ConnectedViewerMain\n studies={this.props.studies}\n isStudyLoaded={this.props.isStudyLoaded}\n />\n </ErrorBoundaryDialog>\n </div>\n\n {/* RIGHT */}\n <ErrorBoundaryDialog context=\"RightSidePanel\">\n <SidePanel from=\"right\" isOpen={this.state.isRightSidePanelOpen}>\n {VisiblePanelRight && (\n <VisiblePanelRight\n isOpen={this.state.isRightSidePanelOpen}\n viewports={this.props.viewports}\n studies={this.props.studies}\n activeIndex={this.props.activeViewportIndex}\n activeViewport={\n this.props.viewports[this.props.activeViewportIndex]\n }\n getActiveViewport={this._getActiveViewport}\n />\n )}\n </SidePanel>\n </ErrorBoundaryDialog>\n </div>\n </>\n );\n }\n}\n\nexport default withDialog(Viewer);\n\n/**\n * Async function to check if there are any inconsistences in the series\n * (i.e. reconstructable to a 3D volume). If not reconstructable MPR is disabled.\n * The actual computations are done in isDisplaySetReconstructable.\n *\n * 1) Is series multiframe?\n * 2) Do the frames have different dimensions/numer of components/orientations?\n * 3) Has the series any missing frames or irregular spacing?\n * 4) Is the series 4D?\n *\n * @param {*object} displaySet\n * @returns {[string]} an array of strings containing the warnings\n */\nconst _checkForSeriesInconsistencesWarnings = async function (displaySet) {\n // NOTE: at the moment this function is async even if it does not perfom any heavy calculation.\n // We may add or move here some of the computations\n // done when creating the displaySet (see makeDisplaySet and isDisplaySetReconstructable).\n // the thumbnail footnotes warning react element is already set up to handle a promise.\n const warningsList = [];\n if (displaySet.warningIssues && displaySet.warningIssues.length !== 0) {\n displaySet.warningIssues.forEach(warning => {\n switch (warning) {\n case ReconstructionIssues.DATASET_4D:\n warningsList.push(\"The dataset is 4D.\");\n break;\n case ReconstructionIssues.VARYING_IMAGESDIMENSIONS:\n warningsList.push(\"The dataset frames have different dimensions (rows, columns).\");\n break;\n case ReconstructionIssues.VARYING_IMAGESCOMPONENTS:\n warningsList.push(\"The dataset frames have different components (Sample per pixel).\");\n break;\n case ReconstructionIssues.VARYING_IMAGESORIENTATION:\n warningsList.push(\"The dataset frames have different orientation.\");\n break;\n case ReconstructionIssues.IRREGULAR_SPACING:\n warningsList.push(\"The dataset frames have different pixel spacing.\");\n break;\n case ReconstructionIssues.MULTIFFRAMES:\n warningsList.push(\"The dataset is a multiframes.\");\n break;\n default:\n break;\n }\n });\n warningsList.push('The datasets is not a reconstructable 3D volume. MPR mode is not available.');\n }\n\n if (displaySet.missingFrames &&\n (!displaySet.warningIssues ||\n (displaySet.warningIssues && !displaySet.warningIssues.find(warn => warn === ReconstructionIssues.DATASET_4D)))) {\n warningsList.push('The datasets is missing frames: ' + displaySet.missingFrames + '.');\n }\n\n return warningsList\n}\n\n/**\n * What types are these? Why do we have \"mapping\" dropped in here instead of in\n * a mapping layer?\n *\n * TODO[react]:\n * - Add showStackLoadingProgressBar option\n *\n * @param {Study[]} studies\n * @param {DisplaySet[]} studies[].displaySets\n */\nconst _mapStudiesToThumbnails = function(studies) {\n return studies.map(study => {\n const { StudyInstanceUID } = study;\n\n const thumbnails = study.displaySets.map(displaySet => {\n const {\n displaySetInstanceUID,\n SeriesDescription,\n InstanceNumber,\n numImageFrames,\n SeriesNumber,\n } = displaySet;\n\n let imageId;\n let altImageText;\n\n if (displaySet.Modality && displaySet.Modality === 'SEG') {\n // TODO: We want to replace this with a thumbnail showing\n // the segmentation map on the image, but this is easier\n // and better than what we have right now.\n altImageText = 'SEG';\n } else if (displaySet.images && displaySet.images.length) {\n const imageIndex = Math.floor(displaySet.images.length / 2);\n\n imageId = displaySet.images[imageIndex].getImageId();\n } else {\n altImageText = displaySet.Modality ? displaySet.Modality : 'UN';\n }\n\n const hasWarnings = _checkForSeriesInconsistencesWarnings(displaySet)\n\n return {\n imageId,\n altImageText,\n displaySetInstanceUID,\n SeriesDescription,\n InstanceNumber,\n numImageFrames,\n SeriesNumber,\n hasWarnings,\n };\n });\n\n return {\n StudyInstanceUID,\n thumbnails,\n };\n });\n};\n","import { connect } from 'react-redux';\nimport Viewer from './Viewer.js';\nimport OHIF from '@ohif/core';\n\nconst { setTimepoints, setMeasurements } = OHIF.redux.actions;\n\nconst getActiveServer = servers => {\n const isActive = a => a.active === true;\n return servers.servers.find(isActive);\n};\n\nconst mapStateToProps = state => {\n const { viewports, servers } = state;\n return {\n viewports: viewports.viewportSpecificData,\n activeViewportIndex: viewports.activeViewportIndex,\n activeServer: getActiveServer(servers),\n };\n};\n\nconst mapDispatchToProps = dispatch => {\n return {\n onTimepointsUpdated: timepoints => {\n dispatch(setTimepoints(timepoints));\n },\n onMeasurementsUpdated: measurements => {\n dispatch(setMeasurements(measurements));\n },\n };\n};\n\nconst ConnectedViewer = connect(\n mapStateToProps,\n mapDispatchToProps\n)(Viewer);\n\nexport default ConnectedViewer;\n","export default class FileLoader {\n fileType;\n loadFile(file, imageId) { }\n getDataset(image, imageId) { }\n getStudies(dataset, imageId) { }\n}\n","import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';\nimport FileLoader from './fileLoader';\n\nconst PDFFileLoader = new (class extends FileLoader {\n fileType = 'application/pdf';\n loadFile(file, imageId) {\n return cornerstoneWADOImageLoader.wadouri.loadFileRequest(imageId);\n }\n\n getDataset(image, imageId) {\n const dataset = {};\n dataset.imageId = image.imageId || imageId;\n return dataset;\n }\n\n getStudies(dataset, imageId) {\n return this.getDefaultStudy(imageId);\n }\n\n getDefaultStudy(imageId) {\n const study = {\n StudyInstanceUID: '',\n StudyDate: '',\n StudyTime: '',\n AccessionNumber: '',\n ReferringPhysicianName: '',\n PatientName: '',\n PatientID: '',\n PatientBirthdate: '',\n PatientSex: '',\n StudyId: '',\n StudyDescription: '',\n series: [\n {\n SeriesInstanceUID: '',\n SeriesDescription: '',\n SeriesNumber: '',\n instances: [\n {\n metadata: {\n SOPInstanceUID: '',\n SOPClassUID: '1.2.840.10008.5.1.4.1.1.104.1',\n Rows: '',\n Columns: '',\n NumberOfFrames: 0,\n InstanceNumber: 1,\n },\n getImageId: () => imageId,\n isLocalFile: true,\n },\n ],\n },\n ],\n };\n\n return study;\n }\n})();\n\nexport default PDFFileLoader;\n","import dcmjs from 'dcmjs';\nimport cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';\nimport FileLoader from './fileLoader';\nimport OHIF from '@ohif/core';\n\nconst metadataProvider = OHIF.cornerstone.metadataProvider;\n\nconst DICOMFileLoader = new (class extends FileLoader {\n fileType = 'application/dicom';\n loadFile(file, imageId) {\n return cornerstoneWADOImageLoader.wadouri.loadFileRequest(imageId);\n }\n\n getDataset(image, imageId) {\n let dataset = {};\n try {\n const dicomData = dcmjs.data.DicomMessage.readFile(image);\n\n dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(\n dicomData.dict\n );\n\n metadataProvider.addInstance(dataset);\n\n dataset._meta = dcmjs.data.DicomMetaDictionary.namifyDataset(\n dicomData.meta\n );\n } catch (e) {\n console.error('Error reading dicom file', e);\n }\n // Set imageId on dataset to be consumed later on\n dataset.imageId = imageId;\n\n return dataset;\n }\n\n getStudies(dataset, imageId) {\n return this.getStudyFromDataset(dataset);\n }\n\n getStudyFromDataset(dataset = {}) {\n const {\n StudyInstanceUID,\n StudyDate,\n StudyTime,\n AccessionNumber,\n ReferringPhysicianName,\n PatientName,\n PatientID,\n PatientBirthDate,\n PatientSex,\n StudyID,\n StudyDescription,\n SeriesInstanceUID,\n SeriesDescription,\n SeriesNumber,\n imageId,\n } = dataset;\n\n const instance = {\n metadata: dataset,\n url: imageId,\n };\n\n const series = {\n SeriesInstanceUID: SeriesInstanceUID,\n SeriesDescription: SeriesDescription,\n SeriesNumber: SeriesNumber,\n instances: [instance],\n };\n\n const study = {\n StudyInstanceUID,\n StudyDate,\n StudyTime,\n AccessionNumber,\n ReferringPhysicianName,\n PatientName,\n PatientID,\n PatientBirthDate,\n PatientSex,\n StudyID,\n StudyDescription,\n /*\n TODO: in case necessary to uncomment this block, double check every property\n numberOfStudyRelatedSeries: NumberOfStudyRelatedSeries || DICOMWeb.getString(dataset['00201206']),\n numberOfStudyRelatedInstances: NumberOfStudyRelatedInstances || DICOMWeb.getString(dataset['00201208']),\n Modality: Modality || DICOMWeb.getString(dataset['00080060']),\n ModalitiesInStudy: ModalitiesInStudy || DICOMWeb.getString(dataset['00080061']),\n modalities:\n */\n series: [series],\n };\n\n return study;\n }\n})();\n\nexport default DICOMFileLoader;\n","import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';\nimport FileLoader from './fileLoader';\nimport PDFFileLoader from './pdfFileLoader';\nimport DICOMFileLoader from './dicomFileLoader';\n\nclass FileLoaderService extends FileLoader {\n fileType;\n loader;\n constructor(file) {\n super();\n const fileType = file && file.type;\n this.loader = this.getLoader(fileType);\n this.fileType = this.loader.fileType;\n }\n\n static groupSeries(studies) {\n const groupBy = (list, groupByKey, listKey) => {\n let nonKeyCounter = 1;\n\n return list.reduce((acc, obj) => {\n let key = obj[groupByKey];\n const list = obj[listKey];\n\n // in case key not found, group it using counter\n key = !!key ? key : '' + nonKeyCounter++;\n\n if (!acc[key]) {\n acc[key] = { ...obj };\n acc[key][listKey] = [];\n }\n\n acc[key][listKey].push(...list);\n\n return acc;\n }, {});\n };\n\n const studiesGrouped = Object.values(\n groupBy(studies, 'StudyInstanceUID', 'series')\n );\n\n const result = studiesGrouped.map(studyGroup => {\n const seriesGrouped = groupBy(\n studyGroup.series,\n 'SeriesInstanceUID',\n 'instances'\n );\n studyGroup.series = Object.values(seriesGrouped);\n\n return studyGroup;\n });\n\n return result;\n }\n\n addFile(file) {\n return cornerstoneWADOImageLoader.wadouri.fileManager.add(file);\n }\n\n loadFile(file, imageId) {\n return this.loader.loadFile(file, imageId);\n }\n\n getDataset(image, imageId) {\n return this.loader.getDataset(image, imageId);\n }\n\n getStudies(dataset, imageId) {\n return this.loader.getStudies(dataset, imageId);\n }\n\n getLoader(fileType) {\n if (fileType === 'application/pdf') {\n return PDFFileLoader;\n } else {\n // Default to dicom loader\n return DICOMFileLoader;\n }\n }\n}\n\nexport default FileLoaderService;\n","import FileLoaderService from './localFileLoaders/fileLoaderService';\n\nconst processFile = async file => {\n try {\n const fileLoaderService = new FileLoaderService(file);\n const imageId = fileLoaderService.addFile(file);\n const image = await fileLoaderService.loadFile(file, imageId);\n const dataset = await fileLoaderService.getDataset(image, imageId);\n const studies = await fileLoaderService.getStudies(dataset, imageId);\n\n return studies;\n } catch (error) {\n console.log(\n error.name,\n ':Error when trying to load and process local files:',\n error.message\n );\n }\n};\n\nexport default async function filesToStudies(files) {\n const processFilesPromises = files.map(processFile);\n const studies = await Promise.all(processFilesPromises);\n\n return FileLoaderService.groupSeries(studies.flat());\n}\n","import React, { Component } from 'react';\nimport { metadata, utils } from '@ohif/core';\n\nimport ConnectedViewer from './ConnectedViewer.js';\nimport PropTypes from 'prop-types';\nimport { extensionManager } from './../App.js';\nimport Dropzone from 'react-dropzone';\nimport filesToStudies from '../lib/filesToStudies';\nimport './ViewerLocalFileData.css';\nimport { withTranslation } from 'react-i18next';\n\nconst { OHIFStudyMetadata } = metadata;\nconst { studyMetadataManager } = utils;\n\nconst dropZoneLinkDialog = (onDrop, i18n, dir) => {\n return (\n <Dropzone onDrop={onDrop} noDrag>\n {({ getRootProps, getInputProps }) => (\n <span {...getRootProps()} className=\"link-dialog\">\n {dir ? (\n <span>\n {i18n('Load folders')}\n <input\n {...getInputProps()}\n webkitdirectory=\"true\"\n mozdirectory=\"true\"\n />\n </span>\n ) : (\n <span>\n {i18n('Load files')}\n <input {...getInputProps()} />\n </span>\n )}\n </span>\n )}\n </Dropzone>\n );\n};\n\nconst linksDialogMessage = (onDrop, i18n) => {\n return (\n <>\n {i18n('Or click to ')}\n {dropZoneLinkDialog(onDrop, i18n)}\n {i18n(' or ')}\n {dropZoneLinkDialog(onDrop, i18n, true)}\n {i18n(' from dialog')}\n </>\n );\n};\n\nclass ViewerLocalFileData extends Component {\n static propTypes = {\n studies: PropTypes.array,\n };\n\n state = {\n studies: null,\n loading: false,\n error: null,\n };\n\n updateStudies = studies => {\n // Render the viewer when the data is ready\n studyMetadataManager.purge();\n\n // Map studies to new format, update metadata manager?\n const updatedStudies = studies.map(study => {\n const studyMetadata = new OHIFStudyMetadata(\n study,\n study.StudyInstanceUID\n );\n const sopClassHandlerModules =\n extensionManager.modules['sopClassHandlerModule'];\n\n study.displaySets =\n study.displaySets ||\n studyMetadata.createDisplaySets(sopClassHandlerModules);\n\n studyMetadata.forEachDisplaySet(displayset => {\n displayset.localFile = true;\n });\n\n studyMetadataManager.add(studyMetadata);\n\n return study;\n });\n\n this.setState({\n studies: updatedStudies,\n });\n };\n\n render() {\n const onDrop = async acceptedFiles => {\n this.setState({ loading: true });\n\n const studies = await filesToStudies(acceptedFiles);\n const updatedStudies = this.updateStudies(studies);\n\n if (!updatedStudies) {\n return;\n }\n\n this.setState({ studies: updatedStudies, loading: false });\n };\n\n if (this.state.error) {\n return <div>Error: {JSON.stringify(this.state.error)}</div>;\n }\n\n return (\n <Dropzone onDrop={onDrop} noClick>\n {({ getRootProps, getInputProps }) => (\n <div {...getRootProps()} style={{ width: '100%', height: '100%' }}>\n {this.state.studies ? (\n <ConnectedViewer\n studies={this.state.studies}\n studyInstanceUIDs={\n this.state.studies &&\n this.state.studies.map(a => a.StudyInstanceUID)\n }\n />\n ) : (\n <div className={'drag-drop-instructions'}>\n <div className={'drag-drop-contents'}>\n {this.state.loading ? (\n <h3>{this.props.t('Loading...')}</h3>\n ) : (\n <>\n <h3>\n {this.props.t(\n 'Drag and Drop DICOM files here to load them in the Viewer'\n )}\n </h3>\n <h4>{linksDialogMessage(onDrop, this.props.t)}</h4>\n </>\n )}\n </div>\n </div>\n )}\n </div>\n )}\n </Dropzone>\n );\n }\n}\n\nexport default withTranslation('Common')(ViewerLocalFileData);\n"],"sourceRoot":""}