@bento-core/query-bar 1.0.1-icdc.0 → 1.0.1-icdc.10

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.
package/README.md CHANGED
@@ -58,6 +58,30 @@ const CONFIG = {
58
58
  * @var {number}
59
59
  */
60
60
  maxItems: 2,
61
+ /**
62
+ * overirdes maxItems to display all the active filter items
63
+ * @var {boolean}
64
+ */
65
+ displayAllActiveFilters: false,
66
+ /**
67
+ * key to access label text
68
+ * @var {boolean}
69
+ */
70
+ group: 'group',
71
+
72
+ /**
73
+ * root path of bento app {window.location.href} or react PUBLIC_URL
74
+ * PR (https://github.com/CBIIT/bento-icdc-frontend/pull/953)
75
+ * @var {string}
76
+ */
77
+ rootPath: null,
78
+ /**
79
+ * display query URL
80
+ * @var {boolean}
81
+ * PR (https://github.com/CBIIT/bento-icdc-frontend/pull/953)
82
+ */
83
+ viewQueryURL: false,
84
+
61
85
  },
62
86
 
63
87
  /* Component Helper Functions */
@@ -115,6 +139,7 @@ const CONFIG = {
115
139
  * @returns {void}
116
140
  */
117
141
  resetFacetSlider: (section) => {},
142
+
118
143
  },
119
144
  };
120
145
  ```
@@ -0,0 +1,3 @@
1
+ <svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M13 9.75715C13 10.0452 12.78 10.2714 12.5 10.2714H7.5C7.22 10.2714 7 10.0452 7 9.75715C7 9.46915 7.22 9.24287 7.5 9.24287H12.5C12.78 9.24287 13 9.46915 13 9.75715ZM12.5 11.3H7.5C7.22 11.3 7 11.5263 7 11.8143C7 12.1023 7.22 12.3286 7.5 12.3286H12.5C12.78 12.3286 13 12.1023 13 11.8143C13 11.5263 12.78 11.3 12.5 11.3ZM12.5 13.3572H7.5C7.22 13.3572 7 13.5834 7 13.8714C7 14.1594 7.22 14.3857 7.5 14.3857H12.5C12.78 14.3857 13 14.1594 13 13.8714C13 13.5834 12.78 13.3572 12.5 13.3572ZM16 8.21429V16.4429C16 17.5743 15.1 18.5 14 18.5H6C4.9 18.5 4 17.5743 4 16.4429V15.4143H2C0.9 15.4143 0 14.4886 0 13.3572V4.10001C0 2.96858 0.9 2.04286 2 2.04286H4.5C4.5 1.18915 5.17 0.500008 6 0.500008C6.83 0.500008 7.5 1.18915 7.5 2.04286H10C11.1 2.04286 12 2.96858 12 4.10001V6.15715H14C15.1 6.15715 16 7.08287 16 8.21429ZM6 6.15715H11V4.10001C11 3.53429 10.55 3.07144 10 3.07144H9V4.10001H3V3.07144H2C1.45 3.07144 1 3.53429 1 4.10001V13.3572C1 13.9229 1.45 14.3857 2 14.3857H4V8.21429C4 7.08287 4.9 6.15715 6 6.15715ZM15 8.21429C15 7.64858 14.55 7.18572 14 7.18572H6C5.45 7.18572 5 7.64858 5 8.21429V16.4429C5 17.0086 5.45 17.4714 6 17.4714H14C14.55 17.4714 15 17.0086 15 16.4429V8.21429Z" fill="#142D64"/>
3
+ </svg>
@@ -4,9 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _clsx = _interopRequireDefault(require("clsx"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
11
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
10
12
  var _default = _ref => {
11
13
  let {
12
14
  index,
@@ -14,26 +16,45 @@ var _default = _ref => {
14
16
  classes,
15
17
  maxItems,
16
18
  onSectionClick,
17
- onItemClick
19
+ onItemClick,
20
+ displayAllActiveFilters
18
21
  } = _ref;
19
22
  const {
20
23
  items,
21
24
  section
22
25
  } = data;
26
+ const [expand, setExpand] = (0, _react.useState)(false);
27
+ const noOfItems = expand ? items.length : maxItems;
28
+ (0, _react.useEffect)(() => {
29
+ if (items.length <= maxItems && expand) {
30
+ setExpand(!expand);
31
+ }
32
+ }, [items]);
33
+ const clsName = function clsName() {
34
+ let text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
35
+ let attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
36
+ return "facetSection".concat(text.replace(/\s+/g, '')).concat(attr);
37
+ };
23
38
  return /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement("span", null, ' ', index !== 0 ? /*#__PURE__*/_react.default.createElement("span", {
24
39
  className: classes.operators
25
40
  }, " AND ") : '', /*#__PURE__*/_react.default.createElement("span", {
26
- className: (0, _clsx.default)(classes.filterName, classes["facetSection".concat(section, "Background")]),
41
+ className: (0, _clsx.default)(classes.filterName, classes["".concat(clsName(section, 'Background'))]),
27
42
  onClick: () => onSectionClick(data)
28
43
  }, data.label), ' '), /*#__PURE__*/_react.default.createElement("span", null, ' ', /*#__PURE__*/_react.default.createElement("span", {
29
44
  className: classes.operators
30
45
  }, items.length === 1 ? 'IS ' : 'IN '), items.length > 1 && /*#__PURE__*/_react.default.createElement("span", {
31
46
  className: classes.bracketsOpen
32
- }, "("), items.slice(0, maxItems).map((d, idx) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
33
- className: (0, _clsx.default)(classes.filterCheckboxes, classes["facetSection".concat(section)]),
47
+ }, "("), items.slice(0, noOfItems).map((d, idx) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
48
+ className: (0, _clsx.default)(classes.filterCheckboxes, classes[clsName(section)]),
34
49
  key: idx,
35
50
  onClick: () => onItemClick(data, d)
36
- }, d), idx === maxItems - 1 ? null : ' ')), items.length > maxItems && '...', items.length > 1 && /*#__PURE__*/_react.default.createElement("span", {
51
+ }, d), idx === maxItems - 1 ? null : ' ')), items.length > maxItems && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, displayAllActiveFilters ? /*#__PURE__*/_react.default.createElement("span", {
52
+ className: classes.expandBtn,
53
+ onClick: () => setExpand(!expand)
54
+ }, "...") : '...'), expand && items.length > maxItems && /*#__PURE__*/_react.default.createElement("span", {
55
+ className: classes.collapseBtn,
56
+ onClick: () => setExpand(!expand)
57
+ }, ' LESS'), items.length > 1 && /*#__PURE__*/_react.default.createElement("span", {
37
58
  className: classes.bracketsClose
38
59
  }, ")")));
39
60
  };
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _clsx = _interopRequireDefault(require("clsx"));
9
+ var _core = require("@material-ui/core");
10
+ var _CopyIcon = _interopRequireDefault(require("../assets/CopyIcon.svg"));
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
14
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
15
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
16
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
17
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
18
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
19
+ const ViewFullLinkComponent = _ref => {
20
+ let {
21
+ classes,
22
+ url,
23
+ maxWidth = 1200
24
+ } = _ref;
25
+ const linkRef = (0, _react.useRef)(null);
26
+ const [expandLink, setExpand] = (0, _react.useState)(false);
27
+
28
+ /**
29
+ * Compute url link width based on the windowsize
30
+ */
31
+ (0, _react.useEffect)(() => {
32
+ var _linkRef$current;
33
+ const urlWidth = linkRef === null || linkRef === void 0 ? void 0 : (_linkRef$current = linkRef.current) === null || _linkRef$current === void 0 ? void 0 : _linkRef$current.offsetWidth;
34
+ if (urlWidth > maxWidth / 2) {
35
+ setExpand(true);
36
+ }
37
+ }, []);
38
+ const expandUrl = () => {
39
+ setExpand(!expandLink);
40
+ };
41
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
42
+ ref: linkRef,
43
+ className: classes.link
44
+ }, /*#__PURE__*/_react.default.createElement("span", {
45
+ className: (0, _clsx.default)(classes.viewLink, {
46
+ [classes.collapseLink]: expandLink
47
+ })
48
+ }, /*#__PURE__*/_react.default.createElement("span", {
49
+ className: classes.urlView
50
+ }, url), expandLink && /*#__PURE__*/_react.default.createElement("span", {
51
+ className: classes.expandLinkBtn,
52
+ type: "button",
53
+ onClick: expandUrl
54
+ }, "..."))));
55
+ };
56
+ const QueryUrl = _ref2 => {
57
+ var _queryRef$current;
58
+ let {
59
+ classes,
60
+ filterItems,
61
+ localFind,
62
+ rootPath
63
+ } = _ref2;
64
+ const [display, setDisplay] = (0, _react.useState)(false);
65
+ const toggleDisplay = () => setDisplay(!display);
66
+ const [expand, setExpand] = (0, _react.useState)(false);
67
+ const [open, toggleOpen] = (0, _react.useState)(false);
68
+ const {
69
+ autocomplete = [],
70
+ upload
71
+ } = localFind;
72
+ const pathFilterParams = filterItems.reduce((acc, item) => {
73
+ const {
74
+ datafield,
75
+ items = []
76
+ } = item;
77
+ acc[datafield] = items;
78
+ return acc;
79
+ }, {});
80
+ const query = JSON.stringify(_objectSpread(_objectSpread({}, pathFilterParams), {}, {
81
+ autocomplete,
82
+ upload
83
+ }));
84
+ const url = encodeURI(rootPath.concat(query));
85
+ const copyUrl = async () => {
86
+ toggleOpen(!open);
87
+ await navigator.clipboard.writeText(url);
88
+ };
89
+ const queryRef = (0, _react.useRef)(null);
90
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
91
+ ref: queryRef,
92
+ className: classes.urlContainer
93
+ }, /*#__PURE__*/_react.default.createElement(_core.Button, {
94
+ onClick: toggleDisplay,
95
+ className: classes.viewLinkToggleBtn
96
+ }, display ? 'Hide Query URL' : 'Show Query URL'), display && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, expand ? /*#__PURE__*/_react.default.createElement("span", {
97
+ type: "button",
98
+ onClick: () => setExpand(!expand),
99
+ className: (0, _clsx.default)(classes.link, classes.viewLink, classes.expandLink)
100
+ }, url) : /*#__PURE__*/_react.default.createElement(ViewFullLinkComponent, {
101
+ url: url,
102
+ classes: classes,
103
+ maxWidth: queryRef === null || queryRef === void 0 ? void 0 : (_queryRef$current = queryRef.current) === null || _queryRef$current === void 0 ? void 0 : _queryRef$current.offsetWidth
104
+ }), /*#__PURE__*/_react.default.createElement(_core.Tooltip, {
105
+ arrow: true,
106
+ title: "Copy to Clipboard"
107
+ }, /*#__PURE__*/_react.default.createElement(_core.IconButton, {
108
+ onClick: copyUrl,
109
+ className: classes.copyIconBtn
110
+ }, /*#__PURE__*/_react.default.createElement("img", {
111
+ src: _CopyIcon.default,
112
+ alt: "copy icon"
113
+ }))))), /*#__PURE__*/_react.default.createElement(_core.Dialog, {
114
+ open: open,
115
+ "aria-labelledby": "alert-dialog-title",
116
+ "aria-describedby": "alert-dialog-description",
117
+ className: (0, _clsx.default)(classes.dialogBox, 'dialogBox')
118
+ }, /*#__PURE__*/_react.default.createElement(_core.DialogContent, {
119
+ className: classes.okText
120
+ }, /*#__PURE__*/_react.default.createElement(_core.DialogContentText, {
121
+ id: "alert-dialog-description"
122
+ }, "Your query URL has been copied!")), /*#__PURE__*/_react.default.createElement(_core.DialogActions, null, /*#__PURE__*/_react.default.createElement(_core.Button, {
123
+ onClick: () => toggleOpen(!open)
124
+ }, "OK"))));
125
+ };
126
+ const styles = () => ({
127
+ urlContainer: {
128
+ marginTop: '10px',
129
+ minHeight: '10px',
130
+ marginBottom: '10px'
131
+ },
132
+ link: {
133
+ lineBreak: 'anywhere',
134
+ overflow: 'hidden',
135
+ fontFamily: 'Nunito',
136
+ fontSize: '12px',
137
+ fontWeight: '500',
138
+ lineHeight: '16px',
139
+ letterSpacing: '0em',
140
+ padding: '5px',
141
+ borderRadius: '5px',
142
+ float: 'left',
143
+ color: '#1D79A8',
144
+ backgroundColor: '#fff',
145
+ maxWidth: '80%'
146
+ },
147
+ viewLink: {
148
+ margin: '0'
149
+ },
150
+ collapseLink: {
151
+ maxHeight: '1em',
152
+ display: 'block',
153
+ // display: '-webkit-box',
154
+ '-webkit-box-orient': 'vertical',
155
+ '-webkit-line-clamp': '1',
156
+ overflow: 'hidden'
157
+ },
158
+ expandLink: {
159
+ cursor: 'pointer'
160
+ },
161
+ expandLinkBtn: {
162
+ float: 'left',
163
+ '&:hover': {
164
+ cursor: 'pointer'
165
+ }
166
+ },
167
+ viewLinkToggleBtn: {
168
+ height: '20px',
169
+ marginRight: '10px',
170
+ fontFamily: 'Nunito',
171
+ fontSize: '12px',
172
+ fontWeight: '500',
173
+ lineHeight: '16px',
174
+ letterSpacing: '0em',
175
+ textAlign: 'left',
176
+ backgroundColor: '#1D79A8',
177
+ textTransform: 'none',
178
+ color: '#fff',
179
+ float: 'left',
180
+ '&:hover': {
181
+ backgroundColor: '#1D79A8',
182
+ color: '#fff'
183
+ }
184
+ },
185
+ urlView: {
186
+ float: 'left',
187
+ width: 'calc(100% - 13px)',
188
+ minWidth: '840px',
189
+ '@media (max-width: 2560px)': {
190
+ maxWidth: '1800px'
191
+ },
192
+ '@media (max-width: 2000px)': {
193
+ maxWidth: '1400px'
194
+ },
195
+ '@media (max-width: 1600px)': {
196
+ maxWidth: '1200px'
197
+ },
198
+ '@media (max-width: 1300px)': {
199
+ maxWidth: '1050px'
200
+ }
201
+ },
202
+ copyIconBtn: {
203
+ padding: '0px',
204
+ marginLeft: '10px',
205
+ float: 'left'
206
+ }
207
+ });
208
+ var _default = (0, _core.withStyles)(styles)(QueryUrl);
209
+ exports.default = _default;
@@ -4,14 +4,17 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.QueryBarGenerator = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _core = require("@material-ui/core");
9
9
  var _facetFilter = require("@bento-core/facet-filter");
10
10
  var _clsx = _interopRequireDefault(require("clsx"));
11
11
  var _FilterMap = require("../components/FilterMap");
12
12
  var _styles = _interopRequireDefault(require("./styles"));
13
13
  var _config = _interopRequireDefault(require("./config"));
14
+ var _QueryUrl = _interopRequireDefault(require("../components/QueryUrl"));
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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
18
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
16
19
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
17
20
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -27,12 +30,21 @@ const QueryBarGenerator = function QueryBarGenerator() {
27
30
  let uiConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _config.default;
28
31
  const {
29
32
  config,
30
- functions
33
+ functions,
34
+ customStyles = {}
31
35
  } = uiConfig;
32
36
  const {
33
37
  CHECKBOX
34
38
  } = _facetFilter.InputTypes;
39
+ const styles = () => _objectSpread(_objectSpread({}, (0, _styles.default)()), customStyles);
35
40
  const maxItems = config && typeof config.maxItems === 'number' ? config.maxItems : _config.default.config.maxItems;
41
+ const queryURLRootPath = config && typeof config.rootPath === 'string' ? config.rootPath : _config.default.config.rootPath;
42
+ const viewQueryURL = config && typeof config.viewQueryURL === 'boolean' ? config.viewQueryURL : _config.default.config.viewQueryURL;
43
+ const displayAllActiveFilters = config && typeof config.displayAllActiveFilters === 'boolean' ? config.displayAllActiveFilters : _config.default.config.displayAllActiveFilters;
44
+
45
+ // const group = config && typeof config.group === 'string'
46
+ // ? config.group : DEFAULT_CONFIG.config.group;
47
+
36
48
  const clearAll = functions && typeof functions.clearAll === 'function' ? functions.clearAll : _config.default.functions.clearAll;
37
49
  const clearUpload = functions && typeof functions.clearUpload === 'function' ? functions.clearUpload : _config.default.functions.clearUpload;
38
50
  const clearAutocomplete = functions && typeof functions.clearAutocomplete === 'function' ? functions.clearAutocomplete : _config.default.functions.clearAutocomplete;
@@ -45,7 +57,7 @@ const QueryBarGenerator = function QueryBarGenerator() {
45
57
  return text.replace(/\s+/g, '-').toLowerCase();
46
58
  };
47
59
  return {
48
- QueryBar: (0, _core.withStyles)(_styles.default, {
60
+ QueryBar: (0, _core.withStyles)(styles, {
49
61
  withTheme: true
50
62
  })(props => {
51
63
  const {
@@ -57,6 +69,13 @@ const QueryBarGenerator = function QueryBarGenerator() {
57
69
  autocomplete,
58
70
  upload
59
71
  } = localFind;
72
+ const [expand, setExpand] = (0, _react.useState)(false);
73
+ const noOfItems = expand ? autocomplete.length : maxItems;
74
+ (0, _react.useEffect)(() => {
75
+ if (autocomplete.length <= maxItems && expand) {
76
+ setExpand(!expand);
77
+ }
78
+ }, [autocomplete]);
60
79
 
61
80
  // Remove any sections without checkboxes selected
62
81
  const mappedInputs = statusReducer.filter(facet => facet.section && facet.type).map(facet => {
@@ -64,7 +83,6 @@ const QueryBarGenerator = function QueryBarGenerator() {
64
83
  return facet;
65
84
  }
66
85
  const {
67
- data,
68
86
  items
69
87
  } = facet;
70
88
  const itemKeys = Object.keys(items);
@@ -72,11 +90,17 @@ const QueryBarGenerator = function QueryBarGenerator() {
72
90
 
73
91
  /* Find any SELECTED CHECKBOXES that do NOT have any data
74
92
  * and remove them from the list of selected checkboxes artificially */
75
- itemKeys.forEach(item => {
76
- if (data.findIndex(d => d.group === item) < 0) {
77
- itemKeys.splice(itemKeys.indexOf(item), 1);
78
- }
79
- });
93
+ // itemKeys.forEach((item) => {
94
+ // if (data.findIndex((d) => d.group === item) < 0) {
95
+ // itemKeys.splice(itemKeys.indexOf(item), 1);
96
+ // }
97
+ // });
98
+
99
+ /**
100
+ * commenting out line 89-93
101
+ * to display all the active filters in the query bar
102
+ * ICDC-3287
103
+ */
80
104
  return _objectSpread(_objectSpread({}, facet), {}, {
81
105
  items: itemKeys
82
106
  });
@@ -84,7 +108,7 @@ const QueryBarGenerator = function QueryBarGenerator() {
84
108
  if ((mappedInputs.length || autocomplete.length || upload.length) <= 0) {
85
109
  return null;
86
110
  }
87
- return /*#__PURE__*/_react.default.createElement("div", {
111
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
88
112
  className: classes.queryWrapper
89
113
  }, /*#__PURE__*/_react.default.createElement(_core.Button, {
90
114
  className: classes.clearQueryButton,
@@ -101,18 +125,24 @@ const QueryBarGenerator = function QueryBarGenerator() {
101
125
  }, "INPUT CASE SET") : null, autocomplete.length ? /*#__PURE__*/_react.default.createElement("span", null, ' ', /*#__PURE__*/_react.default.createElement("span", {
102
126
  className: (0, _clsx.default)(classes.filterName, classes.localFindBackground),
103
127
  onClick: clearAutocomplete
104
- }, "Case IDs"), ' ', ' ', /*#__PURE__*/_react.default.createElement("span", {
128
+ }, "Case ID"), ' ', ' ', /*#__PURE__*/_react.default.createElement("span", {
105
129
  className: classes.operators
106
130
  }, autocomplete.length === 1 && !upload.length ? 'IS ' : 'IN ')) : null, /*#__PURE__*/_react.default.createElement("span", null, (upload.length > 0 ? 1 : 0) + autocomplete.length > 1 ? /*#__PURE__*/_react.default.createElement("span", {
107
131
  className: classes.bracketsOpen
108
132
  }, "(") : null, upload.length && autocomplete.length ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, ' ', /*#__PURE__*/_react.default.createElement("span", {
109
133
  className: (0, _clsx.default)(classes.filterCheckboxes, classes.localFind),
110
134
  onClick: clearUpload
111
- }, "INPUT CASE SET"), ' ') : null, autocomplete.slice(0, maxItems).map((d, idx) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
135
+ }, "INPUT CASE SET"), ' ') : null, autocomplete.slice(0, noOfItems).map((d, idx) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
112
136
  className: (0, _clsx.default)(classes.filterCheckboxes, classes.facetSectionCases),
113
137
  key: idx,
114
138
  onClick: () => deleteAutocompleteItem(d.title)
115
- }, d.title), idx === maxItems - 1 ? null : ' ')), autocomplete.length > maxItems && '...', (upload.length > 0 ? 1 : 0) + autocomplete.length > 1 ? /*#__PURE__*/_react.default.createElement("span", {
139
+ }, d.title), idx === noOfItems - 1 ? null : ' ')), autocomplete.length > maxItems && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, displayAllActiveFilters ? /*#__PURE__*/_react.default.createElement("span", {
140
+ className: classes.expandBtn,
141
+ onClick: () => setExpand(!expand)
142
+ }, "...") : '...'), expand && autocomplete.length > maxItems && /*#__PURE__*/_react.default.createElement("span", {
143
+ className: classes.collapseBtn,
144
+ onClick: () => setExpand(!expand)
145
+ }, ' LESS'), (upload.length > 0 ? 1 : 0) + autocomplete.length > 1 ? /*#__PURE__*/_react.default.createElement("span", {
116
146
  className: classes.bracketsClose
117
147
  }, ")") : null)) : null, (autocomplete.length || upload.length) && mappedInputs.length ? /*#__PURE__*/_react.default.createElement("span", {
118
148
  className: classes.operators
@@ -123,10 +153,16 @@ const QueryBarGenerator = function QueryBarGenerator() {
123
153
  type: filter.type,
124
154
  data: filter,
125
155
  maxItems: maxItems,
156
+ displayAllActiveFilters: displayAllActiveFilters,
126
157
  classes: classes,
127
158
  onSectionClick: filter.type === CHECKBOX ? resetFacetSection : resetFacetSlider,
128
159
  onItemClick: filter.type === CHECKBOX ? resetFacetCheckbox : resetFacetSlider
129
- })))));
160
+ })))), viewQueryURL && queryURLRootPath && /*#__PURE__*/_react.default.createElement(_QueryUrl.default, {
161
+ classes: classes,
162
+ localFind: localFind,
163
+ filterItems: mappedInputs,
164
+ rootPath: queryURLRootPath
165
+ })));
130
166
  })
131
167
  };
132
168
  };
@@ -12,7 +12,27 @@ var _default = {
12
12
  * The maximum number of items to display in a query bar facet section
13
13
  * @var {number}
14
14
  */
15
- maxItems: 2
15
+ maxItems: 2,
16
+ /**
17
+ * overirdes maxItems to display all the active filter items
18
+ * @var {boolean}
19
+ */
20
+ displayAllActiveFilters: false,
21
+ /**
22
+ * key to access label text
23
+ * @var {boolean}
24
+ */
25
+ group: 'group',
26
+ /**
27
+ * root path of bento app
28
+ * @var {boolean}
29
+ */
30
+ rootPath: 'localhost',
31
+ /**
32
+ * display query URL
33
+ * @var {boolean}
34
+ */
35
+ viewQueryURL: true
16
36
  },
17
37
  /* Component Helper Functions */
18
38
  functions: {
@@ -109,6 +109,16 @@ var _default = () => ({
109
109
  },
110
110
  facetSectionSamplesBackground: {
111
111
  backgroundColor: '#C3EAF5'
112
+ },
113
+ expandBtn: {
114
+ '&:hover': {
115
+ cursor: 'pointer'
116
+ }
117
+ },
118
+ collapseBtn: {
119
+ '&:hover': {
120
+ cursor: 'pointer'
121
+ }
112
122
  }
113
123
  });
114
124
  exports.default = _default;
package/package.json CHANGED
@@ -1,17 +1,14 @@
1
1
  {
2
2
  "name": "@bento-core/query-bar",
3
- "version": "1.0.1-icdc.0",
4
- "description": "This package provides the Query Bar component that displays the current Facet Search and Local Find filters on the Dashboard/Explore page. It also provides the direct ability to reset all or some of the filters with the click of a button. It is designed to be implemented directly with the:",
3
+ "version": "1.0.1-icdc.10",
4
+ "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "build": "npm run lint && cross-env-shell rm -rf dist && NODE_ENV=production BABEL_ENV=es babel src --out-dir dist --copy-files",
8
8
  "test": "echo \"Error: no test specified\" && exit 1",
9
9
  "lint": "eslint src"
10
10
  },
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/CBIIT/bento-frontend.git"
14
- },
11
+ "repository": "https://github.com/CBIIT/bento-frontend",
15
12
  "publishConfig": {
16
13
  "access": "public"
17
14
  },
@@ -27,10 +24,5 @@
27
24
  "lodash": "^4.17.20"
28
25
  },
29
26
  "author": "CTOS Bento Team",
30
- "license": "ISC",
31
- "bugs": {
32
- "url": "https://github.com/CBIIT/bento-frontend/issues"
33
- },
34
- "homepage": "https://github.com/CBIIT/bento-frontend#readme",
35
- "devDependencies": {}
27
+ "license": "ISC"
36
28
  }
@@ -0,0 +1,3 @@
1
+ <svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M13 9.75715C13 10.0452 12.78 10.2714 12.5 10.2714H7.5C7.22 10.2714 7 10.0452 7 9.75715C7 9.46915 7.22 9.24287 7.5 9.24287H12.5C12.78 9.24287 13 9.46915 13 9.75715ZM12.5 11.3H7.5C7.22 11.3 7 11.5263 7 11.8143C7 12.1023 7.22 12.3286 7.5 12.3286H12.5C12.78 12.3286 13 12.1023 13 11.8143C13 11.5263 12.78 11.3 12.5 11.3ZM12.5 13.3572H7.5C7.22 13.3572 7 13.5834 7 13.8714C7 14.1594 7.22 14.3857 7.5 14.3857H12.5C12.78 14.3857 13 14.1594 13 13.8714C13 13.5834 12.78 13.3572 12.5 13.3572ZM16 8.21429V16.4429C16 17.5743 15.1 18.5 14 18.5H6C4.9 18.5 4 17.5743 4 16.4429V15.4143H2C0.9 15.4143 0 14.4886 0 13.3572V4.10001C0 2.96858 0.9 2.04286 2 2.04286H4.5C4.5 1.18915 5.17 0.500008 6 0.500008C6.83 0.500008 7.5 1.18915 7.5 2.04286H10C11.1 2.04286 12 2.96858 12 4.10001V6.15715H14C15.1 6.15715 16 7.08287 16 8.21429ZM6 6.15715H11V4.10001C11 3.53429 10.55 3.07144 10 3.07144H9V4.10001H3V3.07144H2C1.45 3.07144 1 3.53429 1 4.10001V13.3572C1 13.9229 1.45 14.3857 2 14.3857H4V8.21429C4 7.08287 4.9 6.15715 6 6.15715ZM15 8.21429C15 7.64858 14.55 7.18572 14 7.18572H6C5.45 7.18572 5 7.64858 5 8.21429V16.4429C5 17.0086 5.45 17.4714 6 17.4714H14C14.55 17.4714 15 17.0086 15 16.4429V8.21429Z" fill="#142D64"/>
3
+ </svg>
@@ -1,11 +1,22 @@
1
- import React from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import clsx from 'clsx';
3
3
 
4
4
  export default ({
5
5
  index, data, classes, maxItems,
6
6
  onSectionClick, onItemClick,
7
+ displayAllActiveFilters,
7
8
  }) => {
8
9
  const { items, section } = data;
10
+ const [expand, setExpand] = useState(false);
11
+ const noOfItems = expand ? items.length : maxItems;
12
+
13
+ useEffect(() => {
14
+ if (items.length <= maxItems && expand) {
15
+ setExpand(!expand);
16
+ }
17
+ }, [items]);
18
+
19
+ const clsName = (text = '', attr = '') => `facetSection${text.replace(/\s+/g, '')}${attr}`;
9
20
 
10
21
  return (
11
22
  <span>
@@ -13,7 +24,7 @@ export default ({
13
24
  {' '}
14
25
  {index !== 0 ? <span className={classes.operators}> AND </span> : ''}
15
26
  <span
16
- className={clsx(classes.filterName, classes[`facetSection${section}Background`])}
27
+ className={clsx(classes.filterName, classes[`${clsName(section, 'Background')}`])}
17
28
  onClick={() => onSectionClick(data)}
18
29
  >
19
30
  {data.label}
@@ -26,10 +37,10 @@ export default ({
26
37
  {items.length === 1 ? 'IS ' : 'IN '}
27
38
  </span>
28
39
  {items.length > 1 && <span className={classes.bracketsOpen}>(</span>}
29
- {items.slice(0, maxItems).map((d, idx) => (
40
+ {items.slice(0, noOfItems).map((d, idx) => (
30
41
  <>
31
42
  <span
32
- className={clsx(classes.filterCheckboxes, classes[`facetSection${section}`])}
43
+ className={clsx(classes.filterCheckboxes, classes[clsName(section)])}
33
44
  key={idx}
34
45
  onClick={() => onItemClick(data, d)}
35
46
  >
@@ -38,7 +49,30 @@ export default ({
38
49
  {idx === (maxItems - 1) ? null : ' '}
39
50
  </>
40
51
  ))}
41
- {items.length > maxItems && '...'}
52
+ {items.length > maxItems && (
53
+ <>
54
+ {
55
+ displayAllActiveFilters
56
+ ? (
57
+ <span
58
+ className={classes.expandBtn}
59
+ onClick={() => setExpand(!expand)}
60
+ >
61
+ ...
62
+ </span>
63
+ )
64
+ : '...'
65
+ }
66
+ </>
67
+ )}
68
+ {(expand && items.length > maxItems) && (
69
+ <span
70
+ className={classes.collapseBtn}
71
+ onClick={() => setExpand(!expand)}
72
+ >
73
+ {' LESS'}
74
+ </span>
75
+ )}
42
76
  {items.length > 1 && <span className={classes.bracketsClose}>)</span>}
43
77
  </span>
44
78
  </span>
@@ -0,0 +1,240 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import clsx from 'clsx';
3
+ import {
4
+ Button,
5
+ IconButton,
6
+ Tooltip,
7
+ Dialog,
8
+ DialogActions,
9
+ DialogContent,
10
+ DialogContentText,
11
+ withStyles,
12
+ } from '@material-ui/core';
13
+ import CopyIcon from '../assets/CopyIcon.svg';
14
+
15
+ const ViewFullLinkComponent = ({
16
+ classes,
17
+ url,
18
+ maxWidth = 1200,
19
+ }) => {
20
+ const linkRef = useRef(null);
21
+ const [expandLink, setExpand] = useState(false);
22
+
23
+ /**
24
+ * Compute url link width based on the windowsize
25
+ */
26
+ useEffect(() => {
27
+ const urlWidth = linkRef?.current?.offsetWidth;
28
+ if (urlWidth > maxWidth / 2) {
29
+ setExpand(true);
30
+ }
31
+ }, []);
32
+
33
+ const expandUrl = () => {
34
+ setExpand(!expandLink);
35
+ };
36
+
37
+ return (
38
+ <>
39
+ <span ref={linkRef} className={classes.link}>
40
+ <span
41
+ className={clsx(classes.viewLink,
42
+ { [classes.collapseLink]: expandLink })}
43
+ >
44
+ <span className={classes.urlView}>
45
+ {url}
46
+ </span>
47
+ {(expandLink) && (
48
+ <span
49
+ className={classes.expandLinkBtn}
50
+ type="button"
51
+ onClick={expandUrl}
52
+ >
53
+ ...
54
+ </span>
55
+ )}
56
+ </span>
57
+ </span>
58
+ </>
59
+ );
60
+ };
61
+
62
+ const QueryUrl = ({
63
+ classes,
64
+ filterItems,
65
+ localFind,
66
+ rootPath,
67
+ }) => {
68
+ const [display, setDisplay] = useState(false);
69
+ const toggleDisplay = () => setDisplay(!display);
70
+
71
+ const [expand, setExpand] = useState(false);
72
+
73
+ const [open, toggleOpen] = useState(false);
74
+
75
+ const { autocomplete = [], upload } = localFind;
76
+
77
+ const pathFilterParams = filterItems.reduce((acc, item) => {
78
+ const { datafield, items = [] } = item;
79
+ acc[datafield] = items;
80
+ return acc;
81
+ }, {});
82
+
83
+ const query = JSON.stringify({
84
+ ...pathFilterParams,
85
+ autocomplete,
86
+ upload,
87
+ });
88
+ const url = encodeURI(rootPath.concat(query));
89
+
90
+ const copyUrl = async () => {
91
+ toggleOpen(!open);
92
+ await navigator.clipboard.writeText(url);
93
+ };
94
+
95
+ const queryRef = useRef(null);
96
+
97
+ return (
98
+ <>
99
+ <div ref={queryRef} className={classes.urlContainer}>
100
+ <Button
101
+ onClick={toggleDisplay}
102
+ className={classes.viewLinkToggleBtn}
103
+ >
104
+ { (display) ? 'Hide Query URL' : 'Show Query URL'}
105
+ </Button>
106
+ {
107
+ (display) && (
108
+ <>
109
+ {(expand) ? (
110
+ <span
111
+ type="button"
112
+ onClick={() => setExpand(!expand)}
113
+ className={clsx(classes.link, classes.viewLink, classes.expandLink)}
114
+ >
115
+ {url}
116
+ </span>
117
+ ) : (
118
+ <ViewFullLinkComponent
119
+ url={url}
120
+ classes={classes}
121
+ maxWidth={queryRef?.current?.offsetWidth}
122
+ />
123
+ )}
124
+ <Tooltip
125
+ arrow
126
+ title="Copy to Clipboard"
127
+ >
128
+ <IconButton onClick={copyUrl} className={classes.copyIconBtn}>
129
+ <img src={CopyIcon} alt="copy icon" />
130
+ </IconButton>
131
+ </Tooltip>
132
+ </>
133
+ )
134
+ }
135
+ </div>
136
+ <Dialog
137
+ open={open}
138
+ aria-labelledby="alert-dialog-title"
139
+ aria-describedby="alert-dialog-description"
140
+ className={clsx(classes.dialogBox, 'dialogBox')}
141
+ >
142
+ <DialogContent className={classes.okText}>
143
+ <DialogContentText id="alert-dialog-description">
144
+ Your query URL has been copied!
145
+ </DialogContentText>
146
+ </DialogContent>
147
+ <DialogActions>
148
+ <Button onClick={() => toggleOpen(!open)}>
149
+ OK
150
+ </Button>
151
+ </DialogActions>
152
+ </Dialog>
153
+ </>
154
+ );
155
+ };
156
+
157
+ const styles = () => ({
158
+ urlContainer: {
159
+ marginTop: '10px',
160
+ minHeight: '10px',
161
+ marginBottom: '10px',
162
+ },
163
+ link: {
164
+ lineBreak: 'anywhere',
165
+ overflow: 'hidden',
166
+ fontFamily: 'Nunito',
167
+ fontSize: '12px',
168
+ fontWeight: '500',
169
+ lineHeight: '16px',
170
+ letterSpacing: '0em',
171
+ padding: '5px',
172
+ borderRadius: '5px',
173
+ float: 'left',
174
+ color: '#1D79A8',
175
+ backgroundColor: '#fff',
176
+ maxWidth: '80%',
177
+ },
178
+ viewLink: {
179
+ margin: '0',
180
+ },
181
+ collapseLink: {
182
+ maxHeight: '1em',
183
+ display: 'block',
184
+ // display: '-webkit-box',
185
+ '-webkit-box-orient': 'vertical',
186
+ '-webkit-line-clamp': '1',
187
+ overflow: 'hidden',
188
+ },
189
+ expandLink: {
190
+ cursor: 'pointer',
191
+ },
192
+ expandLinkBtn: {
193
+ float: 'left',
194
+ '&:hover': {
195
+ cursor: 'pointer',
196
+ },
197
+ },
198
+ viewLinkToggleBtn: {
199
+ height: '20px',
200
+ marginRight: '10px',
201
+ fontFamily: 'Nunito',
202
+ fontSize: '12px',
203
+ fontWeight: '500',
204
+ lineHeight: '16px',
205
+ letterSpacing: '0em',
206
+ textAlign: 'left',
207
+ backgroundColor: '#1D79A8',
208
+ textTransform: 'none',
209
+ color: '#fff',
210
+ float: 'left',
211
+ '&:hover': {
212
+ backgroundColor: '#1D79A8',
213
+ color: '#fff',
214
+ },
215
+ },
216
+ urlView: {
217
+ float: 'left',
218
+ width: 'calc(100% - 13px)',
219
+ minWidth: '840px',
220
+ '@media (max-width: 2560px)': {
221
+ maxWidth: '1800px',
222
+ },
223
+ '@media (max-width: 2000px)': {
224
+ maxWidth: '1400px',
225
+ },
226
+ '@media (max-width: 1600px)': {
227
+ maxWidth: '1200px',
228
+ },
229
+ '@media (max-width: 1300px)': {
230
+ maxWidth: '1050px',
231
+ },
232
+ },
233
+ copyIconBtn: {
234
+ padding: '0px',
235
+ marginLeft: '10px',
236
+ float: 'left',
237
+ },
238
+ });
239
+
240
+ export default withStyles(styles)(QueryUrl);
@@ -1,10 +1,11 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import { withStyles, Button } from '@material-ui/core';
3
3
  import { InputTypes } from '@bento-core/facet-filter';
4
4
  import clsx from 'clsx';
5
5
  import { Filter } from '../components/FilterMap';
6
6
  import DEFAULT_STYLES from './styles';
7
7
  import DEFAULT_CONFIG from './config';
8
+ import QueryUrl from '../components/QueryUrl';
8
9
 
9
10
  /**
10
11
  * Generate a pre-configured Explore Query Bar component
@@ -13,13 +14,31 @@ import DEFAULT_CONFIG from './config';
13
14
  * @returns {object} { QueryBar }
14
15
  */
15
16
  export const QueryBarGenerator = (uiConfig = DEFAULT_CONFIG) => {
16
- const { config, functions } = uiConfig;
17
+ const { config, functions, customStyles = {} } = uiConfig;
17
18
  const { CHECKBOX } = InputTypes;
19
+ const styles = () => (
20
+ { ...DEFAULT_STYLES(), ...customStyles }
21
+ );
18
22
 
19
23
  const maxItems = config && typeof config.maxItems === 'number'
20
24
  ? config.maxItems
21
25
  : DEFAULT_CONFIG.config.maxItems;
22
26
 
27
+ const queryURLRootPath = config && typeof config.rootPath === 'string'
28
+ ? config.rootPath
29
+ : DEFAULT_CONFIG.config.rootPath;
30
+
31
+ const viewQueryURL = config && typeof config.viewQueryURL === 'boolean'
32
+ ? config.viewQueryURL
33
+ : DEFAULT_CONFIG.config.viewQueryURL;
34
+
35
+ const displayAllActiveFilters = config && typeof config.displayAllActiveFilters === 'boolean'
36
+ ? config.displayAllActiveFilters
37
+ : DEFAULT_CONFIG.config.displayAllActiveFilters;
38
+
39
+ // const group = config && typeof config.group === 'string'
40
+ // ? config.group : DEFAULT_CONFIG.config.group;
41
+
23
42
  const clearAll = functions && typeof functions.clearAll === 'function'
24
43
  ? functions.clearAll
25
44
  : DEFAULT_CONFIG.functions.clearAll;
@@ -51,28 +70,42 @@ export const QueryBarGenerator = (uiConfig = DEFAULT_CONFIG) => {
51
70
  const clsName = (text = 'filter-section') => text.replace(/\s+/g, '-').toLowerCase();
52
71
 
53
72
  return {
54
- QueryBar: withStyles(DEFAULT_STYLES, { withTheme: true })((props) => {
73
+ QueryBar: withStyles(styles, { withTheme: true })((props) => {
55
74
  const { statusReducer, localFind, classes } = props;
56
75
 
57
76
  const { autocomplete, upload } = localFind;
58
77
 
78
+ const [expand, setExpand] = useState(false);
79
+ const noOfItems = expand ? autocomplete.length : maxItems;
80
+
81
+ useEffect(() => {
82
+ if (autocomplete.length <= maxItems && expand) {
83
+ setExpand(!expand);
84
+ }
85
+ }, [autocomplete]);
86
+
59
87
  // Remove any sections without checkboxes selected
60
88
  const mappedInputs = statusReducer.filter((facet) => facet.section && facet.type)
61
89
  .map((facet) => {
62
90
  if (facet.type !== CHECKBOX) { return facet; }
63
91
 
64
- const { data, items } = facet;
92
+ const { items } = facet;
65
93
  const itemKeys = Object.keys(items);
66
94
  itemKeys.sort((a, b) => a.localeCompare(b));
67
95
 
68
96
  /* Find any SELECTED CHECKBOXES that do NOT have any data
69
97
  * and remove them from the list of selected checkboxes artificially */
70
- itemKeys.forEach((item) => {
71
- if (data.findIndex((d) => d.group === item) < 0) {
72
- itemKeys.splice(itemKeys.indexOf(item), 1);
73
- }
74
- });
98
+ // itemKeys.forEach((item) => {
99
+ // if (data.findIndex((d) => d.group === item) < 0) {
100
+ // itemKeys.splice(itemKeys.indexOf(item), 1);
101
+ // }
102
+ // });
75
103
 
104
+ /**
105
+ * commenting out line 89-93
106
+ * to display all the active filters in the query bar
107
+ * ICDC-3287
108
+ */
76
109
  return { ...facet, items: itemKeys };
77
110
  })
78
111
  .filter((facet) => facet.items.length > 0);
@@ -82,107 +115,143 @@ export const QueryBarGenerator = (uiConfig = DEFAULT_CONFIG) => {
82
115
  }
83
116
 
84
117
  return (
85
- <div className={classes.queryWrapper}>
86
- <Button
87
- className={classes.clearQueryButton}
88
- color="primary"
89
- variant="outlined"
90
- onClick={clearAll}
91
- >
92
- Clear Query
93
- </Button>
94
- <span className={classes.divider} />
95
- <span className={classes.queryContainer}>
96
- {/* Local Find Selections */}
97
- {/* TODO: Refactor this into a separate component */}
98
- {(autocomplete.length || upload.length) ? (
99
- <span>
100
- {/* Standalone case set button */}
101
- {(upload.length && !autocomplete.length)
102
- ? (
103
- <span
104
- className={clsx(classes.filterCheckboxes, classes.localFindBackground)}
105
- onClick={clearUpload}
106
- >
107
- INPUT CASE SET
108
- </span>
109
- ) : null}
110
- {autocomplete.length
111
- ? (
112
- <span>
113
- {' '}
114
- <span
115
- className={clsx(classes.filterName, classes.localFindBackground)}
116
- onClick={clearAutocomplete}
117
- >
118
- Case IDs
119
- </span>
120
- {' '}
121
- {' '}
122
- <span className={classes.operators}>
123
- {(autocomplete.length === 1 && !upload.length) ? 'IS ' : 'IN '}
124
- </span>
125
- </span>
126
- ) : null}
118
+ <>
119
+ <div className={classes.queryWrapper}>
120
+ <Button
121
+ className={classes.clearQueryButton}
122
+ color="primary"
123
+ variant="outlined"
124
+ onClick={clearAll}
125
+ >
126
+ Clear Query
127
+ </Button>
128
+ <span className={classes.divider} />
129
+ <span className={classes.queryContainer}>
130
+ {/* Local Find Selections */}
131
+ {/* TODO: Refactor this into a separate component */}
132
+ {(autocomplete.length || upload.length) ? (
127
133
  <span>
128
- {(((upload.length > 0 ? 1 : 0) + autocomplete.length) > 1)
129
- ? <span className={classes.bracketsOpen}>(</span>
130
- : null}
131
- {upload.length && autocomplete.length ? (
132
- <>
133
- {' '}
134
+ {/* Standalone case set button */}
135
+ {(upload.length && !autocomplete.length)
136
+ ? (
134
137
  <span
135
- className={clsx(classes.filterCheckboxes, classes.localFind)}
138
+ className={clsx(classes.filterCheckboxes, classes.localFindBackground)}
136
139
  onClick={clearUpload}
137
140
  >
138
141
  INPUT CASE SET
139
142
  </span>
140
- {' '}
141
- </>
142
- ) : null}
143
- {autocomplete.slice(0, maxItems).map((d, idx) => (
144
- <>
143
+ ) : null}
144
+ {autocomplete.length
145
+ ? (
146
+ <span>
147
+ {' '}
148
+ <span
149
+ className={clsx(classes.filterName, classes.localFindBackground)}
150
+ onClick={clearAutocomplete}
151
+ >
152
+ Case ID
153
+ </span>
154
+ {' '}
155
+ {' '}
156
+ <span className={classes.operators}>
157
+ {(autocomplete.length === 1 && !upload.length) ? 'IS ' : 'IN '}
158
+ </span>
159
+ </span>
160
+ ) : null}
161
+ <span>
162
+ {(((upload.length > 0 ? 1 : 0) + autocomplete.length) > 1)
163
+ ? <span className={classes.bracketsOpen}>(</span>
164
+ : null}
165
+ {upload.length && autocomplete.length ? (
166
+ <>
167
+ {' '}
168
+ <span
169
+ className={clsx(classes.filterCheckboxes, classes.localFind)}
170
+ onClick={clearUpload}
171
+ >
172
+ INPUT CASE SET
173
+ </span>
174
+ {' '}
175
+ </>
176
+ ) : null}
177
+ {autocomplete.slice(0, noOfItems).map((d, idx) => (
178
+ <>
179
+ <span
180
+ className={clsx(classes.filterCheckboxes, classes.facetSectionCases)}
181
+ key={idx}
182
+ onClick={() => deleteAutocompleteItem(d.title)}
183
+ >
184
+ {d.title}
185
+ </span>
186
+ {idx === (noOfItems - 1) ? null : ' '}
187
+ </>
188
+ ))}
189
+ {autocomplete.length > maxItems && (
190
+ <>
191
+ {
192
+ displayAllActiveFilters
193
+ ? (
194
+ <span
195
+ className={classes.expandBtn}
196
+ onClick={() => setExpand(!expand)}
197
+ >
198
+ ...
199
+ </span>
200
+ )
201
+ : '...'
202
+ }
203
+ </>
204
+ )}
205
+ {(expand && autocomplete.length > maxItems) && (
145
206
  <span
146
- className={clsx(classes.filterCheckboxes, classes.facetSectionCases)}
147
- key={idx}
148
- onClick={() => deleteAutocompleteItem(d.title)}
207
+ className={classes.collapseBtn}
208
+ onClick={() => setExpand(!expand)}
149
209
  >
150
- {d.title}
210
+ {' LESS'}
151
211
  </span>
152
- {idx === (maxItems - 1) ? null : ' '}
153
- </>
154
- ))}
155
- {autocomplete.length > maxItems && '...'}
156
- {(((upload.length > 0 ? 1 : 0) + autocomplete.length) > 1)
157
- ? <span className={classes.bracketsClose}>)</span>
158
- : null}
212
+ )}
213
+ {(((upload.length > 0 ? 1 : 0) + autocomplete.length) > 1)
214
+ ? <span className={classes.bracketsClose}>)</span>
215
+ : null}
216
+ </span>
159
217
  </span>
160
- </span>
161
- ) : null}
162
-
163
- {/* Facet Sidebar Selections */}
164
- {((autocomplete.length || upload.length) && mappedInputs.length)
165
- ? <span className={classes.operators}> AND </span>
166
- : null}
167
- {mappedInputs.map((filter, index) => (
168
- <span className={clsName(filter.section)}>
169
- <Filter
170
- index={index}
171
- type={filter.type}
172
- data={filter}
173
- maxItems={maxItems}
218
+ ) : null}
219
+
220
+ {/* Facet Sidebar Selections */}
221
+ {((autocomplete.length || upload.length) && mappedInputs.length)
222
+ ? <span className={classes.operators}> AND </span>
223
+ : null}
224
+ {mappedInputs.map((filter, index) => (
225
+ <span className={clsName(filter.section)}>
226
+ <Filter
227
+ index={index}
228
+ type={filter.type}
229
+ data={filter}
230
+ maxItems={maxItems}
231
+ displayAllActiveFilters={displayAllActiveFilters}
232
+ classes={classes}
233
+ onSectionClick={filter.type === CHECKBOX
234
+ ? resetFacetSection
235
+ : resetFacetSlider}
236
+ onItemClick={filter.type === CHECKBOX
237
+ ? resetFacetCheckbox
238
+ : resetFacetSlider}
239
+ />
240
+ </span>
241
+ ))}
242
+ </span>
243
+ {
244
+ (viewQueryURL && queryURLRootPath) && (
245
+ <QueryUrl
174
246
  classes={classes}
175
- onSectionClick={filter.type === CHECKBOX
176
- ? resetFacetSection
177
- : resetFacetSlider}
178
- onItemClick={filter.type === CHECKBOX
179
- ? resetFacetCheckbox
180
- : resetFacetSlider}
247
+ localFind={localFind}
248
+ filterItems={mappedInputs}
249
+ rootPath={queryURLRootPath}
181
250
  />
182
- </span>
183
- ))}
184
- </span>
185
- </div>
251
+ )
252
+ }
253
+ </div>
254
+ </>
186
255
  );
187
256
  }),
188
257
  };
@@ -7,6 +7,26 @@ export default {
7
7
  * @var {number}
8
8
  */
9
9
  maxItems: 2,
10
+ /**
11
+ * overirdes maxItems to display all the active filter items
12
+ * @var {boolean}
13
+ */
14
+ displayAllActiveFilters: false,
15
+ /**
16
+ * key to access label text
17
+ * @var {boolean}
18
+ */
19
+ group: 'group',
20
+ /**
21
+ * root path of bento app
22
+ * @var {boolean}
23
+ */
24
+ rootPath: 'localhost',
25
+ /**
26
+ * display query URL
27
+ * @var {boolean}
28
+ */
29
+ viewQueryURL: true,
10
30
  },
11
31
 
12
32
  /* Component Helper Functions */
@@ -104,4 +104,14 @@ export default () => ({
104
104
  facetSectionSamplesBackground: {
105
105
  backgroundColor: '#C3EAF5',
106
106
  },
107
+ expandBtn: {
108
+ '&:hover': {
109
+ cursor: 'pointer',
110
+ },
111
+ },
112
+ collapseBtn: {
113
+ '&:hover': {
114
+ cursor: 'pointer',
115
+ },
116
+ },
107
117
  });