@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
package/src/commands.ts CHANGED
@@ -14,7 +14,11 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { isDeleted, skipTracking, skipSelect } from '@manuscripts/track-changes-plugin'
17
+ import {
18
+ isDeleted,
19
+ skipTracking,
20
+ skipSelect,
21
+ } from '@manuscripts/track-changes-plugin'
18
22
  import {
19
23
  AttachmentNode,
20
24
  AwardNode,
@@ -525,7 +529,7 @@ export const insertSupplementWeblink = (
525
529
  const supplement = schema.nodes.supplement.createAndFill(
526
530
  {
527
531
  id: generateNodeID(schema.nodes.supplement),
528
- href: url
532
+ href: url,
529
533
  },
530
534
  createAndFillCaption()
531
535
  ) as SupplementNode
@@ -554,7 +558,7 @@ export const updateSupplementWeblink = (
554
558
  ...node.attrs,
555
559
  href: url,
556
560
  title: title,
557
- })
561
+ })
558
562
  view.dispatch(tr)
559
563
  return true
560
564
  }
@@ -782,21 +786,62 @@ export const insertInlineCitation = (
782
786
  return true
783
787
  }
784
788
 
789
+ export const canInsertCrossReference = (
790
+ state: ManuscriptEditorState
791
+ ): boolean => {
792
+ if (!canInsert(schema.nodes.cross_reference)(state)) {
793
+ return false
794
+ }
795
+ const { from, to, empty, $from, $to } = state.selection
796
+ if (empty) {
797
+ return true
798
+ }
799
+ if (!$from.sameParent($to)) {
800
+ return false
801
+ }
802
+ let overlaps = false
803
+ state.doc.nodesBetween(from, to, (node) => {
804
+ if (node.isAtom && !node.isText) {
805
+ overlaps = true
806
+ return false
807
+ }
808
+ return !overlaps
809
+ })
810
+ return !overlaps
811
+ }
812
+
785
813
  export const insertCrossReference = (
786
814
  state: ManuscriptEditorState,
787
815
  dispatch?: Dispatch
788
816
  ) => {
817
+ if (!canInsertCrossReference(state)) {
818
+ return false
819
+ }
820
+
821
+ const text = selectedText()
822
+
789
823
  const node = state.schema.nodes.cross_reference.create({
824
+ id: generateNodeID(schema.nodes.cross_reference),
790
825
  rids: [],
826
+ label: text,
791
827
  })
792
828
 
793
- const pos = state.selection.to
829
+ const { tr } = state
830
+ let pos: number
831
+ const isWrap = !state.selection.empty
794
832
 
795
- const tr = state.tr.insert(pos, node)
833
+ if (isWrap) {
834
+ pos = state.selection.from
835
+ tr.replaceSelectionWith(node)
836
+ } else {
837
+ pos = state.selection.to
838
+ tr.insert(pos, node)
839
+ }
796
840
 
797
841
  if (dispatch) {
798
842
  const selection = NodeSelection.create(tr.doc, pos)
799
- dispatch(tr.setSelection(selection).scrollIntoView())
843
+ tr.setSelection(selection).scrollIntoView()
844
+ dispatch(isWrap ? skipTracking(tr) : tr)
800
845
  }
801
846
 
802
847
  return true
@@ -1524,10 +1569,7 @@ export const insertTransGraphicalAbstract =
1524
1569
  lang,
1525
1570
  category: category.id,
1526
1571
  },
1527
- [
1528
- schema.nodes.section_title.create(),
1529
- createAndFillFigureElement(state),
1530
- ]
1572
+ [schema.nodes.section_title.create(), createAndFillFigureElement(state)]
1531
1573
  ) as TransGraphicalAbstractNode
1532
1574
 
1533
1575
  const tr = state.tr.insert(pos, node)
@@ -17,8 +17,10 @@ import { Form, useFormikContext } from 'formik'
17
17
  import React, { MutableRefObject, PropsWithChildren, useEffect } from 'react'
18
18
  import styled from 'styled-components'
19
19
 
20
- export interface ChangeHandlingFormProps<Values>
21
- extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onChange'> {
20
+ export interface ChangeHandlingFormProps<Values> extends Omit<
21
+ React.FormHTMLAttributes<HTMLFormElement>,
22
+ 'onChange'
23
+ > {
22
24
  onChange: (values: Values) => void
23
25
  id?: string
24
26
  formRef?: MutableRefObject<HTMLFormElement | null>
@@ -37,14 +37,16 @@ const StyledIconTextButton = styled(IconTextButton)`
37
37
  const FormFooter = ({
38
38
  onCancel,
39
39
  primaryAction,
40
+ cancelLabel = 'Close',
40
41
  }: {
41
42
  onCancel: () => void
42
43
  primaryAction?: React.ReactNode
44
+ cancelLabel?: string
43
45
  }) => {
44
46
  return (
45
47
  <Footer>
46
48
  <StyledIconTextButton color="secondary" onClick={onCancel}>
47
- Close
49
+ {cancelLabel}
48
50
  </StyledIconTextButton>
49
51
  {primaryAction}
50
52
  </Footer>
@@ -86,14 +86,11 @@ export const KeyboardShortcutsModal: React.FC<KeyboardShortcutsModalProps> = ({
86
86
  </StyledModalSidebarTitle>
87
87
  </StyledModalSidebarHeader>
88
88
  <StyledSidebarContent>
89
- <ShortcutTabs
90
- selectedIndex={tabIndex}
91
- onChange={setTabIndex}
92
- >
89
+ <ShortcutTabs selectedIndex={tabIndex} onChange={setTabIndex}>
93
90
  <ModalTabsWrapper>
94
91
  <ModalTabs tabLabels={TAB_LABELS} />
95
92
  </ModalTabsWrapper>
96
-
93
+
97
94
  <InspectorTabPanels>
98
95
  {EDITOR_KEYBOARD_SHORTCUT_TABS.map((tab) => (
99
96
  <ShortcutTabPanel key={tab.id}>
@@ -139,7 +136,8 @@ const ShortcutTabs = styled(InspectorTabs)`
139
136
  `
140
137
 
141
138
  const ModalTabsWrapper = styled('div')`
142
- margin: 0 ${(props) => props.theme.grid.unit * 8}px ${(props) => props.theme.grid.unit * 3}px;
139
+ margin: 0 ${(props) => props.theme.grid.unit * 8}px
140
+ ${(props) => props.theme.grid.unit * 3}px;
143
141
  `
144
142
 
145
143
  const ShortcutTabPanel = styled(InspectorTabPanel).attrs({
@@ -198,7 +196,8 @@ const Section = styled.section`
198
196
  `
199
197
 
200
198
  const SectionTitle = styled.h3`
201
- margin: 0 ${(props) => props.theme.grid.unit * 8}px ${(props) => props.theme.grid.unit * 2}px;
199
+ margin: 0 ${(props) => props.theme.grid.unit * 8}px
200
+ ${(props) => props.theme.grid.unit * 2}px;
202
201
  font-size: ${(props) => props.theme.font.size.large};
203
202
  font-weight: ${(props) => props.theme.font.weight.normal};
204
203
  line-height: ${(props) => props.theme.font.lineHeight.large};
@@ -36,7 +36,6 @@ import { arrayReducer, attrsReducer } from '../../lib/array-reducer'
36
36
  import { cleanItemValues } from '../../lib/utils'
37
37
  import { BibliographyItemSource } from './BibliographyItemSource'
38
38
  import { CitedItem, CitedItems } from './CitationViewer'
39
- import { ImportBibliographyModal } from './ImportBibliographyModal'
40
39
  import { ReferenceLine } from './ReferenceLine'
41
40
  import { ReferenceSearch } from './ReferenceSearch'
42
41
  import { ReferencesModal } from './ReferencesModal'
@@ -92,7 +91,7 @@ export interface CitationEditorProps {
92
91
  sources: BibliographyItemSource[]
93
92
  onCite: (items: BibliographyItemAttrs[]) => void
94
93
  onUncite: (id: string) => void
95
- onSave: (item: BibliographyItemAttrs) => void
94
+ onSave: (item: BibliographyItemAttrs[]) => void
96
95
  onDelete: (item: BibliographyItemAttrs) => void
97
96
  onCancel: () => void
98
97
  canEdit: boolean
@@ -118,7 +117,7 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
118
117
  const [rids, dispatchRids] = useReducer(ridsReducer, $rids)
119
118
  const handleSave = (item: BibliographyItemAttrs) => {
120
119
  const cleanedItem = cleanItemValues(item)
121
- onSave(cleanedItem)
120
+ onSave([cleanedItem])
122
121
  dispatchItems({
123
122
  type: 'update',
124
123
  items: [cleanedItem],
@@ -163,7 +162,6 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
163
162
  })
164
163
 
165
164
  const [searching, setSearching] = useState(false)
166
- const [importing, setImporting] = useState(false)
167
165
 
168
166
  const handleAdd = () => {
169
167
  setSearching(false)
@@ -178,16 +176,19 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
178
176
  setEditingForm({ show: true, item: item })
179
177
  }
180
178
 
181
- const handleImport = () => {
182
- setSearching(false)
183
- setImporting(true)
184
- }
185
- const handleSaveImport = (data: BibliographyItemAttrs[]) => {
186
- data.forEach((item) => {
187
- const newItem = { ...item }
188
- newItem.id = generateNodeID(schema.nodes.bibliography_item)
189
- handleSave(newItem)
190
- handleCite([newItem])
179
+ const handleImport = (data: BibliographyItemAttrs[]) => {
180
+ const newItems = data.map((item) =>
181
+ cleanItemValues({
182
+ ...item,
183
+ id: generateNodeID(schema.nodes.bibliography_item),
184
+ })
185
+ )
186
+
187
+ onSave(newItems)
188
+
189
+ dispatchItems({
190
+ type: 'set',
191
+ state: [...items, ...newItems],
191
192
  })
192
193
  }
193
194
 
@@ -205,15 +206,7 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
205
206
  item={editingForm.item}
206
207
  onSave={handleSave}
207
208
  onDelete={handleDelete}
208
- />
209
- )
210
- }
211
-
212
- if (importing) {
213
- return (
214
- <ImportBibliographyModal
215
- onCancel={() => setImporting(false)}
216
- onSave={handleSaveImport}
209
+ handleImport={handleImport}
217
210
  />
218
211
  )
219
212
  }
@@ -223,7 +216,6 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
223
216
  sources={sources}
224
217
  items={items}
225
218
  onAdd={handleAdd}
226
- onImport={handleImport}
227
219
  onCite={(items) => {
228
220
  setSearching(false)
229
221
  handleCite(items)
@@ -239,7 +231,6 @@ export const CitationEditor: React.FC<CitationEditorProps> = ({
239
231
  sources={sources}
240
232
  items={items}
241
233
  onAdd={handleAdd}
242
- onImport={handleImport}
243
234
  onCite={handleCite}
244
235
  onCancel={onCancel}
245
236
  />
@@ -0,0 +1,119 @@
1
+ /*!
2
+ * © 2026 Atypon Systems LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { ModalTitle, Tooltip } from '@manuscripts/style-guide'
17
+ import { BibliographyItemAttrs } from '@manuscripts/transform'
18
+ import React from 'react'
19
+ import styled from 'styled-components'
20
+
21
+ import { ImportBibliographyForm } from './ImportBibliographyForm'
22
+
23
+ const exampleBibtex = `@book{abramowitz+stegun,
24
+ author = "Milton {Abramowitz} and Irene A. {Stegun}",
25
+ title = "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
26
+ publisher = "Dover",
27
+ year = 1964,
28
+ address = "New York City",
29
+ edition = "ninth Dover printing, tenth GPO printing"
30
+ }`
31
+
32
+ const examplePubmed = `Example Identifiers:
33
+ pmid:17170128
34
+ PMC1852221`
35
+
36
+ const exampleRis = `TY - JOUR
37
+ AU - Shannon, Claude E.
38
+ PY - 1948
39
+ DA - July
40
+ TI - A Mathematical Theory of Communication
41
+ T2 - Bell System Technical Journal
42
+ SP - 379
43
+ EP - 423
44
+ VL - 27
45
+ ER - `
46
+
47
+ const exampleEnw = `%0 Journal Article
48
+ %D 2018
49
+ %@ 0903-4641
50
+ %A Abbassi-Daloii, Tooba
51
+ %A Yousefi, Soheil
52
+ %A Sekhavati, Mohammad Hadi
53
+ %A Tahmoorespur, Mojtaba
54
+ %J APMIS
55
+ %N 1
56
+ %P 65-75
57
+ %T Impact of heat shock protein 60KD in combination with outer membrane proteins on immune response against Brucella melitensis
58
+ %R https://doi.org/10.1111/apm.12778
59
+ %U https://onlinelibrary.wiley.com/doi/abs/10.1111/apm.12778
60
+ %V 126
61
+ %X Lorem ipsum dolor sit amet`
62
+
63
+ const exampleDoi = `Example DOI Identifiers:
64
+ 10.1080/15588742.2015.1017684
65
+ http://dx.doi.org/10.1080/15588742.2015.1017684`
66
+
67
+ const supportedFormats = [
68
+ { label: 'BibTex', example: exampleBibtex },
69
+ { label: 'PubMed', example: examplePubmed },
70
+ { label: 'RIS', example: exampleRis },
71
+ { label: 'ENW', example: exampleEnw },
72
+ { label: 'DOI', example: exampleDoi },
73
+ ] as const
74
+
75
+ export interface ImportBibliographyProps {
76
+ onCancel: () => void
77
+ onContinue: (data: BibliographyItemAttrs[]) => void
78
+ }
79
+
80
+ export const ImportBibliography: React.FC<ImportBibliographyProps> = ({
81
+ onCancel,
82
+ onContinue,
83
+ }) => (
84
+ <>
85
+ <ModalTitle>Import Bibliography</ModalTitle>
86
+ <p>
87
+ {supportedFormats.map(({ label, example }, index) => (
88
+ <React.Fragment key={label}>
89
+ {index > 0 &&
90
+ (index === supportedFormats.length - 1 ? ' and ' : ', ')}
91
+ <SpanWithExample
92
+ data-tooltip-id="import-example-tooltip"
93
+ data-tooltip-content={example}
94
+ >
95
+ {label}
96
+ </SpanWithExample>
97
+ </React.Fragment>
98
+ ))}{' '}
99
+ formats are supported
100
+ </p>
101
+ <ImportBibliographyForm onCancel={onCancel} onSave={onContinue} />
102
+ <Example
103
+ id="import-example-tooltip"
104
+ place="bottom"
105
+ render={(s) => <pre>{s.content}</pre>}
106
+ />
107
+ </>
108
+ )
109
+
110
+ const SpanWithExample = styled.span`
111
+ text-decoration: underline dotted;
112
+ text-underline-offset: 4px;
113
+ `
114
+
115
+ const Example = styled(Tooltip)`
116
+ text-align: left !important;
117
+ max-width: 480px !important;
118
+ overflow: hidden !important;
119
+ `
@@ -182,7 +182,7 @@ export const ImportBibliographyForm = ({
182
182
  !formik.dirty || formik.isSubmitting || !formik.values.data.length
183
183
  }
184
184
  >
185
- Save
185
+ Import References
186
186
  </PrimaryButton>
187
187
  </FormActionsBar>
188
188
  </form>
@@ -18,142 +18,66 @@ import {
18
18
  ModalCardBody,
19
19
  ModalContainer,
20
20
  ModalHeader,
21
- ModalTitle,
22
21
  StyledModal,
23
- Tooltip,
24
22
  } from '@manuscripts/style-guide'
25
23
  import { BibliographyItemAttrs } from '@manuscripts/transform'
26
24
  import React, { useState } from 'react'
27
- import styled from 'styled-components'
28
25
 
29
- import { ImportBibliographyForm } from './ImportBibliographyForm'
26
+ import { ImportBibliography } from './ImportBibliography'
27
+ import { ImportReferencesConfirmation } from './ImportReferencesConfirmation'
28
+
30
29
  export interface ImportBibliographyModalProps {
31
30
  onCancel: () => void
32
31
  onSave: (data: BibliographyItemAttrs[]) => void
33
32
  }
34
33
 
35
- const exampleBibtex = `@book{abramowitz+stegun,
36
- author = "Milton {Abramowitz} and Irene A. {Stegun}",
37
- title = "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
38
- publisher = "Dover",
39
- year = 1964,
40
- address = "New York City",
41
- edition = "ninth Dover printing, tenth GPO printing"
42
- }`
43
-
44
- const examplePubmed = `Example Identifiers:
45
- pmid:17170128
46
- PMC1852221`
47
-
48
- const exampleRis = `TY - JOUR
49
- AU - Shannon, Claude E.
50
- PY - 1948
51
- DA - July
52
- TI - A Mathematical Theory of Communication
53
- T2 - Bell System Technical Journal
54
- SP - 379
55
- EP - 423
56
- VL - 27
57
- ER - `
58
-
59
- const exampleEnw = `%0 Journal Article
60
- %D 2018
61
- %@ 0903-4641
62
- %A Abbassi-Daloii, Tooba
63
- %A Yousefi, Soheil
64
- %A Sekhavati, Mohammad Hadi
65
- %A Tahmoorespur, Mojtaba
66
- %J APMIS
67
- %N 1
68
- %P 65-75
69
- %T Impact of heat shock protein 60KD in combination with outer membrane proteins on immune response against Brucella melitensis
70
- %R https://doi.org/10.1111/apm.12778
71
- %U https://onlinelibrary.wiley.com/doi/abs/10.1111/apm.12778
72
- %V 126
73
- %X Lorem ipsum dolor sit amet`
74
-
75
- const exampleDoi = `Example DOI Identifiers:
76
- 10.1080/15588742.2015.1017684
77
- http://dx.doi.org/10.1080/15588742.2015.1017684`
78
-
79
34
  export const ImportBibliographyModal: React.FC<
80
35
  ImportBibliographyModalProps
81
36
  > = ({ onCancel, onSave }) => {
82
37
  const [isOpen, setOpen] = useState(true)
38
+ const [pendingItems, setPendingItems] = useState<
39
+ BibliographyItemAttrs[] | null
40
+ >(null)
83
41
 
84
- const handleCancel = () => {
85
- handleClose()
86
- }
42
+ const isConfirming = pendingItems !== null
87
43
  const handleClose = () => setOpen(false)
44
+ const handleBack = () => setPendingItems(null)
88
45
 
89
- const handleSave = (data: BibliographyItemAttrs[]) => {
90
- onSave(data)
46
+ const handleConfirm = (items: BibliographyItemAttrs[]) => {
47
+ onSave(items)
91
48
  handleClose()
92
49
  }
93
50
 
94
51
  return (
95
52
  <StyledModal isOpen={isOpen} onRequestClose={onCancel}>
96
- <ModalContainer data-cy="import-bibliography-modal">
53
+ <ModalContainer
54
+ data-cy={
55
+ isConfirming
56
+ ? 'import-confirmation-modal'
57
+ : 'import-bibliography-modal'
58
+ }
59
+ >
97
60
  <ModalHeader>
98
- <CloseButton onClick={onCancel} data-cy="modal-close-button" />
99
- </ModalHeader>
100
- <ModalCardBody $width={640}>
101
- <ModalTitle>Import Bibliography</ModalTitle>
102
- <p>
103
- <SpanWithExample
104
- data-tooltip-id="import-example-tooltip"
105
- data-tooltip-content={exampleBibtex}
106
- >
107
- BibTex
108
- </SpanWithExample>
109
- ,{' '}
110
- <SpanWithExample
111
- data-tooltip-id="import-example-tooltip"
112
- data-tooltip-content={examplePubmed}
113
- >
114
- PubMed
115
- </SpanWithExample>
116
- ,{' '}
117
- <SpanWithExample
118
- data-tooltip-id="import-example-tooltip"
119
- data-tooltip-content={exampleRis}
120
- >
121
- RIS
122
- </SpanWithExample>
123
- ,{' '}
124
- <SpanWithExample
125
- data-tooltip-id="import-example-tooltip"
126
- data-tooltip-content={exampleEnw}
127
- >
128
- ENW
129
- </SpanWithExample>{' '}
130
- and{' '}
131
- <SpanWithExample
132
- data-tooltip-id="import-example-tooltip"
133
- data-tooltip-content={exampleDoi}
134
- >
135
- DOI
136
- </SpanWithExample>{' '}
137
- formats are supported
138
- </p>
139
- <ImportBibliographyForm onCancel={handleCancel} onSave={handleSave} />
140
- <Example
141
- id="import-example-tooltip"
142
- place="bottom"
143
- render={(s) => <pre>{s.content}</pre>}
61
+ <CloseButton
62
+ onClick={isConfirming ? handleBack : onCancel}
63
+ data-cy="modal-close-button"
144
64
  />
65
+ </ModalHeader>
66
+ <ModalCardBody $width={724}>
67
+ {pendingItems ? (
68
+ <ImportReferencesConfirmation
69
+ items={pendingItems}
70
+ onCancel={handleBack}
71
+ onConfirm={handleConfirm}
72
+ />
73
+ ) : (
74
+ <ImportBibliography
75
+ onCancel={onCancel}
76
+ onContinue={setPendingItems}
77
+ />
78
+ )}
145
79
  </ModalCardBody>
146
80
  </ModalContainer>
147
81
  </StyledModal>
148
82
  )
149
83
  }
150
-
151
- const SpanWithExample = styled.span`
152
- text-decoration: underline dotted;
153
- text-underline-offset: 4px;
154
- `
155
- const Example = styled(Tooltip)`
156
- text-align: left !important;
157
- max-width: 480px !important;
158
- overflow: hidden !important;
159
- `