@manuscripts/body-editor 3.16.0 → 3.16.2

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.
Files changed (99) hide show
  1. package/dist/cjs/commands.js +45 -10
  2. package/dist/cjs/components/form/FormFooter.js +2 -2
  3. package/dist/cjs/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.js +4 -2
  4. package/dist/cjs/components/references/CitationEditor.js +13 -19
  5. package/dist/cjs/components/references/ImportBibliography.js +77 -0
  6. package/dist/cjs/components/references/ImportBibliographyForm.js +1 -1
  7. package/dist/cjs/components/references/ImportBibliographyModal.js +12 -81
  8. package/dist/cjs/components/references/ImportReferencesConfirmation.js +113 -0
  9. package/dist/cjs/components/references/ImportSuccessPlaceholder.js +56 -0
  10. package/dist/cjs/components/references/ReferenceSearch.js +2 -5
  11. package/dist/cjs/components/references/ReferencesEditor.js +18 -2
  12. package/dist/cjs/components/references/ReferencesModal.js +86 -33
  13. package/dist/cjs/components/views/CrossReferenceItems.js +139 -52
  14. package/dist/cjs/components/views/DeleteSupplementDialog.js +1 -1
  15. package/dist/cjs/lib/supplements.js +9 -1
  16. package/dist/cjs/lib/view.js +39 -1
  17. package/dist/cjs/menus.js +35 -0
  18. package/dist/cjs/plugins/objects.js +1 -1
  19. package/dist/cjs/toolbar.js +6 -0
  20. package/dist/cjs/versions.js +1 -1
  21. package/dist/cjs/views/bibliography_element.js +1 -2
  22. package/dist/cjs/views/citation_editable.js +2 -29
  23. package/dist/cjs/views/cross_reference.js +12 -2
  24. package/dist/cjs/views/cross_reference_editable.js +95 -4
  25. package/dist/cjs/views/figure_editable.js +3 -0
  26. package/dist/es/commands.js +43 -9
  27. package/dist/es/components/form/FormFooter.js +2 -2
  28. package/dist/es/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.js +4 -2
  29. package/dist/es/components/references/CitationEditor.js +13 -19
  30. package/dist/es/components/references/ImportBibliography.js +70 -0
  31. package/dist/es/components/references/ImportBibliographyForm.js +1 -1
  32. package/dist/es/components/references/ImportBibliographyModal.js +13 -79
  33. package/dist/es/components/references/ImportReferencesConfirmation.js +73 -0
  34. package/dist/es/components/references/ImportSuccessPlaceholder.js +49 -0
  35. package/dist/es/components/references/ReferenceSearch.js +3 -6
  36. package/dist/es/components/references/ReferencesEditor.js +19 -3
  37. package/dist/es/components/references/ReferencesModal.js +88 -35
  38. package/dist/es/components/views/CrossReferenceItems.js +141 -54
  39. package/dist/es/components/views/DeleteSupplementDialog.js +2 -2
  40. package/dist/es/lib/supplements.js +8 -1
  41. package/dist/es/lib/view.js +36 -0
  42. package/dist/es/menus.js +36 -1
  43. package/dist/es/plugins/objects.js +1 -1
  44. package/dist/es/toolbar.js +8 -2
  45. package/dist/es/versions.js +1 -1
  46. package/dist/es/views/bibliography_element.js +2 -3
  47. package/dist/es/views/citation_editable.js +3 -30
  48. package/dist/es/views/cross_reference.js +12 -2
  49. package/dist/es/views/cross_reference_editable.js +96 -5
  50. package/dist/es/views/figure_editable.js +3 -0
  51. package/dist/types/commands.d.ts +1 -0
  52. package/dist/types/components/form/FormFooter.d.ts +2 -1
  53. package/dist/types/components/references/CitationEditor.d.ts +1 -1
  54. package/dist/types/components/references/ImportBibliography.d.ts +7 -0
  55. package/dist/types/components/references/ImportReferencesConfirmation.d.ts +8 -0
  56. package/dist/types/components/references/ImportSuccessPlaceholder.d.ts +5 -0
  57. package/dist/types/components/references/ReferenceSearch.d.ts +0 -1
  58. package/dist/types/components/references/ReferencesEditor.d.ts +4 -1
  59. package/dist/types/components/references/ReferencesModal.d.ts +1 -0
  60. package/dist/types/components/views/CrossReferenceItems.d.ts +3 -0
  61. package/dist/types/lib/supplements.d.ts +1 -0
  62. package/dist/types/lib/view.d.ts +3 -1
  63. package/dist/types/versions.d.ts +1 -1
  64. package/dist/types/views/citation_editable.d.ts +0 -1
  65. package/dist/types/views/cross_reference_editable.d.ts +6 -0
  66. package/package.json +4 -4
  67. package/src/commands.ts +52 -10
  68. package/src/components/ChangeHandlingForm.tsx +4 -2
  69. package/src/components/form/FormFooter.tsx +3 -1
  70. package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +6 -7
  71. package/src/components/references/CitationEditor.tsx +16 -25
  72. package/src/components/references/ImportBibliography.tsx +119 -0
  73. package/src/components/references/ImportBibliographyForm.tsx +1 -1
  74. package/src/components/references/ImportBibliographyModal.tsx +34 -110
  75. package/src/components/references/ImportReferencesConfirmation.tsx +133 -0
  76. package/src/components/references/ImportSuccessPlaceholder.tsx +93 -0
  77. package/src/components/references/ReferenceSearch.tsx +0 -7
  78. package/src/components/references/ReferencesEditor.tsx +35 -6
  79. package/src/components/references/ReferencesModal.tsx +164 -78
  80. package/src/components/toolbar/InsertEmbedDialog.tsx +6 -2
  81. package/src/components/toolbar/type-selector/styles.ts +2 -1
  82. package/src/components/views/CrossReferenceItems.tsx +227 -100
  83. package/src/components/views/DeleteSupplementDialog.tsx +3 -6
  84. package/src/lib/footnotes.ts +3 -1
  85. package/src/lib/supplements.ts +13 -1
  86. package/src/lib/utils.ts +15 -4
  87. package/src/lib/view.ts +65 -0
  88. package/src/menus.tsx +39 -0
  89. package/src/plugins/add-subtitle.ts +18 -16
  90. package/src/plugins/objects.ts +2 -6
  91. package/src/toolbar.tsx +9 -0
  92. package/src/versions.ts +1 -1
  93. package/src/views/bibliography_element.ts +3 -4
  94. package/src/views/citation_editable.ts +5 -50
  95. package/src/views/cross_reference.ts +17 -3
  96. package/src/views/cross_reference_editable.ts +123 -11
  97. package/src/views/figure_editable.ts +4 -0
  98. package/src/views/supplement.ts +0 -1
  99. package/src/views/supplements.ts +2 -2
@@ -21,9 +21,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.CitationEditableView = void 0;
22
22
  const style_guide_1 = require("@manuscripts/style-guide");
23
23
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
24
- const transform_1 = require("@manuscripts/transform");
25
24
  const prosemirror_state_1 = require("prosemirror-state");
26
- const prosemirror_utils_1 = require("prosemirror-utils");
27
25
  const CitationEditor_1 = require("../components/references/CitationEditor");
28
26
  const CitationViewer_1 = require("../components/references/CitationViewer");
29
27
  const comments_1 = require("../lib/comments");
@@ -34,10 +32,6 @@ const bibliography_1 = require("../plugins/bibliography");
34
32
  const citation_1 = require("./citation");
35
33
  const creators_1 = require("./creators");
36
34
  const ReactSubView_1 = __importDefault(require("./ReactSubView"));
37
- const createBibliographySection = (node) => transform_1.schema.nodes.bibliography_section.createAndFill({}, [
38
- transform_1.schema.nodes.section_title.create({}, transform_1.schema.text('References')),
39
- transform_1.schema.nodes.bibliography_element.create({}, node ? [node] : []),
40
- ]);
41
35
  class CitationEditableView extends citation_1.CitationView {
42
36
  constructor() {
43
37
  super(...arguments);
@@ -143,12 +137,7 @@ class CitationEditableView extends citation_1.CitationView {
143
137
  this.props.popper.destroy();
144
138
  };
145
139
  this.handleSave = (attrs) => {
146
- if (!(0, view_1.findChildByID)(this.view, attrs.id)) {
147
- this.insertBibliographyNode(attrs);
148
- }
149
- else {
150
- (0, view_1.updateNodeAttrs)(this.view, transform_1.schema.nodes.bibliography_item, attrs);
151
- }
140
+ (0, view_1.saveBibliographyItem)(this.view, attrs);
152
141
  };
153
142
  this.handleUncite = (id) => {
154
143
  const attrs = this.node.attrs;
@@ -181,7 +170,7 @@ class CitationEditableView extends citation_1.CitationView {
181
170
  item.id = existingItem.id;
182
171
  }
183
172
  else {
184
- this.insertBibliographyNode(item);
173
+ (0, view_1.saveBibliographyItem)(this.view, [item]);
185
174
  }
186
175
  rids.push(item.id);
187
176
  }
@@ -200,22 +189,6 @@ class CitationEditableView extends citation_1.CitationView {
200
189
  this.dom.addEventListener('mouseup', () => this.handleClick(false));
201
190
  this.dom.addEventListener('keydown', (0, navigation_utils_1.handleEnterKey)(() => this.handleClick(true)));
202
191
  }
203
- insertBibliographyNode(attrs) {
204
- const { doc, tr } = this.view.state;
205
- const biblioSection = (0, prosemirror_utils_1.findChildrenByType)(doc, transform_1.schema.nodes.bibliography_element, true);
206
- const backmatter = (0, prosemirror_utils_1.findChildrenByType)(doc, transform_1.schema.nodes.backmatter, true);
207
- const backmatterEnd = backmatter[0]
208
- ? backmatter[0].node.nodeSize + backmatter[0].pos
209
- : 0;
210
- const node = transform_1.schema.nodes.bibliography_item.create(attrs);
211
- if (biblioSection.length) {
212
- this.view.dispatch(tr.insert(biblioSection[0].pos + 1, node));
213
- }
214
- else {
215
- this.view.dispatch(tr.insert(backmatterEnd ? backmatterEnd - 1 : tr.doc.content.size, createBibliographySection(node)));
216
- }
217
- return false;
218
- }
219
192
  }
220
193
  exports.CitationEditableView = CitationEditableView;
221
194
  exports.default = (0, creators_1.createEditableNodeView)(CitationEditableView);
@@ -16,7 +16,10 @@
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.CrossReferenceView = void 0;
19
+ const transform_1 = require("@manuscripts/transform");
20
+ const doc_1 = require("../lib/doc");
19
21
  const navigation_utils_1 = require("../lib/navigation-utils");
22
+ const supplements_1 = require("../lib/supplements");
20
23
  const objects_1 = require("../plugins/objects");
21
24
  const base_node_view_1 = require("./base_node_view");
22
25
  const creators_1 = require("./creators");
@@ -49,8 +52,15 @@ class CrossReferenceView extends base_node_view_1.BaseNodeView {
49
52
  super.updateContents();
50
53
  const targets = objects_1.objectsKey.getState(this.view.state);
51
54
  const attrs = this.node.attrs;
52
- const label = attrs.rids.length && targets.get(attrs.rids[0])?.label;
53
- this.dom.textContent = attrs.label || label || '';
55
+ const target = attrs.rids.length ? targets.get(attrs.rids[0]) : undefined;
56
+ let derivedLabel = target?.label || '';
57
+ if (target?.type === transform_1.schema.nodes.supplement.name && target.href) {
58
+ const found = (0, doc_1.findNodeByID)(this.view.state.doc, target.id);
59
+ if (found) {
60
+ derivedLabel = (0, supplements_1.getSupplementDisplayLabel)(found.node, this.props.getFiles());
61
+ }
62
+ }
63
+ this.dom.textContent = attrs.label || derivedLabel;
54
64
  this.dom.addEventListener('click', this.handleClick);
55
65
  }
56
66
  }
@@ -19,10 +19,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.CrossReferenceEditableView = void 0;
22
+ const style_guide_1 = require("@manuscripts/style-guide");
22
23
  const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
23
24
  const transform_1 = require("@manuscripts/transform");
24
25
  const prosemirror_state_1 = require("prosemirror-state");
25
26
  const CrossReferenceItems_1 = require("../components/views/CrossReferenceItems");
27
+ const comments_1 = require("../lib/comments");
28
+ const doc_1 = require("../lib/doc");
29
+ const supplements_1 = require("../lib/supplements");
26
30
  const objects_1 = require("../plugins/objects");
27
31
  const creators_1 = require("./creators");
28
32
  const cross_reference_1 = require("./cross_reference");
@@ -37,14 +41,20 @@ class CrossReferenceEditableView extends cross_reference_1.CrossReferenceView {
37
41
  if (!can?.editArticle || rids.length) {
38
42
  return;
39
43
  }
44
+ this.showPicker();
45
+ };
46
+ this.showPicker = () => {
47
+ const rids = this.node.attrs.rids;
40
48
  const componentProps = {
41
49
  handleSelect: this.handleSelect,
42
50
  targets: this.getTargets(),
51
+ files: this.props.getFiles(),
43
52
  handleCancel: this.handleCancel,
44
53
  currentTargetId: rids[0],
45
54
  currentCustomLabel: this.node.attrs.label,
55
+ isEdit: rids.length > 0,
46
56
  };
47
- this.popperContainer = (0, ReactSubView_1.default)(this.props, CrossReferenceItems_1.CrossReferenceItems, componentProps, this.node, this.getPos, this.view, ['cross-reference-editor']);
57
+ this.popperContainer = (0, ReactSubView_1.default)(this.props, CrossReferenceItems_1.CrossReferenceItems, componentProps, this.node, this.getPos, this.view);
48
58
  this.popperContainer.setAttribute('tabindex', '0');
49
59
  this.props.popper.show(this.dom, this.popperContainer, 'auto');
50
60
  };
@@ -56,15 +66,39 @@ class CrossReferenceEditableView extends cross_reference_1.CrossReferenceView {
56
66
  this.handleCancel();
57
67
  };
58
68
  this.getTargets = () => {
59
- const excludedTypes = [transform_1.schema.nodes.image_element.name];
60
69
  const targets = objects_1.objectsKey.getState(this.view.state);
61
- return Array.from(targets.values()).filter((t) => !excludedTypes.includes(t.type));
70
+ const files = this.props.getFiles();
71
+ const fileMap = new Map(files.map((f) => [f.id, f.name]));
72
+ const excludedTypes = [transform_1.schema.nodes.image_element.name];
73
+ const supplement = transform_1.schema.nodes.supplement.name;
74
+ return Array.from(targets.values()).reduce((acc, t) => {
75
+ if (excludedTypes.includes(t.type)) {
76
+ return acc;
77
+ }
78
+ if (t.type === supplement && t.href) {
79
+ const found = (0, doc_1.findNodeByID)(this.view.state.doc, t.id);
80
+ const label = found
81
+ ? (0, supplements_1.getSupplementDisplayLabel)(found.node, files)
82
+ : (fileMap.get(t.href) ?? t.href);
83
+ acc.push({ ...t, label, caption: '' });
84
+ }
85
+ else {
86
+ acc.push(t);
87
+ }
88
+ return acc;
89
+ }, []);
62
90
  };
63
91
  this.handleCancel = () => {
64
92
  if (!this.node.attrs.rids.length) {
65
93
  const { state } = this.view;
66
94
  const pos = this.getPos();
67
- const tr = state.tr.delete(pos, pos + this.node.nodeSize);
95
+ if (pos === undefined) {
96
+ return;
97
+ }
98
+ const label = this.node.attrs.label;
99
+ const tr = label
100
+ ? state.tr.replaceWith(pos, pos + this.node.nodeSize, state.schema.text(label))
101
+ : state.tr.delete(pos, pos + this.node.nodeSize);
68
102
  tr.setSelection(prosemirror_state_1.TextSelection.create(tr.doc, pos));
69
103
  (0, track_changes_plugin_1.skipTracking)(tr);
70
104
  this.view.dispatch(tr);
@@ -85,6 +119,63 @@ class CrossReferenceEditableView extends cross_reference_1.CrossReferenceView {
85
119
  this.view.dispatch(tr.setSelection(selection));
86
120
  this.destroy();
87
121
  };
122
+ this.handleClick = () => {
123
+ if ((0, track_changes_plugin_1.isDeleted)(this.node)) {
124
+ return;
125
+ }
126
+ if (!this.node.attrs.rids.length) {
127
+ return;
128
+ }
129
+ this.showContextMenu();
130
+ };
131
+ this.showContextMenu = () => {
132
+ this.props.popper.destroy();
133
+ const can = this.props.getCapabilities();
134
+ const targets = objects_1.objectsKey.getState(this.view.state);
135
+ const rid = this.node.attrs.rids[0];
136
+ const isOrphaned = !targets?.get(rid);
137
+ const actions = [
138
+ {
139
+ label: 'Comment',
140
+ icon: 'AddComment',
141
+ action: () => {
142
+ this.props.popper.destroy();
143
+ (0, comments_1.handleComment)(this.node, this.view);
144
+ },
145
+ },
146
+ {
147
+ label: 'Go to content',
148
+ icon: 'Scroll',
149
+ action: () => this.navigateToTarget(),
150
+ disabled: isOrphaned,
151
+ },
152
+ ];
153
+ if (can?.editArticle) {
154
+ actions.unshift({
155
+ label: 'Edit',
156
+ icon: 'Edit',
157
+ action: () => this.handleEdit(),
158
+ disabled: isOrphaned,
159
+ });
160
+ }
161
+ this.contextMenu = (0, ReactSubView_1.default)(this.props, style_guide_1.ContextMenu, { actions }, this.node, this.getPos, this.view, ['context-menu']);
162
+ this.props.popper.show(this.dom, this.contextMenu, 'right-start', false);
163
+ };
164
+ this.navigateToTarget = () => {
165
+ this.props.popper.destroy();
166
+ const rids = this.node.attrs.rids;
167
+ if (!rids.length) {
168
+ return;
169
+ }
170
+ this.props.navigate({
171
+ pathname: this.props.location.pathname,
172
+ hash: '#' + rids[0],
173
+ });
174
+ };
175
+ this.handleEdit = () => {
176
+ this.props.popper.destroy();
177
+ this.showPicker();
178
+ };
88
179
  }
89
180
  }
90
181
  exports.CrossReferenceEditableView = CrossReferenceEditableView;
@@ -198,6 +198,9 @@ class FigureEditableView extends figure_1.FigureView {
198
198
  this.addTools();
199
199
  }
200
200
  addTools() {
201
+ if (this.getPos() === undefined) {
202
+ return;
203
+ }
201
204
  this.manageReactTools();
202
205
  const existingDragHandlers = this.container.querySelectorAll('.drag-handler');
203
206
  existingDragHandlers.forEach((handler) => handler.remove());
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { isDeleted, skipTracking, skipSelect } from '@manuscripts/track-changes-plugin';
16
+ import { isDeleted, skipTracking, skipSelect, } from '@manuscripts/track-changes-plugin';
17
17
  import { generateNodeID, isElementNodeType, isListNode, isSectionNodeType, isTableElementNode, schema, } from '@manuscripts/transform';
18
18
  import { Fragment, NodeRange, Slice, } from 'prosemirror-model';
19
19
  import { wrapInList } from 'prosemirror-schema-list';
@@ -298,7 +298,7 @@ export const insertSupplement = (file, view, setSelection = true) => {
298
298
  export const insertSupplementWeblink = (url, title, view) => {
299
299
  const supplement = schema.nodes.supplement.createAndFill({
300
300
  id: generateNodeID(schema.nodes.supplement),
301
- href: url
301
+ href: url,
302
302
  }, createAndFillCaption());
303
303
  const tr = view.state.tr;
304
304
  const { pos } = upsertSupplementsSection(tr, supplement);
@@ -466,15 +466,52 @@ export const insertInlineCitation = (state, dispatch) => {
466
466
  }
467
467
  return true;
468
468
  };
469
+ export const canInsertCrossReference = (state) => {
470
+ if (!canInsert(schema.nodes.cross_reference)(state)) {
471
+ return false;
472
+ }
473
+ const { from, to, empty, $from, $to } = state.selection;
474
+ if (empty) {
475
+ return true;
476
+ }
477
+ if (!$from.sameParent($to)) {
478
+ return false;
479
+ }
480
+ let overlaps = false;
481
+ state.doc.nodesBetween(from, to, (node) => {
482
+ if (node.isAtom && !node.isText) {
483
+ overlaps = true;
484
+ return false;
485
+ }
486
+ return !overlaps;
487
+ });
488
+ return !overlaps;
489
+ };
469
490
  export const insertCrossReference = (state, dispatch) => {
491
+ if (!canInsertCrossReference(state)) {
492
+ return false;
493
+ }
494
+ const text = selectedText();
470
495
  const node = state.schema.nodes.cross_reference.create({
496
+ id: generateNodeID(schema.nodes.cross_reference),
471
497
  rids: [],
498
+ label: text,
472
499
  });
473
- const pos = state.selection.to;
474
- const tr = state.tr.insert(pos, node);
500
+ const { tr } = state;
501
+ let pos;
502
+ const isWrap = !state.selection.empty;
503
+ if (isWrap) {
504
+ pos = state.selection.from;
505
+ tr.replaceSelectionWith(node);
506
+ }
507
+ else {
508
+ pos = state.selection.to;
509
+ tr.insert(pos, node);
510
+ }
475
511
  if (dispatch) {
476
512
  const selection = NodeSelection.create(tr.doc, pos);
477
- dispatch(tr.setSelection(selection).scrollIntoView());
513
+ tr.setSelection(selection).scrollIntoView();
514
+ dispatch(isWrap ? skipTracking(tr) : tr);
478
515
  }
479
516
  return true;
480
517
  };
@@ -963,10 +1000,7 @@ export const insertTransGraphicalAbstract = (category, insertAfterPos) => (state
963
1000
  const node = schema.nodes.trans_graphical_abstract.createAndFill({
964
1001
  lang,
965
1002
  category: category.id,
966
- }, [
967
- schema.nodes.section_title.create(),
968
- createAndFillFigureElement(state),
969
- ]);
1003
+ }, [schema.nodes.section_title.create(), createAndFillFigureElement(state)]);
970
1004
  const tr = state.tr.insert(pos, node);
971
1005
  if (node.lastChild) {
972
1006
  expandAccessibilitySection(tr, node.lastChild);
@@ -16,9 +16,9 @@ const Footer = styled.div `
16
16
  const StyledIconTextButton = styled(IconTextButton) `
17
17
  color: ${(props) => props.theme.colors.brand.default};
18
18
  `;
19
- const FormFooter = ({ onCancel, primaryAction, }) => {
19
+ const FormFooter = ({ onCancel, primaryAction, cancelLabel = 'Close', }) => {
20
20
  return (React.createElement(Footer, null,
21
- React.createElement(StyledIconTextButton, { color: "secondary", onClick: onCancel }, "Close"),
21
+ React.createElement(StyledIconTextButton, { color: "secondary", onClick: onCancel }, cancelLabel),
22
22
  primaryAction));
23
23
  };
24
24
  export default FormFooter;
@@ -41,7 +41,8 @@ const ShortcutTabs = styled(InspectorTabs) `
41
41
  min-height: 0;
42
42
  `;
43
43
  const ModalTabsWrapper = styled('div') `
44
- margin: 0 ${(props) => props.theme.grid.unit * 8}px ${(props) => props.theme.grid.unit * 3}px;
44
+ margin: 0 ${(props) => props.theme.grid.unit * 8}px
45
+ ${(props) => props.theme.grid.unit * 3}px;
45
46
  `;
46
47
  const ShortcutTabPanel = styled(InspectorTabPanel).attrs({
47
48
  tabIndex: -1,
@@ -92,7 +93,8 @@ const Section = styled.section `
92
93
  }
93
94
  `;
94
95
  const SectionTitle = styled.h3 `
95
- margin: 0 ${(props) => props.theme.grid.unit * 8}px ${(props) => props.theme.grid.unit * 2}px;
96
+ margin: 0 ${(props) => props.theme.grid.unit * 8}px
97
+ ${(props) => props.theme.grid.unit * 2}px;
96
98
  font-size: ${(props) => props.theme.font.size.large};
97
99
  font-weight: ${(props) => props.theme.font.weight.normal};
98
100
  line-height: ${(props) => props.theme.font.lineHeight.large};
@@ -5,7 +5,6 @@ import styled from 'styled-components';
5
5
  import { arrayReducer, attrsReducer } from '../../lib/array-reducer';
6
6
  import { cleanItemValues } from '../../lib/utils';
7
7
  import { CitedItem, CitedItems } from './CitationViewer';
8
- import { ImportBibliographyModal } from './ImportBibliographyModal';
9
8
  import { ReferenceLine } from './ReferenceLine';
10
9
  import { ReferenceSearch } from './ReferenceSearch';
11
10
  import { ReferencesModal } from './ReferencesModal';
@@ -55,7 +54,7 @@ export const CitationEditor = ({ query, rids: $rids, items: $items, citationCoun
55
54
  const [rids, dispatchRids] = useReducer(ridsReducer, $rids);
56
55
  const handleSave = (item) => {
57
56
  const cleanedItem = cleanItemValues(item);
58
- onSave(cleanedItem);
57
+ onSave([cleanedItem]);
59
58
  dispatchItems({
60
59
  type: 'update',
61
60
  items: [cleanedItem],
@@ -90,7 +89,6 @@ export const CitationEditor = ({ query, rids: $rids, items: $items, citationCoun
90
89
  show: false,
91
90
  });
92
91
  const [searching, setSearching] = useState(false);
93
- const [importing, setImporting] = useState(false);
94
92
  const handleAdd = () => {
95
93
  setSearching(false);
96
94
  const item = {
@@ -103,35 +101,31 @@ export const CitationEditor = ({ query, rids: $rids, items: $items, citationCoun
103
101
  });
104
102
  setEditingForm({ show: true, item: item });
105
103
  };
106
- const handleImport = () => {
107
- setSearching(false);
108
- setImporting(true);
109
- };
110
- const handleSaveImport = (data) => {
111
- data.forEach((item) => {
112
- const newItem = { ...item };
113
- newItem.id = generateNodeID(schema.nodes.bibliography_item);
114
- handleSave(newItem);
115
- handleCite([newItem]);
104
+ const handleImport = (data) => {
105
+ const newItems = data.map((item) => cleanItemValues({
106
+ ...item,
107
+ id: generateNodeID(schema.nodes.bibliography_item),
108
+ }));
109
+ onSave(newItems);
110
+ dispatchItems({
111
+ type: 'set',
112
+ state: [...items, ...newItems],
116
113
  });
117
114
  };
118
115
  const cited = useMemo(() => {
119
116
  return rids.flatMap((rid) => items.filter((i) => i.id === rid));
120
117
  }, [rids, items]);
121
118
  if (editingForm.show) {
122
- return (React.createElement(ReferencesModal, { isOpen: editingForm.show, onCancel: () => setEditingForm({ show: false }), items: items, citationCounts: citationCounts, item: editingForm.item, onSave: handleSave, onDelete: handleDelete }));
123
- }
124
- if (importing) {
125
- return (React.createElement(ImportBibliographyModal, { onCancel: () => setImporting(false), onSave: handleSaveImport }));
119
+ return (React.createElement(ReferencesModal, { isOpen: editingForm.show, onCancel: () => setEditingForm({ show: false }), items: items, citationCounts: citationCounts, item: editingForm.item, onSave: handleSave, onDelete: handleDelete, handleImport: handleImport }));
126
120
  }
127
121
  if (searching) {
128
- return (React.createElement(ReferenceSearch, { sources: sources, items: items, onAdd: handleAdd, onImport: handleImport, onCite: (items) => {
122
+ return (React.createElement(ReferenceSearch, { sources: sources, items: items, onAdd: handleAdd, onCite: (items) => {
129
123
  setSearching(false);
130
124
  handleCite(items);
131
125
  }, onCancel: () => setSearching(false) }));
132
126
  }
133
127
  if (!rids.length) {
134
- return (React.createElement(ReferenceSearch, { query: query, sources: sources, items: items, onAdd: handleAdd, onImport: handleImport, onCite: handleCite, onCancel: onCancel }));
128
+ return (React.createElement(ReferenceSearch, { query: query, sources: sources, items: items, onAdd: handleAdd, onCite: handleCite, onCancel: onCancel }));
135
129
  }
136
130
  return (React.createElement(Container, null,
137
131
  React.createElement(Dialog, { isOpen: deleteDialog.show, category: Category.confirmation, header: "Remove cited item", message: "Are you sure you want to remove this cited item? It will still exist in the reference list.", actions: {
@@ -0,0 +1,70 @@
1
+ import { ModalTitle, Tooltip } from '@manuscripts/style-guide';
2
+ import React from 'react';
3
+ import styled from 'styled-components';
4
+ import { ImportBibliographyForm } from './ImportBibliographyForm';
5
+ const exampleBibtex = `@book{abramowitz+stegun,
6
+ author = "Milton {Abramowitz} and Irene A. {Stegun}",
7
+ title = "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
8
+ publisher = "Dover",
9
+ year = 1964,
10
+ address = "New York City",
11
+ edition = "ninth Dover printing, tenth GPO printing"
12
+ }`;
13
+ const examplePubmed = `Example Identifiers:
14
+ pmid:17170128
15
+ PMC1852221`;
16
+ const exampleRis = `TY - JOUR
17
+ AU - Shannon, Claude E.
18
+ PY - 1948
19
+ DA - July
20
+ TI - A Mathematical Theory of Communication
21
+ T2 - Bell System Technical Journal
22
+ SP - 379
23
+ EP - 423
24
+ VL - 27
25
+ ER - `;
26
+ const exampleEnw = `%0 Journal Article
27
+ %D 2018
28
+ %@ 0903-4641
29
+ %A Abbassi-Daloii, Tooba
30
+ %A Yousefi, Soheil
31
+ %A Sekhavati, Mohammad Hadi
32
+ %A Tahmoorespur, Mojtaba
33
+ %J APMIS
34
+ %N 1
35
+ %P 65-75
36
+ %T Impact of heat shock protein 60KD in combination with outer membrane proteins on immune response against Brucella melitensis
37
+ %R https://doi.org/10.1111/apm.12778
38
+ %U https://onlinelibrary.wiley.com/doi/abs/10.1111/apm.12778
39
+ %V 126
40
+ %X Lorem ipsum dolor sit amet`;
41
+ const exampleDoi = `Example DOI Identifiers:
42
+ 10.1080/15588742.2015.1017684
43
+ http://dx.doi.org/10.1080/15588742.2015.1017684`;
44
+ const supportedFormats = [
45
+ { label: 'BibTex', example: exampleBibtex },
46
+ { label: 'PubMed', example: examplePubmed },
47
+ { label: 'RIS', example: exampleRis },
48
+ { label: 'ENW', example: exampleEnw },
49
+ { label: 'DOI', example: exampleDoi },
50
+ ];
51
+ export const ImportBibliography = ({ onCancel, onContinue, }) => (React.createElement(React.Fragment, null,
52
+ React.createElement(ModalTitle, null, "Import Bibliography"),
53
+ React.createElement("p", null,
54
+ supportedFormats.map(({ label, example }, index) => (React.createElement(React.Fragment, { key: label },
55
+ index > 0 &&
56
+ (index === supportedFormats.length - 1 ? ' and ' : ', '),
57
+ React.createElement(SpanWithExample, { "data-tooltip-id": "import-example-tooltip", "data-tooltip-content": example }, label)))),
58
+ ' ',
59
+ "formats are supported"),
60
+ React.createElement(ImportBibliographyForm, { onCancel: onCancel, onSave: onContinue }),
61
+ React.createElement(Example, { id: "import-example-tooltip", place: "bottom", render: (s) => React.createElement("pre", null, s.content) })));
62
+ const SpanWithExample = styled.span `
63
+ text-decoration: underline dotted;
64
+ text-underline-offset: 4px;
65
+ `;
66
+ const Example = styled(Tooltip) `
67
+ text-align: left !important;
68
+ max-width: 480px !important;
69
+ overflow: hidden !important;
70
+ `;
@@ -103,7 +103,7 @@ export const ImportBibliographyForm = ({ onCancel, onSave, }) => {
103
103
  formik.values.data.map((item) => (React.createElement(ReferenceLine, { item: item, key: item.id })))),
104
104
  React.createElement(FormActionsBar, null,
105
105
  React.createElement(SecondaryButton, { type: "reset" }, "Cancel"),
106
- React.createElement(PrimaryButton, { type: "submit", disabled: !formik.dirty || formik.isSubmitting || !formik.values.data.length }, "Save"))));
106
+ React.createElement(PrimaryButton, { type: "submit", disabled: !formik.dirty || formik.isSubmitting || !formik.values.data.length }, "Import References"))));
107
107
  };
108
108
  const Preview = styled.div `
109
109
  display: flex;
@@ -1,88 +1,22 @@
1
- import { CloseButton, ModalCardBody, ModalContainer, ModalHeader, ModalTitle, StyledModal, Tooltip, } from '@manuscripts/style-guide';
1
+ import { CloseButton, ModalCardBody, ModalContainer, ModalHeader, StyledModal, } from '@manuscripts/style-guide';
2
2
  import React, { useState } from 'react';
3
- import styled from 'styled-components';
4
- import { ImportBibliographyForm } from './ImportBibliographyForm';
5
- const exampleBibtex = `@book{abramowitz+stegun,
6
- author = "Milton {Abramowitz} and Irene A. {Stegun}",
7
- title = "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
8
- publisher = "Dover",
9
- year = 1964,
10
- address = "New York City",
11
- edition = "ninth Dover printing, tenth GPO printing"
12
- }`;
13
- const examplePubmed = `Example Identifiers:
14
- pmid:17170128
15
- PMC1852221`;
16
- const exampleRis = `TY - JOUR
17
- AU - Shannon, Claude E.
18
- PY - 1948
19
- DA - July
20
- TI - A Mathematical Theory of Communication
21
- T2 - Bell System Technical Journal
22
- SP - 379
23
- EP - 423
24
- VL - 27
25
- ER - `;
26
- const exampleEnw = `%0 Journal Article
27
- %D 2018
28
- %@ 0903-4641
29
- %A Abbassi-Daloii, Tooba
30
- %A Yousefi, Soheil
31
- %A Sekhavati, Mohammad Hadi
32
- %A Tahmoorespur, Mojtaba
33
- %J APMIS
34
- %N 1
35
- %P 65-75
36
- %T Impact of heat shock protein 60KD in combination with outer membrane proteins on immune response against Brucella melitensis
37
- %R https://doi.org/10.1111/apm.12778
38
- %U https://onlinelibrary.wiley.com/doi/abs/10.1111/apm.12778
39
- %V 126
40
- %X Lorem ipsum dolor sit amet`;
41
- const exampleDoi = `Example DOI Identifiers:
42
- 10.1080/15588742.2015.1017684
43
- http://dx.doi.org/10.1080/15588742.2015.1017684`;
3
+ import { ImportBibliography } from './ImportBibliography';
4
+ import { ImportReferencesConfirmation } from './ImportReferencesConfirmation';
44
5
  export const ImportBibliographyModal = ({ onCancel, onSave }) => {
45
6
  const [isOpen, setOpen] = useState(true);
46
- const handleCancel = () => {
47
- handleClose();
48
- };
7
+ const [pendingItems, setPendingItems] = useState(null);
8
+ const isConfirming = pendingItems !== null;
49
9
  const handleClose = () => setOpen(false);
50
- const handleSave = (data) => {
51
- onSave(data);
10
+ const handleBack = () => setPendingItems(null);
11
+ const handleConfirm = (items) => {
12
+ onSave(items);
52
13
  handleClose();
53
14
  };
54
15
  return (React.createElement(StyledModal, { isOpen: isOpen, onRequestClose: onCancel },
55
- React.createElement(ModalContainer, { "data-cy": "import-bibliography-modal" },
16
+ React.createElement(ModalContainer, { "data-cy": isConfirming
17
+ ? 'import-confirmation-modal'
18
+ : 'import-bibliography-modal' },
56
19
  React.createElement(ModalHeader, null,
57
- React.createElement(CloseButton, { onClick: onCancel, "data-cy": "modal-close-button" })),
58
- React.createElement(ModalCardBody, { "$width": 640 },
59
- React.createElement(ModalTitle, null, "Import Bibliography"),
60
- React.createElement("p", null,
61
- React.createElement(SpanWithExample, { "data-tooltip-id": "import-example-tooltip", "data-tooltip-content": exampleBibtex }, "BibTex"),
62
- ",",
63
- ' ',
64
- React.createElement(SpanWithExample, { "data-tooltip-id": "import-example-tooltip", "data-tooltip-content": examplePubmed }, "PubMed"),
65
- ",",
66
- ' ',
67
- React.createElement(SpanWithExample, { "data-tooltip-id": "import-example-tooltip", "data-tooltip-content": exampleRis }, "RIS"),
68
- ",",
69
- ' ',
70
- React.createElement(SpanWithExample, { "data-tooltip-id": "import-example-tooltip", "data-tooltip-content": exampleEnw }, "ENW"),
71
- ' ',
72
- "and",
73
- ' ',
74
- React.createElement(SpanWithExample, { "data-tooltip-id": "import-example-tooltip", "data-tooltip-content": exampleDoi }, "DOI"),
75
- ' ',
76
- "formats are supported"),
77
- React.createElement(ImportBibliographyForm, { onCancel: handleCancel, onSave: handleSave }),
78
- React.createElement(Example, { id: "import-example-tooltip", place: "bottom", render: (s) => React.createElement("pre", null, s.content) })))));
20
+ React.createElement(CloseButton, { onClick: isConfirming ? handleBack : onCancel, "data-cy": "modal-close-button" })),
21
+ React.createElement(ModalCardBody, { "$width": 724 }, pendingItems ? (React.createElement(ImportReferencesConfirmation, { items: pendingItems, onCancel: handleBack, onConfirm: handleConfirm })) : (React.createElement(ImportBibliography, { onCancel: onCancel, onContinue: setPendingItems }))))));
79
22
  };
80
- const SpanWithExample = styled.span `
81
- text-decoration: underline dotted;
82
- text-underline-offset: 4px;
83
- `;
84
- const Example = styled(Tooltip) `
85
- text-align: left !important;
86
- max-width: 480px !important;
87
- overflow: hidden !important;
88
- `;