2727import javafx .beans .property .SimpleObjectProperty ;
2828import javafx .beans .property .SimpleStringProperty ;
2929import javafx .collections .FXCollections ;
30+ import javafx .collections .ListChangeListener ;
3031import javafx .collections .ObservableList ;
3132import javafx .collections .transformation .FilteredList ;
3233import javafx .fxml .FXML ;
3334import javafx .scene .control .*;
3435import javafx .scene .layout .VBox ;
35- import javafx .scene .paint .Color ;
3636import javafx .stage .Stage ;
3737import org .slf4j .Logger ;
3838import org .slf4j .LoggerFactory ;
3939import org .springframework .stereotype .Component ;
4040
4141import java .time .LocalDate ;
4242import java .util .List ;
43+ import java .util .Optional ;
4344
4445@ Component
4546public class MapExternalProjectsController {
@@ -61,9 +62,6 @@ public class MapExternalProjectsController {
6162 @ FXML
6263 private Button cancelButton ;
6364
64- @ FXML
65- private ComboBox <HeimatTask > addNewProjectComboBox ;
66-
6765 @ FXML
6866 private Button addNewProjectButton ;
6967
@@ -165,7 +163,52 @@ protected void updateItem(HeimatTask item, boolean empty) {
165163
166164 mappingTableView .getColumns ().addAll (keepTimeColumn , externalColumn );
167165
168- addNewProjectComboBox .setCellFactory (param -> new ListCell <>() {
166+ addNewProjectButton .setOnAction (e -> {
167+ final List <HeimatTask > unmappedHeimatTasks = externalProjects .stream ().filter (ht -> {
168+ final boolean alreadyMapped = value .stream ()
169+ .anyMatch (mapping -> mapping .getHeimatTask () != null
170+ && mapping .getHeimatTask ().id () == ht .id ());
171+ return !alreadyMapped ;
172+ }).toList ();
173+ List <HeimatTask > selectedItems = showMultiSelectDialog (externalProjectsObservableList , unmappedHeimatTasks );
174+ for (HeimatTask toBeCreatedHeimatTask : selectedItems ) {
175+ final int sortIndex = model .getAvailableProjects ().size ();
176+ final Project project = controller .addNewProject (
177+ new Project (toBeCreatedHeimatTask .name () + " - " + toBeCreatedHeimatTask .taskHolderName (),
178+ toBeCreatedHeimatTask .bookingHint (), ColorHelper .randomColor (), true , sortIndex ));
179+ newProjectMappings .add (new HeimatController .ProjectMapping (project , toBeCreatedHeimatTask ));
180+ }
181+ });
182+
183+ saveButton .setOnAction (ae -> {
184+ heimatController .updateMappings (newProjectMappings );
185+ thisStage .close ();
186+ });
187+
188+ cancelButton .setOnAction (ae -> thisStage .close ());
189+
190+ List <String > warnings = existingAndInvalidMappings .invalidMappingsAsString ();
191+ if (!warnings .isEmpty ()) {
192+ Platform .runLater (() -> showInvalidMappingsDialog (warnings ));
193+ }
194+ }
195+
196+ private List <HeimatTask > showMultiSelectDialog (final ObservableList <HeimatTask > externalProjectsObservableList ,
197+ List <HeimatTask > unmappedHeimatTasks ) {
198+ Dialog <List <HeimatTask >> dialog = new Dialog <>();
199+ dialog .setTitle ("Import HEIMAT projects" );
200+ dialog .setHeaderText ("You can select mutliple items" );
201+ dialog .initOwner (this .thisStage );
202+ dialog .setWidth (600 );
203+ dialog .setHeight (500 );
204+
205+ // Buttons
206+ ButtonType okButtonType = new ButtonType ("OK" , ButtonBar .ButtonData .OK_DONE );
207+ ButtonType cancelButtonType = new ButtonType ("Cancel" , ButtonBar .ButtonData .CANCEL_CLOSE );
208+ dialog .getDialogPane ().getButtonTypes ().addAll (okButtonType , cancelButtonType );
209+
210+ ListView <HeimatTask > listView = new ListView <>();
211+ listView .setCellFactory (param -> new ListCell <>() {
169212 @ Override
170213 protected void updateItem (HeimatTask item , boolean empty ) {
171214 super .updateItem (item , empty );
@@ -178,41 +221,40 @@ protected void updateItem(HeimatTask item, boolean empty) {
178221 }
179222 }
180223 });
181- addNewProjectComboBox .setButtonCell (new ListCell <>() {
182- @ Override
183- protected void updateItem (HeimatTask item , boolean empty ) {
184- super .updateItem (item , empty );
185- if (empty || item == null ) {
186- setText (null );
187- } else {
188- setText (item .taskHolderName () + " - " + item .name ());
189- }
224+ listView .getSelectionModel ().setSelectionMode (SelectionMode .MULTIPLE );
225+ listView .setItems (externalProjectsObservableList );
226+
227+ Button selectAllUnmappedButton = new Button ("Select All Unmapped" );
228+ selectAllUnmappedButton .setOnAction (e -> {
229+ listView .getSelectionModel ().clearSelection ();
230+ for (HeimatTask ht : unmappedHeimatTasks ) {
231+ listView .getSelectionModel ().select (ht );
190232 }
233+ listView .requestFocus ();
191234 });
192- addNewProjectButton .disableProperty ()
193- .bind (addNewProjectComboBox .getSelectionModel ().selectedItemProperty ().isNull ());
194- addNewProjectButton .setOnAction (ae -> {
195- final HeimatTask task = addNewProjectComboBox .getValue ();
196- final int sortIndex = model .getAvailableProjects ().size ();
197- final Project project = controller .addNewProject (
198- new Project (task .taskHolderName () + " - " + task .name (), task .bookingHint (), ColorHelper .randomColor (), true ,
199- sortIndex ));
200- newProjectMappings .add (new HeimatController .ProjectMapping (project , task ));
201- addNewProjectComboBox .getSelectionModel ().clearSelection ();
202- });
203- addNewProjectComboBox .setItems (externalProjectsObservableList );
204235
205- saveButton .setOnAction (ae -> {
206- heimatController .updateMappings (newProjectMappings );
207- thisStage .close ();
236+ VBox content = new VBox (10 , selectAllUnmappedButton , listView );
237+ dialog .getDialogPane ().setContent (content );
238+ final List <HeimatTask > emptyList = List .of ();
239+ // Handle result when OK is clicked
240+ dialog .setResultConverter (dialogButton -> {
241+ if (dialogButton == okButtonType ) {
242+ return listView .getSelectionModel ().getSelectedItems ().stream ().toList ();
243+ }
244+ return emptyList ; // Cancel was clicked
208245 });
209246
210- cancelButton .setOnAction (ae -> thisStage .close ());
247+ Button okButton = (Button ) dialog .getDialogPane ().lookupButton (okButtonType );
248+ okButton .setText ("Import (0)" ); // Initial state
211249
212- List <String > warnings = existingAndInvalidMappings .invalidMappingsAsString ();
213- if (!warnings .isEmpty ()) {
214- Platform .runLater (() -> showInvalidMappingsDialog (warnings ));
215- }
250+ // Listen for selection changes and update button text
251+ listView .getSelectionModel ().getSelectedItems ().addListener ((ListChangeListener <HeimatTask >) change -> {
252+ int selectedCount = listView .getSelectionModel ().getSelectedItems ().size ();
253+ okButton .setText ("Import (" + selectedCount + ")" );
254+ });
255+
256+ Optional <List <HeimatTask >> result = dialog .showAndWait ();
257+ return result .orElse (emptyList );
216258 }
217259
218260 private void showInvalidMappingsDialog (final List <String > warnings ) {
0 commit comments