@manuscripts/body-editor 3.12.66 → 3.13.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/components/toolbar/type-selector/styles.js +2 -1
- package/dist/cjs/versions.js +1 -1
- package/dist/es/components/toolbar/type-selector/styles.js +2 -1
- package/dist/es/versions.js +1 -1
- package/dist/types/components/toolbar/type-selector/styles.d.ts +2 -2
- package/dist/types/lib/footnotes.d.ts +4 -2
- package/dist/types/lib/utils.d.ts +5 -4
- package/dist/types/versions.d.ts +1 -1
- package/package.json +37 -36
- package/{dist/es/lib/statistics.js → src/__mocks__/styleMock.ts} +2 -14
- package/src/assets.ts +20 -0
- package/src/classes/collabProvider.ts +38 -0
- package/src/clipboard.ts +54 -0
- package/src/commands.ts +2109 -0
- package/src/components/ChangeHandlingForm.tsx +54 -0
- package/src/components/LanguageDropdown/index.tsx +343 -0
- package/src/components/affiliations/AffiliationForm.tsx +238 -0
- package/src/components/affiliations/AffiliationItem.tsx +151 -0
- package/src/components/affiliations/AffiliationList.tsx +71 -0
- package/src/components/affiliations/AffiliationsModal.tsx +676 -0
- package/src/components/affiliations/AffiliationsPanel.tsx +76 -0
- package/src/components/affiliations/CreateAffiliationModal.tsx +135 -0
- package/src/components/authors/AuthorDetailsForm.tsx +438 -0
- package/src/components/authors/AuthorList.tsx +81 -0
- package/src/components/authors/AuthorsModal.tsx +642 -0
- package/src/components/authors/AuthorsPanel.tsx +69 -0
- package/src/components/authors/CreateAuthorModal.tsx +172 -0
- package/src/components/authors/CreditDrawer.tsx +71 -0
- package/src/components/authors/DraggableAuthor.tsx +228 -0
- package/src/components/authors/useManageAffiliations.tsx +77 -0
- package/src/components/authors/useManageCredit.tsx +63 -0
- package/src/components/authors-affiliations/AuthorsAndAffiliationsModals.tsx +170 -0
- package/src/components/authors-affiliations/GenericPanel.tsx +164 -0
- package/src/components/authors-affiliations/ModalTabs.tsx +100 -0
- package/src/components/awards/AwardForm.tsx +338 -0
- package/src/components/awards/AwardModal.tsx +120 -0
- package/src/components/awards/DeleteAwardDiaolog.tsx +52 -0
- package/src/components/dialog/ConfirmationDialog.tsx +131 -0
- package/src/components/form/CreateModalStyles.tsx +37 -0
- package/src/components/form/FormFooter.tsx +54 -0
- package/src/components/form/FormPlaceholder.tsx +71 -0
- package/src/components/form/ModalFormActions.tsx +88 -0
- package/src/components/form/UnsavedLabel.tsx +49 -0
- package/src/components/hooks/use-debounce.ts +56 -0
- package/src/components/hooks/useAffiliationShowsErrorIndicator.ts +51 -0
- package/src/components/hooks/useAuthorShowsErrorIndicator.ts +73 -0
- package/src/components/keyboard-shortcuts-modal/FormattedShortcut.tsx +56 -0
- package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +283 -0
- package/src/components/keyboard-shortcuts-modal/keyboard-shortcuts.ts +304 -0
- package/src/components/keywords/AddKeywordInline.tsx +284 -0
- package/src/components/keywords/DeleteKeywordDialog.tsx +52 -0
- package/src/components/modal-drawer/GenericDrawer.tsx +65 -0
- package/src/components/modal-drawer/GenericDrawerGroup.tsx +125 -0
- package/src/components/outline/DraggableTree.tsx +438 -0
- package/src/components/outline/ManuscriptOutline.tsx +127 -0
- package/src/components/outline/Outline.tsx +141 -0
- package/src/components/references/BibliographyItemSource.ts +80 -0
- package/src/components/references/CitationEditor.tsx +301 -0
- package/src/components/references/CitationViewer.tsx +62 -0
- package/src/components/references/ImportBibliographyForm.tsx +232 -0
- package/src/components/references/ImportBibliographyModal.tsx +159 -0
- package/src/components/references/ReferenceForm/PersonDropDown.tsx +93 -0
- package/src/components/references/ReferenceForm/ReferenceForm.tsx +701 -0
- package/src/components/references/ReferenceForm/config.ts +133 -0
- package/src/components/references/ReferenceForm/styled-components.ts +156 -0
- package/src/components/references/ReferenceLine.tsx +43 -0
- package/src/components/references/ReferenceSearch.tsx +163 -0
- package/src/components/references/ReferenceSearchResults.tsx +113 -0
- package/src/components/references/ReferenceSearchResultsPlaceholder.tsx +71 -0
- package/src/components/references/ReferenceSearchSection.tsx +124 -0
- package/src/components/references/ReferencesEditor.tsx +61 -0
- package/src/components/references/ReferencesModal.tsx +352 -0
- package/src/components/references/SearchInput.tsx +98 -0
- package/src/components/toolbar/InsertEmbedDialog.tsx +222 -0
- package/src/components/toolbar/InsertTableDialog.tsx +208 -0
- package/src/components/toolbar/ListMenuItem.tsx +203 -0
- package/src/components/toolbar/helpers.ts +547 -0
- package/src/components/toolbar/type-selector/OptionComponent.tsx +89 -0
- package/src/components/toolbar/type-selector/TypeSelector.tsx +157 -0
- package/src/components/toolbar/type-selector/styles.ts +79 -0
- package/src/components/views/CrossReferenceItems.tsx +199 -0
- package/src/components/views/DeleteEmbedDialog.tsx +83 -0
- package/src/components/views/DeleteFootnoteDialog.tsx +54 -0
- package/src/components/views/FigureDropdown.tsx +423 -0
- package/src/components/views/FootnotesSelector.tsx +255 -0
- package/src/components/views/InsertSpecialCharacter.tsx +245 -0
- package/src/components/views/LinkForm.tsx +220 -0
- package/src/components/views/TableCellContextMenu.tsx +241 -0
- package/src/configs/ManuscriptsEditor.ts +140 -0
- package/src/configs/editor-plugins.ts +119 -0
- package/src/configs/editor-views.ts +139 -0
- package/src/icons.ts +62 -0
- package/src/index.ts +65 -0
- package/src/keys/highlight.ts +65 -0
- package/src/keys/index.ts +33 -0
- package/src/keys/keyword.ts +69 -0
- package/src/keys/list.ts +156 -0
- package/src/keys/misc.ts +112 -0
- package/src/keys/title.ts +221 -0
- package/src/lib/__tests__/__fixtures__/doc.json +388 -0
- package/src/lib/__tests__/__snapshots__/paste.test.ts.snap +24 -0
- package/src/lib/__tests__/authors.test.ts +202 -0
- package/src/lib/__tests__/helpers.test.ts +46 -0
- package/src/lib/__tests__/paste.test.ts +57 -0
- package/src/lib/__tests__/plugins.test.ts +176 -0
- package/src/lib/__tests__/url.test.ts +31 -0
- package/src/lib/array-reducer.ts +68 -0
- package/src/lib/authors-and-affiliations.ts +81 -0
- package/src/lib/authors.ts +67 -0
- package/src/lib/capabilities.ts +55 -0
- package/src/lib/codemirror.ts +37 -0
- package/src/lib/comments.ts +123 -0
- package/src/lib/context-menu.ts +745 -0
- package/src/lib/copy.ts +30 -0
- package/src/lib/crossref.ts +90 -0
- package/src/lib/dnd.ts +29 -0
- package/src/lib/doc.ts +167 -0
- package/src/lib/dompurify.ts +28 -0
- package/src/lib/files.ts +180 -0
- package/src/lib/footnotes.ts +83 -0
- package/src/lib/get-media-type.ts +105 -0
- package/src/lib/helpers.ts +199 -0
- package/src/lib/hierarchy.ts +117 -0
- package/src/lib/languages.ts +37 -0
- package/src/lib/lists.ts +56 -0
- package/src/lib/math.ts +111 -0
- package/src/lib/media.ts +334 -0
- package/src/lib/navigation-utils.ts +235 -0
- package/src/lib/normalize.ts +70 -0
- package/src/lib/paste.ts +304 -0
- package/src/lib/placeholder.ts +32 -0
- package/src/lib/platform.ts +18 -0
- package/src/lib/plugins.ts +22 -0
- package/src/lib/popper.ts +180 -0
- package/src/lib/position-menu.ts +184 -0
- package/src/lib/references.ts +94 -0
- package/src/lib/template.ts +29 -0
- package/src/lib/track-changes-utils.ts +34 -0
- package/{dist/types/lib/statistics.d.ts → src/lib/url.ts} +11 -8
- package/src/lib/use-do-with-debounce.ts +39 -0
- package/src/lib/utils.ts +323 -0
- package/src/lib/view.ts +100 -0
- package/src/menus.tsx +684 -0
- package/src/node-type-icons.tsx +83 -0
- package/src/plugins/__tests__/__fixtures__/deleted-footnote.json +140 -0
- package/src/plugins/__tests__/__fixtures__/inserted-footnote.json +153 -0
- package/src/plugins/__tests__/footnotes.test.ts +67 -0
- package/src/plugins/accessibility_element.ts +219 -0
- package/src/plugins/add-subtitle.ts +102 -0
- package/src/plugins/affiliations.ts +136 -0
- package/src/plugins/alt-titles.ts +219 -0
- package/src/plugins/bibliography.ts +235 -0
- package/src/plugins/comments.ts +328 -0
- package/src/plugins/cross-references.ts +70 -0
- package/src/plugins/detect-inconsistency/detect-inconsistency-utils.ts +102 -0
- package/src/plugins/detect-inconsistency/index.ts +55 -0
- package/src/plugins/detect-inconsistency/validators.ts +283 -0
- package/src/plugins/doi.ts +66 -0
- package/src/plugins/editor-props.ts +39 -0
- package/src/plugins/elements.ts +60 -0
- package/src/plugins/footnotes.ts +298 -0
- package/src/plugins/link.ts +53 -0
- package/src/plugins/lock-body.ts +136 -0
- package/src/plugins/move-node.ts +55 -0
- package/src/plugins/objects.ts +125 -0
- package/src/plugins/paragraphs.ts +90 -0
- package/src/plugins/persist.ts +64 -0
- package/src/plugins/persistent-cursor.ts +66 -0
- package/src/plugins/placeholder.ts +219 -0
- package/src/plugins/prevent-empty.ts +50 -0
- package/src/plugins/search-replace/index.ts +157 -0
- package/src/plugins/search-replace/lib.ts +95 -0
- package/src/plugins/section_category.ts +212 -0
- package/src/plugins/section_title/autocompletion.ts +87 -0
- package/src/plugins/section_title/index.ts +105 -0
- package/src/plugins/selected-suggestion.ts +243 -0
- package/src/plugins/tables-cursor-fix.ts +143 -0
- package/src/plugins/translations.ts +263 -0
- package/src/rules.ts +60 -0
- package/src/selection.ts +112 -0
- package/src/testing/default-capabilities.ts +48 -0
- package/src/testing/default-editor-data.ts +73 -0
- package/src/testing/empty-editor-doc.json +62 -0
- package/src/testing/polyfill-dom.ts +43 -0
- package/src/testing/section-categories.json +161 -0
- package/src/testing/setup-editor.ts +55 -0
- package/src/tests.ts +42 -0
- package/src/toolbar.tsx +259 -0
- package/src/types/@citation-js/core.d.ts +16 -0
- package/src/types/@citation-js/index.d.ts +16 -0
- package/src/types/@citation-js/plugin-bibtex.d.ts +16 -0
- package/src/types/@citation-js/plugin-csl.d.ts +16 -0
- package/src/types/@citation-js/plugin-doi.d.ts +16 -0
- package/src/types/@citation-js/plugin-enw.d.ts +16 -0
- package/src/types/@citation-js/plugin-pubmed.d.ts +16 -0
- package/src/types/@citation-js/plugin-ris.d.ts +16 -0
- package/src/types/citeproc.d.ts +124 -0
- package/src/types/css.d.ts +16 -0
- package/src/types/json.d.ts +17 -0
- package/src/types/prosemirror-dev-tools.d.ts +16 -0
- package/src/types/prosemirror-dropcursor.d.ts +16 -0
- package/src/types/styled-components.d.ts +23 -0
- package/src/types.ts +49 -0
- package/src/useEditor.ts +244 -0
- package/src/versions.ts +3 -0
- package/src/views/ReactSubView.tsx +145 -0
- package/src/views/abstracts.ts +46 -0
- package/src/views/accessibility_element.ts +86 -0
- package/src/views/affiliations.ts +254 -0
- package/src/views/alt_title.ts +85 -0
- package/src/views/alt_titles_section.ts +97 -0
- package/src/views/attachment.ts +160 -0
- package/src/views/attachments.ts +72 -0
- package/src/views/author_notes.ts +96 -0
- package/src/views/award.ts +194 -0
- package/src/views/awards.ts +59 -0
- package/src/views/base_node_view.ts +85 -0
- package/src/views/bibliography_element.ts +313 -0
- package/src/views/block_view.ts +100 -0
- package/src/views/blockquote_element.ts +26 -0
- package/src/views/blockquote_element_editable.ts +24 -0
- package/src/views/box_element.ts +33 -0
- package/src/views/caption.ts +37 -0
- package/src/views/caption_title.ts +33 -0
- package/src/views/citation.ts +67 -0
- package/src/views/citation_editable.ts +312 -0
- package/src/views/contributors.ts +341 -0
- package/src/views/creators.ts +82 -0
- package/src/views/cross_reference.ts +74 -0
- package/src/views/cross_reference_editable.ts +113 -0
- package/src/views/editable_block.ts +141 -0
- package/src/views/embed.ts +345 -0
- package/src/views/empty.ts +26 -0
- package/src/views/equation.ts +47 -0
- package/src/views/equation_editable.ts +84 -0
- package/src/views/equation_element.ts +29 -0
- package/src/views/equation_element_editable.ts +21 -0
- package/src/views/figure.ts +84 -0
- package/src/views/figure_editable.ts +361 -0
- package/src/views/figure_element.ts +197 -0
- package/src/views/figure_element_editable.ts +21 -0
- package/src/views/footnote.ts +236 -0
- package/src/views/footnotes_element.ts +54 -0
- package/src/views/general_table_footnote.ts +140 -0
- package/src/views/hero_image.ts +76 -0
- package/src/views/hero_image_editable.ts +21 -0
- package/src/views/image_element.ts +373 -0
- package/src/views/image_element_editable.ts +21 -0
- package/src/views/inline_equation.ts +47 -0
- package/src/views/inline_equation_editable.ts +70 -0
- package/src/views/inline_footnote.ts +264 -0
- package/src/views/inline_footnote_editable.ts +20 -0
- package/src/views/keyword.ts +127 -0
- package/src/views/keyword_group.ts +109 -0
- package/src/views/link.ts +27 -0
- package/src/views/link_editable.ts +169 -0
- package/src/views/list.ts +46 -0
- package/src/views/list_item.ts +26 -0
- package/src/views/paragraph.ts +26 -0
- package/src/views/paragraph_editable.ts +21 -0
- package/src/views/placeholder.ts +35 -0
- package/src/views/placeholder_element.ts +38 -0
- package/src/views/placeholder_element_editable.ts +21 -0
- package/src/views/pullquote_element.ts +106 -0
- package/src/views/pullquote_element_editable.ts +24 -0
- package/src/views/quote_image_editable.ts +84 -0
- package/src/views/section.ts +64 -0
- package/src/views/section_label.ts +20 -0
- package/src/views/section_title.ts +87 -0
- package/src/views/section_title_editable.ts +21 -0
- package/src/views/subtitle.ts +42 -0
- package/src/views/subtitle_editable.ts +20 -0
- package/src/views/subtitles.ts +34 -0
- package/src/views/subtitles_editable.ts +21 -0
- package/src/views/supplement.ts +236 -0
- package/src/views/supplement_editable.ts +20 -0
- package/src/views/supplements.ts +65 -0
- package/src/views/supplements_editable.ts +21 -0
- package/src/views/table_cell.ts +150 -0
- package/src/views/table_element.ts +33 -0
- package/src/views/table_element_editable.ts +21 -0
- package/src/views/table_element_footer.ts +41 -0
- package/src/views/title.ts +46 -0
- package/src/views/title_editable.ts +20 -0
- package/src/views/trans_graphical_abstract.ts +55 -0
- package/src/views/trans_graphical_abstract_editable.ts +21 -0
- package/src/views/translated_abstract.ts +53 -0
- package/src/views/translated_abstract_editable.ts +21 -0
- package/dist/cjs/lib/statistics.js +0 -38
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2025 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 {
|
|
17
|
+
CloseButton,
|
|
18
|
+
ModalContainer,
|
|
19
|
+
ModalHeader,
|
|
20
|
+
StyledModal,
|
|
21
|
+
} from '@manuscripts/style-guide'
|
|
22
|
+
import { generateNodeID, schema } from '@manuscripts/transform'
|
|
23
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
|
24
|
+
|
|
25
|
+
import { AffiliationAttrs, ContributorAttrs } from '../../lib/authors'
|
|
26
|
+
import { normalizeAuthor } from '../../lib/normalize'
|
|
27
|
+
import {
|
|
28
|
+
MODAL_ON_CLOSE_NOTIFY_DELAY_MS,
|
|
29
|
+
FormTitle,
|
|
30
|
+
StyledModalBody,
|
|
31
|
+
StyledScrollableModalContent,
|
|
32
|
+
} from '../form/CreateModalStyles'
|
|
33
|
+
import FormFooter from '../form/FormFooter'
|
|
34
|
+
import { ModalFormSaveButton } from '../form/ModalFormActions'
|
|
35
|
+
import { AuthorDetailsForm, FormActions } from './AuthorDetailsForm'
|
|
36
|
+
import { useManageAffiliations } from './useManageAffiliations'
|
|
37
|
+
import { useManageCredit } from './useManageCredit'
|
|
38
|
+
|
|
39
|
+
export interface CreateAuthorModalProps {
|
|
40
|
+
authorsCount: number
|
|
41
|
+
affiliations: AffiliationAttrs[]
|
|
42
|
+
onSave: (author: ContributorAttrs) => void
|
|
43
|
+
onClose: () => void
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const CreateAuthorModal: React.FC<CreateAuthorModalProps> = ({
|
|
47
|
+
authorsCount,
|
|
48
|
+
affiliations: $affiliations,
|
|
49
|
+
onSave,
|
|
50
|
+
onClose,
|
|
51
|
+
}) => {
|
|
52
|
+
const [isOpen, setIsOpen] = useState(true)
|
|
53
|
+
const [isDisableSave, setDisableSave] = useState(true)
|
|
54
|
+
const [isEmailRequired, setEmailRequired] = useState(false)
|
|
55
|
+
const [hasError, setHasError] = useState(false)
|
|
56
|
+
const actionsRef = useRef<FormActions>(undefined)
|
|
57
|
+
const authorFormRef = useRef<HTMLFormElement>(null)
|
|
58
|
+
|
|
59
|
+
const selection = useMemo(
|
|
60
|
+
() => createEmptyAuthor(authorsCount),
|
|
61
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
62
|
+
[]
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
// Wait for the close animation to finish before calling onClose.
|
|
66
|
+
const prevIsOpenRef = useRef(true)
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (prevIsOpenRef.current && !isOpen) {
|
|
69
|
+
prevIsOpenRef.current = isOpen
|
|
70
|
+
const id = window.setTimeout(() => {
|
|
71
|
+
onClose()
|
|
72
|
+
}, MODAL_ON_CLOSE_NOTIFY_DELAY_MS)
|
|
73
|
+
return () => window.clearTimeout(id)
|
|
74
|
+
}
|
|
75
|
+
prevIsOpenRef.current = isOpen
|
|
76
|
+
}, [isOpen, onClose])
|
|
77
|
+
|
|
78
|
+
const { selectedAffiliations } = useManageAffiliations(
|
|
79
|
+
selection,
|
|
80
|
+
$affiliations
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
const { selectedCreditRoles } = useManageCredit(selection)
|
|
84
|
+
|
|
85
|
+
const handleSave = (values: ContributorAttrs) => {
|
|
86
|
+
onSave({ ...selection, ...values })
|
|
87
|
+
setIsOpen(false)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const handleChange = (values: ContributorAttrs) => {
|
|
91
|
+
const { given, family, email, isCorresponding } = values
|
|
92
|
+
const isNameFilled = given?.length || family?.length
|
|
93
|
+
|
|
94
|
+
if (isNameFilled) {
|
|
95
|
+
if (isCorresponding) {
|
|
96
|
+
setDisableSave(!email?.length)
|
|
97
|
+
} else {
|
|
98
|
+
setDisableSave(false)
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
setDisableSave(true)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setEmailRequired(!!isCorresponding)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<StyledModal
|
|
109
|
+
isOpen={isOpen}
|
|
110
|
+
onRequestClose={() => setIsOpen(false)}
|
|
111
|
+
shouldCloseOnOverlayClick={true}
|
|
112
|
+
>
|
|
113
|
+
<ModalContainer data-cy="create-author-modal">
|
|
114
|
+
<ModalHeader>
|
|
115
|
+
<CloseButton
|
|
116
|
+
onClick={() => setIsOpen(false)}
|
|
117
|
+
data-cy="modal-close-button"
|
|
118
|
+
/>
|
|
119
|
+
</ModalHeader>
|
|
120
|
+
<StyledModalBody>
|
|
121
|
+
<StyledScrollableModalContent>
|
|
122
|
+
<FormTitle>Create Author</FormTitle>
|
|
123
|
+
<AuthorDetailsForm
|
|
124
|
+
values={normalizeAuthor(selection)}
|
|
125
|
+
onChange={handleChange}
|
|
126
|
+
onSave={handleSave}
|
|
127
|
+
actionsRef={actionsRef}
|
|
128
|
+
isEmailRequired={isEmailRequired}
|
|
129
|
+
selectedAffiliations={selectedAffiliations.map((a) => a.id)}
|
|
130
|
+
authorFormRef={authorFormRef}
|
|
131
|
+
selectedCreditRoles={selectedCreditRoles}
|
|
132
|
+
newEntity={true}
|
|
133
|
+
onAuthorDetailsTabErrorChange={setHasError}
|
|
134
|
+
/>
|
|
135
|
+
</StyledScrollableModalContent>
|
|
136
|
+
</StyledModalBody>
|
|
137
|
+
<FormFooter
|
|
138
|
+
onCancel={() => setIsOpen(false)}
|
|
139
|
+
primaryAction={
|
|
140
|
+
<ModalFormSaveButton
|
|
141
|
+
form="author-details-form"
|
|
142
|
+
isDisableSave={isDisableSave || hasError}
|
|
143
|
+
label="New Author"
|
|
144
|
+
onSubmitForm={() => actionsRef.current?.submitForm?.()}
|
|
145
|
+
/>
|
|
146
|
+
}
|
|
147
|
+
/>
|
|
148
|
+
</ModalContainer>
|
|
149
|
+
</StyledModal>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function createEmptyAuthor(priority: number): ContributorAttrs {
|
|
154
|
+
return {
|
|
155
|
+
id: generateNodeID(schema.nodes.contributor),
|
|
156
|
+
role: '',
|
|
157
|
+
affiliationIDs: [],
|
|
158
|
+
degrees: [],
|
|
159
|
+
given: '',
|
|
160
|
+
family: '',
|
|
161
|
+
email: '',
|
|
162
|
+
suffix: '',
|
|
163
|
+
isCorresponding: false,
|
|
164
|
+
ORCID: '',
|
|
165
|
+
priority,
|
|
166
|
+
isJointContributor: false,
|
|
167
|
+
correspIDs: [],
|
|
168
|
+
footnoteIDs: [],
|
|
169
|
+
prefix: '',
|
|
170
|
+
creditRoles: [],
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2025 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 {
|
|
17
|
+
CheckboxField,
|
|
18
|
+
CheckboxLabel,
|
|
19
|
+
LabelText,
|
|
20
|
+
} from '@manuscripts/style-guide'
|
|
21
|
+
import React from 'react'
|
|
22
|
+
import styled from 'styled-components'
|
|
23
|
+
|
|
24
|
+
import { CheckboxContainer } from './AuthorDetailsForm'
|
|
25
|
+
|
|
26
|
+
export interface CreditContributionsCheckboxesProps {
|
|
27
|
+
items: { id: string; vocabTerm: string }[]
|
|
28
|
+
selectedItems: { id: string }[]
|
|
29
|
+
onSelect: (id: string) => void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const CreditContributionsCheckboxes: React.FC<
|
|
33
|
+
CreditContributionsCheckboxesProps
|
|
34
|
+
> = ({ items, selectedItems = [], onSelect }) => {
|
|
35
|
+
const selectedIds = selectedItems.map((a) => a.id)
|
|
36
|
+
return (
|
|
37
|
+
<TwoColumnContainer
|
|
38
|
+
data-cy="credit-taxnonomy"
|
|
39
|
+
role="group"
|
|
40
|
+
aria-label="Contributions (CRediT)"
|
|
41
|
+
>
|
|
42
|
+
{items.map((item) => (
|
|
43
|
+
<TwoColumnCheckbox key={item.id}>
|
|
44
|
+
<CheckboxLabel>
|
|
45
|
+
<CheckboxField
|
|
46
|
+
name={item.id}
|
|
47
|
+
checked={selectedIds.includes(item.id)}
|
|
48
|
+
onChange={() => {
|
|
49
|
+
onSelect(item.id)
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
<LabelText>{item.vocabTerm}</LabelText>
|
|
53
|
+
</CheckboxLabel>
|
|
54
|
+
</TwoColumnCheckbox>
|
|
55
|
+
))}
|
|
56
|
+
</TwoColumnContainer>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const TwoColumnContainer = styled.ul`
|
|
61
|
+
list-style: none;
|
|
62
|
+
padding: 0 ${(props) => props.theme.grid.unit * 4}px;
|
|
63
|
+
margin: 0;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-flow: row wrap;
|
|
66
|
+
position: relative;
|
|
67
|
+
`
|
|
68
|
+
|
|
69
|
+
const TwoColumnCheckbox = styled(CheckboxContainer)`
|
|
70
|
+
flex: 1 0 50%;
|
|
71
|
+
`
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2019 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
|
+
|
|
17
|
+
import {
|
|
18
|
+
Avatar,
|
|
19
|
+
CorrespondingAuthorIcon,
|
|
20
|
+
CrclTickAnimation,
|
|
21
|
+
DeleteIcon,
|
|
22
|
+
DraggableIcon,
|
|
23
|
+
withNavigableListItem,
|
|
24
|
+
} from '@manuscripts/style-guide'
|
|
25
|
+
import React, { useRef, useState } from 'react'
|
|
26
|
+
import { useDrag, useDrop } from 'react-dnd'
|
|
27
|
+
import styled from 'styled-components'
|
|
28
|
+
|
|
29
|
+
import { authorLabel, ContributorAttrs } from '../../lib/authors'
|
|
30
|
+
import { DropSide, getDropSide } from '../../lib/dnd'
|
|
31
|
+
import { DeleteButton } from '../references/ReferenceForm/styled-components'
|
|
32
|
+
|
|
33
|
+
const AuthorContainer = withNavigableListItem(styled.div`
|
|
34
|
+
padding: ${(props) => props.theme.grid.unit * 2}px 0
|
|
35
|
+
${(props) => props.theme.grid.unit * 2}px;
|
|
36
|
+
display: flex;
|
|
37
|
+
justify-content: space-between;
|
|
38
|
+
align-items: center;
|
|
39
|
+
transition: background-color 0.25s;
|
|
40
|
+
border: 1px solid transparent;
|
|
41
|
+
border-left: 0;
|
|
42
|
+
border-right: 0;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
&:hover,
|
|
45
|
+
&.active {
|
|
46
|
+
background: ${(props) => props.theme.colors.background.fifth};
|
|
47
|
+
border-color: ${(props) => props.theme.colors.border.primary};
|
|
48
|
+
}
|
|
49
|
+
&.dragging {
|
|
50
|
+
opacity: 1;
|
|
51
|
+
cursor: grabbing;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&.dragging * {
|
|
55
|
+
opacity: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&.drop-before {
|
|
59
|
+
cursor: grabbing;
|
|
60
|
+
border-top-color: ${(props) => props.theme.colors.brand.dark};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&.drop-after {
|
|
64
|
+
cursor: grabbing;
|
|
65
|
+
border-bottom-color: ${(props) => props.theme.colors.brand.dark};
|
|
66
|
+
}
|
|
67
|
+
`)
|
|
68
|
+
|
|
69
|
+
const AvatarContainer = styled.div`
|
|
70
|
+
display: inline-flex;
|
|
71
|
+
position: relative;
|
|
72
|
+
align-items: center;
|
|
73
|
+
`
|
|
74
|
+
|
|
75
|
+
const Box = styled.div`
|
|
76
|
+
margin-left: 14px;
|
|
77
|
+
`
|
|
78
|
+
|
|
79
|
+
const AuthorBadge = styled.div`
|
|
80
|
+
display: inline-flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: center;
|
|
83
|
+
position: relative;
|
|
84
|
+
`
|
|
85
|
+
|
|
86
|
+
const AuthorNotes = styled.div`
|
|
87
|
+
position: absolute;
|
|
88
|
+
top: 0;
|
|
89
|
+
right: 0;
|
|
90
|
+
|
|
91
|
+
& ${AuthorBadge}:not(:last-child) {
|
|
92
|
+
right: -20%;
|
|
93
|
+
}
|
|
94
|
+
`
|
|
95
|
+
|
|
96
|
+
const AuthorName = styled.div`
|
|
97
|
+
margin-left: 12px;
|
|
98
|
+
flex: 1;
|
|
99
|
+
`
|
|
100
|
+
|
|
101
|
+
const DragHandle = styled(DraggableIcon)`
|
|
102
|
+
cursor: move;
|
|
103
|
+
margin-left: -4px;
|
|
104
|
+
margin-right: -12px;
|
|
105
|
+
`
|
|
106
|
+
const RemoveButton = styled(DeleteButton)`
|
|
107
|
+
.icon_element {
|
|
108
|
+
fill: ${(props) => (props.disabled && '#c9c9c9') || '#6E6E6E'} !important;
|
|
109
|
+
}
|
|
110
|
+
`
|
|
111
|
+
const StyledCrclTickAnimation = styled(CrclTickAnimation)`
|
|
112
|
+
margin-left: 12px;
|
|
113
|
+
`
|
|
114
|
+
interface DragItem {
|
|
115
|
+
author: ContributorAttrs
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface DraggableAuthorProps {
|
|
119
|
+
author: ContributorAttrs
|
|
120
|
+
isSelected: boolean
|
|
121
|
+
onClick: () => void
|
|
122
|
+
onDelete: () => void
|
|
123
|
+
moveAuthor: (
|
|
124
|
+
from: ContributorAttrs,
|
|
125
|
+
to: ContributorAttrs,
|
|
126
|
+
shift: number
|
|
127
|
+
) => void
|
|
128
|
+
showSuccessIcon?: boolean
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const DraggableAuthor: React.FC<DraggableAuthorProps> = React.memo(
|
|
132
|
+
({ author, isSelected, onClick, onDelete, moveAuthor, showSuccessIcon }) => {
|
|
133
|
+
const [dropSide, setDropSide] = useState<DropSide>()
|
|
134
|
+
const ref = useRef<HTMLDivElement>(null)
|
|
135
|
+
const [{ isDragging }, dragRef, preview] = useDrag({
|
|
136
|
+
type: 'author',
|
|
137
|
+
item: {
|
|
138
|
+
author,
|
|
139
|
+
},
|
|
140
|
+
collect: (monitor) => {
|
|
141
|
+
return {
|
|
142
|
+
isDragging: monitor.isDragging(),
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
})
|
|
146
|
+
preview(ref)
|
|
147
|
+
const [{ isOver }, dropRef] = useDrop({
|
|
148
|
+
accept: 'author',
|
|
149
|
+
hover: (item: DragItem, monitor) => {
|
|
150
|
+
if (!ref.current) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
const side = getDropSide(ref.current, monitor)
|
|
154
|
+
setDropSide(side)
|
|
155
|
+
},
|
|
156
|
+
drop: (item: DragItem, monitor) => {
|
|
157
|
+
if (!ref.current) {
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
const side = getDropSide(ref.current, monitor)
|
|
161
|
+
const diff = side === 'before' ? -0.5 : 0.5
|
|
162
|
+
moveAuthor(item.author, author, diff)
|
|
163
|
+
},
|
|
164
|
+
collect: (monitor) => ({
|
|
165
|
+
isOver: monitor.isOver(),
|
|
166
|
+
}),
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
dragRef(dropRef(ref))
|
|
170
|
+
|
|
171
|
+
const classes: string[] = []
|
|
172
|
+
if (isDragging) {
|
|
173
|
+
classes.push('dragging')
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (isOver && dropSide) {
|
|
177
|
+
classes.push(`drop-${dropSide}`)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (isSelected) {
|
|
181
|
+
classes.push('active')
|
|
182
|
+
if (ref.current) {
|
|
183
|
+
ref.current.scrollIntoView({
|
|
184
|
+
behavior: 'smooth',
|
|
185
|
+
block: 'center',
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<AuthorContainer
|
|
192
|
+
ref={ref}
|
|
193
|
+
className={classes.join(' ')}
|
|
194
|
+
onClick={onClick}
|
|
195
|
+
data-cy="author-item"
|
|
196
|
+
>
|
|
197
|
+
<AvatarContainer data-cy="author-avatar">
|
|
198
|
+
{isSelected && <DragHandle />}
|
|
199
|
+
<Box>
|
|
200
|
+
{showSuccessIcon && <StyledCrclTickAnimation size={36} />}
|
|
201
|
+
<Avatar
|
|
202
|
+
size={36}
|
|
203
|
+
color={'#6e6e6e'}
|
|
204
|
+
opacity={showSuccessIcon ? 0.05 : 1}
|
|
205
|
+
/>
|
|
206
|
+
</Box>
|
|
207
|
+
<AuthorNotes data-cy="author-notes">
|
|
208
|
+
{author.isCorresponding && (
|
|
209
|
+
<AuthorBadge>
|
|
210
|
+
<CorrespondingAuthorIcon />
|
|
211
|
+
</AuthorBadge>
|
|
212
|
+
)}
|
|
213
|
+
</AuthorNotes>
|
|
214
|
+
</AvatarContainer>
|
|
215
|
+
<AuthorName data-cy="author-name">{authorLabel(author)}</AuthorName>
|
|
216
|
+
{isSelected && (
|
|
217
|
+
<RemoveButton
|
|
218
|
+
size={13}
|
|
219
|
+
onClick={() => onDelete()}
|
|
220
|
+
data-tooltip-content="Delete"
|
|
221
|
+
>
|
|
222
|
+
<DeleteIcon fill={'#6E6E6E'} />
|
|
223
|
+
</RemoveButton>
|
|
224
|
+
)}
|
|
225
|
+
</AuthorContainer>
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2025 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 { useEffect, useReducer, useState } from 'react'
|
|
17
|
+
|
|
18
|
+
import { arrayReducer } from '../../lib/array-reducer'
|
|
19
|
+
import { AffiliationAttrs, ContributorAttrs } from '../../lib/authors'
|
|
20
|
+
|
|
21
|
+
export const affiliationsReducer = arrayReducer<AffiliationAttrs>(
|
|
22
|
+
(a, b) => a.id === b.id
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
export const useManageAffiliations = (
|
|
26
|
+
selection: ContributorAttrs | undefined,
|
|
27
|
+
$affiliations: AffiliationAttrs[]
|
|
28
|
+
) => {
|
|
29
|
+
const [affiliations, dispatchAffiliations] = useReducer(affiliationsReducer, [
|
|
30
|
+
...$affiliations,
|
|
31
|
+
])
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
dispatchAffiliations({ type: 'set', state: [...$affiliations] })
|
|
35
|
+
}, [$affiliations])
|
|
36
|
+
const [selectedAffiliations, setSelectedAffiliations] = useState<
|
|
37
|
+
{
|
|
38
|
+
id: string
|
|
39
|
+
institution: string
|
|
40
|
+
}[]
|
|
41
|
+
>([])
|
|
42
|
+
|
|
43
|
+
const removeAffiliation = (affId: string) => {
|
|
44
|
+
if (!selection) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
const newAffiliations = selectedAffiliations
|
|
48
|
+
.map((a) => a.id)
|
|
49
|
+
.filter((id) => id !== affId)
|
|
50
|
+
setSelectedAffiliations(
|
|
51
|
+
affiliations.filter((item) => newAffiliations.includes(item.id))
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
const selectAffiliation = (affiliationId: string) => {
|
|
55
|
+
if (!selection) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const currentAffiliations = selectedAffiliations.map((a) => a.id)
|
|
60
|
+
const isAlreadySelected = currentAffiliations.includes(affiliationId)
|
|
61
|
+
|
|
62
|
+
const newAffiliations = isAlreadySelected
|
|
63
|
+
? currentAffiliations.filter((id) => id !== affiliationId)
|
|
64
|
+
: [...currentAffiliations, affiliationId]
|
|
65
|
+
|
|
66
|
+
setSelectedAffiliations(
|
|
67
|
+
affiliations.filter((item) => newAffiliations.includes(item.id))
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
selectedAffiliations,
|
|
72
|
+
setSelectedAffiliations,
|
|
73
|
+
removeAffiliation,
|
|
74
|
+
selectAffiliation,
|
|
75
|
+
affiliations,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* © 2025 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 { CreditRole, CreditVocabTerm } from '@manuscripts/transform'
|
|
17
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
18
|
+
|
|
19
|
+
import { ContributorAttrs } from '../../lib/authors'
|
|
20
|
+
|
|
21
|
+
export const useManageCredit = (selection: ContributorAttrs | undefined) => {
|
|
22
|
+
const vocabTermItems = useMemo(() => {
|
|
23
|
+
return Object.values(CreditVocabTerm).map((c) => ({
|
|
24
|
+
vocabTerm: c,
|
|
25
|
+
id: c,
|
|
26
|
+
}))
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
setSelectedCreditRoles(selection?.creditRoles ? selection?.creditRoles : [])
|
|
31
|
+
}, [selection])
|
|
32
|
+
|
|
33
|
+
const [selectedCreditRoles, setSelectedCreditRoles] = useState<CreditRole[]>(
|
|
34
|
+
[]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const selectCreditRole = (role: string) => {
|
|
38
|
+
setSelectedCreditRoles((prev) => {
|
|
39
|
+
const clear = prev.filter((t) => t.vocabTerm !== role)
|
|
40
|
+
if (clear.length !== prev.length) {
|
|
41
|
+
return clear
|
|
42
|
+
}
|
|
43
|
+
const newTerm = vocabTermItems.find((t) => t.vocabTerm === role)
|
|
44
|
+
if (newTerm) {
|
|
45
|
+
return [...prev, { vocabTerm: newTerm.vocabTerm }]
|
|
46
|
+
}
|
|
47
|
+
return prev
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const removeCreditRole = (role: string) => {
|
|
52
|
+
setSelectedCreditRoles((prev) => {
|
|
53
|
+
return prev.filter((r) => r.vocabTerm !== role)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
removeCreditRole,
|
|
58
|
+
selectCreditRole,
|
|
59
|
+
selectedCreditRoles,
|
|
60
|
+
setSelectedCreditRoles,
|
|
61
|
+
vocabTermItems,
|
|
62
|
+
}
|
|
63
|
+
}
|