diff --git a/app/logbook/olog/ui/pom.xml b/app/logbook/olog/ui/pom.xml
index 9df3fa0dc3..8103b68f94 100644
--- a/app/logbook/olog/ui/pom.xml
+++ b/app/logbook/olog/ui/pom.xml
@@ -40,6 +40,11 @@
core-security
4.7.4-SNAPSHOT
+
+ org.phoebus
+ core-ui
+ 4.7.4-SNAPSHOT
+
org.jfxtras
jfxtras-agenda
diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java
index 7d5d280eaf..bc56349035 100644
--- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java
+++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java
@@ -23,6 +23,7 @@ public class Messages
AttachmentsDirectoryNotWritable,
AttachmentsFileNotDirectory,
AttachmentsNoStorage,
+ AvailableTemplates,
Back,
CloseRequestHeader,
CloseRequestButtonContinue,
diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/AttachmentsEditorController.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/AttachmentsEditorController.java
index 9a7c4f8958..b8e95a4e78 100644
--- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/AttachmentsEditorController.java
+++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/AttachmentsEditorController.java
@@ -342,10 +342,19 @@ private void addImage(Image image, String id) {
}
}
+ /**
+ *
+ * @return The {@link ObservableList} of {@link Attachment}s managed in the {@link AttachmentsViewController}.
+ */
public ObservableList getAttachments() {
return attachmentsViewController.getAttachments();
}
+ /**
+ * Sets the file upload constraints information in the editor.
+ * @param maxFileSize Maximum size for a single file.
+ * @param maxRequestSize Maximum total size of all attachments.
+ */
public void setSizeLimits(String maxFileSize, String maxRequestSize) {
this.maxFileSize = Double.parseDouble(maxFileSize);
this.maxRequestSize = Double.parseDouble(maxRequestSize);
@@ -387,4 +396,11 @@ private void showFileSizeExceedsLimit(File file) {
private void showTotalSizeExceedsLimit() {
Platform.runLater(() -> sizesErrorMessage.set(Messages.RequestTooLarge));
}
+
+ /**
+ * Clears list of {@link Attachment}s.
+ */
+ public void clearAttachments(){
+ getAttachments().clear();
+ }
}
diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogEntryEditorController.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogEntryEditorController.java
index 6702e2854e..078a1d3b6e 100644
--- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogEntryEditorController.java
+++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogEntryEditorController.java
@@ -23,8 +23,10 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
+import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
@@ -53,6 +55,9 @@
import javafx.scene.paint.Color;
import javafx.util.Callback;
import javafx.util.StringConverter;
+import org.phoebus.framework.autocomplete.Proposal;
+import org.phoebus.framework.autocomplete.ProposalProvider;
+import org.phoebus.framework.autocomplete.ProposalService;
import org.phoebus.framework.jobs.JobManager;
import org.phoebus.framework.selection.SelectionService;
import org.phoebus.logbook.LogClient;
@@ -66,6 +71,7 @@
import org.phoebus.logbook.Tag;
import org.phoebus.logbook.olog.ui.HelpViewer;
import org.phoebus.logbook.olog.ui.LogbookUIPreferences;
+import org.phoebus.logbook.olog.ui.Messages;
import org.phoebus.logbook.olog.ui.PreviewViewer;
import org.phoebus.olog.es.api.OlogProperties;
import org.phoebus.olog.es.api.model.OlogLog;
@@ -74,6 +80,7 @@
import org.phoebus.security.tokens.ScopedAuthenticationToken;
import org.phoebus.security.tokens.SimpleAuthenticationToken;
import org.phoebus.ui.Preferences;
+import org.phoebus.ui.autocomplete.AutocompleteMenu;
import org.phoebus.ui.dialog.ListSelectionPopOver;
import org.phoebus.ui.javafx.ImageCache;
import org.phoebus.util.time.TimestampFormats;
@@ -237,6 +244,10 @@ public class LogEntryEditorController {
*/
private Optional logEntryResult = Optional.empty();
+ private final ObjectProperty> templatesProperty =
+ new SimpleObjectProperty<>(FXCollections.observableArrayList());
+ //private ObservableList extends LogTemplate> templates = FXCollections.observableArrayList();
+
public LogEntryEditorController(LogEntry logEntry, LogEntry inReplyTo, EditMode editMode) {
this.replyTo = inReplyTo;
this.logFactory = LogService.getInstance().getLogFactories().get(LogbookPreferences.logbook_factory);
@@ -456,6 +467,26 @@ public void initialize() {
newSelection.forEach(l -> updateDropDown(logbookDropDown, l, true));
});
+ AutocompleteMenu autocompleteMenu = new AutocompleteMenu(new ProposalService(new ProposalProvider() {
+ @Override
+ public String getName() {
+ return Messages.AvailableTemplates;
+ }
+
+ @Override
+ public List lookup(String text) {
+ List proposals = new ArrayList<>();
+ templatesProperty.get().forEach(template -> {
+ if (template.name().contains(text)) {
+ proposals.add(new Proposal(template.name()));
+ }
+ });
+ return proposals;
+ }
+ }));
+
+ autocompleteMenu.attachField(templateSelector.getEditor());
+
templateSelector.setCellFactory(new Callback<>() {
@Override
public ListCell call(ListView logTemplateListView) {
@@ -475,28 +506,53 @@ protected void updateItem(LogTemplate item, boolean empty) {
templateSelector.valueProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
+ templateSelector.getEditor().textProperty().set(newValue.name());
if (!newValue.equals(oldValue)) {
loadTemplate(newValue);
}
}
+ else{
+ // E.g. if user specifies an invalid template name
+ loadTemplate(null);
+ }
});
- templateSelector.setConverter(
- new StringConverter<>() {
- @Override
- public String toString(LogTemplate template) {
- if (template == null) {
- return "";
- } else {
- return template.name();
- }
- }
+ // Hide autocomplete menu when user clicks drop-down button
+ templateSelector.showingProperty().addListener((obs, wasShowing, isNowShowing) -> autocompleteMenu.hide());
- @Override
- public LogTemplate fromString(String s) {
+ templateSelector.getEditor().textProperty().addListener((obs, o, n) -> {
+ if(n != null && !n.isEmpty()){
+ Optional logTemplate =
+ templatesProperty.get().stream().filter(t -> t.name().equals(n)).findFirst();
+ logTemplate.ifPresent(template -> templateSelector.valueProperty().setValue(template));
+ }
+ });
+
+ templateSelector.setConverter(
+ new StringConverter<>() {
+ @Override
+ public String toString(LogTemplate template) {
+ if (template == null) {
return null;
+ } else {
+ return template.name();
}
- });
+ }
+
+ /**
+ * Converts the user specified string to a {@link LogTemplate}
+ * @param name The name of an (existing) template
+ * @return A {@link LogTemplate} if name
matches an existing one, otherwise null
+ */
+ @Override
+ public LogTemplate fromString(String name) {
+ Optional logTemplate =
+ templatesProperty.get().stream().filter(t -> t.name().equals(name)).findFirst();
+ return logTemplate.orElse(null);
+ }
+ });
+
+ templateSelector.itemsProperty().bind(templatesProperty);
// Note: logbooks and tags are retrieved asynchronously from service
getServerSideStaticData();
@@ -767,8 +823,7 @@ private void getServerSideStaticData() {
logger.log(Level.WARNING, "Failed to get or parse response from server info request", e);
}
- Collection templates = logClient.getTemplates();
- Platform.runLater(() -> templateSelector.getItems().addAll(templates));
+ templatesProperty.get().setAll(logClient.getTemplates().stream().toList());
});
}
@@ -840,16 +895,30 @@ public Optional getLogEntryResult() {
/**
* Loads template to configure UI elements.
*
- * @param logTemplate A {@link LogTemplate} selected by user.
+ * @param logTemplate A {@link LogTemplate} selected by user. If null
, all log entry elements
+ * will be cleared, except the Level selector, which will be set to the top-most item.
*/
private void loadTemplate(LogTemplate logTemplate) {
- titleProperty.set(logTemplate.title());
- descriptionProperty.set(logTemplate.source());
- logPropertiesEditorController.setProperties(logTemplate.properties());
- selectedTags.setAll(logTemplate.tags().stream().map(Tag::getName).toList());
- selectedLogbooks.setAll(logTemplate.logbooks().stream().map(Logbook::getName).toList());
- levelSelector.getSelectionModel().select(logTemplate.level());
- selectedTags.forEach(t -> updateDropDown(tagDropDown, t, true));
- selectedLogbooks.forEach(l -> updateDropDown(logbookDropDown, l, true));
+ if(logTemplate != null){
+ titleProperty.set(logTemplate.title());
+ descriptionProperty.set(logTemplate.source());
+ logPropertiesEditorController.setProperties(logTemplate.properties());
+ selectedTags.setAll(logTemplate.tags().stream().map(Tag::getName).toList());
+ selectedLogbooks.setAll(logTemplate.logbooks().stream().map(Logbook::getName).toList());
+ levelSelector.getSelectionModel().select(logTemplate.level());
+ selectedTags.forEach(t -> updateDropDown(tagDropDown, t, true));
+ selectedLogbooks.forEach(l -> updateDropDown(logbookDropDown, l, true));
+ }
+ else{
+ titleProperty.set(null);
+ descriptionProperty.set(null);
+ logPropertiesEditorController.clearSelectedProperties();
+ attachmentsEditorController.clearAttachments();
+ selectedTags.setAll(Collections.emptyList());
+ selectedLogbooks.setAll(Collections.emptyList());
+ levelSelector.getSelectionModel().select(0);
+ selectedTags.forEach(t -> updateDropDown(tagDropDown, t, false));
+ selectedLogbooks.forEach(l -> updateDropDown(logbookDropDown, l, false));
+ }
}
}
diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogPropertiesEditorController.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogPropertiesEditorController.java
index 463cbae732..cb520e094e 100644
--- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogPropertiesEditorController.java
+++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/write/LogPropertiesEditorController.java
@@ -173,12 +173,22 @@ public List getProperties() {
return selectedProperties;
}
+ /**
+ * @param properties {@link Collection} of {@link Property}s to set in the editor.
+ */
public void setProperties(Collection properties){
- if(properties == null){
- return;
+ if(properties != null){
+ selectedProperties.addAll(properties);
+ availableProperties.removeAll(properties);
}
- selectedProperties.addAll(properties);
- availableProperties.removeAll(properties);
+ }
+
+ /**
+ * Moves all selected {@link Property}s back to list of available.
+ */
+ public void clearSelectedProperties(){
+ availableProperties.addAll(selectedProperties);
+ selectedProperties.clear();
}
/**
diff --git a/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties b/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties
index 7e064c37b8..21bd2841f8 100644
--- a/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties
+++ b/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties
@@ -16,6 +16,7 @@ Attachments=Attachments
AttachmentsDirectoryFailedCreate=Failed to create directory {0} for attachments
AttachmentsFileNotDirectory=File {0} exists but is not a directory
AttachmentsSearchProperty=Attachments:
+AvailableTemplates=Available Templates
Back=Back
BrowseButton=Browse
Cancel=Cancel
diff --git a/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/write/LogEntryEditor.fxml b/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/write/LogEntryEditor.fxml
index 6fb8337f15..8bd98cd5d9 100644
--- a/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/write/LogEntryEditor.fxml
+++ b/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/write/LogEntryEditor.fxml
@@ -49,7 +49,7 @@
-
+
diff --git a/core/logbook/src/main/java/org/phoebus/logbook/LogTemplate.java b/core/logbook/src/main/java/org/phoebus/logbook/LogTemplate.java
index 9d7c41fa43..fddae0cde2 100644
--- a/core/logbook/src/main/java/org/phoebus/logbook/LogTemplate.java
+++ b/core/logbook/src/main/java/org/phoebus/logbook/LogTemplate.java
@@ -32,4 +32,9 @@ public record LogTemplate(String id,
Collection logbooks,
Collection tags,
Collection properties){
+
+ @Override
+ public String toString(){
+ return name;
+ }
}
diff --git a/core/ui/src/main/java/org/phoebus/ui/autocomplete/AutocompleteMenu.java b/core/ui/src/main/java/org/phoebus/ui/autocomplete/AutocompleteMenu.java
index 2ee36016bd..c17c21924e 100644
--- a/core/ui/src/main/java/org/phoebus/ui/autocomplete/AutocompleteMenu.java
+++ b/core/ui/src/main/java/org/phoebus/ui/autocomplete/AutocompleteMenu.java
@@ -320,4 +320,11 @@ private void invokeAction(final TextInputControl field)
}
menu.hide();
}
+
+ /**
+ * Explicitly hides the menu.
+ */
+ public void hide(){
+ menu.hide();
+ }
}