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

MIR-1361 Allow to enter ROR as affiliation for authors #1074

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ $grayDark: #ECF0F1 !default;
height:200px;
}

.mir-ror-logo {
height: 20px;
}
.mir-toc-sections {
list-style-type: none;
padding-left: 0;
Expand Down
1 change: 1 addition & 0 deletions mir-module/GruntFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ module.exports = function(grunt) {
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/relatedItem-modal.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/relatedItem-modal.js',
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/relatedItem-autocomplete.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/relatedItem-autocomplete.js',
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/xeditor-form.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/xeditor-form.js',
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/ror-search.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/ror-search.js',
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/openaire.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/openaire.js',
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/classification-modal-select.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/classification-modal-select.js',
'<%= globalConfig.moduleDirectory %>/target/classes/META-INF/resources/js/mir/geo-coords.min.js': '<%= globalConfig.moduleDirectory %>/src/main/resources/META-INF/resources/js/mir/geo-coords.js',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@
</xed:template>

<xed:template id="person.affiliation">
<mir:textfield repeat="true" xpath="mods:affiliation" help-text="{i18n:mir.help.affiliation}" label="mir.affiliation" />
<mir:textfield repeat="true" xpath="mods:affiliation[not(@authorityURI)]" help-text="{i18n:mir.help.affiliation}" label="mir.affiliation" />
<mir:textfield repeat="true" xpath="mods:affiliation[@authorityURI='https://ror.org/']" help-text="{i18n:mir.help.affiliation.ror}" label="mir.affiliation.ror" id="mir-ror-input"/>
</xed:template>

<xed:template id="nameIdentifier.repeated">
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
148 changes: 148 additions & 0 deletions mir-module/src/main/resources/META-INF/resources/js/mir/ror-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
const RORSearch = {
baseURL: "https://api.ror.org/",

search: async function (text) {
const q = await fetch(RORSearch.baseURL + "organizations?query=" + encodeURIComponent(text));
let json = await q.json();

let rorIdentifiers = [];

json.items.forEach((item) => {
item.label = item.name + " (" + item.id + ")";
rorIdentifiers.push(item);
});

rorIdentifiers.sort((a, b) => {
if (a.label < b.label) {
return -1;
}
if (a.label > b.label) {
return 1;
}
return 0;
});
return rorIdentifiers;
},

/**
* Find the option (if any) matching the given label.
*
* @param dataListId the id of the datalist
* @param label the label to find in the given datalist
*
* @return the option element with the givel label or null
* */
getOption: function (dataListId, label) {
let dataList = document.getElementById(dataListId);

for (const option of dataList.childNodes) {
if (option.value === label) {
return option;
}
}

return null;
},

/**
* Searches ROR for the given text at https://api.ror.org/ .
* */
onInput: async function (event) {
let input = event.target;
let dataListId = input.getAttribute("list");

let option = RORSearch.getOption(dataListId, input.value);

// User selects value from list
if (option != null) {
input.value = option.getAttribute("data-ror");
input.title = option.getAttribute("value")
event.preventDefault();
return;
}

// Selected value is not in list, actually execute search at ROR
let result = await RORSearch.search(input.value);
let dataList = document.getElementById(dataListId);
dataList.textContent = "";

// Update datalist with results from ROR
for (const suggestion of result) {
let option = document.createElement("option");
option.setAttribute("value", suggestion.label);
option.setAttribute("data-ror", suggestion.id);
dataList.appendChild(option);
}
},

debounce: (f, wait) => {
let timeoutId = null;

return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
f.apply(null, args);
}, wait);
};
},

/**
* Resolve ror links in xEditor and update title attributes of ror inputs.
* */
updateXEditorInputTitle: async function () {
let rorInputs = document.querySelectorAll("[id='mir-ror-input']");
for (const rorInput of rorInputs) {
if (rorInput.value.length == 0) {
continue;
}

RORSearch.search(rorInput.value).then(data => {
if (data.length > 0) {
rorInput.setAttribute("title", data[0].name + " (" + data[0].id + ")");
}
});
}
},

/**
* Resolve ror links on metadata page.
* */
resolve: async function () {
let rorLinks = document.querySelectorAll("a.mir-ror-link");
for (const rorLink of rorLinks) {
RORSearch.search(rorLink.href).then(data => {
if (data.length > 0) {
if (data[0].name.length > 25) {
rorLink.innerHTML = data[0].name.substring(0, 25).trim() + " …";
} else {
rorLink.innerHTML = data[0].name;
}
rorLink.setAttribute("title", data[0].name + " | " + data[0].id);
}
});
}
}
};

/**
* Adds event handler to every ror input element.
* */
document.addEventListener('DOMContentLoaded', function () {
const debouncedInputHandler = RORSearch.debounce(RORSearch.onInput, 500);

for (const input of document.querySelectorAll('[id="mir-ror-input"]')) {
// create datalist element with random uuid as element id
let dataList = document.createElement("datalist");
dataList.id = self.crypto.randomUUID();

// set the previously created datalist as list to the ror input element
input.setAttribute("list", dataList.id);
input.parentElement.append(dataList);

// add the actual event handler
input.addEventListener('input', debouncedInputHandler);
}

RORSearch.resolve();
RORSearch.updateXEditorInputTitle();
});
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ mir.actions.noaccess = Um das Dokument zu bearbeiten,
mir.actions.norights = Sie besitzen nicht die ben\u00F6tigten Rechte, um das Dokument zu bearbeiten.
mir.admineditor = Bearbeiten im Admin-Editor
mir.affiliation = Zugeh\u00F6rigkeit
mir.affiliation.ror = Zugeh\u00F6rigkeit (ROR ID)
mir.articlenumber = Artikelnummer:
mir.articlenumber.short = Art.-Nr.:
mir.breadcrumb.home = Start
Expand Down Expand Up @@ -384,6 +385,7 @@ mir.help.abstract.language = Geben Sie die Sprache an, in d
mir.help.abstract.ortext = Eine kurze Zusammenfassung des Dokumentinhalts.
mir.help.access = Geben Sie hier an, wer auf die angehangenen Dokumente zugreifen darf.
mir.help.affiliation = Organisation bzw. Institution der betreffenden Person.
mir.help.affiliation.ror = <a href="https://ror.org/">ROR ID</a> der Organisation bzw. Institution der betreffenden Person.
mir.help.articlenumber = Die Nummer eines Artikels, der in einer Online-Zeitschrift oder auf einer Publikationsplattform erschienen ist.
mir.help.artist.photographer = K\u00FCnstler des Werkes oder Fotograf des Bildes.
mir.help.authorSpecification = Genauere Beschreibung der Autor(innen)-Rolle, meist relevant f\u00C3\u00BCr Kontaktaufnahme oder statistische Auswertungen.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ mir.actions.noaccess = To edit the document, please lo
mir.actions.norights = You don't have the rights to edit the document.
mir.admineditor = Edit in admin editor
mir.affiliation = Affiliation
mir.affiliation.ror = Affiliation (ROR ID)
mir.articlenumber = Article number:
mir.articlenumber.short = Art.-No.:
mir.breadcrumb.home = Home
Expand Down Expand Up @@ -362,6 +363,7 @@ mir.help.abstract.aslink = Weblink to abstract.
mir.help.abstract.ortext = A short summary of the document content.
mir.help.access = Specify who should be able to access the dataset after publication. The metadata will be public in any case.
mir.help.affiliation = Organisation/Affiliation of the Person.
mir.help.affiliation.ror = <a href="https://ror.org/">ROR ID</a> of the Organisation/Affiliation of the Person.
mir.help.articlenumber = The number of an article published in an online journal or publication platform.
mir.help.artist.photographer = Creator of the Picture/Image.
mir.help.author.interviewee = A person, family or organization responsible for creating or contributing to a resource by responding to an interviewer, usually a reporter, pollster, or some other information gathering agent.
Expand Down
6 changes: 6 additions & 0 deletions mir-module/src/main/resources/xsl/editor/mods2xeditor.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@
</xsl:copy>
</xsl:template>

<xsl:template match="mods:affiliation[@authorityURI='https://ror.org/'][@valueURI]">
<mods:affiliation authorityURI="{@authorityURI}">
<xsl:value-of select="@valueURI"/>
</mods:affiliation>
</xsl:template>

<!-- Remove this mods:classification entry, will be created again while saving using mods:accessCondtition (see MIR-161) -->
<xsl:template match="mods:classification[@authority='accessRestriction']">
<!-- do nothing -->
Expand Down
4 changes: 4 additions & 0 deletions mir-module/src/main/resources/xsl/editor/xeditor2mods.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@
</mods:nameIdentifier>
</xsl:template>

<xsl:template match="mods:affiliation[@authorityURI='https://ror.org/']">
<mods:affiliation authorityURI="{@authorityURI}" valueURI="{.}"/>
</xsl:template>

<!-- Copy content of mods:accessCondtition to mods:classification to enable classification support (see MIR-161) -->
<xsl:template match="mods:accessCondition[@type='restriction on access'][contains(@xlink:href,'mir_access')]">
<mods:accessCondition type="restriction on access">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@
<script src="{$WebApplicationBaseURL}js/mir/sherpa.js"></script>
<script src="{$WebApplicationBaseURL}modules/webtools/upload/js/upload-api.js"></script>
<script src="{$WebApplicationBaseURL}modules/webtools/upload/js/upload-gui.js"></script>
<script src="{$WebApplicationBaseURL}js/mir/ror-search.min.js"/>
<link rel="stylesheet" type="text/css" href="{$WebApplicationBaseURL}modules/webtools/upload/css/upload-gui.css" />
</xsl:template>

Expand Down
15 changes: 14 additions & 1 deletion mir-module/src/main/resources/xsl/mir-mods-utils.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
</xsl:variable>

<xsl:variable name="affiliation" select="mods:affiliation/text()" />
<xsl:variable name="affiliation-ror" select="mods:affiliation[contains(@authorityURI, '//ror.org')]" />
<xsl:variable name="personNodeId" select="generate-id(.)"/>
<xsl:variable name="personName"><xsl:apply-templates select="." mode="nameString"/></xsl:variable>
<xsl:if test="count($nameIdentifiers) &gt; 0 or string-length($affiliation) &gt; 0">
Expand All @@ -71,12 +72,24 @@
</dd>
</xsl:for-each>
</xsl:if>
<xsl:if test="string-length($affiliation) &gt; 0">
<xsl:if test="string-length($affiliation) &gt; 0 or $affiliation-ror">
<dt>
<xsl:value-of select="i18n:translate('mir.affiliation')"/>
</dt>
<dd>
<xsl:value-of select="$affiliation"/>
<xsl:for-each select="mods:affiliation[contains(@authorityURI, '//ror.org')][@valueURI]">
<xsl:sort select="@valueURI"/>
<div class="mir-affiliation-ror">
<a href="https://ror.org/" alt="ROR logo">
<img src="{$WebApplicationBaseURL}images/ror/ror-icon-rgb-transparent.svg"
class="pr-1 mir-ror-logo"/>
</a>
<a class="mir-ror-link" href="{@valueURI}">
<xsl:value-of select="@valueURI"/>
</a>
</div>
</xsl:for-each>
</dd>
</xsl:if>
</dl>
Expand Down
Loading