diff --git a/CHANGELOG.md b/CHANGELOG.md index 98965037..6f0ad1c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,20 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - allow boolean for input values [`#269`](https://github.com/mighty-justice/fields-ant/pull/269) - Revert "Infer state in address type (#230)" [`f7cdc2c`](https://github.com/mighty-justice/fields-ant/commit/f7cdc2c730260a57fdd2b538cd40134459df4144) +#### [v1.3.3-3](https://github.com/mighty-justice/fields-ant/compare/v1.3.3-2...v1.3.3-3) + +> 30 August 2023 + +- Clean up [`15ff002`](https://github.com/mighty-justice/fields-ant/commit/15ff00222fccb483a65ef523e7367bbe55a7ce73) + +#### [v1.3.3-2](https://github.com/mighty-justice/fields-ant/compare/v1.3.3-1...v1.3.3-2) + +> 30 August 2023 + +- Add disable props to ArrayCard [`8471545`](https://github.com/mighty-justice/fields-ant/commit/847154596f75b6deb527ebdbf291c6d249010c88) +- Add new disable button props to EditableCard components [`769168d`](https://github.com/mighty-justice/fields-ant/commit/769168dec3678aaa9c05ad49254ef62967d0e1a0) +- Add disableDelete and tooltip props [`02e7543`](https://github.com/mighty-justice/fields-ant/commit/02e7543b04300a122f02a5e7219c07054daf2727) + #### [v1.3.3-1](https://github.com/mighty-justice/fields-ant/compare/v1.3.3...v1.3.3-1) > 19 February 2020 @@ -128,11 +142,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). > 4 September 2019 -#### [v1.0.5](https://github.com/mighty-justice/fields-ant/compare/v1.0.4...v1.0.5) - -> 4 September 2019 - -#### [v1.0.4](https://github.com/mighty-justice/fields-ant/compare/v1.0.3...v1.0.4) +#### [v1.0.5](https://github.com/mighty-justice/fields-ant/compare/v1.0.3...v1.0.5) > 4 September 2019 diff --git a/dist/components/EditableArrayCard.d.ts b/dist/components/EditableArrayCard.d.ts index c0e189ed..8ac4d8a1 100644 --- a/dist/components/EditableArrayCard.d.ts +++ b/dist/components/EditableArrayCard.d.ts @@ -5,6 +5,12 @@ export interface IEditableArrayCardProps extends IArrayCardProps, ISharedFormPro defaults?: object; onCreate: (model: unknown) => Promise; onDelete?: (model: unknown) => Promise; + disableAdd?: boolean; + disableAddTooltip?: string; + disableDeleteTooltip?: string; + disableDelete?: (model: any) => boolean; + disableEditTooltip?: string; + disableEdit?: (model: any) => boolean; } declare class EditableArrayCard extends Component { private isAddingNew; diff --git a/dist/components/EditableCard.d.ts b/dist/components/EditableCard.d.ts index 2c7e3849..d8ca30b6 100644 --- a/dist/components/EditableCard.d.ts +++ b/dist/components/EditableCard.d.ts @@ -4,6 +4,10 @@ import { ICardProps } from './Card'; import FormDrawer from './FormDrawer'; import FormModal from './FormModal'; export interface IEditableCardProps extends ICardProps, ISharedFormProps { + disableDeleteTooltip?: string; + disableDelete: boolean; + disableEditTooltip?: string; + disableEdit: boolean; ModalComponent: new (props: ISharedFormModalProps) => FormModal | FormDrawer; onDelete?: (model: unknown) => Promise; } diff --git a/dist/fieldsAnt.cjs.js b/dist/fieldsAnt.cjs.js index 92c7449e..a49fc684 100644 --- a/dist/fieldsAnt.cjs.js +++ b/dist/fieldsAnt.cjs.js @@ -2278,6 +2278,10 @@ function noopValidator(_rule, _value, callback) { // Useful for clearing manually-set backend validation errors callback(); } +function getBtnClassName(action, classNameSuffix, title) { + var prefix = "btn-".concat(action); + return cx(prefix, lodash.isString(title) && "".concat(prefix, "-").concat(lodash.kebabCase(title)), _defineProperty({}, "".concat(prefix, "-").concat(classNameSuffix), !!classNameSuffix)); +} // Takes an API response and converts it to a string to string map function getFieldErrors(errors) { @@ -3644,26 +3648,31 @@ function (_Component) { key: "deleteButton", get: function get() { var _this$props3 = this.props, + classNameSuffix = _this$props3.classNameSuffix, + disableDeleteTooltip = _this$props3.disableDeleteTooltip, + disableDelete = _this$props3.disableDelete, isGuarded = _this$props3.isGuarded, - title = _this$props3.title, - onDelete = _this$props3.onDelete, isLoading = _this$props3.isLoading, - classNameSuffix = this.props.classNameSuffix || lodash.kebabCase(title); + onDelete = _this$props3.onDelete, + title = _this$props3.title, + className = getBtnClassName('delete', classNameSuffix, title); if (!onDelete) { return; } - return React__default.createElement(GuardedButton, { - className: "btn-delete btn-delete-".concat(classNameSuffix), + return React__default.createElement(Antd.Tooltip, { + title: disableDelete ? disableDeleteTooltip : '' + }, React__default.createElement(GuardedButton, { + className: className, confirm: true, - disabled: isLoading || this.isDeleting.isTrue, + disabled: disableDelete || isLoading || this.isDeleting.isTrue, icon: "delete", isGuarded: isGuarded, onClick: this.handleDelete, size: "small", type: "danger" - }, "Delete"); + }, "Delete")); } }, { key: "editButton", @@ -3672,21 +3681,30 @@ function (_Component) { isLoading = _this$props4.isLoading, title = _this$props4.title, isGuarded = _this$props4.isGuarded, + disableEdit = _this$props4.disableEdit, + disableEditTooltip = _this$props4.disableEditTooltip, classNameSuffix = this.props.classNameSuffix || lodash.kebabCase(title); - return React__default.createElement(GuardedButton, { + return React__default.createElement(Antd.Tooltip, { + title: disableEdit ? disableEditTooltip : '' + }, React__default.createElement(GuardedButton, { className: "btn-edit btn-edit-".concat(classNameSuffix), - disabled: isLoading || this.isEditing.isTrue || this.isDeleting.isTrue, + disabled: isLoading || this.isEditing.isTrue || this.isDeleting.isTrue || disableEdit, icon: "edit", isGuarded: isGuarded, onClick: this.isEditing.setTrue, size: "small", type: "primary" - }, "Edit"); + }, "Edit")); } }]); return EditableCard; -}(React.Component), _class3$3.defaultProps = _objectSpread2({}, formPropsDefaults), _temp$9), (_descriptor$4 = _applyDecoratedDescriptor(_class2$g.prototype, "isDeleting", [mobx.observable], { +}(React.Component), _class3$3.defaultProps = _objectSpread2({}, formPropsDefaults, { + disableDelete: false, + disableDeleteTooltip: '', + disableEdit: false, + disableEditTooltip: '' +}), _temp$9), (_descriptor$4 = _applyDecoratedDescriptor(_class2$g.prototype, "isDeleting", [mobx.observable], { configurable: true, enumerable: true, writable: true, @@ -3776,16 +3794,20 @@ function (_Component) { title = _this$props2.title, isLoading = _this$props2.isLoading, isGuarded = _this$props2.isGuarded, + disableAdd = _this$props2.disableAdd, + disableAddTooltip = _this$props2.disableAddTooltip, classNameSuffix = this.props.classNameSuffix || lodash.kebabCase(title); - return React__default.createElement(GuardedButton, { + return React__default.createElement(Antd.Tooltip, { + title: disableAdd ? disableAddTooltip : '' + }, React__default.createElement(GuardedButton, { className: "btn-new btn-new-".concat(classNameSuffix), - disabled: isLoading || this.isAddingNew.isTrue, + disabled: isLoading || this.isAddingNew.isTrue || disableAdd, icon: "plus", isGuarded: isGuarded, onClick: this.isAddingNew.setTrue, size: "small", type: "primary" - }, "Add"); + }, "Add")); } }, { key: "render", @@ -3798,7 +3820,11 @@ function (_Component) { onDelete = _this$props3.onDelete, onSave = _this$props3.onSave, onSuccess = _this$props3.onSuccess, - title = _this$props3.title; + title = _this$props3.title, + disableDeleteTooltip = _this$props3.disableDeleteTooltip, + disableDelete = _this$props3.disableDelete, + disableEditTooltip = _this$props3.disableEditTooltip, + disableEdit = _this$props3.disableEdit; return React__default.createElement(Antd.Card, { title: title, extra: this.renderAddNew(), @@ -3820,6 +3846,10 @@ function (_Component) { onDelete: onDelete, onSave: onSave, onSuccess: onSuccess, + disableDeleteTooltip: disableDeleteTooltip, + disableDelete: disableDelete ? disableDelete(modelItem) : false, + disableEditTooltip: disableEditTooltip, + disableEdit: disableEdit ? disableEdit(modelItem) : false, title: "" }); })); @@ -3827,7 +3857,18 @@ function (_Component) { }]); return EditableArrayCard; -}(React.Component), _class3$4.defaultProps = _objectSpread2({}, formPropsDefaults), _temp$a), (_descriptor$5 = _applyDecoratedDescriptor(_class2$h.prototype, "isAddingNew", [mobx.observable], { +}(React.Component), _class3$4.defaultProps = _objectSpread2({}, formPropsDefaults, { + disableAdd: false, + disableAddTooltip: '', + disableDelete: function disableDelete() { + return false; + }, + disableDeleteTooltip: '', + disableEdit: function disableEdit() { + return false; + }, + disableEditTooltip: '' +}), _temp$a), (_descriptor$5 = _applyDecoratedDescriptor(_class2$h.prototype, "isAddingNew", [mobx.observable], { configurable: true, enumerable: true, writable: true, @@ -4274,6 +4315,7 @@ exports.filterFieldSets = filterFieldSets; exports.formPropsDefaults = formPropsDefaults; exports.formatOptionSelect = formatOptionSelect; exports.formatRating = formatRating; +exports.getBtnClassName = getBtnClassName; exports.getDateFormatList = getDateFormatList; exports.getFieldSetFields = getFieldSetFields; exports.getFieldSetsFields = getFieldSetsFields; diff --git a/dist/fieldsAnt.esm.js b/dist/fieldsAnt.esm.js index ed505f23..74333963 100644 --- a/dist/fieldsAnt.esm.js +++ b/dist/fieldsAnt.esm.js @@ -4,7 +4,7 @@ import autoBindMethods from 'class-autobind-decorator'; import cx from 'classnames'; import { Form as Form$1, Col, Select, Icon, Button, Tooltip, Input, Radio, Rate as Rate$1, Checkbox as Checkbox$1, DatePicker, notification, Row, Popconfirm, Divider, Card as Card$1, Drawer, Modal, List, Table as Table$1 } from 'antd'; import { toJS, observable, computed } from 'mobx'; -import { get, values, omit, debounce, uniqBy, pick, isObject, isBoolean, isArray, flatten, sortBy, has, set, some, isPlainObject, extend, mapValues, pickBy, noop, isEmpty, kebabCase } from 'lodash'; +import { get, values, omit, debounce, uniqBy, pick, isObject, isBoolean, isArray, flatten, sortBy, has, set, isString, kebabCase, some, isPlainObject, extend, mapValues, pickBy, noop, isEmpty } from 'lodash'; import SmartBool from '@mighty-justice/smart-bool'; import { toKey, inferCentury, getNameOrDefault, EMPTY_FIELD, mapBooleanToText, isValidDate, formatDate, formatEmployerIdNumber, formatMoney, formatCommaSeparatedNumber, getPercentValue, formatPercentage, getPercentDisplay, formatPhoneNumber, formatSocialSecurityNumber, parseAndPreserveNewlines, formatWebsite, formatAddressMultiline, varToLabel, getOrDefault, createDisabledContainer, createGuardedContainer, splitName } from '@mighty-justice/utils'; import moment from 'moment'; @@ -2271,6 +2271,10 @@ function noopValidator(_rule, _value, callback) { // Useful for clearing manually-set backend validation errors callback(); } +function getBtnClassName(action, classNameSuffix, title) { + var prefix = "btn-".concat(action); + return cx(prefix, isString(title) && "".concat(prefix, "-").concat(kebabCase(title)), _defineProperty({}, "".concat(prefix, "-").concat(classNameSuffix), !!classNameSuffix)); +} // Takes an API response and converts it to a string to string map function getFieldErrors(errors) { @@ -3637,26 +3641,31 @@ function (_Component) { key: "deleteButton", get: function get() { var _this$props3 = this.props, + classNameSuffix = _this$props3.classNameSuffix, + disableDeleteTooltip = _this$props3.disableDeleteTooltip, + disableDelete = _this$props3.disableDelete, isGuarded = _this$props3.isGuarded, - title = _this$props3.title, - onDelete = _this$props3.onDelete, isLoading = _this$props3.isLoading, - classNameSuffix = this.props.classNameSuffix || kebabCase(title); + onDelete = _this$props3.onDelete, + title = _this$props3.title, + className = getBtnClassName('delete', classNameSuffix, title); if (!onDelete) { return; } - return React.createElement(GuardedButton, { - className: "btn-delete btn-delete-".concat(classNameSuffix), + return React.createElement(Tooltip, { + title: disableDelete ? disableDeleteTooltip : '' + }, React.createElement(GuardedButton, { + className: className, confirm: true, - disabled: isLoading || this.isDeleting.isTrue, + disabled: disableDelete || isLoading || this.isDeleting.isTrue, icon: "delete", isGuarded: isGuarded, onClick: this.handleDelete, size: "small", type: "danger" - }, "Delete"); + }, "Delete")); } }, { key: "editButton", @@ -3665,21 +3674,30 @@ function (_Component) { isLoading = _this$props4.isLoading, title = _this$props4.title, isGuarded = _this$props4.isGuarded, + disableEdit = _this$props4.disableEdit, + disableEditTooltip = _this$props4.disableEditTooltip, classNameSuffix = this.props.classNameSuffix || kebabCase(title); - return React.createElement(GuardedButton, { + return React.createElement(Tooltip, { + title: disableEdit ? disableEditTooltip : '' + }, React.createElement(GuardedButton, { className: "btn-edit btn-edit-".concat(classNameSuffix), - disabled: isLoading || this.isEditing.isTrue || this.isDeleting.isTrue, + disabled: isLoading || this.isEditing.isTrue || this.isDeleting.isTrue || disableEdit, icon: "edit", isGuarded: isGuarded, onClick: this.isEditing.setTrue, size: "small", type: "primary" - }, "Edit"); + }, "Edit")); } }]); return EditableCard; -}(Component), _class3$3.defaultProps = _objectSpread2({}, formPropsDefaults), _temp$9), (_descriptor$4 = _applyDecoratedDescriptor(_class2$g.prototype, "isDeleting", [observable], { +}(Component), _class3$3.defaultProps = _objectSpread2({}, formPropsDefaults, { + disableDelete: false, + disableDeleteTooltip: '', + disableEdit: false, + disableEditTooltip: '' +}), _temp$9), (_descriptor$4 = _applyDecoratedDescriptor(_class2$g.prototype, "isDeleting", [observable], { configurable: true, enumerable: true, writable: true, @@ -3769,16 +3787,20 @@ function (_Component) { title = _this$props2.title, isLoading = _this$props2.isLoading, isGuarded = _this$props2.isGuarded, + disableAdd = _this$props2.disableAdd, + disableAddTooltip = _this$props2.disableAddTooltip, classNameSuffix = this.props.classNameSuffix || kebabCase(title); - return React.createElement(GuardedButton, { + return React.createElement(Tooltip, { + title: disableAdd ? disableAddTooltip : '' + }, React.createElement(GuardedButton, { className: "btn-new btn-new-".concat(classNameSuffix), - disabled: isLoading || this.isAddingNew.isTrue, + disabled: isLoading || this.isAddingNew.isTrue || disableAdd, icon: "plus", isGuarded: isGuarded, onClick: this.isAddingNew.setTrue, size: "small", type: "primary" - }, "Add"); + }, "Add")); } }, { key: "render", @@ -3791,7 +3813,11 @@ function (_Component) { onDelete = _this$props3.onDelete, onSave = _this$props3.onSave, onSuccess = _this$props3.onSuccess, - title = _this$props3.title; + title = _this$props3.title, + disableDeleteTooltip = _this$props3.disableDeleteTooltip, + disableDelete = _this$props3.disableDelete, + disableEditTooltip = _this$props3.disableEditTooltip, + disableEdit = _this$props3.disableEdit; return React.createElement(Card$1, { title: title, extra: this.renderAddNew(), @@ -3813,6 +3839,10 @@ function (_Component) { onDelete: onDelete, onSave: onSave, onSuccess: onSuccess, + disableDeleteTooltip: disableDeleteTooltip, + disableDelete: disableDelete ? disableDelete(modelItem) : false, + disableEditTooltip: disableEditTooltip, + disableEdit: disableEdit ? disableEdit(modelItem) : false, title: "" }); })); @@ -3820,7 +3850,18 @@ function (_Component) { }]); return EditableArrayCard; -}(Component), _class3$4.defaultProps = _objectSpread2({}, formPropsDefaults), _temp$a), (_descriptor$5 = _applyDecoratedDescriptor(_class2$h.prototype, "isAddingNew", [observable], { +}(Component), _class3$4.defaultProps = _objectSpread2({}, formPropsDefaults, { + disableAdd: false, + disableAddTooltip: '', + disableDelete: function disableDelete() { + return false; + }, + disableDeleteTooltip: '', + disableEdit: function disableEdit() { + return false; + }, + disableEditTooltip: '' +}), _temp$a), (_descriptor$5 = _applyDecoratedDescriptor(_class2$h.prototype, "isAddingNew", [observable], { configurable: true, enumerable: true, writable: true, @@ -4215,4 +4256,4 @@ function (_Component) { return Table; }(Component), (_applyDecoratedDescriptor(_class2$l.prototype, "columns", [computed], Object.getOwnPropertyDescriptor(_class2$l.prototype, "columns"), _class2$l.prototype), _applyDecoratedDescriptor(_class2$l.prototype, "dataSource", [computed], Object.getOwnPropertyDescriptor(_class2$l.prototype, "dataSource"), _class2$l.prototype)), _class2$l)) || _class$x) || _class$x; -export { ArrayCard, ButtonToolbar, CARD_COL_LABEL, CARD_COL_VALUE, CX_PREFIX_SEARCH_CREATE, Card, CardField, DEFAULT_DEBOUNCE_WAIT, DEFAULT_STATE_OPTION_TYPE, Date, EditableArrayCard, EditableCard, Form, FormCard, FormDrawer, FormField, FormFieldSet, FormItem, FormManager, FormModal, GuardedButton, Hidden, ID_ATTR, Info, Label, NestedFieldSet, ObjectSearch, ObjectSearchCreate, OptionSelect, OptionSelectDisplay, REGEXP_EIN, REGEXP_SSN, RadioGroup, Rate, SummaryCard, TYPES, Table, Value, backendValidation, booleanToForm, falseyToString, fieldSetsToColumns, fillInFieldConfig, fillInFieldSet, fillInFieldSets, filterFieldConfig, filterFieldConfigs, filterFieldSet, filterFieldSets, formPropsDefaults, formatOptionSelect, formatRating, getDateFormatList, getFieldSetFields, getFieldSetsFields, getOptions, getUnsortedOptions, isFieldSetSimple, isPartialFieldSetSimple, mapFieldSetFields, modelFromFieldConfigs, noopValidator, renderLabel, renderValue, setFieldSetFields }; +export { ArrayCard, ButtonToolbar, CARD_COL_LABEL, CARD_COL_VALUE, CX_PREFIX_SEARCH_CREATE, Card, CardField, DEFAULT_DEBOUNCE_WAIT, DEFAULT_STATE_OPTION_TYPE, Date, EditableArrayCard, EditableCard, Form, FormCard, FormDrawer, FormField, FormFieldSet, FormItem, FormManager, FormModal, GuardedButton, Hidden, ID_ATTR, Info, Label, NestedFieldSet, ObjectSearch, ObjectSearchCreate, OptionSelect, OptionSelectDisplay, REGEXP_EIN, REGEXP_SSN, RadioGroup, Rate, SummaryCard, TYPES, Table, Value, backendValidation, booleanToForm, falseyToString, fieldSetsToColumns, fillInFieldConfig, fillInFieldSet, fillInFieldSets, filterFieldConfig, filterFieldConfigs, filterFieldSet, filterFieldSets, formPropsDefaults, formatOptionSelect, formatRating, getBtnClassName, getDateFormatList, getFieldSetFields, getFieldSetsFields, getOptions, getUnsortedOptions, isFieldSetSimple, isPartialFieldSetSimple, mapFieldSetFields, modelFromFieldConfigs, noopValidator, renderLabel, renderValue, setFieldSetFields }; diff --git a/dist/fieldsAnt.umd.js b/dist/fieldsAnt.umd.js index 39c25aef..64701e48 100644 --- a/dist/fieldsAnt.umd.js +++ b/dist/fieldsAnt.umd.js @@ -2270,6 +2270,10 @@ // Useful for clearing manually-set backend validation errors callback(); } + function getBtnClassName(action, classNameSuffix, title) { + var prefix = "btn-".concat(action); + return cx(prefix, lodash.isString(title) && "".concat(prefix, "-").concat(lodash.kebabCase(title)), _defineProperty({}, "".concat(prefix, "-").concat(classNameSuffix), !!classNameSuffix)); + } // Takes an API response and converts it to a string to string map function getFieldErrors(errors) { @@ -3636,26 +3640,31 @@ key: "deleteButton", get: function get() { var _this$props3 = this.props, + classNameSuffix = _this$props3.classNameSuffix, + disableDeleteTooltip = _this$props3.disableDeleteTooltip, + disableDelete = _this$props3.disableDelete, isGuarded = _this$props3.isGuarded, - title = _this$props3.title, - onDelete = _this$props3.onDelete, isLoading = _this$props3.isLoading, - classNameSuffix = this.props.classNameSuffix || lodash.kebabCase(title); + onDelete = _this$props3.onDelete, + title = _this$props3.title, + className = getBtnClassName('delete', classNameSuffix, title); if (!onDelete) { return; } - return React__default.createElement(GuardedButton, { - className: "btn-delete btn-delete-".concat(classNameSuffix), + return React__default.createElement(Antd.Tooltip, { + title: disableDelete ? disableDeleteTooltip : '' + }, React__default.createElement(GuardedButton, { + className: className, confirm: true, - disabled: isLoading || this.isDeleting.isTrue, + disabled: disableDelete || isLoading || this.isDeleting.isTrue, icon: "delete", isGuarded: isGuarded, onClick: this.handleDelete, size: "small", type: "danger" - }, "Delete"); + }, "Delete")); } }, { key: "editButton", @@ -3664,21 +3673,30 @@ isLoading = _this$props4.isLoading, title = _this$props4.title, isGuarded = _this$props4.isGuarded, + disableEdit = _this$props4.disableEdit, + disableEditTooltip = _this$props4.disableEditTooltip, classNameSuffix = this.props.classNameSuffix || lodash.kebabCase(title); - return React__default.createElement(GuardedButton, { + return React__default.createElement(Antd.Tooltip, { + title: disableEdit ? disableEditTooltip : '' + }, React__default.createElement(GuardedButton, { className: "btn-edit btn-edit-".concat(classNameSuffix), - disabled: isLoading || this.isEditing.isTrue || this.isDeleting.isTrue, + disabled: isLoading || this.isEditing.isTrue || this.isDeleting.isTrue || disableEdit, icon: "edit", isGuarded: isGuarded, onClick: this.isEditing.setTrue, size: "small", type: "primary" - }, "Edit"); + }, "Edit")); } }]); return EditableCard; - }(React.Component), _class3$3.defaultProps = _objectSpread2({}, formPropsDefaults), _temp$9), (_descriptor$4 = _applyDecoratedDescriptor(_class2$g.prototype, "isDeleting", [mobx.observable], { + }(React.Component), _class3$3.defaultProps = _objectSpread2({}, formPropsDefaults, { + disableDelete: false, + disableDeleteTooltip: '', + disableEdit: false, + disableEditTooltip: '' + }), _temp$9), (_descriptor$4 = _applyDecoratedDescriptor(_class2$g.prototype, "isDeleting", [mobx.observable], { configurable: true, enumerable: true, writable: true, @@ -3768,16 +3786,20 @@ title = _this$props2.title, isLoading = _this$props2.isLoading, isGuarded = _this$props2.isGuarded, + disableAdd = _this$props2.disableAdd, + disableAddTooltip = _this$props2.disableAddTooltip, classNameSuffix = this.props.classNameSuffix || lodash.kebabCase(title); - return React__default.createElement(GuardedButton, { + return React__default.createElement(Antd.Tooltip, { + title: disableAdd ? disableAddTooltip : '' + }, React__default.createElement(GuardedButton, { className: "btn-new btn-new-".concat(classNameSuffix), - disabled: isLoading || this.isAddingNew.isTrue, + disabled: isLoading || this.isAddingNew.isTrue || disableAdd, icon: "plus", isGuarded: isGuarded, onClick: this.isAddingNew.setTrue, size: "small", type: "primary" - }, "Add"); + }, "Add")); } }, { key: "render", @@ -3790,7 +3812,11 @@ onDelete = _this$props3.onDelete, onSave = _this$props3.onSave, onSuccess = _this$props3.onSuccess, - title = _this$props3.title; + title = _this$props3.title, + disableDeleteTooltip = _this$props3.disableDeleteTooltip, + disableDelete = _this$props3.disableDelete, + disableEditTooltip = _this$props3.disableEditTooltip, + disableEdit = _this$props3.disableEdit; return React__default.createElement(Antd.Card, { title: title, extra: this.renderAddNew(), @@ -3812,6 +3838,10 @@ onDelete: onDelete, onSave: onSave, onSuccess: onSuccess, + disableDeleteTooltip: disableDeleteTooltip, + disableDelete: disableDelete ? disableDelete(modelItem) : false, + disableEditTooltip: disableEditTooltip, + disableEdit: disableEdit ? disableEdit(modelItem) : false, title: "" }); })); @@ -3819,7 +3849,18 @@ }]); return EditableArrayCard; - }(React.Component), _class3$4.defaultProps = _objectSpread2({}, formPropsDefaults), _temp$a), (_descriptor$5 = _applyDecoratedDescriptor(_class2$h.prototype, "isAddingNew", [mobx.observable], { + }(React.Component), _class3$4.defaultProps = _objectSpread2({}, formPropsDefaults, { + disableAdd: false, + disableAddTooltip: '', + disableDelete: function disableDelete() { + return false; + }, + disableDeleteTooltip: '', + disableEdit: function disableEdit() { + return false; + }, + disableEditTooltip: '' + }), _temp$a), (_descriptor$5 = _applyDecoratedDescriptor(_class2$h.prototype, "isAddingNew", [mobx.observable], { configurable: true, enumerable: true, writable: true, @@ -4266,6 +4307,7 @@ exports.formPropsDefaults = formPropsDefaults; exports.formatOptionSelect = formatOptionSelect; exports.formatRating = formatRating; + exports.getBtnClassName = getBtnClassName; exports.getDateFormatList = getDateFormatList; exports.getFieldSetFields = getFieldSetFields; exports.getFieldSetsFields = getFieldSetsFields; diff --git a/dist/utilities/common.d.ts b/dist/utilities/common.d.ts index 90c7c4cf..95711ca4 100644 --- a/dist/utilities/common.d.ts +++ b/dist/utilities/common.d.ts @@ -22,4 +22,5 @@ declare type IColumns = Array>; export declare function fieldSetsToColumns(fieldSets: IFieldSetPartial[], tableModel?: IModel[]): IColumns; export declare function modelFromFieldConfigs(fieldConfigs: IFieldConfig[], data: IModel): IModel; export declare function noopValidator(_rule: any, _value: any, callback: (message?: string) => void): void; +export declare function getBtnClassName(action: string, classNameSuffix?: string, title?: React.ReactNode): string; export {}; diff --git a/package.json b/package.json index 1a92195f..48dc985f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mighty-justice/fields-ant", - "version": "1.3.3-1", + "version": "1.3.3-3", "description": "Standard Ant design component interface for Field Sets", "main": "dist/fieldsAnt.cjs.js", "module": "dist/fieldsAnt.esm.js", @@ -150,7 +150,7 @@ "@mighty-justice/smart-bool": "^1.0.0", "@mighty-justice/utils": "1.3.6", "class-autobind-decorator": "^3.0.1", - "classnames": "^2.2.6", + "classnames": "^2.3.2", "date-fns": "^2.9.0", "flat": "^5.0.0", "http-status-codes": "^1.4.0", diff --git a/src/components/EditableArrayCard.tsx b/src/components/EditableArrayCard.tsx index e33f23dc..6fece805 100644 --- a/src/components/EditableArrayCard.tsx +++ b/src/components/EditableArrayCard.tsx @@ -4,7 +4,6 @@ import { observer } from 'mobx-react'; import { isEmpty, kebabCase } from 'lodash'; import autoBindMethods from 'class-autobind-decorator'; import SmartBool from '@mighty-justice/smart-bool'; - import * as Antd from 'antd'; import GuardedButton from '../building-blocks/GuardedButton'; @@ -19,6 +18,12 @@ export interface IEditableArrayCardProps extends IArrayCardProps, ISharedFormPro defaults?: object; onCreate: (model: unknown) => Promise; onDelete?: (model: unknown) => Promise; + disableAdd?: boolean; + disableAddTooltip?: string; + disableDeleteTooltip?: string; + disableDelete?: (model: any) => boolean; + disableEditTooltip?: string; + disableEdit?: (model: any) => boolean; } @autoBindMethods @@ -28,6 +33,12 @@ class EditableArrayCard extends Component { public static defaultProps: Partial = { ...formPropsDefaults, + disableAdd: false, + disableAddTooltip: '', + disableDelete: () => false, + disableDeleteTooltip: '', + disableEdit: () => false, + disableEditTooltip: '', }; private async handleSaveNew (model: any) { @@ -38,21 +49,23 @@ class EditableArrayCard extends Component { } private renderAddNew () { - const { title, isLoading, isGuarded } = this.props + const { title, isLoading, isGuarded, disableAdd, disableAddTooltip } = this.props , classNameSuffix = this.props.classNameSuffix || kebabCase(title); return ( - - Add - + + + Add + + ); } @@ -66,6 +79,10 @@ class EditableArrayCard extends Component { onSave, onSuccess, title, + disableDeleteTooltip, + disableDelete, + disableEditTooltip, + disableEdit, } = this.props; return ( @@ -93,6 +110,10 @@ class EditableArrayCard extends Component { onDelete={onDelete} onSave={onSave} onSuccess={onSuccess} + disableDeleteTooltip={disableDeleteTooltip} + disableDelete={disableDelete ? disableDelete(modelItem) : false} + disableEditTooltip={disableEditTooltip} + disableEdit={disableEdit ? disableEdit(modelItem) : false} title='' /> ))} diff --git a/src/components/EditableCard.tsx b/src/components/EditableCard.tsx index 3cb96890..59546617 100644 --- a/src/components/EditableCard.tsx +++ b/src/components/EditableCard.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import { observable } from 'mobx'; import autoBindMethods from 'class-autobind-decorator'; import { kebabCase } from 'lodash'; - +import { Tooltip } from 'antd'; import SmartBool from '@mighty-justice/smart-bool'; import ButtonToolbar from '../building-blocks/ButtonToolbar'; @@ -15,8 +15,13 @@ import Card, { ICardProps } from './Card'; import FormCard from './FormCard'; import FormDrawer from './FormDrawer'; import FormModal from './FormModal'; +import { getBtnClassName } from '../utilities'; export interface IEditableCardProps extends ICardProps, ISharedFormProps { + disableDeleteTooltip?: string; + disableDelete: boolean; + disableEditTooltip?: string; + disableEdit: boolean; ModalComponent: new (props: ISharedFormModalProps) => FormModal | FormDrawer; onDelete?: (model: unknown) => Promise; } @@ -29,6 +34,10 @@ class EditableCard extends Component { public static defaultProps: Partial = { ...formPropsDefaults, + disableDelete: false, + disableDeleteTooltip: '', + disableEdit: false, + disableEditTooltip: '', }; private async handleDelete () { @@ -55,43 +64,54 @@ class EditableCard extends Component { } private get deleteButton () { - const { isGuarded, title, onDelete, isLoading } = this.props - , classNameSuffix = this.props.classNameSuffix || kebabCase(title); - + const { + classNameSuffix, + disableDeleteTooltip, + disableDelete, + isGuarded, + isLoading, + onDelete, + title, + } = this.props, + className = getBtnClassName('delete', classNameSuffix, title); if (!onDelete) { return; } return ( - - Delete - + + + Delete + + ); } private get editButton () { - const { isLoading, title, isGuarded } = this.props + const { isLoading, title, isGuarded, disableEdit, disableEditTooltip } = this.props , classNameSuffix = this.props.classNameSuffix || kebabCase(title); return ( - - Edit - + + + Edit + + ); } diff --git a/src/utilities/common.tsx b/src/utilities/common.tsx index 325743f2..56d3d880 100644 --- a/src/utilities/common.tsx +++ b/src/utilities/common.tsx @@ -5,11 +5,13 @@ import { has, isArray, isObject, + isString, + kebabCase, set, some, sortBy, } from 'lodash'; - +import cx from 'classnames'; import { ColumnProps } from 'antd/es/table'; import { @@ -183,3 +185,10 @@ export function noopValidator (_rule: any, _value: any, callback: (message?: str // Useful for clearing manually-set backend validation errors callback(); } + +export function getBtnClassName (action: string, classNameSuffix?: string, title?: React.ReactNode): string { + const prefix = `btn-${action}`; + return cx(prefix, isString(title) && `${prefix}-${kebabCase(title)}`, { + [`${prefix}-${classNameSuffix}`]: !!classNameSuffix, + }); +} diff --git a/test/components/EditableArrayCard.test.ts b/test/components/EditableArrayCard.test.ts index 782007b1..d5b06519 100644 --- a/test/components/EditableArrayCard.test.ts +++ b/test/components/EditableArrayCard.test.ts @@ -2,7 +2,7 @@ import faker from 'faker'; import { EditableArrayCard } from '../../src'; import { Tester } from '@mighty-justice/tester'; -import { fakeTextShort } from '../factories'; +import { arrayCardPropsFactory, fakeTextShort } from '../factories'; const title = faker.lorem.sentence() , model = Array(10).fill(null).map(_ => ({ @@ -59,4 +59,31 @@ describe('EditableArrayCard', () => { expect(tester.find('input#name').length).toBe(0); }); }); + + it('Can disable add', async () => { + const props = { + ...arrayCardPropsFactory.build(), + disableAdd: true, + }, + tester = await new Tester(EditableArrayCard, { props }).mount(); + + expect(tester.find('button.btn-new').props().disabled).toBe(true); + }); + + it('Can disabled delete and edit', async () => { + const permissionName = 'canUpdate' + , props = { + ...arrayCardPropsFactory.build(), + disableDelete: model => !model.permissions.includes(permissionName), + disableEdit: model => !model.permissions.includes(permissionName), + model: [{ + permissions: [], + }], + onDelete: jest.fn().mockResolvedValue({}), + }, + tester = await new Tester(EditableArrayCard, { props }).mount(); + + expect(tester.find('button.btn-delete').props().disabled).toBe(true); + expect(tester.find('button.btn-edit').props().disabled).toBe(true); + }) }); diff --git a/test/components/EditableCard.test.ts b/test/components/EditableCard.test.ts index 81f8f1c4..87f604c7 100644 --- a/test/components/EditableCard.test.ts +++ b/test/components/EditableCard.test.ts @@ -55,4 +55,16 @@ describe('EditableCard', () => { tester.click('.btn-delete .ant-popover-inner .ant-btn-primary'); expect(onDelete).toHaveBeenCalled(); }); + + it('Can disable delete and edit buttons', async () => { + const props = { + ...editableCardPropsFactory.build(), + disableDelete: true, + disableEdit: true, + }, + tester = await new Tester(EditableCard, { props }).mount(); + + expect(tester.find('button.btn-delete').props().disabled).toBe(true); + expect(tester.find('button.btn-edit').props().disabled).toBe(true); + }); }); diff --git a/yarn.lock b/yarn.lock index 88cbbc41..a256f956 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3969,6 +3969,11 @@ classnames@2.x, classnames@^2.2.0, classnames@^2.2.1, classnames@^2.2.3, classna resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== +classnames@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== + clean-css@4.2.x, clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"