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

SPIKE Inline validation #1113

Closed
Closed
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
3,857 changes: 3,847 additions & 10 deletions client/dist/js/bundle.js

Large diffs are not rendered by default.

482 changes: 481 additions & 1 deletion client/dist/styles/bundle.css

Large diffs are not rendered by default.

32 changes: 29 additions & 3 deletions client/src/components/ElementActions/SaveAction.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useContext } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import AbstractAction from 'components/ElementActions/AbstractAction';
Expand All @@ -7,12 +7,20 @@ import i18n from 'i18n';
import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue';
import { loadElementFormStateName } from 'state/editor/loadElementFormStateName';
import { initialize } from 'redux-form';
import { ElementContext } from 'components/ElementEditor/Element';
import { submit } from 'redux-form'



/**
* Using a REST backend, serialize the current form data and post it to the backend endpoint to save
* the inline edit form's data for the current block.
*/
const SaveAction = (MenuComponent) => (props) => {
const failureHandlers = useContext(ElementContext);

console.log(['SaveAction.props is',props]);

if (!props.expandable || props.type.broken) {
// Some elemental blocks can not be edited inline (e.g. User form blocks)
// We don't want to add a "Save" action for those blocks.
Expand All @@ -24,7 +32,7 @@ const SaveAction = (MenuComponent) => (props) => {
const handleClick = (event) => {
event.stopPropagation();

const { element, type, securityId, formData, reinitialiseForm } = props;
const { element, type, securityId, formData, reinitialiseForm, submitForm } = props;
const { jQuery: $ } = window;
const noTitle = i18n.inject(
i18n._t(
Expand All @@ -34,6 +42,15 @@ const SaveAction = (MenuComponent) => (props) => {
{ type: type.title }
);

// https://redux-form.com/8.3.0/examples/remotesubmit/
submitForm();

return;


// === The following is wrong, should using the Formbuilder to submit the form ===
// === instead of doing a submissions from the button ==

const endpointSpec = {
url: loadElementSchemaValue('saveUrl', element.id),
method: loadElementSchemaValue('saveMethod'),
Expand Down Expand Up @@ -70,7 +87,7 @@ const SaveAction = (MenuComponent) => (props) => {
type: 'success'
});
})
.catch(() => {
.catch(e => {
$.noticeAdd({
text: i18n.inject(
i18n._t(
Expand All @@ -82,6 +99,11 @@ const SaveAction = (MenuComponent) => (props) => {
stay: false,
type: 'error'
});
e.response.json()
.then(formSchema => {
// console.log(responseJson.errors); // add this as an arg to a callback
failureHandlers.onFailedSave(formSchema);
});
});
};

Expand Down Expand Up @@ -121,6 +143,10 @@ function mapDispatchToProps(dispatch, ownProps) {
return {
reinitialiseForm(savedData) {
dispatch(initialize(`element.${formName}`, savedData));
},
submitForm() {
console.log('submitting form for elmenet with ID 3 - THIS IS HARDCODED TO element #3');
dispatch(submit('element.ElementForm_3'));
}
};
}
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/ElementEditor/Content.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Content extends PureComponent {
handleLoadingError,
formDirty,
broken,
formSchema,
} = this.props;

return (
Expand All @@ -44,6 +45,7 @@ class Content extends PureComponent {
activeTab={activeTab}
onFormInit={onFormInit}
handleLoadingError={handleLoadingError}
formSchema={formSchema}
/>
}
{formDirty &&
Expand All @@ -69,6 +71,7 @@ Content.propTypes = {
InlineEditFormComponent: PropTypes.elementType,
handleLoadingError: PropTypes.func,
broken: PropTypes.bool,
formSchema: PropTypes.object,
};

Content.defaultProps = {};
Expand Down
88 changes: 54 additions & 34 deletions client/src/components/ElementEditor/Element.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global window */

import React, { Component } from 'react';
import React, { Component, createContext } from 'react';
import PropTypes from 'prop-types';
import { elementType } from 'types/elementType';
import { elementTypeType } from 'types/elementTypeType';
Expand Down Expand Up @@ -39,6 +39,7 @@ class Element extends Component {
initialTab: '',
loadingError: false,
childRenderingError: false,
formSchema: {}
};
}

Expand Down Expand Up @@ -215,6 +216,18 @@ class Element extends Component {
}
}

getFailureHandlers() {
// using method to create object rather then defining object directly in render()
// to prevent linting warning about "consider useMemo() instead"
return {
onFailedSave: (formSchema) => {
this.setState({
formSchema
});
}
};
}

render() {
const {
element,
Expand All @@ -231,7 +244,7 @@ class Element extends Component {
onDragEnd,
} = this.props;

const { childRenderingError, previewExpanded } = this.state;
const { childRenderingError, previewExpanded, formSchema } = this.state;

if (!element.id) {
return null;
Expand All @@ -248,6 +261,8 @@ class Element extends Component {
this.getVersionedStateClassName()
);

const failureHandlers = this.getFailureHandlers();

const content = connectDropTarget(<div
className={elementClassNames}
onClick={this.handleExpand}
Expand All @@ -257,40 +272,42 @@ class Element extends Component {
title={this.getLinkTitle(type)}
key={element.id}
>
<HeaderComponent
element={element}
type={type}
areaId={areaId}
expandable={type.inlineEditable}
link={link}
previewExpanded={previewExpanded && !childRenderingError}
handleEditTabsClick={this.handleTabClick}
activeTab={activeTab}
disableTooltip={isDragging}
onDragEnd={onDragEnd}
/>

{
!childRenderingError &&
<ContentComponent
id={element.id}
fileUrl={element.blockSchema.fileURL}
fileTitle={element.blockSchema.fileTitle}
content={this.getSummary(element, type)}
previewExpanded={previewExpanded && !isDragging}
<ElementContext.Provider value={failureHandlers}>
<HeaderComponent
element={element}
type={type}
areaId={areaId}
expandable={type.inlineEditable}
link={link}
previewExpanded={previewExpanded && !childRenderingError}
handleEditTabsClick={this.handleTabClick}
activeTab={activeTab}
onFormInit={() => this.updateFormTab(activeTab)}
handleLoadingError={this.handleLoadingError}
broken={type.broken}
disableTooltip={isDragging}
onDragEnd={onDragEnd}
failureHandlers={failureHandlers}
/>
}

{
childRenderingError &&
<div className="alert alert-danger mt-2">
{i18n._t('ElementalElement.CHILD_RENDERING_ERROR', 'Something went wrong with this block. Please try saving and refreshing the CMS.')}
</div>
}
{
!childRenderingError &&
<ContentComponent
id={element.id}
fileUrl={element.blockSchema.fileURL}
fileTitle={element.blockSchema.fileTitle}
content={this.getSummary(element, type)}
previewExpanded={previewExpanded && !isDragging}
activeTab={activeTab}
onFormInit={() => this.updateFormTab(activeTab)}
handleLoadingError={this.handleLoadingError}
broken={type.broken}
formSchema={formSchema}
/>
}
{
childRenderingError &&
<div className="alert alert-danger mt-2">
{i18n._t('ElementalElement.CHILD_RENDERING_ERROR', 'Something went wrong with this block. Please try saving and refreshing the CMS.')}
</div>
}
</ElementContext.Provider>
</div>);

if (!previewExpanded) {
Expand Down Expand Up @@ -342,6 +359,9 @@ function mapDispatchToProps(dispatch, ownProps) {
};
}

const ElementContext = createContext({});
export { ElementContext as ElementContext };

Element.propTypes = {
element: elementType,
type: elementTypeType.isRequired,
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/ElementEditor/ElementActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ ElementActions.propTypes = {
name: PropTypes.string,
})),
handleEditTabsClick: PropTypes.func.isRequired,
expandable: PropTypes.bool
expandable: PropTypes.bool,
};

ElementActions.defaultProps = {
Expand Down
41 changes: 38 additions & 3 deletions client/src/components/ElementEditor/InlineEditForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import FormBuilder from 'components/FormBuilder/FormBuilder';
import FormBuilderLoader from 'containers/FormBuilderLoader/FormBuilderLoader';
import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue';
import i18n from 'i18n';
Expand Down Expand Up @@ -42,7 +43,7 @@ class InlineEditForm extends PureComponent {
}

render() {
const { elementId, extraClass, onClick, onFormInit, formHasState } = this.props;
const { elementId, extraClass, onClick, onFormInit, formHasState, formSchema } = this.props;
const { loadingError } = this.state;

const classNames = classnames('element-editor-editform', extraClass);
Expand All @@ -56,6 +57,12 @@ class InlineEditForm extends PureComponent {
onLoadingError: this.handleLoadingError
};

console.log(['formSchema is', formSchema]);

if (typeof formSchema !== 'undefined' && Object.keys(formSchema).length > 0) {
formProps.schema = formSchema;
}

if (loadingError) {
formProps.loading = false;
}
Expand All @@ -64,9 +71,36 @@ class InlineEditForm extends PureComponent {
formProps.onReduxFormInit = onFormInit;
}

// ==== BORROWED FROM FormBuilderLoader to use on FormBuilder ===
// function createFormIdentifierFromProps({ identifier, schema = {} }) {
// return [
// identifier,
// schema.schema && schema.schema.name,
// ].filter(id => id).join('.');
// }

// function getIdentifier() {
// return createFormIdentifierFromProps(this.props);
// }

// if (formProps.hasOwnProperty('schema')) {
// formProps.form = getIdentifier(),
// onSubmit: this.handleSubmit,
// onAutofill: this.handleAutofill,
// }
// ======================================

return (
<div className={classNames} onClick={onClick} role="presentation">
<FormBuilderLoader {...formProps} />
{formProps.hasOwnProperty('schema') &&
<>
<div>I HAVE A FORM SCHEMA</div>
<FormBuilder {...formProps} />
</>
}
{!formProps.hasOwnProperty('schema') &&
<FormBuilderLoader {...formProps} />
}
</div>
);
}
Expand All @@ -77,10 +111,11 @@ InlineEditForm.propTypes = {
onClick: PropTypes.func,
elementId: PropTypes.string,
handleLoadingError: PropTypes.func,
formSchema: PropTypes.object,
};

function mapStateToProps(state, ownProps) {
const formName = loadElementFormStateName(ownProps.elementId);
const formName = loadElementFormStateName(ownProps.elementId); // ElementForm_3

return {
formHasState: state.form.formState && state.form.formState.element &&
Expand Down
Loading
Loading