Skip to content

Commit

Permalink
Feature add git workflow for slr search (#7625)
Browse files Browse the repository at this point in the history
* Add study UI and Git support

* Modify localization

* Fix checkstyle

* Fix test issues

* Fix architecture test, modify some formulations in UI

* Add DI for services

* Get table views working
standardize UI

* Clean up

* Make localization consistent

* Compressed fxml and fixed minor visual issue (table cell too small)

* Reduced code duplication

Co-authored-by: Carl Christian Snethlage <cc.snethlage@gmail.com>
Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>
  • Loading branch information
3 people authored Jul 4, 2021
1 parent eed637a commit f0709b7
Show file tree
Hide file tree
Showing 26 changed files with 1,612 additions and 251 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We added two new fields to track the creation and most recent modification date and time for each entry. [koppor#130](https://github.com/koppor/jabref/issues/130)
- We added a feature that allows the user to copy highlighted text in the preview window. [#6962](https://github.com/JabRef/jabref/issues/6962)
- We added a feature that allows you to create new BibEntry via paste arxivId [#2292](https://github.com/JabRef/jabref/issues/2292)
- We added support for conducting automated and systematic literature search across libraries and git support for persistence [#369](https://github.com/koppor/jabref/issues/369)
- We added a add group functionality at the bottom of the side pane. [#4682](https://github.com/JabRef/jabref/issues/4682)
- We added a feature that allows the user to choose whether to trust the target site when unable to find a valid certification path from the file download site. [#7616](https://github.com/JabRef/jabref/issues/7616)
- We added a feature that allows the user to open all linked files of multiple selected entries by "Open file" option. [#6966](https://github.com/JabRef/jabref/issues/6966)
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@
import org.jabref.gui.search.GlobalSearchBar;
import org.jabref.gui.shared.ConnectToSharedDatabaseCommand;
import org.jabref.gui.shared.PullChangesFromSharedAction;
import org.jabref.gui.slr.ExistingStudySearchAction;
import org.jabref.gui.slr.StartNewStudyAction;
import org.jabref.gui.specialfields.SpecialFieldMenuItemFactory;
import org.jabref.gui.texparser.ParseLatexAction;
import org.jabref.gui.undo.CountingUndoManager;
Expand Down Expand Up @@ -813,13 +815,11 @@ private MenuBar createMenu() {

new SeparatorMenuItem(),

factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new SendAsEMailAction(dialogService, prefs, stateManager)),
pushToApplicationMenuItem
// Disabled until PR #7126 can be merged
// new SeparatorMenuItem(),
// factory.createMenuItem(StandardActions.START_SYSTEMATIC_LITERATURE_REVIEW,
// new StartLiteratureReviewAction(this, Globals.getFileUpdateMonitor(), prefs.getWorkingDir(),
// taskExecutor, prefs, prefs.getImportFormatPreferences(), prefs.getSavePreferences()))
factory.createMenuItem(StandardActions.SEND_AS_EMAIL, new SendAsEMailAction(dialogService, this.prefs, stateManager)),
pushToApplicationMenuItem,
new SeparatorMenuItem(),
factory.createMenuItem(StandardActions.START_NEW_STUDY, new StartNewStudyAction(this, Globals.getFileUpdateMonitor(), Globals.TASK_EXECUTOR, prefs)),
factory.createMenuItem(StandardActions.SEARCH_FOR_EXISTING_STUDY, new ExistingStudySearchAction(this, Globals.getFileUpdateMonitor(), Globals.TASK_EXECUTOR, prefs))
);

SidePaneComponent webSearch = sidePaneManager.getComponent(SidePaneType.WEB_SEARCH);
Expand Down
90 changes: 0 additions & 90 deletions src/main/java/org/jabref/gui/StartLiteratureReviewAction.java

This file was deleted.

3 changes: 2 additions & 1 deletion src/main/java/org/jabref/gui/actions/StandardActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public enum StandardActions implements Action {
PARSE_LATEX(Localization.lang("Search for citations in LaTeX files..."), IconTheme.JabRefIcons.LATEX_CITATIONS),
NEW_SUB_LIBRARY_FROM_AUX(Localization.lang("New sublibrary based on AUX file") + "...", Localization.lang("New BibTeX sublibrary") + Localization.lang("This feature generates a new library based on which entries are needed in an existing LaTeX document."), IconTheme.JabRefIcons.NEW),
WRITE_XMP(Localization.lang("Write XMP metadata to PDFs"), Localization.lang("Will write XMP metadata to the PDFs linked from selected entries."), KeyBinding.WRITE_XMP),
START_SYSTEMATIC_LITERATURE_REVIEW(Localization.lang("Start systematic literature review")),
START_NEW_STUDY(Localization.lang("Start new systematic literature review")),
SEARCH_FOR_EXISTING_STUDY(Localization.lang("Perform search for existing systematic literature review")),
OPEN_DATABASE_FOLDER(Localization.lang("Reveal in file explorer")),
OPEN_FOLDER(Localization.lang("Open folder"), Localization.lang("Open folder"), IconTheme.JabRefIcons.FOLDER, KeyBinding.OPEN_FOLDER),
OPEN_FILE(Localization.lang("Open file"), Localization.lang("Open file"), IconTheme.JabRefIcons.FILE, KeyBinding.OPEN_FILE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,20 @@
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<?import org.controlsfx.control.CheckListView?>
<DialogPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="550.0" prefWidth="566.0"
xmlns="http://javafx.com/javafx/8.0.171"
<DialogPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.171"
prefHeight="550.0" prefWidth="566.0"
fx:controller="org.jabref.gui.importer.ImportCustomEntryTypesDialog">
<content>
<VBox spacing="1.0">
<children>
<Label text="%Custom entry types found in file"/>
<Label text="%Select all customized types to be stored in local preferences:"/>
<CheckListView fx:id="unknownEntryTypesCheckList"/>
<VBox fx:id="boxDifferentCustomization">
<children>
<Label text="%Different customization, current settings will be overwritten"/>
<CheckListView fx:id="differentCustomizationCheckList"/>
</children>
</VBox>
</children>
<Label text="%Custom entry types found in file"/>
<Label text="%Select all customized types to be stored in local preferences:"/>
<CheckListView fx:id="unknownEntryTypesCheckList"/>
<VBox fx:id="boxDifferentCustomization">
<Label text="%Different customization, current settings will be overwritten"/>
<CheckListView fx:id="differentCustomizationCheckList"/>
</VBox>
</VBox>
</content>
<buttonTypes>
<ButtonType fx:constant="CANCEL"/>
<ButtonType fx:constant="OK"/>
</buttonTypes>
<ButtonType fx:constant="CANCEL"/>
<ButtonType fx:constant="OK"/>
</DialogPane>
127 changes: 127 additions & 0 deletions src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package org.jabref.gui.slr;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;

import org.jabref.gui.DialogService;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.importer.actions.OpenDatabaseAction;
import org.jabref.gui.util.BackgroundTask;
import org.jabref.gui.util.DirectoryDialogConfiguration;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.crawler.Crawler;
import org.jabref.logic.exporter.SavePreferences;
import org.jabref.logic.git.SlrGitHandler;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.util.FileUpdateMonitor;
import org.jabref.preferences.PreferencesService;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExistingStudySearchAction extends SimpleCommand {
private static final Logger LOGGER = LoggerFactory.getLogger(ExistingStudySearchAction.class);

protected final DialogService dialogService;
protected final Path workingDirectory;

Path studyDirectory;

private final JabRefFrame frame;
private final FileUpdateMonitor fileUpdateMonitor;
private final TaskExecutor taskExecutor;
private final PreferencesService preferencesService;
private final ImportFormatPreferences importFormatPreferneces;
private final SavePreferences savePreferences;
// This can be either populated before crawl is called or is populated in the call using the directory dialog. This is helpful if the directory is selected in a previous dialog/UI element

public ExistingStudySearchAction(JabRefFrame frame, FileUpdateMonitor fileUpdateMonitor, TaskExecutor taskExecutor, PreferencesService preferencesService) {
this.frame = frame;
this.dialogService = frame.getDialogService();
this.fileUpdateMonitor = fileUpdateMonitor;
this.workingDirectory = getInitialDirectory(preferencesService.getWorkingDir());
this.taskExecutor = taskExecutor;
this.preferencesService = preferencesService;
this.importFormatPreferneces = preferencesService.getImportFormatPreferences();
this.savePreferences = preferencesService.getSavePreferences();
}

@Override
public void execute() {
// Reset before each execution
studyDirectory = null;
crawl();
}

public void crawl() {
if (Objects.isNull(studyDirectory)) {
DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder()
.withInitialDirectory(workingDirectory)
.build();

Optional<Path> studyRepositoryRoot = dialogService.showDirectorySelectionDialog(directoryDialogConfiguration);

if (studyRepositoryRoot.isEmpty()) {
// Do nothing if selection was canceled
return;
}
studyDirectory = studyRepositoryRoot.get();
}

try {
setupRepository(studyDirectory);
} catch (IOException | GitAPIException e) {
dialogService.showErrorDialogAndWait(Localization.lang("Study repository could not be created"), e);
return;
}
final Crawler crawler;
try {
crawler = new Crawler(studyDirectory, new SlrGitHandler(studyDirectory), importFormatPreferneces, savePreferences, preferencesService.getTimestampPreferences(), new BibEntryTypesManager(), fileUpdateMonitor);
} catch (IOException | ParseException e) {
LOGGER.error("Error during reading of study definition file.", e);
dialogService.showErrorDialogAndWait(Localization.lang("Error during reading of study definition file."), e);
return;
}
dialogService.notify(Localization.lang("Searching"));
BackgroundTask.wrap(() -> {
crawler.performCrawl();
return 0; // Return any value to make this a callable instead of a runnable. This allows throwing exceptions.
})
.onFailure(e -> {
LOGGER.error("Error during persistence of crawling results.");
dialogService.showErrorDialogAndWait(Localization.lang("Error during persistence of crawling results."), e);
})
.onSuccess(unused -> {
new OpenDatabaseAction(frame, preferencesService, dialogService).openFile(Path.of(studyDirectory.toString(), "studyResult.bib"), true);
// If finished reset command object for next use
studyDirectory = null;
})
.executeWith(taskExecutor);
}

/**
* Hook for setting up the repository
*/
protected void setupRepository(Path studyRepositoryRoot) throws IOException, GitAPIException {
// Do nothing as repository is already setup
}

/**
* @return Path of current panel database directory or the standard working directory
*/
private Path getInitialDirectory(Path standardWorkingDirectory) {
if (frame.getBasePanelCount() == 0) {
return standardWorkingDirectory;
} else {
Optional<Path> databasePath = frame.getCurrentLibraryTab().getBibDatabaseContext().getDatabasePath();
return databasePath.map(Path::getParent).orElse(standardWorkingDirectory);
}
}
}
3 changes: 3 additions & 0 deletions src/main/java/org/jabref/gui/slr/ManageStudyDefinition.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.slr-tab {
-fx-padding: 1em;
}
Loading

0 comments on commit f0709b7

Please sign in to comment.