Skip to content

Commit fbf3405

Browse files
committed
Merge branch 'main' of https://github.com/JabRef/jabref into fix-for-issue-JabRef#12272
2 parents f048c4b + 516ee3c commit fbf3405

14 files changed

+203
-29
lines changed

.github/workflows/assign-issue.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
3535
⏳ Please note, you will be automatically unassigned if the issue isn't closed within **{{ total_days }} days** (by **{{ unassigned_date }}**). A maintainer can also add the "**{{ pin_label }}**"" label to prevent automatic unassignment.
3636
- name: Move Issue to "Assigned" Column in "Candidates for University Projects"
37-
uses: koppor/github-action-move-issues@work-for-labeled
37+
uses: m7kvqbe1/github-action-move-issues@feat/skip-if-not-in-project-flag
3838
# Action currently works for issues only - pre-condition: https://github.com/takanome-dev/assign-issue-action/issues/269 fixed
3939
if: github.event_name == 'issue_comment'
4040
with:
@@ -46,7 +46,7 @@ jobs:
4646
default-column: "Free to take"
4747
skip-if-not-in-project: true
4848
- name: Move Issue to "Assigned" Column in "Good First Issues"
49-
uses: koppor/github-action-move-issues@work-for-labeled
49+
uses: m7kvqbe1/github-action-move-issues@feat/skip-if-not-in-project-flag
5050
if: github.event_name == 'issue_comment'
5151
with:
5252
github-token: ${{ secrets.GH_TOKEN_ACTION_MOVE_ISSUE }}

.github/workflows/product-map.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Product Map Generation
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
generate-map:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 100
18+
19+
- name: Get changed Java files
20+
id: changed-files
21+
run: |
22+
FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} -- '*.java' | sed 's|^|\"|' | sed 's|$|\"|' | paste -sd "," -)
23+
if [ -z "$FILES" ]; then FILES="\"dummy.java\""; fi
24+
echo "expected_files=(${FILES})" >> $GITHUB_ENV
25+
26+
- name: ProductMap Map Generation
27+
uses: product-map/product-map-action@main
28+
# disabled because of https://github.com/product-map/product-map-action/issues/7
29+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
30+
with:
31+
github_token: ${{ secrets.GITHUB_TOKEN }}
32+
expected_files: ${{ env.expected_files }}
33+
user_email: [email protected]

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,21 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
1919
- We added a new "Copy citation (text)" button in the context menu of the preview. [#12551](https://github.com/JabRef/jabref/issues/12551)
2020
- We added a new "Export to clipboard" button in the context menu of the preview. [#12551](https://github.com/JabRef/jabref/issues/12551)
2121
- We added an integrity check if a URL appears in a title. [#12354](https://github.com/JabRef/jabref/issues/12354)
22+
- We added a feature for enabling drag-and-drop of files into groups [#12540](https://github.com/JabRef/jabref/issues/12540)
23+
- We added support for reordering keywords via drag and drop, automatic alphabetical ordering, and improved pasting and editing functionalities in the keyword editor. [#10984](https://github.com/JabRef/jabref/issues/10984)
2224

2325
### Changed
2426

2527
- We moved the "Generate a new key for imported entries" option from the "Web search" tab to the "Citation key generator" tab in preferences. [#12436](https://github.com/JabRef/jabref/pull/12436)
2628
- We improved the offline parsing of BibTeX data from PDF-documents. [#12278](https://github.com/JabRef/jabref/issues/12278)
2729
- The tab bar is now hidden when only one library is open. [#9971](https://github.com/JabRef/jabref/issues/9971)
30+
- We renamed "Rename file to a given name" to "Rename files to configured filename format pattern" in the entry editor. [#12587](https://github.com/JabRef/jabref/pull/12587)
31+
- We renamed "Move DOIs from note and URL field to DOI field and remove http prefix" to "Move DOIs from 'note' field and 'URL' field to 'DOI' field and remove http prefix" in the Cleanup entries. [#12587](https://github.com/JabRef/jabref/pull/12587)
32+
- We renamed "Move preprint information from 'URL' and 'journal' field to the 'eprint' field" to "Move preprint information from 'URL' field and 'journal' field to the 'eprint' field" in the Cleanup entries. [#12587](https://github.com/JabRef/jabref/pull/12587)
33+
- We renamed "Move URL in note field to url field" to "Move URL in 'note' field to 'URL' field" in the Cleanup entries. [#12587](https://github.com/JabRef/jabref/pull/12587)
34+
- We renamed "Rename PDFs to given filename format pattern" to "Rename files to configured filename format pattern" in the Cleanup entries. [#12587](https://github.com/JabRef/jabref/pull/12587)
35+
- We renamed "Rename only PDFs having a relative path" to "Only rename files that have a relative path" in the Cleanup entries. [#12587](https://github.com/JabRef/jabref/pull/12587)
36+
- We renamed "Filename format pattern: " to "Filename format pattern (from preferences)" in the Cleanup entries. [#12587](https://github.com/JabRef/jabref/pull/12587)
2837
- When working with CSL styles in LibreOffice, citing with a new style now updates all other citations in the document to have the currently selected style. [#12472](https://github.com/JabRef/jabref/pull/12472)
2938
- We improved the user comments field visibility so that it remains displayed if it contains text. Additionally, users can now easily toggle the field on or off via buttons unless disabled in preferences. [#11021](https://github.com/JabRef/jabref/issues/11021)
3039
- The LibreOffice integration for CSL styles is now more performant. [#12472](https://github.com/JabRef/jabref/pull/12472)

CONTRIBUTING.md

+21-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ General overview about contributing for non-programmers is available at <https:/
55
We welcome contributions to JabRef and encourage you to follow the GitHub workflow specified below.
66
If you are not familiar with this type of workflow, take a look at GitHub's excellent overview on the [GitHub flow](https://docs.github.com/en/get-started/using-github/github-flow) and the explanation of [Feature Branch Workflow](https://atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow) for the idea behind this kind of development.
77

8+
**JabRef regards its contributors as [software engineers, not just programmers](https://www.phoenix.edu/blog/programmer-vs-software-engineer-key-differences.html)**.
9+
As one consequence, for non-basic issues, you will have to work on the requirements side, too.
10+
811
Before you start, get the JabRef code on your local machine.
912
Detailed instructions about this step can be found in our [guidelines for setting up a local workspace](https://devdocs.jabref.org/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/).
1013

@@ -27,11 +30,27 @@ Some are simpler, while others are more complex. Our primary aim is to guide you
2730

2831
### I am a student and I want to start with something easy
2932

30-
We collect good issues to start with at our [list of good first issues](https://github.com/orgs/JabRef/projects/5/views/1).
33+
We collect good issues to start with at our [list of unassigned good first issues](https://github.com/JabRef/jabref/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20label%3A%22good%20first%20issue%22%20no%3Aassignee).
3134

3235
### I am a student and I want to choose from a curated list of university projects
3336

34-
Take a look at [JabRef's candidates for university projects](https://github.com/orgs/JabRef/projects/3). There, a list of possible projects to work on during a teaching period is offered.
37+
Apart from "good first issues", we also offer collections of curated issues to work on.
38+
We categorize them into "small", "medium", and "large".
39+
All of them are intended to
40+
a) bring you closer to a larger code base with a dedicated issue and
41+
b) be clear in their description of work.
42+
Sometimes, you may need to refine the requirements:
43+
We see contributors as software engineers and [not just programmers](https://www.phoenix.edu/blog/programmer-vs-software-engineer-key-differences.html).
44+
Thus, requirement engineering inherently comes up as a part of the process.
45+
46+
Take a look at [JabRef's candidates for university projects](https://github.com/orgs/JabRef/projects/3).
47+
Here, you will get a table of curated issues.
48+
The table offers filtering for small, medium, and large projects.
49+
You can check the main focus (UI, logic, or both), the issue understanding effort, the implementation effort, and testing effort.
50+
The "issue understanding effort" is an indication of how much time you will need to understand the issue before you can do any coding. It may depend on how easy it is to reproduce the issue, how much background knowledge is needed, etc.
51+
The "implementation effort" is based on our experience of JabRef development.
52+
Note that there may be issues with a high effort in understanding, but low implementation effort.
53+
The challenge of these issues is to understand **where** in the code base something needs to be modified.
3554

3655
### I am a lecturer
3756

src/main/java/org/jabref/gui/actions/StandardActions.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public enum StandardActions implements Action {
157157
DOWNLOAD_FILE(Localization.lang("Download file"), IconTheme.JabRefIcons.DOWNLOAD_FILE),
158158
REDOWNLOAD_FILE(Localization.lang("Redownload file"), IconTheme.JabRefIcons.DOWNLOAD_FILE),
159159
RENAME_FILE_TO_PATTERN(Localization.lang("Rename file to defined pattern"), IconTheme.JabRefIcons.AUTO_RENAME),
160-
RENAME_FILE_TO_NAME(Localization.lang("Rename file to a given name"), IconTheme.JabRefIcons.RENAME, KeyBinding.REPLACE_STRING),
160+
RENAME_FILE_TO_NAME(Localization.lang("Rename files to configured filename format pattern"), IconTheme.JabRefIcons.RENAME, KeyBinding.REPLACE_STRING),
161161
MOVE_FILE_TO_FOLDER(Localization.lang("Move file to file directory"), IconTheme.JabRefIcons.MOVE_TO_FOLDER),
162162
MOVE_FILE_TO_FOLDER_AND_RENAME(Localization.lang("Move file to file directory and rename file")),
163163
COPY_FILE_TO_FOLDER(Localization.lang("Copy linked file to folder..."), IconTheme.JabRefIcons.COPY_TO_FOLDER, KeyBinding.COPY),

src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.fxml

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
<VBox.margin>
1818
<Insets left="20.0" />
1919
</VBox.margin>
20-
<CheckBox fx:id="cleanUpDOI" text="%Move DOIs from note and URL field to DOI field and remove http prefix" />
21-
<CheckBox fx:id="cleanUpEprint" text="%Move preprint information from 'URL' and 'journal' field to the 'eprint' field" />
22-
<CheckBox fx:id="cleanUpURL" text="%Move URL in note field to url field" />
20+
<CheckBox fx:id="cleanUpDOI" text="%Move DOIs from 'note' field and 'URL' field to 'DOI' field and remove http prefix" />
21+
<CheckBox fx:id="cleanUpEprint" text="%Move preprint information from 'URL' field and 'journal' field to the 'eprint' field" />
22+
<CheckBox fx:id="cleanUpURL" text="%Move URL in 'note' field to 'URL' field" />
2323
<CheckBox fx:id="cleanUpISSN" text="%Reformat ISSN" />
2424
<CheckBox fx:id="cleanUpBiblatex" text="%Convert to biblatex format (e.g., store publication date in date field)" />
2525
<CheckBox fx:id="cleanUpBibtex" text="%Convert to BibTeX format (e.g., store publication date in year and month fields)" />
@@ -35,10 +35,10 @@
3535
<CheckBox fx:id="cleanUpUpgradeExternalLinks" />
3636
<CheckBox fx:id="cleanUpMovePDF" />
3737
<CheckBox fx:id="cleanUpMakePathsRelative" text="%Make paths of linked files relative (if possible)" />
38-
<CheckBox fx:id="cleanUpRenamePDF" text="%Rename PDFs to given filename format pattern" />
38+
<CheckBox fx:id="cleanUpRenamePDF" text="%Rename files to configured filename format pattern" />
3939
<VBox prefHeight="40.0" prefWidth="451.0" spacing="10.0">
4040
<Label fx:id="cleanupRenamePDFLabel" />
41-
<CheckBox fx:id="cleanUpRenamePDFonlyRelativePaths" text="%Rename only PDFs having a relative path" />
41+
<CheckBox fx:id="cleanUpRenamePDFonlyRelativePaths" text="%Only rename files that have a relative path" />
4242
<VBox.margin>
4343
<Insets left="20.0" />
4444
</VBox.margin>

src/main/java/org/jabref/gui/cleanup/CleanupPresetPanel.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ private void init(CleanupPreferences cleanupPreferences, FilePreferences filePre
6868

6969
cleanUpUpgradeExternalLinks.setText(Localization.lang("Upgrade external PDF/PS links to use the '%0' field.", StandardField.FILE.getDisplayName()));
7070

71-
String currentPattern = Localization.lang("Filename format pattern")
72-
.concat(": ")
71+
String currentPattern = Localization.lang("Filename format pattern (from preferences)")
7372
.concat(filePreferences.getFileNamePattern());
7473
cleanupRenamePDFLabel.setText(currentPattern);
7574

src/main/java/org/jabref/gui/fieldeditors/KeywordsEditor.java

+80-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jabref.gui.fieldeditors;
22

33
import java.util.Comparator;
4+
import java.util.Optional;
45

56
import javax.swing.undo.UndoManager;
67

@@ -12,6 +13,10 @@
1213
import javafx.scene.control.ContentDisplay;
1314
import javafx.scene.control.ContextMenu;
1415
import javafx.scene.control.Label;
16+
import javafx.scene.input.ClipboardContent;
17+
import javafx.scene.input.DragEvent;
18+
import javafx.scene.input.Dragboard;
19+
import javafx.scene.input.TransferMode;
1520
import javafx.scene.layout.HBox;
1621

1722
import org.jabref.gui.ClipBoardManager;
@@ -22,16 +27,21 @@
2227
import org.jabref.gui.actions.StandardActions;
2328
import org.jabref.gui.autocompleter.SuggestionProvider;
2429
import org.jabref.gui.icon.IconTheme;
30+
import org.jabref.gui.keyboard.KeyBinding;
31+
import org.jabref.gui.keyboard.KeyBindingRepository;
2532
import org.jabref.gui.util.ViewModelListCellFactory;
2633
import org.jabref.logic.integrity.FieldCheckers;
2734
import org.jabref.logic.l10n.Localization;
2835
import org.jabref.logic.preferences.CliPreferences;
2936
import org.jabref.model.entry.BibEntry;
3037
import org.jabref.model.entry.Keyword;
38+
import org.jabref.model.entry.KeywordList;
3139
import org.jabref.model.entry.field.Field;
3240

41+
import com.airhacks.afterburner.injection.Injector;
3342
import com.airhacks.afterburner.views.ViewLoader;
3443
import com.dlsc.gemsfx.TagsField;
44+
import com.google.common.collect.Comparators;
3545
import jakarta.inject.Inject;
3646
import org.slf4j.Logger;
3747
import org.slf4j.LoggerFactory;
@@ -48,6 +58,9 @@ public class KeywordsEditor extends HBox implements FieldEditorFX {
4858
@Inject private UndoManager undoManager;
4959
@Inject private ClipBoardManager clipBoardManager;
5060

61+
private boolean isSortedTagsField = false;
62+
private Optional<Keyword> draggedKeyword = Optional.empty();
63+
5164
public KeywordsEditor(Field field,
5265
SuggestionProvider<?> suggestionProvider,
5366
FieldCheckers fieldCheckers) {
@@ -87,6 +100,29 @@ public KeywordsEditor(Field field,
87100
}
88101
});
89102

103+
this.viewModel.keywordListProperty().addListener((observable, oldValue, newValue) -> {
104+
if (keywordTagsField.getTags().size() < 2) {
105+
isSortedTagsField = false;
106+
} else if ((Comparators.isInOrder(keywordTagsField.getTags(), Comparator.comparing(Keyword::get))) || isSortedTagsField) {
107+
isSortedTagsField = true;
108+
keywordTagsField.getTags().sort(Comparator.comparing(Keyword::get));
109+
}
110+
});
111+
112+
keywordTagsField.getEditor().setOnKeyPressed(event -> {
113+
KeyBindingRepository keyBindingRepository = Injector.instantiateModelOrService(KeyBindingRepository.class);
114+
115+
if (keyBindingRepository.checkKeyCombinationEquality(KeyBinding.PASTE, event)) {
116+
String clipboardText = clipBoardManager.getContents();
117+
if (!clipboardText.isEmpty()) {
118+
KeywordList keywordsList = KeywordList.parse(clipboardText, viewModel.getKeywordSeparator());
119+
keywordsList.stream().forEach(keyword -> keywordTagsField.addTags(keyword));
120+
keywordTagsField.getEditor().clear();
121+
event.consume();
122+
}
123+
}
124+
});
125+
90126
Bindings.bindContentBidirectional(keywordTagsField.getTags(), viewModel.keywordListProperty());
91127
}
92128

@@ -104,6 +140,46 @@ private Node createTag(Keyword keyword) {
104140
factory.createMenuItem(StandardActions.DELETE, new KeywordsEditor.TagContextAction(StandardActions.DELETE, keyword))
105141
);
106142
tagLabel.setContextMenu(contextMenu);
143+
tagLabel.setOnMouseClicked(event -> {
144+
if (event.getClickCount() == 2) {
145+
keywordTagsField.removeTags(keyword);
146+
keywordTagsField.getEditor().setText(keyword.get());
147+
keywordTagsField.getEditor().positionCaret(keyword.get().length());
148+
}
149+
});
150+
tagLabel.setOnDragOver(event -> {
151+
if (event.getGestureSource() != tagLabel && event.getDragboard().hasString()) {
152+
event.acceptTransferModes(TransferMode.MOVE);
153+
}
154+
event.consume();
155+
});
156+
tagLabel.setOnDragDetected(event -> {
157+
Dragboard db = tagLabel.startDragAndDrop(TransferMode.MOVE);
158+
ClipboardContent content = new ClipboardContent();
159+
content.putString(keyword.get());
160+
db.setContent(content);
161+
draggedKeyword = Optional.of(keyword);
162+
event.consume();
163+
});
164+
tagLabel.setOnDragEntered(event -> tagLabel.setStyle("-fx-background-color: lightgrey;"));
165+
tagLabel.setOnDragExited(event -> tagLabel.setStyle(""));
166+
tagLabel.setOnDragDropped(event -> {
167+
Dragboard db = event.getDragboard();
168+
if (db.hasString() && draggedKeyword.isPresent()) {
169+
int oldIndex = keywordTagsField.getTags().indexOf(draggedKeyword.get());
170+
int dropIndex = keywordTagsField.getTags().indexOf(keyword);
171+
if (oldIndex != dropIndex) {
172+
keywordTagsField.removeTags(draggedKeyword.get());
173+
keywordTagsField.getTags().add(dropIndex, draggedKeyword.get());
174+
}
175+
event.setDropCompleted(true);
176+
} else {
177+
event.setDropCompleted(false);
178+
}
179+
draggedKeyword = Optional.empty();
180+
event.consume();
181+
});
182+
tagLabel.setOnDragDone(DragEvent::consume);
107183
return tagLabel;
108184
}
109185

@@ -141,18 +217,18 @@ public void execute() {
141217
case COPY -> {
142218
clipBoardManager.setContent(keyword.get());
143219
dialogService.notify(Localization.lang("Copied '%0' to clipboard.",
144-
JabRefDialogService.shortenDialogMessage(keyword.get())));
220+
JabRefDialogService.shortenDialogMessage(keyword.get())));
145221
}
146222
case CUT -> {
147223
clipBoardManager.setContent(keyword.get());
148224
dialogService.notify(Localization.lang("Copied '%0' to clipboard.",
149-
JabRefDialogService.shortenDialogMessage(keyword.get())));
225+
JabRefDialogService.shortenDialogMessage(keyword.get())));
150226
keywordTagsField.removeTags(keyword);
151227
}
152228
case DELETE ->
153-
keywordTagsField.removeTags(keyword);
229+
keywordTagsField.removeTags(keyword);
154230
default ->
155-
LOGGER.info("Action {} not defined", command.getText());
231+
LOGGER.info("Action {} not defined", command.getText());
156232
}
157233
}
158234
}

src/main/java/org/jabref/gui/groups/GroupNodeViewModel.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,8 @@ public boolean acceptableDrop(Dragboard dragboard) {
349349
// TODO: we should also check isNodeDescendant
350350
boolean canDropOtherGroup = dragboard.hasContent(DragAndDropDataFormats.GROUP);
351351
boolean canDropEntries = localDragBoard.hasBibEntries() && (groupNode.getGroup() instanceof GroupEntryChanger);
352-
return canDropOtherGroup || canDropEntries;
352+
boolean canDropFiles = dragboard.hasFiles();
353+
return canDropOtherGroup || canDropEntries || canDropFiles;
353354
}
354355

355356
public void moveTo(GroupNodeViewModel target) {

0 commit comments

Comments
 (0)