Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: change readonly mode view #55

Merged
merged 1 commit into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@indec/form-builder",
"version": "1.8.0",
"version": "1.9.0",
"description": "Form builder",
"main": "index.js",
"private": false,
Expand Down
45 changes: 17 additions & 28 deletions src/components/Checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,13 @@ import FormGroup from '@mui/material/FormGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import MuiCheckbox from '@mui/material/Checkbox';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';

import FieldMessage from '@/components/FieldMessage';
import InputLabel from '@/components/InputLabel';
import defaultMessages from '@/constants/defaultMessages';
import formikField from '@/utils/propTypes/formikField';
import formikForm from '@/utils/propTypes/formikForm';
import optionPropTypes from '@/utils/propTypes/option';

const getSelectedOptions = (options, selectedValues) => selectedValues.reduce((accumulator, currentValue) => {
const option = options.find(currentOption => currentOption.value === currentValue);
return option ? [...accumulator, option.label] : accumulator;
}, []).join(', ') || defaultMessages.UNANSWERED;

const handleChecked = (e, selectedValue, {name, value}, setFieldValue) => {
const isChecked = e.target.checked;
const values = isChecked
Expand All @@ -31,27 +24,23 @@ function Checkbox({
return (
<Stack direction="column" spacing={2} sx={{width: '100%'}}>
<InputLabel warnings={warnings} required={required} form={form} field={field} label={label} readOnly={readOnlyMode} />
{readOnlyMode ? (
<Typography>
{getSelectedOptions(options, field.value)}
</Typography>
) : (
<FormGroup>
{options.map((option, index) => (
<FormControlLabel
key={option.value}
control={(
<MuiCheckbox
data-testid={`option-${index}`}
checked={field.value.includes(option.value)}
onChange={e => handleChecked(e, option.value, field, form.setFieldValue)}
/>
)}
label={option.label}
/>
))}
</FormGroup>
)}
<FormGroup>
{options.map((option, index) => (
<FormControlLabel
key={option.value}
data-testid={`checkbox-${index}`}
control={(
<MuiCheckbox
data-testid={`option-${index}`}
checked={field.value.includes(option.value)}
onChange={e => handleChecked(e, option.value, field, form.setFieldValue)}
/>
)}
label={option.label}
disabled={readOnlyMode}
/>
))}
</FormGroup>
<FieldMessage warnings={warnings} form={form} field={field} readOnly={readOnlyMode} />
</Stack>
);
Expand Down
8 changes: 5 additions & 3 deletions src/components/Checkbox/Checkbox.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,13 @@ const section = {

function Template(args) {
const {errorSchema: validateSchema, warningSchema} = getSchemas(section);
const {withErrors, withWarnings, ...props} = args;
const {withErrors, withWarnings, initialValues, ...props} = args;
return (
<Formik
initialValues={{S1: [{S1P1: {id: 1, answer: {value: []}}}]}}
initialValues={{S1: [{S1P1: {id: 1, answer: {value: initialValues || []}}}]}}
validationSchema={withErrors ? validateSchema : null}
onSubmit={() => {}}
enableReinitialize
>
{({values, submitForm}) => {
const warnings = withWarnings ? getWarnings(warningSchema, values) || {} : {};
Expand Down Expand Up @@ -128,7 +129,8 @@ WithReadOnlyMode.args = {
required: false,
name: 'S1.0.S1P1.answer.value',
warnings: {},
options
options,
initialValues: ['2']
};

export const WithErrors = Template.bind({});
Expand Down
21 changes: 15 additions & 6 deletions src/components/Checkbox/Checkbox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,18 @@ describe('<Checkbox>', () => {
props.field.value = ['2', '3'];
});

it('should display the selected options', () => {
it('should be checked the selected options', () => {
const {container} = getComponent();
expect(getByText(container, 'Option 2, Option 3')).toBeInTheDocument();
const firstSelectedOption = getByTestId(container, 'checkbox-1');
const secondSelectedOption = getByTestId(container, 'checkbox-2');
expect(firstSelectedOption.querySelector('input').checked).toBe(true);
expect(secondSelectedOption.querySelector('input').checked).toBe(true);
});

it('should not be checked the other options', () => {
const {container} = getComponent();
const unselectedOption = getByTestId(container, 'checkbox-0');
expect(unselectedOption.querySelector('input').checked).toBe(false);
});
});

Expand All @@ -133,16 +142,16 @@ describe('<Checkbox>', () => {
props.field.value = [];
});

it('should display `Sin respuesta.`', () => {
it('should not display `Sin respuesta.`', () => {
const {container} = getComponent();
expect(getByText(container, 'Sin respuesta.')).toBeInTheDocument();
expect(queryByText(container, 'Sin respuesta.')).toBeNull();
});
});

it('should not render the list of checkboxes', () => {
it('should render the list of checkboxes', () => {
const {container} = getComponent();
props.options.forEach(option => {
expect(queryByText(container, option.label)).toBeNull();
expect(getByText(container, option.label)).toBeInTheDocument();
});
});
});
Expand Down
35 changes: 23 additions & 12 deletions src/components/FormBuilder/FormBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ function FormBuilder({
page,
onSubmit,
onPrevious,
isSurvey,
components,
initialValues
initialValues,
isReadOnly
}) {
const [readOnlyMode, setReadOnlyMode] = useState(false);
const [readOnlyMode, setReadOnlyMode] = useState(isReadOnly);
const [showSurvey, setShowSurvey] = useState(false);
const [selectedSectionId, setSelectedSelectionId] = useState();
const [openModal, setOpenModal] = useState();
Expand All @@ -35,7 +35,7 @@ function FormBuilder({

const handleShowSurvey = (sectionId, readOnly) => {
setShowSurvey(sectionId);
setReadOnlyMode(readOnly ? sectionId : false);
setReadOnlyMode(readOnly);
};

const handleOpenModal = (modal, sectionId) => {
Expand All @@ -55,7 +55,7 @@ function FormBuilder({
const newValues = values;
const lastSection = getLastId(values[section.name]);
newValues[section.name].push({...formInitialValues[section.name][0], id: lastSection + 1});
return setValues(newValues);
setValues(newValues);
};

return (
Expand All @@ -79,26 +79,36 @@ function FormBuilder({
<Box key={currentSection.id} mb={2}>
{
components.SectionHeader
? <components.SectionHeader values={currentSection} />
? (
<components.SectionHeader
onView={() => handleShowSurvey(currentSection.id, true)}
onEdit={() => handleShowSurvey(currentSection.id, false)}
onDelete={() => handleOpenModal(modals.CONFIRM_DELETE_SECTION_MODAL, currentSection.id)}
sectionsLength={values[section.name].length}
section={section}
values={currentSection}
isReadOnly={isReadOnly}
/>
)
: (
<SectionHeader
onView={() => handleOpenModal(modals.PREVIEW_MODAL, currentSection.id)}
onView={() => handleShowSurvey(currentSection.id, true)}
onEdit={() => handleShowSurvey(currentSection.id, false)}
onDelete={() => handleOpenModal(modals.CONFIRM_DELETE_SECTION_MODAL, currentSection.id)}
sectionsLength={values[section.name].length}
section={section}
values={currentSection}
isSurvey={isSurvey}
isReadOnly={isReadOnly}
/>
)
}
{(!isSurvey || showSurvey === currentSection.id) && (
{showSurvey === currentSection.id && (
<Box sx={{backgroundColor: '#fff', boxShadow: 2, p: 2}}>
<QuestionBuilder
values={currentSection}
index={index}
section={section}
readOnlyMode={readOnlyMode === currentSection.id}
readOnlyMode={readOnlyMode}
warnings={warnings}
/>
</Box>
Expand Down Expand Up @@ -140,6 +150,7 @@ function FormBuilder({
? () => handleOpenModal(modals.INTERRUPTION_MODAL, section.id)
: undefined
}
readOnlyMode={isReadOnly}
/>
)
}
Expand All @@ -156,7 +167,7 @@ FormBuilder.propTypes = {
section: sectionPropTypes.isRequired,
page: PropTypes.number.isRequired,
isLastSection: PropTypes.bool,
isSurvey: PropTypes.bool,
isReadOnly: PropTypes.bool,
components: PropTypes.shape({
SectionHeader: PropTypes.node,
NavigationButtons: PropTypes.node
Expand All @@ -170,7 +181,7 @@ FormBuilder.defaultProps = {

FormBuilder.defaultProps = {
isLastSection: false,
isSurvey: true,
isReadOnly: false,
components: {}
};

Expand Down
33 changes: 33 additions & 0 deletions src/components/FormBuilder/FormBuilder.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,36 @@ WithCustomNavigationButtons.args = {
NavigationButtons: props => <NavigationButtons {...props} />
}
};

export const WithReadOnlyMode = Template.bind({});
WithReadOnlyMode.args = {
initialValues: {
S1: [
{
id: 1,
S1P1: {
id: 1,
answer: {value: 'test'}
},
S1P2: {
id: 2,
answer: {value: 26}
},
S1P3: {
id: 3,
answer: [
{
id: 1,
value: 123456
},
{
id: 2,
value: 12345678
}
]
}
}
]
},
isReadOnly: true
};
9 changes: 1 addition & 8 deletions src/components/FormBuilder/Modals/Modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';

import Modal from '@/components/Modal';
import QuestionBuilder from '@/components/QuestionBuilder';
import Radio from '@/components/Radio';
import modals from '@/constants/modals';

const getChildren = (modal, {
values, index, section, options, label, name
}) => {
const getChildren = (modal, {options, label, name}) => {
switch (modal) {
case modals.CONFIRM_DELETE_SECTION_MODAL:
return (
Expand All @@ -21,10 +18,6 @@ const getChildren = (modal, {
<Typography>¿Esta seguro que desea borrar esta sección?</Typography>
</>
);
case modals.PREVIEW_MODAL:
return (
<QuestionBuilder values={values} index={index} section={section} readOnlyMode />
);
case modals.INTERRUPTION_MODAL:
return (
<FastField component={Radio} options={options} label={label} name={name} required readOnlyMode={false} />
Expand Down
37 changes: 2 additions & 35 deletions src/components/FormBuilder/Modals/Modals.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,9 @@ function Template(args) {
);
}

export const Preview = Template.bind({});
Preview.args = {
modal: 1,
index: 0,
section: {
id: 1,
name: 'S1',
label: 'Sección 1',
multiple: false,
questions: [
{
id: 1,
label: 'Ingrese su nombre',
name: 'S1P1',
number: '1',
type: 1,
options: [],
validations: [],
userVarName: 's1p1'
}
],
headers: [
{
id: 1,
question: 1
}
]
},
values: {
S1: {id: 1, answer: ''}
}
};

export const Interruption = Template.bind({});
Interruption.args = {
modal: 2,
modal: 1,
label: 'Select an option',
options: [
{
Expand All @@ -77,4 +44,4 @@ Interruption.args = {
};

export const ConfirmDeleteSection = Template.bind({});
ConfirmDeleteSection.args = {modal: 3};
ConfirmDeleteSection.args = {modal: 2};
6 changes: 3 additions & 3 deletions src/components/FormBuilder/Modals/Modals.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getByTestId, getByText} from '@testing-library/react';
import {getByTestId, getByText, queryByTestId} from '@testing-library/react';

import Modals from './Modals';

Expand Down Expand Up @@ -49,9 +49,9 @@ describe('<Modals>', () => {
};
});

it('should render QuestionBuilder component', () => {
it('should not render QuestionBuilder component', () => {
const {baseElement} = getComponent();
expect(getByTestId(baseElement, 'question-builder')).toBeInTheDocument();
expect(queryByTestId(baseElement, 'question-builder')).toBeNull();
});
});

Expand Down
Loading