@@ -47,7 +47,7 @@ import {
4747import { HintsAssistant } from "./Hints" ;
4848import Toggle from 'react-toggle'
4949import "react-toggle/style.css"
50- import { feedbackContentStyle , FeedbackModal } from "./Feedback" ;
50+ import { ErrorBoundary , FeedbackMenuButton } from "./Feedback" ;
5151import birdseyeIcon from "./img/birdseye_icon.png" ;
5252import languageIcon from "./img/language.png" ;
5353import { interrupt , runCode , terminalRef } from "./RunCode" ;
@@ -427,59 +427,73 @@ const CourseText = (
427427
428428class AppComponent extends React . Component {
429429 render ( ) {
430- const {
431- editorContent,
432- assistant,
433- specialMessages,
434- questionWizard,
435- pages,
436- user,
437- prediction,
438- route,
439- previousRoute,
440- running,
441- } = this . props ;
442- if ( route === "toc" ) {
430+ if ( this . props . route === "toc" ) {
443431 return < TableOfContents />
444432 }
445- const isQuestionWizard = route === "question" ;
446- const fullIde = route === "ide" ;
447-
448- const page = currentPage ( ) ;
449- const step = currentStep ( ) ;
450-
451- let showEditor , showSnoop , showPythonTutor , showBirdseye , showQuestionButton ;
452- if ( fullIde || isQuestionWizard ) {
453- showEditor = true ;
454- showSnoop = true ;
455- showPythonTutor = true ;
456- showBirdseye = true ;
457- showQuestionButton = ! ( isQuestionWizard || previousRoute === "question" ) ;
458- } else if ( step . text . length ) {
459- showEditor = page . index >= pages . WritingPrograms . index ;
460- const snoopPageIndex = pages . UnderstandingProgramsWithSnoop . index ;
461- showSnoop = page . index > snoopPageIndex ||
462- ( page . index === snoopPageIndex && step . index >= 1 ) ;
463- showPythonTutor = page . index >= pages . UnderstandingProgramsWithPythonTutor . index ;
464- showBirdseye = page . index >= pages . IntroducingBirdseye . index ;
465- showQuestionButton = page . index > pages . IntroducingBirdseye . index ;
466- }
467433
468- const cantUseEditor = prediction . state === "waiting" || prediction . state === "showingResult" ;
469434 return < div className = "book-container" >
470- < nav className = "navbar navbar-expand-lg navbar-light bg-light" >
435+ < NavBar user = { this . props . user } />
436+ < ErrorBoundary canGiveFeedback >
437+ < AppMain { ...this . props } />
438+ </ ErrorBoundary >
439+ </ div >
440+ }
441+ }
442+
443+ function NavBar ( { user} ) {
444+ return < nav className = "navbar navbar-expand-lg navbar-light bg-light" >
471445 < span className = "nav-item custom-popup" >
472446 < MenuPopup user = { user } />
473447 </ span >
474- < span className = "nav-item navbar-text" >
448+ < span className = "nav-item navbar-text" >
475449 < HeaderLoginInfo email = { user . email } />
476450 </ span >
477- < a className = "nav-item nav-link" href = "#toc" >
478- < FontAwesomeIcon icon = { faListOl } /> { terms . table_of_contents }
479- </ a >
480- </ nav >
451+ < a className = "nav-item nav-link" href = "#toc" >
452+ < FontAwesomeIcon icon = { faListOl } /> { terms . table_of_contents }
453+ </ a >
454+ </ nav > ;
455+ }
456+
457+ function AppMain (
458+ {
459+ editorContent,
460+ assistant,
461+ specialMessages,
462+ questionWizard,
463+ pages,
464+ user,
465+ prediction,
466+ route,
467+ previousRoute,
468+ running,
469+ } ) {
470+ const isQuestionWizard = route === "question" ;
471+ const fullIde = route === "ide" ;
472+
473+ const page = currentPage ( ) ;
474+ const step = currentStep ( ) ;
475+
476+ let showEditor , showSnoop , showPythonTutor , showBirdseye , showQuestionButton ;
477+ if ( fullIde || isQuestionWizard ) {
478+ showEditor = true ;
479+ showSnoop = true ;
480+ showPythonTutor = true ;
481+ showBirdseye = true ;
482+ showQuestionButton = ! ( isQuestionWizard || previousRoute === "question" ) ;
483+ } else if ( step . text . length ) {
484+ showEditor = page . index >= pages . WritingPrograms . index ;
485+ const snoopPageIndex = pages . UnderstandingProgramsWithSnoop . index ;
486+ showSnoop = page . index > snoopPageIndex ||
487+ ( page . index === snoopPageIndex && step . index >= 1 ) ;
488+ showPythonTutor = page . index >= pages . UnderstandingProgramsWithPythonTutor . index ;
489+ showBirdseye = page . index >= pages . IntroducingBirdseye . index ;
490+ showQuestionButton = page . index > pages . IntroducingBirdseye . index ;
491+ }
492+
493+ const cantUseEditor = prediction . state === "waiting" || prediction . state === "showingResult" ;
481494
482- { ! fullIde &&
495+ return < >
496+ { ! fullIde &&
483497 < div className = "book-text markdown-body" >
484498 { isQuestionWizard ?
485499 < QuestionWizard { ...questionWizard } />
@@ -497,47 +511,44 @@ class AppComponent extends React.Component {
497511 }
498512 </ div >
499513
500- }
514+ }
501515
502- < EditorButtons { ...{
503- showBirdseye,
504- showEditor,
505- showSnoop,
506- showPythonTutor,
507- showQuestionButton,
508- disabled : cantUseEditor ,
509- running,
510- } } />
511-
512- < div className = { `ide ide-${ fullIde ? 'full' : 'half' } ` } >
513- < div className = "editor-and-terminal" >
514- { showEditor &&
515- < Editor value = { editorContent } readOnly = { cantUseEditor } />
516- }
517- < div className = "terminal" style = { { height : showEditor ? undefined : "100%" } } >
518- < Shell />
519- </ div >
516+ < EditorButtons { ...{
517+ showBirdseye,
518+ showEditor,
519+ showSnoop,
520+ showPythonTutor,
521+ showQuestionButton,
522+ disabled : cantUseEditor ,
523+ running,
524+ } } />
525+
526+ < div className = { `ide ide-${ fullIde ? 'full' : 'half' } ` } >
527+ < div className = "editor-and-terminal" >
528+ { showEditor &&
529+ < Editor value = { editorContent } readOnly = { cantUseEditor } />
530+ }
531+ < div className = "terminal" style = { { height : showEditor ? undefined : "100%" } } >
532+ < Shell />
520533 </ div >
521534 </ div >
535+ </ div >
522536
523- < a className = "btn btn-primary full-ide-button"
524- href = { "#" + ( ! fullIde ? "ide" : ( specialHash ( previousRoute ) ? previousRoute : page . slug ) ) } >
525- < FontAwesomeIcon icon = { fullIde ? faCompress : faExpand } />
526- </ a >
537+ < a className = "btn btn-primary full-ide-button"
538+ href = { "#" + ( ! fullIde ? "ide" : ( specialHash ( previousRoute ) ? previousRoute : page . slug ) ) } >
539+ < FontAwesomeIcon icon = { fullIde ? faCompress : faExpand } />
540+ </ a >
527541
528- < >
529- { specialMessages . map ( ( message , index ) =>
530- < Popup
531- key = { index }
532- open = { true }
533- onClose = { ( ) => closeSpecialMessage ( index ) }
534- >
535- < SpecialMessageModal message = { message } />
536- </ Popup >
537- ) }
538- </ >
539- </ div >
540- }
542+ { specialMessages . map ( ( message , index ) =>
543+ < Popup
544+ key = { index }
545+ open = { true }
546+ onClose = { ( ) => closeSpecialMessage ( index ) }
547+ >
548+ < SpecialMessageModal message = { message } />
549+ </ Popup >
550+ ) }
551+ </ > ;
541552}
542553
543554const StepButton = ( { delta, label} ) =>
@@ -595,20 +606,7 @@ const MenuPopup = ({user}) =>
595606 < SettingsModal user = { user } />
596607 </ Popup >
597608 </ p >
598- { process . env . REACT_APP_SENTRY_DSN && < p >
599- < Popup
600- trigger = {
601- < button className = "btn btn-success" >
602- < FontAwesomeIcon icon = { faBug } /> { terms . feedback }
603- </ button >
604- }
605- modal
606- nested
607- contentStyle = { feedbackContentStyle }
608- >
609- { close => < FeedbackModal close = { close } /> }
610- </ Popup >
611- </ p > }
609+ < FeedbackMenuButton />
612610 {
613611 otherVisibleLanguages . map ( lang =>
614612 < p key = { lang . code } >
0 commit comments