@strapi/admin 4.0.4 → 4.0.8
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.
- package/admin/src/components/UpgradePlanModal/index.js +7 -2
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/isValidJSONString.js +15 -0
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/schema.js +11 -12
- package/admin/src/content-manager/components/InputJSON/FieldWrapper.js +32 -0
- package/admin/src/content-manager/components/InputJSON/Label.js +5 -11
- package/admin/src/content-manager/components/InputJSON/index.js +27 -27
- package/admin/src/content-manager/components/PreviewWysiwyg/Wrapper.js +4 -0
- package/admin/src/content-manager/components/PreviewWysiwyg/utils/mdRenderer.js +1 -1
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/index.js +4 -0
- package/admin/src/content-manager/components/Wysiwyg/Editor.js +4 -1
- package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +2 -1
- package/admin/src/content-manager/components/Wysiwyg/WysiwygNav.js +14 -8
- package/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.js +1 -0
- package/admin/src/content-manager/components/Wysiwyg/index.js +4 -1
- package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.js +1 -3
- package/admin/src/content-manager/pages/EditSettingsView/components/FormModal.js +4 -3
- package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +52 -11
- package/admin/src/content-manager/pages/EditSettingsView/index.js +10 -1
- package/admin/src/content-manager/pages/EditSettingsView/reducer.js +26 -5
- package/admin/src/content-manager/pages/EditSettingsView/utils/layout.js +40 -9
- package/admin/src/content-manager/pages/EditView/index.js +2 -1
- package/admin/src/pages/Admin/index.js +2 -0
- package/admin/src/pages/InternalErrorPage/index.js +53 -0
- package/admin/src/pages/MarketplacePage/index.js +13 -13
- package/admin/src/pages/NotFoundPage/index.js +45 -2
- package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +2 -10
- package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/utils/schema.js +1 -4
- package/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js +4 -1
- package/admin/src/translations/dk.json +300 -110
- package/admin/src/translations/en.json +5 -1
- package/admin/src/translations/es.json +204 -4
- package/admin/src/translations/fr.json +3 -0
- package/admin/src/translations/hu.json +672 -0
- package/admin/src/translations/ja.json +327 -7
- package/admin/src/translations/languageNativeNames.js +1 -0
- package/admin/src/translations/nl.json +512 -125
- package/admin/src/translations/pt-BR.json +398 -19
- package/admin/src/translations/uk.json +40 -40
- package/admin/src/translations/zh-Hans.json +9 -9
- package/admin/src/translations/zh.json +7 -0
- package/build/1856.a06395b4.chunk.js +1 -0
- package/build/2481.7d15bd79.chunk.js +1 -0
- package/build/2912.38fb9bd1.chunk.js +1 -0
- package/build/{6354.48168bc8.chunk.js → 3215.4d042146.chunk.js} +2 -2
- package/build/{6354.48168bc8.chunk.js.LICENSE.txt → 3215.4d042146.chunk.js.LICENSE.txt} +0 -0
- package/build/4261.a4e1e93c.chunk.js +1 -0
- package/build/4362.e3d2d72b.chunk.js +1 -0
- package/build/460.639962f0.chunk.js +2 -0
- package/build/{6060.3af8877e.chunk.js.LICENSE.txt → 460.639962f0.chunk.js.LICENSE.txt} +0 -0
- package/build/4715.31ca1967.chunk.js +1 -0
- package/build/4741.c2bfe032.chunk.js +2 -0
- package/build/{4741.1fb6ad6e.chunk.js.LICENSE.txt → 4741.c2bfe032.chunk.js.LICENSE.txt} +0 -0
- package/build/497.8f30da61.chunk.js +1 -0
- package/build/4982.da4adb38.chunk.js +1 -0
- package/build/5032.ed02a466.chunk.js +2 -0
- package/build/{8530.a978bde6.chunk.js.LICENSE.txt → 5032.ed02a466.chunk.js.LICENSE.txt} +0 -0
- package/build/6250.dc6d7a58.chunk.js +1 -0
- package/build/6925.bd694b04.chunk.js +2 -0
- package/build/{6925.4767e761.chunk.js.LICENSE.txt → 6925.bd694b04.chunk.js.LICENSE.txt} +2 -1
- package/build/7841.ef9bcee9.chunk.js +1 -0
- package/build/849.9075d399.chunk.js +1 -0
- package/build/9235.ced8aebf.chunk.js +1 -0
- package/build/9238.bdd93dae.chunk.js +1 -0
- package/build/Admin-authenticatedApp.f65c428a.chunk.js +1 -0
- package/build/Admin_homePage.a20b5e76.chunk.js +1 -0
- package/build/Admin_marketplace.e8654056.chunk.js +1 -0
- package/build/Admin_pluginsPage.7d1bd7ce.chunk.js +1 -0
- package/build/{Admin_profilePage.077e17a5.chunk.js → Admin_profilePage.67dd744c.chunk.js} +1 -1
- package/build/Admin_settingsPage.05877e0b.chunk.js +1 -0
- package/build/admin-edit-roles-page.2d1b6461.chunk.js +1 -0
- package/build/admin-edit-users.e736db15.chunk.js +1 -0
- package/build/admin-users.5f79c031.chunk.js +1 -0
- package/build/api-tokens-create-page.10586e16.chunk.js +1 -0
- package/build/{api-tokens-create-page.07be3e07.chunk.js → api-tokens-edit-page.f9e3038d.chunk.js} +1 -1
- package/build/{api-tokens-list-page.da9714d8.chunk.js → api-tokens-list-page.e071058b.chunk.js} +1 -1
- package/build/codemirror-css.48b438c9.chunk.js +1 -0
- package/build/{codemirror-javacript.381a518a.chunk.js → codemirror-javacript.8c7c015d.chunk.js} +1 -1
- package/build/codemirror-theme.b5559efc.chunk.js +1 -0
- package/build/content-manager.07db1dd9.chunk.js +1 -0
- package/build/{content-type-builder-translation-dk-json.5c6344f9.chunk.js → content-type-builder-translation-dk-json.098bd218.chunk.js} +1 -1
- package/build/content-type-builder-translation-es-json.20c177ee.chunk.js +1 -0
- package/build/content-type-builder.52f5975c.chunk.js +1 -0
- package/build/cropper-css.ace19575.chunk.js +1 -0
- package/build/dk-json.7356ea4b.chunk.js +1 -0
- package/build/email-settings-page.4338588d.chunk.js +1 -0
- package/build/email-translation-dk-json.f8a595bf.chunk.js +1 -0
- package/build/email-translation-es-json.eb303dea.chunk.js +1 -0
- package/build/en-json.3422a59e.chunk.js +1 -0
- package/build/es-json.ed9c8bef.chunk.js +1 -0
- package/build/fontawesome-css-all.3b89f909.chunk.js +1 -0
- package/build/fontawesome-css.36cff9ae.chunk.js +1 -0
- package/build/fr-json.390bcdeb.chunk.js +1 -0
- package/build/highlight.js.6321cb45.chunk.js +1 -0
- package/build/hu-json.a741d263.chunk.js +1 -0
- package/build/i18n-settings-page.51e37957.chunk.js +1 -0
- package/build/i18n-translation-dk-json.932d3cc2.chunk.js +1 -0
- package/build/i18n-translation-es-json.347904f3.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/ja-json.52581a2a.chunk.js +1 -0
- package/build/main.59b96514.js +2 -0
- package/build/{main.ca080a1e.js.LICENSE.txt → main.59b96514.js.LICENSE.txt} +0 -0
- package/build/nl-json.ac661b7f.chunk.js +1 -0
- package/build/pt-BR-json.8b3f799d.chunk.js +1 -0
- package/build/runtime~main.75c67df1.js +1 -0
- package/build/{sk-json.2eb1ec0d.chunk.js → sk-json.a40bc2c8.chunk.js} +1 -1
- package/build/sso-settings-page.c073b6d7.chunk.js +1 -0
- package/build/uk-json.da2ed14e.chunk.js +1 -0
- package/build/upload-settings.62631a39.chunk.js +1 -0
- package/build/{upload-translation-dk-json.e8c0a891.chunk.js → upload-translation-dk-json.bc6af8b4.chunk.js} +1 -1
- package/build/upload-translation-en-json.6b529046.chunk.js +1 -0
- package/build/upload-translation-es-json.b53d6641.chunk.js +1 -0
- package/build/{upload-translation-ja-json.568f097e.chunk.js → upload-translation-ja-json.71aa85eb.chunk.js} +1 -1
- package/build/upload.803ab265.chunk.js +1 -0
- package/build/users-advanced-settings-page.7694d3c9.chunk.js +1 -0
- package/build/users-email-settings-page.862eb51e.chunk.js +1 -0
- package/build/{users-permissions-translation-dk-json.a36b323b.chunk.js → users-permissions-translation-dk-json.3e0295e5.chunk.js} +1 -1
- package/build/users-permissions-translation-es-json.a4f81eaa.chunk.js +1 -0
- package/build/{users-permissions-translation-ru-json.44dd1f10.chunk.js → users-permissions-translation-ru-json.5709c5a0.chunk.js} +1 -1
- package/build/users-providers-settings-page.47f97b06.chunk.js +1 -0
- package/build/users-roles-settings-page.b67e2b4d.chunk.js +1 -0
- package/build/webhook-edit-page.adad0a42.chunk.js +1 -0
- package/build/webhook-list-page.5c8f2a91.chunk.js +1 -0
- package/build/zh-Hans-json.5843950b.chunk.js +1 -0
- package/build/zh-json.2e4c9ef4.chunk.js +1 -0
- package/ee/admin/pages/App/utils/customRoutes.js +1 -1
- package/ee/server/controllers/authentication/utils.js +1 -1
- package/index.js +43 -26
- package/package.json +13 -13
- package/server/bootstrap.js +16 -0
- package/server/controllers/webhooks.js +6 -10
- package/server/services/api-token.js +1 -1
- package/server/services/metrics.js +6 -0
- package/server/services/permission/permissions-manager/sanitize.js +13 -5
- package/server/services/user.js +10 -0
- package/server/strategies/api-token.js +0 -3
- package/build/1024.1b15fbb5.chunk.js +0 -1
- package/build/1856.0a6992d6.chunk.js +0 -1
- package/build/2912.d903b59a.chunk.js +0 -1
- package/build/3742.2281afd7.chunk.js +0 -1
- package/build/4045.0b43d55e.chunk.js +0 -1
- package/build/4064.2683bcce.chunk.js +0 -1
- package/build/4261.061aed35.chunk.js +0 -1
- package/build/4672.7ad6782a.chunk.js +0 -1
- package/build/4715.f134f37a.chunk.js +0 -1
- package/build/4741.1fb6ad6e.chunk.js +0 -2
- package/build/497.726adbfa.chunk.js +0 -1
- package/build/4982.a7f87e6c.chunk.js +0 -1
- package/build/6060.3af8877e.chunk.js +0 -2
- package/build/6250.7b4872b1.chunk.js +0 -1
- package/build/6925.4767e761.chunk.js +0 -2
- package/build/7841.d2aa6f5e.chunk.js +0 -1
- package/build/8530.a978bde6.chunk.js +0 -2
- package/build/Admin-authenticatedApp.8c375af0.chunk.js +0 -1
- package/build/Admin_homePage.f9cdd615.chunk.js +0 -1
- package/build/Admin_marketplace.4f6c77f2.chunk.js +0 -1
- package/build/Admin_pluginsPage.cd9a871c.chunk.js +0 -1
- package/build/Admin_settingsPage.9752ef85.chunk.js +0 -1
- package/build/admin-edit-roles-page.27b047fc.chunk.js +0 -1
- package/build/admin-edit-users.a0dede23.chunk.js +0 -1
- package/build/admin-users.a11177c1.chunk.js +0 -1
- package/build/api-tokens-edit-page.d6afc60e.chunk.js +0 -1
- package/build/codemirror-css.f9701755.chunk.js +0 -1
- package/build/codemirror-theme.1563c1c2.chunk.js +0 -1
- package/build/content-manager.51651b3b.chunk.js +0 -1
- package/build/content-type-builder-translation-es-json.7e2055ad.chunk.js +0 -1
- package/build/content-type-builder.c815d0c6.chunk.js +0 -1
- package/build/cropper-css.45c47fe3.chunk.js +0 -1
- package/build/dk-json.9516eb08.chunk.js +0 -1
- package/build/email-settings-page.03e18bb2.chunk.js +0 -1
- package/build/email-translation-dk-json.e1480892.chunk.js +0 -1
- package/build/email-translation-es-json.abbba8e3.chunk.js +0 -1
- package/build/en-json.9e3c8615.chunk.js +0 -1
- package/build/es-json.fa8ddd1d.chunk.js +0 -1
- package/build/fontawesome-css-all.9c41f1d7.chunk.js +0 -1
- package/build/fontawesome-css.24c8dbfc.chunk.js +0 -1
- package/build/fr-json.bae03a2c.chunk.js +0 -1
- package/build/highlight.js.90b600ee.chunk.js +0 -1
- package/build/i18n-settings-page.89d1776c.chunk.js +0 -1
- package/build/ja-json.57abaacb.chunk.js +0 -1
- package/build/main.ca080a1e.js +0 -2
- package/build/nl-json.d757328d.chunk.js +0 -1
- package/build/pt-BR-json.6d1cfdb2.chunk.js +0 -1
- package/build/runtime~main.6f530910.js +0 -1
- package/build/sso-settings-page.d4ab164b.chunk.js +0 -1
- package/build/uk-json.c50ad2a8.chunk.js +0 -1
- package/build/upload-settings.aa148b01.chunk.js +0 -1
- package/build/upload-translation-en-json.31ea0622.chunk.js +0 -1
- package/build/upload-translation-es-json.42b5c758.chunk.js +0 -1
- package/build/upload.1991e997.chunk.js +0 -1
- package/build/users-advanced-settings-page.23ed7ee9.chunk.js +0 -1
- package/build/users-email-settings-page.64dc429a.chunk.js +0 -1
- package/build/users-permissions-translation-es-json.c8ef51bd.chunk.js +0 -1
- package/build/users-providers-settings-page.329f102a.chunk.js +0 -1
- package/build/users-roles-settings-page.e28982b6.chunk.js +0 -1
- package/build/webhook-edit-page.678af4e2.chunk.js +0 -1
- package/build/webhook-list-page.5abda9c2.chunk.js +0 -1
- package/build/zh-Hans-json.fcc53388.chunk.js +0 -1
- package/build/zh-json.496bd6c4.chunk.js +0 -1
|
@@ -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
|
|
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 />} />
|
package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/isValidJSONString.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const isValidJSONString = value => {
|
|
2
|
+
if (typeof value === 'string' && value.startsWith('"') && value.endsWith('"')) {
|
|
3
|
+
try {
|
|
4
|
+
JSON.parse(value);
|
|
5
|
+
|
|
6
|
+
return true;
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return false;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default isValidJSONString;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
isNaN,
|
|
10
|
-
toNumber,
|
|
11
|
-
} from 'lodash';
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import isBoolean from 'lodash/isBoolean';
|
|
3
|
+
import isNumber from 'lodash/isNumber';
|
|
4
|
+
import isNull from 'lodash/isNull';
|
|
5
|
+
import isObject from 'lodash/isObject';
|
|
6
|
+
import isEmpty from 'lodash/isEmpty';
|
|
7
|
+
import isNaN from 'lodash/isNaN';
|
|
8
|
+
import toNumber from 'lodash/toNumber';
|
|
12
9
|
|
|
13
10
|
import * as yup from 'yup';
|
|
14
11
|
import { translatedErrors as errorsTrads } from '@strapi/helper-plugin';
|
|
15
12
|
|
|
13
|
+
import isValidJSONString from './isValidJSONString';
|
|
14
|
+
|
|
16
15
|
yup.addMethod(yup.mixed, 'defined', function() {
|
|
17
16
|
return this.test('defined', errorsTrads.required, value => value !== undefined);
|
|
18
17
|
});
|
|
@@ -224,7 +223,7 @@ const createYupSchemaAttribute = (type, validations, options) => {
|
|
|
224
223
|
return true;
|
|
225
224
|
}
|
|
226
225
|
|
|
227
|
-
if (
|
|
226
|
+
if (isValidJSONString(value) || isNumber(value) || isNull(value) || isObject(value)) {
|
|
228
227
|
return true;
|
|
229
228
|
}
|
|
230
229
|
|
|
@@ -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 {
|
|
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 = ({
|
|
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
|
-
<
|
|
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
|
|
16
|
+
import FieldWrapper from './FieldWrapper';
|
|
17
17
|
|
|
18
18
|
const WAIT = 600;
|
|
19
19
|
const stringify = JSON.stringify;
|
|
@@ -80,7 +80,7 @@ class InputJSON extends React.Component {
|
|
|
80
80
|
try {
|
|
81
81
|
if (value === null) return this.codeMirror.setValue('');
|
|
82
82
|
|
|
83
|
-
const nextValue =
|
|
83
|
+
const nextValue = stringify(value, null, 2);
|
|
84
84
|
|
|
85
85
|
return this.codeMirror.setValue(nextValue);
|
|
86
86
|
} catch (err) {
|
|
@@ -159,30 +159,28 @@ class InputJSON extends React.Component {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
return (
|
|
162
|
-
<
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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;
|
|
@@ -121,6 +121,10 @@ const DraggedItem = ({
|
|
|
121
121
|
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
|
+
// If They are not in the same level, should not move
|
|
125
|
+
if (dragPath.split('.').length !== hoverPath.split('.').length) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
124
128
|
// Time to actually perform the action in the data
|
|
125
129
|
moveComponentField(pathToComponentArray, dragIndex, hoverIndex);
|
|
126
130
|
|
|
@@ -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,
|
|
@@ -64,7 +65,7 @@ const Editor = ({
|
|
|
64
65
|
|
|
65
66
|
return (
|
|
66
67
|
<EditorAndPreviewWrapper>
|
|
67
|
-
<EditorStylesContainer disabled={disabled || isPreviewMode}>
|
|
68
|
+
<EditorStylesContainer isExpandMode={isExpandMode} disabled={disabled || isPreviewMode}>
|
|
68
69
|
<textarea ref={textareaRef} />
|
|
69
70
|
</EditorStylesContainer>
|
|
70
71
|
{isPreviewMode && <PreviewWysiwyg data={value} />}
|
|
@@ -76,6 +77,7 @@ Editor.defaultProps = {
|
|
|
76
77
|
disabled: false,
|
|
77
78
|
error: undefined,
|
|
78
79
|
isPreviewMode: false,
|
|
80
|
+
isExpandMode: false,
|
|
79
81
|
placeholder: '',
|
|
80
82
|
value: '',
|
|
81
83
|
};
|
|
@@ -85,6 +87,7 @@ Editor.propTypes = {
|
|
|
85
87
|
editorRef: PropTypes.shape({ current: PropTypes.any }).isRequired,
|
|
86
88
|
error: PropTypes.string,
|
|
87
89
|
isPreviewMode: PropTypes.bool,
|
|
90
|
+
isExpandMode: PropTypes.bool,
|
|
88
91
|
name: PropTypes.string.isRequired,
|
|
89
92
|
onChange: PropTypes.func.isRequired,
|
|
90
93
|
placeholder: PropTypes.string,
|
|
@@ -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,
|
|
@@ -28,7 +28,9 @@ import {
|
|
|
28
28
|
} from './WysiwygStyles';
|
|
29
29
|
|
|
30
30
|
const WysiwygNav = ({
|
|
31
|
+
disabled,
|
|
31
32
|
editorRef,
|
|
33
|
+
isExpandMode,
|
|
32
34
|
isPreviewMode,
|
|
33
35
|
onActionClick,
|
|
34
36
|
onToggleMediaLib,
|
|
@@ -46,7 +48,7 @@ const WysiwygNav = ({
|
|
|
46
48
|
setVisiblePopover(prev => !prev);
|
|
47
49
|
};
|
|
48
50
|
|
|
49
|
-
if (isPreviewMode) {
|
|
51
|
+
if (disabled || isPreviewMode) {
|
|
50
52
|
return (
|
|
51
53
|
<Box padding={2} background="neutral100">
|
|
52
54
|
<Flex justifyContent="space-between">
|
|
@@ -87,12 +89,14 @@ const WysiwygNav = ({
|
|
|
87
89
|
<MoreButton disabled id="more" label="More" icon={<More />} />
|
|
88
90
|
</Flex>
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
+
)}
|
|
96
100
|
</Flex>
|
|
97
101
|
</Box>
|
|
98
102
|
);
|
|
@@ -149,7 +153,7 @@ const WysiwygNav = ({
|
|
|
149
153
|
/>
|
|
150
154
|
{visiblePopover && (
|
|
151
155
|
<Popover centered source={buttonMoreRef} spacing={4} id="popover">
|
|
152
|
-
<FocusTrap onEscape={handleTogglePopover}>
|
|
156
|
+
<FocusTrap onEscape={handleTogglePopover} restoreFocus={false}>
|
|
153
157
|
<Flex>
|
|
154
158
|
<IconButtonGroupMargin>
|
|
155
159
|
<CustomIconButton
|
|
@@ -235,7 +239,9 @@ WysiwygNav.defaultProps = {
|
|
|
235
239
|
};
|
|
236
240
|
|
|
237
241
|
WysiwygNav.propTypes = {
|
|
242
|
+
disabled: PropTypes.bool.isRequired,
|
|
238
243
|
editorRef: PropTypes.shape({ current: PropTypes.any }).isRequired,
|
|
244
|
+
isExpandMode: PropTypes.bool.isRequired,
|
|
239
245
|
isPreviewMode: PropTypes.bool,
|
|
240
246
|
onActionClick: PropTypes.func,
|
|
241
247
|
onToggleMediaLib: PropTypes.func,
|
|
@@ -144,15 +144,18 @@ const Wysiwyg = ({
|
|
|
144
144
|
onCollapse={handleToggleExpand}
|
|
145
145
|
>
|
|
146
146
|
<WysiwygNav
|
|
147
|
+
isExpandMode={isExpandMode}
|
|
147
148
|
editorRef={editorRef}
|
|
148
149
|
isPreviewMode={isPreviewMode}
|
|
149
150
|
onActionClick={handleActionClick}
|
|
150
151
|
onToggleMediaLib={handleToggleMediaLib}
|
|
151
152
|
onTogglePreviewMode={isExpandMode ? undefined : handleTogglePreviewMode}
|
|
153
|
+
disabled={disabled}
|
|
152
154
|
/>
|
|
153
155
|
|
|
154
156
|
<Editor
|
|
155
157
|
disabled={disabled}
|
|
158
|
+
isExpandMode={isExpandMode}
|
|
156
159
|
editorRef={editorRef}
|
|
157
160
|
error={errorMessage}
|
|
158
161
|
isPreviewMode={isPreviewMode}
|
|
@@ -185,7 +188,7 @@ const Wysiwyg = ({
|
|
|
185
188
|
|
|
186
189
|
Wysiwyg.defaultProps = {
|
|
187
190
|
description: null,
|
|
188
|
-
disabled:
|
|
191
|
+
disabled: false,
|
|
189
192
|
error: '',
|
|
190
193
|
labelAction: undefined,
|
|
191
194
|
placeholder: null,
|
|
@@ -41,9 +41,7 @@ const DisplayedFields = ({ editLayout, editLayoutRemainingFields, onRemoveField,
|
|
|
41
41
|
<Box padding={4} hasRadius borderStyle="dashed" borderWidth="1px" borderColor="neutral300">
|
|
42
42
|
<Stack size={2}>
|
|
43
43
|
{editLayout.map((row, index) => (
|
|
44
|
-
<
|
|
45
|
-
<RowsLayout row={row} rowIndex={index} onRemoveField={onRemoveField} />
|
|
46
|
-
</React.Fragment>
|
|
44
|
+
<RowsLayout key={row.rowId} row={row} rowIndex={index} onRemoveField={onRemoveField} />
|
|
47
45
|
))}
|
|
48
46
|
<SimpleMenu
|
|
49
47
|
id="label"
|
|
@@ -26,7 +26,7 @@ const HeaderContainer = styled(Flex)`
|
|
|
26
26
|
}
|
|
27
27
|
`;
|
|
28
28
|
|
|
29
|
-
const FormModal = ({ onToggle,
|
|
29
|
+
const FormModal = ({ onToggle, onMetaChange, onSizeChange, onSubmit, type }) => {
|
|
30
30
|
const { selectedField } = useLayoutDnd();
|
|
31
31
|
const { formatMessage } = useIntl();
|
|
32
32
|
|
|
@@ -61,7 +61,7 @@ const FormModal = ({ onToggle, onChange, onSubmit, type }) => {
|
|
|
61
61
|
</ModalHeader>
|
|
62
62
|
<ModalBody>
|
|
63
63
|
<Grid gap={4}>
|
|
64
|
-
<ModalForm
|
|
64
|
+
<ModalForm onMetaChange={onMetaChange} onSizeChange={onSizeChange} />
|
|
65
65
|
</Grid>
|
|
66
66
|
</ModalBody>
|
|
67
67
|
<ModalFooter
|
|
@@ -84,7 +84,8 @@ const FormModal = ({ onToggle, onChange, onSubmit, type }) => {
|
|
|
84
84
|
FormModal.propTypes = {
|
|
85
85
|
onSubmit: PropTypes.func.isRequired,
|
|
86
86
|
onToggle: PropTypes.func.isRequired,
|
|
87
|
-
|
|
87
|
+
onMetaChange: PropTypes.func.isRequired,
|
|
88
|
+
onSizeChange: PropTypes.func.isRequired,
|
|
88
89
|
type: PropTypes.string.isRequired,
|
|
89
90
|
};
|
|
90
91
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, { useMemo, useCallback } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
2
3
|
import get from 'lodash/get';
|
|
3
4
|
import { GridItem } from '@strapi/design-system/Grid';
|
|
5
|
+
import { Select, Option } from '@strapi/design-system/Select';
|
|
4
6
|
import { useSelector, shallowEqual } from 'react-redux';
|
|
5
7
|
import { useIntl } from 'react-intl';
|
|
6
8
|
import { useLayoutDnd } from '../../../hooks';
|
|
@@ -9,7 +11,11 @@ import { makeSelectModelAndComponentSchemas } from '../../App/selectors';
|
|
|
9
11
|
import getTrad from '../../../utils/getTrad';
|
|
10
12
|
import GenericInput from './GenericInput';
|
|
11
13
|
|
|
12
|
-
const
|
|
14
|
+
const FIELD_SIZES = [[4, '33%'], [6, '50%'], [8, '66%'], [12, '100%']];
|
|
15
|
+
|
|
16
|
+
const NON_RESIZABLE_FIELD_TYPES = ['dynamiczone', 'component', 'json', 'richtext'];
|
|
17
|
+
|
|
18
|
+
const ModalForm = ({ onMetaChange, onSizeChange }) => {
|
|
13
19
|
const { formatMessage } = useIntl();
|
|
14
20
|
const { modifiedData, selectedField, attributes, fieldForm } = useLayoutDnd();
|
|
15
21
|
const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []);
|
|
@@ -44,22 +50,21 @@ const ModalForm = ({ onChange }) => {
|
|
|
44
50
|
[selectedField, componentsAndModelsPossibleMainFields, modifiedData]
|
|
45
51
|
);
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
const metaFields = formToDisplay.map(meta => {
|
|
48
54
|
const formType = get(attributes, [selectedField, 'type']);
|
|
49
55
|
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if ((formType === 'component' || formType === 'media') && meta !== 'label') {
|
|
56
|
+
if (
|
|
57
|
+
formType === 'dynamiczone' ||
|
|
58
|
+
(formType === 'component' && !['label', 'description'].includes(meta))
|
|
59
|
+
) {
|
|
55
60
|
return null;
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
if (
|
|
63
|
+
if (formType === 'component' && meta !== 'label') {
|
|
59
64
|
return null;
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
if (
|
|
67
|
+
if (['media', 'json', 'boolean'].includes(formType) && meta === 'placeholder') {
|
|
63
68
|
return null;
|
|
64
69
|
}
|
|
65
70
|
|
|
@@ -78,13 +83,49 @@ const ModalForm = ({ onChange }) => {
|
|
|
78
83
|
id: get(getInputProps(meta), 'label.id', 'app.utils.defaultMessage'),
|
|
79
84
|
})}
|
|
80
85
|
name={meta}
|
|
81
|
-
onChange={
|
|
82
|
-
value={get(fieldForm, meta, '')}
|
|
86
|
+
onChange={onMetaChange}
|
|
87
|
+
value={get(fieldForm, ['metadata', meta], '')}
|
|
83
88
|
options={getSelectedItemSelectOptions(formType)}
|
|
84
89
|
/>
|
|
85
90
|
</GridItem>
|
|
86
91
|
);
|
|
87
92
|
});
|
|
93
|
+
|
|
94
|
+
const canResize = !NON_RESIZABLE_FIELD_TYPES.includes(attributes[selectedField].type);
|
|
95
|
+
|
|
96
|
+
const sizeField = (
|
|
97
|
+
<GridItem col={6} key="size">
|
|
98
|
+
<Select
|
|
99
|
+
value={fieldForm?.size}
|
|
100
|
+
name="size"
|
|
101
|
+
onChange={value => {
|
|
102
|
+
onSizeChange({ name: selectedField, value });
|
|
103
|
+
}}
|
|
104
|
+
label={formatMessage({
|
|
105
|
+
id: getTrad('containers.SettingPage.editSettings.size.label'),
|
|
106
|
+
defaultMessage: 'Size',
|
|
107
|
+
})}
|
|
108
|
+
>
|
|
109
|
+
{FIELD_SIZES.map(([value, label]) => (
|
|
110
|
+
<Option key={value} value={value}>
|
|
111
|
+
{label}
|
|
112
|
+
</Option>
|
|
113
|
+
))}
|
|
114
|
+
</Select>
|
|
115
|
+
</GridItem>
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<>
|
|
120
|
+
{metaFields}
|
|
121
|
+
{canResize && sizeField}
|
|
122
|
+
</>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
ModalForm.propTypes = {
|
|
127
|
+
onMetaChange: PropTypes.func.isRequired,
|
|
128
|
+
onSizeChange: PropTypes.func.isRequired,
|
|
88
129
|
};
|
|
89
130
|
|
|
90
131
|
export default ModalForm;
|
|
@@ -110,6 +110,14 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd
|
|
|
110
110
|
});
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
const handleSizeChange = ({ name, value }) => {
|
|
114
|
+
dispatch({
|
|
115
|
+
type: 'ON_CHANGE_SIZE',
|
|
116
|
+
name,
|
|
117
|
+
value,
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
113
121
|
const handleMetaSubmit = e => {
|
|
114
122
|
e.preventDefault();
|
|
115
123
|
dispatch({
|
|
@@ -365,7 +373,8 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd
|
|
|
365
373
|
onSubmit={handleMetaSubmit}
|
|
366
374
|
onToggle={handleToggleModal}
|
|
367
375
|
type={get(attributes, [metaToEdit, 'type'], '')}
|
|
368
|
-
|
|
376
|
+
onMetaChange={handleMetaChange}
|
|
377
|
+
onSizeChange={handleSizeChange}
|
|
369
378
|
/>
|
|
370
379
|
)}
|
|
371
380
|
</Main>
|
|
@@ -4,7 +4,7 @@ import get from 'lodash/get';
|
|
|
4
4
|
import cloneDeep from 'lodash/cloneDeep';
|
|
5
5
|
|
|
6
6
|
import { arrayMoveItem } from '../../utils';
|
|
7
|
-
import { formatLayout,
|
|
7
|
+
import { formatLayout, getDefaultInputSize, getFieldSize, setFieldSize } from './utils/layout';
|
|
8
8
|
|
|
9
9
|
const initialState = {
|
|
10
10
|
fieldForm: {},
|
|
@@ -45,7 +45,7 @@ const reducer = (state = initialState, action) =>
|
|
|
45
45
|
}
|
|
46
46
|
case 'ON_ADD_FIELD': {
|
|
47
47
|
const newState = cloneDeep(state);
|
|
48
|
-
const size =
|
|
48
|
+
const size = getDefaultInputSize(
|
|
49
49
|
get(newState, ['modifiedData', 'attributes', action.name, 'type'], '')
|
|
50
50
|
);
|
|
51
51
|
const listSize = get(newState, layoutPathEdit, []).length;
|
|
@@ -76,7 +76,11 @@ const reducer = (state = initialState, action) =>
|
|
|
76
76
|
break;
|
|
77
77
|
}
|
|
78
78
|
case 'ON_CHANGE_META': {
|
|
79
|
-
set(draftState, ['metaForm', ...action.keys], action.value);
|
|
79
|
+
set(draftState, ['metaForm', 'metadata', ...action.keys], action.value);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case 'ON_CHANGE_SIZE': {
|
|
83
|
+
set(draftState, ['metaForm', 'size'], action.value);
|
|
80
84
|
break;
|
|
81
85
|
}
|
|
82
86
|
case 'ON_RESET': {
|
|
@@ -168,11 +172,28 @@ const reducer = (state = initialState, action) =>
|
|
|
168
172
|
}
|
|
169
173
|
case 'SET_FIELD_TO_EDIT': {
|
|
170
174
|
draftState.metaToEdit = action.name;
|
|
171
|
-
draftState.metaForm =
|
|
175
|
+
draftState.metaForm = {
|
|
176
|
+
metadata: get(state, ['modifiedData', 'metadatas', action.name, 'edit'], {}),
|
|
177
|
+
size:
|
|
178
|
+
getFieldSize(action.name, state.modifiedData?.layouts?.edit) ?? getDefaultInputSize(),
|
|
179
|
+
};
|
|
180
|
+
|
|
172
181
|
break;
|
|
173
182
|
}
|
|
174
183
|
case 'SUBMIT_META_FORM': {
|
|
175
|
-
set(
|
|
184
|
+
set(
|
|
185
|
+
draftState,
|
|
186
|
+
['modifiedData', 'metadatas', state.metaToEdit, 'edit'],
|
|
187
|
+
state.metaForm.metadata
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const layoutsCopy = cloneDeep(get(state, layoutPathEdit, []));
|
|
191
|
+
const nextLayoutValue = setFieldSize(state.metaToEdit, state.metaForm.size, layoutsCopy);
|
|
192
|
+
|
|
193
|
+
if (nextLayoutValue.length > 0) {
|
|
194
|
+
set(draftState, layoutPathEdit, formatLayout(nextLayoutValue));
|
|
195
|
+
}
|
|
196
|
+
|
|
176
197
|
break;
|
|
177
198
|
}
|
|
178
199
|
case 'SUBMIT_SUCCEEDED': {
|