cozy-sharing 40.1.6 → 40.1.8

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 (107) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/components/FederatedFolder/FederatedFolderModal.js +10 -12
  3. package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +2 -2
  4. package/dist/components/Recipient/DowngradePermissionConfirmDialog.js +3 -12
  5. package/dist/components/Recipient/GroupRecipient.js +1 -4
  6. package/dist/components/Recipient/GroupRecipient.stories.js +3 -1
  7. package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +1 -4
  8. package/dist/components/Recipient/GroupRecipientPermissions.js +5 -8
  9. package/dist/components/Recipient/GroupRecipientPermissions.stories.js +2 -0
  10. package/dist/components/Recipient/LinkRecipient.js +2 -6
  11. package/dist/components/Recipient/LinkRecipient.stories.js +4 -0
  12. package/dist/components/Recipient/LinkRecipientPermissions.js +13 -12
  13. package/dist/components/Recipient/LinkRecipientPermissions.stories.js +5 -1
  14. package/dist/components/Recipient/MemberRecipient.js +7 -6
  15. package/dist/components/Recipient/MemberRecipient.spec.js +7 -12
  16. package/dist/components/Recipient/MemberRecipientPermissions.js +28 -13
  17. package/dist/components/Recipient/MemberRecipientPermissions.spec.js +5 -14
  18. package/dist/components/Recipient/MemberRecipientPermissions.stories.js +2 -1
  19. package/dist/components/Recipient/OwnerRecipient.js +4 -17
  20. package/dist/components/Recipient/OwnerRecipient.stories.js +3 -1
  21. package/dist/components/Recipient/OwnerRecipientDefaultLite.js +1 -1
  22. package/dist/components/Recipient/PermissionTypeMenu.js +32 -155
  23. package/dist/components/Recipient/PermissionTypeMenuWrapper.js +37 -0
  24. package/dist/components/Recipient/{PermissionTypeMenu.spec.js → PermissionTypeMenuWrapper.spec.js} +2 -2
  25. package/dist/components/Recipient/RecipientList.js +10 -0
  26. package/dist/components/Recipient/RecipientList.stories.js +3 -0
  27. package/dist/components/{ShareRecipientsInput.js → ShareAutosuggestWrapper.js} +12 -54
  28. package/dist/components/{ShareRecipientsInput.spec.js → ShareAutosuggestWrapper.spec.js} +3 -3
  29. package/dist/components/ShareByEmail.js +2 -2
  30. package/dist/components/ShareDialogCozyToCozy.js +20 -19
  31. package/dist/components/ShareDialogCozyToCozy.spec.js +3 -0
  32. package/dist/components/ShareDialogOnlyByLink.js +3 -5
  33. package/dist/components/ShareDialogOnlyByLink.spec.js +0 -1
  34. package/dist/components/ShareModal/SharingDetailsModal.js +2 -2
  35. package/dist/components/SharedDrive/EditSharedDriveModal.js +11 -10
  36. package/dist/components/SharedDrive/useSharedDrive.js +8 -11
  37. package/dist/components/SharingBanner/components/PublicBanner.js +8 -6
  38. package/dist/components/SharingBanner/components/PublicBanner.spec.js +1 -9
  39. package/dist/components/SharingBanner/components/SharingBanner.js +3 -0
  40. package/dist/components/SharingBanner/index.js +3 -0
  41. package/dist/components/SharingContent.js +3 -5
  42. package/dist/components/WhoHasAccess.js +27 -11
  43. package/dist/components/WhoHasAccessWrapper.js +122 -0
  44. package/dist/helpers/contacts.js +79 -1
  45. package/dist/helpers/contacts.spec.js +122 -1
  46. package/dist/helpers/recipients.js +46 -0
  47. package/dist/helpers/recipients.spec.js +89 -0
  48. package/dist/hooks/useMemberPermissionType.js +191 -0
  49. package/dist/hooks/useResolveRecipients.js +53 -0
  50. package/dist/hooks/useResolveRecipients.spec.js +140 -0
  51. package/dist/index.js +1 -1
  52. package/docs/share-modal-architecture.md +2 -2
  53. package/package.json +3 -3
  54. package/src/components/FederatedFolder/FederatedFolderModal.jsx +6 -12
  55. package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +1 -0
  56. package/src/components/Recipient/DowngradePermissionConfirmDialog.jsx +3 -10
  57. package/src/components/Recipient/GroupRecipient.jsx +1 -5
  58. package/src/components/Recipient/GroupRecipient.stories.jsx +3 -1
  59. package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +1 -4
  60. package/src/components/Recipient/GroupRecipientPermissions.jsx +5 -5
  61. package/src/components/Recipient/GroupRecipientPermissions.stories.jsx +2 -0
  62. package/src/components/Recipient/LinkRecipient.jsx +2 -4
  63. package/src/components/Recipient/LinkRecipient.stories.jsx +4 -0
  64. package/src/components/Recipient/LinkRecipientPermissions.jsx +16 -12
  65. package/src/components/Recipient/LinkRecipientPermissions.stories.jsx +5 -1
  66. package/src/components/Recipient/MemberRecipient.jsx +4 -4
  67. package/src/components/Recipient/MemberRecipient.spec.jsx +7 -10
  68. package/src/components/Recipient/MemberRecipientPermissions.jsx +29 -13
  69. package/src/components/Recipient/MemberRecipientPermissions.spec.jsx +5 -11
  70. package/src/components/Recipient/MemberRecipientPermissions.stories.jsx +2 -1
  71. package/src/components/Recipient/OwnerRecipient.jsx +4 -17
  72. package/src/components/Recipient/OwnerRecipient.stories.jsx +1 -1
  73. package/src/components/Recipient/OwnerRecipientDefaultLite.jsx +1 -1
  74. package/src/components/Recipient/PermissionTypeMenu.jsx +21 -81
  75. package/src/components/Recipient/PermissionTypeMenuWrapper.jsx +32 -0
  76. package/src/components/Recipient/{PermissionTypeMenu.spec.jsx → PermissionTypeMenuWrapper.spec.jsx} +2 -2
  77. package/src/components/Recipient/RecipientList.jsx +10 -0
  78. package/src/components/Recipient/RecipientList.stories.jsx +3 -0
  79. package/src/components/{ShareRecipientsInput.jsx → ShareAutosuggestWrapper.jsx} +14 -65
  80. package/src/components/{ShareRecipientsInput.spec.jsx → ShareAutosuggestWrapper.spec.jsx} +3 -3
  81. package/src/components/ShareByEmail.jsx +2 -2
  82. package/src/components/ShareDialogCozyToCozy.jsx +10 -11
  83. package/src/components/ShareDialogCozyToCozy.spec.jsx +1 -0
  84. package/src/components/ShareDialogOnlyByLink.jsx +2 -4
  85. package/src/components/ShareDialogOnlyByLink.spec.jsx +0 -1
  86. package/src/components/ShareModal/SharingDetailsModal.jsx +2 -2
  87. package/src/components/SharedDrive/EditSharedDriveModal.jsx +6 -11
  88. package/src/components/SharedDrive/useSharedDrive.js +4 -11
  89. package/src/components/SharingBanner/components/PublicBanner.jsx +6 -6
  90. package/src/components/SharingBanner/components/PublicBanner.spec.jsx +1 -8
  91. package/src/components/SharingBanner/components/SharingBanner.jsx +7 -1
  92. package/src/components/SharingBanner/index.jsx +4 -0
  93. package/src/components/SharingContent.jsx +2 -4
  94. package/src/components/WhoHasAccess.jsx +26 -12
  95. package/src/components/WhoHasAccessWrapper.jsx +117 -0
  96. package/src/helpers/contacts.js +83 -0
  97. package/src/helpers/contacts.spec.js +78 -1
  98. package/src/helpers/recipients.js +44 -0
  99. package/src/helpers/recipients.spec.js +82 -0
  100. package/src/hooks/useMemberPermissionType.js +110 -0
  101. package/src/hooks/useResolveRecipients.js +38 -0
  102. package/src/hooks/useResolveRecipients.spec.js +70 -0
  103. package/src/index.jsx +1 -1
  104. package/dist/components/Recipient/OwnerRecipientDefault.js +0 -27
  105. package/dist/components/Recipient/OwnerRecipientDefault.stories.js +0 -10
  106. package/src/components/Recipient/OwnerRecipientDefault.jsx +0 -37
  107. package/src/components/Recipient/OwnerRecipientDefault.stories.jsx +0 -13
@@ -4,7 +4,7 @@ import React from 'react'
4
4
  import flag from 'cozy-flags'
5
5
  import { useI18n } from 'twake-i18n'
6
6
 
7
- import ShareRecipientsInput from './ShareRecipientsInput'
7
+ import ShareAutosuggestWrapper from './ShareAutosuggestWrapper'
8
8
  import ShareTypeSelect from './Sharetypeselect'
9
9
  import {
10
10
  mergeRecipients,
@@ -60,7 +60,7 @@ export const ShareByEmail = ({
60
60
  return (
61
61
  <div className={styles['coz-form-group']}>
62
62
  <div className={styles['coz-form']}>
63
- <ShareRecipientsInput
63
+ <ShareAutosuggestWrapper
64
64
  placeholder={
65
65
  pendingRecipients.length === 0
66
66
  ? t(`${documentType}.share.shareByEmail.emailPlaceholder`)
@@ -1,7 +1,6 @@
1
1
  import PropTypes from 'prop-types'
2
2
  import React, { useCallback, useMemo, useState } from 'react'
3
3
 
4
- import { useClient } from 'cozy-client'
5
4
  import Button from 'cozy-ui/transpiled/react/Buttons'
6
5
  import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
7
6
  import { useI18n } from 'twake-i18n'
@@ -10,10 +9,10 @@ import { default as DumbShareByLink } from './ShareByLink'
10
9
  import ShareDialogTwoStepsConfirmationContainer from './ShareDialogTwoStepsConfirmationContainer'
11
10
  import { ShareRecipientsLimitModal } from './ShareRecipientsLimitModal'
12
11
  import SharingContent from './SharingContent'
13
- import { getOrCreateFromArray } from '../helpers/contacts'
14
12
  import { hasReachRecipientsLimit } from '../helpers/recipients'
15
13
  import { getErrorMessage, getSuccessMessage } from '../helpers/share'
16
14
  import { usePendingRecipients } from '../hooks/usePendingRecipients'
15
+ import { useResolveRecipients } from '../hooks/useResolveRecipients'
17
16
  import { useSharingContext } from '../hooks/useSharingContext'
18
17
 
19
18
  const SharingTitleFunction = ({ documentType, document }) =>
@@ -39,7 +38,7 @@ const ShareDialogCozyToCozy = ({
39
38
  ...props
40
39
  }) => {
41
40
  const { t } = useI18n()
42
- const client = useClient()
41
+ const resolveRecipients = useResolveRecipients()
43
42
  const { showAlert } = useAlert()
44
43
  const { getSharingLink } = useSharingContext()
45
44
 
@@ -67,13 +66,13 @@ const ShareDialogCozyToCozy = ({
67
66
 
68
67
  setSubmitting(true)
69
68
  try {
70
- const contacts = await getOrCreateFromArray(
71
- client,
72
- pendingRecipients,
73
- createContact
74
- )
75
- const readWriteRecipients = selectedOption === 'readOnly' ? [] : contacts
76
- const readOnlyRecipients = selectedOption === 'readOnly' ? contacts : []
69
+ const { recipients: readWriteRecipients, readOnlyRecipients } =
70
+ await resolveRecipients(
71
+ pendingRecipients,
72
+ selectedOption,
73
+ createContact
74
+ )
75
+ const contacts = [...readWriteRecipients, ...readOnlyRecipients]
77
76
 
78
77
  await onShare({
79
78
  document,
@@ -109,7 +108,7 @@ const ShareDialogCozyToCozy = ({
109
108
  }, [
110
109
  pendingRecipients,
111
110
  selectedOption,
112
- client,
111
+ resolveRecipients,
113
112
  showAlert,
114
113
  t,
115
114
  recipients,
@@ -17,6 +17,7 @@ jest.mock('cozy-client', () => ({
17
17
  jest.mock('../hooks/useSharingContext', () => ({
18
18
  useSharingContext: () => ({
19
19
  getSharingLink: jest.fn(() => null),
20
+ getDocumentPermissions: jest.fn(() => []),
20
21
  updateSharingMemberType: jest.fn(),
21
22
  isOrgSharedDrive: jest.fn(() => false)
22
23
  })
@@ -8,7 +8,7 @@ import { useI18n } from 'twake-i18n'
8
8
 
9
9
  import AntivirusAlert from './AntivirusAlert'
10
10
  import { default as DumbShareByLink } from './ShareByLink'
11
- import WhoHasAccess from './WhoHasAccess'
11
+ import WhoHasAccessWrapper from './WhoHasAccessWrapper'
12
12
  import { useSharingContext } from '../hooks/useSharingContext'
13
13
 
14
14
  const ShareDialogOnlyByLink = ({
@@ -19,7 +19,6 @@ const ShareDialogOnlyByLink = ({
19
19
  document,
20
20
  documentType,
21
21
  onClose,
22
- permissions,
23
22
  showGenerateLinkButton,
24
23
  autoOpenShareRestriction
25
24
  }) => {
@@ -46,7 +45,7 @@ const ShareDialogOnlyByLink = ({
46
45
  >
47
46
  {t('Share.contacts.whoHasAccess')}
48
47
  </Typography>
49
- <WhoHasAccess
48
+ <WhoHasAccessWrapper
50
49
  document={document}
51
50
  documentType={documentType}
52
51
  isOwner={isOwner}
@@ -54,7 +53,6 @@ const ShareDialogOnlyByLink = ({
54
53
  onRevokeSelf={onRevokeSelf}
55
54
  recipients={recipients}
56
55
  link={displayedLink}
57
- permissions={permissions}
58
56
  />
59
57
  <div
60
58
  className={cx(
@@ -33,7 +33,6 @@ describe('ShareDialogOnlyByLink', () => {
33
33
  onClose={jest.fn()}
34
34
  onRevoke={jest.fn()}
35
35
  onRevokeSelf={jest.fn()}
36
- permissions={[]}
37
36
  recipients={[]}
38
37
  />
39
38
  </AppLike>
@@ -7,7 +7,7 @@ import { useI18n } from 'twake-i18n'
7
7
  import { useSharingContext } from '../../hooks/useSharingContext'
8
8
  import styles from '../../styles/share.styl'
9
9
  import ShareByLink from '../ShareByLink'
10
- import WhoHasAccess from '../WhoHasAccess'
10
+ import WhoHasAccessWrapper from '../WhoHasAccessWrapper'
11
11
 
12
12
  export const SharingDetailsModal = ({
13
13
  recipients,
@@ -34,7 +34,7 @@ export const SharingDetailsModal = ({
34
34
  title={t(`${documentType}.share.details.title`)}
35
35
  content={
36
36
  <div className={styles['share-modal-content']}>
37
- <WhoHasAccess
37
+ <WhoHasAccessWrapper
38
38
  canManageMembers={false}
39
39
  canManageLink={isSharedDrive}
40
40
  isSharedDrive={isSharedDrive}
@@ -10,13 +10,13 @@ import { useSubmitWithLoader } from 'cozy-ui/transpiled/react/hooks/useSubmitWit
10
10
  import { useI18n } from 'twake-i18n'
11
11
 
12
12
  import SharedDriveHeader from './SharedDriveHeader'
13
- import { getOrCreateFromArray } from '../../helpers/contacts'
14
13
  import withLocales from '../../hoc/withLocales'
15
14
  import { usePendingRecipients } from '../../hooks/usePendingRecipients'
15
+ import { useResolveRecipients } from '../../hooks/useResolveRecipients'
16
16
  import { useSharingContext } from '../../hooks/useSharingContext'
17
17
  import styles from '../../styles/share.styl'
18
18
  import { default as DumbShareByEmail } from '../ShareByEmail'
19
- import WhoHasAccess from '../WhoHasAccess'
19
+ import WhoHasAccessWrapper from '../WhoHasAccessWrapper'
20
20
 
21
21
  export const EditSharedDriveModal = withLocales(({ onClose, document }) => {
22
22
  const client = useClient()
@@ -29,18 +29,13 @@ export const EditSharedDriveModal = withLocales(({ onClose, document }) => {
29
29
  setSelectedOption
30
30
  } = usePendingRecipients()
31
31
  const { onSubmit, isLoading } = useSubmitWithLoader()
32
+ const resolveRecipients = useResolveRecipients()
32
33
 
33
34
  const [driveName, setDriveName] = useState(document.name)
34
35
 
35
36
  const onSave = async () => {
36
- // We add contacts
37
- const contacts = await getOrCreateFromArray(
38
- client,
39
- pendingRecipients,
40
- contact => client.create('io.cozy.contacts', contact)
41
- )
42
- const readWriteRecipients = selectedOption === 'readOnly' ? [] : contacts
43
- const readOnlyRecipients = selectedOption === 'readOnly' ? contacts : []
37
+ const { recipients: readWriteRecipients, readOnlyRecipients } =
38
+ await resolveRecipients(pendingRecipients, selectedOption)
44
39
 
45
40
  await share({
46
41
  document: document,
@@ -100,7 +95,7 @@ export const EditSharedDriveModal = withLocales(({ onClose, document }) => {
100
95
  onSelectedOptionChange={setSelectedOption}
101
96
  />
102
97
  </div>
103
- <WhoHasAccess
98
+ <WhoHasAccessWrapper
104
99
  isOwner
105
100
  isSharedDrive
106
101
  showOwner={false}
@@ -2,12 +2,12 @@ import { useState } from 'react'
2
2
 
3
3
  import { useClient } from 'cozy-client'
4
4
 
5
- import { getOrCreateFromArray } from '../../helpers/contacts'
6
5
  import { usePendingRecipients } from '../../hooks/usePendingRecipients'
7
- import { DOCTYPE_CONTACTS } from '../../models'
6
+ import { useResolveRecipients } from '../../hooks/useResolveRecipients'
8
7
 
9
8
  export const useSharedDrive = () => {
10
9
  const client = useClient()
10
+ const resolveRecipients = useResolveRecipients()
11
11
 
12
12
  const [sharedDriveName, setSharedDriveName] = useState('')
13
13
  const {
@@ -21,16 +21,9 @@ export const useSharedDrive = () => {
21
21
  setSharedDriveName(event.target.value)
22
22
  }
23
23
 
24
- const createContact = contact => client.create(DOCTYPE_CONTACTS, contact)
25
-
26
24
  const onCreate = async () => {
27
- const contacts = await getOrCreateFromArray(
28
- client,
29
- pendingRecipients,
30
- createContact
31
- )
32
- const readWriteRecipients = selectedOption === 'readOnly' ? [] : contacts
33
- const readOnlyRecipients = selectedOption === 'readOnly' ? contacts : []
25
+ const { recipients: readWriteRecipients, readOnlyRecipients } =
26
+ await resolveRecipients(pendingRecipients, selectedOption)
34
27
 
35
28
  await client.collection('io.cozy.sharings').createSharedDrive({
36
29
  name: sharedDriveName,
@@ -3,7 +3,6 @@ import React from 'react'
3
3
  import snarkdown from 'snarkdown'
4
4
 
5
5
  import { Icon, SyncCozy, ToTheCloud } from '@linagora/twake-icons'
6
- import { useClient } from 'cozy-client'
7
6
  import flag from 'cozy-flags'
8
7
  import Alert from 'cozy-ui/transpiled/react/Alert'
9
8
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
@@ -17,11 +16,9 @@ import styles from '../../../styles/publicBanner.styl'
17
16
  const getPublicNameFromSharing = sharing =>
18
17
  sharing.attributes.members[0].public_name
19
18
 
20
- const PublicBannerCozyToCozyContent = ({ sharing }) => {
19
+ const PublicBannerCozyToCozyContent = ({ sharing, avatarURL }) => {
21
20
  const { t } = useI18n()
22
- const client = useClient()
23
21
  const name = getPublicNameFromSharing(sharing)
24
- const avatarURL = `${client.options.uri}/public/avatar?fallback=initials`
25
22
 
26
23
  const withAvatar = snarkdown(
27
24
  t('Share.banner.shared_from', {
@@ -43,13 +40,15 @@ const PublicBannerCozyToCozyContent = ({ sharing }) => {
43
40
  )
44
41
  }
45
42
  PublicBannerCozyToCozyContent.propTypes = {
46
- sharing: PropTypes.object.isRequired
43
+ sharing: PropTypes.object.isRequired,
44
+ avatarURL: PropTypes.string.isRequired
47
45
  }
48
46
 
49
47
  const openExternalLink = url => (window.location = url)
50
48
 
51
49
  const SharingBannerCozyToCozy = ({
52
50
  sharing,
51
+ avatarURL,
53
52
  isSharingShortcutCreated,
54
53
  addSharingLink,
55
54
  onClose
@@ -90,7 +89,7 @@ const SharingBannerCozyToCozy = ({
90
89
  </>
91
90
  }
92
91
  >
93
- <PublicBannerCozyToCozyContent sharing={sharing} />
92
+ <PublicBannerCozyToCozyContent sharing={sharing} avatarURL={avatarURL} />
94
93
  </Alert>
95
94
  )
96
95
  }
@@ -162,6 +161,7 @@ SharingBannerByLink.propTypes = {
162
161
  }
163
162
  SharingBannerCozyToCozy.propTypes = {
164
163
  sharing: PropTypes.object.isRequired,
164
+ avatarURL: PropTypes.string.isRequired,
165
165
  isSharingShortcutCreated: PropTypes.bool.isRequired,
166
166
  addSharingLink: PropTypes.string.isRequired,
167
167
  onClose: PropTypes.func.isRequired
@@ -1,22 +1,14 @@
1
1
  import { render } from '@testing-library/react'
2
2
  import React from 'react'
3
3
 
4
- import { useClient } from 'cozy-client'
5
4
  import { BreakpointsProvider } from 'cozy-ui/transpiled/react/providers/Breakpoints'
6
5
  import { useI18n } from 'twake-i18n'
7
6
 
8
7
  import { SharingBannerCozyToCozy } from './PublicBanner'
9
8
 
10
9
  jest.mock('twake-i18n')
11
- jest.mock('cozy-client')
12
10
 
13
11
  describe('PublicBanner', () => {
14
- beforeEach(() => {
15
- useClient.mockReturnValue({
16
- options: { uri: 'http://cozy.localhost:8080' }
17
- })
18
- })
19
-
20
12
  it('should not add dangerous html', () => {
21
13
  // Given
22
14
  useI18n.mockReturnValue({
@@ -35,6 +27,7 @@ describe('PublicBanner', () => {
35
27
  <BreakpointsProvider>
36
28
  <SharingBannerCozyToCozy
37
29
  sharing={sharing}
30
+ avatarURL="http://cozy.localhost:8080/public/avatar?fallback=initials"
38
31
  isSharingShortcutCreated={true}
39
32
  addSharingLink="discoveryLink"
40
33
  onClose={() => {}}
@@ -3,7 +3,11 @@ import React, { useState, useCallback } from 'react'
3
3
 
4
4
  import { SharingBannerByLink, SharingBannerCozyToCozy } from './PublicBanner'
5
5
 
6
- export const SharingBanner = ({ sharingInfos, hideCreateCozyAction }) => {
6
+ export const SharingBanner = ({
7
+ sharingInfos,
8
+ avatarURL,
9
+ hideCreateCozyAction
10
+ }) => {
7
11
  const [isOpened, setIsOpened] = useState(true)
8
12
  const onClose = useCallback(() => setIsOpened(false), [setIsOpened])
9
13
 
@@ -22,6 +26,7 @@ export const SharingBanner = ({ sharingInfos, hideCreateCozyAction }) => {
22
26
  <SharingBannerCozyToCozy
23
27
  isSharingShortcutCreated={isSharingShortcutCreated}
24
28
  sharing={sharing}
29
+ avatarURL={avatarURL}
25
30
  addSharingLink={addSharingLink}
26
31
  onClose={onClose}
27
32
  />
@@ -31,6 +36,7 @@ export const SharingBanner = ({ sharingInfos, hideCreateCozyAction }) => {
31
36
 
32
37
  SharingBanner.propTypes = {
33
38
  sharingInfos: PropTypes.object,
39
+ avatarURL: PropTypes.string,
34
40
  hideCreateCozyAction: PropTypes.bool
35
41
  }
36
42
 
@@ -1,15 +1,19 @@
1
1
  import PropTypes from 'prop-types'
2
2
  import React from 'react'
3
3
 
4
+ import { useClient } from 'cozy-client'
5
+
4
6
  import { SharingBanner } from './components/SharingBanner'
5
7
  import { useSharingInfos } from './hooks/useSharingInfos'
6
8
  import withLocales from '../../hoc/withLocales'
7
9
 
8
10
  const Plugin = ({ previewPath, hideCreateCozyAction }) => {
11
+ const client = useClient()
9
12
  const sharingInfos = useSharingInfos(previewPath)
10
13
  return (
11
14
  <SharingBanner
12
15
  sharingInfos={sharingInfos}
16
+ avatarURL={`${client.options.uri}/public/avatar?fallback=initials`}
13
17
  hideCreateCozyAction={hideCreateCozyAction}
14
18
  />
15
19
  )
@@ -7,7 +7,7 @@ import { useI18n } from 'twake-i18n'
7
7
 
8
8
  import AntivirusAlert from './AntivirusAlert'
9
9
  import { default as DumbShareByEmail } from './ShareByEmail'
10
- import WhoHasAccess from './WhoHasAccess'
10
+ import WhoHasAccessWrapper from './WhoHasAccessWrapper'
11
11
  import styles from '../styles/share.styl'
12
12
 
13
13
  const SharingContent = ({
@@ -25,7 +25,6 @@ const SharingContent = ({
25
25
  recipientsToBeConfirmed,
26
26
  verifyRecipient,
27
27
  link,
28
- permissions,
29
28
  pendingRecipients,
30
29
  onPendingRecipientsChange,
31
30
  selectedOption,
@@ -74,7 +73,7 @@ const SharingContent = ({
74
73
  )}
75
74
  </div>
76
75
  {showWhoHasAccess && (
77
- <WhoHasAccess
76
+ <WhoHasAccessWrapper
78
77
  document={document}
79
78
  documentType={documentType}
80
79
  isOwner={isOwner}
@@ -84,7 +83,6 @@ const SharingContent = ({
84
83
  recipientsToBeConfirmed={recipientsToBeConfirmed}
85
84
  verifyRecipient={verifyRecipient}
86
85
  link={link}
87
- permissions={permissions}
88
86
  />
89
87
  )}
90
88
  </div>
@@ -8,7 +8,6 @@ import LinkRecipient from './Recipient/LinkRecipient'
8
8
  import OwnerRecipient from './Recipient/OwnerRecipient'
9
9
  import { RecipientList } from './Recipient/RecipientList'
10
10
  import { usePrevious } from '../helpers/hooks'
11
- import { useSharingContext } from '../hooks/useSharingContext'
12
11
 
13
12
  /**
14
13
  * Displays a warning if some contacts are waiting for confirmation of their sharing
@@ -35,6 +34,9 @@ const WhoHasAccess = ({
35
34
  canManageMembers = !isReadOnly,
36
35
  canManageLink = canManageMembers,
37
36
  showOwner = true,
37
+ owner,
38
+ isInsideSharedParent = false,
39
+ sharedParentName,
38
40
  recipients,
39
41
  recipientsToBeConfirmed = [],
40
42
  document,
@@ -42,15 +44,17 @@ const WhoHasAccess = ({
42
44
  className,
43
45
  onRevoke,
44
46
  onRevokeSelf,
45
- onSetType,
47
+ onRevokeGroup,
48
+ onLeaveGroup,
49
+ onSetMemberType,
50
+ onUpdateLinkPermissions,
51
+ onRevokeLink,
46
52
  verifyRecipient,
47
53
  link,
48
54
  permissions
49
55
  }) => {
50
56
  const previousLink = usePrevious(link)
51
57
  const linkHasBeenJustCreated = link && previousLink === null
52
- const { isOrgSharedDrive } = useSharingContext()
53
- const isOrgDrive = isOrgSharedDrive(document?._id)
54
58
 
55
59
  return (
56
60
  <div className={className}>
@@ -66,16 +70,13 @@ const WhoHasAccess = ({
66
70
  onRevoke={onRevoke}
67
71
  onRevokeSelf={onRevokeSelf}
68
72
  permissions={permissions}
73
+ onUpdateLinkPermissions={onUpdateLinkPermissions}
74
+ onRevokeLink={onRevokeLink}
69
75
  fadeIn={linkHasBeenJustCreated}
70
76
  />
71
77
  )}
72
78
 
73
- {showOwner && (
74
- <OwnerRecipient
75
- recipients={recipients}
76
- isOrgSharedDrive={isOrgDrive}
77
- />
78
- )}
79
+ {showOwner && <OwnerRecipient owner={owner} />}
79
80
 
80
81
  <RecipientList
81
82
  recipients={recipients}
@@ -86,9 +87,13 @@ const WhoHasAccess = ({
86
87
  isSharedDrive={isSharedDrive}
87
88
  document={document}
88
89
  documentType={documentType}
90
+ isInsideSharedParent={isInsideSharedParent}
91
+ sharedParentName={sharedParentName}
89
92
  onRevoke={onRevoke}
90
93
  onRevokeSelf={onRevokeSelf}
91
- onSetType={onSetType}
94
+ onRevokeGroup={onRevokeGroup}
95
+ onLeaveGroup={onLeaveGroup}
96
+ onSetMemberType={onSetMemberType}
92
97
  verifyRecipient={verifyRecipient}
93
98
  />
94
99
  </List>
@@ -102,6 +107,9 @@ WhoHasAccess.propTypes = {
102
107
  canManageMembers: PropTypes.bool,
103
108
  canManageLink: PropTypes.bool,
104
109
  showOwner: PropTypes.bool,
110
+ owner: PropTypes.object,
111
+ isInsideSharedParent: PropTypes.bool,
112
+ sharedParentName: PropTypes.string,
105
113
  recipients: PropTypes.array.isRequired,
106
114
  recipientsToBeConfirmed: PropTypes.arrayOf(
107
115
  PropTypes.shape({
@@ -112,6 +120,12 @@ WhoHasAccess.propTypes = {
112
120
  documentType: PropTypes.string.isRequired,
113
121
  onRevoke: PropTypes.func.isRequired,
114
122
  onRevokeSelf: PropTypes.func,
115
- verifyRecipient: PropTypes.func
123
+ onRevokeGroup: PropTypes.func.isRequired,
124
+ onLeaveGroup: PropTypes.func.isRequired,
125
+ onSetMemberType: PropTypes.func.isRequired,
126
+ onUpdateLinkPermissions: PropTypes.func.isRequired,
127
+ onRevokeLink: PropTypes.func.isRequired,
128
+ verifyRecipient: PropTypes.func,
129
+ permissions: PropTypes.arrayOf(PropTypes.object)
116
130
  }
117
131
  export default WhoHasAccess
@@ -0,0 +1,117 @@
1
+ import React from 'react'
2
+
3
+ import { useClient, useQuery, hasQueryBeenLoaded } from 'cozy-client'
4
+
5
+ import WhoHasAccess from './WhoHasAccess'
6
+ import { hasMemberActions, markCurrentUser } from '../helpers/recipients'
7
+ import { useMemberPermissionType } from '../hooks/useMemberPermissionType'
8
+ import { useSharingContext } from '../hooks/useSharingContext'
9
+ import { buildInstanceSettingsQuery } from '../queries/queries'
10
+
11
+ // When the owner is not part of a sharing's members (eg. the folder only has
12
+ // a link), there is no per-sharing avatar to reference. The instance's public
13
+ // avatar still holds the owner's picture. fallback=initials makes the stack
14
+ // serve a generated initials avatar (instead of the app icon) when no picture
15
+ // has been uploaded, matching how avatars are rendered everywhere else.
16
+ const OWNER_PUBLIC_AVATAR_PATH = '/public/avatar?fallback=initials'
17
+
18
+ const WhoHasAccessWrapper = ({
19
+ isOwner = false,
20
+ canManageSharing = isOwner,
21
+ isSharedDrive,
22
+ isReadOnly,
23
+ canManageMembers = !isReadOnly,
24
+ canManageLink,
25
+ showOwner = true,
26
+ recipients,
27
+ recipientsToBeConfirmed = [],
28
+ document,
29
+ documentType,
30
+ className,
31
+ onRevoke,
32
+ onRevokeSelf,
33
+ verifyRecipient,
34
+ link
35
+ }) => {
36
+ const client = useClient()
37
+ const {
38
+ isOrgSharedDrive,
39
+ getDocumentPermissions,
40
+ updateDocumentPermissions,
41
+ revokeSharingLink,
42
+ revokeGroup,
43
+ revokeSelf
44
+ } = useSharingContext()
45
+
46
+ const instanceUri = client.options.uri
47
+ const markedRecipients = markCurrentUser(recipients, instanceUri)
48
+ const hasMemberMenus = markedRecipients.some(
49
+ recipient =>
50
+ !recipient.members &&
51
+ !recipientsToBeConfirmed.some(user => user.email === recipient.email) &&
52
+ hasMemberActions({
53
+ status: recipient.status,
54
+ isCurrentUser: recipient.isCurrentUser,
55
+ isOwner,
56
+ canManageSharing,
57
+ canManageMembers
58
+ })
59
+ )
60
+ const { isInsideSharedParent, sharedParentName, setMemberType } =
61
+ useMemberPermissionType(document, { shouldFetchPath: hasMemberMenus })
62
+ const ownerRecipient = markedRecipients.find(
63
+ recipient => recipient.status === 'owner'
64
+ )
65
+
66
+ const instanceSettingsQuery = buildInstanceSettingsQuery()
67
+ const instanceSettingsResult = useQuery(instanceSettingsQuery.definition, {
68
+ ...instanceSettingsQuery.options,
69
+ enabled: showOwner && !ownerRecipient
70
+ })
71
+
72
+ const defaultOwner = hasQueryBeenLoaded(instanceSettingsResult)
73
+ ? {
74
+ isOwner: true,
75
+ status: 'owner',
76
+ instance: instanceUri,
77
+ avatarPath: OWNER_PUBLIC_AVATAR_PATH,
78
+ public_name: instanceSettingsResult.data?.attributes?.public_name
79
+ }
80
+ : null
81
+
82
+ const owner = ownerRecipient
83
+ ? { ...ownerRecipient, isOrgSharedDrive: isOrgSharedDrive(document?._id) }
84
+ : defaultOwner
85
+
86
+ return (
87
+ <WhoHasAccess
88
+ isOwner={isOwner}
89
+ canManageSharing={canManageSharing}
90
+ isSharedDrive={isSharedDrive}
91
+ isReadOnly={isReadOnly}
92
+ canManageMembers={canManageMembers}
93
+ canManageLink={canManageLink}
94
+ showOwner={showOwner}
95
+ owner={owner}
96
+ isInsideSharedParent={isInsideSharedParent}
97
+ sharedParentName={sharedParentName}
98
+ recipients={markedRecipients}
99
+ recipientsToBeConfirmed={recipientsToBeConfirmed}
100
+ document={document}
101
+ documentType={documentType}
102
+ className={className}
103
+ onRevoke={onRevoke}
104
+ onRevokeSelf={onRevokeSelf}
105
+ onRevokeGroup={revokeGroup}
106
+ onLeaveGroup={revokeSelf}
107
+ onSetMemberType={setMemberType}
108
+ onUpdateLinkPermissions={updateDocumentPermissions}
109
+ onRevokeLink={revokeSharingLink}
110
+ verifyRecipient={verifyRecipient}
111
+ link={link}
112
+ permissions={getDocumentPermissions(document?._id)}
113
+ />
114
+ )
115
+ }
116
+
117
+ export default WhoHasAccessWrapper