@manuscripts/body-editor 3.0.2 → 3.0.3-LEAN-4579.1
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/affiliations/AffiliationsModal.js +79 -126
- package/dist/cjs/components/authors/AffiliationDrawer.js +24 -0
- package/dist/cjs/components/authors/AuthorDetailsForm.js +11 -9
- package/dist/cjs/components/authors/AuthorsModal.js +121 -204
- package/dist/cjs/components/authors/CreditDrawer.js +37 -0
- package/dist/cjs/components/authors/useManageAffiliations.js +41 -0
- package/dist/cjs/components/authors/useManageCredit.js +43 -0
- package/dist/cjs/components/form/FormFooter.js +2 -0
- package/dist/cjs/components/form/ModalFormActions.js +4 -4
- package/dist/cjs/components/modal-drawer/GenericDrawer.js +16 -0
- package/dist/cjs/components/modal-drawer/GenericDrawerGroup.js +75 -0
- package/dist/cjs/lib/normalize.js +49 -0
- package/dist/cjs/versions.js +1 -1
- package/dist/es/components/affiliations/AffiliationsModal.js +80 -127
- package/dist/es/components/authors/AffiliationDrawer.js +17 -0
- package/dist/es/components/authors/AuthorDetailsForm.js +9 -7
- package/dist/es/components/authors/AuthorsModal.js +123 -206
- package/dist/es/components/authors/CreditDrawer.js +30 -0
- package/dist/es/components/authors/useManageAffiliations.js +37 -0
- package/dist/es/components/authors/useManageCredit.js +39 -0
- package/dist/es/components/form/FormFooter.js +2 -0
- package/dist/es/components/form/ModalFormActions.js +4 -4
- package/dist/es/components/modal-drawer/GenericDrawer.js +9 -0
- package/dist/es/components/modal-drawer/GenericDrawerGroup.js +68 -0
- package/dist/es/lib/normalize.js +44 -0
- package/dist/es/versions.js +1 -1
- package/dist/types/components/authors/AffiliationDrawer.d.ts +12 -0
- package/dist/types/components/authors/AuthorDetailsForm.d.ts +4 -1
- package/dist/types/components/authors/AuthorsModal.d.ts +1 -2
- package/dist/types/components/authors/CreditDrawer.d.ts +14 -0
- package/dist/types/components/authors/useManageAffiliations.d.ts +18 -0
- package/dist/types/components/authors/useManageCredit.d.ts +13 -0
- package/dist/types/components/form/ModalFormActions.d.ts +2 -2
- package/dist/types/components/modal-drawer/GenericDrawer.d.ts +14 -0
- package/dist/types/components/modal-drawer/GenericDrawerGroup.d.ts +45 -0
- package/dist/types/lib/normalize.d.ts +25 -0
- package/dist/types/types.d.ts +1 -0
- package/dist/types/versions.d.ts +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* © 2025 Atypon Systems LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.DrawerSection = exports.DrawerSectionHeader = exports.AssignButton = exports.DrawerGroup = void 0;
|
|
22
|
+
const style_guide_1 = require("@manuscripts/style-guide");
|
|
23
|
+
const react_1 = __importDefault(require("react"));
|
|
24
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
25
|
+
function DrawerGroup({ removeItem, selectedItems, onSelect, items, showDrawer, setShowDrawer, title, labelField, Drawer, cy, Icon, buttonText, }) {
|
|
26
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
27
|
+
react_1.default.createElement(exports.DrawerSection, null,
|
|
28
|
+
react_1.default.createElement(exports.DrawerSectionHeader, null,
|
|
29
|
+
react_1.default.createElement(DrawerSectionTitle, null, title),
|
|
30
|
+
react_1.default.createElement(exports.AssignButton, { onClick: () => setShowDrawer(true), "data-cy": cy + 'assign-button' },
|
|
31
|
+
Icon,
|
|
32
|
+
buttonText)),
|
|
33
|
+
react_1.default.createElement(style_guide_1.SelectedItemsBox, { "data-cy": cy + '-selected-items', items: selectedItems.map((i) => ({
|
|
34
|
+
id: String(i.id),
|
|
35
|
+
label: String(i[labelField] ?? ''),
|
|
36
|
+
})), onRemove: removeItem, placeholder: `No ${title}s assigned` })),
|
|
37
|
+
showDrawer && (react_1.default.createElement(Drawer, { items: items, selectedItems: selectedItems, title: title, onSelect: onSelect, onBack: () => setShowDrawer(false), width: "100%" }))));
|
|
38
|
+
}
|
|
39
|
+
exports.DrawerGroup = DrawerGroup;
|
|
40
|
+
const DrawerSectionTitle = styled_components_1.default.h3 `
|
|
41
|
+
margin: 0;
|
|
42
|
+
font-weight: ${(props) => props.theme.font.weight.normal};
|
|
43
|
+
font-size: ${(props) => props.theme.font.size.large};
|
|
44
|
+
font-family: ${(props) => props.theme.font.family.sans};
|
|
45
|
+
color: ${(props) => props.theme.colors.text.secondary};
|
|
46
|
+
`;
|
|
47
|
+
exports.AssignButton = styled_components_1.default.button `
|
|
48
|
+
color: ${(props) => props.theme.colors.brand.default};
|
|
49
|
+
background: none;
|
|
50
|
+
border: none;
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
padding: 0;
|
|
53
|
+
font: ${(props) => props.theme.font.weight.normal}
|
|
54
|
+
${(props) => props.theme.font.size.normal}
|
|
55
|
+
${(props) => props.theme.font.family.sans};
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 4px;
|
|
59
|
+
margin-top: ${(props) => props.theme.grid.unit * 2}px;
|
|
60
|
+
&:hover {
|
|
61
|
+
opacity: 0.8;
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
exports.DrawerSectionHeader = styled_components_1.default.div `
|
|
65
|
+
display: flex;
|
|
66
|
+
justify-content: space-between;
|
|
67
|
+
align-items: flex-start;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
margin-bottom: ${(props) => props.theme.grid.unit * 2}px;
|
|
70
|
+
`;
|
|
71
|
+
exports.DrawerSection = styled_components_1.default.div `
|
|
72
|
+
margin-top: ${(props) => props.theme.grid.unit * 4}px;
|
|
73
|
+
padding-top: ${(props) => props.theme.grid.unit * 4}px;
|
|
74
|
+
border-top: 1px solid ${(props) => props.theme.colors.border.tertiary};
|
|
75
|
+
`;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* © 2025 Atypon Systems LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.checkID = exports.normalizeAuthor = void 0;
|
|
19
|
+
const transform_1 = require("@manuscripts/transform");
|
|
20
|
+
const normalizeAuthor = (author) => {
|
|
21
|
+
const basic = {
|
|
22
|
+
id: author.id,
|
|
23
|
+
role: author.role || '',
|
|
24
|
+
affiliations: (author.affiliations || []).sort(),
|
|
25
|
+
bibliographicName: author.bibliographicName,
|
|
26
|
+
email: author.email || '',
|
|
27
|
+
isCorresponding: author.isCorresponding || false,
|
|
28
|
+
ORCIDIdentifier: author.ORCIDIdentifier || '',
|
|
29
|
+
priority: author.priority || 0,
|
|
30
|
+
isJointContributor: author.isJointContributor || false,
|
|
31
|
+
userID: author.userID || '',
|
|
32
|
+
invitationID: author.invitationID || '',
|
|
33
|
+
footnote: author.footnote || [],
|
|
34
|
+
corresp: author.corresp || [],
|
|
35
|
+
prefix: author.prefix || '',
|
|
36
|
+
};
|
|
37
|
+
if (author.creditRoles && Array.isArray(author.creditRoles)) {
|
|
38
|
+
basic.creditRoles = author.creditRoles;
|
|
39
|
+
}
|
|
40
|
+
return basic;
|
|
41
|
+
};
|
|
42
|
+
exports.normalizeAuthor = normalizeAuthor;
|
|
43
|
+
const checkID = (attrs, nodeType) => {
|
|
44
|
+
return {
|
|
45
|
+
...attrs,
|
|
46
|
+
id: attrs.id || (0, transform_1.generateNodeID)(transform_1.schema.nodes[nodeType]),
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
exports.checkID = checkID;
|
package/dist/cjs/versions.js
CHANGED
|
@@ -1,102 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AddIcon, AddUserIcon, AffiliationPlaceholderIcon, CloseButton, ModalBody, ModalContainer, ModalHeader, ModalSidebar, ModalSidebarHeader, ModalSidebarTitle, ScrollableModalContent, SidebarContent, StyledModal, } from '@manuscripts/style-guide';
|
|
2
|
+
import { generateNodeID, schema } from '@manuscripts/transform';
|
|
3
3
|
import { isEqual } from 'lodash';
|
|
4
4
|
import React, { useCallback, useEffect, useReducer, useRef, useState, } from 'react';
|
|
5
5
|
import styled from 'styled-components';
|
|
6
6
|
import { authorComparator, } from '../../lib/authors';
|
|
7
|
-
import {
|
|
7
|
+
import { checkID } from '../../lib/normalize';
|
|
8
|
+
import { authorsReducer } from '../authors/AuthorsModal';
|
|
9
|
+
import { affiliationsReducer } from '../authors/useManageAffiliations';
|
|
8
10
|
import { ConfirmationDialog, DialogType } from '../dialog/ConfirmationDialog';
|
|
9
11
|
import FormFooter from '../form/FormFooter';
|
|
10
12
|
import { FormPlaceholder } from '../form/FormPlaceholder';
|
|
11
13
|
import { ModalFormActions } from '../form/ModalFormActions';
|
|
14
|
+
import { GenericDrawer } from '../modal-drawer/GenericDrawer';
|
|
15
|
+
import { DrawerGroup } from '../modal-drawer/GenericDrawerGroup';
|
|
12
16
|
import { AffiliationForm } from './AffiliationForm';
|
|
13
17
|
import { AffiliationList } from './AffiliationList';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
padding: 12px 8px 12px 12px;
|
|
21
|
-
cursor: pointer;
|
|
22
|
-
&[data-active='true'] {
|
|
23
|
-
background: ${(props) => props.theme.colors.background.fifth};
|
|
24
|
-
border: 1px solid ${(props) => props.theme.colors.border.primary};
|
|
25
|
-
border-left: 0;
|
|
26
|
-
border-right: 0;
|
|
27
|
-
}
|
|
28
|
-
`;
|
|
29
|
-
const ActionTitle = styled.div `
|
|
30
|
-
padding-left: ${(props) => props.theme.grid.unit * 2}px;
|
|
31
|
-
`;
|
|
32
|
-
const AffiliationForms = styled.div `
|
|
33
|
-
padding-left: ${(props) => props.theme.grid.unit * 3}px;
|
|
34
|
-
padding-right: ${(props) => props.theme.grid.unit * 3}px;
|
|
35
|
-
position: relative;
|
|
36
|
-
margin-top: 20px;
|
|
37
|
-
`;
|
|
38
|
-
const AuthorsSection = styled.div `
|
|
39
|
-
margin-top: ${(props) => props.theme.grid.unit * 4}px;
|
|
40
|
-
padding-top: ${(props) => props.theme.grid.unit * 4}px;
|
|
41
|
-
border-top: 1px solid ${(props) => props.theme.colors.border.tertiary};
|
|
42
|
-
`;
|
|
43
|
-
const AuthorsHeader = styled.div `
|
|
44
|
-
display: flex;
|
|
45
|
-
justify-content: space-between;
|
|
46
|
-
align-items: flex-start;
|
|
47
|
-
flex-direction: column;
|
|
48
|
-
margin-bottom: ${(props) => props.theme.grid.unit * 2}px;
|
|
49
|
-
`;
|
|
50
|
-
const AuthorsTitle = styled.h3 `
|
|
51
|
-
margin: 0;
|
|
52
|
-
font-weight: ${(props) => props.theme.font.weight.normal};
|
|
53
|
-
font-size: ${(props) => props.theme.font.size.large};
|
|
54
|
-
font-family: ${(props) => props.theme.font.family.sans};
|
|
55
|
-
color: ${(props) => props.theme.colors.text.secondary};
|
|
56
|
-
`;
|
|
57
|
-
const AffiliateButton = styled.button `
|
|
58
|
-
color: ${(props) => props.theme.colors.brand.default};
|
|
59
|
-
background: none;
|
|
60
|
-
border: none;
|
|
61
|
-
cursor: pointer;
|
|
62
|
-
padding: 0;
|
|
63
|
-
font: ${(props) => props.theme.font.weight.normal}
|
|
64
|
-
${(props) => props.theme.font.size.normal}
|
|
65
|
-
${(props) => props.theme.font.family.sans};
|
|
66
|
-
display: flex;
|
|
67
|
-
align-items: center;
|
|
68
|
-
gap: 4px;
|
|
69
|
-
margin-top: ${(props) => props.theme.grid.unit * 2}px;
|
|
70
|
-
&:hover {
|
|
71
|
-
opacity: 0.8;
|
|
72
|
-
}
|
|
73
|
-
`;
|
|
74
|
-
const StyledModalBody = styled(ModalBody) `
|
|
75
|
-
position: relative;
|
|
76
|
-
height: calc(90vh - 40px);
|
|
77
|
-
`;
|
|
78
|
-
const StyledModalSidebarHeader = styled(ModalSidebarHeader) `
|
|
79
|
-
margin-top: 8px;
|
|
80
|
-
margin-bottom: 16px;
|
|
81
|
-
`;
|
|
82
|
-
const normalize = (affiliation) => ({
|
|
83
|
-
id: affiliation.id || generateID(ObjectTypes.Affiliation),
|
|
84
|
-
institution: affiliation.institution,
|
|
85
|
-
department: affiliation.department,
|
|
86
|
-
addressLine1: affiliation.addressLine1,
|
|
87
|
-
addressLine2: affiliation.addressLine2,
|
|
88
|
-
addressLine3: affiliation.addressLine3,
|
|
89
|
-
postCode: affiliation.postCode,
|
|
90
|
-
country: affiliation.country,
|
|
91
|
-
county: affiliation.county,
|
|
92
|
-
city: affiliation.city,
|
|
93
|
-
email: affiliation.email,
|
|
94
|
-
priority: affiliation.priority,
|
|
95
|
-
});
|
|
18
|
+
function makeAuthorItems(authors) {
|
|
19
|
+
return authors.map((author) => ({
|
|
20
|
+
id: author.id,
|
|
21
|
+
label: `${author.bibliographicName.given} ${author.bibliographicName.family}`,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
96
24
|
export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, affiliation, onSaveAffiliation, onDeleteAffiliation, onUpdateAuthors, addNewAffiliation = false, }) => {
|
|
97
25
|
const [isOpen, setIsOpen] = useState(true);
|
|
98
26
|
const [selection, setSelection] = useState(affiliation);
|
|
99
|
-
const [
|
|
27
|
+
const [showingDeleteDialog, setShowDeleteDialog] = useState(false);
|
|
100
28
|
const valuesRef = useRef();
|
|
101
29
|
const actionsRef = useRef();
|
|
102
30
|
const [authors, dispatchAuthors] = useReducer(authorsReducer, $authors.sort(authorComparator));
|
|
@@ -128,7 +56,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
128
56
|
}, []);
|
|
129
57
|
const handleClose = () => {
|
|
130
58
|
const values = valuesRef.current;
|
|
131
|
-
const hasAffiliationChanges = selection && !isEqual(values,
|
|
59
|
+
const hasAffiliationChanges = selection && !isEqual(values, checkID(selection, 'affiliation'));
|
|
132
60
|
const originalAuthors = selection
|
|
133
61
|
? affiliationAuthorMap.get(selection.id) ?? []
|
|
134
62
|
: [];
|
|
@@ -150,7 +78,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
150
78
|
};
|
|
151
79
|
const handleSelect = (affiliation) => {
|
|
152
80
|
const values = valuesRef.current;
|
|
153
|
-
const hasAffiliationChanges = selection && !isEqual(values,
|
|
81
|
+
const hasAffiliationChanges = selection && !isEqual(values, checkID(selection, 'affiliation'));
|
|
154
82
|
const originalAuthors = selection
|
|
155
83
|
? affiliationAuthorMap.get(selection.id) ?? []
|
|
156
84
|
: [];
|
|
@@ -188,7 +116,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
188
116
|
}
|
|
189
117
|
setIsDisableSave(true);
|
|
190
118
|
const affiliation = {
|
|
191
|
-
...
|
|
119
|
+
...checkID(selection, 'affiliation'),
|
|
192
120
|
...values,
|
|
193
121
|
};
|
|
194
122
|
onSaveAffiliation(affiliation);
|
|
@@ -235,7 +163,8 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
235
163
|
return;
|
|
236
164
|
}
|
|
237
165
|
const isInstitutionEmpty = !values.institution?.trim();
|
|
238
|
-
const hasAffiliationChanges = selection &&
|
|
166
|
+
const hasAffiliationChanges = selection &&
|
|
167
|
+
!isEqual(checkID(values, 'affiliation'), checkID(selection, 'affiliation'));
|
|
239
168
|
const originalAuthors = affiliationAuthorMap.get(selection.id) ?? [];
|
|
240
169
|
const hasAuthorChanges = selection && !isEqual(originalAuthors.sort(), selectedAuthorIds.sort());
|
|
241
170
|
const shouldEnableSave = !isInstitutionEmpty && (hasAffiliationChanges || hasAuthorChanges);
|
|
@@ -265,7 +194,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
265
194
|
setSelectedAuthorIds([]);
|
|
266
195
|
setSelection(undefined);
|
|
267
196
|
};
|
|
268
|
-
const
|
|
197
|
+
const selectAuthor = (authorId) => {
|
|
269
198
|
if (!selection) {
|
|
270
199
|
return;
|
|
271
200
|
}
|
|
@@ -273,17 +202,13 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
273
202
|
? selectedAuthorIds.filter((id) => id !== authorId)
|
|
274
203
|
: [...selectedAuthorIds, authorId];
|
|
275
204
|
setSelectedAuthorIds(newSelectedAuthorIds);
|
|
276
|
-
const hasAffiliationChanges = !isEqual(valuesRef.current,
|
|
205
|
+
const hasAffiliationChanges = !isEqual(valuesRef.current, checkID(selection, 'affiliation'));
|
|
277
206
|
const originalAuthors = affiliationAuthorMap.get(selection.id) ?? [];
|
|
278
207
|
const hasAuthorChanges = !isEqual(originalAuthors.sort(), newSelectedAuthorIds.sort());
|
|
279
208
|
const isInstitutionEmpty = !valuesRef.current?.institution?.trim();
|
|
280
209
|
const shouldEnableSave = !isInstitutionEmpty && (hasAffiliationChanges || hasAuthorChanges);
|
|
281
210
|
setIsDisableSave(!shouldEnableSave);
|
|
282
211
|
};
|
|
283
|
-
const authorItems = authors.map((author) => ({
|
|
284
|
-
id: author.id,
|
|
285
|
-
label: `${author.bibliographicName.given} ${author.bibliographicName.family}`,
|
|
286
|
-
}));
|
|
287
212
|
const selectedAuthors = selectedAuthorIds
|
|
288
213
|
.map((authorId) => {
|
|
289
214
|
const author = authors.find((a) => a.id === authorId);
|
|
@@ -299,23 +224,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
299
224
|
const values = valuesRef.current;
|
|
300
225
|
const hasChanges = !isDisableSave;
|
|
301
226
|
const isInstitutionEmpty = values?.institution?.trim() === '';
|
|
302
|
-
const emptyAffiliation =
|
|
303
|
-
id: generateID(ObjectTypes.Affiliation),
|
|
304
|
-
institution: '',
|
|
305
|
-
department: '',
|
|
306
|
-
addressLine1: '',
|
|
307
|
-
addressLine2: '',
|
|
308
|
-
addressLine3: '',
|
|
309
|
-
postCode: '',
|
|
310
|
-
country: '',
|
|
311
|
-
county: '',
|
|
312
|
-
city: '',
|
|
313
|
-
email: {
|
|
314
|
-
href: '',
|
|
315
|
-
text: '',
|
|
316
|
-
},
|
|
317
|
-
priority: affiliations.length,
|
|
318
|
-
};
|
|
227
|
+
const emptyAffiliation = createEmptyAffiliation(affiliations.length);
|
|
319
228
|
if (hasChanges) {
|
|
320
229
|
setPendingAction('new');
|
|
321
230
|
if (isInstitutionEmpty) {
|
|
@@ -354,7 +263,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
354
263
|
.filter((author) => author.affiliations?.some((aff) => aff === pendingSelection.id))
|
|
355
264
|
.map((author) => author.id);
|
|
356
265
|
setSelectedAuthorIds(affiliatedAuthorIds);
|
|
357
|
-
valuesRef.current =
|
|
266
|
+
valuesRef.current = checkID(pendingSelection, 'affiliation');
|
|
358
267
|
setIsDisableSave(true);
|
|
359
268
|
setAffiliationAuthorMap((prevMap) => {
|
|
360
269
|
const newMap = new Map(prevMap);
|
|
@@ -392,7 +301,7 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
392
301
|
setSelectedAuthorIds([]);
|
|
393
302
|
}
|
|
394
303
|
if (pendingSelection) {
|
|
395
|
-
valuesRef.current =
|
|
304
|
+
valuesRef.current = checkID(pendingSelection, 'affiliation');
|
|
396
305
|
}
|
|
397
306
|
else {
|
|
398
307
|
valuesRef.current = undefined;
|
|
@@ -417,19 +326,63 @@ export const AffiliationsModal = ({ authors: $authors, affiliations: $affiliatio
|
|
|
417
326
|
React.createElement(ActionTitle, null, "New Affiliation")),
|
|
418
327
|
React.createElement(AffiliationList, { affiliation: selection, affiliations: affiliations, onSelect: handleSelect, onDelete: handleShowDeleteDialog, lastSavedAffiliationId: savedAffiliationId }))),
|
|
419
328
|
React.createElement(ScrollableModalContent, { "data-cy": "affiliations-modal-content" }, selection ? (React.createElement(AffiliationForms, null,
|
|
420
|
-
React.createElement(ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onDelete: handleDeleteAffiliation,
|
|
421
|
-
React.createElement(AffiliationForm, { values:
|
|
329
|
+
React.createElement(ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onDelete: handleDeleteAffiliation, showingDeleteDialog: showingDeleteDialog, showDeleteDialog: handleShowDeleteDialog, newEntity: newAffiliation, isDisableSave: isDisableSave }),
|
|
330
|
+
React.createElement(AffiliationForm, { values: checkID(selection, 'affiliation'), onSave: () => handleSaveAffiliation(valuesRef.current), onChange: handleAffiliationChange, actionsRef: actionsRef }),
|
|
422
331
|
React.createElement(ConfirmationDialog, { isOpen: showRequiredFieldConfirmationDialog, onPrimary: () => setShowRequiredFieldConfirmationDialog(false), onSecondary: handleConfirmationCancel, type: DialogType.REQUIRED, entityType: "affiliation" }),
|
|
423
332
|
React.createElement(ConfirmationDialog, { isOpen: showConfirmationDialog, onPrimary: handleConfirmationSave, onSecondary: handleConfirmationCancel, type: DialogType.SAVE, entityType: "affiliation" }),
|
|
424
|
-
React.createElement(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
React.createElement(AffiliateButton, { onClick: () => setShowAuthorDrawer(true), "data-cy": "affiliate-authors-button" },
|
|
428
|
-
React.createElement(AddUserIcon, { width: 16, height: 16 }),
|
|
429
|
-
"Affiliate Authors")),
|
|
430
|
-
React.createElement(SelectedItemsBox, { "data-cy": "affiliation-authors", items: selectedAuthors, onRemove: (id) => {
|
|
431
|
-
setSelectedAuthorIds((prev) => prev.filter((authorId) => authorId !== id));
|
|
432
|
-
}, placeholder: "No authors assigned" })),
|
|
433
|
-
showAuthorDrawer && (React.createElement(Drawer, { items: authorItems, selectedIds: selectedAuthorIds, title: "Authors", onSelect: handleAuthorSelect, onBack: () => setShowAuthorDrawer(false), width: "100%" })))) : (React.createElement(FormPlaceholder, { type: "affiliation", title: "Affiliation Details", message: "Select an affiliation from the list to display it's details here.", placeholderIcon: React.createElement(AffiliationPlaceholderIcon, null) })))),
|
|
333
|
+
React.createElement(DrawerGroup, { Drawer: GenericDrawer, removeItem: (id) => {
|
|
334
|
+
setSelectedAuthorIds((prev) => prev.filter((authorId) => authorId !== id));
|
|
335
|
+
}, selectedItems: selectedAuthors, onSelect: selectAuthor, items: makeAuthorItems(authors), showDrawer: showAuthorDrawer, setShowDrawer: setShowAuthorDrawer, title: "Authors", cy: "affiliations", labelField: "label", buttonText: "Affiliate Authors", Icon: React.createElement(AddUserIcon, { width: 16, height: 16 }) }))) : (React.createElement(FormPlaceholder, { type: "affiliation", title: "Affiliation Details", message: "Select an affiliation from the list to display it's details here.", placeholderIcon: React.createElement(AffiliationPlaceholderIcon, null) })))),
|
|
434
336
|
React.createElement(FormFooter, { onCancel: handleClose }))));
|
|
435
337
|
};
|
|
338
|
+
function createEmptyAffiliation(priority) {
|
|
339
|
+
return {
|
|
340
|
+
id: generateNodeID(schema.nodes.affiliation),
|
|
341
|
+
institution: '',
|
|
342
|
+
department: '',
|
|
343
|
+
addressLine1: '',
|
|
344
|
+
addressLine2: '',
|
|
345
|
+
addressLine3: '',
|
|
346
|
+
postCode: '',
|
|
347
|
+
country: '',
|
|
348
|
+
county: '',
|
|
349
|
+
city: '',
|
|
350
|
+
email: {
|
|
351
|
+
href: '',
|
|
352
|
+
text: '',
|
|
353
|
+
},
|
|
354
|
+
priority: priority,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
const StyledSidebarContent = styled(SidebarContent) `
|
|
358
|
+
padding: 0;
|
|
359
|
+
`;
|
|
360
|
+
const AddAffiliationButton = styled.div `
|
|
361
|
+
display: flex;
|
|
362
|
+
align-items: center;
|
|
363
|
+
padding: 12px 8px 12px 12px;
|
|
364
|
+
cursor: pointer;
|
|
365
|
+
&[data-active='true'] {
|
|
366
|
+
background: ${(props) => props.theme.colors.background.fifth};
|
|
367
|
+
border: 1px solid ${(props) => props.theme.colors.border.primary};
|
|
368
|
+
border-left: 0;
|
|
369
|
+
border-right: 0;
|
|
370
|
+
}
|
|
371
|
+
`;
|
|
372
|
+
const ActionTitle = styled.div `
|
|
373
|
+
padding-left: ${(props) => props.theme.grid.unit * 2}px;
|
|
374
|
+
`;
|
|
375
|
+
const AffiliationForms = styled.div `
|
|
376
|
+
padding-left: ${(props) => props.theme.grid.unit * 3}px;
|
|
377
|
+
padding-right: ${(props) => props.theme.grid.unit * 3}px;
|
|
378
|
+
position: relative;
|
|
379
|
+
margin-top: 20px;
|
|
380
|
+
`;
|
|
381
|
+
const StyledModalBody = styled(ModalBody) `
|
|
382
|
+
position: relative;
|
|
383
|
+
height: calc(90vh - 40px);
|
|
384
|
+
`;
|
|
385
|
+
const StyledModalSidebarHeader = styled(ModalSidebarHeader) `
|
|
386
|
+
margin-top: 8px;
|
|
387
|
+
margin-bottom: 16px;
|
|
388
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AddedIcon, AddIcon, Drawer, DrawerIcon, DrawerItemLabel, DrawerItemMeta, DrawerItemsList, DrawerLabelContainer, DrawerListItem, } from '@manuscripts/style-guide';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export const AffiliationsDrawer = ({ items, selectedItems = [], onSelect, ...drawerProps }) => {
|
|
4
|
+
return (React.createElement(Drawer, { ...drawerProps },
|
|
5
|
+
React.createElement(DrawerItemsList, null, items.map((item) => (React.createElement(DrawerListItem, { "data-cy": "item", key: item.id, selected: selectedItems?.map((a) => a.id).includes(item.id), onClick: () => onSelect(item.id) },
|
|
6
|
+
React.createElement(DrawerIcon, null, selectedItems?.map((a) => a.id).includes(item.id) ? (React.createElement(AddedIcon, { width: 22, height: 22 })) : (React.createElement(AddIcon, { width: 22, height: 22 }))),
|
|
7
|
+
React.createElement(DrawerLabelContainer, null,
|
|
8
|
+
React.createElement(DrawerItemLabel, null, item.institution),
|
|
9
|
+
React.createElement(DrawerItemMeta, null,
|
|
10
|
+
item.city && (React.createElement(React.Fragment, null,
|
|
11
|
+
item.city,
|
|
12
|
+
item.county || item.country ? ', ' : '')),
|
|
13
|
+
item.county && (React.createElement(React.Fragment, null,
|
|
14
|
+
item.county,
|
|
15
|
+
item.country ? ', ' : '')),
|
|
16
|
+
item.country && React.createElement(React.Fragment, null, item.country)))))))));
|
|
17
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* ©
|
|
2
|
+
* © 2025 Atypon Systems LLC
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -41,18 +41,23 @@ const TextFieldWithError = styled(TextField) `
|
|
|
41
41
|
color: ${(props) => props.theme.colors.text.error};
|
|
42
42
|
}
|
|
43
43
|
`;
|
|
44
|
-
const CheckboxContainer = styled.div `
|
|
44
|
+
export const CheckboxContainer = styled.div `
|
|
45
45
|
display: flex;
|
|
46
46
|
align-items: center;
|
|
47
47
|
gap: 32px;
|
|
48
48
|
`;
|
|
49
|
-
export const AuthorDetailsForm = ({ values, onChange, onSave, actionsRef, isEmailRequired, selectedAffiliations, authorFormRef, }) => {
|
|
49
|
+
export const AuthorDetailsForm = ({ values, onChange, onSave, actionsRef, isEmailRequired, selectedAffiliations, selectedCreditRoles, authorFormRef, }) => {
|
|
50
50
|
const formRef = useRef(null);
|
|
51
51
|
useEffect(() => {
|
|
52
52
|
if (selectedAffiliations && formRef.current) {
|
|
53
53
|
formRef.current.setFieldValue('affiliations', selectedAffiliations);
|
|
54
54
|
}
|
|
55
55
|
}, [selectedAffiliations]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (selectedCreditRoles && formRef.current) {
|
|
58
|
+
formRef.current.setFieldValue('creditRoles', selectedCreditRoles);
|
|
59
|
+
}
|
|
60
|
+
}, [selectedCreditRoles]);
|
|
56
61
|
if (actionsRef && !actionsRef.current) {
|
|
57
62
|
actionsRef.current = {
|
|
58
63
|
reset: () => {
|
|
@@ -81,9 +86,6 @@ export const AuthorDetailsForm = ({ values, onChange, onSave, actionsRef, isEmai
|
|
|
81
86
|
React.createElement(OrcidContainer, null,
|
|
82
87
|
React.createElement(TextFieldLabel, null,
|
|
83
88
|
React.createElement(LabelText, null, "ORCID"),
|
|
84
|
-
React.createElement(Field, { name: 'ORCIDIdentifier', type: 'text' }, (props) => (React.createElement(TextField, { id: 'orcid', placeholder: 'https://orcid.org/...', pattern: "https://orcid\\.org/\\d{4}-\\d{4}-\\d{4}-\\d{4}", title: "Please enter a valid ORCID URL format: https://orcid.org/xxxx-xxxx-xxxx-xxxx", ...props.field })))))
|
|
85
|
-
React.createElement(Field, { name: "affiliations", type: "hidden" }, (props) => {
|
|
86
|
-
return (React.createElement(TextField, { type: "hidden", ...props.field, value: selectedAffiliations || [] }));
|
|
87
|
-
}))));
|
|
89
|
+
React.createElement(Field, { name: 'ORCIDIdentifier', type: 'text' }, (props) => (React.createElement(TextField, { id: 'orcid', placeholder: 'https://orcid.org/...', pattern: "https://orcid\\.org/\\d{4}-\\d{4}-\\d{4}-\\d{4}", title: "Please enter a valid ORCID URL format: https://orcid.org/xxxx-xxxx-xxxx-xxxx", ...props.field }))))))));
|
|
88
90
|
}));
|
|
89
91
|
};
|