cozy-sharing 37.0.2 → 37.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/OpenSharingLinkButton.js +1 -1
  3. package/dist/SharingProvider.js +315 -138
  4. package/dist/SharingProvider.spec.js +454 -240
  5. package/dist/actions/addToCozySharingLink.js +1 -1
  6. package/dist/actions/createCozySharingLink.js +1 -1
  7. package/dist/actions/shareNative.js +1 -1
  8. package/dist/actions/syncToCozySharingLink.js +1 -1
  9. package/dist/components/Avatar/AvatarList.js +1 -1
  10. package/dist/components/Recipient/GroupRecipient.js +0 -2
  11. package/dist/components/Recipient/GroupRecipientDetail.js +2 -25
  12. package/dist/components/Recipient/GroupRecipientDetailWithoutAccess.js +1 -1
  13. package/dist/components/Recipient/LinkRecipient.js +1 -1
  14. package/dist/components/Recipient/LinkRecipientLite.js +1 -1
  15. package/dist/components/Recipient/actions/revokeLink.js +1 -1
  16. package/dist/components/ShareAutosuggest.js +6 -6
  17. package/dist/components/ShareButton.js +1 -1
  18. package/dist/components/ShareByLink.js +1 -1
  19. package/dist/components/ShareLinkAccessModal/ShareLinkAccessModal.js +316 -0
  20. package/dist/components/ShareLinkAccessModal/ShareLinkAccessModal.spec.js +372 -0
  21. package/dist/components/ShareLinkAccessModal/index.js +1 -0
  22. package/dist/components/ShareRestrictionModal/BoxDate.js +1 -1
  23. package/dist/components/ShareRestrictionModal/BoxEditingRights.js +1 -1
  24. package/dist/components/ShareRestrictionModal/BoxPassword.js +1 -1
  25. package/dist/components/ShareRestrictionModal/ShareRestrictionModal.js +1 -1
  26. package/dist/components/ShareRestrictionModal/helpers.js +36 -18
  27. package/dist/components/ShareRestrictionModal/helpers.spec.js +3 -3
  28. package/dist/components/SharedBadge.js +1 -1
  29. package/dist/components/SharedDrive/SharedDriveHeader.js +1 -1
  30. package/dist/index.js +1 -0
  31. package/locales/en.json +21 -3
  32. package/locales/fr.json +22 -4
  33. package/locales/ru.json +21 -3
  34. package/locales/vi.json +21 -3
  35. package/package.json +3 -3
  36. package/src/OpenSharingLinkButton.jsx +1 -1
  37. package/src/SharingProvider.jsx +91 -27
  38. package/src/SharingProvider.spec.jsx +212 -60
  39. package/src/actions/addToCozySharingLink.js +1 -1
  40. package/src/actions/createCozySharingLink.js +1 -1
  41. package/src/actions/shareNative.js +1 -1
  42. package/src/actions/syncToCozySharingLink.js +1 -1
  43. package/src/components/Avatar/AvatarList.jsx +1 -1
  44. package/src/components/Recipient/GroupRecipient.jsx +1 -2
  45. package/src/components/Recipient/GroupRecipientDetail.jsx +3 -33
  46. package/src/components/Recipient/GroupRecipientDetailWithoutAccess.jsx +1 -1
  47. package/src/components/Recipient/LinkRecipient.jsx +1 -1
  48. package/src/components/Recipient/LinkRecipientLite.jsx +1 -1
  49. package/src/components/Recipient/actions/revokeLink.js +1 -1
  50. package/src/components/ShareAutosuggest.jsx +3 -4
  51. package/src/components/ShareButton.jsx +1 -1
  52. package/src/components/ShareByLink.jsx +1 -1
  53. package/src/components/ShareLinkAccessModal/ShareLinkAccessModal.jsx +293 -0
  54. package/src/components/ShareLinkAccessModal/ShareLinkAccessModal.spec.jsx +291 -0
  55. package/src/components/ShareLinkAccessModal/index.js +1 -0
  56. package/src/components/ShareRestrictionModal/BoxDate.jsx +1 -1
  57. package/src/components/ShareRestrictionModal/BoxEditingRights.jsx +1 -1
  58. package/src/components/ShareRestrictionModal/BoxPassword.jsx +1 -1
  59. package/src/components/ShareRestrictionModal/ShareRestrictionModal.jsx +1 -1
  60. package/src/components/ShareRestrictionModal/helpers.js +30 -6
  61. package/src/components/ShareRestrictionModal/helpers.spec.js +3 -3
  62. package/src/components/SharedBadge.jsx +2 -1
  63. package/src/components/SharedDrive/SharedDriveHeader.jsx +1 -1
  64. package/src/helpers/sharings.js +0 -1
  65. package/src/index.jsx +1 -0
@@ -1,6 +1,6 @@
1
- import { Icon, ToTheCloud } from '@linagora/twake-icons'
2
1
  import React, { forwardRef } from 'react'
3
2
 
3
+ import { Icon, ToTheCloud } from '@linagora/twake-icons'
4
4
  import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem'
5
5
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
6
6
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
@@ -1,6 +1,6 @@
1
- import { Icon, Reply } from '@linagora/twake-icons'
2
1
  import React, { forwardRef } from 'react'
3
2
 
3
+ import { Icon, Reply } from '@linagora/twake-icons'
4
4
  import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem'
5
5
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
6
6
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
@@ -1,6 +1,6 @@
1
- import { Icon, Sync } from '@linagora/twake-icons'
2
1
  import React, { forwardRef } from 'react'
3
2
 
3
+ import { Icon, Sync } from '@linagora/twake-icons'
4
4
  import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem'
5
5
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
6
6
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
@@ -1,7 +1,7 @@
1
- import { Icon, Link } from '@linagora/twake-icons'
2
1
  import cx from 'classnames'
3
2
  import React from 'react'
4
3
 
4
+ import { Icon, Link } from '@linagora/twake-icons'
5
5
  import { useClient } from 'cozy-client'
6
6
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
7
7
 
@@ -19,7 +19,7 @@ import {
19
19
  import { GroupAvatar } from '../Avatar/GroupAvatar'
20
20
 
21
21
  const GroupRecipient = props => {
22
- const { name, color, members, fadeIn, owner, isOwner } = props
22
+ const { name, color, members, fadeIn, isOwner } = props
23
23
  const { t } = useI18n()
24
24
  const client = useClient()
25
25
  const { isMobile } = useBreakpoints()
@@ -74,7 +74,6 @@ const GroupRecipient = props => {
74
74
  {isDetailOpened ? (
75
75
  <GroupRecipientDetail
76
76
  isOwner={isOwner}
77
- owner={owner}
78
77
  name={name}
79
78
  members={members}
80
79
  onClose={closeDetail}
@@ -1,17 +1,13 @@
1
1
  import React from 'react'
2
2
 
3
- import { useClient, generateWebLink } from 'cozy-client'
4
- import Buttons from 'cozy-ui/transpiled/react/Buttons'
5
3
  import { Dialog } from 'cozy-ui/transpiled/react/CozyDialogs'
6
4
  import Empty from 'cozy-ui/transpiled/react/Empty'
7
- import Typography from 'cozy-ui/transpiled/react/Typography'
8
5
  import { useI18n } from 'twake-i18n'
9
6
 
10
7
  import { GroupRecipientDetailWithAccess } from './GroupRecipientDetailWithAccess'
11
8
  import { GroupRecipientDetailWithoutAccess } from './GroupRecipientDetailWithoutAccess'
12
9
 
13
- const GroupRecipientDetail = ({ name, owner, members, onClose, isOwner }) => {
14
- const client = useClient()
10
+ const GroupRecipientDetail = ({ name, members, onClose, isOwner }) => {
15
11
  const { t } = useI18n()
16
12
  const withAccess = members.filter(
17
13
  member => !['revoked', 'mail-not-sent'].includes(member.status)
@@ -20,42 +16,16 @@ const GroupRecipientDetail = ({ name, owner, members, onClose, isOwner }) => {
20
16
  ['revoked', 'mail-not-sent'].includes(member.status)
21
17
  )
22
18
 
23
- const ownerName = owner.public_name
24
- const contactsLink = generateWebLink({
25
- cozyUrl: client.getStackClient().uri,
26
- slug: 'contacts',
27
- pathname: '/',
28
- subDomainType: client.getInstanceOptions().subdomain
29
- })
30
-
31
19
  return (
32
20
  <Dialog
33
21
  open
34
22
  size="small"
35
23
  onClose={onClose}
36
- title={
37
- <>
38
- {name}
39
- {ownerName ? (
40
- <Typography variant="caption">
41
- {t('GroupRecipientDetail.subtitle', { ownerName })}
42
- </Typography>
43
- ) : null}
44
- </>
45
- }
24
+ title={name}
46
25
  content={
47
26
  <div className="u-flex u-stack-xs u-flex-column">
48
27
  {members.length === 0 ? (
49
- <Empty text={t('GroupRecipientDetail.empty.content')}>
50
- <Buttons
51
- component="a"
52
- className="u-mt-1"
53
- href={contactsLink}
54
- target="_blank"
55
- rel="noopener noreferrer"
56
- label={t('GroupRecipientDetail.empty.action')}
57
- />
58
- </Empty>
28
+ <Empty text={t('GroupRecipientDetail.empty.content')} />
59
29
  ) : null}
60
30
  {withAccess.length > 0 ? (
61
31
  <GroupRecipientDetailWithAccess withAccess={withAccess} />
@@ -1,6 +1,6 @@
1
- import { Icon, Forbidden } from '@linagora/twake-icons'
2
1
  import React from 'react'
3
2
 
3
+ import { Icon, Forbidden } from '@linagora/twake-icons'
4
4
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
5
5
  import List from 'cozy-ui/transpiled/react/List'
6
6
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
@@ -1,7 +1,7 @@
1
- import { Icon, Gear, Link } from '@linagora/twake-icons'
2
1
  import PropTypes from 'prop-types'
3
2
  import React, { useState } from 'react'
4
3
 
4
+ import { Icon, Gear, Link } from '@linagora/twake-icons'
5
5
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
6
6
  import Fade from 'cozy-ui/transpiled/react/Fade'
7
7
  import IconButton from 'cozy-ui/transpiled/react/IconButton'
@@ -1,7 +1,7 @@
1
- import { Icon, Link } from '@linagora/twake-icons'
2
1
  import PropTypes from 'prop-types'
3
2
  import React from 'react'
4
3
 
4
+ import { Icon, Link } from '@linagora/twake-icons'
5
5
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
6
6
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
7
7
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
@@ -1,6 +1,6 @@
1
- import { Icon, Trash } from '@linagora/twake-icons'
2
1
  import React, { forwardRef } from 'react'
3
2
 
3
+ import { Icon, Trash } from '@linagora/twake-icons'
4
4
  import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem'
5
5
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
6
6
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
@@ -2,15 +2,15 @@ import PropTypes from 'prop-types'
2
2
  import React, { useState, useRef } from 'react'
3
3
  import Autosuggest from 'react-autosuggest'
4
4
 
5
- import Avatar from 'cozy-ui/transpiled/react/Avatar'
6
5
  import Chip from 'cozy-ui/transpiled/react/Chips'
7
6
  import { Spinner } from 'cozy-ui/transpiled/react/Spinner'
8
7
 
9
8
  import { GroupAvatar } from './Avatar/GroupAvatar'
9
+ import { MemberAvatar } from './Avatar/MemberAvatar'
10
10
  import ContactSuggestion from './ContactSuggestion'
11
11
  import { isContactToBeCreated } from '../helpers/contacts'
12
12
  import { extractEmails, validateEmail } from '../helpers/email'
13
- import { getDisplayName, getInitials, Contact, Group } from '../models'
13
+ import { getDisplayName, Contact, Group } from '../models'
14
14
  import styles from '../styles/autosuggest.styl'
15
15
  import { contactOrGroupMatch } from '../suggestionMatchers'
16
16
 
@@ -153,7 +153,6 @@ const ShareAutosuggest = ({
153
153
  <div className={styles['recipientsContainer']}>
154
154
  {recipients.map((recipient, idx) => {
155
155
  const isContactGroup = recipient._type === Group.doctype
156
- const avatarText = getInitials(recipient)
157
156
  const name = getDisplayName(recipient)
158
157
  return (
159
158
  <Chip
@@ -163,7 +162,7 @@ const ShareAutosuggest = ({
163
162
  isContactGroup ? (
164
163
  <GroupAvatar size="xs" color={recipient.color} />
165
164
  ) : (
166
- <Avatar size="xs">{avatarText}</Avatar>
165
+ <MemberAvatar size="xs" recipient={recipient} />
167
166
  )
168
167
  }
169
168
  label={name}
@@ -1,7 +1,7 @@
1
- import { Icon, Share } from '@linagora/twake-icons'
2
1
  import classNames from 'classnames'
3
2
  import React from 'react'
4
3
 
4
+ import { Icon, Share } from '@linagora/twake-icons'
5
5
  import Button from 'cozy-ui/transpiled/react/Buttons'
6
6
 
7
7
  import styles from '../styles/button.styl'
@@ -1,7 +1,7 @@
1
- import { Icon, Copy, Link } from '@linagora/twake-icons'
2
1
  import PropTypes from 'prop-types'
3
2
  import React, { useReducer, useState } from 'react'
4
3
 
4
+ import { Icon, Copy, Link } from '@linagora/twake-icons'
5
5
  import { useClient } from 'cozy-client'
6
6
  import Button from 'cozy-ui/transpiled/react/Buttons'
7
7
  import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
@@ -0,0 +1,293 @@
1
+ import { addDays } from 'date-fns'
2
+ import PropTypes from 'prop-types'
3
+ import React, { useState } from 'react'
4
+
5
+ import { Icon, Link as LinkIcon, Settings } from '@linagora/twake-icons'
6
+ import Alert from 'cozy-ui/transpiled/react/Alert'
7
+ import Box from 'cozy-ui/transpiled/react/Box'
8
+ import Button from 'cozy-ui/transpiled/react/Buttons'
9
+ import Chip from 'cozy-ui/transpiled/react/Chips'
10
+ import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
11
+ import DatePicker from 'cozy-ui/transpiled/react/DatePicker'
12
+ import DropdownButton from 'cozy-ui/transpiled/react/DropdownButton'
13
+ import FormControlLabel from 'cozy-ui/transpiled/react/FormControlLabel'
14
+ import Grid from 'cozy-ui/transpiled/react/Grid'
15
+ import IconButton from 'cozy-ui/transpiled/react/IconButton'
16
+ import Menu from 'cozy-ui/transpiled/react/Menu'
17
+ import MenuItem from 'cozy-ui/transpiled/react/MenuItem'
18
+ import Switch from 'cozy-ui/transpiled/react/Switch'
19
+ import TextField from 'cozy-ui/transpiled/react/TextField'
20
+ import Typography from 'cozy-ui/transpiled/react/Typography'
21
+ import { useI18n } from 'twake-i18n'
22
+
23
+ import withLocales from '../../hoc/withLocales'
24
+ import { useSharingContext } from '../../hooks/useSharingContext'
25
+
26
+ const DIALOG_CLASSES = { paper: 'u-h-auto' }
27
+ const DOCUMENT_ICON_SIZE = 18
28
+ const PASSWORD_MIN_LENGTH = 4
29
+
30
+ export const ShareLinkAccessModal = ({
31
+ documents,
32
+ onCancel,
33
+ onSuccess,
34
+ renderDocumentIcon
35
+ }) => {
36
+ const { t } = useI18n()
37
+ const { ensureSharingLink } = useSharingContext()
38
+ const [editingRights, setEditingRights] = useState('readOnly')
39
+ const [accessAnchorEl, setAccessAnchorEl] = useState(null)
40
+ const [isSettingsOpen, setIsSettingsOpen] = useState(false)
41
+ const [dateEnabled, setDateEnabled] = useState(false)
42
+ const [selectedDate, setSelectedDate] = useState(null)
43
+ const [passwordEnabled, setPasswordEnabled] = useState(false)
44
+ const [password, setPassword] = useState('')
45
+ const [busy, setBusy] = useState(false)
46
+ const [error, setError] = useState(null)
47
+
48
+ const isPasswordValid =
49
+ !passwordEnabled || password.trim().length >= PASSWORD_MIN_LENGTH
50
+ const handleAccessMenuClose = () => {
51
+ setAccessAnchorEl(null)
52
+ }
53
+
54
+ const handleDateEnabledChange = event => {
55
+ setDateEnabled(event.target.checked)
56
+ setSelectedDate(event.target.checked ? addDays(new Date(), 30) : null)
57
+ }
58
+
59
+ const handlePasswordEnabledChange = event => {
60
+ setPasswordEnabled(event.target.checked)
61
+ }
62
+
63
+ const handlePasswordChange = event => {
64
+ setPassword(event.target.value)
65
+ }
66
+
67
+ const handleSettingsOpen = () => {
68
+ setIsSettingsOpen(true)
69
+ }
70
+
71
+ const handleSettingsBack = () => {
72
+ setIsSettingsOpen(false)
73
+ }
74
+
75
+ const handleSubmit = async () => {
76
+ setBusy(true)
77
+ setError(null)
78
+
79
+ try {
80
+ const results = await Promise.all(
81
+ documents.map(document =>
82
+ ensureSharingLink(document, {
83
+ editingRights,
84
+ dateEnabled,
85
+ selectedDate,
86
+ passwordEnabled,
87
+ password: password.trim()
88
+ })
89
+ )
90
+ )
91
+ onSuccess(results)
92
+ } catch {
93
+ setError(t('ShareLinkAccessModal.error.persistence'))
94
+ setBusy(false)
95
+ }
96
+ }
97
+
98
+ if (isSettingsOpen) {
99
+ return (
100
+ <ConfirmDialog
101
+ open
102
+ classes={DIALOG_CLASSES}
103
+ size="small"
104
+ onBack={busy ? undefined : handleSettingsBack}
105
+ onClose={busy ? undefined : handleSettingsBack}
106
+ title={t('ShareLinkAccessModal.settingsTitle')}
107
+ content={
108
+ <Box display="flex" flexDirection="column" gridGap="1rem">
109
+ <FormControlLabel
110
+ control={
111
+ <Switch
112
+ checked={dateEnabled}
113
+ onChange={handleDateEnabledChange}
114
+ disabled={busy}
115
+ color="primary"
116
+ />
117
+ }
118
+ label={t('ShareLinkAccessModal.expiry')}
119
+ />
120
+ {dateEnabled && (
121
+ <DatePicker
122
+ label={t('ShareLinkAccessModal.expiryDate')}
123
+ value={selectedDate}
124
+ minDate={new Date()}
125
+ onChange={setSelectedDate}
126
+ disabled={busy}
127
+ className="u-w-100"
128
+ />
129
+ )}
130
+ <FormControlLabel
131
+ control={
132
+ <Switch
133
+ checked={passwordEnabled}
134
+ onChange={handlePasswordEnabledChange}
135
+ disabled={busy}
136
+ color="primary"
137
+ />
138
+ }
139
+ label={t('ShareLinkAccessModal.password')}
140
+ />
141
+ {passwordEnabled && (
142
+ <TextField
143
+ label={t('ShareLinkAccessModal.passwordLabel')}
144
+ value={password}
145
+ onChange={handlePasswordChange}
146
+ disabled={busy}
147
+ type="password"
148
+ error={!isPasswordValid}
149
+ helperText={
150
+ isPasswordValid
151
+ ? null
152
+ : t('ShareLinkAccessModal.passwordTooShort', {
153
+ count: PASSWORD_MIN_LENGTH
154
+ })
155
+ }
156
+ fullWidth
157
+ inputProps={{ minLength: PASSWORD_MIN_LENGTH }}
158
+ />
159
+ )}
160
+ </Box>
161
+ }
162
+ />
163
+ )
164
+ }
165
+
166
+ return (
167
+ <ConfirmDialog
168
+ open
169
+ classes={DIALOG_CLASSES}
170
+ size="small"
171
+ onBack={busy ? undefined : onCancel}
172
+ onClose={busy ? undefined : onCancel}
173
+ title={t('ShareLinkAccessModal.title')}
174
+ content={
175
+ <Box display="flex" flexDirection="column" gridGap="1rem">
176
+ <Typography>{t('ShareLinkAccessModal.introText')}</Typography>
177
+ <Grid container spacing={1}>
178
+ {documents.map(document => (
179
+ <Grid item key={document._id || document.id} xs={12} sm={6}>
180
+ <Chip
181
+ avatar={
182
+ <Box component="span" className="u-flex u-ov-hidden">
183
+ {renderDocumentIcon(document, DOCUMENT_ICON_SIZE)}
184
+ </Box>
185
+ }
186
+ className="u-maw-100"
187
+ label={document.name}
188
+ size="small"
189
+ />
190
+ </Grid>
191
+ ))}
192
+ </Grid>
193
+ {error && <Alert severity="error">{error}</Alert>}
194
+ <Box
195
+ display="flex"
196
+ alignItems="center"
197
+ justifyContent="space-between"
198
+ >
199
+ <Box display="flex" alignItems="center" gridGap="0.5rem">
200
+ <Icon icon={LinkIcon} />
201
+ <Typography>
202
+ {t('ShareLinkAccessModal.anyoneWithLink')}
203
+ </Typography>
204
+ </Box>
205
+ <Box
206
+ display="flex"
207
+ alignItems="center"
208
+ gridGap="0.5rem"
209
+ className="u-flex-shrink-0"
210
+ >
211
+ <IconButton
212
+ aria-label={t('ShareLinkAccessModal.settings')}
213
+ disabled={busy}
214
+ onClick={handleSettingsOpen}
215
+ >
216
+ <Icon icon={Settings} />
217
+ </IconButton>
218
+ <DropdownButton
219
+ aria-label={t('ShareLinkAccessModal.accessLevel')}
220
+ aria-controls="share-link-access-menu"
221
+ aria-haspopup="true"
222
+ disabled={busy}
223
+ onClick={event => setAccessAnchorEl(event.currentTarget)}
224
+ spaceBetween
225
+ textVariant="body1"
226
+ >
227
+ {t(
228
+ editingRights === 'readOnly'
229
+ ? 'ShareLinkAccessModal.viewer'
230
+ : 'ShareLinkAccessModal.editor'
231
+ )}
232
+ </DropdownButton>
233
+ <Menu
234
+ id="share-link-access-menu"
235
+ anchorEl={accessAnchorEl}
236
+ open={Boolean(accessAnchorEl)}
237
+ onClose={handleAccessMenuClose}
238
+ >
239
+ <MenuItem
240
+ selected={editingRights === 'readOnly'}
241
+ onClick={() => {
242
+ setEditingRights('readOnly')
243
+ handleAccessMenuClose()
244
+ }}
245
+ >
246
+ {t('ShareLinkAccessModal.viewer')}
247
+ </MenuItem>
248
+ <MenuItem
249
+ selected={editingRights === 'write'}
250
+ onClick={() => {
251
+ setEditingRights('write')
252
+ handleAccessMenuClose()
253
+ }}
254
+ >
255
+ {t('ShareLinkAccessModal.editor')}
256
+ </MenuItem>
257
+ </Menu>
258
+ </Box>
259
+ </Box>
260
+ </Box>
261
+ }
262
+ actions={
263
+ <>
264
+ <Button
265
+ label={t('ShareLinkAccessModal.cancel')}
266
+ variant="secondary"
267
+ onClick={onCancel}
268
+ disabled={busy}
269
+ />
270
+ <Button
271
+ label={t('ShareLinkAccessModal.addLinks')}
272
+ onClick={handleSubmit}
273
+ disabled={busy || !isPasswordValid}
274
+ busy={busy}
275
+ />
276
+ </>
277
+ }
278
+ />
279
+ )
280
+ }
281
+
282
+ ShareLinkAccessModal.propTypes = {
283
+ documents: PropTypes.arrayOf(PropTypes.object).isRequired,
284
+ onCancel: PropTypes.func.isRequired,
285
+ onSuccess: PropTypes.func.isRequired,
286
+ renderDocumentIcon: PropTypes.func
287
+ }
288
+
289
+ ShareLinkAccessModal.defaultProps = {
290
+ renderDocumentIcon: () => null
291
+ }
292
+
293
+ export default withLocales(ShareLinkAccessModal)