@strapi/admin 4.0.3 → 4.0.7

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 (161) hide show
  1. package/admin/src/components/LeftMenu/index.js +11 -3
  2. package/admin/src/components/UpgradePlanModal/index.js +7 -2
  3. package/admin/src/content-manager/components/DynamicZone/components/DzLabel/index.js +24 -7
  4. package/admin/src/content-manager/components/DynamicZone/index.js +6 -10
  5. package/admin/src/content-manager/components/InputJSON/FieldWrapper.js +32 -0
  6. package/admin/src/content-manager/components/InputJSON/Label.js +5 -11
  7. package/admin/src/content-manager/components/InputJSON/index.js +26 -26
  8. package/admin/src/content-manager/components/PreviewWysiwyg/Wrapper.js +4 -0
  9. package/admin/src/content-manager/components/PreviewWysiwyg/utils/mdRenderer.js +1 -1
  10. package/admin/src/content-manager/components/Wysiwyg/Editor.js +6 -4
  11. package/admin/src/content-manager/components/Wysiwyg/EditorLayout.js +2 -0
  12. package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +2 -1
  13. package/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.js +2 -4
  14. package/admin/src/content-manager/components/Wysiwyg/WysiwygNav.js +79 -68
  15. package/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.js +1 -0
  16. package/admin/src/content-manager/components/Wysiwyg/index.js +17 -5
  17. package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.js +1 -3
  18. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +6 -7
  19. package/admin/src/pages/Admin/index.js +2 -0
  20. package/admin/src/pages/InternalErrorPage/index.js +53 -0
  21. package/admin/src/pages/NotFoundPage/index.js +45 -2
  22. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +2 -10
  23. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/utils/schema.js +1 -4
  24. package/admin/src/translations/dk.json +300 -110
  25. package/admin/src/translations/en.json +3 -0
  26. package/admin/src/translations/es.json +204 -4
  27. package/admin/src/translations/hu.json +672 -0
  28. package/admin/src/translations/ja.json +327 -7
  29. package/admin/src/translations/languageNativeNames.js +1 -0
  30. package/admin/src/translations/nl.json +512 -125
  31. package/admin/src/translations/pt-BR.json +398 -19
  32. package/admin/src/translations/uk.json +40 -40
  33. package/admin/src/translations/zh.json +7 -0
  34. package/build/1024.efaaca35.chunk.js +1 -0
  35. package/build/1856.ec8cf094.chunk.js +1 -0
  36. package/build/2912.b886455f.chunk.js +1 -0
  37. package/build/{5881.746d7dc1.chunk.js → 3215.b6c950c2.chunk.js} +2 -2
  38. package/build/{5881.746d7dc1.chunk.js.LICENSE.txt → 3215.b6c950c2.chunk.js.LICENSE.txt} +0 -0
  39. package/build/4261.d5024c20.chunk.js +1 -0
  40. package/build/4362.0700c5df.chunk.js +1 -0
  41. package/build/4672.e18b4834.chunk.js +1 -0
  42. package/build/4715.7f86301d.chunk.js +1 -0
  43. package/build/4741.57e58885.chunk.js +2 -0
  44. package/build/{4741.1fb6ad6e.chunk.js.LICENSE.txt → 4741.57e58885.chunk.js.LICENSE.txt} +0 -0
  45. package/build/4801.3a0d8fcd.chunk.js +2 -0
  46. package/build/{9351.a0fbd4ef.chunk.js.LICENSE.txt → 4801.3a0d8fcd.chunk.js.LICENSE.txt} +0 -0
  47. package/build/497.9a3be008.chunk.js +1 -0
  48. package/build/4982.52a2ce10.chunk.js +1 -0
  49. package/build/6060.1a1bd16a.chunk.js +2 -0
  50. package/build/{6060.a5b86bc2.chunk.js.LICENSE.txt → 6060.1a1bd16a.chunk.js.LICENSE.txt} +0 -0
  51. package/build/6250.2172d040.chunk.js +1 -0
  52. package/build/7841.c4d33a2f.chunk.js +1 -0
  53. package/build/{849.4a7be1c0.chunk.js → 849.46892e8e.chunk.js} +1 -1
  54. package/build/9235.63b1528f.chunk.js +1 -0
  55. package/build/Admin-authenticatedApp.c6b9128c.chunk.js +1 -0
  56. package/build/Admin_homePage.f044cfaf.chunk.js +1 -0
  57. package/build/{Admin_marketplace.9661a660.chunk.js → Admin_marketplace.1cf20eeb.chunk.js} +1 -1
  58. package/build/{Admin_pluginsPage.7d1bd7ce.chunk.js → Admin_pluginsPage.0d59d86e.chunk.js} +1 -1
  59. package/build/{Admin_profilePage.67dd744c.chunk.js → Admin_profilePage.c08119de.chunk.js} +1 -1
  60. package/build/Admin_settingsPage.97246c41.chunk.js +1 -0
  61. package/build/{admin-edit-roles-page.2d1b6461.chunk.js → admin-edit-roles-page.8af004a6.chunk.js} +1 -1
  62. package/build/{admin-edit-users.e736db15.chunk.js → admin-edit-users.73877840.chunk.js} +1 -1
  63. package/build/admin-users.e0558d75.chunk.js +1 -0
  64. package/build/{api-tokens-create-page.830b37b7.chunk.js → api-tokens-create-page.ebe57c8e.chunk.js} +1 -1
  65. package/build/{api-tokens-edit-page.dbe07b72.chunk.js → api-tokens-edit-page.35e1522b.chunk.js} +1 -1
  66. package/build/{api-tokens-list-page.1626150f.chunk.js → api-tokens-list-page.f01b7b98.chunk.js} +1 -1
  67. package/build/content-manager.9c7ee647.chunk.js +1 -0
  68. package/build/{content-type-builder-translation-dk-json.5c6344f9.chunk.js → content-type-builder-translation-dk-json.098bd218.chunk.js} +1 -1
  69. package/build/{content-type-builder-translation-en-json.c535d180.chunk.js → content-type-builder-translation-en-json.d70fc3af.chunk.js} +1 -1
  70. package/build/content-type-builder-translation-es-json.20c177ee.chunk.js +1 -0
  71. package/build/content-type-builder.7673250d.chunk.js +1 -0
  72. package/build/dk-json.7356ea4b.chunk.js +1 -0
  73. package/build/email-settings-page.448433af.chunk.js +1 -0
  74. package/build/email-translation-dk-json.f8a595bf.chunk.js +1 -0
  75. package/build/email-translation-es-json.eb303dea.chunk.js +1 -0
  76. package/build/en-json.ec998c8f.chunk.js +1 -0
  77. package/build/es-json.ed9c8bef.chunk.js +1 -0
  78. package/build/{fontawesome-css.ef93ee2a.chunk.js → fontawesome-css.36cff9ae.chunk.js} +1 -1
  79. package/build/hu-json.a741d263.chunk.js +1 -0
  80. package/build/i18n-settings-page.0ba8ab95.chunk.js +1 -0
  81. package/build/i18n-translation-dk-json.932d3cc2.chunk.js +1 -0
  82. package/build/i18n-translation-es-json.347904f3.chunk.js +1 -0
  83. package/build/index.html +1 -1
  84. package/build/ja-json.52581a2a.chunk.js +1 -0
  85. package/build/main.fcbcdd20.js +2 -0
  86. package/build/{main.b227e163.js.LICENSE.txt → main.fcbcdd20.js.LICENSE.txt} +0 -0
  87. package/build/nl-json.ac661b7f.chunk.js +1 -0
  88. package/build/pt-BR-json.8b3f799d.chunk.js +1 -0
  89. package/build/runtime~main.32f93f84.js +1 -0
  90. package/build/{sso-settings-page.c073b6d7.chunk.js → sso-settings-page.36c35df0.chunk.js} +1 -1
  91. package/build/uk-json.da2ed14e.chunk.js +1 -0
  92. package/build/upload-settings.113fd6b8.chunk.js +1 -0
  93. package/build/{upload-translation-dk-json.e8c0a891.chunk.js → upload-translation-dk-json.bc6af8b4.chunk.js} +1 -1
  94. package/build/upload-translation-en-json.6b529046.chunk.js +1 -0
  95. package/build/upload-translation-es-json.b53d6641.chunk.js +1 -0
  96. package/build/upload.36c37a29.chunk.js +1 -0
  97. package/build/users-advanced-settings-page.627f173b.chunk.js +1 -0
  98. package/build/{users-email-settings-page.678794aa.chunk.js → users-email-settings-page.862eb51e.chunk.js} +1 -1
  99. package/build/{users-permissions-translation-dk-json.a36b323b.chunk.js → users-permissions-translation-dk-json.3e0295e5.chunk.js} +1 -1
  100. package/build/users-permissions-translation-es-json.a4f81eaa.chunk.js +1 -0
  101. package/build/users-providers-settings-page.47f97b06.chunk.js +1 -0
  102. package/build/{users-roles-settings-page.4f04bf06.chunk.js → users-roles-settings-page.b67e2b4d.chunk.js} +1 -1
  103. package/build/webhook-edit-page.e463d0ab.chunk.js +1 -0
  104. package/build/webhook-list-page.b7649616.chunk.js +1 -0
  105. package/build/zh-json.2e4c9ef4.chunk.js +1 -0
  106. package/ee/admin/pages/App/utils/customRoutes.js +1 -1
  107. package/ee/server/controllers/authentication/utils.js +1 -1
  108. package/index.js +43 -26
  109. package/package.json +11 -11
  110. package/server/bootstrap.js +16 -0
  111. package/server/controllers/webhooks.js +6 -10
  112. package/server/services/api-token.js +1 -1
  113. package/server/services/metrics.js +6 -0
  114. package/server/services/permission/permissions-manager/sanitize.js +13 -5
  115. package/server/services/user.js +10 -0
  116. package/server/strategies/api-token.js +0 -3
  117. package/build/1024.1b15fbb5.chunk.js +0 -1
  118. package/build/1856.0a6992d6.chunk.js +0 -1
  119. package/build/2912.d903b59a.chunk.js +0 -1
  120. package/build/4064.2683bcce.chunk.js +0 -1
  121. package/build/4261.b7b7ac00.chunk.js +0 -1
  122. package/build/4362.1cf3ccbd.chunk.js +0 -1
  123. package/build/4715.f134f37a.chunk.js +0 -1
  124. package/build/4741.1fb6ad6e.chunk.js +0 -2
  125. package/build/497.726adbfa.chunk.js +0 -1
  126. package/build/4982.a7f87e6c.chunk.js +0 -1
  127. package/build/6060.a5b86bc2.chunk.js +0 -2
  128. package/build/6250.11ba8b50.chunk.js +0 -1
  129. package/build/7841.d2aa6f5e.chunk.js +0 -1
  130. package/build/9238.63386655.chunk.js +0 -1
  131. package/build/9351.a0fbd4ef.chunk.js +0 -2
  132. package/build/Admin-authenticatedApp.956e0be7.chunk.js +0 -1
  133. package/build/Admin_homePage.62ec13fd.chunk.js +0 -1
  134. package/build/Admin_settingsPage.73423460.chunk.js +0 -1
  135. package/build/admin-users.62447405.chunk.js +0 -1
  136. package/build/content-manager.0872e65e.chunk.js +0 -1
  137. package/build/content-type-builder-translation-es-json.7e2055ad.chunk.js +0 -1
  138. package/build/content-type-builder.44fdf56b.chunk.js +0 -1
  139. package/build/dk-json.9516eb08.chunk.js +0 -1
  140. package/build/email-settings-page.3cdedf03.chunk.js +0 -1
  141. package/build/email-translation-dk-json.b3740e8f.chunk.js +0 -1
  142. package/build/email-translation-es-json.abbba8e3.chunk.js +0 -1
  143. package/build/en-json.1c33de7f.chunk.js +0 -1
  144. package/build/es-json.fa8ddd1d.chunk.js +0 -1
  145. package/build/i18n-settings-page.ad670b2c.chunk.js +0 -1
  146. package/build/ja-json.57abaacb.chunk.js +0 -1
  147. package/build/main.b227e163.js +0 -2
  148. package/build/nl-json.d757328d.chunk.js +0 -1
  149. package/build/pt-BR-json.6d1cfdb2.chunk.js +0 -1
  150. package/build/runtime~main.d7a87b81.js +0 -1
  151. package/build/uk-json.c50ad2a8.chunk.js +0 -1
  152. package/build/upload-settings.f65c4d08.chunk.js +0 -1
  153. package/build/upload-translation-en-json.31ea0622.chunk.js +0 -1
  154. package/build/upload-translation-es-json.42b5c758.chunk.js +0 -1
  155. package/build/upload.1e3e2685.chunk.js +0 -1
  156. package/build/users-advanced-settings-page.da9830fd.chunk.js +0 -1
  157. package/build/users-permissions-translation-es-json.c8ef51bd.chunk.js +0 -1
  158. package/build/users-providers-settings-page.d4f78a77.chunk.js +0 -1
  159. package/build/webhook-edit-page.c87c6764.chunk.js +0 -1
  160. package/build/webhook-list-page.8abf0b5f.chunk.js +0 -1
  161. package/build/zh-json.496bd6c4.chunk.js +0 -1
@@ -80,12 +80,20 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
80
80
  }
81
81
  };
82
82
 
83
+ const menuTitle = formatMessage({
84
+ id: 'app.components.LeftMenu.navbrand.title',
85
+ defaultMessage: 'Strapi Dashboard',
86
+ });
87
+
83
88
  return (
84
89
  <MainNav condensed={condensed}>
85
90
  <NavBrand
86
- workplace="Workplace"
87
- title="Strapi Dashboard"
88
- icon={<img src={menuLogo} alt="Strapi Dashboard" />}
91
+ workplace={formatMessage({
92
+ id: 'app.components.LeftMenu.navbrand.workplace',
93
+ defaultMessage: 'Workplace',
94
+ })}
95
+ title={menuTitle}
96
+ icon={<img src={menuLogo} alt={menuTitle} />}
89
97
  />
90
98
 
91
99
  <Divider />
@@ -70,9 +70,14 @@ const UpgradePlanModal = ({ onClose, isOpen }) => {
70
70
 
71
71
  return (
72
72
  <Portal>
73
- <UpgradeWrapper>
73
+ <UpgradeWrapper onClick={onClose}>
74
74
  <FocusTrap onEscape={onClose}>
75
- <UpgradeContainer aria-labelledby="upgrade-plan" background="neutral0" hasRadius>
75
+ <UpgradeContainer
76
+ onClick={e => e.stopPropagation()}
77
+ aria-labelledby="upgrade-plan"
78
+ background="neutral0"
79
+ hasRadius
80
+ >
76
81
  <img src={AirBalloon} alt="air-balloon" />
77
82
  <CloseButtonContainer>
78
83
  <IconButton onClick={onClose} aria-label="Close" icon={<Cross />} />
@@ -17,7 +17,7 @@ const StyledBox = styled(Box)`
17
17
  border-radius: ${pxToRem(26)};
18
18
  `;
19
19
 
20
- const DzLabel = ({ label, labelAction, name, numberOfComponents, required }) => {
20
+ const DzLabel = ({ label, labelAction, name, numberOfComponents, required, intlDescription }) => {
21
21
  const { formatMessage } = useIntl();
22
22
  const intlLabel = formatMessage({ id: label || name, defaultMessage: label || name });
23
23
 
@@ -33,12 +33,24 @@ const DzLabel = ({ label, labelAction, name, numberOfComponents, required }) =>
33
33
  shadow="filterShadow"
34
34
  color="neutral500"
35
35
  >
36
- <Flex>
37
- <Typography fontSize={0} lineHeight={0} textColor="neutral600" fontWeight="bold">
38
- {intlLabel}&nbsp;({numberOfComponents})
39
- </Typography>
40
- {required && <Typography textColor="danger600">*</Typography>}
41
- {labelAction && <Box paddingLeft={1}>{labelAction}</Box>}
36
+ <Flex direction="column" justifyContent="center">
37
+ <Flex maxWidth={pxToRem(356)}>
38
+ <Typography variant="pi" textColor="neutral600" fontWeight="bold" ellipsis>
39
+ {intlLabel}&nbsp;
40
+ </Typography>
41
+ <Typography variant="pi" textColor="neutral600" fontWeight="bold">
42
+ ({numberOfComponents})
43
+ </Typography>
44
+ {required && <Typography textColor="danger600">*</Typography>}
45
+ {labelAction && <Box paddingLeft={1}>{labelAction}</Box>}
46
+ </Flex>
47
+ {intlDescription && (
48
+ <Box paddingTop={1} maxWidth={pxToRem(356)}>
49
+ <Typography variant="pi" textColor="neutral600" ellipsis>
50
+ {formatMessage(intlDescription)}
51
+ </Typography>
52
+ </Box>
53
+ )}
42
54
  </Flex>
43
55
  </StyledBox>
44
56
  </Box>
@@ -47,12 +59,17 @@ const DzLabel = ({ label, labelAction, name, numberOfComponents, required }) =>
47
59
  };
48
60
 
49
61
  DzLabel.defaultProps = {
62
+ intlDescription: undefined,
50
63
  label: '',
51
64
  labelAction: undefined,
52
65
  required: false,
53
66
  };
54
67
 
55
68
  DzLabel.propTypes = {
69
+ intlDescription: PropTypes.shape({
70
+ id: PropTypes.string.isRequired,
71
+ defaultMessage: PropTypes.string.isRequired,
72
+ }),
56
73
  label: PropTypes.string,
57
74
  labelAction: PropTypes.element,
58
75
  name: PropTypes.string.isRequired,
@@ -39,6 +39,9 @@ const DynamicZone = ({
39
39
  const [isOpen, setIsOpen] = useState(false);
40
40
  const [shouldOpenAddedComponent, setShouldOpenAddedComponent] = useState(false);
41
41
  const dynamicDisplayedComponentsLength = dynamicDisplayedComponents.length;
42
+ const intlDescription = metadatas.description
43
+ ? { id: metadatas.description, defaultMessage: metadatas.description }
44
+ : null;
42
45
 
43
46
  const [componentCollapses, setComponentsCollapses] = useState(
44
47
  createCollapses(dynamicDisplayedComponentsLength)
@@ -159,11 +162,7 @@ const DynamicZone = ({
159
162
  if (!isFieldAllowed && isCreatingEntry) {
160
163
  return (
161
164
  <NotAllowedInput
162
- description={
163
- metadatas.description
164
- ? { id: metadatas.description, defaultMessage: metadatas.description }
165
- : null
166
- }
165
+ description={intlDescription}
167
166
  intlLabel={{ id: metadatas.label, defaultMessage: metadatas.label }}
168
167
  labelAction={labelAction}
169
168
  name={name}
@@ -174,11 +173,7 @@ const DynamicZone = ({
174
173
  if (!isFieldAllowed && !isFieldReadable && !isCreatingEntry) {
175
174
  return (
176
175
  <NotAllowedInput
177
- description={
178
- metadatas.description
179
- ? { id: metadatas.description, defaultMessage: metadatas.description }
180
- : null
181
- }
176
+ description={intlDescription}
182
177
  intlLabel={{ id: metadatas.label, defaultMessage: metadatas.label }}
183
178
  labelAction={labelAction}
184
179
  name={name}
@@ -191,6 +186,7 @@ const DynamicZone = ({
191
186
  {dynamicDisplayedComponentsLength > 0 && (
192
187
  <Box>
193
188
  <DzLabel
189
+ intlDescription={intlDescription}
194
190
  label={metadatas.label}
195
191
  labelAction={labelAction}
196
192
  name={name}
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Field } from '@strapi/design-system/Field';
5
+
6
+ const FieldWrapper = ({ name, hint, error, children }) => {
7
+ const { formatMessage } = useIntl();
8
+ const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : '';
9
+
10
+ return (
11
+ <Field name={name} hint={hint && formatMessage(hint)} error={errorMessage} id={name}>
12
+ {children}
13
+ </Field>
14
+ );
15
+ };
16
+
17
+ FieldWrapper.defaultProps = {
18
+ hint: undefined,
19
+ error: '',
20
+ };
21
+
22
+ FieldWrapper.propTypes = {
23
+ name: PropTypes.string.isRequired,
24
+ hint: PropTypes.shape({
25
+ id: PropTypes.string,
26
+ defaultMessage: PropTypes.string,
27
+ }),
28
+ error: PropTypes.string,
29
+ children: PropTypes.node.isRequired,
30
+ };
31
+
32
+ export default FieldWrapper;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import styled from 'styled-components';
4
4
  import { useIntl } from 'react-intl';
5
- import { Typography } from '@strapi/design-system/Typography';
5
+ import { FieldLabel } from '@strapi/design-system/Field';
6
6
  import { Box } from '@strapi/design-system/Box';
7
7
  import { Flex } from '@strapi/design-system/Flex';
8
8
 
@@ -12,7 +12,7 @@ const LabelAction = styled(Box)`
12
12
  }
13
13
  `;
14
14
 
15
- const Label = ({ id, intlLabel, labelAction, name }) => {
15
+ const Label = ({ intlLabel, labelAction, name, required }) => {
16
16
  const { formatMessage } = useIntl();
17
17
  const label = intlLabel?.id
18
18
  ? formatMessage(
@@ -23,15 +23,7 @@ const Label = ({ id, intlLabel, labelAction, name }) => {
23
23
 
24
24
  return (
25
25
  <Flex>
26
- <Typography
27
- textColor="neutral800"
28
- htmlFor={id || name}
29
- variant="pi"
30
- fontWeight="bold"
31
- as="label"
32
- >
33
- {label}
34
- </Typography>
26
+ <FieldLabel required={required}>{label}</FieldLabel>
35
27
  {labelAction && <LabelAction paddingLeft={1}>{labelAction}</LabelAction>}
36
28
  </Flex>
37
29
  );
@@ -41,6 +33,7 @@ Label.defaultProps = {
41
33
  id: undefined,
42
34
  intlLabel: undefined,
43
35
  labelAction: undefined,
36
+ required: false,
44
37
  };
45
38
 
46
39
  Label.propTypes = {
@@ -52,6 +45,7 @@ Label.propTypes = {
52
45
  }),
53
46
  labelAction: PropTypes.element,
54
47
  name: PropTypes.string.isRequired,
48
+ required: PropTypes.bool,
55
49
  };
56
50
 
57
51
  export default Label;
@@ -9,11 +9,11 @@ import PropTypes from 'prop-types';
9
9
  import cm from 'codemirror';
10
10
  import trimStart from 'lodash/trimStart';
11
11
  import { Stack } from '@strapi/design-system/Stack';
12
+ import { FieldHint, FieldError } from '@strapi/design-system/Field';
12
13
  import jsonlint from './jsonlint';
13
14
  import { EditorWrapper, StyledBox } from './components';
14
- import Hint from '../Hint';
15
15
  import Label from './Label';
16
- import FieldError from './FieldError';
16
+ import FieldWrapper from './FieldWrapper';
17
17
 
18
18
  const WAIT = 600;
19
19
  const stringify = JSON.stringify;
@@ -159,30 +159,28 @@ class InputJSON extends React.Component {
159
159
  }
160
160
 
161
161
  return (
162
- <Stack size={1}>
163
- <Label
164
- intlLabel={this.props.intlLabel}
165
- labelAction={this.props.labelAction}
166
- name={this.props.name}
167
- />
168
- <StyledBox error={this.props.error}>
169
- <EditorWrapper disabled={this.props.disabled}>
170
- <textarea
171
- ref={this.editor}
172
- autoComplete="off"
173
- id={this.props.id || this.props.name}
174
- defaultValue=""
175
- />
176
- </EditorWrapper>
177
- </StyledBox>
178
- <Hint
179
- description={this.props.description}
180
- name={this.props.name}
181
- id={this.props.id}
182
- error={this.props.error}
183
- />
184
- <FieldError id={this.props.id} name={this.props.name} error={this.props.error} />
185
- </Stack>
162
+ <FieldWrapper name={this.props.name} hint={this.props.description} error={this.props.error}>
163
+ <Stack size={1}>
164
+ <Label
165
+ intlLabel={this.props.intlLabel}
166
+ labelAction={this.props.labelAction}
167
+ name={this.props.name}
168
+ required={this.props.required}
169
+ />
170
+ <StyledBox error={this.props.error}>
171
+ <EditorWrapper disabled={this.props.disabled}>
172
+ <textarea
173
+ ref={this.editor}
174
+ autoComplete="off"
175
+ id={this.props.id || this.props.name}
176
+ defaultValue=""
177
+ />
178
+ </EditorWrapper>
179
+ </StyledBox>
180
+ <FieldHint />
181
+ <FieldError />
182
+ </Stack>
183
+ </FieldWrapper>
186
184
  );
187
185
  }
188
186
  }
@@ -196,6 +194,7 @@ InputJSON.defaultProps = {
196
194
  labelAction: undefined,
197
195
  onChange: () => {},
198
196
  value: null,
197
+ required: false,
199
198
  };
200
199
 
201
200
  InputJSON.propTypes = {
@@ -216,6 +215,7 @@ InputJSON.propTypes = {
216
215
  name: PropTypes.string.isRequired,
217
216
  onChange: PropTypes.func,
218
217
  value: PropTypes.any,
218
+ required: PropTypes.bool,
219
219
  };
220
220
 
221
221
  export default InputJSON;
@@ -23,6 +23,10 @@ const Wrapper = styled.div`
23
23
  margin-block-end: 10px;
24
24
  }
25
25
 
26
+ p {
27
+ margin-bottom: 10px;
28
+ }
29
+
26
30
  h1 {
27
31
  font-size: ${36 / 16}rem;
28
32
  font-weight: 600;
@@ -20,7 +20,7 @@ loadCss();
20
20
  const md = new Markdown({
21
21
  html: true, // Enable HTML tags in source
22
22
  xhtmlOut: false,
23
- breaks: false,
23
+ breaks: true,
24
24
  langPrefix: 'language-',
25
25
  linkify: true,
26
26
  typographer: true,
@@ -12,6 +12,7 @@ const Editor = ({
12
12
  editorRef,
13
13
  error,
14
14
  isPreviewMode,
15
+ isExpandMode,
15
16
  name,
16
17
  onChange,
17
18
  placeholder,
@@ -25,9 +26,8 @@ const Editor = ({
25
26
  lineWrapping: true,
26
27
  extraKeys: {
27
28
  Enter: 'newlineAndIndentContinueMarkdownList',
28
- // Leaving this commented for now
29
- // Tab: false,
30
- // 'Shift-Tab': false,
29
+ Tab: false,
30
+ 'Shift-Tab': false,
31
31
  },
32
32
  readOnly: false,
33
33
  smartIndent: false,
@@ -65,7 +65,7 @@ const Editor = ({
65
65
 
66
66
  return (
67
67
  <EditorAndPreviewWrapper>
68
- <EditorStylesContainer disabled={disabled || isPreviewMode}>
68
+ <EditorStylesContainer isExpandMode={isExpandMode} disabled={disabled || isPreviewMode}>
69
69
  <textarea ref={textareaRef} />
70
70
  </EditorStylesContainer>
71
71
  {isPreviewMode && <PreviewWysiwyg data={value} />}
@@ -77,6 +77,7 @@ Editor.defaultProps = {
77
77
  disabled: false,
78
78
  error: undefined,
79
79
  isPreviewMode: false,
80
+ isExpandMode: false,
80
81
  placeholder: '',
81
82
  value: '',
82
83
  };
@@ -86,6 +87,7 @@ Editor.propTypes = {
86
87
  editorRef: PropTypes.shape({ current: PropTypes.any }).isRequired,
87
88
  error: PropTypes.string,
88
89
  isPreviewMode: PropTypes.bool,
90
+ isExpandMode: PropTypes.bool,
89
91
  name: PropTypes.string.isRequired,
90
92
  onChange: PropTypes.func.isRequired,
91
93
  placeholder: PropTypes.string,
@@ -68,6 +68,7 @@ export const EditorLayout = ({ children, isExpandMode, error, previewContent, on
68
68
  bottom={0}
69
69
  zIndex={4}
70
70
  justifyContent="center"
71
+ onClick={onCollapse}
71
72
  >
72
73
  <Box
73
74
  id="wysiwyg-expand"
@@ -77,6 +78,7 @@ export const EditorLayout = ({ children, isExpandMode, error, previewContent, on
77
78
  overflow="hidden"
78
79
  width="70%"
79
80
  height="70%"
81
+ onClick={e => e.stopPropagation()}
80
82
  >
81
83
  <Flex height="100%" alignItems="flex-start">
82
84
  <BoxWithBorder flex="1" height="100%">
@@ -4,6 +4,7 @@ import styled from 'styled-components';
4
4
  /* stylelint-disable */
5
5
  export const EditorStylesContainer = styled.div`
6
6
  cursor: ${({ disabled }) => (disabled ? 'not-allowed !important' : 'auto')};
7
+ height: 100%;
7
8
  /* BASICS */
8
9
  .CodeMirror-placeholder {
9
10
  color: ${({ theme }) => theme.colors.neutral600} !important;
@@ -12,7 +13,7 @@ export const EditorStylesContainer = styled.div`
12
13
  .CodeMirror {
13
14
  /* Set height, width, borders, and global font properties here */
14
15
  font-size: ${14 / 16}rem;
15
- height: 290px;
16
+ height: ${({ isExpandMode }) => (isExpandMode ? '100%' : '290px')};
16
17
  color: ${({ theme }) => theme.colors.neutral800};
17
18
  direction: ltr;
18
19
  font-family: --apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
@@ -7,13 +7,13 @@ import { Typography } from '@strapi/design-system/Typography';
7
7
  import Expand from '@strapi/icons/Expand';
8
8
  import { ExpandButton } from './WysiwygStyles';
9
9
 
10
- const WysiwygFooter = ({ isPreviewMode, onToggleExpand }) => {
10
+ const WysiwygFooter = ({ onToggleExpand }) => {
11
11
  const { formatMessage } = useIntl();
12
12
 
13
13
  return (
14
14
  <Box padding={2} background="neutral100" hasRadius>
15
15
  <Flex justifyContent="flex-end" alignItems="flex-end">
16
- <ExpandButton id="expand" disabled={isPreviewMode} onClick={onToggleExpand}>
16
+ <ExpandButton id="expand" onClick={onToggleExpand}>
17
17
  <Typography>
18
18
  {formatMessage({
19
19
  id: 'components.WysiwygBottomControls.fullscreen',
@@ -29,12 +29,10 @@ const WysiwygFooter = ({ isPreviewMode, onToggleExpand }) => {
29
29
 
30
30
  WysiwygFooter.defaultProps = {
31
31
  onToggleExpand: () => {},
32
- isPreviewMode: false,
33
32
  };
34
33
 
35
34
  WysiwygFooter.propTypes = {
36
35
  onToggleExpand: PropTypes.func,
37
- isPreviewMode: PropTypes.bool,
38
36
  };
39
37
 
40
38
  export default WysiwygFooter;
@@ -1,6 +1,7 @@
1
1
  import React, { useRef, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useIntl } from 'react-intl';
4
+ import { FocusTrap } from '@strapi/design-system/FocusTrap';
4
5
  import { Box } from '@strapi/design-system/Box';
5
6
  import { Button } from '@strapi/design-system/Button';
6
7
  import { IconButtonGroup } from '@strapi/design-system/IconButton';
@@ -27,7 +28,9 @@ import {
27
28
  } from './WysiwygStyles';
28
29
 
29
30
  const WysiwygNav = ({
31
+ disabled,
30
32
  editorRef,
33
+ isExpandMode,
31
34
  isPreviewMode,
32
35
  onActionClick,
33
36
  onToggleMediaLib,
@@ -41,9 +44,11 @@ const WysiwygNav = ({
41
44
  });
42
45
  const buttonMoreRef = useRef();
43
46
 
44
- const handleTogglePopover = () => setVisiblePopover(prev => !prev);
47
+ const handleTogglePopover = () => {
48
+ setVisiblePopover(prev => !prev);
49
+ };
45
50
 
46
- if (isPreviewMode) {
51
+ if (disabled || isPreviewMode) {
47
52
  return (
48
53
  <Box padding={2} background="neutral100">
49
54
  <Flex justifyContent="space-between">
@@ -81,15 +86,17 @@ const WysiwygNav = ({
81
86
  />
82
87
  </MainButtons>
83
88
 
84
- <MoreButton disabled ref={buttonMoreRef} id="more" label="More" icon={<More />} />
89
+ <MoreButton disabled id="more" label="More" icon={<More />} />
85
90
  </Flex>
86
91
 
87
- <Button onClick={onTogglePreviewMode} variant="tertiary" size="L" id="preview">
88
- {formatMessage({
89
- id: 'components.Wysiwyg.ToggleMode.markdown-mode',
90
- defaultMessage: 'Markdown mode',
91
- })}
92
- </Button>
92
+ {!isExpandMode && (
93
+ <Button onClick={onTogglePreviewMode} variant="tertiary" id="preview">
94
+ {formatMessage({
95
+ id: 'components.Wysiwyg.ToggleMode.markdown-mode',
96
+ defaultMessage: 'Markdown mode',
97
+ })}
98
+ </Button>
99
+ )}
93
100
  </Flex>
94
101
  </Box>
95
102
  );
@@ -146,65 +153,67 @@ const WysiwygNav = ({
146
153
  />
147
154
  {visiblePopover && (
148
155
  <Popover centered source={buttonMoreRef} spacing={4} id="popover">
149
- <Flex>
150
- <IconButtonGroupMargin>
151
- <CustomIconButton
152
- onClick={() => onActionClick('Strikethrough', editorRef, handleTogglePopover)}
153
- id="Strikethrough"
154
- label="Strikethrough"
155
- name="Strikethrough"
156
- icon={<Strikethrough />}
157
- />
158
- <CustomIconButton
159
- onClick={() => onActionClick('BulletList', editorRef, handleTogglePopover)}
160
- id="BulletList"
161
- label="BulletList"
162
- name="BulletList"
163
- icon={<BulletList />}
164
- />
165
- <CustomIconButton
166
- onClick={() => onActionClick('NumberList', editorRef, handleTogglePopover)}
167
- id="NumberList"
168
- label="NumberList"
169
- name="NumberList"
170
- icon={<NumberList />}
171
- />
172
- </IconButtonGroupMargin>
173
- <IconButtonGroup>
174
- <CustomIconButton
175
- onClick={() => onActionClick('Code', editorRef, handleTogglePopover)}
176
- id="Code"
177
- label="Code"
178
- name="Code"
179
- icon={<Code />}
180
- />
181
- <CustomIconButton
182
- onClick={() => {
183
- handleTogglePopover();
184
- onToggleMediaLib();
185
- }}
186
- id="Image"
187
- label="Image"
188
- name="Image"
189
- icon={<Image />}
190
- />
191
- <CustomLinkIconButton
192
- onClick={() => onActionClick('Link', editorRef, handleTogglePopover)}
193
- id="Link"
194
- label="Link"
195
- name="Link"
196
- // eslint-disable-next-line jsx-a11y/anchor-is-valid
197
- icon={<Link />}
198
- />
199
- <CustomIconButton
200
- onClick={() => onActionClick('Quote', editorRef, handleTogglePopover)}
201
- id="Quote"
202
- label="Quote"
203
- name="Quote"
204
- icon={<Quote />}
205
- />
206
- </IconButtonGroup>
207
- </Flex>
156
+ <FocusTrap onEscape={handleTogglePopover} restoreFocus={false}>
157
+ <Flex>
158
+ <IconButtonGroupMargin>
159
+ <CustomIconButton
160
+ onClick={() => onActionClick('Strikethrough', editorRef, handleTogglePopover)}
161
+ id="Strikethrough"
162
+ label="Strikethrough"
163
+ name="Strikethrough"
164
+ icon={<Strikethrough />}
165
+ />
166
+ <CustomIconButton
167
+ onClick={() => onActionClick('BulletList', editorRef, handleTogglePopover)}
168
+ id="BulletList"
169
+ label="BulletList"
170
+ name="BulletList"
171
+ icon={<BulletList />}
172
+ />
173
+ <CustomIconButton
174
+ onClick={() => onActionClick('NumberList', editorRef, handleTogglePopover)}
175
+ id="NumberList"
176
+ label="NumberList"
177
+ name="NumberList"
178
+ icon={<NumberList />}
179
+ />
180
+ </IconButtonGroupMargin>
181
+ <IconButtonGroup>
182
+ <CustomIconButton
183
+ onClick={() => onActionClick('Code', editorRef, handleTogglePopover)}
184
+ id="Code"
185
+ label="Code"
186
+ name="Code"
187
+ icon={<Code />}
188
+ />
189
+ <CustomIconButton
190
+ onClick={() => {
191
+ handleTogglePopover();
192
+ onToggleMediaLib();
193
+ }}
194
+ id="Image"
195
+ label="Image"
196
+ name="Image"
197
+ icon={<Image />}
198
+ />
199
+ <CustomLinkIconButton
200
+ onClick={() => onActionClick('Link', editorRef, handleTogglePopover)}
201
+ id="Link"
202
+ label="Link"
203
+ name="Link"
204
+ // eslint-disable-next-line jsx-a11y/anchor-is-valid
205
+ icon={<Link />}
206
+ />
207
+ <CustomIconButton
208
+ onClick={() => onActionClick('Quote', editorRef, handleTogglePopover)}
209
+ id="Quote"
210
+ label="Quote"
211
+ name="Quote"
212
+ icon={<Quote />}
213
+ />
214
+ </IconButtonGroup>
215
+ </Flex>
216
+ </FocusTrap>
208
217
  </Popover>
209
218
  )}
210
219
  </Flex>
@@ -230,7 +239,9 @@ WysiwygNav.defaultProps = {
230
239
  };
231
240
 
232
241
  WysiwygNav.propTypes = {
242
+ disabled: PropTypes.bool.isRequired,
233
243
  editorRef: PropTypes.shape({ current: PropTypes.any }).isRequired,
244
+ isExpandMode: PropTypes.bool.isRequired,
234
245
  isPreviewMode: PropTypes.bool,
235
246
  onActionClick: PropTypes.func,
236
247
  onToggleMediaLib: PropTypes.func,
@@ -45,6 +45,7 @@ export const IconButtonGroupMargin = styled(IconButtonGroup)`
45
45
 
46
46
  export const EditorAndPreviewWrapper = styled.div`
47
47
  position: relative;
48
+ height: calc(100% - 48px);
48
49
  `;
49
50
 
50
51
  // FOOTER