cozy-sharing 37.5.4 → 37.6.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 +11 -0
- package/README.md +3 -2
- package/dist/SharingProvider.js +270 -196
- package/dist/SharingProvider.spec.js +34 -4
- package/dist/components/FederatedFolder/FederatedFolderModal.js +61 -82
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +19 -8
- package/dist/components/ShareDialogCozyToCozy.js +21 -108
- package/dist/components/ShareModal/EditableSharingModal.js +44 -8
- package/dist/components/ShareModal/ShareModal.js +2 -2
- package/dist/components/ShareModal.js +2 -2
- package/dist/components/SharingContent.js +92 -0
- package/dist/helpers/effectiveRecipients.js +40 -0
- package/dist/helpers/effectiveRecipients.spec.js +134 -0
- package/dist/state.js +68 -1
- package/dist/state.spec.js +2 -1
- package/package.json +3 -3
- package/src/SharingProvider.jsx +61 -1
- package/src/SharingProvider.spec.jsx +28 -2
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +50 -65
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +16 -8
- package/src/components/ShareDialogCozyToCozy.jsx +1 -87
- package/src/components/ShareModal/EditableSharingModal.jsx +61 -8
- package/src/components/ShareModal/ShareModal.jsx +2 -2
- package/src/components/ShareModal.jsx +2 -2
- package/src/components/SharingContent.jsx +94 -0
- package/src/helpers/effectiveRecipients.js +34 -0
- package/src/helpers/effectiveRecipients.spec.js +125 -0
- package/src/state.js +52 -1
- package/src/state.spec.js +2 -1
|
@@ -533,7 +533,8 @@ describe('shared drive recipient revocation', () => {
|
|
|
533
533
|
sharingCol = {
|
|
534
534
|
addRecipients: jest.fn(),
|
|
535
535
|
create: jest.fn().mockResolvedValue({ data: NEW_SHARING }),
|
|
536
|
-
revokeRecipient: jest.fn().mockResolvedValue({})
|
|
536
|
+
revokeRecipient: jest.fn().mockResolvedValue({}),
|
|
537
|
+
fetchEffectiveRecipients: jest.fn().mockResolvedValue({ data: [] })
|
|
537
538
|
}
|
|
538
539
|
provider.sharingCol = sharingCol
|
|
539
540
|
})
|
|
@@ -792,7 +793,8 @@ describe('updateSharingMemberType', () => {
|
|
|
792
793
|
)
|
|
793
794
|
instance.sharingCol = {
|
|
794
795
|
setReadOnly: jest.fn().mockResolvedValue({}),
|
|
795
|
-
setReadWrite: jest.fn().mockResolvedValue({})
|
|
796
|
+
setReadWrite: jest.fn().mockResolvedValue({}),
|
|
797
|
+
fetchEffectiveRecipients: jest.fn().mockResolvedValue({ data: [] })
|
|
796
798
|
}
|
|
797
799
|
})
|
|
798
800
|
|
|
@@ -913,6 +915,12 @@ describe('updateSharingMemberType', () => {
|
|
|
913
915
|
}
|
|
914
916
|
})
|
|
915
917
|
expect(instance.dispatch).toHaveBeenNthCalledWith(2, {
|
|
918
|
+
type: 'UPDATE_EFFECTIVE_RECIPIENT',
|
|
919
|
+
sharingId: 'sharing-123',
|
|
920
|
+
memberIndex: 1,
|
|
921
|
+
readOnly: true
|
|
922
|
+
})
|
|
923
|
+
expect(instance.dispatch).toHaveBeenNthCalledWith(3, {
|
|
916
924
|
type: 'UPDATE_SHARING',
|
|
917
925
|
sharing: {
|
|
918
926
|
...mockSharing,
|
|
@@ -928,6 +936,12 @@ describe('updateSharingMemberType', () => {
|
|
|
928
936
|
}
|
|
929
937
|
}
|
|
930
938
|
})
|
|
939
|
+
expect(instance.dispatch).toHaveBeenNthCalledWith(4, {
|
|
940
|
+
type: 'UPDATE_EFFECTIVE_RECIPIENT',
|
|
941
|
+
sharingId: 'sharing-123',
|
|
942
|
+
memberIndex: 1,
|
|
943
|
+
readOnly: false
|
|
944
|
+
})
|
|
931
945
|
})
|
|
932
946
|
|
|
933
947
|
it('should preserve realtime changes when rolling back an API failure', async () => {
|
|
@@ -964,6 +978,12 @@ describe('updateSharingMemberType', () => {
|
|
|
964
978
|
).rejects.toThrow('Network error')
|
|
965
979
|
|
|
966
980
|
expect(instance.dispatch).toHaveBeenNthCalledWith(2, {
|
|
981
|
+
type: 'UPDATE_EFFECTIVE_RECIPIENT',
|
|
982
|
+
sharingId: 'sharing-123',
|
|
983
|
+
memberIndex: 1,
|
|
984
|
+
readOnly: true
|
|
985
|
+
})
|
|
986
|
+
expect(instance.dispatch).toHaveBeenNthCalledWith(3, {
|
|
967
987
|
type: 'UPDATE_SHARING',
|
|
968
988
|
sharing: {
|
|
969
989
|
...realtimeSharing,
|
|
@@ -979,6 +999,12 @@ describe('updateSharingMemberType', () => {
|
|
|
979
999
|
}
|
|
980
1000
|
}
|
|
981
1001
|
})
|
|
1002
|
+
expect(instance.dispatch).toHaveBeenNthCalledWith(4, {
|
|
1003
|
+
type: 'UPDATE_EFFECTIVE_RECIPIENT',
|
|
1004
|
+
sharingId: 'sharing-123',
|
|
1005
|
+
memberIndex: 1,
|
|
1006
|
+
readOnly: false
|
|
1007
|
+
})
|
|
982
1008
|
})
|
|
983
1009
|
})
|
|
984
1010
|
|
|
@@ -16,7 +16,6 @@ import { getOrCreateFromArray } from '../../helpers/contacts'
|
|
|
16
16
|
import withLocales from '../../hoc/withLocales'
|
|
17
17
|
import { usePendingRecipients } from '../../hooks/usePendingRecipients'
|
|
18
18
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
19
|
-
import { getRecipientsFromSharing } from '../../state'
|
|
20
19
|
import styles from '../../styles/share.styl'
|
|
21
20
|
import AntivirusAlert from '../AntivirusAlert'
|
|
22
21
|
import { default as DumbShareByEmail } from '../ShareByEmail'
|
|
@@ -29,6 +28,7 @@ const FederatedFolderModalContent = ({
|
|
|
29
28
|
onClose,
|
|
30
29
|
onRevokeSuccess,
|
|
31
30
|
document: existingDocument,
|
|
31
|
+
recipients,
|
|
32
32
|
autoOpenShareRestriction,
|
|
33
33
|
showGenerateLinkButton
|
|
34
34
|
}) => {
|
|
@@ -48,10 +48,6 @@ const FederatedFolderModalContent = ({
|
|
|
48
48
|
getFederatedShareLink,
|
|
49
49
|
getDocumentPermissions,
|
|
50
50
|
fetchSharedDriveSharingLinks,
|
|
51
|
-
getRecipients,
|
|
52
|
-
getSharedParentPath,
|
|
53
|
-
hasSharedChild,
|
|
54
|
-
hasSharedParent,
|
|
55
51
|
isOwner,
|
|
56
52
|
revoke,
|
|
57
53
|
revokeSelf
|
|
@@ -70,11 +66,9 @@ const FederatedFolderModalContent = ({
|
|
|
70
66
|
useState(null)
|
|
71
67
|
const [frozenDoc, setFrozenDoc] = useState(null)
|
|
72
68
|
const [frozenRecipients, setFrozenRecipients] = useState(null)
|
|
73
|
-
const [sharedParentFolder, setSharedParentFolder] = useState(null)
|
|
74
69
|
|
|
75
70
|
const documentId = existingDocument?._id || existingDocument?.id
|
|
76
71
|
const folderName = existingDocument?.name || ''
|
|
77
|
-
const documentPath = existingDocument?.path
|
|
78
72
|
const sharedDriveSharing = existingDocument?.driveId
|
|
79
73
|
? getSharingById(existingDocument.driveId)
|
|
80
74
|
: null
|
|
@@ -83,25 +77,7 @@ const FederatedFolderModalContent = ({
|
|
|
83
77
|
(ids, rule) => ids.concat(rule.values || []),
|
|
84
78
|
[]
|
|
85
79
|
) || []
|
|
86
|
-
|
|
87
|
-
// find the parent shared folder to use its _id for recipient/permission lookups.
|
|
88
|
-
const hasSharedParentByPath = Boolean(
|
|
89
|
-
documentPath && hasSharedParent(documentPath)
|
|
90
|
-
)
|
|
91
|
-
const sharedParentPath =
|
|
92
|
-
!sharedDriveSharing && hasSharedParentByPath && documentPath
|
|
93
|
-
? getSharedParentPath(documentPath)
|
|
94
|
-
: null
|
|
95
|
-
const sharingReferenceId =
|
|
96
|
-
!sharedDriveSharing && sharedParentFolder?._id
|
|
97
|
-
? sharedParentFolder._id
|
|
98
|
-
: documentId
|
|
99
|
-
const existingRecipients =
|
|
100
|
-
sharedDriveSharing?.attributes?.members && documentId
|
|
101
|
-
? getRecipientsFromSharing(sharedDriveSharing, documentId)
|
|
102
|
-
: sharingReferenceId
|
|
103
|
-
? getRecipients(sharingReferenceId)
|
|
104
|
-
: []
|
|
80
|
+
|
|
105
81
|
const documentPermissions = documentId
|
|
106
82
|
? getDocumentPermissions(documentId)
|
|
107
83
|
: []
|
|
@@ -124,11 +100,6 @@ const FederatedFolderModalContent = ({
|
|
|
124
100
|
? isOwner(documentId)
|
|
125
101
|
: false
|
|
126
102
|
const isMemberReadOnly = isInsideSharedDrive && !isCurrentUserOwner
|
|
127
|
-
const hasParentRestriction = isInsideSharedDrive || hasSharedParentByPath
|
|
128
|
-
const hasChildRestriction = Boolean(
|
|
129
|
-
documentPath && hasSharedChild(documentPath)
|
|
130
|
-
)
|
|
131
|
-
const canShareByEmail = !hasParentRestriction && !hasChildRestriction
|
|
132
103
|
const canManageSharing =
|
|
133
104
|
isCurrentUserOwner || (documentId ? canReshare(documentId) : false)
|
|
134
105
|
|
|
@@ -181,7 +152,7 @@ const FederatedFolderModalContent = ({
|
|
|
181
152
|
|
|
182
153
|
setIsSending(true)
|
|
183
154
|
setFrozenDoc(existingDocument)
|
|
184
|
-
setFrozenRecipients(
|
|
155
|
+
setFrozenRecipients(recipients)
|
|
185
156
|
|
|
186
157
|
try {
|
|
187
158
|
const contacts = await getOrCreateFromArray(
|
|
@@ -219,21 +190,6 @@ const FederatedFolderModalContent = ({
|
|
|
219
190
|
}
|
|
220
191
|
}
|
|
221
192
|
|
|
222
|
-
useEffect(() => {
|
|
223
|
-
if (!sharedParentPath) return
|
|
224
|
-
const fetchParentFolder = async () => {
|
|
225
|
-
try {
|
|
226
|
-
const res = await client
|
|
227
|
-
.collection('io.cozy.files')
|
|
228
|
-
.statByPath(sharedParentPath)
|
|
229
|
-
if (res.data) setSharedParentFolder(res.data)
|
|
230
|
-
} catch (err) {
|
|
231
|
-
log.error('Failed to fetch shared parent folder', err)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
fetchParentFolder()
|
|
235
|
-
}, [sharedParentPath, client])
|
|
236
|
-
|
|
237
193
|
useEffect(() => {
|
|
238
194
|
if (!existingDocument?.driveId) return
|
|
239
195
|
if (!documentId) return
|
|
@@ -283,7 +239,7 @@ const FederatedFolderModalContent = ({
|
|
|
283
239
|
<AntivirusAlert
|
|
284
240
|
document={isSending ? frozenDoc : existingDocument}
|
|
285
241
|
/>
|
|
286
|
-
{
|
|
242
|
+
{isInsideSharedDrive ? (
|
|
287
243
|
<div className={styles['share-byemail-onlybylink']}>
|
|
288
244
|
{t('Files.share.shareByEmail.onlyByLink', {
|
|
289
245
|
type: t(
|
|
@@ -292,26 +248,15 @@ const FederatedFolderModalContent = ({
|
|
|
292
248
|
}`
|
|
293
249
|
)
|
|
294
250
|
})}{' '}
|
|
295
|
-
<strong>
|
|
296
|
-
{t(
|
|
297
|
-
`Files.share.shareByEmail.${
|
|
298
|
-
hasParentRestriction
|
|
299
|
-
? 'hasSharedParent'
|
|
300
|
-
: 'hasSharedChild'
|
|
301
|
-
}`
|
|
302
|
-
)}
|
|
303
|
-
</strong>
|
|
251
|
+
<strong>{t('Files.share.shareByEmail.hasSharedParent')}</strong>
|
|
304
252
|
</div>
|
|
305
|
-
)
|
|
306
|
-
{canShareByEmail && (
|
|
253
|
+
) : (
|
|
307
254
|
<>
|
|
308
255
|
<Typography variant="h6" className="u-mt-1-half u-mb-half">
|
|
309
256
|
{t('Share.contacts.addUsers')}
|
|
310
257
|
</Typography>
|
|
311
258
|
<DumbShareByEmail
|
|
312
|
-
currentRecipients={
|
|
313
|
-
isSending ? frozenRecipients : existingRecipients
|
|
314
|
-
}
|
|
259
|
+
currentRecipients={isSending ? frozenRecipients : recipients}
|
|
315
260
|
document={isSending ? frozenDoc : existingDocument}
|
|
316
261
|
documentType="Files"
|
|
317
262
|
pendingRecipients={pendingRecipients}
|
|
@@ -329,7 +274,7 @@ const FederatedFolderModalContent = ({
|
|
|
329
274
|
isSharedDrive
|
|
330
275
|
canManageMembers={!isMemberReadOnly}
|
|
331
276
|
canManageLink={true}
|
|
332
|
-
recipients={isSending ? frozenRecipients :
|
|
277
|
+
recipients={isSending ? frozenRecipients : recipients}
|
|
333
278
|
document={isSending ? frozenDoc : existingDocument}
|
|
334
279
|
documentType="Files"
|
|
335
280
|
className={styles['share-dialog-members']}
|
|
@@ -348,7 +293,7 @@ const FederatedFolderModalContent = ({
|
|
|
348
293
|
showGenerateLinkButton={showGenerateLinkButton}
|
|
349
294
|
autoOpenShareRestriction={autoOpenShareRestriction}
|
|
350
295
|
/>
|
|
351
|
-
{
|
|
296
|
+
{!isInsideSharedDrive && (
|
|
352
297
|
<Button
|
|
353
298
|
variant="primary"
|
|
354
299
|
label={t('FederatedFolder.share')}
|
|
@@ -362,9 +307,49 @@ const FederatedFolderModalContent = ({
|
|
|
362
307
|
)
|
|
363
308
|
}
|
|
364
309
|
|
|
310
|
+
FederatedFolderModalContent.propTypes = {
|
|
311
|
+
onClose: PropTypes.func.isRequired,
|
|
312
|
+
onRevokeSuccess: PropTypes.func,
|
|
313
|
+
document: PropTypes.object.isRequired,
|
|
314
|
+
recipients: PropTypes.array,
|
|
315
|
+
autoOpenShareRestriction: PropTypes.bool,
|
|
316
|
+
showGenerateLinkButton: PropTypes.bool
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const FederatedFolderModalWrapper = ({ document, ...props }) => {
|
|
320
|
+
const fileId = document._id || document.id
|
|
321
|
+
const {
|
|
322
|
+
getEffectiveRecipients,
|
|
323
|
+
fetchEffectiveRecipients,
|
|
324
|
+
invalidateEffectiveRecipients
|
|
325
|
+
} = useSharingContext()
|
|
326
|
+
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
fetchEffectiveRecipients(fileId, document.driveId).catch(log.error)
|
|
329
|
+
return () => {
|
|
330
|
+
invalidateEffectiveRecipients(fileId)
|
|
331
|
+
}
|
|
332
|
+
}, [
|
|
333
|
+
fileId,
|
|
334
|
+
document.driveId,
|
|
335
|
+
fetchEffectiveRecipients,
|
|
336
|
+
invalidateEffectiveRecipients
|
|
337
|
+
])
|
|
338
|
+
|
|
339
|
+
const recipients = getEffectiveRecipients(fileId)
|
|
340
|
+
|
|
341
|
+
return (
|
|
342
|
+
<FederatedFolderModalContent
|
|
343
|
+
document={document}
|
|
344
|
+
recipients={recipients}
|
|
345
|
+
{...props}
|
|
346
|
+
/>
|
|
347
|
+
)
|
|
348
|
+
}
|
|
349
|
+
|
|
365
350
|
export const FederatedFolderModal = withLocales(props => (
|
|
366
351
|
<ConfirmDialogProvider>
|
|
367
|
-
<
|
|
352
|
+
<FederatedFolderModalWrapper {...props} />
|
|
368
353
|
</ConfirmDialogProvider>
|
|
369
354
|
))
|
|
370
355
|
|
|
@@ -16,7 +16,6 @@ const mockIsOwner = jest.fn()
|
|
|
16
16
|
const mockCanReshare = jest.fn()
|
|
17
17
|
const mockGetSharingLink = jest.fn()
|
|
18
18
|
const mockGetFederatedShareLink = jest.fn()
|
|
19
|
-
const mockGetRecipients = jest.fn().mockReturnValue([])
|
|
20
19
|
const mockGetSharingById = jest.fn()
|
|
21
20
|
const mockHasSharedChild = jest.fn()
|
|
22
21
|
const mockHasSharedParent = jest.fn()
|
|
@@ -25,6 +24,8 @@ const mockGetDocumentPermissions = jest.fn().mockReturnValue([])
|
|
|
25
24
|
const mockShowAlert = jest.fn()
|
|
26
25
|
const mockOnClose = jest.fn()
|
|
27
26
|
|
|
27
|
+
const mockGetEffectiveRecipients = jest.fn(() => [])
|
|
28
|
+
|
|
28
29
|
jest.mock('../../hooks/useSharingContext', () => ({
|
|
29
30
|
useSharingContext: () => ({
|
|
30
31
|
share: mockShare,
|
|
@@ -38,12 +39,14 @@ jest.mock('../../hooks/useSharingContext', () => ({
|
|
|
38
39
|
getDocumentPermissions: mockGetDocumentPermissions,
|
|
39
40
|
fetchSharedDriveSharingLinks: mockFetchSharedDriveSharingLinks,
|
|
40
41
|
getOwner: jest.fn(),
|
|
41
|
-
getRecipients: mockGetRecipients,
|
|
42
42
|
getSharedParentPath: jest.fn().mockReturnValue(null),
|
|
43
43
|
getSharingById: mockGetSharingById,
|
|
44
44
|
hasSharedChild: mockHasSharedChild,
|
|
45
45
|
hasSharedParent: mockHasSharedParent,
|
|
46
|
-
isOrgSharedDrive: jest.fn(() => false)
|
|
46
|
+
isOrgSharedDrive: jest.fn(() => false),
|
|
47
|
+
getEffectiveRecipients: (...args) => mockGetEffectiveRecipients(...args),
|
|
48
|
+
fetchEffectiveRecipients: jest.fn().mockResolvedValue(),
|
|
49
|
+
invalidateEffectiveRecipients: jest.fn()
|
|
47
50
|
})
|
|
48
51
|
}))
|
|
49
52
|
|
|
@@ -118,7 +121,6 @@ describe('FederatedFolderModal', () => {
|
|
|
118
121
|
mockGetFederatedShareLink.mockReturnValue(
|
|
119
122
|
'https://example.com/share/federated-abc123'
|
|
120
123
|
)
|
|
121
|
-
mockGetRecipients.mockReturnValue([])
|
|
122
124
|
mockGetSharingById.mockReturnValue(null)
|
|
123
125
|
mockHasSharedChild.mockReturnValue(false)
|
|
124
126
|
mockHasSharedParent.mockReturnValue(false)
|
|
@@ -458,12 +460,15 @@ describe('FederatedFolderModal', () => {
|
|
|
458
460
|
instance: 'https://me.mycozy.cloud',
|
|
459
461
|
memberIndex: 1,
|
|
460
462
|
sharingId: 'sharing-id',
|
|
461
|
-
type: 'two-way'
|
|
463
|
+
type: 'two-way',
|
|
464
|
+
status: 'ready',
|
|
465
|
+
name: 'Me',
|
|
466
|
+
email: 'me@test.com'
|
|
462
467
|
}
|
|
463
468
|
|
|
464
469
|
it('should call onRevokeSelf and onRevokeSuccess when the current user is revoked', async () => {
|
|
465
470
|
const onRevokeSuccess = jest.fn()
|
|
466
|
-
|
|
471
|
+
mockGetEffectiveRecipients.mockReturnValue([currentUserRecipient])
|
|
467
472
|
|
|
468
473
|
const { findByLabelText } = setup({ onRevokeSuccess })
|
|
469
474
|
|
|
@@ -481,10 +486,13 @@ describe('FederatedFolderModal', () => {
|
|
|
481
486
|
instance: 'https://other.mycozy.cloud',
|
|
482
487
|
memberIndex: 2,
|
|
483
488
|
sharingId: 'sharing-id',
|
|
484
|
-
type: 'two-way'
|
|
489
|
+
type: 'two-way',
|
|
490
|
+
status: 'ready',
|
|
491
|
+
name: 'Other',
|
|
492
|
+
email: 'other@test.com'
|
|
485
493
|
}
|
|
486
494
|
mockCanReshare.mockReturnValue(true)
|
|
487
|
-
|
|
495
|
+
mockGetEffectiveRecipients.mockReturnValue([otherRecipient])
|
|
488
496
|
|
|
489
497
|
const { findByLabelText } = setup()
|
|
490
498
|
|
|
@@ -1,106 +1,20 @@
|
|
|
1
|
-
import cx from 'classnames'
|
|
2
1
|
import PropTypes from 'prop-types'
|
|
3
2
|
import React, { useCallback, useMemo, useState } from 'react'
|
|
4
3
|
|
|
5
4
|
import { useClient } from 'cozy-client'
|
|
6
5
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
7
|
-
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
8
6
|
import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
|
|
9
|
-
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
|
|
10
7
|
import { useI18n } from 'twake-i18n'
|
|
11
8
|
|
|
12
|
-
import AntivirusAlert from './AntivirusAlert'
|
|
13
|
-
import { default as DumbShareByEmail } from './ShareByEmail'
|
|
14
9
|
import { default as DumbShareByLink } from './ShareByLink'
|
|
15
10
|
import ShareDialogTwoStepsConfirmationContainer from './ShareDialogTwoStepsConfirmationContainer'
|
|
16
11
|
import { ShareRecipientsLimitModal } from './ShareRecipientsLimitModal'
|
|
17
|
-
import
|
|
12
|
+
import SharingContent from './SharingContent'
|
|
18
13
|
import { getOrCreateFromArray } from '../helpers/contacts'
|
|
19
14
|
import { hasReachRecipientsLimit } from '../helpers/recipients'
|
|
20
15
|
import { getErrorMessage, getSuccessMessage } from '../helpers/share'
|
|
21
16
|
import { usePendingRecipients } from '../hooks/usePendingRecipients'
|
|
22
17
|
import { useSharingContext } from '../hooks/useSharingContext'
|
|
23
|
-
import styles from '../styles/share.styl'
|
|
24
|
-
|
|
25
|
-
const SharingContent = ({
|
|
26
|
-
document,
|
|
27
|
-
documentType,
|
|
28
|
-
hasSharedParent,
|
|
29
|
-
isOwner,
|
|
30
|
-
onRevoke,
|
|
31
|
-
onRevokeSelf,
|
|
32
|
-
recipients,
|
|
33
|
-
sharing,
|
|
34
|
-
showShareByEmail,
|
|
35
|
-
showShareOnlyByLink,
|
|
36
|
-
showWhoHasAccess,
|
|
37
|
-
recipientsToBeConfirmed,
|
|
38
|
-
verifyRecipient,
|
|
39
|
-
link,
|
|
40
|
-
permissions,
|
|
41
|
-
pendingRecipients,
|
|
42
|
-
onPendingRecipientsChange,
|
|
43
|
-
selectedOption,
|
|
44
|
-
onSelectedOptionChange
|
|
45
|
-
}) => {
|
|
46
|
-
const { t } = useI18n()
|
|
47
|
-
const { isMobile } = useBreakpoints()
|
|
48
|
-
return (
|
|
49
|
-
<div className={cx(styles['share-modal-content'])}>
|
|
50
|
-
<div className={cx('u-pt-1-half', isMobile ? 'u-ph-1' : 'u-ph-2')}>
|
|
51
|
-
<AntivirusAlert document={document} />
|
|
52
|
-
{showShareOnlyByLink && (
|
|
53
|
-
<div className={styles['share-byemail-onlybylink']}>
|
|
54
|
-
{t(`${documentType}.share.shareByEmail.onlyByLink`, {
|
|
55
|
-
type: t(
|
|
56
|
-
`${documentType}.share.shareByEmail.type.${
|
|
57
|
-
document.type === 'directory' ? 'folder' : 'file'
|
|
58
|
-
}`
|
|
59
|
-
)
|
|
60
|
-
})}{' '}
|
|
61
|
-
<strong>
|
|
62
|
-
{t(
|
|
63
|
-
`${documentType}.share.shareByEmail.${
|
|
64
|
-
hasSharedParent ? 'hasSharedParent' : 'hasSharedChild'
|
|
65
|
-
}`
|
|
66
|
-
)}
|
|
67
|
-
</strong>
|
|
68
|
-
</div>
|
|
69
|
-
)}
|
|
70
|
-
<Typography variant="h6" className="u-mb-half">
|
|
71
|
-
{t('Share.contacts.addUsers')}
|
|
72
|
-
</Typography>
|
|
73
|
-
{showShareByEmail && (
|
|
74
|
-
<DumbShareByEmail
|
|
75
|
-
currentRecipients={recipients}
|
|
76
|
-
document={document}
|
|
77
|
-
documentType={documentType}
|
|
78
|
-
sharing={sharing}
|
|
79
|
-
pendingRecipients={pendingRecipients}
|
|
80
|
-
onPendingRecipientsChange={onPendingRecipientsChange}
|
|
81
|
-
selectedOption={selectedOption}
|
|
82
|
-
onSelectedOptionChange={onSelectedOptionChange}
|
|
83
|
-
enableCreateContact
|
|
84
|
-
/>
|
|
85
|
-
)}
|
|
86
|
-
</div>
|
|
87
|
-
{showWhoHasAccess && (
|
|
88
|
-
<WhoHasAccess
|
|
89
|
-
document={document}
|
|
90
|
-
documentType={documentType}
|
|
91
|
-
isOwner={isOwner}
|
|
92
|
-
onRevoke={onRevoke}
|
|
93
|
-
onRevokeSelf={onRevokeSelf}
|
|
94
|
-
recipients={recipients}
|
|
95
|
-
recipientsToBeConfirmed={recipientsToBeConfirmed}
|
|
96
|
-
verifyRecipient={verifyRecipient}
|
|
97
|
-
link={link}
|
|
98
|
-
permissions={permissions}
|
|
99
|
-
/>
|
|
100
|
-
)}
|
|
101
|
-
</div>
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
18
|
|
|
105
19
|
const SharingTitleFunction = ({ documentType, document }) =>
|
|
106
20
|
function SharingTitle() {
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
|
-
import React from 'react'
|
|
2
|
+
import React, { useEffect } from 'react'
|
|
3
3
|
|
|
4
4
|
import { useClient } from 'cozy-client'
|
|
5
|
+
import flag from 'cozy-flags'
|
|
6
|
+
import minilog from 'cozy-minilog'
|
|
5
7
|
|
|
6
8
|
import { useFetchDocumentPath } from '../../hooks/useFetchDocumentPath'
|
|
7
9
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
8
10
|
import { Contact } from '../../models'
|
|
9
11
|
import { ShareModal } from '../ShareModal'
|
|
10
12
|
|
|
11
|
-
export const EditableSharingModal = ({ document, ...rest }) => {
|
|
13
|
+
export const EditableSharingModal = ({ document, recipients, ...rest }) => {
|
|
12
14
|
const client = useClient()
|
|
15
|
+
const isFederatedMode = flag('drive.federated-shared-folder.enabled')
|
|
13
16
|
const documentPath = useFetchDocumentPath(client, document)
|
|
14
17
|
|
|
15
18
|
const {
|
|
16
19
|
documentType,
|
|
17
20
|
getDocumentPermissions,
|
|
18
|
-
getRecipients,
|
|
19
21
|
getSharingForSelf,
|
|
20
22
|
getSharingLink,
|
|
21
23
|
hasSharedChild,
|
|
@@ -31,15 +33,23 @@ export const EditableSharingModal = ({ document, ...rest }) => {
|
|
|
31
33
|
createContact={contact => client.create(Contact.doctype, contact)}
|
|
32
34
|
document={document}
|
|
33
35
|
documentType={documentType}
|
|
34
|
-
hasSharedChild={
|
|
35
|
-
|
|
36
|
+
hasSharedChild={
|
|
37
|
+
isFederatedMode
|
|
38
|
+
? undefined
|
|
39
|
+
: documentPath && hasSharedChild(documentPath)
|
|
40
|
+
}
|
|
41
|
+
hasSharedParent={
|
|
42
|
+
isFederatedMode
|
|
43
|
+
? undefined
|
|
44
|
+
: documentPath && hasSharedParent(documentPath)
|
|
45
|
+
}
|
|
36
46
|
isOwner={isOwner(document._id)}
|
|
37
47
|
link={getSharingLink(document._id)}
|
|
38
48
|
onRevoke={revoke}
|
|
39
49
|
onRevokeSelf={revokeSelf}
|
|
40
50
|
onShare={share}
|
|
41
51
|
permissions={getDocumentPermissions(document._id)}
|
|
42
|
-
recipients={
|
|
52
|
+
recipients={recipients}
|
|
43
53
|
sharing={getSharingForSelf(document._id)}
|
|
44
54
|
{...rest}
|
|
45
55
|
/>
|
|
@@ -47,7 +57,50 @@ export const EditableSharingModal = ({ document, ...rest }) => {
|
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
EditableSharingModal.propTypes = {
|
|
50
|
-
document: PropTypes.object
|
|
60
|
+
document: PropTypes.object,
|
|
61
|
+
recipients: PropTypes.array
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const EditableSharingModalWrapper = ({ document, ...rest }) => {
|
|
65
|
+
const log = minilog('EditableSharingModal')
|
|
66
|
+
const isFederatedMode = flag('drive.federated-shared-folder.enabled')
|
|
67
|
+
const {
|
|
68
|
+
getRecipients,
|
|
69
|
+
getEffectiveRecipients,
|
|
70
|
+
fetchEffectiveRecipients,
|
|
71
|
+
invalidateEffectiveRecipients
|
|
72
|
+
} = useSharingContext()
|
|
73
|
+
|
|
74
|
+
const fileId = document._id || document.id
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (isFederatedMode && fileId) {
|
|
78
|
+
fetchEffectiveRecipients(fileId, document.driveId).catch(log.error)
|
|
79
|
+
}
|
|
80
|
+
return () => {
|
|
81
|
+
if (fileId) {
|
|
82
|
+
invalidateEffectiveRecipients(fileId)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}, [
|
|
86
|
+
fileId,
|
|
87
|
+
document.driveId,
|
|
88
|
+
isFederatedMode,
|
|
89
|
+
fetchEffectiveRecipients,
|
|
90
|
+
invalidateEffectiveRecipients
|
|
91
|
+
])
|
|
92
|
+
|
|
93
|
+
const recipients = isFederatedMode
|
|
94
|
+
? getEffectiveRecipients(fileId)
|
|
95
|
+
: getRecipients(fileId)
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<EditableSharingModal
|
|
99
|
+
document={document}
|
|
100
|
+
recipients={recipients}
|
|
101
|
+
{...rest}
|
|
102
|
+
/>
|
|
103
|
+
)
|
|
51
104
|
}
|
|
52
105
|
|
|
53
|
-
export default
|
|
106
|
+
export default EditableSharingModalWrapper
|
|
@@ -6,10 +6,10 @@ import { useLocation } from 'react-router'
|
|
|
6
6
|
import flag from 'cozy-flags'
|
|
7
7
|
|
|
8
8
|
import EditableSharingModal from './EditableSharingModal'
|
|
9
|
-
import
|
|
9
|
+
import SharingDetailsModal from './SharingDetailsModal'
|
|
10
10
|
import withLocales from '../../hoc/withLocales'
|
|
11
11
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
12
|
-
import
|
|
12
|
+
import FederatedFolderModal from '../FederatedFolder/FederatedFolderModal'
|
|
13
13
|
|
|
14
14
|
export const ShareModal = withLocales(props => {
|
|
15
15
|
const location = useLocation?.()
|
|
@@ -75,8 +75,6 @@ export const ShareModal = ({
|
|
|
75
75
|
)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export default ShareModal
|
|
79
|
-
|
|
80
78
|
ShareModal.propTypes = {
|
|
81
79
|
autoOpenShareRestriction: PropTypes.bool,
|
|
82
80
|
createContact: PropTypes.func.isRequired,
|
|
@@ -100,3 +98,5 @@ ShareModal.propTypes = {
|
|
|
100
98
|
recipientConfirmationDialogContent: PropTypes.func
|
|
101
99
|
})
|
|
102
100
|
}
|
|
101
|
+
|
|
102
|
+
export default ShareModal
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import cx from 'classnames'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
5
|
+
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
|
|
6
|
+
import { useI18n } from 'twake-i18n'
|
|
7
|
+
|
|
8
|
+
import AntivirusAlert from './AntivirusAlert'
|
|
9
|
+
import { default as DumbShareByEmail } from './ShareByEmail'
|
|
10
|
+
import WhoHasAccess from './WhoHasAccess'
|
|
11
|
+
import styles from '../styles/share.styl'
|
|
12
|
+
|
|
13
|
+
const SharingContent = ({
|
|
14
|
+
document,
|
|
15
|
+
documentType,
|
|
16
|
+
hasSharedParent,
|
|
17
|
+
isOwner,
|
|
18
|
+
onRevoke,
|
|
19
|
+
onRevokeSelf,
|
|
20
|
+
recipients,
|
|
21
|
+
sharing,
|
|
22
|
+
showShareByEmail,
|
|
23
|
+
showShareOnlyByLink,
|
|
24
|
+
showWhoHasAccess,
|
|
25
|
+
recipientsToBeConfirmed,
|
|
26
|
+
verifyRecipient,
|
|
27
|
+
link,
|
|
28
|
+
permissions,
|
|
29
|
+
pendingRecipients,
|
|
30
|
+
onPendingRecipientsChange,
|
|
31
|
+
selectedOption,
|
|
32
|
+
onSelectedOptionChange
|
|
33
|
+
}) => {
|
|
34
|
+
const { t } = useI18n()
|
|
35
|
+
const { isMobile } = useBreakpoints()
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className={cx(styles['share-modal-content'])}>
|
|
39
|
+
<div className={cx('u-pt-1-half', isMobile ? 'u-ph-1' : 'u-ph-2')}>
|
|
40
|
+
<AntivirusAlert document={document} />
|
|
41
|
+
{showShareOnlyByLink && (
|
|
42
|
+
<div className={styles['share-byemail-onlybylink']}>
|
|
43
|
+
{t(`${documentType}.share.shareByEmail.onlyByLink`, {
|
|
44
|
+
type: t(
|
|
45
|
+
`${documentType}.share.shareByEmail.type.${
|
|
46
|
+
document.type === 'directory' ? 'folder' : 'file'
|
|
47
|
+
}`
|
|
48
|
+
)
|
|
49
|
+
})}{' '}
|
|
50
|
+
<strong>
|
|
51
|
+
{t(
|
|
52
|
+
`${documentType}.share.shareByEmail.${
|
|
53
|
+
hasSharedParent ? 'hasSharedParent' : 'hasSharedChild'
|
|
54
|
+
}`
|
|
55
|
+
)}
|
|
56
|
+
</strong>
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
<Typography variant="h6" className="u-mb-half">
|
|
60
|
+
{t('Share.contacts.addUsers')}
|
|
61
|
+
</Typography>
|
|
62
|
+
{showShareByEmail && (
|
|
63
|
+
<DumbShareByEmail
|
|
64
|
+
currentRecipients={recipients}
|
|
65
|
+
document={document}
|
|
66
|
+
documentType={documentType}
|
|
67
|
+
sharing={sharing}
|
|
68
|
+
pendingRecipients={pendingRecipients}
|
|
69
|
+
onPendingRecipientsChange={onPendingRecipientsChange}
|
|
70
|
+
selectedOption={selectedOption}
|
|
71
|
+
onSelectedOptionChange={onSelectedOptionChange}
|
|
72
|
+
enableCreateContact
|
|
73
|
+
/>
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
{showWhoHasAccess && (
|
|
77
|
+
<WhoHasAccess
|
|
78
|
+
document={document}
|
|
79
|
+
documentType={documentType}
|
|
80
|
+
isOwner={isOwner}
|
|
81
|
+
onRevoke={onRevoke}
|
|
82
|
+
onRevokeSelf={onRevokeSelf}
|
|
83
|
+
recipients={recipients}
|
|
84
|
+
recipientsToBeConfirmed={recipientsToBeConfirmed}
|
|
85
|
+
verifyRecipient={verifyRecipient}
|
|
86
|
+
link={link}
|
|
87
|
+
permissions={permissions}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
</div>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export default SharingContent
|