@gridsuite/commons-ui 0.21.0 → 0.23.0

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.
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports["default"] = void 0;
5
+
6
+ var React = _interopRequireWildcard(require("react"));
7
+
8
+ var _Box = _interopRequireDefault(require("@mui/material/Box"));
9
+
10
+ var _Card = _interopRequireDefault(require("@mui/material/Card"));
11
+
12
+ var _CardHeader = _interopRequireDefault(require("@mui/material/CardHeader"));
13
+
14
+ var _CardContent = _interopRequireDefault(require("@mui/material/CardContent"));
15
+
16
+ var _CardActions = _interopRequireDefault(require("@mui/material/CardActions"));
17
+
18
+ var _Collapse = _interopRequireDefault(require("@mui/material/Collapse"));
19
+
20
+ var _IconButton = _interopRequireDefault(require("@mui/material/IconButton"));
21
+
22
+ var _ExpandMore = _interopRequireDefault(require("@mui/icons-material/ExpandMore"));
23
+
24
+ var _Replay = _interopRequireDefault(require("@mui/icons-material/Replay"));
25
+
26
+ var _Typography = _interopRequireDefault(require("@mui/material/Typography"));
27
+
28
+ var _styles = require("@mui/material/styles");
29
+
30
+ var _reactIntl = require("react-intl");
31
+
32
+ var _excluded = ["expand"];
33
+
34
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
35
+
36
+ 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); }
37
+
38
+ 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; }
39
+
40
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
41
+
42
+ function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
43
+
44
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
45
+
46
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
47
+
48
+ var ExpandMore = (0, _styles.styled)(function (props) {
49
+ var expand = props.expand,
50
+ other = _objectWithoutPropertiesLoose(props, _excluded);
51
+
52
+ return /*#__PURE__*/React.createElement(_IconButton["default"], other);
53
+ })(function (_ref) {
54
+ var theme = _ref.theme,
55
+ expand = _ref.expand;
56
+ return {
57
+ transform: !expand ? 'rotate(0deg)' : 'rotate(180deg)',
58
+ marginLeft: 'auto',
59
+ transition: theme.transitions.create('transform', {
60
+ duration: theme.transitions.duration.shortest
61
+ })
62
+ };
63
+ });
64
+
65
+ var CardErrorBoundary = /*#__PURE__*/function (_React$Component) {
66
+ _inheritsLoose(CardErrorBoundary, _React$Component);
67
+
68
+ function CardErrorBoundary(props) {
69
+ var _this;
70
+
71
+ _this = _React$Component.call(this, props) || this;
72
+ _this.state = {
73
+ hasError: false,
74
+ expanded: false,
75
+ error: undefined
76
+ };
77
+ _this.handleExpandClick = _this.handleExpandClick.bind(_assertThisInitialized(_this));
78
+ _this.handleReloadClick = _this.handleReloadClick.bind(_assertThisInitialized(_this));
79
+ return _this;
80
+ }
81
+
82
+ CardErrorBoundary.getDerivedStateFromError = function getDerivedStateFromError(error) {
83
+ // Update state so the next render will show the fallback UI.
84
+ return {
85
+ hasError: true,
86
+ error: error
87
+ };
88
+ };
89
+
90
+ var _proto = CardErrorBoundary.prototype;
91
+
92
+ _proto.componentDidCatch = function componentDidCatch(error, errorInfo) {
93
+ // You can also log the error to an error reporting service
94
+ console.error('CardErrorBoundary caught: ', error, errorInfo);
95
+ };
96
+
97
+ _proto.handleExpandClick = function handleExpandClick() {
98
+ this.setState(function (state) {
99
+ return {
100
+ expanded: !state.expanded
101
+ };
102
+ });
103
+ };
104
+
105
+ _proto.handleReloadClick = function handleReloadClick() {
106
+ this.setState(function (state) {
107
+ return {
108
+ hasError: false,
109
+ expanded: false,
110
+ error: undefined
111
+ };
112
+ });
113
+ };
114
+
115
+ _proto.render = function render() {
116
+ if (this.state.hasError) {
117
+ var _this$state = this.state,
118
+ error = _this$state.error,
119
+ expanded = _this$state.expanded;
120
+ return /*#__PURE__*/React.createElement(_Box["default"], {
121
+ sx: {
122
+ p: 4
123
+ }
124
+ }, /*#__PURE__*/React.createElement(_Card["default"], {
125
+ sx: {
126
+ mx: 'auto',
127
+ maxWidth: 600
128
+ }
129
+ }, /*#__PURE__*/React.createElement(_CardHeader["default"], {
130
+ title: /*#__PURE__*/React.createElement(_reactIntl.FormattedMessage, {
131
+ id: "card_error_boundary/title",
132
+ defaultMessage: "Sorry, Unexpected error :("
133
+ })
134
+ }), /*#__PURE__*/React.createElement(_CardContent["default"], null, /*#__PURE__*/React.createElement(_Typography["default"], {
135
+ variant: "body2",
136
+ color: "text.secondary"
137
+ }, /*#__PURE__*/React.createElement(_reactIntl.FormattedMessage, {
138
+ id: "card_error_boundary/content",
139
+ defaultMessage: "Please reload, or close and reopen this application, or contact support."
140
+ }))), /*#__PURE__*/React.createElement(_CardActions["default"], {
141
+ disableSpacing: true
142
+ }, /*#__PURE__*/React.createElement(_IconButton["default"], {
143
+ onClick: this.handleReloadClick,
144
+ "aria-label": "reload"
145
+ }, /*#__PURE__*/React.createElement(_Replay["default"], null)), /*#__PURE__*/React.createElement(ExpandMore, {
146
+ expand: expanded,
147
+ onClick: this.handleExpandClick,
148
+ "aria-expanded": expanded,
149
+ "aria-label": "show more"
150
+ }, /*#__PURE__*/React.createElement(_ExpandMore["default"], null))), /*#__PURE__*/React.createElement(_Collapse["default"], {
151
+ "in": expanded
152
+ }, /*#__PURE__*/React.createElement(_CardContent["default"], null, /*#__PURE__*/React.createElement(_Typography["default"], {
153
+ variant: "body2",
154
+ color: "text.secondary"
155
+ }, /*#__PURE__*/React.createElement(_reactIntl.FormattedMessage, {
156
+ id: "card_error_boundary/expandederrorheader",
157
+ defaultMessage: "Error message (and see more information in the developper console):"
158
+ })), /*#__PURE__*/React.createElement(_Typography["default"], {
159
+ variant: "caption"
160
+ }, error.message)))));
161
+ }
162
+
163
+ return this.props.children;
164
+ };
165
+
166
+ return CardErrorBoundary;
167
+ }(React.Component);
168
+
169
+ var _default = CardErrorBoundary;
170
+ exports["default"] = _default;
171
+ module.exports = exports.default;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports["default"] = void 0;
5
+
6
+ var _cardErrorBoundary = _interopRequireDefault(require("./card-error-boundary.js"));
7
+
8
+ exports["default"] = _cardErrorBoundary["default"];
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
11
+
12
+ module.exports = exports.default;
@@ -241,7 +241,8 @@ var MuiVirtualizedTable = /*#__PURE__*/function (_React$PureComponent) {
241
241
  className: (0, _clsx3["default"])(classes.tableCell, classes.flexContainer, (_clsx2 = {}, _clsx2[classes.noClick] = displayedValue === undefined || onCellClick == null || columns[columnIndex].clickable === undefined || !columns[columnIndex].clickable, _clsx2[classes.tableCellColor] = displayedValue === undefined || onCellClick !== null && columns[columnIndex].clickable !== undefined && columns[columnIndex].clickable, _clsx2)),
242
242
  variant: "body",
243
243
  style: {
244
- height: rowHeight
244
+ height: rowHeight,
245
+ whiteSpace: 'pre-line'
245
246
  },
246
247
  align: columnIndex != null && columns[columnIndex].numeric || false ? 'right' : 'left',
247
248
  onClick: function onClick() {
@@ -121,7 +121,7 @@ function ReportViewer(_ref) {
121
121
  xs: 12,
122
122
  sm: 3,
123
123
  style: {
124
- height: '100%',
124
+ height: '95%',
125
125
  borderRight: '1px solid rgba(81, 81, 81, 1)'
126
126
  }
127
127
  }, /*#__PURE__*/_react["default"].createElement(_TreeView["default"], {
@@ -142,7 +142,7 @@ function ReportViewer(_ref) {
142
142
  xs: 12,
143
143
  sm: 9,
144
144
  style: {
145
- height: '100%'
145
+ height: '95%'
146
146
  }
147
147
  }, /*#__PURE__*/_react["default"].createElement(_logTable["default"], {
148
148
  logs: logs
@@ -87,7 +87,8 @@ var useStyles = (0, _makeStyles["default"])(function (theme) {
87
87
  return {
88
88
  grow: {
89
89
  flexGrow: 1,
90
- display: 'flex'
90
+ display: 'flex',
91
+ overflow: 'hidden'
91
92
  },
92
93
  logo: {
93
94
  flexShrink: 0,
@@ -227,6 +228,7 @@ var TopBar = function TopBar(_ref) {
227
228
  onEquipmentLabellingClick = _ref.onEquipmentLabellingClick,
228
229
  equipmentLabelling = _ref.equipmentLabelling,
229
230
  withElementsSearch = _ref.withElementsSearch,
231
+ searchDisabled = _ref.searchDisabled,
230
232
  searchingLabel = _ref.searchingLabel,
231
233
  onSearchTermChange = _ref.onSearchTermChange,
232
234
  _onSelectionChange = _ref.onSelectionChange,
@@ -331,15 +333,20 @@ var TopBar = function TopBar(_ref) {
331
333
  };
332
334
 
333
335
  (0, _react.useEffect)(function () {
334
- if (user && withElementsSearch) {
335
- document.addEventListener('keydown', function (e) {
336
+ if (user && withElementsSearch && !searchDisabled) {
337
+ var openSearch = function openSearch(e) {
336
338
  if (e.ctrlKey && e.key === 'f') {
337
339
  e.preventDefault();
338
340
  setDialogSearchOpen(true);
339
341
  }
340
- });
342
+ };
343
+
344
+ document.addEventListener('keydown', openSearch);
345
+ return function () {
346
+ return document.removeEventListener('keydown', openSearch);
347
+ };
341
348
  }
342
- }, [user, withElementsSearch]);
349
+ }, [user, withElementsSearch, searchDisabled]);
343
350
  return /*#__PURE__*/_react["default"].createElement(_AppBar["default"], {
344
351
  position: "static",
345
352
  color: "default",
@@ -383,7 +390,8 @@ var TopBar = function TopBar(_ref) {
383
390
  renderElement: renderElement
384
391
  }), /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_Button["default"], {
385
392
  color: "inherit",
386
- onClick: handleClickElementSearch
393
+ onClick: handleClickElementSearch,
394
+ disabled: searchDisabled
387
395
  }, /*#__PURE__*/_react["default"].createElement(_Search["default"], null)))), user && /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_Button["default"], {
388
396
  "aria-controls": "apps-menu",
389
397
  "aria-haspopup": "true",
@@ -616,6 +624,7 @@ TopBar.propTypes = process.env.NODE_ENV !== "production" ? {
616
624
  onEquipmentLabellingClick: _propTypes["default"].func,
617
625
  equipmentLabelling: _propTypes["default"].bool,
618
626
  withElementsSearch: _propTypes["default"].bool,
627
+ searchDisabled: _propTypes["default"].bool,
619
628
  searchingLabel: _propTypes["default"].string,
620
629
  onSearchTermChange: _propTypes["default"].func,
621
630
  onSelectionChange: _propTypes["default"].func,
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports["default"] = void 0;
5
+ var card_error_boundary_en = {
6
+ 'card_error_boundary/title': 'Sorry, unexpected error :(',
7
+ 'card_error_boundary/content': 'Please reload, or close and reopen this application, or contact support.',
8
+ 'card_error_boundary/expandederrorheader': 'Error message (and see more information in the developper console):'
9
+ };
10
+ var _default = card_error_boundary_en;
11
+ exports["default"] = _default;
12
+ module.exports = exports.default;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports["default"] = void 0;
5
+ var card_error_boundary_fr = {
6
+ 'card_error_boundary/title': 'Désolé, erreur inattendue :(',
7
+ 'card_error_boundary/content': 'Veuillez recharger, ou fermer et réouvrir cette application, ou contacter le support.',
8
+ 'card_error_boundary/expandederrorheader': "Message d'erreur (et voir plus d'informations dans la console developpeur):"
9
+ };
10
+ var _default = card_error_boundary_fr;
11
+ exports["default"] = _default;
12
+ module.exports = exports.default;
package/lib/index.js CHANGED
@@ -136,10 +136,22 @@ var _equipmentSearchFr = _interopRequireDefault(require("./components/translatio
136
136
 
137
137
  exports.equipment_search_fr = _equipmentSearchFr["default"];
138
138
 
139
+ var _cardErrorBoundaryEn = _interopRequireDefault(require("./components/translations/card-error-boundary-en"));
140
+
141
+ exports.card_error_boundary_en = _cardErrorBoundaryEn["default"];
142
+
143
+ var _cardErrorBoundaryFr = _interopRequireDefault(require("./components/translations/card-error-boundary-fr"));
144
+
145
+ exports.card_error_boundary_fr = _cardErrorBoundaryFr["default"];
146
+
139
147
  var _equipmentItem = require("./components/ElementSearchDialog/equipment-item");
140
148
 
141
149
  exports.EquipmentItem = _equipmentItem.EquipmentItem;
142
150
 
151
+ var _CardErrorBoundary2 = _interopRequireDefault(require("./components/CardErrorBoundary"));
152
+
153
+ exports.CardErrorBoundary = _CardErrorBoundary2["default"];
154
+
143
155
  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); }
144
156
 
145
157
  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; }
@@ -41,6 +41,8 @@ function initializeAuthenticationDev(dispatch, isSilentRenew) {
41
41
  return Promise.resolve(userManager);
42
42
  }
43
43
 
44
+ var accessTokenExpiringNotificationTime = 60; // seconds
45
+
44
46
  function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings) {
45
47
  return idpSettings.then(function (r) {
46
48
  return r.json();
@@ -74,10 +76,23 @@ function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings) {
74
76
  var expires_in = parseInt(matched_expires[0].split('=')[1]);
75
77
  var now = parseInt(Date.now() / 1000);
76
78
  var exp = decoded.exp;
79
+ var idTokenExpiresIn = exp - now;
80
+ var minAccesstokenOrIdtokenOrIdpSettingsExpiresIn = expires_in;
81
+ var newExpireReplaceReason;
82
+
83
+ if (idTokenExpiresIn < minAccesstokenOrIdtokenOrIdpSettingsExpiresIn) {
84
+ minAccesstokenOrIdtokenOrIdpSettingsExpiresIn = idTokenExpiresIn;
85
+ newExpireReplaceReason = 'idtoken.exp is earlier';
86
+ }
87
+
88
+ if (idpSettings.maxExpiresIn && idpSettings.maxExpiresIn < minAccesstokenOrIdtokenOrIdpSettingsExpiresIn) {
89
+ minAccesstokenOrIdtokenOrIdpSettingsExpiresIn = idpSettings.maxExpiresIn;
90
+ newExpireReplaceReason = 'idpSettings.maxExpiresIn is smaller';
91
+ }
77
92
 
78
- if (exp < now + expires_in) {
79
- var newhash = window.location.hash.replace(matched_expires[0], 'expires_in=' + (exp - now));
80
- console.debug('Replacing expires_in in window.location.hash because idtoken.exp is earlier. Before: ', window.location.hash, 'after: ', newhash);
93
+ if (newExpireReplaceReason) {
94
+ var newhash = window.location.hash.replace(matched_expires[0], 'expires_in=' + minAccesstokenOrIdtokenOrIdpSettingsExpiresIn);
95
+ console.debug('Replacing expires_in in window.location.hash to ' + minAccesstokenOrIdtokenOrIdpSettingsExpiresIn + ' because ' + newExpireReplaceReason + '. ', 'debug:', 'original expires_in: ' + expires_in + ', ', 'idTokenExpiresIn: ' + idTokenExpiresIn + '(idtoken exp: ' + exp + '), ', 'idpSettings maxExpiresIn: ' + idpSettings.maxExpiresIn);
81
96
  window.location.hash = newhash;
82
97
  }
83
98
  }
@@ -96,9 +111,10 @@ function initializeAuthenticationProd(dispatch, isSilentRenew, idpSettings) {
96
111
  response_type: 'id_token token',
97
112
  scope: idpSettings.scope,
98
113
  automaticSilentRenew: !isSilentRenew,
99
- accessTokenExpiringNotificationTime: 60
114
+ accessTokenExpiringNotificationTime: accessTokenExpiringNotificationTime
100
115
  };
101
116
  var userManager = new _oidcClient.UserManager(settings);
117
+ userManager.idpSettings = idpSettings; //store our settings in there as well to use it later
102
118
 
103
119
  if (!isSilentRenew) {
104
120
  handleUser(dispatch, userManager);
@@ -119,7 +135,11 @@ function logout(dispatch, userManagerInstance) {
119
135
  dispatch((0, _actions.setLoggedUser)(null));
120
136
  sessionStorage.removeItem(hackauthoritykey); //To remove when hack is removed
121
137
 
122
- return userManagerInstance.signoutRedirect().then(function () {
138
+ return userManagerInstance.signoutRedirect({
139
+ extraQueryParams: {
140
+ TargetResource: userManagerInstance.settings.post_logout_redirect_uri
141
+ }
142
+ }).then(function () {
123
143
  return console.debug('logged out');
124
144
  });
125
145
  }
@@ -160,8 +180,41 @@ function handleUser(dispatch, userManager) {
160
180
  dispatchUser(dispatch, userManager);
161
181
  });
162
182
  userManager.events.addSilentRenewError(function (error) {
163
- console.debug(error);
164
- logout(dispatch, userManager);
183
+ console.debug(error); // wait for accessTokenExpiringNotificationTime so that the user is expired
184
+ // otherwise the library tries to signin immediately when we do getUser()
185
+
186
+ window.setTimeout(function () {
187
+ userManager.getUser().then(function (user) {
188
+ var now = parseInt(Date.now() / 1000);
189
+ var exp = (0, _jwtDecode["default"])(user.id_token).exp;
190
+ var idTokenExpiresIn = exp - now;
191
+
192
+ if (idTokenExpiresIn < 0) {
193
+ console.log('Error in silent renew, idtoken expired: ' + idTokenExpiresIn + ' => Logging out.', error); // TODO here allow to continue to use the app but in some kind of frozen state because we can't make API calls anymore
194
+ // remove the user from our app, but don't sso logout on all other apps
195
+
196
+ return dispatch((0, _actions.setLoggedUser)(null));
197
+ } else if (userManager.idpSettings.maxExpiresIn) {
198
+ if (idTokenExpiresIn < userManager.idpSettings.maxExpiresIn) {
199
+ // TODO here attempt last chance login ? snackbar to notify the user ? Popup ?
200
+ // for now we do the same thing as in the else block
201
+ console.log('Error in silent renew, but idtoken ALMOST expiring (expiring in' + idTokenExpiresIn + ') => last chance' + userManager.idpSettings.maxExpiresIn, error);
202
+ user.expires_in = userManager.idpSettings.maxExpiresIn;
203
+ userManager.storeUser(user).then(function () {
204
+ userManager.getUser();
205
+ });
206
+ } else {
207
+ console.log('Error in silent renew, but idtoken NOT expiring (expiring in' + idTokenExpiresIn + ') => postponing expiration to' + userManager.idpSettings.maxExpiresIn, error);
208
+ user.expires_in = userManager.idpSettings.maxExpiresIn;
209
+ userManager.storeUser(user).then(function () {
210
+ userManager.getUser();
211
+ });
212
+ }
213
+ } else {
214
+ console.log('Error in silent renew, unsupported configuration: token still valid for ' + idTokenExpiresIn + ' but maxExpiresIn is not configured:' + userManager.idpSettings.maxExpiresIn, error);
215
+ }
216
+ });
217
+ }, accessTokenExpiringNotificationTime * 1000);
165
218
  });
166
219
  console.debug('dispatch user');
167
220
  dispatchUser(dispatch, userManager);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gridsuite/commons-ui",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "common react components for gridsuite applications",
5
5
  "engines": {
6
6
  "npm": "<=6",