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

formik/ENG-5161 reimplement single content widget config with formik #1551

Merged
merged 1 commit into from
Oct 9, 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import { injectIntl } from 'react-intl';
import { routeConverter } from '@entando/utils';
import { getContentTemplateList } from 'state/content-template/selectors';
import { adminConsoleUrl } from 'helpers/urlUtils';
import SingleContentConfigForm, { SingleContentConfigFormBody, SingleContentConfigContainerId } from 'ui/widget-forms/publish-single-content-config/SingleContentConfigFormBody';
import SingleContentConfigForm, { SingleContentConfigFormBody } from 'ui/widget-forms/publish-single-content-config/SingleContentConfigFormBody';
import { fetchContentTemplateList } from 'state/content-template/actions';
import { sendPutWidgetConfig } from 'state/page-config/actions';
import { ROUTE_APP_BUILDER_PAGE_CONFIG } from 'app-init/router';
import { formValueSelector, submit, change } from 'redux-form';
import { setVisibleModal } from 'state/modal/actions';
import { ConfirmCancelModalID } from 'ui/common/cancel-modal/ConfirmCancelModal';
import { NoDefaultWarningModalId } from 'ui/widget-forms/publish-single-content-config/NoDefaultWarningModal';
Expand All @@ -25,11 +24,17 @@ import { getAppTourProgress } from 'state/app-tour/selectors';
import { APP_TOUR_STARTED } from 'state/app-tour/const';
import { setAppTourLastStep } from 'state/app-tour/actions';

const INITIAL_VALUES = {
chosenContent: {},
contentId: '',
chosenContentType: '',
modelId: '',
contentDescription: '',
joinGroups: [],
ownerGroup: '',
};

export const mapStateToProps = (state, ownProps) => {
const formToUse = get(ownProps, 'extFormName', SingleContentConfigContainerId);
const parentField = get(ownProps, 'input.name', '');
const putPrefixField = field => (parentField !== '' ? `${parentField}.${field}` : field);
const formSelect = formValueSelector(formToUse);
let widgetConfig = null;
if (ownProps.widgetConfig !== null && ownProps.widgetConfig !== undefined) {
const { contents, ...rest } = ownProps.widgetConfig;
Expand All @@ -38,31 +43,29 @@ export const mapStateToProps = (state, ownProps) => {
return {
contentTemplates: getContentTemplateList(state),
contentType: getSelectedContentType(state),
initialValues: widgetConfig || {},
initialValues: widgetConfig || INITIAL_VALUES,
chosenContent: widgetConfig,
ownerGroup: formSelect(state, putPrefixField('ownerGroup')),
joinGroups: formSelect(state, putPrefixField('joinGroups')),
contentTypes: getContentTypeList(state),
appTourProgress: getAppTourProgress(state),
};
};

export const mapDispatchToProps = (dispatch, ownProps) => {
const formToUse = get(ownProps, 'extFormName', SingleContentConfigContainerId);
const parentField = get(ownProps, 'input.name', '');
const putPrefixField = field => (parentField !== '' ? `${parentField}.${field}` : field);
return {
onDidMount: () => {
onDidMount: (setFieldValue) => {
dispatch(fetchContentTypeListPaged({ page: 1, pageSize: 0 }));
dispatch(fetchContentTemplateList({ page: 1, pageSize: 0 }));
dispatch(fetchPage(ownProps.pageCode, PAGE_STATUS_DRAFT)).then((res) => {
const { ownerGroup, joinGroups } = res.payload || {};
dispatch(change(formToUse, putPrefixField('ownerGroup'), ownerGroup));
dispatch(change(formToUse, putPrefixField('joinGroups'), joinGroups));
setFieldValue(putPrefixField('ownerGroup'), ownerGroup);
setFieldValue(putPrefixField('joinGroups'), joinGroups);
});
},
parentField,
putPrefixField,
onSubmit: (values) => {
onSubmit: (values, setSubmitting) => {
dispatch(clearErrors());
const {
pageCode, frameId, intl, history, widgetCode,
Expand All @@ -80,6 +83,7 @@ export const mapDispatchToProps = (dispatch, ownProps) => {
return dispatch(setVisibleModal(NoDefaultWarningModalId));
}
return dispatch(sendPutWidgetConfig(pageCode, frameId, configItem)).then((res) => {
setSubmitting(false);
if (res) {
dispatch(addToast(
intl.formatMessage({ id: 'widget.update.success' }),
Expand All @@ -88,17 +92,18 @@ export const mapDispatchToProps = (dispatch, ownProps) => {
dispatch(setAppTourLastStep(22));
history.push(routeConverter(ROUTE_APP_BUILDER_PAGE_CONFIG, { pageCode }));
}
});
}).catch(() => setSubmitting(false));
},
onSave: () => {
onSave: (submitForm) => {
dispatch(setAppTourLastStep(22));
dispatch(setVisibleModal(''));
dispatch(submit(SingleContentConfigContainerId));
submitForm();
},
loadContentTypeDetails: contentTypeCode => dispatch(fetchContentType(contentTypeCode, false))
.then(ctype => (
dispatch(change(formToUse, putPrefixField('chosenContentType'), ctype))
)),
loadContentTypeDetails: (contentTypeCode, setFieldValue) =>
dispatch(fetchContentType(contentTypeCode, false))
.then((ctype) => {
setFieldValue(putPrefixField('chosenContentType'), ctype);
}),
onCancel: () => dispatch(setVisibleModal(ConfirmCancelModalID)),
onDiscard: () => {
dispatch(setVisibleModal(''));
Expand All @@ -111,9 +116,9 @@ export const mapDispatchToProps = (dispatch, ownProps) => {
}
dispatch(setVisibleModal(ContentsFilterModalID));
},
onSelectContent: (selectContent, andCloseModal = true) => {
dispatch(change(formToUse, putPrefixField('contentId'), selectContent.id));
dispatch(change(formToUse, putPrefixField('contentDescription'), selectContent.description));
onSelectContent: (selectContent, andCloseModal = true, setFieldValue) => {
setFieldValue(putPrefixField('contentId'), selectContent.id);
setFieldValue(putPrefixField('contentDescription'), selectContent.description);
if (andCloseModal) {
dispatch(setVisibleModal(''));
dispatch(setAppTourLastStep(21));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
import { intlShape, FormattedMessage } from 'react-intl';
import { reduxForm, Field } from 'redux-form';
import { withFormik, Field } from 'formik';
import { get, isEmpty } from 'lodash';
import { Button, Row, Col, DropdownButton, MenuItem } from 'patternfly-react';
import SectionTitle from 'ui/common/SectionTitle';
Expand All @@ -10,13 +10,10 @@ import ContentsFilterModalContainer from 'ui/widget-forms/contents-filter/Conten
import NoDefaultWarningModal from 'ui/widget-forms/publish-single-content-config/NoDefaultWarningModal';
import { getContentById } from 'api/contents';

import { SINGLE_CONTENT_CONFIG } from 'ui/widget-forms/const';
import ContentTableRow from 'ui/widget-forms/publish-single-content-config/ContentTableRow';
import { APP_TOUR_STARTED } from 'state/app-tour/const';
import WidgetConfigPortal from 'ui/widgets/config/WidgetConfigPortal';

export const SingleContentConfigContainerId = `widgets.${SINGLE_CONTENT_CONFIG}`;

export class SingleContentConfigFormBody extends PureComponent {
constructor(props) {
super(props);
Expand All @@ -25,11 +22,12 @@ export class SingleContentConfigFormBody extends PureComponent {
contentLoading: false,
};
this.handleContentSelect = this.handleContentSelect.bind(this);
this.renderFormFields = this.renderFormFields.bind(this);
}

componentDidMount() {
const { onDidMount } = this.props;
onDidMount();
const { onDidMount, setFieldValue } = this.props;
onDidMount(setFieldValue);

// fetch content from URL params
const queryString = window.location.search;
Expand Down Expand Up @@ -72,13 +70,20 @@ export class SingleContentConfigFormBody extends PureComponent {
}

handleContentSelect(selectedContent, closeModal = true) {
const { onSelectContent, loadContentTypeDetails } = this.props;
const {
onSelectContent, loadContentTypeDetails, setFieldValue, putPrefixField,
} = this.props;
const contentId = get(selectedContent, 'contentId', get(selectedContent, 'id', ''));
const typeCodeSub = contentId ? contentId.substr(0, 3) : '';
const contentTypeCode = get(selectedContent, 'typeCode', typeCodeSub);
loadContentTypeDetails(contentTypeCode);
loadContentTypeDetails(contentTypeCode, setFieldValue);
this.setState({ selectedContent });
onSelectContent(selectedContent, closeModal);
// if closeModal is true, it means we selected content from modal
// and now we need to reset contentModelId to default
if (closeModal) {
setFieldValue(putPrefixField('modelId'), 'default');
}
onSelectContent(selectedContent, closeModal, setFieldValue);
}

enclosedWithForm(fields) {
Expand All @@ -94,11 +99,12 @@ export class SingleContentConfigFormBody extends PureComponent {
const {
onCancel,
onDiscard,
invalid,
isValid,
dirty,
submitting,
isSubmitting,
appTourProgress,
onSave,
submitForm,
} = this.props;

const { selectedContent } = this.state;
Expand All @@ -120,8 +126,8 @@ export class SingleContentConfigFormBody extends PureComponent {
className="pull-right AddContentTypeFormBody__save--btn app-tour-step-21"
type="submit"
bsStyle="primary"
disabled={invalid || submitting || !contentExists}
onClick={onSave}
disabled={!isValid || isSubmitting || !contentExists}
onClick={() => onSave(submitForm)}
>
<FormattedMessage id="app.save" />
</Button>
Expand All @@ -141,18 +147,17 @@ export class SingleContentConfigFormBody extends PureComponent {
renderFormFields() {
const {
contentTemplates,
invalid,
submitting,
isValid,
isSubmitting,
intl,
showFilterModal,
onDiscard,
ownerGroup,
joinGroups,
extFormName,
putPrefixField,
contentTypes,
onClickAddContent,
appTourProgress,
values,
parentField,
} = this.props;

const { selectedContent } = this.state;
Expand Down Expand Up @@ -262,14 +267,14 @@ export class SingleContentConfigFormBody extends PureComponent {
</div>
<ContentsFilterModalContainer
modalTitleText={intl.formatMessage({ id: 'cms.contents.modal.filter.title' })}
invalid={invalid}
submitting={submitting}
invalid={!isValid}
submitting={isSubmitting}
onSave={this.handleContentSelect}
onDiscard={onDiscard}
ownerGroup={ownerGroup}
joinGroups={joinGroups}
ownerGroup={values.ownerGroup}
joinGroups={values.joinGroups}
compatibility={{
joinGroups, ownerGroup,
joinGroups: values.joinGroups, ownerGroup: values.ownerGroup,
}}
/>
<NoDefaultWarningModal />
Expand All @@ -287,20 +292,21 @@ export class SingleContentConfigFormBody extends PureComponent {
</Col>
</Row>
)}
{!extFormName && this.renderActionButtons()}
{!parentField && this.renderActionButtons()}
</div>
);
}

render() {
const {
extFormName,
invalid,
submitting,
isValid,
isSubmitting,
intl,
onSave,
onDiscard,
appTourProgress,
parentField,
submitForm,
} = this.props;

const formFields = this.renderFormFields();
Expand All @@ -309,15 +315,16 @@ export class SingleContentConfigFormBody extends PureComponent {
<Fragment>
<Row>
<Col xs={12}>
{extFormName ? formFields : this.enclosedWithForm(formFields)}
{/* {putPrefixField ? formFields : this.enclosedWithForm(this.renderFormFields)} */}
{this.enclosedWithForm(formFields)}
</Col>
</Row>
{!extFormName && appTourProgress !== APP_TOUR_STARTED && (
{!parentField && appTourProgress !== APP_TOUR_STARTED && (
<ConfirmCancelModalContainer
contentText={intl.formatMessage({ id: 'cms.label.modal.confirmCancel' })}
invalid={invalid}
submitting={submitting}
onSave={onSave}
invalid={!isValid}
submitting={isSubmitting}
onSave={() => onSave(submitForm)}
onDiscard={onDiscard}
/>
)}
Expand All @@ -331,8 +338,6 @@ SingleContentConfigFormBody.propTypes = {
contentTemplates: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
onDidMount: PropTypes.func.isRequired,
handleSubmit: PropTypes.func,
invalid: PropTypes.bool,
submitting: PropTypes.bool,
chosenContent: PropTypes.shape({
id: PropTypes.string,
contentId: PropTypes.string,
Expand All @@ -344,9 +349,6 @@ SingleContentConfigFormBody.propTypes = {
showFilterModal: PropTypes.func.isRequired,
onSelectContent: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
ownerGroup: PropTypes.string,
joinGroups: PropTypes.arrayOf(PropTypes.string),
extFormName: PropTypes.string,
putPrefixField: PropTypes.func,
onClickAddContent: PropTypes.func.isRequired,
contentTypes: PropTypes.arrayOf(PropTypes.shape({
Expand All @@ -355,22 +357,38 @@ SingleContentConfigFormBody.propTypes = {
})),
appTourProgress: PropTypes.string,
loadContentTypeDetails: PropTypes.func.isRequired,
isValid: PropTypes.bool.isRequired,
isSubmitting: PropTypes.bool.isRequired,
values: PropTypes.shape({
ownerGroup: PropTypes.string,
joinGroups: PropTypes.arrayOf(PropTypes.string),
}),
setFieldValue: PropTypes.func.isRequired,
parentField: PropTypes.string,
submitForm: PropTypes.func.isRequired,
};

SingleContentConfigFormBody.defaultProps = {
chosenContent: {},
dirty: false,
ownerGroup: '',
joinGroups: [],
extFormName: '',
handleSubmit: () => {},
invalid: false,
submitting: false,
putPrefixField: name => name,
contentTypes: {},
appTourProgress: '',
values: {
ownerGroup: '',
joinGroups: [],
},
parentField: '',
};

export default reduxForm({
form: SingleContentConfigContainerId,
const SingleContentConfigForm = withFormik({
mapPropsToValues: ({ initialValues }) => initialValues,
enableReinitialize: true,
handleSubmit: (values, { setSubmitting, props: { onSubmit } }) => {
onSubmit(values, setSubmitting);
},
displayName: 'SingleContentConfigFormBodyFormik',
})(SingleContentConfigFormBody);

export default SingleContentConfigForm;
Loading