55import de .doubleslash .keeptime .controller .HeimatController ;
66import de .doubleslash .keeptime .model .Project ;
77import de .doubleslash .keeptime .model .Work ;
8+ import javafx .animation .PauseTransition ;
89import javafx .animation .RotateTransition ;
10+ import javafx .application .Platform ;
911import javafx .beans .binding .Bindings ;
1012import javafx .beans .binding .StringBinding ;
1113import javafx .beans .property .*;
1416import javafx .collections .ObservableList ;
1517import javafx .concurrent .Task ;
1618import javafx .fxml .FXML ;
19+ import javafx .scene .Node ;
1720import javafx .scene .control .*;
1821import javafx .scene .effect .GaussianBlur ;
1922import javafx .scene .layout .AnchorPane ;
@@ -67,12 +70,19 @@ public class ExternalProjectsSyncController {
6770 @ FXML
6871 private AnchorPane pane ;
6972
73+ @ FXML
74+ private Label loadingMessage ;
75+
76+ private final SVGPath loadingSpinner = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_SPINNER_SOLID , 0.1 , 0.1 );
77+ private final SVGPath loadingSuccess = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_THUMBS_UP_SOLID , 0.1 , 0.1 );
78+ private final SVGPath loadingFailure = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_XMARK_SOLID , 0.1 , 0.1 );
79+
7080 private final LocalTimeStringConverter localTimeStringConverter = new LocalTimeStringConverter (FormatStyle .MEDIUM );
7181 private ObservableList <TableRow > items ;
7282
7383 private LocalDate currentReportDate ;
7484 private Stage thisStage ;
75- final private HeimatController heimatController ;
85+ private final HeimatController heimatController ;
7686
7787 public ExternalProjectsSyncController (final HeimatController heimatController ) {
7888 this .heimatController = heimatController ;
@@ -301,6 +311,7 @@ protected List<HeimatController.HeimatErrors> call() {
301311 LOG .error ("Task successfull" );
302312 final List <HeimatController .HeimatErrors > errors = task .getValue ();
303313 if (!errors .isEmpty ()) {
314+ loadingScreenShowSyncing ("Something did not work :(" , loadingFailure );
304315 List <String > a = errors .stream ().map (error -> {
305316 return error .mapping ().getMapping ().heimatTaskId () + ": " + error .errorMessage ()
306317 + ". Wanted to store '" + error .mapping ().getUserMinutes () + "' minutes with notes '"
@@ -309,24 +320,28 @@ protected List<HeimatController.HeimatErrors> call() {
309320
310321 showErrorDialog (a );
311322 } else {
312- // show done
323+ loadingScreenShowSyncing ( "Successfully synced!" , loadingSuccess );
313324 }
314325
315- showLoadingScreen (false );
316- thisStage .close ();
326+ PauseTransition delay = new PauseTransition (Duration .seconds (3 ));
327+ delay .setOnFinished (event -> {
328+ showLoadingScreen (false );
329+ thisStage .close ();
330+ });
331+ delay .play ();
317332 });
318333
319334 task .setOnFailed (e -> {
320335 final Throwable exception = task .getException ();
321336 LOG .error ("Task failed" , exception );
337+ loadingScreenShowSyncing ("Something did not work :(" , loadingFailure );
322338
323339 showErrorDialog (Collections .singletonList ("ERROR" + exception .getMessage ()));
324340 showLoadingScreen (false );
325341 thisStage .close ();
326342 });
327-
328- // Start the task in a background thread
329- new Thread (task ).start ();
343+ loadingScreenShowSyncing ("Syncing..." , loadingSpinner );
344+ Platform .runLater (() -> new Thread (task ).start ());
330345 });
331346
332347 cancelButton .setOnAction (ae -> {
@@ -337,14 +352,32 @@ protected List<HeimatController.HeimatErrors> call() {
337352 }
338353
339354 private void initializeLoadingScreen () {
340- SVGPath loadingSpinner = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_SPINNER_SOLID , 0.05 , 0.05 );
341355 loadingScreen .getChildren ().add (0 , loadingSpinner );
356+
357+ loadingSuccess .setFill (Color .GREEN );
358+ loadingSuccess .prefHeight (50 );
359+ loadingSuccess .prefWidth (50 );
360+
361+ loadingFailure .setFill (Color .RED );
362+ loadingFailure .prefHeight (50 );
363+ loadingFailure .prefWidth (50 );
364+
365+ loadingSpinner .prefHeight (50 );
366+ loadingSpinner .prefWidth (50 );
367+
342368 RotateTransition rotateTransition = new RotateTransition (Duration .seconds (1 ), loadingSpinner );
343369 rotateTransition .setByAngle (360 );
344370 rotateTransition .setCycleCount (RotateTransition .INDEFINITE );
345371 rotateTransition .play ();
346372 }
347373
374+ private void loadingScreenShowSyncing (String statusMessage , SVGPath icon ) {
375+ final ObservableList <Node > children = loadingScreen .getChildren ();
376+ children .remove (0 );
377+ children .add (0 , icon );
378+ loadingMessage .setText (statusMessage );
379+ }
380+
348381 private void showLoadingScreen (final boolean show ) {
349382 pane .setDisable (show );
350383 loadingScreen .setVisible (show );
@@ -421,8 +454,6 @@ public void increment(final int steps) {
421454 });
422455
423456 spinner .getValueFactory ().setConverter (new LocalTimeStringConverter (FormatStyle .MEDIUM ));
424-
425- // TODO mark red if not a 15 minute slot
426457 }
427458
428459 public static LocalTime decrementToLastFullQuarter (LocalTime time ) {
0 commit comments