Add loader to content header

This commit is contained in:
cyril lopez 2017-09-01 11:16:39 +02:00
parent c965be83ea
commit c76b112367
9 changed files with 102 additions and 4 deletions

View File

@ -13,6 +13,15 @@ class Button extends React.Component {
render() {
const label = this.props.handlei18n ? <FormattedMessage id={this.props.label} /> : this.props.label;
const addShape = this.props.addShape ? <i className="fa fa-plus" /> : '';
if (this.props.loader) {
return (
<button {...this.props} type="submit" className={`${styles.primary} ${styles.loader} ${styles[this.props.buttonSize]}`} disabled>
<div className={styles.saving}>
<span>.</span><span>.</span><span>.</span>
</div>
</button>
)
}
return (
<button className={`${styles[this.props.buttonSize]} ${styles[this.props.buttonBackground]} ${styles.button}`} {...this.props}>
{addShape}{label}
@ -27,6 +36,7 @@ Button.propTypes = {
buttonSize: React.PropTypes.string,
handlei18n: React.PropTypes.bool,
label: React.PropTypes.string.isRequired,
loader: React.PropTypes.bool,
};
export default Button;

View File

@ -67,3 +67,50 @@
padding-left: 1.6rem;
padding-right: 1.6rem;
}
@keyframes blink {
0% {
opacity: .2;
}
20% {
opacity: 1;
}
100% {
opacity: .2;
}
}
.saving {
margin-top: -2rem;
line-height: 3.8rem;
font-size: 4rem;
}
.loader {
height: 3rem;
padding: 0;
border-radius: 0.3rem;
letter-spacing: .5rem;
font-family: Lato;
cursor: not-allowed;
opacity: .65;
&:focus {
outline: 0;
}
}
.saving span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
// font-size: 5rem;
}
.saving span:nth-child(2) {
animation-delay: .2s;
}
.saving span:nth-child(3) {
animation-delay: .4s;
}

View File

@ -18,7 +18,18 @@ class ContentHeader extends React.Component { // eslint-disable-line react/prefe
}
renderButtonContainer = () => {
console.log('waiting');
if (this.props.isLoading) {
return (
<div className={styles.buttonContainer}>
<FormattedMessage id="form.button.save">
{(message) => (
<Button type="submit" label={message} buttonSize={"buttonLg"} buttonBackground={"primary"} onClick={this.props.handleSubmit} loader />
)}
</FormattedMessage>
</div>
);
}
return (
<div className={styles.buttonContainer}>
<FormattedMessage id="form.button.cancel">
@ -81,6 +92,7 @@ ContentHeader.propTypes = {
handleCancel: React.PropTypes.func,
handleSubmit: React.PropTypes.func,
icoType: React.PropTypes.string,
isLoading: React.PropTypes.bool,
name: React.PropTypes.string,
noMargin: React.PropTypes.bool,
};

View File

@ -124,7 +124,7 @@ PopUpForm.propTypes = {
renderCustomPopUpHeader: React.PropTypes.oneOfType([
React.PropTypes.func,
React.PropTypes.object,
React.PropTypes.object,
React.PropTypes.bool,
]),
renderModalBody: React.PropTypes.oneOfType([
React.PropTypes.bool,

View File

@ -15,8 +15,10 @@ import {
MODEL_FETCH,
MODEL_FETCH_SUCCEEDED,
POST_CONTENT_TYPE_SUCCEEDED,
SET_BUTTON_LOADER,
SUBMIT,
RESET_SHOW_BUTTONS_PROPS,
UNSET_BUTTON_LOADER,
UPDATE_CONTENT_TYPE,
} from './constants';
@ -103,12 +105,24 @@ export function resetShowButtonsProps() {
};
}
export function setButtonLoader() {
return {
type: SET_BUTTON_LOADER,
};
}
export function submit() {
return {
type: SUBMIT,
}
}
export function unsetButtonLoader() {
return {
type: UNSET_BUTTON_LOADER,
};
}
export function updateContentType(data) {
return {
type: UPDATE_CONTENT_TYPE,

View File

@ -12,6 +12,8 @@ export const DELETE_ATTRIBUTE = 'ContentTypeBuilder/ModelPage/DELETE_ATTRIBUTE';
export const MODEL_FETCH = 'ContentTypeBuilder/ModelPage/MODEL_FETCH';
export const MODEL_FETCH_SUCCEEDED = 'ContentTypeBuilder/ModelPage/MODEL_FETCH_SUCCEEDED';
export const POST_CONTENT_TYPE_SUCCEEDED = 'ContentTypeBuilder/ModelPage/POST_CONTENT_TYPE_SUCCEEDED';
export const SET_BUTTON_LOADER = 'ContentTypeBuilder/ModelPage/SET_BUTTON_LOADER';
export const SUBMIT = 'ContentTypeBuilder/ModelPage/SUBMIT';
export const UPDATE_CONTENT_TYPE = 'ContentTypeBuilder/ModelPage/UPDATE_CONTENT_TYPE';
export const UNSET_BUTTON_LOADER = 'ContentTypeBuilder/ModelPage/UNSET_BUTTON_LOADER';
export const RESET_SHOW_BUTTONS_PROPS = 'ContentTypeBuilder/ModelPage/RESET_SHOW_BUTTONS_PROPS';

View File

@ -194,7 +194,7 @@ export class ModelPage extends React.Component { // eslint-disable-line react/pr
const redirectRoute = replace(this.props.route.path, '/:modelName', '');
// const addButtons = this.props.modelPage.showButtons;
const addButtons = get(storeData.getContentType(), 'name') === this.props.params.modelName && size(get(storeData.getContentType(), 'attributes')) > 0 || this.props.modelPage.showButtons;
const content = size(this.props.modelPage.model.attributes) === 0 ?
<EmptyAttributesView handleClick={this.handleClickAddAttribute} /> :
<List
@ -224,6 +224,7 @@ export class ModelPage extends React.Component { // eslint-disable-line react/pr
addButtons={addButtons}
handleSubmit={this.props.submit}
handleCancel={this.props.cancelChanges}
isLoading={this.props.modelPage.showButtonLoader}
/>
{content}
</div>

View File

@ -16,6 +16,8 @@ import {
MODEL_FETCH_SUCCEEDED,
POST_CONTENT_TYPE_SUCCEEDED,
RESET_SHOW_BUTTONS_PROPS,
SET_BUTTON_LOADER,
UNSET_BUTTON_LOADER,
UPDATE_CONTENT_TYPE,
} from './constants';
@ -29,6 +31,7 @@ const initialState = fromJS({
postContentTypeSuccess: false,
showButtons: false,
modelLoading: true,
showButtonLoader: false,
});
function modelPageReducer(state = initialState, action) {
@ -72,6 +75,10 @@ function modelPageReducer(state = initialState, action) {
return state.set('postContentTypeSuccess', !state.get('postContentTypeSuccess'));
case RESET_SHOW_BUTTONS_PROPS:
return state.set('showButtons', false);
case SET_BUTTON_LOADER:
return state.set('showButtonLoader', true);
case UNSET_BUTTON_LOADER:
return state.set('showButtonLoader', false);
case UPDATE_CONTENT_TYPE:
return state
.set('model', Map(action.data))

View File

@ -10,7 +10,7 @@ import { temporaryContentTypePosted } from 'containers/App/actions';
import { storeData } from '../../utils/storeData';
import { MODEL_FETCH, SUBMIT } from './constants';
import { modelFetchSucceeded, postContentTypeSucceeded, resetShowButtonsProps } from './actions';
import { modelFetchSucceeded, postContentTypeSucceeded, resetShowButtonsProps, setButtonLoader, unsetButtonLoader } from './actions';
import { makeSelectModel } from './selectors';
export function* fetchModel(action) {
@ -28,6 +28,9 @@ export function* fetchModel(action) {
export function* submitChanges() {
try {
// Show button loader
yield put(setButtonLoader());
const modelName = get(storeData.getContentType(), 'name');
const body = yield select(makeSelectModel());
@ -70,6 +73,8 @@ export function* submitChanges() {
});
yield put(resetShowButtonsProps());
// Remove loader
yield put(unsetButtonLoader());
} catch(error) {
console.log(error);