From 50cd59e082d9061e91dd27c0296158d55cd885a9 Mon Sep 17 00:00:00 2001 From: soupette Date: Tue, 21 Sep 2021 10:27:46 +0200 Subject: [PATCH 1/4] Add textarea Signed-off-by: soupette --- .../address/content-types/address/schema.json | 24 --- .../api/temp/content-types/temp/schema.json | 41 +---- .../components/Inputs/GenericInput.js | 162 +++++++++++++----- .../components/Inputs/index.js | 3 +- 4 files changed, 128 insertions(+), 102 deletions(-) diff --git a/examples/getstarted/api/address/content-types/address/schema.json b/examples/getstarted/api/address/content-types/address/schema.json index 1121090c1d..94a41e2ca1 100755 --- a/examples/getstarted/api/address/content-types/address/schema.json +++ b/examples/getstarted/api/address/content-types/address/schema.json @@ -115,30 +115,6 @@ "component": "blog.test-como", "required": false, "min": 2 - }, - "temp_one_to_one": { - "type": "relation", - "relation": "oneToOne", - "target": "api::temp.temp", - "inversedBy": "one_to_one" - }, - "temp": { - "type": "relation", - "relation": "manyToOne", - "target": "api::temp.temp", - "inversedBy": "one_to_many" - }, - "temps": { - "type": "relation", - "relation": "oneToMany", - "target": "api::temp.temp", - "mappedBy": "many_to_one" - }, - "many_to_many_temp": { - "type": "relation", - "relation": "manyToMany", - "target": "api::temp.temp", - "inversedBy": "many_to_many" } } } diff --git a/examples/getstarted/api/temp/content-types/temp/schema.json b/examples/getstarted/api/temp/content-types/temp/schema.json index 41e854efd1..0e1e91b163 100644 --- a/examples/getstarted/api/temp/content-types/temp/schema.json +++ b/examples/getstarted/api/temp/content-types/temp/schema.json @@ -17,7 +17,7 @@ "type": "string" }, "long": { - "type": "string" + "type": "text" }, "email": { "type": "email" @@ -28,7 +28,7 @@ "password": { "type": "password" }, - "number": { + "number_int": { "type": "integer" }, "enum": { @@ -77,39 +77,14 @@ "uid": { "type": "uid" }, - "one_way": { - "type": "relation", - "relation": "oneToOne", - "target": "api::address.address" + "number_big": { + "type": "biginteger" }, - "one_to_one": { - "type": "relation", - "relation": "oneToOne", - "target": "api::address.address", - "inversedBy": "temp_one_to_one" + "number_dec": { + "type": "decimal" }, - "one_to_many": { - "type": "relation", - "relation": "oneToMany", - "target": "api::address.address", - "mappedBy": "temp" - }, - "many_to_one": { - "type": "relation", - "relation": "manyToOne", - "target": "api::address.address", - "inversedBy": "temps" - }, - "many_to_many": { - "type": "relation", - "relation": "manyToMany", - "target": "api::address.address", - "inversedBy": "many_to_many_temp" - }, - "many_way": { - "type": "relation", - "relation": "oneToMany", - "target": "api::address.address" + "number_float": { + "type": "float" } } } diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js b/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js index 30cf68ab68..c8fd385f7f 100644 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js +++ b/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js @@ -4,13 +4,17 @@ * This is a temp file move it to the helper plugin when ready */ -import React from 'react'; +import React, { useState } from 'react'; import { useIntl } from 'react-intl'; import { ToggleInput } from '@strapi/parts/ToggleInput'; +import { Textarea } from '@strapi/parts/Textarea'; import { TextInput } from '@strapi/parts/TextInput'; +import Hide from '@strapi/icons/Hide'; +import Show from '@strapi/icons/Show'; import PropTypes from 'prop-types'; const Input = ({ + autoComplete, customInputs, description, disabled, @@ -25,6 +29,7 @@ const Input = ({ ...rest }) => { const { formatMessage } = useIntl(); + const [showPassword, setShowPassword] = useState(false); const CustomInput = customInputs ? customInputs[type] : null; @@ -46,10 +51,12 @@ const Input = ({ ); } - const label = formatMessage( - { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage }, - { ...intlLabel.values } - ); + const label = intlLabel.id + ? formatMessage( + { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage }, + { ...intlLabel.values } + ) + : name; const hint = description ? formatMessage( @@ -58,30 +65,6 @@ const Input = ({ ) : ''; - if (type === 'bool') { - return ( - { - onChange({ target: { name, value: e.target.checked } }); - }} - /> - ); - } - const formattedPlaceholder = placeholder ? formatMessage( { id: placeholder.id, defaultMessage: placeholder.defaultMessage }, @@ -91,24 +74,114 @@ const Input = ({ const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : ''; - return ( - - ); + switch (type) { + case 'bool': { + return ( + { + onChange({ target: { name, value: e.target.checked } }); + }} + /> + ); + } + case 'email': + case 'text': + case 'string': { + return ( + + ); + } + case 'password': { + return ( + { + setShowPassword(prev => !prev); + }} + style={{ + border: 'none', + padding: 0, + background: 'transparent', + }} + type="button" + > + {showPassword ? : } + + } + label={label} + labelAction={labelAction} + id={name} + hint={hint} + name={name} + onChange={onChange} + placeholder={formattedPlaceholder} + type={showPassword ? 'text' : 'password'} + value={value || ''} + /> + ); + } + case 'textarea': { + return ( + + ); + } + default: { + return
{type} is not supported
; + } + } }; Input.defaultProps = { + autoComplete: undefined, customInputs: null, description: null, disabled: false, @@ -119,6 +192,7 @@ Input.defaultProps = { }; Input.propTypes = { + autoComplete: PropTypes.string, customInputs: PropTypes.object, description: PropTypes.shape({ id: PropTypes.string.isRequired, diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/index.js b/packages/core/admin/admin/src/content-manager/components/Inputs/index.js index ef595bba38..759bbedea4 100644 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/index.js +++ b/packages/core/admin/admin/src/content-manager/components/Inputs/index.js @@ -166,7 +166,7 @@ function Inputs({ isRequired, ]); - const { label, description, visible } = metadatas; + const { label, description, placeholder, visible } = metadatas; if (visible === false) { return null; @@ -227,6 +227,7 @@ function Inputs({ onBlur={onBlur} onChange={onChange} options={options} + placeholder={placeholder ? { id: placeholder, defaultMessage: placeholder } : null} step={step} type={inputType} validations={validations} From 6d512c09347277da43b8bd3aecf61c49e84cb89c Mon Sep 17 00:00:00 2001 From: soupette Date: Tue, 21 Sep 2021 11:33:28 +0200 Subject: [PATCH 2/4] Add number input Signed-off-by: soupette --- .../EditViewDataManagerProvider/index.js | 1 + .../components/Inputs/GenericInput.js | 35 +++++++++++++++---- .../content-manager/pages/EditView/index.js | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.js index 8d6fc45438..fcba10cd12 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.js @@ -93,6 +93,7 @@ const EditViewDataManagerProvider = ({ const errorsInForm = Object.keys(formErrors); // TODO check if working with DZ, components... + // TODO use querySelector querySelectorAll('[data-strapi-field-error]') if (errorsInForm.length > 0) { const firstError = errorsInForm[0]; const el = document.getElementById(firstError); diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js b/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js index c8fd385f7f..f41a7e1683 100644 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js +++ b/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js @@ -1,19 +1,20 @@ /** * - * Input + * GenericInput * This is a temp file move it to the helper plugin when ready */ import React, { useState } from 'react'; import { useIntl } from 'react-intl'; -import { ToggleInput } from '@strapi/parts/ToggleInput'; +import { NumberInput } from '@strapi/parts/NumberInput'; import { Textarea } from '@strapi/parts/Textarea'; import { TextInput } from '@strapi/parts/TextInput'; +import { ToggleInput } from '@strapi/parts/ToggleInput'; import Hide from '@strapi/icons/Hide'; import Show from '@strapi/icons/Show'; import PropTypes from 'prop-types'; -const Input = ({ +const GenericInput = ({ autoComplete, customInputs, description, @@ -24,6 +25,7 @@ const Input = ({ name, onChange, placeholder, + step, type, value, ...rest @@ -98,6 +100,25 @@ const Input = ({ /> ); } + case 'number': { + return ( + { + onChange({ target: { name, value, type } }); + }} + placeholder={formattedPlaceholder} + step={step} + value={value || undefined} + /> + ); + } case 'email': case 'text': case 'string': { @@ -180,7 +201,7 @@ const Input = ({ } }; -Input.defaultProps = { +GenericInput.defaultProps = { autoComplete: undefined, customInputs: null, description: null, @@ -188,10 +209,11 @@ Input.defaultProps = { error: '', labelAction: undefined, placeholder: null, + step: 1, value: '', }; -Input.propTypes = { +GenericInput.propTypes = { autoComplete: PropTypes.string, customInputs: PropTypes.object, description: PropTypes.shape({ @@ -214,8 +236,9 @@ Input.propTypes = { defaultMessage: PropTypes.string.isRequired, values: PropTypes.object, }), + step: PropTypes.number, type: PropTypes.string.isRequired, value: PropTypes.any, }; -export default Input; +export default GenericInput; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js index c3b5d73320..c0b61545e0 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/index.js +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/index.js @@ -156,7 +156,7 @@ const EditView = ({ {grid.map( ({ fieldSchema, labelAction, metadatas, name, size }) => { return ( - + Date: Tue, 21 Sep 2021 12:10:15 +0200 Subject: [PATCH 3/4] Add enum Signed-off-by: soupette --- .../api/temp/content-types/temp/schema.json | 21 ++++++++- .../components/Inputs/GenericInput.js | 43 +++++++++++++++++ .../components/Inputs/index.js | 4 +- .../Inputs/utils/generateOptions.js | 47 ++++++++++++------- .../CMEditViewLocalePicker/index.js | 1 + 5 files changed, 97 insertions(+), 19 deletions(-) diff --git a/examples/getstarted/api/temp/content-types/temp/schema.json b/examples/getstarted/api/temp/content-types/temp/schema.json index 0e1e91b163..16d64a891f 100644 --- a/examples/getstarted/api/temp/content-types/temp/schema.json +++ b/examples/getstarted/api/temp/content-types/temp/schema.json @@ -9,7 +9,7 @@ "description": "" }, "options": { - "draftAndPublish": true + "draftAndPublish": false }, "pluginOptions": {}, "attributes": { @@ -85,6 +85,25 @@ }, "number_float": { "type": "float" + }, + "enum_req_def": { + "type": "enumeration", + "enum": [ + "un", + "deux", + "trois" + ], + "required": true, + "default": "un" + }, + "enum_req": { + "type": "enumeration", + "enum": [ + "un", + "deux", + "trois" + ], + "required": true } } } diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js b/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js index f41a7e1683..35218fe277 100644 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js +++ b/packages/core/admin/admin/src/content-manager/components/Inputs/GenericInput.js @@ -7,6 +7,7 @@ import React, { useState } from 'react'; import { useIntl } from 'react-intl'; import { NumberInput } from '@strapi/parts/NumberInput'; +import { Select, Option } from '@strapi/parts/Select'; import { Textarea } from '@strapi/parts/Textarea'; import { TextInput } from '@strapi/parts/TextInput'; import { ToggleInput } from '@strapi/parts/ToggleInput'; @@ -24,6 +25,7 @@ const GenericInput = ({ error, name, onChange, + options, placeholder, step, type, @@ -176,6 +178,32 @@ const GenericInput = ({ /> ); } + case 'select': { + return ( + + ); + } case 'textarea': { return ( ); } + case 'time': { + let time = value; + + // The backend send a value which has the following format: '00:45:00.000' + // or the time picker only supports hours & minutes so we need to mutate the value + if (value && value.split(':').length > 2) { + time = time.split(':'); + time.pop(); + time = time.join(':'); + } + + return ( + { + onChange({ target: { name, value: `${time}`, type } }); + }} + onClear={() => { + onChange({ target: { name, value: null, type } }); + }} + placeholder={formattedPlaceholder} + step={step} + value={time} + /> + ); + } default: { return
{type} is not supported
; } diff --git a/packages/core/helper-plugin/lib/src/components/FilterPopoverURLQuery/Inputs.js b/packages/core/helper-plugin/lib/src/components/FilterPopoverURLQuery/Inputs.js index ef9f0c5f6d..58faf48465 100644 --- a/packages/core/helper-plugin/lib/src/components/FilterPopoverURLQuery/Inputs.js +++ b/packages/core/helper-plugin/lib/src/components/FilterPopoverURLQuery/Inputs.js @@ -7,7 +7,7 @@ import { TimePicker } from '@strapi/parts/TimePicker'; import { Select, Option } from '@strapi/parts/Select'; import { useIntl } from 'react-intl'; import { formatISO } from 'date-fns'; -import { cloneDeep } from 'lodash'; +import cloneDeep from 'lodash/cloneDeep'; const Inputs = ({ label, onChange, options, type, value }) => { const { formatMessage } = useIntl();