cozy-sharing 40.1.6 → 40.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/components/FederatedFolder/FederatedFolderModal.js +10 -12
  3. package/dist/components/Recipient/DowngradePermissionConfirmDialog.js +3 -12
  4. package/dist/components/Recipient/GroupRecipient.js +1 -4
  5. package/dist/components/Recipient/GroupRecipient.stories.js +3 -1
  6. package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +1 -4
  7. package/dist/components/Recipient/GroupRecipientPermissions.js +5 -8
  8. package/dist/components/Recipient/GroupRecipientPermissions.stories.js +2 -0
  9. package/dist/components/Recipient/LinkRecipient.js +2 -6
  10. package/dist/components/Recipient/LinkRecipient.stories.js +4 -0
  11. package/dist/components/Recipient/LinkRecipientPermissions.js +13 -12
  12. package/dist/components/Recipient/LinkRecipientPermissions.stories.js +5 -1
  13. package/dist/components/Recipient/MemberRecipient.js +7 -6
  14. package/dist/components/Recipient/MemberRecipient.spec.js +7 -12
  15. package/dist/components/Recipient/MemberRecipientPermissions.js +28 -13
  16. package/dist/components/Recipient/MemberRecipientPermissions.spec.js +5 -14
  17. package/dist/components/Recipient/MemberRecipientPermissions.stories.js +2 -1
  18. package/dist/components/Recipient/OwnerRecipient.js +4 -17
  19. package/dist/components/Recipient/OwnerRecipient.stories.js +3 -1
  20. package/dist/components/Recipient/OwnerRecipientDefaultLite.js +1 -1
  21. package/dist/components/Recipient/PermissionTypeMenu.js +32 -155
  22. package/dist/components/Recipient/PermissionTypeMenuWrapper.js +37 -0
  23. package/dist/components/Recipient/{PermissionTypeMenu.spec.js → PermissionTypeMenuWrapper.spec.js} +2 -2
  24. package/dist/components/Recipient/RecipientList.js +10 -0
  25. package/dist/components/Recipient/RecipientList.stories.js +3 -0
  26. package/dist/components/ShareDialogCozyToCozy.js +20 -19
  27. package/dist/components/ShareDialogCozyToCozy.spec.js +3 -0
  28. package/dist/components/ShareDialogOnlyByLink.js +3 -5
  29. package/dist/components/ShareDialogOnlyByLink.spec.js +0 -1
  30. package/dist/components/ShareModal/SharingDetailsModal.js +2 -2
  31. package/dist/components/SharedDrive/EditSharedDriveModal.js +11 -10
  32. package/dist/components/SharedDrive/useSharedDrive.js +8 -11
  33. package/dist/components/SharingContent.js +3 -5
  34. package/dist/components/WhoHasAccess.js +27 -11
  35. package/dist/components/WhoHasAccessWrapper.js +122 -0
  36. package/dist/helpers/recipients.js +46 -0
  37. package/dist/helpers/recipients.spec.js +89 -0
  38. package/dist/hooks/useMemberPermissionType.js +191 -0
  39. package/dist/hooks/useResolveRecipients.js +53 -0
  40. package/dist/hooks/useResolveRecipients.spec.js +140 -0
  41. package/dist/index.js +1 -1
  42. package/package.json +3 -3
  43. package/src/components/FederatedFolder/FederatedFolderModal.jsx +6 -12
  44. package/src/components/Recipient/DowngradePermissionConfirmDialog.jsx +3 -10
  45. package/src/components/Recipient/GroupRecipient.jsx +1 -5
  46. package/src/components/Recipient/GroupRecipient.stories.jsx +3 -1
  47. package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +1 -4
  48. package/src/components/Recipient/GroupRecipientPermissions.jsx +5 -5
  49. package/src/components/Recipient/GroupRecipientPermissions.stories.jsx +2 -0
  50. package/src/components/Recipient/LinkRecipient.jsx +2 -4
  51. package/src/components/Recipient/LinkRecipient.stories.jsx +4 -0
  52. package/src/components/Recipient/LinkRecipientPermissions.jsx +16 -12
  53. package/src/components/Recipient/LinkRecipientPermissions.stories.jsx +5 -1
  54. package/src/components/Recipient/MemberRecipient.jsx +4 -4
  55. package/src/components/Recipient/MemberRecipient.spec.jsx +7 -10
  56. package/src/components/Recipient/MemberRecipientPermissions.jsx +29 -13
  57. package/src/components/Recipient/MemberRecipientPermissions.spec.jsx +5 -11
  58. package/src/components/Recipient/MemberRecipientPermissions.stories.jsx +2 -1
  59. package/src/components/Recipient/OwnerRecipient.jsx +4 -17
  60. package/src/components/Recipient/OwnerRecipient.stories.jsx +1 -1
  61. package/src/components/Recipient/OwnerRecipientDefaultLite.jsx +1 -1
  62. package/src/components/Recipient/PermissionTypeMenu.jsx +21 -81
  63. package/src/components/Recipient/PermissionTypeMenuWrapper.jsx +32 -0
  64. package/src/components/Recipient/{PermissionTypeMenu.spec.jsx → PermissionTypeMenuWrapper.spec.jsx} +2 -2
  65. package/src/components/Recipient/RecipientList.jsx +10 -0
  66. package/src/components/Recipient/RecipientList.stories.jsx +3 -0
  67. package/src/components/ShareDialogCozyToCozy.jsx +10 -11
  68. package/src/components/ShareDialogCozyToCozy.spec.jsx +1 -0
  69. package/src/components/ShareDialogOnlyByLink.jsx +2 -4
  70. package/src/components/ShareDialogOnlyByLink.spec.jsx +0 -1
  71. package/src/components/ShareModal/SharingDetailsModal.jsx +2 -2
  72. package/src/components/SharedDrive/EditSharedDriveModal.jsx +6 -11
  73. package/src/components/SharedDrive/useSharedDrive.js +4 -11
  74. package/src/components/SharingContent.jsx +2 -4
  75. package/src/components/WhoHasAccess.jsx +26 -12
  76. package/src/components/WhoHasAccessWrapper.jsx +117 -0
  77. package/src/helpers/recipients.js +44 -0
  78. package/src/helpers/recipients.spec.js +82 -0
  79. package/src/hooks/useMemberPermissionType.js +110 -0
  80. package/src/hooks/useResolveRecipients.js +38 -0
  81. package/src/hooks/useResolveRecipients.spec.js +70 -0
  82. package/src/index.jsx +1 -1
  83. package/dist/components/Recipient/OwnerRecipientDefault.js +0 -27
  84. package/dist/components/Recipient/OwnerRecipientDefault.stories.js +0 -10
  85. package/src/components/Recipient/OwnerRecipientDefault.jsx +0 -37
  86. package/src/components/Recipient/OwnerRecipientDefault.stories.jsx +0 -13
@@ -6,6 +6,10 @@ const meta = {
6
6
  recipientConfirmationData: false,
7
7
  verifyRecipient: () => true,
8
8
  document: { _id: '123' },
9
+ documentType: 'Files',
10
+ permissions: [],
11
+ onUpdateLinkPermissions: () => {},
12
+ onRevokeLink: () => {},
9
13
  fadeIn: false
10
14
  }
11
15
  }
@@ -15,21 +15,20 @@ import { setReadOnlySharedPermission } from './actions/setReadOnlySharedPermissi
15
15
  import { setReadWriteSharedPermission } from './actions/setReadWriteSharedPermission'
16
16
  import { isOnlyReadOnlyLinkAllowed } from '../../helpers/link'
17
17
  import { checkIsReadOnlyPermissions } from '../../helpers/permissions'
18
- import { useSharingContext } from '../../hooks/useSharingContext'
19
18
  import { WRITE_PERMS, READ_ONLY_PERMS } from '../ShareRestrictionModal/helpers'
20
19
 
21
- const LinkRecipientPermissions = ({ document, isReadOnly }) => {
20
+ const LinkRecipientPermissions = ({
21
+ document,
22
+ documentType,
23
+ isReadOnly,
24
+ permissions,
25
+ onUpdateLinkPermissions,
26
+ onRevokeLink
27
+ }) => {
22
28
  const { t } = useI18n()
23
29
  const buttonRef = useRef()
24
30
  const [isMenuDisplayed, setMenuDisplayed] = useState(false)
25
- const {
26
- updateDocumentPermissions,
27
- revokeSharingLink,
28
- documentType,
29
- getDocumentPermissions
30
- } = useSharingContext()
31
31
 
32
- const permissions = getDocumentPermissions(document._id)
33
32
  const isReadOnlyPermissions = checkIsReadOnlyPermissions(permissions)
34
33
  const type = isReadOnlyPermissions ? 'one-way' : 'two-way'
35
34
 
@@ -38,11 +37,11 @@ const LinkRecipientPermissions = ({ document, isReadOnly }) => {
38
37
 
39
38
  const handleSetType = newType => {
40
39
  const verbs = newType === 'one-way' ? READ_ONLY_PERMS : WRITE_PERMS
41
- updateDocumentPermissions(document, { verbs })
40
+ onUpdateLinkPermissions(document, { verbs })
42
41
  hideMenu()
43
42
  }
44
43
 
45
- const handleRevocation = () => revokeSharingLink(document)
44
+ const handleRevocation = () => onRevokeLink(document)
46
45
 
47
46
  const actionsToShow = [setReadOnlySharedPermission]
48
47
  if (!isOnlyReadOnlyLinkAllowed({ documentType })) {
@@ -87,7 +86,12 @@ const LinkRecipientPermissions = ({ document, isReadOnly }) => {
87
86
  }
88
87
 
89
88
  LinkRecipientPermissions.propTypes = {
90
- document: PropTypes.object.isRequired
89
+ document: PropTypes.object.isRequired,
90
+ documentType: PropTypes.string.isRequired,
91
+ isReadOnly: PropTypes.bool,
92
+ permissions: PropTypes.arrayOf(PropTypes.object).isRequired,
93
+ onUpdateLinkPermissions: PropTypes.func.isRequired,
94
+ onRevokeLink: PropTypes.func.isRequired
91
95
  }
92
96
 
93
97
  export default LinkRecipientPermissions
@@ -3,7 +3,11 @@ import LinkRecipientPermissions from './LinkRecipientPermissions'
3
3
  const meta = {
4
4
  component: LinkRecipientPermissions,
5
5
  args: {
6
- document: { _id: '123' }
6
+ document: { _id: '123' },
7
+ documentType: 'Files',
8
+ permissions: [],
9
+ onUpdateLinkPermissions: () => {},
10
+ onRevokeLink: () => {}
7
11
  }
8
12
  }
9
13
 
@@ -1,7 +1,6 @@
1
1
  import PropTypes from 'prop-types'
2
2
  import React from 'react'
3
3
 
4
- import { useClient } from 'cozy-client'
5
4
  import Fade from 'cozy-ui/transpiled/react/Fade'
6
5
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
7
6
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
@@ -22,13 +21,13 @@ import { MemberAvatar } from '../Avatar/MemberAvatar'
22
21
 
23
22
  const MemberRecipient = props => {
24
23
  const { t } = useI18n()
25
- const client = useClient()
26
24
  const { isMobile } = useBreakpoints()
27
25
 
28
26
  const {
29
27
  instance,
30
28
  isOwner,
31
29
  status,
30
+ isCurrentUser = false,
32
31
  recipientConfirmationData,
33
32
  verifyRecipient,
34
33
  fadeIn,
@@ -36,8 +35,7 @@ const MemberRecipient = props => {
36
35
  ...rest
37
36
  } = props
38
37
 
39
- const isMe =
40
- (isOwner && status === 'owner') || instance === client.options.uri
38
+ const isMe = (isOwner && status === 'owner') || isCurrentUser
41
39
  const defaultDisplayName = t(DEFAULT_DISPLAY_NAME)
42
40
  const name = getDisplayName(rest, defaultDisplayName)
43
41
 
@@ -52,6 +50,7 @@ const MemberRecipient = props => {
52
50
  instance={instance}
53
51
  isOwner={isOwner}
54
52
  status={status}
53
+ isCurrentUser={isCurrentUser}
55
54
  />
56
55
  )
57
56
 
@@ -88,6 +87,7 @@ MemberRecipient.propTypes = {
88
87
  instance: PropTypes.string,
89
88
  isOwner: PropTypes.bool,
90
89
  status: PropTypes.string,
90
+ isCurrentUser: PropTypes.bool,
91
91
  recipientConfirmationData: PropTypes.object,
92
92
  verifyRecipient: PropTypes.func,
93
93
  isOrgSharedDrive: PropTypes.bool
@@ -6,16 +6,6 @@ import { createMockClient } from 'cozy-client'
6
6
  import MemberRecipient from './MemberRecipient'
7
7
  import AppLike from '../../../test/AppLike'
8
8
 
9
- const mockUpdateDocumentPermissions = jest.fn()
10
- const mockUpdateSharingMemberType = jest.fn()
11
-
12
- jest.mock('../../hooks/useSharingContext', () => ({
13
- useSharingContext: () => ({
14
- updateDocumentPermissions: mockUpdateDocumentPermissions,
15
- updateSharingMemberType: mockUpdateSharingMemberType
16
- })
17
- }))
18
-
19
9
  describe('MemberRecipient component', () => {
20
10
  const client = createMockClient({})
21
11
  client.options = {
@@ -51,6 +41,7 @@ describe('MemberRecipient component', () => {
51
41
  it('should render if isMe ', () => {
52
42
  const { getByText } = setup({
53
43
  instance: 'foo.mycozy.cloud',
44
+ isCurrentUser: true,
54
45
  status: 'ready',
55
46
  type: 'two-way'
56
47
  })
@@ -61,6 +52,7 @@ describe('MemberRecipient component', () => {
61
52
  it('should match snapshot if isOwner', () => {
62
53
  const { getByText } = setup({
63
54
  instance: 'foo.mycozy.cloud',
55
+ isCurrentUser: true,
64
56
  status: 'ready',
65
57
  type: 'two-way',
66
58
  isOwner: true
@@ -75,6 +67,7 @@ describe('MemberRecipient component', () => {
75
67
 
76
68
  const { getByLabelText } = setup({
77
69
  instance: 'foo.mycozy.cloud',
70
+ isCurrentUser: true,
78
71
  status: 'ready',
79
72
  type: 'two-way',
80
73
  documentType: 'Files',
@@ -93,6 +86,7 @@ describe('MemberRecipient component', () => {
93
86
 
94
87
  const { getByLabelText } = setup({
95
88
  instance: 'foo.mycozy.cloud',
89
+ isCurrentUser: true,
96
90
  status: 'ready',
97
91
  type: 'two-way',
98
92
  isOwner: true,
@@ -112,6 +106,7 @@ describe('MemberRecipient component', () => {
112
106
 
113
107
  const { getByText } = setup({
114
108
  instance: 'foo.mycozy.cloud',
109
+ isCurrentUser: true,
115
110
  status: 'ready',
116
111
  type: 'two-way',
117
112
  isOwner: false,
@@ -132,6 +127,7 @@ describe('MemberRecipient component', () => {
132
127
 
133
128
  const { queryByText } = setup({
134
129
  instance: 'foo.mycozy.cloud',
130
+ isCurrentUser: true,
135
131
  status: 'ready',
136
132
  type: 'two-way',
137
133
  isOwner: false,
@@ -149,6 +145,7 @@ describe('MemberRecipient component', () => {
149
145
 
150
146
  const { getByText } = setup({
151
147
  instance: 'foo.mycozy.cloud',
148
+ isCurrentUser: true,
152
149
  status: 'ready',
153
150
  type: 'two-way',
154
151
  isOwner: false,
@@ -1,46 +1,50 @@
1
1
  import React, { useState, useCallback } from 'react'
2
2
 
3
3
  import { Icon, CrossCircleOutline } from '@linagora/twake-icons'
4
- import { useClient } from 'cozy-client'
5
4
  import IconButton from 'cozy-ui/transpiled/react/IconButton'
6
5
  import Spinner from 'cozy-ui/transpiled/react/Spinner'
7
6
  import Typography from 'cozy-ui/transpiled/react/Typography'
8
7
  import { useI18n } from 'twake-i18n'
9
8
 
10
- import { PermissionTypeMenu } from './PermissionTypeMenu'
9
+ import PermissionTypeMenu from './PermissionTypeMenu'
10
+ import { hasMemberActions } from '../../helpers/recipients'
11
11
 
12
12
  const MemberRecipientPermissions = ({
13
13
  isOwner,
14
14
  canManageSharing = isOwner,
15
15
  canManageMembers = true,
16
16
  status,
17
- instance,
17
+ isCurrentUser = false,
18
18
  type,
19
19
  document,
20
+ isInsideSharedParent,
21
+ sharedParentName,
20
22
  onRevoke,
21
23
  onRevokeSelf,
24
+ onSetMemberType,
22
25
  sharingId,
23
26
  memberIndex,
24
27
  ...recipient
25
28
  }) => {
26
29
  const { t } = useI18n()
27
- const client = useClient()
28
30
 
29
31
  const [revoking, setRevoking] = useState(false)
30
32
 
31
- const instanceMatchesClient =
32
- instance !== undefined && instance === client.options.uri
33
33
  const contactIsOwner = status === 'owner'
34
34
  const shouldShowMenu =
35
- canManageMembers &&
36
35
  !revoking &&
37
- !contactIsOwner &&
38
- ((instanceMatchesClient && !isOwner) || canManageSharing)
36
+ hasMemberActions({
37
+ status,
38
+ isCurrentUser,
39
+ isOwner,
40
+ canManageSharing,
41
+ canManageMembers
42
+ })
39
43
 
40
44
  const handleRevocation = useCallback(async () => {
41
45
  setRevoking(true)
42
46
  try {
43
- if (instanceMatchesClient && !isOwner) {
47
+ if (isCurrentUser && !isOwner) {
44
48
  await onRevokeSelf(document)
45
49
  } else {
46
50
  await onRevoke(document, sharingId, memberIndex)
@@ -50,7 +54,7 @@ const MemberRecipientPermissions = ({
50
54
  }
51
55
  }, [
52
56
  document,
53
- instanceMatchesClient,
57
+ isCurrentUser,
54
58
  isOwner,
55
59
  memberIndex,
56
60
  onRevoke,
@@ -71,11 +75,23 @@ const MemberRecipientPermissions = ({
71
75
  {shouldShowMenu && (
72
76
  <>
73
77
  <PermissionTypeMenu
74
- sharingId={sharingId}
75
- memberIndex={memberIndex}
76
78
  type={type ?? 'one-way'}
77
79
  document={document}
78
80
  recipient={recipient}
81
+ isInsideSharedParent={isInsideSharedParent}
82
+ sharedParentName={sharedParentName}
83
+ onSetType={(newType, options) =>
84
+ onSetMemberType(
85
+ {
86
+ sharingId,
87
+ memberIndex,
88
+ type: type ?? 'one-way',
89
+ recipient
90
+ },
91
+ newType,
92
+ options
93
+ )
94
+ }
79
95
  />
80
96
  <IconButton
81
97
  onClick={handleRevocation}
@@ -6,15 +6,8 @@ import { createMockClient } from 'cozy-client'
6
6
  import MemberRecipientPermissions from './MemberRecipientPermissions'
7
7
  import AppLike from '../../../test/AppLike'
8
8
 
9
- const mockUpdateSharingMemberType = jest.fn()
10
9
  const mockShowAlert = jest.fn()
11
10
 
12
- jest.mock('../../hooks/useSharingContext', () => ({
13
- useSharingContext: () => ({
14
- updateSharingMemberType: mockUpdateSharingMemberType
15
- })
16
- }))
17
-
18
11
  jest.mock('cozy-ui/transpiled/react/providers/Alert', () => ({
19
12
  __esModule: true,
20
13
  default: ({ children }) => children,
@@ -33,13 +26,14 @@ describe('MemberRecipientPermissions component', () => {
33
26
  isOwner: true,
34
27
  isSharedDrive: false,
35
28
  status: 'ready',
36
- instance: 'http://cozy.local:8080',
29
+ isCurrentUser: true,
37
30
  type: 'two-way',
38
31
  document: { id: 'doc-123', type: 'io.cozy.files', path: '/test' },
39
32
  sharingId: 'sharing-123',
40
33
  memberIndex: 1,
41
34
  onRevoke: jest.fn(),
42
- onRevokeSelf: jest.fn()
35
+ onRevokeSelf: jest.fn(),
36
+ onSetMemberType: jest.fn()
43
37
  }
44
38
 
45
39
  beforeEach(() => {
@@ -75,7 +69,7 @@ describe('MemberRecipientPermissions component', () => {
75
69
  it('should not render menu when user is not owner and not the shared drive contact', () => {
76
70
  const { queryByRole } = setup({
77
71
  isOwner: false,
78
- instance: 'http://other-cozy.local:8080'
72
+ isCurrentUser: false
79
73
  })
80
74
 
81
75
  expect(queryByRole('button', { name: 'Editor' })).not.toBeInTheDocument()
@@ -91,7 +85,7 @@ describe('MemberRecipientPermissions component', () => {
91
85
  it('should render menu for the user themselves', () => {
92
86
  const { getByRole } = setup({
93
87
  isOwner: false,
94
- instance: 'http://cozy.local:8080'
88
+ isCurrentUser: true
95
89
  })
96
90
 
97
91
  expect(getByRole('button', { name: 'Editor' })).toBeInTheDocument()
@@ -5,6 +5,7 @@ const meta = {
5
5
  args: {
6
6
  onRevoke: () => {},
7
7
  onRevokeSelf: () => {},
8
+ onSetMemberType: () => {},
8
9
  type: 'two-way',
9
10
  status: 'ready'
10
11
  },
@@ -35,6 +36,6 @@ export const Self = {
35
36
  name: 'Self',
36
37
  args: {
37
38
  isOwner: false,
38
- instance: 'http://alice.cozy.localhost:8080'
39
+ isCurrentUser: true
39
40
  }
40
41
  }
@@ -2,28 +2,15 @@ import PropTypes from 'prop-types'
2
2
  import React from 'react'
3
3
 
4
4
  import MemberRecipient from './MemberRecipient'
5
- import OwnerRecipientDefault from './OwnerRecipientDefault'
6
5
 
7
- const OwnerRecipient = ({ recipients, isOrgSharedDrive }) => {
8
- const ownerRecipient = recipients.find(
9
- recipient => recipient.status === 'owner'
10
- )
6
+ const OwnerRecipient = ({ owner }) => {
7
+ if (!owner) return null
11
8
 
12
- if (ownerRecipient) {
13
- return (
14
- <MemberRecipient
15
- {...ownerRecipient}
16
- isOrgSharedDrive={isOrgSharedDrive}
17
- />
18
- )
19
- }
20
-
21
- return <OwnerRecipientDefault />
9
+ return <MemberRecipient {...owner} />
22
10
  }
23
11
 
24
12
  OwnerRecipient.propTypes = {
25
- recipients: PropTypes.array.isRequired,
26
- isOrgSharedDrive: PropTypes.bool
13
+ owner: PropTypes.object
27
14
  }
28
15
 
29
16
  export default OwnerRecipient
@@ -4,7 +4,7 @@ import { recipients } from '../../../.storybook/fixtures/recipients'
4
4
  const meta = {
5
5
  component: OwnerRecipient,
6
6
  args: {
7
- recipients
7
+ owner: recipients.find(recipient => recipient.status === 'owner')
8
8
  }
9
9
  }
10
10
 
@@ -6,7 +6,7 @@ import MemberRecipientLite from './MemberRecipientLite'
6
6
  import withLocales from '../../hoc/withLocales'
7
7
  import { buildInstanceSettingsQuery } from '../../queries/queries'
8
8
 
9
- // See OwnerRecipientDefault: show the instance public avatar (with an initials
9
+ // See containers/WhoHasAccess: show the instance public avatar (with an initials
10
10
  // fallback) when the owner has no per-sharing avatar to reference.
11
11
  const OWNER_PUBLIC_AVATAR_PATH = '/public/avatar?fallback=initials'
12
12
 
@@ -1,7 +1,6 @@
1
+ import PropTypes from 'prop-types'
1
2
  import React, { useCallback, useRef, useState } from 'react'
2
3
 
3
- import { useClient } from 'cozy-client'
4
- import flag from 'cozy-flags'
5
4
  import minilog from 'cozy-minilog'
6
5
  import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
7
6
  import { makeActions } from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
@@ -12,86 +11,32 @@ import { useI18n } from 'twake-i18n'
12
11
  import DowngradePermissionConfirmDialog from './DowngradePermissionConfirmDialog'
13
12
  import { setReadOnlySharedPermission } from './actions/setReadOnlySharedPermission'
14
13
  import { setReadWriteSharedPermission } from './actions/setReadWriteSharedPermission'
15
- import { getOrCreateFromArray } from '../../helpers/contacts'
16
- import withLocales from '../../hoc/withLocales'
17
- import { useFetchDocumentPath } from '../../hooks/useFetchDocumentPath'
18
- import { useSharingContext } from '../../hooks/useSharingContext'
19
- import { getSharingDocIds } from '../../state'
20
14
 
21
15
  const log = minilog('PermissionTypeMenu')
22
16
 
23
- const PermissionTypeMenuComponent = ({
24
- sharingId,
25
- memberIndex,
17
+ const PermissionTypeMenu = ({
26
18
  type,
27
19
  document,
28
- recipient
20
+ recipient,
21
+ isInsideSharedParent,
22
+ sharedParentName,
23
+ onSetType
29
24
  }) => {
30
25
  const { t } = useI18n()
31
- const client = useClient()
32
26
  const buttonRef = useRef()
33
- const { hasSharedParent, updateSharingMemberType, getSharingById, share } =
34
- useSharingContext()
35
27
  const { showAlert } = useAlert()
36
28
 
37
29
  const [isMenuDisplayed, setMenuDisplayed] = useState(false)
38
30
  const [pendingType, setPendingType] = useState(null)
39
31
 
40
- const documentPath = useFetchDocumentPath(client, document)
41
-
42
32
  const hideMenu = useCallback(() => {
43
33
  setMenuDisplayed(false)
44
34
  }, [])
45
35
 
46
36
  const applyType = useCallback(
47
- async (newType, { withAncestors = false } = {}) => {
37
+ async (newType, options) => {
48
38
  try {
49
- if (withAncestors) {
50
- // Ancestors first: only the target's own update refetches its
51
- // effective recipients, which must already see them downgraded.
52
- const ancestors = (recipient?.sources || []).filter(
53
- s => s.kind === 'ancestor' && !s.read_only
54
- )
55
- for (const ancestor of ancestors) {
56
- await updateSharingMemberType(
57
- ancestor.sharing_id,
58
- ancestor.member_index,
59
- newType
60
- )
61
- }
62
- }
63
-
64
- const documentId = document?._id || document?.id
65
- if (
66
- flag('drive.federated-shared-folder.enabled') &&
67
- type === 'one-way' &&
68
- newType === 'two-way' &&
69
- documentId
70
- ) {
71
- const sourceSharing = getSharingById(sharingId)
72
- if (
73
- sourceSharing &&
74
- !getSharingDocIds(sourceSharing).includes(documentId)
75
- ) {
76
- const contacts = await getOrCreateFromArray(
77
- client,
78
- [recipient],
79
- contact => client.create('io.cozy.contacts', contact)
80
- )
81
- if (!contacts[0]) throw new Error('Recipient contact not found')
82
- await share({
83
- document: { ...document, id: documentId },
84
- description: document.name,
85
- recipients: contacts,
86
- readOnlyRecipients: [],
87
- sharedDrive: true,
88
- openSharing: false
89
- })
90
- return
91
- }
92
- }
93
-
94
- await updateSharingMemberType(sharingId, memberIndex, newType, document)
39
+ await onSetType(newType, options)
95
40
  } catch (error) {
96
41
  log.error('Failed to change member permission type', error)
97
42
  showAlert({
@@ -101,27 +46,12 @@ const PermissionTypeMenuComponent = ({
101
46
  })
102
47
  }
103
48
  },
104
- [
105
- client,
106
- document,
107
- getSharingById,
108
- memberIndex,
109
- recipient,
110
- share,
111
- sharingId,
112
- showAlert,
113
- t,
114
- type,
115
- updateSharingMemberType
116
- ]
49
+ [onSetType, showAlert, t]
117
50
  )
118
51
 
119
52
  // Downgrading to viewer on a folder inside a shared parent also reduces
120
53
  // the member's rights on the parent: require explicit confirmation first.
121
- const shouldConfirmDowngrade =
122
- type === 'two-way' &&
123
- Boolean(documentPath) &&
124
- hasSharedParent?.(documentPath)
54
+ const shouldConfirmDowngrade = type === 'two-way' && isInsideSharedParent
125
55
 
126
56
  const setType = useCallback(
127
57
  newType => {
@@ -177,6 +107,7 @@ const PermissionTypeMenuComponent = ({
177
107
  <DowngradePermissionConfirmDialog
178
108
  document={document}
179
109
  recipient={recipient}
110
+ sharedParentName={sharedParentName}
180
111
  onCancel={handleCancelDowngrade}
181
112
  onConfirm={handleConfirmDowngrade}
182
113
  />
@@ -185,4 +116,13 @@ const PermissionTypeMenuComponent = ({
185
116
  )
186
117
  }
187
118
 
188
- export const PermissionTypeMenu = withLocales(PermissionTypeMenuComponent)
119
+ PermissionTypeMenu.propTypes = {
120
+ type: PropTypes.oneOf(['one-way', 'two-way']),
121
+ document: PropTypes.object,
122
+ recipient: PropTypes.object,
123
+ isInsideSharedParent: PropTypes.bool,
124
+ sharedParentName: PropTypes.string,
125
+ onSetType: PropTypes.func.isRequired
126
+ }
127
+
128
+ export default PermissionTypeMenu
@@ -0,0 +1,32 @@
1
+ import React from 'react'
2
+
3
+ import PermissionTypeMenu from './PermissionTypeMenu'
4
+ import withLocales from '../../hoc/withLocales'
5
+ import { useMemberPermissionType } from '../../hooks/useMemberPermissionType'
6
+
7
+ const PermissionTypeMenuWrapper = ({
8
+ sharingId,
9
+ memberIndex,
10
+ type,
11
+ document,
12
+ recipient
13
+ }) => {
14
+ const { isInsideSharedParent, sharedParentName, setMemberType } =
15
+ useMemberPermissionType(document)
16
+
17
+ const handleSetType = (newType, options) =>
18
+ setMemberType({ sharingId, memberIndex, type, recipient }, newType, options)
19
+
20
+ return (
21
+ <PermissionTypeMenu
22
+ type={type}
23
+ document={document}
24
+ recipient={recipient}
25
+ isInsideSharedParent={isInsideSharedParent}
26
+ sharedParentName={sharedParentName}
27
+ onSetType={handleSetType}
28
+ />
29
+ )
30
+ }
31
+
32
+ export default withLocales(PermissionTypeMenuWrapper)
@@ -4,7 +4,7 @@ import React from 'react'
4
4
  import { createMockClient } from 'cozy-client'
5
5
  import flag from 'cozy-flags'
6
6
 
7
- import { PermissionTypeMenu } from './PermissionTypeMenu'
7
+ import PermissionTypeMenuWrapper from './PermissionTypeMenuWrapper'
8
8
  import AppLike from '../../../test/AppLike'
9
9
 
10
10
  const mockUpdateSharingMemberType = jest.fn()
@@ -56,7 +56,7 @@ describe('PermissionTypeMenu component', () => {
56
56
  const setup = props => {
57
57
  return render(
58
58
  <AppLike client={client}>
59
- <PermissionTypeMenu {...defaultProps} {...props} />
59
+ <PermissionTypeMenuWrapper {...defaultProps} {...props} />
60
60
  </AppLike>
61
61
  )
62
62
  }
@@ -14,8 +14,13 @@ const RecipientList = ({
14
14
  isSharedDrive,
15
15
  document,
16
16
  documentType,
17
+ isInsideSharedParent,
18
+ sharedParentName,
17
19
  onRevoke,
18
20
  onRevokeSelf,
21
+ onRevokeGroup,
22
+ onLeaveGroup,
23
+ onSetMemberType,
19
24
  verifyRecipient
20
25
  }) => {
21
26
  const previousRecipients = usePrevious(recipients)
@@ -41,6 +46,8 @@ const RecipientList = ({
41
46
  documentType={documentType}
42
47
  onRevoke={onRevoke}
43
48
  onRevokeSelf={onRevokeSelf}
49
+ onRevokeGroup={onRevokeGroup}
50
+ onLeaveGroup={onLeaveGroup}
44
51
  fadeIn={recipient.hasBeenJustAdded}
45
52
  />
46
53
  )
@@ -56,8 +63,11 @@ const RecipientList = ({
56
63
  isSharedDrive={isSharedDrive}
57
64
  document={document}
58
65
  documentType={documentType}
66
+ isInsideSharedParent={isInsideSharedParent}
67
+ sharedParentName={sharedParentName}
59
68
  onRevoke={onRevoke}
60
69
  onRevokeSelf={onRevokeSelf}
70
+ onSetMemberType={onSetMemberType}
61
71
  recipientConfirmationData={recipientConfirmationData}
62
72
  verifyRecipient={verifyRecipient}
63
73
  fadeIn={recipient.hasBeenJustAdded}
@@ -9,6 +9,9 @@ const meta = {
9
9
  isOwner: false,
10
10
  onRevoke: () => {},
11
11
  onRevokeSelf: () => {},
12
+ onRevokeGroup: () => {},
13
+ onLeaveGroup: () => {},
14
+ onSetMemberType: () => {},
12
15
  verifyRecipient: () => true
13
16
  }
14
17
  }