├── .DS_Store ├── .eslintrc.js ├── .flowconfig ├── .github └── workflows │ └── tests.js.yml ├── .gitignore ├── .npmignore ├── .prettierrc ├── CONTRIBUTING.md ├── CRUD_Toon_SMALL.png ├── LICENSE.md ├── README.md ├── badges ├── badge-branches.svg ├── badge-functions.svg ├── badge-lines.svg └── badge-statements.svg ├── build ├── Button │ ├── index.js │ └── wrappers.js ├── CRUDTable │ ├── Body.js │ ├── Header.js │ ├── actions.js │ ├── constants.js │ ├── helpers.js │ ├── index.js │ └── wrappers.js ├── Form │ ├── Base.js │ ├── helpers.js │ ├── index.js │ └── wrappers.js ├── FormModal │ ├── helpers.js │ └── index.js ├── Label │ ├── index.js │ └── wrappers.js ├── Modal │ ├── index.js │ └── wrappers.js ├── Pagination │ ├── index.js │ └── wrappers.js ├── QueryBuilder │ ├── RuleBuilder.js │ ├── Rules.js │ ├── Select.js │ ├── constants.js │ ├── helpers.js │ ├── index.js │ └── wrappers.js ├── Select │ └── index.js └── helpers.js ├── jest.setup.js ├── package-lock.json ├── package.json ├── screenshot-pagination.jpg ├── screenshot-simple.png └── src ├── Button ├── __snapshots__ │ └── index.test.js.snap ├── index.js ├── index.test.js └── wrappers.js ├── CRUDTable ├── Body.js ├── Body.test.js ├── Header.js ├── Header.test.js ├── __snapshots__ │ ├── Body.test.js.snap │ ├── Header.test.js.snap │ └── index.test.js.snap ├── actions.js ├── constants.js ├── helpers.js ├── index.js ├── index.test.js └── wrappers.js ├── Form ├── Base.js ├── Base.test.js ├── __snapshots__ │ ├── Base.test.js.snap │ └── index.test.js.snap ├── helpers.js ├── index.js ├── index.test.js └── wrappers.js ├── FormModal ├── __snapshots__ │ └── index.test.js.snap ├── helpers.js ├── helpers.test.js ├── index.js └── index.test.js ├── Label ├── __snapshots__ │ └── index.test.js.snap ├── index.js ├── index.test.js └── wrappers.js ├── Modal ├── __snapshots__ │ └── index.test.js.snap ├── index.js ├── index.test.js └── wrappers.js ├── Pagination ├── __snapshots__ │ └── index.test.js.snap ├── index.js ├── index.test.js └── wrappers.js ├── QueryBuilder ├── RuleBuilder.js ├── RuleBuilder.test.js ├── Rules.js ├── Rules.test.js ├── __snapshots__ │ ├── RuleBuilder.test.js.snap │ ├── Rules.test.js.snap │ └── index.test.js.snap ├── constants.js ├── helpers.js ├── index.js ├── index.test.js └── wrappers.js ├── Select ├── __snapshots__ │ └── index.test.js.snap ├── index.js └── index.test.js ├── helpers.js └── index.css /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xvicmanx/react-crud-table/fad9815a470e3bd4c9bb9596d7619bb77704b298/.DS_Store -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | }, 7 | parserOptions: { 8 | parser: 'babel-eslint', 9 | ecmaVersion: 2018, 10 | sourceType: 'module', 11 | }, 12 | extends: [ 13 | 'plugin:react/recommended', 14 | 'plugin:prettier/recommended', 15 | 'plugin:flowtype/recommended', 16 | ], 17 | plugins: ['flowtype'], 18 | rules: { 19 | 'react/prop-types': 1, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | 11 | [strict] 12 | -------------------------------------------------------------------------------- /.github/workflows/tests.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow run apps tests 2 | name: Tests 3 | 4 | on: 5 | push: 6 | branches: [ master ] 7 | pull_request: 8 | branches: [ master ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | matrix: 17 | node-version: [12.x] 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Tests 22 | uses: actions/setup-node@v1 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | - run: npm install 26 | - run: npm run lint 27 | - run: npm test 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode/ 3 | build/__tests__/ 4 | .DS_Store 5 | coverage 6 | build/**/*.test.js -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | coverage 3 | build/**/*.test.js -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | - Fork the repository 3 | - Create a feature branch (git checkout -b new-feature) 4 | - Commit the changes (git commit -m 'Add some feature') 5 | - Push the branch (git push origin new-feature) 6 | - Create a new Pull Request 7 | - Get some reviews 8 | -------------------------------------------------------------------------------- /CRUD_Toon_SMALL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xvicmanx/react-crud-table/fad9815a470e3bd4c9bb9596d7619bb77704b298/CRUD_Toon_SMALL.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Approachable Open Source 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /badges/badge-branches.svg: -------------------------------------------------------------------------------- 1 | Coverage:branches: 91.91%Coverage:branches91.91% -------------------------------------------------------------------------------- /badges/badge-functions.svg: -------------------------------------------------------------------------------- 1 | Coverage:functions: 93.16%Coverage:functions93.16% -------------------------------------------------------------------------------- /badges/badge-lines.svg: -------------------------------------------------------------------------------- 1 | Coverage:lines: 97.73%Coverage:lines97.73% -------------------------------------------------------------------------------- /badges/badge-statements.svg: -------------------------------------------------------------------------------- 1 | Coverage:statements: 96.26%Coverage:statements96.26% -------------------------------------------------------------------------------- /build/Button/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _wrappers = require("./wrappers"); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 13 | 14 | var Button = function Button(props) { 15 | return /*#__PURE__*/_react["default"].createElement(_wrappers.Btn, props); 16 | }; 17 | 18 | var _default = Button; 19 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Button/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.Btn = void 0; 7 | 8 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 11 | 12 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-button'), 13 | block = _bcc.block; 14 | 15 | var Btn = block('button'); 16 | exports.Btn = Btn; 17 | Btn.displayName = 'Button'; 18 | var _default = { 19 | Btn: Btn 20 | }; 21 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/CRUDTable/Body.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var React = _interopRequireWildcard(require("react")); 11 | 12 | var _helpers = require("./helpers"); 13 | 14 | var _wrappers = require("./wrappers"); 15 | 16 | var _Button = _interopRequireDefault(require("../Button")); 17 | 18 | var _helpers2 = require("../helpers"); 19 | 20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 21 | 22 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 23 | 24 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 25 | 26 | var Body = function Body(props) { 27 | var fields = props.fields, 28 | items = props.items, 29 | onDeleteClick = props.onDeleteClick, 30 | onUpdateClick = props.onUpdateClick, 31 | actionsLabel = props.actionsLabel, 32 | updateTrigger = props.updateTrigger, 33 | deleteTrigger = props.deleteTrigger; 34 | return /*#__PURE__*/React.createElement(_wrappers.Table.Body, null, items.map(function (item) { 35 | return /*#__PURE__*/React.createElement(_wrappers.Table.Row, { 36 | key: item.id 37 | }, fields.map(function (field) { 38 | return /*#__PURE__*/React.createElement(_wrappers.Table.Cell, { 39 | key: field.name 40 | }, /*#__PURE__*/React.createElement(_wrappers.Table.CellLabel, null, field.label), (0, _helpers.getTableFieldValue)(field, item)); 41 | }), (updateTrigger || deleteTrigger) && /*#__PURE__*/React.createElement(_wrappers.Table.Cell, null, /*#__PURE__*/React.createElement(_wrappers.Table.CellLabel, null, actionsLabel), updateTrigger && /*#__PURE__*/React.createElement(_Button["default"], { 42 | modifiers: "primary", 43 | onClick: function onClick() { 44 | onUpdateClick(item); 45 | (0, _helpers.scrollToTop)(); 46 | } 47 | }, updateTrigger), ' ', deleteTrigger && /*#__PURE__*/React.createElement(_Button["default"], { 48 | modifiers: "negative", 49 | onClick: function onClick() { 50 | onDeleteClick(item); 51 | (0, _helpers.scrollToTop)(); 52 | } 53 | }, deleteTrigger))); 54 | })); 55 | }; 56 | 57 | Body.defaultProps = { 58 | fields: [], 59 | items: [], 60 | actionsLabel: '', 61 | onDeleteClick: _helpers2.NO_OP, 62 | onUpdateClick: _helpers2.NO_OP, 63 | updateTrigger: null, 64 | deleteTrigger: null 65 | }; 66 | var _default = Body; 67 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/CRUDTable/Header.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var React = _interopRequireWildcard(require("react")); 11 | 12 | var _wrappers = require("./wrappers"); 13 | 14 | var _helpers = require("./helpers"); 15 | 16 | var _helpers2 = require("../helpers"); 17 | 18 | var _Select = _interopRequireDefault(require("../Select")); 19 | 20 | var _constants = require("./constants"); 21 | 22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 23 | 24 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 25 | 26 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 27 | 28 | var mapFieldsToOptions = function mapFieldsToOptions(fields) { 29 | return fields.map(function (x) { 30 | return { 31 | text: x.label, 32 | value: x.name, 33 | key: x.name 34 | }; 35 | }); 36 | }; 37 | 38 | var sortDirectionsOptions = Object.keys(_constants.SORT_DIRECTIONS).map(function (k) { 39 | return { 40 | text: _constants.SORT_DIRECTIONS[k], 41 | value: _constants.SORT_DIRECTIONS[k], 42 | key: k 43 | }; 44 | }); 45 | 46 | var Header = function Header(props) { 47 | var fields = props.fields, 48 | sort = props.sort, 49 | _onChange = props.onChange, 50 | actionsLabel = props.actionsLabel; 51 | var sortableFields = fields.filter(function (field) { 52 | return field.sortable; 53 | }); 54 | return /*#__PURE__*/React.createElement(_wrappers.Table.Header, null, /*#__PURE__*/React.createElement(_wrappers.Table.Row, { 55 | modifiers: "fields" 56 | }, fields.map(function (field) { 57 | return /*#__PURE__*/React.createElement(_wrappers.Table.HeaderCell, { 58 | key: field.name, 59 | onClick: function onClick() { 60 | if (field.sortable) { 61 | var newDirection = (0, _helpers.toggleDirection)(sort.direction, field.name === sort.field); 62 | 63 | _onChange(field.name, newDirection); 64 | } 65 | } 66 | }, field.label, " ", sort.field === field.name && (0, _helpers.chevron)(sort.direction)); 67 | }), actionsLabel && /*#__PURE__*/React.createElement(_wrappers.Table.HeaderCell, null, actionsLabel)), sortableFields.length > 0 && /*#__PURE__*/React.createElement(_wrappers.Table.Row, { 68 | modifiers: "sorter" 69 | }, /*#__PURE__*/React.createElement(_wrappers.Table.HeaderCell, { 70 | colSpan: fields.length + +!!actionsLabel 71 | }, "Sort by: ", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(_Select["default"], { 72 | placeholder: "Select field", 73 | options: mapFieldsToOptions(sortableFields), 74 | value: sort.field, 75 | onChange: function onChange(evt) { 76 | var value = evt.currentTarget.value; 77 | 78 | if (value) { 79 | _onChange(value, sort.direction); 80 | } 81 | } 82 | }), ' ', /*#__PURE__*/React.createElement(_Select["default"], { 83 | placeholder: "Select direction", 84 | options: sortDirectionsOptions, 85 | value: sort.direction, 86 | onChange: function onChange(evt) { 87 | var value = evt.currentTarget.value; 88 | 89 | if (value) { 90 | _onChange(sort.field, value); 91 | } 92 | } 93 | })))); 94 | }; 95 | 96 | Header.defaultProps = { 97 | fields: [], 98 | onChange: _helpers2.NO_OP, 99 | actionsLabel: '' 100 | }; 101 | var _default = Header; 102 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/CRUDTable/actions.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.removeRule = exports.addRule = exports.changePage = exports.changeSort = void 0; 7 | 8 | function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } 9 | 10 | function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } 11 | 12 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } 13 | 14 | function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } 15 | 16 | function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } 17 | 18 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } 19 | 20 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 21 | 22 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 23 | 24 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 25 | 26 | var changeSort = function changeSort(field, direction) { 27 | return function (state, props) { 28 | var sort = state.sort; 29 | return { 30 | sort: { 31 | field: field, 32 | direction: direction 33 | } 34 | }; 35 | }; 36 | }; 37 | 38 | exports.changeSort = changeSort; 39 | 40 | var changePage = function changePage(activePage) { 41 | return function (state, props) { 42 | return { 43 | pagination: _objectSpread(_objectSpread({}, state.pagination), {}, { 44 | activePage: activePage 45 | }) 46 | }; 47 | }; 48 | }; 49 | 50 | exports.changePage = changePage; 51 | 52 | var addRule = function addRule(rule) { 53 | return function (state, props) { 54 | return { 55 | queryRules: [].concat(_toConsumableArray(state.queryRules), [rule]) 56 | }; 57 | }; 58 | }; 59 | 60 | exports.addRule = addRule; 61 | 62 | var removeRule = function removeRule(rule) { 63 | return function (state, props) { 64 | return { 65 | queryRules: state.queryRules.filter(function (x) { 66 | return x.field !== rule.field || x.condition !== rule.condition; 67 | }) 68 | }; 69 | }; 70 | }; 71 | 72 | exports.removeRule = removeRule; -------------------------------------------------------------------------------- /build/CRUDTable/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.PAGINATION_COMPONENT_TYPE = exports.UPDATE_FORM_COMPONENT_TYPE = exports.DELETE_FORM_COMPONENT_TYPE = exports.CREATE_FORM_COMPONENT_TYPE = exports.FIELD_COMPONENT_TYPE = exports.FIELDS_COMPONENT_TYPE = exports.ID_FIELD = exports.SORT_DIRECTIONS = void 0; 7 | var SORT_DIRECTIONS = { 8 | DESCENDING: 'descending', 9 | ASCENDING: 'ascending' 10 | }; 11 | exports.SORT_DIRECTIONS = SORT_DIRECTIONS; 12 | var ID_FIELD = 'id'; 13 | exports.ID_FIELD = ID_FIELD; 14 | var FIELDS_COMPONENT_TYPE = 'CRUDTable_Fields'; 15 | exports.FIELDS_COMPONENT_TYPE = FIELDS_COMPONENT_TYPE; 16 | var FIELD_COMPONENT_TYPE = 'CRUDTable_Field'; 17 | exports.FIELD_COMPONENT_TYPE = FIELD_COMPONENT_TYPE; 18 | var CREATE_FORM_COMPONENT_TYPE = 'CRUDTable_CreateForm'; 19 | exports.CREATE_FORM_COMPONENT_TYPE = CREATE_FORM_COMPONENT_TYPE; 20 | var DELETE_FORM_COMPONENT_TYPE = 'CRUDTable_DeleteForm'; 21 | exports.DELETE_FORM_COMPONENT_TYPE = DELETE_FORM_COMPONENT_TYPE; 22 | var UPDATE_FORM_COMPONENT_TYPE = 'CRUDTable_UpdateForm'; 23 | exports.UPDATE_FORM_COMPONENT_TYPE = UPDATE_FORM_COMPONENT_TYPE; 24 | var PAGINATION_COMPONENT_TYPE = 'CRUDTable_Pagination'; 25 | exports.PAGINATION_COMPONENT_TYPE = PAGINATION_COMPONENT_TYPE; 26 | var _default = { 27 | SORT_DIRECTIONS: SORT_DIRECTIONS, 28 | ID_FIELD: ID_FIELD, 29 | FIELDS_COMPONENT_TYPE: FIELDS_COMPONENT_TYPE, 30 | FIELD_COMPONENT_TYPE: FIELD_COMPONENT_TYPE, 31 | CREATE_FORM_COMPONENT_TYPE: CREATE_FORM_COMPONENT_TYPE, 32 | DELETE_FORM_COMPONENT_TYPE: DELETE_FORM_COMPONENT_TYPE, 33 | UPDATE_FORM_COMPONENT_TYPE: UPDATE_FORM_COMPONENT_TYPE, 34 | PAGINATION_COMPONENT_TYPE: PAGINATION_COMPONENT_TYPE 35 | }; 36 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/CRUDTable/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.scrollToTop = exports.getDefaultState = exports.getPaginationProps = exports.getTableFieldValue = exports.extractForms = exports.extractQueryFields = exports.extractPagination = exports.extractFields = exports.getProps = exports.FILTER_BY_TYPE = exports.queryValue = exports.toggleDirection = exports.chevron = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _constants = require("./constants"); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 13 | 14 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 15 | 16 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 17 | 18 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 19 | 20 | var UpArrow = function UpArrow() { 21 | return /*#__PURE__*/_react["default"].createElement("span", null, "\u25B2"); 22 | }; 23 | 24 | var DownArrow = function DownArrow() { 25 | return /*#__PURE__*/_react["default"].createElement("span", null, "\u25BC"); 26 | }; 27 | 28 | var chevron = function chevron(direction) { 29 | if (direction === _constants.SORT_DIRECTIONS.ASCENDING) { 30 | return /*#__PURE__*/_react["default"].createElement(UpArrow, null); 31 | } 32 | 33 | return /*#__PURE__*/_react["default"].createElement(DownArrow, null); 34 | }; 35 | 36 | exports.chevron = chevron; 37 | 38 | var toggleDirection = function toggleDirection(direction, toggle) { 39 | if (toggle) { 40 | switch (direction) { 41 | case 'ascending': 42 | return 'descending'; 43 | 44 | default: 45 | return 'ascending'; 46 | } 47 | } 48 | 49 | return direction; 50 | }; 51 | 52 | exports.toggleDirection = toggleDirection; 53 | 54 | var queryValue = function queryValue(source) { 55 | var query = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; 56 | var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; 57 | var value = query.split('.').reduce(function (result, key) { 58 | return result && result[key] ? result[key] : null; 59 | }, source); 60 | return value || defaultValue; 61 | }; 62 | 63 | exports.queryValue = queryValue; 64 | 65 | var FILTER_BY_TYPE = function FILTER_BY_TYPE(t) { 66 | return function (item) { 67 | return item.type && item.type.displayName === t; 68 | }; 69 | }; 70 | 71 | exports.FILTER_BY_TYPE = FILTER_BY_TYPE; 72 | 73 | var getProps = function getProps(comp) { 74 | var fields = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; 75 | var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; 76 | var props = comp ? comp.props : null; 77 | if (!props) return defaultValue; 78 | return _objectSpread(_objectSpread({}, props), {}, { 79 | fields: fields 80 | }); 81 | }; 82 | 83 | exports.getProps = getProps; 84 | 85 | var extractFields = function extractFields(items) { 86 | var container = items.find(FILTER_BY_TYPE(_constants.FIELDS_COMPONENT_TYPE)); 87 | var children = container ? _react["default"].Children.toArray(container.props.children) : []; 88 | return children.filter(FILTER_BY_TYPE(_constants.FIELD_COMPONENT_TYPE)).map(function (c) { 89 | return c.props; 90 | }); 91 | }; 92 | 93 | exports.extractFields = extractFields; 94 | 95 | var extractPagination = function extractPagination(items) { 96 | var container = items.find(FILTER_BY_TYPE(_constants.PAGINATION_COMPONENT_TYPE)); 97 | return getProps(container, [], {}); 98 | }; 99 | 100 | exports.extractPagination = extractPagination; 101 | 102 | var extractQueryFields = function extractQueryFields(items) { 103 | var fields = extractFields(items); 104 | return fields.filter(function (f) { 105 | return f.queryable; 106 | }).map(function (f) { 107 | return _objectSpread(_objectSpread({}, f), {}, { 108 | value: f.name 109 | }); 110 | }); 111 | }; 112 | 113 | exports.extractQueryFields = extractQueryFields; 114 | 115 | var extractForms = function extractForms(items, fields) { 116 | return { 117 | create: getProps(items.find(FILTER_BY_TYPE(_constants.CREATE_FORM_COMPONENT_TYPE)), fields.filter(function (f) { 118 | return !f.hideInCreateForm; 119 | })), 120 | update: getProps(items.find(FILTER_BY_TYPE(_constants.UPDATE_FORM_COMPONENT_TYPE)), fields.filter(function (f) { 121 | return !f.hideInUpdateForm; 122 | })), 123 | "delete": getProps(items.find(FILTER_BY_TYPE(_constants.DELETE_FORM_COMPONENT_TYPE))) 124 | }; 125 | }; 126 | 127 | exports.extractForms = extractForms; 128 | 129 | var getTableFieldValue = function getTableFieldValue(field, item) { 130 | if (typeof field.tableValueResolver === 'string') { 131 | return queryValue(item, field.tableValueResolver); 132 | } 133 | 134 | if (typeof field.tableValueResolver === 'function') { 135 | return field.tableValueResolver(item); 136 | } 137 | 138 | return item[field.name]; 139 | }; 140 | 141 | exports.getTableFieldValue = getTableFieldValue; 142 | 143 | var getPaginationProps = function getPaginationProps(props) { 144 | var items = _react["default"].Children.toArray(props.children); 145 | 146 | return extractPagination(items); 147 | }; 148 | 149 | exports.getPaginationProps = getPaginationProps; 150 | 151 | var getDefaultState = function getDefaultState(items, pagination) { 152 | return { 153 | items: items, 154 | sort: { 155 | field: _constants.ID_FIELD, 156 | direction: _constants.SORT_DIRECTIONS.DESCENDING 157 | }, 158 | queryRules: [], 159 | updateItem: {}, 160 | deleteItem: {}, 161 | createModalVisible: false, 162 | deleteModalVisible: false, 163 | updateModalVisible: false, 164 | pagination: _objectSpread(_objectSpread({}, pagination), {}, { 165 | activePage: pagination.activePage || pagination.defaultActivePage || 1, 166 | totalOfItems: pagination.totalOfItems || 0, 167 | itemsPerPage: pagination.itemsPerPage || 10 168 | }), 169 | totalOfItems: pagination.totalOfItems || 0 170 | }; 171 | }; 172 | 173 | exports.getDefaultState = getDefaultState; 174 | 175 | var scrollToTop = function scrollToTop() { 176 | if (typeof window !== 'undefined' && window.scrollTo) { 177 | window.scrollTo({ 178 | top: 0, 179 | behavior: 'smooth' 180 | }); 181 | } 182 | }; 183 | 184 | exports.scrollToTop = scrollToTop; 185 | var _default = { 186 | chevron: chevron, 187 | toggleDirection: toggleDirection, 188 | queryValue: queryValue, 189 | getTableFieldValue: getTableFieldValue, 190 | FILTER_BY_TYPE: FILTER_BY_TYPE, 191 | extractFields: extractFields, 192 | getProps: getProps, 193 | extractForms: extractForms, 194 | extractPagination: extractPagination, 195 | extractQueryFields: extractQueryFields, 196 | getPaginationProps: getPaginationProps 197 | }; 198 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/CRUDTable/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.Table = void 0; 7 | 8 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 11 | 12 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-table'), 13 | block = _bcc.block, 14 | element = _bcc.element; 15 | 16 | var Table = block('table'); 17 | exports.Table = Table; 18 | Table.displayName = 'Table'; 19 | Table.Row = element('tr', 'row'); 20 | Table.Row.displayName = 'Row'; 21 | Table.HeaderCell = element('th', 'header-cell'); 22 | Table.HeaderCell.displayName = 'HeaderCell'; 23 | Table.Header = element('thead', 'header'); 24 | Table.Header.displayName = 'Header'; 25 | Table.Body = element('tbody', 'body'); 26 | Table.Body.displayName = 'Body'; 27 | Table.Cell = element('td', 'cell'); 28 | Table.Cell.displayName = 'Cell'; 29 | Table.CellLabel = element('div', 'cell-label'); 30 | Table.CellLabel.displayName = 'CellLabel'; 31 | Table.Caption = element('div', 'caption'); 32 | Table.Caption.displayName = 'Caption'; 33 | var _default = { 34 | Table: Table 35 | }; 36 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Form/Base.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _formik = require("formik"); 11 | 12 | var _wrappers = require("./wrappers"); 13 | 14 | var _Button = _interopRequireDefault(require("../Button")); 15 | 16 | var _helpers = require("./helpers"); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 19 | 20 | function _extends() { _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; }; return _extends.apply(this, arguments); } 21 | 22 | var FormBase = function FormBase(_ref) { 23 | var data = _ref.data, 24 | errors = _ref.errors, 25 | touched = _ref.touched, 26 | error = _ref.error; 27 | return /*#__PURE__*/_react["default"].createElement(_wrappers.Form, null, data.message && /*#__PURE__*/_react["default"].createElement(_wrappers.Form.Message, null, data.message), error && /*#__PURE__*/_react["default"].createElement(_wrappers.Form.ErrorMessage, null, error), (0, _helpers.generalValidationError)({ 28 | touched: touched, 29 | errors: errors, 30 | message: data.generalErrorMessage 31 | }), data.fields.map(function (field) { 32 | return /*#__PURE__*/_react["default"].createElement(_wrappers.Form.FieldContainer, { 33 | key: field.name 34 | }, /*#__PURE__*/_react["default"].createElement(_wrappers.Form.Label, { 35 | htmlFor: field.name 36 | }, field.label), /*#__PURE__*/_react["default"].createElement(_formik.Field, { 37 | name: field.name, 38 | placeholder: field.placeholder, 39 | render: field.render, 40 | type: field.type, 41 | readOnly: field.readOnly 42 | }), errors[field.name] && touched[field.name] && /*#__PURE__*/_react["default"].createElement(_wrappers.Form.FieldError, null, errors[field.name])); 43 | }), (0, _helpers.generalValidationError)({ 44 | touched: touched, 45 | errors: errors, 46 | message: data.generalErrorMessage 47 | }), /*#__PURE__*/_react["default"].createElement(_Button["default"], _extends({ 48 | type: "submit", 49 | modifiers: "positive" 50 | }, data.submitButtonProps), data.submitText)); 51 | }; 52 | 53 | var _default = FormBase; 54 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Form/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.generalValidationError = exports.DEFAULT_VALIDATE = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _helpers = require("../CRUDTable/helpers"); 11 | 12 | var _wrappers = require("./wrappers"); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 15 | 16 | var DEFAULT_VALIDATE = function DEFAULT_VALIDATE() { 17 | return {}; 18 | }; 19 | 20 | exports.DEFAULT_VALIDATE = DEFAULT_VALIDATE; 21 | 22 | var generalValidationError = function generalValidationError(payload) { 23 | var showErrorMessage = Object.keys(payload.errors).reduce(function (acc, key) { 24 | return acc || payload.touched[key]; 25 | }, false); 26 | return showErrorMessage && /*#__PURE__*/_react["default"].createElement(_wrappers.Form.ErrorMessage, null, (0, _helpers.queryValue)(payload, 'message', 'There are some errors')); 27 | }; 28 | 29 | exports.generalValidationError = generalValidationError; -------------------------------------------------------------------------------- /build/Form/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _formik = require("formik"); 11 | 12 | var _wrappers = require("./wrappers"); 13 | 14 | var _Button = _interopRequireDefault(require("../Button")); 15 | 16 | var _helpers = require("./helpers"); 17 | 18 | var _Base = _interopRequireDefault(require("./Base")); 19 | 20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 21 | 22 | var BasicForm = function BasicForm(props) { 23 | var data = props.data, 24 | onSubmit = props.onSubmit, 25 | initialValues = props.initialValues; 26 | return /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_formik.Formik, { 27 | enableReinitialize: true, 28 | initialValues: initialValues, 29 | validate: data.validate || _helpers.DEFAULT_VALIDATE, 30 | onSubmit: onSubmit, 31 | render: function render(_ref) { 32 | var errors = _ref.errors, 33 | touched = _ref.touched, 34 | error = _ref.error; 35 | return /*#__PURE__*/_react["default"].createElement(_Base["default"], { 36 | data: data, 37 | errors: errors || {}, 38 | touched: touched || {}, 39 | error: error 40 | }); 41 | } 42 | })); 43 | }; 44 | 45 | BasicForm.defaultProps = { 46 | initialValues: {}, 47 | data: { 48 | message: null, 49 | fields: [], 50 | submitText: null 51 | } 52 | }; 53 | var _default = BasicForm; 54 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Form/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.Form = void 0; 7 | 8 | var _formik = require("formik"); 9 | 10 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 13 | 14 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-modal-form'), 15 | block = _bcc.block, 16 | element = _bcc.element; 17 | 18 | var Form = block(_formik.Form); 19 | exports.Form = Form; 20 | Form.displayName = 'FormikForm'; 21 | Form.Label = element('label', 'label'); 22 | Form.Label.displayName = 'Label'; 23 | Form.Message = element('div', 'message'); 24 | Form.Message.displayName = 'Message'; 25 | Form.ErrorMessage = element('div', 'error-message'); 26 | Form.ErrorMessage.displayName = 'ErrorMessage'; 27 | Form.FieldError = element('div', 'field-error'); 28 | Form.FieldError.displayName = 'FieldError'; 29 | Form.FieldContainer = element('div', 'field-container'); 30 | Form.FieldContainer.displayName = 'FieldContainer'; 31 | var _default = { 32 | Form: Form 33 | }; 34 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/FormModal/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.onSubmitHandler = void 0; 7 | 8 | var _helpers = require("../CRUDTable/helpers"); 9 | 10 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 11 | 12 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 13 | 14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 15 | 16 | var onSubmitHandler = function onSubmitHandler(onSubmit, shouldReset, callback) { 17 | return function (values, _ref) { 18 | var setError = _ref.setError, 19 | resetForm = _ref.resetForm, 20 | setSubmitting = _ref.setSubmitting; 21 | var reset = Object.keys(values).reduce(function (result, prop) { 22 | return _objectSpread(_objectSpread({}, result), {}, _defineProperty({}, prop, '')); 23 | }, {}); 24 | var result = onSubmit(values); 25 | return result.then(function () { 26 | if (shouldReset) { 27 | resetForm(reset); 28 | } 29 | 30 | setSubmitting(false); 31 | callback(); 32 | })["catch"](function (err) { 33 | setError((0, _helpers.queryValue)(err, 'message', 'Unexpected error')); 34 | setSubmitting(false); 35 | }); 36 | }; 37 | }; 38 | 39 | exports.onSubmitHandler = onSubmitHandler; -------------------------------------------------------------------------------- /build/FormModal/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var React = _interopRequireWildcard(require("react")); 11 | 12 | var _Modal = _interopRequireDefault(require("../Modal")); 13 | 14 | var _Form = _interopRequireDefault(require("../Form")); 15 | 16 | var _helpers = require("../helpers"); 17 | 18 | var _helpers2 = require("./helpers"); 19 | 20 | var _helpers3 = require("../CRUDTable/helpers"); 21 | 22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 23 | 24 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 25 | 26 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 27 | 28 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 29 | 30 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 31 | 32 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 33 | 34 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 35 | 36 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 37 | 38 | function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 39 | 40 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 41 | 42 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 43 | 44 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 45 | 46 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 47 | 48 | var FormModal = /*#__PURE__*/function (_React$Component) { 49 | _inherits(FormModal, _React$Component); 50 | 51 | var _super = _createSuper(FormModal); 52 | 53 | function FormModal(props) { 54 | var _this; 55 | 56 | _classCallCheck(this, FormModal); 57 | 58 | _this = _super.call(this, props); 59 | _this.state = { 60 | key: 0 61 | }; 62 | return _this; 63 | } 64 | 65 | _createClass(FormModal, [{ 66 | key: "render", 67 | value: function render() { 68 | var _this2 = this; 69 | 70 | var _this$props = this.props, 71 | data = _this$props.data, 72 | trigger = _this$props.trigger, 73 | initialValues = _this$props.initialValues, 74 | shouldReset = _this$props.shouldReset, 75 | onSubmit = _this$props.onSubmit, 76 | visible = _this$props.visible, 77 | onVisibilityChange = _this$props.onVisibilityChange; 78 | var key = this.state.key; 79 | return /*#__PURE__*/React.createElement(_Modal["default"], { 80 | trigger: trigger, 81 | title: data.title, 82 | visible: visible, 83 | onShow: function onShow() { 84 | (0, _helpers3.scrollToTop)(); 85 | onVisibilityChange(true); 86 | 87 | _this2.setState({ 88 | key: new Date().getTime() 89 | }); 90 | }, 91 | onHide: function onHide() { 92 | onVisibilityChange(false); 93 | } 94 | }, /*#__PURE__*/React.createElement(_Form["default"], { 95 | key: key, 96 | data: data, 97 | initialValues: initialValues, 98 | onSubmit: (0, _helpers2.onSubmitHandler)(onSubmit, shouldReset, function () { 99 | return onVisibilityChange(false); 100 | }) 101 | })); 102 | } 103 | }]); 104 | 105 | return FormModal; 106 | }(React.Component); // $FlowFixMe 107 | 108 | 109 | FormModal.defaultProps = { 110 | onVisibilityChange: _helpers.NO_OP, 111 | onSubmit: _helpers.NO_OP, 112 | shouldReset: false, 113 | trigger: null, 114 | initialValues: null, 115 | visible: false 116 | }; 117 | var _default = FormModal; 118 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Label/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var React = _interopRequireWildcard(require("react")); 11 | 12 | var _wrappers = _interopRequireDefault(require("./wrappers")); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 15 | 16 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 17 | 18 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 19 | 20 | var Label = function Label(props) { 21 | var children = props.children; 22 | return /*#__PURE__*/React.createElement(_wrappers["default"], null, children); 23 | }; 24 | 25 | var _default = Label; 26 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Label/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 11 | 12 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-label'), 13 | block = _bcc.block; 14 | 15 | var Label = block('div'); 16 | Label.displayName = 'Label'; 17 | var _default = Label; 18 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Modal/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var React = _interopRequireWildcard(require("react")); 11 | 12 | var _wrappers = require("./wrappers"); 13 | 14 | var _Button = _interopRequireDefault(require("../Button")); 15 | 16 | var _helpers = require("../helpers"); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 19 | 20 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 21 | 22 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 23 | 24 | var getDisplay = function getDisplay(visible) { 25 | return visible ? 'block' : 'none'; 26 | }; 27 | 28 | var Modal = function Modal(props) { 29 | var children = props.children, 30 | trigger = props.trigger, 31 | title = props.title, 32 | visible = props.visible, 33 | onHide = props.onHide, 34 | onShow = props.onShow; 35 | var style = { 36 | display: getDisplay(visible) 37 | }; 38 | return /*#__PURE__*/React.createElement("div", null, trigger && /*#__PURE__*/React.createElement(_Button["default"], { 39 | modifiers: "positive,modal-trigger", 40 | onClick: onShow 41 | }, trigger), /*#__PURE__*/React.createElement(_wrappers.Container, { 42 | style: style 43 | }, /*#__PURE__*/React.createElement(_wrappers.Container.BG, { 44 | onClick: onHide 45 | }), /*#__PURE__*/React.createElement(_wrappers.Container.Modal, null, /*#__PURE__*/React.createElement(_Button["default"], { 46 | modifiers: "circular,close", 47 | onClick: onHide 48 | }, "X"), title && /*#__PURE__*/React.createElement(_wrappers.Container.Title, null, title), children))); 49 | }; 50 | 51 | Modal.defaultProps = { 52 | onHide: _helpers.NO_OP, 53 | onShow: _helpers.NO_OP, 54 | title: '', 55 | children: null, 56 | trigger: null, 57 | visible: false 58 | }; 59 | var _default = Modal; 60 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Modal/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.Container = void 0; 7 | 8 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 11 | 12 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-modal-wrapper'), 13 | block = _bcc.block, 14 | element = _bcc.element; 15 | 16 | var Container = block('div'); 17 | exports.Container = Container; 18 | Container.displayName = 'Wrapper'; 19 | Container.BG = element('div', 'background'); 20 | Container.BG.displayName = 'Background'; 21 | Container.Modal = element('div', 'modal'); 22 | Container.Modal.displayName = 'Modal'; 23 | Container.Title = element('h3', 'title'); 24 | Container.Title.displayName = 'Title'; 25 | var _default = { 26 | Container: Container 27 | }; 28 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Pagination/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var _react = _interopRequireWildcard(require("react")); 11 | 12 | var _wrappers = require("./wrappers"); 13 | 14 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 15 | 16 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 17 | 18 | function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } 19 | 20 | function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } 21 | 22 | function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } 23 | 24 | function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } 25 | 26 | function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } 27 | 28 | function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } 29 | 30 | var linkModifier = function linkModifier(active) { 31 | return active ? 'active' : 'inactive'; 32 | }; 33 | 34 | var Pagination = function Pagination(props) { 35 | var activePage = props.activePage, 36 | totalOfItems = props.totalOfItems, 37 | itemsPerPage = props.itemsPerPage, 38 | onPageChange = props.onPageChange; 39 | var numberOfPages = Math.ceil(totalOfItems / itemsPerPage) || 1; 40 | 41 | var pageNumbers = _toConsumableArray(Array(numberOfPages).keys()); 42 | 43 | var canIncreasePage = activePage < numberOfPages; 44 | var canDecreasePage = activePage > 1; 45 | return /*#__PURE__*/_react["default"].createElement(_wrappers.Pagination, null, canDecreasePage && /*#__PURE__*/_react["default"].createElement(_wrappers.Pagination.Prev, { 46 | onClick: function onClick() { 47 | onPageChange(activePage - 1); 48 | } 49 | }, "\xAB"), pageNumbers.map(function (i) { 50 | var page = i + 1; 51 | return /*#__PURE__*/_react["default"].createElement(_wrappers.Pagination.Link, { 52 | key: page, 53 | modifiers: linkModifier(page === activePage), 54 | onClick: function onClick() { 55 | onPageChange(page); 56 | } 57 | }, page); 58 | }), canIncreasePage && /*#__PURE__*/_react["default"].createElement(_wrappers.Pagination.Next, { 59 | onClick: function onClick() { 60 | onPageChange(activePage + 1); 61 | } 62 | }, "\xBB")); 63 | }; 64 | 65 | var _default = Pagination; 66 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Pagination/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.Pagination = void 0; 7 | 8 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 11 | 12 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-table-pagination'), 13 | block = _bcc.block, 14 | element = _bcc.element; 15 | 16 | var Pagination = block('div'); 17 | exports.Pagination = Pagination; 18 | Pagination.displayName = 'Pagination'; 19 | Pagination.Link = element('button', 'link'); 20 | Pagination.Link.displayName = 'PaginationLink'; 21 | Pagination.Prev = element('button', 'previous'); 22 | Pagination.Prev.displayName = 'PaginationPrev'; 23 | Pagination.Next = element('button', 'next'); 24 | Pagination.Next.displayName = 'PaginationNext'; 25 | var _default = { 26 | Pagination: Pagination 27 | }; 28 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/RuleBuilder.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _Button = _interopRequireDefault(require("../Button")); 13 | 14 | var _Select = _interopRequireDefault(require("../Select")); 15 | 16 | var _helpers = require("../CRUDTable/helpers"); 17 | 18 | var _helpers2 = require("./helpers"); 19 | 20 | var _constants = require("./constants"); 21 | 22 | var _wrappers = require("./wrappers"); 23 | 24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 25 | 26 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 27 | 28 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 29 | 30 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 31 | 32 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 33 | 34 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 35 | 36 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 37 | 38 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 39 | 40 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 41 | 42 | function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 43 | 44 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 45 | 46 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 47 | 48 | function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } 49 | 50 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 51 | 52 | var RuleBuilder = /*#__PURE__*/function (_React$Component) { 53 | _inherits(RuleBuilder, _React$Component); 54 | 55 | var _super = _createSuper(RuleBuilder); 56 | 57 | function RuleBuilder(props) { 58 | var _this; 59 | 60 | _classCallCheck(this, RuleBuilder); 61 | 62 | _this = _super.call(this, props); 63 | _this.state = _constants.DEFAULT_STATE; // $FlowFixMe 64 | 65 | _this.handleFieldSelectChange = _this.handleFieldSelectChange.bind(_assertThisInitialized(_this)); // $FlowFixMe 66 | 67 | _this.save = _this.save.bind(_assertThisInitialized(_this)); 68 | return _this; 69 | } 70 | 71 | _createClass(RuleBuilder, [{ 72 | key: "handleFieldSelectChange", 73 | value: function handleFieldSelectChange(evt) { 74 | var value = evt.currentTarget.value; 75 | 76 | var update = _objectSpread(_objectSpread({}, this.state), {}, { 77 | field: value, 78 | type: this.getType(value), 79 | label: this.getLabel(value), 80 | collection: this.getCollection(value) 81 | }); 82 | 83 | update.condition = this.getDefaultCondition(value); 84 | 85 | if ((0, _helpers2.isBoolean)(update.type)) { 86 | update.condition = _constants.CONDITIONS.IS; 87 | update.value = false; 88 | } 89 | 90 | this.setState(update); 91 | } 92 | }, { 93 | key: "getLabel", 94 | value: function getLabel(field) { 95 | return (0, _helpers.queryValue)(this.find(field), 'label', ''); 96 | } 97 | }, { 98 | key: "getDefaultCondition", 99 | value: function getDefaultCondition(field) { 100 | var defaultconditionForType = (0, _helpers2.getDefaultConditionForType)(this.getType(field)); 101 | return (0, _helpers.queryValue)(this.find(field), 'defaultCondition', defaultconditionForType); 102 | } 103 | }, { 104 | key: "getCollection", 105 | value: function getCollection(field) { 106 | return (0, _helpers.queryValue)(this.find(field), 'collection', ''); 107 | } 108 | }, { 109 | key: "getType", 110 | value: function getType(field) { 111 | return (0, _helpers.queryValue)(this.find(field), 'type', ''); 112 | } 113 | }, { 114 | key: "find", 115 | value: function find(field) { 116 | var fields = this.props.fields; 117 | return fields.find(function (f) { 118 | return f.value === field; 119 | }); 120 | } 121 | }, { 122 | key: "save", 123 | value: function save() { 124 | var onSave = this.props.onSave; 125 | 126 | if ((0, _helpers2.isRuleComplete)(this.state)) { 127 | onSave(this.state); 128 | this.setState(_constants.DEFAULT_STATE); 129 | } 130 | } 131 | }, { 132 | key: "render", 133 | value: function render() { 134 | var _this2 = this; 135 | 136 | var _this$props = this.props, 137 | fields = _this$props.fields, 138 | conditionsSelectPlaceholder = _this$props.conditionsSelectPlaceholder, 139 | fieldsSelectPlaceholder = _this$props.fieldsSelectPlaceholder; 140 | var _this$state = this.state, 141 | field = _this$state.field, 142 | value = _this$state.value, 143 | condition = _this$state.condition; 144 | var type = this.getType(field); 145 | var input = (0, _helpers2.inputForType)(type, { 146 | value: value, 147 | onChange: function onChange(evt) { 148 | _this2.setState({ 149 | value: evt.currentTarget.value 150 | }); 151 | } 152 | }); 153 | return /*#__PURE__*/_react["default"].createElement(_wrappers.RuleBuilder, null, /*#__PURE__*/_react["default"].createElement(_Select["default"], { 154 | placeholder: fieldsSelectPlaceholder, 155 | options: (0, _helpers2.mapFieldsToOptions)(fields), 156 | value: field, 157 | onChange: this.handleFieldSelectChange 158 | }), "\xA0\xA0", !(0, _helpers2.isBoolean)(type) && /*#__PURE__*/_react["default"].createElement("span", null, /*#__PURE__*/_react["default"].createElement(_Select["default"], { 159 | placeholder: conditionsSelectPlaceholder, 160 | options: (0, _helpers2.conditionsForType)(type), 161 | value: condition, 162 | onChange: function onChange(evt, data) { 163 | _this2.setState({ 164 | condition: evt.currentTarget.value 165 | }); 166 | } 167 | }), "\xA0\xA0"), input, "\xA0\xA0", /*#__PURE__*/_react["default"].createElement(_Button["default"], { 168 | modifiers: "positive,add", 169 | onClick: this.save 170 | }, "+")); 171 | } 172 | }]); 173 | 174 | return RuleBuilder; 175 | }(_react["default"].Component); 176 | 177 | var _default = RuleBuilder; 178 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/Rules.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _helpers = require("./helpers"); 11 | 12 | var _Button = _interopRequireDefault(require("../Button")); 13 | 14 | var _helpers2 = require("../helpers"); 15 | 16 | var _wrappers = require("./wrappers"); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 19 | 20 | var Rules = function Rules(props) { 21 | var queryRules = props.queryRules, 22 | onRuleRemoved = props.onRuleRemoved, 23 | renderRule = props.renderRule; 24 | return /*#__PURE__*/_react["default"].createElement(_wrappers.SearchRules, null, queryRules.map(function (rule) { 25 | return /*#__PURE__*/_react["default"].createElement("div", { 26 | key: "".concat(rule.field, ":").concat(rule.condition) 27 | }, renderRule(rule), ' ', /*#__PURE__*/_react["default"].createElement(_Button["default"], { 28 | onClick: function onClick() { 29 | onRuleRemoved(rule); 30 | }, 31 | modifiers: "negative,circular" 32 | }, "X")); 33 | })); 34 | }; 35 | 36 | Rules.defaultProps = { 37 | renderRule: _helpers.defaultRuleRender, 38 | queryRules: [], 39 | onRuleRemoved: _helpers2.NO_OP 40 | }; 41 | var _default = Rules; 42 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/Select.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var _react = _interopRequireWildcard(require("react")); 11 | 12 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 13 | 14 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 15 | 16 | var Select = function Select(props) { 17 | var placeholder = props.placeholder, 18 | options = props.options, 19 | value = props.value, 20 | onChange = props.onChange; 21 | return /*#__PURE__*/_react["default"].createElement("select", { 22 | onChange: onChange, 23 | value: value 24 | }, /*#__PURE__*/_react["default"].createElement("option", { 25 | value: "" 26 | }, placeholder), options.map(function (option) { 27 | return /*#__PURE__*/_react["default"].createElement("option", { 28 | key: option.key, 29 | value: option.value 30 | }, option.text); 31 | })); 32 | }; 33 | 34 | var _default = Select; 35 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.DEFAULT_STATE = exports.CONDITIONS = exports.CONDITIONS_LABEL = void 0; 7 | var CONDITIONS_LABEL = { 8 | EQUALS_TO: 'Equals to', 9 | BEGINS_WITH: 'Begins with', 10 | ENDS_WITH: 'Ends with', 11 | CONTAINS: 'Contains', 12 | LESS_THAN: 'Less than', 13 | GREATER_THAN: 'Greater than', 14 | LESS_OR_EQUALS_THAN: 'Less or equals than', 15 | GREATER_OR_EQUALS_THAN: 'Greater or equals than', 16 | IS: 'Is', 17 | IS_NOT: 'Is not', 18 | IS_NOT_EQUALS_TO: 'Is not equals to', 19 | DOES_NOT_BEGIN_WITH: ' Does not begin with', 20 | DOES_NOT_END_WITH: ' Does not end with', 21 | DOES_NOT_CONTAIN: ' Does not contain', 22 | IS_NOT_LESS_THAN: 'Is not less than', 23 | IS_NOT_GREATER_THAN: 'Is not greater than', 24 | IS_NOT_LESS_OR_EQUALS_THAN: 'Is not less or equals than', 25 | IS_NOT_GREATER_OR_EQUALS_THAN: 'Is not greater or equals than' 26 | }; 27 | exports.CONDITIONS_LABEL = CONDITIONS_LABEL; 28 | var CONDITIONS = { 29 | EQUALS_TO: 'EQUALS_TO', 30 | BEGINS_WITH: 'BEGINS_WITH', 31 | ENDS_WITH: 'ENDS_WITH', 32 | CONTAINS: 'CONTAINS', 33 | LESS_THAN: 'LESS_THAN', 34 | GREATER_THAN: 'GREATER_THAN', 35 | LESS_OR_EQUALS_THAN: 'LESS_OR_EQUALS_THAN', 36 | GREATER_OR_EQUALS_THAN: 'GREATER_OR_EQUALS_THAN', 37 | IS: 'IS', 38 | IS_NOT: 'IS_NOT', 39 | IS_NOT_EQUALS_TO: 'IS_NOT_EQUALS_TO', 40 | DOES_NOT_BEGIN_WITH: 'DOES_NOT_BEGIN_WITH', 41 | DOES_NOT_END_WITH: 'DOES_NOT_END_WITH', 42 | DOES_NOT_CONTAIN: 'DOES_NOT_CONTAIN', 43 | IS_NOT_LESS_THAN: 'IS_NOT_LESS_THAN', 44 | IS_NOT_GREATER_THAN: 'IS_NOT_GREATER_THAN', 45 | IS_NOT_LESS_OR_EQUALS_THAN: 'IS_NOT_LESS_OR_EQUALS_THAN', 46 | IS_NOT_GREATER_OR_EQUALS_THAN: 'IS_NOT_GREATER_OR_EQUALS_THAN' 47 | }; 48 | exports.CONDITIONS = CONDITIONS; 49 | var DEFAULT_STATE = { 50 | field: '', 51 | value: '', 52 | type: '', 53 | condition: '', 54 | collection: '' 55 | }; 56 | exports.DEFAULT_STATE = DEFAULT_STATE; 57 | var _default = { 58 | CONDITIONS_LABEL: CONDITIONS_LABEL, 59 | CONDITIONS: CONDITIONS, 60 | DEFAULT_STATE: DEFAULT_STATE 61 | }; 62 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.inputForType = exports.getDefaultConditionForType = exports.conditionsForType = exports.defaultRuleRender = exports.mapFieldsToOptions = exports.isBoolean = exports.isRuleComplete = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _reactDatetime = _interopRequireDefault(require("react-datetime")); 11 | 12 | var _helpers = require("../helpers"); 13 | 14 | var _Label = _interopRequireDefault(require("../Label")); 15 | 16 | var _constants = require("./constants"); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 19 | 20 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 21 | 22 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 23 | 24 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 25 | 26 | function _extends() { _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; }; return _extends.apply(this, arguments); } 27 | 28 | var styles = { 29 | label: { 30 | marginBottom: '5px' 31 | } 32 | }; 33 | 34 | var Input = function Input(props) { 35 | return /*#__PURE__*/_react["default"].createElement("input", props); 36 | }; 37 | 38 | var isRuleComplete = function isRuleComplete(rule) { 39 | var condition = rule.condition, 40 | value = rule.value, 41 | field = rule.field; 42 | return condition !== '' && value !== '' && field !== ''; 43 | }; 44 | 45 | exports.isRuleComplete = isRuleComplete; 46 | 47 | var isBoolean = function isBoolean(type) { 48 | return type === 'boolean'; 49 | }; 50 | 51 | exports.isBoolean = isBoolean; 52 | 53 | var mapFieldsToOptions = function mapFieldsToOptions(fields) { 54 | return fields.map(function (x) { 55 | return { 56 | text: x.label, 57 | value: x.value, 58 | key: x.value 59 | }; 60 | }); 61 | }; 62 | 63 | exports.mapFieldsToOptions = mapFieldsToOptions; 64 | 65 | var defaultRuleRender = function defaultRuleRender(rule) { 66 | if (isBoolean(rule.type)) { 67 | return /*#__PURE__*/_react["default"].createElement("span", null, /*#__PURE__*/_react["default"].createElement(_Label["default"], { 68 | style: styles.label 69 | }, rule.condition), "\xA0", /*#__PURE__*/_react["default"].createElement(_Label["default"], { 70 | style: styles.label 71 | }, rule.label)); 72 | } 73 | 74 | return /*#__PURE__*/_react["default"].createElement("span", null, /*#__PURE__*/_react["default"].createElement(_Label["default"], { 75 | style: styles.label 76 | }, rule.label), "\xA0", /*#__PURE__*/_react["default"].createElement(_Label["default"], { 77 | style: styles.label 78 | }, _constants.CONDITIONS_LABEL[rule.condition]), "\xA0", /*#__PURE__*/_react["default"].createElement(_Label["default"], { 79 | style: styles.label 80 | }, rule.value)); 81 | }; 82 | 83 | exports.defaultRuleRender = defaultRuleRender; 84 | 85 | var conditionsForType = function conditionsForType(type) { 86 | var result; 87 | 88 | switch (type) { 89 | case 'number': 90 | case 'date': 91 | result = [_constants.CONDITIONS.EQUALS_TO, _constants.CONDITIONS.LESS_THAN, _constants.CONDITIONS.GREATER_THAN, _constants.CONDITIONS.LESS_OR_EQUALS_THAN, _constants.CONDITIONS.GREATER_OR_EQUALS_THAN, _constants.CONDITIONS.IS_NOT_EQUALS_TO, _constants.CONDITIONS.IS_NOT_LESS_THAN, _constants.CONDITIONS.IS_NOT_GREATER_THAN, _constants.CONDITIONS.IS_NOT_LESS_OR_EQUALS_THAN, _constants.CONDITIONS.IS_NOT_GREATER_OR_EQUALS_THAN]; 92 | break; 93 | 94 | case 'boolean': 95 | result = [_constants.CONDITIONS.IS, _constants.CONDITIONS.IS_NOT]; 96 | break; 97 | 98 | default: 99 | result = [_constants.CONDITIONS.CONTAINS, _constants.CONDITIONS.EQUALS_TO, _constants.CONDITIONS.BEGINS_WITH, _constants.CONDITIONS.ENDS_WITH, _constants.CONDITIONS.IS_NOT_EQUALS_TO, _constants.CONDITIONS.DOES_NOT_BEGIN_WITH, _constants.CONDITIONS.DOES_NOT_END_WITH, _constants.CONDITIONS.DOES_NOT_CONTAIN]; 100 | break; 101 | } 102 | 103 | return result.map(function (r) { 104 | return { 105 | value: r, 106 | text: _constants.CONDITIONS_LABEL[r], 107 | key: r 108 | }; 109 | }); 110 | }; 111 | 112 | exports.conditionsForType = conditionsForType; 113 | 114 | var getDefaultConditionForType = function getDefaultConditionForType(type) { 115 | switch (type) { 116 | case 'number': 117 | return _constants.CONDITIONS.EQUALS_TO; 118 | 119 | case 'date': 120 | return _constants.CONDITIONS.GREATER_OR_EQUALS_THAN; 121 | 122 | default: 123 | return _constants.CONDITIONS.CONTAINS; 124 | } 125 | }; 126 | 127 | exports.getDefaultConditionForType = getDefaultConditionForType; 128 | 129 | var inputForType = function inputForType(type, props) { 130 | switch (type) { 131 | case 'number': 132 | return /*#__PURE__*/_react["default"].createElement(Input, _extends({ 133 | type: "number" 134 | }, props)); 135 | 136 | case 'boolean': 137 | return /*#__PURE__*/_react["default"].createElement(Input, _extends({}, props, { 138 | type: "checkbox", 139 | onClick: function onClick(evt) { 140 | props.onChange(_objectSpread(_objectSpread({}, evt), {}, { 141 | currentTarget: _objectSpread(_objectSpread({}, evt.currentTarget), {}, { 142 | value: evt.currentTarget.checked 143 | }) 144 | })); 145 | }, 146 | onChange: _helpers.NO_OP 147 | })); 148 | 149 | case 'date': 150 | return /*#__PURE__*/_react["default"].createElement(_reactDatetime["default"], _extends({}, props, { 151 | className: "ui input", 152 | dateFormat: "YYYY-MM-DD", 153 | timeFormat: "hh:mm A", 154 | onChange: function onChange(data) { 155 | props.onChange({ 156 | currentTarget: { 157 | value: data.format('YYYY-MM-DD hh:mm A') 158 | } 159 | }); 160 | } 161 | })); 162 | 163 | default: 164 | return /*#__PURE__*/_react["default"].createElement(Input, _extends({ 165 | type: "text" 166 | }, props)); 167 | } 168 | }; 169 | 170 | exports.inputForType = inputForType; 171 | var _default = { 172 | defaultRuleRender: defaultRuleRender, 173 | conditionsForType: conditionsForType, 174 | getDefaultConditionForType: getDefaultConditionForType, 175 | inputForType: inputForType, 176 | mapFieldsToOptions: mapFieldsToOptions, 177 | isBoolean: isBoolean, 178 | isRuleComplete: isRuleComplete 179 | }; 180 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _RuleBuilder = _interopRequireDefault(require("./RuleBuilder")); 11 | 12 | var _Rules = _interopRequireDefault(require("./Rules")); 13 | 14 | var _wrappers = require("./wrappers"); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 17 | 18 | var QueryBuilder = function QueryBuilder(props) { 19 | var queryRules = props.queryRules, 20 | fields = props.fields, 21 | renderRule = props.renderRule, 22 | onRuleAdded = props.onRuleAdded, 23 | onRuleRemoved = props.onRuleRemoved; 24 | return /*#__PURE__*/_react["default"].createElement(_wrappers.Container, null, /*#__PURE__*/_react["default"].createElement(_RuleBuilder["default"], { 25 | fields: fields, 26 | onSave: onRuleAdded, 27 | fieldsSelectPlaceholder: "Select field", 28 | conditionsSelectPlaceholder: "Select condition" 29 | }), /*#__PURE__*/_react["default"].createElement(_Rules["default"], { 30 | queryRules: queryRules, 31 | onRuleRemoved: onRuleRemoved, 32 | renderRule: renderRule 33 | })); 34 | }; 35 | 36 | var _default = QueryBuilder; 37 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/QueryBuilder/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports["default"] = exports.SearchRules = exports.RuleBuilder = exports.Container = void 0; 7 | 8 | var _bemReactComponentCreator = _interopRequireDefault(require("bem-react-component-creator")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 11 | 12 | var _bcc = (0, _bemReactComponentCreator["default"])('crud-table-query-builder'), 13 | block = _bcc.block, 14 | element = _bcc.element; 15 | 16 | var Container = block('div'); 17 | exports.Container = Container; 18 | Container.displayName = 'Container'; 19 | var RuleBuilder = element('div', 'search-rule-builder'); 20 | exports.RuleBuilder = RuleBuilder; 21 | RuleBuilder.displayName = 'RuleBuilder'; 22 | var SearchRules = element('div', 'search-rules'); 23 | exports.SearchRules = SearchRules; 24 | SearchRules.displayName = 'SearchRules'; 25 | var _default = { 26 | Container: Container, 27 | RuleBuilder: RuleBuilder, 28 | SearchRules: SearchRules 29 | }; 30 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/Select/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports["default"] = void 0; 9 | 10 | var _react = _interopRequireWildcard(require("react")); 11 | 12 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 13 | 14 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 15 | 16 | var Select = function Select(props) { 17 | var placeholder = props.placeholder, 18 | options = props.options, 19 | value = props.value, 20 | onChange = props.onChange; 21 | return /*#__PURE__*/_react["default"].createElement("select", { 22 | className: "crud-table__select", 23 | onChange: onChange, 24 | value: value 25 | }, /*#__PURE__*/_react["default"].createElement("option", { 26 | value: "" 27 | }, placeholder), options.map(function (option) { 28 | return /*#__PURE__*/_react["default"].createElement("option", { 29 | key: option.key, 30 | value: option.value 31 | }, option.text); 32 | })); 33 | }; 34 | 35 | var _default = Select; 36 | exports["default"] = _default; -------------------------------------------------------------------------------- /build/helpers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.NO_OP = void 0; 7 | 8 | var NO_OP = function NO_OP() {}; 9 | 10 | exports.NO_OP = NO_OP; -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | import { configure } from 'enzyme'; 2 | import Adapter from 'enzyme-adapter-react-16'; 3 | 4 | configure({ adapter: new Adapter() }); 5 | 6 | global.scrollTo = jest.fn(); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-crud-table", 3 | "version": "0.3.1", 4 | "description": "A table that includes all the CRUD operations.", 5 | "main": "build/CRUDTable/index.js", 6 | "scripts": { 7 | "dev": "watch 'npm run build' src", 8 | "lint": "eslint './src/**/*.{js,jsx}'", 9 | "lint:fix": "eslint './src/**/*.{js,jsx}' --fix", 10 | "build": "babel src -d build", 11 | "types:check": "flow ./src", 12 | "test": "jest ./src --no-watchman", 13 | "test:watch": "jest ./src --watch", 14 | "test:coverage": "CI=true npm test -- --coverage", 15 | "test:badges": "npm run test:coverage && jest-coverage-badges", 16 | "prepublish": "npm run build", 17 | "release": "np" 18 | }, 19 | "jest": { 20 | "setupFilesAfterEnv": [ 21 | "/jest.setup.js" 22 | ], 23 | "collectCoverageFrom": [ 24 | "src/**/*.{js,jsx,ts,tsx}", 25 | "!/node_modules/" 26 | ], 27 | "coverageReporters": [ 28 | "json-summary", 29 | "text", 30 | "lcov" 31 | ], 32 | "coverageThreshold": { 33 | "global": { 34 | "branches": 80, 35 | "functions": 80, 36 | "lines": 80, 37 | "statements": 80 38 | } 39 | } 40 | }, 41 | "babel": { 42 | "presets": [ 43 | [ 44 | "@babel/preset-env", 45 | { 46 | "useBuiltIns": "entry", 47 | "corejs": "2.0.0" 48 | } 49 | ], 50 | "@babel/preset-react", 51 | "@babel/preset-flow" 52 | ] 53 | }, 54 | "repository": { 55 | "type": "git", 56 | "url": "git+https://github.com/xvicmanx/react-crud-table" 57 | }, 58 | "keywords": [ 59 | "CRUD", 60 | "react" 61 | ], 62 | "author": "Victor Trejo", 63 | "license": "ISC", 64 | "dependencies": { 65 | "bem-react-component-creator": "^1.2.0", 66 | "formik": "0.11.11", 67 | "moment": "^2.22.1", 68 | "prop-types": "^15.7.2", 69 | "react": "^17.0.1", 70 | "react-datetime": "^2.14.0" 71 | }, 72 | "devDependencies": { 73 | "@babel/cli": "^7.12.8", 74 | "@babel/core": "^7.12.9", 75 | "@babel/plugin-transform-react-jsx": "^7.12.10", 76 | "@babel/preset-env": "^7.12.7", 77 | "@babel/preset-flow": "^7.12.1", 78 | "@babel/preset-react": "^7.12.7", 79 | "enzyme-adapter-react-16": "^1.15.5", 80 | "babel-eslint": "^10.1.0", 81 | "enzyme": "^3.11.0", 82 | "eslint": "^7.15.0", 83 | "eslint-config-airbnb": "^18.2.1", 84 | "eslint-config-prettier": "^7.0.0", 85 | "eslint-plugin-flowtype": "^5.2.0", 86 | "eslint-plugin-import": "^2.22.1", 87 | "eslint-plugin-jsx-a11y": "^6.4.1", 88 | "eslint-plugin-prettier": "^3.2.0", 89 | "eslint-plugin-react": "^7.21.5", 90 | "eslint-plugin-react-hooks": "^4.2.0", 91 | "flow-bin": "^0.140.0", 92 | "jest": "^26.6.3", 93 | "jest-coverage-badges": "^1.1.2", 94 | "np": "^2.18.2", 95 | "prettier-eslint": "^12.0.0", 96 | "react-dom": "^16.14.0", 97 | "react-test-renderer": "^16.2.0", 98 | "watch": "^1.0.2" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /screenshot-pagination.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xvicmanx/react-crud-table/fad9815a470e3bd4c9bb9596d7619bb77704b298/screenshot-pagination.jpg -------------------------------------------------------------------------------- /screenshot-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xvicmanx/react-crud-table/fad9815a470e3bd4c9bb9596d7619bb77704b298/screenshot-simple.png -------------------------------------------------------------------------------- /src/Button/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Button renders properly 1`] = ` 4 | 9 | `; 10 | -------------------------------------------------------------------------------- /src/Button/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Btn } from './wrappers'; 3 | 4 | const Button = (props) => ; 5 | 6 | export default Button; 7 | -------------------------------------------------------------------------------- /src/Button/index.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ShallowRenderer from 'react-test-renderer/shallow'; 3 | import Button from '.'; 4 | 5 | describe('Button', () => { 6 | it('renders properly', () => { 7 | const renderer = new ShallowRenderer(); 8 | const result = renderer.render( 9 | 10 | ); 11 | expect(result).toMatchSnapshot(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /src/Button/wrappers.js: -------------------------------------------------------------------------------- 1 | import bcc from 'bem-react-component-creator'; 2 | 3 | const { block } = bcc('crud-button'); 4 | 5 | export const Btn = block('button'); 6 | 7 | Btn.displayName = 'Button'; 8 | 9 | export default { Btn }; 10 | -------------------------------------------------------------------------------- /src/CRUDTable/Body.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import * as React from 'react'; 4 | 5 | import { getTableFieldValue, scrollToTop } from './helpers'; 6 | import { Table } from './wrappers'; 7 | import Button from '../Button'; 8 | import { NO_OP } from '../helpers'; 9 | 10 | export type Props = { 11 | actionsLabel: number | string | React.Element | Array, 12 | updateTrigger: number | string | React.Element | Array, 13 | deleteTrigger: number | string | React.Element | Array, 14 | fields: Array, 15 | items: Array, 16 | onDeleteClick: Function, 17 | onUpdateClick: Function, 18 | }; 19 | 20 | const Body = (props: Props): React$Element => { 21 | const { 22 | fields, 23 | items, 24 | onDeleteClick, 25 | onUpdateClick, 26 | actionsLabel, 27 | updateTrigger, 28 | deleteTrigger, 29 | } = props; 30 | 31 | return ( 32 | 33 | {items.map((item) => ( 34 | 35 | {fields.map((field) => ( 36 | 37 | {field.label} 38 | {getTableFieldValue(field, item)} 39 | 40 | ))} 41 | {(updateTrigger || deleteTrigger) && ( 42 | 43 | {actionsLabel} 44 | {updateTrigger && ( 45 | 54 | )}{' '} 55 | {deleteTrigger && ( 56 | 65 | )} 66 | 67 | )} 68 | 69 | ))} 70 | 71 | ); 72 | }; 73 | 74 | Body.defaultProps = { 75 | fields: ([]: Array), 76 | items: ([]: Array), 77 | actionsLabel: '', 78 | onDeleteClick: NO_OP, 79 | onUpdateClick: NO_OP, 80 | updateTrigger: null, 81 | deleteTrigger: null, 82 | }; 83 | 84 | export default Body; 85 | -------------------------------------------------------------------------------- /src/CRUDTable/Body.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ShallowRenderer from 'react-test-renderer/shallow'; 3 | import { create } from 'react-test-renderer'; 4 | 5 | import { Table } from './wrappers'; 6 | import Button from '../Button'; 7 | import Body from './Body'; 8 | 9 | const renderer = new ShallowRenderer(); 10 | 11 | describe('Body', () => { 12 | let props; 13 | const items = [ 14 | { 15 | id: 1, 16 | name: 'John', 17 | age: 45, 18 | description: 'I love my family', 19 | }, 20 | { 21 | id: 2, 22 | name: 'Mary', 23 | age: 35, 24 | description: 'Nature is beatiful', 25 | }, 26 | ]; 27 | 28 | beforeEach(() => { 29 | props = { 30 | onDeleteClick: jest.fn(), 31 | onUpdateClick: jest.fn(), 32 | actionsLabel: 'Act', 33 | updateTrigger: 'Update', 34 | deleteTrigger: 'Delete', 35 | items, 36 | fields: [ 37 | { 38 | name: 'id', 39 | label: 'Id', 40 | }, 41 | { 42 | name: 'name', 43 | label: 'Name', 44 | tableValueResolver: 'name', 45 | }, 46 | { 47 | name: 'age', 48 | label: 'Age', 49 | tableValueResolver: (item) => `${item.age} years`, 50 | }, 51 | { 52 | name: 'description', 53 | label: 'Description', 54 | }, 55 | ], 56 | sort: { 57 | field: 'name', 58 | direction: 'ascending', 59 | }, 60 | }; 61 | }); 62 | 63 | it('renders as expected with the given props', () => { 64 | const result = renderer.render(); 65 | expect(result).toMatchSnapshot(); 66 | }); 67 | 68 | it('notifies when clicking trigger buttons', () => { 69 | const result = create(); 70 | 71 | const buttons = result.root.findAllByType(Button); 72 | 73 | buttons[0].props.onClick(); 74 | buttons[1].props.onClick(); 75 | 76 | expect(props.onDeleteClick).toHaveBeenCalledTimes(1); 77 | expect(props.onDeleteClick).toHaveBeenCalledWith(items[0]); 78 | 79 | expect(props.onUpdateClick).toHaveBeenCalledTimes(1); 80 | expect(props.onUpdateClick).toHaveBeenCalledWith(items[0]); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /src/CRUDTable/Header.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import * as React from 'react'; 3 | 4 | import { Table } from './wrappers'; 5 | import { chevron, toggleDirection } from './helpers'; 6 | import { NO_OP } from '../helpers'; 7 | import Select from '../Select'; 8 | import { SORT_DIRECTIONS } from './constants'; 9 | 10 | type Field = { 11 | name: string, 12 | label: string, 13 | sortable?: boolean, 14 | }; 15 | 16 | type Sort = { 17 | field: string, 18 | direction: 'descending' | 'ascending', 19 | }; 20 | 21 | const mapFieldsToOptions = (fields: Array) => 22 | fields.map((x) => ({ 23 | text: x.label, 24 | value: x.name, 25 | key: x.name, 26 | })); 27 | 28 | const sortDirectionsOptions = Object.keys(SORT_DIRECTIONS).map((k) => ({ 29 | text: SORT_DIRECTIONS[k], 30 | value: SORT_DIRECTIONS[k], 31 | key: k, 32 | })); 33 | 34 | export type Props = { 35 | onChange: Function, 36 | actionsLabel: number | string | React.Element | Array, 37 | fields: Array, 38 | sort: Sort, 39 | }; 40 | 41 | const Header = (props: Props): React.Element => { 42 | const { fields, sort, onChange, actionsLabel } = props; 43 | const sortableFields = fields.filter((field) => field.sortable); 44 | 45 | return ( 46 | 47 | 48 | {fields.map((field) => ( 49 | { 52 | if (field.sortable) { 53 | const newDirection = toggleDirection( 54 | sort.direction, 55 | field.name === sort.field 56 | ); 57 | onChange(field.name, newDirection); 58 | } 59 | }} 60 | > 61 | {field.label} {sort.field === field.name && chevron(sort.direction)} 62 | 63 | ))} 64 | {actionsLabel && {actionsLabel}} 65 | 66 | {sortableFields.length > 0 && ( 67 | 68 | 69 | Sort by:
70 | { 86 | const { value } = evt.currentTarget; 87 | if (value) { 88 | onChange(sort.field, value); 89 | } 90 | }} 91 | /> 92 |
93 |
94 | )} 95 |
96 | ); 97 | }; 98 | 99 | Header.defaultProps = { 100 | fields: ([]: Array), 101 | onChange: NO_OP, 102 | actionsLabel: '', 103 | }; 104 | 105 | export default Header; 106 | -------------------------------------------------------------------------------- /src/CRUDTable/Header.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ShallowRenderer from 'react-test-renderer/shallow'; 3 | import { create } from 'react-test-renderer'; 4 | 5 | import { Table } from './wrappers'; 6 | import Header from './Header'; 7 | 8 | const renderer = new ShallowRenderer(); 9 | 10 | describe('Header', () => { 11 | let props; 12 | 13 | beforeEach(() => { 14 | props = { 15 | trigger: 'Open', 16 | title: 'Test title', 17 | onChange: jest.fn(), 18 | actionsLabel: 'Act', 19 | fields: [ 20 | { 21 | name: 'name', 22 | label: 'Name', 23 | sortable: true, 24 | }, 25 | { 26 | name: 'age', 27 | label: 'Age', 28 | sortable: false, 29 | }, 30 | ], 31 | sort: { 32 | field: 'name', 33 | direction: 'ascending', 34 | }, 35 | }; 36 | }); 37 | 38 | it('renders as expected with the given props', () => { 39 | const result = renderer.render(
); 40 | expect(result).toMatchSnapshot(); 41 | }); 42 | 43 | it('renders as expected with the given props (descending sort)', () => { 44 | props.sort.direction = 'descending'; 45 | const result = renderer.render(
); 46 | expect(result).toMatchSnapshot(); 47 | }); 48 | 49 | it('notifies when click on cells', () => { 50 | const result = create(
); 51 | 52 | const cells = result.root.findAllByType(Table.HeaderCell); 53 | 54 | cells[0].props.onClick(); 55 | cells[1].props.onClick(); 56 | 57 | expect(props.onChange).toHaveBeenCalledTimes(1); 58 | expect(props.onChange).toHaveBeenCalledWith('name', 'descending'); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /src/CRUDTable/__snapshots__/Body.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Body renders as expected with the given props 1`] = ` 4 | 5 | 6 | 7 | 8 | Id 9 | 10 | 1 11 | 12 | 13 | 14 | Name 15 | 16 | John 17 | 18 | 19 | 20 | Age 21 | 22 | 45 years 23 | 24 | 25 | 26 | Description 27 | 28 | I love my family 29 | 30 | 31 | 32 | Act 33 | 34 | 40 | 41 | 47 | 48 | 49 | 50 | 51 | 52 | Id 53 | 54 | 2 55 | 56 | 57 | 58 | Name 59 | 60 | Mary 61 | 62 | 63 | 64 | Age 65 | 66 | 35 years 67 | 68 | 69 | 70 | Description 71 | 72 | Nature is beatiful 73 | 74 | 75 | 76 | Act 77 | 78 | 84 | 85 | 91 | 92 | 93 | 94 | `; 95 | -------------------------------------------------------------------------------- /src/CRUDTable/__snapshots__/Header.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Header renders as expected with the given props (descending sort) 1`] = ` 4 |
5 | 8 | 11 | Name 12 | 13 | 14 | 15 | 18 | Age 19 | 20 | 21 | 22 | Act 23 | 24 | 25 | 28 | 31 | Sort by: 32 |
33 | 67 |
68 |
69 |
70 | `; 71 | 72 | exports[`Header renders as expected with the given props 1`] = ` 73 |
74 | 77 | 80 | Name 81 | 82 | 83 | 84 | 87 | Age 88 | 89 | 90 | 91 | Act 92 | 93 | 94 | 97 | 100 | Sort by: 101 |
102 | 136 |
137 |
138 |
139 | `; 140 | -------------------------------------------------------------------------------- /src/CRUDTable/actions.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export const changeSort = (field: string, direction: string): Object => ( 4 | state: Object, 5 | props: Object 6 | ): Object => { 7 | const { sort } = state; 8 | return { 9 | sort: { 10 | field, 11 | direction, 12 | }, 13 | }; 14 | }; 15 | 16 | export const changePage = (activePage: number): Object => ( 17 | state: Object, 18 | props: Object 19 | ): Object => ({ 20 | pagination: { 21 | ...state.pagination, 22 | activePage, 23 | }, 24 | }); 25 | 26 | export const addRule = (rule: Object): Object => ( 27 | state: Object, 28 | props: Object 29 | ): Object => ({ 30 | queryRules: [...state.queryRules, rule], 31 | }); 32 | 33 | export const removeRule = (rule: Object): Object => ( 34 | state: Object, 35 | props: Object 36 | ): Object => ({ 37 | queryRules: state.queryRules.filter( 38 | (x) => x.field !== rule.field || x.condition !== rule.condition 39 | ), 40 | }); 41 | -------------------------------------------------------------------------------- /src/CRUDTable/constants.js: -------------------------------------------------------------------------------- 1 | export const SORT_DIRECTIONS = { 2 | DESCENDING: 'descending', 3 | ASCENDING: 'ascending', 4 | }; 5 | 6 | export const ID_FIELD = 'id'; 7 | 8 | export const FIELDS_COMPONENT_TYPE = 'CRUDTable_Fields'; 9 | export const FIELD_COMPONENT_TYPE = 'CRUDTable_Field'; 10 | export const CREATE_FORM_COMPONENT_TYPE = 'CRUDTable_CreateForm'; 11 | export const DELETE_FORM_COMPONENT_TYPE = 'CRUDTable_DeleteForm'; 12 | export const UPDATE_FORM_COMPONENT_TYPE = 'CRUDTable_UpdateForm'; 13 | export const PAGINATION_COMPONENT_TYPE = 'CRUDTable_Pagination'; 14 | 15 | export default { 16 | SORT_DIRECTIONS, 17 | ID_FIELD, 18 | FIELDS_COMPONENT_TYPE, 19 | FIELD_COMPONENT_TYPE, 20 | CREATE_FORM_COMPONENT_TYPE, 21 | DELETE_FORM_COMPONENT_TYPE, 22 | UPDATE_FORM_COMPONENT_TYPE, 23 | PAGINATION_COMPONENT_TYPE, 24 | }; 25 | -------------------------------------------------------------------------------- /src/CRUDTable/helpers.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | SORT_DIRECTIONS, 4 | ID_FIELD, 5 | FIELDS_COMPONENT_TYPE, 6 | FIELD_COMPONENT_TYPE, 7 | CREATE_FORM_COMPONENT_TYPE, 8 | DELETE_FORM_COMPONENT_TYPE, 9 | UPDATE_FORM_COMPONENT_TYPE, 10 | PAGINATION_COMPONENT_TYPE, 11 | } from './constants'; 12 | 13 | const UpArrow = () => ; 14 | const DownArrow = () => ; 15 | 16 | export const chevron = (direction) => { 17 | if (direction === SORT_DIRECTIONS.ASCENDING) { 18 | return ; 19 | } 20 | 21 | return ; 22 | }; 23 | 24 | export const toggleDirection = (direction, toggle) => { 25 | if (toggle) { 26 | switch (direction) { 27 | case 'ascending': 28 | return 'descending'; 29 | default: 30 | return 'ascending'; 31 | } 32 | } 33 | return direction; 34 | }; 35 | 36 | export const queryValue = (source, query = '', defaultValue = null) => { 37 | const value = query 38 | .split('.') 39 | .reduce( 40 | (result, key) => (result && result[key] ? result[key] : null), 41 | source 42 | ); 43 | return value || defaultValue; 44 | }; 45 | 46 | export const FILTER_BY_TYPE = (t) => (item) => 47 | item.type && item.type.displayName === t; 48 | 49 | export const getProps = (comp, fields = [], defaultValue = null) => { 50 | const props = comp ? comp.props : null; 51 | if (!props) return defaultValue; 52 | return { 53 | ...props, 54 | fields, 55 | }; 56 | }; 57 | 58 | export const extractFields = (items) => { 59 | const container = items.find(FILTER_BY_TYPE(FIELDS_COMPONENT_TYPE)); 60 | const children = container 61 | ? React.Children.toArray(container.props.children) 62 | : []; 63 | return children 64 | .filter(FILTER_BY_TYPE(FIELD_COMPONENT_TYPE)) 65 | .map((c) => c.props); 66 | }; 67 | 68 | export const extractPagination = (items) => { 69 | const container = items.find(FILTER_BY_TYPE(PAGINATION_COMPONENT_TYPE)); 70 | return getProps(container, [], {}); 71 | }; 72 | 73 | export const extractQueryFields = (items) => { 74 | const fields = extractFields(items); 75 | return fields 76 | .filter((f) => f.queryable) 77 | .map((f) => ({ 78 | ...f, 79 | value: f.name, 80 | })); 81 | }; 82 | 83 | export const extractForms = (items, fields) => ({ 84 | create: getProps( 85 | items.find(FILTER_BY_TYPE(CREATE_FORM_COMPONENT_TYPE)), 86 | fields.filter((f) => !f.hideInCreateForm) 87 | ), 88 | update: getProps( 89 | items.find(FILTER_BY_TYPE(UPDATE_FORM_COMPONENT_TYPE)), 90 | fields.filter((f) => !f.hideInUpdateForm) 91 | ), 92 | delete: getProps(items.find(FILTER_BY_TYPE(DELETE_FORM_COMPONENT_TYPE))), 93 | }); 94 | 95 | export const getTableFieldValue = (field, item) => { 96 | if (typeof field.tableValueResolver === 'string') { 97 | return queryValue(item, field.tableValueResolver); 98 | } 99 | 100 | if (typeof field.tableValueResolver === 'function') { 101 | return field.tableValueResolver(item); 102 | } 103 | 104 | return item[field.name]; 105 | }; 106 | 107 | export const getPaginationProps = (props) => { 108 | const items = React.Children.toArray(props.children); 109 | return extractPagination(items); 110 | }; 111 | 112 | export const getDefaultState = (items, pagination) => ({ 113 | items, 114 | sort: { 115 | field: ID_FIELD, 116 | direction: SORT_DIRECTIONS.DESCENDING, 117 | }, 118 | queryRules: [], 119 | updateItem: {}, 120 | deleteItem: {}, 121 | createModalVisible: false, 122 | deleteModalVisible: false, 123 | updateModalVisible: false, 124 | pagination: { 125 | ...pagination, 126 | activePage: pagination.activePage || pagination.defaultActivePage || 1, 127 | totalOfItems: pagination.totalOfItems || 0, 128 | itemsPerPage: pagination.itemsPerPage || 10, 129 | }, 130 | totalOfItems: pagination.totalOfItems || 0, 131 | }); 132 | 133 | export const scrollToTop = () => { 134 | if (typeof window !== 'undefined' && window.scrollTo) { 135 | window.scrollTo({ top: 0, behavior: 'smooth' }); 136 | } 137 | }; 138 | 139 | export default { 140 | chevron, 141 | toggleDirection, 142 | queryValue, 143 | getTableFieldValue, 144 | FILTER_BY_TYPE, 145 | extractFields, 146 | getProps, 147 | extractForms, 148 | extractPagination, 149 | extractQueryFields, 150 | getPaginationProps, 151 | }; 152 | -------------------------------------------------------------------------------- /src/CRUDTable/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import * as React from 'react'; 3 | 4 | import { 5 | SORT_DIRECTIONS, 6 | ID_FIELD, 7 | FIELDS_COMPONENT_TYPE, 8 | FIELD_COMPONENT_TYPE, 9 | CREATE_FORM_COMPONENT_TYPE, 10 | DELETE_FORM_COMPONENT_TYPE, 11 | UPDATE_FORM_COMPONENT_TYPE, 12 | PAGINATION_COMPONENT_TYPE, 13 | } from './constants'; 14 | import { 15 | toggleDirection, 16 | extractFields, 17 | extractPagination, 18 | extractForms, 19 | extractQueryFields, 20 | queryValue, 21 | getPaginationProps, 22 | getDefaultState, 23 | } from './helpers'; 24 | import { Table } from './wrappers'; 25 | import Header from './Header'; 26 | import Body from './Body'; 27 | import PaginationCpt from '../Pagination'; 28 | import FormModal from '../FormModal'; 29 | import QueryBuilder from '../QueryBuilder'; 30 | import { NO_OP } from '../helpers'; 31 | import { addRule, changePage, changeSort, removeRule } from './actions'; 32 | 33 | type Props = { 34 | onChange?: Function, 35 | actionsLabel?: number | string | React.Element | Array, 36 | showQueryBuilder?: boolean, 37 | items?: Object, 38 | caption?: number | string | React.Element | Array, 39 | fetchItems?: Function, 40 | children: number | string | React.Element | Array, 41 | }; 42 | 43 | type State = { 44 | queryRules: Array, 45 | updateItem: ?Object, 46 | deleteItem: ?Object, 47 | createModalVisible: boolean, 48 | deleteModalVisible: boolean, 49 | updateModalVisible: boolean, 50 | items?: Array, 51 | sort: Object, 52 | pagination: Object, 53 | totalOfItems: number, 54 | }; 55 | 56 | class CRUDTable extends React.Component { 57 | forms: Object; 58 | queryFields: Array; 59 | pagination: Object; 60 | fields: Array; 61 | 62 | constructor(props: Props) { 63 | super(props); 64 | 65 | const target: any = this; 66 | target.handleOnCreateSubmission = this.handleOnCreateSubmission.bind(this); 67 | target.handleOnDeleteSubmission = this.handleOnDeleteSubmission.bind(this); 68 | target.handleOnUpdateSubmission = this.handleOnUpdateSubmission.bind(this); 69 | target.handleSortChange = this.handleSortChange.bind(this); 70 | target.handlePageChange = this.handlePageChange.bind(this); 71 | target.handleRuleAdded = this.handleRuleAdded.bind(this); 72 | target.handleRuleRemoved = this.handleRuleRemoved.bind(this); 73 | 74 | const configItems = React.Children.toArray(props.children); 75 | this.fields = extractFields(configItems); 76 | this.forms = extractForms(configItems, this.fields); 77 | this.pagination = extractPagination(configItems); 78 | this.queryFields = extractQueryFields(configItems); 79 | this.state = getDefaultState(props.items, this.pagination); 80 | } 81 | 82 | props: Props; 83 | 84 | componentDidMount() { 85 | this.update(undefined, false); 86 | } 87 | 88 | // eslint-disable-next-line camelcase 89 | UNSAFE_componentWillReceiveProps(nextProps: Props) { 90 | const { items } = this.props; 91 | const newState = {}; 92 | 93 | if (nextProps.items !== items) { 94 | newState.items = nextProps.items; 95 | const paginationProps = getPaginationProps(nextProps); 96 | newState.totalOfItems = paginationProps.totalOfItems || 0; 97 | } 98 | 99 | if (Object.keys(newState).length) { 100 | this.setState(newState); 101 | } 102 | } 103 | 104 | handleSortChange(field: string, direction: string) { 105 | this.setState(changeSort(field, direction), () => { 106 | const { sort } = this.state; 107 | this.update({ sort }); 108 | }); 109 | } 110 | 111 | handlePageChange(activePage: number) { 112 | this.setState(changePage(activePage), () => { 113 | const { pagination } = this.state; 114 | this.update({ pagination }); 115 | }); 116 | } 117 | 118 | handleOnCreateSubmission(values: Object): any { 119 | return this.formSubmission(this.forms.create, values); 120 | } 121 | 122 | handleOnUpdateSubmission(values: Object): any { 123 | return this.formSubmission(this.forms.update, values); 124 | } 125 | 126 | handleOnDeleteSubmission(values: Object): any { 127 | return this.formSubmission(this.forms.delete, values); 128 | } 129 | 130 | formSubmission(form: Object, values: Object): any { 131 | return form.onSubmit(values).then((result) => { 132 | this.update(); 133 | return result; 134 | }); 135 | } 136 | 137 | handleRuleAdded(rule: Object) { 138 | this.setState(addRule(rule), () => { 139 | const { queryRules } = this.state; 140 | this.update({ queryRules }); 141 | }); 142 | } 143 | 144 | handleRuleRemoved(rule: Object) { 145 | this.setState(removeRule(rule), () => { 146 | const { queryRules } = this.state; 147 | this.update({ queryRules }); 148 | }); 149 | } 150 | 151 | getPayload(extension: Object = {}): Object { 152 | const { queryRules, pagination, sort } = this.state; 153 | return { 154 | queryRules, 155 | pagination, 156 | sort, 157 | ...extension, 158 | }; 159 | } 160 | 161 | update(data: Object = undefined, reportChange: Object = true) { 162 | const { fetchItems, onChange } = this.props; 163 | const payload = this.getPayload(data); 164 | 165 | if (fetchItems) { 166 | fetchItems(payload).then((items) => { 167 | this.setState({ items }); 168 | }); 169 | } 170 | 171 | if (this.pagination.fetchTotalOfItems) { 172 | this.pagination.fetchTotalOfItems(payload).then((totalOfItems) => { 173 | this.setState({ totalOfItems }); 174 | }); 175 | } 176 | 177 | if (reportChange) { 178 | onChange(payload); 179 | } 180 | } 181 | 182 | render(): React$Element { 183 | const { 184 | items, 185 | sort, 186 | pagination, 187 | totalOfItems, 188 | deleteItem, 189 | updateItem, 190 | queryRules, 191 | createModalVisible, 192 | deleteModalVisible, 193 | updateModalVisible, 194 | } = this.state; 195 | const { caption, showQueryBuilder, actionsLabel } = this.props; 196 | const tabularFields = this.fields.filter((f) => !f.hideFromTable); 197 | const updateTrigger = queryValue(this.forms, 'update.trigger'); 198 | const deleteTrigger = queryValue(this.forms, 'delete.trigger'); 199 | return ( 200 |
201 | {this.forms.create && ( 202 | { 209 | this.setState({ 210 | createModalVisible: visible, 211 | }); 212 | }} 213 | /> 214 | )} 215 | 216 | {caption && {caption}} 217 | 218 | {showQueryBuilder && ( 219 | 225 | )} 226 | 227 | 228 |
234 | { 241 | this.setState({ 242 | deleteItem: item, 243 | deleteModalVisible: true, 244 | }); 245 | }} 246 | onUpdateClick={(item) => { 247 | this.setState({ 248 | updateItem: item, 249 | updateModalVisible: true, 250 | }); 251 | }} 252 | /> 253 |
254 | 255 | {!!pagination && totalOfItems > 0 && ( 256 | 261 | )} 262 | 263 | {this.forms.update && ( 264 | { 270 | this.setState({ 271 | updateModalVisible: visible, 272 | }); 273 | }} 274 | /> 275 | )} 276 | 277 | {this.forms.delete && ( 278 | { 285 | this.setState({ 286 | deleteModalVisible: visible, 287 | }); 288 | }} 289 | /> 290 | )} 291 |
292 | ); 293 | } 294 | } 295 | 296 | // $FlowFixMe 297 | CRUDTable.defaultProps = { 298 | onChange: NO_OP, 299 | actionsLabel: 'Actions', 300 | showQueryBuilder: false, 301 | items: [], 302 | caption: null, 303 | fetchItems: null, 304 | }; 305 | 306 | export const Fields = (): React$Element =>
; 307 | Fields.displayName = FIELDS_COMPONENT_TYPE; 308 | 309 | export type FieldProps = { 310 | name: string, 311 | label: string, 312 | type?: string, 313 | tableValueResolver?: Function | string, 314 | hideInCreateForm?: boolean, 315 | hideInUpdateForm?: boolean, 316 | hideFromTable?: boolean, 317 | queryable?: boolean, 318 | sortable?: boolean, 319 | }; 320 | 321 | export const Field = (props: FieldProps): React$Element => { 322 | const { 323 | name, 324 | label, 325 | tableValueResolver, 326 | hideInCreateForm, 327 | hideInUpdateForm, 328 | hideFromTable, 329 | queryable, 330 | type, 331 | sortable, 332 | } = props; 333 | 334 | return
; 335 | }; 336 | Field.displayName = FIELD_COMPONENT_TYPE; 337 | Field.defaultProps = { 338 | queryable: true, 339 | sortable: true, 340 | type: 'text', 341 | hideInCreateForm: false, 342 | hideInUpdateForm: false, 343 | hideFromTable: false, 344 | tableValueResolver: null, 345 | }; 346 | 347 | export const CreateForm = (): React$Element =>
; 348 | CreateForm.displayName = CREATE_FORM_COMPONENT_TYPE; 349 | 350 | export const UpdateForm = (): React$Element =>
; 351 | UpdateForm.displayName = UPDATE_FORM_COMPONENT_TYPE; 352 | 353 | export const DeleteForm = (): React$Element =>
; 354 | DeleteForm.displayName = DELETE_FORM_COMPONENT_TYPE; 355 | 356 | export const Pagination = (): React$Element =>
; 357 | Pagination.displayName = PAGINATION_COMPONENT_TYPE; 358 | 359 | export default CRUDTable; 360 | -------------------------------------------------------------------------------- /src/CRUDTable/index.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ShallowRenderer from 'react-test-renderer/shallow'; 3 | import { create } from 'react-test-renderer'; 4 | 5 | import CRUDTable, { 6 | Fields, 7 | Field, 8 | CreateForm, 9 | UpdateForm, 10 | DeleteForm, 11 | Pagination, 12 | } from '.'; 13 | 14 | import Header from './Header'; 15 | import Body from './Body'; 16 | import PaginationCpt from '../Pagination'; 17 | import FormModal from '../FormModal'; 18 | import QueryBuilder from '../QueryBuilder'; 19 | 20 | // eslint-disable-next-line react/prop-types 21 | const DescriptionRenderer = ({ field }) =>