Skip to content

Commit

Permalink
User specific comment (#9727)
Browse files Browse the repository at this point in the history
* Create user specific comment field

* User can make user-specific comments

* User specific comment will not display in other fields

* Refactor the code

* Make changes

* Force to make user specific comments

* Fix error

* Test if to show the other user's comments

* Delete useless code

* Add changes in CHANGELOG

* Make changes only author can edit user specific comment

* Specify the user specific comment does not belong to current user

* Add test case for comments tab

* Refactor code based on the feedback

* Refactor tests about the CommentsTab

* Add missing localization keys in the English language file.

* Modify the failing checkstyle tests

* Modify the order of import

* Separate the UndoManager import

* Make changes

* Update the user specific comment field

* Remove the dependency on the entry type for presence of comments

* Change code for checkstyle

* Additional logic to parseField to better handle user specific comment.

* Fetch the username using PreferencesService to improve simplicity.

* Merge "All-Comments" into tab "Comments"

* Minor code beautification

* Simplify tests (and add one more test)

* Always list "Comment" field

* Refine CHANGELOG entry

* Remove tool tip (not containing much additional information)

---------

Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Oliver Kopp <kopp.dev@gmail.com>
  • Loading branch information
3 people committed Jun 6, 2023
1 parent 2a621f0 commit 76e2ce7
Show file tree
Hide file tree
Showing 21 changed files with 352 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
### Added

- We added a field showing the BibTeX/biblatex source for added and deleted entries in the "External Changes Resolver" dialog. [#9509](https://github.com/JabRef/jabref/issues/9509)
- We added user-specific comment field so that multiple users can make separate comments. [#543](https://github.com/koppor/jabref/issues/543)
- We added a search history list in the search field's right click menu. [#7906](https://github.com/JabRef/jabref/issues/7906)
- We added a full text fetcher for IACR eprints. [#9651](https://github.com/JabRef/jabref/pull/9651)
- We added "Attach file from URL" to right-click context menu to download and store a file with the reference library. [#9646](https://github.com/JabRef/jabref/issues/9646)
Expand Down
91 changes: 91 additions & 0 deletions src/main/java/org/jabref/gui/entryeditor/CommentsTab.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.jabref.gui.entryeditor;

import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.swing.undo.UndoManager;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.autocompleter.SuggestionProviders;
import org.jabref.gui.fieldeditors.FieldEditorFX;
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.theme.ThemeManager;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.journals.JournalAbbreviationRepository;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.pdf.search.indexing.IndexingTaskManager;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.field.UserSpecificCommentField;
import org.jabref.preferences.PreferencesService;

public class CommentsTab extends FieldsEditorTab {
public static final String NAME = "Comments";

private final String defaultOwner;
public CommentsTab(PreferencesService preferences,
BibDatabaseContext databaseContext,
SuggestionProviders suggestionProviders,
UndoManager undoManager,
DialogService dialogService,
StateManager stateManager,
ThemeManager themeManager,
IndexingTaskManager indexingTaskManager,
TaskExecutor taskExecutor,
JournalAbbreviationRepository journalAbbreviationRepository) {
super(
false,
databaseContext,
suggestionProviders,
undoManager,
dialogService,
preferences,
stateManager,
themeManager,
taskExecutor,
journalAbbreviationRepository,
indexingTaskManager
);
this.defaultOwner = preferences.getOwnerPreferences().getDefaultOwner();
setText(Localization.lang("Comments"));
setGraphic(IconTheme.JabRefIcons.COMMENT.getGraphicNode());
}

@Override
protected Set<Field> determineFieldsToShow(BibEntry entry) {
UserSpecificCommentField defaultCommentField = new UserSpecificCommentField(defaultOwner);

// As default: Show BibTeX comment field and the user-specific comment field of the default owner
Set<Field> comments = new LinkedHashSet<>(Set.of(defaultCommentField, StandardField.COMMENT));

comments.addAll(entry.getFields().stream()
.filter(field -> field instanceof UserSpecificCommentField ||
field.getName().toLowerCase().contains("comment"))
.collect(Collectors.toSet()));

return comments;
}

@Override
protected void setupPanel(BibEntry entry, boolean compressed) {
super.setupPanel(entry, compressed);

for (Map.Entry<Field, FieldEditorFX> fieldEditorEntry : editors.entrySet()) {
Field field = fieldEditorEntry.getKey();
FieldEditorFX editor = fieldEditorEntry.getValue();

if (field instanceof UserSpecificCommentField) {
if (field.getName().contains(defaultOwner)) {
editor.getNode().setDisable(false);
}
} else {
editor.getNode().setDisable(!field.getName().equals(StandardField.COMMENT.getName()));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

public class DeprecatedFieldsTab extends FieldsEditorTab {

public static final String NAME = "Deprecated fields";
private final BibEntryTypesManager entryTypesManager;

public DeprecatedFieldsTab(BibDatabaseContext databaseContext,
Expand Down
36 changes: 24 additions & 12 deletions src/main/java/org/jabref/gui/entryeditor/EntryEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.File;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -245,31 +246,43 @@ private void navigateToNextEntry() {
}

private List<EntryEditorTab> createTabs() {
// Preview tab
entryEditorTabs.add(new PreviewTab(databaseContext, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager()));

// Required fields
// Required, optional, deprecated, and "other" fields
entryEditorTabs.add(new RequiredFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository));

// Optional fields
entryEditorTabs.add(new OptionalFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository));
entryEditorTabs.add(new OptionalFields2Tab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository));
entryEditorTabs.add(new DeprecatedFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository));

// Other fields
entryEditorTabs.add(new OtherFieldsTab(databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), bibEntryTypesManager, taskExecutor, journalAbbreviationRepository));

// Comment Tab: Tab for general and user-specific comments
entryEditorTabs.add(new CommentsTab(preferencesService, databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), taskExecutor, journalAbbreviationRepository));

// General fields from preferences
for (Map.Entry<String, Set<Field>> tab : entryEditorPreferences.getEntryEditorTabList().entrySet()) {
// First, remove all tabs that are already handled above or below; except for the source tab (which has different titles for BibTeX and BibLaTeX mode)
Map<String, Set<Field>> entryEditorTabList = new HashMap<>(entryEditorPreferences.getEntryEditorTabList());
entryEditorTabList.remove(PreviewTab.NAME);
entryEditorTabList.remove(RequiredFieldsTab.NAME);
entryEditorTabList.remove(OptionalFieldsTab.NAME);
entryEditorTabList.remove(OptionalFields2Tab.NAME);
entryEditorTabList.remove(DeprecatedFieldsTab.NAME);
entryEditorTabList.remove(CommentsTab.NAME);
entryEditorTabList.remove(MathSciNetTab.NAME);
entryEditorTabList.remove(FileAnnotationTab.NAME);
entryEditorTabList.remove(RelatedArticlesTab.NAME);
entryEditorTabList.remove(LatexCitationsTab.NAME);
entryEditorTabList.remove(FulltextSearchResultsTab.NAME);
entryEditorTabList.remove("Comments");
// Then show the remaining configured
for (Map.Entry<String, Set<Field>> tab : entryEditorTabList.entrySet()) {
entryEditorTabs.add(new UserDefinedFieldsTab(tab.getKey(), tab.getValue(), databaseContext, libraryTab.getSuggestionProviders(), undoManager, dialogService, preferencesService, stateManager, themeManager, libraryTab.getIndexingTaskManager(), taskExecutor, journalAbbreviationRepository));
}

// Special tabs
// "Special" tabs
entryEditorTabs.add(new MathSciNetTab());
entryEditorTabs.add(new FileAnnotationTab(libraryTab.getAnnotationCache()));
entryEditorTabs.add(new RelatedArticlesTab(this, entryEditorPreferences, preferencesService, dialogService));

// Source tab
sourceTab = new SourceTab(
databaseContext,
undoManager,
Expand All @@ -281,7 +294,6 @@ private List<EntryEditorTab> createTabs() {
keyBindingRepository);
entryEditorTabs.add(sourceTab);

// LaTeX citations tab
entryEditorTabs.add(new LatexCitationsTab(databaseContext, preferencesService, taskExecutor, dialogService));

entryEditorTabs.add(new FulltextSearchResultsTab(stateManager, preferencesService, dialogService));
Expand Down Expand Up @@ -408,8 +420,8 @@ private void fetchAndMerge(EntryBasedFetcher fetcher) {
public void setFocusToField(Field field) {
DefaultTaskExecutor.runInJavaFXThread(() -> {
for (Tab tab : tabbed.getTabs()) {
if ((tab instanceof FieldsEditorTab fieldsEditorTab) && fieldsEditorTab.getShownFields()
.contains(field)) {
if ((tab instanceof FieldsEditorTab fieldsEditorTab)
&& fieldsEditorTab.getShownFields().contains(field)) {
tabbed.getSelectionModel().select(tab);
fieldsEditorTab.requestFocus(field);
}
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
*/
abstract class FieldsEditorTab extends EntryEditorTab {
protected final BibDatabaseContext databaseContext;
private final Map<Field, FieldEditorFX> editors = new LinkedHashMap<>();
protected final Map<Field, FieldEditorFX> editors = new LinkedHashMap<>();
private final boolean isCompressed;
private final SuggestionProviders suggestionProviders;
private final DialogService dialogService;
Expand Down Expand Up @@ -93,7 +93,7 @@ private static void addColumn(GridPane gridPane, int columnIndex, Stream<Parent>
gridPane.addColumn(columnIndex, nodes.toArray(Node[]::new));
}

private void setupPanel(BibEntry entry, boolean compressed) {
protected void setupPanel(BibEntry entry, boolean compressed) {
// The preferences might be not initialized in tests -> return immediately
// TODO: Replace this ugly workaround by proper injection propagation
if (preferences == null) {
Expand Down Expand Up @@ -184,9 +184,6 @@ private void setCompressedRowLayout(GridPane gridPane, int rows) {
}
}

/**
* Focuses the given field.
*/
public void requestFocus(Field fieldName) {
if (editors.containsKey(fieldName)) {
editors.get(fieldName).focus();
Expand All @@ -202,7 +199,6 @@ public boolean shouldShow(BibEntry entry) {
protected void bindToEntry(BibEntry entry) {
initPanel();
setupPanel(entry, isCompressed);

if (previewPanel != null) {
previewPanel.setEntry(entry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

public class LatexCitationsTab extends EntryEditorTab {

public static final String NAME = "LaTeX Citations";
private final LatexCitationsTabViewModel viewModel;
private final GridPane searchPane;
private final ProgressIndicator progressIndicator;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/jabref/gui/entryeditor/MathSciNetTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

public class MathSciNetTab extends EntryEditorTab {

public static final String NAME = "MathSciNet Review";

public MathSciNetTab() {
setText(Localization.lang("MathSciNet Review"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import org.jabref.preferences.PreferencesService;

public class OptionalFields2Tab extends OptionalFieldsTabBase {

public static final String NAME = "Optional fields 2";

public OptionalFields2Tab(BibDatabaseContext databaseContext,
SuggestionProviders suggestionProviders,
UndoManager undoManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import org.jabref.preferences.PreferencesService;

public class OptionalFieldsTab extends OptionalFieldsTabBase {

public static final String NAME = "Optional fields";

public OptionalFieldsTab(BibDatabaseContext databaseContext,
SuggestionProviders suggestionProviders,
UndoManager undoManager,
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/org/jabref/gui/entryeditor/OtherFieldsTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@
import org.jabref.model.entry.field.BibField;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.InternalField;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.field.UserSpecificCommentField;
import org.jabref.preferences.PreferencesService;

public class OtherFieldsTab extends FieldsEditorTab {

public static final String NAME = "Other fields";
private final List<Field> customTabFieldNames;
private final BibEntryTypesManager entryTypesManager;

Expand Down Expand Up @@ -72,8 +75,10 @@ protected Set<Field> determineFieldsToShow(BibEntry entry) {
Optional<BibEntryType> entryType = entryTypesManager.enrich(entry.getType(), mode);
if (entryType.isPresent()) {
Set<Field> allKnownFields = entryType.get().getAllFields();
Set<Field> otherFields = entry.getFields().stream().filter(field -> !allKnownFields.contains(field)).collect(Collectors.toCollection(LinkedHashSet::new));

Set<Field> otherFields = entry.getFields().stream()
.filter(field -> !allKnownFields.contains(field) &&
!(field.equals(StandardField.COMMENT) || field instanceof UserSpecificCommentField))
.collect(Collectors.toCollection(LinkedHashSet::new));
otherFields.removeAll(entryType.get().getDeprecatedFields(mode));
otherFields.removeAll(entryType.get().getOptionalFields().stream().map(BibField::field).collect(Collectors.toSet()));
otherFields.remove(InternalField.KEY_FIELD);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/gui/entryeditor/PreviewTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.jabref.preferences.PreferencesService;

public class PreviewTab extends EntryEditorTab {
public static final String NAME = "Preview";
private final DialogService dialogService;
private final BibDatabaseContext databaseContext;
private final PreferencesService preferences;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
*/
public class RelatedArticlesTab extends EntryEditorTab {

public static final String NAME = "Related articles";
private static final Logger LOGGER = LoggerFactory.getLogger(RelatedArticlesTab.class);
private final EntryEditorPreferences preferences;
private final DialogService dialogService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

public class RequiredFieldsTab extends FieldsEditorTab {

public static final String NAME = "Required fields";
private final BibEntryTypesManager entryTypesManager;

public RequiredFieldsTab(BibDatabaseContext databaseContext,
Expand All @@ -44,7 +45,6 @@ public RequiredFieldsTab(BibDatabaseContext databaseContext,
super(false, databaseContext, suggestionProviders, undoManager, dialogService,
preferences, stateManager, themeManager, taskExecutor, journalAbbreviationRepository, indexingTaskManager);
this.entryTypesManager = entryTypesManager;

setText(Localization.lang("Required fields"));
setTooltip(new Tooltip(Localization.lang("Show required fields")));
setGraphic(IconTheme.JabRefIcons.REQUIRED.getGraphicNode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

public class FileAnnotationTab extends EntryEditorTab {

public static final String NAME = "File annotations";
private final FileAnnotationCache fileAnnotationCache;

public FileAnnotationTab(FileAnnotationCache cache) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

public class FulltextSearchResultsTab extends EntryEditorTab {

public static final String NAME = "Search results";
private static final Logger LOGGER = LoggerFactory.getLogger(FulltextSearchResultsTab.class);

private final StateManager stateManager;
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/jabref/model/entry/field/FieldFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public static String serializeFieldsList(Collection<Field> fields) {
}

public static <T> Field parseField(T type, String fieldName) {
// Check if the field name starts with "comment-" which indicates it's a UserSpecificCommentField
if (fieldName.startsWith("comment-")) {
String username = fieldName.substring("comment-".length());
return new UserSpecificCommentField(username);
}
return OptionalUtil.<Field>orElse(
OptionalUtil.<Field>orElse(
OptionalUtil.<Field>orElse(
Expand Down Expand Up @@ -156,6 +161,7 @@ private static Set<Field> getAllFields() {
fields.addAll(EnumSet.allOf(InternalField.class));
fields.addAll(EnumSet.allOf(SpecialField.class));
fields.addAll(EnumSet.allOf(StandardField.class));
fields.removeIf(field -> field instanceof UserSpecificCommentField);
return fields;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ public enum FieldProperty {
SINGLE_ENTRY_LINK,
TYPE,
VERBATIM,
YES_NO
YES_NO,
COMMENT
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public enum StandardField implements Field {
BOOKTITLEADDON("booktitleaddon"),
CHAPTER("chapter"),
COMMENTATOR("commentator", FieldProperty.PERSON_NAMES),
COMMENT("comment"),
COMMENT("comment", FieldProperty.COMMENT),
CROSSREF("crossref", FieldProperty.SINGLE_ENTRY_LINK),
DATE("date", FieldProperty.DATE),
DAY("day"),
Expand Down
Loading

0 comments on commit 76e2ce7

Please sign in to comment.