@reltio/components 1.4.1165 → 1.4.1169

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/cjs/components/EntityTypeBadge/EntityTypeBadge.js +7 -4
  2. package/cjs/components/EntityTypeBadge/styles.d.ts +1 -1
  3. package/cjs/components/EntityTypeBadge/styles.js +5 -2
  4. package/cjs/components/ProfileCard/styles.js +1 -0
  5. package/cjs/components/attributes/editMode/AttributesList/AttributesList.d.ts +3 -1
  6. package/cjs/components/attributes/editMode/AttributesList/AttributesList.js +9 -4
  7. package/cjs/components/attributes/editMode/ComplexAttribute/ComplexAttribute.js +1 -1
  8. package/cjs/components/attributes/editMode/MoreAttributesButton/MoreAttributesButton.d.ts +3 -1
  9. package/cjs/components/attributes/editMode/MoreAttributesButton/MoreAttributesButton.js +22 -23
  10. package/cjs/components/attributes/editMode/MoreAttributesButton/helpers.d.ts +8 -0
  11. package/cjs/components/attributes/editMode/MoreAttributesButton/helpers.js +18 -0
  12. package/cjs/components/attributes/editMode/MoreAttributesButton/styles.d.ts +1 -1
  13. package/cjs/components/attributes/editMode/MoreAttributesButton/styles.js +20 -0
  14. package/cjs/components/attributes/editMode/MoreAttributesButton/useMoreAttributesItems.d.ts +22 -0
  15. package/cjs/components/attributes/editMode/MoreAttributesButton/useMoreAttributesItems.js +60 -0
  16. package/esm/components/EntityTypeBadge/EntityTypeBadge.js +7 -4
  17. package/esm/components/EntityTypeBadge/styles.d.ts +1 -1
  18. package/esm/components/EntityTypeBadge/styles.js +5 -2
  19. package/esm/components/ProfileCard/styles.js +1 -0
  20. package/esm/components/attributes/editMode/AttributesList/AttributesList.d.ts +3 -1
  21. package/esm/components/attributes/editMode/AttributesList/AttributesList.js +10 -5
  22. package/esm/components/attributes/editMode/ComplexAttribute/ComplexAttribute.js +1 -1
  23. package/esm/components/attributes/editMode/MoreAttributesButton/MoreAttributesButton.d.ts +3 -1
  24. package/esm/components/attributes/editMode/MoreAttributesButton/MoreAttributesButton.js +23 -24
  25. package/esm/components/attributes/editMode/MoreAttributesButton/helpers.d.ts +8 -0
  26. package/esm/components/attributes/editMode/MoreAttributesButton/helpers.js +15 -0
  27. package/esm/components/attributes/editMode/MoreAttributesButton/styles.d.ts +1 -1
  28. package/esm/components/attributes/editMode/MoreAttributesButton/styles.js +20 -0
  29. package/esm/components/attributes/editMode/MoreAttributesButton/useMoreAttributesItems.d.ts +22 -0
  30. package/esm/components/attributes/editMode/MoreAttributesButton/useMoreAttributesItems.js +53 -0
  31. package/package.json +3 -3
@@ -9,6 +9,7 @@ var classnames_1 = __importDefault(require("classnames"));
9
9
  var Typography_1 = __importDefault(require("@material-ui/core/Typography"));
10
10
  var mdm_sdk_1 = require("@reltio/mdm-sdk");
11
11
  var mdm_module_1 = __importDefault(require("@reltio/mdm-module"));
12
+ var ExpandedValueTooltip_1 = __importDefault(require("../ExpandedValueTooltip/ExpandedValueTooltip"));
12
13
  var styles_1 = __importDefault(require("./styles"));
13
14
  var EntityTypeBadge = function (_a) {
14
15
  var entity = _a.entity, className = _a.className, _b = _a.size, size = _b === void 0 ? 'small' : _b;
@@ -17,9 +18,11 @@ var EntityTypeBadge = function (_a) {
17
18
  var entityTypeUri = entity.type;
18
19
  var entityType = mdm_sdk_1.getEntityType(metadata, entityTypeUri) || {};
19
20
  var entityTypeColor = mdm_sdk_1.getPropWithInheritance(metadata, entityType, 'typeColor') || mdm_sdk_1.theme.palette.primary.main;
20
- return (react_1.default.createElement(Typography_1.default, { style: {
21
- backgroundColor: entityTypeColor,
22
- color: mdm_sdk_1.utils.Colors.getColor(entityTypeColor) ? '#FFFFFF' : '#212121'
23
- }, className: classnames_1.default(styles["entityType-" + size], className), component: "div" }, mdm_sdk_1.getEntityTypeLabel(metadata, entity)));
21
+ var entityTypeLabel = mdm_sdk_1.getEntityTypeLabel(metadata, entity);
22
+ return (react_1.default.createElement(ExpandedValueTooltip_1.default, { value: entityTypeLabel, placement: "top" },
23
+ react_1.default.createElement(Typography_1.default, { style: {
24
+ backgroundColor: entityTypeColor,
25
+ color: mdm_sdk_1.utils.Colors.getColor(entityTypeColor) ? '#FFFFFF' : '#212121'
26
+ }, className: classnames_1.default(styles["entityType-" + size], styles['entityType-overflow'], className), component: "div" }, entityTypeLabel)));
24
27
  };
25
28
  exports.default = EntityTypeBadge;
@@ -1,2 +1,2 @@
1
- declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"entityType-small" | "entityType-medium">;
1
+ declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"entityType-overflow" | "entityType-small" | "entityType-medium">;
2
2
  export default useStyles;
@@ -2,11 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  var styles_1 = require("@material-ui/core/styles");
4
4
  var useStyles = styles_1.makeStyles({
5
+ 'entityType-overflow': {
6
+ textOverflow: 'ellipsis',
7
+ overflow: 'hidden',
8
+ whiteSpace: 'nowrap'
9
+ },
5
10
  'entityType-small': {
6
11
  padding: '1px 4px',
7
12
  fontSize: '10px',
8
13
  lineHeight: 'normal',
9
- display: 'inline-flex',
10
14
  marginRight: '12px',
11
15
  borderRadius: '2px'
12
16
  },
@@ -16,7 +20,6 @@ var useStyles = styles_1.makeStyles({
16
20
  fontSize: '13px',
17
21
  fontWeight: 500,
18
22
  lineHeight: '15px',
19
- display: 'inline-flex',
20
23
  marginRight: '16px'
21
24
  }
22
25
  });
@@ -48,6 +48,7 @@ var useStyles = styles_1.makeStyles(function (theme) { return ({
48
48
  entityId: {
49
49
  display: 'flex',
50
50
  alignItems: 'baseline',
51
+ whiteSpace: 'nowrap',
51
52
  fontWeight: 400,
52
53
  fontSize: '12px',
53
54
  lineHeight: '16px'
@@ -1,5 +1,6 @@
1
1
  declare var _default: React.MemoExoticComponent<{
2
- ({ attrTypes, entity, parentUri, showEmptyEditors, mode, crosswalks, drawLines, children, className, alwaysVisibleTypeUris, onAddAttributes, onChangeAttribute, onDeleteAttribute, additionalControlsRenderer, showNonOv }: {
2
+ ({ parentAttributeType, attrTypes, entity, parentUri, showEmptyEditors, mode, crosswalks, drawLines, children, className, alwaysVisibleTypeUris, onAddAttributes, onChangeAttribute, onDeleteAttribute, additionalControlsRenderer, showNonOv }: {
3
+ parentAttributeType: any;
3
4
  attrTypes: any;
4
5
  entity: any;
5
6
  parentUri: any;
@@ -17,6 +18,7 @@ declare var _default: React.MemoExoticComponent<{
17
18
  showNonOv: any;
18
19
  }): JSX.Element;
19
20
  propTypes: {
21
+ parentAttributeType: PropTypes.Requireable<object>;
20
22
  attrTypes: PropTypes.Requireable<any[]>;
21
23
  entity: PropTypes.Requireable<object>;
22
24
  parentUri: PropTypes.Requireable<string>;
@@ -47,7 +47,7 @@ var helpers_1 = require("./helpers");
47
47
  var PinnedAttributesContext_1 = require("../contexts/PinnedAttributesContext");
48
48
  var HasDeletionsContext_1 = require("../contexts/HasDeletionsContext");
49
49
  var AttributesList = function (_a) {
50
- var attrTypes = _a.attrTypes, entity = _a.entity, parentUri = _a.parentUri, showEmptyEditors = _a.showEmptyEditors, mode = _a.mode, crosswalks = _a.crosswalks, drawLines = _a.drawLines, children = _a.children, className = _a.className, _b = _a.alwaysVisibleTypeUris, alwaysVisibleTypeUris = _b === void 0 ? constants_1.ALWAYS_VISIBLE_TYPE_URIS : _b, onAddAttributes = _a.onAddAttributes, onChangeAttribute = _a.onChangeAttribute, onDeleteAttribute = _a.onDeleteAttribute, additionalControlsRenderer = _a.additionalControlsRenderer, showNonOv = _a.showNonOv;
50
+ var parentAttributeType = _a.parentAttributeType, attrTypes = _a.attrTypes, entity = _a.entity, parentUri = _a.parentUri, showEmptyEditors = _a.showEmptyEditors, mode = _a.mode, crosswalks = _a.crosswalks, drawLines = _a.drawLines, children = _a.children, className = _a.className, _b = _a.alwaysVisibleTypeUris, alwaysVisibleTypeUris = _b === void 0 ? constants_1.ALWAYS_VISIBLE_TYPE_URIS : _b, onAddAttributes = _a.onAddAttributes, onChangeAttribute = _a.onChangeAttribute, onDeleteAttribute = _a.onDeleteAttribute, additionalControlsRenderer = _a.additionalControlsRenderer, showNonOv = _a.showNonOv;
51
51
  var _c = entity.attributes, attributes = _c === void 0 ? {} : _c;
52
52
  var _d = react_1.useState({}), hasDeletionsMap = _d[0], setHasDeletionsMap = _d[1];
53
53
  var setHasDeletions = react_1.useCallback(function (attrTypeUri, value) {
@@ -59,14 +59,18 @@ var AttributesList = function (_a) {
59
59
  react_1.useEffect(function () {
60
60
  setHasDeletionsMap({});
61
61
  }, [parentUri]);
62
+ var canCreateParentAttrType = react_1.useMemo(function () { return parentAttributeType && mdm_sdk_1.checkCanCreateAttribute({ attributeType: parentAttributeType, mode: mode }); }, [parentAttributeType, mode]);
62
63
  var creatableAttrTypes = react_1.useMemo(function () { return mdm_sdk_1.getCreatableAttributeTypes(mode, attrTypes); }, [attrTypes, mode]);
63
64
  var moreAttrTypes = helpers_1.getMoreAttrTypes(creatableAttrTypes, entity, showEmptyEditors, hasDeletionsMap);
64
65
  var pinnedAttributes = react_1.useContext(PinnedAttributesContext_1.PinnedAttributesContext);
65
66
  var pagersData = react_1.useMemo(function () { return mdm_sdk_1.getAttributesListForEditMode(attrTypes, mode, entity, showEmptyEditors, showNonOv, pinnedAttributes); }, [attrTypes, mode, entity, showEmptyEditors, showNonOv, pinnedAttributes]);
66
67
  var _e = react_1.useMemo(function () { return attributesView_1.splitPagersData(alwaysVisibleTypeUris, pagersData); }, [pagersData, alwaysVisibleTypeUris]), alwaysVisiblePagersData = _e[0], regularPagersData = _e[1];
67
68
  var onAddMoreAttributes = react_1.useCallback(function (attributeTypes) {
68
- onAddAttributes(attributeTypes.map(function (attributeType) { return ({ attributeType: attributeType, parentUri: parentUri }); }));
69
- }, [onAddAttributes, parentUri]);
69
+ onAddAttributes(attributeTypes.map(function (attributeType) { return ({
70
+ attributeType: attributeType,
71
+ parentUri: attributeType === parentAttributeType ? mdm_sdk_1.getParentUri(parentUri) : parentUri
72
+ }); }));
73
+ }, [onAddAttributes, parentUri, parentAttributeType]);
70
74
  var decoratorProps = {
71
75
  enabled: drawLines
72
76
  };
@@ -76,13 +80,14 @@ var AttributesList = function (_a) {
76
80
  }); }, [hasDeletionsMap, setHasDeletions]);
77
81
  return (react_1.default.createElement("div", { className: className },
78
82
  children && react_1.default.createElement(BranchDecorator_1.default, __assign({}, decoratorProps), children),
79
- react_1.default.createElement(BranchDecorator_1.default, __assign({}, decoratorProps, { plain: true }), moreAttrTypes.length > 0 && (react_1.default.createElement(MoreAttributesButton_1.default, { label: ui_i18n_1.default.text('More attributes'), onApply: onAddMoreAttributes, dense: drawLines, data: moreAttrTypes }))),
83
+ react_1.default.createElement(BranchDecorator_1.default, __assign({}, decoratorProps, { plain: true }), moreAttrTypes.length > 0 && (react_1.default.createElement(MoreAttributesButton_1.default, { label: ui_i18n_1.default.text('More attributes'), onApply: onAddMoreAttributes, dense: drawLines, data: moreAttrTypes, parent: canCreateParentAttrType && parentAttributeType }))),
80
84
  react_1.default.createElement(HasDeletionsContext_1.HasDeletionsContext.Provider, { value: hasDeletionsContextValue }, regularPagersData.concat(alwaysVisiblePagersData).map(function (_a) {
81
85
  var attrType = _a.attrType, values = _a.values;
82
86
  return (react_1.default.createElement(AttributesPager_1.default, { key: attrType.uri, attributeType: attrType, drawLines: drawLines, values: values, paging: ramda_1.path(['paging', attrType.uri], attributes), parentUri: parentUri, showEmptyEditors: showEmptyEditors, mode: mode, crosswalks: crosswalks, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute, additionalControlsRenderer: additionalControlsRenderer, showNonOv: showNonOv }));
83
87
  }))));
84
88
  };
85
89
  AttributesList.propTypes = {
90
+ parentAttributeType: prop_types_1.default.object,
86
91
  attrTypes: prop_types_1.default.array,
87
92
  entity: prop_types_1.default.object,
88
93
  parentUri: prop_types_1.default.string,
@@ -103,7 +103,7 @@ var ComplexAttribute = function (_a) {
103
103
  ")")),
104
104
  additionalControlsRenderer && additionalControlsRenderer({ attributeType: attributeType, attributeValue: attributeValue }),
105
105
  showDeleteButton && react_1.default.createElement(SmallIconButton_1.default, { icon: Delete_1.default, onClick: onDeleteThis, size: "L" }))),
106
- expanded && (react_1.default.createElement(AttributesList_1.default, { attrTypes: attributeTypesList, entity: attributeListEntity, showEmptyEditors: showEmptyEditors || isNew, drawLines: true, parentUri: uri, mode: mode, crosswalks: crosswalks, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute, additionalControlsRenderer: additionalControlsRenderer, showNonOv: showNonOv }, children))));
106
+ expanded && (react_1.default.createElement(AttributesList_1.default, { parentAttributeType: attributeType, attrTypes: attributeTypesList, entity: attributeListEntity, showEmptyEditors: showEmptyEditors || isNew, drawLines: true, parentUri: uri, mode: mode, crosswalks: crosswalks, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute, additionalControlsRenderer: additionalControlsRenderer, showNonOv: showNonOv }, children))));
107
107
  };
108
108
  ComplexAttribute.propTypes = __assign({ label: prop_types_1.default.string, children: prop_types_1.default.node, attributeTypesList: prop_types_1.default.arrayOf(mdm_sdk_1.AttributeTypeType), attributeValue: prop_types_1.default.oneOfType([mdm_sdk_1.NestedAttributeValueType, mdm_sdk_1.ReferenceAttributeValueType]) }, mdm_sdk_1.ComplexAttributeType);
109
109
  exports.default = ComplexAttribute;
@@ -1,8 +1,9 @@
1
1
  export default MoreAttributesButton;
2
- declare function MoreAttributesButton({ label, popupTitle, data, dense, onApply }: {
2
+ declare function MoreAttributesButton({ label, popupTitle, data, parent, dense, onApply }: {
3
3
  label: any;
4
4
  popupTitle?: any;
5
5
  data: any;
6
+ parent: any;
6
7
  dense: any;
7
8
  onApply: any;
8
9
  }): JSX.Element;
@@ -11,6 +12,7 @@ declare namespace MoreAttributesButton {
11
12
  const label: PropTypes.Requireable<string>;
12
13
  const popupTitle: PropTypes.Requireable<string>;
13
14
  const data: PropTypes.Requireable<any[]>;
15
+ const parent: PropTypes.Requireable<object>;
14
16
  const dense: PropTypes.Requireable<boolean>;
15
17
  const onApply: PropTypes.Requireable<(...args: any[]) => any>;
16
18
  }
@@ -23,29 +23,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  var react_1 = __importStar(require("react"));
26
+ var ui_i18n_1 = __importDefault(require("ui-i18n"));
26
27
  var classnames_1 = __importDefault(require("classnames"));
27
28
  var prop_types_1 = __importDefault(require("prop-types"));
28
29
  var ramda_1 = require("ramda");
29
30
  var Button_1 = __importDefault(require("@material-ui/core/Button"));
31
+ var ListItem_1 = __importDefault(require("@material-ui/core/ListItem"));
32
+ var Typography_1 = __importDefault(require("@material-ui/core/Typography"));
30
33
  var styles_1 = require("./styles");
31
34
  var SelectionPopup_1 = __importDefault(require("../../../SelectionPopup/SelectionPopup"));
32
35
  var AttributeListItem_1 = __importDefault(require("../../../AttributeListItem/AttributeListItem"));
33
- var helpers_1 = require("../../../VirtualGroupedList/helpers");
34
36
  var VirtualGroupedList_1 = __importDefault(require("../../../VirtualGroupedList/VirtualGroupedList"));
35
- var helpers_2 = require("../../../SelectionPopup/helpers");
37
+ var helpers_1 = require("../../../SelectionPopup/helpers");
36
38
  var Add_1 = __importDefault(require("@material-ui/icons/Add"));
37
39
  var Highlighter_1 = __importDefault(require("../../../Highlighter/Highlighter"));
40
+ var useMoreAttributesItems_1 = require("./useMoreAttributesItems");
38
41
  var ITEM_HEIGHT = 28;
42
+ var ITEM_GROUP_TITLE_HEIGHT = 40;
39
43
  var LIST_CONTAINER_WIDTH = 320;
40
44
  var MAX_LIST_CONTAINER_HEIGHT = 255;
41
45
  var MIN_CONTAINER_HEIGHT = 140;
42
46
  var CONTAINER_HEADER_HEIGHT = 112;
43
- var filterItems = ramda_1.curry(function (filterText, items) {
44
- return ramda_1.filter(function (item) { return item.label.toLowerCase().includes(filterText.toLowerCase()); })(items);
45
- });
46
47
  var MoreAttributesButton = function (_a) {
47
48
  var _b;
48
- var label = _a.label, _c = _a.popupTitle, popupTitle = _c === void 0 ? label : _c, data = _a.data, dense = _a.dense, onApply = _a.onApply;
49
+ var label = _a.label, _c = _a.popupTitle, popupTitle = _c === void 0 ? label : _c, data = _a.data, parent = _a.parent, dense = _a.dense, onApply = _a.onApply;
49
50
  var styles = styles_1.useStyles();
50
51
  var inputRef = react_1.useRef();
51
52
  var _d = react_1.useState(false), isOpen = _d[0], setIsOpen = _d[1];
@@ -55,6 +56,7 @@ var MoreAttributesButton = function (_a) {
55
56
  var clearFilter = function () { return setFilter(''); };
56
57
  var _f = react_1.useState([]), selectedItems = _f[0], setSelectedItems = _f[1];
57
58
  var clearSelectedItems = function () { return setSelectedItems([]); };
59
+ var _g = useMoreAttributesItems_1.useMoreAttributesItems({ data: data, parent: parent, filter: filter }), items = _g.items, hasGroups = _g.hasGroups, parentGroupLength = _g.parentGroupLength, attributesGroupLength = _g.attributesGroupLength;
58
60
  var addSelectedAttributes = function () {
59
61
  if (selectedItems.length > 0) {
60
62
  onApply(ramda_1.pluck('attrType', selectedItems));
@@ -63,48 +65,45 @@ var MoreAttributesButton = function (_a) {
63
65
  var handleListItemClick = react_1.useCallback(function (item, checked) {
64
66
  setSelectedItems(ramda_1.ifElse(ramda_1.always(checked), ramda_1.append(item), ramda_1.reject(ramda_1.propEq('id', item.id)))(selectedItems));
65
67
  }, [selectedItems]);
66
- var preparedGroupedItems = react_1.useMemo(function () {
67
- return ramda_1.pipe(filterItems(filter), ramda_1.map(function (attrType) { return ({
68
- item: {
69
- id: attrType.uri,
70
- label: attrType.label,
71
- attrType: attrType
72
- }
73
- }); }))(data);
74
- }, [data, filter]);
75
- var items = react_1.useMemo(function () { return helpers_1.flattenGroupedItemsData(preparedGroupedItems); }, [preparedGroupedItems]);
76
- var getItemSize = react_1.useCallback(function () { return ITEM_HEIGHT; }, []);
68
+ var getItemSize = react_1.useCallback(function (i, item) { return (item.items ? ITEM_GROUP_TITLE_HEIGHT : ITEM_HEIGHT); }, []);
77
69
  var handleSearchOnEnter = react_1.useCallback(function (_a) {
78
70
  var item = _a.item;
79
71
  handleListItemClick(item, ramda_1.not(ramda_1.any(ramda_1.propEq('id', item.id))(selectedItems)));
80
72
  }, [handleListItemClick, selectedItems]);
81
- var _g = helpers_2.useKeyboardNavigation({
73
+ var _h = helpers_1.useKeyboardNavigation({
82
74
  items: items,
83
75
  open: isOpen,
84
76
  onSelectFocusedItem: handleSearchOnEnter,
85
77
  selectedItems: selectedItems
86
- }), focusIndex = _g.focusIndex, handleKeyDown = _g.handleKeyDown;
78
+ }), focusIndex = _h.focusIndex, handleKeyDown = _h.handleKeyDown;
87
79
  var focusIndexRef = react_1.useRef(null);
88
80
  focusIndexRef.current = focusIndex;
89
- var listHeight = Math.min(MAX_LIST_CONTAINER_HEIGHT, ITEM_HEIGHT * items.length);
81
+ var groupsCount = hasGroups ? (parentGroupLength ? 1 : 0) + (attributesGroupLength ? 1 : 0) : 0;
82
+ var itemsCount = items.length - groupsCount;
83
+ var listHeight = Math.min(MAX_LIST_CONTAINER_HEIGHT, ITEM_HEIGHT * itemsCount + ITEM_GROUP_TITLE_HEIGHT * groupsCount);
90
84
  var containerHeight = Math.max(MIN_CONTAINER_HEIGHT, listHeight + CONTAINER_HEADER_HEIGHT);
91
85
  var listItemRenderer = react_1.useCallback(function (style, _a, index) {
92
- var item = _a.item, _b = _a.level, level = _b === void 0 ? 0 : _b;
86
+ var _b;
87
+ var item = _a.item, _c = _a.level, level = _c === void 0 ? 0 : _c;
93
88
  var isChecked = ramda_1.any(ramda_1.propEq('id', item.id))(selectedItems);
94
89
  var isFocused = focusIndexRef.current === index;
95
- return (react_1.default.createElement(AttributeListItem_1.default, { key: item.uri, onClick: handleListItemClick, checked: isChecked, level: level, data: item, label: react_1.default.createElement(Highlighter_1.default, { text: item.label, highlight: filter }), labelInText: item.label, style: style, isFocused: isFocused, isRequired: !!item.attrType.required, LogoIcon: item.LogoIcon }));
90
+ return (react_1.default.createElement(AttributeListItem_1.default, { key: item.uri, onClick: handleListItemClick, checked: isChecked, level: level, data: item, label: react_1.default.createElement(Highlighter_1.default, { text: item.label, highlight: filter }), labelInText: item.label, style: style, isFocused: isFocused, isRequired: !!((_b = item.attrType) === null || _b === void 0 ? void 0 : _b.required), LogoIcon: item.LogoIcon }));
96
91
  }, [filter, handleListItemClick, selectedItems]);
92
+ var renderGroupTitle = react_1.useCallback(function (style, item) { return (react_1.default.createElement(ListItem_1.default, { component: 'div', className: styles.subHeader, style: style, key: "group-" + item.item.id }, item.item.label)); }, []);
97
93
  return (react_1.default.createElement("div", { className: classnames_1.default(styles.moreAttributes, (_b = {}, _b[styles.dense] = dense, _b)) },
98
94
  react_1.default.createElement(Button_1.default, { color: "primary", onClick: togglePopupOpen, ref: inputRef, className: styles.moreButton },
99
95
  react_1.default.createElement(Add_1.default, { classes: { root: styles.icon } }),
100
96
  react_1.default.createElement("div", { className: styles.buttonLabel }, label)),
101
97
  react_1.default.createElement(SelectionPopup_1.default, { open: isOpen, className: classnames_1.default(styles.moreAttributesPopup, styles.popupContainer), anchorEl: inputRef.current, onClose: ramda_1.pipe(addSelectedAttributes, closePopup, clearFilter, clearSelectedItems), onSearch: setFilter, containerHeight: containerHeight, title: popupTitle, containerWidth: LIST_CONTAINER_WIDTH, searchInputOnKeyDown: handleKeyDown },
102
- react_1.default.createElement(VirtualGroupedList_1.default, { getItemSize: getItemSize, renderItem: listItemRenderer, items: items, height: listHeight, containerWidth: LIST_CONTAINER_WIDTH, focusIndex: focusIndex }))));
98
+ react_1.default.createElement(VirtualGroupedList_1.default, { getItemSize: getItemSize, renderItem: listItemRenderer, renderGroupTitle: renderGroupTitle, items: items, height: listHeight, containerWidth: LIST_CONTAINER_WIDTH, focusIndex: focusIndex }),
99
+ items.length === 0 && (react_1.default.createElement("div", { className: styles.noResultsCaptionContainer },
100
+ react_1.default.createElement(Typography_1.default, { variant: "caption", display: "block", gutterBottom: true }, ui_i18n_1.default.text('No results found')))))));
103
101
  };
104
102
  MoreAttributesButton.propTypes = {
105
103
  label: prop_types_1.default.string,
106
104
  popupTitle: prop_types_1.default.string,
107
105
  data: prop_types_1.default.array,
106
+ parent: prop_types_1.default.object,
108
107
  dense: prop_types_1.default.bool,
109
108
  onApply: prop_types_1.default.func
110
109
  };
@@ -0,0 +1,8 @@
1
+ import { AttributeType } from '@reltio/mdm-sdk';
2
+ import { GroupedItem } from './useMoreAttributesItems';
3
+ declare type Props = {
4
+ attrTypes: AttributeType[];
5
+ filter?: string;
6
+ };
7
+ declare const preparedGroupedItems: ({ attrTypes, filter }: Props) => GroupedItem[];
8
+ export { preparedGroupedItems };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preparedGroupedItems = void 0;
4
+ var ramda_1 = require("ramda");
5
+ var filterItems = ramda_1.curry(function (filterText, items) {
6
+ return ramda_1.filter(function (item) { return item.label.toLowerCase().includes(filterText.toLowerCase()); })(items);
7
+ });
8
+ var preparedGroupedItems = function (_a) {
9
+ var attrTypes = _a.attrTypes, _b = _a.filter, filter = _b === void 0 ? '' : _b;
10
+ return ramda_1.pipe(filterItems(filter), ramda_1.map(function (attrType) { return ({
11
+ item: {
12
+ id: attrType.uri,
13
+ label: attrType.label,
14
+ attrType: attrType
15
+ }
16
+ }); }))(attrTypes);
17
+ };
18
+ exports.preparedGroupedItems = preparedGroupedItems;
@@ -1 +1 @@
1
- export const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"icon" | "dense" | "buttonLabel" | "moreButton" | "moreAttributes" | "popupContainer" | "moreAttributesPopup">;
1
+ export const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"icon" | "dense" | "buttonLabel" | "moreButton" | "subHeader" | "moreAttributes" | "popupContainer" | "moreAttributesPopup" | "noResultsCaptionContainer">;
@@ -27,5 +27,25 @@ exports.useStyles = styles_1.makeStyles({
27
27
  icon: {
28
28
  fontSize: '18px',
29
29
  marginRight: '8px'
30
+ },
31
+ subHeader: {
32
+ backgroundColor: 'rgb(245, 245, 245)',
33
+ padding: '0 16px',
34
+ margin: 0,
35
+ display: 'flex',
36
+ alignItems: 'center',
37
+ color: 'rgba(0,0,0,0.84)',
38
+ fontSize: '14px',
39
+ fontWeight: 500
40
+ },
41
+ noResultsCaptionContainer: {
42
+ position: 'absolute',
43
+ top: 0,
44
+ bottom: 0,
45
+ left: 0,
46
+ right: 0,
47
+ display: 'flex',
48
+ justifyContent: 'center',
49
+ alignItems: 'center'
30
50
  }
31
51
  });
@@ -0,0 +1,22 @@
1
+ import { AttributeType } from '@reltio/mdm-sdk';
2
+ declare type Props = {
3
+ data: AttributeType[];
4
+ parent?: AttributeType;
5
+ filter?: string;
6
+ };
7
+ declare type Item = {
8
+ id: string;
9
+ label: string;
10
+ attrType?: AttributeType;
11
+ };
12
+ export declare type GroupedItem = {
13
+ item: Item;
14
+ items?: GroupedItem[];
15
+ };
16
+ export declare const useMoreAttributesItems: ({ data, parent, filter }: Props) => {
17
+ items: any;
18
+ hasGroups: boolean;
19
+ parentGroupLength: number;
20
+ attributesGroupLength: number;
21
+ };
22
+ export {};
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useMoreAttributesItems = void 0;
7
+ var react_1 = require("react");
8
+ var ui_i18n_1 = __importDefault(require("ui-i18n"));
9
+ var helpers_1 = require("../../../VirtualGroupedList/helpers");
10
+ var helpers_2 = require("./helpers");
11
+ var GROUP_NAMES;
12
+ (function (GROUP_NAMES) {
13
+ GROUP_NAMES["parent"] = "parent";
14
+ GROUP_NAMES["attributes"] = "attributes";
15
+ })(GROUP_NAMES || (GROUP_NAMES = {}));
16
+ var useMoreAttributesItems = function (_a) {
17
+ var data = _a.data, parent = _a.parent, filter = _a.filter;
18
+ var hasGroups = Boolean(parent);
19
+ var preparedParentGroupItem = react_1.useMemo(function () { return (hasGroups ? helpers_2.preparedGroupedItems({ attrTypes: [parent], filter: filter }) : []); }, [hasGroups, parent, filter]);
20
+ var parentGroup = react_1.useMemo(function () {
21
+ return hasGroups && (preparedParentGroupItem === null || preparedParentGroupItem === void 0 ? void 0 : preparedParentGroupItem.length)
22
+ ? [
23
+ {
24
+ item: {
25
+ id: GROUP_NAMES.parent,
26
+ label: ui_i18n_1.default.text('Parent')
27
+ },
28
+ items: preparedParentGroupItem
29
+ }
30
+ ]
31
+ : [];
32
+ }, [hasGroups, preparedParentGroupItem]);
33
+ var preparedAttributesGroupItems = react_1.useMemo(function () {
34
+ return helpers_2.preparedGroupedItems({
35
+ attrTypes: data,
36
+ filter: filter
37
+ });
38
+ }, [data, filter]);
39
+ var attributesGroup = react_1.useMemo(function () {
40
+ return hasGroups && (preparedAttributesGroupItems === null || preparedAttributesGroupItems === void 0 ? void 0 : preparedAttributesGroupItems.length)
41
+ ? [
42
+ {
43
+ item: {
44
+ id: GROUP_NAMES.attributes,
45
+ label: ui_i18n_1.default.text('Attributes')
46
+ },
47
+ items: preparedAttributesGroupItems
48
+ }
49
+ ]
50
+ : preparedAttributesGroupItems;
51
+ }, [hasGroups, preparedAttributesGroupItems]);
52
+ var items = react_1.useMemo(function () { return helpers_1.flattenGroupedItemsData((parentGroup || []).concat(attributesGroup)); }, [
53
+ parentGroup,
54
+ attributesGroup
55
+ ]);
56
+ var parentGroupLength = parentGroup.length;
57
+ var attributesGroupLength = attributesGroup.length;
58
+ return { items: items, hasGroups: hasGroups, parentGroupLength: parentGroupLength, attributesGroupLength: attributesGroupLength };
59
+ };
60
+ exports.useMoreAttributesItems = useMoreAttributesItems;
@@ -4,6 +4,7 @@ import classnames from 'classnames';
4
4
  import Typography from '@material-ui/core/Typography';
5
5
  import { getEntityType, getEntityTypeLabel, getPropWithInheritance, theme, utils } from '@reltio/mdm-sdk';
6
6
  import mdmModule from '@reltio/mdm-module';
7
+ import ExpandedValueTooltip from '../ExpandedValueTooltip/ExpandedValueTooltip';
7
8
  import useStyles from './styles';
8
9
  var EntityTypeBadge = function (_a) {
9
10
  var entity = _a.entity, className = _a.className, _b = _a.size, size = _b === void 0 ? 'small' : _b;
@@ -12,9 +13,11 @@ var EntityTypeBadge = function (_a) {
12
13
  var entityTypeUri = entity.type;
13
14
  var entityType = getEntityType(metadata, entityTypeUri) || {};
14
15
  var entityTypeColor = getPropWithInheritance(metadata, entityType, 'typeColor') || theme.palette.primary.main;
15
- return (React.createElement(Typography, { style: {
16
- backgroundColor: entityTypeColor,
17
- color: utils.Colors.getColor(entityTypeColor) ? '#FFFFFF' : '#212121'
18
- }, className: classnames(styles["entityType-" + size], className), component: "div" }, getEntityTypeLabel(metadata, entity)));
16
+ var entityTypeLabel = getEntityTypeLabel(metadata, entity);
17
+ return (React.createElement(ExpandedValueTooltip, { value: entityTypeLabel, placement: "top" },
18
+ React.createElement(Typography, { style: {
19
+ backgroundColor: entityTypeColor,
20
+ color: utils.Colors.getColor(entityTypeColor) ? '#FFFFFF' : '#212121'
21
+ }, className: classnames(styles["entityType-" + size], styles['entityType-overflow'], className), component: "div" }, entityTypeLabel)));
19
22
  };
20
23
  export default EntityTypeBadge;
@@ -1,2 +1,2 @@
1
- declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"entityType-small" | "entityType-medium">;
1
+ declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"entityType-overflow" | "entityType-small" | "entityType-medium">;
2
2
  export default useStyles;
@@ -1,10 +1,14 @@
1
1
  import { makeStyles } from '@material-ui/core/styles';
2
2
  var useStyles = makeStyles({
3
+ 'entityType-overflow': {
4
+ textOverflow: 'ellipsis',
5
+ overflow: 'hidden',
6
+ whiteSpace: 'nowrap'
7
+ },
3
8
  'entityType-small': {
4
9
  padding: '1px 4px',
5
10
  fontSize: '10px',
6
11
  lineHeight: 'normal',
7
- display: 'inline-flex',
8
12
  marginRight: '12px',
9
13
  borderRadius: '2px'
10
14
  },
@@ -14,7 +18,6 @@ var useStyles = makeStyles({
14
18
  fontSize: '13px',
15
19
  fontWeight: 500,
16
20
  lineHeight: '15px',
17
- display: 'inline-flex',
18
21
  marginRight: '16px'
19
22
  }
20
23
  });
@@ -46,6 +46,7 @@ var useStyles = makeStyles(function (theme) { return ({
46
46
  entityId: {
47
47
  display: 'flex',
48
48
  alignItems: 'baseline',
49
+ whiteSpace: 'nowrap',
49
50
  fontWeight: 400,
50
51
  fontSize: '12px',
51
52
  lineHeight: '16px'
@@ -1,5 +1,6 @@
1
1
  declare var _default: React.MemoExoticComponent<{
2
- ({ attrTypes, entity, parentUri, showEmptyEditors, mode, crosswalks, drawLines, children, className, alwaysVisibleTypeUris, onAddAttributes, onChangeAttribute, onDeleteAttribute, additionalControlsRenderer, showNonOv }: {
2
+ ({ parentAttributeType, attrTypes, entity, parentUri, showEmptyEditors, mode, crosswalks, drawLines, children, className, alwaysVisibleTypeUris, onAddAttributes, onChangeAttribute, onDeleteAttribute, additionalControlsRenderer, showNonOv }: {
3
+ parentAttributeType: any;
3
4
  attrTypes: any;
4
5
  entity: any;
5
6
  parentUri: any;
@@ -17,6 +18,7 @@ declare var _default: React.MemoExoticComponent<{
17
18
  showNonOv: any;
18
19
  }): JSX.Element;
19
20
  propTypes: {
21
+ parentAttributeType: PropTypes.Requireable<object>;
20
22
  attrTypes: PropTypes.Requireable<any[]>;
21
23
  entity: PropTypes.Requireable<object>;
22
24
  parentUri: PropTypes.Requireable<string>;
@@ -12,7 +12,7 @@ var __assign = (this && this.__assign) || function () {
12
12
  import React, { memo, useCallback, useContext, useMemo, useState, useEffect } from 'react';
13
13
  import PropTypes from 'prop-types';
14
14
  import i18n from 'ui-i18n';
15
- import { getCreatableAttributeTypes, getAttributesListForEditMode, ModeType } from '@reltio/mdm-sdk';
15
+ import { getCreatableAttributeTypes, getAttributesListForEditMode, ModeType, getParentUri, checkCanCreateAttribute } from '@reltio/mdm-sdk';
16
16
  import { path } from 'ramda';
17
17
  import AttributesPager from '../AttributesPager';
18
18
  import BranchDecorator from '../../BranchDecorator/BranchDecorator';
@@ -23,7 +23,7 @@ import { getMoreAttrTypes } from './helpers';
23
23
  import { PinnedAttributesContext } from '../contexts/PinnedAttributesContext';
24
24
  import { HasDeletionsContext } from '../contexts/HasDeletionsContext';
25
25
  var AttributesList = function (_a) {
26
- var attrTypes = _a.attrTypes, entity = _a.entity, parentUri = _a.parentUri, showEmptyEditors = _a.showEmptyEditors, mode = _a.mode, crosswalks = _a.crosswalks, drawLines = _a.drawLines, children = _a.children, className = _a.className, _b = _a.alwaysVisibleTypeUris, alwaysVisibleTypeUris = _b === void 0 ? ALWAYS_VISIBLE_TYPE_URIS : _b, onAddAttributes = _a.onAddAttributes, onChangeAttribute = _a.onChangeAttribute, onDeleteAttribute = _a.onDeleteAttribute, additionalControlsRenderer = _a.additionalControlsRenderer, showNonOv = _a.showNonOv;
26
+ var parentAttributeType = _a.parentAttributeType, attrTypes = _a.attrTypes, entity = _a.entity, parentUri = _a.parentUri, showEmptyEditors = _a.showEmptyEditors, mode = _a.mode, crosswalks = _a.crosswalks, drawLines = _a.drawLines, children = _a.children, className = _a.className, _b = _a.alwaysVisibleTypeUris, alwaysVisibleTypeUris = _b === void 0 ? ALWAYS_VISIBLE_TYPE_URIS : _b, onAddAttributes = _a.onAddAttributes, onChangeAttribute = _a.onChangeAttribute, onDeleteAttribute = _a.onDeleteAttribute, additionalControlsRenderer = _a.additionalControlsRenderer, showNonOv = _a.showNonOv;
27
27
  var _c = entity.attributes, attributes = _c === void 0 ? {} : _c;
28
28
  var _d = useState({}), hasDeletionsMap = _d[0], setHasDeletionsMap = _d[1];
29
29
  var setHasDeletions = useCallback(function (attrTypeUri, value) {
@@ -35,14 +35,18 @@ var AttributesList = function (_a) {
35
35
  useEffect(function () {
36
36
  setHasDeletionsMap({});
37
37
  }, [parentUri]);
38
+ var canCreateParentAttrType = useMemo(function () { return parentAttributeType && checkCanCreateAttribute({ attributeType: parentAttributeType, mode: mode }); }, [parentAttributeType, mode]);
38
39
  var creatableAttrTypes = useMemo(function () { return getCreatableAttributeTypes(mode, attrTypes); }, [attrTypes, mode]);
39
40
  var moreAttrTypes = getMoreAttrTypes(creatableAttrTypes, entity, showEmptyEditors, hasDeletionsMap);
40
41
  var pinnedAttributes = useContext(PinnedAttributesContext);
41
42
  var pagersData = useMemo(function () { return getAttributesListForEditMode(attrTypes, mode, entity, showEmptyEditors, showNonOv, pinnedAttributes); }, [attrTypes, mode, entity, showEmptyEditors, showNonOv, pinnedAttributes]);
42
43
  var _e = useMemo(function () { return splitPagersData(alwaysVisibleTypeUris, pagersData); }, [pagersData, alwaysVisibleTypeUris]), alwaysVisiblePagersData = _e[0], regularPagersData = _e[1];
43
44
  var onAddMoreAttributes = useCallback(function (attributeTypes) {
44
- onAddAttributes(attributeTypes.map(function (attributeType) { return ({ attributeType: attributeType, parentUri: parentUri }); }));
45
- }, [onAddAttributes, parentUri]);
45
+ onAddAttributes(attributeTypes.map(function (attributeType) { return ({
46
+ attributeType: attributeType,
47
+ parentUri: attributeType === parentAttributeType ? getParentUri(parentUri) : parentUri
48
+ }); }));
49
+ }, [onAddAttributes, parentUri, parentAttributeType]);
46
50
  var decoratorProps = {
47
51
  enabled: drawLines
48
52
  };
@@ -52,13 +56,14 @@ var AttributesList = function (_a) {
52
56
  }); }, [hasDeletionsMap, setHasDeletions]);
53
57
  return (React.createElement("div", { className: className },
54
58
  children && React.createElement(BranchDecorator, __assign({}, decoratorProps), children),
55
- React.createElement(BranchDecorator, __assign({}, decoratorProps, { plain: true }), moreAttrTypes.length > 0 && (React.createElement(MoreAttributesButton, { label: i18n.text('More attributes'), onApply: onAddMoreAttributes, dense: drawLines, data: moreAttrTypes }))),
59
+ React.createElement(BranchDecorator, __assign({}, decoratorProps, { plain: true }), moreAttrTypes.length > 0 && (React.createElement(MoreAttributesButton, { label: i18n.text('More attributes'), onApply: onAddMoreAttributes, dense: drawLines, data: moreAttrTypes, parent: canCreateParentAttrType && parentAttributeType }))),
56
60
  React.createElement(HasDeletionsContext.Provider, { value: hasDeletionsContextValue }, regularPagersData.concat(alwaysVisiblePagersData).map(function (_a) {
57
61
  var attrType = _a.attrType, values = _a.values;
58
62
  return (React.createElement(AttributesPager, { key: attrType.uri, attributeType: attrType, drawLines: drawLines, values: values, paging: path(['paging', attrType.uri], attributes), parentUri: parentUri, showEmptyEditors: showEmptyEditors, mode: mode, crosswalks: crosswalks, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute, additionalControlsRenderer: additionalControlsRenderer, showNonOv: showNonOv }));
59
63
  }))));
60
64
  };
61
65
  AttributesList.propTypes = {
66
+ parentAttributeType: PropTypes.object,
62
67
  attrTypes: PropTypes.array,
63
68
  entity: PropTypes.object,
64
69
  parentUri: PropTypes.string,
@@ -79,7 +79,7 @@ var ComplexAttribute = function (_a) {
79
79
  ")")),
80
80
  additionalControlsRenderer && additionalControlsRenderer({ attributeType: attributeType, attributeValue: attributeValue }),
81
81
  showDeleteButton && React.createElement(SmallIconButton, { icon: DeleteIcon, onClick: onDeleteThis, size: "L" }))),
82
- expanded && (React.createElement(AttributesList, { attrTypes: attributeTypesList, entity: attributeListEntity, showEmptyEditors: showEmptyEditors || isNew, drawLines: true, parentUri: uri, mode: mode, crosswalks: crosswalks, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute, additionalControlsRenderer: additionalControlsRenderer, showNonOv: showNonOv }, children))));
82
+ expanded && (React.createElement(AttributesList, { parentAttributeType: attributeType, attrTypes: attributeTypesList, entity: attributeListEntity, showEmptyEditors: showEmptyEditors || isNew, drawLines: true, parentUri: uri, mode: mode, crosswalks: crosswalks, onAddAttributes: onAddAttributes, onChangeAttribute: onChangeAttribute, onDeleteAttribute: onDeleteAttribute, additionalControlsRenderer: additionalControlsRenderer, showNonOv: showNonOv }, children))));
83
83
  };
84
84
  ComplexAttribute.propTypes = __assign({ label: PropTypes.string, children: PropTypes.node, attributeTypesList: PropTypes.arrayOf(AttributeTypeType), attributeValue: PropTypes.oneOfType([NestedAttributeValueType, ReferenceAttributeValueType]) }, ComplexAttributeType);
85
85
  export default ComplexAttribute;
@@ -1,8 +1,9 @@
1
1
  export default MoreAttributesButton;
2
- declare function MoreAttributesButton({ label, popupTitle, data, dense, onApply }: {
2
+ declare function MoreAttributesButton({ label, popupTitle, data, parent, dense, onApply }: {
3
3
  label: any;
4
4
  popupTitle?: any;
5
5
  data: any;
6
+ parent: any;
6
7
  dense: any;
7
8
  onApply: any;
8
9
  }): JSX.Element;
@@ -11,6 +12,7 @@ declare namespace MoreAttributesButton {
11
12
  const label: PropTypes.Requireable<string>;
12
13
  const popupTitle: PropTypes.Requireable<string>;
13
14
  const data: PropTypes.Requireable<any[]>;
15
+ const parent: PropTypes.Requireable<object>;
14
16
  const dense: PropTypes.Requireable<boolean>;
15
17
  const onApply: PropTypes.Requireable<(...args: any[]) => any>;
16
18
  }
@@ -1,27 +1,28 @@
1
- import React, { useCallback, useMemo, useRef, useState } from 'react';
1
+ import React, { useCallback, useRef, useState } from 'react';
2
+ import i18n from 'ui-i18n';
2
3
  import classnames from 'classnames';
3
4
  import PropTypes from 'prop-types';
4
- import { always, any, append, curry, filter, ifElse, map, not, pipe, pluck, propEq, reject } from 'ramda';
5
+ import { always, any, append, ifElse, not, pipe, pluck, propEq, reject } from 'ramda';
5
6
  import Button from '@material-ui/core/Button';
7
+ import ListItem from '@material-ui/core/ListItem';
8
+ import Typography from '@material-ui/core/Typography';
6
9
  import { useStyles } from './styles';
7
10
  import SelectionPopup from '../../../SelectionPopup/SelectionPopup';
8
11
  import AttributeListItem from '../../../AttributeListItem/AttributeListItem';
9
- import { flattenGroupedItemsData } from '../../../VirtualGroupedList/helpers';
10
12
  import VirtualGroupedList from '../../../VirtualGroupedList/VirtualGroupedList';
11
13
  import { useKeyboardNavigation } from '../../../SelectionPopup/helpers';
12
14
  import AddIcon from '@material-ui/icons/Add';
13
15
  import Highlighter from '../../../Highlighter/Highlighter';
16
+ import { useMoreAttributesItems } from './useMoreAttributesItems';
14
17
  var ITEM_HEIGHT = 28;
18
+ var ITEM_GROUP_TITLE_HEIGHT = 40;
15
19
  var LIST_CONTAINER_WIDTH = 320;
16
20
  var MAX_LIST_CONTAINER_HEIGHT = 255;
17
21
  var MIN_CONTAINER_HEIGHT = 140;
18
22
  var CONTAINER_HEADER_HEIGHT = 112;
19
- var filterItems = curry(function (filterText, items) {
20
- return filter(function (item) { return item.label.toLowerCase().includes(filterText.toLowerCase()); })(items);
21
- });
22
23
  var MoreAttributesButton = function (_a) {
23
24
  var _b;
24
- var label = _a.label, _c = _a.popupTitle, popupTitle = _c === void 0 ? label : _c, data = _a.data, dense = _a.dense, onApply = _a.onApply;
25
+ var label = _a.label, _c = _a.popupTitle, popupTitle = _c === void 0 ? label : _c, data = _a.data, parent = _a.parent, dense = _a.dense, onApply = _a.onApply;
25
26
  var styles = useStyles();
26
27
  var inputRef = useRef();
27
28
  var _d = useState(false), isOpen = _d[0], setIsOpen = _d[1];
@@ -31,6 +32,7 @@ var MoreAttributesButton = function (_a) {
31
32
  var clearFilter = function () { return setFilter(''); };
32
33
  var _f = useState([]), selectedItems = _f[0], setSelectedItems = _f[1];
33
34
  var clearSelectedItems = function () { return setSelectedItems([]); };
35
+ var _g = useMoreAttributesItems({ data: data, parent: parent, filter: filter }), items = _g.items, hasGroups = _g.hasGroups, parentGroupLength = _g.parentGroupLength, attributesGroupLength = _g.attributesGroupLength;
34
36
  var addSelectedAttributes = function () {
35
37
  if (selectedItems.length > 0) {
36
38
  onApply(pluck('attrType', selectedItems));
@@ -39,48 +41,45 @@ var MoreAttributesButton = function (_a) {
39
41
  var handleListItemClick = useCallback(function (item, checked) {
40
42
  setSelectedItems(ifElse(always(checked), append(item), reject(propEq('id', item.id)))(selectedItems));
41
43
  }, [selectedItems]);
42
- var preparedGroupedItems = useMemo(function () {
43
- return pipe(filterItems(filter), map(function (attrType) { return ({
44
- item: {
45
- id: attrType.uri,
46
- label: attrType.label,
47
- attrType: attrType
48
- }
49
- }); }))(data);
50
- }, [data, filter]);
51
- var items = useMemo(function () { return flattenGroupedItemsData(preparedGroupedItems); }, [preparedGroupedItems]);
52
- var getItemSize = useCallback(function () { return ITEM_HEIGHT; }, []);
44
+ var getItemSize = useCallback(function (i, item) { return (item.items ? ITEM_GROUP_TITLE_HEIGHT : ITEM_HEIGHT); }, []);
53
45
  var handleSearchOnEnter = useCallback(function (_a) {
54
46
  var item = _a.item;
55
47
  handleListItemClick(item, not(any(propEq('id', item.id))(selectedItems)));
56
48
  }, [handleListItemClick, selectedItems]);
57
- var _g = useKeyboardNavigation({
49
+ var _h = useKeyboardNavigation({
58
50
  items: items,
59
51
  open: isOpen,
60
52
  onSelectFocusedItem: handleSearchOnEnter,
61
53
  selectedItems: selectedItems
62
- }), focusIndex = _g.focusIndex, handleKeyDown = _g.handleKeyDown;
54
+ }), focusIndex = _h.focusIndex, handleKeyDown = _h.handleKeyDown;
63
55
  var focusIndexRef = useRef(null);
64
56
  focusIndexRef.current = focusIndex;
65
- var listHeight = Math.min(MAX_LIST_CONTAINER_HEIGHT, ITEM_HEIGHT * items.length);
57
+ var groupsCount = hasGroups ? (parentGroupLength ? 1 : 0) + (attributesGroupLength ? 1 : 0) : 0;
58
+ var itemsCount = items.length - groupsCount;
59
+ var listHeight = Math.min(MAX_LIST_CONTAINER_HEIGHT, ITEM_HEIGHT * itemsCount + ITEM_GROUP_TITLE_HEIGHT * groupsCount);
66
60
  var containerHeight = Math.max(MIN_CONTAINER_HEIGHT, listHeight + CONTAINER_HEADER_HEIGHT);
67
61
  var listItemRenderer = useCallback(function (style, _a, index) {
68
- var item = _a.item, _b = _a.level, level = _b === void 0 ? 0 : _b;
62
+ var _b;
63
+ var item = _a.item, _c = _a.level, level = _c === void 0 ? 0 : _c;
69
64
  var isChecked = any(propEq('id', item.id))(selectedItems);
70
65
  var isFocused = focusIndexRef.current === index;
71
- return (React.createElement(AttributeListItem, { key: item.uri, onClick: handleListItemClick, checked: isChecked, level: level, data: item, label: React.createElement(Highlighter, { text: item.label, highlight: filter }), labelInText: item.label, style: style, isFocused: isFocused, isRequired: !!item.attrType.required, LogoIcon: item.LogoIcon }));
66
+ return (React.createElement(AttributeListItem, { key: item.uri, onClick: handleListItemClick, checked: isChecked, level: level, data: item, label: React.createElement(Highlighter, { text: item.label, highlight: filter }), labelInText: item.label, style: style, isFocused: isFocused, isRequired: !!((_b = item.attrType) === null || _b === void 0 ? void 0 : _b.required), LogoIcon: item.LogoIcon }));
72
67
  }, [filter, handleListItemClick, selectedItems]);
68
+ var renderGroupTitle = useCallback(function (style, item) { return (React.createElement(ListItem, { component: 'div', className: styles.subHeader, style: style, key: "group-" + item.item.id }, item.item.label)); }, []);
73
69
  return (React.createElement("div", { className: classnames(styles.moreAttributes, (_b = {}, _b[styles.dense] = dense, _b)) },
74
70
  React.createElement(Button, { color: "primary", onClick: togglePopupOpen, ref: inputRef, className: styles.moreButton },
75
71
  React.createElement(AddIcon, { classes: { root: styles.icon } }),
76
72
  React.createElement("div", { className: styles.buttonLabel }, label)),
77
73
  React.createElement(SelectionPopup, { open: isOpen, className: classnames(styles.moreAttributesPopup, styles.popupContainer), anchorEl: inputRef.current, onClose: pipe(addSelectedAttributes, closePopup, clearFilter, clearSelectedItems), onSearch: setFilter, containerHeight: containerHeight, title: popupTitle, containerWidth: LIST_CONTAINER_WIDTH, searchInputOnKeyDown: handleKeyDown },
78
- React.createElement(VirtualGroupedList, { getItemSize: getItemSize, renderItem: listItemRenderer, items: items, height: listHeight, containerWidth: LIST_CONTAINER_WIDTH, focusIndex: focusIndex }))));
74
+ React.createElement(VirtualGroupedList, { getItemSize: getItemSize, renderItem: listItemRenderer, renderGroupTitle: renderGroupTitle, items: items, height: listHeight, containerWidth: LIST_CONTAINER_WIDTH, focusIndex: focusIndex }),
75
+ items.length === 0 && (React.createElement("div", { className: styles.noResultsCaptionContainer },
76
+ React.createElement(Typography, { variant: "caption", display: "block", gutterBottom: true }, i18n.text('No results found')))))));
79
77
  };
80
78
  MoreAttributesButton.propTypes = {
81
79
  label: PropTypes.string,
82
80
  popupTitle: PropTypes.string,
83
81
  data: PropTypes.array,
82
+ parent: PropTypes.object,
84
83
  dense: PropTypes.bool,
85
84
  onApply: PropTypes.func
86
85
  };
@@ -0,0 +1,8 @@
1
+ import { AttributeType } from '@reltio/mdm-sdk';
2
+ import { GroupedItem } from './useMoreAttributesItems';
3
+ declare type Props = {
4
+ attrTypes: AttributeType[];
5
+ filter?: string;
6
+ };
7
+ declare const preparedGroupedItems: ({ attrTypes, filter }: Props) => GroupedItem[];
8
+ export { preparedGroupedItems };
@@ -0,0 +1,15 @@
1
+ import { curry, filter, map, pipe } from 'ramda';
2
+ var filterItems = curry(function (filterText, items) {
3
+ return filter(function (item) { return item.label.toLowerCase().includes(filterText.toLowerCase()); })(items);
4
+ });
5
+ var preparedGroupedItems = function (_a) {
6
+ var attrTypes = _a.attrTypes, _b = _a.filter, filter = _b === void 0 ? '' : _b;
7
+ return pipe(filterItems(filter), map(function (attrType) { return ({
8
+ item: {
9
+ id: attrType.uri,
10
+ label: attrType.label,
11
+ attrType: attrType
12
+ }
13
+ }); }))(attrTypes);
14
+ };
15
+ export { preparedGroupedItems };
@@ -1 +1 @@
1
- export const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"icon" | "dense" | "buttonLabel" | "moreButton" | "moreAttributes" | "popupContainer" | "moreAttributesPopup">;
1
+ export const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"icon" | "dense" | "buttonLabel" | "moreButton" | "subHeader" | "moreAttributes" | "popupContainer" | "moreAttributesPopup" | "noResultsCaptionContainer">;
@@ -24,5 +24,25 @@ export var useStyles = makeStyles({
24
24
  icon: {
25
25
  fontSize: '18px',
26
26
  marginRight: '8px'
27
+ },
28
+ subHeader: {
29
+ backgroundColor: 'rgb(245, 245, 245)',
30
+ padding: '0 16px',
31
+ margin: 0,
32
+ display: 'flex',
33
+ alignItems: 'center',
34
+ color: 'rgba(0,0,0,0.84)',
35
+ fontSize: '14px',
36
+ fontWeight: 500
37
+ },
38
+ noResultsCaptionContainer: {
39
+ position: 'absolute',
40
+ top: 0,
41
+ bottom: 0,
42
+ left: 0,
43
+ right: 0,
44
+ display: 'flex',
45
+ justifyContent: 'center',
46
+ alignItems: 'center'
27
47
  }
28
48
  });
@@ -0,0 +1,22 @@
1
+ import { AttributeType } from '@reltio/mdm-sdk';
2
+ declare type Props = {
3
+ data: AttributeType[];
4
+ parent?: AttributeType;
5
+ filter?: string;
6
+ };
7
+ declare type Item = {
8
+ id: string;
9
+ label: string;
10
+ attrType?: AttributeType;
11
+ };
12
+ export declare type GroupedItem = {
13
+ item: Item;
14
+ items?: GroupedItem[];
15
+ };
16
+ export declare const useMoreAttributesItems: ({ data, parent, filter }: Props) => {
17
+ items: any;
18
+ hasGroups: boolean;
19
+ parentGroupLength: number;
20
+ attributesGroupLength: number;
21
+ };
22
+ export {};
@@ -0,0 +1,53 @@
1
+ import { useMemo } from 'react';
2
+ import i18n from 'ui-i18n';
3
+ import { flattenGroupedItemsData } from '../../../VirtualGroupedList/helpers';
4
+ import { preparedGroupedItems } from './helpers';
5
+ var GROUP_NAMES;
6
+ (function (GROUP_NAMES) {
7
+ GROUP_NAMES["parent"] = "parent";
8
+ GROUP_NAMES["attributes"] = "attributes";
9
+ })(GROUP_NAMES || (GROUP_NAMES = {}));
10
+ export var useMoreAttributesItems = function (_a) {
11
+ var data = _a.data, parent = _a.parent, filter = _a.filter;
12
+ var hasGroups = Boolean(parent);
13
+ var preparedParentGroupItem = useMemo(function () { return (hasGroups ? preparedGroupedItems({ attrTypes: [parent], filter: filter }) : []); }, [hasGroups, parent, filter]);
14
+ var parentGroup = useMemo(function () {
15
+ return hasGroups && (preparedParentGroupItem === null || preparedParentGroupItem === void 0 ? void 0 : preparedParentGroupItem.length)
16
+ ? [
17
+ {
18
+ item: {
19
+ id: GROUP_NAMES.parent,
20
+ label: i18n.text('Parent')
21
+ },
22
+ items: preparedParentGroupItem
23
+ }
24
+ ]
25
+ : [];
26
+ }, [hasGroups, preparedParentGroupItem]);
27
+ var preparedAttributesGroupItems = useMemo(function () {
28
+ return preparedGroupedItems({
29
+ attrTypes: data,
30
+ filter: filter
31
+ });
32
+ }, [data, filter]);
33
+ var attributesGroup = useMemo(function () {
34
+ return hasGroups && (preparedAttributesGroupItems === null || preparedAttributesGroupItems === void 0 ? void 0 : preparedAttributesGroupItems.length)
35
+ ? [
36
+ {
37
+ item: {
38
+ id: GROUP_NAMES.attributes,
39
+ label: i18n.text('Attributes')
40
+ },
41
+ items: preparedAttributesGroupItems
42
+ }
43
+ ]
44
+ : preparedAttributesGroupItems;
45
+ }, [hasGroups, preparedAttributesGroupItems]);
46
+ var items = useMemo(function () { return flattenGroupedItemsData((parentGroup || []).concat(attributesGroup)); }, [
47
+ parentGroup,
48
+ attributesGroup
49
+ ]);
50
+ var parentGroupLength = parentGroup.length;
51
+ var attributesGroupLength = attributesGroup.length;
52
+ return { items: items, hasGroups: hasGroups, parentGroupLength: parentGroupLength, attributesGroupLength: attributesGroupLength };
53
+ };
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@reltio/components",
3
- "version": "1.4.1165",
3
+ "version": "1.4.1169",
4
4
  "license": "SEE LICENSE IN LICENSE FILE",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
7
7
  "dependencies": {
8
8
  "@date-io/moment": "^1.3.5",
9
9
  "@react-google-maps/api": "2.7.0",
10
- "@reltio/mdm-module": "^1.4.1165",
11
- "@reltio/mdm-sdk": "^1.4.1165",
10
+ "@reltio/mdm-module": "^1.4.1169",
11
+ "@reltio/mdm-sdk": "^1.4.1169",
12
12
  "classnames": "^2.2.5",
13
13
  "d3-cloud": "^1.2.5",
14
14
  "d3-geo": "^2.0.1",