mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
125 lines
3.9 KiB
JavaScript
125 lines
3.9 KiB
JavaScript
import React from 'react';
|
|
import { bindActionCreators } from 'redux';
|
|
import { connect } from 'react-redux';
|
|
import SilverStripeComponent from 'silverstripe-component';
|
|
import GridFieldTable from './table';
|
|
import GridFieldHeader from './header';
|
|
import GridFieldHeaderCell from './header-cell';
|
|
import GridFieldRow from './row';
|
|
import GridFieldCell from './cell';
|
|
import GridFieldAction from './action';
|
|
import * as actions from 'state/records/actions';
|
|
|
|
/**
|
|
* The component acts as a container for a grid field,
|
|
* with smarts around data retrieval from external sources.
|
|
*
|
|
* @todo Convert to higher order component which hooks up form schema data to an API backend as a grid data source
|
|
* @todo Replace "dumb" inner components with third party library (e.g. https://griddlegriddle.github.io)
|
|
*/
|
|
class GridField extends SilverStripeComponent {
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.deleteRecord = this.deleteRecord.bind(this);
|
|
this.editRecord = this.editRecord.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
super.componentDidMount();
|
|
|
|
let data = this.props.data;
|
|
|
|
this.props.actions.fetchRecords(data.recordType, data.collectionReadEndpoint.method, data.collectionReadEndpoint.url);
|
|
}
|
|
|
|
render() {
|
|
const records = this.props.records;
|
|
if(!records) {
|
|
return <div></div>;
|
|
}
|
|
|
|
const columns = this.props.data.columns;
|
|
|
|
// TODO Replace with display: table based system
|
|
const cellWidth = 5;
|
|
const actionCellWidth = 2 * 36 + 12;
|
|
|
|
// Placeholder to align the headers correctly with the content
|
|
const actionPlaceholder = <span key={'actionPlaceholder'} style={{width: actionCellWidth}} />;
|
|
const headerCells = columns.map((column, i) => <GridFieldHeaderCell key={i} width={cellWidth}>{column.name}</GridFieldHeaderCell>);
|
|
const header = <GridFieldHeader>{headerCells.concat(actionPlaceholder)}</GridFieldHeader>;
|
|
|
|
const rows = records.map((record, i) => {
|
|
var cells = columns.map((column, i) => {
|
|
// Get value by dot notation
|
|
var val = column.field.split('.').reduce((a, b) => a[b], record)
|
|
return <GridFieldCell key={i} width={column.width}>{val}</GridFieldCell>
|
|
});
|
|
|
|
var rowActions = [
|
|
<GridFieldAction
|
|
icon={'cog'}
|
|
handleClick={this.editRecord.bind(this, record.ID)}
|
|
key={"action-" + i + "-edit"}
|
|
/>,
|
|
<GridFieldAction
|
|
icon={'cancel'}
|
|
handleClick={this.deleteRecord.bind(this, record.ID)}
|
|
key={"action-" + i + "-delete"}
|
|
/>
|
|
];
|
|
|
|
return <GridFieldRow key={i}>{cells.concat(rowActions)}</GridFieldRow>;
|
|
});
|
|
|
|
return (
|
|
<GridFieldTable header={header} rows={rows}></GridFieldTable>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param number int
|
|
* @param event
|
|
*/
|
|
deleteRecord(id, event) {
|
|
event.preventDefault();
|
|
this.props.actions.deleteRecord(
|
|
this.props.data.recordType,
|
|
id,
|
|
this.props.data.itemDeleteEndpoint.method,
|
|
this.props.data.itemDeleteEndpoint.url
|
|
);
|
|
}
|
|
|
|
editRecord(event) {
|
|
event.preventDefault();
|
|
// TODO
|
|
}
|
|
|
|
}
|
|
|
|
GridField.propTypes = {
|
|
data: React.PropTypes.shape({
|
|
recordType: React.PropTypes.string.isRequired,
|
|
headerColumns: React.PropTypes.array,
|
|
collectionReadEndpoint: React.PropTypes.object
|
|
})
|
|
};
|
|
|
|
function mapStateToProps(state, ownProps) {
|
|
let recordType = ownProps.data ? ownProps.data.recordType : null;
|
|
return {
|
|
records: (state.records && recordType) ? state.records[recordType] : []
|
|
}
|
|
}
|
|
|
|
function mapDispatchToProps(dispatch) {
|
|
return {
|
|
actions: bindActionCreators(actions, dispatch)
|
|
}
|
|
}
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(GridField);
|