cozy-sharing 40.1.6 → 40.1.7

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 (86) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/components/FederatedFolder/FederatedFolderModal.js +10 -12
  3. package/dist/components/Recipient/DowngradePermissionConfirmDialog.js +3 -12
  4. package/dist/components/Recipient/GroupRecipient.js +1 -4
  5. package/dist/components/Recipient/GroupRecipient.stories.js +3 -1
  6. package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +1 -4
  7. package/dist/components/Recipient/GroupRecipientPermissions.js +5 -8
  8. package/dist/components/Recipient/GroupRecipientPermissions.stories.js +2 -0
  9. package/dist/components/Recipient/LinkRecipient.js +2 -6
  10. package/dist/components/Recipient/LinkRecipient.stories.js +4 -0
  11. package/dist/components/Recipient/LinkRecipientPermissions.js +13 -12
  12. package/dist/components/Recipient/LinkRecipientPermissions.stories.js +5 -1
  13. package/dist/components/Recipient/MemberRecipient.js +7 -6
  14. package/dist/components/Recipient/MemberRecipient.spec.js +7 -12
  15. package/dist/components/Recipient/MemberRecipientPermissions.js +28 -13
  16. package/dist/components/Recipient/MemberRecipientPermissions.spec.js +5 -14
  17. package/dist/components/Recipient/MemberRecipientPermissions.stories.js +2 -1
  18. package/dist/components/Recipient/OwnerRecipient.js +4 -17
  19. package/dist/components/Recipient/OwnerRecipient.stories.js +3 -1
  20. package/dist/components/Recipient/OwnerRecipientDefaultLite.js +1 -1
  21. package/dist/components/Recipient/PermissionTypeMenu.js +32 -155
  22. package/dist/components/Recipient/PermissionTypeMenuWrapper.js +37 -0
  23. package/dist/components/Recipient/{PermissionTypeMenu.spec.js → PermissionTypeMenuWrapper.spec.js} +2 -2
  24. package/dist/components/Recipient/RecipientList.js +10 -0
  25. package/dist/components/Recipient/RecipientList.stories.js +3 -0
  26. package/dist/components/ShareDialogCozyToCozy.js +20 -19
  27. package/dist/components/ShareDialogCozyToCozy.spec.js +3 -0
  28. package/dist/components/ShareDialogOnlyByLink.js +3 -5
  29. package/dist/components/ShareDialogOnlyByLink.spec.js +0 -1
  30. package/dist/components/ShareModal/SharingDetailsModal.js +2 -2
  31. package/dist/components/SharedDrive/EditSharedDriveModal.js +11 -10
  32. package/dist/components/SharedDrive/useSharedDrive.js +8 -11
  33. package/dist/components/SharingContent.js +3 -5
  34. package/dist/components/WhoHasAccess.js +27 -11
  35. package/dist/components/WhoHasAccessWrapper.js +122 -0
  36. package/dist/helpers/recipients.js +46 -0
  37. package/dist/helpers/recipients.spec.js +89 -0
  38. package/dist/hooks/useMemberPermissionType.js +191 -0
  39. package/dist/hooks/useResolveRecipients.js +53 -0
  40. package/dist/hooks/useResolveRecipients.spec.js +140 -0
  41. package/dist/index.js +1 -1
  42. package/package.json +3 -3
  43. package/src/components/FederatedFolder/FederatedFolderModal.jsx +6 -12
  44. package/src/components/Recipient/DowngradePermissionConfirmDialog.jsx +3 -10
  45. package/src/components/Recipient/GroupRecipient.jsx +1 -5
  46. package/src/components/Recipient/GroupRecipient.stories.jsx +3 -1
  47. package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +1 -4
  48. package/src/components/Recipient/GroupRecipientPermissions.jsx +5 -5
  49. package/src/components/Recipient/GroupRecipientPermissions.stories.jsx +2 -0
  50. package/src/components/Recipient/LinkRecipient.jsx +2 -4
  51. package/src/components/Recipient/LinkRecipient.stories.jsx +4 -0
  52. package/src/components/Recipient/LinkRecipientPermissions.jsx +16 -12
  53. package/src/components/Recipient/LinkRecipientPermissions.stories.jsx +5 -1
  54. package/src/components/Recipient/MemberRecipient.jsx +4 -4
  55. package/src/components/Recipient/MemberRecipient.spec.jsx +7 -10
  56. package/src/components/Recipient/MemberRecipientPermissions.jsx +29 -13
  57. package/src/components/Recipient/MemberRecipientPermissions.spec.jsx +5 -11
  58. package/src/components/Recipient/MemberRecipientPermissions.stories.jsx +2 -1
  59. package/src/components/Recipient/OwnerRecipient.jsx +4 -17
  60. package/src/components/Recipient/OwnerRecipient.stories.jsx +1 -1
  61. package/src/components/Recipient/OwnerRecipientDefaultLite.jsx +1 -1
  62. package/src/components/Recipient/PermissionTypeMenu.jsx +21 -81
  63. package/src/components/Recipient/PermissionTypeMenuWrapper.jsx +32 -0
  64. package/src/components/Recipient/{PermissionTypeMenu.spec.jsx → PermissionTypeMenuWrapper.spec.jsx} +2 -2
  65. package/src/components/Recipient/RecipientList.jsx +10 -0
  66. package/src/components/Recipient/RecipientList.stories.jsx +3 -0
  67. package/src/components/ShareDialogCozyToCozy.jsx +10 -11
  68. package/src/components/ShareDialogCozyToCozy.spec.jsx +1 -0
  69. package/src/components/ShareDialogOnlyByLink.jsx +2 -4
  70. package/src/components/ShareDialogOnlyByLink.spec.jsx +0 -1
  71. package/src/components/ShareModal/SharingDetailsModal.jsx +2 -2
  72. package/src/components/SharedDrive/EditSharedDriveModal.jsx +6 -11
  73. package/src/components/SharedDrive/useSharedDrive.js +4 -11
  74. package/src/components/SharingContent.jsx +2 -4
  75. package/src/components/WhoHasAccess.jsx +26 -12
  76. package/src/components/WhoHasAccessWrapper.jsx +117 -0
  77. package/src/helpers/recipients.js +44 -0
  78. package/src/helpers/recipients.spec.js +82 -0
  79. package/src/hooks/useMemberPermissionType.js +110 -0
  80. package/src/hooks/useResolveRecipients.js +38 -0
  81. package/src/hooks/useResolveRecipients.spec.js +70 -0
  82. package/src/index.jsx +1 -1
  83. package/dist/components/Recipient/OwnerRecipientDefault.js +0 -27
  84. package/dist/components/Recipient/OwnerRecipientDefault.stories.js +0 -10
  85. package/src/components/Recipient/OwnerRecipientDefault.jsx +0 -37
  86. package/src/components/Recipient/OwnerRecipientDefault.stories.jsx +0 -13
@@ -0,0 +1,191 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+
5
+ 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; }
6
+
7
+ 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; }
8
+
9
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
10
+
11
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
12
+
13
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
14
+
15
+ import { useCallback } from 'react';
16
+ import { useClient } from 'cozy-client';
17
+ import flag from 'cozy-flags';
18
+ import { useFetchDocumentPath } from './useFetchDocumentPath';
19
+ import { useResolveRecipients } from './useResolveRecipients';
20
+ import { useSharingContext } from './useSharingContext';
21
+ import { getSharingDocIds } from '../state';
22
+ /**
23
+ * Gives what is needed to change the permission type of the members
24
+ * of a document's sharing
25
+ *
26
+ * @param {object} document - Shared document
27
+ * @param {object} [options]
28
+ * @param {boolean} [options.shouldFetchPath] - Whether to fetch the document
29
+ * path, needed to know the shared parent
30
+ * @returns {{ isInsideSharedParent: boolean, sharedParentName: string|null, setMemberType: Function }}
31
+ * `setMemberType({ sharingId, memberIndex, type, recipient }, newType, { withAncestors })`
32
+ * also downgrades the member on the read-write ancestor sharings when `withAncestors` is set
33
+ */
34
+
35
+ export var useMemberPermissionType = function useMemberPermissionType(document) {
36
+ var _sharedParentPath$spl;
37
+
38
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
39
+ _ref$shouldFetchPath = _ref.shouldFetchPath,
40
+ shouldFetchPath = _ref$shouldFetchPath === void 0 ? true : _ref$shouldFetchPath;
41
+
42
+ var client = useClient();
43
+
44
+ var _useSharingContext = useSharingContext(),
45
+ hasSharedParent = _useSharingContext.hasSharedParent,
46
+ getSharedParentPath = _useSharingContext.getSharedParentPath,
47
+ updateSharingMemberType = _useSharingContext.updateSharingMemberType,
48
+ getSharingById = _useSharingContext.getSharingById,
49
+ share = _useSharingContext.share;
50
+
51
+ var resolveRecipients = useResolveRecipients();
52
+ var documentPath = useFetchDocumentPath(client, shouldFetchPath ? document : null);
53
+ var isInsideSharedParent = Boolean(documentPath) && Boolean(hasSharedParent === null || hasSharedParent === void 0 ? void 0 : hasSharedParent(documentPath));
54
+ var sharedParentPath = documentPath ? getSharedParentPath === null || getSharedParentPath === void 0 ? void 0 : getSharedParentPath(documentPath) : null;
55
+ var setMemberType = useCallback( /*#__PURE__*/function () {
56
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref2, newType) {
57
+ var sharingId,
58
+ memberIndex,
59
+ type,
60
+ recipient,
61
+ _ref4,
62
+ _ref4$withAncestors,
63
+ withAncestors,
64
+ ancestors,
65
+ _iterator,
66
+ _step,
67
+ ancestor,
68
+ documentId,
69
+ sourceSharing,
70
+ _yield$resolveRecipie2,
71
+ recipients,
72
+ _args = arguments;
73
+
74
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
75
+ while (1) switch (_context.prev = _context.next) {
76
+ case 0:
77
+ sharingId = _ref2.sharingId, memberIndex = _ref2.memberIndex, type = _ref2.type, recipient = _ref2.recipient;
78
+ _ref4 = _args.length > 2 && _args[2] !== undefined ? _args[2] : {}, _ref4$withAncestors = _ref4.withAncestors, withAncestors = _ref4$withAncestors === void 0 ? false : _ref4$withAncestors;
79
+
80
+ if (!withAncestors) {
81
+ _context.next = 21;
82
+ break;
83
+ }
84
+
85
+ // Ancestors first: only the target's own update refetches its
86
+ // effective recipients, which must already see them downgraded.
87
+ ancestors = ((recipient === null || recipient === void 0 ? void 0 : recipient.sources) || []).filter(function (s) {
88
+ return s.kind === 'ancestor' && !s.read_only;
89
+ });
90
+ _iterator = _createForOfIteratorHelper(ancestors);
91
+ _context.prev = 5;
92
+
93
+ _iterator.s();
94
+
95
+ case 7:
96
+ if ((_step = _iterator.n()).done) {
97
+ _context.next = 13;
98
+ break;
99
+ }
100
+
101
+ ancestor = _step.value;
102
+ _context.next = 11;
103
+ return updateSharingMemberType(ancestor.sharing_id, ancestor.member_index, newType);
104
+
105
+ case 11:
106
+ _context.next = 7;
107
+ break;
108
+
109
+ case 13:
110
+ _context.next = 18;
111
+ break;
112
+
113
+ case 15:
114
+ _context.prev = 15;
115
+ _context.t0 = _context["catch"](5);
116
+
117
+ _iterator.e(_context.t0);
118
+
119
+ case 18:
120
+ _context.prev = 18;
121
+
122
+ _iterator.f();
123
+
124
+ return _context.finish(18);
125
+
126
+ case 21:
127
+ documentId = (document === null || document === void 0 ? void 0 : document._id) || (document === null || document === void 0 ? void 0 : document.id);
128
+
129
+ if (!(flag('drive.federated-shared-folder.enabled') && type === 'one-way' && newType === 'two-way' && documentId)) {
130
+ _context.next = 34;
131
+ break;
132
+ }
133
+
134
+ sourceSharing = getSharingById(sharingId);
135
+
136
+ if (!(sourceSharing && !getSharingDocIds(sourceSharing).includes(documentId))) {
137
+ _context.next = 34;
138
+ break;
139
+ }
140
+
141
+ _context.next = 27;
142
+ return resolveRecipients([recipient]);
143
+
144
+ case 27:
145
+ _yield$resolveRecipie2 = _context.sent;
146
+ recipients = _yield$resolveRecipie2.recipients;
147
+
148
+ if (recipients[0]) {
149
+ _context.next = 31;
150
+ break;
151
+ }
152
+
153
+ throw new Error('Recipient contact not found');
154
+
155
+ case 31:
156
+ _context.next = 33;
157
+ return share({
158
+ document: _objectSpread(_objectSpread({}, document), {}, {
159
+ id: documentId
160
+ }),
161
+ description: document.name,
162
+ recipients: recipients,
163
+ readOnlyRecipients: [],
164
+ sharedDrive: true,
165
+ openSharing: false
166
+ });
167
+
168
+ case 33:
169
+ return _context.abrupt("return");
170
+
171
+ case 34:
172
+ _context.next = 36;
173
+ return updateSharingMemberType(sharingId, memberIndex, newType, document);
174
+
175
+ case 36:
176
+ case "end":
177
+ return _context.stop();
178
+ }
179
+ }, _callee, null, [[5, 15, 18, 21]]);
180
+ }));
181
+
182
+ return function (_x, _x2) {
183
+ return _ref3.apply(this, arguments);
184
+ };
185
+ }(), [document, getSharingById, resolveRecipients, share, updateSharingMemberType]);
186
+ return {
187
+ isInsideSharedParent: isInsideSharedParent,
188
+ sharedParentName: (_sharedParentPath$spl = sharedParentPath === null || sharedParentPath === void 0 ? void 0 : sharedParentPath.split('/').pop()) !== null && _sharedParentPath$spl !== void 0 ? _sharedParentPath$spl : null,
189
+ setMemberType: setMemberType
190
+ };
191
+ };
@@ -0,0 +1,53 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ import { useCallback } from 'react';
4
+ import { useClient } from 'cozy-client';
5
+ import { getOrCreateFromArray } from '../helpers/contacts';
6
+ import { DOCTYPE_CONTACTS } from '../models';
7
+ /**
8
+ * Turns the recipients picked in a sharing form into contacts, creating the
9
+ * missing ones, and splits them by the selected sharing right.
10
+ *
11
+ * @returns {Function} `resolveRecipients(pendingRecipients, selectedOption, createContact?)`
12
+ * resolving to `{ recipients, readOnlyRecipients }`, ready to be passed to `share`
13
+ */
14
+
15
+ export var useResolveRecipients = function useResolveRecipients() {
16
+ var client = useClient();
17
+ return useCallback( /*#__PURE__*/function () {
18
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(pendingRecipients) {
19
+ var selectedOption,
20
+ createContact,
21
+ contacts,
22
+ isReadOnly,
23
+ _args = arguments;
24
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
25
+ while (1) switch (_context.prev = _context.next) {
26
+ case 0:
27
+ selectedOption = _args.length > 1 && _args[1] !== undefined ? _args[1] : 'readWrite';
28
+ createContact = _args.length > 2 && _args[2] !== undefined ? _args[2] : function (contact) {
29
+ return client.create(DOCTYPE_CONTACTS, contact);
30
+ };
31
+ _context.next = 4;
32
+ return getOrCreateFromArray(client, pendingRecipients, createContact);
33
+
34
+ case 4:
35
+ contacts = _context.sent;
36
+ isReadOnly = selectedOption === 'readOnly';
37
+ return _context.abrupt("return", {
38
+ recipients: isReadOnly ? [] : contacts,
39
+ readOnlyRecipients: isReadOnly ? contacts : []
40
+ });
41
+
42
+ case 7:
43
+ case "end":
44
+ return _context.stop();
45
+ }
46
+ }, _callee);
47
+ }));
48
+
49
+ return function (_x) {
50
+ return _ref.apply(this, arguments);
51
+ };
52
+ }(), [client]);
53
+ };
@@ -0,0 +1,140 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ import { renderHook } from '@testing-library/react-hooks';
4
+ import { useResolveRecipients } from './useResolveRecipients';
5
+ import { getOrCreateFromArray } from '../helpers/contacts';
6
+ var mockClient = {
7
+ create: jest.fn()
8
+ };
9
+ jest.mock('cozy-client', function () {
10
+ return {
11
+ useClient: function useClient() {
12
+ return mockClient;
13
+ }
14
+ };
15
+ });
16
+ jest.mock('../helpers/contacts', function () {
17
+ return {
18
+ getOrCreateFromArray: jest.fn()
19
+ };
20
+ });
21
+ var contacts = [{
22
+ _id: 'alice'
23
+ }, {
24
+ _id: 'bob'
25
+ }];
26
+ describe('useResolveRecipients', function () {
27
+ beforeEach(function () {
28
+ jest.clearAllMocks();
29
+ getOrCreateFromArray.mockResolvedValue(contacts);
30
+ });
31
+ it('gives read-write rights by default', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
32
+ var _renderHook, result, resolved;
33
+
34
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
35
+ while (1) switch (_context.prev = _context.next) {
36
+ case 0:
37
+ _renderHook = renderHook(function () {
38
+ return useResolveRecipients();
39
+ }), result = _renderHook.result;
40
+ _context.next = 3;
41
+ return result.current([{
42
+ email: 'alice@cozy.cc'
43
+ }]);
44
+
45
+ case 3:
46
+ resolved = _context.sent;
47
+ expect(resolved).toEqual({
48
+ recipients: contacts,
49
+ readOnlyRecipients: []
50
+ });
51
+
52
+ case 5:
53
+ case "end":
54
+ return _context.stop();
55
+ }
56
+ }, _callee);
57
+ })));
58
+ it('gives read-only rights when the read-only option is selected', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
59
+ var _renderHook2, result, resolved;
60
+
61
+ return _regeneratorRuntime.wrap(function _callee2$(_context2) {
62
+ while (1) switch (_context2.prev = _context2.next) {
63
+ case 0:
64
+ _renderHook2 = renderHook(function () {
65
+ return useResolveRecipients();
66
+ }), result = _renderHook2.result;
67
+ _context2.next = 3;
68
+ return result.current([], 'readOnly');
69
+
70
+ case 3:
71
+ resolved = _context2.sent;
72
+ expect(resolved).toEqual({
73
+ recipients: [],
74
+ readOnlyRecipients: contacts
75
+ });
76
+
77
+ case 5:
78
+ case "end":
79
+ return _context2.stop();
80
+ }
81
+ }, _callee2);
82
+ })));
83
+ it('creates missing contacts with the client by default', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
84
+ var _renderHook3, result, pendingRecipients, createContact;
85
+
86
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
87
+ while (1) switch (_context3.prev = _context3.next) {
88
+ case 0:
89
+ _renderHook3 = renderHook(function () {
90
+ return useResolveRecipients();
91
+ }), result = _renderHook3.result;
92
+ pendingRecipients = [{
93
+ email: 'alice@cozy.cc'
94
+ }];
95
+ _context3.next = 4;
96
+ return result.current(pendingRecipients);
97
+
98
+ case 4:
99
+ createContact = getOrCreateFromArray.mock.calls[0][2];
100
+ createContact({
101
+ email: [{
102
+ address: 'alice@cozy.cc'
103
+ }]
104
+ });
105
+ expect(getOrCreateFromArray).toHaveBeenCalledWith(mockClient, pendingRecipients, expect.any(Function));
106
+ expect(mockClient.create).toHaveBeenCalledWith('io.cozy.contacts', {
107
+ email: [{
108
+ address: 'alice@cozy.cc'
109
+ }]
110
+ });
111
+
112
+ case 8:
113
+ case "end":
114
+ return _context3.stop();
115
+ }
116
+ }, _callee3);
117
+ })));
118
+ it('creates missing contacts with the given function', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
119
+ var _renderHook4, result, createContact;
120
+
121
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
122
+ while (1) switch (_context4.prev = _context4.next) {
123
+ case 0:
124
+ _renderHook4 = renderHook(function () {
125
+ return useResolveRecipients();
126
+ }), result = _renderHook4.result;
127
+ createContact = jest.fn();
128
+ _context4.next = 4;
129
+ return result.current([], 'readWrite', createContact);
130
+
131
+ case 4:
132
+ expect(getOrCreateFromArray).toHaveBeenCalledWith(mockClient, [], createContact);
133
+
134
+ case 5:
135
+ case "end":
136
+ return _context4.stop();
137
+ }
138
+ }, _callee4);
139
+ })));
140
+ });
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ export { ShareButtonWithRecipients } from './ShareButtonWithRecipients';
32
32
  export { DOCUMENT_TYPE } from './helpers/documentType';
33
33
  export { getRecipientsFromSharing } from './state';
34
34
  export { default as OpenSharingLinkButton } from './OpenSharingLinkButton';
35
- export { PermissionTypeMenu } from './components/Recipient/PermissionTypeMenu';
35
+ export { default as PermissionTypeMenu } from './components/Recipient/PermissionTypeMenuWrapper';
36
36
  export { default as OpenSharingLinkFabButton } from './OpenSharingLinkFabButton';
37
37
  export { NativeFileSharingProvider, useNativeFileSharing } from './providers/NativeFileSharingProvider';
38
38
  export { createCozySharingLink } from './actions/createCozySharingLink';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-sharing",
3
- "version": "40.1.6",
3
+ "version": "40.1.7",
4
4
  "description": "Provides sharing login for React applications.",
5
5
  "main": "dist/index.js",
6
6
  "author": "Cozy",
@@ -58,7 +58,7 @@
58
58
  "cozy-intent": "^2.31.1",
59
59
  "cozy-minilog": "^3.10.1",
60
60
  "cozy-ui": "^140.5.0",
61
- "cozy-ui-plus": "^14.1.1",
61
+ "cozy-ui-plus": "^14.1.2",
62
62
  "jest": "30.3.0",
63
63
  "jest-environment-jsdom": "30.3.0",
64
64
  "react": "16.12.0",
@@ -84,5 +84,5 @@
84
84
  "sideEffects": [
85
85
  "*.css"
86
86
  ],
87
- "gitHead": "d6b5c4b1938d425b6d1d6da2c479d2056db4b171"
87
+ "gitHead": "ff9d90f0000f5446b91840dbb4237b48336c3997"
88
88
  }
@@ -1,7 +1,6 @@
1
1
  import PropTypes from 'prop-types'
2
2
  import React, { useCallback, useEffect, useState } from 'react'
3
3
 
4
- import { useClient } from 'cozy-client'
5
4
  import minilog from 'cozy-minilog'
6
5
  import Button from 'cozy-ui/transpiled/react/Buttons'
7
6
  import { FixedDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
@@ -12,15 +11,15 @@ import ConfirmDialogProvider, {
12
11
  } from 'cozy-ui/transpiled/react/providers/ConfirmDialog'
13
12
  import { useI18n } from 'twake-i18n'
14
13
 
15
- import { getOrCreateFromArray } from '../../helpers/contacts'
16
14
  import withLocales from '../../hoc/withLocales'
17
15
  import { usePendingRecipients } from '../../hooks/usePendingRecipients'
16
+ import { useResolveRecipients } from '../../hooks/useResolveRecipients'
18
17
  import { useSharingContext } from '../../hooks/useSharingContext'
19
18
  import styles from '../../styles/share.styl'
20
19
  import AntivirusAlert from '../AntivirusAlert'
21
20
  import { default as DumbShareByEmail } from '../ShareByEmail'
22
21
  import ShareByLink from '../ShareByLink'
23
- import WhoHasAccess from '../WhoHasAccess'
22
+ import WhoHasAccessWrapper from '../WhoHasAccessWrapper'
24
23
 
25
24
  const log = minilog('FederatedFolderModal')
26
25
 
@@ -38,7 +37,7 @@ const FederatedFolderModalContent = ({
38
37
  // we close the popup and we do not want to see briefly the new contacts added
39
38
  // in members before the modal closes. That's why when clicking on "Share"
40
39
  // we do not use the reactive existingDocument and existingRecipients.
41
- const client = useClient()
40
+ const resolveRecipients = useResolveRecipients()
42
41
  const { t } = useI18n()
43
42
  const {
44
43
  canReshare,
@@ -162,13 +161,8 @@ const FederatedFolderModalContent = ({
162
161
  setFrozenRecipients(recipients)
163
162
 
164
163
  try {
165
- const contacts = await getOrCreateFromArray(
166
- client,
167
- pendingRecipients,
168
- contact => client.create('io.cozy.contacts', contact)
169
- )
170
- const readWriteRecipients = selectedOption === 'readOnly' ? [] : contacts
171
- const readOnlyRecipients = selectedOption === 'readOnly' ? contacts : []
164
+ const { recipients: readWriteRecipients, readOnlyRecipients } =
165
+ await resolveRecipients(pendingRecipients, selectedOption)
172
166
 
173
167
  await share({
174
168
  description: folderName,
@@ -275,7 +269,7 @@ const FederatedFolderModalContent = ({
275
269
  </>
276
270
  )}
277
271
  </div>
278
- <WhoHasAccess
272
+ <WhoHasAccessWrapper
279
273
  isOwner={isCurrentUserOwner}
280
274
  canManageSharing={canManageSharing}
281
275
  isSharedDrive
@@ -3,7 +3,6 @@ import React from 'react'
3
3
  import snarkdown from 'snarkdown'
4
4
 
5
5
  import { Icon, FolderOutlined, ArrowUp } from '@linagora/twake-icons'
6
- import { useClient } from 'cozy-client'
7
6
  import Button from 'cozy-ui/transpiled/react/Buttons'
8
7
  import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
9
8
  import Timeline from 'cozy-ui/transpiled/react/Timeline'
@@ -17,23 +16,16 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
17
16
  import { useI18n } from 'twake-i18n'
18
17
 
19
18
  import { DEFAULT_DISPLAY_NAME } from '../../helpers/recipients'
20
- import { useFetchDocumentPath } from '../../hooks/useFetchDocumentPath'
21
- import { useSharingContext } from '../../hooks/useSharingContext'
22
19
  import { getDisplayName } from '../../models'
23
20
 
24
21
  const DowngradePermissionConfirmDialog = ({
25
22
  document,
26
23
  recipient,
24
+ sharedParentName,
27
25
  onCancel,
28
26
  onConfirm
29
27
  }) => {
30
28
  const { t } = useI18n()
31
- const client = useClient()
32
- const { getSharedParentPath } = useSharingContext()
33
-
34
- const documentPath = useFetchDocumentPath(client, document)
35
- const sharedParentPath = documentPath && getSharedParentPath(documentPath)
36
- const parentFolderName = sharedParentPath?.split('/').pop()
37
29
  const contactName = getDisplayName(recipient, t(DEFAULT_DISPLAY_NAME))
38
30
  const [before, afterOpen] = snarkdown(
39
31
  t('DowngradePermissionConfirmDialog.content', { contactName })
@@ -68,7 +60,7 @@ const DowngradePermissionConfirmDialog = ({
68
60
  <TimelineConnector />
69
61
  </TimelineSeparator>
70
62
  <TimelineContent>
71
- <Typography variant="body2">{parentFolderName}</Typography>
63
+ <Typography variant="body2">{sharedParentName}</Typography>
72
64
  <div>
73
65
  <s>
74
66
  <Typography display="inline" variant="caption">
@@ -147,6 +139,7 @@ const DowngradePermissionConfirmDialog = ({
147
139
  DowngradePermissionConfirmDialog.propTypes = {
148
140
  document: PropTypes.object.isRequired,
149
141
  recipient: PropTypes.object.isRequired,
142
+ sharedParentName: PropTypes.string,
150
143
  onCancel: PropTypes.func.isRequired,
151
144
  onConfirm: PropTypes.func.isRequired
152
145
  }
@@ -1,6 +1,5 @@
1
1
  import React, { useState } from 'react'
2
2
 
3
- import { useClient } from 'cozy-client'
4
3
  import Fade from 'cozy-ui/transpiled/react/Fade'
5
4
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
6
5
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
@@ -21,7 +20,6 @@ import { GroupAvatar } from '../Avatar/GroupAvatar'
21
20
  const GroupRecipient = props => {
22
21
  const { name, color, members, fadeIn, isOwner } = props
23
22
  const { t } = useI18n()
24
- const client = useClient()
25
23
  const { isMobile } = useBreakpoints()
26
24
 
27
25
  const [isDetailOpened, setDetailOpened] = useState(false)
@@ -30,9 +28,7 @@ const GroupRecipient = props => {
30
28
  const nbMemberReady = members.filter(
31
29
  member => !['revoked', 'mail-not-sent'].includes(member.status)
32
30
  ).length
33
- const isUserInsideMembers = members.some(
34
- member => member.instance === client.options.uri
35
- )
31
+ const isUserInsideMembers = members.some(member => member.isCurrentUser)
36
32
 
37
33
  const toogleDetailOpened = () => {
38
34
  setDetailOpened(!isDetailOpened)
@@ -13,7 +13,9 @@ const meta = {
13
13
  { status: 'pending' },
14
14
  { status: 'revoked' }
15
15
  ],
16
- groupIndex: 0
16
+ groupIndex: 0,
17
+ onRevokeGroup: () => {},
18
+ onLeaveGroup: () => {}
17
19
  }
18
20
  }
19
21
 
@@ -1,6 +1,5 @@
1
1
  import React from 'react'
2
2
 
3
- import { useClient } from 'cozy-client'
4
3
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
5
4
  import List from 'cozy-ui/transpiled/react/List'
6
5
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
@@ -14,7 +13,6 @@ import { getInitials, getDisplayName } from '../../models'
14
13
 
15
14
  const GroupRecipientDetailWithAccess = ({ withAccess }) => {
16
15
  const { t } = useI18n()
17
- const client = useClient()
18
16
 
19
17
  return (
20
18
  <div>
@@ -24,7 +22,6 @@ const GroupRecipientDetailWithAccess = ({ withAccess }) => {
24
22
  <List>
25
23
  {withAccess.map(recipient => {
26
24
  const name = getDisplayName(recipient)
27
- const isMe = recipient.instance === client.options.uri
28
25
 
29
26
  return (
30
27
  <ListItem disableGutters key={recipient.index} size="small">
@@ -36,7 +33,7 @@ const GroupRecipientDetailWithAccess = ({ withAccess }) => {
36
33
  secondary={
37
34
  <MemberRecipientStatus
38
35
  status={recipient.status}
39
- isMe={isMe}
36
+ isMe={Boolean(recipient.isCurrentUser)}
40
37
  instance={recipient.instance}
41
38
  email={recipient.email}
42
39
  name={recipient.name || recipient.public_name}
@@ -13,7 +13,6 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
13
13
  import { useI18n } from 'twake-i18n'
14
14
 
15
15
  import { permission } from './actions/permission'
16
- import { useSharingContext } from '../../hooks/useSharingContext'
17
16
  import { GroupAvatar } from '../Avatar/GroupAvatar'
18
17
 
19
18
  const GroupRecipientPermissions = ({
@@ -26,11 +25,12 @@ const GroupRecipientPermissions = ({
26
25
  read_only = false,
27
26
  className,
28
27
  isUserInsideMembers,
29
- document
28
+ document,
29
+ onRevokeGroup,
30
+ onLeaveGroup
30
31
  }) => {
31
32
  const { t } = useI18n()
32
33
  const buttonRef = useRef()
33
- const { revokeGroup, revokeSelf } = useSharingContext()
34
34
 
35
35
  const [isMenuDisplayed, setMenuDisplayed] = useState(false)
36
36
  const [revoking, setRevoking] = useState(false)
@@ -44,9 +44,9 @@ const GroupRecipientPermissions = ({
44
44
  const handleRevocation = async () => {
45
45
  setRevoking(true)
46
46
  if (isOwner) {
47
- await revokeGroup(document, sharingId, groupIndex)
47
+ await onRevokeGroup(document, sharingId, groupIndex)
48
48
  } else {
49
- await revokeSelf(document)
49
+ await onLeaveGroup(document)
50
50
  }
51
51
  setRevoking(false)
52
52
  }
@@ -5,6 +5,8 @@ const meta = {
5
5
  args: {
6
6
  onRevoke: () => {},
7
7
  onRevokeSelf: () => {},
8
+ onRevokeGroup: () => {},
9
+ onLeaveGroup: () => {},
8
10
  type: 'two-way',
9
11
  status: 'ready',
10
12
  groupIndex: 0
@@ -19,7 +19,6 @@ import {
19
19
  getPermissionExpiresDate
20
20
  } from '../../helpers/permissions'
21
21
  import { FADE_IN_DURATION } from '../../helpers/recipients'
22
- import { useSharingContext } from '../../hooks/useSharingContext'
23
22
  import { ShareRestrictionModal } from '../ShareRestrictionModal/ShareRestrictionModal'
24
23
 
25
24
  const LinkRecipientTextReadOnly = ({ textPrimary, textSecondary }) => {
@@ -55,19 +54,18 @@ const LinkRecipientText = ({ onClick, textPrimary, textSecondary }) => {
55
54
  const LinkRecipient = props => {
56
55
  const { t, f, lang } = useI18n()
57
56
  const { isMobile } = useBreakpoints()
58
- const { getDocumentPermissions } = useSharingContext()
59
57
 
60
58
  const {
61
59
  recipientConfirmationData,
62
60
  verifyRecipient,
63
61
  fadeIn,
64
62
  document,
65
- isReadOnly
63
+ isReadOnly,
64
+ permissions
66
65
  } = props
67
66
 
68
67
  const [openShareRestrictionModal, setOpenShareRestrictionModal] =
69
68
  useState(false)
70
- const permissions = getDocumentPermissions(document?._id)
71
69
  const hasPassword = checkIsPermissionHasPassword(permissions)
72
70
  const expiresDate = getPermissionExpiresDate(permissions)
73
71
  const dateFormatted = expiresDate