cozy-sharing 13.0.0 → 13.1.1

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/CHANGELOG.md CHANGED
@@ -3,6 +3,31 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [13.1.1](https://github.com/cozy/cozy-libs/compare/cozy-sharing@13.1.0...cozy-sharing@13.1.1) (2024-04-15)
7
+
8
+ **Note:** Version bump only for package cozy-sharing
9
+
10
+
11
+
12
+
13
+
14
+ # [13.1.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@13.0.0...cozy-sharing@13.1.0) (2024-04-09)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * Resetting sharing rights after a share ([5f3ebaa](https://github.com/cozy/cozy-libs/commit/5f3ebaa4b220655c97f07fa6918f2be830568fb5))
20
+
21
+
22
+ ### Features
23
+
24
+ * Alert if group shared with members already in it with other rights ([786b1a0](https://github.com/cozy/cozy-libs/commit/786b1a08d9f30db3126e6d1b77c14f25b0f129a5))
25
+ * Hide groups when they are already shared ([f64ee06](https://github.com/cozy/cozy-libs/commit/f64ee06637c0f74b776cde72bdea9ae693c26638))
26
+
27
+
28
+
29
+
30
+
6
31
  # [13.0.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@12.3.0...cozy-sharing@13.0.0) (2024-04-08)
7
32
 
8
33
 
@@ -6,7 +6,6 @@ import PropTypes from 'prop-types';
6
6
  import React, { useState } from 'react';
7
7
  import { useClient } from 'cozy-client';
8
8
  import flag from 'cozy-flags';
9
- import Alerter from 'cozy-ui/transpiled/react/deprecated/Alerter';
10
9
  import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert';
11
10
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
12
11
  import ShareRecipientsInput from './ShareRecipientsInput';
@@ -66,7 +65,7 @@ export var ShareByEmail = function ShareByEmail(_ref) {
66
65
  loading = _useState4[0],
67
66
  setLoading = _useState4[1];
68
67
 
69
- var _useState5 = useState(),
68
+ var _useState5 = useState('readWrite'),
70
69
  _useState6 = _slicedToArray(_useState5, 2),
71
70
  selectedOption = _useState6[0],
72
71
  setSelectedOption = _useState6[1];
@@ -77,6 +76,7 @@ export var ShareByEmail = function ShareByEmail(_ref) {
77
76
  setRecipientsLimit = _useState8[1];
78
77
 
79
78
  var reset = function reset() {
79
+ setSelectedOption('readWrite');
80
80
  setRecipients([]);
81
81
  setLoading(false);
82
82
  };
@@ -99,7 +99,7 @@ export var ShareByEmail = function ShareByEmail(_ref) {
99
99
 
100
100
  var share = /*#__PURE__*/function () {
101
101
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
102
- var recipientsBefore, contacts, readWriteRecipients, readOnlyRecipients;
102
+ var recipientsBefore, contacts, readWriteRecipients, readOnlyRecipients, showGenericAlert, detail, sharingRights;
103
103
  return _regeneratorRuntime.wrap(function _callee$(_context) {
104
104
  while (1) switch (_context.prev = _context.next) {
105
105
  case 0:
@@ -155,22 +155,54 @@ export var ShareByEmail = function ShareByEmail(_ref) {
155
155
  severity: 'success',
156
156
  variant: 'filled'
157
157
  });
158
- reset();
159
158
  _context.next = 25;
160
159
  break;
161
160
 
162
- case 20:
163
- _context.prev = 20;
161
+ case 19:
162
+ _context.prev = 19;
164
163
  _context.t0 = _context["catch"](7);
165
- Alerter.error('Error.generic');
166
- reset();
164
+ showGenericAlert = true;
165
+
166
+ if (_context.t0.name === 'FetchError' && _context.t0.status === 400) {
167
+ detail = JSON.parse(_context.t0.message).errors[0].detail;
168
+
169
+ if (detail.startsWith('A group member cannot be added as they are already in')) {
170
+ // To know the sharing rights of the other group
171
+ sharingRights = selectedOption === 'readOnly' ? 'readWrite' : 'readOnly';
172
+ showAlert({
173
+ message: t('Share.errors.groupMemberAlreadyInSharing', {
174
+ smart_count: recipients.length,
175
+ groupName: recipients[0].name,
176
+ sharingRights: t("Share.errors.sharingRights.".concat(sharingRights)),
177
+ icon: false
178
+ }),
179
+ severity: 'error',
180
+ variant: 'filled'
181
+ });
182
+ showGenericAlert = false;
183
+ }
184
+ }
185
+
186
+ if (showGenericAlert) {
187
+ showAlert({
188
+ message: t("".concat(documentType, ".share.error.generic")),
189
+ severity: 'error',
190
+ variant: 'filled'
191
+ });
192
+ }
193
+
167
194
  throw _context.t0;
168
195
 
169
196
  case 25:
197
+ _context.prev = 25;
198
+ reset();
199
+ return _context.finish(25);
200
+
201
+ case 28:
170
202
  case "end":
171
203
  return _context.stop();
172
204
  }
173
- }, _callee, null, [[7, 20]]);
205
+ }, _callee, null, [[7, 19, 25, 28]]);
174
206
  }));
175
207
 
176
208
  return function share() {
@@ -208,10 +240,12 @@ export var ShareByEmail = function ShareByEmail(_ref) {
208
240
  onRemove: function onRemove(recipient) {
209
241
  return onRecipientRemove(recipient);
210
242
  },
243
+ currentRecipients: currentRecipients,
211
244
  recipients: recipients
212
245
  })), showShareControl && /*#__PURE__*/React.createElement("div", {
213
246
  className: styles['share-type-control']
214
247
  }, /*#__PURE__*/React.createElement(ShareTypeSelect, {
248
+ value: selectedOption,
215
249
  options: getSharingOptions(),
216
250
  onChange: onChange
217
251
  }), /*#__PURE__*/React.createElement(ShareSubmit, {
@@ -19,7 +19,8 @@ import { buildReachableContactsQuery, buildContactGroupsByIdsQuery, buildUnreach
19
19
  */
20
20
 
21
21
  var ShareRecipientsInput = function ShareRecipientsInput(_ref) {
22
- var recipients = _ref.recipients,
22
+ var currentRecipients = _ref.currentRecipients,
23
+ recipients = _ref.recipients,
23
24
  placeholder = _ref.placeholder,
24
25
  onPick = _ref.onPick,
25
26
  onRemove = _ref.onRemove;
@@ -38,7 +39,14 @@ var ShareRecipientsInput = function ShareRecipientsInput(_ref) {
38
39
  }))));
39
40
  var contactGroupsByIdsResult = useQueryAll(contactGroupsByIdsQuery.definition, contactGroupsByIdsQuery.options);
40
41
  var isLoading = isQueryLoading(reachableContactsResult) || reachableContactsResult.hasMore || isQueryLoading(contactGroupsByIdsResult) || contactGroupsByIdsResult.hasMore || flag('sharing.show-recipient-groups') && (isQueryLoading(unreachableContactsWithGroupsResult) || unreachableContactsWithGroupsResult.hasMore);
41
- var contactGroups = (contactGroupsByIdsResult.data || []).map(function (contactGroup) {
42
+ var currentRecipientGroups = currentRecipients.map(function (_ref2) {
43
+ var id = _ref2.id;
44
+ return id;
45
+ }).filter(Boolean);
46
+ var contactGroups = (contactGroupsByIdsResult.data || []).filter(function (_ref3) {
47
+ var _id = _ref3._id;
48
+ return !flag('sharing.show-recipient-groups') || !currentRecipientGroups.includes(_id);
49
+ }).map(function (contactGroup) {
42
50
  var reachableMembers = getContactsFromGroupId(reachableContactsResult.data, contactGroup.id).map(function (contact) {
43
51
  return _objectSpread(_objectSpread({}, contact), {}, {
44
52
  isReachable: true
@@ -72,12 +80,14 @@ var ShareRecipientsInput = function ShareRecipientsInput(_ref) {
72
80
  };
73
81
 
74
82
  ShareRecipientsInput.propTypes = {
83
+ currentRecipients: PropTypes.array,
75
84
  recipients: PropTypes.array,
76
85
  placeholder: PropTypes.string,
77
86
  onPick: PropTypes.func.isRequired,
78
87
  onRemove: PropTypes.func.isRequired
79
88
  };
80
89
  ShareRecipientsInput.defaultProps = {
90
+ currentRecipients: [],
81
91
  recipients: []
82
92
  };
83
93
  export default ShareRecipientsInput;
@@ -9,7 +9,9 @@ import AppLike from './SharingBanner/test/AppLike';
9
9
  jest.mock('cozy-flags', function () {
10
10
  return {
11
11
  __esModule: true,
12
- default: jest.fn()
12
+ default: jest.fn(function () {
13
+ return null;
14
+ })
13
15
  };
14
16
  });
15
17
  jest.mock('./ShareAutosuggest', function () {
package/locales/en.json CHANGED
@@ -75,6 +75,15 @@
75
75
  "deactivate": "Deactivate link",
76
76
  "cancel": "Cancel",
77
77
  "confirm": "OK"
78
+ },
79
+ "errors": {
80
+ "errors": {
81
+ "groupMemberAlreadyInSharing": "%{groupName} members have already been invited with %{sharingRights} rights. It is not possible to invite the same contact twice with different rights. |||| Contacts have already been invited with %{sharingRights} rights. It is not possible to invite the same contact twice with different rights.",
82
+ "sharingRights": {
83
+ "readOnly": "read",
84
+ "readWrite": "write"
85
+ }
86
+ }
78
87
  }
79
88
  },
80
89
  "Sharings": {
package/locales/fr.json CHANGED
@@ -75,6 +75,13 @@
75
75
  "deactivate": "Désactiver le lien",
76
76
  "cancel": "Annuler",
77
77
  "confirm": "OK"
78
+ },
79
+ "errors": {
80
+ "groupMemberAlreadyInSharing": "Des membres de %{groupName} ont déjà été invités avec des droits de %{sharingRights}. Impossible d’inviter 2 fois le même contact avec des droits différents. |||| Des contacts ont déjà été invités avec des droits de %{sharingRights}. Impossible d’inviter 2 fois le même contact avec des droits différents.",
81
+ "sharingRights": {
82
+ "readOnly": "lecture",
83
+ "readWrite": "modification"
84
+ }
78
85
  }
79
86
  },
80
87
  "Sharings": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-sharing",
3
- "version": "13.0.0",
3
+ "version": "13.1.1",
4
4
  "description": "Provides sharing login for React applications.",
5
5
  "main": "dist/index.js",
6
6
  "author": "Cozy",
@@ -31,7 +31,7 @@
31
31
  "@cozy/minilog": "^1.0.0",
32
32
  "classnames": "^2.2.6",
33
33
  "cozy-device-helper": "^3.0.0",
34
- "cozy-doctypes": "^1.89.5",
34
+ "cozy-doctypes": "^1.90.0",
35
35
  "lodash": "^4.17.19",
36
36
  "react-autosuggest": "^10.1.0",
37
37
  "react-tooltip": "^3.11.1",
@@ -71,5 +71,5 @@
71
71
  "sideEffects": [
72
72
  "*.css"
73
73
  ],
74
- "gitHead": "ba86f000e46844edb26e07edec601bc7669fcda9"
74
+ "gitHead": "d8c61c1542294c68eec4ad1b747d7fb553d1039b"
75
75
  }
@@ -3,7 +3,6 @@ import React, { useState } from 'react'
3
3
 
4
4
  import { useClient } from 'cozy-client'
5
5
  import flag from 'cozy-flags'
6
- import Alerter from 'cozy-ui/transpiled/react/deprecated/Alerter'
7
6
  import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
8
7
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
9
8
 
@@ -36,10 +35,11 @@ export const ShareByEmail = ({
36
35
 
37
36
  const [recipients, setRecipients] = useState([])
38
37
  const [loading, setLoading] = useState(false)
39
- const [selectedOption, setSelectedOption] = useState()
38
+ const [selectedOption, setSelectedOption] = useState('readWrite')
40
39
  const [showRecipientsLimit, setRecipientsLimit] = useState(false)
41
40
 
42
41
  const reset = () => {
42
+ setSelectedOption('readWrite')
43
43
  setRecipients([])
44
44
  setLoading(false)
45
45
  }
@@ -103,11 +103,43 @@ export const ShareByEmail = ({
103
103
  severity: 'success',
104
104
  variant: 'filled'
105
105
  })
106
- reset()
107
106
  } catch (err) {
108
- Alerter.error('Error.generic')
109
- reset()
107
+ let showGenericAlert = true
108
+ if (err.name === 'FetchError' && err.status === 400) {
109
+ const detail = JSON.parse(err.message).errors[0].detail
110
+ if (
111
+ detail.startsWith(
112
+ 'A group member cannot be added as they are already in'
113
+ )
114
+ ) {
115
+ // To know the sharing rights of the other group
116
+ const sharingRights =
117
+ selectedOption === 'readOnly' ? 'readWrite' : 'readOnly'
118
+ showAlert({
119
+ message: t('Share.errors.groupMemberAlreadyInSharing', {
120
+ smart_count: recipients.length,
121
+ groupName: recipients[0].name,
122
+ sharingRights: t(`Share.errors.sharingRights.${sharingRights}`),
123
+ icon: false
124
+ }),
125
+ severity: 'error',
126
+ variant: 'filled'
127
+ })
128
+ showGenericAlert = false
129
+ }
130
+ }
131
+
132
+ if (showGenericAlert) {
133
+ showAlert({
134
+ message: t(`${documentType}.share.error.generic`),
135
+ severity: 'error',
136
+ variant: 'filled'
137
+ })
138
+ }
139
+
110
140
  throw err
141
+ } finally {
142
+ reset()
111
143
  }
112
144
  }
113
145
 
@@ -143,12 +175,17 @@ export const ShareByEmail = ({
143
175
  }
144
176
  onPick={recipient => onRecipientPick(recipient)}
145
177
  onRemove={recipient => onRecipientRemove(recipient)}
178
+ currentRecipients={currentRecipients}
146
179
  recipients={recipients}
147
180
  />
148
181
  </div>
149
182
  {showShareControl && (
150
183
  <div className={styles['share-type-control']}>
151
- <ShareTypeSelect options={getSharingOptions()} onChange={onChange} />
184
+ <ShareTypeSelect
185
+ value={selectedOption}
186
+ options={getSharingOptions()}
187
+ onChange={onChange}
188
+ />
152
189
  <ShareSubmit
153
190
  label={t(`${documentType}.share.shareByEmail.send`)}
154
191
  onSubmit={share}
@@ -18,6 +18,7 @@ import {
18
18
  * In order to display the total number of members in each group, we also retrieve the contacts that are not reachable.
19
19
  */
20
20
  const ShareRecipientsInput = ({
21
+ currentRecipients,
21
22
  recipients,
22
23
  placeholder,
23
24
  onPick,
@@ -62,8 +63,16 @@ const ShareRecipientsInput = ({
62
63
  (isQueryLoading(unreachableContactsWithGroupsResult) ||
63
64
  unreachableContactsWithGroupsResult.hasMore))
64
65
 
65
- const contactGroups = (contactGroupsByIdsResult.data || []).map(
66
- contactGroup => {
66
+ const currentRecipientGroups = currentRecipients
67
+ .map(({ id }) => id)
68
+ .filter(Boolean)
69
+ const contactGroups = (contactGroupsByIdsResult.data || [])
70
+ .filter(
71
+ ({ _id }) =>
72
+ !flag('sharing.show-recipient-groups') ||
73
+ !currentRecipientGroups.includes(_id)
74
+ )
75
+ .map(contactGroup => {
67
76
  const reachableMembers = getContactsFromGroupId(
68
77
  reachableContactsResult.data,
69
78
  contactGroup.id
@@ -91,8 +100,7 @@ const ShareRecipientsInput = ({
91
100
  ...contactGroup,
92
101
  members: [...reachableMembers, ...unreachableMembers]
93
102
  }
94
- }
95
- )
103
+ })
96
104
 
97
105
  const contactsAndGroups = [
98
106
  ...(reachableContactsResult.data || []),
@@ -112,6 +120,7 @@ const ShareRecipientsInput = ({
112
120
  }
113
121
 
114
122
  ShareRecipientsInput.propTypes = {
123
+ currentRecipients: PropTypes.array,
115
124
  recipients: PropTypes.array,
116
125
  placeholder: PropTypes.string,
117
126
  onPick: PropTypes.func.isRequired,
@@ -119,6 +128,7 @@ ShareRecipientsInput.propTypes = {
119
128
  }
120
129
 
121
130
  ShareRecipientsInput.defaultProps = {
131
+ currentRecipients: [],
122
132
  recipients: []
123
133
  }
124
134
 
@@ -9,7 +9,7 @@ import AppLike from './SharingBanner/test/AppLike'
9
9
 
10
10
  jest.mock('cozy-flags', () => ({
11
11
  __esModule: true,
12
- default: jest.fn()
12
+ default: jest.fn(() => null)
13
13
  }))
14
14
 
15
15
  jest.mock('./ShareAutosuggest', () => ({