Skip to content
Snippets Groups Projects
Commit f3760436 authored by Simon Delcamp's avatar Simon Delcamp
Browse files

Resolve "Improve the Mint DOI panel"

parent 888548f2
No related branches found
No related tags found
1 merge request!689Resolve "Improve the Mint DOI panel"
...@@ -31,8 +31,10 @@ ...@@ -31,8 +31,10 @@
"doi": { "doi": {
"link": "https://doi.esrf.fr/", "link": "https://doi.esrf.fr/",
"minimalAbstractLength": 150, "minimalAbstractLength": 150,
"minimalTitleLength": 40,
"facilityPrefix": "10.15151", "facilityPrefix": "10.15151",
"facilitySuffix": "ESRF-DC" "facilitySuffix": "ESRF-DC",
"referenceDoi": "https://doi.esrf.fr/10.15151/ESRF-DC-2011729981"
}, },
"fileBrowser": { "fileBrowser": {
"maxFileNb": 1000 "maxFileNb": 1000
......
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
"doi": { "doi": {
"link": "https://doi.esrf.fr/", "link": "https://doi.esrf.fr/",
"minimalAbstractLength": 150, "minimalAbstractLength": 150,
"minimalTitleLength": 40,
"facilityPrefix": "10.15151", "facilityPrefix": "10.15151",
"facilitySuffix": "ESRF-DC" "facilitySuffix": "ESRF-DC",
"referenceDoi": "https://doi.esrf.fr/10.15151/ESRF-DC-2011729981"
}, },
"fileBrowser": { "fileBrowser": {
"maxFileNb": 1000 "maxFileNb": 1000
......
import { Button, Modal, Spinner } from 'react-bootstrap'; import { Button, Modal, Spinner, Form } from 'react-bootstrap';
import { useState } from 'react';
import { ORCID } from '@edata-portal/core';
import { useConfig } from '@edata-portal/core';
export function MintDOIModal({ export function MintDOIModal({
show, show,
...@@ -15,39 +18,74 @@ export function MintDOIModal({ ...@@ -15,39 +18,74 @@ export function MintDOIModal({
data: any; // TODO : type to be updated when endpoint will be updated data: any; // TODO : type to be updated when endpoint will be updated
submitting: boolean; submitting: boolean;
}) { }) {
const [certify, setCertify] = useState(false);
const config = useConfig();
const onClose = () => {
setCertify(false);
onCancel();
};
return ( return (
<Modal show={show} onHide={onCancel} size="lg"> <Modal show={show} onHide={onClose} size="lg" scrollable={true}>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>Confirmation</Modal.Title> <Modal.Title>Confirmation</Modal.Title>
</Modal.Header> </Modal.Header>
{data !== null && ( {data !== null && (
<Modal.Body> <Modal.Body>
<p> <p>
Minting a DOI is <b>irreversible</b>. Please carefully review the DOIs are a system of persistent identifiers, therefore minting a DOI
following points before proceeding: is permanent i.e. <strong>irreversible</strong>. Data DOIs are like
publications, they should be as clear as possible. Here is an
example of a well formatted{' '}
<a
href={config.ui.doi.referenceDoi}
target="_blank"
rel="noreferrer"
>
DOI.
</a>
<p>
We kindly ask you to please carefully review the following points
before clicking on <strong>Mint</strong>:
</p>
</p> </p>
<ul> <ul>
<li className="p-2 "> <li className="p-2">
<strong>
{' '}
Number of dataset{data.datasetIdList.length > 1
? 's'
: ''}:{' '}
</strong>
{data.datasetIdList.length}
</li>
<li className="p-2">
<strong>Title</strong> : Ensure it provides a concise and <strong>Title</strong> : Ensure it provides a concise and
descriptive name for the data, offering a clear understanding of descriptive name for the data, offering a clear understanding of
its content. its content.
<div className="fst-italic">{data.title}</div> <div className="fst-italic p-2">{data.title}</div>
</li> </li>
<li className="p-2"> <li className="p-2">
<strong>Abstract</strong> : Confirm it provides detailed <strong>Abstract</strong> : Confirm it provides detailed
information about the resource, explaining its purpose and information about the data pointed to by the DOI, explaining what
significance. they represent, their purpose and significance. Add additional
<div className="fst-italic">{data.abstract}</div> information about the files included.
<div className="fst-italic p-2">{data.abstract}</div>
</li> </li>
<li className="p-2"> <li className="p-2">
<strong>Authors</strong>: Double-check the list of authors, ensure <strong>Authors</strong>: Double-check the list of authors, ensure
their order is correct, and include their ORCID IDs wherever their order is correct (first author on top), and include their
possible. ORCID IDs wherever possible. The order of authors can be modified
by selecting an author and moving the author up or down.
<ul className="fst-italic"> <ul className="fst-italic">
{data.authors.map((authors: any, index: any) => ( {data.authors.map((authors: any, index: any) => (
<li key={authors.name}> <li key={authors.name} className="p-1">
{authors.name}, {authors.surname}, {authors.orcid} {authors.name}, {authors.surname}
{authors.orcid !== '' && (
<>
, <ORCID orcid={authors.orcid} isCompactView={true} />
</>
)}
</li> </li>
))} ))}
</ul> </ul>
...@@ -95,12 +133,31 @@ export function MintDOIModal({ ...@@ -95,12 +133,31 @@ export function MintDOIModal({
</ul> </ul>
</Modal.Body> </Modal.Body>
)} )}
<Form.Check
type="switch"
id="switch-herby"
checked={certify}
label={
'I confirm that there are no mistake in the fields above and that they help make the data interoperable and reusable. I want to proceed to mint the DOI.'
}
onChange={(e) => {
setCertify(e.currentTarget.checked);
}}
className="m-2"
required
/>
<div className="justify-content-left p-1"> <div className="justify-content-left p-1">
<Button onClick={onMint} className="m-1" variant="primary"> <Button
onClick={onMint}
className="m-1"
variant="primary"
disabled={!certify}
>
{submitting ? <Spinner size="sm" /> : 'Mint DOI'} {submitting ? <Spinner size="sm" /> : 'Mint DOI'}
</Button> </Button>
<Button onClick={onCancel} className="m-1" variant="danger"> <Button onClick={onClose} className="m-1" variant="danger">
Cancel Return
</Button> </Button>
</div> </div>
</Modal> </Modal>
......
...@@ -144,6 +144,7 @@ function FormSection({ ...@@ -144,6 +144,7 @@ function FormSection({
type: 'textarea', type: 'textarea',
label: 'Title', label: 'Title',
required: true, required: true,
minLength: config.ui.doi.minimalTitleLength,
}, },
abstract: { abstract: {
type: 'textarea', type: 'textarea',
......
import { import {
faArrowDown, faArrowDown,
faArrowUp, faArrowUp,
faBars,
faPlus, faPlus,
faRemove, faRemove,
faTrash, faTrash,
faEllipsis,
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { import type {
...@@ -61,6 +61,172 @@ export function RenderFormArray({ ...@@ -61,6 +61,172 @@ export function RenderFormArray({
<Card className={error ? 'border-danger' : ''}> <Card className={error ? 'border-danger' : ''}>
<Card.Body className="p-2"> <Card.Body className="p-2">
<Row className="g-2"> <Row className="g-2">
{resolvedDescription.addFromPreset?.length ? (
<Col xs={'auto'}>
<ReactSelect
menuPortalTarget={document.body}
placeholder={`Select an ${labelSingular} to add...`}
isClearable={false}
value={null}
options={resolvedDescription.addFromPreset}
onChange={(v) => {
if (v?.value) {
fields.push(v.value);
}
}}
/>
</Col>
) : null}
{fields?.length ? (
<small>
<Table
size="sm"
responsive
hover
borderless
className="mt-2"
>
<tbody>
{reorderedIndexesWithDragState.map(
(originalIndex, currentIndex) => {
const newPath = `${path}.${originalIndex}`;
return (
<tr
key={originalIndex}
onDragOver={(e) => {
setDraggingOver(currentIndex);
}}
>
{enableDragNDrop ? (
<td
style={{
width: 1,
verticalAlign: 'middle',
cursor: 'move',
fontSize: '1.5em',
}}
draggable={enableDragNDrop}
//drag for desktops
onDragStart={(e) => {
setDragging(originalIndex);
//no image for drag
e.dataTransfer.setDragImage(
document.createElement('div'),
0,
0,
);
}}
onDragEnd={(e) => {
if (dragging !== undefined) {
fields.move(dragging, currentIndex);
}
setDragging(undefined);
setDraggingOver(undefined);
}}
>
<FontAwesomeIcon
icon={faEllipsis}
className="me-1 mt-3 "
/>
</td>
) : (
<>
<td
style={{
width: 1,
verticalAlign: 'top',
}}
>
{originalIndex === 0 ? null : (
<Button
className="p-0 text-info"
variant="link"
onClick={() => {
fields.move(
originalIndex,
originalIndex - 1,
);
}}
disabled={
resolvedDescription.readonly
}
style={{
fontSize: '1.5em',
}}
>
<FontAwesomeIcon icon={faArrowUp} />
</Button>
)}
</td>
<td
style={{
width: 1,
verticalAlign: 'top',
}}
>
{fields.length &&
originalIndex ===
fields.length - 1 ? null : (
<Button
className="p-0 text-info"
variant="link"
onClick={() => {
fields.move(
originalIndex,
originalIndex + 1,
);
}}
disabled={
resolvedDescription.readonly
}
style={{
fontSize: '1.5em',
}}
>
<FontAwesomeIcon icon={faArrowDown} />
</Button>
)}
</td>
</>
)}
<td>
<Row className="g-2">
<RenderFormObject
description={resolvedDescription.item}
path={newPath}
/>
</Row>
</td>
<td
style={{
width: 1,
verticalAlign: enableDragNDrop
? 'middle'
: 'top',
}}
>
<Button
className="p-0 text-danger"
variant="link"
onClick={() => {
fields.remove(originalIndex);
}}
disabled={resolvedDescription.readonly}
style={{
fontSize: '1.5em',
}}
>
<FontAwesomeIcon icon={faRemove} />
</Button>
</td>
</tr>
);
},
)}
</tbody>
</Table>
</small>
) : null}
{resolvedDescription.newItem ? ( {resolvedDescription.newItem ? (
<Col xs={'auto'}> <Col xs={'auto'}>
<Button <Button
...@@ -91,163 +257,7 @@ export function RenderFormArray({ ...@@ -91,163 +257,7 @@ export function RenderFormArray({
Clear all {labelPlural} Clear all {labelPlural}
</Button> </Button>
</Col> </Col>
{resolvedDescription.addFromPreset?.length ? (
<Col xs={'auto'}>
<ReactSelect
menuPortalTarget={document.body}
placeholder={`Select an ${labelSingular} to add...`}
isClearable={false}
value={null}
options={resolvedDescription.addFromPreset}
onChange={(v) => {
if (v?.value) {
fields.push(v.value);
}
}}
/>
</Col>
) : null}
</Row> </Row>
{fields?.length ? (
<small>
<Table size="sm" responsive hover borderless className="mt-2">
<tbody>
{reorderedIndexesWithDragState.map(
(originalIndex, currentIndex) => {
const newPath = `${path}.${originalIndex}`;
return (
<tr
key={originalIndex}
onDragOver={(e) => {
setDraggingOver(currentIndex);
}}
>
{enableDragNDrop ? (
<td
style={{
width: 1,
verticalAlign: 'middle',
cursor: 'move',
fontSize: '1.5em',
}}
draggable={enableDragNDrop}
//drag for desktops
onDragStart={(e) => {
setDragging(originalIndex);
//no image for drag
e.dataTransfer.setDragImage(
document.createElement('div'),
0,
0,
);
}}
onDragEnd={(e) => {
if (dragging !== undefined) {
fields.move(dragging, currentIndex);
}
setDragging(undefined);
setDraggingOver(undefined);
}}
>
<FontAwesomeIcon
icon={faBars}
className="me-1"
/>
</td>
) : (
<>
<td
style={{
width: 1,
verticalAlign: 'top',
}}
>
{originalIndex === 0 ? null : (
<Button
className="p-0 text-info"
variant="link"
onClick={() => {
fields.move(
originalIndex,
originalIndex - 1,
);
}}
disabled={resolvedDescription.readonly}
style={{
fontSize: '1.5em',
}}
>
<FontAwesomeIcon icon={faArrowUp} />
</Button>
)}
</td>
<td
style={{
width: 1,
verticalAlign: 'top',
}}
>
{fields.length &&
originalIndex ===
fields.length - 1 ? null : (
<Button
className="p-0 text-info"
variant="link"
onClick={() => {
fields.move(
originalIndex,
originalIndex + 1,
);
}}
disabled={resolvedDescription.readonly}
style={{
fontSize: '1.5em',
}}
>
<FontAwesomeIcon icon={faArrowDown} />
</Button>
)}
</td>
</>
)}
<td>
<Row className="g-2">
<RenderFormObject
description={resolvedDescription.item}
path={newPath}
/>
</Row>
</td>
<td
style={{
width: 1,
verticalAlign: enableDragNDrop
? 'middle'
: 'top',
}}
>
<Button
className="p-0 text-danger"
variant="link"
onClick={() => {
fields.remove(originalIndex);
}}
disabled={resolvedDescription.readonly}
style={{
fontSize: '1.5em',
}}
>
<FontAwesomeIcon icon={faRemove} />
</Button>
</td>
</tr>
);
},
)}
</tbody>
</Table>
</small>
) : null}
</Card.Body> </Card.Body>
</Card> </Card>
); );
......
...@@ -18,8 +18,10 @@ export interface UIConfig { ...@@ -18,8 +18,10 @@ export interface UIConfig {
doi: { doi: {
link: string; link: string;
minimalAbstractLength: number; minimalAbstractLength: number;
minimalTitleLength: number;
facilityPrefix: string; facilityPrefix: string;
facilitySuffix: string; facilitySuffix: string;
referenceDoi: string;
}; };
fileBrowser: { fileBrowser: {
maxFileNb: number; maxFileNb: number;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment