Lanes.Components.Grid.EditingMixin = { propTypes: rowIndex: React.PropTypes.number.isRequired onSave: React.PropTypes.func.isRequired onCancel: React.PropTypes.func.isRequired model: Lanes.PropTypes.State.isRequired query: Lanes.PropTypes.State.isRequired editors: React.PropTypes.object beforeSave: React.PropTypes.func afterSave: React.PropTypes.func allowDelete: React.PropTypes.bool syncImmediatly: React.PropTypes.oneOfType([ React.PropTypes.bool, React.PropTypes.func ]) editorTypes: text: (props) -> props.value ||= '' <input type="text" {...props} onChange={_.partial(@onFieldChange, _, props.field)} /> bigdec: (props) -> <LC.NumberInput unstyled {...props} /> date: (props) -> <LC.DateTime {...props} inputOnly step={15} onChange={_.partial(@onDateFieldChange, _, props.field)} /> displayTypes: bigdec: (props) -> <span>{props.value.toFixed(2)}</span> text: (props) -> <span>{props.value}</span> listenNetworkEvents: true getDefaultProps: -> editors: {} componentDidMount: -> qs = if @props.initiallyFocusedField then ".field[data-id=\"#{@props.initiallyFocusedField}\"] input" else 'input' _.defer => _.dom(@).qs(qs).focusAndSelect() renderControls: -> if @props.allowDelete deleteBtn = <button type="button" className="btn delete" onClick={@deleteRecord}> <i className="icon icon-trash" />Delete </button> <div className="controls"> <div className="buttons"> <button type="button" className="btn cancel" onClick={@onCancel}> <i className="icon icon-refresh" /> Cancel </button> {deleteBtn} <button type="button" className="btn save" onClick={@saveRecord}> <i className="icon icon-save" />Save </button> </div> </div> getFieldValue: (field) -> @props.model[field.id] || '' onDateFieldChange: (date, field) -> @props.model[field.id] = date onFieldChange: (ev, field) -> @props.model[field.id] = ev.target.value renderFields: -> for field, index in @props.query.fields.models when field.visible @renderField(field, index) renderEditingBody: -> if _.isFunction(@renderBody) @renderBody() else <div className="editing-body"> <div className="fields"> {@renderFields()} </div> {@renderControls()} </div> renderEditValue: (props) -> ( @props.editors[props.field.id] || @editorTypes[props.field.type] || @editorTypes['text'] ).call(this, props) renderDisplayValue: (props) -> ( @displayTypes[props.field.type] || @displayTypes['text'] ).call(this, props) renderField: (field, index) -> props = _.extend( { index, field, props: @props, name: field.id, value: @getFieldValue(field) }, _.pick(@props, 'model', 'query', 'rowIndex') ) control = if field.editable then @renderEditValue(props) else @renderDisplayValue(props) <div key={field.id} data-id={field.id} style = {@props.cellStyles.styles[index]} className = {_.classnames('field', @props.cellStyles.classes[index])} > <label>{field.title}</label> {control} </div> onCancel: -> @props.onCancel(@props.model) shouldPerformSync: -> !!Lanes.u.resultsFor(@props, 'syncImmediatly', @props.model) saveRecord: -> return if false == @props.beforeSave?(@props.model, @props.rowIndex) if @shouldPerformSync() @props.model.save().then (model) => @props.onSave(model) @props.afterEdit?(model, @props.rowIndex) else @props.onSave(@props.model) @props.afterEdit?(@props.model, @props.rowIndex) deleteRecord: -> if @shouldPerformSync() @props.model.destroy().then (model) => @props.onSave(model, true) else @props.onSave(@props.model, true) }