@strapi/admin 4.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/admin/src/components/Notifications/Notification/index.js +3 -3
  2. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +2 -2
  3. package/admin/src/content-manager/components/ComponentInitializer/index.js +4 -9
  4. package/admin/src/content-manager/components/DragLayer/index.js +1 -1
  5. package/admin/src/content-manager/components/DynamicTable/index.js +7 -0
  6. package/admin/src/content-manager/components/DynamicZone/index.js +25 -5
  7. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/schema.js +4 -1
  8. package/admin/src/content-manager/components/RepeatableComponent/AccordionGroupCustom/index.js +1 -3
  9. package/admin/src/content-manager/components/SelectWrapper/index.js +15 -81
  10. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +2 -2
  11. package/admin/src/content-manager/pages/App/LeftMenu/index.js +2 -6
  12. package/admin/src/content-manager/pages/App/index.js +3 -1
  13. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -1
  14. package/admin/src/content-manager/pages/EditView/Informations/index.js +37 -13
  15. package/admin/src/content-manager/pages/ListSettingsView/components/CardPreview.js +19 -8
  16. package/admin/src/content-manager/pages/ListSettingsView/components/DraggableCard.js +123 -67
  17. package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +4 -1
  18. package/admin/src/content-manager/pages/ListSettingsView/index.js +1 -1
  19. package/admin/src/content-manager/pages/ListView/index.js +37 -20
  20. package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +1 -1
  21. package/admin/src/pages/App/utils/unique-identifier.js +3 -1
  22. package/admin/src/pages/AuthPage/index.js +8 -2
  23. package/admin/src/pages/ProfilePage/index.js +32 -6
  24. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -2
  25. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +20 -7
  26. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
  27. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +3 -3
  28. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +3 -3
  29. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/utils/stepper.js +1 -1
  30. package/admin/src/pages/SettingsPage/pages/Users/ListPage/index.js +5 -11
  31. package/admin/src/pages/SettingsPage/pages/Users/ListPage/utils/tableHeaders.js +1 -1
  32. package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/index.js +1 -1
  33. package/admin/src/pages/SettingsPage/pages/Users/components/SelectRoles/index.js +1 -1
  34. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/index.js +1 -1
  35. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/index.js +1 -1
  36. package/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js +5 -5
  37. package/admin/src/translations/en.json +29 -23
  38. package/admin/src/translations/fr.json +315 -6
  39. package/admin/src/translations/ko.json +670 -263
  40. package/admin/src/translations/nl.json +1 -1
  41. package/admin/src/translations/zh.json +482 -41
  42. package/build/{01a600d9e6e0dea21e33017a97bdf431.png → 01a600d9e6e0dea21e33.png} +0 -0
  43. package/build/{15026a3d58aeb282813457f060f2d6ac.png → 15026a3d58aeb2828134.png} +0 -0
  44. package/build/{1551f4f60c37af51121f106501f69b80.woff2 → 1551f4f60c37af51121f.woff2} +0 -0
  45. package/build/{1e59d2330b4c6deb84b340635ed36249.ttf → 1e59d2330b4c6deb84b3.ttf} +0 -0
  46. package/build/{20fd1704ea223900efa9fd4e869efb08.woff2 → 20fd1704ea223900efa9.woff2} +0 -0
  47. package/build/{2285773e6b4b172f07d9b777c81b0775.woff → 2285773e6b4b172f07d9.woff} +0 -0
  48. package/build/{23f19bb08961f37aaf692ff943823453.eot → 23f19bb08961f37aaf69.eot} +0 -0
  49. package/build/2664.f33f619d.chunk.js +2 -0
  50. package/build/2664.f33f619d.chunk.js.LICENSE.txt +7 -0
  51. package/build/{2a9e9ef5c4c775bb7c7b3625041b1354.png → 2a9e9ef5c4c775bb7c7b.png} +0 -0
  52. package/build/{2f517e09eb2ca6650ff5bec5a95157ab.svg → 2f517e09eb2ca6650ff5.svg} +0 -0
  53. package/build/3226.1a4b5cd1.chunk.js +2 -0
  54. package/build/{3226.0dc582b2.chunk.js.LICENSE.txt → 3226.1a4b5cd1.chunk.js.LICENSE.txt} +0 -0
  55. package/build/4362.c65ab24b.chunk.js +1 -0
  56. package/build/{4689f52cc96215721344e51e5831eec1.svg → 4689f52cc96215721344.svg} +0 -0
  57. package/build/{4715.35096dd7.chunk.js → 4715.f134f37a.chunk.js} +1 -1
  58. package/build/{491974d108fe4002b2aaf7ffc48249a0.ttf → 491974d108fe4002b2aa.ttf} +0 -0
  59. package/build/{527940b104eb2ea366c8630f3f038603.ttf → 527940b104eb2ea366c8.ttf} +0 -0
  60. package/build/{77206a6bb316fa0aded5083cc57f92b9.eot → 77206a6bb316fa0aded5.eot} +0 -0
  61. package/build/{7a3337626410ca2f40718481c755640f.woff2 → 7a3337626410ca2f4071.woff2} +0 -0
  62. package/build/{7a8b4f130182d19a2d7c67d80c090397.svg → 7a8b4f130182d19a2d7c.svg} +0 -0
  63. package/build/{849.fc26299c.chunk.js → 849.35b7e7af.chunk.js} +1 -1
  64. package/build/{8b43027f47b20503057dfbbaa9401fef.eot → 8b43027f47b20503057d.eot} +0 -0
  65. package/build/{9238.f112d6c9.chunk.js → 9238.63386655.chunk.js} +1 -1
  66. package/build/{9bbb245e67a133f6e486d8d2545e14a5.eot → 9bbb245e67a133f6e486.eot} +0 -0
  67. package/build/{Admin-authenticatedApp.0298a225.chunk.js → Admin-authenticatedApp.bcc1dcbe.chunk.js} +1 -1
  68. package/build/{Admin_homePage.31e37124.chunk.js → Admin_homePage.74b48134.chunk.js} +1 -1
  69. package/build/Admin_marketplace.8d0028cc.chunk.js +1 -0
  70. package/build/Admin_profilePage.f276f571.chunk.js +1 -0
  71. package/build/Admin_settingsPage.1947fe0c.chunk.js +1 -0
  72. package/build/{admin-edit-roles-page.e91bd9e5.chunk.js → admin-edit-roles-page.2bccaf76.chunk.js} +1 -1
  73. package/build/admin-edit-users.1632dcf7.chunk.js +1 -0
  74. package/build/admin-users.1f0533e6.chunk.js +1 -0
  75. package/build/{api-tokens-create-page.ac4285ba.chunk.js → api-tokens-create-page.ab33d46d.chunk.js} +1 -1
  76. package/build/{api-tokens-edit-page.b8900ddd.chunk.js → api-tokens-edit-page.749496cc.chunk.js} +1 -1
  77. package/build/{b997a22a2e0b87ef1fa23258f14f3b27.ico → b997a22a2e0b87ef1fa2.ico} +0 -0
  78. package/build/{bb58e57c48a3e911f15fa834ff00d44a.woff → bb58e57c48a3e911f15f.woff} +0 -0
  79. package/build/{bd81ba6c07827282255d031b2a6f4fe4.png → bd81ba6c07827282255d.png} +0 -0
  80. package/build/{be9ee23c0c6390141475d519c2c5fb8f.ttf → be9ee23c0c6390141475.ttf} +0 -0
  81. package/build/{c1e38fd9e0e74ba58f7a2b77ef29fdd3.svg → c1e38fd9e0e74ba58f7a.svg} +0 -0
  82. package/build/{c3de6118ef47086ad05c83a1c78f006d.png → c3de6118ef47086ad05c.png} +0 -0
  83. package/build/codemirror-css.d09c79d2.chunk.js +1 -0
  84. package/build/content-manager.be0bf12e.chunk.js +1 -0
  85. package/build/{content-type-builder-translation-en-json.d860718a.chunk.js → content-type-builder-translation-en-json.81257d0d.chunk.js} +1 -1
  86. package/build/content-type-builder-translation-ko-json.0288cb2b.chunk.js +1 -0
  87. package/build/content-type-builder.aa13e7a4.chunk.js +1 -0
  88. package/build/{d878b0a6a1144760244ff0665888404c.woff2 → d878b0a6a1144760244f.woff2} +0 -0
  89. package/build/{eeccf4f66002c6f2ba24d3d22f2434c2.woff → eeccf4f66002c6f2ba24.woff} +0 -0
  90. package/build/{email-settings-page.def5ceaf.chunk.js → email-settings-page.d3ce077f.chunk.js} +1 -1
  91. package/build/email-translation-en-json.ef8208e3.chunk.js +1 -0
  92. package/build/email-translation-ja-json.66b21ec1.chunk.js +1 -0
  93. package/build/email-translation-ko-json.e383ad57.chunk.js +1 -0
  94. package/build/en-json.4c3c1c95.chunk.js +1 -0
  95. package/build/{f691f37e57f04c152e2315ab7dbad881.woff → f691f37e57f04c152e23.woff} +0 -0
  96. package/build/{fde9b1ad0670d29a251605a5e8eef02b.png → fde9b1ad0670d29a2516.png} +0 -0
  97. package/build/fontawesome-css-all.90be2358.chunk.js +1 -0
  98. package/build/fontawesome-css.32df0f91.chunk.js +1 -0
  99. package/build/fr-json.c75e1a2e.chunk.js +1 -0
  100. package/build/i18n-settings-page.ad670b2c.chunk.js +1 -0
  101. package/build/i18n-translation-en-json.a90b9dc5.chunk.js +1 -0
  102. package/build/i18n-translation-ko-json.f0628aff.chunk.js +1 -0
  103. package/build/index.html +1 -1
  104. package/build/ko-json.35832b30.chunk.js +1 -0
  105. package/build/main.9b622560.js +2 -0
  106. package/build/{main.a5bd9650.js.LICENSE.txt → main.9b622560.js.LICENSE.txt} +0 -0
  107. package/build/nl-json.9e55cf9c.chunk.js +1 -0
  108. package/build/runtime~main.726e5497.js +1 -0
  109. package/build/{upload-settings.8a380d3d.chunk.js → upload-settings.f65c4d08.chunk.js} +1 -1
  110. package/build/{upload-translation-en-json.58d8ce44.chunk.js → upload-translation-en-json.d205cecd.chunk.js} +1 -1
  111. package/build/upload-translation-ko-json.b6602572.chunk.js +1 -0
  112. package/build/{users-advanced-settings-page.bda19eae.chunk.js → users-advanced-settings-page.da9830fd.chunk.js} +1 -1
  113. package/build/{users-email-settings-page.b1d1f551.chunk.js → users-email-settings-page.36142cd7.chunk.js} +1 -1
  114. package/build/users-permissions-translation-ko-json.4677f640.chunk.js +1 -0
  115. package/build/{users-providers-settings-page.733a51ec.chunk.js → users-providers-settings-page.2c0685d3.chunk.js} +1 -1
  116. package/build/{users-roles-settings-page.0eb926e7.chunk.js → users-roles-settings-page.61c9b376.chunk.js} +1 -1
  117. package/build/{webhook-edit-page.634e50da.chunk.js → webhook-edit-page.36755ae4.chunk.js} +1 -1
  118. package/build/{webhook-list-page.aae66737.chunk.js → webhook-list-page.8abf0b5f.chunk.js} +1 -1
  119. package/build/zh-json.3b683748.chunk.js +1 -0
  120. package/ee/admin/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
  121. package/ee/admin/pages/SettingsPage/pages/Users/components/MagicLink/index.js +1 -1
  122. package/index.js +40 -1
  123. package/jest.config.front.js +10 -0
  124. package/package.json +16 -11
  125. package/server/register.js +5 -0
  126. package/server/routes/serve-admin-panel.js +59 -0
  127. package/server/strategies/api-token.js +2 -1
  128. package/webpack.config.js +11 -7
  129. package/build/3226.0dc582b2.chunk.js +0 -2
  130. package/build/4362.e71cf036.chunk.js +0 -1
  131. package/build/8447.32ee17be.chunk.js +0 -2
  132. package/build/8447.32ee17be.chunk.js.LICENSE.txt +0 -22
  133. package/build/Admin_marketplace.201373e2.chunk.js +0 -1
  134. package/build/Admin_profilePage.3aa61921.chunk.js +0 -1
  135. package/build/Admin_settingsPage.363ad01d.chunk.js +0 -1
  136. package/build/admin-edit-users.bcdd2e4d.chunk.js +0 -1
  137. package/build/admin-users.a2d08780.chunk.js +0 -1
  138. package/build/codemirror-css.7b034e03.chunk.js +0 -1
  139. package/build/content-manager.4a449a52.chunk.js +0 -1
  140. package/build/content-type-builder-translation-ko-json.20ad3eac.chunk.js +0 -1
  141. package/build/content-type-builder.eeae4ee8.chunk.js +0 -1
  142. package/build/email-translation-en-json.5ec38fe9.chunk.js +0 -1
  143. package/build/email-translation-ja-json.b75afc52.chunk.js +0 -1
  144. package/build/email-translation-ko-json.eb9a23cd.chunk.js +0 -1
  145. package/build/en-json.6282a00f.chunk.js +0 -1
  146. package/build/fontawesome-css-all.162c8569.chunk.js +0 -1
  147. package/build/fontawesome-css.b1736497.chunk.js +0 -1
  148. package/build/fr-json.f7d484a8.chunk.js +0 -1
  149. package/build/i18n-settings-page.00c74503.chunk.js +0 -1
  150. package/build/i18n-translation-en-json.17af559c.chunk.js +0 -1
  151. package/build/ko-json.7203b08b.chunk.js +0 -1
  152. package/build/main.a5bd9650.js +0 -2
  153. package/build/nl-json.9c7f83db.chunk.js +0 -1
  154. package/build/runtime~main.bddfe3c6.js +0 -1
  155. package/build/users-permissions-translation-ko-json.90c2d129.chunk.js +0 -1
  156. package/build/zh-json.414d826f.chunk.js +0 -1
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import PropTypes from 'prop-types';
4
4
  import { useDrag, useDrop } from 'react-dnd';
@@ -11,6 +11,7 @@ import { Stack } from '@strapi/design-system/Stack';
11
11
  import Pencil from '@strapi/icons/Pencil';
12
12
  import Cross from '@strapi/icons/Cross';
13
13
  import Drag from '@strapi/icons/Drag';
14
+ import CardPreview from './CardPreview';
14
15
  import ellipsisCardTitle from '../utils/ellipsisCardTitle';
15
16
  import { getTrad, ItemTypes } from '../../../utils';
16
17
 
@@ -38,7 +39,6 @@ const DragButton = styled(ActionButton)`
38
39
  const FieldContainer = styled(Flex)`
39
40
  max-height: ${32 / 16}rem;
40
41
  cursor: pointer;
41
- opacity: ${({ isDragging }) => (isDragging ? 0 : 1)};
42
42
 
43
43
  svg {
44
44
  width: ${10 / 16}rem;
@@ -77,14 +77,18 @@ const FieldWrapper = styled(Box)`
77
77
 
78
78
  const DraggableCard = ({
79
79
  index,
80
+ isDraggingSibling,
80
81
  labelField,
81
82
  onClickEditField,
82
83
  onMoveField,
83
84
  onRemoveField,
84
85
  name,
86
+ setIsDraggingSibling,
85
87
  }) => {
86
88
  const { formatMessage } = useIntl();
87
- const ref = useRef(null);
89
+ const dragRef = useRef(null);
90
+ const dropRef = useRef(null);
91
+ const [, forceRerenderAfterDnd] = useState(false);
88
92
  const editButtonRef = useRef();
89
93
  const cardEllipsisTitle = ellipsisCardTitle(labelField);
90
94
 
@@ -96,8 +100,8 @@ const DraggableCard = ({
96
100
 
97
101
  const [, drop] = useDrop({
98
102
  accept: ItemTypes.FIELD,
99
- hover(item) {
100
- if (!ref.current) {
103
+ hover(item, monitor) {
104
+ if (!dropRef.current) {
101
105
  return;
102
106
  }
103
107
  const dragIndex = item.index;
@@ -108,6 +112,27 @@ const DraggableCard = ({
108
112
  return;
109
113
  }
110
114
 
115
+ // Determine rectangle on screen
116
+ const hoverBoundingRect = dropRef.current.getBoundingClientRect();
117
+ // Get vertical middle
118
+ const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
119
+ // Determine mouse position
120
+ const clientOffset = monitor.getClientOffset();
121
+ // Get pixels to the top
122
+ const hoverClientX = clientOffset.x - hoverBoundingRect.left;
123
+
124
+ // Only perform the move when the mouse has crossed half of the items height
125
+ // When dragging downwards, only move when the cursor is below 50%
126
+ // When dragging upwards, only move when the cursor is above 50%
127
+ // Dragging downwards
128
+ if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
129
+ return;
130
+ }
131
+ // Dragging upwards
132
+ if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {
133
+ return;
134
+ }
135
+
111
136
  onMoveField(dragIndex, hoverIndex);
112
137
 
113
138
  item.index = hoverIndex;
@@ -122,86 +147,117 @@ const DraggableCard = ({
122
147
  collect: monitor => ({
123
148
  isDragging: monitor.isDragging(),
124
149
  }),
150
+ end: () => {
151
+ setIsDraggingSibling(false);
152
+ },
125
153
  });
126
154
 
127
155
  useEffect(() => {
128
- preview(getEmptyImage(), { captureDraggingState: true });
156
+ preview(getEmptyImage(), { captureDraggingState: false });
129
157
  }, [preview]);
130
158
 
131
- drag(drop(ref));
159
+ useEffect(() => {
160
+ if (isDragging) {
161
+ setIsDraggingSibling(true);
162
+ }
163
+ }, [isDragging, setIsDraggingSibling]);
164
+
165
+ // Effect in order to force a rerender after reordering the components
166
+ // Since we are removing the Accordion when doing the DnD we are losing the dragRef, therefore the replaced element cannot be dragged
167
+ // anymore, this hack forces a rerender in order to apply the dragRef
168
+ useEffect(() => {
169
+ if (!isDraggingSibling) {
170
+ forceRerenderAfterDnd(prev => !prev);
171
+ }
172
+ }, [isDraggingSibling]);
173
+
174
+ // Create the refs
175
+ // We need 1 for the drop target
176
+ // 1 for the drag target
177
+ const refs = {
178
+ dragRef: drag(dragRef),
179
+ dropRef: drop(dropRef),
180
+ };
132
181
 
133
182
  return (
134
- <FieldWrapper>
135
- <FieldContainer
136
- borderColor="neutral150"
137
- background="neutral100"
138
- hasRadius
139
- justifyContent="space-between"
140
- onClick={handleClickEditRow}
141
- isDragging={isDragging}
142
- >
143
- <Stack horizontal size={3}>
144
- <DragButton
145
- aria-label={formatMessage(
146
- {
147
- id: getTrad('components.DraggableCard.move.field'),
148
- defaultMessage: 'Move {item}',
149
- },
150
- { item: name }
151
- )}
152
- onClick={e => e.stopPropagation()}
153
- ref={ref}
154
- type="button"
155
- >
156
- <Drag />
157
- </DragButton>
158
- <Typography fontWeight="bold">{cardEllipsisTitle}</Typography>
159
- </Stack>
160
- <Flex paddingLeft={3}>
161
- <ActionButton
162
- ref={editButtonRef}
163
- onClick={e => {
164
- e.stopPropagation();
165
- onClickEditField(name);
166
- }}
167
- aria-label={formatMessage(
168
- {
169
- id: getTrad('components.DraggableCard.edit.field'),
170
- defaultMessage: 'Edit {item}',
171
- },
172
- { item: name }
173
- )}
174
- type="button"
175
- >
176
- <Pencil />
177
- </ActionButton>
178
- <ActionButton
179
- onClick={onRemoveField}
180
- data-testid={`delete-${name}`}
181
- aria-label={formatMessage(
182
- {
183
- id: getTrad('components.DraggableCard.delete.field'),
184
- defaultMessage: 'Delete {item}',
185
- },
186
- { item: name }
187
- )}
188
- type="button"
189
- >
190
- <Cross />
191
- </ActionButton>
192
- </Flex>
193
- </FieldContainer>
183
+ <FieldWrapper ref={refs ? refs.dropRef : null}>
184
+ {isDragging && <CardPreview transparent labelField={cardEllipsisTitle} />}
185
+ {!isDragging && isDraggingSibling && <CardPreview isSibling labelField={cardEllipsisTitle} />}
186
+
187
+ {!isDragging && !isDraggingSibling && (
188
+ <FieldContainer
189
+ borderColor="neutral150"
190
+ background="neutral100"
191
+ hasRadius
192
+ justifyContent="space-between"
193
+ onClick={handleClickEditRow}
194
+ isDragging={isDragging}
195
+ >
196
+ <Stack horizontal size={3}>
197
+ <DragButton
198
+ aria-label={formatMessage(
199
+ {
200
+ id: getTrad('components.DraggableCard.move.field'),
201
+ defaultMessage: 'Move {item}',
202
+ },
203
+ { item: name }
204
+ )}
205
+ onClick={e => e.stopPropagation()}
206
+ ref={refs.dragRef}
207
+ type="button"
208
+ >
209
+ <Drag />
210
+ </DragButton>
211
+ <Typography fontWeight="bold">{cardEllipsisTitle}</Typography>
212
+ </Stack>
213
+ <Flex paddingLeft={3}>
214
+ <ActionButton
215
+ ref={editButtonRef}
216
+ onClick={e => {
217
+ e.stopPropagation();
218
+ onClickEditField(name);
219
+ }}
220
+ aria-label={formatMessage(
221
+ {
222
+ id: getTrad('components.DraggableCard.edit.field'),
223
+ defaultMessage: 'Edit {item}',
224
+ },
225
+ { item: name }
226
+ )}
227
+ type="button"
228
+ >
229
+ <Pencil />
230
+ </ActionButton>
231
+ <ActionButton
232
+ onClick={onRemoveField}
233
+ data-testid={`delete-${name}`}
234
+ aria-label={formatMessage(
235
+ {
236
+ id: getTrad('components.DraggableCard.delete.field'),
237
+ defaultMessage: 'Delete {item}',
238
+ },
239
+ { item: name }
240
+ )}
241
+ type="button"
242
+ >
243
+ <Cross />
244
+ </ActionButton>
245
+ </Flex>
246
+ </FieldContainer>
247
+ )}
194
248
  </FieldWrapper>
195
249
  );
196
250
  };
197
251
 
198
252
  DraggableCard.propTypes = {
199
253
  index: PropTypes.number.isRequired,
254
+ isDraggingSibling: PropTypes.bool.isRequired,
200
255
  labelField: PropTypes.string.isRequired,
201
256
  name: PropTypes.string.isRequired,
202
257
  onClickEditField: PropTypes.func.isRequired,
203
258
  onMoveField: PropTypes.func.isRequired,
204
259
  onRemoveField: PropTypes.func.isRequired,
260
+ setIsDraggingSibling: PropTypes.func.isRequired,
205
261
  };
206
262
 
207
263
  export default DraggableCard;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import { PropTypes } from 'prop-types';
4
4
  import { useIntl } from 'react-intl';
@@ -35,6 +35,7 @@ const SortDisplayedFields = ({
35
35
  onRemoveField,
36
36
  }) => {
37
37
  const { formatMessage } = useIntl();
38
+ const [isDraggingSibling, setIsDraggingSibling] = useState(false);
38
39
 
39
40
  return (
40
41
  <>
@@ -61,11 +62,13 @@ const SortDisplayedFields = ({
61
62
  <DraggableCard
62
63
  key={field}
63
64
  index={index}
65
+ isDraggingSibling={isDraggingSibling}
64
66
  onMoveField={onMoveField}
65
67
  onClickEditField={onClickEditField}
66
68
  onRemoveField={e => onRemoveField(e, index)}
67
69
  name={field}
68
70
  labelField={metadatas[field].list.label || field}
71
+ setIsDraggingSibling={setIsDraggingSibling}
69
72
  />
70
73
  ))}
71
74
  </Stack>
@@ -191,7 +191,7 @@ const ListSettingsView = ({ layout, slug }) => {
191
191
  <HeaderLayout
192
192
  navigationAction={
193
193
  <Link startIcon={<ArrowLeft />} to={goBackUrl} id="go-back">
194
- {formatMessage({ id: 'app.components.go-back', defaultMessage: 'Go back' })}
194
+ {formatMessage({ id: 'app.components.go-back', defaultMessage: 'Back' })}
195
195
  </Link>
196
196
  }
197
197
  primaryAction={
@@ -24,6 +24,8 @@ import { Box } from '@strapi/design-system/Box';
24
24
  import { ActionLayout, ContentLayout, HeaderLayout } from '@strapi/design-system/Layout';
25
25
  import { useNotifyAT } from '@strapi/design-system/LiveRegions';
26
26
  import { Button } from '@strapi/design-system/Button';
27
+ import { Link } from '@strapi/design-system/Link';
28
+ import ArrowLeft from '@strapi/icons/ArrowLeft';
27
29
  import Plus from '@strapi/icons/Plus';
28
30
  import Cog from '@strapi/icons/Cog';
29
31
  import axios from 'axios';
@@ -234,29 +236,43 @@ function ListView({
234
236
  )
235
237
  : null;
236
238
 
237
- const createAction = canCreate ? (
238
- <Button
239
- onClick={() => {
240
- const trackerProperty = hasDraftAndPublish ? { status: 'draft' } : {};
241
-
242
- trackUsageRef.current('willCreateEntry', trackerProperty);
243
- push({
244
- pathname: `${pathname}/create`,
245
- search: query.plugins ? pluginsQueryParams : '',
246
- });
247
- }}
248
- startIcon={<Plus />}
249
- >
250
- {formatMessage({
251
- id: getTrad('HeaderLayout.button.label-add-entry'),
252
- defaultMessage: 'Add new entry',
253
- })}
254
- </Button>
255
- ) : null;
239
+ const getCreateAction = props =>
240
+ canCreate ? (
241
+ <Button
242
+ {...props}
243
+ onClick={() => {
244
+ const trackerProperty = hasDraftAndPublish ? { status: 'draft' } : {};
245
+
246
+ trackUsageRef.current('willCreateEntry', trackerProperty);
247
+ push({
248
+ pathname: `${pathname}/create`,
249
+ search: query.plugins ? pluginsQueryParams : '',
250
+ });
251
+ }}
252
+ startIcon={<Plus />}
253
+ >
254
+ {formatMessage({
255
+ id: getTrad('HeaderLayout.button.label-add-entry'),
256
+ defaultMessage: 'Create new entry',
257
+ })}
258
+ </Button>
259
+ ) : null;
256
260
 
257
261
  return (
258
262
  <Main aria-busy={isLoading}>
259
- <HeaderLayout primaryAction={createAction} subtitle={subtitle} title={headerLayoutTitle} />
263
+ <HeaderLayout
264
+ primaryAction={getCreateAction()}
265
+ subtitle={subtitle}
266
+ title={headerLayoutTitle}
267
+ navigationAction={
268
+ <Link startIcon={<ArrowLeft />} to="/content-manager/">
269
+ {formatMessage({
270
+ id: 'app.components.HeaderLayout.link.go-back',
271
+ defaultMessage: 'Back',
272
+ })}
273
+ </Link>
274
+ }
275
+ />
260
276
  {!canRead && (
261
277
  <ActionLayout endActions={<InjectionZone area="contentManager.listView.actions" />} />
262
278
  )}
@@ -320,6 +336,7 @@ function ListView({
320
336
  // FIXME: remove the layout props drilling
321
337
  layout={layout}
322
338
  rows={data}
339
+ action={getCreateAction({ variant: 'secondary' })}
323
340
  />
324
341
  <PaginationFooter pagination={{ pageCount: pagination?.pageCount || 1 }} />
325
342
  </>
@@ -2,7 +2,7 @@ import adminPermissions from '../../../permissions';
2
2
 
3
3
  const defaultGlobalLinks = [
4
4
  {
5
- intlLabel: { id: 'Settings.application.title', defaultMessage: 'Application' },
5
+ intlLabel: { id: 'Settings.application.title', defaultMessage: 'Overview' },
6
6
  to: '/settings/application-infos',
7
7
  id: '000-application-infos',
8
8
  isDisplayed: false,
@@ -4,7 +4,9 @@ const getUniqueIdentifier = async () => {
4
4
  const fp = await FingerprintJS.load();
5
5
  const result = await fp.get();
6
6
 
7
- return result.visitorId;
7
+ const deviceId = `web-fingerprint-${result.visitorId}`;
8
+
9
+ return deviceId;
8
10
  };
9
11
 
10
12
  export default getUniqueIdentifier;
@@ -1,6 +1,8 @@
1
1
  import React, { useEffect, useReducer } from 'react';
2
2
  import axios from 'axios';
3
- import { camelCase, get, omit } from 'lodash';
3
+ import camelCase from 'lodash/camelCase';
4
+ import get from 'lodash/get';
5
+ import omit from 'lodash/omit';
4
6
  import { Redirect, useRouteMatch, useHistory } from 'react-router-dom';
5
7
  import { auth, useQuery } from '@strapi/helper-plugin';
6
8
  import PropTypes from 'prop-types';
@@ -117,7 +119,11 @@ const AuthPage = ({ hasAdmin, setHasAdmin }) => {
117
119
  push('/');
118
120
  } catch (err) {
119
121
  if (err.response) {
120
- const errorMessage = get(err, ['response', 'data', 'message'], 'Something went wrong');
122
+ const errorMessage = get(
123
+ err,
124
+ ['response', 'data', 'error', 'message'],
125
+ 'Something went wrong'
126
+ );
121
127
 
122
128
  if (camelCase(errorMessage).toLowerCase() === 'usernotactive') {
123
129
  push('/auth/oops');
@@ -409,12 +409,38 @@ const ProfilePage = () => {
409
409
  paddingRight={7}
410
410
  >
411
411
  <Stack size={4}>
412
- <Typography variant="delta" as="h2">
413
- {formatMessage({
414
- id: 'Settings.profile.form.section.experience.title',
415
- defaultMessage: 'Experience',
416
- })}
417
- </Typography>
412
+ <Stack size={1}>
413
+ <Typography variant="delta" as="h2">
414
+ {formatMessage({
415
+ id: 'Settings.profile.form.section.experience.title',
416
+ defaultMessage: 'Experience',
417
+ })}
418
+ </Typography>
419
+ <Typography>
420
+ {formatMessage(
421
+ {
422
+ id:
423
+ 'Settings.profile.form.section.experience.interfaceLanguageHelp',
424
+ defaultMessage:
425
+ 'Selection will change the interface language only for you. Please refer to this {documentation} to make other languages available for your team.',
426
+ },
427
+ {
428
+ documentation: (
429
+ <a
430
+ target="_blank"
431
+ rel="noopener noreferrer"
432
+ href="https://docs.strapi.io/developer-docs/latest/development/admin-customization.html#locales"
433
+ >
434
+ {formatMessage({
435
+ id: 'Settings.profile.form.section.experience.documentation',
436
+ defaultMessage: 'documentation',
437
+ })}
438
+ </a>
439
+ ),
440
+ }
441
+ )}
442
+ </Typography>
443
+ </Stack>
418
444
  <Grid gap={5}>
419
445
  <GridItem s={12} col={6}>
420
446
  <Select
@@ -165,7 +165,7 @@ const ApiTokenCreateView = () => {
165
165
  <Link startIcon={<ArrowLeft />} to="/settings/api-tokens">
166
166
  {formatMessage({
167
167
  id: 'app.components.go-back',
168
- defaultMessage: 'Go back',
168
+ defaultMessage: 'Back',
169
169
  })}
170
170
  </Link>
171
171
  }
@@ -185,7 +185,7 @@ const ApiTokenCreateView = () => {
185
185
  <Stack size={4}>
186
186
  <Typography variant="delta" as="h2">
187
187
  {formatMessage({
188
- id: 'app.components.Users.ModalCreateBody.block-title.details',
188
+ id: 'Settings.apiTokens.details',
189
189
  defaultMessage: 'Details',
190
190
  })}
191
191
  </Typography>
@@ -26,10 +26,10 @@ const ApplicationInfosPage = () => {
26
26
  <SettingsPageTitle name="Application" />
27
27
  <Main>
28
28
  <HeaderLayout
29
- title={formatMessage({ id: 'Settings.application.title', defaultMessage: 'Application' })}
29
+ title={formatMessage({ id: 'Settings.application.title', defaultMessage: 'Overview' })}
30
30
  subtitle={formatMessage({
31
31
  id: 'Settings.application.description',
32
- defaultMessage: "See your project's details",
32
+ defaultMessage: 'Administration panel’s global information',
33
33
  })}
34
34
  />
35
35
  <ContentLayout>
@@ -45,8 +45,8 @@ const ApplicationInfosPage = () => {
45
45
  <Stack size={5}>
46
46
  <Typography variant="delta" as="h3">
47
47
  {formatMessage({
48
- id: 'Settings.application.information',
49
- defaultMessage: 'Information',
48
+ id: 'Settings.application.details',
49
+ defaultMessage: 'Details',
50
50
  })}
51
51
  </Typography>
52
52
 
@@ -54,11 +54,24 @@ const ApplicationInfosPage = () => {
54
54
  <GridItem col={6} s={12}>
55
55
  <Typography variant="sigma" textColor="neutral600">
56
56
  {formatMessage({
57
- id: 'Settings.application.details',
58
- defaultMessage: 'details',
57
+ id: 'Settings.application.strapiVersion',
58
+ defaultMessage: 'strapi version',
59
59
  })}
60
60
  </Typography>
61
61
  <Typography as="p">v{strapiVersion}</Typography>
62
+ <Link
63
+ href={
64
+ appInfos.communityEdition
65
+ ? 'https://discord.strapi.io'
66
+ : 'https://support.strapi.io/support/home'
67
+ }
68
+ endIcon={<ExternalLink />}
69
+ >
70
+ {formatMessage({
71
+ id: 'Settings.application.get-help',
72
+ defaultMessage: 'Get help',
73
+ })}
74
+ </Link>
62
75
  </GridItem>
63
76
  <GridItem col={6} s={12}>
64
77
  <Typography variant="sigma" textColor="neutral600">
@@ -96,7 +109,7 @@ const ApplicationInfosPage = () => {
96
109
  <Link href="https://strapi.io/pricing-self-hosted" endIcon={<ExternalLink />}>
97
110
  {formatMessage({
98
111
  id: 'Settings.application.link-pricing',
99
- defaultMessage: 'See all pricing',
112
+ defaultMessage: 'See all pricing plans',
100
113
  })}
101
114
  </Link>
102
115
  </GridItem>
@@ -135,7 +135,7 @@ const EditPage = () => {
135
135
  <Link startIcon={<ArrowLeft />} to="/settings/roles">
136
136
  {formatMessage({
137
137
  id: 'app.components.go-back',
138
- defaultMessage: 'Go back',
138
+ defaultMessage: 'Back',
139
139
  })}
140
140
  </Link>
141
141
  }
@@ -150,7 +150,7 @@ const EditPage = ({ canUpdate }) => {
150
150
  <Link startIcon={<ArrowLeft />} to="/settings/users?pageSize=10&page=1&sort=firstname">
151
151
  {formatMessage({
152
152
  id: 'app.components.go-back',
153
- defaultMessage: 'Go back',
153
+ defaultMessage: 'Back',
154
154
  })}
155
155
  </Link>
156
156
  }
@@ -194,7 +194,7 @@ const EditPage = ({ canUpdate }) => {
194
194
  >
195
195
  {formatMessage({
196
196
  id: 'app.components.go-back',
197
- defaultMessage: 'Go back',
197
+ defaultMessage: 'Back',
198
198
  })}
199
199
  </Link>
200
200
  }
@@ -254,7 +254,7 @@ const EditPage = ({ canUpdate }) => {
254
254
  <Typography variant="delta" as="h2">
255
255
  {formatMessage({
256
256
  id: 'app.components.Users.ModalCreateBody.block-title.login',
257
- defaultMessage: 'Login settings',
257
+ defaultMessage: "User's role",
258
258
  })}
259
259
  </Typography>
260
260
  <Grid gap={5}>
@@ -58,7 +58,7 @@ const ModalForm = ({ queryName, onToggle }) => {
58
58
 
59
59
  const headerTitle = formatMessage({
60
60
  id: 'Settings.permissions.users.create',
61
- defaultMessage: 'Create new user',
61
+ defaultMessage: 'Invite new user',
62
62
  });
63
63
 
64
64
  const handleSubmit = async (body, { setErrors }) => {
@@ -118,7 +118,7 @@ const ModalForm = ({ queryName, onToggle }) => {
118
118
  <Typography variant="beta" as="h2">
119
119
  {formatMessage({
120
120
  id: 'app.components.Users.ModalCreateBody.block-title.details',
121
- defaultMessage: 'Details',
121
+ defaultMessage: 'User details',
122
122
  })}
123
123
  </Typography>
124
124
  <Box paddingTop={4}>
@@ -147,7 +147,7 @@ const ModalForm = ({ queryName, onToggle }) => {
147
147
  <Typography variant="beta" as="h2">
148
148
  {formatMessage({
149
149
  id: 'app.components.Users.ModalCreateBody.block-title.login',
150
- defaultMessage: 'Login settings',
150
+ defaultMessage: "User's role",
151
151
  })}
152
152
  </Typography>
153
153
  <Box paddingTop={4}>
@@ -2,7 +2,7 @@ const stepper = {
2
2
  create: {
3
3
  buttonSubmitLabel: {
4
4
  id: 'app.containers.Users.ModalForm.footer.button-success',
5
- defaultMessage: 'Create user',
5
+ defaultMessage: 'Invite user',
6
6
  },
7
7
  isDisabled: false,
8
8
  next: 'magic-link',