Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show information about the journal #10015

Merged
merged 44 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d64b87a
add script for getting journal data
aqurilla Jun 16, 2023
44abbc2
reduce json size
aqurilla Jun 16, 2023
c01434a
add journal info UI button & gui components
aqurilla Jun 18, 2023
047ad88
add placeholder charts
aqurilla Jun 19, 2023
dd1532f
add journal information fetcher
aqurilla Jun 20, 2023
68fc579
run fetch as background task
aqurilla Jun 22, 2023
3069b02
fetch data using entry issn
aqurilla Jun 22, 2023
88c7f51
add journal information preferences
aqurilla Jun 25, 2023
99fdc18
make journal info service opt-in
aqurilla Jun 25, 2023
ef3d677
add fields to journal info view
aqurilla Jun 25, 2023
3c122ef
update fetcher to use jabref api
aqurilla Jun 27, 2023
564e222
parse remaining fields from json response
aqurilla Jun 28, 2023
a98e233
handle journal info fetching errors
aqurilla Jun 29, 2023
4f93c62
add charts to journal info view
aqurilla Jun 29, 2023
d835179
add fetcher tests
aqurilla Jul 1, 2023
6d03e5b
Update url
tobiasdiez Jul 6, 2023
f96eab5
Merge branch 'main' into fix-for-issue-6189
aqurilla Jul 7, 2023
fe7a990
update translation keys, add script comments
aqurilla Jul 7, 2023
db461de
use issn parser
aqurilla Jul 7, 2023
016a3c2
check error in api response
aqurilla Jul 9, 2023
6bcab0a
add enablement states for online service
aqurilla Jul 9, 2023
5f9a387
add journal info button to ISSN editor
aqurilla Jul 10, 2023
2bc7c78
Merge branch 'main' into fix-for-issue-6189
koppor Jul 11, 2023
8fc14a9
update chart titles and error msg
aqurilla Jul 12, 2023
a5208b3
Merge branch 'main' into fix-for-issue-6189
koppor Jul 12, 2023
3d9a303
Merge branch 'main' into fix-for-issue-6189
aqurilla Jul 13, 2023
9b1b2aa
use enum string in preferences
aqurilla Jul 13, 2023
979b855
Merge branch 'main' into fix-for-issue-6189
aqurilla Jul 15, 2023
b536850
add support for journal name in fetcher
aqurilla Jul 15, 2023
541a56c
update journal info ui
aqurilla Jul 15, 2023
095a715
fix localization tests
aqurilla Jul 15, 2023
2a38fc7
Merge branch 'main' into fix-for-issue-6189
aqurilla Jul 18, 2023
6ec5026
add changelog entry
aqurilla Jul 18, 2023
7156553
Merge branch 'main' into fix-for-issue-6189
aqurilla Jul 22, 2023
9fbeb1c
Remove script to get journal data
tobiasdiez Jul 26, 2023
a6f6473
Change API url to production
tobiasdiez Jul 26, 2023
d3312f2
Merge branch 'main' into fix-for-issue-6189
aqurilla Jul 30, 2023
48a8f9e
change log pattern, make popover detachable
aqurilla Jul 30, 2023
0892751
show info only on fetch failure
aqurilla Jul 30, 2023
257e389
Merge branch 'main' into fix-for-issue-6189
aqurilla Aug 1, 2023
ee104ac
Merge branch 'main' into fix-for-issue-6189
aqurilla Aug 9, 2023
77b3f09
Merge branch 'main' into fix-for-issue-6189
aqurilla Aug 10, 2023
85216eb
update tests
aqurilla Aug 10, 2023
c289c50
Merge branch 'main' into fix-for-issue-6189
aqurilla Aug 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We integrated two mail actions ("As Email" and "To Kindle") under a new "Send" option in the right-click & Tools menus. The Kindle option creates an email targeted to the user's Kindle email, which can be set in preferences under "External programs" [#6186](https://github.com/JabRef/jabref/issues/6186)
- We added an option to clear recent libraries' history. [#10003](https://github.com/JabRef/jabref/issues/10003)
- We added an option to encrypt and remember the proxy password. [#8055](https://github.com/JabRef/jabref/issues/8055)[#10044](https://github.com/JabRef/jabref/issues/10044)
- We added support for showing journal information, via info buttons next to the `Journal` and `ISSN` fields in the entry editor. [#6189](https://github.com/JabRef/jabref/issues/6189)

### Changed

Expand Down
149 changes: 149 additions & 0 deletions scripts/get-journal-data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
"""
This script downloads data for multiple years from the Scimago Journal Rank website
(https://www.scimagojr.com/journalrank.php), parses the CSV files, and builds a consolidated
dataset over all the years, in JSON format.
The downloaded data includes various metrics for academic journals such as SJR,
h-index, doc counts, citation counts, etc.

Usage:
- Update the `current_year` variable to the latest year of data available.
- The script downloads data from the specified start year to the current year.
- The consolidated dataset is saved as `scimagojr_combined_data.json`.

Note:
The dataset is made available via a JabRef Online API, and is accessed at
`org.jabref.logic.journals.JournalInformationFetcher.getJournalInformation()`
"""


import urllib.request
import csv
import os
import json

koppor marked this conversation as resolved.
Show resolved Hide resolved
# current_year should be the latest year of data available at https://www.scimagojr.com/journalrank.php
current_year = 2022
start_year = 1999
data_directory = 'data'


def journal_url(year):
return f'https://www.scimagojr.com/journalrank.php?year={year}&out=xls'


def parse_float(str):
try:
float_val = float(str.replace(',', '.'))
return float_val
except ValueError:
return 0.0


def parse_int(str):
try:
int_val = int(str)
return int_val
except ValueError:
return 0


def download_all_data():
for year in range(start_year, current_year+1):
# download file
print(f'Downloading data for {year}')
url = journal_url(year)
filename = f'scimagojr-journal-{year}.csv'
urllib.request.urlretrieve(url, os.path.join(data_directory, filename))


def get_combined_data():
download_all_data()

# iterate over files and build consolidated dataset
journals = {}
for year in range(start_year, current_year+1):
print(f'Processing {year}')
filename = f'scimagojr-journal-{year}.csv'
with open(os.path.join(data_directory, filename), mode='r') as csv_file:
csv_reader = csv.DictReader(csv_file, delimiter=';')
for row in csv_reader:
# Columns present in the csv:
# 'Rank', 'Sourceid', 'Title', 'Type', 'Issn', 'SJR', 'SJR Best Quartile', 'H index',
# 'Total Docs. (2020)', 'Total Docs. (3years)', 'Total Refs.', 'Total Cites (3years)',
# 'Citable Docs. (3years)', 'Cites / Doc. (2years)', 'Ref. / Doc.', 'Country', 'Region',
# 'Publisher', 'Coverage', 'Categories', 'Areas'

issn = row['Issn']
hIndex = parse_int(row['H index'])
sjr = parse_float(row['SJR'])
rank = parse_int(row['Rank'])
totalDocs = parse_int(row[f'Total Docs. ({year})'])
totalDocs3Years = parse_int(row['Total Docs. (3years)'])
totalRefs = parse_int(row['Total Refs.'])
totalCites3Years = parse_int(row['Total Cites (3years)'])
citableDocs3Years = parse_int(row['Citable Docs. (3years)'])
citesPerDoc2Years = parse_float(row['Cites / Doc. (2years)'])
refPerDoc = parse_float(row['Ref. / Doc.'])

if issn not in journals:
journals[issn] = get_default_entry()
# populate non-varying fields
entry = journals[issn]
entry['sourceId'] = row['Sourceid']
entry['title'] = row['Title']
entry['type'] = row['Type']
entry['issn'] = issn
entry['country'] = row['Country']
entry['region'] = row['Region']
entry['publisher'] = row['Publisher']
entry['coverage'] = row['Coverage']
entry['categories'] = row['Categories']
entry['areas'] = row['Areas']

# populate yearly varying fields
entry = journals[issn]
entry['rank'].append((year, rank))
entry['sjr'].append((year, sjr))
entry['hIndex'].append((year, hIndex))
entry['totalDocs'].append((year, totalDocs))
entry['totalDocs3Years'].append((year, totalDocs3Years))
entry['totalRefs'].append((year, totalRefs))
entry['totalCites3Years'].append((year, totalCites3Years))
entry['citableDocs3Years'].append((year, citableDocs3Years))
entry['citesPerDoc2Years'].append((year, citesPerDoc2Years))
entry['refPerDoc'].append((year, refPerDoc))

# write to json file
print('Writing to json')
with open('scimagojr_combined_data.json', 'w') as fp:
json.dump(journals, fp)

print(f'Number of journals collected: {len(journals)}')


def get_default_entry():
return {
'sourceId': '',
'title': '',
'type': '',
'issn': '',
'country': '',
'region': '',
'publisher': '',
'coverage': '',
'categories': '',
'areas': '',
'rank': [],
'sjr': [],
'hIndex': [],
'totalDocs': [],
'totalDocs3Years': [],
'totalRefs': [],
'totalCites3Years': [],
'citableDocs3Years': [],
'citesPerDoc2Years': [],
'refPerDoc': [],
}


get_combined_data()
4 changes: 3 additions & 1 deletion src/main/java/org/jabref/gui/fieldeditors/FieldEditors.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static FieldEditorFX getForField(final Field field,
} else if (fieldProperties.contains(FieldProperty.EXTERNAL)) {
return new UrlEditor(field, dialogService, suggestionProvider, fieldCheckers, preferences);
} else if (fieldProperties.contains(FieldProperty.JOURNAL_NAME)) {
return new JournalEditor(field, journalAbbreviationRepository, preferences, suggestionProvider, fieldCheckers);
return new JournalEditor(field, taskExecutor, dialogService, journalAbbreviationRepository, preferences, suggestionProvider, fieldCheckers);
} else if (fieldProperties.contains(FieldProperty.DOI) || fieldProperties.contains(FieldProperty.EPRINT) || fieldProperties.contains(FieldProperty.ISBN)) {
return new IdentifierEditor(field, taskExecutor, dialogService, suggestionProvider, fieldCheckers, preferences);
} else if (field == StandardField.OWNER) {
Expand Down Expand Up @@ -97,6 +97,8 @@ public static FieldEditorFX getForField(final Field field,
return new KeywordsEditor(field, suggestionProvider, fieldCheckers, preferences);
} else if (field == InternalField.KEY_FIELD) {
return new CitationKeyEditor(field, preferences, suggestionProvider, fieldCheckers, databaseContext, undoManager, dialogService);
} else if (field == StandardField.ISSN) {
return new ISSNEditor(field, suggestionProvider, fieldCheckers, preferences, taskExecutor, dialogService);
} else {
// default
return new SimpleEditor(field, suggestionProvider, fieldCheckers, preferences, isMultiLine);
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/org/jabref/gui/fieldeditors/ISSNEditor.fxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.HBox?>
<?import org.jabref.gui.icon.JabRefIconView?>
<?import javafx.scene.layout.VBox?>
<?import org.jabref.gui.fieldeditors.EditorTextArea?>
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="HBox" xmlns="http://javafx.com/javafx/8.0.112"
fx:controller="org.jabref.gui.fieldeditors.ISSNEditor">
<EditorTextArea fx:id="textArea"/>
<VBox>
<Button fx:id="journalInfoButton"
onAction="#showJournalInfo"
styleClass="icon-button">
<graphic>
<JabRefIconView glyph="VIEW_JOURNAL_INFO"/>
</graphic>
<tooltip>
<Tooltip text="%View journal info"/>
</tooltip>
</Button>
</VBox>
</fx:root>
77 changes: 77 additions & 0 deletions src/main/java/org/jabref/gui/fieldeditors/ISSNEditor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.jabref.gui.fieldeditors;

import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;

import org.jabref.gui.DialogService;
import org.jabref.gui.autocompleter.SuggestionProvider;
import org.jabref.gui.fieldeditors.contextmenu.DefaultMenu;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.integrity.FieldCheckers;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.Field;
import org.jabref.preferences.PreferencesService;

import com.airhacks.afterburner.views.ViewLoader;

public class ISSNEditor extends HBox implements FieldEditorFX {
@FXML private ISSNEditorViewModel viewModel;
@FXML private EditorTextArea textArea;
@FXML private Button journalInfoButton;
private final DialogService dialogService;
private final PreferencesService preferencesService;

public ISSNEditor(Field field,
SuggestionProvider<?> suggestionProvider,
FieldCheckers fieldCheckers,
PreferencesService preferences,
TaskExecutor taskExecutor,
DialogService dialogService) {
this.preferencesService = preferences;
this.dialogService = dialogService;

this.viewModel = new ISSNEditorViewModel(
field,
suggestionProvider,
fieldCheckers,
taskExecutor,
dialogService);

ViewLoader.view(this)
.root(this)
.load();

textArea.textProperty().bindBidirectional(viewModel.textProperty());
textArea.initContextMenu(new DefaultMenu(textArea));

new EditorValidator(preferences).configureValidation(viewModel.getFieldValidator().getValidationStatus(), textArea);
}

public ISSNEditorViewModel getViewModel() {
return viewModel;
}

@Override
public void bindToEntry(BibEntry entry) {
viewModel.bindToEntry(entry);
}

@Override
public Parent getNode() {
return this;
}

@Override
public void requestFocus() {
textArea.requestFocus();
}

@FXML
private void showJournalInfo() {
if (JournalInfoOptInDialogHelper.isJournalInfoEnabled(dialogService, preferencesService.getJournalInformationPreferences())) {
viewModel.showJournalInfo(journalInfoButton);
}
}
}
29 changes: 29 additions & 0 deletions src/main/java/org/jabref/gui/fieldeditors/ISSNEditorViewModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.jabref.gui.fieldeditors;

import javafx.scene.control.Button;

import org.jabref.gui.DialogService;
import org.jabref.gui.autocompleter.SuggestionProvider;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.integrity.FieldCheckers;
import org.jabref.model.entry.field.Field;

public class ISSNEditorViewModel extends AbstractEditorViewModel {
private final TaskExecutor taskExecutor;
private final DialogService dialogService;

public ISSNEditorViewModel(
Field field,
SuggestionProvider<?> suggestionProvider,
FieldCheckers fieldCheckers,
TaskExecutor taskExecutor,
DialogService dialogService) {
super(field, suggestionProvider, fieldCheckers);
this.taskExecutor = taskExecutor;
this.dialogService = dialogService;
}

public void showJournalInfo(Button journalInfoButton) {
PopOverUtil.showJournalInfo(journalInfoButton, entry, dialogService, taskExecutor);
}
}
31 changes: 22 additions & 9 deletions src/main/java/org/jabref/gui/fieldeditors/JournalEditor.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,29 @@
<?import javafx.scene.layout.HBox?>
<?import org.jabref.gui.fieldeditors.EditorTextField?>
<?import org.jabref.gui.icon.JabRefIconView?>
<?import javafx.scene.layout.VBox?>
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="HBox" xmlns="http://javafx.com/javafx/8.0.112"
fx:controller="org.jabref.gui.fieldeditors.JournalEditor">
<EditorTextField fx:id="textField"/>
<Button onAction="#toggleAbbreviation"
styleClass="icon-button">
<graphic>
<JabRefIconView glyph="TOGGLE_ABBREVIATION"/>
</graphic>
<tooltip>
<Tooltip text="%Switches between full and abbreviated journal name if the journal name is known."/>
</tooltip>
</Button>
<VBox>
<Button onAction="#toggleAbbreviation"
styleClass="icon-button">
<graphic>
<JabRefIconView glyph="TOGGLE_ABBREVIATION"/>
</graphic>
<tooltip>
<Tooltip text="%Switches between full and abbreviated journal name if the journal name is known."/>
</tooltip>
</Button>
<Button fx:id="journalInfoButton"
onAction="#showJournalInfo"
styleClass="icon-button">
<graphic>
<JabRefIconView glyph="VIEW_JOURNAL_INFO"/>
</graphic>
<tooltip>
<Tooltip text="%View journal info"/>
</tooltip>
</Button>
</VBox>
</fx:root>
Loading