Skip to content

Commit

Permalink
Merge pull request #3092 from ONSdigital/EAR-2321-limit-character-in-…
Browse files Browse the repository at this point in the history
…TextField-answer

EAR 2321 limit character in text field answer
  • Loading branch information
Farhanam76 authored Jan 31, 2024
2 parents a1f4c31 + 8106758 commit 0ba2f77
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 19 deletions.
2 changes: 2 additions & 0 deletions eq-author-api/schema/typeDefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ type BasicAnswer implements Answer {
mutuallyExclusiveOption: Option
repeatingLabelAndInput: Boolean
repeatingLabelAndInputListId: ID
limitCharacter: Boolean
}
type MultipleChoiceAnswer implements Answer {
Expand Down Expand Up @@ -1533,6 +1534,7 @@ input UpdateAnswerInput {
defaultAnswer: Boolean
repeatingLabelAndInput: Boolean
repeatingLabelAndInputListId: ID
limitCharacter: Boolean
}
input UpdateAnswersOfTypeInput {
Expand Down
80 changes: 71 additions & 9 deletions eq-author-api/src/validation/schemas/answer.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,30 @@
"then": {
"$ref": "#/definitions/dateRangeAnswer"
}
},
{
"if": {
"properties": {
"type": {
"const": "TextField"
}
}
},
"then": {
"$ref": "#/definitions/textFieldAnswer"
}
},
{
"if": {
"properties": {
"type": {
"const": "TextArea"
}
}
},
"then": {
"$ref": "#/definitions/textAreaAnswer"
}
}
],
"definitions": {
Expand Down Expand Up @@ -296,18 +320,56 @@
}
]
},
"properties": {
"textFieldAnswer": {
"type": "object",
"if": {
"properties": {
"limitCharacter": {
"const": true
}
}
},
"then": {
"properties": {
"properties": {
"type": "object",
"properties": {
"maxLength": {
"type": "number",
"minimum": 8,
"maximum": 100,
"errorMessage": {
"minimum": "ERR_MAX_LENGTH_TOO_SMALL",
"maximum": "ERR_MAX_LENGTH_TOO_LARGE"
}
}
}
}
}
}
},
"textAreaAnswer": {
"type": "object",
"properties": {
"maxLength": {
"type": "number",
"minimum": 10,
"maximum": 2000,
"errorMessage": {
"minimum": "ERR_MAX_LENGTH_TOO_SMALL",
"maximum": "ERR_MAX_LENGTH_TOO_LARGE"
"properties": {
"type": "object",
"properties": {
"maxLength": {
"type": "number",
"minimum": 10,
"maximum": 2000,
"errorMessage": {
"minimum": "ERR_MAX_LENGTH_TOO_SMALL",
"maximum": "ERR_MAX_LENGTH_TOO_LARGE"
}
}
}
},
}
}
},
"properties": {
"type": "object",
"properties": {
"unit": {
"$ref": "definitions.json#/definitions/populatedString"
}
Expand Down
2 changes: 2 additions & 0 deletions eq-author-api/utils/defaultAnswerProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
UNIT,
DURATION,
TEXTAREA,
TEXTFIELD,
} = require("../constants/answerTypes");

const defaultAnswerPropertiesMap = {
Expand All @@ -18,6 +19,7 @@ const defaultAnswerPropertiesMap = {
[UNIT]: { required: false, decimals: 0, unit: "" },
[DURATION]: { required: false, unit: "YearsMonths" },
[TEXTAREA]: { required: false, maxLength: 2000 },
[TEXTFIELD]: { required: false, maxLength: 100 },
};

module.exports = (type) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ describe("BasicAnswer", () => {
description: "option description",
},
],
validationErrorInfo: {
errors: [],
},
};
onChange = jest.fn();
onUpdate = jest.fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ exports[`BasicAnswer should render with description 1`] = `
}
}
data-test="txt-answer-label"
hasLabelErrors={false}
id="answer-label-ansID1"
label="Label"
listId={null}
Expand Down Expand Up @@ -70,6 +71,9 @@ exports[`BasicAnswer should render with description 1`] = `
},
"title": "Answer title",
"type": "TextField",
"validationErrorInfo": Object {
"errors": Array [],
},
}
}
page={
Expand Down Expand Up @@ -108,6 +112,9 @@ exports[`BasicAnswer should render with description 1`] = `
},
"title": "Answer title",
"type": "TextField",
"validationErrorInfo": Object {
"errors": Array [],
},
}
}
enableHorizontalRule={true}
Expand Down Expand Up @@ -136,6 +143,7 @@ exports[`BasicAnswer should render without description 1`] = `
}
}
data-test="txt-answer-label"
hasLabelErrors={false}
id="answer-label-ansID1"
label="Label"
listId={null}
Expand Down Expand Up @@ -165,6 +173,9 @@ exports[`BasicAnswer should render without description 1`] = `
},
"title": "Answer title",
"type": "TextField",
"validationErrorInfo": Object {
"errors": Array [],
},
}
}
page={
Expand Down Expand Up @@ -203,6 +214,9 @@ exports[`BasicAnswer should render without description 1`] = `
},
"title": "Answer title",
"type": "TextField",
"validationErrorInfo": Object {
"errors": Array [],
},
}
}
enableHorizontalRule={true}
Expand Down
1 change: 1 addition & 0 deletions eq-author/src/App/page/Design/answers/BasicAnswer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ StatelessBasicAnswer.fragments = {
BasicAnswer: gql`
fragment BasicAnswer on BasicAnswer {
repeatingLabelAndInput
limitCharacter
repeatingLabelAndInputListId
options {
id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,17 @@ const TextAreaProperties = ({

return (
<>
<InlineField id="maxCharactersField" label={"Max characters"}>
<InlineField
id="maxCharactersField"
label={"Maximum number of characters"}
>
<SmallNumber
id="maxCharactersInput"
answer={answer}
name={answer.id}
value={maxLength}
onBlur={() => onUpdateMaxLength(maxLength)}
onChange={({ value }) => setMaxLength(value)}
max={2000}
invalid={errors.length > 0}
data-test="maxCharacterInput"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,104 @@
import React from "react";
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";

import Required from "components/AnswerContent/Required";
import InlineField from "components/AnswerContent/Format/InlineField";
import CollapsibleToggled from "components/CollapsibleToggled";
import Number, { NumberInput } from "components/Forms/Number";
import ValidationError from "components/ValidationError";

import { radius } from "constants/theme";
import { textFieldErrors } from "constants/validationMessages";

const SmallNumber = styled(Number)`
width: 7em;
margin-left: 0;
${NumberInput} {
border-radius: ${radius};
padding: 0.25em 0.5em;
}
`;

const TextFieldProperties = ({
answer,
updateAnswer,
hasMutuallyExclusiveAnswer,
}) => (
<Required
answer={answer}
updateAnswer={updateAnswer}
hasMutuallyExclusiveAnswer={hasMutuallyExclusiveAnswer}
/>
);
}) => {
const [maxLength, setMaxLength] = useState(answer.properties.maxLength);
useEffect(() => {
setMaxLength(answer.properties.maxLength);
}, [answer.properties.maxLength]);

const errors = answer.validationErrorInfo.errors.filter(
(error) => error.field === "maxLength"
);

const onUpdateMaxLength = (value) => {
const newValue = value === null ? 100 : value;
updateAnswer({
variables: {
input: {
id: answer.id,
properties: { ...answer.properties, maxLength: newValue },
},
},
});
setMaxLength(newValue);
};

return (
<>
<CollapsibleToggled
id="character-length"
title="Character limit"
ariaLabel="Character limit"
quoted={false}
onChange={({ value }) =>
updateAnswer({
variables: {
input: { id: answer.id, limitCharacter: value },
},
})
}
isOpen={answer.limitCharacter}
>
<InlineField
id="maxCharactersLimit"
label={"Maximum number of characters"}
>
<SmallNumber
id="maxCharactersLimit"
answer={answer}
name={answer.id}
value={maxLength}
onBlur={() => onUpdateMaxLength(maxLength)}
onChange={({ value }) => setMaxLength(value)}
data-test="limitCharacterInput"
/>
</InlineField>
{errors.length > 0 && (
<ValidationError>
{textFieldErrors[errors[0].errorCode].message}
</ValidationError>
)}
</CollapsibleToggled>

<Required
answer={answer}
updateAnswer={updateAnswer}
hasMutuallyExclusiveAnswer={hasMutuallyExclusiveAnswer}
/>
</>
);
};

TextFieldProperties.propTypes = {
updateAnswer: PropTypes.func,
answer: PropTypes.object, //eslint-disable-line
hasMutuallyExclusiveAnswer: PropTypes.bool,
limitCharacter: PropTypes.bool,
};

export default TextFieldProperties;
Loading

0 comments on commit 0ba2f77

Please sign in to comment.