Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- "use strict";
- const Map = require("immutable").Map;
- const objectUtils = require("../util/object.js");
- const React = require("../react.js");
- module.exports = class Datatable extends React.Component {
- /**
- * Public Methods
- */
- mergeFilterParameters(filterParameters) {
- const newDynamicFilterParameters = this.dynamicFilterParameters.merge(filterParameters);
- if (newDynamicFilterParameters !== this.dynamicFilterParameters) {
- this.dynamicFilterParameters = newDynamicFilterParameters;
- $(this.node).DataTable().ajax.reload();
- }
- }
- /**
- * React Callbacks
- */
- render() {
- const filterChildren =
- React.Children.toArray(this.props.children)
- .filter(c => c.type === module.exports.Filters)
- .map(c => React.cloneElement(c, {
- datatable: this,
- }))
- ;
- return (
- <div className="wrapper wrapper-content animated fadeInRight ecommerce">
- {do{ if (filterChildren.length > 0) {
- <div id="filters" className="ibox-content m-b-sm border-bottom">
- {filterChildren}
- </div>
- }}}
- <div className="row">
- <div className="col-lg-12">
- <div className="wrapper wrapper-content animated fadeInRight">
- <div className="ibox float-e-margins">
- <div className="ibox-content">
- <table ref={(ref) => this.node = ref} className="table table-striped dataTable"></table>;
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
- shouldComponentUpdate() {
- return false;
- }
- componentDidMount() {
- this.dynamicFilterParameters = new Map();
- this.csvButton = $('<a class="btn btn-xs btn-primary" data-action="download"><i class="fa fa-download"></i> Download CSV</a>').get(0);
- const defaultOptions = {
- columns:
- React.Children.toArray(this.props.children)
- .filter(c => c.type === module.exports.Column)
- .map(module.exports.Column.getConfiguration)
- ,
- processing: true,
- serverSide: true,
- autoWidth: true,
- dom: [
- "<'row'<'col-sm-2'<'csv'>><'col-sm-2'l><'col-sm-4'r><'col-sm-4'p>>",
- "<'row'<'col-sm-12't>>",
- "<'row'<'col-sm-4'i><'col-sm-4'r><'col-sm-4'p>>",
- ].join(""),
- ajax: {
- url: this.props.url,
- data: (d, settings) => {
- Object.assign(d, this.staticFilterParameters, this.dynamicFilterParameters.toObject());
- const csvParameters = Object.assign({}, d, {
- output: "csv",
- start: 0,
- length: 0,
- });
- $(this.csvButton).attr("href", `${ settings.ajax.url }?${ $.param(csvParameters) }`);
- },
- },
- }
- const propOptions = objectUtils.withoutKeys(this.props, [
- "children",
- "enableCsv",
- "staticFilterParams",
- "dynamicFilterParams",
- "url",
- ]);
- $(this.node).DataTable(objectUtils.assignDeep({}, defaultOptions, propOptions));
- if (this.props.enableCsv) {
- $(this.node).closest("div.dataTables_wrapper").find("div.csv").append(this.csvButton);
- }
- }
- componentWillReceiveProps(nextProps) {
- this.mergeFilterParameters(nextProps.filterParameters || {});
- }
- componentWillUnmount() {
- this.$node.DataTable().destroy(true);
- }
- };
- module.exports.Column = do {
- const ReactDomServer = require("react-dom/server");
- const Column = class Column extends React.ConfigurationComponent {};
- Column.getConfiguration = (column) => {
- if (column.props.RenderComponent) {
- if (column.props.render) {
- throw new Error("Don't set both `render` and `RenderComponent`, they're mutually-exclusive");
- }
- /**
- * I do wonder what the performance implications of `RenderComponent`
- * will be, since we're forcing react to render a component to a string
- * each time. For now I'm going to use this because it gives us a lot
- * of benefits, but if it becomes an issue we can revisit column.
- */
- const RenderComponent = column.props.RenderComponent;
- const restProps = objectUtils.withoutKeys(column.props, ["RenderComponent"]);
- const render = (data, type, row, meta) => {
- const reactEl = <RenderComponent data={data} type={type} row={row} meta={meta} />;
- return ReactDomServer.renderToStaticMarkup(reactEl);
- };
- return Object.assign({}, restProps, { render });
- } else {
- return column.props;
- }
- };
- Column;
- };
- module.exports.Filters = class Filters extends React.StatelessComponent {
- render() { return (
- <div className="row">
- {React.Children.map(this.props.children, c => React.cloneElement(c, {
- datatable: this.props.datatable,
- }))}
- </div>
- ); }
- };
- module.exports.Filters.Action = class ActionFilter extends React.StatelessComponent {
- render() { return (
- <div className="col-sm-4">
- <div className="form-group">
- <label className="control-label">Action</label>
- <input
- type="text"
- name="action"
- className="form-control"
- onChange={({ target: { value } }) => this.props.datatable.mergeFilterParameters({ action: value })}
- />
- </div>
- </div>
- );}
- };
- module.exports.Filters.Date = do{
- const DateTimePicker = require("react-widgets").DateTimePicker;
- (class DateFilter extends React.StatelessComponent {
- render() { return (
- <div className="col-sm-4">
- <div className="form-group">
- <label className="control-label">Date</label>
- <DateTimePicker
- time={false}
- onChange={(date) => this.props.datatable.mergeFilterParameters({ timestamp: moment(date).format("L") })}
- />
- </div>
- </div>
- );}
- });
- };
- module.exports.Filters.User = class UserFilter extends React.Component {
- render() { return (
- <div className="col-sm-4">
- <div className="form-group">
- <label className="control-label">User</label>
- <input className="form-control" ref={ref => this.node = ref} />
- </div>
- </div>
- );}
- shouldComponentUpdate() {
- return false;
- }
- componentDidMount() {
- this.users = this.props.users;
- this.onChange = this.props.onChange;
- const usersByName = {};
- for (const user of this.users) {
- usersByName[user.name] = user;
- }
- const bloodhound = new Bloodhound({
- identify: (obj) => obj.id,
- datumTokenizer: (datum) => Bloodhound.tokenizers.whitespace(datum.name),
- queryTokenizer: Bloodhound.tokenizers.whitespace,
- local: this.users,
- });
- $(this.node).typeahead(
- {
- hint: true,
- highlight: true,
- minLength: 1,
- },
- {
- name: "users",
- source: bloodhound,
- displayKey: "name",
- templates: {
- empty: `
- <div class="empty-message">(no results found)</div>
- `,
- },
- }
- );
- const onInputChange = () => {
- const selected = usersByName[$(this.node).val()];
- if (selected) {
- this.props.datatable.mergeFilterParameters({ userId: selected.id });
- } else {
- this.props.datatable.mergeFilterParameters({ userId: null });
- }
- };
- $(this.node)
- .bind("typeahead:change", onInputChange)
- .bind("typeahead:select", onInputChange)
- .keyup(onInputChange)
- ;
- }
- componentWillUnmount() {
- throw new Error("Handle componentWillUnmount, find some way of uninitializing this jq plugin");
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement