@manuscripts/body-editor 3.12.33 → 3.12.35

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 (70) hide show
  1. package/dist/cjs/components/ChangeHandlingForm.js +3 -2
  2. package/dist/cjs/components/affiliations/AffiliationForm.js +77 -44
  3. package/dist/cjs/components/affiliations/AffiliationsModal.js +69 -58
  4. package/dist/cjs/components/affiliations/AffiliationsPanel.js +1 -1
  5. package/dist/cjs/components/affiliations/CreateAffiliationModal.js +96 -0
  6. package/dist/cjs/components/authors/AuthorDetailsForm.js +110 -54
  7. package/dist/cjs/components/authors/AuthorsModal.js +71 -48
  8. package/dist/cjs/components/authors/AuthorsPanel.js +2 -2
  9. package/dist/cjs/components/authors/CreateAuthorModal.js +121 -0
  10. package/dist/cjs/components/authors/CreditDrawer.js +14 -12
  11. package/dist/cjs/components/authors-affiliations/AuthorsAndAffiliationsModals.js +8 -24
  12. package/dist/cjs/components/authors-affiliations/GenericPanel.js +2 -2
  13. package/dist/cjs/components/authors-affiliations/ModalTabs.js +80 -0
  14. package/dist/cjs/components/dialog/ConfirmationDialog.js +3 -2
  15. package/dist/cjs/components/form/CreateModalStyles.js +24 -0
  16. package/dist/cjs/components/form/FormFooter.js +8 -3
  17. package/dist/cjs/components/form/ModalFormActions.js +19 -42
  18. package/dist/cjs/components/form/UnsavedLabel.js +25 -0
  19. package/dist/cjs/components/hooks/useAffiliationShowsErrorIndicator.js +27 -0
  20. package/dist/cjs/components/hooks/useAuthorShowsErrorIndicator.js +40 -0
  21. package/dist/cjs/lib/authors-and-affiliations.js +51 -0
  22. package/dist/cjs/lib/helpers.js +28 -1
  23. package/dist/cjs/lib/normalize.js +17 -5
  24. package/dist/cjs/useEditor.js +7 -4
  25. package/dist/cjs/versions.js +1 -1
  26. package/dist/es/components/ChangeHandlingForm.js +3 -2
  27. package/dist/es/components/affiliations/AffiliationForm.js +75 -46
  28. package/dist/es/components/affiliations/AffiliationsModal.js +71 -60
  29. package/dist/es/components/affiliations/AffiliationsPanel.js +2 -2
  30. package/dist/es/components/affiliations/CreateAffiliationModal.js +56 -0
  31. package/dist/es/components/authors/AuthorDetailsForm.js +111 -56
  32. package/dist/es/components/authors/AuthorsModal.js +74 -51
  33. package/dist/es/components/authors/AuthorsPanel.js +3 -3
  34. package/dist/es/components/authors/CreateAuthorModal.js +81 -0
  35. package/dist/es/components/authors/CreditDrawer.js +13 -11
  36. package/dist/es/components/authors-affiliations/AuthorsAndAffiliationsModals.js +8 -24
  37. package/dist/es/components/authors-affiliations/GenericPanel.js +2 -2
  38. package/dist/es/components/authors-affiliations/ModalTabs.js +73 -0
  39. package/dist/es/components/dialog/ConfirmationDialog.js +3 -2
  40. package/dist/es/components/form/CreateModalStyles.js +18 -0
  41. package/dist/es/components/form/FormFooter.js +9 -4
  42. package/dist/es/components/form/ModalFormActions.js +18 -42
  43. package/dist/es/components/form/UnsavedLabel.js +18 -0
  44. package/dist/es/components/hooks/useAffiliationShowsErrorIndicator.js +21 -0
  45. package/dist/es/components/hooks/useAuthorShowsErrorIndicator.js +34 -0
  46. package/dist/es/lib/authors-and-affiliations.js +48 -0
  47. package/dist/es/lib/helpers.js +27 -1
  48. package/dist/es/lib/normalize.js +15 -4
  49. package/dist/es/useEditor.js +8 -5
  50. package/dist/es/versions.js +1 -1
  51. package/dist/es/views/affiliations.js +1 -1
  52. package/dist/types/components/affiliations/AffiliationForm.d.ts +6 -2
  53. package/dist/types/components/affiliations/AffiliationsModal.d.ts +1 -1
  54. package/dist/types/components/affiliations/CreateAffiliationModal.d.ts +8 -0
  55. package/dist/types/components/authors/AuthorDetailsForm.d.ts +11 -1
  56. package/dist/types/components/authors/AuthorsPanel.d.ts +1 -1
  57. package/dist/types/components/authors/CreateAuthorModal.d.ts +9 -0
  58. package/dist/types/components/authors/CreditDrawer.d.ts +2 -4
  59. package/dist/types/components/authors-affiliations/ModalTabs.d.ts +22 -0
  60. package/dist/types/components/form/CreateModalStyles.d.ts +4 -0
  61. package/dist/types/components/form/FormFooter.d.ts +2 -1
  62. package/dist/types/components/form/ModalFormActions.d.ts +12 -6
  63. package/dist/types/components/form/UnsavedLabel.d.ts +10 -0
  64. package/dist/types/components/hooks/useAffiliationShowsErrorIndicator.d.ts +5 -0
  65. package/dist/types/components/hooks/useAuthorShowsErrorIndicator.d.ts +5 -0
  66. package/dist/types/lib/authors-and-affiliations.d.ts +19 -0
  67. package/dist/types/lib/helpers.d.ts +2 -0
  68. package/dist/types/lib/normalize.d.ts +2 -1
  69. package/dist/types/versions.d.ts +1 -1
  70. package/package.json +2 -2
@@ -50,8 +50,9 @@ const ChangeHandlingForm = (props) => {
50
50
  };
51
51
  exports.ChangeHandlingForm = ChangeHandlingForm;
52
52
  exports.FlexForm = (0, styled_components_1.default)(formik_1.Form) `
53
- height: 100%;
54
53
  display: flex;
55
54
  flex-direction: column;
56
- overflow: hidden;
55
+ min-height: 0;
56
+ width: 100%;
57
+ box-sizing: border-box;
57
58
  `;
@@ -32,59 +32,92 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.AffiliationForm = void 0;
39
+ exports.AffiliationForm = exports.affiliationShowsErrorIndicator = void 0;
37
40
  const style_guide_1 = require("@manuscripts/style-guide");
38
41
  const formik_1 = require("formik");
39
42
  const react_1 = __importStar(require("react"));
43
+ const styled_components_1 = __importDefault(require("styled-components"));
44
+ const style_guide_2 = require("@manuscripts/style-guide");
45
+ const normalize_1 = require("../../lib/normalize");
40
46
  const ChangeHandlingForm_1 = require("../ChangeHandlingForm");
41
- const AffiliationForm = ({ values, onSave, onChange, actionsRef, }) => {
42
- const formRef = (0, react_1.useRef)(null);
43
- if (actionsRef) {
44
- actionsRef.current = {
45
- reset: () => formRef.current?.resetForm(),
46
- submitForm: () => formRef.current?.submitForm(),
47
- };
48
- }
49
- const validateAffiliation = (values) => {
47
+ const UnsavedLabel_1 = require("../form/UnsavedLabel");
48
+ const useAffiliationShowsErrorIndicator_1 = require("../hooks/useAffiliationShowsErrorIndicator");
49
+ function isAffiliationFieldChanged(formik, key) {
50
+ const v = (0, normalize_1.normalizeAffiliation)(formik.values);
51
+ const i = (0, normalize_1.normalizeAffiliation)(formik.initialValues);
52
+ return (0, formik_1.getIn)(v, key) !== (0, formik_1.getIn)(i, key);
53
+ }
54
+ var useAffiliationShowsErrorIndicator_2 = require("../hooks/useAffiliationShowsErrorIndicator");
55
+ Object.defineProperty(exports, "affiliationShowsErrorIndicator", { enumerable: true, get: function () { return useAffiliationShowsErrorIndicator_2.affiliationShowsErrorIndicator; } });
56
+ const AffiliationForm = ({ values, onSave, onChange, actionsRef, newEntity = false, onAffiliationErrorChange, unsavedContinueActive = false, }) => {
57
+ const validateAffiliation = (vals) => {
50
58
  const errors = {};
51
- if (!values.institution?.trim()) {
59
+ if (!vals.institution?.trim()) {
52
60
  errors.institution = 'Institution Name is required';
53
61
  }
54
62
  return errors;
55
63
  };
56
- return (react_1.default.createElement(formik_1.Formik, { initialValues: values, onSubmit: (attrs) => onSave(attrs), innerRef: formRef, enableReinitialize: true, validate: validateAffiliation }, (formik) => (react_1.default.createElement(ChangeHandlingForm_1.ChangeHandlingForm, { onChange: onChange, id: "affiliation-form", noValidate: true },
57
- react_1.default.createElement(style_guide_1.FormRow, null,
58
- react_1.default.createElement(formik_1.Field, { name: "institution" }, (props) => {
59
- const hasError = formik.touched.institution && formik.errors.institution;
60
- return (react_1.default.createElement(react_1.default.Fragment, null,
61
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "institution" }, "Institution Name*"),
62
- react_1.default.createElement(style_guide_1.TextField, { id: "institution", ...props.field, error: hasError }),
63
- hasError && (react_1.default.createElement(style_guide_1.InputErrorText, null, formik.errors.institution))));
64
- })),
65
- react_1.default.createElement(style_guide_1.FormRow, null,
66
- react_1.default.createElement(formik_1.Field, { name: "department" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
67
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "department" }, "Department"),
68
- react_1.default.createElement(style_guide_1.TextField, { id: "department", ...props.field }))))),
69
- react_1.default.createElement(style_guide_1.FormRow, null,
70
- react_1.default.createElement(formik_1.Field, { name: "addressLine1" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
71
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "addressLine1" }, "Street Address"),
72
- react_1.default.createElement(style_guide_1.TextField, { id: "addressLine1", ...props.field }))))),
73
- react_1.default.createElement(style_guide_1.FormRow, null,
74
- react_1.default.createElement(formik_1.Field, { name: "city" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
75
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "city" }, "City"),
76
- react_1.default.createElement(style_guide_1.TextField, { id: "city", ...props.field }))))),
77
- react_1.default.createElement(style_guide_1.FormRow, null,
78
- react_1.default.createElement(formik_1.Field, { name: "county" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
79
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "county" }, "State / Province"),
80
- react_1.default.createElement(style_guide_1.TextField, { id: "county", ...props.field }))))),
81
- react_1.default.createElement(style_guide_1.FormRow, null,
82
- react_1.default.createElement(formik_1.Field, { name: "postCode" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
83
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "postCode" }, "Postal Code"),
84
- react_1.default.createElement(style_guide_1.TextField, { id: "postCode", ...props.field }))))),
85
- react_1.default.createElement(style_guide_1.FormRow, null,
86
- react_1.default.createElement(formik_1.Field, { name: "country" }, ({ field }) => (react_1.default.createElement(react_1.default.Fragment, null,
87
- react_1.default.createElement(style_guide_1.Label, { htmlFor: "country" }, "Country"),
88
- react_1.default.createElement(style_guide_1.TextField, { id: "country", ...field })))))))));
64
+ const formik = (0, formik_1.useFormik)({
65
+ initialValues: values,
66
+ onSubmit: (attrs) => onSave(attrs),
67
+ enableReinitialize: true,
68
+ validate: validateAffiliation,
69
+ validateOnChange: true,
70
+ });
71
+ if (actionsRef) {
72
+ actionsRef.current = {
73
+ reset: () => formik.resetForm(),
74
+ submitForm: () => formik.submitForm(),
75
+ };
76
+ }
77
+ const showInstitutionError = (0, useAffiliationShowsErrorIndicator_1.isInstitutionError)(formik, newEntity);
78
+ (0, react_1.useEffect)(() => {
79
+ onAffiliationErrorChange?.(showInstitutionError);
80
+ }, [showInstitutionError, onAffiliationErrorChange]);
81
+ const showUnsavedDot = (key) => unsavedContinueActive && isAffiliationFieldChanged(formik, key);
82
+ return (react_1.default.createElement(formik_1.FormikProvider, { value: formik },
83
+ react_1.default.createElement(ChangeHandlingForm_1.ChangeHandlingForm, { onChange: onChange, id: "affiliation-form", noValidate: true },
84
+ react_1.default.createElement(style_guide_1.FormRow, null,
85
+ react_1.default.createElement(formik_1.Field, { name: "institution" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
86
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "institution", showDot: showUnsavedDot('institution') },
87
+ "Institution Name",
88
+ react_1.default.createElement(style_guide_1.RequiredIndicator, null, "*")),
89
+ react_1.default.createElement(style_guide_1.TextField, { id: "institution", ...props.field, error: showInstitutionError }),
90
+ showInstitutionError && (react_1.default.createElement(style_guide_1.InputErrorText, null, formik.errors.institution)))))),
91
+ react_1.default.createElement(style_guide_1.FormRow, null,
92
+ react_1.default.createElement(formik_1.Field, { name: "department", type: "textarea" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
93
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "department", showDot: showUnsavedDot('department') }, "Department"),
94
+ react_1.default.createElement(style_guide_1.TextField, { id: "department", ...props.field, as: "textarea" }))))),
95
+ react_1.default.createElement(style_guide_1.FormRow, null,
96
+ react_1.default.createElement(formik_1.Field, { name: "addressLine1" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
97
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "addressLine1", showDot: showUnsavedDot('addressLine1') }, "Street Address"),
98
+ react_1.default.createElement(style_guide_1.TextField, { id: "addressLine1", ...props.field }))))),
99
+ react_1.default.createElement(StyledFormGroup, null,
100
+ react_1.default.createElement(style_guide_1.FormRow, null,
101
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "country", showDot: showUnsavedDot('country') }, "Country"),
102
+ react_1.default.createElement(formik_1.Field, { id: "country", name: "country", component: style_guide_1.SelectField, options: style_guide_2.COUNTRY_SELECT_OPTIONS, isSearchable: true, variant: "large", listMaxHeight: "140px" })),
103
+ react_1.default.createElement(style_guide_1.FormRow, null,
104
+ react_1.default.createElement(formik_1.Field, { name: "city" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
105
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "city", showDot: showUnsavedDot('city') }, "City"),
106
+ react_1.default.createElement(style_guide_1.TextField, { id: "city", ...props.field })))))),
107
+ react_1.default.createElement(StyledFormGroup, null,
108
+ react_1.default.createElement(style_guide_1.FormRow, null,
109
+ react_1.default.createElement(formik_1.Field, { name: "county" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
110
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "county", showDot: showUnsavedDot('county') }, "State / Province"),
111
+ react_1.default.createElement(style_guide_1.TextField, { id: "county", ...props.field }))))),
112
+ react_1.default.createElement(style_guide_1.FormRow, null,
113
+ react_1.default.createElement(formik_1.Field, { name: "postCode" }, (props) => (react_1.default.createElement(react_1.default.Fragment, null,
114
+ react_1.default.createElement(UnsavedLabel_1.UnsavedLabel, { htmlFor: "postCode", showDot: showUnsavedDot('postCode') }, "Postal Code"),
115
+ react_1.default.createElement(style_guide_1.TextField, { id: "postCode", ...props.field })))))))));
89
116
  };
90
117
  exports.AffiliationForm = AffiliationForm;
118
+ const StyledFormGroup = (0, styled_components_1.default)(style_guide_1.FormGroup) `
119
+ > div {
120
+ flex: 1;
121
+ min-width: 0;
122
+ }
123
+ `;
@@ -50,16 +50,18 @@ const ConfirmationDialog_1 = require("../dialog/ConfirmationDialog");
50
50
  const FormFooter_1 = __importDefault(require("../form/FormFooter"));
51
51
  const FormPlaceholder_1 = require("../form/FormPlaceholder");
52
52
  const ModalFormActions_1 = require("../form/ModalFormActions");
53
+ const ModalTabs_1 = require("../authors-affiliations/ModalTabs");
53
54
  const AuthorsPanel_1 = require("../authors/AuthorsPanel");
54
55
  const AffiliationForm_1 = require("./AffiliationForm");
55
56
  const AffiliationList_1 = require("./AffiliationList");
57
+ const MODAL_ON_CLOSE_NOTIFY_DELAY_MS = 220;
56
58
  function makeAuthorItems(authors) {
57
59
  return authors.map((author) => ({
58
60
  id: author.id,
59
61
  label: `${author.given} ${author.family}`,
60
62
  }));
61
63
  }
62
- const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, affiliation, onSaveAffiliation, onDeleteAffiliation, onUpdateAuthors, addNewAffiliation = false, onClose, onOpenAuthorsModal, }) => {
64
+ const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, affiliation, onSaveAffiliation, onDeleteAffiliation, onUpdateAuthors, addNewAffiliation = false, onClose, openAuthorsModal, }) => {
63
65
  const [isOpen, setIsOpen] = (0, react_1.useState)(true);
64
66
  const [selection, setSelection] = (0, react_1.useState)(affiliation);
65
67
  const [showingDeleteDialog, setShowDeleteDialog] = (0, react_1.useState)(false);
@@ -82,13 +84,31 @@ const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, aff
82
84
  const [pendingAction, setPendingAction] = (0, react_1.useState)(null);
83
85
  const [savedAffiliationId, setSavedAffiliationId] = (0, react_1.useState)(undefined);
84
86
  const [affiliationAuthorMap, setAffiliationAuthorMap] = (0, react_1.useState)(new Map());
85
- const prevIsOpenRef = (0, react_1.useRef)(isOpen);
87
+ const [affiliationTabHasError, setAffiliationTabHasError] = (0, react_1.useState)(false);
88
+ const [affiliationDetailsUnsavedContinue, setAffiliationDetailsUnsavedContinue,] = (0, react_1.useState)(false);
89
+ const [affiliationTabIndex, setAffiliationTabIndex] = (0, react_1.useState)(0);
90
+ const prevIsOpenRef = (0, react_1.useRef)(true);
86
91
  (0, react_1.useEffect)(() => {
87
92
  if (prevIsOpenRef.current && !isOpen) {
88
- onClose?.();
93
+ prevIsOpenRef.current = isOpen;
94
+ const id = window.setTimeout(() => {
95
+ onClose?.();
96
+ }, MODAL_ON_CLOSE_NOTIFY_DELAY_MS);
97
+ return () => window.clearTimeout(id);
89
98
  }
90
99
  prevIsOpenRef.current = isOpen;
91
100
  }, [isOpen, onClose]);
101
+ (0, react_1.useEffect)(() => {
102
+ if (isDisableSave) {
103
+ setAffiliationDetailsUnsavedContinue(false);
104
+ }
105
+ }, [isDisableSave]);
106
+ (0, react_1.useEffect)(() => {
107
+ setAffiliationDetailsUnsavedContinue(false);
108
+ if (selection?.id) {
109
+ setAffiliationTabIndex(0);
110
+ }
111
+ }, [selection?.id]);
92
112
  (0, react_1.useEffect)(() => {
93
113
  if (!selection) {
94
114
  return;
@@ -192,6 +212,7 @@ const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, aff
192
212
  newMap.set(affiliation.id, selectedAuthorIds);
193
213
  return newMap;
194
214
  });
215
+ setAffiliationDetailsUnsavedContinue(false);
195
216
  setSavedAffiliationId(affiliation.id);
196
217
  setTimeout(() => {
197
218
  setSavedAffiliationId(undefined);
@@ -292,70 +313,49 @@ const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, aff
292
313
  setNewAffiliation(true);
293
314
  }
294
315
  }, [addNewAffiliation]);
295
- const handleConfirmationSave = (0, react_1.useCallback)(() => {
296
- handleSaveAffiliation(valuesRef.current);
316
+ const handleConfirmationCancel = () => {
317
+ const action = pendingAction;
318
+ const pending = pendingSelection;
297
319
  setShowConfirmationDialog(false);
298
320
  setShowRequiredFieldConfirmationDialog(false);
299
- if (pendingAction === 'new') {
300
- setNewAffiliation(true);
301
- setSelection(affiliation);
302
- setSelectedAuthorIds([]);
303
- setIsDisableSave(true);
321
+ if (action === 'close') {
322
+ setIsOpen(false);
323
+ setSelection(undefined);
324
+ valuesRef.current = undefined;
325
+ setPendingSelection(null);
326
+ setPendingAction(null);
327
+ return;
304
328
  }
305
- else if (pendingAction === 'select' && pendingSelection) {
306
- setSelection(pendingSelection);
329
+ if (action === 'select' && pending) {
330
+ setSelection(pending);
307
331
  setNewAffiliation(false);
308
332
  const affiliatedAuthorIds = authors
309
- .filter((author) => author.affiliationIDs.some((aff) => aff === pendingSelection.id))
333
+ .filter((author) => author.affiliationIDs?.some((aff) => aff === pending.id))
310
334
  .map((author) => author.id);
311
335
  setSelectedAuthorIds(affiliatedAuthorIds);
312
- valuesRef.current = (0, normalize_1.checkID)(pendingSelection, 'affiliation');
313
- setIsDisableSave(true);
336
+ valuesRef.current = (0, normalize_1.checkID)(pending, 'affiliation');
314
337
  setAffiliationAuthorMap((prevMap) => {
315
338
  const newMap = new Map(prevMap);
316
- newMap.set(pendingSelection.id, affiliatedAuthorIds);
339
+ newMap.set(pending.id, affiliatedAuthorIds);
317
340
  return newMap;
318
341
  });
319
342
  }
320
- if (pendingAction === 'close') {
321
- setIsOpen(false);
322
- }
323
- setPendingSelection(null);
324
- setPendingAction(null);
325
- }, [
326
- authors,
327
- affiliation,
328
- pendingAction,
329
- pendingSelection,
330
- handleSaveAffiliation,
331
- ]);
332
- const handleConfirmationCancel = () => {
333
- setShowConfirmationDialog(false);
334
- setShowRequiredFieldConfirmationDialog(false);
335
- if (pendingAction === 'select' && pendingSelection) {
336
- setSelection(pendingSelection);
337
- setNewAffiliation(false);
338
- const affiliatedAuthorIds = authors
339
- .filter((author) => author.affiliationIDs?.some((aff) => aff === pendingSelection.id))
340
- .map((author) => author.id);
341
- setSelectedAuthorIds(affiliatedAuthorIds);
342
- }
343
- else if (pendingAction === 'new') {
343
+ else if (action === 'new') {
344
344
  setNewAffiliation(true);
345
345
  setSelection(affiliation);
346
346
  setSelectedAuthorIds([]);
347
+ valuesRef.current = affiliation
348
+ ? (0, normalize_1.checkID)(affiliation, 'affiliation')
349
+ : undefined;
347
350
  }
348
- if (pendingSelection) {
349
- valuesRef.current = (0, normalize_1.checkID)(pendingSelection, 'affiliation');
351
+ else if (pending) {
352
+ valuesRef.current = (0, normalize_1.checkID)(pending, 'affiliation');
350
353
  }
351
354
  else {
352
355
  valuesRef.current = undefined;
353
356
  }
354
357
  setPendingSelection(null);
355
358
  setPendingAction(null);
356
- if (pendingAction === 'close') {
357
- setIsOpen(false);
358
- }
359
359
  };
360
360
  return (react_1.default.createElement(style_guide_1.StyledModal, { isOpen: isOpen, onRequestClose: () => handleClose(), shouldCloseOnOverlayClick: true },
361
361
  react_1.default.createElement(style_guide_1.ModalContainer, { "data-cy": "affiliations-modal" },
@@ -364,28 +364,35 @@ const AffiliationsModal = ({ authors: $authors, affiliations: $affiliations, aff
364
364
  react_1.default.createElement(StyledModalBody, null,
365
365
  react_1.default.createElement(style_guide_1.ModalSidebar, null,
366
366
  react_1.default.createElement(StyledModalSidebarHeader, null,
367
- react_1.default.createElement(style_guide_1.ModalSidebarTitle, null, "Affiliations")),
367
+ react_1.default.createElement(style_guide_1.ModalSidebarTitle, null, "Institutional Affiliations")),
368
368
  react_1.default.createElement(StyledSidebarContent, null,
369
369
  react_1.default.createElement(AddAffiliationButton, { "data-cy": "add-affiliation-button", onClick: handleAddAffiliation, "data-active": newAffiliation },
370
370
  react_1.default.createElement(style_guide_1.AddIcon, { width: 18, height: 18 }),
371
371
  react_1.default.createElement(ActionTitle, null, "New Affiliation")),
372
372
  react_1.default.createElement(AffiliationList_1.AffiliationList, { affiliation: selection, affiliations: affiliations, onSelect: handleSelect, onDelete: handleShowDeleteDialog, lastSavedAffiliationId: savedAffiliationId }))),
373
- react_1.default.createElement(style_guide_1.ScrollableModalContent, { "data-cy": "affiliations-modal-content" }, selection ? (react_1.default.createElement(react_1.default.Fragment, null,
374
- react_1.default.createElement(AffiliationTabs, null,
375
- react_1.default.createElement(ModalFormActions_1.ModalFormActions, { type: 'affiliation', form: 'affiliation-form', onSubmitForm: () => actionsRef.current?.submitForm?.(), onDelete: handleDeleteAffiliation, showingDeleteDialog: showingDeleteDialog &&
373
+ react_1.default.createElement(StyledScrollableModalContent, { "data-cy": "affiliations-modal-content" }, selection ? (react_1.default.createElement(react_1.default.Fragment, null,
374
+ react_1.default.createElement(AffiliationTabs, { selectedIndex: affiliationTabIndex, onChange: setAffiliationTabIndex },
375
+ react_1.default.createElement(ModalFormActions_1.ModalFormActions, { type: "affiliation", onDelete: handleDeleteAffiliation, showingDeleteDialog: showingDeleteDialog &&
376
376
  !(showConfirmationDialog ||
377
- showRequiredFieldConfirmationDialog), showDeleteDialog: handleShowDeleteDialog, newEntity: newAffiliation, isDisableSave: isDisableSave }),
378
- react_1.default.createElement(style_guide_1.InspectorTabList, null,
379
- react_1.default.createElement(style_guide_1.InspectorTab, null, "Details"),
380
- onOpenAuthorsModal && react_1.default.createElement(style_guide_1.InspectorTab, null, "Authors")),
377
+ showRequiredFieldConfirmationDialog), showDeleteDialog: handleShowDeleteDialog }),
378
+ react_1.default.createElement(ModalTabs_1.ModalTabs, { tabLabels: ['Affiliation Details', 'Authors'], tabErrorIndicators: [affiliationTabHasError, false], tabWarningIndicators: [
379
+ affiliationDetailsUnsavedContinue &&
380
+ !affiliationTabHasError,
381
+ false,
382
+ ] }),
381
383
  react_1.default.createElement(style_guide_1.InspectorTabPanels, null,
382
384
  react_1.default.createElement(AffiliationTabPanel, null,
383
- react_1.default.createElement(AffiliationForm_1.AffiliationForm, { values: (0, normalize_1.checkID)(selection, 'affiliation'), onSave: (attrs) => handleSaveAffiliation(attrs), onChange: handleAffiliationChange, actionsRef: actionsRef })),
384
- onOpenAuthorsModal && (react_1.default.createElement(AffiliationTabPanel, null,
385
- react_1.default.createElement(AuthorsPanel_1.AuthorsPanel, { items: makeAuthorItems(authors), selectedItems: selectedAuthors, onSelect: selectAuthor, onOpenAuthorsModal: onOpenAuthorsModal }))))),
385
+ react_1.default.createElement(AffiliationForm_1.AffiliationForm, { values: (0, normalize_1.checkID)(selection, 'affiliation'), onSave: (attrs) => handleSaveAffiliation(attrs), onChange: handleAffiliationChange, actionsRef: actionsRef, newEntity: newAffiliation, onAffiliationErrorChange: setAffiliationTabHasError, unsavedContinueActive: affiliationDetailsUnsavedContinue })),
386
+ openAuthorsModal && (react_1.default.createElement(AffiliationTabPanel, null,
387
+ react_1.default.createElement(AuthorsPanel_1.AuthorsPanel, { items: makeAuthorItems(authors), selectedItems: selectedAuthors, onSelect: selectAuthor, openAuthorsModal: openAuthorsModal }))))),
386
388
  react_1.default.createElement(ConfirmationDialog_1.ConfirmationDialog, { isOpen: showRequiredFieldConfirmationDialog, onPrimary: () => setShowRequiredFieldConfirmationDialog(false), onSecondary: handleConfirmationCancel, type: ConfirmationDialog_1.DialogType.REQUIRED, entityType: "affiliation" }),
387
- react_1.default.createElement(ConfirmationDialog_1.ConfirmationDialog, { isOpen: showConfirmationDialog, onPrimary: handleConfirmationSave, onSecondary: handleConfirmationCancel, type: ConfirmationDialog_1.DialogType.SAVE, entityType: "affiliation" }))) : (react_1.default.createElement(FormPlaceholder_1.FormPlaceholder, { type: "affiliation", title: "Affiliation Details", message: "Select an affiliation from the list to display it's details here.", placeholderIcon: react_1.default.createElement(style_guide_1.AffiliationPlaceholderIcon, null) })))),
388
- react_1.default.createElement(FormFooter_1.default, { onCancel: handleClose }))));
389
+ react_1.default.createElement(ConfirmationDialog_1.ConfirmationDialog, { isOpen: showConfirmationDialog, onPrimary: () => {
390
+ setShowConfirmationDialog(false);
391
+ setPendingSelection(null);
392
+ setPendingAction(null);
393
+ setAffiliationDetailsUnsavedContinue(true);
394
+ }, onSecondary: handleConfirmationCancel, type: ConfirmationDialog_1.DialogType.SAVE, entityType: "affiliation" }))) : (react_1.default.createElement(FormPlaceholder_1.FormPlaceholder, { type: "affiliation", title: "Affiliation Details", message: "Select an affiliation from the list to display it's details here.", placeholderIcon: react_1.default.createElement(style_guide_1.AffiliationPlaceholderIcon, null) })))),
395
+ react_1.default.createElement(FormFooter_1.default, { onCancel: handleClose, primaryAction: selection ? (react_1.default.createElement(ModalFormActions_1.ModalFormSaveButton, { form: "affiliation-form", newEntity: newAffiliation, isDisableSave: isDisableSave, onSubmitForm: () => actionsRef.current?.submitForm?.() })) : undefined }))));
389
396
  };
390
397
  exports.AffiliationsModal = AffiliationsModal;
391
398
  function createEmptyAffiliation(priority) {
@@ -440,6 +447,7 @@ const AffiliationTabPanel = (0, styled_components_1.default)(style_guide_1.Inspe
440
447
  unmount: false,
441
448
  }) `
442
449
  margin-top: ${(props) => props.theme.grid.unit * 4}px;
450
+ height: calc(100% - 16px);
443
451
  `;
444
452
  const StyledModalBody = (0, styled_components_1.default)(style_guide_1.ModalBody) `
445
453
  position: relative;
@@ -449,3 +457,6 @@ const StyledModalSidebarHeader = (0, styled_components_1.default)(style_guide_1.
449
457
  margin-top: 8px;
450
458
  margin-bottom: 16px;
451
459
  `;
460
+ const StyledScrollableModalContent = (0, styled_components_1.default)(style_guide_1.ScrollableModalContent) `
461
+ padding: 45px 16px 16px;
462
+ `;
@@ -13,7 +13,7 @@ function affiliationSecondaryLine(item) {
13
13
  }
14
14
  const AffiliationsPanel = ({ items, selectedItems = [], onSelect, onOpenAffiliationsModal, }) => {
15
15
  const selectedIds = (0, GenericPanel_1.useListSelectedIds)(selectedItems);
16
- return (react_1.default.createElement(GenericPanel_1.GenericPanel, { title: "Institutional Affiliations", createLabel: "Create New Affiliation", onCreate: onOpenAffiliationsModal, createDataCy: "add-affiliations-link", emptyDataCy: "affiliations-panel-empty", isEmpty: items.length === 0, emptyIcon: react_1.default.createElement(style_guide_1.AffiliationPlaceholderIcon, null), emptyMessage: react_1.default.createElement(react_1.default.Fragment, null,
16
+ return (react_1.default.createElement(GenericPanel_1.GenericPanel, { title: "Institutional Affiliations", createLabel: "Create New Affiliation", onCreate: onOpenAffiliationsModal, createDataCy: "add-affiliations-link", emptyDataCy: "affiliations-panel-empty", isEmpty: items.length === 0, emptyIcon: react_1.default.createElement(style_guide_1.InfoCircleIcon, null), emptyMessage: react_1.default.createElement(react_1.default.Fragment, null,
17
17
  "There are no affiliations attributed yet!",
18
18
  react_1.default.createElement("br", null),
19
19
  "Click \u2018Create New Affiliation\u2019") },
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.CreateAffiliationModal = void 0;
40
+ const style_guide_1 = require("@manuscripts/style-guide");
41
+ const transform_1 = require("@manuscripts/transform");
42
+ const react_1 = __importStar(require("react"));
43
+ const normalize_1 = require("../../lib/normalize");
44
+ const CreateModalStyles_1 = require("../form/CreateModalStyles");
45
+ const FormFooter_1 = __importDefault(require("../form/FormFooter"));
46
+ const ModalFormActions_1 = require("../form/ModalFormActions");
47
+ const AffiliationForm_1 = require("./AffiliationForm");
48
+ const CreateAffiliationModal = ({ affiliationsCount, onSave, onClose, }) => {
49
+ const [isOpen, setIsOpen] = (0, react_1.useState)(true);
50
+ const [hasError, setHasError] = (0, react_1.useState)(false);
51
+ const [isDisableSave, setIsDisableSave] = (0, react_1.useState)(true);
52
+ const actionsRef = (0, react_1.useRef)(undefined);
53
+ const prevIsOpenRef = (0, react_1.useRef)(true);
54
+ (0, react_1.useEffect)(() => {
55
+ if (prevIsOpenRef.current && !isOpen) {
56
+ prevIsOpenRef.current = isOpen;
57
+ const id = window.setTimeout(() => {
58
+ onClose();
59
+ }, CreateModalStyles_1.MODAL_ON_CLOSE_NOTIFY_DELAY_MS);
60
+ return () => window.clearTimeout(id);
61
+ }
62
+ prevIsOpenRef.current = isOpen;
63
+ }, [isOpen, onClose]);
64
+ const selection = (0, react_1.useMemo)(() => ({
65
+ id: (0, transform_1.generateNodeID)(transform_1.schema.nodes.affiliation),
66
+ institution: '',
67
+ department: '',
68
+ addressLine1: '',
69
+ addressLine2: '',
70
+ addressLine3: '',
71
+ postCode: '',
72
+ country: '',
73
+ county: '',
74
+ city: '',
75
+ email: { href: '', text: '' },
76
+ priority: affiliationsCount,
77
+ }), []);
78
+ const handleSave = (values) => {
79
+ onSave({ ...(0, normalize_1.checkID)(selection, 'affiliation'), ...values });
80
+ setIsOpen(false);
81
+ };
82
+ const handleChange = (values) => {
83
+ const isInstitutionEmpty = !values.institution?.trim();
84
+ setIsDisableSave(isInstitutionEmpty);
85
+ };
86
+ return (react_1.default.createElement(style_guide_1.StyledModal, { isOpen: isOpen, onRequestClose: () => setIsOpen(false), shouldCloseOnOverlayClick: true },
87
+ react_1.default.createElement(style_guide_1.ModalContainer, { "data-cy": "create-affiliation-modal" },
88
+ react_1.default.createElement(style_guide_1.ModalHeader, null,
89
+ react_1.default.createElement(style_guide_1.CloseButton, { onClick: () => setIsOpen(false), "data-cy": "modal-close-button" })),
90
+ react_1.default.createElement(CreateModalStyles_1.StyledModalBody, null,
91
+ react_1.default.createElement(CreateModalStyles_1.StyledScrollableModalContent, null,
92
+ react_1.default.createElement(CreateModalStyles_1.FormTitle, null, "Create New Affiliation"),
93
+ react_1.default.createElement(AffiliationForm_1.AffiliationForm, { values: (0, normalize_1.checkID)(selection, 'affiliation'), onSave: handleSave, onChange: handleChange, actionsRef: actionsRef, newEntity: true, onAffiliationErrorChange: setHasError }))),
94
+ react_1.default.createElement(FormFooter_1.default, { onCancel: () => setIsOpen(false), primaryAction: react_1.default.createElement(ModalFormActions_1.ModalFormSaveButton, { form: "affiliation-form", newEntity: true, isDisableSave: isDisableSave || hasError, createLabel: "Create New Affiliation", onSubmitForm: () => actionsRef.current?.submitForm?.() }) }))));
95
+ };
96
+ exports.CreateAffiliationModal = CreateAffiliationModal;