cozy-sharing 32.1.2 → 32.3.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/.claude/settings.local.json +27 -0
- package/AGENTS.md +7 -0
- package/CHANGELOG.md +18 -0
- package/dist/RefreshableSharings.spec.js +40 -0
- package/dist/assets/illustrations/illustration-shared-drives.svg +1 -0
- package/dist/components/EditLinkPermissionDialog.js +72 -0
- package/dist/components/EditLinkPermissionDialog.spec.js +48 -0
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.js +65 -0
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.spec.js +107 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +41 -4
- package/dist/components/FederatedFolder/FederatedFolderModal.jsx.tmp.179197.1773939270471 +172 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +79 -8
- package/dist/components/Recipient/actions/revokeGroup.js +42 -0
- package/dist/components/Recipient/actions/revokeMember.js +42 -0
- package/dist/components/Recipient/actions/revokeSharedDriveMember.js +41 -0
- package/dist/components/ShareAutosuggest.js +1 -0
- package/dist/components/ShareAutosuggest.spec.js +12 -4
- package/dist/components/ShareDialogCozyToCozy.spec.js +55 -8
- package/dist/components/ShareDiscardChangesModal.js +35 -0
- package/dist/components/ShareModal/ShareModal copy.js +43 -0
- package/dist/components/ShareModal/ShareModal.spec.js +197 -0
- package/dist/components/ShareModal/ShareModalBatchContainer.js +276 -0
- package/dist/components/ShareModal/ShareModalBatchContainer.spec.js +131 -0
- package/dist/components/ShareModal/SharedDriveEditModal.js +59 -0
- package/dist/components/ShareRecipientsInput.js +13 -3
- package/dist/components/ShareRecipientsInput.spec.js +63 -4
- package/dist/components/SharedDrive/DumbSharedDriveModal.js +78 -0
- package/dist/components/SharedDrive/DumbSharedDriveModal.spec.js +126 -0
- package/dist/components/SharedDrive/SharedDriveEditModal.js +110 -0
- package/dist/components/SharedDrive/SharedDriveModal copy.js +356 -0
- package/dist/components/SharedDrive/helpers.js +102 -0
- package/dist/components/SharedDrive/helpers.spec.js +208 -0
- package/dist/components/SharedDriveEditModal.js +43 -0
- package/dist/components/SharedFolder/DumbBatchSharedFolderModal.spec.js +321 -0
- package/dist/components/SharedStatus.js +61 -0
- package/dist/components/SharedStatus.spec.js +44 -0
- package/dist/components/Sharesubmit.js +28 -0
- package/dist/components/__snapshots__/SharedStatus.spec.js.snap +94 -0
- package/dist/helpers/owner.js +14 -0
- package/dist/helpers/owner.spec.js +34 -0
- package/dist/hooks/useConfirmDiscardChanges.js +33 -0
- package/dist/hooks/useContactsAndGroups.js +65 -0
- package/dist/hooks/useSharedDrive.js +130 -0
- package/dist/hooks/useSharedDriveContactsAndGroups.js +65 -0
- package/dist/propTypes.js +26 -0
- package/dist/styles/shareddrive.styl +8 -0
- package/locales/en.json +10 -5
- package/locales/fr.json +10 -5
- package/locales/ru.json +10 -5
- package/locales/vi.json +10 -5
- package/package.json +2 -2
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +184 -138
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +47 -0
- package/src/components/ShareAutosuggest.jsx +1 -0
- package/src/components/ShareAutosuggest.spec.jsx +10 -5
- package/src/components/ShareDialogCozyToCozy.spec.jsx +50 -4
- package/src/components/ShareDiscardChangesModal.jsx +40 -0
- package/src/components/ShareRecipientsInput.jsx +11 -6
- package/src/components/ShareRecipientsInput.spec.jsx +59 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
4
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
5
|
+
|
|
6
|
+
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; }
|
|
7
|
+
|
|
8
|
+
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; }
|
|
9
|
+
|
|
10
|
+
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; } } }; }
|
|
11
|
+
|
|
12
|
+
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); }
|
|
13
|
+
|
|
14
|
+
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; }
|
|
15
|
+
|
|
16
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
17
|
+
import PropTypes from 'prop-types';
|
|
18
|
+
import React, { useState, useEffect } from 'react';
|
|
19
|
+
import { useClient } from 'cozy-client';
|
|
20
|
+
import Button from 'cozy-ui/transpiled/react/Buttons';
|
|
21
|
+
import { FixedDialog } from 'cozy-ui/transpiled/react/CozyDialogs';
|
|
22
|
+
import TextField from 'cozy-ui/transpiled/react/TextField';
|
|
23
|
+
import Typography from 'cozy-ui/transpiled/react/Typography';
|
|
24
|
+
import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert';
|
|
25
|
+
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
|
|
26
|
+
import { mergeAndDeduplicateRecipients, formatRecipients } from './helpers';
|
|
27
|
+
import withLocales from '../../hoc/withLocales';
|
|
28
|
+
import useContactsAndGroups from '../../hooks/useSharedDriveContactsAndGroups';
|
|
29
|
+
import { useSharingContext } from '../../hooks/useSharingContext';
|
|
30
|
+
import { Contact } from '../../models';
|
|
31
|
+
import { buildSharingsByIdQuery } from '../../queries/queries';
|
|
32
|
+
import { default as DumbShareByEmail } from '../ShareByEmail';
|
|
33
|
+
import WhoHasAccess from '../WhoHasAccess';
|
|
34
|
+
export var SharedDriveModal = withLocales( // ({ onClose, sharedDriveId = '59ee1637e38f3dbab1cbb7eb5f0a922a' }) => {
|
|
35
|
+
function (_ref) {
|
|
36
|
+
var onClose = _ref.onClose,
|
|
37
|
+
sharedDrive = _ref.sharedDrive;
|
|
38
|
+
// ({ onClose, sharedDrive
|
|
39
|
+
var client = useClient();
|
|
40
|
+
|
|
41
|
+
var _useI18n = useI18n(),
|
|
42
|
+
t = _useI18n.t;
|
|
43
|
+
|
|
44
|
+
var _useSharingContext = useSharingContext(),
|
|
45
|
+
share = _useSharingContext.share,
|
|
46
|
+
revoke = _useSharingContext.revoke;
|
|
47
|
+
|
|
48
|
+
var _useAlert = useAlert(),
|
|
49
|
+
showAlert = _useAlert.showAlert;
|
|
50
|
+
|
|
51
|
+
var isUpdate = Boolean(sharedDrive);
|
|
52
|
+
|
|
53
|
+
var _useContactsAndGroups = useContactsAndGroups([]),
|
|
54
|
+
contactsAndGroups = _useContactsAndGroups.contactsAndGroups,
|
|
55
|
+
isLoadingContactsAndGroups = _useContactsAndGroups.isLoading;
|
|
56
|
+
|
|
57
|
+
var _useState = useState({
|
|
58
|
+
recipients: [],
|
|
59
|
+
readOnlyRecipients: []
|
|
60
|
+
}),
|
|
61
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
62
|
+
sharedDriveRecipients = _useState2[0],
|
|
63
|
+
setSharedDriveRecipients = _useState2[1];
|
|
64
|
+
|
|
65
|
+
var _useState3 = useState((sharedDrive === null || sharedDrive === void 0 ? void 0 : sharedDrive.name) || ''),
|
|
66
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
67
|
+
sharedDriveName = _useState4[0],
|
|
68
|
+
setSharedDriveName = _useState4[1];
|
|
69
|
+
|
|
70
|
+
useEffect(function () {
|
|
71
|
+
if (sharedDrive && !isLoadingContactsAndGroups) {
|
|
72
|
+
setSharedDriveName(sharedDrive.rules[0].title);
|
|
73
|
+
setSharedDriveRecipients(separateMembersByPermission(associateToContacts(sharedDrive.members, contactsAndGroups)));
|
|
74
|
+
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
75
|
+
|
|
76
|
+
}, [sharedDrive === null || sharedDrive === void 0 ? void 0 : sharedDrive._id, isLoadingContactsAndGroups]);
|
|
77
|
+
|
|
78
|
+
var onShare = function onShare(params) {
|
|
79
|
+
setSharedDriveRecipients({
|
|
80
|
+
recipients: mergeAndDeduplicateRecipients([sharedDriveRecipients.recipients, params.recipients]),
|
|
81
|
+
readOnlyRecipients: mergeAndDeduplicateRecipients([sharedDriveRecipients.readOnlyRecipients, params.readOnlyRecipients])
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
var handleSharedDriveNameChange = function handleSharedDriveNameChange(event) {
|
|
86
|
+
setSharedDriveName(event.target.value);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
var onUpdate = /*#__PURE__*/function () {
|
|
90
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
91
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
92
|
+
while (1) switch (_context.prev = _context.next) {
|
|
93
|
+
case 0:
|
|
94
|
+
// TODO rename the shared drive
|
|
95
|
+
onClose();
|
|
96
|
+
|
|
97
|
+
case 1:
|
|
98
|
+
case "end":
|
|
99
|
+
return _context.stop();
|
|
100
|
+
}
|
|
101
|
+
}, _callee);
|
|
102
|
+
}));
|
|
103
|
+
|
|
104
|
+
return function onUpdate() {
|
|
105
|
+
return _ref2.apply(this, arguments);
|
|
106
|
+
};
|
|
107
|
+
}();
|
|
108
|
+
|
|
109
|
+
var onCreate = /*#__PURE__*/function () {
|
|
110
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
111
|
+
var _yield$client$create2, sharedDriveFolder;
|
|
112
|
+
|
|
113
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
114
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
115
|
+
case 0:
|
|
116
|
+
_context2.prev = 0;
|
|
117
|
+
_context2.next = 3;
|
|
118
|
+
return client.collection('io.cozy.files').getOrCreateSharedDrivesDirectory();
|
|
119
|
+
|
|
120
|
+
case 3:
|
|
121
|
+
_context2.next = 5;
|
|
122
|
+
return client.create('io.cozy.files', {
|
|
123
|
+
name: sharedDriveName,
|
|
124
|
+
dirId: 'io.cozy.files.shared-drives-dir',
|
|
125
|
+
type: 'directory'
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
case 5:
|
|
129
|
+
_yield$client$create2 = _context2.sent;
|
|
130
|
+
sharedDriveFolder = _yield$client$create2.data;
|
|
131
|
+
_context2.next = 9;
|
|
132
|
+
return share({
|
|
133
|
+
document: sharedDriveFolder,
|
|
134
|
+
recipients: sharedDriveRecipients.recipients,
|
|
135
|
+
readOnlyRecipients: sharedDriveRecipients.readOnlyRecipients,
|
|
136
|
+
sharedDrive: true
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
case 9:
|
|
140
|
+
showAlert({
|
|
141
|
+
message: t('SharedDrive.sharedDriveModal.successNotification'),
|
|
142
|
+
severity: 'success',
|
|
143
|
+
variant: 'filled'
|
|
144
|
+
});
|
|
145
|
+
onClose();
|
|
146
|
+
_context2.next = 16;
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case 13:
|
|
150
|
+
_context2.prev = 13;
|
|
151
|
+
_context2.t0 = _context2["catch"](0);
|
|
152
|
+
showAlert({
|
|
153
|
+
message: t('SharedDrive.sharedDriveModal.errorNotification'),
|
|
154
|
+
severity: 'error',
|
|
155
|
+
variant: 'filled'
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
case 16:
|
|
159
|
+
case "end":
|
|
160
|
+
return _context2.stop();
|
|
161
|
+
}
|
|
162
|
+
}, _callee2, null, [[0, 13]]);
|
|
163
|
+
}));
|
|
164
|
+
|
|
165
|
+
return function onCreate() {
|
|
166
|
+
return _ref3.apply(this, arguments);
|
|
167
|
+
};
|
|
168
|
+
}();
|
|
169
|
+
|
|
170
|
+
var onSetType = function onSetType(index, newType) {
|
|
171
|
+
var _id = index.split('virtual-shared-drive-sharing-')[1];
|
|
172
|
+
|
|
173
|
+
if (newType === 'two-way') {
|
|
174
|
+
setSharedDriveRecipients(function (prev) {
|
|
175
|
+
var recipientToMove = prev.readOnlyRecipients.find(function (r) {
|
|
176
|
+
return r._id === _id;
|
|
177
|
+
});
|
|
178
|
+
return {
|
|
179
|
+
recipients: [].concat(_toConsumableArray(prev.recipients), [recipientToMove]),
|
|
180
|
+
readOnlyRecipients: prev.readOnlyRecipients.filter(function (r) {
|
|
181
|
+
return r._id !== _id;
|
|
182
|
+
})
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
} else {
|
|
186
|
+
setSharedDriveRecipients(function (prev) {
|
|
187
|
+
var recipientToMove = prev.recipients.find(function (r) {
|
|
188
|
+
return r._id === _id;
|
|
189
|
+
});
|
|
190
|
+
return {
|
|
191
|
+
recipients: prev.recipients.filter(function (r) {
|
|
192
|
+
return r._id !== _id;
|
|
193
|
+
}),
|
|
194
|
+
readOnlyRecipients: [].concat(_toConsumableArray(prev.readOnlyRecipients), [recipientToMove])
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
var onRevoke = /*#__PURE__*/function () {
|
|
201
|
+
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(index) {
|
|
202
|
+
var _id;
|
|
203
|
+
|
|
204
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
205
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
206
|
+
case 0:
|
|
207
|
+
_id = index.split('virtual-shared-drive-sharing-')[1];
|
|
208
|
+
console.log('onRevoke', _id);
|
|
209
|
+
_context3.next = 4;
|
|
210
|
+
return revoke({
|
|
211
|
+
_id: _id
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
case 4:
|
|
215
|
+
console.log('onRevoke after revoke', _id);
|
|
216
|
+
setSharedDriveRecipients(function (prev) {
|
|
217
|
+
return {
|
|
218
|
+
recipients: prev.recipients.filter(function (r) {
|
|
219
|
+
return r._id !== _id;
|
|
220
|
+
}),
|
|
221
|
+
readOnlyRecipients: prev.readOnlyRecipients.filter(function (r) {
|
|
222
|
+
return r._id !== _id;
|
|
223
|
+
})
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
case 6:
|
|
228
|
+
case "end":
|
|
229
|
+
return _context3.stop();
|
|
230
|
+
}
|
|
231
|
+
}, _callee3);
|
|
232
|
+
}));
|
|
233
|
+
|
|
234
|
+
return function onRevoke(_x) {
|
|
235
|
+
return _ref4.apply(this, arguments);
|
|
236
|
+
};
|
|
237
|
+
}();
|
|
238
|
+
|
|
239
|
+
var recipients = formatRecipients(sharedDriveRecipients);
|
|
240
|
+
return /*#__PURE__*/React.createElement(FixedDialog, {
|
|
241
|
+
open: true,
|
|
242
|
+
disableGutters: true,
|
|
243
|
+
onClose: onClose,
|
|
244
|
+
title: t("SharedDrive.sharedDriveModal.".concat(isUpdate ? 'updateTitle' : 'title')),
|
|
245
|
+
content: /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
|
246
|
+
className: "u-ph-2"
|
|
247
|
+
}, /*#__PURE__*/React.createElement(TextField, {
|
|
248
|
+
required: true,
|
|
249
|
+
label: t('SharedDrive.sharedDriveModal.nameLabel'),
|
|
250
|
+
variant: "outlined",
|
|
251
|
+
size: "small",
|
|
252
|
+
className: "u-w-100 u-mt-1-half",
|
|
253
|
+
value: sharedDriveName,
|
|
254
|
+
onChange: handleSharedDriveNameChange
|
|
255
|
+
}), /*#__PURE__*/React.createElement(Typography, {
|
|
256
|
+
variant: "h6",
|
|
257
|
+
className: "u-mt-1-half u-mb-half"
|
|
258
|
+
}, t('SharedDrive.sharedDriveModal.addPeople')), /*#__PURE__*/React.createElement(DumbShareByEmail, {
|
|
259
|
+
createContact: function createContact(contact) {
|
|
260
|
+
return client.create(Contact.doctype, contact);
|
|
261
|
+
},
|
|
262
|
+
currentRecipients: [],
|
|
263
|
+
document: document,
|
|
264
|
+
documentType: "Files",
|
|
265
|
+
onShare: onShare,
|
|
266
|
+
submitLabel: t('SharedDrive.sharedDriveModal.add'),
|
|
267
|
+
showNotifications: false
|
|
268
|
+
})), /*#__PURE__*/React.createElement(WhoHasAccess, {
|
|
269
|
+
isOwner: true,
|
|
270
|
+
recipients: recipients,
|
|
271
|
+
document: document,
|
|
272
|
+
documentType: "Files",
|
|
273
|
+
className: "u-w-100",
|
|
274
|
+
onRevoke: onRevoke,
|
|
275
|
+
onSetType: onSetType
|
|
276
|
+
})),
|
|
277
|
+
actions: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
278
|
+
variant: "secondary",
|
|
279
|
+
label: t('SharedDrive.sharedDriveModal.cancel'),
|
|
280
|
+
onClick: onClose
|
|
281
|
+
}), /*#__PURE__*/React.createElement(Button, {
|
|
282
|
+
variant: "primary",
|
|
283
|
+
label: t('SharedDrive.sharedDriveModal.update'),
|
|
284
|
+
onClick: onUpdate
|
|
285
|
+
}), /*#__PURE__*/React.createElement(Button, {
|
|
286
|
+
variant: "primary",
|
|
287
|
+
label: t('SharedDrive.sharedDriveModal.create'),
|
|
288
|
+
onClick: onCreate
|
|
289
|
+
}))
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
SharedDriveModal.propTypes = {
|
|
293
|
+
onClose: PropTypes.func.isRequired
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* Separates sharing members into recipients and read-only recipients
|
|
297
|
+
* @param {Array} members - Array of sharing members
|
|
298
|
+
* @returns {Object} Object containing recipients and readOnlyRecipients arrays
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
|
+
var separateMembersByPermission = function separateMembersByPermission(members) {
|
|
302
|
+
return members.reduce(function (acc, member) {
|
|
303
|
+
if (member.status !== 'owner') {
|
|
304
|
+
if (member.read_only === true) {
|
|
305
|
+
acc.readOnlyRecipients.push(member);
|
|
306
|
+
} else {
|
|
307
|
+
acc.recipients.push(member);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return acc;
|
|
312
|
+
}, {
|
|
313
|
+
recipients: [],
|
|
314
|
+
readOnlyRecipients: []
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
var associateToContacts = function associateToContacts(members, contacts) {
|
|
319
|
+
console.log('members', members);
|
|
320
|
+
console.log('contacts', contacts);
|
|
321
|
+
var result = [];
|
|
322
|
+
|
|
323
|
+
var _iterator = _createForOfIteratorHelper(members),
|
|
324
|
+
_step;
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
var _loop = function _loop() {
|
|
328
|
+
var member = _step.value;
|
|
329
|
+
|
|
330
|
+
if (member.status !== 'owner' && member.email && member.instance) {
|
|
331
|
+
console.log('member', member);
|
|
332
|
+
var contact = contacts.find(function (c) {
|
|
333
|
+
var _c$email, _c$cozy;
|
|
334
|
+
|
|
335
|
+
return ((_c$email = c.email) === null || _c$email === void 0 ? void 0 : _c$email[0].address) === member.email && ((_c$cozy = c.cozy) === null || _c$cozy === void 0 || (_c$cozy = _c$cozy[0]) === null || _c$cozy === void 0 ? void 0 : _c$cozy.url) === member.instance;
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (contact) {
|
|
339
|
+
result.push(_objectSpread(_objectSpread({}, member), {}, {
|
|
340
|
+
_id: contact._id
|
|
341
|
+
}));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
347
|
+
_loop();
|
|
348
|
+
}
|
|
349
|
+
} catch (err) {
|
|
350
|
+
_iterator.e(err);
|
|
351
|
+
} finally {
|
|
352
|
+
_iterator.f();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return result;
|
|
356
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
|
|
4
|
+
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; }
|
|
5
|
+
|
|
6
|
+
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; }
|
|
7
|
+
|
|
8
|
+
import { models } from 'cozy-client';
|
|
9
|
+
var ContactModel = models.contact;
|
|
10
|
+
export var RECIPIENT_INDEX_PREFIX = 'virtual-shared-drive-sharing-';
|
|
11
|
+
export var mergeAndDeduplicateRecipients = function mergeAndDeduplicateRecipients(arrays) {
|
|
12
|
+
var combinedArray = arrays.flat().map(function (item) {
|
|
13
|
+
return _objectSpread(_objectSpread({}, item), {}, {
|
|
14
|
+
id: item.id || item._id
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
var seenIds = new Set();
|
|
18
|
+
var uniqueArray = combinedArray.reduce(function (acc, item) {
|
|
19
|
+
var id = item.id || item._id;
|
|
20
|
+
|
|
21
|
+
if (id == null) {
|
|
22
|
+
// Recipients without any identifier are kept as-is to avoid silent data loss
|
|
23
|
+
acc.push(item);
|
|
24
|
+
return acc;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!seenIds.has(id)) {
|
|
28
|
+
seenIds.add(id); // Ensure both id and _id exist for downstream compatibility
|
|
29
|
+
|
|
30
|
+
var normalizedItem = !item.id || !item._id ? _objectSpread(_objectSpread({}, item), {}, {
|
|
31
|
+
id: item.id || item._id,
|
|
32
|
+
_id: item._id || item.id
|
|
33
|
+
}) : item;
|
|
34
|
+
acc.push(normalizedItem);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return acc;
|
|
38
|
+
}, []);
|
|
39
|
+
return uniqueArray;
|
|
40
|
+
};
|
|
41
|
+
export var moveRecipientToReadWrite = function moveRecipientToReadWrite(federatedRecipients, _id) {
|
|
42
|
+
var recipientToMove = federatedRecipients.readOnlyRecipients.find(function (r) {
|
|
43
|
+
return r._id === _id;
|
|
44
|
+
});
|
|
45
|
+
if (!recipientToMove) return federatedRecipients;
|
|
46
|
+
return {
|
|
47
|
+
recipients: [].concat(_toConsumableArray(federatedRecipients.recipients), [recipientToMove]),
|
|
48
|
+
readOnlyRecipients: federatedRecipients.readOnlyRecipients.filter(function (r) {
|
|
49
|
+
return r._id !== _id;
|
|
50
|
+
})
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
export var moveRecipientToReadOnly = function moveRecipientToReadOnly(federatedRecipients, _id) {
|
|
54
|
+
var recipientToMove = federatedRecipients.recipients.find(function (r) {
|
|
55
|
+
return r._id === _id;
|
|
56
|
+
});
|
|
57
|
+
if (!recipientToMove) return federatedRecipients;
|
|
58
|
+
return {
|
|
59
|
+
recipients: federatedRecipients.recipients.filter(function (r) {
|
|
60
|
+
return r._id !== _id;
|
|
61
|
+
}),
|
|
62
|
+
readOnlyRecipients: [].concat(_toConsumableArray(federatedRecipients.readOnlyRecipients), [recipientToMove])
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export var formatRecipients = function formatRecipients(sharedDriveRecipients) {
|
|
66
|
+
var recipients = [];
|
|
67
|
+
sharedDriveRecipients.recipients.forEach(function (r) {
|
|
68
|
+
recipients.push({
|
|
69
|
+
index: "".concat(RECIPIENT_INDEX_PREFIX).concat(r._id),
|
|
70
|
+
email: ContactModel.getPrimaryEmail(r),
|
|
71
|
+
public_name: r.displayName || r.name,
|
|
72
|
+
memberIndex: r._id,
|
|
73
|
+
type: 'two-way',
|
|
74
|
+
members: r.members
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
sharedDriveRecipients.readOnlyRecipients.forEach(function (r) {
|
|
78
|
+
recipients.push({
|
|
79
|
+
index: "".concat(RECIPIENT_INDEX_PREFIX).concat(r._id),
|
|
80
|
+
email: ContactModel.getPrimaryEmail(r),
|
|
81
|
+
public_name: r.displayName || r.name,
|
|
82
|
+
memberIndex: r._id,
|
|
83
|
+
type: 'one-way',
|
|
84
|
+
members: r.members
|
|
85
|
+
});
|
|
86
|
+
}); // We need to sort recipients by public_name
|
|
87
|
+
// to avoid reording them every time we change
|
|
88
|
+
// them from read only to read write.
|
|
89
|
+
|
|
90
|
+
recipients.sort(function (a, b) {
|
|
91
|
+
if (a.public_name < b.public_name) {
|
|
92
|
+
return -1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (a.public_name > b.public_name) {
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return 0;
|
|
100
|
+
});
|
|
101
|
+
return recipients;
|
|
102
|
+
};
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { mergeAndDeduplicateRecipients, moveRecipientToReadWrite, moveRecipientToReadOnly, formatRecipients, RECIPIENT_INDEX_PREFIX } from './helpers';
|
|
2
|
+
describe('mergeAndDeduplicateRecipients', function () {
|
|
3
|
+
it('should merge multiple arrays into one', function () {
|
|
4
|
+
var result = mergeAndDeduplicateRecipients([[{
|
|
5
|
+
id: '1',
|
|
6
|
+
name: 'Alice'
|
|
7
|
+
}], [{
|
|
8
|
+
id: '2',
|
|
9
|
+
name: 'Bob'
|
|
10
|
+
}]]);
|
|
11
|
+
expect(result).toEqual([{
|
|
12
|
+
id: '1',
|
|
13
|
+
_id: '1',
|
|
14
|
+
name: 'Alice'
|
|
15
|
+
}, {
|
|
16
|
+
id: '2',
|
|
17
|
+
_id: '2',
|
|
18
|
+
name: 'Bob'
|
|
19
|
+
}]);
|
|
20
|
+
});
|
|
21
|
+
it('should deduplicate recipients with the same id', function () {
|
|
22
|
+
var result = mergeAndDeduplicateRecipients([[{
|
|
23
|
+
id: '1',
|
|
24
|
+
name: 'Alice'
|
|
25
|
+
}], [{
|
|
26
|
+
id: '1',
|
|
27
|
+
name: 'Alice'
|
|
28
|
+
}]]);
|
|
29
|
+
expect(result).toEqual([{
|
|
30
|
+
id: '1',
|
|
31
|
+
_id: '1',
|
|
32
|
+
name: 'Alice'
|
|
33
|
+
}]);
|
|
34
|
+
});
|
|
35
|
+
it('should normalize _id to id for deduplication', function () {
|
|
36
|
+
var result = mergeAndDeduplicateRecipients([[{
|
|
37
|
+
_id: '1',
|
|
38
|
+
name: 'Alice'
|
|
39
|
+
}], [{
|
|
40
|
+
_id: '2',
|
|
41
|
+
name: 'Bob'
|
|
42
|
+
}]]);
|
|
43
|
+
expect(result).toEqual([{
|
|
44
|
+
_id: '1',
|
|
45
|
+
id: '1',
|
|
46
|
+
name: 'Alice'
|
|
47
|
+
}, {
|
|
48
|
+
_id: '2',
|
|
49
|
+
id: '2',
|
|
50
|
+
name: 'Bob'
|
|
51
|
+
}]);
|
|
52
|
+
});
|
|
53
|
+
it('should deduplicate recipients when one has id and the other has _id', function () {
|
|
54
|
+
var result = mergeAndDeduplicateRecipients([[{
|
|
55
|
+
id: '1',
|
|
56
|
+
name: 'Alice'
|
|
57
|
+
}], [{
|
|
58
|
+
_id: '1',
|
|
59
|
+
name: 'Alice'
|
|
60
|
+
}]]);
|
|
61
|
+
expect(result).toEqual([{
|
|
62
|
+
id: '1',
|
|
63
|
+
_id: '1',
|
|
64
|
+
name: 'Alice'
|
|
65
|
+
}]);
|
|
66
|
+
});
|
|
67
|
+
it('should prefer existing id over _id when both are present', function () {
|
|
68
|
+
var result = mergeAndDeduplicateRecipients([[{
|
|
69
|
+
id: 'real-id',
|
|
70
|
+
_id: 'other-id',
|
|
71
|
+
name: 'Alice'
|
|
72
|
+
}]]);
|
|
73
|
+
expect(result).toEqual([{
|
|
74
|
+
id: 'real-id',
|
|
75
|
+
_id: 'other-id',
|
|
76
|
+
name: 'Alice'
|
|
77
|
+
}]);
|
|
78
|
+
});
|
|
79
|
+
it('should handle empty arrays', function () {
|
|
80
|
+
var result = mergeAndDeduplicateRecipients([[], []]);
|
|
81
|
+
expect(result).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('moveRecipientToReadWrite', function () {
|
|
85
|
+
it('should move a recipient from readOnly to readWrite', function () {
|
|
86
|
+
var state = {
|
|
87
|
+
recipients: [{
|
|
88
|
+
_id: '1',
|
|
89
|
+
name: 'Alice'
|
|
90
|
+
}],
|
|
91
|
+
readOnlyRecipients: [{
|
|
92
|
+
_id: '2',
|
|
93
|
+
name: 'Bob'
|
|
94
|
+
}]
|
|
95
|
+
};
|
|
96
|
+
var result = moveRecipientToReadWrite(state, '2');
|
|
97
|
+
expect(result.recipients).toEqual([{
|
|
98
|
+
_id: '1',
|
|
99
|
+
name: 'Alice'
|
|
100
|
+
}, {
|
|
101
|
+
_id: '2',
|
|
102
|
+
name: 'Bob'
|
|
103
|
+
}]);
|
|
104
|
+
expect(result.readOnlyRecipients).toEqual([]);
|
|
105
|
+
});
|
|
106
|
+
it('should return unchanged state if recipient not found', function () {
|
|
107
|
+
var state = {
|
|
108
|
+
recipients: [{
|
|
109
|
+
_id: '1',
|
|
110
|
+
name: 'Alice'
|
|
111
|
+
}],
|
|
112
|
+
readOnlyRecipients: []
|
|
113
|
+
};
|
|
114
|
+
var result = moveRecipientToReadWrite(state, '999');
|
|
115
|
+
expect(result).toBe(state);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('moveRecipientToReadOnly', function () {
|
|
119
|
+
it('should move a recipient from readWrite to readOnly', function () {
|
|
120
|
+
var state = {
|
|
121
|
+
recipients: [{
|
|
122
|
+
_id: '1',
|
|
123
|
+
name: 'Alice'
|
|
124
|
+
}],
|
|
125
|
+
readOnlyRecipients: [{
|
|
126
|
+
_id: '2',
|
|
127
|
+
name: 'Bob'
|
|
128
|
+
}]
|
|
129
|
+
};
|
|
130
|
+
var result = moveRecipientToReadOnly(state, '1');
|
|
131
|
+
expect(result.recipients).toEqual([]);
|
|
132
|
+
expect(result.readOnlyRecipients).toEqual([{
|
|
133
|
+
_id: '2',
|
|
134
|
+
name: 'Bob'
|
|
135
|
+
}, {
|
|
136
|
+
_id: '1',
|
|
137
|
+
name: 'Alice'
|
|
138
|
+
}]);
|
|
139
|
+
});
|
|
140
|
+
it('should return unchanged state if recipient not found', function () {
|
|
141
|
+
var state = {
|
|
142
|
+
recipients: [],
|
|
143
|
+
readOnlyRecipients: [{
|
|
144
|
+
_id: '1',
|
|
145
|
+
name: 'Alice'
|
|
146
|
+
}]
|
|
147
|
+
};
|
|
148
|
+
var result = moveRecipientToReadOnly(state, '999');
|
|
149
|
+
expect(result).toBe(state);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
describe('formatRecipients', function () {
|
|
153
|
+
it('should format readWrite and readOnly recipients with correct types', function () {
|
|
154
|
+
var input = {
|
|
155
|
+
recipients: [{
|
|
156
|
+
_id: '1',
|
|
157
|
+
displayName: 'Alice',
|
|
158
|
+
email: [{
|
|
159
|
+
address: 'alice@example.com',
|
|
160
|
+
primary: true
|
|
161
|
+
}]
|
|
162
|
+
}],
|
|
163
|
+
readOnlyRecipients: [{
|
|
164
|
+
_id: '2',
|
|
165
|
+
displayName: 'Bob',
|
|
166
|
+
email: [{
|
|
167
|
+
address: 'bob@example.com',
|
|
168
|
+
primary: true
|
|
169
|
+
}]
|
|
170
|
+
}]
|
|
171
|
+
};
|
|
172
|
+
var result = formatRecipients(input);
|
|
173
|
+
expect(result).toHaveLength(2);
|
|
174
|
+
expect(result[0]).toMatchObject({
|
|
175
|
+
index: "".concat(RECIPIENT_INDEX_PREFIX, "1"),
|
|
176
|
+
type: 'two-way',
|
|
177
|
+
public_name: 'Alice'
|
|
178
|
+
});
|
|
179
|
+
expect(result[1]).toMatchObject({
|
|
180
|
+
index: "".concat(RECIPIENT_INDEX_PREFIX, "2"),
|
|
181
|
+
type: 'one-way',
|
|
182
|
+
public_name: 'Bob'
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
it('should sort recipients by public_name', function () {
|
|
186
|
+
var input = {
|
|
187
|
+
recipients: [{
|
|
188
|
+
_id: '1',
|
|
189
|
+
displayName: 'Zara',
|
|
190
|
+
email: [{
|
|
191
|
+
address: 'zara@example.com',
|
|
192
|
+
primary: true
|
|
193
|
+
}]
|
|
194
|
+
}, {
|
|
195
|
+
_id: '2',
|
|
196
|
+
displayName: 'Alice',
|
|
197
|
+
email: [{
|
|
198
|
+
address: 'alice@example.com',
|
|
199
|
+
primary: true
|
|
200
|
+
}]
|
|
201
|
+
}],
|
|
202
|
+
readOnlyRecipients: []
|
|
203
|
+
};
|
|
204
|
+
var result = formatRecipients(input);
|
|
205
|
+
expect(result[0].public_name).toBe('Alice');
|
|
206
|
+
expect(result[1].public_name).toBe('Zara');
|
|
207
|
+
});
|
|
208
|
+
});
|