{"version":3,"sources":["images/logo.png","api/bookFS.js","api/config.js","utilities/pWaCompatUtil.js","constants/constants.js","utilities/themeProvider.ts","images/dibs-logo.png","actions/actionTypes.js","actions/ajaxStatusActions.js","components/common/Loading.jsx","constants/viewerModes.js","api/userAPI.js","vendor/utils-router.js","actions/userActions.js","actions/commonActions.js","App.jsx","constants/styledComponents.js","components/common/UtilValidation.js","components/auth/LoginForm.jsx","components/auth/RegisterForm.js","components/bookview/EpubStyles.ts","components/bookview/EpubAudio.jsx","components/bookview/events.js","utilities/TextToSpeechUtility.tsx","api/bookAPI.js","reducers/initialState.js","actions/bookActions.js","actions/bookViewActions.js","components/bookview/EpubView.tsx","api/blmAPI.js","actions/blmActions.js","actions/bookToolbarActions.js","components/common/CommonModal.jsx","components/bookview/audioPlayer.jsx","models-enums.tsx","actions/audioPlayerActions.js","images/icon_hl_teal.png","images/icon_pen.png","components/bookview/Drawer.jsx","components/header/Header.jsx","images/book.png","images/graphic_organizers.png","components/header/HeaderContainer.js","actions/projectToolbar/projectToolbarActions.js","components/blm/FabricUI.jsx","images/icon_eraser.png","images/icon_pointer.png","components/blm/ProjectToolbar.jsx","images/t.png","images/marker-orange.png","images/marker-black.png","images/marker-blue.png","components/blm/BLM.jsx","components/bookview/NotePopover.jsx","images/student_note_icon.png","images/teacher_note_icon.png","images/class_note_icon.png","images/group_note_icon.png","components/bookview/BookPage.jsx","components/bookview/Pages.jsx","images/icon_arrowleft.png","images/icon_arrowright.png","images/move_icon.png","components/bookview/Toolbar.tsx","images/icon_hl_yellow.png","images/icon_hl_green.png","images/icon_hl_orange.png","utilities/MarkupMergerUtility.jsx","components/bookview/BookView.jsx","components/common/UserProfileForm.jsx","actions/dashboard/dashboardActions.js","components/bookbag/ClassCodeModal.tsx","components/bookbag/BookBagHeader.jsx","images/read.png","images/unread.png","actions/bookbagFiltersActions.js","images/NandF_Square.png","components/bookbag/AdvancedSearchModal.jsx","components/bookbag/BookBagSearch.tsx","images/backpack.png","images/bookshelf.png","images/SocialStudies_Square.png","images/Science_Square.png","images/Math_Square.png","images/Language_Square.png","images/Fiction_Square.png","images/Nonfiction_Square.png","components/bookbag/BookBagSearchContainer.tsx","components/bookbag/BookBag.jsx","images/default.jpg","images/downloaded.png","components/blm/BLMView.jsx","components/auth/Token.jsx","actions/modeActions.js","routes.jsx","store/localStorage.js","api/logger.js","reducers/bookReducer.js","reducers/ajaxStatusReducer.js","reducers/index.ts","reducers/userReducer.js","reducers/blmReducer.js","reducers/modeReducer.js","reducers/bookbagFiltersReducer.js","reducers/dashboardReducer.js","reducers/projectToolbarReducer.js","reducers/bookViewReducer.js","reducers/bookToolbarReducer.js","reducers/readiumReducer.js","store/migrations.ts","store/configureStore.js","serviceWorkerRegistration.js","reportWebVitals.js","actions/readiumActions.js","index.js","utilities/NetworkListener.js"],"names":["BookFS","console","log","fs","clear","isbn","iterate","value","key","index","search","removeItem","then","directory","keys","find","catch","error","IsEPub","testFileLocation","getItem","result","err","zippedBook","basePath","filePromises","forEach","relativePath","file","pathArr","split","pathFileName","pop","pathDirName","length","join","saveProm","async","update","content","setItem","push","Promise","all","zippedSpeech","fileEntry","reject","text","item","window","URL","createObjectURL","localForage","createInstance","name","config","Version","Debug","Environment","API","Main","Storage","Admin","Coralogix","subsystemName","google","clientID","UserRoleIDs","Teacher","SuperAdmin","SchoolAdmin","SalesRep","Student","Generic","Demo","typeGUID","math","languageArts","science","socialStudies","pWaCompatUtil","XMLHttpRequest","prototype","navigator","standalone","manifestEl","internalStorage","debug","capableDisplayModes","userAgent","isSafariMobile","vendor","indexOf","isIEOrEdge","Boolean","match","isEdgePWA","Windows","sessionStorage","e","document","readyState","setup","addEventListener","getElementInHead","selector","head","querySelector","store","k","v","undefined","manifestHref","href","hrefFactory","options","i","opt","part","toString","buildHrefFactory","location","storedResponse","process","JSON","parse","warn","xhr","open","withCredentials","getAttribute","onload","data","responseText","send","localName","attr","check","node","createElement","setAttribute","appendChild","meta","normalizeIcon","icon","parsedSizes","sizes","map","size","Infinity","parseInt","src","type","largestSize","Math","max","apply","purpose","manifest","urlFactory","allIcons","sort","a","b","icons","filter","maskable","appleTouchIcons","querySuffix","metaViewport","viewport","viewportFitCover","display","isCapable","color","themeIsLight","shouldUseLightForeground","t","UI","ViewManagement","ApplicationView","getForCurrentView","titleBar","getEdgeTitleBar","foregroundColor","backgroundColor","readColor","colorToWindowsRGBA","updateThemeColorRender","largest","orientation","String","substr","backgroundIsLight","itunes","related","app","findAppleId","splashFor","width","height","ratio","devicePixelRatio","ctx","contextForCanvas","scale","fillStyle","fillRect","translate","iconWidth","iconHeight","drawImage","font","s","getComputedStyle","getPropertyValue","title","measure","measureText","textHeight","actualBoundingBoxAscent","fillText","words","cand","slice","measureWidth","splice","canvas","toDataURL","appendSplash","generatedSplash","rendered","prev","change","renderBothSplash","applicationIcon","done","screen","portrait","landscape","setTimeout","saveUpdate","stringify","fetchIconAndBuildSplash","shift","img","Image","crossOrigin","onerror","redrawn","updateTransparent","left","redrawRemainingIcons","c","getImageData","f","pow","lum","abs","image","background","force","context","imageData","globalCompositeOperation","getContext","constants","themeProvider","activeTheme","themesById","initTheme","persistedActiveTheme","setTheme","selectThemeBySubdomain","themes","subdomain","Object","normalizeTheme","theme","defaultTheme","this","logo","logoSrc","brainhiveLogo","warningButtonStyle","warningBackground","warningDark","warningFontColor","primaryButtonStyle","primaryBackground","primaryDark","primaryFontColor","secondaryButtonStyle","secondaryBackground","secondaryDark","secondaryFontColor","successButtonStyle","successBackground","successDark","successFontColor","primaryIconOnlyButtonStyle","manifestPlaceholder","manifestUrl","checkUpdatedThemes","request","Request","method","fetch","response","status","json","res","reduce","Name","camelCaseKeys","rawKey","camelCase","toastrSuccessOptions","position","transitionIn","transitionOut","timeOut","toastrErrorOptions","toastrWarningOptions","testSpeechMarkRaw","bookZoomLevels","audioHighlightLeadTime","audioDelayBetweenPages","audioResyncTime","topToolbarToggleHeight","bottomToolbarHeight","forceLogoutTime","forceLogoutTimeWarning","BEGIN_AJAX_CALL","END_AJAX_CALL","USER_LOGIN_SUCCESS","USER_LOGOUT_SUCCESS","USER_UPDATE_SUCCESS","USER_UPDATE_FAILED","USER_UPDATE_PASSWORD_SUCCESS","TOGGLE_CLASS_CODE_MODAL","LOAD_BOOKS_SUCCESS","LOAD_BOOKS_FAILED","DASHBOARD_PAGE_RESULTS","FETCH_BOOK_SUCCESS","FETCH_BOOK_FAILED","LOAD_BOOK_SUCCESS","FETCH_BOOKITEMS_SUCCESS","FETCH_BOOKITEMS_FAILED","FETCH_BOOKITEMS_STUDENT_SUCCESS","SAVE_BOOKITEM_BOOKMARK_SUCCESS","SAVE_BOOKITEM_HIGHLIGHT_SUCCESS","SAVE_BOOKITEM_NOTE_SUCCESS","UPDATE_STUDENT_ITEM_SUCCESS","UPDATE_TEMPLATE_ITEM_SUCCESS","DELETE_BOOKITEM_BOOKMARK_SUCCESS","DELETE_BOOKITEM_HIGHLIGHT_SUCCESS","DELETE_BOOKITEM_NOTE_SUCCESS","UPDATE_BOOKSTATUS_SUCCESS","DOWNLOADED_BOOK_SUCCESS","DOWNLOADED_BOOK_FAILED","DELETE_DOWNLOADED_BOOK","DOWNLOADED_SPEECH_FAILED","GET_SPEECH_MARKS","RESET_BOOK","SET_BOOK_READY","SET_PROJECT_READY","CACHE_BOOK_PAGE","RESET_CACHED_BOOK_PAGES","FETCH_BLM_SUCCESS","FETCH_BLM_FAILED","SAVE_BLMITEM_FABRIC_SUCCESS","SAVE_BLMITEM_FABRIC_FAILED","REMOVE_BLM_DATA_SUCCESS","GET_BLM_ITEMS_SUCCESS","GET_BLM_ITEMS_FAILED","LOAD_BLMS_SUCCESS","UPDATE_BLM_STATUS_SUCCESS","UPDATE_MODE_SUCCESS","BOOK_TOOLBAR_UPDATE_MODE","GET_COMPLETED_BLMS_SUCCESS","GET_BLM_STATUS_SUCCESS","GET_TEACHERS_BLM_COMMENT_SUCCESS","SAVE_TEACHERS_COMMENT_SUCCESS","SAVE_ADVANCED_SEARCH_FILTERS","CLEAR_ADVANCED_SEARCH_FILTERS","ADD_BOOK_TO_BOOKBAG_SUCCESS","REMOVE_BOOK_TO_BOOKBAG_SUCCESS","PURGE_TEMP_ID_NOTES","UPDATE_CURRENT_PAGE","TOGGLE_USER_PROFILE_MODAL","TOGGLE_LOGGOUT_CONFIRM_MODAL","TOOLBAR_ERASER_ON","TOOLBAR_DRAWING_MODE_ON","TOOLBAR_POINTER_ON","TOOLBAR_ADD_TEXT_ON","SHOW_RICH_TEXT_BUTTONS","NEXT_PAGE","PREV_PAGE","TOTAL_PAGE","UPDATE_LEFT_PAGE_CONTAINER","UPDATE_BOOK_SCALE_PERCENT","UPDATE_PROJECT_SCALE_PERCENT","UPDATE_PAGES_VISIBLE","AUTOMATIC_UPDATE_PAGES_VISIBLE","RESET_VIEW","BOOK_TOOLBAR_POINTING","BOOK_TOOLBAR_NOTES","BOOK_TOOLBAR_HIGHLIGHTING","BOOK_TOOLBAR_ERASING","BOOK_TOOLBAR_UNDERLINING","BOOK_TOOLBAR_STRIKING","BOOK_TOOLBAR_MOVING","SET_ACTIVE_NOTE","INCREASE_BOOK_ZOOM","DECREASE_BOOK_ZOOM","UPDATE_PENDING_ITEM","READIUM_INITIALIZED","beginAjaxCall","types","manualAjaxStart","dispatch","manualAjaxEnd","Loading","Modal","show","props","className","Body","style","message","React","viewerModes","UserAPI","loginID","password","schoolID","body","headers","getHeaders","credentials","jsonData","token","authorizationCode","googleAuthorizationCode","bookID","currentPage","totalPages","pageView","bookTimeout","user","getHeadersUrlEncode","firstName","lastName","code","Headers","append","APIKey","roleID","viewerMode","toUpperCase","addQuery","query","assign","hashHistory","getCurrentLocation","removeQuery","queryNames","q","userLoginSuccess","userLoginFailed","userLogoutSuccess","userUpdateProfile","getState","updateProfile","toggleClassCodeModal","userUpdatePW","updateProfilePW","userLogout","resolve","removeAll","checkSession","debouncedCheckSession","debounce","dispatchEvent","Event","App","handleNewVersion","toastr","warning","toastrWarning","reload","logout","shouldForceLogout","now","Date","lastCheckSession","info","shouldRedirectToBookBag","ID","changeSchoolID","pathname","checkUpdatedSchoolID","initialSchoolID","SchoolID","confirmChangeSchoolID","state","loading","isOnline","setState","onLine","removeEventListener","resp","userLogoutSessionOnly","StrictMode","padding","children","Component","connect","ownProps","ajaxCallsInProgress","offlineQueue","schoolid","confirm","okText","cancelText","onOk","replace","onCancel","setInitialNetworkStatus","ONLINE","OFFLINE","StyledButton","styled","Button","css","StyledNavbar","Navbar","StyledDiv","div","StyledRow","Row","validateField","showErrors","formValidations","matchValue","field","errorMessage","validators","validator","valid","pattern","required","mustMatch","validate","validationState","validationMessage","validateForm","ToastMessageFactory","createFactory","ToastMessage","animation","convertToOptions","items","District","label","initialComponentState","schools","shouldHideSchoolSearch","formValid","LoginForm","handleChangeSchool","handleChange","target","fv","vf","validateAllFields","handleLoginSuccess","redirect","handleLoginFailed","toastCont","closeButton","showAnimation","handleSubmit","preventDefault","forceUpdate","userLogin","goToRegister","handleLoadOptions","callback","debouncedSchoolSearch","doSchoolSearch","getSchools","schoolOptions","handleSchoolSelect","selectedSchool","reqGoogleLogin","responseGoogle","handleTokenLogin","tokenId","googleTokenLogin","Error","isStudent","prevProps","userSchoolClassName","bsLayout","xs","span","offset","md","lg","toastMessageFactory","ref","toast","NavbarBrand","alt","id","onSubmit","Container","marginTop","Col","FormGroup","controlId","bsSize","htmlFor","loadOptions","placeholder","defaultOptions","onChange","classNamePrefix","cacheOptions","FormControl","Feedback","Form","Text","clientId","buttonText","onSuccess","onFailure","onRequest","disabled","bottom","marginLeft","bookid","BookID","login","RegisterForm","first","last","password2","bind","goBack","refemail","focus","userRegister","input","refgender","gender","reffirst","reflast","email","refpassword","refpassword2","refrole","role","variant","onClick","data-fontsize","data-lineheight","register","epubViewStyles","viewHolder","view","EpubAudio","setStatus","zIndex","BOOK_NEXT_PAGE","BOOK_PREV_PAGE","BOOK_FIRST_PAGE","BOOK_LAST_PAGE","textToSpeechConfig","intialMarkProcessed","unique","normalizedValue","confirmed","elementMatchConfidence","consecutiveMatchConfidence","isLine","possibleLine","addTappableClassOnly","pageData","$pageData","$","each","$tDiv","innerHTML","lineArray","trim","len","outerHTML","determinElementMatchConfidence","elementIndex","allElements","marks","elementNormalizedText","normalizedText","mark","foundInElementString","matchesNormalizedText","matchesOriginalElement","matchesElementAndUnique","foundInMarkValue","confirmations","foundInMarkValueWeight","divideConsecutiveMatchConfidence","minimumThreashholdForPossibleMatch","determinConsecutiveElementConfidence","element","markIndex","countMissedAfter","nextMark","currentElement","lineIndex","countMissedBefore","prevMark","addTimecode","word","startTimeAttribute","time","matchSingleCharacterElements","allPageElements","speechMarksData","flatSpeechMarksData","flatSpeechMarkData","splitMarkValue","singleCharacter","flattenSpeechMarksData","possibleMarks","foundMark","foundMarksWithConfidence","current","foundElement","addSpeechMarkTimesAndTappableClass","book","pageNumber","pageKey","rawSpeechMarksData","cachedPages","speechMarks","$arrayOfLines","tempMark","toLowerCase","uniqueCount","lineString","lineArrayCleaned","selectedMarks","reducedMark","currentConfidence","prevConfidence","usedMark","reducePossibleMarks","updatedLine","originalWord","flatWordObj","wordHTMLc","chosenMark","timeBeforeWord","timeAfterWord","previousElement","nextElement","targetTime","clossestSpeechMark","updatePageHTML","BookAPI","remoteURL","EBookPath","ISBN","voice","htmURL","svgURL","promise1","getBookFileEntry","promise2","values","svgData","svgPromises","fontPromises","originalPath","getBookFileUrl","newPath","childValues","root","p1","p2","blob","JSZip","loadAsync","zip","saveBook","saveSpeech","downloadedBookIDs","activePage","tag","grl","advancedSearchFilters","selectedReadingLevelTypeOption","readingMin","readingMax","spanishOnly","rltype","tags","TagID","page","bookItem","Content","bookId","passCorrectID","groupID","classID","studentID","BookId","StudentId","initialState","completedBLMs","blm","projectIsReady","blms","books","bookbagFilters","downloadedBooks","LeftPageEven","bookIsReady","bookmarks","highlights","notes","pagecount","routing","mode","bookView","pageIndex","bookScalePercent","projectScalePercent","leftPageContainerWidth","leftPageContainerHeight","pagesVisible","automaticUpdatedPagesVisible","activeNoteID","bookManualZooming","bookManualZoomIndex","bookManualZoomLevel","itemSavePending","dashboard","showUserProfileModal","showLoggoutConfirm","showClassCodeModal","projectToolbar","erasing","startText","drawingMode","pointer","showRichTextButtons","drawingColor","bookToolbar","allowNotes","highlighting","highlightColor","underlining","striking","pointing","pagesClassName","dashboardPageResults","readium","readiumClass","initialDashboardQuery","searchMode","searchBookBagBooks","isFiltersActive","showLoading","getBooks","normalizeBookObjects","pageResults","checkForUpdatedBookFiles","AzureToken","handleInvalidSession","searchBooks","downloadedBook","moment","FileUpdateDate","isBefore","downloadBook","getBookByID","normalizeBook","CurrentPage","isOdd","num","originalCurrentPage","IsAudioEnabled","IsAudioAvailable","bounds","getBookProperties","bookObj","IsEpub","hasBook","bookDownloaded","bookProperties","forceDownload","downloadSpeech","deleteDownloadedBook","removeBook","payload","speechDirectory","hasDirectory","hasFile","isInBookBag","flattenedBooks","Book","uniqBy","parseSpeechMarks","dispatchBookItem","bi","currentDate","utc","format","LastDownloadedFromServer","Type","bookmark","note","parseBookItems","bookItems","Page","saveBookItem","LastBookItemChange","saveBookID","action","args","promise","queueIfOffline","RoleID","canAccessBook","newBookItem","deleteBookItem","updateBookStatus","blmMode","updateCurrentPage","nextPage","prevPage","updatePagesVisible","setActiveNote","noteID","updatePendingItem","EpubView","debouncedSetState","updatePagesVisble","event","detail","updateSettings","syntheticSpread","scroll","readerSettings","reader","openPageNext","openPagePrev","firstPage","openPageIndex","lastPage","lastSpine","spine","increaseBookZoom","newScale","getViewScale","setZoom","decreaseBookZoom","isLoaded","playingMediaOverlay","mediaOverlayPlayable","initBook","setEventHandler","RediumClass","cacheSizeEvictThreshold","useSimpleLoader","openBookOptions","needsFixedLayoutScalerWorkAround","el","on","ReadiumSDK","Events","PAGINATION_CHANGED","pageChangeData","spineItem","isMediaOverlayAvailable","isPlayingMediaOverlay","MEDIA_OVERLAY_STATUS_CHANGED","isPlaying","FXL_VIEW_RESIZED","url","ebookURL","openPackageDocument","packageDocument","totalPage","spineLength","setTotalPage","fontSize","fontSelection","columnGap","columnMaxWidth","columnMinWidth","idref","elementCfi","removeEventHandler","playMediaOverlay","pauseMediaOverlay","styles","closeBookView","aria-hidden","updateMediaOverlayPlaying","defaultProps","loadingView","locationChanged","tocChanged","defaultStyles","renditionOptions","epubInitOptions","pages","BlmAPI","blmID","projectAssignmentID","blmItem","paID","TeacherID","emptyBLMData","blmData","teacherMakesBLMComment","comment","teachersComment","getBLMByID","getstate","saveBLMItem","saveBLMTemplate","updateStatus","updatedBlm","isComplete","IsComplete","startPointing","CommonModal","modalVisable","onHide","cancel","backdrop","Header","Title","submit","Footer","submitText","keyEnabled","verticalVolume","media","artist","sources","free","initializeOptions","viewerDrawerTypeEnum","AudioPlayer","isPlayingRightPage","showPlayer","updateAudioHighlights","unHightlightAudioText","startAudio","stopAudio","shouldLoadAudio","getPageKey","highlightedSpeechMarks","speechMarkIndex","timeouts","pendingResync","cordova","audioPaused","audioTime","duration","handleEndOfAudio","recentlyPaused","timeout","clearTimeout","removeClass","leftPage","pageReady","rightPage","getSpeechAudio","audioURL","leftPageNumber","rightPageNumber","startTime","curr","stop","speechMark","addClass","resyncSpeechMarks","markTime","markDuration","highlightDuration","getAudioSource","source","setMedia","mp3","play","shouldLoad","fontAwesomeTogglePlay","onPlay","jPlayers","paused","currentTime","pause","actions","getFileUrl","Drawer","shorten","getNotesHtml","getHLHtml","parseSerializedHighlight","ret","maxLength","borderForNote","bis","groupBy","buffer","biArr","concat","ListGroupItem","goTo","hlClass","goToPage","hlText","serializedPages","hls","serialized","serializedHighlights","sh","parts","random","remove","drawerClassName","drawerButtonsContainerClassName","drawerButtonsClassName","drawerButtonCSS","hideDrawer","innerHeight","showNotesButton","openDrawer","icon_pen","showHighlightsButton","icon_hl_teal","close","overflow","ListGroup","studentNotes","studentHighlights","searchTerm","filteredBooks","toggleClass","includes","sm","data-toggle","aria-haspopup","aria-expanded","data-pin-nopin","changeBook","changeBlm","FriendlyName","toggleHeader","toggle","class","HeaderContainer","isDownloaded","turnOnEraser","turnOnTextMode","turnOnPointer","turnOnDrawingMode","fabricCanvas","ProjectToolbar","pointerClassName","eraserClassName","textClassName","drawingClassName","parentState","showToolbar","blmButtonsClasses","currentFontSize","showAdminSaveButtons","showMarkersButtons","showStudentSaveButtons","projectToolbarStyle","transform","transformOrigin","exitBlm","startPointer","icon_pointer","as","changeFontSize","toggleBold","toggleItalic","toggleUnderline","toggleLinethrough","isNotCompleteForStudent","Dropdown","Toggle","markerSelected","Menu","Item","startDrawingMode","startTextMode","startEraser","icon_eraser","showBlmSubmitModal","isIOS","doPrint","displayResetModal","FabricUI","closeResetBLMModal","resetActiveTimeout","showResetBLMModal","resetBLM","originalBLMTemplate","loadFromJSON","obj","renderAll","saveBlmDraft","submitBLM","stopDrawingMode","stopTextMode","freezeBlm","toDatalessJSON","blackLineMasterID","saveBLMData","order","submitBLMData","success","closeBlmSubmitModal","commentsSlideUp","teachersCommentForStudent","commentFromTeacher","showCommentButtons","toggleComments","addText","fabric","Canvas","getElementById","initialize","textbox","borderColor","templateObject","set","getObjects","setActiveObject","object","lockMovementX","lockMovementY","lockScalingX","lockScalingY","lockRotation","enterEditing","eraseObjects","setWidth","setHeight","viewerSettings","loadedProjectAssignmentID","blmDataID","styleName","getActiveObject","getSelectionStyles","isEditing","setSelectionStyles","setCoords","getActiveStyle","setActiveStyle","isUnderline","isLinethrough","newFontSize","setFontSize","deactivateAll","isDrawingMode","freeDrawingBrush","__eventListeners","_objects","blmObj","stopEraser","addingText","getPointer","posX","x","posY","y","backgroundColorForText","Textbox","fontFamily","top","borderScaleFactor","transparentCorners","cornerColor","add","fire","HasTemplate","fabricItems","newBLMItem","elem","delimiter","clone","domClone","cloneNode","$printSection","blmContent","firstElementChild","canvasImage","multiplier","printElement","print","removeChild","ProjectAssignmentID","BlackLineMasterID","StudentID","teacherComment","exitBlmMode","freezeComments","commentsContainerClassName","commentsWidth","marker_hl_orange","pointerEvents","canvasClassForBlm","showTeachersComment","submitTeacherComment","bindActionCreators","BLM","pageContainerWidth","pageContainerHeight","pageClassName","pageWidth","pageHeight","resizeProjectPage","shouldResize","maxContentHeight","maxContentWidth","scalePercent","innerWidth","widthOfArrow","heightDiff","widthDiff","getProjectClassName","round","updateProjectScalePercent","projectClassName","blmHtml","pageStyle","jpedalStyle","dangerouslySetInnerHTML","__html","NotePopover","newNote","saveNote","cancelNote","deleteNote","getPopover","popoverClassName","disableNote","hideFromStudent","deleteClassName","saveClassName","Popover","rows","handleToggle","TempID","note_icon","offsetX","offsetY","placement","OverlayTrigger","trigger","onToggle","overlay","pageScalePercent","BookPage","scaleX","scaleY","_lastResized","resizePage","assignBookPageClassName","deserialize","getNotesHTML","retryCount","shouldAssign","highlighterLeft","highlighterRight","whichSide","updateLeftPageContainer","updateBookScalePercent","getBookPageClassName","shouldBookPageResize","noteScalePercent","layerX","nativeEvent","layerY","noteX","noteY","ClassID","GroupID","persist","createTempNote","pagesTapped","whichNotes","combinedNotes","filteredStudentNotes","pageHTML","marginBottom","hight","notesLayerStyle","escapeHTML","bookPageTapped","onMouseDown","pagesOnMouseDown","onMouseMove","pagesOnMouseMove","onMouseUp","pagesOnMouseUp","onTouchStart","onDragStart","withRouter","Pages","shouldShowCloseButton","isGeneric","isDemo","transX","transY","pagesContainerWidth","pagesContainerHeight","leftMarginForArrow","dragging","handleSwipe","resizePagesContainer","shouldShowProject","lastClientX","lastClientY","tallestPageHeight","leftW","leftH","rightW","rightH","leftScalePercent","rightScalePercent","totalWidthOfPages","automaticUpdatePagesVisible","direction","pageID","showProject","clientX","touches","clientY","tempX","tempY","moveX","moveY","pagesContainer","scrollLeft","scrollTop","mouseMove","bookArrowLeftStyle","bookArrowRightStyle","bookReadyClass","shouldShowBook","classes","showBookArrows","pagesContainerStyle","flexDirection","justifyContent","forwardedRef","getBookPage","Toolbar","startedHighlighting","shouldShowMarkupTools","hasCorrectViewerMode","startHL","startHighlighter","closeGoToPageModal","showGoToPageModal","openGoToPageModal","submitGoToPage","toggleColors","isOpen","stopPropagation","inputForm","showBookMarkupTools","toolbarStyle","pointerIcon","icon_hl","bookIsZooming","move_icon","highlighterClassName","strikeClassName","underlineClassName","eraseClassName","notesClassName","drop","onTouchEnd","startNotes","testForSimilarMarkup","textContent","findSimilarMarkups","pid","range","rangy","createRange","currentRange","willMergeMarkups","selectNodeContents","selectNode","findPreviousMarkups","didFindElement","previousElementSibling","parentNode","setStart","findNextMarkups","nextElementSibling","setEnd","firstChild","select","BookView","handleKeyPress","shouldHideDrawer","handleRenewedAzureToken","resetCachedBookPages","loadBook","setBookReady","fadeTo","updateViewerSettings","newViewerSettings","initBooks","initBLMs","getAssignedBLMs","loadBLM","createHighlighter","newHL","pagesRef","addClassApplier","createClassApplier","removeAllHighlights","serializePageMarkups","side","self","serializedText","serialize","serializeHighlightText","alert","unhighlightSelection","clickHighlight","touchHighlight","getSelection","doTouchHighlight","startHighlighting","startErasing","pagesToChange","wordTapped","updateMarkups","updateHighlights","removeAllRanges","highlightSelection","containerElementId","debouncedMarkupUpdate","highlightingMouseDown","highlightingPageNumber","sel","highlightClass","click","highlight","newHighlights","bookData","goToNote","drawerType","showDrawer","closeDrawer","header","visible","animate","toggleBLMMode","showSaveProjectConfirm","saveProjectSubmit","resetBookView","setProjectReady","goToBag","emptyBLMs","IsExternal","externalURL","fadeOut","cb","checkLeftPageEven","pi","checkIfPageExists","test","shouldCheckLeftPageEven","getBookHTMLPages","httpPrefix","EPubUrl","host","getBookParts","promises","getBookItemsByStudentID","getTeacherBookItems","getBookItems","LoginID","cache","lIndex","lpageKey","rIndex","rpageKey","pageIndexToCache","previousPageIndexToCache","pageIndexToCacheTwo","getBookHTMLPage","getSpeechMarks","cacheBookPage","currentObjectID","getBLMObject","getBLMParts","getBLMProperties","getBlmHtml","getBLMStatus","getTeachersComment","getBLMItems","getStudentsBLMItems","getTemplateItems","getBlmPageRemote","blmPage","showDrawerHighlightsButton","showDrawerNotesButton","showHeader","createRef","superDebouncedMarkupUpdate","requireSignIn","init","initialViewerSettings","setupEventHandlers","startMoving","removeEventHandlers","epubcifi","toc","openBLM","blmProperties","parsedBookItems","getBookPageLocal","getBookPageRemote","getSpeechMarksLocal","parsedMarks","getSpeechMarksRemote","tempObj","ProjectItem","BlackLineMaster","ProjectItemID","Class","AccountID","Group","blmStatus","blmItems","fabricItemsStudent","fabricItemsTemplate","ready","startUnderlining","startStriking","UserProfileForm","forms","form","toggleUserProfileModal","ClassCodeModal","addCode","FormLabel","minLength","currentTarget","addClassCode","stringifiedData","replaceAll","parsedData","FontAwesome","require","BookBagHeader","closeLoggoutConfirmModal","showLoggoutConfirmModal","handleLoggout","handleSelect","signOut","toggleLoggoutConfirmModal","statusText","confirmPassword","buildUserProfileForm","First","Last","logoutWarning","Brand","Collapse","Nav","onSelect","School","NavItem","Link","eventKey","clearAdvancedSearchFilter","AdvancedSearchModal","clearAdvancedSearch","handleReadingLevelChange","saveAdvancedSearchFilter","showAdvancedSearch","advancedSearch","debouncedAdvancedSearch","doAdvancedSearch","advancedSearchResults","onValuesChange","closeOnSelect","onSearchChange","req","abort","handleAdvancedSearchChange","uid","filterOptions","renderOption","fontWeight","TagCount","renderValue","rejectedSearch","renderNoResultsFound","isClearable","Check","defaultChecked","checked","getAdvancedSearch","advancedSearchForm","filters","BookBagSearch","initializeComponent","updateBookItems","getBookItemsList","isActiveAdvancedSearch","switchToRemote","switchToLocal","searchForBooks","searchForReadingLevel","handleTagChange","val","handleTypeChange","closeAdvancedSearch","clearAdvancedSearchForm","backpack","bookshelf","bookbagSearchMode","advancedSearchButton","languageBC","socialStudiesBC","mathBC","scienceSearchBC","allTags","allBC","fictionBC","nonFictionBC","showSearchBar","allSquare","BookBagSearchContainer","bookIDs","bookState","unReadBook","BookBag","checkCanAccessBookBag","checkAddCode","handleBookClick","selectedBookID","openBook","openingBook","filtersActive","displayBookReadingLevel","atos","lex","hideBookReadingLevel","GuidedReadingLevel","ATOS","LEX","displayBookImage","downloadedIcon","OfficialImage","bookTitle","dlBook","photo","backgroundImage","backgroundPosition","backgroundSize","backgroundRepeat","prevSelected","selectedTypes","emptySearchMessage","sortBy","o","toggleUserAccountModal","selected","glow","bookHeight","readBook","addBook","IsStudentAdded","margin","boundaryPagesRange","addcode","AddCode","bool","normalizedBook","bookIsbn","BLMView","pullRight","Token","doLogin","params","tokenLogin","bookSaved","blmSaved","updateViewerMode","path","component","loadState","serializedState","localStorage","CL_WARN","CL_ERROR","Logger","severity","reduxStore","privateKey","applicationName","computerName","logEntries","timestamp","getTime","category","sendToCoralogix","ex","rawBook","pickBy","property","actionTypeEndsInSuccess","substring","actionTypeEndsInFailed","rootReducer","combineReducers","appVersion","foundBook","studentBookmarks","newCachedPage","newPage","newCachedPages","newBook","db","newBooks","foundNewBook","bookNote","dlBookBookmark","dlBookNote","dlPurgeTempNotes","dlBookHighlight","CustomEvent","newZoomLevelIndex","newZoomLevel","newZoomLevelIndexD","newZoomLevelD","moving","migrations","162","persistConfig","storage","blacklist","migration","createMigration","offlineActionCreators","isLocalhost","hostname","registerValidSW","swUrl","serviceWorker","registration","onupdatefound","installingWorker","installing","onstatechange","controller","onUpdate","reportWebVitals","onPerfEntry","Function","getCLS","getFID","getFCP","getLCP","getTTFB","readiumInitialized","Provider","NetworkListenerProvider","_onlineListener","_offlineListener","IndexClass","isRehydrated","persistCallback","createStore","compose","applyMiddleware","offlineQueueMiddleware","thunk","autoRehydrate","persistor","persistStore","configureStore","listenToReadiumInit","history","routes","handler","ev","ReactDOM","origin","contentType","get","unregister","checkValidServiceWorker","serviceWorkerRegistration","waiting","postMessage","origConsole","isDebug","logArray","logs","errors","warns","infos","arguments"],"mappings":"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","file":"static/js/main.c87eea0c.chunk.js","sourcesContent":["export default __webpack_public_path__ + \"static/media/logo.fe7dda5a.png\";","import localForage from 'localforage';\nexport default class BookFS {\n static fs = localForage.createInstance({ name: 'dibs-web' });\n\n static removeAll() {\n console.log('removing books');\n return BookFS.fs.clear();\n }\n\n static removeBook(isbn) {\n return BookFS.fs.iterate((value, key, index) => {\n if (key.search(isbn)) {\n BookFS.fs\n .removeItem(key)\n .then(() => console.log('removed a key', key));\n }\n });\n }\n\n /*\n * have we downloaded the file\n */\n static hasDirectory(directory) {\n return BookFS.fs\n .keys()\n .then((keys) => {\n return keys.find((key) => key.search(directory)) ? true : false;\n })\n .catch(() => {\n console.error('error trying to find directory', directory);\n return false;\n });\n }\n\n /* Check if we have already downloaded a book\n * return true or false\n */\n static hasBook({isbn, IsEPub}) {\n let testFileLocation = `books/${isbn}/1.html`;\n if (IsEPub){\n testFileLocation = `books/${isbn}.epub`\n } \n return BookFS.fs\n .getItem(testFileLocation)\n .then((result) => {\n return result ? true : false;\n })\n .catch((err) => {\n console.log(\n 'book does not exist on file system, ' + isbn,\n err\n );\n return false;\n });\n }\n\n /* Save a new book to the file system */\n static saveBook(isbn, zippedBook) {\n const basePath = `books/${isbn}`;\n let filePromises = [];\n console.log('saving book to file system: ', `books/${isbn}`);\n zippedBook.forEach(function (relativePath, file) {\n // build directory and file names and get MIME type\n let pathArr = relativePath.split('/');\n const pathFileName = pathArr.pop();\n const pathDirName = pathArr.length ? pathArr.join('/') : false;\n // console.log(\"iterating over\", pathDirName, pathFileName, isbn);\n const saveProm = file\n .async('blob', (update) => {\n // console.log('update', update);\n })\n .then((content) => {\n if (pathDirName) {\n // console.log('writing file: ', `${basePath}/${pathDirName}/${pathFileName}`, content );\n return BookFS.fs.setItem(\n `${basePath}/${pathDirName}/${pathFileName}`,\n content\n );\n } else {\n // console.log('writing file: ', `${basePath}/${pathFileName}`);\n return BookFS.fs.setItem(\n `${basePath}/${pathFileName}`,\n content\n );\n }\n });\n // create the array of promises\n filePromises.push(saveProm);\n });\n return Promise.all(filePromises)\n .then((result) => {\n // console.log('promises complete', result);\n return true;\n })\n .catch((err) => {\n // handle the error\n console.error('Error saving book files to file system', err);\n });\n }\n /* Save a new book to the file system */\n static saveSpeech(isbn, zippedSpeech) {\n const basePath = `books/${isbn}/audio/default`;\n let filePromises = [];\n // console.log('saving speech to file system: ', `books/${isbn}`);\n zippedSpeech.forEach(function (relativePath, file) {\n // build directory and file names and get MIME type\n let pathArr = relativePath.split('/');\n const pathFileName = pathArr.pop();\n // console.log(\"iterating over\", pathDirName, pathFileName, isbn);\n const saveProm = file\n .async('blob', (update) => {\n // console.log('update', update);\n })\n .then((content) => {\n // console.log('writing file: ', `${basePath}/${pathFileName}`);\n return BookFS.fs.setItem(\n `${basePath}/${pathFileName}`,\n content\n );\n });\n // create the array of promises\n filePromises.push(saveProm);\n });\n return Promise.all(filePromises)\n .then((result) => {\n // console.log('promises complete', result);\n return true;\n })\n .catch((err) => {\n // handle the error\n console.error('Error saving speech files to file system', err);\n });\n }\n\n /* Get fileEntry object for file */\n static getBookFileEntry(isbn, relativePath) {\n if (!relativePath || !isbn) {\n console.error('missing path to file', isbn, relativePath);\n }\n // console.log(`getting book file entry, isbn: ${isbn}, path: ${relativePath}`, `books/${isbn}/${relativePath}`);\n return BookFS.fs\n .getItem(`books/${isbn}/${relativePath}`)\n .then((fileEntry) => {\n if (fileEntry === null) {\n console.error(\n 'unable to find file',\n `books/${isbn}/${relativePath}`\n );\n return Promise.reject('unable to find file');\n }\n return fileEntry.text();\n });\n }\n\n /* Get filesystem url for file\n */\n static getBookFileUrl(isbn, relativePath) {\n return BookFS.fs\n .getItem(`books/${isbn}/${relativePath}`)\n .then((item) => {\n if (item === null) {\n console.error(\n 'unable to find file for url',\n `books/${isbn}/${relativePath}`\n );\n return Promise.reject('unable to find file');\n }\n return window.URL.createObjectURL(item);\n })\n .catch((err) => {\n console.error('Error getting file, sending 404...', err);\n return 404;\n });\n }\n\n static getFileUrl(isbn, relativePath) {\n return BookFS.fs\n .getItem(`books/${isbn}/${relativePath}`)\n .then((item) => {\n return window.URL.createObjectURL(item);\n });\n }\n}\n","const config = {\nVersion: '1.6.2',\n Debug: false, // true prefills the login form with test bam, enables redux tools, and sets the URL for epubs to http rather than https\n\n // **************** PROD ENVIRONMENT ****\n\n Environment: 'PROD',\n API: {\n Main: 'https://api.digitalbookroom.com',\n Storage: 'https://dibsbookstest.blob.core.windows.net',\n Admin: `https://admin.digitalbookroom.com`\n },\n\n // **************** TEST ENVIRONMENT ****\n\n // Environment: 'TEST',\n // API: {\n // Main: 'https://dibs-api-test.azurewebsites.net',\n // Storage: 'https://dibsbookstest.blob.core.windows.net',\n // Admin: `https://brainhive-admin-test.azurewebsites.net`\n // },\n // Environment: 'TEST',\n // API: {\n // Main: 'https://dibs-api-test.azurewebsites.net',\n // Storage: '',\n // Admin: `https://brainhive-admin-test.azurewebsites.net`\n // },\n\n /* ************** DEV ENVIRONMENT *******/\n // Environment: 'DEV',\n // API: {\n // Main: 'http://api-dev.digitalbookroom.com',\n // Storage: 'https://dibsbookstest.blob.core.windows.net',\n // Admin: `http://dibs-admin-dev.azurewebsites.net`\n // },\n\n Coralogix: {\n key: '88e035bf-5ccb-3a98-29a0-562fcf7162c2',\n subsystemName: 'DiBS.Web.Student'\n },\n google: {\n clientID:\n '170648211199-qldupgprptpkc1mfsg0h6b6p3va5a6te.apps.googleusercontent.com'\n },\n\n UserRoleIDs: {\n Teacher: 'C89F9DD9-ED08-43F5-8FC8-DBFCB1A3D008', // notes on each role are in the README\n SuperAdmin: 'BA2ED223-7F90-4700-B04E-3DA0025D2F5A',\n SchoolAdmin: 'B751ECE9-97E1-439D-BC27-9665E47D847E',\n SalesRep: 'D335673F-182A-4E72-B4B6-F20856698843',\n Student: '357001F1-7DC2-496F-82F3-8FC21813BF6C',\n Generic: '2E4030D1-BD1A-451E-B1C8-010CAA433BBC',\n Demo: 'E3F41C5E-DC13-4859-9A51-3124B6724297'\n },\n\n typeGUID: {\n math: 'FDDCA1E8-4BE2-45E2-9DE7-CB9D43D60A44',\n languageArts: 'D675D783-CA70-47F7-A600-FD7CE2669594',\n science: 'C17493D4-1A3A-4AA3-A707-606C1C839758',\n socialStudies: 'f7a70888-fd0c-43c2-b619-223eff1c1a4f'\n }\n};\n\nexport default config;\n","/* eslint no-unused-expressions: 0 */\n/* eslint no-restricted-globals: 0 */\n/*eslint no-undef: 0 */\n/*\n * Copyright 2018 Google Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n\n\n\nexport const pWaCompatUtil = () => {\n\n\n\n // basic feature detection: from IE10+\n // also fallout on 'navigator.standalone', we _are_ an iOS PWA\n if (!('onload' in XMLHttpRequest.prototype) || navigator.standalone) {\n return;\n }\n\n const debug = false;\n\n const capableDisplayModes = ['standalone', 'fullscreen', 'minimal-ui'];\n const defaultSplashColor = '#f8f9fa';\n const defaultSplashTextSize = 24;\n const defaultFontName = 'HelveticaNeue-CondensedBold';\n const idealSplashIconSize = 128;\n const minimumSplashIconSize = 48;\n const splashIconPadding = 20;\n const appleIconSizeMin = 120;\n\n const userAgent = navigator.userAgent || '';\n const isSafari = (navigator.vendor && navigator.vendor.indexOf('Apple') !== -1);\n const isSafariMobile = isSafari && (userAgent.indexOf('Mobile/') !== -1 || 'standalone' in navigator) || debug;\n const isIEOrEdge = Boolean(userAgent.match(/(MSIE |Edge\\/|Trident\\/)/));\n const isEdgePWA = (typeof Windows !== 'undefined');\n\n let manifestEl; // we need this later, not just for JSON\n let internalStorage;\n try {\n internalStorage = sessionStorage;\n } catch (e) {}\n internalStorage = internalStorage || {};\n\n /**\n * Retrieves element in head if available, otherwise null\n * @param {string} selector CSS selector\n * @return {?Element}\n */\n function getElementInHead(selector) {\n // It's possible to pass \"bad\" attr or values here (originally from the manifest); just\n // return null if there's something wrong.\n try {\n return document.head.querySelector(selector);\n } catch (e) {\n return null;\n }\n }\n\n /**\n * @param {string} k\n * @param {string=} v\n * @return {string|undefined}\n */\n function store(k, v) {\n const key = '__pwacompat_' + k;\n if (v !== undefined) {\n internalStorage[key] = v;\n }\n return internalStorage[key];\n }\n\n function setup() {\n manifestEl = getElementInHead('link[rel=\"manifest\"]');\n const manifestHref = manifestEl ? manifestEl.href : '';\n if (!manifestHref) {\n throw `can't find '`;\n }\n\n const hrefFactory = buildHrefFactory([manifestHref, location]);\n const storedResponse = store('manifest');\n if (storedResponse) {\n try {\n const data = /** @type {!Object} */ (JSON.parse(storedResponse));\n process(data, hrefFactory);\n } catch (err) {\n console.warn('PWACompat error', err);\n }\n return;\n }\n\n const xhr = new XMLHttpRequest();\n xhr.open('GET', manifestHref);\n\n // nb. use getAttribute for older brower safety\n xhr.withCredentials = (manifestEl.getAttribute('crossorigin') === 'use-credentials');\n\n // this is IE10+\n xhr.onload = () => {\n try {\n const data = /** @type {!Object} */ (JSON.parse(xhr.responseText));\n store('manifest', xhr.responseText);\n process(data, hrefFactory);\n } catch (err) {\n console.warn('PWACompat error', err);\n }\n };\n xhr.send(null);\n }\n\n /**\n * @param {!Array} options\n * @return {function(string): string}\n */\n function buildHrefFactory(options) {\n for (let i = 0; i < options.length; ++i) {\n const opt = options[i];\n try {\n new URL('', opt);\n return (part) => (new URL(part || '', opt)).toString();\n } catch (e) {}\n }\n return (part) => part || '';\n }\n\n /**\n * Adds an element in the if it's not present already based on the passed check.\n * @param {string} localName tag name\n * @param {!Object} attr key-value collection of attributes\n * @param {string} check to apply to the tag\n */\n function push(localName, attr, check) {\n if (getElementInHead(localName + check)) {\n return;\n }\n const node = document.createElement(localName);\n for (const k in attr) {\n node.setAttribute(k, attr[k]);\n }\n document.head.appendChild(node);\n return node;\n }\n\n function meta(name, content) {\n if (content) {\n if (content === true) {\n content = 'yes';\n }\n push('meta', {name, content}, `[name=\"${name}\"]`);\n }\n }\n\n /**\n * Pre-process the icon sizes and purpose into a tuple and array.\n */\n function normalizeIcon(icon) {\n const parsedSizes = icon.sizes.split(/\\s+/g).map((size) => {\n if (size === 'any') {\n return Infinity;\n }\n return parseInt(size, 10) || 0; // NaN is falsey\n });\n\n return {\n src: icon.src,\n type: icon.type,\n sizes: icon.sizes,\n // Get the largest size from a processed icon.\n largestSize: Math.max.apply(null, parsedSizes),\n purpose: icon.purpose ? icon.purpose.split(/\\s+/g) : ['any'],\n };\n }\n\n /**\n * @param {!Object} manifest\n * @param {function(string): string} urlFactory\n */\n function process(manifest, urlFactory) {\n // largest first\n const allIcons = (manifest['icons'] || [])\n .map(normalizeIcon)\n .sort((a, b) => b.largestSize - a.largestSize);\n\n const icons = allIcons.filter((icon) => icon.purpose.indexOf('any') > -1)\n const maskable = allIcons.filter((icon) => icon.purpose.indexOf('maskable') > -1);\n\n const appleTouchIcons = (maskable.length > 0 ? maskable : icons).map((icon) => {\n // create regular link icons as byproduct\n const attr = {'rel': 'icon', 'href': urlFactory(icon['src']), 'sizes': icon['sizes']};\n // This checks for matching \"rel\" and \"sizes\". We don't check for the same image file, as\n // it is used literally by ourselves (and could be set by users for another icon).\n const querySuffix = `[sizes=\"${icon['sizes']}\"]`;\n push('link', attr, '[rel=\"icon\"]' + querySuffix);\n if (!isSafariMobile) {\n return;\n }\n if (icon.largestSize < appleIconSizeMin) {\n return;\n }\n attr['rel'] = 'apple-touch-icon';\n\n // nb. we used to call `removeAttribute('sizes')` here, which crashed iOS 8\n // ... sizes has been supported since iOS 4.2 (!)\n return push('link', attr, '[rel=\"apple-touch-icon\"]' + querySuffix);\n }).filter(Boolean);\n\n // nb. only for iOS, but watch for future CSS rule `@viewport { viewport-fit: cover; }`\n const metaViewport = getElementInHead('meta[name=\"viewport\"]');\n const viewport = metaViewport && metaViewport.content || '';\n const viewportFitCover = Boolean(viewport.match(/\\bviewport-fit\\s*=\\s*cover\\b/));\n\n const display = manifest['display'];\n const isCapable = capableDisplayModes.indexOf(display) !== -1;\n meta('mobile-web-app-capable', isCapable);\n updateThemeColorRender(/** @type {string} */ (manifest['theme_color']) || 'black', viewportFitCover);\n\n if (isIEOrEdge) {\n // Pinned Sites, largely from https://technet.microsoft.com/en-us/windows/dn255024(v=vs.60)\n meta('application-name', manifest['short_name']);\n meta('msapplication-tooltip', manifest['description']);\n meta('msapplication-starturl', urlFactory(/** @type {string} */ (manifest['start_url']) || '.'));\n meta('msapplication-navbutton-color', manifest['theme_color']);\n\n const largest = icons[0];\n if (largest) {\n meta('msapplication-TileImage', urlFactory(largest['src']));\n }\n meta('msapplication-TileColor', manifest['background_color']);\n }\n\n meta('theme-color', manifest['theme_color']);\n\n if (!isSafariMobile) {\n // TODO(samthor): We don't detect QQ or UC, we just set the vars anyway.\n const orientation = simpleOrientationFor(manifest['orientation']);\n meta('x5-orientation', orientation); // QQ\n meta('screen-orientation', orientation); // UC\n if (display === 'fullscreen') {\n meta('x5-fullscreen', 'true'); // QQ\n meta('full-screen', 'yes'); // UC\n } else if (isCapable) {\n meta('x5-page-mode', 'app'); // QQ\n meta('browsermode', 'application'); // UC\n }\n\n return; // the rest of this file is for Mobile Safari\n }\n\n const backgroundColor =\n /** @type {string} */ (manifest['background_color']) || defaultSplashColor;\n const backgroundIsLight = shouldUseLightForeground(backgroundColor);\n\n // Add related iTunes app from manifest.\n const itunes = findAppleId(manifest['related_applications']);\n itunes && meta('apple-itunes-app', `app-id=${itunes}`);\n\n // General iOS meta tags.\n meta('apple-mobile-web-app-capable', isCapable);\n meta('apple-mobile-web-app-title', manifest['short_name'] || manifest['name']);\n\n /**\n * @param {number} width\n * @param {number} height\n * @param {string} orientation\n * @param {?Image} icon\n * @return {function(): string}\n */\n function splashFor(width, height, orientation, icon) {\n const ratio = window.devicePixelRatio;\n const ctx = contextForCanvas({width: width * ratio, height: height * ratio});\n\n ctx.scale(ratio, ratio);\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n ctx.translate(width / 2, (height - splashIconPadding) / 2);\n\n if (icon) {\n // nb: on Chrome, we need the image >=48px, use the big layout >=80dp, ideal is >=128dp\n let iconWidth = (icon.width / ratio);\n let iconHeight = (icon.height / ratio);\n if (iconHeight > idealSplashIconSize) {\n // clamp to 128px height max\n iconWidth /= (iconHeight / idealSplashIconSize);\n iconHeight = idealSplashIconSize;\n }\n\n if (iconWidth >= minimumSplashIconSize && iconHeight >= minimumSplashIconSize) {\n ctx.drawImage(icon, iconWidth / -2, iconHeight / -2, iconWidth, iconHeight);\n ctx.translate(0, iconHeight / 2 + splashIconPadding);\n }\n }\n\n ctx.fillStyle = backgroundIsLight ? 'white' : 'black';\n ctx.font = `${defaultSplashTextSize}px ${defaultFontName}`;\n\n // Set the user-requested font; if it's invalid, the set will fail.\n const s = getComputedStyle(manifestEl);\n ctx.font = s.getPropertyValue('--pwacompat-splash-font'); // blank for old browsers\n\n const title = manifest['name'] || manifest['short_name'] || document.title;\n const measure = ctx.measureText(title);\n const textHeight = (measure.actualBoundingBoxAscent || defaultSplashTextSize);\n ctx.translate(0, textHeight);\n\n if (measure.width < width * 0.8) {\n // short-circuit, just draw entire string\n ctx.fillText(title, measure.width / -2, 0);\n } else {\n // longer wrap case, draw once we have >0.7 width accumulated\n const words = title.split(/\\s+/g);\n for (let i = 1; i <= words.length; ++i) {\n const cand = words.slice(0, i).join(' ');\n const measureWidth = ctx.measureText(cand).width;\n if (i === words.length || measureWidth > width * 0.6) {\n // render accumulated words\n ctx.fillText(cand, measureWidth / -2, 0);\n ctx.translate(0, textHeight * 1.2);\n words.splice(0, i);\n i = 0;\n }\n }\n }\n\n return () => {\n const data = ctx.canvas.toDataURL();\n if (debug) {\n const img = document.createElement('img');\n img.src = data;\n document.body.append(img);\n }\n appendSplash(orientation, data);\n return data;\n };\n }\n\n /**\n * @param {string} orientation\n * @param {string} data\n */\n function appendSplash(orientation, data) {\n const generatedSplash = /** @type {!HTMLLinkElement} */ (document.createElement('link'));\n generatedSplash.setAttribute('rel', 'apple-touch-startup-image');\n generatedSplash.setAttribute('media', `(orientation: ${orientation})`);\n generatedSplash.setAttribute('href', data);\n document.head.appendChild(generatedSplash);\n }\n\n // fetch previous (session) iOS image updates\n const rendered = store('iOS');\n if (!debug && rendered) {\n try {\n const prev = /** @type {!Object} */ (JSON.parse(rendered));\n appendSplash('portrait', prev['p']);\n appendSplash('landscape', prev['l']);\n appleTouchIcons.forEach((icon) => {\n const change = prev['i'][icon.href];\n if (change) {\n icon.href = change;\n }\n });\n return;\n } catch (e) {\n // ignore, some problem with the JSON\n }\n }\n const update = {'i': {}};\n\n /**\n * @param {?Image} applicationIcon\n * @param {function(): void} done\n */\n function renderBothSplash(applicationIcon, done) {\n const s = window.screen;\n const portrait = splashFor(s.width, s.height, 'portrait', applicationIcon);\n const landscape = splashFor(s.height, s.width, 'landscape', applicationIcon);\n\n // this is particularly egregious setTimeout use, but the .toDataURL() is one of the\n // \"bottlenecks\" of PWACompat, so don't elongate any single frame more than needed.\n\n setTimeout(() => {\n update['p'] = portrait();\n setTimeout(() => {\n update['l'] = landscape();\n done();\n }, 10);\n }, 10);\n }\n\n // fetches and redraws any remaining icons in appleTouchIcons (to have proper bg)\n function redrawRemainingIcons(done) {\n let left = appleTouchIcons.length + 1;\n const check = () => {\n if (!--left) {\n done();\n }\n };\n check();\n appleTouchIcons.forEach((icon) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onerror = check;\n img.onload = () => {\n img.onload = null;\n icon.href = updateTransparent(img, backgroundColor, true);\n update['i'][img.src] = icon.href;\n check();\n };\n img.src = icon.href;\n });\n }\n\n // write the update to sessionStorage\n function saveUpdate() {\n store('iOS', JSON.stringify(update));\n }\n\n // called repeatedly until a valid icon is found\n function fetchIconAndBuildSplash() {\n const icon = appleTouchIcons.shift();\n if (!icon) {\n renderBothSplash(null, saveUpdate); // ran out of icons, render without one\n return;\n }\n\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onerror = () => void fetchIconAndBuildSplash(); // try again\n img.onload = () => {\n img.onload = null; // iOS Safari might call this many times\n renderBothSplash(img, () => {\n // ... if the icon used for splash changed, redraw others too\n const redrawn = manifest['background_color'] && updateTransparent(img, backgroundColor);\n if (redrawn) {\n icon.href = redrawn;\n update['i'][img.src] = redrawn;\n redrawRemainingIcons(saveUpdate);\n } else {\n saveUpdate();\n }\n });\n };\n\n img.src = icon.href; // trigger load\n }\n fetchIconAndBuildSplash();\n }\n\n function findAppleId(related) {\n let itunes;\n (related || [])\n .filter((app) => app['platform'] === 'itunes')\n .forEach((app) => {\n if (app['id']) {\n itunes = app['id'];\n } else {\n const match = app['url'].match(/id(\\d+)/);\n if (match) {\n itunes = match[1];\n }\n }\n });\n return itunes;\n }\n\n function simpleOrientationFor(v) {\n const prefix = String(v || '').substr(0, 3);\n return {'por': 'portrait', 'lan': 'landscape'}[prefix] || '';\n }\n\n /**\n * @param {string} color\n * @param {boolean} viewportFitCover\n */\n function updateThemeColorRender(color, viewportFitCover) {\n if (!(isSafariMobile || isEdgePWA)) {\n return;\n }\n\n const themeIsLight = shouldUseLightForeground(color);\n if (isSafariMobile) {\n // nb. Safari 11.3+ gives a deprecation warning about this meta tag.\n const content = viewportFitCover ? 'black-translucent' : (themeIsLight ? 'black' : 'default');\n meta('apple-mobile-web-app-status-bar-style', content);\n } else {\n // Edge PWA\n const t = getEdgeTitleBar();\n if (!t) {\n return; // something went wrong, we had a UWP without titleBar\n }\n // Foreground is black if theme is light, otherwise white.\n const v = themeIsLight ? 255 : 0;\n t.foregroundColor = /** @type {WindowsColor} */ ({'r': v, 'g': v, 'b': v, 'a': 255});\n t.backgroundColor = colorToWindowsRGBA(color);\n }\n }\n\n /**\n * @return {!ApplicationViewTitleBar|undefined}\n */\n function getEdgeTitleBar() {\n try {\n return Windows.UI.ViewManagement.ApplicationView.getForCurrentView().titleBar;\n } catch (e) {\n // implicit return undefined\n }\n }\n\n /**\n * The Windows titlebar APIs expect an object of {r, g, b, a}.\n *\n * @param {string} color\n * @return {WindowsColor}\n */\n function colorToWindowsRGBA(color) {\n const data = readColor(color);\n return /** @type {WindowsColor} */ ({\n 'r': data[0],\n 'g': data[1],\n 'b': data[2],\n 'a': data[3],\n });\n }\n\n /**\n * @param {string} color\n * @return {!Uint8ClampedArray}\n */\n function readColor(color) {\n const c = contextForCanvas();\n c.fillStyle = color;\n c.fillRect(0, 0, 1, 1);\n return c.getImageData(0, 0, 1, 1).data || []; // incase this fails for some reason\n }\n\n /**\n * @param {string} color\n * @return {boolean}\n */\n function shouldUseLightForeground(color) {\n const pixelData = readColor(color);\n\n // From https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser/util/ColorUtils.java\n const data = pixelData.map((v) => {\n const f = v / 255;\n return (f < 0.03928) ? f / 12.92 : Math.pow((f + 0.055) / 1.055, 2.4);\n });\n const lum = 0.2126 * data[0] + 0.7152 * data[1] + 0.0722 * data[2];\n const contrast = Math.abs((1.05) / (lum + 0.05));\n return contrast > 3;\n }\n\n function updateTransparent(image, background, force=false) {\n const context = contextForCanvas(image);\n context.drawImage(image, 0, 0);\n\n // look for transparent pixel in top-left\n // TODO: Chrome actually checks the four corners for some cases.\n if (!force) {\n const imageData = context.getImageData(0, 0, 1, 1);\n if (imageData.data[3] === 255) {\n return;\n }\n }\n\n context.globalCompositeOperation = 'destination-over'; // only replace transparent areas\n context.fillStyle = background;\n context.fillRect(0, 0, image.width, image.height);\n return context.canvas.toDataURL();\n }\n\n function contextForCanvas({width, height} = {width: 1, height: 1}) {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas.getContext('2d');\n }\n\n // actually run PWACompat here\n if (document.readyState === 'complete') {\n setup();\n } else {\n window.addEventListener('load', setup);\n }\n};","import { themeProvider } from '../utilities/themeProvider';\n\nconst constants = {\n // UserRoleIDs: {\n // Teacher: \"C89F9DD9-ED08-43F5-8FC8-DBFCB1A3D008\", // access book by clicking e-book in teacher portal\n // SuperAdmin: \"BA2ED223-7F90-4700-B04E-3DA0025D2F5A\", // access book by clicking e-book in teacher portal\n // SchoolAdmin: \"B751ECE9-97E1-439D-BC27-9665E47D847E\", // access book by clicking e-book in teacher portal\n // SalesRep: \"D335673F-182A-4E72-B4B6-F20856698843\", // cannot get into login - only admin panel\n // Student: \"357001F1-7DC2-496F-82F3-8FC21813BF6C\", // can login, has bookbag, remote search, can highlight make notes and those save to db\n // Generic: \"2E4030D1-BD1A-451E-B1C8-010CAA433BBC\", // can login, see remote page, access bookview and highlight but cannot save to db\n // Demo: \"E3F41C5E-DC13-4859-9A51-3124B6724297\" // can access 25% of the book\n // },\n\n // typeGUID: {\n // math: 'FDDCA1E8-4BE2-45E2-9DE7-CB9D43D60A44',\n // languageArts: 'D675D783-CA70-47F7-A600-FD7CE2669594',\n // science: 'C17493D4-1A3A-4AA3-A707-606C1C839758',\n // socialStudies: 'f7a70888-fd0c-43c2-b619-223eff1c1a4f'\n // }\n themeProvider,\n toastrSuccessOptions: {\n position: 'top-right',\n transitionIn: 'fadeIn',\n transitionOut: 'fadeOut',\n timeOut: 5000\n },\n toastrErrorOptions: {\n timeOut: 8000\n },\n toastrWarningOptions: {\n position: 'top-right',\n transitionIn: 'bounceInDown',\n transitionOut: 'bounceOutUp',\n timeOut: 5000\n },\n testSpeechMarkRaw: `{\"time\":6,\"type\":\"word\",\"start\":35,\"end\":36,\"value\":\"6\"}\n {\"time\":596,\"type\":\"word\",\"start\":37,\"end\":45,\"value\":\"HISTORIC\"}\n {\"time\":1253,\"type\":\"word\",\"start\":46,\"end\":53,\"value\":\"FIGURES\"}\n {\"time\":1862,\"type\":\"word\",\"start\":54,\"end\":56,\"value\":\"of\"}\n {\"time\":2093,\"type\":\"word\",\"start\":57,\"end\":65,\"value\":\"theWORLD\"}\n {\"time\":3531,\"type\":\"word\",\"start\":111,\"end\":114,\"value\":\"The\"}\n {\"time\":3733,\"type\":\"word\",\"start\":115,\"end\":126,\"value\":\"Exploration\"}\n {\"time\":4770,\"type\":\"word\",\"start\":127,\"end\":134,\"value\":\"Station\"}\n {\"time\":6145,\"type\":\"word\",\"start\":181,\"end\":191,\"value\":\"Unscramble\"}\n {\"time\":6969,\"type\":\"word\",\"start\":192,\"end\":195,\"value\":\"the\"}\n {\"time\":7064,\"type\":\"word\",\"start\":196,\"end\":204,\"value\":\"captions\"}\n {\"time\":7855,\"type\":\"word\",\"start\":205,\"end\":207,\"value\":\"to\"}\n {\"time\":8036,\"type\":\"word\",\"start\":208,\"end\":216,\"value\":\"discover\"}\n {\"time\":8666,\"type\":\"word\",\"start\":217,\"end\":220,\"value\":\"the\"}\n {\"time\":8784,\"type\":\"word\",\"start\":221,\"end\":226,\"value\":\"names\"}\n {\"time\":9273,\"type\":\"word\",\"start\":227,\"end\":229,\"value\":\"of\"}\n {\"time\":9425,\"type\":\"word\",\"start\":230,\"end\":239,\"value\":\"different\"}\n {\"time\":10012,\"type\":\"word\",\"start\":240,\"end\":249,\"value\":\"explorers\"}\n {\"time\":11456,\"type\":\"word\",\"start\":251,\"end\":255,\"value\":\"Each\"}\n {\"time\":11788,\"type\":\"word\",\"start\":256,\"end\":263,\"value\":\"cartoon\"}\n {\"time\":12341,\"type\":\"word\",\"start\":264,\"end\":269,\"value\":\"gives\"}\n {\"time\":12645,\"type\":\"word\",\"start\":270,\"end\":271,\"value\":\"a\"}\n {\"time\":12722,\"type\":\"word\",\"start\":272,\"end\":276,\"value\":\"clue\"}\n {\"time\":13056,\"type\":\"word\",\"start\":277,\"end\":279,\"value\":\"to\"}\n {\"time\":13234,\"type\":\"word\",\"start\":280,\"end\":283,\"value\":\"the\"}\n {\"time\":13429,\"type\":\"word\",\"start\":284,\"end\":296,\"value\":\"explorer’s\"}\n {\"time\":14349,\"type\":\"word\",\"start\":297,\"end\":305,\"value\":\"identity\"}\n {\"time\":15505,\"type\":\"word\",\"start\":307,\"end\":311,\"value\":\"Find\"}\n {\"time\":15922,\"type\":\"word\",\"start\":312,\"end\":315,\"value\":\"the\"}\n {\"time\":16113,\"type\":\"word\",\"start\":316,\"end\":323,\"value\":\"answers\"}\n {\"time\":16781,\"type\":\"word\",\"start\":324,\"end\":326,\"value\":\"on\"}\n {\"time\":16997,\"type\":\"word\",\"start\":327,\"end\":331,\"value\":\"page\"}\n {\"time\":17433,\"type\":\"word\",\"start\":332,\"end\":334,\"value\":\"44\"}\n {\"time\":18986,\"type\":\"word\",\"start\":383,\"end\":384,\"value\":\"I\"}\n {\"time\":19145,\"type\":\"word\",\"start\":385,\"end\":391,\"value\":\"landed\"}\n {\"time\":19658,\"type\":\"word\",\"start\":392,\"end\":394,\"value\":\"in\"}\n {\"time\":19827,\"type\":\"word\",\"start\":395,\"end\":399,\"value\":\"what\"}\n {\"time\":20092,\"type\":\"word\",\"start\":400,\"end\":402,\"value\":\"is\"}\n {\"time\":20294,\"type\":\"word\",\"start\":403,\"end\":406,\"value\":\"now\"}\n {\"time\":20596,\"type\":\"word\",\"start\":407,\"end\":410,\"value\":\"the\"}\n {\"time\":20712,\"type\":\"word\",\"start\":411,\"end\":418,\"value\":\"Bahamas\"}\n {\"time\":21352,\"type\":\"word\",\"start\":419,\"end\":421,\"value\":\"in\"}\n {\"time\":21567,\"type\":\"word\",\"start\":422,\"end\":424,\"value\":\"14\"}\n {\"time\":22139,\"type\":\"word\",\"start\":424,\"end\":426,\"value\":\"92\"}\n {\"time\":22950,\"type\":\"word\",\"start\":427,\"end\":430,\"value\":\"and\"}\n {\"time\":23126,\"type\":\"word\",\"start\":431,\"end\":435,\"value\":\"then\"}\n {\"time\":23369,\"type\":\"word\",\"start\":436,\"end\":442,\"value\":\"sailed\"}\n {\"time\":23897,\"type\":\"word\",\"start\":443,\"end\":445,\"value\":\"to\"}\n {\"time\":24011,\"type\":\"word\",\"start\":446,\"end\":450,\"value\":\"Cuba\"}\n {\"time\":24453,\"type\":\"word\",\"start\":451,\"end\":454,\"value\":\"and\"}\n {\"time\":24715,\"type\":\"word\",\"start\":455,\"end\":465,\"value\":\"Hispaniola\"}\n {\"time\":26262,\"type\":\"word\",\"start\":467,\"end\":469,\"value\":\"an\"}\n {\"time\":26413,\"type\":\"word\",\"start\":470,\"end\":476,\"value\":\"island\"}\n {\"time\":26834,\"type\":\"word\",\"start\":477,\"end\":481,\"value\":\"that\"}\n {\"time\":27028,\"type\":\"word\",\"start\":482,\"end\":487,\"value\":\"Haiti\"}\n {\"time\":27492,\"type\":\"word\",\"start\":488,\"end\":491,\"value\":\"and\"}\n {\"time\":27729,\"type\":\"word\",\"start\":492,\"end\":495,\"value\":\"the\"}\n {\"time\":27816,\"type\":\"word\",\"start\":496,\"end\":505,\"value\":\"Dominican\"}\n {\"time\":28508,\"type\":\"word\",\"start\":506,\"end\":514,\"value\":\"Republic\"}\n {\"time\":29122,\"type\":\"word\",\"start\":515,\"end\":520,\"value\":\"share\"}\n {\"time\":29481,\"type\":\"word\",\"start\":521,\"end\":526,\"value\":\"today\"}\n {\"time\":30777,\"type\":\"word\",\"start\":573,\"end\":577,\"value\":\"Help\"}\n {\"time\":31089,\"type\":\"word\",\"start\":578,\"end\":581,\"value\":\"Tom\"}\n {\"time\":31427,\"type\":\"word\",\"start\":582,\"end\":587,\"value\":\"Scour\"}\n {\"time\":31957,\"type\":\"word\",\"start\":588,\"end\":591,\"value\":\"His\"}\n {\"time\":32224,\"type\":\"word\",\"start\":592,\"end\":596,\"value\":\"Curb\"}`,\n\n bookZoomLevels: [80, 90, 100, 120, 140, 160, 180, 200],\n audioHighlightLeadTime: 50,\n audioDelayBetweenPages: 200,\n audioResyncTime: 160,\n topToolbarToggleHeight: 40,\n bottomToolbarHeight: 80,\n // closeBookTimeout: 1000 * 60 * 5, // 5 minutes,\n // closeBookTimeout: 1000 * 60 * 5 * 100, // 500 minutes,\n // closeBookWarning: 1000 * 60 * 0.5, // 30 seconds\n // closeBookWarning: 1000 * 60 * 0.5 * 500, // 250 min\n forceLogoutTime: 1000 * 60 * 60 * 24 * 30, // 30 days,\n forceLogoutTimeWarning: 1000 * 60 * 60 * 24 * 27, // 30 days,\n};\n\nexport default constants;\n","import { camelCase } from 'lodash';\nimport dibsLogo from '../images/dibs-logo.png';\nimport brainhiveLogo from '../images/logo.png';\nimport themesById from '../constants/themes.json';\nimport BookFS from '../api/bookFS';\nimport config from '../api/config';\nimport { pWaCompatUtil } from './pWaCompatUtil';\nimport { CSSProp } from 'styled-components';\n\ninterface Itheme {\n name: string;\n logoSrc: string;\n primaryBackground: string;\n primaryDark: string;\n primaryLight:string;\n primaryFontColor: string;\n secondaryBackground: string;\n secondaryButtonStyle?: CSSProp; // generated on front end\n warningButtonStyle?: CSSProp;\n primaryButtonStyle?: CSSProp;\n successButtonStyle?: CSSProp;\n primaryIconOnlyButtonStyle?: CSSProp;\n secondaryDark: string;\n secondaryLight: string;\n secondaryFontColor: string;\n warningBackground: string;\n warningDark: string;\n warningLight: string;\n warningFontColor: string;\n successBackground: string;\n successDark: string;\n successLight: string;\n successFontColor: string;\n error: string;\n manifestUrl: string;\n}\n\nexport const themeProvider = {\n activeTheme: themesById['default'] as Itheme,\n themesById: undefined as {[key:string]: Itheme} | undefined, // only populated if we have received updated themes from the API\n initTheme: function () {\n return BookFS.fs.getItem('activeTheme').then((persistedActiveTheme: any) => {\n // apply any updates we might have received into themesByID\n if (this.themesById) {\n console.log('init theme from API');\n return this.setTheme(\n this.selectThemeBySubdomain(this.themesById)\n );\n } else if (persistedActiveTheme) {\n console.log('init persisted theme');\n return this.setTheme(persistedActiveTheme);\n } else {\n console.log('init fallback theme');\n // no persistedTheme, and no updated themes from the API, fallback to local json version of themes\n return this.setTheme(this.selectThemeBySubdomain());\n }\n }).catch(error => console.error('error initializing theme', error));\n },\n selectThemeBySubdomain: function (themes: {[key:string]: Itheme} = themesById) {\n let subdomain = 'default';\n let hasTheme = false;\n Object.keys(themes).forEach((key) => {\n hasTheme = window.location.href.search(key) !== -1;\n if (hasTheme) {\n subdomain = key;\n }\n });\n return themes[subdomain];\n },\n normalizeTheme: function (theme: Itheme) {\n // if the theme does not have an attribute, fall back to the default attribute\n const defaultTheme = this.selectThemeBySubdomain();\n Object.keys(defaultTheme).forEach((key) => {\n theme = { ...theme, [key]: theme[key as keyof Itheme] || defaultTheme[key as keyof Itheme] };\n });\n\n let logo = theme.logoSrc;\n if (theme.name === 'brainhive') {\n logo = brainhiveLogo;\n }\n if (theme.name === 'default') {\n logo = dibsLogo;\n }\n const warningButtonStyle = {\n 'background-color': theme.warningBackground,\n 'border-bottom-color': theme.warningDark,\n color: theme.warningFontColor,\n '&:active': {\n 'background-color': theme.warningDark,\n 'border-bottom-color': '#000'\n }\n };\n const primaryButtonStyle = {\n 'background-color': theme.primaryBackground,\n 'border-bottom-color': theme.primaryDark,\n color: theme.primaryFontColor,\n '&:active': {\n 'background-color': theme.primaryDark,\n 'border-bottom-color': '#000'\n }\n };\n const secondaryButtonStyle = {\n 'background-color': theme.secondaryBackground,\n 'border-bottom-color': theme.secondaryDark,\n color: theme.secondaryFontColor,\n '&:active': {\n 'background-color': theme.secondaryDark,\n 'border-bottom-color': '#000'\n }\n };\n const successButtonStyle = {\n 'background-color': theme.successBackground,\n 'border-bottom-color': theme.successDark,\n color: theme.successFontColor,\n '&:active': {\n 'background-color': theme.successDark,\n 'border-bottom-color': '#000'\n }\n };\n const primaryIconOnlyButtonStyle = {\n color: theme.primaryBackground,\n '&:active': {\n color: theme.primaryDark\n }\n };\n return {\n ...theme,\n logo,\n warningButtonStyle,\n primaryButtonStyle,\n secondaryButtonStyle,\n successButtonStyle,\n primaryIconOnlyButtonStyle\n };\n },\n setTheme: function (theme: Itheme) {\n // console.log('persisting theme', theme); // TODO why are we persisting so many times?\n this.activeTheme = this.normalizeTheme(theme);\n const manifestPlaceholder = document\n .querySelector('#my-manifest-placeholder');\n if (manifestPlaceholder){\n manifestPlaceholder.setAttribute('href', this.activeTheme.manifestUrl);\n pWaCompatUtil();\n }\n return BookFS.fs.setItem('activeTheme', theme);\n },\n checkUpdatedThemes: function () {\n const URL = `${config.API.Admin}/home/getviewerthemes`;\n var request = new Request(URL, { method: 'GET' });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((res) => {\n this.themesById = res.reduce((themes: any, t: any) => {\n return {\n ...themes,\n [t.Name]: Object.keys(t).reduce(\n (camelCaseKeys, rawKey) => {\n return {\n ...camelCaseKeys,\n [camelCase(rawKey)]: t[rawKey]\n };\n },\n {}\n )\n };\n }, {});\n // console.log('themes', JSON.stringify(this.themesById))\n return this.initTheme();\n })\n .catch((error) => {\n console.error('unable to check for updated theme', error);\n });\n }\n};\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAABQCAYAAAAN+QnTAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0Y1RUY0Nzk4NjNBMTFFNTlBOUI4NkM3NkRBOTEyMDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0Y1RUY0N0E4NjNBMTFFNTlBOUI4NkM3NkRBOTEyMDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDRjVFRjQ3Nzg2M0ExMUU1OUE5Qjg2Qzc2REE5MTIwNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDRjVFRjQ3ODg2M0ExMUU1OUE5Qjg2Qzc2REE5MTIwNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pm940fMAABLGSURBVHja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\"","export const BEGIN_AJAX_CALL = 'BEGIN_AJAX_CALL';\nexport const END_AJAX_CALL = 'END_AJAX_CALL';\n\nexport const USER_LOGIN_SUCCESS = 'USER_LOGIN_SUCCESS';\nexport const USER_LOGIN_FAILED = 'USER_LOGIN_FAILED';\nexport const USER_LOGOUT_SUCCESS = 'USER_LOGOUT_SUCCESS';\nexport const USER_UPDATE_SUCCESS = 'USER_UPDATE_SUCCESS';\nexport const USER_UPDATE_FAILED = 'USER_UPDATE_FAILED';\nexport const USER_UPDATE_PASSWORD_SUCCESS = 'USER_UPDATE_PASSWORD_SUCCESS';\nexport const USER_UPDATE_PASSWORD_FAILED = 'USER_UPDATE_PASSWORD_FAILED';\nexport const USER_ADD_CLASS_CODE_SUCCESS = 'USER_ADD_CLASS_CODE_SUCCESS';\nexport const USER_ADD_CLASS_CODE_FAILED = 'USER_ADD_CLASS_CODE_FAILED';\nexport const TOGGLE_CLASS_CODE_MODAL = 'TOGGLE_ADD_CLASS_CODE_MODAL';\n\nexport const HIGHLIGHTS_UPDATE_SUCCESS = 'HIGHLIGHTS_UPDATE'; //_SUCCESS\n\nexport const LOAD_BOOKS_SUCCESS = 'LOAD_BOOKS_SUCCESS';\nexport const LOAD_BOOKS_FAILED = 'LOAD_BOOKS_FAILED';\n\nexport const DASHBOARD_PAGE_RESULTS = 'DASHBOARD_PAGE_RESULTS';\n\nexport const FETCH_BOOK_SUCCESS = 'FETCH_BOOK_SUCCESS';\nexport const FETCH_BOOK_FAILED = 'FETCH_BOOK_FAILED';\n\nexport const LOAD_BOOK_SUCCESS = 'LOAD_BOOK_SUCCESS';\n\nexport const FETCH_BOOKITEMS_SUCCESS = 'FETCH_BOOKITEMS_SUCCESS';\nexport const FETCH_BOOKITEMS_FAILED = 'FETCH_BOOKITEMS_FAILED';\nexport const FETCH_BOOKITEMS_STUDENT_SUCCESS =\n 'FETCH_BOOKITEMS_STUDENT_SUCCESS';\nexport const FETCH_BOOKITEMS_STUDENT_FAILED = 'FETCH_BOOKITEMS_STUDENT_FAILED';\n\nexport const SAVE_BOOKITEM_BOOKMARK_SUCCESS = 'SAVE_BOOKITEM_BOOKMARK_SUCCESS';\nexport const SAVE_BOOKITEM_HIGHLIGHT_SUCCESS =\n 'SAVE_BOOKITEM_HIGHLIGHT_SUCCESS';\nexport const SAVE_BOOKITEM_NOTE_SUCCESS = 'SAVE_BOOKITEM_NOTE_SUCCESS';\nexport const SAVE_BOOKITEM_FAILED = 'SAVE_BOOKITEM_FAILED';\n\nexport const UPDATE_STUDENT_ITEM_SUCCESS = 'UPDATE_STUDENT_ITEM_SUCCESS';\nexport const UPDATE_TEMPLATE_ITEM_SUCCESS = 'UPDATE_TEMPLATE_ITEM_SUCCESS';\n\nexport const DELETE_BOOKITEM_BOOKMARK_SUCCESS =\n 'DELETE_BOOKITEM_BOOKMARK_SUCCESS';\nexport const DELETE_BOOKITEM_HIGHLIGHT_SUCCESS =\n 'DELETE_BOOKITEM_HIGHLIGHT_SUCCESS';\nexport const DELETE_BOOKITEM_NOTE_SUCCESS = 'DELETE_BOOKITEM_NOTE_SUCCESS';\nexport const DELETE_BOOKITEM_FAILED = 'DELETE_BOOKITEM_FAILED';\n\nexport const UPDATE_BOOKSTATUS_SUCCESS = 'UPDATE_BOOKSTATUS_SUCCESS';\nexport const UPDATE_BOOKSTATUS_FAILED = 'UPDATE_BOOKSTATUS_FAILED';\n\nexport const DOWNLOADED_BOOK_SUCCESS = 'DOWNLOADED_BOOK_SUCCESS';\nexport const DOWNLOADED_BOOK_FAILED = 'DOWNLOADED_BOOK_FAILED';\nexport const DELETE_DOWNLOADED_BOOK = 'DELETE_DOWNLOADED_BOOK';\n\nexport const DOWNLOADED_SPEECH_SUCCESS = 'DOWNLOADED_SPEECH_SUCCESS';\nexport const DOWNLOADED_SPEECH_FAILED = 'DOWNLOADED_SPEECH_FAILED';\n\nexport const GET_SPEECH_MARKS_LOCAL = 'GET_SPEECH_MARKS_LOCAL';\nexport const GET_SPEECH_MARKS = 'GET_SPEECH_MARKS';\n\nexport const RESET_BOOK = 'RESET_BOOK';\nexport const SET_BOOK_READY = 'SET_BOOK_READY';\nexport const SET_PROJECT_READY = 'SET_PROJECT_READY';\n\nexport const CACHE_BOOK_PAGE = 'CACHE_BOOK_PAGE';\nexport const RESET_CACHED_BOOK_PAGES = 'RESET_CACHED_BOOK_PAGES';\n\nexport const FETCH_BLM_SUCCESS = 'FETCH_BLM_SUCCESS';\nexport const FETCH_BLM_FAILED = 'FETCH_BLM_FAILED';\n\nexport const UPDATE_BLM_DATA_SUCCESS = 'UPDATE_BLM_DATA_SUCCESS';\nexport const UPDATE_BLM_DATA_FAILED = 'UPDATE_BLM_DATA_FAILED';\n\nexport const SAVE_BLMITEM_FABRIC_SUCCESS = 'SAVE_BLMITEM_FABRIC_SUCCESS';\nexport const SAVE_BLMITEM_FABRIC_FAILED = 'SAVE_BLMITEM_FABRIC_FAILED';\n\nexport const REMOVE_BLM_DATA_SUCCESS = 'REMOVE_BLM_DATA_SUCCESS';\n\nexport const GET_BLM_ITEMS_SUCCESS = 'GET_BLM_ITEMS_SUCCESS';\nexport const GET_BLM_ITEMS_FAILED = 'GET_BLM_ITEMS_FAILED';\n\nexport const LOAD_BLMS_SUCCESS = 'LOAD_BLMS_SUCCESS';\nexport const LOAD_BLMS_FAILED = 'LOAD_BLMS_FAILED';\n\nexport const EMPTY_BLMS_SUCCESS = 'EMPTY_BLMS_SUCCESS';\n\nexport const SELECTED_BLM_SUCCESS = 'SELECTED_BLM_SUCCESS';\n\nexport const UPDATE_BLM_STATUS_SUCCESS = 'UPDATE_BLM_STATUS_SUCCESS';\nexport const UPDATE_BLM_STATUS_FAILED = 'UPDATE_BLM_STATUS_FAILED';\n\nexport const BLM_DRAFT_SAVED_SUCCESS = 'BLM_DRAFT_SAVED_SUCCESS';\n\nexport const UPDATE_MODE_SUCCESS = 'UPDATE_MODE_SUCCESS';\nexport const BOOK_TOOLBAR_UPDATE_MODE = 'BOOK_TOOLBAR_UPDATE_MODE';\n\nexport const GET_COMPLETED_BLMS_SUCCESS = 'GET_COMPLETED_BLMS_SUCCESS';\nexport const GET_COMPLETED_BLMS_FAILED = 'GET_COMPLETED_BLMS_FAILED';\n\nexport const GET_BLM_STATUS_SUCCESS = 'GET_BLM_STATUS_SUCCESS';\nexport const GET_BLM_STATUS_FAILED = 'GET_BLM_STATUS_FAILED';\n\nexport const GET_TEACHERS_BLM_COMMENT_SUCCESS =\n 'GET_TEACHERS_BLM_COMMENT_SUCCESS';\nexport const GET_TEACHERS_BLM_COMMENT_FAILED =\n 'GET_TEACHERS_BLM_COMMENT_FAILED';\n\nexport const SAVE_TEACHERS_COMMENT_SUCCESS = 'SAVE_TEACHERS_COMMENT_SUCCESS';\nexport const SAVE_TEACHERS_COMMENT_FAILED = 'SAVE_TEACHERS_COMMENT_FAILED';\n\nexport const SAVE_ADVANCED_SEARCH_FILTERS = 'SAVE_ADVANCED_SEARCH_FILTERS';\nexport const CLEAR_ADVANCED_SEARCH_FILTERS = 'CLEAR_ADVANCED_SEARCH_FILTERS';\n\nexport const ADD_BOOK_TO_BOOKBAG_SUCCESS = 'ADD_BOOK_TO_BOOKBAG_SUCCESS';\nexport const ADD_BOOK_TO_BOOKBAG_FAILED = 'ADD_BOOK_TO_BOOKBAG_FAILED';\nexport const REMOVE_BOOK_TO_BOOKBAG_SUCCESS = 'REMOVE_BOOK_TO_BOOKBAG_SUCCESS';\nexport const REMOVE_BOOK_TO_BOOKBAG_FAILED = 'REMOVE_BOOK_TO_BOOKBAG_FAILED';\nexport const PURGE_TEMP_ID_NOTES = 'PURGE_TEMP_ID_NOTES';\nexport const UPDATE_CURRENT_PAGE = 'UPDATE_CURRENT_PAGE';\n\nexport const TOGGLE_USER_PROFILE_MODAL = 'TOGGLE_USER_PROFILE_MODAL';\nexport const TOGGLE_LOGGOUT_CONFIRM_MODAL = 'TOGGLE_LOGGOUT_CONFIRM_MODAL';\n\n// BLM TOOLBAR\nexport const TOGGLE_BLM_TOOLBAR_ERASER = 'TOGGLE_BLM_TOOLBAR_ERASER';\nexport const TOOLBAR_ERASER_OFF = 'TOOLBAR_ERASER_OFF';\nexport const TOOLBAR_ERASER_ON = 'TOOLBAR_ERASER_ON';\n\nexport const TOOLBAR_DRAWING_MODE_ON = 'TOOLBAR_DRAWING_MODE_ON';\nexport const TOOLBAR_POINTER_ON = 'TOOLBAR_POINTER_ON';\nexport const TOOLBAR_ADD_TEXT_ON = 'TOOLBAR_ADD_TEXT_ON';\nexport const SHOW_RICH_TEXT_BUTTONS = 'SHOW_RICH_TEXT_BUTTONS';\n\nexport const NEXT_PAGE = 'NEXT_PAGE';\nexport const PREV_PAGE = 'PREV_PAGE';\nexport const SCALE_PERCENT = 'SCALE_PERCENT';\nexport const FIRST_PAGE = 'FIRST_PAGE';\nexport const LAST_PAGE = 'LAST_PAGE';\nexport const TOTAL_PAGE = 'TOTAL_PAGE';\n\n// Viewer / BookView\nexport const UPDATE_LEFT_PAGE_CONTAINER = 'UPDATE_LEFT_PAGE_CONTAINER';\nexport const UPDATE_BOOK_SCALE_PERCENT = 'UPDATE_BOOK_SCALE_PERCENT';\nexport const UPDATE_PROJECT_SCALE_PERCENT = 'UPDATE_PROJECT_SCALE_PERCENT';\nexport const UPDATE_PAGES_VISIBLE = 'UPDATE_PAGES_VISIBLE';\nexport const AUTOMATIC_UPDATE_PAGES_VISIBLE = 'AUTOMATIC_UPDATE_PAGES_VISIBLE';\nexport const RESET_VIEW = 'RESET_VIEW';\nexport const BOOK_TOOLBAR_POINTING = 'BOOK_TOOLBAR_POINTING';\nexport const BOOK_TOOLBAR_NOTES = 'BOOK_TOOLBAR_NOTES';\nexport const BOOK_TOOLBAR_HIGHLIGHTING = 'BOOK_TOOLBAR_HIGHLIGHTING';\nexport const BOOK_TOOLBAR_ERASING = 'BOOK_TOOLBAR_ERASING';\nexport const BOOK_TOOLBAR_UNDERLINING = 'BOOK_TOOLBAR_UNDERLINING';\nexport const BOOK_TOOLBAR_STRIKING = 'BOOK_TOOLBAR_STRIKING';\nexport const BOOK_TOOLBAR_MOVING = 'BOOK_TOOLBAR_MOVING';\nexport const SET_ACTIVE_NOTE = 'SET_ACTIVE_NOTE';\nexport const INCREASE_BOOK_ZOOM = 'INCREASE_BOOK_ZOOM';\nexport const DECREASE_BOOK_ZOOM = 'DECREASE_BOOK_ZOOM';\nexport const UPDATE_PENDING_ITEM = 'UPDATE_PENDING_ITEM';\nexport const BOOK_UPDATE_AUDIO = 'BOOK_UPDATE_AUDIO';\nexport const READIUM_INITIALIZED = 'READIUM_INITIALIZED';\n","import * as types from './actionTypes';\n\nexport function beginAjaxCall() {\n return { type: types.BEGIN_AJAX_CALL };\n}\n\nexport function endAjaxCall() {\n return { type: types.END_AJAX_CALL };\n}\n\nexport function manualAjaxStart() {\n return function (dispatch) {\n dispatch(beginAjaxCall());\n };\n}\n\nexport function manualAjaxEnd() {\n return function (dispatch) {\n dispatch(endAjaxCall());\n };\n}\n","import * as React from 'react';\nimport { Modal } from 'react-bootstrap';\n\nclass Loading extends React.Component {\n render() {\n return (\n \n \n

{this.props.message || 'LOADING...'}

\n \n
\n
\n );\n }\n}\n\nexport default Loading;\n","export const viewerModes = {\n MODE_GENERIC: 'generic',\n MODE_TEACHER_VIEW_STUDENT_BOOK: 'teacherstudentnotes',\n MODE_TEACHER_CLASS_NOTES: 'teacherclassnotes',\n MODE_TEACHER_GROUP_NOTES: 'teachergroupnotes',\n MODE_TEACHER_STUDENT_BLM: 'teacherstudentblm',\n MODE_TEACHER_BLM: 'teacherblm',\n MODE_ADMIN_CREATE_TEMPLATE: 'create',\n MODE_RESOURCE: 'resource',\n MODE_STUDENT: 'student'\n};\n","import config from './config';\nimport { viewerModes } from '../constants/viewerModes';\n\nexport default class UserAPI {\n static login(loginID, password, schoolID) {\n var URL = `${config.API.Main}/student/login`;\n var data = { loginID, password, schoolID };\n var body = JSON.stringify(data);\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(),\n body: body,\n credentials: 'include'\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((jsonData) => {\n return jsonData;\n });\n }\n\n static tokenLogin(token) {\n var URL = `${config.API.Main}/account/tokenlogin?token=${token}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(),\n credentials: 'include'\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((jsonData) => {\n return jsonData;\n });\n }\n\n static googleTokenLogin(authorizationCode, schoolID) {\n var URL = `${config.API.Main}/google/tokenlogin`;\n var body = JSON.stringify({\n googleAuthorizationCode: authorizationCode,\n schoolID\n });\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(),\n body: body\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((data) => {\n if (!data) {\n return Promise.reject({\n message:\n 'Unknown server error. Please try again or contact support.'\n });\n } else {\n return data;\n }\n });\n }\n\n static updateBookStatus(\n bookID,\n currentPage,\n totalPages,\n pageView,\n bookTimeout,\n user\n ) {\n var URL = `${config.API.Main}/student/updatebookstatus `;\n // var body = JSON.stringify({ bookID, currentPage });\n bookTimeout = bookTimeout ? true : '';\n let body = `bookID=${bookID}¤tPage=${currentPage}&totalPages=${totalPages}&pageView=${pageView}&bookTimeout=${bookTimeout}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeadersUrlEncode(user),\n body: body\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((jsonData) => {\n return jsonData;\n });\n }\n\n // Check if a user is valid and get back current user object\n static checkSession(user) {\n var URL = `${config.API.Main}/account/checksession`;\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static updateProfile(user, firstName, lastName, loginID) {\n var URL = `${config.API.Main}/student/updateprofile`;\n let body = `first=${firstName}&last=${lastName}&loginID=${loginID}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeadersUrlEncode(user),\n body: body\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((jsonData) => {\n return jsonData;\n });\n }\n\n static addClassCode(user, code) {\n var URL = `${config.API.Main}/student/AddClassGroupCode?code=${code}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeadersUrlEncode(user),\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.text();\n })\n .then((jsonData) => {\n return jsonData;\n });\n }\n\n static updateProfilePW(user, password) {\n var URL = `${config.API.Main}/student/updatepassword`;\n let body = `password=${password}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeadersUrlEncode(user),\n body: body\n });\n\n return fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n })\n .then((jsonData) => {\n return jsonData;\n });\n }\n\n /*\n Get schools\n */\n static getSchools(search) {\n const URL = `${config.API.Main}/school/viewersearch?search=${search}`;\n var request = new Request(URL, { method: 'GET' });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getAdvancedSearch(search, user) {\n const URL = `${config.API.Main}/tag/gettagsinaschool?search=${search}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /*\n Convenience method to construct headers using a user object to obtain\n their apiKey\n*/\n static getHeaders(user = false) {\n var headers = new Headers();\n headers.append('Content-Type', 'application/json');\n headers.append('Accept', 'application/json');\n if (!!user) {\n headers.append('apiKey', user.APIKey || '');\n }\n return headers;\n }\n\n static getHeadersUrlEncode(user = false) {\n var headers = new Headers();\n headers.append('Content-Type', 'application/x-www-form-urlencoded');\n if (!!user) {\n headers.append('apiKey', user.APIKey || '');\n }\n return headers;\n }\n\n // Temporary fix for check session roleID being undefined\n // Other Solutions:\n // 1. Check if user is undefined in top component except where there is needed authorization\n // 2. Add a else statement that returns either null or some other property\n // Remember, good things come to those who are patient but better things to those who are crafty. :D\n static canAccessBook(roleID, viewerMode) {\n if (\n roleID !== undefined &&\n (roleID.toUpperCase() ===\n config.UserRoleIDs.Generic.toUpperCase() ||\n viewerMode === viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK ||\n viewerMode === viewerModes.MODE_TEACHER_GROUP_NOTES ||\n viewerMode === viewerModes.MODE_TEACHER_CLASS_NOTES ||\n roleID.toUpperCase() ===\n config.UserRoleIDs.Student.toUpperCase() ||\n viewerMode === viewerModes.MODE_TEACHER_STUDENT_BLM)\n ) {\n return true;\n } else {\n return false;\n }\n }\n static isStudent(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() ===\n config.UserRoleIDs.Student.toUpperCase()\n );\n } else {\n return false;\n }\n }\n static isTeacher(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() ===\n config.UserRoleIDs.Teacher.toUpperCase()\n );\n } else {\n return false;\n }\n }\n static isSuperAdmin(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() ===\n config.UserRoleIDs.SuperAdmin.toUpperCase()\n );\n } else {\n return false;\n }\n }\n static isSchoolAdmin(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() ===\n config.UserRoleIDs.SchoolAdmin.toUpperCase()\n );\n } else {\n return false;\n }\n }\n static isSalesRep(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() ===\n config.UserRoleIDs.SalesRep.toUpperCase()\n );\n } else {\n return false;\n }\n }\n static isGeneric(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() ===\n config.UserRoleIDs.Generic.toUpperCase()\n );\n } else {\n return false;\n }\n }\n static isDemo(roleID) {\n if (roleID !== undefined) {\n return (\n roleID.toUpperCase() === config.UserRoleIDs.Demo.toUpperCase()\n );\n } else {\n return false;\n }\n }\n}\n","/*\n* A little util from https://github.com/ReactTraining/react-router/issues/1100\n*/\nimport { hashHistory } from 'react-router';\n/**\n * @param {Object} query\n */\nexport const addQuery = (query) => {\n const location = Object.assign({}, hashHistory.getCurrentLocation());\n Object.assign(location.query, query);\n hashHistory.push(location);\n};\n\n/**\n * @param {...String} queryNames\n */\nexport const removeQuery = (...queryNames) => {\n const location = Object.assign({}, hashHistory.getCurrentLocation());\n queryNames.forEach(q => delete location.query[q]);\n hashHistory.push(location);\n};\n","import * as types from './actionTypes';\nimport UserAPI from '../api/userAPI';\nimport { beginAjaxCall } from './ajaxStatusActions';\nimport BookFS from '../api/bookFS';\nimport { debounce } from 'lodash';\nimport { toastr } from 'react-redux-toastr';\nimport { hashHistory } from 'react-router';\nimport { removeQuery } from '../vendor/utils-router';\nimport constants from '../constants/constants';\n\nexport function userLoginSuccess(user) {\n return { type: types.USER_LOGIN_SUCCESS, user };\n}\n\nexport function userLoginFailed(error) {\n return { type: types.USER_LOGIN_FAILED, error };\n}\n\nexport function userLogoutSuccess() {\n return { type: types.USER_LOGOUT_SUCCESS, user: {} };\n}\n\nexport function userRegister(user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n var { gender, first, last, loginID, password, role, roleID } = user;\n return UserAPI.register(\n gender,\n first,\n last,\n loginID,\n password,\n roleID,\n role\n )\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'unknown server error';\n } else {\n dispatch(userLoginSuccess(data));\n return data;\n }\n })\n .catch((error) => {\n dispatch(userLoginFailed(error));\n throw error;\n });\n };\n}\n\nexport function userUpdateProfile(user, firstName, lastName, loginID) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return UserAPI.updateProfile(user, firstName, lastName, loginID)\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'unknown server error';\n } else {\n dispatch({ type: types.USER_UPDATE_SUCCESS, user: data });\n return data;\n }\n })\n .catch((error) => {\n dispatch({ type: types.USER_UPDATE_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function addClassCode(code) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n const {user} = getState();\n return UserAPI.addClassCode(user, code)\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'unknown server error';\n } else {\n if (typeof data === 'string' && data.search('error') !== -1){\n const stringifiedData = data.replace(\"error\", \"'error'\").replaceAll('\"', '').replaceAll(\"'\", '\"');\n const parsedData = JSON.parse(stringifiedData);\n if (parsedData.error){\n throw new Error(parsedData.error); \n }\n }\n dispatch({ type: types.USER_ADD_CLASS_CODE_SUCCESS, user: data });\n dispatch(toggleClassCodeModal());\n toastr.success('Success', `${data} added successfully.`, constants.toastrSuccessOptions)\n }\n })\n .catch((error) => {\n console.error('error adding classcode', error)\n dispatch({ type: types.USER_ADD_CLASS_CODE_FAILED, error });\n let message = 'Error adding class or group code. Please try again or contact support.';\n if (error && error.message){\n message = error.message;\n }\n toastr.error('Error', message, constants.toastrErrorOptions)\n });\n };\n}\n\nexport const toggleClassCodeModal = (show) => ({\n type: types.TOGGLE_CLASS_CODE_MODAL,\n show\n});\n\nexport function userUpdatePW(user, password) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return UserAPI.updateProfilePW(user, password)\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'unknown server error';\n } else {\n dispatch({\n type: types.USER_UPDATE_PASSWORD_SUCCESS,\n user: data\n });\n return data;\n }\n })\n .catch((error) => {\n dispatch({ type: types.USER_UPDATE_PASSWORD_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function userLogin(loginID, password, schoolID) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return UserAPI.login(loginID, password, schoolID)\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'unknown server error';\n } else {\n dispatch(userLoginSuccess(data));\n dispatch(checkSession(data)); // check session in order to get the School\n return data;\n }\n })\n .catch((error) => {\n dispatch(userLoginFailed(error));\n throw error;\n });\n };\n}\n\nexport function confirmChangeSchoolID(schoolID) {\n return function (dispatch, getState) {\n const onOk = () => {\n if (schoolID){\n hashHistory.replace(`/?changeSchoolID=${schoolID}`);\n } else {\n hashHistory.replace(`/`);\n }\n };\n toastr.confirm(\n 'You are already logged into another school/user account. Do you want to logout?',\n {\n okText: 'Logout',\n cancelText: 'Cancel',\n onOk,\n onCancel: () => {\n removeQuery(['schoolID']);\n removeQuery(['SchoolID']);\n removeQuery(['schoolid']);\n removeQuery(['schoolId']);\n window.location.reload();\n }\n }\n );\n };\n}\n\nexport function userLogout() {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return new Promise((resolve, reject) => {\n dispatch(userLogoutSuccess());\n BookFS.removeAll()\n .then(() => {\n console.log('successfully removed all directories');\n resolve();\n })\n .catch((err) => {\n console.error(err);\n resolve();\n });\n });\n };\n}\nexport function userLogoutSessionOnly() {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return new Promise((resolve, reject) => {\n dispatch(userLogoutSuccess());\n });\n };\n}\n\n/*\n * Token Login for Teachers\n */\nexport function tokenLogin(token) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return UserAPI.tokenLogin(token)\n .then((data) => {\n if (!data) {\n return Promise.reject({\n message: `token login failed, no data`\n });\n } else {\n dispatch(userLoginSuccess(data));\n return data;\n }\n })\n .catch((error) => {\n dispatch(userLoginFailed(error));\n return Promise.reject(error);\n });\n };\n}\n\n/*\n * Google Login for web and iOS\n */\nexport function googleTokenLogin(authorizationCode, schoolID) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return UserAPI.googleTokenLogin(authorizationCode, schoolID)\n .then((data) => {\n dispatch(userLoginSuccess(data));\n return data;\n })\n .catch((error) => {\n dispatch(userLoginFailed(error));\n return Promise.reject(error);\n });\n };\n}\n\n/*\n * CheckSession has 2 purposes. 1 is to verify that the DiBS API key is valid and 2 to renew the Azure token\n */\nexport function checkSession(user) {\n return function (dispatch, getState) {\n // dispatch(beginAjaxCall()); // no need to block the user while we check session\n return UserAPI.checkSession(user)\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'invalidApiKey';\n } else {\n dispatch({ type: types.USER_UPDATE_SUCCESS, user: data });\n return data;\n }\n })\n .catch((error) => {\n dispatch({ type: types.USER_UPDATE_FAILED, error });\n throw error;\n });\n };\n}\n\n/*\n * checkSessionUtil and DebouncedCheckSession handle expired Azure tokens.\n * it is debounced because when we get the files for a page we get 30+ files.\n * we only want to call this once if all 30 of those fail\n * after it renews the Azure token get the book again via an event listener in the bookView\n * the other time the Azure token fails is in the bookView component where it gets the BLM files - this is not curently handled\n * TODO turn all the BLM file getters into Actions and remove BLMAPI from bookview then handle expired Azure tokens\n */\nfunction checkSessionUtil(user, dispatch) {\n return UserAPI.checkSession(user)\n .then((data) => {\n if (!data) {\n // eslint-disable-next-line\n throw 'unknown server error';\n } else {\n dispatch({ type: types.USER_UPDATE_SUCCESS, user: data });\n // TODO move getBookHTMLPages from the BookView into the bookActions and then call it here.\n setTimeout(() => {\n document.dispatchEvent(new Event('renewedAzureToken'));\n }, 100);\n }\n })\n .catch((error) => {\n dispatch({ type: types.USER_UPDATE_FAILED, error });\n throw error;\n });\n}\nexport const debouncedCheckSession = debounce(checkSessionUtil, 5000);\n\nexport function isTouchDevice() {\n if ('ontouchstart' in window || navigator.maxTouchPoints) {\n return true;\n } else {\n return false;\n }\n}\n","import { ONLINE, OFFLINE } from 'redux-queue-offline';\n\nexport const setInitialNetworkStatus = () => ({\n type: navigator.onLine ? ONLINE : OFFLINE\n});\n","import React, { Component } from 'react';\nimport { manualAjaxEnd, manualAjaxStart } from './actions/ajaxStatusActions';\n\nimport Loading from './components/common/Loading';\nimport {\n checkSession,\n confirmChangeSchoolID,\n userLogout,\n userLogoutSessionOnly\n} from './actions/userActions';\nimport { connect } from 'react-redux';\nimport constants from './constants/constants';\nimport { hashHistory } from 'react-router';\nimport { toastr } from 'react-redux-toastr';\n\nimport { setInitialNetworkStatus } from './actions/commonActions';\nclass App extends Component {\n constructor(props) {\n super(props);\n this.state = {\n loading: true\n };\n\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n if (\n this.props.user &&\n this.props.user.APIKey &&\n this.props.user.APIKey !== ''\n ) {\n setTimeout(() => {\n this.shouldForceLogout();\n }, 1000);\n const initialSchoolID = this.props.schoolID;\n if (this.props.isOnline) {\n this.checkSession(initialSchoolID);\n constants.themeProvider.checkUpdatedThemes().then(() => {\n return constants.themeProvider.initTheme().then(() => {\n this.theme = constants.themeProvider.activeTheme;\n this.setState({ loading: true }, () => {\n this.setState({ loading: false });\n });\n });\n });\n }\n }\n constants.themeProvider.checkUpdatedThemes().then(() => {\n return constants.themeProvider\n .initTheme()\n .then(() => {\n this.theme = constants.themeProvider.activeTheme;\n this.setState({ loading: false });\n })\n .catch(() => {\n this.setState({ loading: false });\n });\n });\n document.addEventListener(\n 'newVersionAvailable',\n this.handleNewVersion,\n false\n );\n console.log('DISPATCHING ONLINE', navigator.onLine);\n }\n componentWillUnmount() {\n document.removeEventListener(\n 'newVersionAvailable',\n this.handleNewVersion,\n false\n );\n }\n handleNewVersion = () => {\n toastr.warning('Installing Update', 'Please wait...', {\n ...constants.toastrWarning,\n timeOut: 8000\n });\n setTimeout(() => {\n window.location.reload();\n }, 6000);\n };\n logout = () => {\n this.props\n .userLogout()\n .then(() => {\n this.props.manualAjaxEnd();\n setTimeout(() => {\n hashHistory.push('/');\n }, 500);\n })\n .catch((err) => {\n console.error(err);\n });\n };\n\n checkSession(initialSchoolID) {\n this.props.manualAjaxStart();\n this.props\n .checkSession(this.props.user)\n .then((resp) => {\n this.checkUpdatedSchoolID(initialSchoolID);\n this.props.manualAjaxEnd();\n })\n .catch((err) => {\n console.error('error while checking session', err);\n this.props.manualAjaxEnd();\n if (err && err === 'invalidApiKey') {\n toastr.warning('Session expired', 'Please login...', {\n ...constants.toastrWarning,\n timeOut: 5000\n });\n setTimeout(() => {\n this.props.userLogoutSessionOnly();\n }, 5000);\n }\n this.shouldForceLogout();\n });\n }\n\n /*\n * if it has been too long since renewing the session or logging in, then first warn, then force logout\n */\n shouldForceLogout = () => {\n const now = Date.now();\n if (\n now - this.props.user.lastCheckSession >\n constants.forceLogoutTime\n ) {\n toastr.warning(\n 'Session expired for more than 30 days',\n 'Please login...',\n {\n ...constants.toastrWarning,\n timeOut: 5000\n }\n );\n setTimeout(() => {\n this.props.userLogout();\n }, 5000);\n return;\n }\n\n if (\n now - this.props.user.lastCheckSession >\n constants.forceLogoutTimeWarning\n ) {\n console.info('session expired warning');\n toastr.warning(\n 'Session expired for more than 30 days',\n 'If you do not logout and login soon, you will be automatically logged out.',\n {\n ...constants.toastrWarning,\n timeOut: 0\n }\n );\n return;\n }\n };\n\n /*\n * shouldRedirectToBookBag\n * if we have a valid user and are not actively changing the school id then redirect to the bookbag\n */\n shouldRedirectToBookBag = () => {\n if (\n this.props.user.ID.length > 0 &&\n !this.props.changeSchoolID &&\n (this.props.location.pathname.search('login') !== -1 ||\n this.props.location.pathname === '/')\n ) {\n hashHistory.push('bag');\n }\n };\n\n /*\n * checkUpdatedSchoolID\n * when the schoolID in the URL is different from the User's schoolID, log them out\n */\n checkUpdatedSchoolID = (initialSchoolID) => {\n // console.log('checking school id', this.props.schoolID, this.props.user.SchoolID)\n if (initialSchoolID && this.props.user.SchoolID) {\n if (this.props.user.SchoolID !== initialSchoolID) {\n console.log(\n 'schoolID is different, logging out',\n this.props.user.SchoolID,\n initialSchoolID\n );\n this.props.confirmChangeSchoolID(initialSchoolID);\n }\n }\n };\n\n render() {\n if (this.state.loading === true) {\n return (\n \n \n \n \n \n );\n }\n return (\n \n
{this.props.children}
\n
\n );\n }\n}\n\nconst mapStateToProps = (state, ownProps) => {\n return {\n user: state.user,\n loading: state.ajaxCallsInProgress > 0,\n isOnline: state.offlineQueue.isOnline && navigator.onLine,\n schoolID:\n ownProps.location.query.SchoolID ||\n ownProps.location.query.schoolid ||\n ownProps.location.query.schoolID\n };\n};\n\nexport default connect(mapStateToProps, {\n userLogout,\n checkSession,\n userLogoutSessionOnly,\n manualAjaxStart,\n manualAjaxEnd,\n confirmChangeSchoolID,\n setInitialNetworkStatus\n})(App);\n","import styled from 'styled-components';\nimport { Button, Navbar, Row } from 'react-bootstrap';\n\nexport const StyledButton = styled(Button)`\n &&& {\n ${(props) => props.css}\n }\n`;\n\nexport const StyledNavbar = styled(Navbar)`\n &&& {\n ${(props) => props.css}\n }\n`;\n\nexport const StyledDiv = styled.div`\n &&& {\n ${(props) => props.css}\n }\n`;\n\nexport const StyledRow = styled(Row)`\n &&& {\n ${(props) => props.css}\n }\n`;\n","/*\n* 1: import this util with something like: import {validateField, validateForm} from '../common/UtilValidation.ts';\n 2: add formValidations and formValid to state\n 3: call validateAllFields inside didMount\n 4: call validateField inside handleChange like this:\n const fv = validateField(name, value, true, this.state.formValidations);\n const vf = validateForm(this.state.formValidations);\n this.setState({ [name]: value, formValidations: fv, formValid: vf });\n 5: update the react-bootstrap form elements\n 6: inside validateAllFields - add all the fields you want to validate\n 7: inside handleSubmit check state.formValid and if it is not valid then prevent submitting the form\n and display some sort of error encouraging the user to check their inputs\n 8: inside handleSubmit you also need to trigger re-validating the fields like this:\n this.validateAllFields(true);\n this.forceUpdate(); // needed because if the user clicks submit whithout touching some fields, then the inlide validation does not show as expected\n\n*\n*/\nimport { forEach, find } from 'lodash';\n// export interface FormField{\n// validationState: string;\n// validators: FormValidators[];\n// }\n\n// export interface FormValidations{\n// name: FormField;\n// }\n\n// export interface FormValidators{\n// pattern?: any;\n// require?: boolean;\n// message: string;\n// }\n\n/*\n * FORM VALIDATION\n */\nconst validate = (value: string, validator: any, matchValue?: string) => {\n let valid = true;\n if (validator.pattern && value.length > 0) {\n let newValue = value.match(validator.pattern);\n valid = newValue ? true : false;\n }\n if (validator.required) {\n valid = !!value.length || false;\n }\n if (validator.mustMatch) {\n valid = matchValue === value ? true : false;\n }\n return valid;\n};\nexport const validateField = (\n name: string,\n value: string,\n showErrors: boolean,\n formValidations: any,\n matchValue?: string\n) => {\n // loop over each field we need to validate\n forEach(formValidations, (field, key) => {\n if (key === name) {\n // let newFormValidations = Object.assign({}, this.state.formValidations);\n let errorMessage = '';\n\n // loop over each validation for this field, and set error to the error message if something is invalid\n field.validators.forEach((validator) => {\n if (!validate(value, validator, matchValue)) {\n errorMessage = validator.message;\n }\n });\n // after we have checked all the validators, is there an error message for this field?\n if (!errorMessage) {\n // no error message\n formValidations[name].validationState = 'success';\n formValidations[name].validationMessage = '';\n formValidations[name].valid = true;\n if (!showErrors) {\n formValidations[name].validationState = null;\n formValidations[name].validationMessage = '';\n }\n } else {\n // error\n // only show the errors if showErrors\n if (showErrors) {\n formValidations[name].validationState = 'error';\n formValidations[name].validationMessage = errorMessage;\n }\n\n formValidations[name].valid = false;\n }\n // return formValidations;\n // this.setState({formValidations: formValidations}, this.validateForm);\n }\n });\n return formValidations;\n};\n\nexport const validateForm = (formValidations: any) => {\n return !find(formValidations, ['valid', false]);\n // this.setState({formValid});\n};\n\nexport default validateField;\n","import {\n Col,\n FormControl,\n FormGroup,\n Container,\n Row,\n NavbarBrand,\n Form\n} from 'react-bootstrap';\nimport React, { Component } from 'react';\nimport {\n StyledButton,\n StyledNavbar\n} from '../../constants/styledComponents.js';\nimport { ToastContainer, ToastMessage } from 'react-toastr';\nimport {\n googleTokenLogin,\n userLogin,\n userLogout\n} from '../../actions/userActions';\nimport {\n manualAjaxEnd,\n manualAjaxStart\n} from '../../actions/ajaxStatusActions';\nimport { validateField, validateForm } from '../common/UtilValidation';\n\nimport AsyncSelect from 'react-select/lib/Async';\nimport { GoogleLogin } from 'react-google-login';\nimport UserAPI from '../../api/userAPI.js';\nimport config from '../../api/config';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants.js';\nimport debounce from 'throttle-debounce/debounce';\nimport { hashHistory } from 'react-router';\nimport { map } from 'lodash';\n/* global chrome */\n\nconst ToastMessageFactory = React.createFactory(ToastMessage.animation);\n\nconst convertToOptions = (items) => {\n return map(items, (item) => {\n if (item.District) {\n return {\n value: item.ID,\n label: `${item.Name} - ${item.District.Name}`\n };\n } else {\n return { value: '', label: '' };\n }\n });\n};\n\nconst initialComponentState = {\n loginID: '',\n password: '',\n schoolID: '',\n schools: [{ Name: 'type at least 3 characters' }],\n shouldHideSchoolSearch: false,\n formValidations: {\n loginID: {\n validationState: null,\n validationMessage: '',\n valid: true,\n validators: [\n { required: true, message: 'email or username is required' }\n ]\n },\n password: {\n validationState: null,\n validationMessage: '',\n valid: true,\n validators: [\n { required: true, message: 'password is required' },\n {\n pattern: '^.{3,}',\n message: 'Password must be at least 3 characters'\n }\n ]\n },\n schoolID: {\n validationState: null,\n validationMessage: '',\n valid: true,\n validators: [\n {\n required: true,\n message:\n 'You must select a School. Type at least 3 characters then wait for the list to populate.'\n }\n ]\n }\n },\n formValid: false\n /* loading the autosuggestTheme so that we can add \"form-control\" class to the input.\n * This lets us use the built in form validation classes built into react-bootstrap\n */\n};\n\nclass LoginForm extends Component {\n loginIDInput;\n passwordInput;\n toastCont;\n\n constructor(props) {\n super(props);\n\n this.state = initialComponentState;\n this.debouncedSchoolSearch = debounce(800, this.doSchoolSearch);\n console.log('theme in login form', constants.themeProvider.activeTheme);\n\n this.theme = constants.themeProvider.activeTheme;\n this.logo = this.theme.logo;\n }\n componentDidMount() {\n // console.log('login did mount', this.theme, window.dibsThemes)\n // console.log(\n // \"book and school from login form\",\n // this.props.bookID,\n // this.props.schoolID,\n // this.props.changeSchoolID,\n // this.theme.schoolID ? true : false\n // );\n // schoolID is retrieved first from the Theme, then from the Query params. if none then leave it blank and show the select\n\n const schoolIDFromTheme = this.theme.schoolID;\n const schoolID = schoolIDFromTheme || this.props.schoolID || '';\n this.setState(\n {\n schoolID,\n shouldHideSchoolSearch: !!schoolID\n },\n () => {\n // validate all the form fields but do not show errors\n this.validateAllFields(false);\n }\n );\n\n if (this.props.changeSchoolID) {\n this.handleChangeSchool();\n }\n this.shouldRedirectToBookBag();\n\n // if we are debugging, then pre-fill the login form with test bam\n if (config.Debug) {\n this.setState(\n {\n // loginID: 'audio',\n // password: 'audio',\n // loginID: '98765',\n // password: 'test',\n loginID: '87654',\n password: 'test',\n schoolID: '16fca1c8-d8fb-4452-aa77-99e1232b3e8d',\n schools: [{ Name: 'type at least 3 characters' }],\n shouldHideSchoolSearch: false,\n formValid: true\n },\n () => {\n this.validateAllFields(false);\n }\n );\n }\n }\n componentDidUpdate(prevProps) {\n if (this.props.schoolID !== prevProps.schoolID) {\n this.setState(\n {\n schoolID: this.props.schoolID || '',\n shouldHideSchoolSearch: !!this.props.schoolID\n },\n () => {\n // validate all the form fields but do not show errors\n this.validateAllFields(false);\n }\n );\n }\n if (\n this.props.changeSchoolID !== prevProps.changeSchoolID &&\n this.props.changeSchoolID &&\n this.props.changeSchoolID.length\n ) {\n this.handleChangeSchool();\n }\n }\n\n /*\n * shouldRedirectToBookBag\n * if we have a valid user and are not actively changing the school id then redirect to the bookbag\n */\n shouldRedirectToBookBag = () => {\n if (\n this.props.user.ID.length > 0 &&\n !this.props.changeSchoolID &&\n (this.props.location.pathname.search('login') !== -1 ||\n this.props.location.pathname === '/')\n ) {\n hashHistory.push('bag');\n }\n };\n handleChangeSchool = () => {\n this.props\n .userLogout()\n .then(() => {\n this.props.manualAjaxEnd();\n setTimeout(() => {\n hashHistory.push(\n `/login?schoolID=${this.props.changeSchoolID}`\n );\n }, 500);\n })\n .catch((err) => {\n console.error(err);\n });\n };\n\n handleChange = (e) => {\n // this.setState({ [e.target.name]: e.target.value });\n const name = e.target.name;\n const value = e.target.value;\n const fv = validateField(name, value, true, this.state.formValidations);\n const vf = validateForm(this.state.formValidations);\n\n this.setState({ [name]: value, formValidations: fv, formValid: vf });\n };\n\n validateAllFields = (showErrors) => {\n validateField(\n 'loginID',\n this.state.loginID,\n showErrors,\n this.state.formValidations\n );\n validateField(\n 'password',\n this.state.password,\n showErrors,\n this.state.formValidations\n );\n validateField(\n 'schoolID',\n this.state.schoolID,\n showErrors,\n this.state.formValidations\n );\n };\n\n handleLoginSuccess = () => {\n if (this.props.redirect && this.props.redirect.length) {\n hashHistory.push(this.props.redirect);\n } else if (this.props.bookID && this.props.bookID.length) {\n hashHistory.push(`viewer?bookID=${this.props.bookID}`);\n } else {\n hashHistory.push('/bag');\n }\n };\n\n handleLoginFailed = (error) => {\n let message = `Unable to login`;\n \n if (navigator.onLine === false){\n message = 'Please connect to the internet.'\n }\n if (error === undefined || (error && error.status === 404)) {\n message = `Sorry, we could not find a student account with that login information.`;\n }\n if (error && error.status === 417){\n message = 'Ooops, we found your account but the password is incorrect.'\n }\n if (error && error.status === 411){\n message = 'Ooops, we found your account, but you have selected the wrong school. Please contact your teacher or school administrator.'\n }\n if (error && error.status === 406){\n message = `Ooops, you are trying to login to the student portal with a teacher account. Please navigate to the admin portal if you were trying to login there.`\n }\n if (error && error.status === 412){\n message = `Ooops, we are having an issue logging in with Google. Please try again or contact support.`\n }\n\n this.toastCont.error(message, `Error`, {\n closeButton: true,\n showAnimation: 'animated fadeInUp'\n });\n }\n\n handleSubmit = (e) => {\n if (e !== '') {\n e.preventDefault();\n }\n if (this.state.formValid === false) {\n this.toastCont.error(\n `Please check form errors above and try again.`,\n `Login Error`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInUp'\n }\n );\n // validate and show errors\n this.validateAllFields(true);\n this.forceUpdate(); // needed because if the user clicks submit whithout touching some fields, then the inlide validation does not show as expected\n\n return;\n }\n\n this.props\n .userLogin(\n this.state.loginID,\n this.state.password,\n this.state.schoolID\n )\n .then((user) => {\n this.handleLoginSuccess();\n })\n .catch((error) => {\n console.error(`error logging in`, error);\n this.handleLoginFailed(error)\n });\n };\n\n goToRegister = () => {\n hashHistory.push('/register');\n };\n\n handleLoadOptions = (value, callback) => {\n this.debouncedSchoolSearch(value, callback);\n };\n\n doSchoolSearch = (value, callback) => {\n if (value.length >= 3) {\n this.props.manualAjaxStart();\n UserAPI.getSchools(value)\n .then((schools) => {\n // this.setState({ schools });\n const schoolOptions = convertToOptions(schools);\n this.props.manualAjaxEnd();\n callback(schoolOptions);\n })\n .catch((error) => {\n console.error(error);\n\n this.props.manualAjaxEnd();\n callback(null);\n });\n }\n };\n handleSchoolSelect = (selectedSchool) => {\n validateField(\n 'schoolID',\n selectedSchool.value,\n true,\n this.state.formValidations\n );\n // set the menu to only the selected item\n const fv = validateField(\n 'schoolID',\n selectedSchool.value,\n true,\n this.state.formValidations\n );\n const vf = validateForm(this.state.formValidations);\n\n this.setState({\n schoolID: selectedSchool.value,\n formValidations: fv,\n formValid: vf\n });\n };\n\n reqGoogleLogin = () => {\n this.props.manualAjaxStart();\n };\n\n responseGoogle = (resp) => {\n this.props.manualAjaxEnd();\n if (!!resp.error) {\n console.error('Error from Google Auth', resp);\n } else {\n this.handleTokenLogin(resp.tokenId);\n }\n };\n\n handleTokenLogin = (authorizationCode) => {\n this.props\n .googleTokenLogin(authorizationCode, this.state.schoolID)\n .then((user) => {\n if (user.Error) {\n throw { message: user.Error };\n }\n if (UserAPI.isStudent(user.roleID)) {\n hashHistory.push('/bag');\n } else {\n hashHistory.push('/bag');\n }\n })\n .catch((err) => {\n // let message =\n // err.message || 'Unable to authenticate with Google.';\n // let status = err.status || '';\n // this.toastCont.error(\n // `${message} ${status}`,\n // `Unable to Login`,\n // config.toastrErrorOptions\n // );\n console.error('Google auth error', err);\n this.handleLoginFailed(err)\n });\n };\n\n render() {\n const versionStyle = {\n position: 'absolute',\n bottom: 0,\n marginLeft: '20px'\n };\n // console.log('search', this.state.shouldHideSchoolSearch, theme.schoolID)\n const userSchoolClassName = this.state.shouldHideSchoolSearch\n ? 'autocomplete-container d-none'\n : 'autocomplete-container';\n\n const bsLayout = {\n xs: { span: 10, offset: 1 },\n md: { span: 8, offset: 2 },\n lg: { span: 6, offset: 3 }\n };\n return (\n
\n {\n this.toastCont = toast;\n }}\n className=\"toast-top-right\"\n />\n \n \n \"\"\n \n \n this.handleSubmit(e)}\n className=\"dibs-form\"\n >\n \n \n \n

Welcome! Please sign in.

\n \n
\n \n \n \n {!this.props.loading && (\n \n Start typing to select your school.\n \n )}\n {this.props.loading && (\n \n Loading...{' '}\n \n \n )}\n \n \n \n {\n this.state.formValidations.schoolID\n .validationMessage\n }\n \n \n\n \n \n \n \n {\n this.state.formValidations.loginID\n .validationMessage\n }\n \n \n\n \n \n \n \n {\n this.state.formValidations.password\n .validationMessage\n }\n \n \n \n \n \n \n \n \n Login\n \n \n \n
\n

\n \n {' '}\n Version: {config.Version}, Environment:{' '}\n {config.Environment}{' '}\n {' '}\n

\n
\n \n \n
\n );\n }\n}\nconst mapStateToProps = (state, ownProps) => {\n return {\n user: state.user,\n loading: state.ajaxCallsInProgress > 0,\n bookID:\n ownProps.location.query.bookID ||\n ownProps.location.query.bookid ||\n ownProps.location.query.BookID,\n schoolID:\n ownProps.location.query.SchoolID ||\n ownProps.location.query.schoolid ||\n ownProps.location.query.schoolID,\n changeSchoolID: ownProps.location.query.changeSchoolID,\n redirect: ownProps.location.query.redirect\n };\n};\n\nexport default connect(mapStateToProps, {\n userLogin,\n manualAjaxStart,\n manualAjaxEnd,\n googleTokenLogin,\n userLogout\n})(LoginForm);\n","/*\n * This page is not currently being used in DiBS\n */\n\nimport React, { Component } from 'react';\nimport { connect } from 'react-redux';\nimport { userRegister } from '../../actions/userActions';\n\nimport { hashHistory } from 'react-router';\nimport { ToastContainer, ToastMessage } from 'react-toastr';\nimport { Container, Button } from 'react-bootstrap';\nimport constants from '../../constants/constants';\n\nconst ToastMessageFactory = React.createFactory(ToastMessage.animation);\n\nclass RegisterForm extends Component {\n reffirst;\n reflast;\n refemail;\n refpassword;\n refpassword2;\n toastCont;\n\n constructor(props) {\n super(props);\n this.state = {\n first: 'Billy',\n last: 'Bookreader',\n loginID: 'tester',\n password: '12345',\n password2: '12345'\n };\n\n // var apikey = localStorage.getItem(\"GF-APIKey\");\n // if (apikey) {\n // window.location = '/admin/';\n // }\n\n this.handleChange = this.handleChange.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.goBack = this.goBack.bind(this);\n this.theme = constants.themeProvider.activeTheme;\n }\n\n goBack() {\n hashHistory.push('/');\n }\n\n handleChange(e) {\n this.setState({ [e.target.name]: e.target.value });\n }\n\n handleSubmit(e) {\n if (e !== '') {\n e.preventDefault();\n }\n\n if (this.state.loginID === '') {\n this.toastCont.error(\n `Please enter a valid email address.`,\n `Form Error`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInUp'\n }\n );\n this.refemail.focus();\n return;\n }\n\n this.props\n .userRegister(this.state)\n .then((user) => {\n // TODO: route somewhere for student and admin\n })\n .catch((error) => {\n console.error(error);\n if (error.status === 409) {\n // email already exists\n this.toastCont.error(\n `That email address is already registered in our system.`,\n `Registration Error`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInUp'\n }\n );\n }\n });\n }\n\n render() {\n return (\n \n

Welcome to GrammarFlip!

\n
\n
\n this.handleSubmit(e)}\n >\n
\n \n {\n this.refgender = input;\n }}\n name=\"gender\"\n value={this.state.gender}\n onChange={this.handleChange}\n >\n \n \n \n \n
\n
\n \n {\n this.reffirst = input;\n }}\n name=\"first\"\n placeholder=\"First Name\"\n value={this.state.first}\n onChange={this.handleChange}\n />\n
\n
\n \n {\n this.reflast = input;\n }}\n name=\"last\"\n placeholder=\"Last Name\"\n value={this.state.last}\n onChange={this.handleChange}\n />\n
\n
\n \n {\n this.refemail = input;\n }}\n name=\"email\"\n placeholder=\"Email\"\n value={this.state.email}\n onChange={this.handleChange}\n />\n
\n
\n \n {\n this.refpassword = input;\n }}\n name=\"password\"\n placeholder=\"Password\"\n value={this.state.password}\n onChange={this.handleChange}\n />\n
\n
\n \n {\n this.refpassword2 = input;\n }}\n name=\"password2\"\n placeholder=\"Confirm Password\"\n value={this.state.password2}\n onChange={this.handleChange}\n />\n
\n
\n I am a\n {\n this.refrole = input;\n }}\n name=\"role\"\n value={this.state.role}\n onChange={this.handleChange}\n >\n \n \n \n \n \n \n \n \n \n
\n

\n \n By clicking Be a Teacher below you\n agree to the GrammarFlip{' '}\n \n Privacy Policy and Terms of Use\n \n .\n \n

\n
\n
\n
\n \n BE A TEACHER\n \n \n back to login\n \n
\n
\n
\n \n
\n
\n
\n

\n Start your FREE, 30-day trial today!\n

\n\n

\n Experience GrammarFlip's 60-Lesson Subscription.\n Each lesson contains the following features:\n

\n\n
    \n
  • \n Instructional videos that allow for\n self-paced learning\n
  • \n
  • \n Slideshow presentations that provide quick\n review of material\n
  • \n
  • \n Practice exercises with instant feedback\n
  • \n
  • \n Writing activities to apply the concepts\n learned\n
  • \n
\n\n

\n A Teacher Trial Account comes with the\n following:\n

\n
    \n
  • 150 FREE student accounts
  • \n
  • As many as 6 different class sections
  • \n
  • \n Easy student account management and setup\n
  • \n
  • \n Student progress reports in quick-view\n format\n
  • \n
  • \n Additional content integrations with\n Formative and Kahoot\n
  • \n
\n\n \n Get started today! It’s free!\n \n
\n
\n
\n {\n this.toastCont = toast;\n }}\n className=\"toast-bottom-center\"\n />\n
\n );\n }\n}\n\nconst mapStateToProps = (state, ownProps) => {\n return {\n user: state.user,\n loading: state.ajaxCallsInProgress > 0\n };\n};\n\nexport default connect(mapStateToProps, { userRegister })(RegisterForm);\n","\nconst epubViewStyles = {\n viewHolder: {\n position: \"relative\",\n height: \"100%\",\n width: \"100%\"\n },\n view: {\n height: \"100%\"\n }\n };\n \n export default epubViewStyles","import React from \"react\";\nimport { Button } from \"react-bootstrap\";\n\nexport function EpubAudio({ status, setStatus, show }) {\n if (show === false){\n return null;\n }\n return (\n
\n \n
\n );\n}\n","export const BOOK_NEXT_PAGE = \"BOOK_NEXT_PAGE\";\nexport const BOOK_PREV_PAGE = \"BOOK_PREV_PAGE\";\nexport const BOOK_FIRST_PAGE = \"BOOK_FIRST_PAGE\";\nexport const BOOK_LAST_PAGE = \"BOOK_LAST_PAGE\";\nexport const BOOK_SINGLE_PAGE_LAYOUT = 'BOOK_SINGLE_PAGE_LAYOUT';\nexport const BOOK_DOUBLE_PAGE_LAYOUT = 'BOOK_DOUBLE_PAGE_LAYOUT';\n","import { filter, map, reduce, forEach } from 'lodash';\nimport $ from 'jquery';\nimport { Ibook, ImarkProcessed } from '../models';\n\ninterface IpageElement {\n lineIndex: number;\n text: string;\n normalizedText: string;\n possibleMarks: ImarkProcessed[];\n}\n\nconst textToSpeechConfig = {\n skipMissedConsecutive: 1,\n foundInElementStringWeight: 0.5,\n matchesNormalizedTextWeight: 1,\n matchesOriginalElementWeight: 1,\n matchesElementAndUniqueWeight: 4,\n foundInMarkValueWeight: 0.25,\n divideConsecutiveMatchConfidence: 2,\n minimumThreashholdForPossibleMatch: 1,\n minimumThreashholdForTryingSingleCharacterMatch: 2.75, // foundInElementStringWeight + matchesNormalizedTextWeight + matchesOriginalElementWeight\n maximumTimeBetweenMatches: 2000,\n speechMarkRegex: /([’'?])|/g,\n HTMLelementRegex: /([;:?!\"()”“|`’'~*])|([,.-]\\B|( ))/g\n};\n\nconst intialMarkProcessed = {\n unique: false,\n normalizedValue: '',\n confirmed: 0,\n elementMatchConfidence: 0,\n consecutiveMatchConfidence: 0\n};\n\n/*\n* receive what might be line with words and return false if it is not\n*/\nconst isLine = (possibleLine: string) => {\n if (possibleLine.search(' {\n // add tappable class to each word\n const $pageData = $(pageData);\n $pageData.find('.t').each((index, $tDiv) => {\n // array of divs with class \"t\"\n if (isLine($tDiv.innerHTML) === false){\n return;\n }\n const lineArray = $tDiv.innerHTML.trim().split(' '), // array of words inside that div - which is a single line\n len = lineArray.length,\n result = [];\n for (var i = 0; i < len; i++) {\n result[i] = `${lineArray[i]} `;\n }\n $tDiv.innerHTML = result.join(' ');\n });\n return $pageData[0].outerHTML;\n};\n\n/*\n * determinElementMatchConfidence\n * return a new array of possible matching speechmarks for the element with added weight for how confident we are in the match\n */\nconst determinElementMatchConfidence = (\n elementIndex: number,\n allElements: IpageElement[],\n marks: ImarkProcessed[]\n) => {\n const elementNormalizedText = allElements[elementIndex].normalizedText;\n return map(marks, (mark, index) => {\n const foundInElementString =\n elementNormalizedText.search(mark.normalizedValue) >= 0;\n const matchesNormalizedText =\n elementNormalizedText === mark.normalizedValue;\n const matchesOriginalElement =\n allElements[elementIndex].text === mark.value;\n const matchesElementAndUnique = matchesNormalizedText && mark.unique; // if the mark value is unique and we matched it with the element\n const foundInMarkValue =\n mark.normalizedValue.search(elementNormalizedText) >= 0;\n let consecutiveMatchConfidence = 0;\n let confirmations = 0;\n\n const {\n foundInElementStringWeight,\n matchesNormalizedTextWeight,\n matchesOriginalElementWeight,\n matchesElementAndUniqueWeight,\n foundInMarkValueWeight,\n divideConsecutiveMatchConfidence,\n minimumThreashholdForPossibleMatch\n } = textToSpeechConfig;\n confirmations = foundInElementString\n ? confirmations + foundInElementStringWeight\n : confirmations;\n confirmations = matchesNormalizedText\n ? confirmations + matchesNormalizedTextWeight\n : confirmations;\n confirmations = matchesOriginalElement\n ? confirmations + matchesOriginalElementWeight\n : confirmations;\n confirmations = matchesElementAndUnique\n ? confirmations + matchesElementAndUniqueWeight\n : confirmations;\n /* not sure if foundInMarkValue is helpuful, if comment in, set foundInElementString to .5 and minimum confimations to .25???\n * this is because not finding a match here and finding the clossest timecode based on the elements around this one\n * will be more reliable\n */\n confirmations = foundInMarkValue\n ? confirmations + foundInMarkValueWeight\n : confirmations;\n\n // if match and element.length greater than 3\n if (\n (matchesNormalizedText || matchesOriginalElement) &&\n elementNormalizedText.length > 2\n ) {\n confirmations += 2;\n }\n\n // only check consecutive if we have at least one confirmation so far\n if (confirmations > foundInMarkValueWeight) {\n consecutiveMatchConfidence = determinConsecutiveElementConfidence(\n elementNormalizedText,\n elementIndex,\n allElements,\n marks,\n index\n );\n if (consecutiveMatchConfidence > 0) {\n consecutiveMatchConfidence =\n consecutiveMatchConfidence /\n divideConsecutiveMatchConfidence;\n }\n }\n\n // minimum threshhold for being considered a possible match, add foundInMarkValueWeight because we do not want to\n // include a match solely based on that.\n if (\n confirmations + consecutiveMatchConfidence <\n minimumThreashholdForPossibleMatch + foundInMarkValueWeight\n ) {\n return {\n ...mark,\n elementMatchConfidence: 0,\n consecutiveMatchConfidence: 0\n };\n }\n return {\n ...mark,\n elementMatchConfidence: confirmations,\n consecutiveMatchConfidence\n };\n });\n};\n\n/*\n * determinConsecutiveElementConfidence\n * return a new array of possible matching speechmarks for the element with the added weight for how many\n * consecutive words before and after match up between the elements and the speech marks\n * if no match is found, break out of the for loop early\n */\nconst determinConsecutiveElementConfidence = (\n element: string,\n elementIndex: number,\n allElements: IpageElement[],\n marks: ImarkProcessed[],\n markIndex: number\n) => {\n let confirmations = 0;\n let countMissedAfter = 0;\n // how many consecutive AFTER this mark\n for (\n let index = 1;\n markIndex + index < marks.length &&\n elementIndex + index < allElements.length;\n index++\n ) {\n // console.log('checking consecutive', markIndex, index, elementIndex, allElements, element)\n const nextMark = marks[markIndex + index];\n const currentElement = allElements[elementIndex + index];\n\n if (\n currentElement &&\n nextMark.normalizedValue === currentElement.normalizedText\n ) {\n if (\n currentElement &&\n allElements[elementIndex].lineIndex === currentElement.lineIndex\n ) {\n confirmations += 1;\n } else {\n confirmations += 0.5;\n }\n } else if (\n countMissedAfter > textToSpeechConfig.skipMissedConsecutive\n ) {\n break;\n } else {\n countMissedAfter++;\n }\n }\n // how many consecutive BEFORE this mark\n let countMissedBefore = 0;\n for (\n let index = -1;\n markIndex + index >= 0 && elementIndex + index >= 0;\n index--\n ) {\n // console.log('checking consecutive', markIndex, index, elementIndex, allElements, element)\n const prevMark = marks[markIndex + index];\n const currentElement = allElements[elementIndex + index];\n if (\n currentElement &&\n prevMark.normalizedValue === currentElement.normalizedText\n ) {\n if (\n currentElement &&\n allElements[elementIndex].lineIndex === currentElement.lineIndex\n ) {\n confirmations += 1;\n } else {\n confirmations += 0.5;\n }\n } else if (\n countMissedBefore > textToSpeechConfig.skipMissedConsecutive\n ) {\n break;\n } else {\n countMissedBefore++;\n }\n }\n return confirmations;\n};\n\n/*\n * add the timecode to the HTML\n */\nconst addTimecode = (word: string, mark: { time: string }) => {\n let startTimeAttribute = `data-time-start=\"${mark.time}\"`;\n return `${word} `;\n};\n\nconst updatePageHTML = (\n $arrayOfLines: JQuery,\n allPageElements: IpageElement[],\n speechMarksData: ImarkProcessed[]\n) => {\n let elementIndex = 0;\n $arrayOfLines.each((lineIndex, $tDiv) => {\n const lineString = $tDiv.innerHTML.trim();\n const lineArray = lineString.split(' ');\n const updatedLine = lineArray.map((originalWord, index) => {\n const flatWordObj = allPageElements[elementIndex];\n let wordHTMLc = '';\n if (\n flatWordObj &&\n flatWordObj.possibleMarks &&\n flatWordObj.possibleMarks.length\n ) {\n let chosenMark = flatWordObj.possibleMarks[0];\n if (flatWordObj.possibleMarks.length > 1) {\n // we will have multiple possible marks only if both matchSingleCharacterElements() and matchSingleCharacterElements() find a match\n const reducedMark = reduce(\n flatWordObj.possibleMarks,\n (prev, current) => {\n return current.elementMatchConfidence +\n current.consecutiveMatchConfidence >\n prev.elementMatchConfidence +\n prev.consecutiveMatchConfidence\n ? current\n : prev;\n }\n );\n if (reducedMark) {\n chosenMark = reducedMark;\n }\n }\n wordHTMLc = addTimecode(flatWordObj.text, chosenMark);\n } else {\n /*\n * if there are 0 possibleMarks and there is a possibleMark for the element before and after this\n * that span a maximum of 2000ms, use the mark between the two possible marks or use the mark time for\n * after\n */\n let timeBeforeWord: number = 0;\n let timeAfterWord: number = 0;\n console.log(\n 'element missing timecode, trying to find timecodes before and after: ' +\n originalWord\n );\n if (elementIndex > 0) {\n const previousElement = allPageElements[elementIndex - 1];\n timeBeforeWord = previousElement.possibleMarks.length\n ? parseInt(previousElement.possibleMarks[0].time)\n : 0;\n }\n if (elementIndex + 1 < allPageElements.length) {\n const nextElement = allPageElements[elementIndex + 1];\n timeAfterWord = nextElement.possibleMarks.length\n ? parseInt(nextElement.possibleMarks[0].time)\n : 0;\n }\n if (\n timeBeforeWord &&\n timeAfterWord &&\n Math.abs(timeAfterWord - timeBeforeWord) <\n textToSpeechConfig.maximumTimeBetweenMatches\n ) {\n const targetTime = (timeBeforeWord + timeAfterWord) / 2;\n const clossestSpeechMark = reduce(\n speechMarksData,\n (prev, current) => {\n return Math.abs(\n parseInt(current.time) - targetTime\n ) < Math.abs(parseInt(prev.time) - targetTime)\n ? current\n : prev;\n }\n );\n if (clossestSpeechMark) {\n wordHTMLc = addTimecode(flatWordObj.text, {\n time: clossestSpeechMark.time\n });\n console.log(\n 'found clossest time for missing timecode: ' +\n flatWordObj.text +\n ' ' +\n clossestSpeechMark.value,\n clossestSpeechMark\n );\n }\n // had an idea to only use the time before or after, but it is very unreliable.\n // } else if (timeBeforeWord) {\n // const targetTime = timeBeforeWord + 500;\n // const clossestSpeechMark = reduce(speechMarksData, (prev, current) => {\n // return (Math.abs(current.time - targetTime) < Math.abs(prev.time - targetTime) ? current: prev)\n // })\n // wordHTMLc = addTimecode(flatWordObj.text, {time: clossestSpeechMark.time})\n // console.log('found clossest BEFORE time for missing timecode: ' + flatWordObj.text + ' ' + clossestSpeechMark.value, clossestSpeechMark)\n // } else if (timeAfterWord) {\n // const targetTime = timeAfterWord - 500;\n // const clossestSpeechMark = reduce(speechMarksData, (prev, current) => {\n // return (Math.abs(current.time - targetTime) < Math.abs(prev.time - targetTime) ? current: prev)\n // })\n // wordHTMLc = addTimecode(flatWordObj.text, {time: clossestSpeechMark.time})\n // console.log('found clossest BEFORE time for missing timecode: ' + flatWordObj.text + ' ' + clossestSpeechMark.value, clossestSpeechMark)\n } else {\n wordHTMLc = `${flatWordObj.text} `;\n console.warn(\n 'could not find missing timecode for: ' +\n flatWordObj.text\n );\n }\n }\n elementIndex++;\n return wordHTMLc;\n });\n $tDiv.innerHTML = updatedLine.join(' ');\n });\n};\n\nconst reducePossibleMarks = (\n allPageElements: IpageElement[],\n speechMarksData: ImarkProcessed[]\n) => {\n let selectedMarks: {[key: string]: ImarkProcessed} = {} // keep track of which marks have been used\n // if a mark has been used before, compare the confidence. If the confidence for the usedMark is equal or lower\n // then add .5 to the confidence because we can be more confident in a mark that has Not been used yet.\n return map(allPageElements, (element, elementIndex) => {\n if (element.normalizedText === '') {\n return element;\n }\n let foundMark: ImarkProcessed | undefined = undefined;\n const foundMarksWithConfidence = determinElementMatchConfidence(\n elementIndex,\n allPageElements,\n speechMarksData\n );\n // if we have multiple matches, then reduce down to the word we have the most confidence in\n if (foundMarksWithConfidence.length > 1) {\n const reducedMark = reduce(\n foundMarksWithConfidence,\n (prev, current) => {\n let currentConfidence = current.elementMatchConfidence +\n current.consecutiveMatchConfidence;\n const prevConfidence = prev.elementMatchConfidence +\n prev.consecutiveMatchConfidence;\n const usedMark = selectedMarks[prev.time];\n if (prevConfidence === currentConfidence && prevConfidence !== 0 && usedMark && usedMark.elementMatchConfidence + usedMark.consecutiveMatchConfidence >= currentConfidence){\n currentConfidence += .5;\n }\n return currentConfidence >\n prevConfidence\n ? current\n : prev;\n }\n );\n if (reducedMark) {\n foundMark = reducedMark;\n }\n } else {\n foundMark = foundMarksWithConfidence[0];\n }\n\n if (\n !foundMark ||\n (foundMark.elementMatchConfidence === 0 &&\n foundMark.consecutiveMatchConfidence === 0)\n ) {\n // did not find any possibleMarks\n // try again with speechMarksData that has been flattened out to single characters.\n return element;\n }\n selectedMarks[foundMark.time] = foundMark;\n return {\n ...element,\n possibleMarks: [...element.possibleMarks, foundMark],\n foundElement: foundMark.value\n };\n });\n};\n\nconst flattenSpeechMarksData = (speechMarksData: ImarkProcessed[]) => {\n let flatSpeechMarkData: ImarkProcessed[] = [];\n forEach(speechMarksData, (mark) => {\n const splitMarkValue = mark.normalizedValue.split('');\n forEach(splitMarkValue, (singleCharacter) => {\n flatSpeechMarkData.push({\n ...mark,\n normalizedValue: singleCharacter,\n unique: false\n });\n });\n });\n return flatSpeechMarkData;\n};\n\nconst matchSingleCharacterElements = (\n allPageElements: IpageElement[],\n speechMarksData: ImarkProcessed[]\n) => {\n const flatSpeechMarksData = flattenSpeechMarksData(speechMarksData);\n // console.log('flatMarks', flatSpeechMarksData)\n return map(allPageElements, (element, elementIndex) => {\n // skip if the text is empty or the number of characters is more than 1\n if (\n element.normalizedText === '' ||\n element.normalizedText.length > 1\n ) {\n return element;\n }\n\n // if we already found a mark and the elementMatchConfidence is reasonably high\n if (\n element.possibleMarks.length > 0 &&\n element.possibleMarks[0].elementMatchConfidence >\n textToSpeechConfig.minimumThreashholdForTryingSingleCharacterMatch\n ) {\n return element;\n }\n let foundMark: ImarkProcessed | undefined;\n const foundMarksWithConfidence = determinElementMatchConfidence(\n elementIndex,\n allPageElements,\n flatSpeechMarksData\n );\n\n // if we have multiple matches, then reduce down to the word we have the most confidence in\n if (foundMarksWithConfidence.length > 1) {\n foundMark = reduce(foundMarksWithConfidence, (prev, current) => {\n return current.elementMatchConfidence +\n current.consecutiveMatchConfidence >\n prev.elementMatchConfidence +\n prev.consecutiveMatchConfidence\n ? current\n : prev;\n });\n } else {\n foundMark = foundMarksWithConfidence[0];\n }\n\n if (\n foundMark === undefined ||\n (foundMark.elementMatchConfidence === 0 &&\n foundMark.consecutiveMatchConfidence === 0)\n ) {\n // did not find any possibleMarks\n return element;\n }\n\n return {\n ...element,\n possibleMarks: [...element.possibleMarks, foundMark],\n foundElement: foundMark.value\n };\n });\n};\n/*\n * The MAIN function for adding speech mark times to the HTML\n */\nexport const addSpeechMarkTimesAndTappableClass = (\n book: Ibook,\n pageData: string,\n pageNumber: number\n) => {\n const pageKey = `page${pageNumber}`;\n const rawSpeechMarksData = book.cachedPages[pageKey].speechMarks;\n const $pageData = $(pageData);\n const $arrayOfLines = $pageData.find('.t');\n let allPageElements: IpageElement[] = []; // {lineIndex: 0, text: 'The', normalizedText: 'the ', possibleMarks: []}\n\n // prep speech Marks\n // sometimes a single mark has 2 words, split them up and add the same timecode for both\n let speechMarksData: ImarkProcessed[] = [];\n forEach(rawSpeechMarksData, (tempMark, index) => {\n const splitMarkValue = tempMark.value.split(' ');\n if (splitMarkValue.length > 1) {\n speechMarksData.push({\n ...intialMarkProcessed,\n ...tempMark,\n unique: false,\n confirmed: 0,\n normalizedValue: splitMarkValue[0]\n .toLowerCase()\n .replace(textToSpeechConfig.speechMarkRegex, '')\n });\n speechMarksData.push({\n ...intialMarkProcessed,\n ...tempMark,\n unique: false,\n confirmed: 0,\n normalizedValue: splitMarkValue[1]\n .toLowerCase()\n .replace(textToSpeechConfig.speechMarkRegex, '')\n });\n return;\n }\n const normalizedValue = tempMark.value\n .toLowerCase()\n .replace(textToSpeechConfig.speechMarkRegex, '');\n let uniqueCount = filter(\n rawSpeechMarksData,\n (value) =>\n value.value\n .toLowerCase()\n .replace(textToSpeechConfig.speechMarkRegex, '') ===\n normalizedValue\n ).length;\n if (uniqueCount && uniqueCount === 1 && tempMark.value.length > 3) {\n speechMarksData.push({\n ...intialMarkProcessed,\n ...tempMark,\n unique: true,\n confirmed: 0,\n normalizedValue\n });\n } else {\n speechMarksData.push({\n ...intialMarkProcessed,\n ...tempMark,\n unique: false,\n confirmed: 0,\n normalizedValue\n });\n }\n });\n\n if (!speechMarksData || speechMarksData.length <= 0) {\n console.error(\n 'missing speechMarks data, switching to only adding tappable classes'\n );\n return addTappableClassOnly(pageData);\n }\n\n /*\n * normalize to an array of indexed elements\n * for each element, loop over the speech marks and assign a confidence rating for how confident we are tha a\n * particular mark matches this element.\n * Then send this arry of all the elements to a function that changes the HTML of the page\n */\n // console.log(`starting first pass for speechamarks page: ${pageNumber}`);\n $arrayOfLines.each((lineIndex, $tDiv) => {\n // array of divs with class \"t\"\n if (isLine($tDiv.innerHTML) === false){\n return;\n }\n const lineString = $tDiv.innerHTML.trim();\n const lineArray = lineString.split(' ');\n const lineArrayCleaned = lineString.split(' ').map((text) => {\n const normalizedText = text\n .trim()\n .toLowerCase()\n .replace(textToSpeechConfig.HTMLelementRegex, '');\n allPageElements.push({\n lineIndex,\n text,\n normalizedText,\n possibleMarks: []\n });\n return normalizedText;\n }); // array of words inside that div - which is a single line\n\n if (lineArrayCleaned.length <= 0) {\n console.error('empty line', lineArrayCleaned, lineArray);\n return;\n }\n if (lineArrayCleaned.length !== lineArray.length) {\n console.error('lineArrayCleaned length different than lineArray');\n }\n });\n\n allPageElements = reducePossibleMarks(allPageElements, speechMarksData);\n allPageElements = matchSingleCharacterElements(\n allPageElements,\n speechMarksData\n );\n\n // console.log('result of adding speechMarks', speechMarksData);\n // console.log('index of class', pageData);\n // console.log('allPageElements', allPageElements);\n updatePageHTML($arrayOfLines, allPageElements, speechMarksData);\n const updatedHTML = $pageData[0].outerHTML;\n return updatedHTML;\n};\n","import config from './config';\nimport { forEach } from 'lodash';\nimport JSZip from 'jszip';\nimport BookFS from './bookFS';\nimport {\n addTappableClassOnly,\n addSpeechMarkTimesAndTappableClass\n} from '../utilities/TextToSpeechUtility';\nimport UserAPI from './userAPI';\n\nexport default class BookAPI {\n /* get the json properties for a particular book from blob storage */\n static getBookProperties(book, token) {\n const remoteURL = `${config.API.Storage}${book.EBookPath}${book.ISBN}/properties.json${token}`;\n var request = new Request(remoteURL, { method: 'GET' });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /*\n * Get the speechmarks\n */\n static getSpeechMarksRemote(book, index, token, voice = 'default') {\n if (!book.EBookPath || !book.ISBN || !token) {\n throw new Error(\n `missing book info path: ${book.EBookPath} ISBN: ${book.ISBN} token: ${token}`\n );\n }\n const URL = `${config.API.Storage}${book.EBookPath}${book.ISBN}/audio/${voice}/${index}.marks${token}`;\n // return Promise.resolve(constants.testSpeechMarkRaw); // test speech marks\n var request = new Request(URL, { method: 'GET' });\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n return Promise.resolve([]);\n }\n return response.text();\n });\n }\n\n /* get and process data for a particular book page from file storage (type blob) */\n static getBookPageLocal(book, index, pageKey) {\n console.log('getting book page local');\n const htmURL = `${index}.html`;\n const svgURL = `${index}/${index}.svg`;\n\n // fetch the html for the page\n const promise1 = BookFS.getBookFileEntry(book.ISBN, htmURL);\n\n // fetch the svg data for the page\n const promise2 = BookFS.getBookFileEntry(book.ISBN, svgURL);\n\n return Promise.all([promise1, promise2]).then((values) => {\n // return values;\n let pageData = values[0]; // html page data\n let svgData = values[1]; // temporarily set this to an array with the SVG file and the URL to the file\n let fontPath = '';\n if (svgData === 404) {\n //not found\n svgData = '';\n } else {\n // const childImageUrl = svgData.search()\n // return BookFS.getBookFileUrl(book.ISBN, )\n const svgPromises = [];\n const fontPromises = [];\n // let rootPath = svgData[1]; // URL to the file\n // rootPath = rootPath.substring(0, rootPath.lastIndexOf('/')); // we are only replacing the rootPath, not the file name or the extension\n // fontPath = rootPath.substring(0, rootPath.lastIndexOf('/')); // the root directory of this book\n // svgData = svgData[0];\n // replace all relative image urls with full url\n svgData.replace(\n /((\\w*)\\/[0-9]*.(png|jpg))+/g,\n (originalPath) => {\n svgPromises.push(\n BookFS.getBookFileUrl(\n book.ISBN,\n `${index}/${originalPath}`\n ).then((newPath) => {\n svgData = svgData.replace(\n originalPath,\n newPath\n );\n })\n );\n }\n );\n\n pageData.replace(\n /(fonts\\/[a-zA-Z0-9\\-_]*.\\w*)/g,\n (originalPath) => {\n fontPromises.push(\n BookFS.getBookFileUrl(\n book.ISBN,\n `${originalPath}`\n ).then((newPath) => {\n pageData = pageData.replace(\n originalPath,\n newPath\n );\n })\n );\n }\n );\n\n return Promise.all([...svgPromises, ...fontPromises]).then(\n (childValues) => {\n svgData = svgData.replace(\n '',\n ''\n );\n // now replace the entire svg in the html with the svg element\n pageData = pageData.replace(\n /()+/,\n svgData\n );\n\n // if marks are enabled and available, the speechMarks array for this page will have length\n if (\n book.cachedPages[pageKey] &&\n book.cachedPages[pageKey].speechMarks.length > 0\n ) {\n pageData = addSpeechMarkTimesAndTappableClass(\n book,\n pageData,\n index\n );\n } else {\n pageData = addTappableClassOnly(pageData);\n }\n return pageData;\n }\n );\n }\n });\n }\n\n /* get and process data for a particular book page from blob storage */\n static getBookPageRemote(book, index, token, pageKey) {\n if (!book.EBookPath || !book.ISBN || !token) {\n throw new Error(\n `missing book info path: ${book.EBookPath} ISBN: ${book.ISBN} token: ${token}`\n );\n }\n\n const root = `${config.API.Storage}${book.EBookPath}${book.ISBN}/`;\n const htmURL = `${root}${index}.html${token}`;\n const svgURL = `${root}${index}/${index}.svg${token}`;\n\n // fetch the html for the page\n const p1 = fetch(htmURL).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.text();\n });\n // fetch the svg data for the page\n const p2 = fetch(svgURL)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.text();\n })\n // catch any errors with svg fetch so we can\n // inspect and not autofail the whole request.\n .catch((err) => {\n if (err.status === 404) {\n // then this is a benign error - the svg is simply not there as expected\n return err.status;\n } else {\n throw err;\n }\n });\n return Promise.all([p1, p2]).then((values) => {\n // return values;\n let pageData = values[0];\n let svgData = values[1];\n if (svgData === 404) {\n //not found\n svgData = '';\n } else {\n // replace all relative image urls with full url\n svgData = svgData.replace(\n /((\\w*)\\/[0-9]*.(png|jpg))+/g,\n `${root}${index}/$1${token}`\n );\n // remove extra crap we do not need for an embedded svg\n svgData = svgData.replace(\n '',\n ''\n );\n }\n // now replace the entire svg in the html with the svg element\n pageData = pageData.replace(/()+/, svgData);\n // replace fonts path\n pageData = pageData.replace(\n /(fonts\\/[a-zA-Z0-9\\-_]*.\\w*)/g,\n `${root}$1${token}`\n );\n\n // if marks are enabled and available, the speechMarks array for this page will have length\n if (\n book.cachedPages[pageKey] &&\n book.cachedPages[pageKey].speechMarks.length > 0\n ) {\n pageData = addSpeechMarkTimesAndTappableClass(\n book,\n pageData,\n index\n );\n } else {\n pageData = addTappableClassOnly(pageData);\n }\n return pageData;\n });\n }\n\n /* get the zipped up book from blob storage */\n static downloadBook(book, token) {\n const URL = `${config.API.Storage}${book.EBookPath}${book.ISBN}/${book.ISBN}.zip${token}`;\n const request = new Request(URL, { method: 'GET' });\n\n return (\n fetch(request)\n .then((response) => {\n console.log('downloaded book zip');\n if (response.status !== 200) {\n throw response;\n }\n // decode the base64 encoded response\n return response.blob();\n })\n // unzip the zip\n .then(JSZip.loadAsync)\n .then(function (zip) {\n console.log('unzipped book zip');\n // save the unziped files to the file system\n return BookFS.saveBook(book.ISBN, zip);\n })\n );\n }\n\n /*\n * Get the zipped up speech files\n */\n static downloadSpeech(book, token) {\n const URL = `${config.API.Storage}${book.EBookPath}${book.ISBN}/audio/default/${book.ISBN}_audio.zip${token}`;\n const request = new Request(URL, { method: 'GET' });\n\n return (\n fetch(request)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n // decode the base64 encoded response\n return response.blob();\n })\n // unzip the zip\n .then(JSZip.loadAsync)\n .then(function (zip) {\n console.log('unzipped speech zip');\n // save the unziped files to the file system\n return BookFS.saveSpeech(book.ISBN, zip);\n })\n );\n }\n\n static getBookItemsList(downloadedBookIDs, user) {\n let URL = `${config.API.Main}/viewer/getbookitemlist`;\n\n forEach(downloadedBookIDs, (bookID, index) => {\n if (index === 0) {\n URL += `?bookIDs=${bookID}`;\n } else {\n URL += `&bookIDs=${bookID}`;\n }\n });\n\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /* Get a list of books the current user has access to*/\n static getBooks(\n activePage,\n search,\n type,\n tag,\n grl,\n user,\n advancedSearchFilters\n ) {\n if (type === 'All') {\n type = '';\n }\n const {\n selectedReadingLevelTypeOption = null,\n readingMin = '',\n readingMax = '',\n spanishOnly = ''\n } = advancedSearchFilters;\n const rltype = selectedReadingLevelTypeOption\n ? selectedReadingLevelTypeOption.value\n : '';\n let URL = `${\n config.API.Main\n }/student/getbooks?page=${activePage}&search=${search}&grl=${grl}\n &type=${type}&rltype=${rltype || ''}&rlmin=${readingMin || ''}&rlmax=${\n readingMax || ''\n }&spanishonly=${spanishOnly}`;\n\n if (tag !== undefined && tag !== '' && tag !== 'allTags') {\n URL += `&tags=${config.typeGUID[tag]}`;\n } else {\n URL += `&tags=`;\n }\n\n if (\n advancedSearchFilters.tags &&\n advancedSearchFilters.tags.length > 0\n ) {\n forEach(advancedSearchFilters.tags, (value, key) => {\n URL += `&tags=${value.TagID}`;\n });\n }\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static addBook(bookID, user) {\n const URL = `${config.API.Main}/student/addtobookbag?bookid=${bookID}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: UserAPI.getHeaders(user)\n });\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n static removeBook(bookID, user) {\n const URL = `${config.API.Main}/student/removefrombookbag?bookid=${bookID}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: UserAPI.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getBookByID(bookID, user) {\n const URL = `${config.API.Main}/book/getbookbyid?bookid=${bookID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeaders(user)\n });\n\n console.log('gettingbook', user, request);\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static searchBooks(\n page,\n search,\n type,\n tag,\n grl,\n user,\n advancedSearchFilters\n ) {\n if (type === 'All') {\n type = '';\n }\n const {\n selectedReadingLevelTypeOption = null,\n readingMin = '',\n readingMax = '',\n spanishOnly = ''\n } = advancedSearchFilters;\n const rltype = selectedReadingLevelTypeOption\n ? selectedReadingLevelTypeOption.value\n : '';\n let URL = `${\n config.API.Main\n }/book/ebooksearch?page=${page}&search=${search}&type=${type}&grl=${grl}\n &rltype=${rltype || ''}&rlmin=${readingMin || ''}&rlmax=${\n readingMax || ''\n }&spanishonly=${spanishOnly}`;\n // grabbing the tag name and assigning it as the key pair to grab the value in config\n if (tag !== undefined && tag !== '' && tag !== 'allTags') {\n URL += `&tags=${config.typeGUID[tag]}`;\n } else {\n URL += `&tags=`;\n }\n\n if (\n advancedSearchFilters.tags &&\n advancedSearchFilters.tags.length > 0\n ) {\n forEach(advancedSearchFilters.tags, (value, key) => {\n URL += `&tags=${value.TagID}`;\n });\n }\n\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeadersUrlEncode(user)\n });\n console.log('before fetch');\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /*\n save bookitem\n */\n static saveBookItem(bookItem, user) {\n const URL = `${config.API.Main}/viewer/savebookitem`;\n const body = JSON.stringify({\n ...bookItem,\n Content: JSON.stringify(bookItem.Content)\n });\n var request = new Request(URL, {\n method: 'POST',\n headers: UserAPI.getHeaders(user),\n body\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n /*\n save bookitem offline\n */\n\n /*\n delete bookitem\n */\n static deleteBookItem(bookItem, user) {\n const URL = `${config.API.Main}/viewer/deletebookitem`;\n let body = `ID=${bookItem.ID}`;\n var request = new Request(URL, {\n method: 'POST',\n headers: UserAPI.getHeaders(user),\n body: body\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /*\n get book items\n */\n static getBookItems(bookId, user) {\n const URL = `${config.API.Main}/viewer/getbookitems?bookID=${bookId}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getTeacherBookItems(data, user) {\n let passCorrectID;\n if (data.groupID) {\n passCorrectID = `&groupID=${data.groupID}`;\n } else if (data.classID) {\n passCorrectID = `&classID=${data.classID}`;\n } else {\n passCorrectID = `&studentID=${data.studentID}`;\n }\n\n const URL = `${config.API.Main}/viewer/getteacherbookitems?bookID=${data.book}${passCorrectID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /*\n get book items by student id (used by teacher token login)\n */\n static getBookItemsByStudentID(BookId, StudentId, user) {\n const URL = `${config.API.Main}/viewer/getstudentbookitems?bookID=${BookId}&studentID=${StudentId}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: UserAPI.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n}\n","const initialState = {\n completedBLMs: {},\n user: {\n ID: ''\n },\n blm: {\n projectIsReady: false\n },\n blms: [],\n books: [],\n bookbagFilters: {\n tags: [],\n selectedReadingLevelTypeOption: { value: 'grl', label: 'GRL' },\n readingMin: null,\n readingMax: null,\n spanishOnly: false\n },\n downloadedBooks: [],\n book: {\n cachedPages: {},\n currentPage: 1,\n LeftPageEven: false,\n bookIsReady: false,\n speechMarks: {}, // object of per page speechMarks arrays\n ISBN: '',\n EBookPath: '',\n bookmarks: [],\n highlights: {},\n notes: [],\n pagecount: 1,\n },\n routing: [],\n viewerMode: {\n mode: 'normal',\n data: {}\n },\n bookView: {\n pageIndex: 1,\n bookScalePercent: 1,\n projectScalePercent: 1,\n leftPageContainerWidth: 0,\n leftPageContainerHeight: 0,\n pagesVisible: 2,\n automaticUpdatedPagesVisible: false,\n activeNoteID: '',\n bookManualZooming: false,\n bookManualZoomIndex: 2,\n bookManualZoomLevel: 1,\n itemSavePending: false\n },\n dashboard: {\n showUserProfileModal: false,\n showLoggoutConfirm: false,\n showClassCodeModal: false\n },\n projectToolbar: {\n erasing: false,\n startText: false,\n drawingMode: false,\n pointer: false,\n showRichTextButtons: false,\n drawingColor: '#ff8f02'\n },\n bookToolbar: {\n erasing: false,\n allowNotes: false,\n highlighting: false,\n highlightColor: 'hl-yellow',\n underlining: false,\n striking: false,\n pointing: true,\n pagesClassName: 'pointer-mode'\n },\n dashboardPageResults: 1,\n ajaxCallsInProgress: 0,\n readium: {\n readiumClass: null,\n },\n};\n\nexport default initialState;","import * as types from './actionTypes';\nimport { beginAjaxCall } from './ajaxStatusActions';\nimport BookAPI from '../api/bookAPI';\nimport UserAPI from '../api/userAPI';\nimport { forEach, uniqBy, find } from 'lodash';\nimport config from '../api/config';\nimport moment from 'moment';\nimport BookFS from '../api/bookFS';\nimport { debouncedCheckSession } from './userActions';\nimport { toastr } from 'react-redux-toastr';\nimport constants from '../constants/constants';\nimport initialState from '../reducers/initialState';\n\nexport const initialDashboardQuery = {\n tag: 'allTags',\n grl: '',\n type: 'All',\n activePage: 1,\n search: '',\n searchMode: 'local'\n};\n\nexport const searchBookBagBooks = (\n isFiltersActive = false,\n query = initialDashboardQuery\n) => {\n return (dispatch, getState) => {\n const {\n offlineQueue,\n books,\n downloadedBooks,\n user,\n bookbagFilters\n } = getState();\n if (!offlineQueue.isOnline || !navigator.onLine) {\n return;\n }\n const { activePage, search, type, tag, grl } = query;\n console.log('query', query);\n if (!query.searchMode || query.searchMode === 'local') {\n // if we have local books already and there are no search params, then don't show loading\n let showLoading = true;\n if (books.length > 0 && !isFiltersActive) {\n showLoading = false;\n }\n\n // when we are loading local books, we have them in redux already, we don't show loading.\n if (showLoading) dispatch(beginAjaxCall());\n return BookAPI.getBooks(\n activePage,\n search,\n type,\n tag,\n grl,\n user,\n bookbagFilters\n )\n .then((response) => {\n if (response === null) {\n response = [0, []];\n }\n const books = normalizeBookObjects(response[1], true);\n const pageResults = response[0];\n dispatch({\n type: types.DASHBOARD_PAGE_RESULTS,\n pageResults\n });\n dispatch({ type: types.LOAD_BOOKS_SUCCESS, books });\n // dispatch({\n // type: \"LOAD_BOOKS_SUCCESS\",\n // books: [{\n // \"Publisher\": null,\n // \"ID\": \"ddf6b481-770f-49d3-9c30-130ebaa08654\",\n // \"PublisherID\": \"2471b447-a506-4162-8e19-0939ee8d03f6\",\n // \"ISBN\": \"Chickens\",\n // \"Title\": \"#02 Made for Each Other\",\n // \"Description\": \"Tom Stone stepped into Seward High and into Maria McBride's life like a bolt of lightning. He's the perfect guy for Maria—nice, smart, and well-built. There's just one problem: his family. Tom's father is the town's new funeral director, and business is booming. The bodies are piling up thick and fast in Persephone Falls, Alaska, so Dr. Stone keeps Tom up late at night working in the funeral home. And it's clear that Dr. Stone and his creepy assistant, Graves, don't want Maria around. Maria knows Tom was made for her. She's determined to find out what Dr. Stone has against her. When Tom refuses to stand up to his father, Maria begins to stitch together the clues...and finds out that the Stones are into recycling in ways she never could have imagined.\",\n // // \"EBookUrl\": \"http://localhost:8080/books/ePUBS/Crabtree/test/unzipped/Chickens\",\n // // \"EBookUrl\": \"https://dibs-viewer-dev.herokuapp.com/books/ePUBS/Crabtree/test/unzipped/Chickens\",\n // \"EBookUrl\": \"books/Chickens\", // for testing with npm start\n // \"EBookPath\": \"/books/\",\n // \"GuidedReadingLevel\": \"\",\n // \"OfficialImage\": \"https://s3.amazonaws.com/dibsuploads/945fbd2e-e308-4bf2-a7d2-2f56a95a202f.jpg\",\n // \"ThumbnailImage\": null,\n // \"PreviewImage\": null,\n // \"FrontPhoto\": null,\n // \"BackPhoto\": null,\n // \"IsFiction\": true,\n // \"IsTeacherGuideAvailable\": false,\n // \"IsCustomTeacherGuideAvailable\": false,\n // \"IsApproved\": true,\n // \"IsExternal\": false,\n // \"ATOS\": null,\n // \"LEX\": null,\n // \"LeftPageEven\": true,\n // \"IsAudioAvailable\": true,\n // \"AudioVoices\": null,\n // \"FileUpdateDate\": \"1900-01-01T00:00:00\",\n // \"ProductURL\": null,\n // \"Series\": null,\n // \"FormatType\": 0,\n // \"CreateTime\": \"2016-02-09T03:50:31.493\",\n // \"UpdateTime\": \"2016-03-09T16:32:16.043\",\n // \"RequestAccountID\": null,\n // \"CurrentPage\": 22,\n // \"BLMs\": null,\n // \"IsAudioEnabled\": true,\n // \"IsStudentAdded\": true,\n // \"IsEPub\": true\n // } ]\n // });\n })\n .then(() => {\n if (!isFiltersActive && downloadedBooks.length > 0) {\n dispatch(\n checkForUpdatedBookFiles(\n books,\n downloadedBooks,\n user.AzureToken\n )\n );\n } else {\n return Promise.resolve(true);\n }\n })\n .catch((error) => {\n dispatch({ type: types.LOAD_BOOKS_FAILED, error });\n console.error('Error loading books in bookbag', error);\n if (error.status === 403) {\n this.props.handleInvalidSession();\n } else {\n toastr.error(\n `Error`,\n 'Unable to load books. Please try again or contact support.',\n constants.toastrErrorOptions\n );\n }\n throw error;\n });\n } else if (query.searchMode === 'remote') {\n dispatch(beginAjaxCall());\n return BookAPI.searchBooks(\n activePage,\n search,\n type,\n tag,\n grl,\n user,\n bookbagFilters\n )\n .then((response) => {\n if (response === null) {\n response = [0, []];\n }\n const pageResults = response[0];\n const books = normalizeBookObjects(response[1], false);\n dispatch({ type: types.LOAD_BOOKS_SUCCESS, books });\n dispatch({\n type: types.DASHBOARD_PAGE_RESULTS,\n pageResults\n });\n // books.pageResults = pgResult\n // return books;\n })\n .catch((error) => {\n dispatch({ type: types.LOAD_BOOKS_FAILED, error });\n // this.setState({ loading: false });\n // TODO for download books, could we get a specific error code if we are offline?\n console.error('hit this error searching for books', error);\n if (error.status === 403) {\n this.props.handleInvalidSession();\n } else {\n toastr.error(\n 'Error searching for books',\n `Error`,\n constants.toastrErrorOptions\n );\n }\n throw error;\n });\n }\n };\n};\n\n/*\n * compare the last updatedDate in downloadedBooks to books. if books is newer, then re-download the book. FileUpdateDate\n */\nexport function checkForUpdatedBookFiles(books, downloadedBooks, AzureToken) {\n return function (dispatch, getState) {\n // console.log('checking for updated book files', JSON.stringify(downloadedBooks))\n forEach(downloadedBooks, (downloadedBook) => {\n const book = find(books, { ID: downloadedBook.ID });\n // console.log('book:', book.ID, 'downloadedBook:', downloadedBook.ID);\n if (\n book &&\n downloadedBook &&\n moment(downloadedBook.FileUpdateDate).isBefore(\n book.FileUpdateDate\n )\n ) {\n // if (moment(downloadedBook.FileUpdateDate).isBefore(\"2000-01-01T00:00:00\")){ // to test redownloading books\n console.log('new book files available, redownloading book');\n dispatch(downloadBook(book, true));\n }\n });\n };\n}\n\n/*\n * Add a book to the bookbag\n */\nexport function addBook(book) {\n return function (dispatch, getState) {\n const { user } = getState();\n return BookAPI.addBook(book.ID, user)\n .then((bool) => {\n if (bool) {\n toastr.success(\n `Successfully added!`,\n `Success`,\n constants.toastrSuccessOptions\n );\n const normalizedBook = normalizeBookObjects(\n [book],\n true\n )[0];\n dispatch({\n type: types.ADD_BOOK_TO_BOOKBAG_SUCCESS,\n normalizedBook\n });\n } else {\n toastr.warning(\n `Looks like you have this book already`,\n `Oops!`,\n constants.toastrWarningOptions\n );\n }\n })\n .catch((error) => {\n console.error('Error adding book', error);\n toastr.error(\n `Error Loading Book. ${error.statusText}`,\n `Error`,\n constants.toastrErrorOptions\n );\n });\n };\n}\n\n/*\n * Remove a book from the bookbag\n */\nexport function removeBook(bookID, bookIsbn) {\n return function (dispatch, getState) {\n const { user } = getState();\n return BookAPI.removeBook(bookID, user)\n .then((bool) => {\n if (bool) {\n dispatch({\n type: types.REMOVE_BOOK_TO_BOOKBAG_SUCCESS,\n bookID\n });\n dispatch(deleteDownloadedBook(bookIsbn))\n } else {\n toastr.error(\n `Unable to remove book.`,\n `Error`,\n constants.toastrWarningOptions\n );\n }\n })\n .catch((error) => {\n console.error('Error removing book', error);\n toastr.error(\n `Unable to Remove Book. ${error.statusText}`,\n `Error`,\n constants.toastrErrorOptions\n );\n });\n };\n}\n\n/*\n * get the book data by it's ID from redux, downloadBooks, books, or the API\n */\nexport function getBookByID(bookID, user) {\n return function (dispatch, getState) {\n let book = getState().book;\n \n // 1) if the book is already in redux as the active book (this happens after token login and page refresh)\n if (book.ID === bookID) {\n return Promise.resolve(book);\n }\n // 2) search downloadedBooks, downloadedBooks should have bookItems\n book = getState().downloadedBooks.filter((b) => {\n return b.ID === bookID;\n })[0];\n if (book) {\n dispatch({ type: types.LOAD_BOOK_SUCCESS, book });\n return Promise.resolve(book);\n }\n // 3) search books\n book = getState().books.filter((b) => {\n return b.ID === bookID;\n })[0];\n if (book) {\n dispatch({ type: types.LOAD_BOOK_SUCCESS, book });\n return Promise.resolve(book);\n }\n \n // 4) get it from the API\n // only users who are not a student should get here. We do not keep track of page numbers or support offline bookitems\n if (getState().offlineQueue.isOnline && navigator.onLine) {\n dispatch(beginAjaxCall());\n return BookAPI.getBookByID(bookID, user)\n .then((book) => {\n dispatch({ type: types.FETCH_BOOK_SUCCESS, book });\n return book;\n })\n .catch((error) => {\n dispatch({ type: types.FETCH_BOOK_FAILED, error });\n\n throw error;\n });\n } else {\n return Promise.reject(\n 'unable to get book object. Please check your internet connection and try again'\n );\n }\n };\n}\n\nconst normalizeBook = (book, pagesVisible, dispatch) => {\n const isOdd = (num) => {\n return num % 2;\n };\n const originalCurrentPage = book.CurrentPage || initialState.book.CurrentPage;\n let CurrentPage;\n if (book.LeftPageEven && pagesVisible === 2 && isOdd(originalCurrentPage)) {\n CurrentPage = originalCurrentPage - 1;\n } else if (\n !book.LeftPageEven &&\n pagesVisible === 2 &&\n !isOdd(originalCurrentPage)\n ) {\n CurrentPage = originalCurrentPage - 1;\n } else {\n CurrentPage = originalCurrentPage;\n }\n if (config.Debug) {\n book = { ...book, IsAudioEnabled: true, IsAudioAvailable: true }; // helping test when audio is not enabled\n }\n\n // if the book page is wider than it is tall, switch to single page view automatically\n const bookPageWidth = book.bounds[0][0];\n const bookPageHeight = book.bounds[0][1];\n if (bookPageWidth > bookPageHeight) {\n dispatch({\n type: types.AUTOMATIC_UPDATE_PAGES_VISIBLE,\n pagesVisible: 1\n });\n }\n return { ...book, CurrentPage };\n};\n\n/*\n * Get all the book items for the books the user has downloaded to their device\n * This helps us make sure their book items are up to date before the user goes offline\n */\nexport function getBookItemsList(downloadedBooks, user) {\n let bookIDs = [];\n forEach(downloadedBooks, (book) => {\n bookIDs.push(book.ID);\n });\n return function (dispatch, getState) {\n return BookAPI.getBookItemsList(bookIDs, user)\n .then((bookItems) => {\n forEach(bookItems, (bi) => {\n bi.Content = JSON.parse(bi.Content);\n dispatchBookItem(dispatch, bi, bi.BookID);\n });\n })\n .catch((err) => {\n dispatch({ type: types.FETCH_BOOKITEMS_FAILED, err });\n console.error('failed to fetch getBookItemsList');\n throw err;\n });\n };\n}\n\n/*\n * pass in the bookObj from the Books reducer or the DownloadedBooks reducer, as well as the Azure token\n * get get properties.json file from the file system or Azure\n * TODO improve hasBook by also checking downloadedBooks - this will help us verify that a file exists and that if finished downloading\n */\nexport function getBookProperties(bookObj, token) {\n return function (dispatch, getState) {\n const { pagesVisible } = getState().bookView;\n if (bookObj.IsEpub){\n return Promise.resolve(bookObj);\n }\n return BookFS.hasBook(bookObj).then((hasBook) => {\n const bookDownloaded = getState().downloadedBooks.find(\n (b) => b.ISBN === bookObj.ISBN\n );\n if (hasBook && bookDownloaded && bookDownloaded.bounds) {\n const book = normalizeBook(\n bookDownloaded,\n pagesVisible,\n dispatch\n );\n dispatch({ type: types.FETCH_BOOK_SUCCESS, book }); // update the book in the book reducer\n dispatch({ type: types.DOWNLOADED_BOOK_SUCCESS, book }); // update the book in the downloadedBooksReducer\n return book;\n } else {\n if (!bookObj.EBookPath || !bookObj.ISBN || !token) {\n dispatch({ type: types.FETCH_BOOK_FAILED });\n throw new Error(\n `missing book info path: ${bookObj.EBookPath} ISBN: ${bookObj.ISBN} token: ${token}`\n );\n }\n // if the book has been downloaded, but the files are no longer there, re-download it\n if (hasBook === false && bookDownloaded){\n return dispatch(downloadBook(bookDownloaded, true))\n }\n // show a special warning if we get here, we are offline and the book has been downloaded\n if (navigator.onLine === false && bookDownloaded){\n throw new Error('The download of this book has been removed. Please connect to the internet and re-download this book.')\n }\n return BookAPI.getBookProperties(bookObj, token)\n .then((bookProperties) => {\n const book = normalizeBook(\n { ...bookObj, ...bookProperties },\n pagesVisible,\n dispatch\n );\n dispatch({ type: types.FETCH_BOOK_SUCCESS, book }); // update the book in the book reducer\n // update the book in the downloadedBooksReducer if we have it downloaded\n if (bookDownloaded){\n dispatch({type: types.DOWNLOADED_BOOK_SUCCESS, book }); \n }\n return book;\n })\n .catch((err) => {\n if (err.status === 403) {\n debouncedCheckSession(getState().user, dispatch);\n }\n dispatch({ type: types.FETCH_BOOK_FAILED, err });\n throw err;\n });\n }\n });\n };\n}\n\n/*\n * get the page from local storage or remote?\n */\nexport function getBookPage(book, index, token, pageKey) {\n return function (dispatch, getState) {\n return BookFS.hasBook(book).then((hasBook) => {\n // console.log('checking for book page', hasBook, book.ISBN)\n if (hasBook) {\n return BookAPI.getBookPageLocal(book, index, pageKey);\n } else {\n return BookAPI.getBookPageRemote(\n book,\n index,\n token,\n pageKey\n ).catch((err) => {\n if (err.status === 403) {\n debouncedCheckSession(getState().user, dispatch);\n throw err;\n } else {\n throw err;\n }\n });\n }\n });\n };\n}\n\n/*\n * Download the book\n * download the book, then speechmarks, then book properties\n */\nexport function downloadBook(book, forceDownload = false) {\n return function (dispatch, getState) {\n return BookFS.hasBook(book).then((hasBook) => {\n if (hasBook && forceDownload === false) {\n console.log('have book, returning true');\n return Promise.resolve(true);\n } else {\n dispatch(beginAjaxCall());\n return BookAPI.downloadBook(book, getState().user.AzureToken)\n .then(() => {\n dispatch({ type: types.DOWNLOADED_BOOK_SUCCESS, book });\n return dispatch(downloadSpeech(book)).then(()=>{\n return dispatch(getBookProperties(book, getState().user.AzureToken))\n });\n })\n .catch((error) => {\n console.error('error downloading book', error);\n let message =\n 'Error downloading book. Please contact support or try again.';\n if (error.status === 403) {\n debouncedCheckSession(getState().user, dispatch);\n }\n if (error.status === 404) {\n message = `Book not available for offline viewing (404). Please contact support or try again`;\n }\n toastr.error(\n `Error`,\n message,\n constants.toastrErrorOptions\n );\n dispatch({ type: types.DOWNLOADED_BOOK_FAILED });\n return Promise.reject(error);\n });\n }\n });\n };\n}\n\nexport function deleteDownloadedBook(isbn) {\n return function (dispatch, getState) {\n toastr.confirm(\n 'Are you sure you want to remove this downloaded book?',\n {\n okText: 'Remove Download',\n cancelText: 'Cancel',\n onOk: () => {\n BookFS.removeBook(isbn)\n .then(() => {\n console.log('removed downloaded book', isbn);\n })\n .catch((error) => {\n console.error(\n 'ignoring error removing book',\n error\n );\n });\n dispatch({\n type: types.DELETE_DOWNLOADED_BOOK,\n payload: isbn\n });\n },\n onCancel: () => {}\n }\n );\n };\n}\n\nexport function downloadSpeech(book) {\n return function (dispatch, getState) {\n if (!book.IsAudioAvailable) {\n // TODO switch this to check !book.IsAudioEnabled || !book.IsAudioAvailable\n return Promise.resolve(true);\n } else {\n const speechDirectory = `books/${book.ISBN}/audio`;\n return BookFS.hasDirectory(speechDirectory).then((hasFile) => {\n if (hasFile) {\n return true;\n } else {\n dispatch(beginAjaxCall());\n return BookAPI.downloadSpeech(\n book,\n getState().user.AzureToken\n )\n .then(() => {\n dispatch({\n type: types.DOWNLOADED_SPEECH_SUCCESS,\n book\n });\n })\n .catch((error) => {\n if (error.status === 403) {\n debouncedCheckSession(\n getState().user,\n dispatch\n );\n dispatch({\n type: types.DOWNLOADED_SPEECH_FAILED\n });\n }\n dispatch({ type: types.DOWNLOADED_SPEECH_FAILED });\n return Promise.reject(error);\n });\n }\n });\n }\n };\n}\n\n/*\n * get audio for text to speech\n * TODO improve how we hanlde successfully getting the speechmark files, but not the audio files. Curently if this happens\n * when the user clicks the play button we log an error but we show nothing to the user.\n */\nexport function getSpeechAudio(book, index, voice, token) {\n return function (dispatch, getState) {\n return BookFS.hasBook(book).then((hasBook) => {\n if (hasBook) {\n const speechDirectory = `books/${book.ISBN}/audio`;\n return BookFS.hasDirectory(speechDirectory).then((hasFile) => {\n if (hasFile) {\n return BookFS.getFileUrl(\n book.ISBN,\n `audio/default/${index}.mp3`\n );\n } else {\n // if we don't have the file locally, try to get it from the server\n const root = `${config.API.Storage}${book.EBookPath}${book.ISBN}/`;\n return `${root}audio/${voice}/${index}.mp3${token}`;\n }\n });\n } else {\n const root = `${config.API.Storage}${book.EBookPath}${book.ISBN}/`;\n return `${root}audio/${voice}/${index}.mp3${token}`;\n }\n });\n };\n}\n/*\n * getSpeechMarks determins if speechMarks is enabled then gets the marks locally or remotely\n */\nexport function getSpeechMarks(book, index, token, pageKey) {\n return function (dispatch, getState) {\n if (book.IsEpub){\n return Promise.resolve(true);\n }\n if (!book.IsAudioAvailable) {\n // test speechmarks - TODO switch this to check !book.IsAudioEnabled || !book.IsAudioAvailable\n // if audio is Not enabled, simply return true\n return Promise.resolve(true);\n } else {\n return BookFS.hasBook(book).then((hasBook) => {\n if (hasBook) {\n return getSpeechMarksLocal(book, index).then((marks) => {\n const parsedMarks = parseSpeechMarks(marks);\n dispatch({\n type: types.GET_SPEECH_MARKS,\n parsedMarks,\n pageKey\n });\n });\n } else {\n return BookAPI.getSpeechMarksRemote(\n book,\n index,\n token\n ).then((marks) => {\n const parsedMarks = parseSpeechMarks(marks);\n // not including \"SUCCESS\" on end of dispatch type because we do not want to block the user\n dispatch({\n type: types.GET_SPEECH_MARKS,\n parsedMarks,\n pageKey\n });\n });\n }\n });\n }\n };\n}\n\n/*\n * utility function to normalize book objects\n */\nfunction normalizeBookObjects(books, isInBookBag) {\n const flattenedBooks = books.map((book) => {\n return { ...book, ...book.Book, isInBookBag };\n });\n return uniqBy(flattenedBooks, 'ID');\n // const CurrentPage = book.CurrentPage || 1;\n // return {...book, CurrentPage}\n}\n/*\n * utility function to get the speechMarksData from filesystem\n */\nfunction getSpeechMarksLocal(book, index) {\n return BookFS.getBookFileEntry(book.ISBN, `audio/default/${index}.marks`)\n .then((result) => {\n return result;\n })\n .catch((error) => {\n console.error('failed to get marks for:', book.ISBN, index);\n return Promise.resolve([]); // return an empty speechMarks for this page\n });\n}\n/*\n * utility function to parse the speech marks into proper JSON\n */\nfunction parseSpeechMarks(marks) {\n // console.log('marks', marks)\n if (marks.length <= 0) {\n return marks;\n } else {\n const speechMarksArray = marks.trim().split(/\\n/);\n return speechMarksArray.map((mark) => {\n return JSON.parse(mark);\n });\n }\n}\n\n/*\n * utility function to identify a single bookItem and dispatch it to the correct action\n */\nfunction dispatchBookItem(dispatch, bi, bookID) {\n let currentDate = moment.utc().format();\n bi = Object.assign(bi, { LastDownloadedFromServer: currentDate });\n if (!bi) {\n throw new Error('missing book item');\n }\n switch (bi.Type) {\n case 1:\n dispatch({\n type: types.SAVE_BOOKITEM_BOOKMARK_SUCCESS,\n bookmark: bi,\n bookID\n });\n break;\n case 2:\n dispatch({\n type: types.SAVE_BOOKITEM_HIGHLIGHT_SUCCESS,\n highlights: bi,\n bookID\n });\n break;\n case 3:\n dispatch({\n type: types.SAVE_BOOKITEM_NOTE_SUCCESS,\n note: bi,\n bookID\n });\n break;\n case 4:\n // TODO should we save this offline?\n dispatch({\n type: types.SAVE_BOOKITEM_NOTE_SUCCESS,\n note: bi,\n bookID\n });\n break;\n case 5:\n dispatch({\n type: types.SAVE_BOOKITEM_NOTE_SUCCESS,\n note: bi,\n bookID\n });\n break;\n case 6:\n dispatch({\n type: types.SAVE_BOOKITEM_NOTE_SUCCESS,\n note: bi,\n bookID\n });\n break;\n default:\n console.error('received invalid bookItem.Type', bi);\n }\n return bi;\n}\n\n/*\n * utility function to parse the bookItems and return an object with the bookItems split into the appropriate object\n */\nfunction parseBookItems(bookItems, user, bookID) {\n let currentDate = moment.utc().format();\n let highlights = {};\n let notes = [];\n let bookmarks = [];\n bookItems.sort((a, b) => {\n return a.Page - b.Page;\n });\n forEach(bookItems, (bi) => {\n let Content = {};\n try {\n Content = JSON.parse(bi.Content);\n } catch (error) {\n console.error('unable to parse book item', bi.Content);\n return;\n }\n bi = Object.assign(bi, {\n LastDownloadedFromServer: currentDate,\n Content\n });\n // if(UserAPI.isStudent(user.RoleID)) { // commenting this out - TODO need to test opening books as different user types\n switch (bi.Type) {\n case 1:\n bookmarks.push(bi);\n break; // 1 = bookmark\n case 2:\n highlights = bi;\n break; // 2 = markup\n case 3:\n notes.push(bi);\n break; // 3 = student note\n case 4:\n notes.push(bi);\n break; // 4 = teacher note to student\n case 5:\n notes.push(bi);\n break; // 5 = teacher note to class\n case 6:\n notes.push(bi);\n break; // 6 = teacher note to group\n default:\n console.error('unknown bookitem type', bi);\n }\n });\n return { highlights, notes, bookmarks, bookID };\n}\n\n/*\n * Get the bookItems.\n * Pass in the bookID, user, and downloadedBooks\n * if we are offline, then return the bookItems from the downloadedBooks\n */\nexport function getBookItems(bookID, user, downloadedBooks) {\n return function (dispatch, getState) {\n // if (!getState().offlineQueue.isOnline || !navigator.onLine) {\n let downloadedBook = downloadedBooks.filter((book) => {\n return book.ID === bookID;\n })[0];\n if (!downloadedBook) {\n if (navigator.onLine === false) {\n throw new Error(\n 'Missing book in downloadedBooks, please connect to the internet.'\n );\n }\n dispatch(beginAjaxCall());\n return BookAPI.getBookItems(bookID, user)\n .then((bookItems) => {\n const parsedBookItems = parseBookItems(\n bookItems,\n user,\n bookID\n );\n //update the bookItems in the book reducer and the downloadedBooks reducer\n dispatch({\n type: types.FETCH_BOOKITEMS_SUCCESS,\n ...parsedBookItems\n });\n return bookItems;\n })\n .catch((error) => {\n dispatch({ type: types.FETCH_BOOKITEMS_FAILED, error });\n throw error;\n });\n } else {\n dispatch({\n type: types.FETCH_BOOKITEMS_SUCCESS,\n bookmarks: downloadedBook.bookmarks,\n highlights: downloadedBook.highlights,\n notes: downloadedBook.notes,\n bookID: bookID\n }); // updates the bookItems in the book reducer and the downloadedBooks reducer\n return Promise.resolve('OFFLINE');\n }\n\n // } else {\n // dispatch(beginAjaxCall());\n // return BookAPI.getBookItems(bookID, user)\n // .then((bookItems) => {\n // const parsedBookItems = parseBookItems(bookItems, user, bookID);\n // //update the bookItems in the book reducer and the downloadedBooks reducer\n // dispatch({ type: types.FETCH_BOOKITEMS_SUCCESS, ...parsedBookItems });\n // return bookItems;\n // })\n // .catch((error) => {\n // dispatch({ type: types.FETCH_BOOKITEMS_FAILED, error });\n // throw error;\n // });\n // }\n };\n}\n\nexport function getBookItemsByStudentID(bookID, StudentID, user) {\n return function (dispatch, getState) {\n if (!getState().offlineQueue.isOnline || !navigator.onLine) {\n return Promise.resolve('OFFLINE');\n }\n dispatch(beginAjaxCall());\n return BookAPI.getBookItemsByStudentID(bookID, StudentID, user)\n .then((bookItems) => {\n const parsedBookItems = parseBookItems(bookItems, user, bookID);\n dispatch({\n type: types.FETCH_BOOKITEMS_STUDENT_SUCCESS,\n ...parsedBookItems\n });\n return bookItems;\n })\n .catch((error) => {\n dispatch({ type: types.FETCH_BOOKITEMS_STUDENT_FAILED, error });\n throw error;\n });\n };\n}\n\n// We call this when a teacher gets a token to leave a note for a class or a group\n// This is the TEACHERS items, meaning if they made a comment, they can what they\n// have previously made when they come back in the future.\n\nexport function getTeacherBookItems(data, user, bookID) {\n return function (dispatch, getState) {\n if (!getState().offlineQueue.isOnline || !navigator.onLine) {\n return Promise.resolve('OFFLINE');\n }\n dispatch(beginAjaxCall());\n return BookAPI.getTeacherBookItems(data, user)\n .then((bookItems) => {\n let currentDate = moment.utc().format();\n let notes = [];\n bookItems.sort((a, b) => {\n return a.Page > b.Page;\n });\n forEach(bookItems, (bi) => {\n bi = Object.assign(bi, {\n LastDownloadedFromServer: currentDate,\n Content: JSON.parse(bi.Content)\n });\n if (bi.Type === 4) {\n notes.push(bi);\n } else if (bi.Type === 5) {\n notes.push(bi);\n } else if (bi.Type === 6) {\n notes.push(bi);\n }\n });\n dispatch({\n type: types.FETCH_BOOKITEMS_SUCCESS,\n notes,\n bookID\n });\n return bookItems;\n })\n .catch((error) => {\n dispatch({ type: types.FETCH_BOOKITEMS_FAILED, error });\n throw error;\n });\n };\n}\n// Switch the if statments to case statments\nexport function saveBookItem(bookItem, user, viewerMode, bookID) {\n return function (dispatch, getState) {\n // TODO add lastBookItemChanges\n let currentDate = moment.utc().format();\n Object.assign(bookItem, { LastBookItemChange: currentDate });\n if (!getState().offlineQueue.isOnline || !navigator.onLine) {\n let saveBookID = bookID;\n dispatch({\n type: 'OFFLINE_BOOKITEM_SAVE',\n payload: {\n action: 'saveBookItem',\n args: [bookItem, user, viewerMode, saveBookID],\n promise: {}\n },\n meta: {\n queueIfOffline: true\n }\n });\n // Lets be optimistic and assume things will go well once we come back online!\n dispatchBookItem(dispatch, bookItem, saveBookID);\n return Promise.resolve('OFFLINE');\n }\n // Online. this is the api call that persists bi-data bi-data = highlights and notes etc\n // If not a student, user should not be able to save highlights to the API\n // Checking if the roles are correct to save this item\n if (\n UserAPI.isStudent(user.RoleID) ||\n UserAPI.canAccessBook(user.RoleID, viewerMode)\n ) {\n // dispatch(beginAjaxCall()); // we probably do not want to block the user when saving bookItems\n return BookAPI.saveBookItem(bookItem, user)\n .then((bi) => {\n bi.Content = JSON.parse(bi.Content);\n const newBookItem = Object.assign({}, bookItem, bi);\n dispatchBookItem(dispatch, newBookItem, bookID);\n // dispatch({ type: types.PURGE_TEMP_ID_NOTES, bookID });\n })\n .catch((error) => {\n dispatch({ type: types.SAVE_BOOKITEM_FAILED, error });\n throw error;\n });\n } else {\n // only persist the book item locally\n dispatchBookItem(dispatch, bookItem, bookID);\n return Promise.resolve(bookItem);\n }\n };\n}\n\nexport function deleteBookItem(bookItem, user, bookID) {\n return function (dispatch, getState) {\n if (!getState().offlineQueue.isOnline || !navigator.onLine) {\n dispatch({\n type: 'OFFLINE_BOOKITEM_DELETE',\n payload: {\n action: 'deleteBookItem',\n args: [bookItem, user, bookID],\n promise: {}\n },\n meta: {\n queueIfOffline: true\n }\n });\n // Lets be optimistic and assume things will go well once we come back online!\n if (bookItem.Type === 1) {\n dispatch({\n type: types.DELETE_BOOKITEM_BOOKMARK_SUCCESS,\n bookmark: bookItem,\n bookID\n });\n } else if (bookItem.Type === 2) {\n console.error(\n 'we should not delete highlights, only save updated versions'\n );\n } else if (bookItem.Type === 3) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n } else if (bookItem.Type === 4) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n } else if (bookItem.Type === 5) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n } else if (bookItem.Type === 6) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n }\n return Promise.resolve('OFFLINE');\n }\n // dispatch(beginAjaxCall()); don't bother showing loading\n // TODO need to support deleting book items while offline and maybe for non student users\n return BookAPI.deleteBookItem(bookItem, user)\n .then((res) => {\n if (bookItem.Type === 1) {\n dispatch({\n type: types.DELETE_BOOKITEM_BOOKMARK_SUCCESS,\n bookmark: bookItem,\n bookID\n });\n } else if (bookItem.Type === 2) {\n console.error(\n 'we should not delete highlights, only save updated versions'\n );\n } else if (bookItem.Type === 3) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n } else if (bookItem.Type === 4) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n } else if (bookItem.Type === 5) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n } else if (bookItem.Type === 6) {\n dispatch({\n type: types.DELETE_BOOKITEM_NOTE_SUCCESS,\n note: bookItem,\n bookID\n });\n }\n return res;\n })\n .catch((error) => {\n dispatch({ type: types.DELETE_BOOKITEM_FAILED, error });\n throw error;\n });\n };\n}\n\n/*\n * bookTimeout : boolean = if this book was closed by timeout\n */\nexport function updateBookStatus(\n bookID,\n pageIndex,\n totalPages,\n bookTimeout,\n blmMode\n) {\n return function (dispatch, getState) {\n const { offlineQueue, bookView, user } = getState();\n const pageView =\n bookView.pagesVisible === 1 ||\n (bookView.pagesVisible === 2 && blmMode)\n ? 1\n : 2;\n if (!offlineQueue.isOnline || !navigator.onLine) {\n dispatch({\n type: 'OFFLINE_BOOKITEM_SAVE',\n payload: {\n action: 'updateBookStatus',\n args: [\n bookID,\n pageIndex,\n totalPages,\n pageView,\n bookTimeout,\n user\n ],\n promise: {}\n },\n meta: {\n queueIfOffline: true\n }\n });\n // Lets be optimistic and assume things will go well once we come back online!\n dispatch({\n type: types.UPDATE_BOOKSTATUS_SUCCESS,\n bookID,\n pageIndex,\n totalPages\n });\n return Promise.resolve('OFFLINE');\n }\n // dispatch(beginAjaxCall());\n return UserAPI.updateBookStatus(\n bookID,\n pageIndex,\n totalPages,\n pageView,\n bookTimeout,\n user\n )\n .then((resp) => {\n dispatch({\n type: types.UPDATE_BOOKSTATUS_SUCCESS,\n bookID,\n pageIndex,\n totalPages\n });\n return resp;\n })\n .catch((error) => {\n dispatch({ type: types.UPDATE_BOOKSTATUS_FAILED, error });\n throw error;\n });\n };\n}\n\nexport const updateCurrentPage = (currentPage, bookID) => ({\n type: types.UPDATE_CURRENT_PAGE,\n currentPage,\n bookID\n});\nexport const nextPage = () => ({\n type: types.NEXT_PAGE\n});\n\nexport const prevPage = () => ({\n type: types.PREV_PAGE\n});\n\nexport const setTotalPage = (totalPage) => ({\n type: types.TOTAL_PAGE,\n totalPage,\n});\n\nexport const cacheBookPage = (page) => ({\n type: types.CACHE_BOOK_PAGE,\n page\n});\n\n// export const resetBook = () => ({\n// type: types.RESET_BOOK\n// });\nexport const setBookReady = (ready) => ({\n type: types.SET_BOOK_READY,\n ready\n});\n\nexport const resetCachedBookPages = () => ({\n type: types.RESET_CACHED_BOOK_PAGES\n});\n// export const updateBookAudioUrl = (audioUrl) => ({\n// type: types.BOOK_UPDATE_AUDIO,\n// audioUrl\n// });\n","import * as types from './actionTypes';\n\nexport const updateLeftPageContainer = (width, height) => ({\n type: types.UPDATE_LEFT_PAGE_CONTAINER,\n width,\n height\n});\n\nexport const updateBookScalePercent = (scale) => ({\n type: types.UPDATE_BOOK_SCALE_PERCENT,\n scale\n});\n\nexport const updateProjectScalePercent = (scale) => ({\n type: types.UPDATE_PROJECT_SCALE_PERCENT,\n scale\n});\n\nexport const updatePagesVisible = (pagesVisible) => ({\n type: types.UPDATE_PAGES_VISIBLE,\n pagesVisible\n});\n\nexport const automaticUpdatePagesVisible = (pagesVisible) => ({\n type: types.AUTOMATIC_UPDATE_PAGES_VISIBLE,\n pagesVisible\n});\n\nexport const resetBookView = () => ({\n type: types.RESET_VIEW\n});\n\nexport const setActiveNote = (noteID) => ({\n type: types.SET_ACTIVE_NOTE,\n noteID\n});\n\n// if the zoom level is 100 then turn on automatic zoom\n// if it is not 100 then turn on manual zoom and set the manual zoom level by increasing or decreasing the index of the bookZoomLevels array\n// export const increaseBookZoom = (e) => {\n// return function (dispatch, getState) {\n// e.preventDefault();\n// dispatch({type: types.INCREASE_BOOK_ZOOM});\n// }\n// };\n\n// export const decreaseBookZoom = (e) => {\n// return function (dispatch, getState) {\n// e.preventDefault();\n// dispatch({type: types.DECREASE_BOOK_ZOOM});\n// }\n// };\n\nexport const increaseBookZoom = () => ({\n type: types.INCREASE_BOOK_ZOOM\n});\n\nexport const decreaseBookZoom = () => ({\n type: types.DECREASE_BOOK_ZOOM\n});\nexport const updatePendingItem = (status) => ({\n type: types.UPDATE_PENDING_ITEM,\n status\n});\n","import React, { Component, ReactElement } from 'react';\nimport { connect } from 'react-redux';\nimport defaultStyles from './EpubStyles';\nimport { EpubAudio } from './EpubAudio';\nimport {\n BOOK_FIRST_PAGE,\n BOOK_LAST_PAGE,\n BOOK_NEXT_PAGE,\n BOOK_PREV_PAGE\n} from './events';\nimport {\n nextPage,\n prevPage,\n setTotalPage,\n updateCurrentPage\n} from '../../actions/bookActions';\nimport { debounce } from 'lodash';\nimport * as types from '../../actions/actionTypes';\nimport { Dispatch } from 'redux';\nimport { IinitialState } from '../../reducers';\nimport { Ibook } from '../../models';\nimport { StyledButton } from '../../constants/styledComponents';\nimport constants from '../../constants/constants';\nimport { updatePagesVisible } from '../../actions/bookViewActions';\n\ndeclare namespace ReadiumSDK {\n const Events: {\n CONTENT_DOCUMENT_LOADED: 'ContentDocumentLoaded';\n CONTENT_DOCUMENT_LOAD_START: 'ContentDocumentLoadStart';\n CONTENT_DOCUMENT_UNLOADED: 'ContentDocumentUnloaded';\n FXL_VIEW_RESIZED: 'FXLViewResized';\n MEDIA_OVERLAY_STATUS_CHANGED: 'MediaOverlayStatusChanged';\n MEDIA_OVERLAY_TTS_SPEAK: 'MediaOverlayTTSSpeak';\n MEDIA_OVERLAY_TTS_STOP: 'MediaOverlayTTSStop';\n PAGINATION_CHANGED: 'PaginationChanged';\n PLUGINS_LOADED: 'PluginsLoaded';\n READER_INITIALIZED: 'ReaderInitialized';\n READER_VIEW_CREATED: 'ReaderViewCreated';\n READER_VIEW_DESTROYED: 'ReaderViewDestroyed';\n SETTINGS_APPLIED: 'SettingsApplied';\n };\n}\n\ninterface EpubViewOwnProps {\n url: string;\n loadingView: ReactElement;\n // audioChanged: (audio: string) => string;\n styles: { viewHolder: React.CSSProperties; view: React.CSSProperties };\n handleKeyPress: () => void;\n handleTextSelected: () => void;\n}\n\ninterface Istate {\n isLoaded: boolean;\n playingMediaOverlay: boolean;\n mediaOverlayPlayable: boolean;\n readium: any;\n}\n\ninterface EpubViewStateProps {\n readiumClass: any;\n book: Ibook;\n closeBookView: () => void;\n updatePagesVisible: (pages: number) => void;\n}\n\ninterface EpubViewDispatchProps {\n setTotalPage: (totalPage: number) => void;\n updateCurrentPage: (pageNumber: number) => void;\n}\n\ntype Iprops = EpubViewOwnProps & EpubViewDispatchProps & EpubViewStateProps;\n\nclass EpubView extends Component {\n static defaultProps = {\n loadingView: null,\n locationChanged: null,\n tocChanged: null,\n styles: defaultStyles,\n renditionOptions: {},\n epubInitOptions: {}\n };\n private readium: any;\n private debouncedSetState: any;\n private theme: any;\n\n constructor(props: Iprops) {\n super(props);\n this.state = {\n isLoaded: false,\n playingMediaOverlay: false,\n mediaOverlayPlayable: false,\n readium: {}\n };\n this.debouncedSetState = debounce(this.setState, 800).bind(this);\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n this.initBook();\n this.setEventHandler();\n }\n\n initBook() {\n const { readiumClass: RediumClass } = this.props;\n\n if (!RediumClass) {\n return;\n }\n const readerOptions = {\n needsFixedLayoutScalerWorkAround: false,\n // el:\"#viewport\",\n el: '#readium-id'\n // annotationCSSUrl: prefix + \"/annotations.css\",\n // mathJaxUrl: \"/MathJax.js\"\n };\n const readiumOptions = {\n // jsLibRoot: \"../build-output/\",\n cacheSizeEvictThreshold: undefined,\n useSimpleLoader: true, // false so we can load ZIP'ed EPUBs\n openBookOptions: {}\n };\n const readium = new RediumClass(readiumOptions, readerOptions);\n const openPageRequest = { idref: 'cover', elementCfi: '/0' }; //{idref: bookmark.idref, elementCfi: bookmark.contentCFI};\n\n this.readium = readium;\n\n readium.reader.on(\n ReadiumSDK.Events.PAGINATION_CHANGED,\n (pageChangeData: any) => {\n console.log('PAGE CHANGED:', pageChangeData);\n const { spineItem } = pageChangeData;\n this.props.updateCurrentPage(\n spineItem.index ? spineItem.index + 1 : 0\n );\n console.log(\n readium.reader.isMediaOverlayAvailable(),\n readium.reader.isPlayingMediaOverlay()\n );\n this.debouncedSetState({\n playingMediaOverlay:\n !!readium.reader.isPlayingMediaOverlay(),\n mediaOverlayPlayable:\n readium.reader.isMediaOverlayAvailable()\n });\n }\n );\n\n readium.reader.on(\n ReadiumSDK.Events.MEDIA_OVERLAY_STATUS_CHANGED,\n (event: any) => {\n console.log('MEDIA OVERLAY CHANGED:', event);\n if (event.isPlaying != null) {\n this.debouncedSetState({\n playingMediaOverlay: event.isPlaying\n });\n }\n }\n );\n readium.reader.on(ReadiumSDK.Events.FXL_VIEW_RESIZED, (event: any) => {\n console.log('view resized', readium.reader.getViewScale());\n });\n\n // Comment in the appropriate URL for Testing Epub\n // const ebookURL = 'books/Chickens';\n // const ebookURL = \"http://localhost:8080/books/ePUBS/Crabtree/test/unzipped/Chickens\";\n // const ebookURL = 'https://dibs-viewer-dev.herokuapp.com/books/ePUBS/Crabtree/test/unzipped/Chickens'\n if (!this.props.url) {\n return;\n }\n const ebookURL = this.props.url;\n readium.openPackageDocument(\n ebookURL,\n (packageDocument: any, options: any) => {\n if (!packageDocument) {\n console.error('ERROR OPENING EBOOK: ');\n }\n const totalPage = packageDocument.spineLength();\n this.props.setTotalPage(totalPage);\n // console.log('readium reader', readium.reader);\n\n // change these values to affec the default state of the application's preferences at first-run.\n var defaultSettings = {\n fontSize: 100,\n fontSelection: 0, //0 is the index of default for our purposes.\n syntheticSpread: 'auto',\n scroll: 'auto',\n columnGap: 60,\n columnMaxWidth: 550,\n columnMinWidth: 400\n };\n\n this.updateSettings(defaultSettings);\n },\n openPageRequest\n );\n }\n\n updatePagesVisble = (event: any) => {\n if (\n event.detail &&\n typeof event.detail.pagesVisible === 'number' &&\n event.detail.pagesVisible === 1\n ) {\n this.updateSettings({ syntheticSpread: 'single', scroll: 'auto' });\n } else {\n this.updateSettings({ syntheticSpread: 'double', scroll: 'auto' });\n }\n };\n\n updateSettings = (readerSettings: any) => {\n if (this.readium.reader) {\n this.readium.reader.updateSettings(readerSettings);\n }\n };\n\n componentWillUnmount() {\n // this.book = this.rendition = this.prevPage = this.nextPage = null;\n this.removeEventHandler();\n }\n\n componentDidUpdate(prevProps: Iprops) {\n if (\n prevProps.url !== this.props.url ||\n prevProps.readiumClass !== this.props.readiumClass\n ) {\n this.initBook();\n }\n }\n\n setEventHandler() {\n document.addEventListener(BOOK_NEXT_PAGE, this.nextPage);\n document.addEventListener(BOOK_PREV_PAGE, this.prevPage);\n document.addEventListener(BOOK_FIRST_PAGE, this.firstPage);\n document.addEventListener(BOOK_LAST_PAGE, this.lastPage);\n document.addEventListener(\n types.UPDATE_PAGES_VISIBLE,\n this.updatePagesVisble\n );\n document.addEventListener(\n types.INCREASE_BOOK_ZOOM,\n this.increaseBookZoom\n );\n document.addEventListener(\n types.DECREASE_BOOK_ZOOM,\n this.decreaseBookZoom\n );\n }\n\n removeEventHandler() {\n document.removeEventListener(BOOK_NEXT_PAGE, this.nextPage);\n document.removeEventListener(BOOK_PREV_PAGE, this.prevPage);\n document.removeEventListener(BOOK_FIRST_PAGE, this.firstPage);\n document.removeEventListener(BOOK_LAST_PAGE, this.lastPage);\n document.removeEventListener(\n types.UPDATE_PAGES_VISIBLE,\n this.updatePagesVisble\n );\n document.removeEventListener(\n types.INCREASE_BOOK_ZOOM,\n this.increaseBookZoom\n );\n document.removeEventListener(\n types.DECREASE_BOOK_ZOOM,\n this.decreaseBookZoom\n );\n }\n\n nextPage = () => {\n if (!this.readium) {\n return;\n }\n this.readium.reader.openPageNext();\n };\n\n prevPage = () => {\n this.readium && this.readium.reader.openPagePrev();\n };\n\n firstPage = () => {\n if (!this.readium) {\n return;\n }\n this.readium.reader.openPageIndex(0);\n };\n\n lastPage = () => {\n if (!this.readium) {\n return;\n }\n const lastSpine = this.readium.reader.spine().last();\n this.readium.reader.openPageIndex(lastSpine.index);\n };\n\n increaseBookZoom = (): void => {\n const currentScale = this.readium.reader.getViewScale();\n const newScale = (currentScale + 10) / 100;\n this.readium.reader.setZoom({ scale: newScale, style: 'user' });\n };\n decreaseBookZoom = (): void => {\n const currentScale = this.readium.reader.getViewScale();\n const newScale = (currentScale - 10) / 100;\n this.readium.reader.setZoom({ scale: newScale, style: 'user' });\n };\n\n updateMediaOverlayPlaying(status: boolean) {\n if (!this.state.mediaOverlayPlayable) {\n this.setState({\n playingMediaOverlay: false\n });\n return;\n }\n\n if (status) {\n this.readium.reader.playMediaOverlay();\n } else {\n this.readium.reader.pauseMediaOverlay();\n }\n }\n\n render() {\n const { styles } = this.props;\n return (\n <>\n this.props.closeBookView()}\n >\n \n \n
\n this.props.updatePagesVisible(1)}\n >\n \n \n this.props.updatePagesVisible(2)}\n >\n \n \n
\n
\n \n \n );\n }\n}\n\nconst mapStateToProps = (state: IinitialState) => ({\n readiumClass: state.readium.readiumClass,\n book: state.book\n});\n\nconst mapDispatchToProps = (dispatch: Dispatch) => ({\n nextPage: () => dispatch(nextPage()),\n prevPage: () => dispatch(prevPage()),\n updatePagesVisible: (pages: number) => dispatch(updatePagesVisible(pages)),\n setTotalPage: (totalPage: number) => dispatch(setTotalPage(totalPage)),\n updateCurrentPage: (pageNumber: number) =>\n dispatch(updateCurrentPage(pageNumber))\n});\n\nexport default connect(mapStateToProps, mapDispatchToProps)(EpubView);\n","import config from './config';\n\nexport default class BlmAPI {\n static getAssignedBLMs(bookID, user) {\n const URL = `${config.API.Main}/blacklinemaster/getassignedblms?bookid=${bookID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json().then((blms) => {\n return blms;\n });\n });\n }\n\n static studentAssignedBLMs(user) {\n const URL = `${config.API.Main}/blacklinemaster/getstudentassignedblms`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json().then((blms) => {\n return blms;\n });\n });\n }\n\n static getBLMByID(blmID, user) {\n // blacklinemaster/getblm?blmiID=XXX\n const URL = `${config.API.Main}/blacklinemaster/getblm?blmID=${blmID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getBLMProperties(blm, user) {\n const remoteURL = `${config.API.Storage}${blm.EBookPath}properties.json${user}`;\n var request = new Request(remoteURL, { method: 'GET' });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getBLMStatus(blmID, projectAssignmentID, user) {\n const URL = `${config.API.Main}/blacklinemaster/getstatus?blmID=${blmID}&projectAssignmentID=${projectAssignmentID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getBlmPageRemote(blm, index, token) {\n if (!token) {\n throw new Error('missing token');\n }\n // Just took this out from root url: ${book.ISBN}\n //https://dibsbookstest.blob.core.windows.net/books/BrainHive/Batch18/1/?sv=2016-05-31&sr=c&sig=FdBI2tdzVIdUMA4CQ1a7y2y6F6dS7a5v9QegJlqnmqM%3D&se=2017-09-16T20%3A21%3A19Z&sp=rl\n const root = `${config.API.Storage}${blm.EBookPath}`;\n // const htmURL = `${root}/${index}.html${token}`;\n const htmURL = `${root}${index}.html${token}`;\n const svgURL = `${root}${index}/${index}.svg${token}`;\n\n // fetch the html for the page\n const p1 = fetch(htmURL).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.text();\n });\n // fetch the svg data for the page\n const p2 = fetch(svgURL)\n .then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.text();\n })\n // catch any errors with svg fetch so we can\n // inspect and not autofail the whole request.\n .catch((err) => {\n if (err.status === 404) {\n // then this is a benign error - the svg is simply not there as expected\n return err.status;\n } else {\n throw err;\n }\n });\n return Promise.all([p1, p2]).then((values) => {\n // return values;\n let pageData = values[0];\n let svgData = values[1];\n if (svgData === 404) {\n //not found\n svgData = '';\n } else {\n // replace all relative image urls with full url\n svgData = svgData.replace(\n /((\\w*)\\/[0-9]*.(png|jpg))+/g,\n `${root}${index}/$1${token}`\n );\n // remove extra crap we do not need for an embedded svg\n svgData = svgData.replace(\n '',\n ''\n );\n }\n // now replace the entire svg in the html with the svg element\n pageData = pageData.replace(/()+/, svgData);\n // replace fonts path\n pageData = pageData.replace(\n /(fonts\\/[a-zA-Z0-9\\-_]*.\\w*)/g,\n `${root}$1${token}`\n );\n return pageData;\n });\n }\n\n static updateStatus(blm, user) {\n const URL = `${config.API.Main}/blacklinemaster/updatestatus`;\n const body = JSON.stringify({\n ...blm,\n Content: JSON.stringify(blm.Content)\n });\n\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(user),\n body: body\n });\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static saveBLMTemplate(blmItem, user) {\n const URL = `${config.API.Main}/viewer/saveblmtemplate`;\n const body = JSON.stringify({\n ...blmItem,\n Content: JSON.stringify(blmItem.Content)\n });\n\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(user),\n body: body\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static saveBLMItem(blmItem, user) {\n const URL = `${config.API.Main}/viewer/saveblmitem`;\n const body = JSON.stringify({\n ...blmItem,\n Content: JSON.stringify(blmItem.Content)\n });\n\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(user),\n body: body\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getBLMItems(blmID, paID, user) {\n const URL = `${config.API.Main}/viewer/getblmitems?blmID=${blmID}&projectAssignmentID=${paID}`;\n\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getTemplateItems(blmID, user) {\n const URL = `${config.API.Main}/viewer/gettemplateitems?blmID=${blmID}`;\n\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getStudentsBLMItems(blmID, paID, studentID, user) {\n const URL = `${config.API.Main}/viewer/getstudentblmitems?blmID=${blmID}&studentID=${studentID}&projectAssignmentID=${paID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static teacherMakesBLMComment(data, user) {\n const URL = `${config.API.Main}/blacklinemaster/saveteachercomment`;\n const body = JSON.stringify({\n ...data,\n Content: JSON.stringify(data.Content)\n });\n\n var request = new Request(URL, {\n method: 'POST',\n headers: this.getHeaders(user),\n body: body\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n static getTeachersComment(paID, TeacherID, user) {\n const URL = `${config.API.Main}/blacklinemaster/getstudentteachercomment?ProjectAssignmentID=${paID}&teacherId=${TeacherID}`;\n var request = new Request(URL, {\n method: 'GET',\n headers: this.getHeaders(user)\n });\n\n return fetch(request).then((response) => {\n if (response.status !== 200) {\n throw response;\n }\n return response.json();\n });\n }\n\n /*\n Convenience method to construct headers using a user object to obtain\n their apiKey\n */\n\n static getHeaders(user = false) {\n var headers = new Headers();\n headers.append('Content-Type', 'application/json');\n if (!!user) {\n headers.append('apiKey', user.APIKey || '');\n }\n return headers;\n }\n}\n","import * as types from './actionTypes';\nimport BlmAPI from '../api/blmAPI';\nimport { beginAjaxCall } from './ajaxStatusActions';\nimport { map, forEach } from 'lodash';\nimport { debouncedCheckSession } from './userActions';\n\nexport function getAssignedBLMs(bookID, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getAssignedBLMs(bookID, user)\n .then((blms) => {\n blms = map(blms[0], (blm) => {\n let tempObj = Object.assign(\n {},\n blm.ProjectItem.BlackLineMaster\n );\n tempObj.ProjectItemID = blm.ProjectItemID;\n tempObj.projectAssignmentID = blm.ID;\n // grab the AccountID - this is the teacher's ID. sometimes it is assinged to a class and sometimes a group\n if (blm.Class && blm.Class.AccountID) {\n tempObj.TeacherID = blm.Class.AccountID;\n }\n if (blm.Group && blm.Group.AccountID) {\n tempObj.TeacherID = blm.Group.AccountID;\n }\n return tempObj;\n });\n dispatch({ type: types.LOAD_BLMS_SUCCESS, blms });\n\n return blms;\n })\n .catch((error) => {\n dispatch({ type: types.LOAD_BLMS_FAILED });\n throw error;\n });\n };\n}\n// We might need this call in the future\n// export function studentAssignedBLMs(user){\n// return function (dispatch, getState) {\n// return BlmAPI.studentAssignedBLMs(user)\n// .then(blms => {\n// dispatch({ type: types.GET_COMPLETED_BLMS_SUCCESS, completedBLMs: blms[1] });\n// })\n// .catch(err => {\n// dispatch({ type: types.GET_COMPLETED_BLMS_FAILED})\n// console.log(err);\n// })\n// }\n// }\n\nexport function emptyBLMs() {\n return { type: types.LOAD_BLMS_SUCCESS, blms: [] };\n}\n\nexport function emptyBLMData(blm) {\n delete blm.blmData;\n return {\n type: types.REMOVE_BLM_DATA_SUCCESS,\n blm: blm\n };\n}\n\nexport function teacherMakesBLMComment(data, token) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.teacherMakesBLMComment(data, token)\n .then((comment) => {\n let teachersComment = comment.Text;\n dispatch({\n type: types.SAVE_TEACHERS_COMMENT_SUCCESS,\n teachersComment\n });\n return teachersComment;\n })\n .catch((error) => {\n dispatch({ type: types.SAVE_TEACHERS_COMMENT_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function getBLMProperties(blmObj, token) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getBLMProperties(blmObj, token)\n .then((blmProperties) => {\n const blm = Object.assign({}, blmObj, blmProperties);\n\n // if (!blm.fabricjs) { blm.fabricjs = {}; } // TODO store the fabricjs item here???\n dispatch({ type: types.FETCH_BLM_SUCCESS, blm });\n return blm;\n })\n .catch((error) => {\n if (error.status === 403) {\n debouncedCheckSession(getState().user, dispatch);\n }\n dispatch({ type: types.FETCH_BLM_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function getTeachersComment(paID, TeacherID, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getTeachersComment(paID, TeacherID, user)\n .then((comment) => {\n let teachersComment;\n if (comment === null) {\n teachersComment = '';\n } else {\n teachersComment = comment.Text;\n }\n dispatch({\n type: types.GET_TEACHERS_BLM_COMMENT_SUCCESS,\n teachersComment\n });\n })\n .catch((error) => {\n dispatch({\n type: types.GET_TEACHERS_BLM_COMMENT_FAILED,\n error\n });\n throw error;\n });\n };\n}\nexport function getBLMStatus(blm, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getBLMStatus(blm.ID, blm.projectAssignmentID, user)\n .then((blmStatus) => {\n let isComplete;\n if (blmStatus === null) {\n isComplete = false;\n } else {\n isComplete = blmStatus.IsComplete;\n }\n dispatch({ type: types.GET_BLM_STATUS_SUCCESS, isComplete });\n return blm;\n })\n .catch((error) => {\n dispatch({ type: types.GET_BLM_STATUS_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function getBLMByID(blmID, user) {\n return function (dispatch, getstate) {\n dispatch(beginAjaxCall());\n return BlmAPI.getBLMByID(blmID, user)\n .then((blm) => {\n dispatch({ type: types.FETCH_BLM_SUCCESS, blm });\n return blm;\n })\n .catch((error) => {\n dispatch({ type: types.FETCH_BLM_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function getBLMItems(blmID, paID, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getBLMItems(blmID, paID, user)\n .then((blmItems) => {\n let originalBLMTemplate;\n // include the original blm template in the dispatch\n // determine what the template information is\n let fabricItemsStudent = {\n Type: 1,\n HasTemplate: false,\n Content: {}\n };\n let fabricItemsTemplate = {};\n let fabricItems, blmData;\n\n forEach(blmItems, (bi) => {\n bi.Content = JSON.parse(bi.Content);\n if (bi.Type === 1) {\n fabricItemsStudent = bi;\n } else if (bi.Type === 2) {\n fabricItemsTemplate = bi;\n originalBLMTemplate = bi;\n }\n });\n\n // If there is a template and there is not student template\n // That means a student has never worked on the template\n // we will add the attribute HasTemplate to determine viewer functionality\n // HasTemplate = students starting off a pre-existing creator template\n if (fabricItemsTemplate.ID && !fabricItemsStudent.ID) {\n fabricItems = fabricItemsTemplate;\n fabricItems.HasTemplate = true;\n fabricItems.Type = 1;\n } else {\n // either nothing from the api or something from the api and no template\n fabricItems = fabricItemsStudent;\n }\n blmData = fabricItems.Content;\n\n dispatch({\n type: types.GET_BLM_ITEMS_SUCCESS,\n blmData,\n fabricItems,\n originalBLMTemplate\n });\n return blmItems;\n })\n .catch((error) => {\n dispatch({ type: types.GET_BLM_ITEMS_FAILED });\n throw error;\n });\n };\n}\n\n// We call getTemplateItems when we are in MODE_ADMIN_CREATE_TEMPLATE\n// getTemplateItems grabs any previously made content with this particular blm\n\nexport function getTemplateItems(blmID, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getTemplateItems(blmID, user)\n .then((blmItems) => {\n let fabricItems = { Type: 2, HasTemplate: false, Content: {} };\n\n if (blmItems.length > 0 && blmItems[0].ID.length > 0) {\n fabricItems.Content = JSON.parse(blmItems[0].Content);\n }\n\n let blmData = fabricItems.Content;\n dispatch({\n type: types.GET_BLM_ITEMS_SUCCESS,\n blmData,\n fabricItems\n });\n })\n .catch((error) => {\n dispatch({ type: types.GET_BLM_ITEMS_FAILED });\n throw error;\n });\n };\n}\n\nexport function getStudentsBLMItems(blmID, paID, studentID, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.getStudentsBLMItems(blmID, paID, studentID, user)\n .then((blmItems) => {\n let blmData = JSON.parse(blmItems[0].Content);\n dispatch({ type: types.GET_BLM_ITEMS_SUCCESS, blmData });\n })\n .catch((error) => {\n dispatch({ type: types.GET_BLM_ITEMS_FAILED });\n throw error;\n });\n };\n}\n\nexport function saveBLMItem(blmItem, user, showLoading) {\n return function (dispatch, getState) {\n if (showLoading) {\n dispatch(beginAjaxCall());\n }\n\n if (!getState().offlineQueue.isOnline || !navigator.onLine) {\n dispatch({\n type: 'OFFLINE_PROJECT_ITEM_SAVE',\n payload: {\n action: 'saveBLMItem',\n args: [blmItem, user, showLoading],\n promise: {}\n },\n meta: {\n queueIfOffline: true\n }\n });\n // Lets be optimistic and assume things will go well once we come back online!\n dispatch({\n type: types.SAVE_BLMITEM_FABRIC_SUCCESS,\n blmData: blmItem.Content\n });\n\n return Promise.resolve('OFFLINE');\n } else {\n return BlmAPI.saveBLMItem(blmItem, user)\n .then((blmItem) => {\n let blmData = JSON.parse(blmItem.Content);\n if (blmItem.Type === 1) {\n dispatch({\n type: types.SAVE_BLMITEM_FABRIC_SUCCESS,\n blmData\n });\n } else {\n throw blmItem;\n }\n })\n .catch((error) => {\n dispatch({ type: types.SAVE_BLMITEM_FABRIC_FAILED, error });\n throw error;\n });\n }\n };\n}\n\nexport function saveBLMTemplate(blmItem, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.saveBLMTemplate(blmItem, user)\n .then((blmItem) => {\n let blmData = JSON.parse(blmItem.Content);\n dispatch({ type: types.SAVE_BLMITEM_FABRIC_SUCCESS, blmData }); // TODO why are we not dispatching here???\n })\n .catch((error) => {\n dispatch({ type: types.SAVE_BLMITEM_FABRIC_FAILED, error });\n throw error;\n });\n };\n}\n\nexport function updateStatus(data, user) {\n return function (dispatch, getState) {\n dispatch(beginAjaxCall());\n return BlmAPI.updateStatus(data, user)\n .then((updatedBlm) => {\n dispatch({\n type: types.UPDATE_BLM_STATUS_SUCCESS,\n isComplete: updatedBlm.IsComplete\n });\n return updatedBlm;\n })\n .catch((error) => {\n dispatch({ type: types.UPDATE_BLM_STATUS_FAILED });\n throw error;\n });\n };\n}\n\nexport const setProjectReady = (ready) => ({\n type: types.SET_PROJECT_READY,\n ready\n});\n","import * as types from './actionTypes';\n\nexport const startPointing = () => ({\n type: types.BOOK_TOOLBAR_POINTING\n});\n\nexport const startNotes = (allowNotes) => ({\n type: types.BOOK_TOOLBAR_NOTES,\n allowNotes\n});\n\nexport const startHighlighting = (highlighting, highlightColor) => ({\n type: types.BOOK_TOOLBAR_HIGHLIGHTING,\n highlighting,\n highlightColor\n});\n\nexport const startErasing = (erasing) => ({\n type: types.BOOK_TOOLBAR_ERASING,\n erasing\n});\n\nexport const startUnderlining = (underlining) => ({\n type: types.BOOK_TOOLBAR_UNDERLINING,\n underlining\n});\n\nexport const startStriking = (striking) => ({\n type: types.BOOK_TOOLBAR_STRIKING,\n striking\n});\n\nexport const startMoving = () => ({\n type: types.BOOK_TOOLBAR_MOVING\n});\n","import * as React from 'react';\nimport { Modal, Button } from 'react-bootstrap';\nimport constants from '../../constants/constants';\nimport { StyledButton } from '../../constants/styledComponents';\n\nclass CommonModal extends React.Component {\n theme = constants.themeProvider.activeTheme;\n\n render() {\n return (\n
\n \n \n {this.props.title}\n \n {\n e.preventDefault();\n this.props.submit(e);\n }}\n className=\"dibs-form\"\n >\n {this.props.children}\n \n \n {this.props.cancelText}\n \n \n {this.props.submitText}\n \n \n \n \n
\n );\n }\n}\n\nexport default CommonModal;\n","import JPlayer, {\n Audio,\n BrowserUnsupported,\n Gui,\n initializeOptions\n} from 'react-jplayer';\nimport React, { Component } from 'react';\nimport { pause, play, setMedia, stop } from '../../actions/audioPlayerActions';\n\nimport FontAwesome from 'react-fontawesome';\nimport { StyledButton } from '../../constants/styledComponents';\nimport UserAPI from '../../api/userAPI';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants';\nimport { getSpeechAudio } from '../../actions/bookActions';\nimport $ from 'jquery';\n\n// const intro = require('../../../public/audio/8.mp3'); // test audio\n\nconst defaultOptions = {\n id: 'AudioPlayer',\n keyEnabled: true,\n verticalVolume: true,\n media: {\n title: 'Bubble',\n artist: 'Miaow',\n sources: {},\n free: false\n }\n};\n\ninitializeOptions(defaultOptions);\n\nclass AudioPlayer extends Component {\n constructor(props) {\n super(props);\n this.state = {\n isPlayingRightPage: false,\n voice: 'default',\n showPlayer: false\n };\n this.updateAudioHighlights = this.updateAudioHighlights.bind(this);\n this.unHightlightAudioText = this.unHightlightAudioText.bind(this);\n this.startAudio = this.startAudio.bind(this);\n this.stopAudio = this.stopAudio.bind(this);\n this.shouldLoadAudio = this.shouldLoadAudio.bind(this);\n this.getPageKey = this.getPageKey.bind(this);\n\n this.highlightedSpeechMarks = [];\n this.speechMarkIndex = 0;\n this.timeouts = [];\n this.pendingResync = false;\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n if (window.cordova) {\n // audio on the device uses the file system, so lets wait for it to be ready\n document.addEventListener(\n 'deviceready',\n () => {\n this.shouldLoadAudio(this.getPageKey());\n },\n false\n );\n } else {\n this.shouldLoadAudio(this.getPageKey());\n }\n\n // TODO listen for an event that the audio files have been downloaded\n }\n componentDidUpdate(prevProps) {\n // if (prevProps.audioPaused === true && this.props.audioPaused === false){\n // if (this.shouldLoadAudio(this.getPageKey())){\n // this.startAudio();\n // } else {\n // alert('no audio for these pages');\n // }\n // }\n if (\n prevProps.audioPaused === false &&\n this.props.audioPaused === true\n ) {\n if (this.props.audioTime === this.props.duration) {\n console.log('reached end of audio file');\n this.handleEndOfAudio();\n } else {\n // paused in the middle of a page\n // reset the last 3 highlighted words so that we are ready to go when start playing again\n this.highlightedSpeechMarks.splice(-3, 3);\n this.recentlyPaused = true;\n // loop over all timeouts and cancel them\n this.timeouts.forEach((timeout) => {\n clearTimeout(timeout);\n });\n // remove all highlights\n $(`[data-time-start]`).removeClass('audio-highlight-text');\n }\n }\n\n // if the payer is playing and there is a pendingResync then resync and start the audio\n if (prevProps.audioTime !== this.props.audioTime) {\n // let startTime = parseInt(this.props.audioTime*1000, 10) || 50;\n // console.log('time from player', startTime);\n if (this.pendingResync) {\n console.log('resyncing audio highlights');\n this.pendingResync = false;\n this.startAudio();\n }\n }\n\n // if the page changes, stop the audio\n if (prevProps.currentPage !== this.props.currentPage) {\n this.stopAudio();\n this.setState({ isPlayingRightPage: false }, () => {\n this.shouldLoadAudio(this.getPageKey());\n });\n }\n\n if (\n prevProps.leftPage &&\n this.props.leftPage &&\n prevProps.leftPage.pageReady !== this.props.leftPage.pageReady\n ) {\n this.shouldLoadAudio(this.getPageKey());\n }\n if (\n prevProps.rightPage &&\n this.props.rightPage &&\n prevProps.rightPage.pageReady !== this.props.rightPage.pageReady\n ) {\n this.shouldLoadAudio(this.getPageKey());\n }\n // if (prevProps.audioUrl !== this.props.audioUrl){\n // this.shouldLoadAudio(this.getPageKey());\n // }\n }\n\n getAudioSource(pageNumber) {\n // if (this.props.book.IsEPub){\n // return Promise.resolve(this.props.audioUrl);\n // }\n return this.props\n .getSpeechAudio(\n this.props.book,\n pageNumber,\n this.state.voice,\n this.props.AzureToken\n )\n .then((audioURL) => {\n return audioURL;\n })\n .catch((error) => {\n console.log(\n 'unable to get audio source, either there is no audio for this page, or something went wrong.',\n error\n );\n return '';\n });\n }\n\n getPageKey() {\n let pageKey = '';\n const leftPageNumber = this.props.currentPage;\n const rightPageNumber = this.props.currentPage + 1;\n // set the pageKey\n if (this.state.isPlayingRightPage) {\n pageKey = `page${rightPageNumber}`;\n } else {\n pageKey = `page${leftPageNumber}`;\n }\n return pageKey;\n }\n\n /*\n * check if this page supports audio, if not then check the right page. If both pages do not have audio, then show a message\n */\n startAudio() {\n // if (this.props.book.IsEPub){\n // return;\n // }\n let startTime =\n parseInt(this.props.audioTime * 1000, 10) +\n constants.audioHighlightLeadTime ||\n constants.audioHighlightLeadTime;\n const pageKey = this.getPageKey();\n\n let speechMarks;\n if (this.state.isPlayingRightPage) {\n speechMarks = this.props.rightPage.speechMarks;\n } else {\n speechMarks = this.props.leftPage.speechMarks;\n }\n // get the time closest to the startTime in the speechMarksData\n let mark = speechMarks.reduce((prev, curr) => {\n if (!prev) {\n prev = { time: 0 };\n }\n return Math.abs(curr.time - startTime) <\n Math.abs(prev.time - startTime)\n ? curr\n : prev;\n });\n this.updateAudioHighlights(mark, pageKey);\n }\n\n /*\n * Stop the audio, reset the highlightedSpeechMarks, stop the audio playback, set the index to 0, reset\n * back to the left page audio if there is any, cancel all timeouts, remove all highlights\n */\n stopAudio() {\n this.highlightedSpeechMarks = [];\n this.props.stop(defaultOptions.id);\n this.speechMarkIndex = 0;\n this.setState({ isPlayingRightPage: false }, () => {\n this.shouldLoadAudio(this.getPageKey());\n });\n // loop over all timeouts and cancel them\n this.timeouts.forEach((timeout) => {\n clearTimeout(timeout);\n });\n // remove all highlights\n $(`[data-time-start]`).removeClass('audio-highlight-text');\n }\n\n /*\n * accepts the speechMark that is closest to the audioTime\n * highlight the word then call the unhighlight function\n */\n updateAudioHighlights(speechMark, pageKey) {\n if (!speechMark || !speechMark.time) {\n console.log('missing speechMark');\n return false;\n }\n let speechMarks;\n if (this.state.isPlayingRightPage) {\n speechMarks = this.props.rightPage.speechMarks;\n } else {\n speechMarks = this.props.leftPage.speechMarks;\n }\n\n if (this.props.audioPaused) {\n console.log('not playing audio');\n return;\n }\n\n // we really only need the time for the clossest word when the play button is pushed. then it should take it from there expecting the exact time for the next word.\n let duration = 300; // how long this word will be highlighted\n let nextMark = {};\n\n if (speechMarks.length > this.speechMarkIndex + 1) {\n nextMark = speechMarks[this.speechMarkIndex + 1];\n duration = nextMark.time - speechMark.time;\n this.speechMarkIndex++;\n }\n\n // has this word been highlighted already?\n if (this.highlightedSpeechMarks.indexOf(speechMark.time) === -1) {\n //highlight it\n $(`#${pageKey} [data-time-start=\"${speechMark.time}\"]`).addClass(\n 'audio-highlight-text'\n );\n this.highlightedSpeechMarks.push(speechMark.time);\n // console.log('highlighted', speechMark.value, speechMark.time);\n\n // has the audio gotten too far out of sync?\n if (\n parseInt(this.props.audioTime * 1000, 10) - speechMark.time >\n constants.audioResyncTime ||\n parseInt(this.props.audioTime * 1000, 10) - speechMark.time >\n constants.audioResyncTime\n ) {\n console.log('audio out of sync');\n this.resyncSpeechMarks();\n return; // return so that we do not set an unhighlight timeout and potentially have two processes highlighting\n }\n\n // set a timeout to unhighlight this word and highlight the next word.\n this.unHightlightAudioText(\n speechMark.time,\n nextMark,\n duration,\n pageKey\n );\n } else {\n // no word was highlighted, so wait for the next timecode from the audio payer and continue highlighting words\n console.log('nothing highlighted, setting pending resync');\n this.timeouts.push(\n setTimeout(() => {\n this.pendingResync = true;\n }, 200)\n );\n }\n }\n\n /*\n * remove the highlight from the text after it has been highlighted for the duration that word is spoken.\n * Then call the original function to highlight the next word.\n */\n unHightlightAudioText(markTime, nextMark, markDuration, pageKey) {\n this.timeouts.push(\n setTimeout(() => {\n // console.log('timeout', markTime, nextMark.time, markDuration);\n // $(`#${pageKey} [data-time-start=\"${markTime}\"]`).removeClass('audio-highlight-text');\n if (nextMark.time !== 0 && !this.props.audioPaused) {\n this.updateAudioHighlights(nextMark, pageKey);\n }\n }, markDuration)\n ); // minus 10 miliseconds to account for the time the function takes to run\n\n // sometimes the duration is too short for the user to see the highlight\n let highlightDuration = 0;\n if (markDuration < 100) {\n highlightDuration = 300;\n } else {\n highlightDuration = markDuration;\n }\n this.timeouts.push(\n setTimeout(() => {\n // console.log('timeout', markTime, nextMark.time, markDuration);\n $(`#${pageKey} [data-time-start=\"${markTime}\"]`).removeClass(\n 'audio-highlight-text'\n );\n }, highlightDuration)\n );\n }\n\n /*\n * if audio is out of sync, then resync it.\n */\n resyncSpeechMarks() {\n // loop over all timeouts and cancel them\n this.timeouts.forEach((timeout) => {\n clearTimeout(timeout);\n });\n // remove all highlights\n $(`[data-time-start]`).removeClass('audio-highlight-text');\n this.pendingResync = true;\n }\n\n /*\n * Should we play the audio for the right page or stop and reset back to the left page\n */\n handleEndOfAudio() {\n this.stopAudio();\n // if (this.props.book.IsEPub){\n // return;\n // }\n if (\n !this.state.isPlayingRightPage &&\n this.props.pagesVisible === 2 &&\n !this.props.blmMode &&\n this.props.rightPage.speechMarks &&\n this.props.rightPage.speechMarks.length > 0\n ) {\n setTimeout(() => {\n this.setState({ isPlayingRightPage: true }, () => {\n this.getAudioSource(this.props.currentPage + 1).then(\n (source) => {\n this.props.setMedia('AudioPlayer', {\n sources: { mp3: source }\n });\n this.props.play('AudioPlayer');\n }\n );\n });\n }, constants.audioDelayBetweenPages);\n\n // if this was the end of the right page, then reset back to the left page\n } else if (this.state.isPlayingRightPage) {\n console.log('end of right page, reset');\n this.setState({ isPlayingRightPage: false }, () => {\n this.getAudioSource(this.props.currentPage).then((source) => {\n this.props.setMedia('AudioPlayer', {\n sources: { mp3: source }\n });\n });\n });\n }\n }\n\n /*\n * Should we load audio for the left and right page?\n * hide the speech buttons if there is no audio for the left or the right page\n *\n */\n shouldLoadAudio(pageKey) {\n let shouldLoad = false;\n\n \n // if they are a student, check if audio is enabled, otherwise enable audio if it is available\n if (\n (UserAPI.isStudent(this.props.user.RoleID) &&\n this.props.book.IsAudioAvailable &&\n this.props.book.IsAudioEnabled) ||\n !UserAPI.isStudent(this.props.user.RoleID)\n ) {\n // if (this.props.book.IsEPub){\n // if (this.props.audioUrl && this.props.audioUrl.length){\n // shouldLoad = true;\n // this.getAudioSource(this.props.currentPage).then((source) => {\n // this.props.setMedia('AudioPlayer', {\n // sources: { m4a: source }\n // });\n // });\n // }\n // } else {\n // check for marks on the pages\n if (\n this.props.leftPage &&\n this.props.leftPage.speechMarks &&\n this.props.leftPage.speechMarks.length > 0\n ) {\n // we have speechMarks for the left page\n shouldLoad = true;\n this.getAudioSource(this.props.currentPage).then((source) => {\n this.props.setMedia('AudioPlayer', {\n sources: { mp3: source }\n });\n });\n } else if (\n !this.state.isPlayingRightPage &&\n this.props.pagesVisible === 2 &&\n !this.props.blmMode &&\n this.props.rightPage &&\n this.props.rightPage.speechMarks &&\n this.props.rightPage.speechMarks.length > 0\n ) {\n // we have speechMarks for the right page\n shouldLoad = true;\n this.setState({ isPlayingRightPage: true }, () => {\n this.getAudioSource(this.props.currentPage + 1).then(\n (source) => {\n this.props.setMedia('AudioPlayer', {\n sources: { mp3: source }\n });\n // play the audio on the right page if audio is playing\n if (!this.props.audioPaused) {\n this.startAudio();\n }\n }\n );\n });\n } else {\n // no speechMarks\n shouldLoad = false;\n }\n // }\n } else {\n // audio is not enabled\n shouldLoad = false;\n }\n\n if (shouldLoad === false) {\n this.setState({ showPlayer: false });\n } else {\n this.setState({ showPlayer: true });\n }\n return shouldLoad;\n }\n\n render() {\n if (!this.state.showPlayer) {\n return null;\n }\n\n let fontAwesomeTogglePlay = 'play';\n if (!this.props.audioPaused) {\n fontAwesomeTogglePlay = 'pause';\n }\n return (\n \n \n );\n }\n}\n\nAudioPlayer.propTypes = {};\nconst mapStateToProps = (state, ownProps) => {\n return {\n user: state.user,\n audioPaused: state.jPlayers.AudioPlayer.paused,\n audioTime: state.jPlayers.AudioPlayer.currentTime,\n duration: state.jPlayers.AudioPlayer.duration,\n currentPage: state.book.currentPage,\n pagesVisible: state.bookView.pagesVisible,\n speechMarks: state.book.speechMarks,\n book: state.book,\n AzureToken: state.user.AzureToken,\n leftPage: state.book.cachedPages[`page${state.book.currentPage}`],\n rightPage: state.book.cachedPages[`page${state.book.currentPage + 1}`],\n // audioUrl: state.bookView.audioUrl\n };\n};\n\nexport default connect(mapStateToProps, {\n pause,\n stop,\n setMedia,\n play,\n getSpeechAudio\n})(AudioPlayer);\n","export enum viewerDrawerTypeEnum {\n Notes,\n Markups,\n Bookmarks\n}","import { actions } from 'react-jplayer';\n\nexport const pause = (id) => {\n return function (dispatch, getState) {\n dispatch(actions.pause(id));\n };\n};\n\nexport const stop = (id, media) => {\n return function (dispatch, getState) {\n dispatch(actions.pause(id, 0));\n };\n};\n\nexport const setMedia = (id, media) => {\n return function (dispatch, getState) {\n dispatch(actions.setMedia(id, media));\n };\n};\n\nexport const play = () => {\n return function (dispatch, getState) {\n if (getState().jPlayers.AudioPlayer.paused) {\n dispatch(actions.play('AudioPlayer'));\n } else {\n dispatch(actions.pause('AudioPlayer'));\n }\n };\n};\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTk1NzA3OEYxQkQ1MTFFNzlBMUJCMEE1NUQ2NTNDMTYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTk1NzA3OEUxQkQ1MTFFNzlBMUJCMEE1NUQ2NTNDMTYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDJDRjg0MEExOEFGMTFFN0FGODM5QTNEOTRBOEQxQUYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDJDRjg0MEIxOEFGMTFFN0FGODM5QTNEOTRBOEQxQUYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5DAd5MAAATSElEQVR42txc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\"","export default \"data:image/png;base64,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\"","import * as React from 'react';\n\nimport { Col, ListGroup, ListGroupItem, Row } from 'react-bootstrap';\nimport { StyledButton, StyledDiv } from '../../constants/styledComponents';\nimport { forEach, groupBy, remove } from 'lodash';\n\nimport AudioPlayer from './audioPlayer';\nimport FontAwesome from 'react-fontawesome';\nimport PropTypes from 'prop-types';\nimport constants from '../../constants/constants';\nimport icon_hl_teal from '../../images/icon_hl_teal.png';\nimport icon_pen from '../../images/icon_pen.png';\nimport { viewerModes } from '../../constants/viewerModes';\nimport { viewerDrawerTypeEnum } from '../../models-enums';\nclass Drawer extends React.Component {\n static defaultProps = {\n showNotesButton: true,\n showHighlightsButton: true\n };\n constructor(props) {\n super(props);\n\n this.shorten = this.shorten.bind(this);\n this.getNotesHtml = this.getNotesHtml.bind(this);\n this.getHLHtml = this.getHLHtml.bind(this);\n this.parseSerializedHighlight = this.parseSerializedHighlight.bind(\n this\n );\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidUpdate(prevProps) {\n if (\n this.props.book.notes !== prevProps.book.notes ||\n this.props.book.highlights !== prevProps.book.highlights\n ) {\n this.forceUpdate();\n }\n }\n\n shorten(text) {\n if (!text) {\n return '';\n }\n let ret = text;\n let maxLength = 95;\n if (ret.length > maxLength) {\n ret = ret.substr(0, maxLength - 3) + '...';\n }\n return ret;\n }\n\n getNotesHtml(bookItems) {\n let borderForNote = 'drawer-item';\n // group the book items by their Page attribute\n const bis = groupBy(bookItems, 'Page');\n // build jsx array to return for print out\n let buffer = [];\n forEach(bis, (biArr, key) => {\n buffer.push(

Page {key}

);\n buffer = buffer.concat(\n biArr.map((bi) => {\n if (bi.Type === 4) {\n borderForNote = 'drawer-item teacher-student-note';\n // popoverNote = 'teacher-student-popover-bookItems';\n } else if (bi.Type === 5) {\n borderForNote = 'drawer-item class-note';\n // popoverNote = 'teacher-class-popover-bis';\n } else if (bi.Type === 6) {\n borderForNote = 'drawer-item group-note';\n // popoverNote = 'teacher-group-popover-bis';\n } else if (bi.Type === 3) {\n borderForNote = 'drawer-item student-note';\n // popoverNote = 'student-popover-note';\n }\n return (\n {\n this.props.goTo(bi);\n }}\n >\n

{this.shorten(bi.Content.value)}

\n \n );\n })\n );\n });\n return buffer;\n }\n\n getHLHtml(bookItem) {\n var bookItems = this.parseSerializedHighlight(bookItem.Content);\n // group the hl items by their page attribute\n const bis = groupBy(bookItems, 'page');\n // build jsx array to return for print out\n let buffer = [];\n forEach(bis, (biArr, key) => {\n buffer.push(

Page {key}

);\n buffer = buffer.concat(\n biArr.map((bi) => {\n return (\n {\n this.props.goToPage(bi.Page);\n }}\n >\n

{this.shorten(bi.hlText)}

\n \n );\n })\n );\n });\n return buffer;\n }\n\n parseSerializedHighlight(serializedPages) {\n /*\n type:TextRange|165$192$3$hl-strikethrough$page6$t cover by First Avenue Edi\n */\n let hls = [];\n forEach(serializedPages, (serialized) => {\n var serializedHighlights = serialized.split('|');\n // remove the first node: type:TextRange\n serializedHighlights.shift();\n // console.log(serializedHighlights);\n // loop over the rest and extraxt the page, style and text\n hls = hls.concat(\n serializedHighlights.map((sh) => {\n const parts = sh.split('$');\n if (parts.length < 6) {\n return null;\n }\n // console.log(parts);\n var id = (Math.random() * 10000 + '').replace('.', '');\n var page = parseInt(parts[4].substr(4), 10);\n var hlClass = parts[3];\n var hlText = parts[5];\n return { id, page, hlClass, hlText };\n })\n );\n });\n return remove(hls, null);\n }\n\n render() {\n if (this.props.hideDrawer) {\n return null;\n }\n let drawerClassName,\n drawerButtonsContainerClassName,\n drawerButtonsClassName,\n drawerButtonCSS;\n if (this.props.show) {\n drawerClassName = 'drawer shown';\n drawerButtonsClassName = 'item icon-btn shown';\n drawerButtonsContainerClassName = 'drawer-buttons-container shown';\n } else {\n drawerButtonsClassName = 'item icon-btn btn-arrow-right';\n drawerClassName = 'drawer';\n drawerButtonsContainerClassName = 'drawer-buttons-container';\n drawerButtonCSS = {\n '&:hover:after': {\n 'border-left': `15px solid ${this.theme.primaryBackground}`\n },\n '&:active:after': {\n 'border-left': `15px solid ${this.theme.primaryDark}`\n },\n '&:after': {\n 'border-left': `15px solid ${this.theme.primaryBackground}`\n }\n };\n }\n\n const title = viewerDrawerTypeEnum[this.props.type];\n\n return (\n
\n
\n \n
\n \n
\n
\n
\n {\n this.props.openDrawer(0);\n }}\n role=\"button\"\n >\n \"\"\n \n
\n
\n {\n this.props.openDrawer(1);\n }}\n role=\"button\"\n >\n \"\"\n \n
\n
\n
\n \n \n

{title}

\n \n \n \n \n \n \n
\n
\n \n {this.props.type === 0 &&\n !!this.props.book &&\n !!this.props.book.notes && (\n \n {this.getNotesHtml(\n this.props.book.notes\n )}\n \n )}\n {this.props.type === 1 &&\n !!this.props.book &&\n !!this.props.book.highlights && (\n \n {this.getHLHtml(\n this.props.book.highlights\n )}\n \n )}\n {(this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM) && (\n
\n {this.props.type === 0 &&\n !!this.props.book &&\n !!this.props.book.studentNotes &&\n !!this.props.book.studentNotes\n .length && (\n \n {this.getNotesHtml(\n this.props.book.studentNotes\n )}\n \n )}\n {this.props.type === 1 &&\n !!this.props.book &&\n !!this.props.book.studentHighlights && (\n \n {this.getHLHtml(\n this.props.book\n .studentHighlights\n )}\n \n )}\n
\n )}\n
\n
\n \n \n );\n }\n}\n\nDrawer.propTypes = {\n show: PropTypes.bool.isRequired,\n user: PropTypes.object.isRequired,\n book: PropTypes.object.isRequired,\n goTo: PropTypes.func.isRequired,\n goToPage: PropTypes.func.isRequired,\n close: PropTypes.func.isRequired,\n type: PropTypes.number.isRequired,\n hideDrawer: PropTypes.bool.isRequired,\n showNotesButton: PropTypes.bool,\n showHighlightsButton: PropTypes.bool\n};\n\nexport default Drawer;\n","import * as React from 'react';\n\nimport { Button, Col, FormControl } from 'react-bootstrap';\nimport { StyledButton, StyledRow } from '../../constants/styledComponents';\n\nimport UserAPI from '../../api/userAPI';\nimport book from '../../images/book.png';\nimport constants from '../../constants/constants';\nimport graphic_organizers from '../../images/graphic_organizers.png';\nimport { toastr } from 'react-redux-toastr';\n\nclass Header extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n searchTerm: '',\n filteredBooks: this.props.books\n };\n this.searchBooks = this.searchBooks.bind(this);\n this.toggleClass = 'fa fa-angle-double-up';\n this.theme = constants.themeProvider.activeTheme;\n }\n\n searchBooks(event) {\n let filteredBooks = this.props.books.filter((book) =>\n book.Title.toLowerCase().includes(event.target.value.toLowerCase())\n );\n if (!filteredBooks) {\n filteredBooks = [];\n }\n this.setState({\n search: event.target.value,\n filteredBooks\n });\n }\n\n render() {\n return (\n
\n \n \n {UserAPI.isStudent(this.props.user.RoleID) && (\n
\n
\n \n \n Book \n \n
    \n \n \n \n {this.props.books.length > 0 &&\n this.state.filteredBooks.map(\n (book) => {\n return (\n
    \n
  • \n {\n this.props.changeBook(\n book\n );\n }}\n >\n {book.Title}\n \n
  • \n
    \n );\n }\n )}\n
\n
\n {\n // \n // \n }\n \n \n \n Activities{' '}\n \n \n
    \n {this.props.blms.length > 0 &&\n this.props.blms.map((blm) => {\n return (\n
  • \n {\n this.props.changeBlm(\n blm.projectAssignmentID,\n blm.ID\n );\n }}\n >\n {blm.FriendlyName ||\n blm.Title}\n \n
  • \n );\n })}\n
\n
\n {/* {this.props.isDownloaded === false && (\n \n this.props.downloadBook(\n this.props.book\n )\n }\n >\n Download Book\n \n )}\n {this.props.isDownloaded === true && (\n \n Book Downloaded (Remove?)\n \n )} */}\n
\n )}\n \n {/*
\n \n \n
*/}\n \n
\n \n \n \n
\n
\n );\n }\n}\n\nexport default Header;\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAYCAYAAACfpi8JAAAFiklEQVRIic2W3W8cVxnGf+ec2ZnZD3vXXn8noakTuzFpoKU0pC5O0y+aqhWISlzQi0ogVBWBKlXlv4ALuOIOuEB8SFxwRaNSYQNN27Rpmjh1jeXaaUK88W6Stb327szszpzDxWzsbHfTune80l7sec/znud9znNejQC4ulLISSlfTFjWV9xkUgOjwBCwB3CJQwMF4AowC7wNnOrKpEsAm1vVAeAk8FDlT797Vl14b6+Skv/MXgTAf+55/PFDJhJoI4U32NsfCCE+MsL8YPK+B5ass888apt6/XpNa8t1XdxkkjuEBPY2f5PASxhjSufOFjHGYMwQQggAohBLqRawQGAjBQZFRMZGZnzPn3Id9+MzJ6dSFpDCaOt2kKluYm5ch60KJggQSoFtg5tCDAwh0plmdSGS4xNDbZQj3bZkrxbQqTRRVzdhNrdzFgag22pDAHruAtSq0JVFuC5IifF9KK0SnX0LNjcQuV7UiZOI3vw2buOvf8FfXIByCadVEITRJNbKuFc+oXJ0su3MjkTU0W92Wo5ztzop3wSrFe4e+SrZbz9H5Y+/gfnZllwwvJdofOKOdTsSiaZPoa9cguaVk0xBPYAwBKUQA0PIg4eQdx1owclUmsrrr+F/NIcjWmt2ffAuankRDJSffHp3RNSJp1BCdEpB2MAUr6EX5tAJG7lv/3Zqa+YN3Il7YWwcPp6n6KRpPPQIibf/yeb9R7+4InrlCua/lzCbFfB9UPE2kUoh+gYRg8Oox9q76vn+C0SVCqXpUzScLoJUFyljMIfvx1pexNRqhN3dePsPtGE7EsGrIXr7kaPjYDfHiDGYzQ3MjRL63TcxxWuoJ59FfunubVjplz9H2Dbd+8eY3yhj9Y9gms9YRBHS97AqGwhjdkdEjk1Ao4GprIPvba+LXE98sDjWlK71mQ68/CpICcCD62u88/e/4TrpuA+lCHO91IdGOvbe2az/eA197SqiOwepdGxareO5srEOWiP27EMdOx7vacbm9Bv4c7PoIEBlMhzu7ePy0gIJlUCEDWStivR9yk/s1qyPPY3qlLgVxqCvXoYoai3W10/+xZ8g3Z3pnNOamdMzuNL+rIp3MOvs++jFeUytCsaAUs1rEIjuLGJwGDk6hujJt+Cc0YN4589Rv3yJsFTEhCFCKe41hpvXSwjLJsxm2XzgG7sjIkb2oUbHEZmuNiXMehlTLBCdeRN55GvI217A2p9/jzN2D+nJKRKDwwh7R4U+rfnX6RnSaxVMh9HQmUg6gy6tYpYXMbWtHVOm0oh8P/KuA8hDR9pw+R/9GBOGhKsFvIsXiNbKGB1fn0ylOZrt5X0/QDUN/blEogtnwatBTx6R749HeRRBdQu9OE/01jTUqlhPfQcxsm8bd+PXv0J7HonhEayhEaz+AYTjgDFElQrhaoEvF1b4cGxsd0TUseM7fxr1HVM6LvKWrFq3mTX/w5fig5thggAThduK3IoprVlaXt6FIjOvoy8vxUa1HYTjxAV9PyZg2/H13Pd1RCKxjaudP4d/8TzhWhkhJcJ2kMkkplFHez4YDULQ/9NXGOjro1gqoQ0IhOmsyNTjqBPf6pSKo15HLy+A50H6NkOHDbLf/R5Wvu+OUBNFCClB+GSzWTzPI1Cq3nnEq8+cIrEiHcyafvh4h82tIT5VO5dKUiT+/Pu/iG1FBCACn+o7HxJeLxHevIGuVjFB7AthOwjXxerpJTGyB/vuAyRG9rQUaxRWqF9aolFYIVwrY3wfUw9ASoTjItNprHxf/JpGD3L7NLGiMAy3/vBbgvk51jc2dt2BshI4A4NkJh/BRCHVM6cJSkWisLH7GtkszsRhojAMBcC/H30w93mgthDi4UTC+YVS6h6AKIoWGo3gZxhz+ouWmpp+b/1/OLA6oA26xVwAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAZCAYAAADaILXQAAABy0lEQVRIidWWTWsTQRiAn0mnSTZpmmwSIWwLgvZiSQXptVKhV/HmwaMi+AsCHvXs0VPBo+APUNpL9yJ4lApCY+2HiqTEVojS6CZrZuKlrmvIJFvTHvrcZt93nvdlvlhBiJlltQBIImBbOp611NrazaQ25Yge+TcgG0U+netgp/TGYUvMmQrEoohMFFJqdjKp3yw8Xu/rGUkOkE/puYxd+HLXbYremHFZFqc12XjXKPWFoiVUMN6rN+pOyXaeLE0Ek4ybl5ZdMgPkHw8afPW8cJelt+9qL4GrQ+UHnsBTpijEU0U+b29Q+/T+77fcVCGcY5Sfn+xStMydA3B5lhVP0Nrf7BuWAFW3Mg6kb+164o9udcfs7BLjp04AYDllgL4FZNWtjAF1IP/swsPBnYbYbk/xYO8O31U6KKD95j85MWAcyEe2HjGTqHG/9BR5dGIsp0yieHGrV/7flK0P3C6sBGM5ca4Rjkd6RwZxI/eK/Y7NbtvBloel527lGlC7tPRoS1TdShLwhjiOiwaSI19/AzFg7LTkQYVTQ/q+Jzsd/+TFMi6lUr9kq90cnn1MLJGRZ3fNz7bc+GswIloAvH5x7wqQPkHxj/nry+u/Ad2AiYwVDnUIAAAAAElFTkSuQmCC\"","import { connect } from 'react-redux';\nimport { deleteDownloadedBook, downloadBook } from '../../actions/bookActions';\nimport { updatePagesVisible } from '../../actions/bookViewActions';\nimport Header from './Header';\n\nconst mapStateToProps = (state, ownProps) => {\n const books = navigator.onLine ? state.books : state.downloadedBooks;\n const isDownloaded = state.downloadedBooks.find(\n (book) => book.ID === state.book.ID\n )\n ? true\n : false;\n return {\n user: state.user,\n books,\n blms: state.blms,\n book: state.book,\n isDownloaded\n };\n};\n\nexport const HeaderContainer = connect(mapStateToProps, {\n downloadBook,\n updatePagesVisible,\n deleteDownloadedBook\n})(Header);\n","import * as types from '../actionTypes';\n\nexport function turnOnEraser() {\n let projectToolbar = {\n erasing: true,\n pointer: false,\n startText: false,\n drawingMode: false,\n showRichTextButtons: false,\n drawingColor: '#ff8f02'\n };\n return { type: types.TOOLBAR_ERASER_ON, projectToolbar };\n}\n\nexport function turnOnTextMode() {\n let projectToolbar = {\n erasing: false,\n pointer: false,\n startText: true,\n drawingMode: false,\n showRichTextButtons: false,\n drawingColor: '#ff8f02'\n };\n return { type: types.TOOLBAR_ADD_TEXT_ON, projectToolbar };\n}\n\nexport function showRichTextButtons() {\n let projectToolbar = {\n erasing: false,\n pointer: false,\n startText: false,\n drawingMode: false,\n showRichTextButtons: true,\n drawingColor: '#ff8f02'\n };\n return { type: types.SHOW_RICH_TEXT_BUTTONS, projectToolbar };\n}\n\nexport function turnOnPointer() {\n let projectToolbar = {\n erasing: false,\n pointer: true,\n startText: false,\n drawingMode: false,\n showRichTextButtons: false,\n drawingColor: '#ff8f02'\n };\n return { type: types.TOOLBAR_POINTER_ON, projectToolbar };\n}\n\nexport function turnOnDrawingMode(color) {\n let projectToolbar = {\n erasing: false,\n pointer: false,\n startText: false,\n drawingMode: true,\n showRichTextButtons: false,\n drawingColor: `${color}`\n };\n return { type: types.TOOLBAR_DRAWING_MODE_ON, projectToolbar };\n}\n","import { Button, Col, FormControl, Row } from 'react-bootstrap';\nimport { ToastContainer, ToastMessage } from 'react-toastr';\nimport {\n emptyBLMData,\n saveBLMItem,\n saveBLMTemplate,\n teacherMakesBLMComment,\n updateStatus\n} from '../../actions/blmActions';\nimport {\n showRichTextButtons,\n turnOnDrawingMode,\n turnOnEraser,\n turnOnPointer,\n turnOnTextMode\n} from '../../actions/projectToolbar/projectToolbarActions';\n\nimport CommonModal from '../common/CommonModal';\nimport ProjectToolbar from './ProjectToolbar';\nimport React from 'react';\nimport { StyledButton } from '../../constants/styledComponents';\nimport UserAPI from '../../api/userAPI';\nimport { bindActionCreators } from 'redux';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants';\nimport { fabric } from 'fabric';\nimport marker_hl_black from '../../images/marker-black.png';\nimport marker_hl_blue from '../../images/marker-blue.png';\nimport marker_hl_orange from '../../images/marker-orange.png';\nimport { updatePendingItem } from '../../actions/bookViewActions';\nimport { viewerModes } from '../../constants/viewerModes';\n\nconst ToastMessageFactory = React.createFactory(ToastMessage.animation);\n\n// Global Fabric canvas\nlet fabricCanvas;\nclass FabricUI extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n commentsSlideUp: false,\n toggleClass: 'fa fa-angle-double-up',\n teachersCommentForStudent: '',\n commentFromTeacher: '',\n showMarkersButtons:\n this.props.location.query.viewerMode !==\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE,\n showCommentButtons:\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM,\n showToolbar:\n this.props.location.query.viewerMode !==\n viewerModes.MODE_TEACHER_STUDENT_BLM,\n showStudentSaveButtons:\n this.props.location.query.viewerMode !==\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE,\n showAdminSaveButtons:\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE,\n currentFontSize: '40', // part of projectToolbar\n freezeBlm:\n this.props.blm.isComplete ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ? 'none'\n : 'auto',\n blmButtonsClasses: this.props.blm.isComplete\n ? 'freeze-buttons'\n : 'blm-buttons',\n showBlmSubmitModal: false,\n showResetBLMModal: false\n };\n this.stopDrawingMode = this.stopDrawingMode.bind(this);\n this.startDrawingMode = this.startDrawingMode.bind(this);\n this.toggleComments = this.toggleComments.bind(this);\n this.handleChange = this.handleChange.bind(this);\n\n // rich text functions used in render\n this.toggleBold = this.toggleBold.bind(this);\n this.toggleLinethrough = this.toggleLinethrough.bind(this);\n this.toggleUnderline = this.toggleUnderline.bind(this);\n this.toggleItalic = this.toggleItalic.bind(this);\n this.changeFontSize = this.changeFontSize.bind(this);\n this.startPointer = this.startPointer.bind(this);\n this.addText = this.addText.bind(this);\n this.showBlmSubmitModal = this.showBlmSubmitModal.bind(this);\n this.doPrint = this.doPrint.bind(this);\n this.saveBLMTemplate = this.saveBLMTemplate.bind(this);\n this.startEraser = this.startEraser.bind(this);\n this.startTextMode = this.startTextMode.bind(this);\n this.displayResetModal = this.displayResetModal.bind(this);\n this.isNotCompleteForStudent = this.isNotCompleteForStudent.bind(this);\n this.exitBlm = this.exitBlm.bind(this);\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n console.log('FabricUI component mounted');\n fabricCanvas = new fabric.Canvas();\n var el = document.getElementById('blm-canvas');\n this.props.turnOnPointer();\n\n /* initialize the width and height\n */\n fabricCanvas.initialize(el, {\n width: `${this.props.blm.bounds[0][0]}`,\n height: `${this.props.blm.bounds[0][1]}`\n });\n\n if (this.props.blm) {\n fabricCanvas.loadFromJSON(this.props.blm.blmData, function (obj) {\n fabricCanvas.renderAll();\n });\n // console.log('HAS TEMPLATE', this.props.blm.fabricItems.HasTemplate)\n }\n\n // TODO refactor/blms\n // These are fabric.js listeners\n // save data is a listener we made\n fabricCanvas.on('saveData', () => {\n console.log('saving data');\n this.saveBlmDraft();\n });\n\n // fabricCanvas.on('submitData', () => {\n // console.log(\"inside of submit data\");\n // this.props.updateBLMData(fabricCanvas.toObject());\n // this.saveBlmDraft();\n // })\n\n // This is called whenever a drawing is made\n fabricCanvas.on('path:created', () => {\n // console.log('drawing created');\n this.saveBlmDraft();\n });\n\n // this is called whenever an object is moved (I believe)\n fabricCanvas.on('object:modified', () => {\n // console.log('inside of object modified');\n this.saveBlmDraft();\n });\n\n // this is called wehenever we enter a text box\n fabricCanvas.on('text:editing:entered', (e) => {\n let textbox = e.target;\n let borderColor =\n e.target.templateObject === true\n ? 'rgba(102,153,255,0.45)'\n : 'rgba(255, 251, 165, 3)';\n textbox.set({ borderColor: borderColor }); //({borderColor: '#FF5733'});\n if (\n !!e.target &&\n e.target.type === 'textbox' &&\n !this.props.projectToolbar.showRichTextButtons\n ) {\n this.props.updatePendingItem(true);\n var id = fabricCanvas.getObjects().indexOf(e.target);\n this.props.showRichTextButtons();\n this.setState({ currentFontSize: textbox.fontSize }, () => {\n fabricCanvas.setActiveObject(fabricCanvas.item(id));\n });\n } else if (!e.target || e.target.type !== 'textbox') {\n this.props.turnOnPointer();\n }\n });\n\n // this is called when a user leaves a text box\n fabricCanvas.on('text:editing:exited', (e) => {\n // console.log('EDITING EXITED')\n this.startPointer();\n // this.saveBlmDraft(); // @jfbloom22 why do we save draft here???\n });\n\n // this is called when a user selects a box\n // This is also called when we go to erase a text box\n fabricCanvas.on('object:selected', (e) => {\n // console.log('object selected');\n let object = e.target;\n let fontSize = object.fontSize;\n if (\n UserAPI.isStudent(this.props.user.RoleID) &&\n e.target.templateObject === true\n ) {\n // console.log('what is going on?')\n // does this template have a fontSize set on the first character?\n if (\n object.styles &&\n object.styles['0'] &&\n object.styles['0']['0'] &&\n object.styles['0']['0'].fontSize\n ) {\n fontSize = object.styles[0][0].fontSize;\n }\n object.set({\n lockMovementX: true,\n lockMovementY: true,\n lockScalingX: true,\n lockScalingY: true,\n lockRotation: true,\n fontSize: fontSize\n });\n object.enterEditing(); // students clicking on a template textbox start editing automatically\n }\n // console.log('erasing', this.props.projectToolbar.erasing);\n if (this.props.projectToolbar.erasing) {\n // console.log('erasing an object!');\n this.eraseObjects(e);\n }\n });\n }\n componentDidUpdate(prevProps) {\n if (this.props.blm.isComplete !== prevProps.blm.isComplete) {\n if (this.props.blm.isComplete) {\n this.setState({\n freezeBlm: 'none',\n blmButtonsClasses: 'freeze-buttons'\n });\n } else {\n this.setState({\n freezeBlm: 'auto',\n blmButtonsClasses: 'blm-buttons'\n });\n }\n }\n\n if (\n this.props.blm.projectAssignmentID !==\n prevProps.blm.projectAssignmentID\n ) {\n fabricCanvas.setWidth(this.props.blm.bounds[0][0]);\n fabricCanvas.setHeight(this.props.blm.bounds[0][1]);\n fabricCanvas.clear();\n this.props.turnOnPointer();\n }\n // why are we checking loaded blm data id?\n if (\n this.props.viewerSettings.loadedProjectAssignmentID !==\n prevProps.viewerSettings.loadedProjectAssignmentID\n ) {\n fabricCanvas.loadFromJSON(this.props.blm.blmData, (obj) => {\n fabricCanvas.renderAll();\n // we were using this.props.location.query.blmID\n // TODO: why have blmDataID set in state?\n this.setState({\n blmDataID: this.props.location.query.projectAssignmentID\n });\n });\n }\n }\n\n /************** Fabricjs functions **************/\n\n getActiveStyle(styleName, object) {\n object = object || fabricCanvas.getActiveObject();\n if (!object) return '';\n\n return object.getSelectionStyles && object.isEditing\n ? object.getSelectionStyles()[styleName] || ''\n : object[styleName] || '';\n }\n\n setActiveStyle(styleName, value, object) {\n object = object || fabricCanvas.getActiveObject();\n if (!object) return;\n\n if (object.setSelectionStyles && object.isEditing) {\n var style = {};\n style[styleName] = value;\n object.setSelectionStyles(style);\n object.setCoords();\n } else {\n object.set(styleName, value);\n }\n\n object.setCoords();\n fabricCanvas.renderAll();\n }\n\n isBold() {\n return this.getActiveStyle('fontWeight') === 'bold';\n }\n\n toggleBold() {\n this.props.resetActiveTimeout();\n this.setActiveStyle(\n 'fontWeight',\n this.getActiveStyle('fontWeight') === 'bold' ? '' : 'bold'\n );\n }\n\n isItalic() {\n return this.getActiveStyle('fontStyle') === 'italic';\n }\n\n toggleItalic() {\n this.props.resetActiveTimeout();\n this.setActiveStyle(\n 'fontStyle',\n this.getActiveStyle('fontStyle') === 'italic' ? '' : 'italic'\n );\n }\n\n isUnderline() {\n return (\n this.getActiveStyle('textDecoration').indexOf('underline') > -1 ||\n this.getActiveStyle('underline')\n );\n }\n\n toggleUnderline() {\n this.props.resetActiveTimeout();\n var value = this.isUnderline()\n ? this.getActiveStyle('textDecoration').replace('underline', '')\n : this.getActiveStyle('textDecoration') + ' underline';\n\n this.setActiveStyle('textDecoration', value);\n this.setActiveStyle('underline', !this.getActiveStyle('underline'));\n }\n\n isLinethrough() {\n return (\n this.getActiveStyle('textDecoration').indexOf('line-through') >\n -1 || this.getActiveStyle('linethrough')\n );\n }\n\n toggleLinethrough() {\n this.props.resetActiveTimeout();\n var value = this.isLinethrough()\n ? this.getActiveStyle('textDecoration').replace('line-through', '')\n : this.getActiveStyle('textDecoration') + ' line-through';\n\n this.setActiveStyle('textDecoration', value);\n this.setActiveStyle('linethrough', !this.getActiveStyle('linethrough'));\n }\n\n changeFontSize(event) {\n this.props.resetActiveTimeout();\n const newFontSize = event.target.value;\n var id = fabricCanvas\n .getObjects()\n .indexOf(fabricCanvas.getActiveObject());\n this.setState({ currentFontSize: newFontSize }, () => {\n fabricCanvas.setActiveObject(fabricCanvas.item(id));\n this.setFontSize(newFontSize);\n });\n }\n\n getFontSize() {\n return this.getActiveStyle('fontSize');\n }\n\n /*\n * set font size of a single character\n */\n\n setFontSize(value) {\n this.props.resetActiveTimeout();\n this.setActiveStyle('fontSize', parseInt(value, 10));\n }\n\n /*\n * set font size of the entire textbox (not currently being used)\n * this.setDefaultFontSize(fabricCanvas.getActiveObject(), newFontSize);\n */\n\n setDefaultFontSize(textbox, fontSize) {\n this.props.resetActiveTimeout();\n textbox.set({ fontSize });\n }\n\n /*\n * Modes ********************************************************\n */\n\n startPointer() {\n this.props.resetActiveTimeout();\n // stopDrawingMode() What are we doing here? (fabricUI element that is setting drawingMode to false)\n // stopTextMode() --> fabricUI element that is setting textMode to false\n // console.log('inside start pointer');\n this.props.turnOnPointer();\n this.stopDrawingMode();\n this.stopTextMode();\n fabricCanvas.deactivateAll().renderAll();\n }\n\n stopDrawingMode() {\n fabricCanvas.isDrawingMode = false;\n }\n\n startDrawingMode(color = '#09d8f8') {\n this.props.resetActiveTimeout();\n this.props.updatePendingItem(true);\n fabricCanvas.isDrawingMode = true;\n fabricCanvas.freeDrawingBrush.color = color;\n fabricCanvas.freeDrawingBrush.width = 10;\n // fabricCanvas.free\n this.props.turnOnDrawingMode(color);\n fabricCanvas.deactivateAll().renderAll();\n }\n\n startTextMode() {\n this.props.resetActiveTimeout();\n this.props.updatePendingItem(true);\n fabricCanvas.on('mouse:up', this.addText);\n this.stopDrawingMode();\n this.props.turnOnTextMode();\n // this.props.showRichTextButtons()\n fabricCanvas.deactivateAll().renderAll();\n }\n\n displayResetModal() {\n this.props.resetActiveTimeout();\n this.setState({ showResetBLMModal: true });\n }\n\n closeResetBLMModal = () => {\n this.props.resetActiveTimeout();\n this.setState({ showResetBLMModal: false });\n };\n\n resetBLM = () => {\n this.props.resetActiveTimeout();\n // console.log('inside of reset blm');\n if (this.props.blm.originalBLMTemplate) {\n fabricCanvas.loadFromJSON(\n this.props.blm.originalBLMTemplate.Content,\n function (obj) {\n fabricCanvas.renderAll();\n }\n );\n } else {\n fabricCanvas.loadFromJSON([], function (obj) {\n fabricCanvas.renderAll();\n });\n }\n this.saveBlmDraft();\n this.setState({ showResetBLMModal: false });\n };\n\n stopTextMode() {\n // console.log('inside stop text mode');\n // this.props.turnOnPointer();\n fabricCanvas.__eventListeners['mouse:up'] = [];\n }\n\n startEraser() {\n this.props.resetActiveTimeout();\n this.props.updatePendingItem(true);\n this.stopDrawingMode();\n this.stopTextMode();\n fabricCanvas.deactivateAll().renderAll();\n this.props.turnOnEraser();\n // console.log(\"turning on eraser\");\n }\n stopEraser() {\n this.props.turnOnPointer();\n }\n eraseObjects(e) {\n this.props.resetActiveTimeout();\n // console.log('inside of erase objects');\n if (!!e.target._objects && e.target._objects.length > 1) {\n let blmObjects = e.target._objects;\n blmObjects.forEach((blmObj) => {\n if (blmObj.type === 'textbox') {\n if (\n blmObj.templateObject === false ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ) {\n fabricCanvas.remove(blmObj);\n } else {\n // console.log('you cannot delete that object!');\n this.props.toastCont.error(\n `You cannot delete a template object`,\n `ERROR`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n }\n } else {\n fabricCanvas.remove(blmObj);\n this.saveBlmDraft();\n }\n });\n this.saveBlmDraft();\n fabricCanvas.deactivateAll().renderAll();\n } else {\n if (e.target.type === 'textbox') {\n if (\n e.target.templateObject === false ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ) {\n fabricCanvas.remove(e.target);\n this.saveBlmDraft();\n } else {\n // console.log('you cannot delete that object!');\n this.props.toastCont.error(\n `You cannot delete a template object`,\n `ERROR`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n } else {\n fabricCanvas.remove(e.target);\n this.saveBlmDraft();\n }\n }\n this.stopEraser();\n }\n\n addText(e) {\n this.props.resetActiveTimeout();\n if (this.state.addingText === false) {\n return;\n }\n const pointer = fabricCanvas.getPointer(e.e);\n const posX = pointer.x;\n const posY = pointer.y;\n let templateObject =\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ? true\n : false;\n let borderColor =\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ? 'rgba(102,153,255,0.45)'\n : 'rgba(255, 251, 165, 3)';\n let backgroundColorForText =\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ? 'rgba(102,153,255,0.25)'\n : 'rgba(251, 250, 219, 1)';\n\n let textbox = new fabric.Textbox('', {\n fontFamily: 'comic sans',\n fontSize: 24,\n templateObject: templateObject,\n backgroundColor: backgroundColorForText,\n width: 200,\n left: posX,\n top: posY\n });\n\n textbox.set({ borderColor: borderColor }); //({borderColor: '#FF5733'});\n textbox.set({ backgroundColor: backgroundColorForText });\n textbox.set({ borderScaleFactor: 5 });\n textbox.set({ padding: 10 });\n textbox.set({ transparentCorners: true });\n textbox.set({ cornerColor: borderColor });\n\n fabricCanvas.add(textbox);\n fabricCanvas.setActiveObject(textbox);\n textbox.enterEditing();\n this.stopTextMode();\n fabricCanvas.fire('saveData');\n }\n\n saveBLMTemplate() {\n this.props.resetActiveTimeout();\n this.stopDrawingMode();\n this.stopTextMode();\n\n if (!this.props.isOnline) {\n this.props.toastCont.warning(\n `No internet connection.`,\n `Error Saving Template`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n\n let jsonData = fabricCanvas.toDatalessJSON([\n 'cornerColor',\n 'templateObject',\n 'backgroundColor',\n 'borderColor',\n 'borderScaleFactor',\n 'padding',\n 'transparentCorners'\n ]);\n let blmID = this.props.blm.ID;\n\n const saveBLMData = Object.assign(\n {},\n { blackLineMasterID: blmID, Content: jsonData, order: 1 }\n );\n this.props\n .saveBLMTemplate(saveBLMData, this.props.user)\n .then((blmItem) => {\n // this.props.emptyBLMData(this.props.blm); // @jfbloom22 Why do we empty???\n this.props.updatePendingItem(false);\n this.props.toastCont.success(`Blm is saved!`, `Success`, {\n showAnimation: 'animated fadeInDown'\n });\n })\n .catch((error) => {\n console.error('Error saving blm item', error);\n this.props.toastCont.error(\n 'Unable to save template. Please try again or contact support.',\n `Error Saving`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n });\n }\n\n saveBlmDraft() {\n this.props.resetActiveTimeout();\n if (\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ) {\n return;\n } else if (\n this.props.location.query.projectAssignmentID !==\n this.props.blm.projectAssignmentID\n ) {\n console.error('Error saving BLM draft: blmIDs do not match');\n return;\n }\n if (!this.props.isOnline) {\n this.props.toastCont.warning(\n `You may loose your work. Please connect to the internet.`,\n `Auto Save Error`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n }\n // Determine the mode and then pass in the correct type\n // When you save a blm, it should clear this.props.blm.blmData\n const jsonData = fabricCanvas.toDatalessJSON([\n 'cornerColor',\n 'templateObject',\n 'backgroundColor',\n 'borderColor',\n 'borderScaleFactor',\n 'padding',\n 'transparentCorners'\n ]);\n const blackLineMasterID = this.props.location.query.blmID;\n const HasTemplate = this.props.blm.fabricItems.HasTemplate;\n // const HasTemplate = false; // for testing\n const projectAssignmentID = this.props.location.query\n .projectAssignmentID;\n // double check to make sure we have everything\n if (\n !blackLineMasterID ||\n !projectAssignmentID ||\n projectAssignmentID === '00000000-0000-0000-0000-000000000000'\n ) {\n console.error('missing blmID or projectAssignmentID');\n this.props.toastCont.error(\n 'ERROR',\n 'Error submitting assignment. Missing an ID. Please try again or contact support.',\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n const newBLMItem = Object.assign(\n {},\n {\n type: 1,\n blackLineMasterID,\n projectAssignmentID,\n Content: jsonData,\n order: 1,\n HasTemplate: HasTemplate\n }\n );\n\n this.props\n .saveBLMItem(newBLMItem, this.props.user, false)\n .then((blmItem) => {\n this.props.updatePendingItem(false);\n })\n .catch((error) => {\n console.error('Error saving blm item', error);\n\n this.props.toastCont.error(\n 'You may loose your work if you continue editing the project. Please contact support.',\n `Error Auto Saving`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n });\n // Potential Solutions:\n // Book actions (pull into two page view blmactions and bookactions and make sure)\n // things are identical\n // Save this to redux\n // Issue is we are saving to redux AND THEN we are sending to the API\n // If we are saving a blm draft we also need to save to canvas\n // We already have a listener (save to canvas saves blm draft)\n }\n\n submitBLM = () => {\n this.props.resetActiveTimeout();\n if (!this.props.isOnline) {\n this.props.toastCont.warning(\n `No internet connection.`,\n `Error Submitting`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n\n this.stopDrawingMode();\n this.stopTextMode();\n this.setState({\n freezeBlm: 'none',\n blmButtonsClasses: 'freeze-buttons',\n showBlmSubmitModal: false\n });\n\n const jsonData = fabricCanvas.toDatalessJSON([\n 'cornerColor',\n 'templateObject',\n 'backgroundColor',\n 'borderColor',\n 'borderScaleFactor',\n 'padding',\n 'transparentCorners'\n ]);\n const blackLineMasterID = this.props.location.query.blmID;\n const projectAssignmentID = this.props.location.query\n .projectAssignmentID;\n // double check to make sure we have everything\n if (\n !blackLineMasterID ||\n !projectAssignmentID ||\n projectAssignmentID === '00000000-0000-0000-0000-000000000000'\n ) {\n console.error('missing blmID or paID');\n this.props.toastCont.error(\n 'ERROR',\n 'Error submitting assignment. Missing an ID. Please try again or contact support.',\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n\n const saveBLMData = Object.assign(\n {},\n {\n type: 1,\n blackLineMasterID,\n projectAssignmentID,\n Content: jsonData,\n order: 1\n }\n );\n const submitBLMData = Object.assign(\n {},\n { blackLineMasterID, IsComplete: true, projectAssignmentID }\n );\n\n this.props\n .saveBLMItem(saveBLMData, this.props.user, true)\n .then((blmItem) => {\n return this.props\n .updateStatus(submitBLMData, this.props.user)\n .then((updatedBlm) => {\n this.props.updatePendingItem(false);\n this.props.toastCont.success(\n `Your worksheet has been sent to your teacher!`,\n `Success`,\n {\n showAnimation: 'animated fadeInDown'\n }\n );\n });\n })\n .catch((error) => {\n console.error('Error saving and submitting blm', error);\n this.props.toastCont.error(\n 'Unable to submit project. Please try again or contact support.',\n `Error`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n });\n };\n\n printElement(elem, append, delimiter, clone = true) {\n this.props.resetActiveTimeout();\n var domClone = clone ? elem.cloneNode(true) : elem;\n domClone.style.transform = 'none';\n var $printSection = document.getElementById('printSection');\n\n if (!$printSection) {\n $printSection = document.createElement('div');\n $printSection.id = 'printSection';\n document.body.appendChild($printSection);\n }\n\n if (append !== true) {\n $printSection.innerHTML = '';\n } else if (append === true) {\n if (typeof delimiter === 'string') {\n $printSection.innerHTML += delimiter;\n } else if (typeof delimiter === 'object') {\n $printSection.appendChild(delimiter);\n }\n }\n\n $printSection.appendChild(domClone);\n }\n\n doPrint() {\n this.props.resetActiveTimeout();\n this.stopDrawingMode();\n this.stopTextMode();\n this.setState({ erasing: false });\n let blmContent = document.getElementById(`blm`).firstElementChild;\n\n let canvasImage = fabricCanvas.toDataURL({\n format: 'png',\n multiplier: 2\n });\n // Make another div that has the additional information we need ex:\n // var info = document.createElement('div'); info.innerHTML = 'THE ACTUAL INFO'\n let image = document.createElement('img');\n image.src = canvasImage;\n image.style.width = blmContent.style.width;\n image.style.height = blmContent.style.height;\n image.style.position = 'absolute';\n image.style.top = '0';\n image.style.left = '0';\n this.printElement(blmContent, null, null);\n this.printElement(image, true, '', false);\n setTimeout(function () {\n window.print();\n let $printSection = document.getElementById('printSection');\n document.body.removeChild($printSection);\n }, 100);\n }\n\n showTeachersComment() {\n this.props.resetActiveTimeout();\n if (\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ) {\n return false;\n } else if (this.props.blm.teachersComment === '') {\n return false;\n } else {\n return true;\n }\n }\n\n toggleComments() {\n this.props.resetActiveTimeout();\n this.stopDrawingMode();\n this.stopTextMode();\n if (this.state.commentsSlideUp) {\n this.setState({\n commentsSlideUp: false,\n toggleClass: 'fa fa-angle-double-up'\n });\n } else {\n this.setState({\n commentsSlideUp: true,\n toggleClass: 'fa fa-angle-double-down'\n });\n }\n }\n\n handleChange(e) {\n this.props.resetActiveTimeout();\n this.setState({ teachersCommentForStudent: e.target.value });\n }\n\n submitTeacherComment() {\n this.props.resetActiveTimeout();\n if (!this.props.isOnline) {\n this.props.toastCont.warning(\n `No internet connection.`,\n `Error Commenting`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n\n const ProjectAssignmentID = this.props.location.query\n .projectAssignmentID;\n const BlackLineMasterID = this.props.blm.ID;\n const StudentID = this.props.location.query.studentID;\n const teacherComment = Object.assign(\n {},\n {\n BlackLineMasterID,\n StudentID,\n text: this.state.teachersCommentForStudent,\n ProjectAssignmentID\n }\n );\n this.toggleComments(); // hide the comment to make it look like it sent\n\n this.props\n .teacherMakesBLMComment(teacherComment, this.props.user)\n .then((comment) => {\n // console.log('teacher comment saved', teacherComment);\n this.toastCont.success('Comment was saved!', `Success`, {\n closeButton: true,\n showAnimation: 'animated fadeInUp'\n });\n })\n .catch((error) => {\n console.error('Comment was not saved', error);\n this.toastCont.error('Comment was not saved', `Error`, {\n closeButton: true,\n showAnimation: 'animated fadeInUp'\n });\n });\n }\n\n isNotCompleteForStudent() {\n // if the user is a student then we check if this is not complete\n // if it is not complete then we return true which means (SHOW THIS!)\n // If we are not a student, then we need to return true to say, show this)\n if (UserAPI.isStudent(this.props.user.RoleID)) {\n if (this.props.blm.isComplete !== true) {\n return true;\n }\n } else {\n return true;\n }\n }\n\n exitBlm() {\n if (\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n // console.log('closing the project as a student');\n this.props.turnOnPointer();\n this.props.closeBookView();\n } else {\n // console.log('closing project as Not a student')\n this.props.turnOnPointer();\n this.props.exitBlmMode(false);\n }\n }\n // MODAL LOGIC BELOW\n closeBlmSubmitModal = () => {\n this.props.resetActiveTimeout();\n this.setState({ showBlmSubmitModal: false });\n };\n\n showBlmSubmitModal() {\n this.props.resetActiveTimeout();\n this.stopDrawingMode();\n this.stopTextMode();\n this.props.turnOnPointer();\n this.setState({ showBlmSubmitModal: true });\n }\n render() {\n let freezeComments = 'teacher-comments';\n let commentsContainerClassName = this.state.commentsSlideUp\n ? 'comments-container comments-slide-up'\n : 'comments-container';\n let commentsWidth = 12;\n let teachersComment;\n let markerSelected = marker_hl_orange;\n let styles = {\n width: `${this.props.blm.bounds[0][0]}px`,\n height: `${this.props.blm.bounds[0][1]}px`,\n // transform: `scale(${this.props.projectScalePercent})`,\n // WebkitTransform: `scale(${this.props.projectScalePercent})`,\n pointerEvents: `${this.state.freezeBlm}`\n };\n if (\n this.props.location.query.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n freezeComments = 'teacher-comments';\n commentsWidth = 8;\n teachersComment = this.state.teachersCommentForStudent;\n } else {\n freezeComments = 'teacher-comments freeze';\n teachersComment = this.props.blm.teachersComment;\n }\n if (this.props.projectToolbar.drawingColor === '#000') {\n markerSelected = marker_hl_black;\n } else if (this.props.projectToolbar.drawingColor === '#2A3DB9') {\n markerSelected = marker_hl_blue;\n } else if (this.props.projectToolbar.drawingColor === '#ff8f02') {\n markerSelected = marker_hl_orange;\n }\n\n return (\n
\n
\n
\n \n
\n {this.showTeachersComment() && (\n \n
\n this.toggleComments()}\n >\n \n \n
\n \n
\n \n \n \n {this.state.showCommentButtons && (\n \n \n this.submitTeacherComment()\n }\n role=\"button\"\n type=\"button\"\n >\n Save\n \n \n Cancel\n \n \n )}\n
\n
\n
\n )}\n
\n \n \n \n {\n this.toastCont = toast;\n }}\n className=\"toast-top-right\"\n />\n
\n );\n }\n}\n\nfunction mapStateToProps(state) {\n return {\n completedBLMs: state.completedBLMs,\n blmData: state.blmData,\n viewerMode: state.viewerMode,\n projectToolbar: state.projectToolbar\n };\n}\n\nfunction mapDispatchToProps(dispatch) {\n return bindActionCreators(\n {\n saveBLMTemplate,\n emptyBLMData,\n saveBLMItem,\n updateStatus,\n teacherMakesBLMComment,\n turnOnEraser,\n turnOnPointer,\n turnOnDrawingMode,\n turnOnTextMode,\n showRichTextButtons,\n updatePendingItem\n },\n dispatch\n );\n}\n\nexport default connect(mapStateToProps, mapDispatchToProps)(FabricUI);\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAALEwAACxMBAJqcGAAAC6VJREFUeJzVnHmQFNUdx799zMFe7MkajsVdQFFTZZEAQgSjoIgICUkFExPEAwvDIbKJaLAsnTKJR5ISo4jB0iReWJLDhAWX06UMUVdAzB8RkV1gd/aamZ6eu6enr5c/OOTY2Xk90z0z+fw33b/3fr/6znv97sfg/wCPx8POaKwdDxZjCVgnIYhzRO6YfefPegsdG1PoADKxc/OLK3pHjX42Xl7muvBdtSiG6wZ8P7958ao/FiI2oMgF3LF545qOyyasN1h2SLuRfQNfVoaD37tx8erP8xTaWYpWwL1vbRjb2dh4XHa7h1bvNA5VJaO8Pe+Wx7if3HD33bLd8Z2BKrhCIA6v3E0rHgCoDgdzsqnx+ycbq8I7Nm9cY2ds51KUJbB18x/WHZs44clc8qgfGOiuEwK3zVqypt2quAaj6ATcs/m5+pMN43qkkhI+17x4TcOont7dDin+g3mLV0etiO9Ciq4KR8qqd1ohHgBoPI+uS8fe1D+2UWh9+yWPFXleSFGVwF1vblz5xZWXb7Ar/9qAEKgNBG6fs3jVXqvyLBoB2/60vvJEU5MvXl7mtNMPaxgY1dP7UUk0sPDmJWv9OednRVBWEKmqarVbPAAwWBbehjHTu8Zd2ffeOy8/n2t+RVECd7214Y6jEye+Tpj8h1MtipG6Pv8dNy9Z2ZJN+oIL2LJpU0nw8hFCtKJiWKFiYHUDjcdPbLr1h8t+ajqtHQGZQatzthRSPAAwOBbHxzfd1/r2xkfNpi2ogHveeGFhb8PoWYWM4QyEYdA7eszjbR6PqS5UwQTcssXj7Bs58o1MEwX5RCot4VOXjVhlJk3Bonezo7eEqyrLCuU/Hb2ukpVm7Asi4K43N8z2jm34biF8Z0JiMcaMfd4F9Hg8rL++/q86x+XbNRUJTXWYsc+7gJOvGvW6WFNdmW+/NKiyjATHs5uefng4bZq8Crj7zeendY9t+HE+fdJCCEEsKJ76IWs30KbLq4CBuvqtGs8XvPM+GFI4Al3VTv3g+em06fIm4Pa/vPySUFdbly9/ZtAUBVL0q+lC1eW8mjZtXgR8/88brvKOGXNfPnyZhgAxIQiQrx6pblcTbfK8CBiuqtiqOJ3FWXUjEWiKet6zVEnJJbTpbRdQWLN04fT9HzZN/PwLMIRkTpBHNFWFFLl4pl8uKyulzcPWUhFevrxKcylHANQDQLiqEgeumYLAiOL4FIb6B6CllEHfVXQKZWvXrk1kysPWEqi5lPU4LR4AVIbCuGnHbkz798dwySk7XWckGY2mFQ8AKmXfCJp8bBMw2HzPHAB3DvauqfM4FvyjBROOHrPL/ZDoqoZEKDKkjUFQOAH9K1aUEcK8MpSNU1Ewpf0A5m7fgRohaEcYaYkFRZBM32ODoRqN2CIg60g9A9ANyquDIua07sLUjz+BU0lfpawiGYtDlTPv/GAYg2qwbrmA/uZ7Z4LBcjNpGEIw/ssOLHi3BeM6Oq0O6SyGpiMRClPZcppOZWipgCc8d7lZQl5Flq27K5XCNR+2Y07rLlSJIStDA3C66hpGRjvGMMByOEKTp6UCVkT4JwBMyDWf2oCAudt34JsHDsGhqpkTUCDHE1CSSTr/Xd0H7/Y8R1UCLZuUCzTfMxkEr8KiP4UBUCsEMa7zOJIlwxCuyn4GzNB1RP2BzA0HAFcioVd2901u+Vd7xj4gYJGAZNkyR9JBWgFQD4Fo4TUNY7q9qB/wQairRcp90UbVjMSCIjTKBuqSLzt+dd8Tz26jzdsSAVfNnPQYA9xmRV7pKE0kMP5YBxyqCmFEHWgXo1KSBCk8dJ/vDFW9fT33P/TL75iJK+fqJq5e+nUGZF2u+dDAGgau+O8RzP/nNjR0dWe0J4aBeJCuMeJUlVT1BxaYjSmnEkgWLeKk4c4WgGnIJR+zOFQVDV3dqA0ICNbVQnENXq3jQRFqim7IeEnn8XeWPf7bF83GklMJFEZVNAPMlFzyyIWv9fXj1q3bcfXh/4DT9fPeKckk5DhVO4AyUYzXNh1bnE0MWZdA/+q7JrAMtwWAqVUsq2EIwQh/AJee6EK8vAyxigoYuoGIj67VZQhBfeeJHy1Z+UpWO/yzEpAAjDx98t8AMj6b9HbgVBRceqILlWIIHSwHmWTuMANAXVf3RyvWPbk2W79ZVeFg89LlAPl2tk7tpOaLoxjxMd2+cldCUkuikfm5+DMtoPjAsgYQPJ2LU7sghoF+bw9qvF4q+xpv92P3etaLufg0LaAOfROA8lyc2kXA54OSSqHC5wefoeNcOeA7sfyRZ3IuCKYEFJqX3skwmJurUzuQpSSCAQHAqYahqrcvrS2nqsQdE2+1wi+1gJHmpdUgeNYKp1ZDCEGf1wuc0+rWeHvS2td6va+tfPg3VLMtmaAWUFaMRwBUW+HUaoJ+P1IXTJJW9wwuYGkoFBHi3FKrfFMLqOlas1VOrSQlyxB8F59WKAuKcErSec8YQlAREG73eDx0fRwKqAQ8vPD6SpYroq2kZzhdddN1mGt6zj+PXd3bu2/FL55stTIEKlEMg2s4u/GmiAgKAmQp/SRp9TnfQVciobDQLd/USSUgIUyFnCzsOu6FKCkFgf6BIW3O/Q4O9/kfWr3aY/mBQ8od6UaJnExBSalwugo69D1L/xBV9wzDojEMi0ThlOVj9z/4xO/tiIPuu2YQBwCEgxGoRVCVQ0IQUoJupqW2qzvKJpPz7IrF1JkIwzAg+kMoqyhFaXmJXTENiaqq8Pf3U9uPa29fPLt1f4dd8ZhuWQkhiEXiEAaCUGT7F8IvpN/bA4NiaRIACPDO7Nb9WZ2Bo4VKQAa4aMpX03SIQhjhYAS6pg+WzHIiYgiJWIzWPOxk2QfsjAegrMIESNsEy8kUUrKC0vISlJaXgLHpxKWmafD1pR/fXghDmAen7W332RLMOVB2Y9gh6yohBPFoAoJPhF3dnYGeXug6XUlngA+u3fdJXi7joRKQA6FSRdd0hIMRiEIYmoXVOhqJIBahW5oEoABkGXPermf7oCyBhqnWQpEVCL4gYpE41brEUOi6Dl8P/RVZBPj1jLaDR3NyagI6AXnQbWk6LxGQiEkIDASRlLK/SMjX2wdNo+x7MuRI3B16JmtnWUDbjRGydWDoBiJiFEF/yHQnPB6NIRKi36XFGGTZvNaOvI45qQSc3LJPMAwjpyGIqqgI+kREQzGqfpymquhPM6eXhpdn7Du0P+sAs4R+PlBVdlnhUEokIQyIkOLJtJ/5lCyjq/M4NPqtbT6NqA9bEZ9ZqIdyBtyLdEPzcyxPfYYibV6GgWg4hkRMgnuYC7yTByEGUskk4rEY4lGTkyYMc/8NbZ+Z/05bgKle74FbbpzkGuZsZ1nO8ikZTVUQi2axwshg28z3D5jeFGQVpsbCU1r3HJZlaaqua1Jma5OBsFltkkgwrGHqiL7VmJ5MmPrevs8SkjFGVWRLr5VjszjBzjDk0Rl7DmXe52YjWa1zfGvnTnHS1t3TUpJ0i6apWXdxLgrGXCk82FfT+IJVvrPFkpH/p/NnPcU73Q+yLJfTtXWxiAhNoxr06IZOpnz7g4OHc/FnBZastH1j2/vr4gm9XknJ+3IZutFWY0KwvhjEA2w4rfnpvFnXsQ7H27zDOdJs2qQUh5yMD2nDACfdZcZVk1sOWd6QZYNtx10Pzp+9zulweViOo77SLpVKQooPPetCwMy9ru2TnTkHaBG2LZZP3rb3KY6XalIpeTuhrNdc5kZkczGJB+Tp+rsDt9w4yeHk/s47nJcOZWcYOiKhQLrXIutwXHHtrg9zvnXSSvJ6j8Gh+bNX8g7n7ziOd6ezCQXTLZaTpTPbDhbsyvd05P0iiLbrr3dXlvOv8U73ImaQBZRIKADDuGg2e9+MtgOz8jXLbIaC3aTRPm/2ZU4Ht9XhcF1+7vNYVISmntcX7GV4beqM3YfpV5TySMGvIvl0waw7ON71Isfx5QCQiEegpE5tGCLAVpbXlhereADwPyNf2L8kpaU8AAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,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\"","import * as React from 'react';\n\nimport { Button, Dropdown, FormControl, FormGroup } from 'react-bootstrap';\n\nimport { StyledButton } from '../../constants/styledComponents';\nimport constants from '../../constants/constants';\nimport icon_eraser from '../../images/icon_eraser.png';\nimport icon_pointer from '../../images/icon_pointer.png';\nimport icon_text from '../../images/t.png';\nimport { isIOS } from 'react-device-detect';\n\nclass ProjectToolbar extends React.Component {\n theme = constants.themeProvider.activeTheme;\n\n render() {\n const {\n showToolbar,\n blmButtonsClasses,\n currentFontSize,\n showAdminSaveButtons,\n showMarkersButtons,\n showStudentSaveButtons\n } = this.props.parentState;\n const showRichTextButtons = this.props.projectToolbar\n .showRichTextButtons;\n let pointerClassName, eraserClassName, textClassName, drawingClassName;\n this.props.projectToolbar.pointer\n ? (pointerClassName = 'hl-pointer active-button')\n : (pointerClassName = 'hl-pointer');\n this.props.projectToolbar.erasing\n ? (eraserClassName = 'eraser active-button')\n : (eraserClassName = 'eraser');\n this.props.projectToolbar.startText\n ? (textClassName = 'add-text active-button')\n : (textClassName = 'add-text');\n this.props.projectToolbar.drawingMode\n ? (drawingClassName = 'markers active-button')\n : (drawingClassName = 'markers');\n const projectToolbarStyle = {\n transform: `scale(${1 / this.props.projectScalePercent})`,\n transformOrigin: 'bottom left'\n };\n\n if (!showToolbar) {\n return null;\n }\n\n return (\n
\n {!showRichTextButtons && (\n \n \n \n )}\n
\n \n \"\"\n \n {showRichTextButtons && (\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n )}\n {showMarkersButtons &&\n this.props.isNotCompleteForStudent() &&\n !showRichTextButtons && (\n
\n \n \n \n \n \n \n this.props.startDrawingMode(\n '#ff8f02'\n )\n }\n />\n \n this.props.startDrawingMode(\n '#000'\n )\n }\n />\n \n this.props.startDrawingMode(\n '#2A3DB9'\n )\n }\n />\n \n \n
\n )}\n
\n {this.props.isNotCompleteForStudent() && !showRichTextButtons && (\n \n \"\"\n \n )}\n {this.props.isNotCompleteForStudent() && !showRichTextButtons && (\n \n \"\"\n \n )}\n {showAdminSaveButtons && (\n \n Save\n \n )}\n {showStudentSaveButtons &&\n this.props.isNotCompleteForStudent() &&\n !showRichTextButtons && (\n \n Submit\n \n )}\n {showStudentSaveButtons && !showRichTextButtons && !isIOS && (\n \n Print\n \n )}\n {this.props.isNotCompleteForStudent() && !showRichTextButtons && (\n \n Reset\n \n )}\n
\n );\n }\n}\n\nProjectToolbar.propTypes = {};\n\nexport default ProjectToolbar;\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAARCAYAAAACCvahAAAAiklEQVQ4je3TUQ3CQBAE0NcGA7VwFmoBC1jAQrGABSRgoRqQABYqYfk5kuuF9Ai/MMkke5udnfvYgYT4gtedNS545PqYF8MZS64nDJn2edMUEV7EXLikoj/gjrmvXJuIiCXPJqXbJ84l+w2TJv7iHxZ3XTdiLFqHt+rqJFvxXIWnjuSC08ZPb+XjCV2cbIyiaLRxAAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxNTRmMGUzYi02NjM1LTZkNDAtODc4My1hOWMxMWRlMGM1YjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTIwNUZCMzE1NzgyMTFFN0JBQTQ4NEYzOUM4RTIyN0IiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTIwNUZCMzA1NzgyMTFFN0JBQTQ4NEYzOUM4RTIyN0IiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MTU0ZjBlM2ItNjYzNS02ZDQwLTg3ODMtYTljMTFkZTBjNWIwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE1NGYwZTNiLTY2MzUtNmQ0MC04NzgzLWE5YzExZGUwYzViMCIv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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxNTRmMGUzYi02NjM1LTZkNDAtODc4My1hOWMxMWRlMGM1YjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEM4MUQ5OTk1NzgyMTFFN0I1OTdGQjM1RDY2NTQyNzciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEM4MUQ5OTg1NzgyMTFFN0I1OTdGQjM1RDY2NTQyNzciIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MTU0ZjBlM2ItNjYzNS02ZDQwLTg3ODMtYTljMTFkZTBjNWIwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE1NGYwZTNiLTY2MzUtNmQ0MC04NzgzLWE5YzExZGUwYzViMCIv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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxNTRmMGUzYi02NjM1LTZkNDAtODc4My1hOWMxMWRlMGM1YjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjlENDY1NDM1NzgyMTFFNzkxMTZFMUYxRjM2RTBERDEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjlENDY1NDI1NzgyMTFFNzkxMTZFMUYxRjM2RTBERDEiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MTU0ZjBlM2ItNjYzNS02ZDQwLTg3ODMtYTljMTFkZTBjNWIwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjE1NGYwZTNiLTY2MzUtNmQ0MC04NzgzLWE5YzExZGUwYzViMCIv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\"","import React from 'react';\nimport FabricUI from './FabricUI';\nimport { round } from 'lodash';\n\nclass BLM extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n pageContainerWidth: 0,\n pageContainerHeight: 0,\n marginLeft: 0,\n pageClassName: '',\n pageWidth: 0,\n pageHeight: 0\n };\n this.resizeProjectPage = this.resizeProjectPage.bind(this);\n }\n componentDidMount() {\n console.log('Project (BLM) component mounted');\n this.resizeProjectPage();\n window.addEventListener('resize', this.resizeProjectPage);\n }\n componentWillUnmount() {\n window.removeEventListener('resize', this.resizeProjectPage);\n console.log('unmounting BLM');\n }\n componentDidUpdate(prevProps) {\n let shouldResize = false;\n if (\n prevProps.leftPageContainerWidth !==\n this.props.leftPageContainerWidth ||\n prevProps.leftPageContainerHeight !==\n this.props.leftPageContainerHeight\n ) {\n shouldResize = true;\n // console.log('leftPageContainer changed in Project');\n }\n if (\n prevProps.blm.Title !== this.props.blm.Title ||\n prevProps.blmMode !== this.props.blmMode\n ) {\n shouldResize = true;\n // console.log('blm changed in project');\n }\n if (prevProps.pagesVisible !== this.props.pagesVisible) {\n shouldResize = true;\n // console.log('pagesVisible changed in project')\n }\n if (shouldResize) {\n this.resizeProjectPage();\n }\n }\n resizeProjectPage() {\n const topToolbarToggle = 40; // and close button\n const bottomToolbarHeight = 120;\n const widthOfArrow = 60;\n const widthOfProjectToolbar = 50;\n let maxContentHeight = 0;\n let maxContentWidth = 0;\n let scalePercent = 1;\n let pageContainerWidth = 0;\n let pageContainerHeight = 0;\n let marginLeft = 0;\n\n const pageWidth = this.props.blm.bounds[0][0];\n const pageHeight = this.props.blm.bounds[0][1];\n\n // if Project is displaying next to a book page, then subtract the page width and the two arrow buttson from the available space\n if (this.props.pagesVisible === 1) {\n maxContentHeight = window.innerHeight - topToolbarToggle;\n maxContentWidth = window.innerWidth - widthOfProjectToolbar - 80; // plus some extra whitespace\n } else {\n maxContentHeight =\n window.innerHeight - topToolbarToggle - bottomToolbarHeight;\n maxContentWidth =\n window.innerWidth -\n this.props.leftPageContainerWidth -\n widthOfArrow * 2 -\n widthOfProjectToolbar;\n marginLeft = this.props.leftPageContainerWidth + 50;\n }\n const heightDiff = pageHeight - maxContentHeight; // difference between the height of the project and the available hight we can display it in\n let widthDiff = pageWidth - maxContentWidth; // difference between the width of the project and the available width we have to display it in\n\n let pageClassName = this.getProjectClassName();\n // if we are lacking mostly height, then scale down by height\n if (heightDiff < widthDiff) {\n // TODO we might be able to increase the available width to display the wide BLM by adding margin top for the close button\n // limit by width\n scalePercent = round(maxContentWidth / pageWidth, 3);\n pageContainerWidth = pageWidth * scalePercent;\n pageContainerHeight = pageHeight * scalePercent;\n // console.log('resizing blm by width', maxContentHeight, maxContentWidth, pageContainerWidth, pageContainerHeight)\n } else {\n // limit by height\n scalePercent = round(maxContentHeight / pageHeight, 3);\n pageContainerWidth = pageWidth * scalePercent;\n pageContainerHeight = pageHeight * scalePercent;\n // console.log('resizing blm by height', maxContentHeight, maxContentWidth, pageContainerWidth, pageContainerHeight)\n }\n this.setState({\n pageContainerWidth,\n pageContainerHeight,\n pageClassName,\n marginLeft,\n pageWidth,\n pageHeight\n });\n this.props.updateProjectScalePercent(scalePercent);\n }\n\n getProjectClassName() {\n let pageClassName = 'blm ';\n if (this.props.pagesVisible === 1) {\n pageClassName += 'single-page';\n }\n return pageClassName;\n }\n\n render() {\n /*\n * size and position self\n * if single page: 'left page-left single-page'\n * if 2 page: 'right page-right blm-page'\n */\n const pagesVisible = this.props.pagesVisible;\n let projectClassName = '';\n if (pagesVisible === 1) {\n projectClassName = 'page left page-left single-page';\n } else {\n projectClassName = 'page right page-right blm-page';\n }\n if (!this.props.blmHtml) {\n return null;\n }\n const pageStyle = {\n width: `${this.state.pageContainerWidth}px`,\n height: `${this.state.pageContainerHeight}px`,\n marginLeft: `${this.state.marginLeft}px`,\n position: 'absolute'\n }; // the width and height will change as we zoom\n const jpedalStyle = {\n width: `${this.state.pageWidth}px`,\n height: `${this.state.pageHeight}px`,\n position: 'relative',\n display: 'block',\n transform: `translateY(0px) translateX(0px) scale(${this.props.projectScalePercent})`,\n transformOrigin: 'top left'\n }; // the scale will change as we zoom.\n return (\n
\n
\n \n \n
\n
\n );\n }\n}\n\nexport default BLM;\n","// NotesPopover is responsible for displaying the note icon and displaying the popover\n\nimport * as React from 'react';\n\nimport {\n FormControl,\n FormGroup,\n OverlayTrigger,\n Popover\n} from 'react-bootstrap';\n\nimport { StyledButton } from '../../constants/styledComponents';\nimport class_note_icon from '../../images/class_note_icon.png';\nimport constants from '../../constants/constants';\nimport group_note_icon from '../../images/group_note_icon.png';\nimport student_note_icon from '../../images/student_note_icon.png';\nimport teacher_note_icon from '../../images/teacher_note_icon.png';\n\nclass NotePopover extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n value: this.props.note.Content.value || '',\n show: false\n };\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n if (\n this.props.activeNoteID === this.props.note.ID ||\n this.props.activeNoteID === this.props.note.TempID\n ) {\n this.setState({ show: true });\n }\n }\n componentDidUpdate(prevProps) {\n if (this.props.activeNoteID !== prevProps.activeNoteID) {\n if (\n this.props.activeNoteID === this.props.note.ID ||\n this.props.activeNoteID === this.props.note.TempID\n ) {\n this.setState({ show: true });\n } else {\n this.setState({ show: false });\n }\n }\n }\n\n onSubmit = (e) => {\n if (e) {\n e.preventDefault();\n }\n const note = this.props.note;\n const newNote = {\n ...note,\n Content: { ...note.Content, value: this.state.value }\n };\n this.props.saveNote(newNote);\n this.props.setActiveNote('');\n };\n\n cancelNote = () => {\n this.props.setActiveNote('');\n // delete the note if the user never saved any content\n if (this.props.note.Content.value === '') {\n this.props.deleteNote(this.props.note);\n }\n };\n\n handleChange = (e) => {\n this.setState({ value: e.target.value });\n };\n\n getPopover = (note) => {\n let popoverClassName = '';\n let disableNote = false;\n let hideFromStudent = '';\n\n if (note.Type === 4) {\n popoverClassName = 'teacher-student-popover-note';\n } else if (note.Type === 5) {\n popoverClassName = 'teacher-class-popover-note';\n } else if (note.Type === 6) {\n popoverClassName = 'teacher-group-popover-note';\n } else if (note.Type === 3) {\n popoverClassName = 'student-popover-note';\n }\n if (this.props.isStudent) {\n if (note.Type === 5 || note.Type === 4 || note.Type === 6) {\n disableNote = true;\n hideFromStudent = 'hide';\n }\n }\n const cancelClassName = `btn-popover popover-cancel`;\n const deleteClassName = `btn-popover popover-delete ${hideFromStudent}`;\n const saveClassName = `btn-popover popover-submit ${hideFromStudent}`;\n\n return (\n \n
\n \n \n \n
\n {\n this.cancelNote(this.props.note);\n }}\n type=\"button\"\n role=\"button\"\n >\n Cancel\n \n {\n this.props.deleteNote(this.props.note);\n }}\n type=\"button\"\n role=\"button\"\n >\n Delete\n \n \n Save\n \n
\n
\n \n );\n };\n handleToggle = () => {\n const noteID = this.props.note.ID || this.props.note.TempID;\n this.props.setActiveNote(noteID);\n };\n\n render() {\n const note = this.props.note;\n const offsetX = note.Content.offsetX;\n const offsetY = note.Content.offsetY;\n const ID = !!note.ID ? note.ID : note.TempID;\n let note_icon;\n if (note.Type === 3) {\n note_icon = student_note_icon;\n } else if (note.Type === 4) {\n note_icon = teacher_note_icon;\n } else if (note.Type === 5) {\n note_icon = class_note_icon;\n } else if (note.Type === 6) {\n note_icon = group_note_icon;\n }\n let placement = 'top';\n if (note.Content.offsetY < 240) {\n // 190 is the height of the popover\n placement = 'bottom';\n }\n return (\n \n \n \"\"\n \n \n );\n }\n}\n\nexport default NotePopover;\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAB7CAYAAACCYiUaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE1QjY5RDM4MThBODExRTc5QTY4RDg4Nzg0MjU3MkUzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE1QjY5RDM5MThBODExRTc5QTY4RDg4Nzg0MjU3MkUzIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTVCNjlEMzYxOEE4MTFFNzlBNjhEODg3ODQyNTcyRTMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTVCNjlEMzcxOEE4MTFFNzlBNjhEODg3ODQyNTcyRTMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5lk+8TAAADLElEQVR42uza20uTYRzA8ed9ndvew+YhAsnoD4jqPgq6iCgCobJsm4c8TdMMMiikyDIIKcibMoouhBIhKoKC7iLoNroKwgvLw8yEaIkuT7HZ3EVgaF70+vZrfb8gYwg+8Hx8nt8Gr/a2tGRB0ZLsoPkiMTm9Z+vjZ67vjc72Lwdi7U6jPP8bawOyMsq+wZrQU0BkXV0lQ7WhB4AIygqYZUO14T5ARKEY4eG6cA8ggjJto3q4PnIHEEkolr9hpD5yCxBBGZa/aSQa6QJEEorpb41Fy68DIii/6Tsdayi/AogkFMN3brSx4jIggvL5vRfSKO2AyELp+Hi8sg0QQXl9uZ3pmdIOiKyZ0jFQebAHEEHlFRZUD1QduguIJJSC/Pr3x0pvACKoYH5ey4fqw12ACCqQF2wdrDlyFRBB2cHA2aG6sg5ABGXZdvtw3dGLgAjKtK1LI9FQGyCCMkyzMxYNnwFE0pdH07g22hg5tdLvNacelAvu3a8KI1VZsWmz50+u+Rrzc/Mtxbd7uzkhQvL6vDfHmiqaARFUrtfbPdZcWQGIoDwez/00Sujne6f+cDL+Rc32v/vnN2hufEz5XFxP07RFlL7xE1XJou57DzWefl9aKpVUGzYVub7uQro0zgEPBL8MVT1HxT9PqNmZKbWQSrl3UnRdK1i3fjMgy34k/b44ctW3RDxzYtz6R9B1fz9D/TcbZAcLM6+ursvWr4IScBcFkNU2KMddFECEoTg21I0t25S1fUd2w/T2qMlPsTUd9I6B5BZvVPbOXVkNMvHkUeakJKbW7tMXV5aw6wsQYSiACENxbIYkXr1U029eZzVC8mt8WRQnZ4pjIKmZmczP/3pSnELhyhJ2fQEiDAUQYSiACEMBRBgKIMJQABGGAogwFECEoQAiDAUQYSiACEMBRBgKIMJQABGGAogwFECEoFiBfEAkpWk6ICJPC1sACAECCAECCAECCAECCAFCgABCgABCgABCgABCgBAggBAggBAggBAggBAgBAggBAggBAggBAggBAgBAggBAggBAggBAggBQoAAQoAAQoAAQoAAQoAQIIAQIIDQH/dDgAEAe4W3cY50hLgAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAABQCAYAAACtSqN4AAADeUlEQVR4nO3by04TURzH8d/0zMyZaTuFkUskgDEuVDQh4MpEE+NCFPH2DD6BW1/Blc9iZGNcaGKCRBcICFTuLiTBkJRLre20HRf8qUQt9HQOyMyc765k5j/kkzn0dBq00ZsrPkJWB29ZK1W9q9dfdX6VNTMha9BxZjOzq41nZt4NrZ+RNTOUEACQZDzVzjPTY7c3TsuYF1oIALAZd1wzlZWBEWoIALAZz7hmeu7jcK4jyJzQQwCAzcyWjJFcmLi73fSdEQkIAOAJI5PUeXZqJN/ZzPmRgQB2MTgzstP3fggvk0hBAABPGK1mQv8iihE5CGAXw9BY9sWtqbONnhNJCACwmOn28u750aGZhjZdkYUAgFO6q3ebXQuv78x3HXZspCEAwNVbjXa9feXN8HLPQcdFHgIAXL3VbNPblj6MrHfXOyYWEACQYY5hJ6y6GLGBAACHOaadsBc/3/97BxorCABwWJr7wPKfGLGDAACHpS0fWF546NW246GEqKIaeIbD0laxWqxhhBIi729LmZNmqWSpWlxafeR36FImHnM7JQ9jxXGU/bKMcanLVv9IKCG8ig/Db8GiN4GSXww8z/V7VkK5NADA0mz0GYPgmi1lXmghAIBrFvqMASkYoYYAAFPjUjBCDwHIwYgEBBAcIzIQQDAM4bdP000g2cOEL3SUlfM+dpZ29xR7GLPeBIp+oeEZwhDuFRMXnjiipx1pm9MePj3N1V43gxGppbE/U+O4ZAzC1lINHR9ZCAAwNBN9xkBDGMJLY2vGQ/a5nA89svJy9T+N6ppRWyYFP1//ONGLFtYqKKxVRE/7rzWCEemlsb89jHrLJDYQwMEYsYIA6mPEDgL4jZHU0r9/Jjqk/RrHuceNvTcfV9vZMmafbQmdo2sG+swBzJUmd1+LXpRZGqzOk7XFLq439zCXQcdFsx9ATJfG/hjdC8J3RPF7BRvjwZ8Tyiy/GnxfIwyRm/SQm/QCX/ikFfulsZeCoBQEpSAo4T+WznkdnTeso/hdmq6wVsG3l40/lvtXwhDJXh3dD+R8uySrzWkvMIRaGpSCoISXxvrbn9h4f7J2lr6EB2bCEH4ZKJdD929gh6aWBqUgKAVBKQhKQVAKglIQlIKgFASlICgFQSkISkFQCoJSEJSCoBQEpSAoBUEpCEpBUAqCUhCUgqAUBKUgKAVB/QLxhdIrvhyPSQAAAABJRU5ErkJggg==\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAABQCAYAAABGfRh7AAADQklEQVR4nO3YTUgUcRjH8e/MzuyuL+tLZlIqhB1D6hbdurS7QtAt6NChi9Ehkt6I9FLrViq+nII6RAQdOnSLIE9dIq8RQgqKlsqKaea76750GJSlfPvPzO46s//fbXfmeebhwz4zwyo/oufSOCgeVaHU631RfvvjNbt6qnY1ylUUFAJ+b/Of7tAzu3o6DgFAAQJ+7/WFnlC3Hf0ciQAGRKnPe2uhJ9RhtZdjEWAL4t5iT7jdSh9HI4ABUeLTW5d6w21mezgeAQyIYq8eWeoNt5qpdwUCbEG0L/c13RGtdQ0CGBBFuta10tfUIlLnKgQwIPy61jv1OLjvm6XrEMCAqCnztY48PN+7n/NdiQCgKnC8yt8y9ijYuee5uRgoX1EVqD/kuzseCUZ2PS9XA+UrqgJ1lb62yWjowY7n5HKgfEVVoKZMj45Hgje3PZ7rgfIVj6pQW+Htm4yGmv89VjAIYEDUlOnPY0/CVzO/LygEMCAOl2ovp5+Gr2x+V3AIYEBUlWivZzubLgFo+R5INPMrKY6WWe/jURXKizxvf3c1pRyHEChSGJpeYW4pZUu/2krthuMQ0uk0xb4ksYUkP2eTlvvpWnLGsfeEhmoP9VUeW3o5FgHsg3A0AtgD4XgEsA7hCgSwBuEaBDAPIfyIVCuOoZZWCV8om0nOjJJeXwYMCEDo8SmM4D91Ad/pi6JlWc3iu/skJr5tfRaFcNU6ZEZkNVyLAPuHEF6H+NAnEjOjpobKVlJzEzse289qCCMkYsMQGxYty2v2gnD1OmRmt9UoGATYGaKgEGB7iIJDgP8hxF+WzlzGdzJo61BWs/yhg0Tsu1DN5s0SzLw2+wOogSOiZdmNppsqa6j2kEgSK8h1yIzmISH8S0j+GmNjdCAb85hOenXBUr0wwvpgP+uD/ZYuetBS8OsAEgGQCIBEAEzcGPUTZ9HrGrMxi+msfX1Pan7KdL04Ql3jgft7LT7yxRKCXAckAmBiHVY/v2J14E0WRjGf9MaapXphhHQiDom4pYsetMh1QCIAEgGQCIBEACQCIBEAiQBIBEAiABIBkAiARAAkAiARAIkASARAIgASAZAIgEQAJAIgEQCJAEgEQCIAEgGAv7fzrEqn+q8pAAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAABQCAYAAABGfRh7AAADgElEQVR4nO3az28UdRjH8ffznZ0fO93WBlIPJkqCFwxQDl7gDAnSdm27RH5FCXcuGG9eICHeetD4B5AAB6MxMTHoP6DGejFV0dREmpLoerDQbF3obukOB7qWhtbt/OgOM/t8bjvzfZ48eeX7nd1MVo4e/SMgQzFWgf6hl2nUax/e+mLw3UR6JtGk+xFcf+DS6Pi9K0l0yygCIILTN3h5dOL++3FbZRcBEBEc/4UPxiYX34vTJ9MI8ATCLg5MjVVqF6P2yDwCrEF4pY/HKrVzUepzgQAgImJ7fTfLlaVTYWtzgwAgYqTg+Z+UT/5bCVOXKwRYg3CLn41M/vX2dmtyhwAgYozr7b5xvHz7wnbW5xIBQIxDsfTqtTfGZ9/qtDa3CADGuHj+nk9HJu+M/u+6bg2UVoxxcbyXvhyp3D2+5ZpuDpRWjHHFcYe+HpmcP7Lp/W4PlFaM8cRxh74ZO/nn68/cS2OgtGKsoinYu35489TCwQ3X0xoorRjLM8byfxw/s/Taf9fSHCitGONZQuGniTP1PZBBhFawlEgfY3kF4PeJs41XCol07GIEn+UHdwloJtHOMTJwPXMIQSugUWvSbP1MK1iM3c82+/7J3HF4EoNjDmJkMKFumU0bYiCBTplOG6I/ZpfMp4BjhmNB5AAB4kLkBAHWIUqhK3OEAFDANsOI9IWsCpnTp0scO1YMW7ajmZpaZHZ2BQDBxjGHaLZmCIL6tupDI5T6DUMvWmHLdjS2LRs+h4XI2XFYTxtC8DuuDb0T/q4+4vYvifxuTyz1+ub/LhBsHGuY5uoMAQ+3rJes/T8hSgIaW0LYZt/nuT0OT0dwcaxDCJs/0HsCAZ6G8J651zMI0IYYRnA3XO8pBAChuLYj1iFCfzvsP+Cwd6+d6GBx8923yywsrG57fRuiuToDREA4fNijXO783dvNzN1ZCYUA6xBB0HiQuddrSUYoIlK813PPhM0Seid8davO9PfLOzFL5MzNPYpVHxqhWl2lWg13/p736HFAEQBFABQBiPBgfOd8PydOPF8/lq5evc9vv0Z/xxEawXEE35fOC7sYK+Z+1uNAhJ0wP7/C9HRjJ2aJnNpSK1Z9T7xe65CP9DigzwRAEQBFABQBUARAEQBFABQBUARAEQBFABQBUARAEQBFABQBUARAEQBFABQBUARAEQBFABQBUARAEQBFAOAxIqKt2pZP1SsAAAAASUVORK5CYII=\"","/*\n * BookPage component is responsible for a single book page\n * it knows how to size itself, render highlights and notes.\n * The reason the Pages component does not size the BookPage is because the Pages component would need\n * to send sizing data for all the pages. However we really only need the currently visible pages.\n * Then the only thing the BookPage component would need to do is figure out if it is the left or right page.\n */\n\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport { connect } from 'react-redux';\nimport { withRouter } from 'react-router';\nimport { viewerModes } from '../../constants/viewerModes';\nimport { round, filter } from 'lodash';\nimport { toastr } from 'react-redux-toastr';\nimport NotePopover from './NotePopover';\nimport { saveBookItem, deleteBookItem } from '../../actions/bookActions';\nimport { setActiveNote } from '../../actions/bookViewActions';\nimport { startPointing } from '../../actions/bookToolbarActions';\nimport UserAPI from '../../api/userAPI';\nimport constants from '../../constants/constants';\n\nclass BookPage extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n scaleX: '',\n scaleY: '',\n pageContainerWidth: 0,\n pageContainerHeight: 0,\n pageClassName: '',\n marginLeft: 0,\n pageScalePercent: 0\n };\n this._lastResized = 0;\n this.resizePage = this.resizePage.bind(this);\n this.assignBookPageClassName = this.assignBookPageClassName.bind(this);\n this.saveNote = this.saveNote.bind(this);\n this.deleteNote = this.deleteNote.bind(this);\n this.deserialize = this.deserialize.bind(this);\n this.getNotesHTML = this.getNotesHTML.bind(this);\n\n this.retryCount = 0;\n }\n\n componentDidMount() {\n this.assignBookPageClassName();\n\n // window.addEventListener('resize', () => this.resizePage());\n window.addEventListener('resize', this.assignBookPageClassName);\n\n /*\n * Setup Mobile Safari listeners\n */\n\n // TODO refactor/blms\n // We are setting up event listeners\n // $(document.body).on('touchend', '.pages .left, .pages .right', (e) => {\n // this.props.pagesTapped(e);\n // });\n // $(document.body).on('touchend', '.pages .left .tappable, .pages .right .tappable', (e) => {\n // this.props.wordTapped(e);\n // });\n // not sure how to properly trigger these events on Mobile Safari\n // $(document.body).on('touchstart', '.pages .left, .pages .right', (e) => {\n // this.props.onMouseDown(e);\n // });\n // $(document.body).on('touchmove', '.pages .left, .pages .right', (e) => {\n // this.props.onMouseMove(e);\n // });\n // $(document.body).on('touchend', '.pages .left, .pages .right', (e) => {\n // this.props.onMouseUp(e);\n // });\n\n /*\n * Setup Desktop Browser listeners\n */\n // $(document.body).on('click', '.pages .left, .pages .right', (e) => {\n // this.props.pagesTapped(e);\n // });\n // $(document.body).on('click', '.pages .left .tappable, .pages .right .tappable', (e) => {\n // this.props.wordTapped(e);\n // });\n // $(document.body).on('mousedown', '.pages .left, .pages .right', (e) => {\n // this.props.onMouseDown(e);\n // });\n // $(document.body).on('mousemove', '.pages .left, .pages .right', (e) => {\n // this.props.onMouseMove(e);\n // });\n // $(document.body).on('mouseup', '.pages .left, .pages .right', (e) => {\n // this.props.onMouseUp(e);\n // });\n\n // initialize sizes, and deserialize after 2 second (should be enough time to load)\n // TODO rather than a 2 second timeout, can we wait until the HTML renders?\n }\n\n componentWillUnmount() {\n // $(document.body).off();\n window.removeEventListener('resize', this.assignBookPageClassName);\n }\n\n /*\n * Step 5 in loading a book page\n *\n */\n componentDidUpdate(prevProps) {\n let shouldAssign = false;\n if (\n prevProps.blm.Title !== this.props.blm.Title ||\n prevProps.blmMode !== this.props.blmMode\n ) {\n // console.log('blm mode changed in bookpage');\n shouldAssign = true;\n }\n\n if (prevProps.book.currentPage !== this.props.book.currentPage) {\n shouldAssign = true;\n // console.log('current page changed in BookPage');\n }\n\n if (prevProps.pagesVisible !== this.props.pagesVisible) {\n shouldAssign = true;\n // console.log('pagesVisible changed in BookPage', prevProps.pagesVisible, this.props.pagesVisible)\n }\n // change in manual zoom\n if (\n prevProps.bookView.bookManualZoomLevel !==\n this.props.bookView.bookManualZoomLevel\n ) {\n shouldAssign = true;\n // console.log('change in manual zoom level');\n }\n if (\n prevProps.leftPageContainerWidth !==\n this.props.leftPageContainerWidth ||\n prevProps.leftPageContainerHeight !==\n this.props.leftPageContainerHeight\n ) {\n shouldAssign = true;\n // console.log('leftPageContainerWidth changed in BookPage')\n }\n if (prevProps.page.pageReady !== this.props.page.pageReady) {\n shouldAssign = true;\n }\n if (shouldAssign) {\n this.assignBookPageClassName();\n }\n\n // received new notes\n if (\n prevProps.book.notes &&\n this.props.book.notes &&\n prevProps.book.notes.length !== this.props.book.notes.length &&\n (this.props.book.currentPage === this.props.page.pageNumber ||\n this.props.book.currentPage === this.props.page.pageNumber + 1)\n ) {\n this.forceUpdate();\n }\n // if (prevProps.book.studentNotes.length !== this.props.book.studentNotes.length && (this.props.book.currentPage === this.props.page.pageNumber || this.props.book.currentPage === this.props.page.pageNumber+1)){\n // this.forceUpdate();\n // }\n }\n\n /*\n * Step 6 in loading a book page\n * if we have markups for a page, then deserialize them to render them in the viewer\n */\n // This is where we deserialize the pages of a book\n deserialize() {\n // wait until the rangy highlighters are ready\n if (!this.props.highlighterLeft || !this.props.highlighterRight) {\n if (this.retryCount < 5) {\n setTimeout(this.deserialize, 300);\n this.retryCount++;\n } else {\n console.error(\n 'Unable to deserailize markups, highlighters never became ready'\n );\n }\n\n console.log(\n 'rangy highlighters, not ready. retrying...' + this.retryCount\n );\n return;\n }\n // console.log('deserializing markups', this.props.book.highlights.Content);\n const pageNumber = this.props.page.pageNumber; // this page\n const whichSide =\n this.props.book.currentPage === pageNumber ? 'Left' : 'Right';\n\n // we need to check viewer mode and display student highlights here\n // console.log(`deseralizing markups on page: ${this.props.page.pageNumber} while ${this.props.book.currentPage} is open`);\n if (\n !this.props.location.query.viewerMode ||\n this.props.location.query.viewerMode === 'normal'\n ) {\n if (\n !!this.props.book.highlights &&\n !!this.props.book.highlights.Content &&\n !!this.props.book.highlights.Content[`page${pageNumber}`]\n ) {\n this.props[`highlighter${whichSide}`].deserialize(\n this.props.book.highlights.Content[`page${pageNumber}`]\n );\n }\n // mode: teacher is viewing a student book to see students content and leave notes for a student\n // action: we deseralize the content made by the student\n } else if (\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n if (\n !!this.props.book.studentHighlights &&\n !!this.props.book.studentHighlights.Content &&\n !!this.props.book.studentHighlights.Content[`page${pageNumber}`]\n ) {\n this.props[`highlighter${whichSide}`].deserialize(\n this.props.book.studentHighlights.Content[\n `page${pageNumber}`\n ]\n );\n }\n }\n }\n\n resizePage() {\n const { topToolbarToggleHeight, bottomToolbarHeight } = constants;\n const widthOfArrow = 60;\n let widthOfProjectToolbar = 50;\n let maxContentHeight = 0;\n let maxContentWidth = 0;\n let pageScalePercent = 1;\n let pageContainerWidth = 0;\n let pageContainerHeight = 0;\n let marginLeft = 0;\n\n const pageWidth = this.props.page.width;\n const pageHeight = this.props.page.height;\n const pageNumber = this.props.page.pageNumber; // this page\n const currentPage = this.props.book.currentPage; // the page the viewer is viewing\n\n if (this.props.pagesVisible === 1) {\n maxContentHeight =\n window.innerHeight -\n topToolbarToggleHeight -\n bottomToolbarHeight; // height of window - toolbar and top toggle\n maxContentWidth = window.innerWidth - widthOfArrow * 2; // width of window - space for arrows and blm toolbar\n } else {\n maxContentHeight =\n window.innerHeight -\n topToolbarToggleHeight -\n bottomToolbarHeight; // height of window - toolbar and top toggle\n if (this.props.blmMode) {\n maxContentWidth =\n window.innerWidth / 2 -\n widthOfArrow -\n widthOfProjectToolbar;\n } else {\n maxContentWidth = window.innerWidth / 2 - widthOfArrow;\n }\n }\n const heightDiff = pageHeight - maxContentHeight;\n const widthDiff = pageWidth - maxContentWidth + widthOfArrow;\n\n if (heightDiff < widthDiff) {\n // limit by width\n // console.log('resizing page by width', maxContentHeight, maxContentWidth, this.props.blmMode, pageNumber)\n pageScalePercent = round(\n (maxContentWidth / pageWidth) *\n this.props.bookView.bookManualZoomLevel,\n 3\n );\n\n pageContainerWidth = pageWidth * pageScalePercent;\n pageContainerHeight = pageHeight * pageScalePercent;\n } else {\n // limit by height\n pageScalePercent = round(\n (maxContentHeight / pageHeight) *\n this.props.bookView.bookManualZoomLevel,\n 3\n );\n\n pageContainerWidth = pageWidth * pageScalePercent;\n pageContainerHeight = pageHeight * pageScalePercent;\n // console.log('resizing page', maxContentHeight, maxContentWidth, this.props.blmMode, pageNumber)\n }\n /*\n * Handle assigning the right css classes to the book page\n * if the pageNumber is the same as the pageIndex - this is the left page\n * if this is one page after the pageIndex and pages visible is 2 then this is the right page\n * everything else is invisble.\n * if viewing a single page, then add single page\n *\n * If in BLM mode and single pagesvisible - then left book page should be invisible\n */\n\n if (pageNumber === currentPage) {\n // pageClassName += 'left page-left'\n this.props.updateLeftPageContainer(\n pageContainerWidth,\n pageContainerHeight\n );\n setTimeout(this.deserialize, 300);\n this.props.updateBookScalePercent(pageScalePercent);\n if (this.props.pagesVisible === 1) {\n // pageClassName += ' single-page'\n }\n } else if (pageNumber === currentPage + 1) {\n if (this.props.blmMode || this.props.pagesVisible === 1) {\n // pageClassName += 'invisible-right'\n marginLeft = 0;\n } else {\n // pageClassName += 'right page-right'\n setTimeout(this.deserialize, 300);\n marginLeft = this.props.leftPageContainerWidth + 5; // add 5 for the space inbetween the pages\n }\n } else {\n // pageClassName += 'invisible-left';\n }\n let pageClassName = this.getBookPageClassName(pageNumber, currentPage);\n this.setState({\n pageContainerWidth,\n pageContainerHeight,\n pageClassName,\n marginLeft,\n pageScalePercent\n });\n }\n\n getBookPageClassName(pageNumber, currentPage) {\n let pageClassName = 'page ';\n if (pageNumber === currentPage) {\n pageClassName += 'left page-left';\n // this.props.updateLeftPageContainer(pageContainerWidth, pageContainerHeight);\n if (this.props.pagesVisible === 1) {\n pageClassName += ' single-page';\n }\n } else if (pageNumber === currentPage + 1) {\n if (this.props.blmMode || this.props.pagesVisible === 1) {\n pageClassName += 'invisible-right';\n // marginLeft = 0;\n } else {\n pageClassName += 'right page-right';\n // marginLeft = this.props.leftPageContainerWidth + 5; // add 5 for the space inbetween the pages\n }\n } else {\n pageClassName += 'invisible-left';\n }\n return pageClassName;\n }\n\n /*\n * should this page be visible or not\n */\n assignBookPageClassName() {\n const pageNumber = this.props.page.pageNumber; // this page\n const currentPage = this.props.book.currentPage; // the page the viewer is viewing\n\n if (this.shouldBookPageResize(currentPage, pageNumber)) {\n this.resizePage();\n } else {\n let pageClassName = this.getBookPageClassName(\n pageNumber,\n currentPage\n );\n let marginLeft = 0;\n if (pageClassName === 'page right page-right') {\n marginLeft = this.props.leftPageContainerWidth + 5; // add 5 for the space inbetween the pages\n }\n this.setState({ pageClassName, marginLeft });\n }\n }\n\n /*\n * Does this page need to resize??\n * it needs to resize if it is the left or right page\n * it needs to resize the left page first - currently we are doing this on bookView load, but not when the book changes or pages change\n */\n shouldBookPageResize(currentPage, pageNumber) {\n // we cannot assign the correct amount of leftMargin to the right page until the left page is sized, so wait.\n // the pages skipped by this return will be caught in componentDidUpdate check for a change in leftPageContainerWidth\n if (\n pageNumber !== currentPage &&\n this.props.leftPageContainerWidth === 0\n ) {\n // console.log('left page not sized yet');\n return false;\n }\n if (pageNumber === currentPage || pageNumber === currentPage + 1) {\n return true;\n } else {\n return false;\n }\n }\n\n /*\n * save a note\n */\n saveNote(note) {\n this.props\n .saveBookItem(\n note,\n this.props.user,\n this.props.location.query.viewerMode,\n this.props.book.ID\n )\n .then()\n .catch((error) => {\n console.error('Error saving note', error);\n toastr.error(\n 'Unable to save note. Please try again or contact support.',\n `Error Saving Note`,\n constants.toastrErrorOptions\n );\n });\n const noteID = note.ID || note.TempID;\n this.props.setActiveNote(noteID);\n }\n /*\n * create a note that temporarily only lives in redux\n */\n createTempNote(e, pageNumber) {\n const pageScalePercent = this.state.pageScalePercent;\n const viewerMode = this.props.location.query.viewerMode;\n const noteScalePercent = 1 / pageScalePercent;\n\n /*\n * If we need to add back the onTouchEnd event use this because the layerX is not defined on touch events:\n * onTouchEnd={(e) => this.bookPageTapped(e, pageNumber)}\n * const rect = e.nativeEvent.target.getBoundingClientRect();\n * const layerX = e.changedTouches[0].clientX - rect.left;\n * const layerY = e.nativeEvent.layerY || e.changedTouches[0].clientY - rect.top;\n */\n\n /* get the offset for mobile Safari touch events with Jonathan's solution\n * he even posted it to stackoverflow:\n * https://stackoverflow.com/questions/17130940/retrieve-the-same-offsetx-on-touch-like-mouse-event/46105718#46105718\n */\n\n const layerX = e.nativeEvent.layerX;\n const layerY = e.nativeEvent.layerY;\n const noteX = e.nativeEvent.offsetX || layerX * noteScalePercent;\n const noteY = e.nativeEvent.offsetY || layerY * noteScalePercent;\n let newNote = {\n Type: 3,\n TempID: (Math.random() * 10000 + '').replace('.', ''),\n Page: pageNumber,\n bookID: this.props.book.ID,\n Content: {\n page: `page${pageNumber}`,\n value: '',\n offsetX: noteX, // x coordinate for note icon\n offsetY: noteY // y coordinate for note icon\n }\n };\n // Step 3: determining the current mode we are in\n // This determines what we add to the Note object\n // Mode: teacher viewing a students book\n // Teacher is leaving a note specific to a student (type 4)\n if (\n viewerMode === viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK ||\n viewerMode === viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n newNote = {\n ...newNote,\n Type: 4,\n StudentID: this.props.location.query.studentID,\n TeacherID: this.props.user.ID\n };\n }\n // Mode: teacher leaving notes for a class\n // Teacher is leaving a note specific to a class (type 5)\n if (viewerMode === viewerModes.MODE_TEACHER_CLASS_NOTES) {\n newNote = {\n ...newNote,\n Type: 5,\n ClassID: this.props.location.query.classID,\n TeacherID: this.props.user.ID\n };\n }\n // Mode: teacher leaving a group notes\n // Teacher is leaving a note specific to a group (type 6)\n if (viewerMode === viewerModes.MODE_TEACHER_GROUP_NOTES) {\n newNote = {\n ...newNote,\n Type: 6,\n GroupID: this.props.location.query.groupID,\n TeacherID: this.props.user.ID\n };\n }\n this.saveNote(newNote);\n this.props.startPointing();\n }\n\n deleteNote(note) {\n // prevent teacher's from deleting student notes\n if (!UserAPI.isStudent(this.props.user.RoleID) && note.Type === 3) {\n toastr.error(\n `Only student's can delete their notes.`,\n `Warning`,\n constants.toastrWarningOptions\n );\n return;\n }\n this.props.deleteBookItem(note, this.props.user, this.props.book.ID);\n this.props.setActiveNote('');\n }\n\n bookPageTapped(e, pageNumber) {\n e.persist();\n if (this.props.bookToolbar.allowNotes) {\n this.createTempNote(e, pageNumber);\n } else {\n this.props.pagesTapped(e, pageNumber);\n }\n // close any open notes\n if (this.props.bookView.activeNoteID) {\n // uncomment this to be able to click anywhere and close a note. Issue is that if the user did not type anything, there is not a good way to\n // automatically delete the note.\n // this.props.setActiveNote('');\n }\n }\n\n /*\n * Render the Note HTML\n */\n getNotesHTML() {\n const pageNumber = this.props.page.pageNumber;\n // which notes\n const notes = this.whichNotes();\n return notes.map((note) => {\n if (note.Page === 0) {\n note = Object.assign({}, note, { Page: 1 });\n }\n if (\n note.Page !== this.props.book.currentPage &&\n note.Page !== this.props.book.currentPage + 1\n ) {\n // only render notes within current visible page bounds\n return '';\n } else if (\n this.props.pagesVisible === 1 &&\n note.Page === this.props.book.currentPage + 1\n ) {\n // dont render notes for second page if we are only viewing one\n return '';\n } else if (note.Page !== pageNumber) {\n return '';\n } else {\n const key = note.ID || note.TempID;\n return (\n \n );\n }\n });\n }\n\n /*\n * which notes should we load?\n */\n whichNotes() {\n let combinedNotes = [];\n if (\n !!this.props.book &&\n !!this.props.book.notes &&\n !!this.props.book.notes.length\n ) {\n combinedNotes = [...combinedNotes, ...this.props.book.notes];\n }\n if (\n !!this.props.book &&\n (this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK ||\n this.props.location.query.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM)\n ) {\n const filteredStudentNotes = filter(this.props.book.studentNotes, {\n Type: 3\n });\n combinedNotes = [...combinedNotes, ...filteredStudentNotes];\n }\n if (this.props.notes && !!this.props.notes.length) {\n combinedNotes = [...combinedNotes, ...this.props.notes];\n }\n return combinedNotes;\n }\n escapeHTML(data) {\n return { __html: data };\n }\n\n render() {\n if (!this.props.page.pageReady) {\n return null;\n }\n let pageHTML = this.props.page.pageHTML;\n let key = this.props.page.pageKey;\n const pageNumber = this.props.page.pageNumber; // this page\n\n const pageStyle = {\n width: `${this.state.pageContainerWidth}px`,\n height: `${this.state.pageContainerHeight}px`,\n marginLeft: `${this.state.marginLeft}px`,\n position: 'absolute',\n marginBottom: `${constants.bottomToolbarHeight + 10}`\n }; // the width and height will change as we zoom\n const jpedalStyle = {\n width: `${this.props.page.width}px`,\n height: `${this.props.page.hight}px`,\n position: 'relative',\n display: 'block',\n transform: `translateY(0px) translateX(0px) scale(${this.state.pageScalePercent})`,\n transformOrigin: 'top left'\n }; // the scale will change as we zoom.\n\n const notesLayerStyle = Object.assign({}, jpedalStyle, {});\n\n return (\n \n
\n {this.getNotesHTML()}\n this.bookPageTapped(e, pageNumber)}\n onMouseDown={(e) =>\n this.props.pagesOnMouseDown(e, pageNumber)\n }\n onMouseMove={this.props.pagesOnMouseMove}\n onMouseUp={(e) =>\n this.props.pagesOnMouseUp(e, pageNumber)\n }\n onTouchStart={(e) =>\n this.props.pagesOnMouseDown(e, pageNumber)\n }\n onDragStart={(e) => {\n e.preventDefault();\n }}\n />\n
\n \n );\n }\n}\n\nBookPage.propTypes = {\n pagesOnMouseDown: PropTypes.func.isRequired,\n pagesOnMouseUp: PropTypes.func.isRequired,\n pagesOnMouseMove: PropTypes.func.isRequired,\n pagesVisible: PropTypes.number.isRequired,\n blmMode: PropTypes.bool.isRequired,\n user: PropTypes.object.isRequired,\n highlighterRight: PropTypes.object,\n highlighterLeft: PropTypes.object,\n wordTapped: PropTypes.func.isRequired,\n location: PropTypes.object,\n page: PropTypes.object.isRequired,\n pagesContainerHeight: PropTypes.number.isRequired,\n pagesContainerWidth: PropTypes.number.isRequired,\n updateLeftPageContainer: PropTypes.func.isRequired,\n leftPageContainerWidth: PropTypes.number.isRequired,\n leftPageContainerHeight: PropTypes.number.isRequired,\n updateBookScalePercent: PropTypes.func.isRequired\n};\n\nconst mapStateToProps = (state, ownProps) => {\n return {\n bookToolbar: state.bookToolbar,\n bookView: state.bookView,\n loading: state.ajaxCallsInProgress > 0,\n book: state.book\n };\n};\nexport default connect(mapStateToProps, {\n saveBookItem,\n setActiveNote,\n deleteBookItem,\n startPointing\n})(withRouter(BookPage));\n","/*\n * Pages component is responsible for containing the book and/or project pages.\n * it is also responsible for gestures and changing pages\n * It centers the pages currently only horrizontally ( in the future we would like it to center vertically as well) It positions the left and right arrow buttons.\n * it does this by adding up the width and height of the elements it contains, then centers itself\n * try simply adding up the width of the elements inside and then setting the pages container width.\n * calculate the width of each page by multiplying their bounds by the scalePercent of that page.\n */\n\nimport * as React from 'react';\n\nimport BLM from '../blm/BLM';\nimport BookPage from './BookPage';\nimport { Button } from 'react-bootstrap';\nimport PropTypes from 'prop-types';\nimport { StyledButton } from '../../constants/styledComponents';\nimport UserAPI from '../../api/userAPI';\nimport constants from '../../constants/constants';\nimport icon_arrowleft from '../../images/icon_arrowleft.png';\nimport icon_arrowright from '../../images/icon_arrowright.png';\nimport { viewerModes } from '../../constants/viewerModes';\nimport {map} from 'lodash';\nclass Pages extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n transX: '',\n transY: '',\n scaleX: '',\n scaleY: '',\n pagesContainerWidth: 0,\n pagesContainerHeight: 0,\n leftMarginForArrow: 0,\n dragging: false\n };\n this.handleSwipe = this.handleSwipe.bind(this);\n this.resizePagesContainer = this.resizePagesContainer.bind(this);\n this.pagesOnMouseDown = this.pagesOnMouseDown.bind(this);\n this.pagesOnMouseMove = this.pagesOnMouseMove.bind(this);\n this.pagesOnMouseUp = this.pagesOnMouseUp.bind(this);\n this.shouldShowProject = this.shouldShowProject.bind(this);\n\n this.lastClientX = 0;\n this.lastClientY = 0;\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n // window.addEventListener('resize', this.resizePagesContainer);\n // this.resizePagesContainer();\n }\n\n componentWillUnmount() {\n // window.removeEventListener('resize', this.resizePagesContainer);\n }\n\n /*\n * Step 5 in loading pages container\n *\n */\n componentDidUpdate(prevProps) {\n let shouldResize = false;\n if (\n prevProps.leftPageContainerWidth !==\n this.props.leftPageContainerWidth ||\n prevProps.leftPageContainerHeight !==\n this.props.leftPageContainerHeight\n ) {\n shouldResize = true;\n }\n if (prevProps.pagesVisible !== this.props.pagesVisible) {\n shouldResize = true;\n }\n // we must check for BLM mode changes here because the size and scale do not change when closing a BLM on a wide screen\n if (\n prevProps.blm.Title !== this.props.blm.Title ||\n prevProps.blmMode !== this.props.blmMode\n ) {\n shouldResize = true;\n }\n // if (prevProps.book.ID !== this.props.book.ID || prevProps.book.CurrentPage !== this.props.book.CurrentPage) {\n // this.resizePagesContainer();\n // }\n // if (prevProps.bookScalePercent !== this.props.bookScalePercent){\n // this.resizePagesContainer();\n // }\n // when the project is the right page, we need to resize after it has\n if (prevProps.projectScalePercent !== this.props.projectScalePercent) {\n shouldResize = true;\n }\n if (prevProps.book.bookIsReady !== this.props.book.bookIsReady) {\n shouldResize = true;\n }\n if (prevProps.blm.projectIsReady !== this.props.blm.projectIsReady) {\n shouldResize = true;\n }\n if (shouldResize) {\n this.resizePagesContainer();\n }\n }\n\n /*\n * resize the pages container\n *\n */\n resizePagesContainer() {\n // console.log('resizing pages container')\n // const maxContentHeight = window.innerHeight - 120; // height of window - toolbar and top toggle\n let leftW = 0;\n let leftH = 0;\n // let rightW = this.props.book.bounds[rIndex][0];\n // let rightH = this.props.book.bounds[rIndex][1];\n let rightW = 0;\n let rightH = 0;\n const pagesVisible = this.props.pagesVisible;\n let leftScalePercent = this.props.bookScalePercent; // TODO might rename bookScalePercent to leftPageScalePercent. We are Assuming that the pages of the book are all the same size.\n let rightScalePercent = 0;\n let totalWidthOfPages = 0;\n let tallestPageHeight = 0;\n let widthOfArrow = 50;\n let widthOfProjectToolbar = 50;\n let leftMarginForArrow = 0;\n let gapBetweenPages = 5;\n\n // if blmMode then use the bounds of the BLM instead.\n if (this.props.blmMode && this.props.blm.projectIsReady) {\n if (pagesVisible === 1) {\n leftScalePercent = this.props.projectScalePercent;\n leftW = this.props.blm.bounds[0][0] * leftScalePercent;\n leftH = this.props.blm.bounds[0][1] * leftScalePercent;\n totalWidthOfPages = leftW + widthOfProjectToolbar;\n } else {\n leftW = this.props.leftPageContainerWidth;\n leftH = this.props.leftPageContainerHeight;\n // TODO before determining the rightScalePercent we need to determin if we are limiting by height or width.\n // maybe we calculate both the scalePercent for height and width - then use the greater scaling (resulting in smaller page size)\n rightScalePercent = this.props.projectScalePercent;\n // rightScalePercentWidth = maxContentWidth / rightW;\n rightW = this.props.blm.bounds[0][0] * rightScalePercent;\n rightH = this.props.blm.bounds[0][1] * rightScalePercent;\n totalWidthOfPages =\n leftW + rightW + widthOfArrow + gapBetweenPages;\n leftMarginForArrow = leftW;\n // if the Project is wider than it is tall, switch to single page view automatically\n if (leftW > leftH) {\n this.props.automaticUpdatePagesVisible(1);\n }\n }\n } else if (this.props.book.bookIsReady) {\n if (pagesVisible === 1) {\n leftW = this.props.leftPageContainerWidth;\n leftH = this.props.leftPageContainerHeight;\n totalWidthOfPages = leftW;\n leftMarginForArrow = leftW;\n } else {\n // set both left and right to the leftPageContainer because it is easier and we can assume that both pages of the book are the same size.\n leftW = this.props.leftPageContainerWidth;\n leftH = this.props.leftPageContainerHeight;\n rightW = this.props.leftPageContainerWidth;\n rightH = this.props.leftPageContainerHeight;\n totalWidthOfPages = leftW + rightW + gapBetweenPages;\n leftMarginForArrow = leftW + rightW + gapBetweenPages;\n // if the book page is wider than it is tall, switch to single page view automatically\n // if (leftW > leftH){\n // this.props.automaticUpdatePagesVisible(1);\n // }\n }\n }\n\n tallestPageHeight = leftH > rightH ? leftH : rightH;\n\n this.setState({\n pagesContainerHeight: tallestPageHeight,\n pagesContainerWidth: totalWidthOfPages,\n leftMarginForArrow\n });\n }\n\n handleSwipe(direction) {\n this.props.resetActiveTimeout();\n console.log(`you swiped ${direction}`);\n switch (direction) {\n case 'top':\n break;\n case 'bottom':\n break;\n case 'left':\n this.props.nextPage();\n break;\n case 'right':\n this.props.prevPage();\n break;\n default:\n break;\n }\n }\n\n getBookPage(page, pageID) {\n return (\n \n );\n }\n\n /*\n * do Not show the book if we are in BLMMode and only 1 page visible\n * wait to show the book until prop.pages is defined\n */\n shouldShowBook() {\n let showBook = false;\n if (this.state.pagesContainerWidth === 0) {\n showBook = false;\n }\n if (!this.props.book.bookIsReady) {\n return false;\n }\n\n // wait for the highlighters to be ready - this might block the book page from loading completely\n // if (!this.props.highlighterLeft || !this.props.highlighterRight){\n // return false;\n // }\n if (this.props.blmMode && this.props.pagesVisible === 1) {\n showBook = false;\n } else if (!!this.props.book.cachedPages) {\n showBook = true;\n } else {\n showBook = false;\n }\n return showBook;\n }\n shouldShowProject() {\n let showProject = false;\n if (\n this.props.blmMode &&\n this.props.blm.bounds &&\n this.state.pagesContainerWidth &&\n this.props.blm.projectIsReady\n ) {\n showProject = true;\n }\n return showProject;\n }\n\n /*\n * shouldShowCLoseButton\n */\n shouldShowCloseButton = () => {\n const { RoleID } = this.props.user;\n if (\n // is a student\n UserAPI.isStudent(RoleID) === true ||\n // is generic and not resource mode\n (UserAPI.isGeneric(RoleID) === true &&\n this.props.viewerMode !== viewerModes.MODE_RESOURCE) ||\n // is demo\n UserAPI.isDemo(RoleID) === true\n ) {\n return true;\n } else {\n return false;\n }\n };\n\n /*\n * respond to mouse down\n * if we are not already dragging and the pointer tool is active, then drag scroll\n */\n pagesOnMouseDown(e, pageNumber) {\n e.persist();\n if (!this.state.dragging && this.props.bookToolbar.pointing) {\n this.setState({ dragging: true });\n this.lastClientX = e.clientX || e.touches[0].clientX;\n this.lastClientY = e.clientY || e.touches[0].clientY;\n const tempX = this.lastClientX;\n const tempY = this.lastClientY;\n\n // if they don't move much, then they are highlighting rather than dragging\n setTimeout(() => {\n const moveX = parseInt(tempX - this.lastClientX, 10);\n const moveY = parseInt(tempY - this.lastClientY, 10);\n if (moveX < 30 || moveY < 30) {\n this.setState({ dragging: false });\n }\n }, 200);\n }\n this.props.onMouseDown(e, pageNumber);\n }\n pagesOnMouseMove(e) {\n e.persist();\n if (this.state.dragging) {\n this.pagesContainer.scrollLeft -=\n -this.lastClientX + (this.lastClientX = e.clientX);\n this.pagesContainer.scrollTop -=\n -this.lastClientY + (this.lastClientY = e.clientY);\n this.mouseMove++;\n }\n this.props.onMouseMove(e);\n }\n\n pagesOnMouseUp(e, pageNumber) {\n if (this.state.dragging) {\n this.setState({ dragging: false });\n }\n\n e.persist();\n this.props.onMouseUp(e, pageNumber);\n }\n\n render() {\n let bookReadyClass = this.shouldShowBook() ? 'book-ready' : '';\n let classes = `pages ${this.props.bookToolbar.pagesClassName} ${bookReadyClass}`;\n let showBookArrows = 'block';\n // TODO canvasClassForBLM is defined in Pages as well as BLM - pick one!\n let canvasClassForBlm, bookArrowLeftStyle, bookArrowRightStyle;\n if (this.props.pagesVisible === 1 && this.props.blmMode) {\n showBookArrows = 'none';\n canvasClassForBlm = 'page single-page blm-canvas-container';\n } else if (this.props.pagesVisible === 2 && this.props.blmMode) {\n canvasClassForBlm = 'page blm-page blm-canvas-container';\n }\n if (this.props.blmMode) {\n classes += ' blm-mode';\n }\n if (this.props.pagesVisible === 1) {\n classes += ' one-visible';\n } else {\n classes += ' two-visible';\n }\n bookArrowLeftStyle = { display: `${showBookArrows}` };\n bookArrowRightStyle = {\n display: `${showBookArrows}`,\n marginLeft: `${this.state.leftMarginForArrow}px`\n };\n const pagesContainerStyle = {\n width: `${this.state.pagesContainerWidth}px`,\n height: `${this.state.pagesContainerHeight}px`\n };\n return (\n \n {this.shouldShowCloseButton() && (\n this.props.closeBookView()}\n >\n \n \n )}\n
\n this.props.updatePagesVisible(1)}\n >\n \n \n this.props.updatePagesVisible(2)}\n >\n \n \n
\n
\n
\n \n \"\"\n \n
\n
\n \n \"\"\n \n
\n\n {this.shouldShowBook() &&\n map(this.props.book.cachedPages, (page, pageID) => {\n return this.getBookPage(page, pageID);\n })}\n\n {this.shouldShowProject() && (\n \n )}\n
\n \n );\n }\n}\n\nPages.propTypes = {\n onMouseDown: PropTypes.func.isRequired,\n onMouseUp: PropTypes.func.isRequired,\n onMouseMove: PropTypes.func.isRequired,\n nextPage: PropTypes.func.isRequired,\n prevPage: PropTypes.func.isRequired,\n pagesVisible: PropTypes.number.isRequired,\n blmMode: PropTypes.bool.isRequired,\n user: PropTypes.object.isRequired,\n book: PropTypes.object.isRequired,\n highlighterRight: PropTypes.object,\n highlighterLeft: PropTypes.object,\n wordTapped: PropTypes.func.isRequired,\n location: PropTypes.object,\n updateLeftPageContainer: PropTypes.func.isRequired,\n leftPageContainerWidth: PropTypes.number.isRequired,\n leftPageContainerHeight: PropTypes.number.isRequired,\n bookScalePercent: PropTypes.number.isRequired,\n updateBookScalePercent: PropTypes.func.isRequired,\n updateProjectScalePercent: PropTypes.func.isRequired,\n projectScalePercent: PropTypes.number,\n automaticUpdatePagesVisible: PropTypes.func.isRequired,\n bookToolbar: PropTypes.object.isRequired,\n resetActiveTimeout: PropTypes.func.isRequired,\n viewerMode: PropTypes.string.isRequired\n};\n\nexport default React.forwardRef((props, ref) => {\n return ;\n });;\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD0AAABlCAYAAAD+v+tzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZEMDQ4NEZGRjU0QzExRTY5RUM2RUQ4MzQ0ODNGODQwIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZEMDQ4NTAwRjU0QzExRTY5RUM2RUQ4MzQ0ODNGODQwIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkQwNDg0RkRGNTRDMTFFNjlFQzZFRDgzNDQ4M0Y4NDAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NkQwNDg0RkVGNTRDMTFFNjlFQzZFRDgzNDQ4M0Y4NDAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7G0d7LAAAF50lEQVR42uSc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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD0AAABlCAYAAAD+v+tzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjYzRUU5MTk3RjU0QzExRTY5NjZERjZEQUY4QUIxMzVCIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjYzRUU5MTk4RjU0QzExRTY5NjZERjZEQUY4QUIxMzVCIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NjNFRTkxOTVGNTRDMTFFNjk2NkRGNkRBRjhBQjEzNUIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NjNFRTkxOTZGNTRDMTFFNjk2NkRGNkRBRjhBQjEzNUIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6Y0xUQAAAF1UlEQVR42uSci28URRzH5/a2FCFqSWx8gVZ8gkaJ8f2Iz6BUjfJ3amIAaUuLtajBGORRsbaVaylVEIS2YLHl7sqtv2/2O3FyuZ69x+7OzE3yDcdRdvudz/xmfjM7O7koilSNslnUI9ouul+0TYQfXBZdFv0puiZaFVWUYyWs8V1uHak63zttOhDtEO0RPSN6nJS38N9vkfYF0c+iU6JpV01rao+IXhd9KHqZf69F86roR9HdorLooqjEEHDGNAj30Ww/Ke+o03x7RS/w/90hGhONu2Q6L3pU9LZov+itdWK9utzHn0WH18VO7QJDILLd9GMG4ec2aFiXraLdbNooR0WnXSD9rugz0RsNGtYFpF9hM88ZxFdtJR4YMRy2cB2M60/wWp+KnrK5iYekdE8broWh7TU2+YCxDeIrtlVAwI6s3X3EPoaMlcRDEmlnwdj9KhMaVGqRxG/aUgFBQtdF69nJGN9vG/EwwWv3GMTzHNZA/EbWFRCkcI8+I8af9J20GeMvibpZySA+J7qeFfEgxXtVE8/5TNok/iITGcT4mui8aDFt4kEGFY3Z2weiT7IiHmZguofT0i7ev0ziC2kRD1R25WHO7jTxvM+kTeLPs+JBHQuMBRUvOEa+kjaJI8Y/ZuaW95m0OTvbRrOa+DkVr8NFvprW5SHGOEwPiJbYyXltuocyf6+pJIjbZLq6V69Qi0xkvDZ9l+hpJi0hNSm64rNpM3P7iJ818bLvpu+kIlLPk/hln03rsp1jeI4VgF696LtprK7qxUY9lv+i4sfF3po2ifeT9m0Sv+W7aay17WTKqpeumyLukulavTqo/y36x3fTeGbWJ9pL2ptEZ0SXfDZtEt/Hz2skftN305uZsr7PGAfx0yQe+WraJN5vZG6I7+u+m+7mcPaeEeM/qXgfTOSraZP4XtJGjK8wX/fa9CYaf4e+kLmdqEXcJ9PmfHyLQRxZ2zXfTYPwAyreLRUy5o9zdlbx1XQt4qCNzX5XfTcNb9jMq/fFYSwfQ5P32bQuSFmxBPWXipeWS51gGoSxe2qXih8mFDvBtC7Yz7q7U0jr8qDo2U4zjWWne2E66CDTEYevSieRxszr905r3tiV/EenmI4obNybEJU7hfS86KSKV1a8Jq3Xx+dE31HTvndkukmPiL5S8StV3s6yIs6jZ0Xfig6IRpXxxNNH0xWD8ADjuOzrIkJEcwXG7wH+Waw15/SN8NeiIcZwcb2Jtg+ES5wrg+xBFS8PrdRbXfCB8JxBeLyeYddNR2y+v4mOkfAPTDeVz6bnORwNis5uxLCrpivrEN7wrgRXTaOXPsJxeEI1uA0jdKw5o/lOGoSPqya2UIYOEj5KwpOqyT2joSOEV2jyGyOGm94k64ppvOMx3CphV0xjD8kUE49DKn4e1fI26NDyGJ5lljVE823Z922r6WU24xHOlk6qNm50Dy0lPMMsa4hJiNc7+7EX7FcOS4e4AND2s5FCywgX2EOPkHAih0HZYvoGCZuLeLeTulloCeFzJDzKz4ke9xVaQHiCicdhfi4lfdMsTaP5TtPsKGN4LY0bZ2V6qYrwlGrxvQzbTZdJVcdwQSX0eqEtpkH4LJMOTbiUdq2nabrEGB7k0FRIK4azMr3IsXeYpieyMpyW6RKb8SDTy8QyLVtMg/AZY3o4mSXhNEyXmVoO2ELYNN2VwHUXSPgINWUDYdN0u88dqLCjwgLeWBq5dDOmseu9t03Xw7XGOQYPZzks1SsBx87lNhHGu49fstOaSXJ62Crpg/zlcGZoX5Od2wJXOQ4z8bDWsDYNKqtcqsnTeCOHKEVs0l8whmeU5cdfwzRexf2eTRxPEt5U8VlC3Q0QxnoW1qbP20y4epy+xMlAicL3u/6HeMRh6XMVP26ZVY6d+qzfUTzFpAJPFnDUNU6ZwRE7W9V/u3dQORdJFXs8jvGzMye652ocX6+PuMUJUntovJemEPvzbNInSHfJFcLmkFWr2TYqp8q/AgwApQPHzqiEnkUAAAAASUVORK5CYII=\"","export default __webpack_public_path__ + \"static/media/move_icon.de0c46bd.png\";","import * as React from 'react';\n\nimport {\n Button,\n Col,\n Dropdown,\n FormControl,\n FormGroup,\n Row\n} from 'react-bootstrap';\nimport { StyledButton, StyledDiv } from '../../constants/styledComponents';\n\nimport CommonModal from '../common/CommonModal';\nimport FontAwesome from 'react-fontawesome';\nimport constants from '../../constants/constants';\nimport icon_eraser from '../../images/icon_eraser.png';\nimport icon_hl_green from '../../images/icon_hl_green.png';\nimport icon_hl_orange from '../../images/icon_hl_orange.png';\nimport icon_hl_teal from '../../images/icon_hl_teal.png';\nimport icon_hl_yellow from '../../images/icon_hl_yellow.png';\nimport icon_pen from '../../images/icon_pen.png';\nimport icon_pointer from '../../images/icon_pointer.png';\nimport move_icon from '../../images/move_icon.png';\nimport { Ibook, IbookToolbar, Iuser, IviewerSettings } from '../../models';\nimport { viewerModes } from '../../constants/viewerModes';\n\ninterface Iprops {\n lastPage: ()=>void;\n firstPage: ()=>void;\n nextPage: ()=>void;\n prevPage: ()=>void;\n user: Iuser;\n book: Ibook;\n startHighlighter: (e: any, color: string)=>void;\n startEraser: ()=>void;\n startPointer: ()=>void;\n startNotes: ()=>void;\n openDrawer: ()=>void;\n viewerSettings: IviewerSettings;\n currentPage: number;\n blmMode: boolean;\n pagesVisible: number;\n bookToolbar: IbookToolbar;\n decreaseBookZoom: ()=>void;\n increaseBookZoom: ()=>void;\n resetActiveTimeout: ()=>void;\n viewerMode?: string;\n goToPage: (pageNumber: number, callback?: ()=>void, shouldCheckLeftPageEven?: boolean)=>void;\n bookIsZooming: boolean;\n}\ninterface Istate {\n showGoToPageModal: boolean;\n goToPage: string;\n showBookMarkupTools: boolean;\n}\nconst theme = constants.themeProvider.activeTheme;\n\nclass Toolbar extends React.Component {\n private startedHighlighting = false;\n\n constructor(props: Iprops) {\n super(props);\n\n this.state = {\n showGoToPageModal: false,\n goToPage: '',\n showBookMarkupTools: this.shouldShowMarkupTools()\n \n };\n this.startedHighlighting = false;\n }\n/**\n * @return {boolean}\n */\n shouldShowMarkupTools = (): boolean => {\n const hasCorrectViewerMode = this.props.viewerMode !==\n viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK &&\n this.props.viewerMode !==\n viewerModes.MODE_TEACHER_CLASS_NOTES &&\n this.props.viewerMode !==\n viewerModes.MODE_TEACHER_GROUP_NOTES &&\n this.props.viewerMode !==\n viewerModes.MODE_TEACHER_STUDENT_BLM &&\n this.props.viewerMode !== viewerModes.MODE_RESOURCE;\n\n const {IsEPub} = this.props.book;\n return hasCorrectViewerMode && IsEPub === false;\n }\n\n startHL = (e: any, color: string) => {\n // console.log('starting hl', e.type)\n /*\n * stopPropegation rather than preventDefault because preventDefault on iOS leaves the selected text highlighted\n * and we do not want the text to remain highlighted. Then you can't see the color of the highlight.\n * Unfortunately only dong stopPropagation does not prevent this from being clicked twice... so we have a timeout.\n * after further testing apparently we do not need to preventDefault here... Will keep this around for a bit.\n */\n // if (this.startedHighlighting) return;\n // this.startedHighlighting = true;\n // setTimeout(() => {\n // this.startedHighlighting = false;\n // }, 300)\n\n // if (e.type === 'touchend'){\n // e.stopPropagation();\n // }\n // e.preventDefault();\n\n this.props.startHighlighter(e, color);\n };\n closeGoToPageModal = () => {\n this.setState({ showGoToPageModal: false });\n };\n openGoToPageModal = (e: any) => {\n this.props.resetActiveTimeout();\n e.preventDefault();\n this.setState({ showGoToPageModal: true });\n };\n\n submitGoToPage = () => {\n this.props.resetActiveTimeout();\n this.setState(\n {\n showGoToPageModal: false\n },\n () => {\n this.props.goToPage(parseInt(this.state.goToPage, 10));\n this.setState({ goToPage: '' });\n }\n );\n };\n toggleColors = (isOpen: boolean, e: any) => {\n this.props.resetActiveTimeout();\n if (e) {\n e.stopPropagation();\n e.preventDefault();\n }\n };\n\n handleChange = (e: any) => {\n this.setState({\n goToPage: e.target.value\n });\n };\n\n inputForm = () => {\n return (\n \n \n \n \n \n \n \n );\n };\n\n render() {\n let icon_hl = icon_hl_yellow;\n let toolbarStyle, pointerIcon;\n if (this.props.bookToolbar.highlightColor === 'hl-green') {\n icon_hl = icon_hl_green;\n } else if (this.props.bookToolbar.highlightColor === 'hl-teal') {\n icon_hl = icon_hl_teal;\n }\n if (this.props.bookToolbar.highlightColor === 'hl-orange') {\n icon_hl = icon_hl_orange;\n }\n if (this.props.viewerSettings.showToolbar) {\n toolbarStyle = 'toolbar row';\n } else {\n toolbarStyle = 'toolbar row d-none';\n }\n if (this.props.bookIsZooming) {\n pointerIcon = move_icon;\n } else {\n pointerIcon = icon_pointer;\n }\n const bookToolbar = this.props.bookToolbar;\n const pointerClassName = bookToolbar.pointing\n ? 'item hl-pointer active'\n : 'item hl-pointer';\n const highlighterClassName =\n bookToolbar.highlighting &&\n bookToolbar.highlightColor !== 'hl-strikethrough' &&\n bookToolbar.highlightColor !== 'hl-underline'\n ? `item-child btn btn-light dropdown-toggle hl-highlight active`\n : 'item-child btn btn-light dropdown-toggle hl-highlight';\n const strikeClassName =\n bookToolbar.highlighting &&\n bookToolbar.highlightColor === 'hl-strikethrough'\n ? 'item icon-btn hl-strike active'\n : 'item icon-btn hl-strike';\n const underlineClassName =\n bookToolbar.highlighting &&\n bookToolbar.highlightColor === 'hl-underline'\n ? 'item icon-btn hl-under active'\n : 'item icon-btn hl-under';\n const eraseClassName = bookToolbar.erasing\n ? 'item hl-erase active'\n : 'item hl-erase';\n let notesClassName = bookToolbar.allowNotes\n ? 'item hl-notes active'\n : 'item hl-notes';\n if (this.props.book.IsEPub){\n notesClassName = 'hide'\n }\n // hide the bottom toolbar if in single page Project mode\n if (this.props.blmMode && this.props.pagesVisible === 1) {\n return null;\n }\n return (\n \n
\n
\n {this.state.showBookMarkupTools && (\n \n \n \"\"\n \n \n this.toggleColors(isOpen, e)\n }\n drop=\"up\"\n >\n \n \"\"\n \n \n {\n this.startHL(e, 'hl-yellow');\n }}\n onTouchEnd={(e: any) => {\n this.startHL(e, 'hl-yellow');\n }}\n />\n {\n this.startHL(e, 'hl-orange');\n }}\n onTouchEnd={(e: any) => {\n this.startHL(e, 'hl-orange');\n }}\n />\n {\n this.startHL(e, 'hl-green');\n }}\n onTouchEnd={(e: Event) => {\n this.startHL(e, 'hl-green');\n }}\n />\n {\n this.startHL(e, 'hl-teal');\n }}\n onTouchEnd={(e: any) => {\n this.startHL(e, 'hl-teal');\n }}\n />\n \n \n \n this.props.startHighlighter(\n e,\n 'hl-strikethrough'\n )\n }\n onTouchEnd={(e) =>\n this.props.startHighlighter(\n e,\n 'hl-strikethrough'\n )\n }\n role=\"button\"\n type=\"button\"\n >\n \n \n \n this.props.startHighlighter(\n e,\n 'hl-underline'\n )\n }\n onTouchEnd={(e) =>\n this.props.startHighlighter(\n e,\n 'hl-underline'\n )\n }\n role=\"button\"\n type=\"button\"\n >\n \n \n \n \"\"\n \n \n )}\n {/* notes button stays outside the span above for teachers to add notes */}\n \n \"\"\n \n
\n
\n {/*\n \n \"\"\n \n \n \n \n \n \n \n */}\n
\n {\n this.props.resetActiveTimeout();\n this.props.decreaseBookZoom();\n }}\n >\n \n \n {\n this.props.resetActiveTimeout();\n this.props.increaseBookZoom();\n }}\n >\n \n \n
\n
\n \n \n \n \n \n \n \n {this.props.currentPage}\n {!this.props.blmMode &&\n this.props.pagesVisible !== 1 &&\n '-' + (this.props.currentPage + 1)}\n /{this.props.book.pagecount}\n \n \n \n \n \n \n \n
\n this.closeGoToPageModal()}\n submit={this.submitGoToPage}\n />\n \n );\n }\n}\n\nexport default Toolbar;\n","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjU2QTczNkYxQkQ1MTFFNzhEQ0E4NTM4MDY1RjQ2MjMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjU2QTczNkUxQkQ1MTFFNzhEQ0E4NTM4MDY1RjQ2MjMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RTZEMDE2OEUxOEFFMTFFNzlCM0ZDNzE0NzI1Rjk2RTQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RTZEMDE2OEYxOEFFMTFFNzlCM0ZDNzE0NzI1Rjk2RTQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4Z7xmGAAASrUlEQVR42uSd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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzAzODk2OEExQkQ1MTFFNzhCNjdFMUJCQUJBRTJEM0UiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzAzODk2ODkxQkQ1MTFFNzhCNjdFMUJCQUJBRTJEM0UiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkIwQTQ3NEYxOEFFMTFFN0FFRDVFRkQ4NzZCM0Y5NjYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkIwQTQ3NTAxOEFFMTFFN0FFRDVFRkQ4NzZCM0Y5NjYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5zgoaNAAAQSElEQVR42uxc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\"","import rangy from 'rangy/lib/rangy-core';\nimport 'rangy/lib/rangy-textrange';\nimport 'rangy/lib/rangy-serializer';\nimport 'rangy/lib/rangy-selectionsaverestore';\nimport 'rangy/lib/rangy-highlighter';\nimport 'rangy/lib/rangy-classapplier';\n\nconst testForSimilarMarkup = (element, highlightColor) => {\n if (\n element.className.includes(highlightColor) &&\n element.textContent !== ' '\n ) {\n // alert('found similar')\n return true;\n } else {\n return false;\n }\n};\n\n// search through all the possible matches, then merge them\nconst findSimilarMarkups = (target, whichSide, pid, highlightColor) => {\n let range = rangy.createRange();\n let currentRange = rangy.createRange();\n let willMergeMarkups = false;\n currentRange.selectNodeContents(target);\n range.selectNode(target); // start with the initial selection of the word\n findPreviousMarkups(target); // increase the range before this markup?\n findNextMarkups(target); // increase the selection range after this markup?\n if (willMergeMarkups) {\n range.select();\n }\n\n function findPreviousMarkups(element) {\n let didFindElement = false; // keep track of if we found one\n let foundElement;\n\n // find elements in non-audio books\n try {\n if (\n testForSimilarMarkup(\n element.previousElementSibling,\n highlightColor\n )\n ) {\n didFindElement = true;\n foundElement = element.previousElementSibling;\n }\n } catch (error) {}\n // find elements that are on different lines\n try {\n if (\n !foundElement &&\n element.parentNode.children.length === 1 &&\n element.parentNode.className.includes('t') &&\n testForSimilarMarkup(\n element.parentNode.previousElementSibling.children[0],\n highlightColor\n )\n ) {\n didFindElement = true;\n foundElement =\n element.parentNode.previousElementSibling.children[0];\n }\n } catch (error) {}\n // find elements in audio books - they are buried in an additional span occassionaly\n try {\n if (\n !foundElement &&\n element.parentNode.children.length === 1 &&\n element.parentNode.className.includes('t') &&\n testForSimilarMarkup(\n element.parentNode.previousElementSibling.children[0]\n .children[0],\n highlightColor\n )\n ) {\n didFindElement = true;\n foundElement =\n element.parentNode.previousElementSibling.children[0]\n .children[0];\n }\n } catch (error) {}\n\n // if we found something, then take that something and see if there is another similar markup before that\n if (didFindElement) {\n willMergeMarkups = true;\n range.setStart(foundElement);\n\n findPreviousMarkups(foundElement);\n }\n }\n\n function findNextMarkups(element) {\n let didFindElement = false; // keep track of if we found one\n let foundElement;\n try {\n if (\n testForSimilarMarkup(element.nextElementSibling, highlightColor)\n ) {\n didFindElement = true;\n foundElement = element.nextElementSibling;\n }\n } catch (error) {}\n\n try {\n if (\n !foundElement &&\n element.parentNode.children.length === 1 &&\n element.parentNode.className.includes('t') &&\n testForSimilarMarkup(\n element.parentNode.nextElementSibling.children[0],\n highlightColor\n )\n ) {\n didFindElement = true;\n foundElement =\n element.parentNode.nextElementSibling.children[0];\n }\n } catch (error) {}\n try {\n if (\n !foundElement &&\n element.parentNode.children.length === 1 &&\n element.parentNode.className.includes('t') &&\n testForSimilarMarkup(\n element.parentNode.nextElementSibling.children[0]\n .children[0],\n highlightColor\n )\n ) {\n didFindElement = true;\n foundElement =\n element.parentNode.nextElementSibling.children[0]\n .children[0];\n }\n } catch (error) {}\n // if we found something, then take that something and see if there is another similar markup AFTER that\n if (didFindElement) {\n willMergeMarkups = true;\n range.setEnd(\n foundElement.firstChild,\n foundElement.firstChild.length\n );\n\n findNextMarkups(foundElement);\n }\n }\n};\n\nexport default findSimilarMarkups;\n","/*\n * Eventually the BookView component will only be responsible for\n */\n\nimport 'rangy/lib/rangy-textrange';\nimport 'rangy/lib/rangy-serializer';\nimport 'rangy/lib/rangy-selectionsaverestore';\nimport 'rangy/lib/rangy-highlighter';\nimport 'rangy/lib/rangy-classapplier';\n\n// import 'react-jplayer/src/less/skins/sleek.less';\n// Styles Play/Pause/Mute etc when icons () are used for them\n// import 'react-jplayer/src/less/controls/iconControls.less';\n\nimport { viewerModes } from '../../constants/viewerModes';\nimport EpubView from './EpubView';\nimport React, { Component } from 'react';\nimport {\n automaticUpdatePagesVisible,\n decreaseBookZoom,\n increaseBookZoom,\n resetBookView,\n setActiveNote,\n updateBookScalePercent,\n updateLeftPageContainer,\n updatePagesVisible,\n updatePendingItem,\n updateProjectScalePercent\n} from '../../actions/bookViewActions';\nimport {\n cacheBookPage,\n deleteBookItem,\n downloadSpeech,\n getBookByID,\n getBookItems,\n getBookItemsByStudentID,\n getBookPage,\n getBookProperties,\n searchBookBagBooks,\n getSpeechMarks,\n getTeacherBookItems,\n nextPage,\n prevPage,\n resetCachedBookPages,\n saveBookItem,\n setBookReady,\n updateBookStatus,\n updateCurrentPage,\n} from '../../actions/bookActions';\nimport {\n emptyBLMs,\n getAssignedBLMs,\n getBLMByID,\n getBLMItems,\n getBLMProperties,\n getBLMStatus,\n getStudentsBLMItems,\n getTeachersComment,\n getTemplateItems,\n setProjectReady\n} from '../../actions/blmActions';\nimport { hashHistory, withRouter } from 'react-router';\nimport {\n manualAjaxEnd,\n manualAjaxStart\n} from '../../actions/ajaxStatusActions';\nimport {\n startErasing,\n startHighlighting,\n startMoving,\n startNotes,\n startPointing,\n startStriking,\n startUnderlining\n} from '../../actions/bookToolbarActions';\n\nimport BlmAPI from '../../api/blmAPI';\nimport CommonModal from '../common/CommonModal';\nimport Drawer from './Drawer';\nimport { HeaderContainer } from '../header/HeaderContainer';\nimport Loading from '../common/Loading';\nimport Pages from './Pages';\nimport Toolbar from './Toolbar';\nimport UserAPI from '../../api/userAPI';\nimport config from '../../api/config';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants';\nimport { debounce } from 'lodash';\nimport findSimilarMarkups from '../../utilities/MarkupMergerUtility';\nimport rangy from 'rangy/lib/rangy-core';\nimport { removeQuery } from '../../vendor/utils-router';\nimport { toastr } from 'react-redux-toastr';\nimport { userLogout } from '../../actions/userActions';\nimport { requireSignIn } from '../../routes';\nimport $ from 'jquery';\nimport {\n BOOK_FIRST_PAGE,\n BOOK_LAST_PAGE,\n BOOK_NEXT_PAGE,\n BOOK_PREV_PAGE\n} from './events';\nimport { viewerDrawerTypeEnum } from '../../models-enums';\n\nwindow.rangy = rangy;\n\nclass BookView extends Component {\n highlights;\n activeTimeout;\n activeWarningTimeout;\n\n constructor(props) {\n super(props);\n this.state = {\n highlighterLeft: null,\n highlighterRight: null,\n EPubUrl: '',\n blmHtml: {},\n viewerSettings: {\n showDrawer: false,\n showDrawerHighlightsButton: true,\n showDrawerNotesButton: true,\n drawerType: viewerDrawerTypeEnum.notes,\n highlightingMouseDown: false,\n header: { visible: false, class: 'fa fa-angle-double-down' },\n showToolbar: true,\n showHeader: true,\n highlightingPageNumber: 1,\n loadedProjectAssignmentID: '' // keep track of what Project Assignment the blmData belongs too so we know when to re-load it\n },\n showSaveProjectConfirm: false,\n saveProjectSubmit: () => {\n console.error('saveProjectModal function not replaced');\n }\n };\n this.pagesRef = React.createRef();\n\n this.superDebouncedMarkupUpdate = debounce(this.updateMarkups, 8000);\n this.debouncedMarkupUpdate = debounce(this.updateMarkups, 1000);\n\n // lets store moseMove on the BookView class because we are changing it very quickly as the mouse moves.\n this.mouseMove = 0;\n\n // let speechMarkRaw = constants.testSpeechMarkRaw;\n // this.speechMarksData = speechMarkRaw.split(/\\n/);\n this.highlightedSpeechMarks = [];\n this.speechMarkIndex = 0;\n }\n\n componentDidMount() {\n console.info('bookview mounted');\n if (requireSignIn(this.props.user, this.props.location)) {\n return;\n }\n\n // initialize all rangy stuff\n rangy.init();\n this.setState({\n highlighterRight: this.createHighlighter(),\n highlighterLeft: this.createHighlighter()\n });\n // open the header for testing\n // this.toggleHeader();\n\n /*\n * Initial Viewer Settings\n */\n let initialViewerSettings = {};\n\n // should we show the header?\n initialViewerSettings.showHeader = UserAPI.canAccessBook(\n this.props.user.RoleID\n );\n\n // load list of BLMs and Books?\n if (UserAPI.isStudent(this.props.user.RoleID)) {\n // this.initBooks(); // TODO fix the action in here... it expects a lot of params\n this.initBLMs();\n } else {\n // load blm if you are not a student\n if (this.props.blmMode) {\n if (\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n this.loadBLM(\n this.props.projectAssignmentID,\n this.props.blmID\n ).then(() => {\n this.props.setProjectReady(true);\n $('#pages').fadeTo('fast', 1.0);\n // if blmID and No bookID then we will only display a single page blm\n if (!this.props.bookID) {\n this.props.updatePagesVisible(1);\n }\n });\n } else {\n this.loadBLM('', this.props.blmID).then(() => {\n this.props.setProjectReady(true);\n $('#pages').fadeTo('fast', 1.0);\n // if blmID and No bookID then we will only display a single page blm\n if (!this.props.bookID) {\n this.props.updatePagesVisible(1);\n }\n });\n }\n }\n if (\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_CLASS_NOTES ||\n this.props.viewerMode === viewerModes.MODE_TEACHER_GROUP_NOTES\n ) {\n initialViewerSettings.showDrawerHighlightsButton = false;\n }\n }\n\n initialViewerSettings.hideDrawer = this.shouldHideDrawer();\n\n this.updateViewerSettings(initialViewerSettings, () => {\n console.log('updated initial viewer settings');\n\n // Load Book?\n if (this.props.bookID && this.props.bookID.length) {\n if (this.props.book.ID !== this.props.bookID) {\n this.props.resetCachedBookPages();\n this.loadBook(this.props.bookID).then(() => {\n setTimeout(() => {\n this.props.setBookReady(true);\n // check if the left page is supposed to be even\n this.goToPage(this.props.currentPage, false, false);\n }, 100);\n $('#pages').fadeTo('fast', 1.0);\n });\n return;\n }\n this.loadBook(this.props.bookID).then(() => {\n setTimeout(() => {\n this.props.setBookReady(true);\n // check if the left page is supposed to be even\n this.goToPage(this.props.currentPage, false, false);\n }, 100);\n $('#pages').fadeTo('fast', 1.0);\n });\n }\n });\n\n // listen for active user\n // document.addEventListener(\n // 'visibilitychange',\n // this.handleVisibilityChange,\n // false\n // );\n // this.resetActiveTimeout();\n this.setupEventHandlers();\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.bookIsZooming !== this.props.bookIsZooming) {\n if (this.props.bookIsZooming) {\n this.props.startMoving();\n } else {\n this.props.startPointing(); // this is a little strange to zoom to normal and then it switches to pointer, but cant think of simple solution\n }\n }\n // if the pages visible changes we need to check if the left page is supposed to be even\n // unless the book or the blm is not ready yet\n if (\n prevProps.pagesVisible !== this.props.pagesVisible &&\n (this.props.blm.projectIsReady || this.props.book.bookIsReady)\n ) {\n this.goToPage(this.props.book.currentPage);\n }\n\n // TODO can we improve this flow by grouping the things to do when a book or blm loads here?\n // if (prevProps.blm.projectIsReady !== this.props.blm.projectIsReady && this.props.blm.projectIsReady){\n // $(\"#pages\").fadeTo(\"fast\", 1.0);\n // }\n // if (prevProps.book.bookIsReady !== this.props.book.bookIsReady && this.props.book.bookIsReady){\n // $(\"#pages\").fadeTo(\"fast\", 1.0);\n // }\n\n if (prevProps.book.ID && !this.props.book.ID) {\n console.log(\n 'book has been reset in bookView, redirecting to bookbag'\n );\n this.goToBag();\n }\n }\n\n componentWillUnmount() {\n setTimeout(() => {\n this.removeAllHighlights();\n }, 100);\n if (this.props.blms.length > 0) {\n this.props.emptyBLMs();\n }\n this.superDebouncedMarkupUpdate.cancel();\n this.debouncedMarkupUpdate.cancel();\n // document.removeEventListener(\n // 'visibilitychange',\n // this.handleVisibilityChange\n // );\n // if (this.activeTimeout) {\n // clearTimeout(this.activeTimeout);\n // }\n // if (this.activeWarningTimeout) {\n // clearTimeout(this.activeWarningTimeout);\n // }\n // if (this.handleTimeoutCloseBook) {\n // clearTimeout(this.handleTimeoutCloseBook);\n // }\n this.removeEventHandlers();\n }\n\n setupEventHandlers() {\n // listen for renewedAzureToken\n document.addEventListener(\n 'renewedAzureToken',\n this.handleRenewedAzureToken\n );\n document.addEventListener('keyup', this.handleKeyPress, false);\n }\n\n removeEventHandlers() {\n document.removeEventListener(\n 'renewedAzureToken',\n this.handleRenewedAzureToken\n );\n document.removeEventListener('keyup', this.handleKeyPress, false);\n }\n\n handleKeyPress = ({ key }) => {\n key && key === 'ArrowRight' && this.nextPage();\n key && key === 'ArrowLeft' && this.prevPage();\n };\n\n /*\n * shouldHideDrawer\n * don't show the left drawer in resource mode or when viewing an ePub\n */\n shouldHideDrawer = () => {\n return (\n this.props.viewerMode === viewerModes.MODE_RESOURCE ||\n this.props.book.IsEPub === true\n );\n };\n\n handleRenewedAzureToken = () => {\n console.log('handling renewed Azure token');\n\n // if( config.System === 'web' && this.props.isOnline){\n // this.props.resetCachedBookPages();\n // this.getBookHTMLPages(this.props.book, this.props.currentPage, true);\n // } else if (config.System !== 'web' && this.props.isOnline){\n\n if (this.props.isOnline) {\n // if on a device we need to re-download the entire book\n this.props.resetCachedBookPages();\n this.loadBook(this.props.bookID).then(() => {\n setTimeout(() => {\n this.props.setBookReady(true);\n // check if the left page is supposed to be even\n this.goToPage(this.props.currentPage);\n }, 100);\n $('#pages').fadeTo('fast', 1.0);\n });\n } else {\n toastr.error(\n `No internet connection.`,\n `Error Loading Book`,\n constants.toastrErrorOptions\n );\n }\n };\n\n // handleVisibilityChange = () => {\n // if (document.hidden) {\n // this.activeTimeout = setTimeout(\n // this.handleTimeoutWarning,\n // constants.closeBookTimeout\n // );\n // console.log('view hidden');\n // } else {\n // console.log('view visible');\n // clearTimeout(this.activeTimeout);\n // clearTimeout(this.activeWarningTimeout);\n // }\n // };\n\n // handleTimeoutWarning = () => {\n // toastr.warning(\n // `Still there?`,\n // `We will be closing the book in 30 seconds due to inactivity`,\n // {\n // ...constants.toastrWarningOptions,\n // id: 'countdownWarning',\n // timeOut: constants.closeBookWarning,\n // onCloseButtonClick: this.resetActiveTimeout\n // }\n // );\n // this.activeWarningTimeout = setTimeout(\n // this.handleTimeoutCloseBook,\n // constants.closeBookWarning\n // );\n // clearTimeout(this.activeTimeout);\n // };\n\n // handleTimeoutCloseBook = () => {\n // clearTimeout(this.activeWarningTimeout);\n // this.props.updateBookStatus(\n // this.props.book.ID,\n // this.props.book.currentPage,\n // this.props.book.pagecount,\n // true,\n // this.props.blmMode\n // );\n // this.closeBookView();\n // toastr.warning(\n // '',\n // \"We have closed the book due to inactivity. Don't worry, we put in a bookmark for ya.\",\n // { ...constants.toastrWarningOptions, timeOut: 0 }\n // );\n // };\n\n resetActiveTimeout = () => {\n console.log('resetting countdown timeout');\n // clearTimeout(this.activeTimeout);\n // clearTimeout(this.activeWarningTimeout);\n // this.activeTimeout = setTimeout(\n // this.handleTimeoutWarning,\n // constants.closeBookTimeout\n // );\n // // toastr.remove('countdownWarning') // not sure why this did not work.\n // toastr.removeByType('warning');\n };\n\n /*\n * function to call from child components to update viewerSettings\n * newViewerSettings = some subset of the viewer settings\n * object that you want to update.\n * callback - setState is asynchronus, so I am allowing an optional callback\n * in case we need to do something AFTER the update completes\n */\n updateViewerSettings = (newViewerSettings, callback) => {\n // let now = new Date().getTime();\n // console.error('UPDATING VIEWER SETTINGS: old, new', now ,this.state.viewerSettings, newViewerSettings );\n\n let viewerSettings = Object.assign(\n {},\n this.state.viewerSettings,\n newViewerSettings\n );\n return this.setState({ viewerSettings }, callback);\n };\n\n /*\n * Gets an array of books\n */\n initBooks = () => {\n if (this.props.books.length === 0) {\n // check if we are online\n if (!this.props.isOnline) {\n // if we do not have books and we are offline, we need to show an error\n console.warn('unable to load bookview while offline');\n toastr.error(\n `No internet connection.`,\n `Error Loading Book`,\n constants.toastrErrorOptions\n );\n return;\n }\n this.props.searchBookBagBooks();\n }\n };\n\n initBLMs = () => {\n console.log('initializing BLMs');\n if (!this.props.isOnline) {\n console.log('offline, skipping getAssigndBlms');\n return;\n }\n this.props\n .getAssignedBLMs(this.props.bookID, this.props.user)\n .then((blms) => {\n // Load BLM?\n if (this.props.projectAssignmentID && this.props.blmMode) {\n this.loadBLM(\n this.props.projectAssignmentID,\n this.props.blmID\n );\n\n // if blmID and No bookID then we will only display a single page blm\n // commented out for now as a student never views a blm by itself\n // if (!this.props.bookID) {\n // initialViewerSettings.pagesVisible = 1;\n // }\n }\n })\n .catch((error) => {\n console.error('Error searching for blm', error);\n if (this.props.isOnline) {\n toastr.error(\n 'Error searching for blm',\n `Error`,\n constants.toastrErrorOptions\n );\n }\n });\n };\n\n /*\n ***************************************** RANGY HIGHLIGHTER ***************************************************\n /*\n\n /*\n * create Rangy highlighter objects for the various markup types and colors\n */\n createHighlighter = () => {\n var newHL = rangy.createHighlighter(this.pagesRef.current, 'TextRange');\n newHL.addClassApplier(rangy.createClassApplier('hl-yellow'));\n newHL.addClassApplier(rangy.createClassApplier('hl-teal'));\n newHL.addClassApplier(rangy.createClassApplier('hl-green'));\n newHL.addClassApplier(rangy.createClassApplier('hl-orange'));\n newHL.addClassApplier(rangy.createClassApplier('hl-underline'));\n newHL.addClassApplier(rangy.createClassApplier('hl-strikethrough'));\n return newHL;\n };\n\n removeAllHighlights = () => {\n this.state.highlighterLeft.removeAllHighlights();\n this.state.highlighterRight.removeAllHighlights();\n };\n\n /*\n * pass in which side then make sure all selections are safe before saving them\n * we have to have two highlighters because this saves all the highlights for the highlighter.\n * this function is performance intensive and blocking\n */\n serializePageMarkups = (side) => {\n let self = this;\n let serializedText = this.state[`highlighter${side}`].serialize({\n serializeHighlightText: true\n });\n /* if we find a \" or a -webkit-transform throw an error */\n if (\n serializedText.indexOf('\"') !== -1 &&\n serializedText.indexOf('-webkit-transform') !== -1\n ) {\n console.error('unable to serialize markup', serializedText);\n alert('Error selecting text, please try again');\n self.state[`highlighter${side}`].unhighlightSelection();\n throw new Error('unable to serialize text');\n } else {\n return serializedText;\n }\n };\n\n /*\n ****************************************************** BOTTOM TOOLBAR *********************************************\n */\n startNotes = (e) => {\n this.resetActiveTimeout();\n if (e) {\n e.preventDefault();\n }\n if (\n !this.props.isOnline &&\n !UserAPI.isStudent(this.props.user.RoleID)\n ) {\n // if we do not have books and we are offline, we need to show an error\n console.warn('unable to create note while offline');\n toastr.error(\n `No internet connection.`,\n `Error Saving Note`,\n constants.toastrErrorOptions\n );\n return;\n }\n this.props.startNotes(true);\n };\n startHighlighter = (e, hlClass) => {\n this.resetActiveTimeout();\n // if this is a touch then we highlight what is selected then turn off the highlight mode.\n // as of 6/2018 we are no longer doing touch highlight mode\n // if (e.type === 'touchend'){\n // this.touchHighlight(e, hlClass);\n // } else {\n this.clickHighlight(e, hlClass);\n // }\n };\n\n // this function is being depricated\n touchHighlight = (e, hlClass) => {\n this.resetActiveTimeout();\n console.log('touch highlight');\n e.preventDefault();\n\n // make sure they selected some text first\n if (window.getSelection().type === 'None') {\n toastr.warning(\n `When using touch, please select text first.`,\n ``,\n constants.toastrWarningOptions\n );\n return;\n }\n this.doTouchHighlight(hlClass);\n };\n\n clickHighlight = (e, hlClass) => {\n this.resetActiveTimeout();\n console.log('started click highlighter ' + hlClass);\n this.props.startHighlighting(true, hlClass);\n };\n\n startEraser = () => {\n this.resetActiveTimeout();\n console.log('started eraser');\n this.props.startErasing(true);\n };\n\n startPointer = () => {\n this.resetActiveTimeout();\n console.log('started pointer');\n this.props.startPointing();\n };\n\n /*\n * Book Navigation (first, last, next, previous)\n */\n firstPage = (e) => {\n this.resetActiveTimeout();\n if (e) e.preventDefault();\n this.goToPage(1);\n document.dispatchEvent(new Event(BOOK_FIRST_PAGE));\n };\n\n lastPage = (e) => {\n this.resetActiveTimeout();\n if (e) e.preventDefault();\n this.goToPage(this.props.book.totalPage);\n document.dispatchEvent(new Event(BOOK_LAST_PAGE));\n // if (this.props.currentPage !== this.props.book.pagecount) {\n // const pi = this.props.book.pagecount - this.props.pagesVisible + 1;\n // this.goToPage(pi);\n // }\n };\n\n nextPage = (e) => {\n this.resetActiveTimeout();\n if (e) e.preventDefault();\n \n let pagesToChange = 1;\n \n if (!this.props.blmMode && this.props.pagesVisible === 2) {\n pagesToChange = 2;\n }\n \n if (this.props.currentPage >= this.props.totalPage) {\n return;\n }\n this.goToPage(this.props.currentPage + pagesToChange);\n document.dispatchEvent(new Event(BOOK_NEXT_PAGE));\n };\n\n prevPage = (e) => {\n this.resetActiveTimeout();\n if (e) e.preventDefault();\n let pagesToChange = 1;\n\n if (!this.props.blmMode && this.props.pagesVisible === 2) {\n pagesToChange = 2;\n }\n\n if (this.props.currentPage <= 0) {\n return;\n }\n this.goToPage(this.props.currentPage - pagesToChange);\n document.dispatchEvent(new Event(BOOK_PREV_PAGE));\n };\n\n /*\n ************************************************* CLICK SWIPE AND DRAG LISTENERS *****************************************\n */\n\n // TODO create a get relative position util function. accepts pageW, pageH, layerX, layerY, offsetX, offsetY, scaleX, scaleY then returns offsetX and offsetY\n\n /*\n * respond to page taps.\n */\n pagesTapped = (e, pageNumber) => {\n this.resetActiveTimeout();\n // console.log('page tapped: ', e.type);\n if (\n e.target.className.includes('tappable') ||\n e.target.parentNode.className.includes('tappable')\n ) {\n this.wordTapped(e, pageNumber);\n }\n\n // on mobile Safari we use the e.originalEvent.layerX (with react e.nativeEvent.layerX) from the touch event, but on Chrome, touch event's don't have this.\n // we don't need it on desktop browsers because they will trigger a click event right after the touch event.\n if (e.type === 'touchend' && !e.nativeEvent.layerX) {\n return;\n }\n };\n\n updateMarkups = (whichSide, pid) => {\n this.updateHighlights(this.serializePageMarkups(whichSide), pid);\n rangy.getSelection().removeAllRanges(); // this only slightly helps to be debounced and we call it unnecessarily when erasing\n this.props.updatePendingItem(false);\n };\n\n /*\n * respond to word taps\n */\n wordTapped = (e, pageNumber) => {\n this.resetActiveTimeout();\n // console.log('word tapped', e.type);\n // if (config.System === 'mobile'){\n // this.props.manualAjaxStart();\n // }\n // console.log($(e.currentTarget).text(), e);\n // console.log(this.state.highlighter);\n // console.log($('.pages .left').attr('id'));\n let erasing = this.props.bookToolbar.erasing;\n const pid = `page${pageNumber}`;\n const whichSide =\n this.props.book.currentPage === pageNumber ? 'Left' : 'Right';\n\n if (this.props.bookToolbar.highlighting) {\n /*\n * Before we added user-select: all to the .t class we had to manually highlight the\n * characters before applying the highlights with the code below:\n */\n // let sel = rangy.getSelection();\n // sel.selectCharacters(e.target, 0, e.target.textContent.length);\n\n /*\n * find similar markups and merge them in order to help iOS users tap to highlight\n */\n findSimilarMarkups(\n e.target,\n whichSide,\n pid,\n this.props.bookToolbar.highlightColor\n );\n\n // console.log('word tapped, highlighting selection', e.target.textContent.length, sel);\n this.state[`highlighter${whichSide}`].highlightSelection(\n this.props.bookToolbar.highlightColor,\n {\n containerElementId: pid\n }\n );\n\n // this is blocking rendering the view, so we wait for view to show highlight before serializing\n // on iOS we need a much longer delay\n this.props.updatePendingItem(true);\n // if (config.System === 'mobile'){\n // this.superDebouncedMarkupUpdate(whichSide, pid);\n // } else {\n this.debouncedMarkupUpdate(whichSide, pid);\n // }\n } else if (this.props.bookToolbar.erasing) {\n /*\n * since a word was tapped, we must manually\n * highlight the characters before applying highlights. only if it is not Mobile\n * we do not support highlighting a single word on mobile. when on mobile we are erasing the entire selection.\n */\n // var sel = rangy.getSelection();\n // sel.selectCharacters(e.target, 0, e.target.textContent.length);\n this.state[`highlighter${whichSide}`].unhighlightSelection();\n\n // this is blocking rendering the view, so we wait for view to show highlight before serializing\n // on iOS we need a much longer delay\n this.props.updatePendingItem(true);\n // if (config.System === 'mobile'){\n // this.superDebouncedMarkupUpdate(whichSide, pid);\n // } else {\n this.debouncedMarkupUpdate(whichSide, pid);\n // }\n\n // turn off erasing\n erasing = false;\n }\n this.updateViewerSettings({ highlighting: false }, () => {\n // if it was a touch event and we just erased something then automatically turn off erasing\n // commented out while we are only doing single tap markups\n if (e.type === 'touchend' && !erasing) {\n // this.startPointer();\n }\n });\n this.props.manualAjaxEnd();\n };\n\n /*\n * respond to mouse down\n */\n onMouseDown = (e, pageNumber) => {\n this.updateViewerSettings({\n highlightingMouseDown: true,\n highlightingPageNumber: pageNumber\n });\n this.mouseMove = 0;\n };\n\n /*\n * respond to mouse up\n */\n onMouseUp = (e, pageNumber) => {\n const pid = `page${pageNumber}`;\n const whichSide =\n this.props.book.currentPage === pageNumber ? 'Left' : 'Right';\n var sel = rangy.getSelection();\n if (\n this.props.bookToolbar.highlighting &&\n this.state.viewerSettings.highlightingMouseDown &&\n this.mouseMove > 1\n ) {\n this.state[`highlighter${whichSide}`].highlightSelection(\n this.props.bookToolbar.highlightColor,\n {\n containerElementId: pid\n }\n );\n this.updateHighlights(this.serializePageMarkups(whichSide), pid);\n // remove the selection from view\n sel.removeAllRanges();\n } else if (\n this.props.bookToolbar.erasing &&\n this.state.viewerSettings.highlightingMouseDown &&\n this.mouseMove > 5\n ) {\n this.state[`highlighter${whichSide}`].unhighlightSelection();\n this.updateHighlights(this.serializePageMarkups(whichSide), pid);\n }\n this.updateViewerSettings({ highlightingMouseDown: false });\n this.mouseMove = 0;\n };\n\n onMouseMove = (e) => {\n this.mouseMove++;\n };\n\n /*\n * doTouchHighlight highlights the text after a touch devices has highlighted a piece of text and then chosen the highlight color\n */\n doTouchHighlight = (highlightClass) => {\n // get the current selection\n var sel = rangy.getSelection();\n const pid = `page${this.state.viewerSettings.highlightingPageNumber}`;\n const whichSide =\n this.props.book.currentPage ===\n this.state.viewerSettings.highlightingPageNumber\n ? 'Left'\n : 'Right';\n this.state[`highlighter${whichSide}`].highlightSelection(\n highlightClass,\n {\n containerElementId: pid\n }\n );\n this.updateHighlights(this.serializePageMarkups(whichSide), pid);\n // remove the selection from view\n sel.removeAllRanges();\n this.startPointer();\n\n // workaround the iOS bug that does not remove the highlight automatically\n $('.pages .left').click();\n };\n /*\n * save the markups to the server by sending all the highlights and the page id (pid) example: \"page13\"\n */\n updateHighlights = (highlight, pid) => {\n const newHighlights = Object.assign(\n {},\n this.props.book.highlights.Content,\n { [pid]: highlight }\n );\n const bookData = Object.assign(\n {},\n {\n Type: 2,\n Content: newHighlights,\n bookID: this.props.book.ID,\n LastDownloadedFromServer:\n this.props.book.highlights.LastDownloadedFromServer\n }\n );\n this.props\n .saveBookItem(\n bookData,\n this.props.user,\n this.props.viewerMode,\n this.props.book.ID\n )\n .then((bi) => {\n console.log('saved book item');\n })\n .catch((error) => {\n console.error('Error saving book item', error);\n toastr.error(\n 'Unable to save markup. Please try again or contact support.',\n `Error Saving`,\n constants.toastrErrorOptions\n );\n });\n };\n\n /*\n ************************************************* DRAWER *******************************************\n */\n goToNote = (note) => {\n this.resetActiveTimeout();\n const noteID = note.ID || note.TempID;\n this.goToPage(note.Page, () => {\n // give the page time to fade in\n setTimeout(() => {\n this.props.setActiveNote(noteID);\n }, 200);\n });\n };\n\n openDrawer = (drawerType = viewerDrawerTypeEnum.notes) => {\n this.resetActiveTimeout();\n const showDrawer = !this.state.viewerSettings.showDrawer;\n if (drawerType !== this.state.viewerSettings.drawerType) {\n this.updateViewerSettings({\n showDrawer: true,\n drawerType: drawerType\n });\n } else {\n this.updateViewerSettings({\n showDrawer: showDrawer,\n drawerType: drawerType\n });\n }\n };\n closeDrawer = () => {\n this.resetActiveTimeout();\n //close the drawer only if it is open this way we do not call updateViewerSettings too often\n if (this.state.viewerSettings.showDrawer) {\n this.updateViewerSettings({ showDrawer: false });\n }\n };\n\n /*\n ****************************************************** HEADER *************************************************\n */\n\n toggleHeader = () => {\n this.resetActiveTimeout();\n const self = this;\n if (this.state.viewerSettings.header.visible) {\n // TODO refactor to CSS animations\n $('.page-header').animate({ top: '-60px' }, 500);\n $('.toggle').animate({ top: '-25px' }, 500);\n self.updateViewerSettings({\n header: { visible: false, class: 'fa fa-angle-double-down' }\n });\n } else {\n $('.page-header').animate({ top: '0px' }, 500);\n $('.toggle').animate({ top: '35px' }, 500);\n self.updateViewerSettings({\n header: { visible: true, class: 'fa fa-angle-double-up' }\n });\n }\n };\n\n /*\n * toggle BLM mode\n */\n\n toggleBLMMode = (blmMode = false) => {\n this.resetActiveTimeout();\n if (this.props.itemSavePending && blmMode === false) {\n this.setState({\n showSaveProjectConfirm: true,\n saveProjectSubmit: () => {\n removeQuery('blmID');\n removeQuery('projectAssignmentID');\n this.props.updatePendingItem(false);\n }\n });\n } else {\n this.props.updatePendingItem(false);\n if (blmMode === false) {\n removeQuery('blmID');\n removeQuery('projectAssignmentID');\n }\n }\n };\n\n closeBookView = () => {\n // students or .... are able to go to the bookbag, everyone else is logged out\n if (this.props.itemSavePending) {\n this.setState({\n showSaveProjectConfirm: true,\n saveProjectSubmit: () => {\n this.props.updatePendingItem(false);\n this.closeBookView();\n this.setState({ showSaveProjectConfirm: false });\n }\n });\n return;\n }\n this.props.resetBookView();\n this.props.startPointing();\n this.props.setBookReady(false);\n this.props.setProjectReady(false);\n $('#pages').fadeTo('fast', 0.0);\n\n if (\n UserAPI.isStudent(this.props.user.RoleID) ||\n UserAPI.isGeneric(this.props.user.RoleID)\n ) {\n this.goToBag();\n } else {\n this.props.userLogout();\n hashHistory.replace('/');\n }\n };\n\n goToBag = () => {\n // TODO @jfbloom22 why do we empty blms?\n if (!this.props.itemSavePending) {\n this.props.emptyBLMs();\n }\n // let the API know user closed the book by passing -1 in as the page index\n this.props\n .updateBookStatus(\n this.props.book.ID,\n -1,\n this.props.book.pagecount,\n false,\n this.props.blmMode\n )\n .then((resp) => {\n console.log('updated book status - close book');\n })\n .catch((err) => {\n console.error('Error updating book status - close book', err);\n // I don't think we want to show an error if this does not work\n // toastr.error(`Please try again or contact support`, `Error Changing Page`, {\n // closeButton: true,\n // showAnimation: 'animated fadeInDown'\n // });\n });\n\n hashHistory.push({\n pathname: '/bag',\n query: this.props.location.query\n });\n };\n /*\n *\n * update the URL, close the drawer, change to the most recent book page\n * TODO going to need to do this for BLM, they will grab a BLM id\n */\n changeBook = (book) => {\n this.resetActiveTimeout();\n if (this.props.itemSavePending) {\n this.setState({\n showSaveProjectConfirm: true,\n saveProjectSubmit: () => {\n this.changeBook(book);\n this.setState({ showSaveProjectConfirm: false });\n this.props.updatePendingItem(false);\n }\n });\n return;\n }\n if (book.IsExternal) {\n // open the book in the Lerner viewer, not in the DiBS viewer\n const externalURL = `${config.API.Main}/book/openexternalviewer?bookID=${book.ID}`;\n var win = window.open(externalURL, '_blank');\n win.focus();\n return;\n }\n this.props.setProjectReady(false);\n this.props.setBookReady(false);\n this.setState({ pages: {} }, () => {\n const query = { ...this.props.location.query, bookID: book.ID };\n hashHistory.replace({\n pathname: `/viewer`,\n query: query\n });\n this.closeDrawer();\n this.loadBook(book.ID).then(() => {\n this.toggleBLMMode(false);\n setTimeout(() => {\n this.props.setBookReady(true);\n }, 100);\n $('#pages').fadeTo('fast', 1.0);\n this.initBLMs();\n });\n });\n };\n\n changeBlm = (projectAssignmentID, blmID) => {\n this.resetActiveTimeout();\n this.closeDrawer();\n this.props.setProjectReady(false);\n this.loadBLM(projectAssignmentID, blmID).then(() => {\n this.props.setProjectReady(true);\n }); // TODO this will get removed when we add some listeners in did receive props\n };\n\n /*\n **************************************************** GENERAL VIEWER FUNCTIONS *******************************************\n */\n\n fadeOut = (duration, cb) => {\n $('#pages').fadeTo(duration, 0.01, cb);\n // TODO verify that we do not need to handle fading out and in better.\n setTimeout(() => {\n $('#pages').fadeTo('fast', 1.0);\n }, 300);\n };\n /*\n * to support images that span two pages, we make sure we are displaying even or odd pages on the left\n * if left page is supposed to be even, if viewing two pages, if not BLM mode, if pi is odd then subtract one\n * if left page is supposed to be odd, and pi is not odd, then subtract one\n */\n checkLeftPageEven = (pi) => {\n function isOdd(num) {\n return num % 2;\n }\n if (\n this.props.book.LeftPageEven &&\n this.props.pagesVisible === 2 &&\n !this.props.blmMode &&\n isOdd(pi)\n ) {\n return pi - 1;\n } else if (\n !this.props.book.LeftPageEven &&\n this.props.pagesVisible === 2 &&\n !this.props.blmMode &&\n !isOdd(pi)\n ) {\n return pi - 1;\n } else {\n return pi;\n }\n };\n\n checkIfPageExists = (pi) => {\n // if the user tries to view a page and has a letter in the search, it will reject the search\n let re = /^\\d+$/;\n if (!re.test(pi)) {\n return false;\n }\n // if it exceeds the page count\n // if it is 0 and we are viewing a single page or in blm mode\n // if it is -1\n if (\n pi > this.props.book.pagecount ||\n (pi <= 0 &&\n (this.props.pagesVisible === 1 || this.props.blmMode)) ||\n pi < 0\n ) {\n return false;\n }\n return true;\n };\n\n /*\n * go to a specific page\n */\n goToPage = (pi, cb, shouldCheckLeftPageEven = true) => {\n this.resetActiveTimeout();\n // only check the left page even if it is not the the initial load of the book\n if (shouldCheckLeftPageEven) {\n pi = this.checkLeftPageEven(pi); // make sure the correct page is displaying on the left\n }\n\n if (!this.checkIfPageExists(pi)) {\n if (!pi || (pi && pi === 0 && this.props.pagesVisible === 1)) {\n pi = 1;\n } else {\n toastr.error(\n `Page does not exist`,\n `The page you are looking for does not exist.`,\n constants.toastrErrorOptions\n );\n return;\n }\n }\n\n if (pi === this.props.currentPage)\n if (!!cb) {\n return cb();\n } else {\n return;\n }\n // close any notes that happen to be open\n this.props.setActiveNote('');\n if (!!this.state.highlighterRight) {\n this.state.highlighterRight.removeAllHighlights();\n }\n if (!!this.state.highlighterLeft) {\n this.state.highlighterLeft.removeAllHighlights();\n }\n const self = this;\n self.fadeOut(200, function () {\n // update the current page number that we are on\n self.props.updateCurrentPage(pi, self.props.book.ID);\n self.props\n .updateBookStatus(\n self.props.book.ID,\n pi,\n self.props.book.pagecount,\n false,\n self.props.blmMode\n )\n .catch((err) => {\n console.warn('Error updating book status', err);\n });\n // sometimes we go to page 0 in order to display an even page on the left side, don't try to get the html\n if (pi !== 0) {\n self.getBookHTMLPages(self.props.book, pi, true);\n } else if (\n pi === 0 &&\n self.props.pagesVisible === 2 &&\n !self.props.blmMode\n ) {\n self.getBookHTMLPages(self.props.book, 1, true);\n }\n\n if (!!cb) {\n window.setTimeout(() => {\n return cb();\n }, 750);\n }\n });\n };\n\n /*\n * Load the selected book\n * step 1 of 5 in loading a book page\n */\n loadBook = (bookID) => {\n $('#pages').fadeTo('fast', 0.0);\n return this.props\n .getBookByID(bookID, this.props.user)\n .then((book) => {\n console.log(\n `opening book: ISBN: ${book.ISBN}, Title: ${book.Title}, ID: ${book.ID}`\n );\n if (book.IsEPub){\n const httpPrefix = config.Debug ? 'http://' : 'https://';\n this.setState({EPubUrl: `${httpPrefix}${window.location.host}${book.EBookPath}/${book.ISBN}`})\n return Promise.resolve(true);\n }\n return this.getBookParts(book);\n })\n .catch((error) => {\n console.error('error loading book', error);\n let message = `We encountered an error loading the book.`;\n if (error.message) {\n message = error.message;\n }\n this.closeBookView();\n if (error.status === 403) {\n this.handleInvalidSession();\n return;\n } else {\n toastr.error(\n `Error`,\n message,\n constants.toastrErrorOptions\n );\n }\n });\n };\n\n /*\n * step 2 of 5 get the book\n * a book has 3 parts, the properties.json file, HTML pages, and book items\n */\n getBookParts = (book) => {\n let data = {};\n // start step 3\n return this.props\n .getBookProperties(book, this.props.user.AzureToken) // get book properties.json (part 1 of 3)\n .then((bookObj) => {\n // bookReducer UPDATE_BOOK_STATUS_SUCCESS deals with this logic, don't return this since we don't care if it fails\n this.props\n .updateBookStatus(\n bookObj.ID,\n 0,\n bookObj.pagecount,\n false,\n this.props.blmMode\n )\n .then((resp) => {})\n .catch((err) => {\n console.error('Error updating book status', err);\n // do not display an error if updating the status fails\n });\n // we are returning the book obj along with the properties\n // start step 4a\n this.getBookHTMLPages(bookObj, this.props.currentPage, true); // get book html pages (part 2 of 3)\n\n // start step 4b - get student book items if user is a teacher viewing student book\n // MODE: teacher token to view a students items and pull up teacher items with that book\n // action: getTeacherBookItems shows the teacher the items they have made\n // teachers will not have downloaded books as they load in with a token (requiring internet support)\n if (\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK\n ) {\n Object.assign(data, {\n book: book.ID,\n classID: this.props.location.query.classID,\n groupID: this.props.location.query.groupID,\n studentID: this.props.location.query.studentID\n });\n let promises = [];\n promises.push(\n this.props.getBookItemsByStudentID(\n book.ID,\n this.props.location.query.studentID,\n this.props.user\n )\n );\n promises.push(\n this.props.getTeacherBookItems(\n data,\n this.props.user,\n book.ID\n )\n );\n return Promise.all(promises);\n\n // MODE: teacher token to view a group or class and pull up their teacher items with that class or group\n } else if (\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_GROUP_NOTES ||\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_CLASS_NOTES\n ) {\n Object.assign(data, {\n book: book.ID,\n classID: this.props.location.query.classID,\n groupID: this.props.location.query.groupID\n });\n return this.props.getTeacherBookItems(\n data,\n this.props.user,\n book.ID\n );\n\n // MODE: teacher has a token to view a students blm, also grab items for the student\n } else if (\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n Object.assign(data, {\n book: book.ID,\n classID: this.props.location.query.classID,\n groupID: this.props.location.query.groupID,\n StudentID: this.props.location.query.studentID\n });\n let promises = [];\n promises.push(\n this.props.getBookItemsByStudentID(\n book.ID,\n this.props.location.query.studentID,\n this.props.user\n )\n );\n promises.push(\n this.props.getTeacherBookItems(\n data,\n this.props.user,\n book.ID\n )\n );\n return Promise.all(promises);\n } else if (UserAPI.isStudent(this.props.user.RoleID)) {\n // TODO 2/16/18 determine this is online\n // start step 4c - get the book items and set them in the redux store\n // action: getBookItems shows the student the items they have made in the book\n return this.props\n .getBookItems(\n book.ID,\n this.props.user,\n this.props.downloadedBooks\n )\n .then(() => {\n // if offline and there are no highlights and no notes - then show an error. TODO add support for doing markups in multiple books while offline\n // if (!this.props.isOnline && !this.props.book.highlights.Content && this.state.notes.length === 0 ){\n // this.updateViewerSettings({showToolbar: false});\n // throw {message: 'Please connect to the internet and re-open this book before doing any markups.'};\n // }\n }); // get book items (part 3 of 3)\n // TODO 2/16/18 create another if statment determining if the user is a student and we are offline -->\n // Load from downloaded books in redux where we have book items\n } else if (UserAPI.isGeneric(this.props.user.RoleID)) {\n // console.log('not getting book items when a generic user.')\n return Promise.resolve(true);\n } else if (this.props.viewerMode === viewerModes.MODE_GENERIC) {\n // console.log('not getting book items when in generic mode.')\n return Promise.resolve(true);\n } else if (\n this.props.viewerMode === viewerModes.MODE_RESOURCE\n ) {\n console.log('resource mode');\n return Promise.resolve(true);\n } else {\n return Promise.reject({\n message: `not getting book items for this user: ${this.props.user.LoginID}`\n });\n }\n });\n };\n\n /*\n * step 4a grab the HTML assets for the page passed in (left page) plus the nextpage (right page)\n * then wait 1.5 seconds and cache the next 2 pages, wait 2 seconds and cache the previous 2 pages\n *\n */\n getBookHTMLPages = (book, pi, cache) => {\n if (book.IsEPub) {\n return;\n }\n const lIndex = pi; // left page index\n const lpageKey = `page${lIndex}`; // left page key\n const rIndex = lIndex + 1; // right page index we manually add 1 to get the right pi\n const rpageKey = `page${rIndex}`; // right page key\n const pageIndexToCache = lIndex + this.props.pagesVisible;\n const previousPageIndexToCache = lIndex - this.props.pagesVisible;\n const pageIndexToCacheTwo = lIndex + this.props.pagesVisible * 2;\n\n // if left page does not already exist in state, then grab it from the server\n if (!this.props.book.cachedPages[lpageKey]) {\n this.getBookHTMLPage(lpageKey, book, lIndex);\n }\n // if right page does not already exist in state and the right page index is less then or equal to the total pages in the book\n // then grab the book page for the right side\n // TODO how does this work when we are in single page view?\n if (\n !this.props.book.cachedPages[rpageKey] &&\n rIndex <= book.pagecount\n ) {\n this.getBookHTMLPage(rpageKey, book, rIndex);\n }\n\n /*\n * should we cache and is the page index less than the total pages in the book\n * if yes and yes then cache them\n */\n if (cache && lIndex < book.pagecount - 1) {\n setTimeout(() => {\n this.getBookHTMLPages(this.props.book, pageIndexToCache, false);\n }, 1500);\n }\n\n /*\n * should we cache and is the page index more than 2\n * this caches the previous two pages\n */\n if (cache && lIndex > 2) {\n setTimeout(() => {\n this.getBookHTMLPages(\n this.props.book,\n previousPageIndexToCache,\n false\n );\n }, 2500);\n }\n\n /*\n * should we cache and is the page index less than 4 pages ahead of the current index and less than the total pages in the book\n * this caches up to 4 pages ahead of the current viewer page index\n */\n if (\n cache &&\n lIndex - this.props.currentPage < 4 &&\n pageIndexToCacheTwo <= book.pagecount - 1\n ) {\n setTimeout(() => {\n this.getBookHTMLPages(\n this.props.book,\n pageIndexToCacheTwo,\n false\n );\n }, 2000);\n }\n };\n\n /*\n * Get the assets for a single book HTML page and store them in cachedPages\n */\n getBookHTMLPage = (pageKey, bookObj, index) => {\n if (index === 0) {\n this.props.cacheBookPage({\n pageKey,\n pageHTML: '
',\n pageNumber: 0,\n width: bookObj.bounds[0][0],\n height: bookObj.bounds[0][1]\n });\n return;\n }\n // since the book pages are so temporary we do not store them in Redux\n return this.props\n .getSpeechMarks(bookObj, index, this.props.user.AzureToken, pageKey)\n .then(() => {\n return this.props\n .getBookPage(\n this.props.book,\n index,\n this.props.user.AzureToken,\n pageKey\n )\n .then((pageHTML) => {\n // console.info('retrieved book page', pageData);\n if (!pageHTML) {\n console.error('failed to process page', pageHTML);\n throw new Error({\n message: 'failed to process page'\n });\n }\n this.props.cacheBookPage({\n pageKey,\n pageHTML,\n pageNumber: index,\n width: bookObj.bounds[index - 1][0],\n height: bookObj.bounds[index - 1][1]\n });\n });\n })\n .catch((error) => {\n // check if we are online\n if (!this.props.isOnline) {\n // if we do not have books and we are offline, we need to show an error\n console.warn('unable to load page while offline');\n toastr.error(\n `No internet connection.`,\n `Error Loading Book Page`,\n constants.toastrErrorOptions\n );\n return;\n }\n console.error('Error trying to get book page', error);\n if (error.status === 403) {\n this.handleInvalidSession();\n } else {\n toastr.error(\n `We encountered an error getting the book page.`,\n `Error Getting Page`,\n constants.toastrErrorOptions\n );\n }\n });\n };\n\n loadBLM = (projectAssignmentID, blmID) => {\n // if the projectAssignmentID is empty, the current object is the blmID or vice versa\n // For example: blmCreator does not have a projectAssignmentID, only a blmID\n // A student does not use a blmID only a projectAssignmentID\n let currentObjectID;\n if (this.props.itemSavePending) {\n this.setState({\n showSaveProjectConfirm: true,\n saveProjectSubmit: () => {\n this.loadBLM(projectAssignmentID, blmID);\n removeQuery('blmID');\n this.setState({ showSaveProjectConfirm: false });\n this.props.updatePendingItem(false);\n }\n });\n return Promise.reject({ message: 'not saved' });\n }\n\n const query = {\n ...this.props.location.query,\n blmID,\n projectAssignmentID\n };\n hashHistory.replace({\n pathname: `/viewer`,\n query: query\n });\n\n // projectAssignmentID is empty here for a creator\n if (projectAssignmentID === '') {\n currentObjectID = blmID;\n } else {\n currentObjectID = projectAssignmentID;\n }\n return this.getBLMObject(currentObjectID)\n .then((blm) => {\n // need to not fade out if we have already loaded the blm\n if (\n this.props.projectAssignmentID &&\n this.props.blm.projectAssignmentID !==\n blm.projectAssignmentID\n ) {\n this.fadeOut(600, () => {});\n return this.getBLMParts(blm);\n } else {\n return this.getBLMParts(blm);\n }\n })\n .catch((err) => {\n console.error('unable to load BLM', err);\n toastr.error(\n ``,\n `Error Loading BLM`,\n constants.toastrErrorOptions\n );\n throw err;\n });\n };\n\n getBLMObject = (projectAssignmentID) => {\n let blm = this.props.blm;\n\n // if the book is already in redux as the active book (this happens after token login and page refresh)\n // For a student, we check to see if projectAssignmentID equals the paID on the blm\n // For an admin making a blm, we do not have a projectAssignmentID, so we pass a blmID\n // For a teacher, we do not have a projectAssignmentID on the blm but we have it in props\n if (this.props.viewerMode === viewerModes.MODE_TEACHER_STUDENT_BLM) {\n if (this.props.projectAssignmentID === projectAssignmentID) {\n return Promise.resolve(blm);\n }\n } else {\n if (\n blm.projectAssignmentID === projectAssignmentID ||\n blm.ID === projectAssignmentID\n ) {\n return Promise.resolve(blm);\n }\n }\n\n blm = this.props.blms.filter((b) => {\n return b.projectAssignmentID === projectAssignmentID;\n })[0];\n if (blm) {\n return Promise.resolve(blm);\n } else {\n // console.error('unable to find the project in the array of projects');\n // return reject(false);\n // TODO enable downloaded BLMs ????\n // if we are on mobile or chrome then try to find it in the array of downloaded blms\n // if (config.System === 'chrome' || config.System === 'mobile'){\n // blm = this.props.downloadedBlms.filter((b) => { return b.ID === blmID })[0];\n // if (blm){\n // console.log('have blm in downloadedBooks');\n // resolve(blm);\n // }\n }\n if (this.props.isOnline) {\n // we are online so grab it from the API\n return this.props\n .getBLMByID(this.props.blmID, this.props.user)\n .then((result) => {\n // this.loadBook(bookSaved);\n // book = result;\n return result;\n });\n } else {\n return Promise.reject(false);\n }\n };\n\n getBLMParts = (blm) => {\n return this.props\n .getBLMProperties(blm, this.props.user.AzureToken) // step 1, get blm properties\n .then((blmObj) => {\n if (!this.props.blmMode) {\n this.toggleBLMMode(true);\n }\n this.getBlmHtml(blmObj); // step 2, get blm html\n\n if (UserAPI.isStudent(this.props.user.RoleID)) {\n return this.props\n .getBLMStatus(blm, this.props.user)\n .then(() => {\n return this.props.getTeachersComment(\n blm.projectAssignmentID,\n blm.TeacherID,\n this.props.user\n );\n })\n .then(() => {\n return this.props.getBLMItems(\n blmObj.ID,\n blm.projectAssignmentID,\n this.props.user\n );\n })\n .then(() => {\n this.updateViewerSettings({\n loadedProjectAssignmentID:\n blm.projectAssignmentID\n });\n });\n }\n\n // MODE: teacher has token to view a students blm, this call grabs the students blm items\n if (\n this.props.viewerMode ===\n viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n return this.props\n .getStudentsBLMItems(\n blm.ID,\n this.props.projectAssignmentID,\n this.props.location.query.studentID,\n this.props.user\n )\n .then(() => {\n this.updateViewerSettings({\n loadedProjectAssignmentID:\n blm.projectAssignmentID\n });\n });\n\n // MODE: teacher has token to create a blm template. They find any items they have previously made with the template\n } else if (\n this.props.viewerMode ===\n viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ) {\n return this.props\n .getTemplateItems(blmObj.ID, this.props.user)\n .then(() => {\n this.updateViewerSettings({\n loadedProjectAssignmentID:\n blm.projectAssignmentID\n });\n });\n }\n })\n .catch((error) => {\n console.error('Error getting BLM', error);\n if (error.status === 403) {\n this.handleInvalidSession();\n } else {\n toastr.error(\n `We encountered an error loading the BLM.`,\n `Error Loading BLM`,\n constants.toastrErrorOptions\n );\n }\n });\n };\n handleInvalidSession = () => {\n toastr.warning(\n `Trying to fix an issue with the book.`,\n `Please wait a moment`,\n constants.toastrWarningOptions\n );\n };\n\n getBlmHtml = (blm) => {\n // console.log(blm, 'BLM getting html');\n // passing in blm, 1 (because there is always only 1 page of the BLM, and the azure token)\n BlmAPI.getBlmPageRemote(blm, 1, this.props.user.AzureToken)\n .then((blmPage) => {\n this.setState({ blmHtml: blmPage });\n })\n .catch((error) => {\n // check if we are online\n if (!this.props.isOnline) {\n // if we do not have books and we are offline, we need to show an error\n console.warn('unable to load BLM while offline');\n toastr.error(\n `No internet connection.`,\n `Error Loading BLM`,\n constants.toastrErrorOptions\n );\n return;\n }\n console.error('Error trying to get BLM', error);\n if (error.status === 403) {\n this.handleInvalidSession();\n } else {\n toastr.error(\n `We encountered an error getting the BLM.`,\n `Error Getting BLM`,\n constants.toastrErrorOptions\n );\n }\n });\n };\n\n render() {\n if (requireSignIn(this.props.user, this.props.location)) {\n return null;\n }\n let books;\n if (this.props.isOnline) {\n books = this.props.books;\n } else {\n books = this.props.downloadedBooks;\n }\n return (\n
\n {this.props.book.IsEPub && this.state.EPubUrl && (\n
\n \n console.log(epubcifi)\n }\n tocChanged={(toc) => console.log(toc)}\n closeBookView={this.closeBookView}\n // audioChanged={this.props.updateBookAudioUrl}\n />\n
\n )}\n {this.props.book.IsEPub === false && (\n \n )}\n
\n {this.state.viewerSettings.showHeader && (\n \n )}\n\n \n \n
\n \n {\n this.setState({ showSaveProjectConfirm: false });\n }}\n submit={this.state.saveProjectSubmit}\n />\n
\n );\n }\n}\n\nconst mapStateToProps = (state, ownProps) => {\n return {\n user: state.user,\n highlights: state.highlights,\n book: state.book,\n books: state.books,\n completedBLMs: state.completedBLMs,\n blms: state.blms,\n blm: state.blm,\n blmProperties: state.blmProperties,\n isOnline: state.offlineQueue.isOnline && navigator.onLine,\n loading: state.ajaxCallsInProgress > 0,\n downloadedBooks: state.downloadedBooks,\n currentPage: state.book.currentPage,\n totalPage: state.book.pagecount,\n leftPageContainerWidth: state.bookView.leftPageContainerWidth,\n leftPageContainerHeight: state.bookView.leftPageContainerHeight,\n bookScalePercent: state.bookView.bookScalePercent,\n projectScalePercent: state.bookView.projectScalePercent,\n blmMode: !!(\n ownProps.location.query.blmID &&\n ownProps.location.query.blmID.length > 0\n ),\n pagesVisible: state.bookView.pagesVisible,\n bookID: ownProps.location.query.bookID,\n viewerMode: ownProps.location.query.viewerMode,\n projectAssignmentID: ownProps.location.query.projectAssignmentID,\n blmID: ownProps.location.query.blmID,\n bookToolbar: state.bookToolbar,\n bookIsZooming: state.bookView.bookManualZoomLevel !== 1,\n itemSavePending: state.bookView.itemSavePending\n };\n};\n\nexport default connect(mapStateToProps, {\n userLogout,\n getBookProperties,\n getBookItems,\n getBookItemsByStudentID,\n getTeacherBookItems,\n getBookPage,\n getSpeechMarks,\n searchBookBagBooks,\n saveBookItem,\n deleteBookItem,\n updateBookStatus,\n getAssignedBLMs,\n getBLMProperties,\n getBLMStatus,\n getTeachersComment,\n emptyBLMs,\n getBLMItems,\n getStudentsBLMItems,\n getTemplateItems,\n getBookByID,\n getBLMByID,\n manualAjaxStart,\n manualAjaxEnd,\n updateCurrentPage,\n nextPage,\n prevPage,\n cacheBookPage,\n updateLeftPageContainer,\n updateBookScalePercent,\n updateProjectScalePercent,\n updatePagesVisible,\n resetBookView,\n automaticUpdatePagesVisible,\n setBookReady,\n setProjectReady,\n startNotes,\n startPointing,\n startHighlighting,\n startErasing,\n startUnderlining,\n startStriking,\n setActiveNote,\n increaseBookZoom,\n decreaseBookZoom,\n startMoving,\n downloadSpeech,\n updatePendingItem,\n resetCachedBookPages,\n})(withRouter(BookView));\n","import * as React from 'react';\nimport { FormGroup, FormControl, Row, Col } from 'react-bootstrap';\n\nclass UserProfileForm extends React.Component {\n render() {\n return (\n \n \n {this.props.forms.map((form) => {\n return (\n \n \n \n );\n })}\n

\n \n Need to update your password?\n \n
\n \n Enter the new one twice above, otherwise leave it\n blank.\n \n

\n \n
\n );\n }\n}\n\nexport default UserProfileForm;\n","import * as types from '../actionTypes';\n\nexport const toggleUserProfileModal = () => ({\n type: types.TOGGLE_USER_PROFILE_MODAL\n});\n\nexport const toggleLoggoutConfirmModal = () => ({\n type: types.TOGGLE_LOGGOUT_CONFIRM_MODAL\n});\n","import React from 'react';\nimport { Col, FormControl, FormGroup, Row, FormLabel } from 'react-bootstrap';\nimport { connect } from 'react-redux';\nimport { addClassCode, toggleClassCodeModal } from '../../actions/userActions';\nimport CommonModal from '../common/CommonModal';\n\n\ninterface Iprops {\n show: boolean;\n submit: typeof addClassCode;\n cancel: ()=> void;\n addCode?: string;\n}\n\ninterface Istate {\n code: string;\n}\n\nclass ClassCodeModal extends React.Component {\n constructor(props: Iprops) {\n super(props);\n this.state = {\n code: this.props.addCode || ''\n }\n }\n render() {\n return (\n
\n {e.preventDefault(); this.props.submit(this.state.code)}}\n >\n
\n \n \n \n \n Class Code or Group\n \n this.setState({code: e.currentTarget.value})}\n />\n \n \n \n
\n\n \n
\n );\n }\n}\n\n\nfunction mapStateToProps(state: any, ownProps: any) {\n return {\n loading: state.ajaxCallsInProgress > 0,\n show: state.dashboard.showClassCodeModal\n };\n}\n\nexport default connect(mapStateToProps, {\n submit: addClassCode,\n cancel: toggleClassCodeModal\n})(ClassCodeModal);\n","import * as React from 'react';\nimport { connect } from 'react-redux';\nimport { toastr } from 'react-redux-toastr';\nimport { hashHistory } from 'react-router';\nimport UserProfileForm from '../common/UserProfileForm';\nimport CommonModal from '../common/CommonModal';\nimport { Nav, Navbar, NavItem } from 'react-bootstrap';\n\nimport {\n userUpdateProfile,\n userUpdatePW,\n userLogout,\n toggleClassCodeModal\n} from '../../actions/userActions';\nimport {\n toggleUserProfileModal,\n toggleLoggoutConfirmModal\n} from '../../actions/dashboard/dashboardActions';\n\nimport constants from '../../constants/constants';\nimport UserAPI from '../../api/userAPI';\nimport { StyledNavbar } from '../../constants/styledComponents';\nimport ClassCodeModal from './ClassCodeModal';\n\nconst FontAwesome = require('react-fontawesome');\n\nclass BookBagHeader extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n firstName: this.props.user.First,\n lastName: this.props.user.Last,\n password: '',\n confirmPassword: '',\n loginID: this.props.user.LoginID,\n logoutWarning:\n 'All of your downloaded books will be removed and you will have to redownload them. Are you sure you want to continue?'\n };\n this.theme = constants.themeProvider.activeTheme;\n this.logo = this.theme.logo;\n }\n\n componentDidMount() {\n this.setState({ logoutWarning: '' });\n }\n\n closeLoggoutConfirmModal = () => {\n this.setState({ showLoggoutConfirmModal: false });\n };\n\n handleLoggout = () => {\n this.props.userLogout();\n hashHistory.push('/login');\n };\n\n handleSelect = (e) => {\n switch (e) {\n case '1':\n this.props.toggleUserProfileModal();\n break;\n case '2':\n this.signOut();\n break;\n case '3':\n this.props.toggleClassCodeModal();\n break;\n default:\n }\n };\n\n handleChange = (e) => {\n this.setState({ [e.target.name]: e.target.value });\n };\n\n signOut = () => {\n // prevent user from logging out if there is no internet connection\n if (!this.props.isOnline) {\n toastr.error(\n `You must be connected to the internet before logging out.`,\n `Warning`,\n constants.toastrWarningOptions\n );\n return;\n }\n this.props.toggleLoggoutConfirmModal();\n };\n\n handleSubmit = () => {\n if (!this.props.isOnline) {\n toastr.error(\n `You must be connected to the internet before updating your profile or changing your password.`,\n `No Internet Connection`,\n {\n closeButton: true,\n showAnimation: 'animated fadeInDown'\n }\n );\n return;\n }\n if (\n this.state.firstName !== '' &&\n this.state.lastName !== '' &&\n this.state.loginID !== ''\n ) {\n const firstName = this.state.firstName;\n const lastName = this.state.lastName;\n const loginID = this.state.loginID;\n this.props.toggleUserProfileModal();\n\n this.props\n .userUpdateProfile(\n this.props.user,\n firstName,\n lastName,\n loginID\n )\n .then(() => {\n toastr.success(\n `Updated profile info.`,\n `Success`,\n constants.toastrSuccessOptions\n );\n })\n .catch((error) => {\n console.error('Error updating profile', error);\n toastr.error(\n `Unable to update profile. ${error.statusText}`,\n `Error`,\n constants.toastrErrorOptions\n );\n });\n }\n\n if (\n this.state.password === this.state.confirmPassword &&\n this.state.password !== ''\n ) {\n const password = this.state.password;\n this.props\n .userUpdatePW(this.props.user, password)\n .then(() => {\n toastr.success(\n `Updated password.`,\n `Success`,\n constants.toastrSuccessOptions\n );\n })\n .catch((error) => {\n console.error('Error updating password', error);\n toastr.error(\n `Unable to update password. ${error.statusText}`,\n `Error`,\n constants.toastrErrorOptions\n );\n });\n this.setState({ password: '', confirmPassword: '' });\n this.props.toggleUserProfileModal();\n }\n };\n buildUserProfileForm = () => {\n return (\n \n );\n };\n\n render() {\n return (\n
\n \n {/* */}\n \n \"\"\n \n {/* */}\n \n \n {this.props.user && this.props.user.School && (\n \n \n {this.props.user.School.Name}\n \n \n )}\n {this.props.user && this.props.user.School && (\n \n |\n \n )}\n {UserAPI.isStudent(this.props.user.RoleID) && (\n \n \n \n {' '}Add Class/Group\n \n \n )}\n {UserAPI.isStudent(this.props.user.RoleID) && (\n\n \n \n \n {' '}{this.props.user.First}{' '}\n {this.props.user.Last}\n \n \n \n )}\n\n \n \n Logout\n \n \n \n \n \n\n \n\n \n \n
\n );\n }\n}\n\nfunction mapStateToProps(state, ownProps) {\n return {\n user: state.user,\n showUserProfileModal: state.dashboard.showUserProfileModal,\n showLoggoutConfirmModal: state.dashboard.showLoggoutConfirmModal\n };\n}\n\nexport default connect(mapStateToProps, {\n userUpdateProfile,\n userUpdatePW,\n userLogout,\n toggleUserProfileModal,\n toggleLoggoutConfirmModal,\n toggleClassCodeModal\n})(BookBagHeader);\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOQAAAEjCAYAAAAiza01AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNFQjRFNzcyMjQ4MzExRTdCQjNERDhCODU5NDJDMkJFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNFQjRFNzczMjQ4MzExRTdCQjNERDhCODU5NDJDMkJFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6M0VCNEU3NzAyNDgzMTFFN0JCM0REOEI4NTk0MkMyQkUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6M0VCNEU3NzEyNDgzMTFFN0JCM0REOEI4NTk0MkMyQkUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6pSFKnAAAO5klEQVR42uzd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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOQAAAEjCAYAAAAiza01AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjM2NDRFOTE0MjQ4MzExRTc5Q0I1ODVFMUUyQTY2Q0Q4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjM2NDRFOTE1MjQ4MzExRTc5Q0I1ODVFMUUyQTY2Q0Q4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MzY0NEU5MTIyNDgzMTFFNzlDQjU4NUUxRTJBNjZDRDgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzY0NEU5MTMyNDgzMTFFNzlDQjU4NUUxRTJBNjZDRDgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6b15M9AAANXUlEQVR42uzd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\"","import * as types from './actionTypes';\n\nexport const saveAdvancedSearchFilter = (filters) => ({\n type: types.SAVE_ADVANCED_SEARCH_FILTERS,\n filters\n});\n\nexport const clearAdvancedSearchFilter = () => ({\n type: types.CLEAR_ADVANCED_SEARCH_FILTERS\n});\n","export default \"data:image/png;base64,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\"","import React from 'react';\nimport { connect } from 'react-redux';\nimport config from '../../api/config';\nimport {\n saveAdvancedSearchFilter,\n clearAdvancedSearchFilter\n} from '../../actions/bookbagFiltersActions';\nimport { Col, Row, FormGroup, FormControl, Form } from 'react-bootstrap';\nimport PropTypes from 'prop-types';\nimport debounce from 'throttle-debounce/debounce';\nimport CommonModal from '../common/CommonModal';\nimport { MultiSelect } from 'react-selectize';\nimport { reject } from 'lodash';\nimport UserAPI from '../../api/userAPI';\nimport Select from 'react-select';\n\nclass AdvancedSearchModal extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n showAdvancedSearch: false,\n advancedSearch: ''\n };\n this.debouncedAdvancedSearch = debounce(800, this.doAdvancedSearch);\n }\n\n clearAdvancedSearch = () => {\n this.props.clearAdvancedSearchFilter();\n this.props.cancel();\n };\n handleReadingLevelChange = (selectedReadingLevelTypeOption) => {\n this.props.saveAdvancedSearchFilter({ selectedReadingLevelTypeOption });\n };\n\n advancedSearchForm() {\n return (\n
\n \n \n

\n {this.state.loading && (\n \n Searching for tags...{' '}\n \n \n )}\n

\n \n
\n \n \n \n {\n this.props.saveAdvancedSearchFilter({\n tags: value\n });\n }}\n closeOnSelect={true}\n onSearchChange={(advancedSearch) => {\n if (\n this.state.advancedSearch ===\n advancedSearch\n )\n return;\n this.setState({ advancedSearch });\n\n if (advancedSearch.length > 0) {\n this.setState({ loading: true });\n if (!!this.req) {\n this.req.abort();\n }\n this.handleAdvancedSearchChange(\n advancedSearch\n );\n }\n }}\n uid={(item) => {\n return item.TagID;\n }}\n filterOptions={(options, search) => {\n return options;\n }}\n renderOption={(item) => {\n return (\n \n
\n \n {item.name}\n \n \n {'@' +\n item.Name +\n ' (' +\n item.TagCount +\n ')'}\n \n
\n
\n );\n }}\n renderValue={(item) => {\n return (\n
\n {\n let rejectedSearch = reject(\n this.props\n .bookbagFilters,\n (search) => {\n return (\n search.TagID ===\n item.TagID\n );\n }\n );\n this.props.saveAdvancedSearchFilter(\n rejectedSearch\n );\n }}\n >\n x\n \n\n \n {item.name}\n \n \n {'@' +\n item.Name +\n ' (' +\n item.TagCount +\n ')'}\n \n
\n );\n }}\n renderNoResultsFound={(value, search) => {\n return (\n \n {typeof this.req === 'undefined' &&\n this.state.advancedSearch.length ===\n 0\n ? 'type a few characters to kick off remote search'\n : 'No results found'}\n \n );\n }}\n />\n \n \n \n\n \n \n \n \n \n \n \n \n \n this.props.saveAdvancedSearchFilter({\n readingMin: e.target.value\n })\n }\n />\n \n \n \n \n \n this.props.saveAdvancedSearchFilter({\n readingMax: e.target.value\n })\n }\n />\n \n \n \n \n \n \n \n this.props.saveAdvancedSearchFilter({\n spanishOnly: e.target.checked\n })\n }\n label=\"Spanish Only\"\n />\n \n \n \n \n );\n }\n\n doAdvancedSearch(value) {\n UserAPI.getAdvancedSearch(value, this.props.user)\n .then((advancedSearchResults) => {\n this.setState({\n advancedSearchResults: advancedSearchResults,\n loading: false\n });\n })\n .catch((error) => {\n this.setState({ loading: false });\n console.error(error, 'Error with advanced search');\n });\n }\n\n handleAdvancedSearchChange(value) {\n this.debouncedAdvancedSearch(value);\n }\n render() {\n return (\n
\n \n
\n );\n }\n}\n\nAdvancedSearchModal.propTypes = {\n show: PropTypes.bool.isRequired,\n cancel: PropTypes.func.isRequired\n};\n\nfunction mapStateToProps(state, ownProps) {\n return {\n user: state.user,\n bookbagFilters: state.bookbagFilters,\n loading: state.ajaxCallsInProgress > 0,\n isOnline: state.offlineQueue.isOnline && navigator.onLine\n };\n}\n\nexport default connect(mapStateToProps, {\n saveAdvancedSearchFilter,\n clearAdvancedSearchFilter\n})(AdvancedSearchModal);\n","import * as React from 'react';\nimport allSquare from '../../images/NandF_Square.png';\nimport backpackImg from '../../images/backpack.png';\nimport bookshelfImg from '../../images/bookshelf.png';\nimport languageSquare from '../../images/Language_Square.png';\nimport mathSquare from '../../images/Math_Square.png';\nimport nonFictionSquare from '../../images/Nonfiction_Square.png';\nimport AdvancedSearchModal from './AdvancedSearchModal';\nimport scienceSquare from '../../images/Science_Square.png';\nimport socialStudiesSquare from '../../images/SocialStudies_Square.png';\nimport fictionSquare from '../../images/Fiction_Square.png';\nimport { FormGroup, Row, Col, FormControl, Button } from 'react-bootstrap';\nimport { StyledButton } from '../../constants/styledComponents';\nimport { addQuery, removeQuery } from '../../vendor/utils-router';\nconst FontAwesome = require('react-fontawesome');\n\nimport {\n checkForUpdatedBookFiles,\n getBookItemsList,\n initialDashboardQuery,\n searchBookBagBooks\n} from '../../actions/bookActions';\nimport { clearAdvancedSearchFilter } from '../../actions/bookbagFiltersActions';\n\ninterface Iprops {\n query: typeof initialDashboardQuery;\n isOnline: boolean;\n bookbagFilters: {\n tags: any;\n spanishOnly: any;\n selectedReadingLevelTypeOption: any;\n readingMax: any;\n readingMin: any;\n };\n showSearchBar: boolean;\n theme: any;\n books: Array;\n searchBookBagBooks: typeof searchBookBagBooks;\n isFiltersActive: boolean;\n user: any;\n downloadedBooks: Array;\n checkForUpdatedBookFiles: typeof checkForUpdatedBookFiles;\n manualAjaxEnd: () => void;\n handleInvalidSession: () => void;\n clearAdvancedSearchFilter: typeof clearAdvancedSearchFilter;\n loading: boolean;\n isStudent: boolean;\n isGeneric: boolean;\n getBookItemsList: typeof getBookItemsList;\n}\n\ninterface Istate {\n showAdvancedSearch: boolean;\n}\n\nclass BookBagSearch extends React.Component {\n constructor(props: Iprops) {\n super(props);\n this.state = {\n showAdvancedSearch: false\n };\n }\n componentDidMount() {\n this.initializeComponent();\n }\n componentDidUpdate(prevProps: Iprops) {\n if (prevProps.isOnline !== this.props.isOnline && this.props.isOnline) {\n setTimeout(() => {\n this.updateBookItems();\n }, 300);\n }\n }\n /*\n * initial setup of the component\n * call getBookListItems to get the latest book items for DOWNLOADED books only\n * this.props.downloadedBooks, loop through array to get all bookIDs\n * Action: save the book contents to downloaded books\n * Potential Issue: Being offline, saving a book item, going online and going straight to book bag:\n * Solution: check to see if there are any ajaxCallsInProgress\n */\n initializeComponent = () => {\n if (!this.props.query.searchMode) {\n addQuery({ searchMode: 'local' });\n }\n this.updateBookItems();\n\n if (this.props.isGeneric) {\n addQuery({ searchMode: 'remote' });\n setTimeout(() => {\n this.props.searchBookBagBooks(\n this.props.isFiltersActive,\n this.props.query\n );\n }, 100);\n } else if (this.props.isStudent) {\n // if local then always load books. If remote the only load books if there is a search\n if (\n !this.props.query.searchMode ||\n this.props.query.searchMode === 'local'\n ) {\n this.props.searchBookBagBooks(\n this.props.isFiltersActive,\n this.props.query\n );\n } else if (\n this.props.query.searchMode === 'remote' &&\n this.props.query.search.length > 0 &&\n this.props.books.length === 0\n ) {\n this.props.searchBookBagBooks(\n this.props.isFiltersActive,\n this.props.query\n );\n }\n if (this.props.isOnline) {\n console.log('****** we are online');\n } else {\n console.log('****** we are offline');\n }\n } else {\n // if you are not a student or a Generic user, they will be sent to the login screen via the auth check in the render function.\n }\n // TODO load all assigned blms and save this to redux\n // TODO start with including it into props\n };\n /*\n * If we are on a device and downloaded books, check to see if there are updated Book Items or updated Book files\n */\n updateBookItems = () => {\n console.log('about to update book items');\n if (this.props.isOnline && this.props.downloadedBooks.length > 0) {\n // Make call to grab all book items if ajax calls are not currently in progress\n if (!this.props.loading) {\n this.props.getBookItemsList(\n this.props.downloadedBooks,\n this.props.user\n );\n } else {\n //wait 5 seconds then try again\n setTimeout(() => {\n this.updateBookItems();\n }, 5000);\n }\n }\n };\n\n isActiveAdvancedSearch = () => {\n const {\n tags,\n spanishOnly,\n selectedReadingLevelTypeOption,\n readingMax,\n readingMin\n } = this.props.bookbagFilters;\n if (\n (tags && tags.length) ||\n spanishOnly ||\n (selectedReadingLevelTypeOption &&\n selectedReadingLevelTypeOption.value !== 'grl') ||\n readingMax ||\n readingMin\n ) {\n return true;\n } else {\n return false;\n }\n };\n\n /*\n * Switch to Remote Books\n */\n switchToRemote = () => {\n // this.setState({ searchMode: 'remote' }, () => {\n // // only load remote books if there is a search paramater\n // // do we want to search if there is a tag, type, or reading level selected??? Lets stick with search for now\n // // if (this.state.search.length > 0 || this.state.tag !== 'all-tags' || this.state.type !== 'all' || this.state.readingLeve.length > 0){\n // });\n addQuery({ searchMode: 'remote' });\n removeQuery('activePage');\n };\n\n /*\n * Switch to Local Books\n */\n switchToLocal = () => {\n addQuery({ searchMode: 'local' });\n removeQuery('activePage');\n };\n\n searchForBooks = (event: React.ChangeEvent) => {\n if (event) {\n addQuery({ search: event.target.value });\n }\n };\n\n searchForReadingLevel = (event: React.ChangeEvent) => {\n if (event) {\n addQuery({ grl: event.target.value });\n }\n };\n\n handleTagChange = (val: string) => {\n addQuery({ tag: val });\n };\n\n handleTypeChange = (val: string) => {\n addQuery({ type: val });\n };\n\n showAdvancedSearch = () => {\n this.setState({ showAdvancedSearch: true });\n };\n\n closeAdvancedSearch = () => {\n this.setState({ showAdvancedSearch: false });\n };\n clearAdvancedSearchForm = () => {\n removeQuery('search', 'type', 'tag', 'grl');\n addQuery({ activePage: 1 });\n this.props.clearAdvancedSearchFilter();\n };\n\n handleSubmit = (\n event: React.FormEvent,\n activePage: number\n ) => {\n if (event) {\n event.preventDefault();\n }\n console.log(`initiating a bookbag search: ${this.props.query.search}`);\n addQuery({ activePage });\n this.props.searchBookBagBooks(this.props.isFiltersActive, {\n ...this.props.query,\n activePage\n });\n };\n\n render() {\n let backpack = '';\n let bookshelf = '';\n let bookbagSearchMode = 'bookbag-searchmode';\n if (this.props.isGeneric) {\n bookbagSearchMode = 'd-none';\n }\n if (\n !this.props.query.searchMode ||\n this.props.query.searchMode === 'local'\n ) {\n backpack += 'backpack';\n bookshelf += '';\n } else {\n backpack += '';\n bookshelf += 'bookshelf';\n }\n\n let advancedSearchButton = this.isActiveAdvancedSearch()\n ? 'advanced-search-active'\n : 'advanced-search';\n // tags\n let languageBC =\n this.props.query.tag === 'languageArts' ? 'language-bc' : '';\n let socialStudiesBC =\n this.props.query.tag === 'socialStudies' ? 'social-science-bc' : '';\n let mathBC = this.props.query.tag === 'math' ? 'math-bc' : '';\n let scienceSearchBC =\n this.props.query.tag === 'science' ? 'science-bc' : '';\n let allTags = this.props.query.tag === 'allTags' ? 'all-tags' : '';\n // types\n let allBC = this.props.query.type === 'All' ? 'all-bc' : '';\n let fictionBC = this.props.query.type === 'Fiction' ? 'fiction-bc' : '';\n let nonFictionBC =\n this.props.query.type === 'Non-Fiction' ? 'non-fiction-bc' : '';\n\n return (\n \n {this.props.showSearchBar && this.props.isOnline && (\n
\n this.handleSubmit(e, 1)}\n className=\"dibs-form bookbag-search-form\"\n >\n \n \n
\n {\n this.switchToLocal();\n }}\n src={backpackImg}\n alt=\"Book Bag\"\n />\n
Book Bag
\n
\n
\n {\n this.switchToRemote();\n }}\n src={bookshelfImg}\n alt=\"Book Room\"\n />\n
Book Room
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n {' '}\n Go{' '}\n \n \n
\n \n\n {/* search icon buttons */}\n \n \n
\n {\n this.handleTagChange('allTags');\n }}\n src={allSquare}\n alt=\"\"\n />\n
All
\n
\n
\n {\n this.handleTagChange(\n 'socialStudies'\n );\n }}\n src={socialStudiesSquare}\n alt=\"\"\n title=\"scienceSearch\"\n />\n
Social Studies
\n
\n
\n {\n this.handleTagChange('science');\n }}\n src={scienceSquare}\n alt=\"\"\n />\n
Science
\n
\n
\n {\n this.handleTagChange('math');\n }}\n src={mathSquare}\n alt=\"\"\n />\n
Math
\n
\n
\n {\n this.handleTagChange(\n 'languageArts'\n );\n }}\n src={languageSquare}\n alt=\"\"\n />\n
Language
\n
\n \n \n
\n {\n this.handleTypeChange('All');\n }}\n src={allSquare}\n alt=\"\"\n />\n
All
\n
\n
\n {\n this.handleTypeChange('Fiction');\n }}\n src={fictionSquare}\n alt=\"\"\n />\n
Fiction
\n
\n
\n {\n this.handleTypeChange(\n 'Non-Fiction'\n );\n }}\n src={nonFictionSquare}\n alt=\"\"\n />\n
Non-Fiction
\n
\n \n \n this.showAdvancedSearch()}\n >\n Advanced\n Search\n \n \n this.clearAdvancedSearchForm()\n }\n >\n Clear Search\n \n \n
\n \n
\n )}\n
\n );\n }\n}\n\nexport default BookBagSearch;\n","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAADoFJREFUeNrsnX+IVWUax89NW6WRxrKMhEYNjQRLx/pDaCV/EJIs6fSHGG2Yf7QJ+8cMC5tsLKzBsossxMw/i9Qf2kZbFDRKYRSk008UMnUNHNBldAQjrVYFxajYPZ/jee6+973vuff8vOece94nTuc69573nvM83+fn+7zvrTkZ0Y6ndix1TyvdY4l7zPNfWwpPY+5x2j2O8Xrbq9uOZvEltZSFvsE9rXcPzjOtDFOli+6xxz32umDYUxgAuEJH0EPusdnXdEvZE5bhFfcYdsFwMTcAuMLf7p4GrbbnahVGXBBs7ygAXMHjz3dZjS+URdjiAmEsUwD45v5Pvsm3VDwado8XoriFWgTho+2j7rHU8rnQRLYw4ILgdGoA8FO6A9bXlyo2WBUmdaxZ4VcbBDUr/GqDoNbG5x+xwu8KEPQHxQQ3tIj2R63wu4I8WfoyDQcAP9Wz0X730FJfpu1dgF/kOWB51pW0Si8WmSzALsunrqVdLV2AX9ufZ/nUtTTPl3GzC/CDhAkb+FUiK5gv5WLVAgxZ4VcmKxgyuYDNljeVoc0NAPA7eazvr1YssEG1AOstTypH61UAbLD8qBx5Mq/5Ez5HLD8qSf1YgJWWD5WllQBgieVDZWnJDTb6j0/TbprmPDTwkHcuazZgXUACenDtgx4AFj6wsNQuwFICAEC9t/WW9hksAGLS4hWLy2z6LQCSEqZf6PzkeQuAqglfNfvnz/wfAMQDZYoJLAAiEoIX3w9d+vaSd8h7A4MDDe9bAHQZrX5ydYPv/+qTr+qv1/1mnXUB3R746eZdAIDW33XvXd7ra1euWQB0o+lf8+SaJuFj/mf3zW4ICk9+edICoJsIkz8wNNCU9n02+pn3N0y/+t7JwxYAXUVoPlquCx/tf3zo8Yb3sAo/XP2hbjWKXiSyAAiR8uH7VULwX7z/hbPumXV1vw8heIAhVuPpPz9d+MDQAqBN0Kf6dqH3Xn7Pswo6MAAF4ED4Tzz/RCkqhRYALYSPhuuEkBf/cnGT8KkGSkyA8MUtFD0emFrEaFvMLK9hdN+iPo+RML8TRKpnEj73NP2m6U3Cx/SPDo82Cd8CIIbWSaoF41RGk1tfu3rN6bu3z+m9/TpIjn9yvKEQk/Y9mMDZu6I5qBsdGa1nCqrwxSVYAIQgNE4VuK5lphp72hYhyOy3on0v7/POus9H8BIQ2higTY4N83SBhyG0La1AK67wsQqb/rCp4T7EJUg6KG7MWgADqT4Thummv12KhlXY99K+RFOylHGp8UchtPu+Ffc1pIFCH772oXc/gEKyBZ5r8sSktQC62Rfhw9Cdv9sZuYzK9XrgFfUeogpfQGMSPlaBuETuS8Bc1PJwbgCAMcIcKazcMfeOyGZY3Ihejg1zDVO3cVyPXK9nAiJ8LBNFIAElz5d2sFpqF6BPrPDvwZ2DicaE2WhlmMDLlK4lIYT/+l9ed6b3TG8QfD1LGB61WYBK+px6WgQAsCQSfLVyGWl9vxSA1vx6TaBLKHLLWMcBQDScVcsUQmXsIHMbJ9Jvp/kcuJKgLKGopj83AFBGDWImhR2I6DquhlIoMjEdq5N2qxb3aNJ6Lw0cGS1k1J87AKSKZ/KhEjCd+vKUl1urhFDDBGym8fUiU5Z0dvys8/bw2w01AIJCGkcBReUBgFboU6gIf/bc2Z6gyJd1RvGZsCVVXSM7JXzub/9r+737l8ZRvlfmNmwWoBRQRDMkQhbhy3y6LjD+FidiJx7IWvjcM4Engie+MWUBBIFJy9aMmUUwmUsWgEDVxgmicrEEnNUUEc0hNtj64tbU4o20LVpQ34AIX54rbr1E1iHs/uPu1EGQeylYAj5Jl9AgCQARPn8nyg4bFKqMJi/PmlplNGg9QI8jfFXwUd1gqQAgghXfKeYT5uFTid6jpI1FyLkJBBF8nCxAF7wQ/IlrRQoNAAQOsiWnHtk6Ukd8nABObcDQA86sYwFpWokDQkAO2IOaSLNqhuk4AHhITDtMQvg8uCo0GAkT4pZq1bF4HeSb0xQ6Ez2cuV/SUJ6JgBDwYcXCCI94JUj48Cory9ZxAMA0hCsAUDtpRRPQ/DiFIGnV1hmXVs3fJBgE7t3v4DTjs4Z1A8Q6fZ/2Ga1AlilkLmkgjAPxRPeH3z9cF1qceXlVGKaJIGnfzoJauReeiRQ3rOYCFkBvsgJSIe0KAIhp1pslkxRsJNUyBmQnznb02RA8oI7qs7FSkv5iDRYuW1if18gi+CtMECian1T4QUzqRFMmUT+mHlDH9dXMJmIBGENMvgeAT7OtIOYOAIl+41oStCUtDQEsWAzOCLLduN+c+SaV71YnlQgaxe93onycKwC8Tp6Y/lmKREkKNaoVgfF5zd7RCSWWpNNt5LkCANMfJ9qHUWGE7wFg2cK2QKKJ09TgiXYDDtYklHkfoEIDIA6FjYrbTQZ5vXquj2WeIQwQAQFWAgBmseLn5tturg4AEE6WiyeJqtu5F5Z5RZlnYEzpPZQikF57iEPEEhApoF4Yy5py6wpOUpxp5Tpk+1Z1UqlVDBIXhFyHdXn2xWcTN5gCJqyKpMNZFa5MNOWRJY9sz8v8z5ozK9a1Pb09zqLli5ya+9/UX0ytl1+Xrl7qrN2y1pl///yOPguay3dznhyfdH7+8efo6eyZ894zASzGEpcTZ6woxO8F/DcPAKA1nZqo6SQl6QfUO5al2aRdp3MpLQDaUtT1comCqhun1gNPMeth6cqlK87R/UedGb0zvC4pxoJH/av7vddZWITcAEDu22lT3UlCcHFcAp9ldhHw4NoYQwXC919/7x2lBwBoL9OOmrECXVeL777/bufEwRORNVeWk3FG+ICAgzgBUKS11jA3AODTCNwI6LqZeL64IJBAELcw685Z9aAZYKUFgtwAAP3040+l+7EFBIIJvvztZa+OgFaGBQGCjEMAZ/zQ+PWWubmz6yCQeyktALy+ADdggpF5kphb3FK71PSdv7/jFX/4/KF3D9W7m6BW1wKCpFrLtRJbQHMWzPGmnksLAOjC5IWOrdrRiUCLLd+YCJo4PuEJMExmogpR5gvQUMAAmEVLTTFBnOxAJSyP8IvvSmoFct0ggpz30oVLsRoe1ZU4cSzPG399w+sjoAwrexWEEYy62sd0T0xSMXZQ3p70N4aoL6il56RVw9wsAJoGMzjDNDXICUOgv2dmj/P5ns+96xEeEzscQRYFoXz85sf1mUQ6cKgcEllzHx/s/iCUS+KzrYI6BIS/x++bglz+Pn5wPHZx554H7qmDsFarJeobyA0Am57fdF2IfoCEKaY2EGVvXa6VLdyn3DjF8+FXLl6pl1J1c//W395yzv37nPPwxoedx377WL3YIgUcBIeJbecG5J7PnTrnfWdQ4AZITCCQvD5uUMjUtfCJ+y0dAMj/0TqVoTAEAcEcgpuoqRbX4As5q9ejZQRuH735kQeUjb/fGChgAIF1CNJc/Tul/g9wVCBglgHZ1ctXnYPvHjSOJ/+OEw+kCYDOLw93b9zUqw/TmJdnYQhMabVIIoiIJZgFFJJmD0AQpuOY72M2jm7eMLOJEhOIy9Fb0LmeeQFiDVPPAXyI2keo70lADFWqGIDt1W+981aj30RTOaPJCA8zilsIk2vzea5b/qvl9egeQIif/u7r77zXlFdb+XjiEICw/5/7PYsQpVClf3bGzBleqsj3TvxrwrN6+rNgraK4Ap5PtWBSNi4FANBCk39GeGiKms7ANB4MBsokyLSeaYHCk+vRKK7RmzRkPPJmPoPJxjKYAk/+JtobxyWpvl7WKnjxiXvoGUCU+oBpG1syoaA4pFAuANTqJhgBYKLb+TB9HcFz/3iuCUAi8DDmVF1qBfNN5h6wcH8wGNCYfjcgKnGfJhcoP0LJdwV1F5lcmHQvJ6GOAAC/qG+kJPsBpNFsmaR3Xpio71qi9h1Kfg9YAbL4edm0QdY4moCmExZBdkFXSfZCBuiAj2vpEZSxTfGQtJAXGgCmbdl4OAKtOL10OqMZI2k7t96MGdSAUV8Maig+GXcGOWMGt9QhTBYl7A9PYk3S6B3MtBKItujC93bUfGlf7EZKfQo5KRNMa/HTWpDRyq8DAjQ4TjEo7JqI3CyA+DkTwmUj5Thj4gP1NrK4LkSaR3VAMV4UcMo4uvaLtWiXtsoS9jDxhaykTnOvgFQB4JmvZa178aNql7RhB7WRUwiJOh73F7QXYVh3gnVbsGxB4Dhh1y6o8YUsTiFVFUB5gHRzfdmDIO3ewKlJBS4alEaDpywVk7190hgTqyFLr8KMF8RgGYd7DDMBE1VQagNoJylRDCBbpkcRVKtqHAwGVFHGfPSZRwMFItYjynh8Xh9P9v1jjLCzb6ZxikiJLAD+KOoWLK2qcEzNerny7dFKwEG7gcmmEVG7j6XbRjXTccbhOYq+pjC3dQGWikH2dwMtACxZAFiyALBkAWDJAsCSBYClygFgzLKhsjQGAE5bPlSWTgOAY5YPlaVj1gVU3AXU+P+Op3b8xz3NtPyoFF3c9uq2WyQL2GP5UTnao6aBey0/KkeezGvyL9cNTLineZYv1Yj+XfM/X7UA0CuWL5WhuqxVAAwTGFjedH/w58u6EQCuSeCNEcufrqcRX9ZOQwxgY4Fq+X6TCxDaYvnUtdQk2yYAuAgZU32Epa6hYV+2TjsLAL3gHkctz7qGjvoybaJa0BVuLEAccMSxJeJuiPr7Xe0/bXozsCHEv2CVTQ1LL/xVQcJvaQEUS8CeLgesJSit8Fu68lqYkSwIulP4LV2A5g4YqN8GhqUJ+PrDCD80ALSYwKaIBU712vn8WC7A4BJWuqddjq0YFoUQ+BZTnp8JABQgbHdPgzY2yNXXU9vfHneAWtI7cEGA8IfcY7O1CB3VeKZ0h9WJnVwAoIFhg3ta7x4brFXIRNtp49rrCj21Fr5aVnfrp47ECkt8y7DSyjASjfmaTtv+WNioPir9T4ABAEQ10sB1PaP4AAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,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\"","import { connect } from 'react-redux';\nimport { manualAjaxEnd } from '../../actions/ajaxStatusActions';\nimport {\n checkForUpdatedBookFiles,\n getBookItemsList,\n initialDashboardQuery,\n searchBookBagBooks\n} from '../../actions/bookActions';\nimport { clearAdvancedSearchFilter } from '../../actions/bookbagFiltersActions';\nimport UserAPI from '../../api/userAPI';\nimport BookBagSearch from './BookBagSearch';\n\ninterface Iprops {\n query: typeof initialDashboardQuery;\n theme: any;\n isFiltersActive: boolean;\n handleInvalidSession: () => void;\n}\n\nconst mapStateToProps = (state: any, ownProps: Iprops) => {\n const showSearchBar =\n UserAPI.isStudent(state.user.RoleID) ||\n UserAPI.isGeneric(state.user.RoleID);\n return {\n loading: state.ajaxCallsInProgress > 0,\n books: state.books,\n downloadedBooks: state.downloadedBooks,\n isGeneric: UserAPI.isGeneric(state.user.RoleID),\n isStudent: UserAPI.isStudent(state.user.RoleID),\n user: state.user,\n isOnline: state.offlineQueue.isOnline && navigator.onLine,\n bookbagFilters: state.bookbagFilters,\n showSearchBar\n };\n};\n\nexport const BookBagSearchContainer = connect(mapStateToProps, {\n getBookItemsList,\n checkForUpdatedBookFiles,\n clearAdvancedSearchFilter,\n searchBookBagBooks: searchBookBagBooks,\n manualAjaxEnd: manualAjaxEnd\n})(BookBagSearch);\n","import { Col, Container, Row } from 'react-bootstrap';\nimport { StyledButton, StyledDiv } from '../../constants/styledComponents';\nimport {\n addBook,\n searchBookBagBooks,\n initialDashboardQuery,\n removeBook,\n downloadBook,\n deleteDownloadedBook\n} from '../../actions/bookActions';\nimport { addQuery, removeQuery } from '../../vendor/utils-router';\nimport { manualAjaxStart } from '../../actions/ajaxStatusActions';\n\nimport BookBagHeader from './BookBagHeader';\nimport Loading from '../common/Loading';\nimport React from 'react';\n\nimport config from '../../api/config';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants';\nimport defaultPhoto from '../../images/default.jpg';\nimport downloadedImage from '../../images/downloaded.png';\nimport { forEach } from 'lodash';\nimport { hashHistory } from 'react-router';\nimport { indexOf } from 'lodash';\n\nimport readBook from '../../images/read.png';\nimport { requireSignIn } from '../../routes';\n\nimport { sortBy } from 'lodash';\nimport { toastr } from 'react-redux-toastr';\nimport { toggleUserProfileModal } from '../../actions/dashboard/dashboardActions';\nimport unReadBook from '../../images/unread.png';\nimport { toggleClassCodeModal, userLogout } from '../../actions/userActions';\nimport UltimatePagination from 'react-ultimate-pagination-bootstrap-4';\nimport { BookBagSearchContainer } from './BookBagSearchContainer';\nimport UserAPI from '../../api/userAPI';\n\nlet bookState = unReadBook;\n\nclass BookBag extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n prevSelected: [],\n selectedTypes: [],\n selectedBookID: false,\n loading: false,\n emptySearchMessage:\n \"Please enter your search criteria above and press 'Go'\"\n };\n\n this.openingBook = false;\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n console.log('bookbag is mounted');\n // this.handleTypeChange(this.props.query.tag); // TODO what is this????\n // this.handleTypeChange(this.props.query.type);\n // remove the BLM ID and projectAssignmentID from query so that we do not stay in BLM mode when switching books\n removeQuery('blmID');\n removeQuery('projectAssignmentID');\n this.checkAddCode();\n this.checkCanAccessBookBag();\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.books !== this.props.books) {\n // set the appropriate empty search message. If this is the local bag and they have no search criteria, then they have no books in their bag\n let emptySearchMessage = '';\n if (this.props.books.length <= 0 && !this.filtersActive()) {\n emptySearchMessage = `You currently do not have any books in your book bag.`;\n }\n this.setState({ emptySearchMessage });\n }\n if (prevProps.query !== this.props.query) {\n this.setState({ prevSelected: [] });\n }\n }\n\n /*\n * only students, generic, and demo can access the bookbag. otherwise log them out\n */\n checkCanAccessBookBag = () => {\n if (this.props.user.SchoolID && (this.props.isStudent || this.props.isDemo || this.props.isGeneric) === false){\n toastr.warning('Warning', 'User does not have access to the bookbag. Logging out...', constants.toastrWarningOptions);\n setTimeout(() => {\n this.props.userLogout();\n hashHistory.replace('/');\n }, 5000);\n }\n\n\n }\n\n checkAddCode = () =>{\n console.log('checking addcode')\n if (this.props.addCode){\n setTimeout(() => {\n this.props.toggleClassCodeModal(true);\n }, 1000);\n }\n }\n\n handleBookClick = (e, book) => {\n if (e) {\n e.preventDefault();\n }\n if (this.state.selectedBookID === book.ID) {\n this.openBook(book);\n } else {\n this.setState({ selectedBookID: book.ID });\n }\n };\n\n openBook = (book) => {\n // prevent double click on open book\n // If we are offline:\n if (this.openingBook) return;\n\n this.openingBook = true;\n setTimeout(() => {\n this.openingBook = false;\n }, 300);\n\n if (book.IsExternal) {\n // open the book in the Lerner viewer, not in the DiBS viewer\n const externalURL = `${config.API.Main}/book/openexternalviewer?bookID=${book.ID}`;\n var win = window.open(externalURL, '_blank');\n win.focus();\n } else {\n // addQuery({bookID: book.ID});\n const location = Object.assign(\n {},\n hashHistory.getCurrentLocation()\n );\n Object.assign(location.query, { bookID: book.ID });\n hashHistory.push({\n pathname: `/viewer`,\n query: location.query\n });\n }\n };\n\n handleSubmit = (e, activePage) => {\n if (e) {\n e.preventDefault();\n }\n console.log(`initiating a bookbag search: ${this.props.query.search}`);\n addQuery({ activePage });\n this.props.searchBookBagBooks(this.filtersActive(), {\n ...this.props.query,\n activePage\n });\n };\n\n // are any book bag filters active? returns a boolean\n filtersActive = () => {\n if (\n this.props.query.search.length === 0 &&\n this.props.query.type.length === 0 &&\n this.props.query.tag.length === 0 &&\n this.props.query.grl.length === 0 &&\n this.props.bookbagFilters.length === 0\n ) {\n return false;\n } else {\n return true;\n }\n };\n\n handleInvalidSession = () => {\n toastr.error(\n `Please login again.`,\n `Session Expired`,\n constants.toastrErrorOptions\n );\n setTimeout(() => {\n this.props.userLogout();\n hashHistory.replace('/');\n }, 3000);\n };\n\n displayBookReadingLevel = (book) => {\n let grl, atos, lex;\n let hideBookReadingLevel = 'book-reading-level';\n if (\n book.GuidedReadingLevel === '' ||\n book.GuidedReadingLevel === null\n ) {\n grl = 'grl-hide';\n } else if (book.ATOS === '' || book.ATOS === null) {\n atos = 'atos-hide';\n } else if (book.LEX === '' || book.LEX === null) {\n lex = 'lex-hide';\n }\n\n if (!book.GuidedReadingLevel && !book.ATOS && !book.LEX) {\n hideBookReadingLevel = '';\n return;\n }\n\n return (\n
\n {book.ATOS !== null && book.ATOS !== '' && (\n A: {book.ATOS}, \n )}\n {book.LEX !== null && book.LEX !== '' && (\n L: {book.LEX}, \n )}\n {book.GuidedReadingLevel !== null &&\n book.GuidedReadingLevel !== '' && (\n \n GRL: {book.GuidedReadingLevel}\n \n )}\n
\n );\n };\n\n displayBookImage = (book) => {\n let img = !!book.OfficialImage ? book.OfficialImage : defaultPhoto;\n const bookTitle = book.Title;\n let downloadedIcon;\n forEach(this.props.downloadedBooks, (dlBook) => {\n if (book.ID === dlBook.ID) {\n downloadedIcon = downloadedImage;\n }\n });\n\n let photo = {\n backgroundImage: `url(${img})`,\n backgroundPosition: 'center center',\n backgroundSize: 'contain',\n backgroundRepeat: 'no-repeat'\n };\n if (!!book.OfficialImage) {\n return (\n
\n

{bookTitle}

\n this.handleBookClick(e, book)}\n >\n \n {book.IsExternal && (\n
\n \n
\n )}\n {this.displayBookReadingLevel(book)}\n
\n \n );\n } else {\n return (\n this.handleBookClick(e, book)}\n >\n \n {book.IsExternal && (\n
\n \n
\n )}\n

{bookTitle}

\n {this.displayBookReadingLevel(book)}\n \n );\n }\n };\n\n render() {\n if (requireSignIn(this.props.user, this.props.location)) {\n return null;\n }\n let books = !!this.props.books\n ? this.props.books.filter((book) => {\n return book;\n })\n : [];\n const downloadedBooks = this.props.downloadedBooks;\n let filteredBooks = this.props.isOnline\n ? sortBy(books, [\n function (o) {\n return o.Title;\n }\n ])\n : sortBy(downloadedBooks, [\n function (o) {\n return o.Title;\n }\n ]);\n\n return (\n \n \n \n\n {!this.props.isOnline && (\n \n \n You are offline\n \n \n )}\n \n {filteredBooks.length <= 0 && (\n \n
\n {this.state.emptySearchMessage}\n
\n \n )}\n {filteredBooks.map((book) => {\n let selected = 'd-none';\n let glow = 'book-cover book-shadow';\n let bookHeight = '';\n\n if (this.state.selectedBookID === book.ID) {\n selected = 'visible animated fadeInDown';\n bookHeight = ' pulse raise-book';\n glow = 'book-cover glow';\n if (book.CurrentPage !== null && book.CurrentPage !== 1) {\n bookState = readBook;\n }\n } else if (\n indexOf(this.state.prevSelected, book.ID) !== -1\n ) {\n bookHeight = ' ';\n }\n if (book.CurrentPage !== null && book.CurrentPage !== 1) {\n bookState = readBook;\n } else {\n bookState = unReadBook;\n }\n const isDownloaded = this.props.downloadedBooks.find(\n (downloadedBook) => downloadedBook.ID === book.ID\n )\n ? true\n : false;\n return (\n \n
\n
\n {this.displayBookImage(book)}\n \"\"\n
\n
\n this.openBook(book)}\n >\n READ\n \n {book.isInBookBag === true &&\n isDownloaded === false && (\n \n this.props\n .downloadBook(book)\n .then(() => {\n toastr.success('Succcess', 'Book downloaded for viewing offline.', constants.toastrSuccessOptions)\n })\n }\n >\n \n DOWNLOAD\n \n \n )}\n {book.isInBookBag === true &&\n isDownloaded === true && (\n \n this.props.deleteDownloadedBook(\n book.ISBN\n )\n }\n >\n \n REMOVE DOWNLOAD\n \n \n )}\n\n {book.isInBookBag === false && (\n \n this.props.addBook(book)\n }\n >\n \n ADD TO BOOK BAG\n \n \n )}\n {book.IsStudentAdded === true &&\n book.isInBookBag === true && (\n \n this.props.removeBook(\n book.ID, book.ISBN\n )\n }\n >\n \n REMOVE FROM BAG\n \n \n )}\n
\n
\n \n );\n })}\n
\n {this.props.books.length > 0 && (\n \n \n \n \n this.handleSubmit('', pageNumber)\n }\n />\n \n \n \n )}\n \n
\n );\n }\n}\n\nfunction mapStateToProps(state, ownProps) {\n const addCode = ownProps.location.query.addCode || ownProps.location.query.addcode || ownProps.location.query.AddCode;\n return {\n completedBLMs: state.completedBLMs,\n user: state.user,\n book: state.book,\n books: state.books,\n bookbagFilters: state.bookbagFilters,\n loading: state.ajaxCallsInProgress > 0,\n isOnline: state.offlineQueue.isOnline && navigator.onLine,\n downloadedBooks: state.downloadedBooks,\n pageResults: state.dashboardPageResults,\n query: { ...initialDashboardQuery, ...ownProps.location.query },\n addCode,\n isGeneric: UserAPI.isGeneric(state.user.RoleID),\n isStudent: UserAPI.isStudent(state.user.RoleID),\n isDemo: UserAPI.isDemo(state.user.RoleID)\n };\n}\n\nexport default connect(mapStateToProps, {\n addBook,\n removeBook,\n searchBookBagBooks,\n userLogout,\n manualAjaxStart,\n toggleUserProfileModal,\n downloadBook,\n deleteDownloadedBook,\n toggleClassCodeModal\n})(BookBag);\n","export default \"data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMqaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0MiA3OS4xNjA5MjQsIDIwMTcvMDcvMTMtMDE6MDY6MzkgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NEMwMzFGOTFCQjQxMTFFN0I4OEI5RDQ3NkJDREEyODEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NEMwMzFGOTJCQjQxMTFFN0I4OEI5RDQ3NkJDREEyODEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0QzAzMUY4RkJCNDExMUU3Qjg4QjlENDc2QkNEQTI4MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0QzAzMUY5MEJCNDExMUU3Qjg4QjlENDc2QkNEQTI4MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv/uAA5BZG9iZQBkwAAAAAH/2wCEAAYEBAQFBAYFBQYJBgUGCQsIBgYI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P6kqf95b/qIRG/hgvILr3Y5D7rhHWRN/5Un4WItbz4gamjsW3VDYaFohhqZ2QxRNPhDAC8j1ZsqJGJ8MJI05fCPEVTP6pCoJV/EBuVFVzRNq6fLHI5o/s8fgHEIuK5udwqblcKm4VRDqmrkdNM5oDQXvOY4AeHEorGQEBAQEBAQEBB6jkkie2SNxY9pxa9pIII8wQgkLtf6lqmUVLeayW72ujkbL93VUjzFJlOIbIQQ9w9ZQxe2k/iK0bWRxUt1ppLJK0BjSB3aYAcBg5gDmj1s4elGcWdR3Cx363PdST09yoJ2lkmRzZY3NcOLXAY+I8iiOVNffbNF6zqrTYLtIbdSTGppKdkpkjgfKwtcxzDizOwOLfDHBGogaKIOg9j9c6QsuhJKG63ano6t1TM8QyuIdlc1oB4DzwRmxz675x9aNPiDoLcLXOkLhs9HaKO7U89ybTUTDSscS/NHkzjDD8XAokjzuhrjSNz2mhtVBdYKm4tZRA0zHEvxjy5+GHlghFbbNanpNO68o6yumbT0EzJKeqmeSGta9pLScPptCFb34gNaWrUd/t0Noq2VlvoaYnvRklvemf749jWNQjffD7rHSthsd2gvVzhoZZ6ljo2SuILmiPAkcPShW6fYfhsle6R1bSlzyXOJqphxJxP4yJ6q3VFl0CKi9z2mvDYoJnNtkMcmdjmNjaW/OBc7O4u8+GCKgqKICAgICAgICAgICDKt91ultm79urJ6KbDDu08j4nYejMwgoMZznPcXvJc5xJc4nEknxJKD4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPuR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkgZH9J5IGR/SeSBkf0nkg/9k=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAAuCAYAAACMAoEVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjlGMzQyRjE5MUY5QzExRTdBRDNGOUNDNTU1NTlENzcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjlGMzQyRjFBMUY5QzExRTdBRDNGOUNDNTU1NTlENzcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OUYzNDJGMTcxRjlDMTFFN0FEM0Y5Q0M1NTU1OUQ3NzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OUYzNDJGMTgxRjlDMTFFN0FEM0Y5Q0M1NTU1OUQ3NzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4QtWyDAAAHI0lEQVR42tSZ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\"","import { Container, Nav, NavItem, Navbar } from 'react-bootstrap';\nimport { ToastContainer, ToastMessage } from 'react-toastr';\nimport {\n manualAjaxEnd,\n manualAjaxStart\n} from '../../actions/ajaxStatusActions';\nimport {\n userLogout,\n userUpdatePW,\n userUpdateProfile\n} from '../../actions/userActions';\n\nimport FabricUI from './FabricUI';\nimport FontAwesome from 'react-fontawesome';\nimport React from 'react';\nimport { StyledNavbar } from '../../constants/styledComponents';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants';\nimport { hashHistory } from 'react-router';\nimport logo from '../../images/logo.png';\nimport { requireSignIn } from '../../routes';\n\nconst ToastMessageFactory = React.createFactory(ToastMessage.animation);\n\nclass BLMView extends React.Component {\n toastCont;\n\n constructor(props) {\n super(props);\n this.state = {};\n\n this.handleSelect = this.handleSelect.bind(this);\n this.theme = constants.themeProvider.activeTheme;\n }\n\n signOut() {\n this.props.userLogout();\n hashHistory.push('/login');\n }\n\n handleSelect(e) {\n switch (e) {\n case 2:\n this.signOut();\n break;\n default:\n }\n }\n\n render() {\n if (requireSignIn(this.props.user, this.props.location)) {\n return null;\n }\n\n return (\n \n \n \n \n \"\"\n \n \n \n \n \n \n \n {\n // \n }\n {\n this.toastCont = toast;\n }}\n className=\"toast-top-right\"\n />\n \n );\n }\n}\n\n/*\n \n*/\n\nfunction mapStateToProps(state, ownProps) {\n return {\n user: state.user,\n book: state.book,\n books: state.books,\n loading: state.ajaxCallsInProgress > 0\n };\n}\n\nexport default connect(mapStateToProps, {\n userUpdateProfile,\n userUpdatePW,\n userLogout,\n manualAjaxStart,\n manualAjaxEnd\n})(BLMView);\n","import React, { Component } from 'react';\nimport {\n manualAjaxEnd,\n manualAjaxStart\n} from '../../actions/ajaxStatusActions';\nimport { tokenLogin, userLogout } from '../../actions/userActions';\n\nimport { Container } from 'react-bootstrap';\nimport Loading from '../common/Loading';\nimport { Navbar } from 'react-bootstrap';\nimport { StyledNavbar } from '../../constants/styledComponents';\nimport { connect } from 'react-redux';\nimport constants from '../../constants/constants';\nimport { getBLMByID } from '../../actions/blmActions';\nimport { getBookByID } from '../../actions/bookActions';\nimport { hashHistory } from 'react-router';\nimport logo from '../../images/logo.png';\nimport { toastr } from 'react-redux-toastr';\nimport { updateViewerMode } from '../../actions/modeActions';\nimport { viewerModes } from '../../constants/viewerModes';\n\n/*\n *** IMPORTANT ***\n - Tokens are only applicable for web deployments\n - (will not be used for iOS and Android)\n *** IMPORTANT ***\n*/\n\nclass Token extends Component {\n constructor(props) {\n super(props);\n\n this.state = {\n showLoading: true\n };\n\n this.theme = constants.themeProvider.activeTheme;\n }\n\n componentDidMount() {\n console.log('opening book with token login');\n // return;\n let params = this.props.location.query;\n if (!params || !params.token) {\n // fail\n this.setState({ showLoading: false });\n toastr.error(\n `Error`,\n `Missing token/bookID, unable to load book`,\n constants.toastrWarningOptions\n );\n } else {\n // console.log(params);\n this.doLogin(params);\n }\n }\n\n doLogin = (params) => {\n this.props\n .userLogout()\n .then(() => {\n return this.props.tokenLogin(params.token);\n })\n .then((user) => {\n console.log('***USER', user.LoginID);\n if (user.APIKey === null) {\n toastr.error(\n `Error`,\n 'Unable to load book. Please contact support. User missing API Key.',\n constants.toastrWarningOptions\n );\n return;\n }\n // we need to account for multiple possibilities now...\n // if we have a bookID only, we should just load up the book\n if (params.viewerMode === viewerModes.MODE_GENERIC) {\n return this.props\n .getBookByID(params.bookID, user)\n .then((bookSaved) => {\n this.setState({ loading: false });\n // hashHistory.push('/viewer/' + params.bookID);\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n // TODO: error handling here?\n }\n // if we have a bookID and a studentID, we should load the book\n // and load the student's highlights\n else if (\n params.viewerMode ===\n viewerModes.MODE_TEACHER_VIEW_STUDENT_BOOK\n ) {\n console.log(\n 'TOKEN: LOADING TEACHER VIEW STUDENT HIHGLIGHTS'\n );\n return this.props\n .getBookByID(params.bookID, user)\n .then((bookSaved) => {\n this.setState({ loading: false });\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n // TODO: error handling here?\n } else if (\n params.viewerMode === viewerModes.MODE_TEACHER_CLASS_NOTES\n ) {\n console.log('TOKEN: LOADING TEACHER VIEW CLASS NOTES');\n return this.props\n .getBookByID(params.bookID, user)\n .then((bookSaved) => {\n this.setState({ loading: false });\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n // TODO: error handling here?\n } else if (\n params.viewerMode === viewerModes.MODE_TEACHER_GROUP_NOTES\n ) {\n console.log('TOKEN: LOADING TEACHER VIEW Group NOTES');\n return this.props\n .getBookByID(params.bookID, user)\n .then((bookSaved) => {\n this.setState({ loading: false });\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n // TODO: error handling here?\n }\n // if we have a blmID, we should load up the blm in admin\n // create template mode\n else if (\n params.viewerMode === viewerModes.MODE_ADMIN_CREATE_TEMPLATE\n ) {\n // TODO: load admin create mode\n return this.props\n .getBLMByID(params.blmID, user)\n .then((blmSaved) => {\n this.setState({ loading: false });\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n } else if (\n params.viewerMode === viewerModes.MODE_TEACHER_STUDENT_BLM\n ) {\n return this.props\n .getBLMByID(params.blmID, user)\n .then((blmSaved) => {\n this.setState({ loading: false });\n // hashHistory.push(`/viewer/${blmSaved.BookID}/${params.blmID}`);\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n } else if (params.viewerMode === viewerModes.MODE_RESOURCE) {\n return this.props\n .getBookByID(params.bookID, user)\n .then((bookSaved) => {\n this.setState({ loading: false });\n // hashHistory.push('/viewer/' + params.bookID);\n hashHistory.push({\n pathname: `/viewer`,\n query: this.props.location.query\n });\n });\n } else if (params.viewerMode === viewerModes.MODE_STUDENT) {\n hashHistory.push({\n pathname: `/bag?searchMode=local&tag=allTags`,\n query: ''\n });\n }\n })\n .catch((error) => {\n this.setState({ showLoading: false });\n console.error(\n `error logging in or loading book with token`,\n error\n );\n let message = `Unable to login or load book with token`;\n if (error === undefined) {\n message = `The provided login token is invalid.`;\n }\n toastr.error(`Error`, message, constants.toastrWarningOptions);\n });\n };\n\n render() {\n return (\n \n \n {' '}\n \n \n \"\"\n \n \n \n
\n \n
\n
\n );\n }\n}\n\nconst mapStateToProps = (state, ownProps) => {\n return {\n user: state.user,\n loading: state.ajaxCallsInProgress > 0\n };\n};\n\nexport default connect(mapStateToProps, {\n userLogout,\n tokenLogin,\n getBookByID,\n getBLMByID,\n updateViewerMode,\n manualAjaxStart,\n manualAjaxEnd\n})(Token);\n","import * as types from './actionTypes';\n\nexport function updateViewerMode(viewerMode) {\n return function (dispatch) {\n dispatch({ type: types.UPDATE_MODE_SUCCESS, viewerMode });\n };\n}\n","import * as React from 'react';\nimport { Route, IndexRoute } from 'react-router';\nimport App from './App';\nimport LoginForm from './components/auth/LoginForm';\nimport RegisterForm from './components/auth/RegisterForm';\nimport BookView from './components/bookview/BookView';\nimport BookBag from './components/bookbag/BookBag';\nimport BLMView from './components/blm/BLMView';\nimport Token from './components/auth/Token';\nimport { hashHistory } from 'react-router';\n\nexport const requireSignIn = (user, location) => {\n const redirect = `${location.pathname}${location.search}`;\n if (\n !user ||\n (user && !user.APIKey) ||\n (user && user.APIKey && user.APIKey.length === 0)\n ) {\n console.info('sign in required, redirecting user', redirect, user);\n hashHistory.push(`/?redirect=${redirect}`);\n return true;\n }\n return false;\n};\n\nexport default (\n \n \n \n \n \n {/* // All params for the BookBag are GET params... managed within the component */}\n \n \n {/* // All params for the Token component are GET params... managed within the component */}\n \n \n);\n","import config from '../api/config';\n\n/*\n * load state localStorage\n */\nexport const loadState = (key) => {\n var statePromise = new Promise((resolve, reject) => {\n try {\n const serializedState = localStorage.getItem(`state-${key}`);\n if (serializedState === null) {\n resolve(undefined);\n } else {\n resolve(JSON.parse(serializedState));\n }\n } catch (error) {\n console.error('Error loading state', error);\n resolve(undefined);\n }\n });\n return statePromise;\n};\n\n/*\n * Save state\n */\nexport const saveState = (key, state) => {\n try {\n const serializedState = JSON.stringify(state);\n localStorage.setItem(`state-${key}`, serializedState);\n } catch (error) {\n // ignore write error\n console.error('Error saving state', error);\n }\n};\n","import config from './config';\nimport { loadState } from '../store/localStorage';\n\nexport const CL_DEBUG = 1;\nexport const CL_VERBOSE = 2;\nexport const CL_INFO = 3;\nexport const CL_WARN = 4;\nexport const CL_ERROR = 5;\nexport const CL_CRITICAL = 6;\n\nexport class Logger {\n static log(severity, ...args) {\n return loadState('dibs').then((state) => {\n let text = { ...args };\n if (severity === CL_ERROR || severity === CL_CRITICAL) {\n text = { ...args, reduxStore: state };\n }\n var obj = {\n privateKey: config.Coralogix.key,\n applicationName: 'DiBS.' + config.Environment,\n subsystemName: config.Coralogix.subsystemName,\n computerName:\n state && state.user\n ? `${state.user.First} ${state.user.Last}`\n : 'not logged in',\n logEntries: [\n {\n timestamp: new Date().getTime(),\n severity: severity,\n text: text,\n category:\n state && state.user\n ? state.user.APIKey\n : 'no api key'\n }\n ]\n };\n\n return this.sendToCoralogix(obj);\n });\n }\n\n static sendToCoralogix(obj) {\n if (process.env.NODE_ENV !== 'production') {\n return true;\n }\n return fetch('https://api.coralogix.com/api/v1/logs', {\n method: 'POST',\n headers: new Headers({ 'content-type': 'application/json' }),\n body: JSON.stringify(obj)\n })\n .then(function (response) {\n return response.text();\n })\n .then(function (data) {\n return data;\n })\n .catch(function (ex) {\n // if logging fails... what can ya do?\n throw ex;\n });\n }\n}\n","import { map, pickBy, find } from 'lodash';\nimport * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nconst normalizeBook = (rawBook) => {\n return {\n ...initialState.book,\n ...pickBy(rawBook, (property) => property !== null)\n };\n};\n\n/*\n * Book Reducer\n */\nexport function bookReducer(state = initialState.book, action) {\n switch (action.type) {\n case types.FETCH_BOOK_SUCCESS:\n return normalizeBook(action.book);\n case types.FETCH_BOOK_FAILED: {\n return initialState.book;\n }\n case types.LOAD_BOOKS_SUCCESS:{\n const foundBook = find(action.books, {ID: state.ID})\n if (foundBook){\n return {...state, ...normalizeBook(foundBook)}\n }\n return state;\n }\n\n case types.LOAD_BOOK_SUCCESS:\n return Object.assign({}, state, action.book);\n\n case types.FETCH_BOOKITEMS_STUDENT_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n return Object.assign({}, state, {\n studentBookmarks: action.bookmarks,\n studentHighlights: action.highlights,\n studentNotes: action.notes\n });\n\n case types.FETCH_BOOKITEMS_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n return Object.assign({}, state, {\n bookmarks: action.bookmarks,\n highlights: action.highlights,\n notes: action.notes\n });\n\n case types.SAVE_BOOKITEM_BOOKMARK_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n let bookmarks = [];\n if (!state.bookmarks) {\n Object.assign({}, state, {\n bookmarks: bookmarks\n });\n }\n bookmarks = [\n ...state.bookmarks.filter(\n (bookmark) => bookmark.ID !== action.bookmark.ID\n ),\n Object.assign({}, action.bookmark)\n ];\n return Object.assign({}, state, {\n bookmarks: bookmarks\n });\n\n case types.SAVE_BOOKITEM_NOTE_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n let notes = [];\n if (!state.notes) {\n Object.assign({}, state, {\n notes: notes\n });\n }\n\n if (action.note.ID === undefined) {\n // this is for non-students who only save these notes locally - thus they never get a real ID\n notes = [\n ...state.notes.filter(\n (note) => note.TempID !== action.note.TempID\n ),\n Object.assign({}, action.note)\n ];\n } else {\n notes = [\n ...state.notes.filter((note) => note.ID !== action.note.ID),\n Object.assign({}, action.note)\n ];\n }\n notes.sort((a, b) => {\n return a.Page > b.Page;\n });\n return Object.assign({}, state, {\n notes: notes\n });\n\n case types.SAVE_BOOKITEM_HIGHLIGHT_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n return Object.assign({}, state, {\n highlights: action.highlights\n });\n\n case types.DELETE_BOOKITEM_BOOKMARK_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n return Object.assign({}, state, {\n bookmarks: state.bookmarks.filter(\n (bookmark) => bookmark.ID !== action.bookmark.ID\n )\n });\n\n case types.DELETE_BOOKITEM_NOTE_SUCCESS:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n\n return Object.assign({}, state, {\n notes: state.notes.filter((note) => note.ID !== action.note.ID)\n });\n // TODO do we need to support teachers deleting student notes?\n // case types.TEACHER_DELETE_BOOKITEM_NOTE_SUCCESS:\n // if (state.ID !== action.bookID){\n // return state;\n // }\n // return Object.assign({}, state, {\n // 'studentNotes': state.studentNotes.filter((note) => note.ID !== action.note.ID)\n // });\n\n // case types.UPDATE_BOOKSTATUS_SUCCESS:\n // if (state.ID !== action.bookID) {\n // return state;\n // } else {\n // // we send 0 when initially opening the book and -1 when closing it. Don't actually set this to the current page\n // if (action.pageIndex === 0 || action.pageIndex === -1){\n // action.pageIndex = state.currentPage ? state.currentPage : 0;\n // }\n // const book = Object.assign({}, state, { currentPage: action.pageIndex });\n // return Object.assign({}, state, book);\n // }\n\n case types.PURGE_TEMP_ID_NOTES:\n // when connecting back online, dispatch actions might have been triggered for a different book\n if (state.ID !== action.bookID) {\n return state;\n }\n return Object.assign({}, state, {\n notes: state.notes.filter((note) => !note.TempID)\n });\n\n case types.CACHE_BOOK_PAGE:\n // if (!state.cachedPages[action.page.pageKey].pageKey){\n const newCachedPage = Object.assign(\n {},\n state.cachedPages[action.page.pageKey],\n { ...action.page, pageReady: true }\n );\n return Object.assign({}, state, {\n cachedPages: {\n ...state.cachedPages,\n [action.page.pageKey]: newCachedPage\n }\n });\n // } else {\n // return state;\n // }\n case types.RESET_CACHED_BOOK_PAGES:\n return { ...state, cachedPages: {} };\n case types.NEXT_PAGE:\n return { ...state, currentPage: state.currentPage + 1 };\n case types.PREV_PAGE:\n return { ...state, currentPage: state.currentPage - 1 };\n case types.UPDATE_CURRENT_PAGE:\n return { ...state, currentPage: action.currentPage };\n case types.SET_BOOK_READY:\n return { ...state, bookIsReady: action.ready };\n case types.TOTAL_PAGE:\n return { ...state, pagecount: action.totalPage };\n case types.GET_SPEECH_MARKS:\n if (!state.cachedPages[action.pageKey]) {\n const newPage = Object.assign(\n {},\n { speechMarks: action.parsedMarks, pageReady: false }\n );\n const newCachedPages = {\n ...state.cachedPages,\n [action.pageKey]: newPage\n };\n return Object.assign({}, state, {\n cachedPages: newCachedPages\n });\n } else {\n return state;\n }\n case types.USER_LOGOUT_SUCCESS:\n return initialState.book;\n case types.RESET_BOOK:\n return initialState.book;\n\n default:\n return state;\n }\n}\n/*\n * Books Reducer\n */\nexport function booksReducer(state = initialState.books, action) {\n switch (action.type) {\n case types.LOAD_BOOKS_SUCCESS:\n return map(action.books, normalizeBook);\n case types.ADD_BOOK_TO_BOOKBAG_SUCCESS:\n // return [...state, normalizeBook(action.book)]; // don't do anything because the user will switch back and hit search again\n case types.REMOVE_BOOK_TO_BOOKBAG_SUCCESS:\n return state.filter((book) => book.ID !== action.bookID);\n case types.UPDATE_CURRENT_PAGE:\n let newBook = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!newBook) {\n return state;\n }\n return [\n ...state.filter((b) => {\n return b.ID !== action.bookID;\n }),\n Object.assign({}, newBook, { currentPage: action.currentPage })\n ];\n\n case types.USER_LOGOUT_SUCCESS:\n return initialState.books;\n\n default:\n return state;\n }\n}\n\n/*\n * Downloaded Books Reducer\n */\nexport function downloadedBooksReducer(\n state = initialState.downloadedBooks,\n action\n) {\n switch (action.type) {\n case types.DOWNLOADED_BOOK_SUCCESS:\n // filter the array for this book already on the array, it it is not there then add it\n console.error('why is it downloading')\n return [\n ...state.filter((db) => {\n return db.ID !== action.book.ID;\n }),\n Object.assign({}, normalizeBook(action.book))\n ];\n case types.LOAD_BOOKS_SUCCESS:{\n const newBooks = map(action.books, normalizeBook);\n return map(state, (book)=>{\n const foundNewBook = find(newBooks, {ID: book.ID});\n if (foundNewBook){\n return {...book, ...foundNewBook}\n } else {\n return book;\n }\n })\n }\n case types.DELETE_DOWNLOADED_BOOK: {\n return [...state.filter((db) => db.ISBN !== action.payload)];\n }\n\n case types.FETCH_BOOKITEMS_SUCCESS:\n let downloadedBook = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!downloadedBook) {\n return state;\n }\n downloadedBook = Object.assign({}, downloadedBook, {\n bookmarks: action.bookmarks,\n highlights: action.highlights,\n notes: action.notes\n });\n if (!downloadedBook.ID) {\n console.error(\n 'Error: undefined book ID in saving bookitem highlight.'\n );\n return state;\n }\n return [\n ...state.filter((b) => {\n return b.ID !== action.bookID;\n }),\n downloadedBook\n ];\n\n case types.SAVE_BOOKITEM_HIGHLIGHT_SUCCESS:\n let book = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!book) {\n return state;\n }\n book = Object.assign({}, book, { highlights: action.highlights });\n if (!book.ID) {\n console.error(\n 'Error: undefined book ID in saving bookitem highlight.'\n );\n return state;\n }\n\n // check to see if state has any length, if not return\n\n return [\n ...state.filter((b) => {\n return b.ID !== action.bookID;\n }),\n book\n ];\n\n case types.SAVE_BOOKITEM_NOTE_SUCCESS:\n let bookNote = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n // console.log('book note', bookNote, action.bookID, state)\n if (!bookNote || (bookNote && !bookNote.notes)) {\n return state;\n }\n let notes = [];\n if (action.note.ID === undefined) {\n // this is for non-students who only save these notes locally - thus they never get a real ID\n notes = [\n ...bookNote.notes.filter(\n (note) => note.TempID !== action.note.TempID\n ),\n Object.assign({}, action.note)\n ];\n } else {\n notes = [\n ...bookNote.notes.filter(\n (note) => note.ID !== action.note.ID\n ),\n Object.assign({}, action.note)\n ];\n }\n\n notes.sort((a, b) => {\n return a.Page > b.Page;\n });\n bookNote = Object.assign({}, bookNote, { notes: notes });\n\n return [\n ...state.filter((b) => {\n return b.ID !== action.bookID;\n }),\n bookNote\n ];\n\n case types.UPDATE_CURRENT_PAGE:\n let newBook = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!newBook) {\n return state;\n }\n return [\n ...state.filter((b) => {\n return b.ID !== action.bookID;\n }),\n Object.assign({}, newBook, { currentPage: action.currentPage })\n ];\n\n case types.DELETE_BOOKITEM_BOOKMARK_SUCCESS:\n // dlBookBookmark is a downloaded book object and in this use case, we are deleting a bookmark\n let dlBookBookmark = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!dlBookBookmark) {\n return state;\n }\n Object.assign({}, dlBookBookmark, {\n bookmarks: dlBookBookmark.bookmarks.filter(\n (bookmark) => bookmark.ID !== action.bookmark.ID\n )\n });\n if (!dlBookBookmark.ID) {\n console.error(\n 'Error: undefined book ID in saving bookitem highlight.'\n );\n return state;\n }\n // if something unexpected happens return state\n return state;\n\n case types.DELETE_BOOKITEM_NOTE_SUCCESS:\n // dlBookNote is a downloaded book object and in this use case, we are deleting the note\n let dlBookNote = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!dlBookNote) {\n return state;\n }\n\n if (action.note.ID === undefined) {\n // this is for non-students who only save these notes locally - thus they never get a real ID\n notes = [\n ...dlBookNote.notes.filter(\n (note) => note.TempID !== action.note.TempID\n ),\n Object.assign({}, action.note)\n ];\n } else {\n notes = [\n ...dlBookNote.notes.filter(\n (note) => note.ID !== action.note.ID\n ),\n Object.assign({}, action.note)\n ];\n }\n if (!dlBookNote.ID) {\n console.error(\n 'Error: undefined book ID in saving bookitem highlight.'\n );\n return state;\n }\n // if something unexpected happens, return state\n return state;\n\n case types.PURGE_TEMP_ID_NOTES:\n // dlPurgeTempNotes is a downloaded book object and in this use case, we are purging any temp ID's\n let dlPurgeTempNotes = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!dlPurgeTempNotes) {\n return state;\n }\n dlPurgeTempNotes = Object.assign({}, dlPurgeTempNotes, {\n notes: dlPurgeTempNotes.notes.filter((note) => !note.TempID)\n });\n\n return [\n ...state.filter((b) => {\n return b.ID !== action.bookID;\n }),\n dlPurgeTempNotes\n ];\n\n case types.DELETE_BOOKITEM_HIGHLIGHT_SUCCESS:\n // dlBookHighlight is a downloaded book object and in this use case, we are deleting the highlight\n let dlBookHighlight = state.filter((b) => {\n return b.ID === action.bookID;\n })[0];\n if (!dlBookHighlight) {\n return state;\n }\n return Object.assign({}, dlBookHighlight, {\n highlights: dlBookHighlight.highlights\n });\n\n case types.USER_LOGOUT_SUCCESS:\n return initialState.downloadedBooks;\n\n default:\n return state;\n }\n}\n\nexport function dashboardPageResultsReducer(state = 1, action) {\n switch (action.type) {\n case types.DASHBOARD_PAGE_RESULTS:\n if (action.pageResults && action.pageResults > 0) {\n return action.pageResults;\n }\n return state;\n case types.USER_LOGOUT_SUCCESS:\n return 1;\n default:\n return state;\n }\n}\n","import * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nfunction actionTypeEndsInSuccess(type) {\n return type.substring(type.length - 8) === '_SUCCESS';\n}\n\nfunction actionTypeEndsInFailed(type) {\n return type.substring(type.length - 7) === '_FAILED';\n}\n\nexport default function ajaxStatusReducer(\n state = initialState.ajaxCallsInProgress,\n action\n) {\n if (action.type === types.BEGIN_AJAX_CALL) {\n return state + 1;\n } else if (\n state >= 1 &&\n (actionTypeEndsInSuccess(action.type) ||\n actionTypeEndsInFailed(action.type))\n ) {\n return state - 1;\n } else if (state >= 1 && action.type === types.END_AJAX_CALL) {\n return state - 1;\n }\n\n return state;\n}\n","import { reducer as offlineQueue } from 'redux-queue-offline';\nimport { combineReducers } from 'redux';\nimport { routerReducer as routing } from 'react-router-redux';\nimport { reducer as toastr, ToastrState } from 'react-redux-toastr';\nimport user from './userReducer';\nimport { bookbagFiltersReducer as bookbagFilters } from './bookbagFiltersReducer';\nimport { dashboard } from './dashboardReducer';\n\nimport { reducer as jPlayers } from 'react-jplayer';\nimport {\n blmReducer as blm,\n blmsReducer as blms,\n completedBLMsReducer as completedBLMs\n} from './blmReducer';\nimport {\n bookReducer as book,\n booksReducer as books,\n downloadedBooksReducer as downloadedBooks,\n dashboardPageResultsReducer as dashboardPageResults\n} from './bookReducer';\nimport bookView from './bookViewReducer';\nimport { projectToolbar } from './projectToolbarReducer';\nimport bookToolbar from './bookToolbarReducer';\nimport ajaxCallsInProgress from './ajaxStatusReducer';\nimport viewerMode from './modeReducer';\nimport readium from './readiumReducer';\n\nconst rootReducer = combineReducers({\n appVersion: (state = {}) => state,\n offlineQueue,\n toastr,\n user,\n blms,\n completedBLMs,\n blm,\n book,\n books,\n downloadedBooks,\n routing,\n viewerMode,\n bookbagFilters,\n dashboard,\n ajaxCallsInProgress,\n jPlayers,\n projectToolbar,\n bookView,\n bookToolbar,\n dashboardPageResults,\n readium,\n});\n\nexport type IinitialState = ReturnType &\n { toastr: ToastrState };\n\nexport default rootReducer;\n","/*\n * Reducer for the user and user account\n */\n\nimport * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport default function userReducer(state = initialState.user, action) {\n switch (action.type) {\n case types.USER_LOGIN_SUCCESS:\n case types.USER_UPDATE_SUCCESS:\n case types.USER_UPDATE_PASSWORD_SUCCESS:\n const lastCheckSession = Date.now();\n return {...state, ...action.user, lastCheckSession}\n case types.USER_LOGOUT_SUCCESS:\n return initialState.user;\n\n default:\n return state;\n }\n}\n","import * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport function blmsReducer(state = initialState.blms, action) {\n switch (action.type) {\n case types.LOAD_BLMS_SUCCESS:\n return action.blms;\n\n default:\n return state;\n }\n}\n\nexport function completedBLMsReducer(\n state = initialState.completedBLMs,\n action\n) {\n switch (action.type) {\n case types.GET_COMPLETED_BLMS_SUCCESS:\n return action.completedBLMs;\n\n default:\n return state;\n }\n}\n\nexport function blmReducer(state = initialState.blm, action) {\n switch (action.type) {\n case types.FETCH_BLM_SUCCESS:\n return action.blm;\n\n case types.GET_BLM_ITEMS_SUCCESS:\n return Object.assign({}, state, {\n blmData: action.blmData,\n fabricItems: action.fabricItems,\n originalBLMTemplate: action.originalBLMTemplate\n });\n\n case types.SAVE_TEACHERS_COMMENT_SUCCESS:\n return Object.assign({}, state, {\n teachersComment: action.teachersComment\n });\n\n case types.GET_TEACHERS_BLM_COMMENT_SUCCESS:\n return Object.assign({}, state, {\n teachersComment: action.teachersComment\n });\n\n case types.GET_BLM_STATUS_SUCCESS:\n return Object.assign({}, state, {\n isComplete: action.isComplete\n });\n\n case types.SAVE_BLMITEM_FABRIC_SUCCESS:\n return Object.assign({}, state, {\n blmData: action.blmData\n });\n\n case types.UPDATE_STUDENT_ITEM_SUCCESS:\n return Object.assign({}, state, {\n fabricItemsStudent: action.fabricItemsStudent\n });\n case types.UPDATE_TEMPLATE_ITEM_SUCCESS:\n return Object.assign({}, state, {\n fabricItemsTemplate: action.fabricItemsTemplate\n });\n\n case types.UPDATE_BLM_STATUS_SUCCESS:\n return Object.assign({}, state, {\n isComplete: action.isComplete\n });\n\n case types.REMOVE_BLM_DATA_SUCCESS:\n return action.blm;\n case types.SET_PROJECT_READY:\n return { ...state, projectIsReady: action.ready };\n\n case types.USER_LOGOUT_SUCCESS:\n return initialState.blms;\n\n default:\n return state;\n }\n}\n","import * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport default function modeReducer(state = initialState.viewerMode, action) {\n switch (action.type) {\n case types.UPDATE_MODE_SUCCESS:\n return action.viewerMode;\n\n case types.USER_LOGOUT_SUCCESS:\n return initialState.viewerMode;\n\n default:\n return state;\n }\n}\n","import * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport function bookbagFiltersReducer(\n state = initialState.bookbagFilters,\n action\n) {\n switch (action.type) {\n case types.SAVE_ADVANCED_SEARCH_FILTERS:\n return { ...state, ...action.filters };\n // return Array.from(new Set(action.filters.tags));\n case types.CLEAR_ADVANCED_SEARCH_FILTERS:\n return initialState.bookbagFilters;\n case types.USER_LOGOUT_SUCCESS:\n return initialState.bookbagFilters;\n\n default:\n return state;\n }\n}\n","/*\n * This reducer contains all the visual state of the dashboard\n */\n\nimport * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport function dashboard(state = initialState.dashboard, action) {\n switch (action.type) {\n case types.TOGGLE_USER_PROFILE_MODAL:\n return {\n ...state,\n showUserProfileModal: !state.showUserProfileModal\n };\n\n case types.TOGGLE_LOGGOUT_CONFIRM_MODAL:\n return {\n ...state,\n showLoggoutConfirmModal: !state.showLoggoutConfirmModal\n };\n case types.TOGGLE_CLASS_CODE_MODAL:\n let showClassCodeModal = !state.showClassCodeModal;\n if (action.show && typeof action.show === 'boolean'){\n showClassCodeModal = action.show;\n }\n return {\n ...state,\n showClassCodeModal\n };\n case types.USER_LOGOUT_SUCCESS:\n return initialState.dashboard;\n\n default:\n return state;\n }\n}\n","import * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport function projectToolbar(state = initialState.projectToolbar, action) {\n switch (action.type) {\n case types.TOOLBAR_ERASER_ON:\n return Object.assign({}, state, action.projectToolbar);\n case types.TOOLBAR_POINTER_ON:\n return Object.assign({}, state, action.projectToolbar);\n case types.TOOLBAR_DRAWING_MODE_ON:\n return Object.assign({}, state, action.projectToolbar);\n case types.TOOLBAR_ADD_TEXT_ON:\n return Object.assign({}, state, action.projectToolbar);\n case types.SHOW_RICH_TEXT_BUTTONS:\n return Object.assign({}, state, action.projectToolbar);\n default:\n return state;\n }\n}\n","/*\n * This reducer contains all the visual state of the viewer\n */\n\nimport * as types from '../actions/actionTypes';\nimport initialState from './initialState';\nimport constants from '../constants/constants';\n\nexport default function bookViewReducer(state = initialState.bookView, action) {\n // dispatch all redux events as document events - probably a bad idea\n document.dispatchEvent(new CustomEvent(action.type, {detail: action}))\n switch (action.type) {\n case types.USER_LOGOUT_SUCCESS:\n return initialState.bookView;\n case types.RESET_VIEW:\n return initialState.bookView;\n case types.UPDATE_BOOK_SCALE_PERCENT:\n return { ...state, bookScalePercent: action.scale };\n case types.UPDATE_PROJECT_SCALE_PERCENT:\n return { ...state, projectScalePercent: action.scale };\n case types.UPDATE_LEFT_PAGE_CONTAINER:\n return {\n ...state,\n leftPageContainerWidth: action.width,\n leftPageContainerHeight: action.height\n };\n case types.UPDATE_PAGES_VISIBLE:\n return { ...state, pagesVisible: action.pagesVisible };\n case types.AUTOMATIC_UPDATE_PAGES_VISIBLE:\n if (state.automaticUpdatedPagesVisible) {\n return state;\n }\n return {\n ...state,\n pagesVisible: action.pagesVisible,\n automaticUpdatedPagesVisible: true\n };\n\n case types.BOOK_TOOLBAR_UPDATE_MODE:\n return { ...state, bookToolbar: action.bookToolbar };\n case types.SET_ACTIVE_NOTE:\n return { ...state, activeNoteID: action.noteID };\n case types.INCREASE_BOOK_ZOOM:\n const newZoomLevelIndex = state.bookManualZoomIndex + 1;\n const newZoomLevel = constants.bookZoomLevels[newZoomLevelIndex];\n if (newZoomLevel === undefined) {\n return state;\n }\n if (\n newZoomLevelIndex === initialState.bookView.bookManualZoomIndex\n ) {\n return {\n ...state,\n bookManualZooming: false,\n bookManualZoomIndex: newZoomLevelIndex,\n bookManualZoomLevel: newZoomLevel / 100\n };\n } else {\n return {\n ...state,\n bookManualZooming: true,\n bookManualZoomIndex: newZoomLevelIndex,\n bookManualZoomLevel: newZoomLevel / 100\n };\n }\n case types.DECREASE_BOOK_ZOOM:\n const newZoomLevelIndexD = state.bookManualZoomIndex - 1;\n const newZoomLevelD = constants.bookZoomLevels[newZoomLevelIndexD];\n if (newZoomLevelD === undefined) {\n return state;\n }\n if (\n newZoomLevelIndexD === initialState.bookView.bookManualZoomIndex\n ) {\n return {\n ...state,\n bookManualZooming: false,\n bookManualZoomIndex: newZoomLevelIndexD,\n bookManualZoomLevel: newZoomLevelD / 100\n };\n } else {\n return {\n ...state,\n bookManualZooming: true,\n bookManualZoomIndex: newZoomLevelIndexD,\n bookManualZoomLevel: newZoomLevelD / 100\n };\n }\n case types.UPDATE_PENDING_ITEM:\n return { ...state, itemSavePending: action.status };\n\n // case types.BOOK_UPDATE_AUDIO:\n // return { ...state, audioUrl: action.audioUrl}\n\n default:\n return state;\n }\n}\n","/*\n * This reducer contains all the state for managing the book toolbar\n */\n\nimport * as types from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport default function bookToolbar(state = initialState.bookToolbar, action) {\n switch (action.type) {\n case types.USER_LOGOUT_SUCCESS:\n return initialState.bookToolbar;\n case types.BOOK_TOOLBAR_POINTING:\n return initialState.bookToolbar;\n case types.BOOK_TOOLBAR_NOTES:\n return {\n ...initialState.bookToolbar,\n allowNotes: action.allowNotes,\n pointing: false,\n pagesClassName: 'note-mode'\n };\n case types.BOOK_TOOLBAR_HIGHLIGHTING:\n return {\n ...initialState.bookToolbar,\n highlighting: action.highlighting,\n highlightColor: action.highlightColor,\n pointing: false,\n pagesClassName: `hl-mode-${action.highlightColor}`\n };\n case types.BOOK_TOOLBAR_ERASING:\n return {\n ...initialState.bookToolbar,\n erasing: action.erasing,\n pointing: false,\n pagesClassName: 'eraser-mode'\n };\n case types.BOOK_TOOLBAR_UNDERLINING:\n return {\n ...initialState.bookToolbar,\n underlining: action.underlining,\n pointing: false,\n pagesClassName: 'hl-underline'\n };\n case types.BOOK_TOOLBAR_STRIKING:\n return {\n ...initialState.bookToolbar,\n striking: action.striking,\n pointing: false,\n pagesClassName: 'hl-strikethrough'\n };\n case types.BOOK_TOOLBAR_UPDATE_MODE:\n return { ...state, bookToolbar: action.bookToolbar };\n case types.BOOK_TOOLBAR_MOVING:\n return {\n ...initialState.bookToolbar,\n moving: true,\n pointing: true,\n pagesClassName: 'move-mode'\n };\n default:\n return state;\n }\n}\n","import { READIUM_INITIALIZED } from '../actions/actionTypes';\nimport initialState from './initialState';\n\nexport default function readiumReducer(state = initialState.readium, action) {\n switch (action.type) {\n case READIUM_INITIALIZED:\n return { ...state, readiumClass: action.readiumClass };\n default:\n return state;\n }\n}\n","import { IinitialState } from '../reducers/index';\nimport initialState from '../reducers/initialState';\n\n/*\n * Migration 1 runs when upgrading from 0 to 1\n */\n\nconst typedMigrations = {\n 162: (state: IinitialState): IinitialState => {\n console.log('running migration 162', state.appVersion);\n try {\n const serializedState = localStorage.getItem(`state-dibs`);\n if (serializedState !== null) {\n console.log(\"migrating previous state\")\n localStorage.removeItem('state-dibs');\n return {\n ...JSON.parse(serializedState),\n ...state\n };\n }\n } catch {\n console.log('no previous state');\n }\n const { downloadedBooks } = initialState;\n return {\n ...state,\n downloadedBooks\n };\n }\n} as { [key: number]: (state: IinitialState) => IinitialState };\n\nconst untypedMigrations = typedMigrations as any;\nexport const migrations = untypedMigrations;\n","import { middleware as offlineQueueMiddleware } from 'redux-queue-offline';\nimport { createStore, applyMiddleware, compose } from 'redux';\nimport rootReducer from '../reducers';\nimport thunk from 'redux-thunk';\nimport * as createMigration from 'redux-persist-migrate';\nimport initialState from '../reducers/initialState';\nimport {persistStore, autoRehydrate} from 'redux-persist';\n\nimport {\n saveBookItem,\n updateBookStatus,\n deleteBookItem\n} from '../actions/bookActions';\nimport { saveBLMItem } from '../actions/blmActions';\nimport { composeWithDevTools } from 'redux-devtools-extension/developmentOnly';\nimport BookFS from '../api/bookFS';\nimport { migrations } from './migrations';\n\nexport const persistConfig = {\n // keyPrefix: 'dibs',\n debounce: 300,\n storage: BookFS.fs,\n blacklist: ['showEditProfileModal', 'ajaxCallsInProgress', 'toastr']\n // transforms: [createTransform(encode, decode)]\n};\n// see https://github.com/diegoddox/react-redux-toastr/issues/249 about blacklisting toastr\nconst migration = createMigration.default(migrations, 'appVersion');\n\nconst offlineActionCreators = {\n saveBookItem: saveBookItem,\n updateBookStatus: updateBookStatus,\n deleteBookItem: deleteBookItem,\n saveBLMItem: saveBLMItem\n};\n\n\nexport const configureStore = (persistCallback) => {\n if (process.env.NODE_ENV !== 'production') {\n // if (false){ // comment in for testing localling without redux dev tools\n\n const store = createStore(\n rootReducer,\n initialState,\n composeWithDevTools(\n applyMiddleware(\n offlineQueueMiddleware(\n 'offlineQueue',\n ['payload.promise'],\n offlineActionCreators\n ),\n thunk\n ),\n compose(autoRehydrate(), migration) // , require('redux-immutable-state-invariant').default()\n )\n );\n const persistor = persistStore(store, persistConfig, persistCallback);\n return {store, persistor};\n } else {\n const store = createStore(\n rootReducer,\n initialState,\n compose(applyMiddleware(\n offlineQueueMiddleware(\n 'offlineQueue',\n ['payload.promise'],\n offlineActionCreators\n ),\n thunk,\n ),\n autoRehydrate(), migration)\n );\n const persistor = persistStore(store, persistConfig, persistCallback);\n return {store, persistor};\n }\n}\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://cra.link/PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://cra.link/PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then((registration) => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://cra.link/PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch((error) => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' }\n })\n .then((response) => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null &&\n contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then((registration) => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready\n .then((registration) => {\n registration.unregister();\n })\n .catch((error) => {\n console.error(error.message);\n });\n }\n}\n","const reportWebVitals = (onPerfEntry) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(\n ({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n }\n );\n }\n};\n\nexport default reportWebVitals;\n","import { READIUM_INITIALIZED } from './actionTypes';\n\nexport const readiumInitialized = (readiumClass) => {\n return { type: READIUM_INITIALIZED, readiumClass };\n};\n","/* eslint-disable */\nimport * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport constants from './constants/constants';\n\nimport { NetworkListener } from './utilities/NetworkListener';\nimport { Provider } from 'react-redux';\nimport { Router, hashHistory } from 'react-router';\nimport routes from './routes';\nimport { Logger, CL_WARN, CL_ERROR } from './api/logger';\nimport config from './api/config';\nimport ReduxToastr from 'react-redux-toastr';\nimport {configureStore} from './store/configureStore';\n\nimport 'whatwg-fetch';\n// import 'bootstrap/dist/css/bootstrap.min.css';\nimport 'font-awesome/css/font-awesome.min.css';\nimport './App.scss';\nimport 'bootstrap/dist/js/bootstrap.min.js';\nimport './vendor/animate.min.css';\nimport './vendor/toastr.min.css';\nimport './vendor/reactReduxToaster.min.css';\nimport './vendor/fonts.css';\nimport * as serviceWorkerRegistration from './serviceWorkerRegistration';\nimport reportWebVitals from './reportWebVitals';\nimport { readiumInitialized } from './actions/readiumActions';\n\n// print version\nconsole.log(\n `***** Version: ${config.Version} **** Environment: ${config.Environment}`\n);\n\nconst NetworkListenerProvider = NetworkListener(Provider);\n\nconstants.themeProvider\n.initTheme()\n\nclass IndexClass extends React.Component {\n constructor(props) {\n super(props);\n this.state = { isRehydrated: false };\n const {store, persistor} = configureStore(() => {\n this.setState({ isRehydrated: true });\n });\n this.store = store;\n this.persistor = persistor;\n this.listenToReadiumInit();\n }\n render() {\n if (!this.state.isRehydrated) {\n return null;\n }\n return (\n // \n \n
\n \n \n
\n
\n //
\n );\n }\n\n listenToReadiumInit() {\n if (window.readiumClass) {\n this.store.dispatch(readiumInitialized(window.readiumClass));\n return;\n }\n const handler = (ev) => {\n if (ev.data === 'readium-initialized') {\n window.removeEventListener('message', handler);\n this.store.dispatch(readiumInitialized(window.readiumClass));\n }\n };\n window.addEventListener('message', handler);\n }\n}\n\nReactDOM.render(\n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://cra.link/PWA\nserviceWorkerRegistration.register({\n onUpdate: (registration) => {\n document.dispatchEvent(new Event('newVersionAvailable'));\n if (registration && registration.waiting) {\n registration.waiting.postMessage({ type: 'SKIP_WAITING' });\n }\n }\n});\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n\nwindow.console = (function (origConsole) {\n if (!window.console || !origConsole) origConsole = {};\n var isDebug = false,\n logArray = {\n logs: [],\n errors: [],\n warns: [],\n infos: []\n };\n return {\n log: function () {\n logArray.logs.push(arguments);\n // Logger.log(CL_DEBUG, ...arguments);\n isDebug &&\n origConsole.log &&\n origConsole.log.apply(origConsole, arguments);\n },\n warn: function () {\n logArray.warns.push(arguments);\n Logger.log(CL_WARN, ...arguments);\n isDebug &&\n origConsole.warn &&\n origConsole.warn.apply(origConsole, arguments);\n },\n error: function () {\n logArray.errors.push(arguments);\n Logger.log(CL_ERROR, ...arguments);\n isDebug &&\n origConsole.error &&\n origConsole.error.apply(origConsole, arguments);\n },\n info: function (v) {\n logArray.infos.push(arguments);\n // Logger.log(CL_INFO, ...arguments);\n isDebug &&\n origConsole.info &&\n origConsole.info.apply(origConsole, arguments);\n },\n debug: function (bool) {\n isDebug = bool;\n },\n logArray: function () {\n return logArray;\n }\n };\n})(window.console);\nwindow.console.debug(true);\n","import * as React from 'react';\nimport { ONLINE, OFFLINE } from 'redux-queue-offline';\n\nexport const NetworkListener = (Provider) => {\n return class NetworkListenerComponent extends React.Component {\n defaultProps = { store: {} };\n componentDidMount() {\n if (window && window.addEventListener) {\n window.addEventListener('online', this._onlineListener);\n window.addEventListener('offline', this._offlineListener);\n }\n }\n componentWillUnmount() {\n if (window && window.removeEventListener) {\n window.removeEventListener('online', this._onlineListener);\n window.removeEventListener('offline', this._offlineListener);\n }\n }\n render() {\n return React.createElement(Provider, this.props);\n }\n _onlineListener = () => {\n this.props.store.dispatch({\n type: ONLINE\n });\n };\n _offlineListener = () => {\n this.props.store.dispatch({\n type: OFFLINE\n });\n };\n };\n};\n"],"sourceRoot":""}