cozy-sharing 31.1.0 → 31.2.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.
- package/CHANGELOG.md +16 -0
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.js +15 -16
- package/dist/components/FederatedFolder/FederatedFolderModal.js +78 -103
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +102 -292
- package/dist/components/Recipient/RecipientConfirm.js +0 -5
- package/dist/components/ShareAutosuggest.js +9 -4
- package/dist/components/ShareByEmail.js +29 -274
- package/dist/components/ShareByEmail.spec.js +52 -230
- package/dist/components/ShareByLink.js +1 -3
- package/dist/components/ShareDialogCozyToCozy.js +169 -35
- package/dist/components/ShareDialogCozyToCozy.spec.js +122 -35
- package/dist/components/ShareDialogTwoStepsConfirmationContainer.js +13 -3
- package/dist/components/ShareModal/SharingDetailsModal.js +0 -5
- package/dist/components/ShareRecipientsInput.js +6 -3
- package/dist/components/SharedDrive/SharedDriveForm.js +11 -23
- package/dist/components/SharedDrive/SharedDriveModal.js +1 -1
- package/dist/components/SharedDrive/useSharedDrive.js +33 -57
- package/dist/components/SharedDrive/useSharedDrive.spec.js +29 -93
- package/dist/components/SharedFolder/DumbBatchSharedFolderModal.js +15 -26
- package/dist/components/Sharetypeselect.js +85 -90
- package/dist/hooks/usePendingRecipients.js +20 -0
- package/dist/hooks/usePendingRecipients.spec.js +30 -0
- package/dist/styles/autosuggest.styl +8 -2
- package/dist/styles/share.styl +0 -39
- package/dist/stylesheet.css +8 -36
- package/locales/en.json +5 -9
- package/locales/fr.json +5 -9
- package/locales/ru.json +5 -9
- package/locales/vi.json +5 -9
- package/package.json +2 -2
- package/src/components/FederatedFolder/DumbFederatedFolderModal.jsx +14 -15
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +50 -67
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +63 -186
- package/src/components/ShareAutosuggest.jsx +7 -2
- package/src/components/ShareByEmail.jsx +35 -186
- package/src/components/ShareByEmail.spec.jsx +22 -173
- package/src/components/ShareByLink.jsx +1 -7
- package/src/components/ShareDialogCozyToCozy.jsx +171 -38
- package/src/components/ShareDialogCozyToCozy.spec.jsx +66 -0
- package/src/components/ShareDialogTwoStepsConfirmationContainer.jsx +11 -1
- package/src/components/ShareRecipientsInput.jsx +5 -2
- package/src/components/SharedDrive/SharedDriveForm.jsx +10 -23
- package/src/components/SharedDrive/SharedDriveModal.jsx +1 -1
- package/src/components/SharedDrive/useSharedDrive.js +24 -50
- package/src/components/SharedDrive/useSharedDrive.spec.js +19 -67
- package/src/components/SharedFolder/DumbBatchSharedFolderModal.jsx +15 -29
- package/src/components/Sharetypeselect.jsx +75 -58
- package/src/hooks/usePendingRecipients.js +13 -0
- package/src/hooks/usePendingRecipients.spec.js +21 -0
- package/src/styles/autosuggest.styl +8 -2
- package/src/styles/share.styl +0 -39
- package/dist/components/SharedDrive/helpers.js +0 -102
- package/dist/components/SharedDrive/helpers.spec.js +0 -227
- package/dist/components/Sharesubmit.js +0 -28
- package/src/components/SharedDrive/helpers.js +0 -108
- package/src/components/SharedDrive/helpers.spec.js +0 -177
- package/src/components/Sharesubmit.jsx +0 -31
|
@@ -1,102 +0,0 @@
|
|
|
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: ContactModel.getDisplayName(r),
|
|
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: ContactModel.getDisplayName(r),
|
|
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
|
-
};
|
|
@@ -1,227 +0,0 @@
|
|
|
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 flatten an object-shaped contact name into a string public_name', function () {
|
|
186
|
-
var input = {
|
|
187
|
-
recipients: [{
|
|
188
|
-
_id: '3',
|
|
189
|
-
name: {
|
|
190
|
-
givenName: 'Arya',
|
|
191
|
-
familyName: 'Stark'
|
|
192
|
-
},
|
|
193
|
-
email: [{
|
|
194
|
-
address: 'arya@example.com',
|
|
195
|
-
primary: true
|
|
196
|
-
}]
|
|
197
|
-
}],
|
|
198
|
-
readOnlyRecipients: []
|
|
199
|
-
};
|
|
200
|
-
var result = formatRecipients(input);
|
|
201
|
-
expect(typeof result[0].public_name).toBe('string');
|
|
202
|
-
expect(result[0].public_name).toBe('Arya Stark');
|
|
203
|
-
});
|
|
204
|
-
it('should sort recipients by public_name', function () {
|
|
205
|
-
var input = {
|
|
206
|
-
recipients: [{
|
|
207
|
-
_id: '1',
|
|
208
|
-
displayName: 'Zara',
|
|
209
|
-
email: [{
|
|
210
|
-
address: 'zara@example.com',
|
|
211
|
-
primary: true
|
|
212
|
-
}]
|
|
213
|
-
}, {
|
|
214
|
-
_id: '2',
|
|
215
|
-
displayName: 'Alice',
|
|
216
|
-
email: [{
|
|
217
|
-
address: 'alice@example.com',
|
|
218
|
-
primary: true
|
|
219
|
-
}]
|
|
220
|
-
}],
|
|
221
|
-
readOnlyRecipients: []
|
|
222
|
-
};
|
|
223
|
-
var result = formatRecipients(input);
|
|
224
|
-
expect(result[0].public_name).toBe('Alice');
|
|
225
|
-
expect(result[1].public_name).toBe('Zara');
|
|
226
|
-
});
|
|
227
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import Button from 'cozy-ui/transpiled/react/Buttons';
|
|
4
|
-
|
|
5
|
-
var ShareSubmit = function ShareSubmit(props) {
|
|
6
|
-
return /*#__PURE__*/React.createElement(Button, {
|
|
7
|
-
onClick: function onClick() {
|
|
8
|
-
props.onSubmit();
|
|
9
|
-
},
|
|
10
|
-
size: "large",
|
|
11
|
-
busy: props.loading,
|
|
12
|
-
label: props.label,
|
|
13
|
-
disabled: props.disabled,
|
|
14
|
-
variant: "ghost"
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
ShareSubmit.propTypes = {
|
|
19
|
-
onSubmit: PropTypes.func.isRequired,
|
|
20
|
-
label: PropTypes.string,
|
|
21
|
-
loading: PropTypes.bool,
|
|
22
|
-
disabled: PropTypes.bool
|
|
23
|
-
};
|
|
24
|
-
ShareSubmit.defaultProps = {
|
|
25
|
-
label: 'Submit',
|
|
26
|
-
loading: false
|
|
27
|
-
};
|
|
28
|
-
export default ShareSubmit;
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { models } from 'cozy-client'
|
|
2
|
-
|
|
3
|
-
const ContactModel = models.contact
|
|
4
|
-
|
|
5
|
-
export const RECIPIENT_INDEX_PREFIX = 'virtual-shared-drive-sharing-'
|
|
6
|
-
|
|
7
|
-
export const mergeAndDeduplicateRecipients = arrays => {
|
|
8
|
-
const combinedArray = arrays.flat().map(item => ({
|
|
9
|
-
...item,
|
|
10
|
-
id: item.id || item._id
|
|
11
|
-
}))
|
|
12
|
-
|
|
13
|
-
const seenIds = new Set()
|
|
14
|
-
|
|
15
|
-
const uniqueArray = combinedArray.reduce((acc, item) => {
|
|
16
|
-
const id = item.id || item._id
|
|
17
|
-
|
|
18
|
-
if (id == null) {
|
|
19
|
-
// Recipients without any identifier are kept as-is to avoid silent data loss
|
|
20
|
-
acc.push(item)
|
|
21
|
-
return acc
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (!seenIds.has(id)) {
|
|
25
|
-
seenIds.add(id)
|
|
26
|
-
// Ensure both id and _id exist for downstream compatibility
|
|
27
|
-
const normalizedItem =
|
|
28
|
-
!item.id || !item._id
|
|
29
|
-
? { ...item, id: item.id || item._id, _id: item._id || item.id }
|
|
30
|
-
: item
|
|
31
|
-
acc.push(normalizedItem)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return acc
|
|
35
|
-
}, [])
|
|
36
|
-
|
|
37
|
-
return uniqueArray
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const moveRecipientToReadWrite = (federatedRecipients, _id) => {
|
|
41
|
-
const recipientToMove = federatedRecipients.readOnlyRecipients.find(
|
|
42
|
-
r => r._id === _id
|
|
43
|
-
)
|
|
44
|
-
if (!recipientToMove) return federatedRecipients
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
recipients: [...federatedRecipients.recipients, recipientToMove],
|
|
48
|
-
readOnlyRecipients: federatedRecipients.readOnlyRecipients.filter(
|
|
49
|
-
r => r._id !== _id
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const moveRecipientToReadOnly = (federatedRecipients, _id) => {
|
|
55
|
-
const recipientToMove = federatedRecipients.recipients.find(
|
|
56
|
-
r => r._id === _id
|
|
57
|
-
)
|
|
58
|
-
if (!recipientToMove) return federatedRecipients
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
recipients: federatedRecipients.recipients.filter(r => r._id !== _id),
|
|
62
|
-
readOnlyRecipients: [
|
|
63
|
-
...federatedRecipients.readOnlyRecipients,
|
|
64
|
-
recipientToMove
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export const formatRecipients = sharedDriveRecipients => {
|
|
70
|
-
const recipients = []
|
|
71
|
-
|
|
72
|
-
sharedDriveRecipients.recipients.forEach(r => {
|
|
73
|
-
recipients.push({
|
|
74
|
-
index: `${RECIPIENT_INDEX_PREFIX}${r._id}`,
|
|
75
|
-
email: ContactModel.getPrimaryEmail(r),
|
|
76
|
-
public_name: ContactModel.getDisplayName(r),
|
|
77
|
-
memberIndex: r._id,
|
|
78
|
-
type: 'two-way',
|
|
79
|
-
members: r.members
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
sharedDriveRecipients.readOnlyRecipients.forEach(r => {
|
|
84
|
-
recipients.push({
|
|
85
|
-
index: `${RECIPIENT_INDEX_PREFIX}${r._id}`,
|
|
86
|
-
email: ContactModel.getPrimaryEmail(r),
|
|
87
|
-
public_name: ContactModel.getDisplayName(r),
|
|
88
|
-
memberIndex: r._id,
|
|
89
|
-
type: 'one-way',
|
|
90
|
-
members: r.members
|
|
91
|
-
})
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
// We need to sort recipients by public_name
|
|
95
|
-
// to avoid reording them every time we change
|
|
96
|
-
// them from read only to read write.
|
|
97
|
-
recipients.sort((a, b) => {
|
|
98
|
-
if (a.public_name < b.public_name) {
|
|
99
|
-
return -1
|
|
100
|
-
}
|
|
101
|
-
if (a.public_name > b.public_name) {
|
|
102
|
-
return 1
|
|
103
|
-
}
|
|
104
|
-
return 0
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
return recipients
|
|
108
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
mergeAndDeduplicateRecipients,
|
|
3
|
-
moveRecipientToReadWrite,
|
|
4
|
-
moveRecipientToReadOnly,
|
|
5
|
-
formatRecipients,
|
|
6
|
-
RECIPIENT_INDEX_PREFIX
|
|
7
|
-
} from './helpers'
|
|
8
|
-
|
|
9
|
-
describe('mergeAndDeduplicateRecipients', () => {
|
|
10
|
-
it('should merge multiple arrays into one', () => {
|
|
11
|
-
const result = mergeAndDeduplicateRecipients([
|
|
12
|
-
[{ id: '1', name: 'Alice' }],
|
|
13
|
-
[{ id: '2', name: 'Bob' }]
|
|
14
|
-
])
|
|
15
|
-
expect(result).toEqual([
|
|
16
|
-
{ id: '1', _id: '1', name: 'Alice' },
|
|
17
|
-
{ id: '2', _id: '2', name: 'Bob' }
|
|
18
|
-
])
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('should deduplicate recipients with the same id', () => {
|
|
22
|
-
const result = mergeAndDeduplicateRecipients([
|
|
23
|
-
[{ id: '1', name: 'Alice' }],
|
|
24
|
-
[{ id: '1', name: 'Alice' }]
|
|
25
|
-
])
|
|
26
|
-
expect(result).toEqual([{ id: '1', _id: '1', name: 'Alice' }])
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('should normalize _id to id for deduplication', () => {
|
|
30
|
-
const result = mergeAndDeduplicateRecipients([
|
|
31
|
-
[{ _id: '1', name: 'Alice' }],
|
|
32
|
-
[{ _id: '2', name: 'Bob' }]
|
|
33
|
-
])
|
|
34
|
-
expect(result).toEqual([
|
|
35
|
-
{ _id: '1', id: '1', name: 'Alice' },
|
|
36
|
-
{ _id: '2', id: '2', name: 'Bob' }
|
|
37
|
-
])
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('should deduplicate recipients when one has id and the other has _id', () => {
|
|
41
|
-
const result = mergeAndDeduplicateRecipients([
|
|
42
|
-
[{ id: '1', name: 'Alice' }],
|
|
43
|
-
[{ _id: '1', name: 'Alice' }]
|
|
44
|
-
])
|
|
45
|
-
expect(result).toEqual([{ id: '1', _id: '1', name: 'Alice' }])
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('should prefer existing id over _id when both are present', () => {
|
|
49
|
-
const result = mergeAndDeduplicateRecipients([
|
|
50
|
-
[{ id: 'real-id', _id: 'other-id', name: 'Alice' }]
|
|
51
|
-
])
|
|
52
|
-
expect(result).toEqual([{ id: 'real-id', _id: 'other-id', name: 'Alice' }])
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should handle empty arrays', () => {
|
|
56
|
-
const result = mergeAndDeduplicateRecipients([[], []])
|
|
57
|
-
expect(result).toEqual([])
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
describe('moveRecipientToReadWrite', () => {
|
|
62
|
-
it('should move a recipient from readOnly to readWrite', () => {
|
|
63
|
-
const state = {
|
|
64
|
-
recipients: [{ _id: '1', name: 'Alice' }],
|
|
65
|
-
readOnlyRecipients: [{ _id: '2', name: 'Bob' }]
|
|
66
|
-
}
|
|
67
|
-
const result = moveRecipientToReadWrite(state, '2')
|
|
68
|
-
expect(result.recipients).toEqual([
|
|
69
|
-
{ _id: '1', name: 'Alice' },
|
|
70
|
-
{ _id: '2', name: 'Bob' }
|
|
71
|
-
])
|
|
72
|
-
expect(result.readOnlyRecipients).toEqual([])
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('should return unchanged state if recipient not found', () => {
|
|
76
|
-
const state = {
|
|
77
|
-
recipients: [{ _id: '1', name: 'Alice' }],
|
|
78
|
-
readOnlyRecipients: []
|
|
79
|
-
}
|
|
80
|
-
const result = moveRecipientToReadWrite(state, '999')
|
|
81
|
-
expect(result).toBe(state)
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
describe('moveRecipientToReadOnly', () => {
|
|
86
|
-
it('should move a recipient from readWrite to readOnly', () => {
|
|
87
|
-
const state = {
|
|
88
|
-
recipients: [{ _id: '1', name: 'Alice' }],
|
|
89
|
-
readOnlyRecipients: [{ _id: '2', name: 'Bob' }]
|
|
90
|
-
}
|
|
91
|
-
const result = moveRecipientToReadOnly(state, '1')
|
|
92
|
-
expect(result.recipients).toEqual([])
|
|
93
|
-
expect(result.readOnlyRecipients).toEqual([
|
|
94
|
-
{ _id: '2', name: 'Bob' },
|
|
95
|
-
{ _id: '1', name: 'Alice' }
|
|
96
|
-
])
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it('should return unchanged state if recipient not found', () => {
|
|
100
|
-
const state = {
|
|
101
|
-
recipients: [],
|
|
102
|
-
readOnlyRecipients: [{ _id: '1', name: 'Alice' }]
|
|
103
|
-
}
|
|
104
|
-
const result = moveRecipientToReadOnly(state, '999')
|
|
105
|
-
expect(result).toBe(state)
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
describe('formatRecipients', () => {
|
|
110
|
-
it('should format readWrite and readOnly recipients with correct types', () => {
|
|
111
|
-
const input = {
|
|
112
|
-
recipients: [
|
|
113
|
-
{
|
|
114
|
-
_id: '1',
|
|
115
|
-
displayName: 'Alice',
|
|
116
|
-
email: [{ address: 'alice@example.com', primary: true }]
|
|
117
|
-
}
|
|
118
|
-
],
|
|
119
|
-
readOnlyRecipients: [
|
|
120
|
-
{
|
|
121
|
-
_id: '2',
|
|
122
|
-
displayName: 'Bob',
|
|
123
|
-
email: [{ address: 'bob@example.com', primary: true }]
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
const result = formatRecipients(input)
|
|
128
|
-
expect(result).toHaveLength(2)
|
|
129
|
-
expect(result[0]).toMatchObject({
|
|
130
|
-
index: `${RECIPIENT_INDEX_PREFIX}1`,
|
|
131
|
-
type: 'two-way',
|
|
132
|
-
public_name: 'Alice'
|
|
133
|
-
})
|
|
134
|
-
expect(result[1]).toMatchObject({
|
|
135
|
-
index: `${RECIPIENT_INDEX_PREFIX}2`,
|
|
136
|
-
type: 'one-way',
|
|
137
|
-
public_name: 'Bob'
|
|
138
|
-
})
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
it('should flatten an object-shaped contact name into a string public_name', () => {
|
|
142
|
-
const input = {
|
|
143
|
-
recipients: [
|
|
144
|
-
{
|
|
145
|
-
_id: '3',
|
|
146
|
-
name: { givenName: 'Arya', familyName: 'Stark' },
|
|
147
|
-
email: [{ address: 'arya@example.com', primary: true }]
|
|
148
|
-
}
|
|
149
|
-
],
|
|
150
|
-
readOnlyRecipients: []
|
|
151
|
-
}
|
|
152
|
-
const result = formatRecipients(input)
|
|
153
|
-
expect(typeof result[0].public_name).toBe('string')
|
|
154
|
-
expect(result[0].public_name).toBe('Arya Stark')
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('should sort recipients by public_name', () => {
|
|
158
|
-
const input = {
|
|
159
|
-
recipients: [
|
|
160
|
-
{
|
|
161
|
-
_id: '1',
|
|
162
|
-
displayName: 'Zara',
|
|
163
|
-
email: [{ address: 'zara@example.com', primary: true }]
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
_id: '2',
|
|
167
|
-
displayName: 'Alice',
|
|
168
|
-
email: [{ address: 'alice@example.com', primary: true }]
|
|
169
|
-
}
|
|
170
|
-
],
|
|
171
|
-
readOnlyRecipients: []
|
|
172
|
-
}
|
|
173
|
-
const result = formatRecipients(input)
|
|
174
|
-
expect(result[0].public_name).toBe('Alice')
|
|
175
|
-
expect(result[1].public_name).toBe('Zara')
|
|
176
|
-
})
|
|
177
|
-
})
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
|
|
4
|
-
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
5
|
-
|
|
6
|
-
const ShareSubmit = props => (
|
|
7
|
-
<Button
|
|
8
|
-
onClick={() => {
|
|
9
|
-
props.onSubmit()
|
|
10
|
-
}}
|
|
11
|
-
size="large"
|
|
12
|
-
busy={props.loading}
|
|
13
|
-
label={props.label}
|
|
14
|
-
disabled={props.disabled}
|
|
15
|
-
variant="ghost"
|
|
16
|
-
/>
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
ShareSubmit.propTypes = {
|
|
20
|
-
onSubmit: PropTypes.func.isRequired,
|
|
21
|
-
label: PropTypes.string,
|
|
22
|
-
loading: PropTypes.bool,
|
|
23
|
-
disabled: PropTypes.bool
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
ShareSubmit.defaultProps = {
|
|
27
|
-
label: 'Submit',
|
|
28
|
-
loading: false
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export default ShareSubmit
|