@manuscripts/body-editor 2.7.7 → 2.7.8-LEAN-4213.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.
Files changed (72) hide show
  1. package/dist/cjs/components/affiliations/AffiliationForm.js +106 -0
  2. package/dist/cjs/components/affiliations/AffiliationItem.js +112 -0
  3. package/dist/cjs/components/affiliations/AffiliationList.js +47 -0
  4. package/dist/cjs/components/affiliations/AffiliationsModal.js +418 -0
  5. package/dist/cjs/components/authors/AuthorDetailsForm.js +10 -2
  6. package/dist/cjs/components/authors/AuthorList.js +1 -1
  7. package/dist/cjs/components/authors/AuthorsModal.js +184 -80
  8. package/dist/cjs/components/authors/DraggableAuthor.js +0 -3
  9. package/dist/cjs/components/dialog/ConfirmationDialog.js +86 -0
  10. package/dist/cjs/components/form/FormFooter.js +32 -0
  11. package/dist/cjs/components/form/FormPlaceholder.js +43 -0
  12. package/dist/cjs/components/{authors/AuthorActions.js → form/ModalFormActions.js} +12 -11
  13. package/dist/cjs/plugins/affiliations.js +5 -38
  14. package/dist/cjs/useEditor.js +0 -1
  15. package/dist/cjs/versions.js +1 -1
  16. package/dist/cjs/views/affiliations.js +82 -14
  17. package/dist/cjs/views/contributors.js +1 -9
  18. package/dist/es/components/affiliations/AffiliationForm.js +76 -0
  19. package/dist/es/components/affiliations/AffiliationItem.js +82 -0
  20. package/dist/es/components/affiliations/AffiliationList.js +40 -0
  21. package/dist/es/components/affiliations/AffiliationsModal.js +388 -0
  22. package/dist/es/components/authors/AuthorDetailsForm.js +11 -3
  23. package/dist/es/components/authors/AuthorList.js +1 -1
  24. package/dist/es/components/authors/AuthorsModal.js +183 -79
  25. package/dist/es/components/authors/DraggableAuthor.js +0 -3
  26. package/dist/es/components/dialog/ConfirmationDialog.js +79 -0
  27. package/dist/es/components/form/FormFooter.js +27 -0
  28. package/dist/es/components/form/FormPlaceholder.js +36 -0
  29. package/dist/es/components/{authors/AuthorActions.js → form/ModalFormActions.js} +10 -9
  30. package/dist/es/plugins/affiliations.js +6 -39
  31. package/dist/es/useEditor.js +0 -1
  32. package/dist/es/versions.js +1 -1
  33. package/dist/es/views/affiliations.js +85 -17
  34. package/dist/es/views/contributors.js +1 -9
  35. package/dist/types/components/{authors → affiliations}/AffiliationForm.d.ts +5 -0
  36. package/dist/types/components/affiliations/AffiliationItem.d.ts +10 -0
  37. package/dist/types/components/affiliations/AffiliationList.d.ts +26 -0
  38. package/dist/types/components/affiliations/AffiliationsModal.d.ts +11 -0
  39. package/dist/types/components/authors/AuthorDetailsForm.d.ts +1 -0
  40. package/dist/types/components/authors/AuthorsModal.d.ts +2 -1
  41. package/dist/types/components/dialog/ConfirmationDialog.d.ts +15 -0
  42. package/dist/types/components/form/FormFooter.d.ts +5 -0
  43. package/dist/types/components/form/FormPlaceholder.d.ts +9 -0
  44. package/dist/types/components/{authors/AuthorActions.d.ts → form/ModalFormActions.d.ts} +4 -3
  45. package/dist/types/lib/dnd.d.ts +1 -1
  46. package/dist/types/selection.d.ts +7 -1
  47. package/dist/types/versions.d.ts +1 -1
  48. package/dist/types/views/affiliations.d.ts +11 -0
  49. package/dist/types/views/contributors.d.ts +0 -1
  50. package/package.json +2 -2
  51. package/styles/AdvancedEditor.css +8 -4
  52. package/styles/Editor.css +7 -0
  53. package/dist/cjs/components/authors/AffiliationButton.js +0 -104
  54. package/dist/cjs/components/authors/AffiliationForm.js +0 -50
  55. package/dist/cjs/components/authors/AuthorAffiliations.js +0 -120
  56. package/dist/cjs/components/authors/AuthorFormPlaceholder.js +0 -71
  57. package/dist/cjs/components/authors/DeleteAuthorConfirmationDialog.js +0 -36
  58. package/dist/cjs/components/authors/RequiredFieldConfirmationDialog.js +0 -39
  59. package/dist/cjs/components/authors/SaveAuthorConfirmationDialog.js +0 -39
  60. package/dist/es/components/authors/AffiliationButton.js +0 -74
  61. package/dist/es/components/authors/AffiliationForm.js +0 -43
  62. package/dist/es/components/authors/AuthorAffiliations.js +0 -89
  63. package/dist/es/components/authors/AuthorFormPlaceholder.js +0 -64
  64. package/dist/es/components/authors/DeleteAuthorConfirmationDialog.js +0 -29
  65. package/dist/es/components/authors/RequiredFieldConfirmationDialog.js +0 -32
  66. package/dist/es/components/authors/SaveAuthorConfirmationDialog.js +0 -32
  67. package/dist/types/components/authors/AffiliationButton.d.ts +0 -8
  68. package/dist/types/components/authors/AuthorAffiliations.d.ts +0 -11
  69. package/dist/types/components/authors/AuthorFormPlaceholder.d.ts +0 -2
  70. package/dist/types/components/authors/DeleteAuthorConfirmationDialog.d.ts +0 -7
  71. package/dist/types/components/authors/RequiredFieldConfirmationDialog.d.ts +0 -7
  72. package/dist/types/components/authors/SaveAuthorConfirmationDialog.d.ts +0 -7
@@ -41,7 +41,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
41
41
  return (mod && mod.__esModule) ? mod : { "default": mod };
42
42
  };
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.AuthorsModal = void 0;
44
+ exports.AuthorsModal = exports.affiliationsReducer = exports.authorsReducer = void 0;
45
45
  const json_schema_1 = require("@manuscripts/json-schema");
46
46
  const style_guide_1 = require("@manuscripts/style-guide");
47
47
  const lodash_1 = require("lodash");
@@ -49,25 +49,28 @@ const react_1 = __importStar(require("react"));
49
49
  const styled_components_1 = __importDefault(require("styled-components"));
50
50
  const array_reducer_1 = require("../../lib/array-reducer");
51
51
  const authors_1 = require("../../lib/authors");
52
- const AuthorActions_1 = require("./AuthorActions");
53
- const AuthorAffiliations_1 = require("./AuthorAffiliations");
52
+ const ConfirmationDialog_1 = require("../dialog/ConfirmationDialog");
53
+ const FormFooter_1 = __importDefault(require("../form/FormFooter"));
54
+ const FormPlaceholder_1 = require("../form/FormPlaceholder");
55
+ const ModalFormActions_1 = require("../form/ModalFormActions");
54
56
  const AuthorDetailsForm_1 = require("./AuthorDetailsForm");
55
- const AuthorFormPlaceholder_1 = require("./AuthorFormPlaceholder");
56
57
  const AuthorList_1 = require("./AuthorList");
57
- const RequiredFieldConfirmationDialog_1 = require("./RequiredFieldConfirmationDialog");
58
- const SaveAuthorConfirmationDialog_1 = require("./SaveAuthorConfirmationDialog");
59
58
  const AddAuthorButton = styled_components_1.default.div `
60
59
  display: flex;
61
60
  align-items: center;
62
- margin-bottom: ${(props) => props.theme.grid.unit * 4}px;
63
- margin-left: ${(props) => props.theme.grid.unit * 4}px;
61
+ padding: 12px 8px 12px 12px;
64
62
  cursor: pointer;
63
+ &[data-active='true'] {
64
+ background: ${(props) => props.theme.colors.background.fifth};
65
+ border: 1px solid ${(props) => props.theme.colors.border.primary};
66
+ border-left: 0;
67
+ border-right: 0;
68
+ }
65
69
  `;
66
70
  const ActionTitle = styled_components_1.default.div `
67
71
  padding-left: ${(props) => props.theme.grid.unit * 2}px;
68
72
  `;
69
73
  const FormLabel = styled_components_1.default.legend `
70
- margin-top: 12px;
71
74
  margin-bottom: 12px;
72
75
  font: ${(props) => props.theme.font.weight.normal}
73
76
  ${(props) => props.theme.font.size.xlarge} /
@@ -79,28 +82,73 @@ const FormLabel = styled_components_1.default.legend `
79
82
  const AuthorForms = styled_components_1.default.div `
80
83
  padding-left: ${(props) => props.theme.grid.unit * 3}px;
81
84
  padding-right: ${(props) => props.theme.grid.unit * 3}px;
85
+ position: relative;
86
+ margin-top: 20px;
82
87
  `;
83
88
  const StyledSidebarContent = (0, styled_components_1.default)(style_guide_1.SidebarContent) `
84
89
  padding: 0;
85
90
  `;
86
- const authorsReducer = (0, array_reducer_1.arrayReducer)((a, b) => a.id === b.id);
87
- const affiliationsReducer = (0, array_reducer_1.arrayReducer)((a, b) => a.id === b.id);
91
+ const AuthorsSection = styled_components_1.default.div `
92
+ margin-top: ${(props) => props.theme.grid.unit * 4}px;
93
+ padding-top: ${(props) => props.theme.grid.unit * 4}px;
94
+ border-top: 1px solid ${(props) => props.theme.colors.border.tertiary};
95
+ `;
96
+ const AuthorsHeader = styled_components_1.default.div `
97
+ display: flex;
98
+ justify-content: space-between;
99
+ align-items: flex-start;
100
+ flex-direction: column;
101
+ margin-bottom: ${(props) => props.theme.grid.unit * 2}px;
102
+ `;
103
+ const AuthorsTitle = styled_components_1.default.h3 `
104
+ margin: 0;
105
+ font-weight: ${(props) => props.theme.font.weight.normal};
106
+ font-size: ${(props) => props.theme.font.size.large};
107
+ font-family: ${(props) => props.theme.font.family.sans};
108
+ color: ${(props) => props.theme.colors.text.secondary};
109
+ `;
110
+ const AffiliateButton = styled_components_1.default.button `
111
+ color: ${(props) => props.theme.colors.brand.default};
112
+ background: none;
113
+ border: none;
114
+ cursor: pointer;
115
+ padding: 0;
116
+ font: ${(props) => props.theme.font.weight.normal}
117
+ ${(props) => props.theme.font.size.normal}
118
+ ${(props) => props.theme.font.family.sans};
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 4px;
122
+ margin-top: ${(props) => props.theme.grid.unit * 2}px;
123
+ &:hover {
124
+ opacity: 0.8;
125
+ }
126
+ `;
127
+ const StyledModalBody = (0, styled_components_1.default)(style_guide_1.ModalBody) `
128
+ position: relative;
129
+ height: calc(90vh - 40px);
130
+ `;
131
+ const StyledModalSidebarHeader = (0, styled_components_1.default)(style_guide_1.ModalSidebarHeader) `
132
+ margin-bottom: 16px;
133
+ `;
134
+ exports.authorsReducer = (0, array_reducer_1.arrayReducer)((a, b) => a.id === b.id);
135
+ exports.affiliationsReducer = (0, array_reducer_1.arrayReducer)((a, b) => a.id === b.id);
88
136
  const normalize = (author) => ({
89
137
  id: author.id,
90
- role: author.role,
91
- affiliations: author.affiliations || [],
138
+ role: author.role || 'author',
139
+ affiliations: (author.affiliations || []).sort(),
92
140
  bibliographicName: author.bibliographicName,
93
141
  email: author.email || '',
94
142
  isCorresponding: author.isCorresponding || false,
95
143
  ORCIDIdentifier: author.ORCIDIdentifier || '',
96
- priority: author.priority,
144
+ priority: author.priority || 0,
97
145
  isJointContributor: author.isJointContributor || false,
98
- userID: '',
99
- invitationID: '',
146
+ userID: author.userID || '',
147
+ invitationID: author.invitationID || '',
100
148
  footnote: author.footnote || [],
101
149
  corresp: author.corresp || [],
102
150
  });
103
- const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author, onSaveAuthor, onDeleteAuthor, onSaveAffiliation, addNewAuthor = false, }) => {
151
+ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author, onSaveAuthor, onDeleteAuthor, addNewAuthor = false, }) => {
104
152
  const [isOpen, setOpen] = (0, react_1.useState)(true);
105
153
  const [isDisableSave, setDisableSave] = (0, react_1.useState)(true);
106
154
  const [isEmailRequired, setEmailRequired] = (0, react_1.useState)(false);
@@ -113,38 +161,74 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
113
161
  const [nextAuthor, setNextAuthor] = (0, react_1.useState)(null);
114
162
  const [isSwitchingAuthor, setIsSwitchingAuthor] = (0, react_1.useState)(false);
115
163
  const [isCreatingNewAuthor, setIsCreatingNewAuthor] = (0, react_1.useState)(false);
164
+ const [showAffiliationDrawer, setShowAffiliationDrawer] = (0, react_1.useState)(false);
165
+ const [selectedAffiliations, setSelectedAffiliations] = (0, react_1.useState)([]);
116
166
  const valuesRef = (0, react_1.useRef)();
117
167
  const actionsRef = (0, react_1.useRef)();
118
- const [authors, dispatchAuthors] = (0, react_1.useReducer)(authorsReducer, $authors.sort(authors_1.authorComparator));
119
- const [affiliations, dispatchAffiliations] = (0, react_1.useReducer)(affiliationsReducer, $affiliations);
168
+ const [authors, dispatchAuthors] = (0, react_1.useReducer)(exports.authorsReducer, $authors.sort(authors_1.authorComparator));
169
+ const [affiliations] = (0, react_1.useReducer)(exports.affiliationsReducer, $affiliations);
170
+ const affiliationItems = affiliations.map((affiliation) => ({
171
+ id: affiliation.id,
172
+ label: affiliation.institution,
173
+ country: affiliation.country,
174
+ city: affiliation.city,
175
+ state: affiliation.county,
176
+ }));
177
+ const [selectedAffiliationIds, setSelectedAffiliationIds] = (0, react_1.useState)([]);
120
178
  (0, react_1.useEffect)(() => {
121
179
  if (addNewAuthor) {
122
180
  handleAddAuthor();
123
181
  }
124
182
  }, [addNewAuthor]);
125
183
  const [selection, setSelection] = (0, react_1.useState)(author);
184
+ (0, react_1.useEffect)(() => {
185
+ const currentAuthor = selection;
186
+ const relevantAffiliations = affiliationItems.filter((item) => { var _a; return (_a = currentAuthor === null || currentAuthor === void 0 ? void 0 : currentAuthor.affiliations) === null || _a === void 0 ? void 0 : _a.includes(item.id); });
187
+ setSelectedAffiliations(relevantAffiliations);
188
+ setSelectedAffiliationIds(relevantAffiliations.map((item) => item.id));
189
+ }, []);
126
190
  const handleSelect = (author) => {
127
191
  const values = valuesRef.current;
128
192
  setIsCreatingNewAuthor(false);
129
- if (values && selection && unSavedChanges && !isDisableSave) {
130
- setShowConfirmationDialog(true);
131
- setNextAuthor(author);
132
- }
133
- else if (isDisableSave && unSavedChanges) {
134
- setShowRequiredFieldConfirmationDialog(true);
135
- setNextAuthor(author);
193
+ if (values && selection) {
194
+ const normalizedSelection = normalize(selection);
195
+ const normalizedValues = normalize(values);
196
+ const hasChanges = !(0, lodash_1.isEqual)(normalizedSelection, normalizedValues);
197
+ if (hasChanges && !isDisableSave) {
198
+ setShowConfirmationDialog(true);
199
+ setNextAuthor(author);
200
+ }
201
+ else if (hasChanges && isDisableSave) {
202
+ setShowRequiredFieldConfirmationDialog(true);
203
+ setNextAuthor(author);
204
+ }
205
+ else {
206
+ updateAffiliationSelection(author);
207
+ setSelection(author);
208
+ setShowAffiliationDrawer(false);
209
+ setNewAuthor(false);
210
+ }
136
211
  }
137
212
  else {
213
+ setShowAffiliationDrawer(false);
214
+ updateAffiliationSelection(author);
138
215
  setSelection(author);
139
216
  setNewAuthor(false);
140
217
  }
141
218
  };
219
+ const updateAffiliationSelection = (author) => {
220
+ const relevantAffiliations = affiliationItems.filter((item) => { var _a; return (_a = author.affiliations) === null || _a === void 0 ? void 0 : _a.includes(item.id); });
221
+ setSelectedAffiliations(relevantAffiliations);
222
+ setSelectedAffiliationIds(relevantAffiliations.map((item) => item.id));
223
+ };
142
224
  const handleClose = () => {
143
- if (isDisableSave && unSavedChanges) {
144
- setShowRequiredFieldConfirmationDialog(true);
145
- }
146
- else if (unSavedChanges) {
147
- setShowConfirmationDialog(true);
225
+ if (unSavedChanges) {
226
+ if (isDisableSave) {
227
+ setShowRequiredFieldConfirmationDialog(true);
228
+ }
229
+ else {
230
+ setShowConfirmationDialog(true);
231
+ }
148
232
  }
149
233
  else {
150
234
  setShowRequiredFieldConfirmationDialog(false);
@@ -160,6 +244,7 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
160
244
  setSelection(nextAuthor);
161
245
  setNextAuthor(null);
162
246
  setNewAuthor(false);
247
+ setShowAffiliationDrawer(false);
163
248
  setIsCreatingNewAuthor(false);
164
249
  }
165
250
  else if (isCreatingNewAuthor) {
@@ -171,10 +256,14 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
171
256
  const handleCancel = () => {
172
257
  handleResetAuthor();
173
258
  if (nextAuthor) {
259
+ const affiliations = nextAuthor.affiliations || [];
260
+ setSelectedAffiliationIds(affiliations);
261
+ setSelectedAffiliations(affiliationItems.filter((item) => affiliations.includes(item.id)));
174
262
  setSelection(nextAuthor);
175
263
  setNextAuthor(null);
176
264
  setNewAuthor(false);
177
265
  setIsCreatingNewAuthor(false);
266
+ setUnSavedChanges(false);
178
267
  }
179
268
  else if (newAuthor && unSavedChanges && !isSwitchingAuthor) {
180
269
  setNewAuthor(false);
@@ -186,6 +275,8 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
186
275
  setIsCreatingNewAuthor(false);
187
276
  }
188
277
  setShowConfirmationDialog(false);
278
+ setShowRequiredFieldConfirmationDialog(false);
279
+ setShowAffiliationDrawer(false);
189
280
  };
190
281
  const handleSaveAuthor = (values) => {
191
282
  if (!values || !selection) {
@@ -201,6 +292,9 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
201
292
  setSelection(author);
202
293
  setShowConfirmationDialog(false);
203
294
  setNewAuthor(false);
295
+ setSelectedAffiliationIds([]);
296
+ setSelectedAffiliations([]);
297
+ setShowAffiliationDrawer(false);
204
298
  setIsCreatingNewAuthor(false);
205
299
  dispatchAuthors({
206
300
  type: 'update',
@@ -240,6 +334,8 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
240
334
  footnote: [],
241
335
  };
242
336
  setIsSwitchingAuthor(!!selection);
337
+ setSelectedAffiliations([]);
338
+ setSelectedAffiliationIds([]);
243
339
  setSelection(author);
244
340
  setNewAuthor(true);
245
341
  };
@@ -247,7 +343,9 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
247
343
  const values = valuesRef.current;
248
344
  setIsSwitchingAuthor(!!selection);
249
345
  setIsCreatingNewAuthor(true);
250
- if (values && selection && !(0, lodash_1.isEqual)(values, normalize(selection))) {
346
+ if (values &&
347
+ selection &&
348
+ !(0, lodash_1.isEqual)(normalize(values), normalize(selection))) {
251
349
  if (isDisableSave) {
252
350
  setShowRequiredFieldConfirmationDialog(true);
253
351
  }
@@ -258,6 +356,7 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
258
356
  }
259
357
  else {
260
358
  createNewAuthor();
359
+ setShowAffiliationDrawer(false);
261
360
  }
262
361
  };
263
362
  const handleDeleteAuthor = () => {
@@ -266,37 +365,26 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
266
365
  }
267
366
  onDeleteAuthor(selection);
268
367
  setSelection(undefined);
368
+ setUnSavedChanges(false);
269
369
  dispatchAuthors({
270
370
  type: 'delete',
271
371
  item: selection,
272
372
  });
273
373
  };
274
- const handleSaveAffiliation = (affiliation) => {
275
- onSaveAffiliation(affiliation);
276
- dispatchAffiliations({
277
- type: 'update',
278
- items: [affiliation],
279
- });
280
- };
281
- const handleAddAffiliation = (affiliation) => {
282
- if (!valuesRef.current) {
283
- return;
284
- }
285
- const values = valuesRef.current;
286
- const affiliations = values.affiliations || [];
287
- handleSaveAuthor(Object.assign(Object.assign({}, values), { affiliations: [...affiliations, affiliation.id] }));
288
- };
289
- const handleRemoveAffiliation = (affiliation) => {
290
- var _a;
291
- if (!valuesRef.current) {
374
+ const handleRemoveAffiliation = (affId) => {
375
+ if (!selection) {
292
376
  return;
293
377
  }
294
- const values = valuesRef.current;
295
- handleSaveAuthor(Object.assign(Object.assign({}, values), { affiliations: (_a = values.affiliations) === null || _a === void 0 ? void 0 : _a.filter((i) => i !== affiliation.id) }));
378
+ const newAffiliations = selectedAffiliationIds.filter((id) => id !== affId);
379
+ setSelectedAffiliationIds(newAffiliations);
380
+ setSelectedAffiliations(affiliationItems.filter((item) => newAffiliations.includes(item.id)));
296
381
  };
297
382
  const handleResetAuthor = () => {
298
383
  var _a;
299
384
  (_a = actionsRef.current) === null || _a === void 0 ? void 0 : _a.reset();
385
+ const affiliations = (selection === null || selection === void 0 ? void 0 : selection.affiliations) || [];
386
+ setSelectedAffiliationIds(affiliations);
387
+ setSelectedAffiliations(affiliationItems.filter((item) => affiliations.includes(item.id)));
300
388
  setShowConfirmationDialog(false);
301
389
  setShowRequiredFieldConfirmationDialog(false);
302
390
  setUnSavedChanges(false);
@@ -311,61 +399,77 @@ const AuthorsModal = ({ authors: $authors, affiliations: $affiliations, author,
311
399
  };
312
400
  const handleChangeAuthor = (values) => {
313
401
  const normalized = (0, lodash_1.omit)(normalize(selection), 'priority');
314
- const updatedValues = (0, lodash_1.omit)(values, 'priority');
315
- if (updatedValues.id === normalized.id &&
316
- !(0, lodash_1.isEqual)(updatedValues, normalized)) {
402
+ const updatedValues = (0, lodash_1.omit)(normalize(values), 'priority');
403
+ const isSameAuthor = updatedValues.id === normalized.id;
404
+ const hasChanges = !(0, lodash_1.isEqual)(updatedValues, normalized);
405
+ if (isSameAuthor && hasChanges) {
317
406
  setUnSavedChanges(true);
318
407
  }
319
- const isUnchanged = (0, lodash_1.isEqual)(normalize(selection), values);
320
- valuesRef.current = values;
408
+ else {
409
+ setUnSavedChanges(false);
410
+ }
411
+ valuesRef.current = Object.assign(Object.assign({}, updatedValues), { priority: values.priority });
321
412
  const { given, family } = values.bibliographicName;
322
413
  const { email, isCorresponding } = values;
323
414
  const isNameFilled = (given === null || given === void 0 ? void 0 : given.length) && (family === null || family === void 0 ? void 0 : family.length);
324
- if (isNameFilled && !isCorresponding && !isUnchanged) {
325
- setDisableSave(false);
326
- }
327
- else if (isCorresponding &&
328
- (email === null || email === void 0 ? void 0 : email.length) &&
329
- isNameFilled &&
330
- !isUnchanged) {
331
- setDisableSave(false);
415
+ if (hasChanges && isNameFilled) {
416
+ if (isCorresponding) {
417
+ setDisableSave(!(email === null || email === void 0 ? void 0 : email.length));
418
+ }
419
+ else {
420
+ setDisableSave(false);
421
+ }
332
422
  }
333
423
  else {
334
424
  setDisableSave(true);
335
425
  }
336
- if (isCorresponding && !(email === null || email === void 0 ? void 0 : email.length)) {
337
- setEmailRequired(true);
338
- }
339
- else {
340
- setEmailRequired(false);
341
- }
426
+ setEmailRequired(isCorresponding);
342
427
  };
343
428
  const handleShowDeleteDialog = () => {
344
429
  setShowDeleteDialog((prev) => !prev);
345
430
  };
431
+ const handleAffiliationSelect = (affiliationId) => {
432
+ if (!selection) {
433
+ return;
434
+ }
435
+ const currentAffiliations = selectedAffiliationIds || [];
436
+ const isAlreadySelected = currentAffiliations.includes(affiliationId);
437
+ const newAffiliations = isAlreadySelected
438
+ ? currentAffiliations.filter((id) => id !== affiliationId)
439
+ : [...currentAffiliations, affiliationId];
440
+ setSelectedAffiliationIds(newAffiliations);
441
+ setSelectedAffiliations(affiliationItems.filter((item) => newAffiliations.includes(item.id)));
442
+ };
346
443
  return (react_1.default.createElement(style_guide_1.StyledModal, { isOpen: isOpen, onRequestClose: () => handleClose(), shouldCloseOnOverlayClick: true },
347
444
  react_1.default.createElement(style_guide_1.ModalContainer, null,
348
445
  react_1.default.createElement(style_guide_1.ModalHeader, null,
349
446
  react_1.default.createElement(style_guide_1.CloseButton, { onClick: () => handleClose(), "data-cy": "modal-close-button" })),
350
- react_1.default.createElement(style_guide_1.ModalBody, null,
447
+ react_1.default.createElement(StyledModalBody, null,
351
448
  react_1.default.createElement(style_guide_1.ModalSidebar, { "data-cy": "authors-sidebar" },
352
- react_1.default.createElement(style_guide_1.ModalSidebarHeader, null,
449
+ react_1.default.createElement(StyledModalSidebarHeader, null,
353
450
  react_1.default.createElement(style_guide_1.ModalSidebarTitle, null, "Authors")),
354
451
  react_1.default.createElement(StyledSidebarContent, null,
355
- react_1.default.createElement(AddAuthorButton, { "data-cy": "add-author-button", onClick: handleAddAuthor },
452
+ react_1.default.createElement(AddAuthorButton, { "data-cy": "add-author-button", onClick: handleAddAuthor, "data-active": isCreatingNewAuthor },
356
453
  react_1.default.createElement(style_guide_1.AddIcon, { width: 18, height: 18 }),
357
454
  react_1.default.createElement(ActionTitle, null, "New Author")),
358
455
  react_1.default.createElement(AuthorList_1.AuthorList, { author: selection, authors: authors, onSelect: handleSelect, onDelete: handleShowDeleteDialog, moveAuthor: handleMoveAuthor, lastSavedAuthor: lastSavedAuthor }))),
359
456
  react_1.default.createElement(style_guide_1.ScrollableModalContent, { "data-cy": "author-modal-content" }, selection ? (react_1.default.createElement(AuthorForms, null,
360
- react_1.default.createElement(RequiredFieldConfirmationDialog_1.RequiredFieldConfirmationDialog, { isOpen: showRequiredFieldConfirmationDialog, onSave: () => setShowRequiredFieldConfirmationDialog(false), onCancel: handleCancel }),
361
- react_1.default.createElement(SaveAuthorConfirmationDialog_1.SaveAuthorConfirmationDialog, { isOpen: showConfirmationDialog, onSave: handleSave, onCancel: handleCancel }),
362
- react_1.default.createElement(AuthorActions_1.AuthorActions, { onSave: () => handleSaveAuthor(valuesRef.current), onDelete: handleDeleteAuthor, showDeleteDialog: showDeleteDialog, handleShowDeleteDialog: handleShowDeleteDialog, newAuthor: newAuthor ||
457
+ react_1.default.createElement(ConfirmationDialog_1.ConfirmationDialog, { isOpen: showRequiredFieldConfirmationDialog, onPrimary: () => setShowRequiredFieldConfirmationDialog(false), onSecondary: handleCancel, type: ConfirmationDialog_1.DialogType.REQUIRED, entityType: "author" }),
458
+ react_1.default.createElement(ConfirmationDialog_1.ConfirmationDialog, { isOpen: showConfirmationDialog, onPrimary: handleSave, onSecondary: handleCancel, type: ConfirmationDialog_1.DialogType.SAVE, entityType: "author" }),
459
+ react_1.default.createElement(ModalFormActions_1.ModalFormActions, { type: "author", onSave: () => handleSaveAuthor(valuesRef.current), onDelete: handleDeleteAuthor, showDeleteDialog: showDeleteDialog, handleShowDeleteDialog: handleShowDeleteDialog, newEntity: newAuthor ||
363
460
  (isCreatingNewAuthor &&
364
461
  !showConfirmationDialog &&
365
462
  !showRequiredFieldConfirmationDialog), isDisableSave: isDisableSave }),
366
463
  react_1.default.createElement(FormLabel, null, "Details"),
367
- react_1.default.createElement(AuthorDetailsForm_1.AuthorDetailsForm, { values: normalize(selection), onChange: handleChangeAuthor, onSave: handleSaveAuthor, actionsRef: actionsRef, isEmailRequired: isEmailRequired }),
368
- react_1.default.createElement(FormLabel, null, "Affiliations"),
369
- react_1.default.createElement(AuthorAffiliations_1.AuthorAffiliations, { author: selection, affiliations: affiliations, onSave: handleSaveAffiliation, onAdd: handleAddAffiliation, onRemove: handleRemoveAffiliation }))) : (react_1.default.createElement(AuthorFormPlaceholder_1.AuthorFormPlaceholder, null)))))));
464
+ react_1.default.createElement(AuthorDetailsForm_1.AuthorDetailsForm, { values: normalize(selection), onChange: handleChangeAuthor, onSave: handleSaveAuthor, actionsRef: actionsRef, isEmailRequired: isEmailRequired, selectedAffiliations: selectedAffiliationIds }),
465
+ react_1.default.createElement(AuthorsSection, null,
466
+ react_1.default.createElement(AuthorsHeader, null,
467
+ react_1.default.createElement(AuthorsTitle, null, "Authors"),
468
+ react_1.default.createElement(AffiliateButton, { onClick: () => setShowAffiliationDrawer(true), "data-cy": "affiliate-authors-button" },
469
+ react_1.default.createElement(style_guide_1.AddInstitutionIcon, { width: 16, height: 16 }),
470
+ "Assign Institutions")),
471
+ react_1.default.createElement(style_guide_1.SelectedItemsBox, { items: selectedAffiliations, onRemove: handleRemoveAffiliation, placeholder: "No institutions assigned" })),
472
+ showAffiliationDrawer && (react_1.default.createElement(style_guide_1.Drawer, { items: affiliationItems, selectedIds: selectedAffiliationIds, title: "Authors", onSelect: handleAffiliationSelect, onBack: () => setShowAffiliationDrawer(false), width: "100%" })))) : (react_1.default.createElement(FormPlaceholder_1.FormPlaceholder, { type: "author", title: 'Author Details', message: 'Select an author from the list to display their details here.', placeholderIcon: react_1.default.createElement(style_guide_1.AuthorPlaceholderIcon, null) })))),
473
+ react_1.default.createElement(FormFooter_1.default, { onCancel: handleClose }))));
370
474
  };
371
475
  exports.AuthorsModal = AuthorsModal;
@@ -62,9 +62,6 @@ const AuthorContainer = styled_components_1.default.div `
62
62
  &:hover,
63
63
  &.active {
64
64
  background: ${(props) => props.theme.colors.background.fifth};
65
- }
66
-
67
- &.active {
68
65
  border-color: ${(props) => props.theme.colors.border.primary};
69
66
  }
70
67
 
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ConfirmationDialog = exports.DialogType = void 0;
7
+ const style_guide_1 = require("@manuscripts/style-guide");
8
+ const react_1 = __importDefault(require("react"));
9
+ const styled_components_1 = __importDefault(require("styled-components"));
10
+ const StyledIcon = (0, styled_components_1.default)(style_guide_1.AttentionOrangeIcon) `
11
+ margin-right: 8px;
12
+ `;
13
+ const MessageBox = styled_components_1.default.div `
14
+ display: flex;
15
+ flex-direction: column;
16
+ justify-content: space-between;
17
+ min-height: 90px;
18
+ `;
19
+ var DialogType;
20
+ (function (DialogType) {
21
+ DialogType["SAVE"] = "save";
22
+ DialogType["DELETE"] = "delete";
23
+ DialogType["REQUIRED"] = "required";
24
+ })(DialogType = exports.DialogType || (exports.DialogType = {}));
25
+ const getDialogConfig = (dialogType, entityType) => {
26
+ const configs = {
27
+ [DialogType.SAVE]: {
28
+ title: 'Unsaved changes',
29
+ message: {
30
+ primary: "You've made changes but not saved them!",
31
+ secondary: 'Would you like to save or discard your changes?',
32
+ },
33
+ buttons: {
34
+ primary: 'Save',
35
+ secondary: 'Discard',
36
+ },
37
+ },
38
+ [DialogType.DELETE]: {
39
+ title: `Delete ${entityType}`,
40
+ message: {
41
+ primary: entityType === 'affiliation'
42
+ ? 'This action will delete the institution and any links to authors affiliated to it.'
43
+ : `Are you sure you want to remove this ${entityType} from the list?`,
44
+ secondary: 'Do you want to continue?',
45
+ },
46
+ buttons: {
47
+ primary: 'Delete',
48
+ secondary: 'Cancel',
49
+ },
50
+ },
51
+ [DialogType.REQUIRED]: {
52
+ title: 'Empty required field',
53
+ message: {
54
+ primary: 'A required field has been left empty. If you discard, any updates will not be saved!',
55
+ secondary: 'Would you like to discard or continue editing?',
56
+ },
57
+ buttons: {
58
+ primary: 'Continue editing',
59
+ secondary: 'Discard',
60
+ },
61
+ minHeight: '90px',
62
+ },
63
+ };
64
+ return configs[dialogType];
65
+ };
66
+ const ConfirmationDialog = ({ isOpen, type, entityType, onPrimary, onSecondary, }) => {
67
+ const config = getDialogConfig(type, entityType);
68
+ const Header = () => (react_1.default.createElement(react_1.default.Fragment, null,
69
+ react_1.default.createElement(StyledIcon, null),
70
+ " ",
71
+ config.title));
72
+ const Message = () => (react_1.default.createElement(MessageBox, null,
73
+ react_1.default.createElement("div", null, config.message.primary),
74
+ config.message.secondary && react_1.default.createElement("div", null, config.message.secondary)));
75
+ return (react_1.default.createElement(style_guide_1.Dialog, { isOpen: isOpen, category: style_guide_1.Category.confirmation, header: react_1.default.createElement(Header, null), message: react_1.default.createElement(Message, null), actions: {
76
+ primary: {
77
+ action: onPrimary,
78
+ title: config.buttons.primary,
79
+ },
80
+ secondary: {
81
+ action: onSecondary,
82
+ title: config.buttons.secondary,
83
+ },
84
+ } }));
85
+ };
86
+ exports.ConfirmationDialog = ConfirmationDialog;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const styled_components_1 = __importDefault(require("styled-components"));
8
+ const Footer = styled_components_1.default.div `
9
+ display: flex;
10
+ justify-content: flex-end;
11
+ align-items: center;
12
+ padding: 16px 32px;
13
+ height: 40px;
14
+ box-shadow: 0px -2px 12px 0px rgba(216, 216, 216, 0.26);
15
+ border-radius: 0px 0px 8px 8px;
16
+ `;
17
+ const RemoveButton = styled_components_1.default.button `
18
+ background-color: #0d79d0;
19
+ color: ${(props) => props.theme.colors.text.onDark};
20
+ padding: 8px 32px;
21
+ border-radius: 4px;
22
+ border: 1px solid #0d79d0;
23
+ &:hover {
24
+ background-color: ${(props) => props.theme.colors.background.hover};
25
+ }
26
+ cursor: pointer;
27
+ `;
28
+ const FormFooter = ({ onCancel }) => {
29
+ return (react_1.default.createElement(Footer, null,
30
+ react_1.default.createElement(RemoveButton, { onClick: onCancel }, "Close")));
31
+ };
32
+ exports.default = FormFooter;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FormPlaceholder = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const styled_components_1 = __importDefault(require("styled-components"));
9
+ const Container = styled_components_1.default.div `
10
+ display: flex;
11
+ flex-direction: column;
12
+ align-items: center;
13
+ justify-content: center;
14
+ height: 100%;
15
+ overflow-y: auto;
16
+ `;
17
+ const Placeholder = styled_components_1.default.div `
18
+ margin-bottom: ${(props) => props.theme.grid.unit * 5}px;
19
+ `;
20
+ const Action = styled_components_1.default.div `
21
+ font-size: ${(props) => props.theme.font.size.xlarge};
22
+ font-weight: ${(props) => props.theme.font.weight.medium};
23
+ letter-spacing: -0.5px;
24
+ `;
25
+ const Message = styled_components_1.default.div `
26
+ max-width: 400px;
27
+ font-size: ${(props) => props.theme.font.size.xlarge};
28
+ margin-top: ${(props) => props.theme.grid.unit * 6}px;
29
+ font-weight: ${(props) => props.theme.font.weight.light};
30
+ color: ${(props) => props.theme.colors.text.secondary};
31
+ text-align: center;
32
+
33
+ @media (max-width: 850px) {
34
+ margin-right: ${(props) => props.theme.grid.unit * 5}px;
35
+ margin-left: ${(props) => props.theme.grid.unit * 5}px;
36
+ max-width: 350px;
37
+ }
38
+ `;
39
+ const FormPlaceholder = ({ type, title, message, placeholderIcon, }) => (react_1.default.createElement(Container, { "data-cy": `${type}-details` },
40
+ react_1.default.createElement(Placeholder, null, placeholderIcon),
41
+ react_1.default.createElement(Action, null, title),
42
+ react_1.default.createElement(Message, null, message)));
43
+ exports.FormPlaceholder = FormPlaceholder;