@bigfishtv/cockpit
Version:
532 lines (443 loc) • 19.4 kB
JavaScript
'use strict';
exports.__esModule = true;
exports.default = exports.AutoTableIndexBase = exports.AutoTableIndexContainer = undefined;
var _class, _temp;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _newId = require('../../utils/newId');
var _newId2 = _interopRequireDefault(_newId);
var _Conditions = require('../../constants/Conditions');
var Conditions = _interopRequireWildcard(_Conditions);
var _promptUtils = require('../../utils/promptUtils');
var _typeUtils = require('../../utils/typeUtils');
var _xhrUtils = require('../../api/xhrUtils');
var _stringUtils = require('../../utils/stringUtils');
var _formUtils = require('../../utils/formUtils');
var _tableUtils = require('../../utils/tableUtils');
var _Table = require('../table/Table');
var _Table2 = _interopRequireDefault(_Table);
var _Spinner = require('../Spinner');
var _Spinner2 = _interopRequireDefault(_Spinner);
var _MainContent = require('../container/MainContent');
var _MainContent2 = _interopRequireDefault(_MainContent);
var _Panel = require('../container/panel/Panel');
var _Panel2 = _interopRequireDefault(_Panel);
var _Bulkhead = require('../page/Bulkhead');
var _Bulkhead2 = _interopRequireDefault(_Bulkhead);
var _SearchInput = require('../input/SearchInput');
var _SearchInput2 = _interopRequireDefault(_SearchInput);
var _Hint = require('../Hint');
var _Hint2 = _interopRequireDefault(_Hint);
var _Button = require('../button/Button');
var _Button2 = _interopRequireDefault(_Button);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
var DefaultPanelToolbar = function DefaultPanelToolbar(_ref) {
var movable = _ref.movable,
duplicable = _ref.duplicable,
handleMove = _ref.handleMove,
handleDuplicate = _ref.handleDuplicate,
exportable = _ref.exportable,
handleExport = _ref.handleExport,
selectedIds = _ref.selectedIds,
data = _ref.data,
handleDelete = _ref.handleDelete,
props = _objectWithoutProperties(_ref, ['movable', 'duplicable', 'handleMove', 'handleDuplicate', 'exportable', 'handleExport', 'selectedIds', 'data', 'handleDelete']);
return _react2.default.createElement(
'div',
null,
duplicable && _react2.default.createElement(_Button2.default, { text: 'Duplicate', onClick: handleDuplicate, disabled: selectedIds.length !== 1 }),
movable && _react2.default.createElement(_Button2.default, { text: 'Move', onClick: handleMove, disabled: !selectedIds.length }),
_react2.default.createElement(_Button2.default, { text: 'Delete', onClick: handleDelete, style: 'error', disabled: !selectedIds.length }),
exportable && _react2.default.createElement(_Button2.default, { text: selectedIds.length > 0 ? 'Export ' + selectedIds.length : 'Export', onClick: handleExport })
);
};
var DefaultBulkheadToolbar = function DefaultBulkheadToolbar(_ref2) {
var modelLabel = _ref2.modelLabel,
model = _ref2.model,
addUrl = _ref2.addUrl;
return _react2.default.createElement(_Button2.default, {
text: 'New ' + (0, _stringUtils.titleCase)(modelLabel || model),
onClick: function onClick() {
return window.location.href = addUrl;
},
style: 'primary',
size: 'large'
});
};
var DefaultPanelDrawer = function DefaultPanelDrawer(_ref3) {
var data = _ref3.data,
originalData = _ref3.originalData,
filterset = _ref3.filterset,
query = _ref3.query,
selectedIds = _ref3.selectedIds;
var filters = Object.keys(filterset).reduce(function (obj, key) {
var _extends2;
return filterset[key] !== null ? _extends({}, obj, (_extends2 = {}, _extends2[key] = filterset[key], _extends2)) : obj;
}, {});
var filterKeys = Object.keys(filters);
var numKeys = filterKeys.length;
var queryStr = '';
if (!!query || numKeys > 0) queryStr += 'Filtered ';
if (!!query) queryStr += 'by "' + query + '" ';
if (numKeys > 0) queryStr += 'where ';
return _react2.default.createElement(
'div',
{ className: 'panel-drawer' },
_react2.default.createElement(
'span',
{ style: { float: 'left' } },
'Showing ',
_react2.default.createElement(
'strong',
null,
data.length
),
' of ',
_react2.default.createElement(
'strong',
null,
originalData.length
),
selectedIds.length > 0 && _react2.default.createElement(
'span',
null,
'\xA0\xA0\u2013\xA0\xA0',
_react2.default.createElement(
'strong',
null,
selectedIds.length === data.length ? 'All' : selectedIds.length
),
' selected'
)
),
(!!query || numKeys > 0) && _react2.default.createElement(
'span',
{ style: { float: 'right' } },
queryStr,
numKeys > 0 && filterKeys.map(function (key, i) {
var value = filters[key];
if ((0, _typeUtils.isObject)(value)) value = ' is ' + JSON.encode(value);else if (typeof value == 'function') value = ' matches a custom function';else value = ' is ' + value.toString();
return _react2.default.createElement(
'span',
{ key: key },
(0, _stringUtils.titleCase)(key),
value,
i < numKeys - 2 ? ', ' : i < numKeys - 1 ? ' and ' : '.'
);
})
)
);
};
var AutoTableIndexContainer = exports.AutoTableIndexContainer = (_temp = _class = function (_Component) {
_inherits(AutoTableIndexContainer, _Component);
function AutoTableIndexContainer(props) {
_classCallCheck(this, AutoTableIndexContainer);
var _this = _possibleConstructorReturn(this, _Component.call(this, props));
_this.handleQueryChange = function (value) {
var query = typeof value == 'string' ? value : value.target.value;
_this.setState({ query: query, selectedIds: [] });
};
_this.handleSelectionChange = function (selectedIds) {
_this.setState({ selectedIds: selectedIds });
};
_this.handleNegativeHeightChange = function (negativeHeight) {
_this.setState({ negativeHeight: negativeHeight });
};
_this.handleFilterChange = function (property, value) {
var filterset = _this.state.filterset;
if ((0, _typeUtils.isObject)(property)) {
Object.keys(property).forEach(function (key) {
return filterset[key] = property[key];
});
} else {
filterset[property] = value;
}
_this.setState({ filterset: filterset });
};
_this.handleEdit = function (item) {
var isNew = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (_this.props.onSelect) _this.props.onSelect(item);else window.location.href = _this.props.updateUrl + item.id;
};
_this.handleDelete = function () {
var _this$state = _this.state,
data = _this$state.data,
selectedIds = _this$state.selectedIds;
(0, _promptUtils.showDeletePrompt)({
subject: _this.props.modelLabel || null,
selectedIds: selectedIds,
renderListItem: _this.props.renderListItem,
data: data.filter(function (item) {
return selectedIds.indexOf(item.id) >= 0;
}),
queryUrl: _this.props.deleteUrl,
callback: function callback(deletedData) {
var deletedIds = selectedIds; // deletedData.map(item => item.id)
var data = _this.state.data.filter(function (item) {
return deletedIds.indexOf(item.id) < 0;
});
_this.setState({ data: data, selectedIds: [] });
}
});
};
_this.handleDuplicate = function () {
var _this$props = _this.props,
model = _this$props.model,
duplicateUrl = _this$props.duplicateUrl,
duplicateTransformer = _this$props.duplicateTransformer;
var _this$state2 = _this.state,
data = _this$state2.data,
selectedIds = _this$state2.selectedIds;
var selectedItem = data.filter(function (item) {
return item.id === selectedIds[0];
})[0];
var url = duplicateUrl || '/admin/' + model + '/' + selectedItem.id + '.json?clone=1';
(0, _xhrUtils.post)({
url: url,
data: _extends({}, duplicateTransformer(selectedItem), { id: (0, _newId2.default)() }),
callback: function callback(result) {
return _this.setState({ data: [].concat(data, [result]) });
}
});
};
_this.handleExport = function () {
var _this$state3 = _this.state,
data = _this$state3.data,
selectedIds = _this$state3.selectedIds;
var itemIds = selectedIds.length > 0 ? selectedIds : data.map(function (item) {
return item.id;
});
var query = itemIds.map(function (id) {
return 'ids[]=' + id;
}).join('&');
window.open(_this.props.exportUrl + '?' + query);
};
_this.handleMove = function () {
if (_this.props.onMove) {
var _this$state4 = _this.state,
data = _this$state4.data,
selectedIds = _this$state4.selectedIds;
var selectedItems = data.filter(function (item) {
return ~selectedIds.indexOf(item.id);
});
_this.props.onMove(selectedItems, _this.handleUpdateCallback);
}
};
_this.handleUpdateCallback = function (mapperFunc) {
var data = _this.state.data;
var newData = mapperFunc(data);
_this.setState({ data: newData, originalData: newData });
};
_this.handleDataUpdate = function (data) {
_this.setState({ data: data, originalData: data });
};
_this.state = {
data: props.defaultValue,
selectedIds: [],
filterset: props.defaultFilterset,
query: props.defaultQuery,
loading: false,
negativeHeight: props.hint ? props.negativeHeight + 49 : props.negativeHeight
};
_this.fields = (0, _tableUtils.getFieldsFromSchemaAndAssociations)(props.schema, props.associations, props.componentResolver, props.attributeModifier);
return _this;
}
AutoTableIndexContainer.prototype.getSubmitUrl = function getSubmitUrl(data) {
return data.id ? this.props.updateUrl + '/' + data.id + '.json' : this.props.addUrl;
};
/**
* Overloaded function -- handles updates to filterset object, usually used by dropdown selectors
* @param {String / Object} property - is property or object of key values
* @param {String} value - is value of property, otherwise leave blank
*/
AutoTableIndexContainer.prototype.render = function render() {
var _props = this.props,
schema = _props.schema,
associations = _props.associations,
protectedFieldWhitelist = _props.protectedFieldWhitelist,
panelProps = _props.panelProps;
var _state = this.state,
data = _state.data,
query = _state.query,
selectedIds = _state.selectedIds,
loading = _state.loading,
filterset = _state.filterset,
negativeHeight = _state.negativeHeight;
var _schema = (0, _formUtils.filterOutProtectedSchema)((0, _formUtils.removeAssocationsFromSchema)(associations, schema), protectedFieldWhitelist);
var _data = (0, _tableUtils.filterDataByFilterset)((0, _tableUtils.filterDataByQueryWithFields)(data, this.fields, query), filterset, Conditions.AND);
var _panelProps = _extends({
handleEdit: this.handleEdit,
handleDelete: this.handleDelete,
handleExport: this.handleExport,
handleMove: this.handleMove,
handleDuplicate: this.handleDuplicate,
handleQueryChange: this.handleQueryChange,
handleFilterChange: this.handleFilterChange,
handleDataUpdate: this.handleDataUpdate,
handleSelectionChange: this.handleSelectionChange,
handleNegativeHeightChange: this.handleNegativeHeightChange,
movable: this.props.movable,
duplicable: this.props.duplicable,
exportable: this.props.exportable,
originalData: data,
data: _data,
selectedIds: selectedIds,
filterset: filterset,
query: query
}, panelProps);
return this.props.children(_extends({}, this.props, _panelProps, {
panelProps: _panelProps,
schema: _schema,
data: _data,
loading: loading,
negativeHeight: negativeHeight
}));
};
return AutoTableIndexContainer;
}(_react.Component), _class.propTypes = {
/** the lowercase plural model e.g. volunteer_applications */
model: _propTypes2.default.string,
/** array of table schema passed in from backend */
schema: _propTypes2.default.array,
/** array of entity assocations passed in from backend */
assocations: _propTypes2.default.array,
/** array of entity assocations passed in from backend */
hint: _propTypes2.default.string,
/** function that receives assocations and schema column, returns a component */
componentResolver: _propTypes2.default.func,
/** function that receives assocations and schema column, returns a field object to be merged with auto-generated field e.g. {width: 60} */
attributeModifier: _propTypes2.default.func,
/** function to handle when a row is double clicked */
onSelect: _propTypes2.default.func,
/** default form value provided from backend, typically array of entity objects */
defaultValue: _propTypes2.default.array,
/** fields that start with an underscore (_) get excluded by default, this offers a way to whitelist some of those */
protectedFieldWhitelist: _propTypes2.default.array,
/** panel title component to replace default search field */
PanelTitle: _propTypes2.default.func,
/** panel toolbar component to replace default one, takes props: selectedIds, data, originalData, duplicable, handleDuplicate, handleDelete */
PanelToolbar: _propTypes2.default.func,
/** Any extra props to pass through to PanelToolbar */
panelProps: _propTypes2.default.object,
/** Function for rendering item titles, used in delete prompt */
renderListItem: _propTypes2.default.func,
/** panel toolbar component to replace default one, takes props: selectedIds, data, originalData, duplicable, handleDuplicate, handleDelete */
BulkheadToolbar: _propTypes2.default.func,
children: _propTypes2.default.func,
duplicateTransformer: _propTypes2.default.func
}, _class.defaultProps = {
defaultValue: [],
schema: [],
associations: [],
model: 'model',
negativeHeight: 228,
movable: false,
duplicable: false,
exportable: false,
defaultQuery: '',
defaultFilterset: {},
panelProps: {},
renderListItem: null,
protectedFieldWhitelist: [],
PanelToolbar: DefaultPanelToolbar,
PanelDrawer: DefaultPanelDrawer,
BulkheadToolbar: DefaultBulkheadToolbar,
duplicateTransformer: function duplicateTransformer(item) {
return item;
}
}, _temp);
var AutoTableIndexBase = exports.AutoTableIndexBase = function (_Component2) {
_inherits(AutoTableIndexBase, _Component2);
function AutoTableIndexBase() {
_classCallCheck(this, AutoTableIndexBase);
return _possibleConstructorReturn(this, _Component2.apply(this, arguments));
}
AutoTableIndexBase.prototype.render = function render() {
var _props2 = this.props,
PanelToolbar = _props2.PanelToolbar,
PanelDrawer = _props2.PanelDrawer,
PanelTitle = _props2.PanelTitle,
panelProps = _props2.panelProps,
handleQueryChange = _props2.handleQueryChange,
handleSelectionChange = _props2.handleSelectionChange,
handleEdit = _props2.handleEdit,
handleNegativeHeightChange = _props2.handleNegativeHeightChange,
query = _props2.query,
hint = _props2.hint,
negativeHeight = _props2.negativeHeight,
loading = _props2.loading,
schema = _props2.schema,
associations = _props2.associations,
data = _props2.data,
selectedIds = _props2.selectedIds,
props = _objectWithoutProperties(_props2, ['PanelToolbar', 'PanelDrawer', 'PanelTitle', 'panelProps', 'handleQueryChange', 'handleSelectionChange', 'handleEdit', 'handleNegativeHeightChange', 'query', 'hint', 'negativeHeight', 'loading', 'schema', 'associations', 'data', 'selectedIds']);
return _react2.default.createElement(
_Panel2.default,
_extends({
PanelToolbar: PanelToolbar,
PanelDrawer: PanelDrawer,
title: PanelTitle !== undefined ? PanelTitle : _react2.default.createElement(_SearchInput2.default, { value: query, onChange: handleQueryChange })
}, panelProps),
hint && _react2.default.createElement(_Hint2.default, { title: hint, onHide: function onHide() {
return handleNegativeHeightChange(negativeHeight - 49);
} }),
loading ? _react2.default.createElement(
'div',
{ className: 'loader-center margin-top-xlarge' },
_react2.default.createElement(_Spinner2.default, { spinnerName: 'circle' })
) : _react2.default.createElement(_Table2.default, _extends({}, props, {
schema: schema,
associations: associations,
data: data,
selectedIds: selectedIds,
onSelect: handleEdit,
onSelectionChange: handleSelectionChange,
negativeHeight: negativeHeight
}))
);
};
return AutoTableIndexBase;
}(_react.Component);
var AutoTableIndex = function (_Component3) {
_inherits(AutoTableIndex, _Component3);
function AutoTableIndex() {
_classCallCheck(this, AutoTableIndex);
return _possibleConstructorReturn(this, _Component3.apply(this, arguments));
}
AutoTableIndex.prototype.render = function render() {
return _react2.default.createElement(
AutoTableIndexContainer,
this.props,
function (props) {
var model = props.model,
panelProps = props.panelProps,
BulkheadToolbar = props.BulkheadToolbar;
return _react2.default.createElement(
_MainContent2.default,
null,
_react2.default.createElement(_Bulkhead2.default, { title: (0, _stringUtils.titleCase)(model), Toolbar: function Toolbar() {
return _react2.default.createElement(BulkheadToolbar, _extends({}, props, panelProps));
} }),
_react2.default.createElement(
'div',
{ className: 'finder' },
_react2.default.createElement(
'div',
{ className: 'finder-content', ref: 'finderContent' },
_react2.default.createElement(AutoTableIndexBase, props)
)
)
);
}
);
};
return AutoTableIndex;
}(_react.Component);
exports.default = AutoTableIndex;