@@ -194,7 +194,9 @@ export class App extends UIComponent<{}, IAppState> {
194194 }
195195
196196 public override componentDidUpdate ( _prevProps : { } , prevState : IAppState ) : void {
197- if ( prevState . phase !== AppPhase . Running && this . state . phase === AppPhase . Running ) {
197+ const { phase } = this . state ;
198+
199+ if ( prevState . phase !== AppPhase . Running && phase === AppPhase . Running ) {
198200 this . updateStatsItem ( ) ;
199201 }
200202 }
@@ -213,7 +215,8 @@ export class App extends UIComponent<{}, IAppState> {
213215 }
214216
215217 public render ( ) {
216- const { phase, displayMode, sidebarOpen, headerPinned, instrumentEditorEnabled } = this . state ;
218+ const { phase, displayMode, sidebarOpen, headerPinned, instrumentEditorEnabled, printing,
219+ printOptions } = this . state ;
217220 const isRunning = phase === AppPhase . Running ;
218221
219222 let splashContent : ComponentChild ;
@@ -225,9 +228,6 @@ export class App extends UIComponent<{}, IAppState> {
225228 splashContent = (
226229 < BackendSetupDialog
227230 ref = { this . backendSetupDialogRef }
228- onSetupComplete = { ( ) => {
229- void this . handleBackendSetupComplete ( ) ;
230- } }
231231 />
232232 ) ;
233233
@@ -249,8 +249,6 @@ export class App extends UIComponent<{}, IAppState> {
249249 < LoginDialog
250250 ref = { this . loginDialogRef }
251251 dataModel = { this . dataModel }
252- onLoginSuccess = { this . handleLoginSuccess }
253- onContinueAnonymous = { this . handleContinueAnonymous }
254252 />
255253 ) ;
256254
@@ -500,14 +498,9 @@ export class App extends UIComponent<{}, IAppState> {
500498 < LoginDialog
501499 ref = { this . loginDialogRef }
502500 dataModel = { this . dataModel }
503- onLoginSuccess = { this . handleLoginSuccess }
504- onContinueAnonymous = { this . handleContinueAnonymous }
505501 />
506502 < BackendSetupDialog
507503 ref = { this . backendSetupDialogRef }
508- onSetupComplete = { ( ) => {
509- void this . handleBackendSetupComplete ( ) ;
510- } }
511504 />
512505 < PrintDialog ref = { this . printDialogRef } onAccept = { this . handlePrintAccept } />
513506 < UserGroupEditor
@@ -524,11 +517,11 @@ export class App extends UIComponent<{}, IAppState> {
524517 } }
525518 />
526519 {
527- this . state . printing && this . dataModel . arrangement && this . state . printOptions
520+ printing && this . dataModel . arrangement && printOptions
528521 && this . arrangementPlayer && this . undoManager && (
529522 < PrintView
530523 arrangement = { this . dataModel . arrangement as Arrangement }
531- options = { this . state . printOptions }
524+ options = { printOptions }
532525 dataModel = { this . dataModel }
533526 arrangementPlayer = { this . arrangementPlayer }
534527 services = { this . services }
@@ -567,6 +560,8 @@ export class App extends UIComponent<{}, IAppState> {
567560 /**
568561 * Checks if the backend is reachable and initialised. If not, opens the setup dialog.
569562 * Once the backend is ready, proceeds with data model initialisation.
563+ *
564+ * @returns A promise that resolves when the check is complete.
570565 */
571566 private async checkBackendThenInitialize ( ) : Promise < void > {
572567 let health : {
@@ -588,7 +583,7 @@ export class App extends UIComponent<{}, IAppState> {
588583
589584 if ( ! health . configLoaded ) {
590585 this . setState ( { phase : AppPhase . Setup } , ( ) => {
591- this . backendSetupDialogRef . current ?. open ( {
586+ void this . backendSetupDialogRef . current ?. show ( {
592587 mode : "fatal" ,
593588 configError : health . configError ,
594589 } ) ;
@@ -599,7 +594,7 @@ export class App extends UIComponent<{}, IAppState> {
599594
600595 if ( ! health . initialized ) {
601596 this . setState ( { phase : AppPhase . Setup } , ( ) => {
602- this . backendSetupDialogRef . current ?. open ( {
597+ void this . backendSetupDialogRef . current ?. show ( {
603598 mode : "initial" ,
604599 dbError : health . dbError ,
605600 } ) ;
@@ -608,6 +603,50 @@ export class App extends UIComponent<{}, IAppState> {
608603 return ;
609604 }
610605
606+ if ( health . dbError ) {
607+ // Pipeline: logout → setup dialog → confirmation → login → reset.
608+ await this . dataModel . logout ( ) ;
609+ await this . setStatePromise ( { phase : AppPhase . Setup } ) ;
610+
611+ const setupResult = await this . backendSetupDialogRef . current ?. show ( {
612+ mode : "admin" ,
613+ dbError : health . dbError ,
614+ } ) ;
615+
616+ if ( setupResult !== "reset" ) {
617+ return ;
618+ }
619+
620+ const confirmed = await this . confirmDialogRef . current ?. show (
621+ "This will delete all scores, folders, users and groups.\n"
622+ + "The database tables will be recreated from scratch." ,
623+ { accept : "Reset Database" , refuse : "Cancel" } ,
624+ "Reset Database" ,
625+ [ "This cannot be undone. Make sure to export your scores if you want to keep them." ] ,
626+ ) ;
627+
628+ if ( confirmed !== DialogResponseClosure . Accept ) {
629+ return ;
630+ }
631+
632+ await this . setStatePromise ( { phase : AppPhase . Login } ) ;
633+ const loggedIn = await this . loginDialogRef . current ?. show ( true ) ;
634+
635+ if ( ! loggedIn ) {
636+ return ;
637+ }
638+
639+ const ok = await this . dataModel . resetDatabase ( ) ;
640+
641+ if ( ! ok ) {
642+ // Reset failed — restart the health check so the setup dialog can show the error.
643+ return this . checkBackendThenInitialize ( ) ;
644+ }
645+
646+ // Restart the health check — the backend is now fresh.
647+ return this . checkBackendThenInitialize ( ) ;
648+ }
649+
611650 if ( ! health . hasUsers ) {
612651 this . setState ( { phase : AppPhase . AdminSetup } , ( ) => {
613652 this . adminSetupDialogRef . current ?. open ( ) ;
@@ -655,7 +694,7 @@ export class App extends UIComponent<{}, IAppState> {
655694 }
656695
657696 this . setState ( { phase : AppPhase . Login } , ( ) => {
658- this . loginDialogRef . current ?. open ( ) ;
697+ void this . loginDialogRef . current ?. show ( ) . then ( this . handleLoginDialogResult ) ;
659698 } ) ;
660699 }
661700
@@ -671,9 +710,11 @@ export class App extends UIComponent<{}, IAppState> {
671710 } ;
672711
673712 private handleAuthChanged = ( ) : Promise < boolean > => {
674- if ( ! this . dataModel . authenticated && this . state . phase === AppPhase . Running ) {
713+ const { phase } = this . state ;
714+
715+ if ( ! this . dataModel . authenticated && phase === AppPhase . Running ) {
675716 this . setState ( { phase : AppPhase . Login } , ( ) => {
676- this . loginDialogRef . current ?. open ( ) ;
717+ void this . loginDialogRef . current ?. show ( ) . then ( this . handleLoginDialogResult ) ;
677718 } ) ;
678719 } else {
679720 this . forceUpdate ( ) ;
@@ -682,6 +723,19 @@ export class App extends UIComponent<{}, IAppState> {
682723 return Promise . resolve ( true ) ;
683724 } ;
684725
726+ /**
727+ * Handles the result of a login dialog show() call for non-pipeline paths.
728+ *
729+ * @param loggedIn Whether the user logged in successfully.
730+ */
731+ private handleLoginDialogResult = ( loggedIn : boolean ) : void => {
732+ if ( loggedIn ) {
733+ this . handleLoginSuccess ( ) ;
734+ } else {
735+ this . handleContinueAnonymous ( ) ;
736+ }
737+ } ;
738+
685739 private handleLoginSuccess = ( ) : void => {
686740 this . signInFromRunning = false ;
687741 void this . initializeApp ( ) . then ( ( ) => {
@@ -747,7 +801,7 @@ export class App extends UIComponent<{}, IAppState> {
747801 }
748802
749803 this . setState ( { phase : AppPhase . Login } , ( ) => {
750- this . loginDialogRef . current ?. open ( ) ;
804+ void this . loginDialogRef . current ?. show ( ) . then ( this . handleLoginDialogResult ) ;
751805 } ) ;
752806
753807 return ;
@@ -826,7 +880,7 @@ export class App extends UIComponent<{}, IAppState> {
826880 private handleSignInClick = ( ) => {
827881 this . signInFromRunning = true ;
828882 this . setState ( { phase : AppPhase . Login } , ( ) => {
829- this . loginDialogRef . current ?. open ( ) ;
883+ void this . loginDialogRef . current ?. show ( ) . then ( this . handleLoginDialogResult ) ;
830884 } ) ;
831885 } ;
832886
@@ -848,7 +902,7 @@ export class App extends UIComponent<{}, IAppState> {
848902 this . notificationItem = undefined ;
849903
850904 this . setState ( { phase : AppPhase . Login } , ( ) => {
851- this . loginDialogRef . current ?. open ( ) ;
905+ void this . loginDialogRef . current ?. show ( ) . then ( this . handleLoginDialogResult ) ;
852906 } ) ;
853907 } ;
854908
@@ -880,7 +934,7 @@ export class App extends UIComponent<{}, IAppState> {
880934 label : "Reset Backend" ,
881935 icon : < Icon src = { Codicon . Server } /> ,
882936 onClick : ( ) => {
883- this . backendSetupDialogRef . current ?. open ( { mode : "admin" } ) ;
937+ void this . backendSetupDialogRef . current ?. show ( { mode : "admin" } ) ;
884938 } ,
885939 } ) ;
886940 } else if ( user ) {
0 commit comments