payload 1.0.34 → 1.1.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 (150) hide show
  1. package/.eslintrc.js +1 -0
  2. package/components/elements.ts +1 -1
  3. package/components/index.js +2 -2
  4. package/dist/admin/components/elements/DeleteDocument/index.js +6 -6
  5. package/dist/admin/components/elements/DuplicateDocument/index.js +4 -4
  6. package/dist/admin/components/elements/GenerateConfirmation/index.js +7 -5
  7. package/dist/admin/components/elements/ListControls/index.js +3 -2
  8. package/dist/admin/components/elements/Nav/index.js +43 -24
  9. package/dist/admin/components/elements/Nav/index.scss +22 -26
  10. package/dist/admin/components/elements/NavGroup/index.d.ts +8 -0
  11. package/dist/admin/components/elements/NavGroup/index.js +52 -0
  12. package/dist/admin/components/elements/NavGroup/index.scss +53 -0
  13. package/dist/admin/components/elements/Popup/index.js +14 -13
  14. package/dist/admin/components/elements/SearchFilter/index.js +45 -16
  15. package/dist/admin/components/elements/SearchFilter/types.d.ts +2 -0
  16. package/dist/admin/components/elements/Status/index.js +14 -9
  17. package/dist/admin/components/elements/WhereBuilder/index.js +14 -1
  18. package/dist/admin/components/forms/Error/index.scss +2 -1
  19. package/dist/admin/components/forms/Form/buildStateFromSchema/addFieldStatePromise.js +3 -3
  20. package/dist/admin/components/forms/Label/index.scss +3 -1
  21. package/dist/admin/components/forms/field-types/Array/index.js +14 -9
  22. package/dist/admin/components/forms/field-types/Blocks/index.js +12 -7
  23. package/dist/admin/components/forms/field-types/Collapsible/index.js +7 -7
  24. package/dist/admin/components/forms/field-types/RichText/RichText.d.ts +2 -2
  25. package/dist/admin/components/forms/field-types/RichText/RichText.js +3 -6
  26. package/dist/admin/components/forms/field-types/RichText/elements/indent/index.js +0 -3
  27. package/dist/admin/components/forms/field-types/RichText/elements/index.d.ts +6 -3
  28. package/dist/admin/components/forms/field-types/RichText/elements/link/Button.d.ts +4 -0
  29. package/dist/admin/components/forms/field-types/RichText/elements/link/Button.js +105 -0
  30. package/dist/admin/components/forms/field-types/RichText/elements/link/Element.d.ts +9 -0
  31. package/dist/admin/components/forms/field-types/RichText/elements/link/Element.js +120 -0
  32. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/baseFields.d.ts +3 -0
  33. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/baseFields.js +56 -0
  34. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/index.d.ts +4 -0
  35. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/index.js +22 -0
  36. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/index.scss +29 -0
  37. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/types.d.ts +9 -0
  38. package/dist/admin/components/forms/field-types/RichText/elements/link/Modal/types.js +1 -0
  39. package/dist/admin/components/forms/field-types/RichText/elements/link/index.d.ts +6 -5
  40. package/dist/admin/components/forms/field-types/RichText/elements/link/index.js +4 -67
  41. package/dist/admin/components/forms/field-types/RichText/elements/link/index.scss +36 -63
  42. package/dist/admin/components/forms/field-types/RichText/elements/link/shared.d.ts +1 -0
  43. package/dist/admin/components/forms/field-types/RichText/elements/link/shared.js +1 -0
  44. package/dist/admin/components/forms/field-types/RichText/elements/link/utilities.d.ts +1 -1
  45. package/dist/admin/components/forms/field-types/RichText/elements/link/utilities.js +13 -23
  46. package/dist/admin/components/forms/field-types/RichText/elements/relationship/Button/index.js +6 -10
  47. package/dist/admin/components/forms/field-types/RichText/elements/toggle.js +0 -3
  48. package/dist/admin/components/forms/field-types/RichText/elements/upload/Button/index.js +8 -12
  49. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/EditModal/index.js +2 -3
  50. package/dist/admin/components/forms/field-types/RichText/elements/upload/Element/index.js +6 -6
  51. package/dist/admin/components/forms/field-types/RichText/types.d.ts +0 -4
  52. package/dist/admin/components/forms/field-types/Tabs/index.js +4 -4
  53. package/dist/admin/components/forms/field-types/Text/Input.d.ts +2 -0
  54. package/dist/admin/components/forms/field-types/Text/Input.js +2 -3
  55. package/dist/admin/components/forms/field-types/Text/index.js +2 -2
  56. package/dist/admin/components/forms/field-types/Text/types.d.ts +3 -0
  57. package/dist/admin/components/forms/field-types/Upload/Add/index.js +4 -4
  58. package/dist/admin/components/forms/field-types/Upload/Input.js +3 -3
  59. package/dist/admin/components/forms/field-types/Upload/SelectExisting/index.js +6 -6
  60. package/dist/admin/components/forms/field-types/rowReducer.d.ts +1 -0
  61. package/dist/admin/components/forms/field-types/rowReducer.js +2 -2
  62. package/dist/admin/components/graphics/Account/Gravatar.d.ts +3 -0
  63. package/dist/admin/components/graphics/Account/Gravatar.js +15 -0
  64. package/dist/admin/components/graphics/Account/index.d.ts +2 -2
  65. package/dist/admin/components/graphics/Account/index.js +24 -1
  66. package/dist/admin/components/modals/StayLoggedIn/index.js +4 -3
  67. package/dist/admin/components/utilities/Auth/index.js +1 -1
  68. package/dist/admin/components/views/Account/index.js +1 -1
  69. package/dist/admin/components/views/Dashboard/Default.js +44 -12
  70. package/dist/admin/components/views/Dashboard/index.scss +1 -1
  71. package/dist/admin/components/views/Version/Restore/index.js +3 -3
  72. package/dist/admin/components/views/collections/List/RelationshipProvider/index.js +1 -1
  73. package/dist/admin/components/views/collections/List/getInitialColumns.js +2 -2
  74. package/dist/admin/hooks/useThrottledEffect.js +15 -10
  75. package/dist/admin/index.js +1 -1
  76. package/dist/admin/scss/vars.scss +2 -2
  77. package/dist/admin/utilities/groupNavItems.d.ts +19 -0
  78. package/dist/admin/utilities/groupNavItems.js +36 -0
  79. package/dist/auth/types.d.ts +1 -1
  80. package/dist/bin/generateTypes.js +20 -4
  81. package/dist/collections/config/schema.js +18 -2
  82. package/dist/collections/config/types.d.ts +9 -0
  83. package/dist/collections/operations/create.js +3 -1
  84. package/dist/collections/operations/local/create.d.ts +2 -2
  85. package/dist/collections/operations/local/create.js +3 -3
  86. package/dist/collections/operations/local/update.js +2 -2
  87. package/dist/collections/operations/restoreVersion.js +11 -1
  88. package/dist/collections/operations/update.js +3 -1
  89. package/dist/config/defaults.js +2 -1
  90. package/dist/config/schema.js +3 -1
  91. package/dist/config/types.d.ts +1 -0
  92. package/dist/fields/config/schema.js +14 -6
  93. package/dist/fields/config/types.d.ts +45 -9
  94. package/dist/fields/config/types.js +10 -2
  95. package/dist/fields/hooks/afterChange/index.d.ts +2 -1
  96. package/dist/fields/hooks/afterChange/index.js +4 -2
  97. package/dist/fields/hooks/afterChange/promise.d.ts +5 -3
  98. package/dist/fields/hooks/afterChange/promise.js +49 -18
  99. package/dist/fields/hooks/afterChange/traverseFields.d.ts +5 -3
  100. package/dist/fields/hooks/afterChange/traverseFields.js +4 -2
  101. package/dist/fields/hooks/afterRead/promise.d.ts +2 -2
  102. package/dist/fields/hooks/afterRead/promise.js +50 -22
  103. package/dist/fields/hooks/afterRead/traverseFields.d.ts +2 -2
  104. package/dist/fields/hooks/beforeChange/promise.d.ts +2 -2
  105. package/dist/fields/hooks/beforeChange/promise.js +51 -20
  106. package/dist/fields/hooks/beforeChange/traverseFields.d.ts +2 -2
  107. package/dist/fields/hooks/beforeValidate/promise.d.ts +2 -2
  108. package/dist/fields/hooks/beforeValidate/promise.js +35 -15
  109. package/dist/fields/hooks/beforeValidate/traverseFields.d.ts +2 -2
  110. package/dist/fields/richText/recurseNestedFields.js +3 -3
  111. package/dist/fields/richText/{relationshipPromise.d.ts → richTextRelationshipPromise.d.ts} +0 -0
  112. package/dist/fields/richText/richTextRelationshipPromise.js +104 -0
  113. package/dist/globals/config/schema.js +2 -1
  114. package/dist/globals/config/types.d.ts +2 -0
  115. package/dist/globals/operations/restoreVersion.js +10 -1
  116. package/dist/globals/operations/update.js +4 -1
  117. package/dist/graphql/schema/buildMutationInputType.js +27 -13
  118. package/dist/graphql/schema/buildObjectType.js +18 -3
  119. package/dist/graphql/schema/withNullableType.d.ts +2 -2
  120. package/dist/graphql/schema/withNullableType.js +1 -1
  121. package/dist/mongoose/buildQuery.js +4 -2
  122. package/dist/mongoose/buildSchema.js +25 -14
  123. package/dist/types/index.d.ts +1 -1
  124. package/dist/uploads/getBaseFields.js +3 -3
  125. package/dist/uploads/getFileByPath.d.ts +1 -1
  126. package/dist/uploads/getFileByPath.js +5 -5
  127. package/dist/uploads/getSafeFilename.js +3 -4
  128. package/dist/uploads/imageResizer.d.ts +1 -9
  129. package/dist/uploads/imageResizer.js +18 -18
  130. package/dist/uploads/types.d.ts +18 -3
  131. package/dist/uploads/uploadFile.js +29 -8
  132. package/dist/utilities/flattenTopLevelFields.js +2 -2
  133. package/dist/utilities/groupOrTabHasRequiredSubfield.d.ts +2 -0
  134. package/dist/utilities/groupOrTabHasRequiredSubfield.js +17 -0
  135. package/dist/utilities/logger.js +2 -3
  136. package/dist/utilities/wordBoundariesRegex.js +2 -2
  137. package/docs/admin/overview.mdx +2 -1
  138. package/docs/configuration/collections.mdx +14 -1
  139. package/docs/fields/array.mdx +10 -1
  140. package/docs/fields/blocks.mdx +9 -1
  141. package/docs/fields/collapsible.mdx +13 -5
  142. package/docs/fields/rich-text.mdx +7 -0
  143. package/docs/fields/tabs.mdx +4 -2
  144. package/docs/hooks/collections.mdx +3 -2
  145. package/docs/hooks/fields.mdx +11 -9
  146. package/docs/hooks/globals.mdx +1 -0
  147. package/docs/upload/overview.mdx +5 -3
  148. package/package.json +4 -4
  149. package/CHANGELOG.md +0 -1870
  150. package/dist/fields/richText/relationshipPromise.js +0 -71
@@ -1,6 +1,5 @@
1
1
  import React, { Fragment, useCallback, useEffect, useState } from 'react';
2
2
  import { Modal, useModal } from '@faceless-ui/modal';
3
- import { Transforms } from 'slate';
4
3
  import { ReactEditor, useSlate } from 'slate-react';
5
4
  import { useConfig } from '../../../../../../utilities/Config';
6
5
  import ElementButton from '../../Button';
@@ -26,14 +25,11 @@ const insertRelationship = (editor, { value, relationTo }) => {
26
25
  text,
27
26
  ],
28
27
  };
29
- if (editor.blurSelection) {
30
- Transforms.select(editor, editor.blurSelection);
31
- }
32
28
  injectVoidElement(editor, relationship);
33
29
  ReactEditor.focus(editor);
34
30
  };
35
31
  const RelationshipButton = ({ path }) => {
36
- const { open, closeAll } = useModal();
32
+ const { toggleModal } = useModal();
37
33
  const editor = useSlate();
38
34
  const { serverURL, routes: { api }, collections } = useConfig();
39
35
  const [renderModal, setRenderModal] = useState(false);
@@ -45,15 +41,15 @@ const RelationshipButton = ({ path }) => {
45
41
  const res = await requests.get(`${serverURL}${api}/${relationTo}/${value}?depth=0`);
46
42
  const json = await res.json();
47
43
  insertRelationship(editor, { value: { id: json.id }, relationTo });
48
- closeAll();
44
+ toggleModal(modalSlug);
49
45
  setRenderModal(false);
50
46
  setLoading(false);
51
- }, [editor, closeAll, api, serverURL]);
47
+ }, [editor, toggleModal, modalSlug, api, serverURL]);
52
48
  useEffect(() => {
53
49
  if (renderModal) {
54
- open(modalSlug);
50
+ toggleModal(modalSlug);
55
51
  }
56
- }, [renderModal, open, modalSlug]);
52
+ }, [renderModal, toggleModal, modalSlug]);
57
53
  if (!hasEnabledCollections)
58
54
  return null;
59
55
  return (React.createElement(Fragment, null,
@@ -64,7 +60,7 @@ const RelationshipButton = ({ path }) => {
64
60
  React.createElement("header", { className: `${baseClass}__header` },
65
61
  React.createElement("h3", null, "Add Relationship"),
66
62
  React.createElement(Button, { buttonStyle: "none", onClick: () => {
67
- closeAll();
63
+ toggleModal(modalSlug);
68
64
  setRenderModal(false);
69
65
  } },
70
66
  React.createElement(X, null))),
@@ -12,9 +12,6 @@ const toggleElement = (editor, format) => {
12
12
  else if (isList) {
13
13
  type = 'li';
14
14
  }
15
- if (editor.blurSelection) {
16
- Transforms.select(editor, editor.blurSelection);
17
- }
18
15
  Transforms.unwrapNodes(editor, {
19
16
  match: (n) => Element.isElement(n) && listTypes.includes(n.type),
20
17
  split: true,
@@ -1,6 +1,5 @@
1
1
  import React, { Fragment, useEffect, useState } from 'react';
2
2
  import { Modal, useModal } from '@faceless-ui/modal';
3
- import { Transforms } from 'slate';
4
3
  import { ReactEditor, useSlate } from 'slate-react';
5
4
  import { useConfig } from '../../../../../../utilities/Config';
6
5
  import ElementButton from '../../Button';
@@ -30,15 +29,12 @@ const insertUpload = (editor, { value, relationTo }) => {
30
29
  text,
31
30
  ],
32
31
  };
33
- if (editor.blurSelection) {
34
- Transforms.select(editor, editor.blurSelection);
35
- }
36
32
  injectVoidElement(editor, upload);
37
33
  ReactEditor.focus(editor);
38
34
  };
39
35
  const UploadButton = ({ path }) => {
40
- var _a, _b;
41
- const { open, closeAll, currentModal } = useModal();
36
+ var _a, _b, _c;
37
+ const { toggleModal, modalState } = useModal();
42
38
  const editor = useSlate();
43
39
  const { serverURL, routes: { api }, collections } = useConfig();
44
40
  const [availableCollections] = useState(() => collections.filter(({ admin: { enableRichTextRelationship }, upload }) => (Boolean(upload) && enableRichTextRelationship)));
@@ -58,7 +54,7 @@ const UploadButton = ({ path }) => {
58
54
  const [page, setPage] = useState(null);
59
55
  const modalSlug = `${path}-add-upload`;
60
56
  const moreThanOneAvailableCollection = availableCollections.length > 1;
61
- const isOpen = currentModal === modalSlug;
57
+ const isOpen = (_a = modalState[modalSlug]) === null || _a === void 0 ? void 0 : _a.isOpen;
62
58
  // If modal is open, get active page of upload gallery
63
59
  const apiURL = isOpen ? `${serverURL}${api}/${modalCollection.slug}` : null;
64
60
  const [{ data }, { setParams }] = usePayloadAPI(apiURL, {});
@@ -69,9 +65,9 @@ const UploadButton = ({ path }) => {
69
65
  }, [modalCollection]);
70
66
  useEffect(() => {
71
67
  if (renderModal) {
72
- open(modalSlug);
68
+ toggleModal(modalSlug);
73
69
  }
74
- }, [renderModal, open, modalSlug]);
70
+ }, [renderModal, toggleModal, modalSlug]);
75
71
  useEffect(() => {
76
72
  const params = {};
77
73
  if (page)
@@ -102,7 +98,7 @@ const UploadButton = ({ path }) => {
102
98
  ' ',
103
99
  modalCollection.labels.singular),
104
100
  React.createElement(Button, { icon: "x", round: true, buttonStyle: "icon-label", iconStyle: "with-border", onClick: () => {
105
- closeAll();
101
+ toggleModal(modalSlug);
106
102
  setRenderModal(false);
107
103
  } })),
108
104
  moreThanOneAvailableCollection && (React.createElement("div", { className: `${baseModalClass}__select-collection-wrap` },
@@ -120,7 +116,7 @@ const UploadButton = ({ path }) => {
120
116
  relationTo: modalCollection.slug,
121
117
  });
122
118
  setRenderModal(false);
123
- closeAll();
119
+ toggleModal(modalSlug);
124
120
  } }),
125
121
  React.createElement("div", { className: `${baseModalClass}__page-controls` },
126
122
  React.createElement(Paginator, { limit: data.limit, totalPages: data.totalPages, page: data.page, hasPrevPage: data.hasPrevPage, hasNextPage: data.hasNextPage, prevPage: data.prevPage, nextPage: data.nextPage, numberOfNeighbors: 1, onChange: setPage, disableHistoryChange: true }),
@@ -133,6 +129,6 @@ const UploadButton = ({ path }) => {
133
129
  "of",
134
130
  ' ',
135
131
  data.totalDocs),
136
- React.createElement(PerPage, { limits: (_b = (_a = modalCollection === null || modalCollection === void 0 ? void 0 : modalCollection.admin) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.limits, limit: limit, modifySearchParams: false, handleChange: setLimit }))))))))));
132
+ React.createElement(PerPage, { limits: (_c = (_b = modalCollection === null || modalCollection === void 0 ? void 0 : modalCollection.admin) === null || _b === void 0 ? void 0 : _b.pagination) === null || _c === void 0 ? void 0 : _c.limits, limit: limit, modifySearchParams: false, handleChange: setLimit }))))))))));
137
133
  };
138
134
  export default UploadButton;
@@ -9,7 +9,6 @@ import Button from '../../../../../../../elements/Button';
9
9
  import RenderFields from '../../../../../../RenderFields';
10
10
  import fieldTypes from '../../../../..';
11
11
  import Form from '../../../../../../Form';
12
- import reduceFieldsToValues from '../../../../../../Form/reduceFieldsToValues';
13
12
  import Submit from '../../../../../../Submit';
14
13
  import { useLocale } from '../../../../../../../utilities/Locale';
15
14
  import './index.scss';
@@ -19,9 +18,9 @@ export const EditModal = ({ slug, closeModal, relatedCollectionConfig, fieldSche
19
18
  const [initialState, setInitialState] = useState({});
20
19
  const { user } = useAuth();
21
20
  const locale = useLocale();
22
- const handleUpdateEditData = useCallback((fields) => {
21
+ const handleUpdateEditData = useCallback((_, data) => {
23
22
  const newNode = {
24
- fields: reduceFieldsToValues(fields, true),
23
+ fields: data,
25
24
  };
26
25
  const elementPath = ReactEditor.findPath(editor, element);
27
26
  Transforms.setNodes(editor, newNode, { at: elementPath });
@@ -17,7 +17,7 @@ const initialParams = {
17
17
  const Element = ({ attributes, children, element, path, fieldProps }) => {
18
18
  var _a, _b, _c, _d;
19
19
  const { relationTo, value } = element;
20
- const { closeAll, open } = useModal();
20
+ const { toggleModal } = useModal();
21
21
  const { collections, serverURL, routes: { api } } = useConfig();
22
22
  const [modalToRender, setModalToRender] = useState(undefined);
23
23
  const [relatedCollection, setRelatedCollection] = useState(() => collections.find((coll) => coll.slug === relationTo));
@@ -33,14 +33,14 @@ const Element = ({ attributes, children, element, path, fieldProps }) => {
33
33
  Transforms.removeNodes(editor, { at: elementPath });
34
34
  }, [editor, element]);
35
35
  const closeModal = useCallback(() => {
36
- closeAll();
36
+ toggleModal(modalSlug);
37
37
  setModalToRender(null);
38
- }, [closeAll]);
38
+ }, [toggleModal, modalSlug]);
39
39
  useEffect(() => {
40
- if (modalToRender && modalSlug) {
41
- open(`${modalSlug}`);
40
+ if (modalToRender) {
41
+ toggleModal(modalSlug);
42
42
  }
43
- }, [modalToRender, open, modalSlug]);
43
+ }, [modalToRender, toggleModal, modalSlug]);
44
44
  const fieldSchema = (_d = (_c = (_b = (_a = fieldProps === null || fieldProps === void 0 ? void 0 : fieldProps.admin) === null || _a === void 0 ? void 0 : _a.upload) === null || _b === void 0 ? void 0 : _b.collections) === null || _c === void 0 ? void 0 : _c[relatedCollection.slug]) === null || _d === void 0 ? void 0 : _d.fields;
45
45
  return (React.createElement("div", { className: [
46
46
  baseClass,
@@ -1,8 +1,4 @@
1
- import { BaseEditor, Selection } from 'slate';
2
1
  import { RichTextField } from '../../../../../fields/config/types';
3
2
  export declare type Props = Omit<RichTextField, 'type'> & {
4
3
  path?: string;
5
4
  };
6
- export interface BlurSelectionEditor extends BaseEditor {
7
- blurSelection?: Selection;
8
- }
@@ -1,11 +1,11 @@
1
1
  import React, { useState } from 'react';
2
2
  import RenderFields from '../../RenderFields';
3
3
  import withCondition from '../../withCondition';
4
+ import { fieldAffectsData, tabHasName } from '../../../../../fields/config/types';
4
5
  import FieldDescription from '../../FieldDescription';
5
6
  import toKebabCase from '../../../../../utilities/toKebabCase';
6
7
  import { useCollapsible } from '../../../elements/Collapsible/provider';
7
8
  import { TabsProvider } from './provider';
8
- import { getFieldPath } from '../getFieldPath';
9
9
  import './index.scss';
10
10
  const baseClass = 'tabs-field';
11
11
  const TabsField = (props) => {
@@ -24,16 +24,16 @@ const TabsField = (props) => {
24
24
  return (React.createElement("button", { key: i, type: "button", className: [
25
25
  `${baseClass}__tab-button`,
26
26
  active === i && `${baseClass}__tab-button--active`,
27
- ].filter(Boolean).join(' '), onClick: () => setActive(i) }, tab.label));
27
+ ].filter(Boolean).join(' '), onClick: () => setActive(i) }, tab.label ? tab.label : (tabHasName(tab) && tab.name)));
28
28
  }))),
29
29
  React.createElement("div", { className: `${baseClass}__content-wrap` }, activeTab && (React.createElement("div", { className: [
30
30
  `${baseClass}__tab`,
31
31
  `${baseClass}__tab-${toKebabCase(activeTab.label)}`,
32
32
  ].join(' ') },
33
33
  React.createElement(FieldDescription, { className: `${baseClass}__description`, description: activeTab.description }),
34
- React.createElement(RenderFields, { key: activeTab.label, forceRender: true, readOnly: readOnly, permissions: permissions === null || permissions === void 0 ? void 0 : permissions.fields, fieldTypes: fieldTypes, fieldSchema: activeTab.fields.map((field) => ({
34
+ React.createElement(RenderFields, { forceRender: true, readOnly: readOnly, permissions: permissions === null || permissions === void 0 ? void 0 : permissions.fields, fieldTypes: fieldTypes, fieldSchema: activeTab.fields.map((field) => ({
35
35
  ...field,
36
- path: getFieldPath(path, field),
36
+ path: `${path ? `${path}.` : ''}${tabHasName(activeTab) ? `${activeTab.name}.` : ''}${fieldAffectsData(field) ? field.name : ''}`,
37
37
  })) })))))));
38
38
  };
39
39
  export default withCondition(TabsField);
@@ -11,10 +11,12 @@ export declare type TextInputProps = Omit<TextField, 'type'> & {
11
11
  value?: string;
12
12
  description?: Description;
13
13
  onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
14
+ onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
14
15
  placeholder?: string;
15
16
  style?: React.CSSProperties;
16
17
  className?: string;
17
18
  width?: string;
19
+ inputRef?: React.MutableRefObject<HTMLInputElement>;
18
20
  };
19
21
  declare const TextInput: React.FC<TextInputProps>;
20
22
  export default TextInput;
@@ -2,10 +2,9 @@ import React from 'react';
2
2
  import Label from '../../Label';
3
3
  import Error from '../../Error';
4
4
  import FieldDescription from '../../FieldDescription';
5
- // import { FieldType } from '../../useField/types';
6
5
  import './index.scss';
7
6
  const TextInput = (props) => {
8
- const { showError, errorMessage, placeholder, readOnly, path, label, required, value, onChange, description, style, className, width, } = props;
7
+ const { showError, errorMessage, placeholder, readOnly, path, label, required, value, onChange, onKeyDown, description, style, className, width, inputRef, } = props;
9
8
  const classes = [
10
9
  'field-type',
11
10
  'text',
@@ -19,7 +18,7 @@ const TextInput = (props) => {
19
18
  } },
20
19
  React.createElement(Error, { showError: showError, message: errorMessage }),
21
20
  React.createElement(Label, { htmlFor: `field-${path.replace(/\./gi, '__')}`, label: label, required: required }),
22
- React.createElement("input", { id: `field-${path.replace(/\./gi, '__')}`, value: value || '', onChange: onChange, disabled: readOnly, placeholder: placeholder, type: "text", name: path }),
21
+ React.createElement("input", { ref: inputRef, id: `field-${path.replace(/\./gi, '__')}`, value: value || '', onChange: onChange, onKeyDown: onKeyDown, disabled: readOnly, placeholder: placeholder, type: "text", name: path }),
23
22
  React.createElement(FieldDescription, { value: value, description: description })));
24
23
  };
25
24
  export default TextInput;
@@ -4,7 +4,7 @@ import withCondition from '../../withCondition';
4
4
  import { text } from '../../../../../fields/validations';
5
5
  import TextInput from './Input';
6
6
  const Text = (props) => {
7
- const { path: pathFromProps, name, required, validate = text, label, minLength, maxLength, admin: { placeholder, readOnly, style, className, width, description, condition, } = {}, } = props;
7
+ const { path: pathFromProps, name, required, validate = text, label, minLength, maxLength, admin: { placeholder, readOnly, style, className, width, description, condition, } = {}, inputRef, } = props;
8
8
  const path = pathFromProps || name;
9
9
  const memoizedValidate = useCallback((value, options) => {
10
10
  return validate(value, { ...options, minLength, maxLength, required });
@@ -18,6 +18,6 @@ const Text = (props) => {
18
18
  const { value, showError, setValue, errorMessage, } = field;
19
19
  return (React.createElement(TextInput, { path: path, name: name, onChange: (e) => {
20
20
  setValue(e.target.value);
21
- }, showError: showError, errorMessage: errorMessage, required: required, label: label, value: value, placeholder: placeholder, readOnly: readOnly, style: style, className: className, width: width, description: description }));
21
+ }, showError: showError, errorMessage: errorMessage, required: required, label: label, value: value, placeholder: placeholder, readOnly: readOnly, style: style, className: className, width: width, description: description, inputRef: inputRef }));
22
22
  };
23
23
  export default withCondition(Text);
@@ -1,4 +1,7 @@
1
+ /// <reference types="react" />
1
2
  import { TextField } from '../../../../../fields/config/types';
2
3
  export declare type Props = Omit<TextField, 'type'> & {
3
4
  path?: string;
5
+ inputRef?: React.MutableRefObject<HTMLInputElement>;
6
+ onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
4
7
  };
@@ -16,11 +16,11 @@ const AddUploadModal = (props) => {
16
16
  const { collection, collection: { admin: { description, } = {}, } = {}, slug, fieldTypes, setValue, } = props;
17
17
  const { permissions } = useAuth();
18
18
  const { serverURL, routes: { api } } = useConfig();
19
- const { closeAll } = useModal();
19
+ const { toggleModal } = useModal();
20
20
  const onSuccess = useCallback((json) => {
21
- closeAll();
21
+ toggleModal(slug);
22
22
  setValue(json.doc);
23
- }, [closeAll, setValue]);
23
+ }, [toggleModal, slug, setValue]);
24
24
  const classes = [
25
25
  baseClass,
26
26
  ].filter(Boolean).join(' ');
@@ -35,7 +35,7 @@ const AddUploadModal = (props) => {
35
35
  ' ',
36
36
  collection.labels.singular),
37
37
  React.createElement(FormSubmit, null, "Save"),
38
- React.createElement(Button, { icon: "x", round: true, buttonStyle: "icon-label", iconStyle: "with-border", onClick: closeAll })),
38
+ React.createElement(Button, { icon: "x", round: true, buttonStyle: "icon-label", iconStyle: "with-border", onClick: () => toggleModal(slug) })),
39
39
  description && (React.createElement("div", { className: `${baseClass}__sub-header` },
40
40
  React.createElement(ViewDescription, { description: description })))),
41
41
  React.createElement(Upload, { collection: collection }),
@@ -11,7 +11,7 @@ import './index.scss';
11
11
  const baseClass = 'upload';
12
12
  const UploadInput = (props) => {
13
13
  const { path, required, readOnly, style, className, width, description, label, relationTo, fieldTypes, value, onChange, showError, serverURL = 'http://localhost:3000', api = '/api', collection, errorMessage, filterOptions, } = props;
14
- const { toggle } = useModal();
14
+ const { toggleModal } = useModal();
15
15
  const addModalSlug = `${path}-add`;
16
16
  const selectExistingModalSlug = `${path}-select-existing`;
17
17
  const [file, setFile] = useState(undefined);
@@ -59,13 +59,13 @@ const UploadInput = (props) => {
59
59
  } })),
60
60
  (!file || missingFile) && (React.createElement("div", { className: `${baseClass}__wrap` },
61
61
  React.createElement(Button, { buttonStyle: "secondary", onClick: () => {
62
- toggle(addModalSlug);
62
+ toggleModal(addModalSlug);
63
63
  } },
64
64
  "Upload new",
65
65
  ' ',
66
66
  collection.labels.singular),
67
67
  React.createElement(Button, { buttonStyle: "secondary", onClick: () => {
68
- toggle(selectExistingModalSlug);
68
+ toggleModal(selectExistingModalSlug);
69
69
  } }, "Choose from existing"))),
70
70
  React.createElement(AddModal, { ...{
71
71
  collection,
@@ -18,13 +18,13 @@ import ViewDescription from '../../../../elements/ViewDescription';
18
18
  import './index.scss';
19
19
  const baseClass = 'select-existing-upload-modal';
20
20
  const SelectExistingUploadModal = (props) => {
21
- var _a, _b;
21
+ var _a, _b, _c;
22
22
  const { setValue, collection, collection: { slug: collectionSlug, admin: { description, pagination: { defaultLimit, }, } = {}, } = {}, slug: modalSlug, path, filterOptions, } = props;
23
23
  const { serverURL, routes: { api } } = useConfig();
24
24
  const { id } = useDocumentInfo();
25
25
  const { user } = useAuth();
26
26
  const { getData, getSiblingData } = useWatchForm();
27
- const { closeAll, currentModal } = useModal();
27
+ const { toggleModal, modalState } = useModal();
28
28
  const [fields] = useState(() => formatFields(collection));
29
29
  const [limit, setLimit] = useState(defaultLimit);
30
30
  const [sort, setSort] = useState(null);
@@ -34,7 +34,7 @@ const SelectExistingUploadModal = (props) => {
34
34
  const classes = [
35
35
  baseClass,
36
36
  ].filter(Boolean).join(' ');
37
- const isOpen = currentModal === modalSlug;
37
+ const isOpen = (_a = modalState[modalSlug]) === null || _a === void 0 ? void 0 : _a.isOpen;
38
38
  const apiURL = isOpen ? `${serverURL}${api}/${collectionSlug}` : null;
39
39
  const [{ data }, { setParams }] = usePayloadAPI(apiURL, {});
40
40
  useEffect(() => {
@@ -72,7 +72,7 @@ const SelectExistingUploadModal = (props) => {
72
72
  "Select existing",
73
73
  ' ',
74
74
  collection.labels.singular),
75
- React.createElement(Button, { icon: "x", round: true, buttonStyle: "icon-label", iconStyle: "with-border", onClick: closeAll })),
75
+ React.createElement(Button, { icon: "x", round: true, buttonStyle: "icon-label", iconStyle: "with-border", onClick: () => toggleModal(modalSlug) })),
76
76
  description && (React.createElement("div", { className: `${baseClass}__sub-header` },
77
77
  React.createElement(ViewDescription, { description: description })))),
78
78
  React.createElement(ListControls, { collection: {
@@ -81,7 +81,7 @@ const SelectExistingUploadModal = (props) => {
81
81
  }, enableColumns: false, enableSort: true, modifySearchQuery: false, handleSortChange: setSort, handleWhereChange: setWhere }),
82
82
  React.createElement(UploadGallery, { docs: data === null || data === void 0 ? void 0 : data.docs, collection: collection, onCardClick: (doc) => {
83
83
  setValue(doc);
84
- closeAll();
84
+ toggleModal(modalSlug);
85
85
  } }),
86
86
  React.createElement("div", { className: `${baseClass}__page-controls` },
87
87
  React.createElement(Paginator, { limit: data.limit, totalPages: data.totalPages, page: data.page, hasPrevPage: data.hasPrevPage, hasNextPage: data.hasNextPage, prevPage: data.prevPage, nextPage: data.nextPage, numberOfNeighbors: 1, onChange: setPage, disableHistoryChange: true }),
@@ -94,6 +94,6 @@ const SelectExistingUploadModal = (props) => {
94
94
  "of",
95
95
  ' ',
96
96
  data.totalDocs),
97
- React.createElement(PerPage, { limits: (_b = (_a = collection === null || collection === void 0 ? void 0 : collection.admin) === null || _a === void 0 ? void 0 : _a.pagination) === null || _b === void 0 ? void 0 : _b.limits, limit: limit, modifySearchParams: false, handleChange: setLimit }))))))));
97
+ React.createElement(PerPage, { limits: (_c = (_b = collection === null || collection === void 0 ? void 0 : collection.admin) === null || _b === void 0 ? void 0 : _b.pagination) === null || _c === void 0 ? void 0 : _c.limits, limit: limit, modifySearchParams: false, handleChange: setLimit }))))))));
98
98
  };
99
99
  export default SelectExistingUploadModal;
@@ -11,6 +11,7 @@ declare type SET_ALL = {
11
11
  }[];
12
12
  collapsedState?: string[];
13
13
  blockType?: string;
14
+ initCollapsed?: boolean;
14
15
  };
15
16
  declare type SET_COLLAPSE = {
16
17
  type: 'SET_COLLAPSE';
@@ -3,12 +3,12 @@ const reducer = (currentState, action) => {
3
3
  const stateCopy = [...currentState || []];
4
4
  switch (action.type) {
5
5
  case 'SET_ALL': {
6
- const { data, collapsedState } = action;
6
+ const { data, collapsedState, initCollapsed } = action;
7
7
  if (Array.isArray(data)) {
8
8
  return data.map((dataRow, i) => {
9
9
  const row = {
10
10
  id: (dataRow === null || dataRow === void 0 ? void 0 : dataRow.id) || new ObjectID().toHexString(),
11
- collapsed: (collapsedState || []).includes(dataRow === null || dataRow === void 0 ? void 0 : dataRow.id),
11
+ collapsed: Array.isArray(collapsedState) ? collapsedState.includes(dataRow === null || dataRow === void 0 ? void 0 : dataRow.id) : initCollapsed,
12
12
  blockType: dataRow === null || dataRow === void 0 ? void 0 : dataRow.blockType,
13
13
  };
14
14
  return row;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const Gravatar: React.FC;
3
+ export default Gravatar;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import md5 from 'md5';
3
+ import qs from 'qs';
4
+ import { useAuth } from '../../utilities/Auth';
5
+ const Gravatar = () => {
6
+ const { user } = useAuth();
7
+ const hash = md5(user.email.trim().toLowerCase());
8
+ const query = qs.stringify({
9
+ s: 50,
10
+ r: 'g',
11
+ default: 'mp',
12
+ });
13
+ return (React.createElement("img", { className: "gravatar-account", style: { borderRadius: '50%' }, src: `https://www.gravatar.com/avatar/${hash}?${query}`, alt: "yas", width: 25, height: 25 }));
14
+ };
15
+ export default Gravatar;
@@ -1,3 +1,3 @@
1
- import React from 'react';
2
- declare const Account: React.FC;
1
+ /// <reference types="react" />
2
+ declare const Account: () => JSX.Element;
3
3
  export default Account;
@@ -1,4 +1,7 @@
1
1
  import React from 'react';
2
+ import { useAuth } from '../../utilities/Auth';
3
+ import { useConfig } from '../../utilities/Config';
4
+ import Gravatar from './Gravatar';
2
5
  const css = `
3
6
  .graphic-account .circle1 {
4
7
  fill: var(--theme-elevation-100);
@@ -8,9 +11,29 @@ const css = `
8
11
  fill: var(--theme-elevation-300);
9
12
  }
10
13
  `;
11
- const Account = () => (React.createElement("svg", { className: "graphic-account", width: "25", height: "25", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 25" },
14
+ const Default = () => (React.createElement("svg", { className: "graphic-account", width: "25", height: "25", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 25 25" },
12
15
  React.createElement("style", null, css),
13
16
  React.createElement("circle", { className: "circle1", cx: "12.5", cy: "12.5", r: "11.5" }),
14
17
  React.createElement("circle", { className: "circle2", cx: "12.5", cy: "10.73", r: "3.98" }),
15
18
  React.createElement("path", { d: "M12.5,24a11.44,11.44,0,0,0,7.66-2.94c-.5-2.71-3.73-4.8-7.66-4.8s-7.16,2.09-7.66,4.8A11.44,11.44,0,0,0,12.5,24Z" })));
19
+ const Account = () => {
20
+ const { admin: { avatar: Avatar }, } = useConfig();
21
+ const { user } = useAuth();
22
+ if (!user.email || Avatar === 'default')
23
+ return React.createElement(Default, null);
24
+ if (Avatar === 'gravatar')
25
+ return React.createElement(Gravatar, null);
26
+ if (Avatar)
27
+ return React.createElement(Avatar, null);
28
+ return React.createElement(Default, null);
29
+ };
16
30
  export default Account;
31
+ function isClassComponent(component) {
32
+ return typeof component === 'function' && !!component.prototype.isReactComponent;
33
+ }
34
+ function isFunctionComponent(component) {
35
+ return typeof component === 'function' && String(component).includes('return React.createElement');
36
+ }
37
+ function isReactComponent(component) {
38
+ return isClassComponent(component) || isFunctionComponent(component);
39
+ }
@@ -6,23 +6,24 @@ import MinimalTemplate from '../../templates/Minimal';
6
6
  import Button from '../../elements/Button';
7
7
  import './index.scss';
8
8
  const baseClass = 'stay-logged-in';
9
+ const modalSlug = 'stay-logged-in';
9
10
  const StayLoggedInModal = (props) => {
10
11
  const { refreshCookie } = props;
11
12
  const history = useHistory();
12
13
  const { routes: { admin } } = useConfig();
13
- const { closeAll: closeAllModals } = useModal();
14
+ const { toggleModal } = useModal();
14
15
  return (React.createElement(Modal, { className: baseClass, slug: "stay-logged-in" },
15
16
  React.createElement(MinimalTemplate, { className: `${baseClass}__template` },
16
17
  React.createElement("h1", null, "Stay logged in"),
17
18
  React.createElement("p", null, "You haven't been active in a little while and will shortly be automatically logged out for your own security. Would you like to stay logged in?"),
18
19
  React.createElement("div", { className: `${baseClass}__actions` },
19
20
  React.createElement(Button, { buttonStyle: "secondary", onClick: () => {
20
- closeAllModals();
21
+ toggleModal(modalSlug);
21
22
  history.push(`${admin}/logout`);
22
23
  } }, "Log out"),
23
24
  React.createElement(Button, { onClick: () => {
24
25
  refreshCookie();
25
- closeAllModals();
26
+ toggleModal(modalSlug);
26
27
  } }, "Stay logged in")))));
27
28
  };
28
29
  export default StayLoggedInModal;
@@ -16,7 +16,7 @@ export const AuthProvider = ({ children }) => {
16
16
  const { admin: { user: userSlug, }, serverURL, routes: { admin, api, }, } = config;
17
17
  const exp = user === null || user === void 0 ? void 0 : user.exp;
18
18
  const [permissions, setPermissions] = useState();
19
- const { open: openModal, closeAll: closeAllModals } = useModal();
19
+ const { openModal, closeAllModals } = useModal();
20
20
  const [lastLocationChange, setLastLocationChange] = useState(0);
21
21
  const debouncedLocationChange = useDebounce(lastLocationChange, 10000);
22
22
  const id = user === null || user === void 0 ? void 0 : user.id;
@@ -24,7 +24,7 @@ const AccountView = () => {
24
24
  }, } = {}, } = {
25
25
  user: 'users',
26
26
  }, } = useConfig();
27
- const collection = collections.find((coll) => coll.slug === user.collection);
27
+ const collection = collections.find((coll) => coll.slug === adminUser);
28
28
  const { fields } = collection;
29
29
  const collectionPermissions = (_a = permissions === null || permissions === void 0 ? void 0 : permissions.collections) === null || _a === void 0 ? void 0 : _a[adminUser];
30
30
  const [{ data }] = usePayloadAPI(`${serverURL}${api}/${collection === null || collection === void 0 ? void 0 : collection.slug}/${user === null || user === void 0 ? void 0 : user.id}?depth=0`, { initialParams: { 'fallback-locale': 'null' } });
@@ -1,31 +1,63 @@
1
- import React from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { useHistory } from 'react-router-dom';
3
3
  import { useConfig } from '../../utilities/Config';
4
4
  import Eyebrow from '../../elements/Eyebrow';
5
5
  import Card from '../../elements/Card';
6
6
  import Button from '../../elements/Button';
7
7
  import { Gutter } from '../../elements/Gutter';
8
+ import { groupNavItems, EntityType } from '../../../utilities/groupNavItems';
8
9
  import './index.scss';
9
10
  const baseClass = 'dashboard';
10
11
  const Dashboard = (props) => {
11
12
  const { collections, globals, permissions, } = props;
12
13
  const { push } = useHistory();
13
14
  const { routes: { admin, }, admin: { components: { afterDashboard, beforeDashboard, }, }, } = useConfig();
15
+ const [groups, setGroups] = useState([]);
16
+ useEffect(() => {
17
+ setGroups(groupNavItems([
18
+ ...collections.map((collection) => {
19
+ const entityToGroup = {
20
+ type: EntityType.collection,
21
+ entity: collection,
22
+ };
23
+ return entityToGroup;
24
+ }),
25
+ ...globals.map((global) => {
26
+ const entityToGroup = {
27
+ type: EntityType.global,
28
+ entity: global,
29
+ };
30
+ return entityToGroup;
31
+ }),
32
+ ], permissions));
33
+ }, [collections, globals, permissions]);
14
34
  return (React.createElement("div", { className: baseClass },
15
35
  React.createElement(Eyebrow, null),
16
36
  React.createElement(Gutter, { className: `${baseClass}__wrap` },
17
37
  Array.isArray(beforeDashboard) && beforeDashboard.map((Component, i) => React.createElement(Component, { key: i })),
18
- React.createElement("h2", { className: `${baseClass}__label` }, "Collections"),
19
- React.createElement("ul", { className: `${baseClass}__card-list` }, collections.map((collection) => {
20
- var _a, _b, _c;
21
- const hasCreatePermission = (_c = (_b = (_a = permissions === null || permissions === void 0 ? void 0 : permissions.collections) === null || _a === void 0 ? void 0 : _a[collection.slug]) === null || _b === void 0 ? void 0 : _b.create) === null || _c === void 0 ? void 0 : _c.permission;
22
- return (React.createElement("li", { key: collection.slug },
23
- React.createElement(Card, { title: collection.labels.plural, id: `card-${collection.slug}`, onClick: () => push({ pathname: `${admin}/collections/${collection.slug}` }), actions: hasCreatePermission ? (React.createElement(Button, { el: "link", to: `${admin}/collections/${collection.slug}/create`, icon: "plus", round: true, buttonStyle: "icon-label", iconStyle: "with-border" })) : undefined })));
24
- })),
25
- (globals.length > 0) && (React.createElement(React.Fragment, null,
26
- React.createElement("h2", { className: `${baseClass}__label` }, "Globals"),
27
- React.createElement("ul", { className: `${baseClass}__card-list` }, globals.map((global) => (React.createElement("li", { key: global.slug },
28
- React.createElement(Card, { title: global.label, onClick: () => push({ pathname: `${admin}/globals/${global.slug}` }) }))))))),
38
+ groups.map(({ label, entities }, groupIndex) => {
39
+ return (React.createElement(React.Fragment, { key: groupIndex },
40
+ React.createElement("h2", { className: `${baseClass}__label` }, label),
41
+ React.createElement("ul", { className: `${baseClass}__card-list` }, entities.map(({ entity, type }, entityIndex) => {
42
+ var _a, _b, _c;
43
+ let title;
44
+ let createHREF;
45
+ let onClick;
46
+ let hasCreatePermission;
47
+ if (type === EntityType.collection) {
48
+ title = entity.labels.plural;
49
+ onClick = () => push({ pathname: `${admin}/collections/${entity.slug}` });
50
+ createHREF = `${admin}/collections/${entity.slug}/create`;
51
+ hasCreatePermission = (_c = (_b = (_a = permissions === null || permissions === void 0 ? void 0 : permissions.collections) === null || _a === void 0 ? void 0 : _a[entity.slug]) === null || _b === void 0 ? void 0 : _b.create) === null || _c === void 0 ? void 0 : _c.permission;
52
+ }
53
+ if (type === EntityType.global) {
54
+ title = entity.label;
55
+ onClick = () => push({ pathname: `${admin}/globals/${global.slug}` });
56
+ }
57
+ return (React.createElement("li", { key: entityIndex },
58
+ React.createElement(Card, { title: title, id: `card-${entity.slug}`, onClick: onClick, actions: (hasCreatePermission && type === EntityType.collection) ? (React.createElement(Button, { el: "link", to: createHREF, icon: "plus", round: true, buttonStyle: "icon-label", iconStyle: "with-border" })) : undefined })));
59
+ }))));
60
+ }),
29
61
  Array.isArray(afterDashboard) && afterDashboard.map((Component, i) => React.createElement(Component, { key: i })))));
30
62
  };
31
63
  export default Dashboard;
@@ -57,4 +57,4 @@
57
57
  margin: 0 base(.25) base(.5);
58
58
  }
59
59
  }
60
- }
60
+ }