11package de .doubleslash .keeptime .view ;
22
3+ import de .doubleslash .keeptime .common .BrowserHelper ;
4+ import de .doubleslash .keeptime .common .DateFormatter ;
35import de .doubleslash .keeptime .common .Resources ;
46import de .doubleslash .keeptime .common .SvgNodeProvider ;
57import de .doubleslash .keeptime .controller .HeimatController ;
3436
3537import java .time .LocalDate ;
3638import java .time .LocalTime ;
37- import java .time .format .DateTimeFormatter ;
3839import java .time .format .DateTimeParseException ;
3940import java .time .format .FormatStyle ;
4041import java .util .Collections ;
4142import java .util .List ;
4243import java .util .function .Consumer ;
4344
45+ import static de .doubleslash .keeptime .view .ReportController .copyToClipboard ;
46+
4447@ Component
4548public class ExternalProjectsSyncController {
4649
@@ -60,6 +63,10 @@ public class ExternalProjectsSyncController {
6063
6164 @ FXML
6265 private Label sumTimeLabel ;
66+ @ FXML
67+ private Label keepTimeTimeLabel ;
68+ @ FXML
69+ private Label heimatTimeLabel ;
6370
6471 @ FXML
6572 private Hyperlink externalSystemLink ;
@@ -73,23 +80,26 @@ public class ExternalProjectsSyncController {
7380 @ FXML
7481 private Label loadingMessage ;
7582
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 );
83+ private final SVGPath loadingSpinner = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_SPINNER_SOLID , 0.1 ,
84+ 0.1 );
85+ private final SVGPath loadingSuccess = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_THUMBS_UP_SOLID ,
86+ 0.1 , 0.1 );
87+ private final SVGPath loadingFailure = SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_XMARK_SOLID , 0.1 ,
88+ 0.1 );
7989
8090 private final LocalTimeStringConverter localTimeStringConverter = new LocalTimeStringConverter (FormatStyle .MEDIUM );
8191 private ObservableList <TableRow > items ;
8292
8393 private LocalDate currentReportDate ;
8494 private Stage thisStage ;
85- private final HeimatController heimatController ;
95+ private final HeimatController heimatController ;
8696
8797 public ExternalProjectsSyncController (final HeimatController heimatController ) {
8898 this .heimatController = heimatController ;
8999 }
90100
91101 public void initForDate (LocalDate currentReportDate , List <Work > currentWorkItems ) {
92- dayOfSyncLabel .setText (currentReportDate . format ( DateTimeFormatter . BASIC_ISO_DATE ));
102+ dayOfSyncLabel .setText (DateFormatter . toDayDateString ( currentReportDate ));
93103 this .currentReportDate = currentReportDate ;
94104
95105 // TODO add a spinner while loading?
@@ -99,7 +109,7 @@ public void initForDate(LocalDate currentReportDate, List<Work> currentWorkItems
99109 items = FXCollections .observableArrayList (tableRows .stream ().map (mapping -> {
100110 String userNotes = mapping .keeptimeNotes ();
101111 long userSeconds = mapping .keeptimeSeconds ();
102- // use info from heimat
112+ // use info from heimat when already present
103113 if (mapping .heimatSeconds () != 0L ) {
104114 userNotes = mapping .heimatNotes ();
105115 userSeconds = mapping .heimatSeconds ();
@@ -113,13 +123,17 @@ public void initForDate(LocalDate currentReportDate, List<Work> currentWorkItems
113123 item -> new javafx .beans .Observable [] { item .userTimeSeconds , item .shouldSyncCheckBox });
114124 items2 .addAll (items );
115125 StringBinding totalSum = Bindings .createStringBinding (() -> localTimeStringConverter .toString (
116- LocalTime .ofSecondOfDay (items .stream ()
117- .filter (item -> item .shouldSyncCheckBox .get ())
118- .mapToLong (item -> item .userTimeSeconds .getValue ())
119- .sum ())), items2 );
120- sumTimeLabel .textProperty ().bind (Bindings .concat ("Total Sum: " , totalSum ));
121- // TODO add a label with current Heimat Time
122- // TODO add a label with current Keeptime time
126+ LocalTime .ofSecondOfDay (
127+ items .stream ().filter (item -> item .mapping .heimatTaskId () != -1L ) // if its bookable in heimat
128+ .mapToLong (item -> item .userTimeSeconds .getValue ()).sum ())), items2 );
129+ sumTimeLabel .textProperty ().bind (totalSum );
130+
131+ keepTimeTimeLabel .setText (localTimeStringConverter .toString (
132+ LocalTime .ofSecondOfDay (tableRows .stream ().mapToLong (HeimatController .Mapping ::keeptimeSeconds ).sum ())));
133+ heimatTimeLabel .setText (localTimeStringConverter .toString (
134+ LocalTime .ofSecondOfDay (tableRows .stream ().mapToLong (HeimatController .Mapping ::heimatSeconds ).sum ())));
135+
136+ externalSystemLink .setOnAction (ae -> BrowserHelper .openURL (heimatController .getUrlForDay (currentReportDate )));
123137 }
124138
125139 @ FXML
@@ -160,8 +174,6 @@ protected void updateItem(TableRow item, boolean empty) {
160174 TableColumn <TableRow , List <Project >> projectColumn = new TableColumn <>("Project" );
161175 projectColumn .setCellValueFactory (data -> new SimpleObjectProperty (data .getValue ().mapping .projects ()));
162176 projectColumn .setCellFactory (column -> new TableCell <>() {
163- //private final Label label = new Label();
164-
165177 @ Override
166178 protected void updateItem (List <Project > item , boolean empty ) {
167179 super .updateItem (item , empty );
@@ -222,13 +234,17 @@ protected void updateItem(TableRow item, boolean empty) {
222234 LocalTime .ofSecondOfDay (item .keeptimeTimeSeconds .get ())));
223235 heimatLabel .setText ("Heimat: " + localTimeStringConverter .toString (
224236 LocalTime .ofSecondOfDay (item .heimatTimeSeconds .get ())));
225- timeSpinner .getValueFactory ().setValue (LocalTime .ofSecondOfDay (item .userTimeSeconds .get ()));
226- localTimeChangeListener = (observable , oldValue , newValue ) -> {
227- item .userTimeSeconds .set (newValue .toSecondOfDay ());
237+ timeSpinner .setDisable (!item .mapping .canBeSynced ());
238+ timeSpinner .getValueFactory ().setValue (LocalTime .ofSecondOfDay (0 ));
239+ if (item .mapping .canBeSynced ()) {
240+ timeSpinner .getValueFactory ().setValue (LocalTime .ofSecondOfDay (item .userTimeSeconds .get ()));
241+ localTimeChangeListener = (observable , oldValue , newValue ) -> {
242+ item .userTimeSeconds .set (newValue .toSecondOfDay ());
243+ spinnerValid .accept (timeSpinner );
244+ };
228245 spinnerValid .accept (timeSpinner );
229- };
230- spinnerValid .accept (timeSpinner );
231- timeSpinner .valueProperty ().addListener (localTimeChangeListener );
246+ timeSpinner .valueProperty ().addListener (localTimeChangeListener );
247+ }
232248 setGraphic (container );
233249 }
234250 }
@@ -258,9 +274,25 @@ protected void updateItem(TableRow item, boolean empty) {
258274 textArea .setPrefHeight (50 );
259275 textArea .setPrefWidth (100 );
260276 textArea .setWrapText (true );
261- // TODO make it possible to copy content of heimatNotesLabel
262- hbox .getChildren ().addAll (new Label ("Keeptime:" ), keepTimeNotesLabel );
263- hbox2 .getChildren ().addAll (new Label ("Heimat:" ), heimatNotesLabel );
277+
278+ final Button copyKeepTimeNotes = new Button ("" ,
279+ SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_CLIPBOARD_ICON , 0.03 , 0.03 ));
280+ copyKeepTimeNotes .setMaxSize (20 , 18 );
281+ copyKeepTimeNotes .setMinSize (20 , 18 );
282+ copyKeepTimeNotes .setContentDisplay (ContentDisplay .GRAPHIC_ONLY );
283+ copyKeepTimeNotes .setTooltip (new Tooltip ("Copy notes" ));
284+ copyKeepTimeNotes .setOnAction (me -> copyToClipboard (keepTimeNotesLabel .getText ()));
285+
286+ final Button copyHeimatNotes = new Button ("" ,
287+ SvgNodeProvider .getSvgNodeWithScale (Resources .RESOURCE .SVG_CLIPBOARD_ICON , 0.03 , 0.03 ));
288+ copyHeimatNotes .setMaxSize (20 , 18 );
289+ copyHeimatNotes .setMinSize (20 , 18 );
290+ copyHeimatNotes .setContentDisplay (ContentDisplay .GRAPHIC_ONLY );
291+ copyHeimatNotes .setTooltip (new Tooltip ("Copy notes" ));
292+ copyHeimatNotes .setOnAction (me -> copyToClipboard (heimatNotesLabel .getText ()));
293+
294+ hbox .getChildren ().addAll (copyKeepTimeNotes , new Label ("KeepTime:" ), keepTimeNotesLabel );
295+ hbox2 .getChildren ().addAll (copyHeimatNotes , new Label ("Heimat:" ), heimatNotesLabel );
264296 container .getChildren ().addAll (textArea , hbox , hbox2 );
265297 }
266298
@@ -272,13 +304,17 @@ protected void updateItem(TableRow item, boolean empty) {
272304 if (empty || item == null ) {
273305 setGraphic (null );
274306 } else {
275- textArea .setText (item .userNotes .get ());
276- stringChangeListener = (obs , oldText , newText ) -> {
277- item .userNotes .set (newText );
307+ textArea .setDisable (!item .mapping .canBeSynced ());
308+ textArea .setText ("" );
309+ if (item .mapping .canBeSynced ()) {
310+ textArea .setText (item .userNotes .get ());
311+ stringChangeListener = (obs , oldText , newText ) -> {
312+ item .userNotes .set (newText );
313+ textAreaValid .accept (textArea );
314+ };
278315 textAreaValid .accept (textArea );
279- };
280- textAreaValid .accept (textArea );
281- textArea .textProperty ().addListener (stringChangeListener );
316+ textArea .textProperty ().addListener (stringChangeListener );
317+ }
282318 heimatNotesLabel .setText (item .heimatNotes .get ());
283319 keepTimeNotesLabel .setText (item .keeptimeNotes .get ());
284320 setGraphic (container );
@@ -291,6 +327,7 @@ protected void updateItem(TableRow item, boolean empty) {
291327 syncColumn .setCellValueFactory (data -> data .getValue ().syncStatus );
292328 syncColumn .setPrefWidth (250 );
293329 mappingTableView .getColumns ().addAll (shouldSyncColumn , projectColumn , timeColumn , notesColumn , syncColumn );
330+ mappingTableView .setSelectionModel (null );
294331
295332 saveButton .setOnAction ((ae ) -> {
296333 LOG .debug ("New mappings to be synced '{}'." , "TODO" );
0 commit comments