ldx-widgets
Version:
widgets
316 lines (284 loc) • 10.1 kB
JavaScript
(function() {
var ConfirmSave, ESCAPE, Form, KEY_S, PropTypes, React, Spinner, StyleSheet, assign, button, createClass, css, dialogueMixin, div, ref, ref1, ref2, span, styles;
React = require('react');
createClass = require('create-react-class');
PropTypes = require('prop-types');
ref = require('aphrodite/no-important'), StyleSheet = ref.StyleSheet, css = ref.css;
assign = require('lodash/assign');
dialogueMixin = require('../mixins/dialogue_mixin');
ref1 = require('../constants/keyboard'), ESCAPE = ref1.ESCAPE, KEY_S = ref1.KEY_S;
ConfirmSave = React.createFactory(require('./confirm_save'));
Spinner = React.createFactory(require('./spinner'));
ref2 = require('react-dom-factories'), div = ref2.div, span = ref2.span, button = ref2.button;
/*&
@props.title - OPTIONAL - [String]
title for the modal header
@props.buttons - OPTIONAL - [Array]
Array of button objects with name, handler to be called on click, and disabled boolean, eg...
```
[
{
name: 'Create'
handler: @create
disabled: no
}
]
```
@props.children - REQUIRED - [Element]
React element (or array of elements) to inserted as the form body
@props.styleOverride - OPTIONAL - [Object]
aphrodite style object, optionally can contain .form, .title, .bar, .btn, .class defs, eg...
```
{
formBase: {}
form: {}
title: {}
bar: {}
btn: {}
}
```
@props.canUpdate - OPTIONAL - [Boolean]
Defaults to no, whether or not the user can update and save the form
@props.save - OPTIONAL - [Function]
Function that save the form
@props.close - OPTIONAL - [Function]
Function that closes the form
@props.onClose - OPTIONAL - [Function]
Function that is called right before the modal closes
@props.showClose - OPTIONAL - [Boolean]
Defaults to yes, set it to no to not show the close button
@props.closeAfterSave - OPTIONAL - [Boolean]
Defaults to yes, set it to no to prevent the modal from calling @props.close after a save is complete
Note: in this case you MUST pass an onSaveComplete handler that sets the saveState to null after a save
@props.onSaveComplete - OPTIONAL - [Function]
Function that is called right after the saveState is set to complete and the success indicator finishes animating
@props.closeBtnText - OPTIONAL - [String]
Defaults to 'Cancel', text to display in the close button
@props.loading - OPTIONAL - [Boolean]
Defaults to no, whether or not to show the spinner instead of the children
@props.displayProgressBar - OPTIONAL - [Boolean]
Defaults to no, whether or not the confirm/save show the progress bar instead of the spinner
@props.uploadProgress - OPTIONAL
Progress of a file being uploaded
@props.unSavedMessage - OPTIONAL
Message to be displayed in dialog if you have unsaved changes
&
*/
Form = createClass({
displayName: 'Form',
mixins: [dialogueMixin],
propTypes: {
styleOverride: PropTypes.shape({
form: PropTypes.object,
bar: PropTypes.object,
title: PropTypes.object,
btn: PropTypes.object
}),
title: PropTypes.string,
buttons: PropTypes.array,
canUpdate: PropTypes.bool,
save: PropTypes.func.isRequired,
close: PropTypes.func.isRequired,
onClose: PropTypes.func,
onSaveComplete: PropTypes.func,
showClose: PropTypes.bool,
closeAfterSave: PropTypes.bool,
closeBtnText: PropTypes.string,
unSavedMessage: PropTypes.string,
unSavedDialogueHeight: PropTypes.number,
unSavedChanges: PropTypes.bool,
onSaveFail: PropTypes.func,
inLineStyle: PropTypes.object,
loading: PropTypes.bool,
spinnerProps: PropTypes.object,
displayProgressBar: PropTypes.bool,
uploadProgress: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
},
getDefaultProps: function() {
return {
styleOverride: {},
inLineStyle: {},
buttons: [],
canUpdate: true,
showClose: true,
closeAfterSave: true,
unSavedDialogueHeight: 100,
saveState: null,
saveMessage: null,
unSavedChanges: false,
loading: false,
spinnerProps: {
length: 7,
radius: 7,
lines: 12,
width: 2
},
displayProgressBar: false,
uploadProgress: ''
};
},
componentWillMount: function() {
this.closeBtnText = t('Cancel');
return document.addEventListener('keydown', this.handleKeyPress);
},
componentWillUnmount: function() {
return document.removeEventListener('keydown', this.handleKeyPress);
},
render: function() {
var b, btns, buttons, canUpdate, children, closeBtnText, displayProgressBar, i, inLineStyle, loading, onSaveFail, ref3, save, saveMessage, saveState, showClose, spinnerProps, styleOverride, title, unSavedChanges, uploadProgress;
ref3 = this.props, styleOverride = ref3.styleOverride, title = ref3.title, buttons = ref3.buttons, closeBtnText = ref3.closeBtnText, showClose = ref3.showClose, children = ref3.children, save = ref3.save, saveState = ref3.saveState, saveMessage = ref3.saveMessage, canUpdate = ref3.canUpdate, unSavedChanges = ref3.unSavedChanges, onSaveFail = ref3.onSaveFail, inLineStyle = ref3.inLineStyle, loading = ref3.loading, spinnerProps = ref3.spinnerProps, displayProgressBar = ref3.displayProgressBar, uploadProgress = ref3.uploadProgress;
closeBtnText = closeBtnText || this.closeBtnText;
btns = [];
if (canUpdate) {
btns.push(button({
key: 'save',
className: unSavedChanges ? css(styles.btn) : css(styles.btn, styles.disabled),
onClick: save,
disabled: !unSavedChanges,
tabIndex: -1
}, t('Save')));
}
if (showClose) {
btns.push(button({
key: 'cancel',
className: css(styles.btn),
onClick: this.closeWithCheck,
tabIndex: -1
}, closeBtnText));
}
for (i = buttons.length - 1; i >= 0; i += -1) {
b = buttons[i];
btns.push(button({
key: b.name,
className: css(styles.btn),
onClick: b.handler,
disabled: b.disabled
}, b.name));
}
assign(styles, styleOverride);
inLineStyle = assign({}, inLineStyle);
assign(spinnerProps, {
key: 'spinner'
});
return div({
className: css(styles.formBase, styles.form),
style: inLineStyle
}, [
!loading ? div({
key: 'bar',
className: css(styles.bar)
}, [
div({
key: 'name',
className: css(styles.title)
}, title), btns
]) : void 0, this.dialogueBox(), saveState != null ? ConfirmSave({
key: 'confirm',
done: this.saveComplete,
fail: function() {
return typeof onSaveFail === "function" ? onSaveFail() : void 0;
},
saveMessage: saveMessage,
saveState: saveState,
displayProgressBar: displayProgressBar,
uploadProgress: uploadProgress
}) : void 0, loading ? Spinner(spinnerProps) : children
]);
},
closeWithCheck: function() {
var ref3, unSavedChanges, unSavedDialogueHeight, unSavedMessage;
ref3 = this.props, unSavedMessage = ref3.unSavedMessage, unSavedDialogueHeight = ref3.unSavedDialogueHeight, unSavedChanges = ref3.unSavedChanges;
if (unSavedChanges) {
return this.showDialogue({
message: unSavedMessage || t('There are unsaved changes. How do you want to proceed?'),
confirmText: t('Discard Changes'),
height: unSavedDialogueHeight,
confirmCallback: this.close
});
} else {
return this.close();
}
},
close: function() {
var close, onClose, ref3;
ref3 = this.props, close = ref3.close, onClose = ref3.onClose;
if (typeof onClose === "function") {
onClose();
}
return close();
},
saveComplete: function() {
var close, closeAfterSave, onSaveComplete, ref3;
ref3 = this.props, close = ref3.close, onSaveComplete = ref3.onSaveComplete, closeAfterSave = ref3.closeAfterSave;
if (typeof onSaveComplete === "function") {
onSaveComplete();
}
if (closeAfterSave) {
return close();
}
},
handleKeyPress: function(e) {
var buttons, keyCode, metaKey, ref3;
keyCode = e.keyCode, metaKey = e.metaKey;
if (keyCode === ESCAPE) {
this.closeWithCheck();
}
if (keyCode === KEY_S && metaKey) {
e.preventDefault();
buttons = this.props.buttons;
if (((ref3 = buttons[0]) != null ? ref3.name : void 0) === t('Save')) {
return buttons[0].handler();
}
}
}
});
styles = StyleSheet.create({
formBase: {
position: 'absolute',
backgroundColor: 'white',
overflow: 'hidden',
width: '100%',
height: '100%'
},
form: {
top: '0px',
left: '0px'
},
bar: {
position: 'absolute',
height: '40px',
backgroundColor: '#fafaf6',
borderBottom: '1px solid #e5e4dc',
overflow: 'hidden',
zIndex: '8',
width: '100%'
},
title: {
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
fontSize: '18px',
height: '100%',
lineHeight: '40px',
color: '#666666',
display: 'inline-block',
marginTop: '0px',
marginLeft: '20px',
paddingRight: '20px'
},
btn: {
float: 'right',
marginRight: '15px',
color: '#007fff',
height: '28px',
textAlign: 'center',
lineHeight: '26px',
marginTop: '6px',
fontSize: '13px'
},
disabled: {
color: '#cccccc'
}
});
module.exports = Form;
}).call(this);