@manuscripts/body-editor 3.17.3 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/commands.js +13 -19
- package/dist/cjs/components/references/ReferenceLine.js +14 -1
- package/dist/cjs/components/references/ReferencesModal.js +155 -131
- package/dist/cjs/configs/editor-views.js +1 -0
- package/dist/cjs/icons.js +2 -2
- package/dist/cjs/lib/context-menu.js +4 -1
- package/dist/cjs/lib/normalize.js +31 -1
- package/dist/cjs/lib/paste.js +0 -1
- package/dist/cjs/menus.js +1 -1
- package/dist/cjs/node-type-icons.js +1 -0
- package/dist/cjs/plugins/add-subtitle.js +1 -1
- package/dist/cjs/plugins/bibliography.js +7 -1
- package/dist/cjs/plugins/section_category.js +5 -2
- package/dist/cjs/plugins/translations.js +9 -21
- package/dist/cjs/versions.js +1 -1
- package/dist/cjs/views/bibliography_element.js +44 -2
- package/dist/cjs/views/figure_element.js +1 -1
- package/dist/cjs/views/headshot_grid.js +1 -1
- package/dist/es/commands.js +13 -19
- package/dist/es/components/references/ReferenceLine.js +14 -1
- package/dist/es/components/references/ReferencesModal.js +156 -132
- package/dist/es/configs/editor-views.js +1 -0
- package/dist/es/icons.js +1 -1
- package/dist/es/lib/context-menu.js +4 -1
- package/dist/es/lib/normalize.js +30 -1
- package/dist/es/lib/paste.js +0 -1
- package/dist/es/menus.js +1 -1
- package/dist/es/node-type-icons.js +1 -0
- package/dist/es/plugins/add-subtitle.js +2 -2
- package/dist/es/plugins/bibliography.js +7 -1
- package/dist/es/plugins/section_category.js +6 -3
- package/dist/es/plugins/translations.js +11 -23
- package/dist/es/versions.js +1 -1
- package/dist/es/views/bibliography_element.js +45 -3
- package/dist/es/views/figure_element.js +2 -2
- package/dist/es/views/headshot_grid.js +2 -2
- package/dist/types/commands.d.ts +2 -2
- package/dist/types/components/references/ReferenceLine.d.ts +1 -0
- package/dist/types/icons.d.ts +1 -1
- package/dist/types/lib/normalize.d.ts +30 -1
- package/dist/types/versions.d.ts +1 -1
- package/dist/types/views/bibliography_element.d.ts +5 -1
- package/package.json +2 -2
- package/src/commands.ts +22 -35
- package/src/components/references/ReferenceLine.tsx +16 -1
- package/src/components/references/ReferencesModal.tsx +178 -140
- package/src/configs/editor-views.ts +1 -0
- package/src/icons.ts +1 -1
- package/src/lib/context-menu.ts +4 -1
- package/src/lib/normalize.ts +36 -1
- package/src/lib/paste.ts +0 -1
- package/src/menus.tsx +1 -1
- package/src/node-type-icons.tsx +1 -0
- package/src/plugins/add-subtitle.ts +2 -2
- package/src/plugins/bibliography.ts +10 -3
- package/src/plugins/section_category.ts +7 -2
- package/src/plugins/translations.ts +18 -29
- package/src/versions.ts +1 -1
- package/src/views/bibliography_element.ts +61 -4
- package/src/views/figure_element.ts +2 -2
- package/src/views/headshot_grid.ts +2 -2
- package/styles/AdvancedEditor.css +29 -2
- package/styles/Editor.css +7 -0
|
@@ -21,8 +21,8 @@ const prosemirror_view_1 = require("prosemirror-view");
|
|
|
21
21
|
const commands_1 = require("../commands");
|
|
22
22
|
const icons_1 = require("../icons");
|
|
23
23
|
const languages_1 = require("../lib/languages");
|
|
24
|
-
const template_1 = require("../lib/template");
|
|
25
24
|
const navigation_utils_1 = require("../lib/navigation-utils");
|
|
25
|
+
const template_1 = require("../lib/template");
|
|
26
26
|
const createMenuItem = (props, contents, handler, isSelected = false, tabIndex) => {
|
|
27
27
|
const item = document.createElement('div');
|
|
28
28
|
item.className = `menu-item ${isSelected ? 'selected' : ''}`;
|
|
@@ -60,10 +60,6 @@ const createLanguageMenu = (props, selectedCode, onSelect) => {
|
|
|
60
60
|
});
|
|
61
61
|
return { menu, destroy };
|
|
62
62
|
};
|
|
63
|
-
const getInsertionPos = (doc, nodePos) => {
|
|
64
|
-
const node = doc.nodeAt(nodePos);
|
|
65
|
-
return node ? nodePos + node.nodeSize : null;
|
|
66
|
-
};
|
|
67
63
|
exports.default = (props) => new prosemirror_state_1.Plugin({
|
|
68
64
|
props: {
|
|
69
65
|
decorations: (state) => {
|
|
@@ -74,14 +70,11 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
|
|
|
74
70
|
const canEditTransGraphicalAbstract = can.editArticle &&
|
|
75
71
|
(0, template_1.templateAllows)(state, transform_1.schema.nodes.trans_graphical_abstract);
|
|
76
72
|
const widgets = [];
|
|
77
|
-
state.doc.descendants((node, pos
|
|
78
|
-
const isAbstractSection = (node
|
|
79
|
-
node.type === transform_1.schema.nodes.graphical_abstract_section) &&
|
|
80
|
-
parent?.type === transform_1.schema.nodes.abstracts;
|
|
73
|
+
state.doc.descendants((node, pos) => {
|
|
74
|
+
const isAbstractSection = (0, transform_1.isAbstractNode)(node) || (0, transform_1.isGraphicalAbstractSectionNode)(node);
|
|
81
75
|
if (isAbstractSection) {
|
|
82
|
-
const isGraphical = node.type === transform_1.schema.nodes.graphical_abstract_section;
|
|
83
76
|
const category = props.sectionCategories.get(node.attrs.category);
|
|
84
|
-
const canEdit =
|
|
77
|
+
const canEdit = (0, transform_1.isGraphicalAbstractSectionNode)(node)
|
|
85
78
|
? canEditTransGraphicalAbstract &&
|
|
86
79
|
category &&
|
|
87
80
|
(0, commands_1.insertTransGraphicalAbstract)(category)(state)
|
|
@@ -92,19 +85,15 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
|
|
|
92
85
|
$span.tabIndex = 0;
|
|
93
86
|
$span.className = 'add-trans-abstract';
|
|
94
87
|
$span.title = 'Add translation';
|
|
95
|
-
$span.innerHTML = `${icons_1.
|
|
88
|
+
$span.innerHTML = `${icons_1.addIcon} <span class="add-trans-abstract-text">Add translation</span>`;
|
|
96
89
|
const handleActivate = (event) => {
|
|
97
90
|
event.preventDefault();
|
|
98
91
|
event.stopPropagation();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (isGraphical && category) {
|
|
104
|
-
(0, commands_1.insertTransGraphicalAbstract)(category, insertPos)(view.state, view.dispatch, view);
|
|
92
|
+
if ((0, transform_1.isGraphicalAbstractSectionNode)(node) && category) {
|
|
93
|
+
(0, commands_1.insertTransGraphicalAbstract)(category)(view.state, view.dispatch, view);
|
|
105
94
|
}
|
|
106
95
|
else {
|
|
107
|
-
(0, commands_1.insertTransAbstract)(view.state, view.dispatch, node.attrs.category
|
|
96
|
+
(0, commands_1.insertTransAbstract)(view.state, view.dispatch, node.attrs.category);
|
|
108
97
|
}
|
|
109
98
|
};
|
|
110
99
|
$span.addEventListener('mousedown', handleActivate);
|
|
@@ -113,8 +102,7 @@ exports.default = (props) => new prosemirror_state_1.Plugin({
|
|
|
113
102
|
}, { key: `add-trans-${node.attrs.id}-${pos}` }));
|
|
114
103
|
}
|
|
115
104
|
}
|
|
116
|
-
const isTransNode = node
|
|
117
|
-
node.type === transform_1.schema.nodes.trans_graphical_abstract;
|
|
105
|
+
const isTransNode = (0, transform_1.isTransAbstractNode)(node) || (0, transform_1.isTransGraphicalAbstractNode)(node);
|
|
118
106
|
if (isTransNode) {
|
|
119
107
|
const canEdit = node.type === transform_1.schema.nodes.trans_abstract
|
|
120
108
|
? canEditTransAbstract
|
package/dist/cjs/versions.js
CHANGED
|
@@ -20,6 +20,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
exports.BibliographyElementBlockView = void 0;
|
|
22
22
|
const style_guide_1 = require("@manuscripts/style-guide");
|
|
23
|
+
const transform_1 = require("@manuscripts/transform");
|
|
23
24
|
const prosemirror_state_1 = require("prosemirror-state");
|
|
24
25
|
const ReferencesEditor_1 = require("../components/references/ReferencesEditor");
|
|
25
26
|
const comments_1 = require("../lib/comments");
|
|
@@ -34,6 +35,7 @@ const block_view_1 = __importDefault(require("./block_view"));
|
|
|
34
35
|
const creators_1 = require("./creators");
|
|
35
36
|
const ReactSubView_1 = __importDefault(require("./ReactSubView"));
|
|
36
37
|
const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
|
|
38
|
+
const icons_1 = require("../icons");
|
|
37
39
|
class BibliographyElementBlockView extends block_view_1.default {
|
|
38
40
|
constructor() {
|
|
39
41
|
super(...arguments);
|
|
@@ -138,7 +140,7 @@ class BibliographyElementBlockView extends block_view_1.default {
|
|
|
138
140
|
const componentProps = {
|
|
139
141
|
items: Array.from(bib.bibliographyItems.values()),
|
|
140
142
|
citationCounts: bib.citationCounts,
|
|
141
|
-
item: bib.bibliographyItems.get(id),
|
|
143
|
+
item: id ? bib.bibliographyItems.get(id) : undefined,
|
|
142
144
|
onSave: this.handleSave,
|
|
143
145
|
onDelete: this.handleDelete,
|
|
144
146
|
};
|
|
@@ -181,7 +183,18 @@ class BibliographyElementBlockView extends block_view_1.default {
|
|
|
181
183
|
return;
|
|
182
184
|
}
|
|
183
185
|
this.version = bib.version;
|
|
186
|
+
this.renderBibs(bib);
|
|
187
|
+
this.createInlineModalButton();
|
|
188
|
+
this.updateSelections();
|
|
189
|
+
}
|
|
190
|
+
renderBibs(bib) {
|
|
184
191
|
const nodes = new Map();
|
|
192
|
+
const rids = [];
|
|
193
|
+
this.view.state.doc.descendants((node) => {
|
|
194
|
+
if ((0, transform_1.isCitationNode)(node)) {
|
|
195
|
+
rids.push(...node.attrs.rids);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
185
198
|
this.node.descendants((node) => {
|
|
186
199
|
const id = node.attrs.id;
|
|
187
200
|
nodes.set(id, node);
|
|
@@ -219,6 +232,12 @@ class BibliographyElementBlockView extends block_view_1.default {
|
|
|
219
232
|
element.tabIndex = 0;
|
|
220
233
|
const comment = (0, comments_1.createCommentMarker)('div', id);
|
|
221
234
|
element.prepend(comment);
|
|
235
|
+
if (!rids.includes(id)) {
|
|
236
|
+
const uncitedMarker = document.createElement('span');
|
|
237
|
+
uncitedMarker.innerHTML = 'UNCITED';
|
|
238
|
+
uncitedMarker.classList.add('uncited-reference-marker');
|
|
239
|
+
element.prepend(uncitedMarker);
|
|
240
|
+
}
|
|
222
241
|
(0, track_changes_plugin_1.addTrackChangesAttributes)(node.attrs, element);
|
|
223
242
|
(0, track_changes_plugin_1.addTrackChangesClassNames)(node.attrs, element);
|
|
224
243
|
wrapper.append(element);
|
|
@@ -236,7 +255,30 @@ class BibliographyElementBlockView extends block_view_1.default {
|
|
|
236
255
|
else {
|
|
237
256
|
this.container.appendChild(wrapper);
|
|
238
257
|
}
|
|
239
|
-
|
|
258
|
+
}
|
|
259
|
+
createInlineModalButton() {
|
|
260
|
+
const can = this.props.getCapabilities();
|
|
261
|
+
if (!can.editCitationsAndRefs) {
|
|
262
|
+
if (this.inlineModalButton) {
|
|
263
|
+
this.inlineModalButton.remove();
|
|
264
|
+
this.inlineModalButton = null;
|
|
265
|
+
}
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (this.inlineModalButton) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const $span = document.createElement('span');
|
|
272
|
+
$span.tabIndex = 0;
|
|
273
|
+
$span.className = 'add-new-reference add-trans-abstract';
|
|
274
|
+
$span.title = 'Add New Reference';
|
|
275
|
+
$span.innerHTML = `${icons_1.addIcon} <span type="button" tabindex="0" class="add-new-reference-text">Add new reference</span>`;
|
|
276
|
+
$span.addEventListener('click', (e) => {
|
|
277
|
+
this.showPopper();
|
|
278
|
+
});
|
|
279
|
+
$span.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(() => this.showPopper()));
|
|
280
|
+
this.inlineModalButton = $span;
|
|
281
|
+
this.dom.appendChild($span);
|
|
240
282
|
}
|
|
241
283
|
}
|
|
242
284
|
exports.BibliographyElementBlockView = BibliographyElementBlockView;
|
|
@@ -71,7 +71,7 @@ class FigureElementView extends image_element_1.ImageElementView {
|
|
|
71
71
|
if (this.props.getCapabilities()?.editArticle) {
|
|
72
72
|
this.addFigureBtn = Object.assign(document.createElement('button'), {
|
|
73
73
|
className: 'add-button',
|
|
74
|
-
innerHTML: icons_1.
|
|
74
|
+
innerHTML: icons_1.addIcon,
|
|
75
75
|
title: 'Add figure',
|
|
76
76
|
});
|
|
77
77
|
this.addFigureBtn.addEventListener('click', () => this.addFigure());
|
|
@@ -51,7 +51,7 @@ class HeadshotGridView extends block_view_1.default {
|
|
|
51
51
|
this.addHeadshotButton.classList.add('add-headshot-element-button');
|
|
52
52
|
this.addHeadshotButton.setAttribute('data-cy', 'headshot-add');
|
|
53
53
|
this.addHeadshotButton.contentEditable = 'false';
|
|
54
|
-
this.addHeadshotButton.innerHTML = icons_1.
|
|
54
|
+
this.addHeadshotButton.innerHTML = icons_1.addIcon;
|
|
55
55
|
const buttonText = document.createElement('span');
|
|
56
56
|
buttonText.classList.add('add-headshot-element-text');
|
|
57
57
|
buttonText.innerText = 'Add Headshot';
|
package/dist/es/commands.js
CHANGED
|
@@ -717,16 +717,14 @@ export const insertAbstractSection = (category) => (state, dispatch, view) => {
|
|
|
717
717
|
return false;
|
|
718
718
|
}
|
|
719
719
|
const abstracts = findAbstractsNode(state.doc);
|
|
720
|
-
const
|
|
721
|
-
if (
|
|
720
|
+
const abstractNodes = findChildrenByType(abstracts.node, schema.nodes.abstract);
|
|
721
|
+
if (abstractNodes.some((s) => s.node.attrs.category === category.id)) {
|
|
722
722
|
return false;
|
|
723
723
|
}
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
729
|
-
const node = schema.nodes.section.create({ category: category.id }, [
|
|
724
|
+
const pos = findInsertionPosition(schema.nodes.abstract, abstracts.node) +
|
|
725
|
+
abstracts.pos +
|
|
726
|
+
1;
|
|
727
|
+
const node = schema.nodes.abstract.create({ category: category.id }, [
|
|
730
728
|
schema.nodes.section_title.create({}, schema.text(category.titles[0])),
|
|
731
729
|
schema.nodes.paragraph.create({ placeholder: 'Type abstract here...' }),
|
|
732
730
|
]);
|
|
@@ -776,9 +774,9 @@ export const insertGraphicalAbstract = (category) => (state, dispatch, view) =>
|
|
|
776
774
|
if (sections.some((s) => s.node.attrs.category === category.id)) {
|
|
777
775
|
return false;
|
|
778
776
|
}
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
|
|
777
|
+
const pos = findInsertionPosition(schema.nodes.graphical_abstract_section, abstracts.node) +
|
|
778
|
+
abstracts.pos +
|
|
779
|
+
1;
|
|
782
780
|
const node = schema.nodes.graphical_abstract_section.createAndFill({ category: category.id }, [
|
|
783
781
|
schema.nodes.section_title.create({}, schema.text(category.titles[0])),
|
|
784
782
|
createAndFillFigureElement(state),
|
|
@@ -982,7 +980,7 @@ export const insertBibliographySection = () => {
|
|
|
982
980
|
export const insertTOCSection = () => {
|
|
983
981
|
return false;
|
|
984
982
|
};
|
|
985
|
-
export const insertTransAbstract = (state, dispatch, category
|
|
983
|
+
export const insertTransAbstract = (state, dispatch, category) => {
|
|
986
984
|
if (!templateAllows(state, schema.nodes.trans_abstract)) {
|
|
987
985
|
return false;
|
|
988
986
|
}
|
|
@@ -997,16 +995,14 @@ export const insertTransAbstract = (state, dispatch, category, insertAfterPos) =
|
|
|
997
995
|
category,
|
|
998
996
|
}, [title, paragraph]);
|
|
999
997
|
const abstracts = findAbstractsNode(state.doc);
|
|
1000
|
-
const pos =
|
|
1001
|
-
? insertAfterPos
|
|
1002
|
-
: abstracts.pos + abstracts.node.nodeSize - 1;
|
|
998
|
+
const pos = abstracts.node.content.size + abstracts.pos + 1;
|
|
1003
999
|
const tr = state.tr.insert(pos, node);
|
|
1004
1000
|
const selection = TextSelection.create(tr.doc, pos + 1);
|
|
1005
1001
|
tr.setSelection(selection).scrollIntoView();
|
|
1006
1002
|
dispatch(tr);
|
|
1007
1003
|
return true;
|
|
1008
1004
|
};
|
|
1009
|
-
export const insertTransGraphicalAbstract = (category
|
|
1005
|
+
export const insertTransGraphicalAbstract = (category) => (state, dispatch, view) => {
|
|
1010
1006
|
if (!templateAllows(state, schema.nodes.trans_graphical_abstract)) {
|
|
1011
1007
|
return false;
|
|
1012
1008
|
}
|
|
@@ -1015,9 +1011,7 @@ export const insertTransGraphicalAbstract = (category, insertAfterPos) => (state
|
|
|
1015
1011
|
}
|
|
1016
1012
|
const lang = state.doc.attrs.primaryLanguageCode || 'en';
|
|
1017
1013
|
const abstracts = findAbstractsNode(state.doc);
|
|
1018
|
-
const pos =
|
|
1019
|
-
? insertAfterPos
|
|
1020
|
-
: abstracts.pos + abstracts.node.content.size + 1;
|
|
1014
|
+
const pos = abstracts.node.content.size + abstracts.pos + 1;
|
|
1021
1015
|
const node = schema.nodes.trans_graphical_abstract.createAndFill({
|
|
1022
1016
|
lang,
|
|
1023
1017
|
category: category.id,
|
|
@@ -23,8 +23,21 @@ export const Metadata = styled.div `
|
|
|
23
23
|
margin-top: ${(props) => props.theme.grid.unit}px;
|
|
24
24
|
`;
|
|
25
25
|
export const MetadataContainer = styled.div `
|
|
26
|
+
position: relative;
|
|
26
27
|
flex: 1;
|
|
27
28
|
`;
|
|
28
|
-
export const ReferenceLine = ({ item }) => (React.createElement(MetadataContainer, null,
|
|
29
|
+
export const ReferenceLine = ({ item, showUncited }) => (React.createElement(MetadataContainer, null,
|
|
30
|
+
showUncited && React.createElement(UncitedBadge, null, "UNCITED"),
|
|
29
31
|
React.createElement("div", { "data-cy": 'reference-title' }, item.title || item.literal || 'Untitled'),
|
|
30
32
|
React.createElement(Metadata, null, metadata(item))));
|
|
33
|
+
const UncitedBadge = styled.span `
|
|
34
|
+
padding: 1px 6px;
|
|
35
|
+
display: flex;
|
|
36
|
+
margin-bottom: 2px;
|
|
37
|
+
max-width: max-content;
|
|
38
|
+
border-radius: 4px;
|
|
39
|
+
color: #353535;
|
|
40
|
+
background-color: #f7b314;
|
|
41
|
+
font-size: 10px;
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AddAuthorIcon, Category, CitationCountIcon, CloseButton, Dialog, ModalBody, ModalContainer, ModalHeader, ModalSidebar, ModalSidebarHeader, ModalSidebarTitle, ScrollableModalContent, SidebarContent, StyledModal, useScrollDetection, withListNavigation, withNavigableListItem, } from '@manuscripts/style-guide';
|
|
1
|
+
import { AddIcon, AddAuthorIcon, Category, CitationCountIcon, CloseButton, Dialog, ModalBody, ModalContainer, ModalHeader, ModalSidebar, ModalSidebarHeader, ModalSidebarTitle, ScrollableModalContent, SidebarContent, StyledModal, useScrollDetection, withListNavigation, withNavigableListItem, } from '@manuscripts/style-guide';
|
|
2
|
+
import { generateNodeID, schema, } from '@manuscripts/transform';
|
|
2
3
|
import isEqual from 'lodash/isEqual';
|
|
3
4
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
4
5
|
import styled from 'styled-components';
|
|
@@ -6,135 +7,19 @@ import { ReferenceForm, } from './ReferenceForm/ReferenceForm';
|
|
|
6
7
|
import { ReferenceLine } from './ReferenceLine';
|
|
7
8
|
import { ImportBibliographyModal } from './ImportBibliographyModal';
|
|
8
9
|
import { ImportSuccessPlaceholder } from './ImportSuccessPlaceholder';
|
|
9
|
-
|
|
10
|
-
min-width: 960px;
|
|
11
|
-
`;
|
|
12
|
-
const ReferencesSidebar = styled(ModalSidebar) `
|
|
13
|
-
width: 70%;
|
|
14
|
-
`;
|
|
15
|
-
const ReferencesSidebarContent = styled(SidebarContent) `
|
|
16
|
-
overflow-y: auto;
|
|
17
|
-
`;
|
|
18
|
-
const ImportFromFileFooter = styled.div `
|
|
19
|
-
padding: 16px;
|
|
20
|
-
`;
|
|
21
|
-
const ImportFromFileButton = styled.button `
|
|
22
|
-
display: flex;
|
|
23
|
-
width: 100%;
|
|
24
|
-
padding: 8px 24px;
|
|
25
|
-
justify-content: center;
|
|
26
|
-
align-items: center;
|
|
27
|
-
gap: 8px;
|
|
28
|
-
border-radius: 4px;
|
|
29
|
-
border: 1px dashed #c9c9c9;
|
|
30
|
-
background: #fafafa;
|
|
31
|
-
cursor: pointer;
|
|
32
|
-
font-family: ${(props) => props.theme.font.family.sans};
|
|
33
|
-
font-size: 14px;
|
|
34
|
-
color: #353535;
|
|
35
|
-
|
|
36
|
-
svg {
|
|
37
|
-
width: 20px;
|
|
38
|
-
height: 20px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
svg rect {
|
|
42
|
-
fill: #6e6e6e;
|
|
43
|
-
}
|
|
44
|
-
`;
|
|
45
|
-
const ReferencesInnerWrapper = withListNavigation(styled.div `
|
|
46
|
-
width: 100%;
|
|
47
|
-
padding: 12px 0;
|
|
48
|
-
`);
|
|
49
|
-
const ReferenceButton = withNavigableListItem(styled.div `
|
|
50
|
-
cursor: pointer;
|
|
51
|
-
display: flex;
|
|
52
|
-
justify-content: flex-start;
|
|
53
|
-
padding: ${(props) => props.theme.grid.unit * 4}px 0;
|
|
54
|
-
border-top: 1px solid transparent;
|
|
55
|
-
border-bottom: 1px solid transparent;
|
|
56
|
-
|
|
57
|
-
path {
|
|
58
|
-
fill: #c9c9c9;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
&:hover {
|
|
62
|
-
background: ${(props) => props.theme.colors.background.info};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
&.selected {
|
|
66
|
-
background: ${(props) => props.theme.colors.background.info};
|
|
67
|
-
border-top-color: #bce7f6;
|
|
68
|
-
border-bottom-color: #bce7f6;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.tooltip {
|
|
72
|
-
max-width: ${(props) => props.theme.grid.unit * 25}px;
|
|
73
|
-
padding: ${(props) => props.theme.grid.unit * 2}px;
|
|
74
|
-
border-radius: 6px;
|
|
75
|
-
}
|
|
76
|
-
`);
|
|
77
|
-
const IconContainer = styled.div `
|
|
78
|
-
padding-right: ${(props) => props.theme.grid.unit * 5}px;
|
|
79
|
-
position: relative;
|
|
80
|
-
`;
|
|
81
|
-
const CitationCount = styled.div `
|
|
82
|
-
border-radius: 50%;
|
|
83
|
-
width: 12px;
|
|
84
|
-
height: 12px;
|
|
85
|
-
position: absolute;
|
|
86
|
-
color: #ffffff;
|
|
87
|
-
background-color: #bce7f6;
|
|
88
|
-
text-align: center;
|
|
89
|
-
vertical-align: top;
|
|
90
|
-
top: 0;
|
|
91
|
-
left: 16px;
|
|
92
|
-
font-size: 9px;
|
|
93
|
-
|
|
94
|
-
&.unused {
|
|
95
|
-
background-color: #fe8f1f;
|
|
96
|
-
}
|
|
97
|
-
`;
|
|
10
|
+
import { normalizeBlblioItem } from '../../lib/normalize';
|
|
98
11
|
const selectionTopOffset = 10;
|
|
99
12
|
const pageSize = 12;
|
|
100
13
|
const topTrigger = 0.2;
|
|
101
14
|
const bottomTrigger = 0.8;
|
|
102
15
|
const dropLimit = 36;
|
|
103
|
-
const normalize = (item) => ({
|
|
104
|
-
id: item.id,
|
|
105
|
-
type: item.type,
|
|
106
|
-
author: item.author || [],
|
|
107
|
-
editor: item.editor || [],
|
|
108
|
-
issued: item.issued,
|
|
109
|
-
['container-title']: item['container-title'] || '',
|
|
110
|
-
['collection-title']: item['collection-title'] || '',
|
|
111
|
-
DOI: item.DOI || '',
|
|
112
|
-
URL: item.URL || '',
|
|
113
|
-
volume: item.volume || '',
|
|
114
|
-
issue: item.issue || '',
|
|
115
|
-
supplement: item.supplement || '',
|
|
116
|
-
edition: item.edition || '',
|
|
117
|
-
page: item.page || '',
|
|
118
|
-
['number-of-pages']: item['number-of-pages'] || '',
|
|
119
|
-
title: item.title || '',
|
|
120
|
-
literal: item.literal || '',
|
|
121
|
-
std: item.std || '',
|
|
122
|
-
publisher: item.publisher || '',
|
|
123
|
-
['publisher-place']: item['publisher-place'] || '',
|
|
124
|
-
event: item.event || '',
|
|
125
|
-
['event-place']: item['event-place'] || '',
|
|
126
|
-
['event-date']: item['event-date'],
|
|
127
|
-
institution: item.institution || '',
|
|
128
|
-
locator: item.locator || '',
|
|
129
|
-
accessed: item.accessed,
|
|
130
|
-
comment: item.comment || '',
|
|
131
|
-
});
|
|
132
16
|
export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts, onSave, onDelete, handleImport, }) => {
|
|
133
17
|
const [importing, setImporting] = useState(false);
|
|
134
18
|
const [importSuccessCount, setImportSuccessCount] = useState(null);
|
|
135
19
|
const [confirm, setConfirm] = useState(false);
|
|
136
20
|
const valuesRef = useRef(undefined);
|
|
137
21
|
const [selection, setSelection] = useState();
|
|
22
|
+
const [isNew, setIsNew] = useState(false);
|
|
138
23
|
const selectionRef = useRef(null);
|
|
139
24
|
const sortedItems = useMemo(() => [...items].sort((a, b) => {
|
|
140
25
|
const aUncited = (citationCounts.get(a.id) ?? 0) === 0;
|
|
@@ -149,7 +34,17 @@ export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts,
|
|
|
149
34
|
};
|
|
150
35
|
const selectionIndex = sortedItems.findIndex(isSelected);
|
|
151
36
|
useEffect(() => {
|
|
152
|
-
|
|
37
|
+
if (item) {
|
|
38
|
+
setSelection(item);
|
|
39
|
+
setIsNew(false);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
setIsNew(true);
|
|
43
|
+
setSelection({
|
|
44
|
+
id: generateNodeID(schema.nodes.bibliography_item),
|
|
45
|
+
type: 'article-journal',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
153
48
|
}, [item]);
|
|
154
49
|
useEffect(() => {
|
|
155
50
|
setTimeout(() => {
|
|
@@ -199,10 +94,11 @@ export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts,
|
|
|
199
94
|
};
|
|
200
95
|
const currentCitationCount = citationCounts.get(item.id);
|
|
201
96
|
if (currentCitationCount === undefined) {
|
|
202
|
-
citationCounts.set(item.id,
|
|
97
|
+
citationCounts.set(item.id, 0);
|
|
203
98
|
}
|
|
204
99
|
onSave(item);
|
|
205
100
|
setSelection(item);
|
|
101
|
+
setIsNew(false);
|
|
206
102
|
setConfirm(false);
|
|
207
103
|
};
|
|
208
104
|
const handleDelete = () => {
|
|
@@ -212,14 +108,18 @@ export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts,
|
|
|
212
108
|
onDelete(selection);
|
|
213
109
|
setSelection(undefined);
|
|
214
110
|
};
|
|
111
|
+
const hasChanged = () => {
|
|
112
|
+
const values = valuesRef.current;
|
|
113
|
+
return (values && selection && !isEqual(values, normalizeBlblioItem(selection)));
|
|
114
|
+
};
|
|
215
115
|
const clearImportSuccess = () => setImportSuccessCount(null);
|
|
216
116
|
const handleItemClick = (item) => {
|
|
217
117
|
clearImportSuccess();
|
|
218
|
-
|
|
219
|
-
if (values && selection && !isEqual(values, normalize(selection))) {
|
|
118
|
+
if (hasChanged()) {
|
|
220
119
|
setConfirm(true);
|
|
221
120
|
return;
|
|
222
121
|
}
|
|
122
|
+
setIsNew(false);
|
|
223
123
|
setSelection(item);
|
|
224
124
|
};
|
|
225
125
|
const handleChange = (values) => {
|
|
@@ -231,9 +131,6 @@ export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts,
|
|
|
231
131
|
setSelection(undefined);
|
|
232
132
|
setImportSuccessCount(data.length);
|
|
233
133
|
};
|
|
234
|
-
if (sortedItems.length <= 0) {
|
|
235
|
-
return React.createElement(React.Fragment, null);
|
|
236
|
-
}
|
|
237
134
|
return (React.createElement(React.Fragment, null,
|
|
238
135
|
importing && (React.createElement(ImportBibliographyModal, { onCancel: () => setImporting(false), onSave: handleImportSave })),
|
|
239
136
|
React.createElement(StyledModal, { isOpen: isOpen, onRequestClose: onCancel },
|
|
@@ -255,15 +152,142 @@ export const ReferencesModal = ({ isOpen, onCancel, items, item, citationCounts,
|
|
|
255
152
|
React.createElement(ModalSidebarHeader, null,
|
|
256
153
|
React.createElement(ModalSidebarTitle, null, "References")),
|
|
257
154
|
React.createElement(ReferencesSidebarContent, { ref: ref },
|
|
258
|
-
React.createElement(
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
155
|
+
React.createElement(NewReferenceButton, { onClick: () => {
|
|
156
|
+
if (hasChanged()) {
|
|
157
|
+
setConfirm(true);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
setIsNew(true);
|
|
161
|
+
setSelection({
|
|
162
|
+
id: generateNodeID(schema.nodes.bibliography_item),
|
|
163
|
+
type: 'article-journal',
|
|
164
|
+
});
|
|
165
|
+
}, className: isNew ? 'selected' : '', disabled: isNew },
|
|
166
|
+
React.createElement(AddIcon, null),
|
|
167
|
+
React.createElement("span", null, "New Reference")),
|
|
168
|
+
React.createElement(ReferencesInnerWrapper, null,
|
|
169
|
+
React.createElement(ExistingReferencesHeading, null, "Existing References"),
|
|
170
|
+
sortedItems.slice(startIndex, endIndex + 1).map((item) => (React.createElement(ReferenceButton, { key: item.id, id: item.id, className: isSelected(item) ? 'selected' : '', onClick: () => handleItemClick(item), ref: isSelected(item) ? selectionRef : null },
|
|
171
|
+
React.createElement(IconContainer, null,
|
|
172
|
+
React.createElement(CitationCountIconStyled, null),
|
|
173
|
+
(citationCounts.get(item.id) || 0) > 0 ? (React.createElement(CitationCount, { "data-tooltip-content": "Number of times used in the document" }, citationCounts.get(item.id))) : (React.createElement(CitationCount, { className: "unused" }, "0"))),
|
|
174
|
+
React.createElement(ReferenceLine, { showUncited: !citationCounts.get(item.id), item: item })))))),
|
|
263
175
|
React.createElement(ImportFromFileFooter, null,
|
|
264
176
|
React.createElement(ImportFromFileButton, { type: "button", "data-cy": "import-from-file-button", onClick: () => setImporting(true) },
|
|
265
177
|
React.createElement(AddAuthorIcon, null),
|
|
266
178
|
"Import from file"))),
|
|
267
|
-
React.createElement(ScrollableModalContent, null, importSuccessCount !== null ? (React.createElement(ImportSuccessPlaceholder, { count: importSuccessCount })) : (selection && (React.createElement(ReferenceForm, { values:
|
|
179
|
+
React.createElement(ScrollableModalContent, null, importSuccessCount !== null ? (React.createElement(ImportSuccessPlaceholder, { count: importSuccessCount })) : (selection && (React.createElement(ReferenceForm, { values: normalizeBlblioItem(selection), showDelete: !citationCounts.get(selection.id) &&
|
|
268
180
|
isNewItem(selection, ['id', 'type']), onChange: handleChange, onCancel: onCancel, onDelete: handleDelete, onSave: handleSave, actionsRef: actionsRef })))))))));
|
|
269
181
|
};
|
|
182
|
+
const ReferencesModalContainer = styled(ModalContainer) `
|
|
183
|
+
min-width: 960px;
|
|
184
|
+
`;
|
|
185
|
+
const ReferencesSidebar = styled(ModalSidebar) `
|
|
186
|
+
width: 70%;
|
|
187
|
+
`;
|
|
188
|
+
const ReferencesSidebarContent = styled(SidebarContent) `
|
|
189
|
+
overflow-y: auto;
|
|
190
|
+
`;
|
|
191
|
+
const ReferencesInnerWrapper = withListNavigation(styled.div `
|
|
192
|
+
width: 100%;
|
|
193
|
+
padding: 12px 0;
|
|
194
|
+
`);
|
|
195
|
+
const CitationCountIconStyled = styled(CitationCountIcon) ``;
|
|
196
|
+
const ReferenceButton = withNavigableListItem(styled.button `
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
display: flex;
|
|
199
|
+
width: 100%;
|
|
200
|
+
justify-content: flex-start;
|
|
201
|
+
font: inherit;
|
|
202
|
+
appearance: none;
|
|
203
|
+
-webkit-appearance: none;
|
|
204
|
+
background: none;
|
|
205
|
+
border: none;
|
|
206
|
+
border-radius: 0;
|
|
207
|
+
text-align: inherit;
|
|
208
|
+
|
|
209
|
+
padding: ${(props) => props.theme.grid.unit * 4}px 0;
|
|
210
|
+
border-top: 1px solid transparent;
|
|
211
|
+
border-bottom: 1px solid transparent;
|
|
212
|
+
|
|
213
|
+
${CitationCountIconStyled} path {
|
|
214
|
+
fill: #c9c9c9;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
&:hover {
|
|
218
|
+
background: ${(props) => props.theme.colors.background.info};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
&.selected {
|
|
222
|
+
background: ${(props) => props.theme.colors.background.info};
|
|
223
|
+
border-top-color: #bce7f6;
|
|
224
|
+
border-bottom-color: #bce7f6;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.tooltip {
|
|
228
|
+
max-width: ${(props) => props.theme.grid.unit * 25}px;
|
|
229
|
+
padding: ${(props) => props.theme.grid.unit * 2}px;
|
|
230
|
+
border-radius: 6px;
|
|
231
|
+
}
|
|
232
|
+
`);
|
|
233
|
+
const IconContainer = styled.div `
|
|
234
|
+
padding-right: ${(props) => props.theme.grid.unit * 5}px;
|
|
235
|
+
position: relative;
|
|
236
|
+
`;
|
|
237
|
+
const CitationCount = styled.div `
|
|
238
|
+
border-radius: 50%;
|
|
239
|
+
width: 12px;
|
|
240
|
+
height: 12px;
|
|
241
|
+
position: absolute;
|
|
242
|
+
color: #ffffff;
|
|
243
|
+
background-color: #bce7f6;
|
|
244
|
+
text-align: center;
|
|
245
|
+
vertical-align: top;
|
|
246
|
+
top: 0;
|
|
247
|
+
left: 16px;
|
|
248
|
+
font-size: 9px;
|
|
249
|
+
|
|
250
|
+
&.unused {
|
|
251
|
+
background-color: #fe8f1f;
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
const NewReferenceButton = styled(ReferenceButton) `
|
|
255
|
+
svg {
|
|
256
|
+
margin-right: 8px;
|
|
257
|
+
}
|
|
258
|
+
`;
|
|
259
|
+
const ExistingReferencesHeading = styled.h3 `
|
|
260
|
+
font-size: 18px;
|
|
261
|
+
font-style: normal;
|
|
262
|
+
font-weight: 400;
|
|
263
|
+
padding: 8px 0 20px;
|
|
264
|
+
margin: 0;
|
|
265
|
+
color: #6e6e6e;
|
|
266
|
+
`;
|
|
267
|
+
const ImportFromFileFooter = styled.div `
|
|
268
|
+
padding: 16px;
|
|
269
|
+
`;
|
|
270
|
+
const ImportFromFileButton = styled.button `
|
|
271
|
+
display: flex;
|
|
272
|
+
width: 100%;
|
|
273
|
+
padding: 8px 24px;
|
|
274
|
+
justify-content: center;
|
|
275
|
+
align-items: center;
|
|
276
|
+
gap: 8px;
|
|
277
|
+
border-radius: 4px;
|
|
278
|
+
border: 1px dashed #c9c9c9;
|
|
279
|
+
background: #fafafa;
|
|
280
|
+
cursor: pointer;
|
|
281
|
+
font-family: ${(props) => props.theme.font.family.sans};
|
|
282
|
+
font-size: 14px;
|
|
283
|
+
color: #353535;
|
|
284
|
+
|
|
285
|
+
svg {
|
|
286
|
+
width: 20px;
|
|
287
|
+
height: 20px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
svg rect {
|
|
291
|
+
fill: #6e6e6e;
|
|
292
|
+
}
|
|
293
|
+
`;
|
|
@@ -113,6 +113,7 @@ export default (props, dispatch) => {
|
|
|
113
113
|
headshot_element: headshotElement(props, dispatch),
|
|
114
114
|
headshot_image: headshotImage(props, dispatch),
|
|
115
115
|
abstracts: abstracts(props),
|
|
116
|
+
abstract: section(props),
|
|
116
117
|
trans_abstract: transAbstract(props),
|
|
117
118
|
trans_graphical_abstract: transGraphicalAbstract(props),
|
|
118
119
|
attachment: attachment(props, dispatch),
|
package/dist/es/icons.js
CHANGED
|
@@ -2,7 +2,7 @@ import { AddAuthorIcon, AlertIcon, ArrowDownCircleIcon, ArrowUpIcon, CameraIcon,
|
|
|
2
2
|
import { createElement } from 'react';
|
|
3
3
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
4
4
|
const renderIcon = (c) => renderToStaticMarkup(createElement(c));
|
|
5
|
-
export const
|
|
5
|
+
export const addIcon = renderIcon(AddAuthorIcon);
|
|
6
6
|
export const arrowDown = renderIcon(ArrowDownCircleIcon);
|
|
7
7
|
export const arrowUp = renderIcon(ArrowUpIcon);
|
|
8
8
|
export const alertIcon = renderIcon(AlertIcon);
|