diff --git a/CHANGELOG.md b/CHANGELOG.md index d171dc7e6ad..5a2f3940d3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We improved JabRef's internal document viewer. It now allows text section, searching and highlighting of search terms and page rotation [#13193](https://github.com/JabRef/jabref/pull/13193). - When importing a PDF, there is no empty entry column shown in the multi merge dialog. [#13132](https://github.com/JabRef/jabref/issues/13132) - We added a progress dialog to the "Check consistency" action and progress output to the corresponding cli command. [#12487](https://github.com/JabRef/jabref/issues/12487) +- We added Enhanced "Citation Relations" feature: "Look up a DOI and try again." is now a clickable hyperlink that triggers a DOI lookup. The link shows result states ("Looking up DOI...", "No DOI found", "List of citations") as appropriate. ### Fixed diff --git a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java b/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java index b883672d884..f5d4ec0a239 100644 --- a/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java +++ b/jabgui/src/main/java/org/jabref/gui/entryeditor/citationrelationtab/CitationRelationsTab.java @@ -20,6 +20,7 @@ import javafx.scene.control.Button; import javafx.scene.control.ButtonType; import javafx.scene.control.DialogPane; +import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ScrollPane; @@ -30,6 +31,8 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; +import javafx.scene.text.Text; +import javafx.scene.text.TextFlow; import org.jabref.gui.DialogService; import org.jabref.gui.LibraryTab; @@ -52,6 +55,9 @@ import org.jabref.logic.citation.SearchCitationsRelationsService; import org.jabref.logic.database.DuplicateCheck; import org.jabref.logic.exporter.BibWriter; +import org.jabref.logic.importer.FetcherClientException; +import org.jabref.logic.importer.FetcherServerException; +import org.jabref.logic.importer.fetcher.CrossRef; import org.jabref.logic.importer.fetcher.citation.CitationFetcher; import org.jabref.logic.l10n.Localization; import org.jabref.logic.os.OS; @@ -201,23 +207,25 @@ private SplitPane getPaneAndStartSearch(BibEntry entry) { refreshCitingButton.setOnMouseClicked(_ -> { searchForRelations( - entry, - citingListView, + entry, + citingListView, abortCitingButton, - refreshCitingButton, - CitationFetcher.SearchType.CITES, - importCitingButton, - citingProgress); + refreshCitingButton, + CitationFetcher.SearchType.CITES, + importCitingButton, + citingProgress, + true); }); refreshCitedByButton.setOnMouseClicked(_ -> searchForRelations( - entry, - citedByListView, + entry, + citedByListView, abortCitedButton, - refreshCitedByButton, - CitationFetcher.SearchType.CITED_BY, - importCitedByButton, - citedByProgress)); + refreshCitedByButton, + CitationFetcher.SearchType.CITED_BY, + importCitedByButton, + citedByProgress, + true)); // Create SplitPane to hold all nodes above SplitPane container = new SplitPane(citingVBox, citedByVBox); @@ -225,22 +233,24 @@ private SplitPane getPaneAndStartSearch(BibEntry entry) { styleFetchedListView(citingListView); searchForRelations( - entry, - citingListView, - abortCitingButton, + entry, + citingListView, + abortCitingButton, refreshCitingButton, - CitationFetcher.SearchType.CITES, - importCitingButton, - citingProgress); + CitationFetcher.SearchType.CITES, + importCitingButton, + citingProgress, + false); searchForRelations( - entry, - citedByListView, - abortCitedButton, + entry, + citedByListView, + abortCitedButton, refreshCitedByButton, - CitationFetcher.SearchType.CITED_BY, - importCitedByButton, - citedByProgress); + CitationFetcher.SearchType.CITED_BY, + importCitedByButton, + citedByProgress, + false); return container; } @@ -434,13 +444,29 @@ protected void bindToEntry(BibEntry entry) { */ private void searchForRelations(BibEntry entry, CheckListView listView, Button abortButton, Button refreshButton, CitationFetcher.SearchType searchType, Button importButton, - ProgressIndicator progress) { + ProgressIndicator progress, boolean shouldRefresh) { if (entry.getDOI().isEmpty()) { hideNodes(abortButton, progress); showNodes(refreshButton); listView.getItems().clear(); - listView.setPlaceholder( - new Label(Localization.lang("The selected entry doesn't have a DOI linked to it. Lookup a DOI and try again."))); + Text doiLookUpText = new Text(Localization.lang("The selected entry doesn't have a DOI linked to it.")); + Hyperlink doiLookUpHyperLink = new Hyperlink(Localization.lang("Lookup a DOI and try again.")); + TextFlow doiLookUpTextFlow = new TextFlow(doiLookUpText, doiLookUpHyperLink); + Label placeHolder = new Label("", doiLookUpTextFlow); + doiLookUpHyperLink.setOnAction(e -> { + CrossRef doiFetcher = new CrossRef(); + BackgroundTask.wrap(() -> doiFetcher.findIdentifier(entry)) + .onRunning(() -> listView.setPlaceholder(new Label("Looking up DOI..."))) + .onSuccess(doiIdentifier -> { + if (doiIdentifier.isPresent()) { + entry.setField(StandardField.DOI, doiIdentifier.get().asString()); + searchForRelations(entry, listView, abortButton, refreshButton, searchType, importButton, progress, shouldRefresh); + } else { + dialogService.notify("No DOI found"); + } + }).onFailure((exception) -> handleIdentifierFetchingError(exception, doiFetcher)).executeWith(taskExecutor); + }); + listView.setPlaceholder(placeHolder); return; } @@ -481,6 +507,19 @@ private void searchForRelations(BibEntry entry, CheckListView