cozy-sharing 18.0.0 → 20.0.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 (48) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/dist/SharingProvider.js +16 -9
  3. package/dist/components/Recipient/LinkRecipient.js +20 -4
  4. package/dist/components/Recipient/LinkRecipientPermissions.js +18 -129
  5. package/dist/components/Recipient/actions/editPermissionLink.js +71 -0
  6. package/dist/components/Recipient/actions/readOnlyPermissionLink.js +63 -0
  7. package/dist/components/ShareByLink.js +45 -185
  8. package/dist/components/ShareDialogCozyToCozy.js +2 -6
  9. package/dist/components/ShareDialogOnlyByLink.js +2 -8
  10. package/dist/components/ShareDialogTwoStepsConfirmationContainer.js +1 -3
  11. package/dist/components/ShareModal/EditableSharingModal.js +1 -7
  12. package/dist/components/ShareModal.js +0 -12
  13. package/dist/components/ShareRestrictionModal/BoxDate.js +77 -0
  14. package/dist/components/ShareRestrictionModal/BoxEditingRights.js +83 -0
  15. package/dist/components/ShareRestrictionModal/BoxPassword.js +155 -0
  16. package/dist/components/ShareRestrictionModal/ShareRestrictionContentModal.js +118 -0
  17. package/dist/components/ShareRestrictionModal/ShareRestrictionModal.js +256 -0
  18. package/dist/components/ShareRestrictionModal/helpers.js +310 -0
  19. package/dist/components/ShareRestrictionModal/helpers.spec.js +232 -0
  20. package/dist/components/WhoHasAccess.js +1 -5
  21. package/dist/helpers/permissions.js +15 -0
  22. package/locales/en.json +30 -0
  23. package/locales/fr.json +31 -0
  24. package/package.json +11 -7
  25. package/src/SharingProvider.jsx +10 -5
  26. package/src/components/Recipient/LinkRecipient.jsx +28 -4
  27. package/src/components/Recipient/LinkRecipientPermissions.jsx +28 -137
  28. package/src/components/Recipient/actions/editPermissionLink.js +63 -0
  29. package/src/components/Recipient/actions/readOnlyPermissionLink.js +59 -0
  30. package/src/components/ShareByLink.jsx +20 -96
  31. package/src/components/ShareDialogCozyToCozy.jsx +1 -5
  32. package/src/components/ShareDialogOnlyByLink.jsx +0 -6
  33. package/src/components/ShareDialogTwoStepsConfirmationContainer.jsx +0 -2
  34. package/src/components/ShareModal/EditableSharingModal.jsx +1 -7
  35. package/src/components/ShareModal.jsx +0 -12
  36. package/src/components/ShareRestrictionModal/BoxDate.jsx +76 -0
  37. package/src/components/ShareRestrictionModal/BoxEditingRights.jsx +91 -0
  38. package/src/components/ShareRestrictionModal/BoxPassword.jsx +126 -0
  39. package/src/components/ShareRestrictionModal/ShareRestrictionContentModal.jsx +124 -0
  40. package/src/components/ShareRestrictionModal/ShareRestrictionModal.jsx +186 -0
  41. package/src/components/ShareRestrictionModal/helpers.js +227 -0
  42. package/src/components/ShareRestrictionModal/helpers.spec.js +159 -0
  43. package/src/components/WhoHasAccess.jsx +1 -5
  44. package/src/helpers/permissions.js +12 -0
  45. package/dist/components/EditLinkPermissionDialog.js +0 -72
  46. package/dist/components/EditLinkPermissionDialog.spec.js +0 -48
  47. package/src/components/EditLinkPermissionDialog.jsx +0 -89
  48. package/src/components/EditLinkPermissionDialog.spec.jsx +0 -53
@@ -23,10 +23,7 @@ export const EditableSharingModal = ({ document, ...rest }) => {
23
23
  isOwner,
24
24
  revoke,
25
25
  revokeSelf,
26
- revokeSharingLink,
27
- share,
28
- shareByLink,
29
- updateDocumentPermissions
26
+ share
30
27
  } = useSharingContext()
31
28
 
32
29
  return (
@@ -39,11 +36,8 @@ export const EditableSharingModal = ({ document, ...rest }) => {
39
36
  isOwner={isOwner(document.id)}
40
37
  link={getSharingLink(document.id)}
41
38
  onRevoke={revoke}
42
- onRevokeLink={revokeSharingLink}
43
39
  onRevokeSelf={revokeSelf}
44
40
  onShare={share}
45
- onShareByLink={shareByLink}
46
- onUpdateShareLinkPermissions={updateDocumentPermissions}
47
41
  permissions={getDocumentPermissions(document.id)}
48
42
  recipients={getRecipients(document.id)}
49
43
  sharing={getSharingForSelf(document.id)}
@@ -15,11 +15,8 @@ export const ShareModal = ({
15
15
  needsContactsPermission,
16
16
  onClose,
17
17
  onRevoke,
18
- onRevokeLink,
19
18
  onRevokeSelf,
20
19
  onShare,
21
- onShareByLink,
22
- onUpdateShareLinkPermissions,
23
20
  permissions,
24
21
  recipients,
25
22
  sharing,
@@ -43,9 +40,6 @@ export const ShareModal = ({
43
40
  documentType={documentType}
44
41
  link={link}
45
42
  onClose={onClose}
46
- onRevokeLink={onRevokeLink}
47
- onShareByLink={onShareByLink}
48
- onUpdateShareLinkPermissions={onUpdateShareLinkPermissions}
49
43
  permissions={permissions}
50
44
  />
51
45
  ) : (
@@ -59,11 +53,8 @@ export const ShareModal = ({
59
53
  needsContactsPermission={needsContactsPermission}
60
54
  onClose={onClose}
61
55
  onRevoke={onRevoke}
62
- onRevokeLink={onRevokeLink}
63
56
  onRevokeSelf={onRevokeSelf}
64
57
  onShare={onShare}
65
- onShareByLink={onShareByLink}
66
- onUpdateShareLinkPermissions={onUpdateShareLinkPermissions}
67
58
  permissions={permissions}
68
59
  recipients={recipients}
69
60
  sharing={sharing}
@@ -90,10 +81,7 @@ ShareModal.propTypes = {
90
81
  needsContactsPermission: PropTypes.bool,
91
82
  onClose: PropTypes.func.isRequired,
92
83
  onRevoke: PropTypes.func.isRequired,
93
- onRevokeLink: PropTypes.func.isRequired,
94
84
  onShare: PropTypes.func.isRequired,
95
- onShareByLink: PropTypes.func.isRequired,
96
- onUpdateShareLinkPermissions: PropTypes.func.isRequired,
97
85
  permissions: PropTypes.array.isRequired,
98
86
  recipients: PropTypes.array.isRequired,
99
87
  sharingDesc: PropTypes.string,
@@ -0,0 +1,76 @@
1
+ import { format } from 'date-fns'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ import Box from 'cozy-ui/transpiled/react/Box'
6
+ import DatePicker from 'cozy-ui/transpiled/react/DatePicker'
7
+ import Icon from 'cozy-ui/transpiled/react/Icon'
8
+ import List from 'cozy-ui/transpiled/react/List'
9
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
10
+ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
11
+ import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
12
+ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
13
+ import Switch from 'cozy-ui/transpiled/react/Switch'
14
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
15
+
16
+ export const BoxDate = ({ onChange, date, toggle, onToggle }) => {
17
+ const { t, lang } = useI18n()
18
+ const formatDate = lang === 'fr' ? 'dd/MM/yyyy' : 'MM/dd/yyyy'
19
+
20
+ const handleDateToggle = val => {
21
+ const value = val?.target?.checked ?? val
22
+ onToggle(value)
23
+ }
24
+
25
+ return (
26
+ <Box borderRadius="0.5rem" border="1px solid var(--borderMainColor)">
27
+ <List className="u-p-0">
28
+ <ListItem
29
+ button
30
+ size="large"
31
+ ellipsis={false}
32
+ onClick={() => handleDateToggle(!toggle)}
33
+ >
34
+ <ListItemIcon>
35
+ <Icon icon="calendar" />
36
+ </ListItemIcon>
37
+ <ListItemText primary={t('BoxDate.text')} />
38
+ <ListItemSecondaryAction>
39
+ <Switch
40
+ edge="end"
41
+ color="primary"
42
+ checked={toggle}
43
+ onChange={handleDateToggle}
44
+ />
45
+ </ListItemSecondaryAction>
46
+ </ListItem>
47
+ </List>
48
+ {toggle && (
49
+ <div className="u-pt-half u-ph-1 u-pb-1">
50
+ <DatePicker
51
+ className="u-w-100"
52
+ enableKeyboard
53
+ label={t('BoxDate.label')}
54
+ placeholder={format(new Date(), formatDate)}
55
+ value={date}
56
+ minDate={new Date()}
57
+ onChange={onChange}
58
+ inputProps={{
59
+ inputMode: 'numeric'
60
+ }}
61
+ KeyboardButtonProps={{
62
+ 'aria-label': t('BoxDate.label')
63
+ }}
64
+ />
65
+ </div>
66
+ )}
67
+ </Box>
68
+ )
69
+ }
70
+
71
+ BoxDate.propTypes = {
72
+ onChange: PropTypes.func.isRequired,
73
+ date: PropTypes.instanceOf(Date),
74
+ toggle: PropTypes.bool.isRequired,
75
+ onToggle: PropTypes.func.isRequired
76
+ }
@@ -0,0 +1,91 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useReducer, useRef } from 'react'
3
+
4
+ import { isDirectory as isDir } from 'cozy-client/dist/models/file'
5
+ import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
6
+ import { makeActions } from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
7
+ import Box from 'cozy-ui/transpiled/react/Box'
8
+ import Icon from 'cozy-ui/transpiled/react/Icon'
9
+ import List from 'cozy-ui/transpiled/react/List'
10
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
11
+ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
12
+ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
13
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
14
+
15
+ import { useSharingContext } from '../../hooks/useSharingContext'
16
+ import { editPermissionLink } from '../Recipient/actions/editPermissionLink'
17
+ import { readOnlyPermissionLink } from '../Recipient/actions/readOnlyPermissionLink'
18
+
19
+ export const BoxEditingRights = ({ file, editingRights, setEditingRights }) => {
20
+ const [isMenuDisplayed, toggleMenuDisplayed] = useReducer(
21
+ state => !state,
22
+ false
23
+ )
24
+ const buttonRef = useRef()
25
+ const { t } = useI18n()
26
+ const { documentType } = useSharingContext()
27
+
28
+ const isDirectory = isDir(file)
29
+
30
+ const actions = makeActions([readOnlyPermissionLink, editPermissionLink], {
31
+ t,
32
+ editingRights,
33
+ setEditingRights,
34
+ documentType,
35
+ isDirectory
36
+ })
37
+
38
+ const textSecondary =
39
+ editingRights === 'readOnly'
40
+ ? t('Share.permissionLink.readDescription')
41
+ : t('Share.permissionLink.writeDescription')
42
+
43
+ return (
44
+ <>
45
+ <Box
46
+ borderRadius="0.5rem"
47
+ border="1px solid var(--borderMainColor)"
48
+ ref={buttonRef}
49
+ >
50
+ <List className="u-p-0">
51
+ <ListItem
52
+ button
53
+ size="large"
54
+ ellipsis={false}
55
+ onClick={toggleMenuDisplayed}
56
+ >
57
+ <ListItemIcon>
58
+ <Icon icon="people" />
59
+ </ListItemIcon>
60
+ <ListItemText
61
+ primary={t('BoxEditingRights.text')}
62
+ secondary={textSecondary}
63
+ />
64
+ <ListItemIcon className="u-mr-half">
65
+ <Icon icon="bottom" />
66
+ </ListItemIcon>
67
+ </ListItem>
68
+ </List>
69
+ </Box>
70
+
71
+ <ActionsMenu
72
+ ref={buttonRef}
73
+ open={isMenuDisplayed}
74
+ docs={[file]}
75
+ actions={actions}
76
+ anchorOrigin={{
77
+ vertical: 'bottom',
78
+ horizontal: 'right'
79
+ }}
80
+ autoClose
81
+ onClose={toggleMenuDisplayed}
82
+ />
83
+ </>
84
+ )
85
+ }
86
+
87
+ BoxEditingRights.propTypes = {
88
+ file: PropTypes.object.isRequired,
89
+ editingRights: PropTypes.oneOf(['readOnly', 'write']).isRequired,
90
+ setEditingRights: PropTypes.func.isRequired
91
+ }
@@ -0,0 +1,126 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useState } from 'react'
3
+
4
+ import Box from 'cozy-ui/transpiled/react/Box'
5
+ import Icon from 'cozy-ui/transpiled/react/Icon'
6
+ import IconButton from 'cozy-ui/transpiled/react/IconButton'
7
+ import List from 'cozy-ui/transpiled/react/List'
8
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
9
+ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
10
+ import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
11
+ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
12
+ import Switch from 'cozy-ui/transpiled/react/Switch'
13
+ import TextField from 'cozy-ui/transpiled/react/TextField'
14
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
15
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
16
+
17
+ import { copyToClipboard } from './helpers'
18
+ import { checkIsPermissionHasPassword } from '../../helpers/permissions'
19
+ import { useSharingContext } from '../../hooks/useSharingContext'
20
+
21
+ export const BoxPassword = ({
22
+ file,
23
+ onChange,
24
+ password,
25
+ onToggle,
26
+ toggle,
27
+ helperText,
28
+ inputProps
29
+ }) => {
30
+ const { t } = useI18n()
31
+ const { showAlert } = useAlert()
32
+ const [displayHelper, setDisplayHelper] = useState(false)
33
+ const inputRef = React.useRef()
34
+ const { getDocumentPermissions } = useSharingContext()
35
+
36
+ const permissions = getDocumentPermissions(file._id)
37
+ const hasPassword = checkIsPermissionHasPassword(permissions)
38
+
39
+ const handlePasswordToggle = val => {
40
+ const value = val?.target?.checked ?? val
41
+ onToggle(value)
42
+ }
43
+
44
+ const handleChange = val => {
45
+ const value = val?.target?.value ?? val
46
+ onChange(value)
47
+ }
48
+ const handleOnFocus = () => {
49
+ setDisplayHelper(false)
50
+ }
51
+ const handleOnBlur = () => {
52
+ handleChange(inputRef.current.value.trim())
53
+ setDisplayHelper(true)
54
+ }
55
+
56
+ const handleCopy = async () => {
57
+ await copyToClipboard(password, { t, showAlert })
58
+ }
59
+
60
+ return (
61
+ <Box borderRadius="0.5rem" border="1px solid var(--borderMainColor)">
62
+ <List className="u-p-0">
63
+ <ListItem
64
+ button
65
+ size="large"
66
+ ellipsis={false}
67
+ onClick={() => handlePasswordToggle(!toggle)}
68
+ >
69
+ <ListItemIcon>
70
+ <Icon icon="password" />
71
+ </ListItemIcon>
72
+ <ListItemText primary={t('BoxPassword.text')} />
73
+ <ListItemSecondaryAction>
74
+ <Switch
75
+ edge="end"
76
+ color="primary"
77
+ checked={toggle}
78
+ onChange={handlePasswordToggle}
79
+ />
80
+ </ListItemSecondaryAction>
81
+ </ListItem>
82
+ </List>
83
+ {toggle && (
84
+ <div className="u-pt-half u-ph-1 u-pb-1">
85
+ <TextField
86
+ inputRef={inputRef}
87
+ autoFocus
88
+ label={t('BoxPassword.label')}
89
+ {...(hasPassword && {
90
+ placeholder: '****',
91
+ InputLabelProps: {
92
+ shrink: true
93
+ }
94
+ })}
95
+ value={password}
96
+ error={displayHelper && !!helperText}
97
+ helperText={displayHelper && helperText}
98
+ onChange={handleChange}
99
+ onFocus={handleOnFocus}
100
+ onBlur={handleOnBlur}
101
+ fullWidth
102
+ type="text"
103
+ variant="outlined"
104
+ InputProps={{
105
+ endAdornment: (
106
+ <IconButton onClick={handleCopy}>
107
+ <Icon icon="copy" />
108
+ </IconButton>
109
+ )
110
+ }}
111
+ inputProps={inputProps}
112
+ />
113
+ </div>
114
+ )}
115
+ </Box>
116
+ )
117
+ }
118
+
119
+ BoxPassword.propTypes = {
120
+ onChange: PropTypes.func.isRequired,
121
+ password: PropTypes.string,
122
+ onToggle: PropTypes.func.isRequired,
123
+ toggle: PropTypes.bool.isRequired,
124
+ helperText: PropTypes.string,
125
+ inputProps: PropTypes.object
126
+ }
@@ -0,0 +1,124 @@
1
+ import { addDays, isValid } from 'date-fns'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ import Box from 'cozy-ui/transpiled/react/Box'
6
+ import Typography from 'cozy-ui/transpiled/react/Typography'
7
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
8
+
9
+ import { BoxDate } from './BoxDate'
10
+ import { BoxEditingRights } from './BoxEditingRights'
11
+ import { BoxPassword } from './BoxPassword'
12
+ import { checkIsPermissionHasPassword } from '../../helpers/permissions'
13
+ import { useSharingContext } from '../../hooks/useSharingContext'
14
+
15
+ const PASSWORD_MIN_LENGTH = 4
16
+
17
+ export const ShareRestrictionContentModal = ({
18
+ file,
19
+ // Date
20
+ selectedDate,
21
+ setSelectedDate,
22
+ dateToggle,
23
+ setDateToggle,
24
+ setIsValidDate,
25
+ // Password
26
+ helperTextPassword,
27
+ password,
28
+ setPassword,
29
+ passwordToggle,
30
+ setPasswordToggle,
31
+ setIsValidPassword,
32
+ // Editing rights
33
+ editingRights,
34
+ setEditingRights
35
+ }) => {
36
+ const { t } = useI18n()
37
+ const { getDocumentPermissions } = useSharingContext()
38
+ const permissions = getDocumentPermissions(file._id)
39
+ const hasPassword = checkIsPermissionHasPassword(permissions)
40
+
41
+ const handlePassword = value => {
42
+ setPassword(value)
43
+ setIsValidPassword(
44
+ (hasPassword && value.trim().length === 0) ||
45
+ value.trim().length >= PASSWORD_MIN_LENGTH
46
+ )
47
+ }
48
+
49
+ const handlePasswordToggle = val => {
50
+ setPasswordToggle(val)
51
+ setPassword('')
52
+ if (val && !password) {
53
+ setIsValidPassword(hasPassword)
54
+ } else {
55
+ setIsValidPassword(true)
56
+ }
57
+ }
58
+
59
+ const handleDate = date => {
60
+ setSelectedDate(date)
61
+ setIsValidDate(isValid(date))
62
+ }
63
+
64
+ const handleDateToggle = val => {
65
+ setDateToggle(val)
66
+ if (!val) {
67
+ setSelectedDate(null)
68
+ setIsValidDate(true)
69
+ } else {
70
+ const defaultValue = val ? addDays(new Date(), 30) : null
71
+ setSelectedDate(defaultValue)
72
+ setIsValidDate(true)
73
+ }
74
+ }
75
+
76
+ return (
77
+ <Box display="flex" flexDirection="column" gridGap="1rem">
78
+ <Typography variant="h4" className="u-mb-half u-ml-half">
79
+ {t('ShareRestrictionModal.title')}
80
+ </Typography>
81
+
82
+ <BoxEditingRights
83
+ file={file}
84
+ editingRights={editingRights}
85
+ setEditingRights={setEditingRights}
86
+ />
87
+ <BoxDate
88
+ onChange={handleDate}
89
+ date={selectedDate}
90
+ onToggle={handleDateToggle}
91
+ toggle={dateToggle}
92
+ />
93
+ <BoxPassword
94
+ file={file}
95
+ onChange={handlePassword}
96
+ password={password}
97
+ onToggle={handlePasswordToggle}
98
+ toggle={passwordToggle}
99
+ helperText={helperTextPassword}
100
+ inputProps={{ minLength: PASSWORD_MIN_LENGTH }}
101
+ />
102
+ </Box>
103
+ )
104
+ }
105
+
106
+ ShareRestrictionContentModal.propTypes = {
107
+ file: PropTypes.object.isRequired,
108
+ // Date
109
+ selectedDate: PropTypes.object,
110
+ setSelectedDate: PropTypes.func.isRequired,
111
+ dateToggle: PropTypes.bool,
112
+ setDateToggle: PropTypes.func.isRequired,
113
+ setIsValidDate: PropTypes.func.isRequired,
114
+ // Password
115
+ helperTextPassword: PropTypes.string,
116
+ password: PropTypes.string,
117
+ setPassword: PropTypes.func.isRequired,
118
+ passwordToggle: PropTypes.bool.isRequired,
119
+ setPasswordToggle: PropTypes.func.isRequired,
120
+ setIsValidPassword: PropTypes.func.isRequired,
121
+ // Editing rights
122
+ editingRights: PropTypes.oneOf(['readOnly', 'write']),
123
+ setEditingRights: PropTypes.func.isRequired
124
+ }
@@ -0,0 +1,186 @@
1
+ import { addDays } from 'date-fns'
2
+ import PropTypes from 'prop-types'
3
+ import React, { useState } from 'react'
4
+
5
+ import { generateWebLink, useClient } from 'cozy-client'
6
+ import Button from 'cozy-ui/transpiled/react/Buttons'
7
+ import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
8
+ import Icon from 'cozy-ui/transpiled/react/Icon'
9
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
10
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
11
+
12
+ import { ShareRestrictionContentModal } from './ShareRestrictionContentModal'
13
+ import {
14
+ copyToClipboard,
15
+ updatePermissions,
16
+ makeTTL,
17
+ revokePermissions,
18
+ createPermissions
19
+ } from './helpers'
20
+ import {
21
+ checkIsPermissionHasExpiresDate,
22
+ checkIsPermissionHasPassword,
23
+ checkIsReadOnlyPermissions,
24
+ getPermissionExpiresDate
25
+ } from '../../helpers/permissions'
26
+ import { useSharingContext } from '../../hooks/useSharingContext'
27
+
28
+ const PASSWORD_MIN_LENGTH = 4
29
+
30
+ export const ShareRestrictionModal = ({ file, onClose }) => {
31
+ const client = useClient()
32
+ const { t } = useI18n()
33
+ const { showAlert } = useAlert()
34
+ const [password, setPassword] = useState('')
35
+ const [isValidDate, setIsValidDate] = useState(true)
36
+ const [isValidPassword, setIsValidPassword] = useState(true)
37
+ const [loading, setLoading] = useState(false)
38
+
39
+ const {
40
+ documentType,
41
+ getDocumentPermissions,
42
+ updateDocumentPermissions,
43
+ shareByLink,
44
+ getSharingLink,
45
+ revokeSharingLink
46
+ } = useSharingContext()
47
+
48
+ const hasSharingLink = getSharingLink(file._id) !== null
49
+ const permissions = getDocumentPermissions(file._id)
50
+ const isReadOnlyPermissions = checkIsReadOnlyPermissions(permissions)
51
+ const hasPassword = checkIsPermissionHasPassword(permissions)
52
+ const hasExpiresDate = checkIsPermissionHasExpiresDate(permissions)
53
+ const expiresDate = getPermissionExpiresDate(permissions)
54
+ const defaultDate = expiresDate
55
+ ? new Date(expiresDate)
56
+ : addDays(new Date(), 30)
57
+
58
+ const [selectedDate, setSelectedDate] = useState(defaultDate)
59
+ const [dateToggle, setDateToggle] = useState(
60
+ permissions.length > 0 ? hasExpiresDate : true
61
+ )
62
+ const [passwordToggle, setPasswordToggle] = useState(hasPassword)
63
+ const [editingRights, setEditingRights] = useState(
64
+ isReadOnlyPermissions || permissions.length === 0 ? 'readOnly' : 'write'
65
+ )
66
+
67
+ const helperTextPassword = !isValidPassword
68
+ ? t('ShareRestrictionModal.invalidPasswordMessage', {
69
+ smart_count: PASSWORD_MIN_LENGTH - password.length
70
+ })
71
+ : null
72
+
73
+ const handleClick = async () => {
74
+ setLoading(true)
75
+ // If the file is not shared, we create a new sharing link
76
+ if (!hasSharingLink) {
77
+ const ttl = makeTTL(dateToggle && selectedDate)
78
+ const { data: perms } = await createPermissions({
79
+ file,
80
+ t,
81
+ ttl,
82
+ password,
83
+ editingRights,
84
+ documentType,
85
+ shareByLink,
86
+ showAlert
87
+ })
88
+ const url = generateWebLink({
89
+ cozyUrl: client.getStackClient().uri,
90
+ searchParams: [['sharecode', perms.attributes.shortcodes.code]],
91
+ pathname: '/public',
92
+ slug: 'drive',
93
+ subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
94
+ })
95
+ await copyToClipboard(url, { t, showAlert })
96
+ onClose()
97
+ } else {
98
+ const [{ data: perms }] = await updatePermissions({
99
+ file,
100
+ t,
101
+ dateToggle,
102
+ selectedDate,
103
+ passwordToggle,
104
+ password,
105
+ editingRights,
106
+ documentType,
107
+ updateDocumentPermissions,
108
+ showAlert
109
+ })
110
+ const url = generateWebLink({
111
+ cozyUrl: client.getStackClient().uri,
112
+ searchParams: [['sharecode', perms.attributes.shortcodes.code]],
113
+ pathname: '/public',
114
+ slug: 'drive',
115
+ subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
116
+ })
117
+ await copyToClipboard(url, { t, showAlert })
118
+ onClose()
119
+ }
120
+ }
121
+
122
+ const handleRevokeLink = async () => {
123
+ setLoading(true)
124
+ await revokePermissions({
125
+ file,
126
+ t,
127
+ documentType,
128
+ revokeSharingLink,
129
+ showAlert
130
+ })
131
+ onClose()
132
+ }
133
+
134
+ return (
135
+ <ConfirmDialog
136
+ open
137
+ onClose={onClose}
138
+ content={
139
+ <ShareRestrictionContentModal
140
+ file={file}
141
+ // Date
142
+ dateToggle={dateToggle}
143
+ setDateToggle={setDateToggle}
144
+ setSelectedDate={setSelectedDate}
145
+ selectedDate={selectedDate}
146
+ setIsValidDate={setIsValidDate}
147
+ // Password
148
+ helperTextPassword={helperTextPassword}
149
+ passwordToggle={passwordToggle}
150
+ setPasswordToggle={setPasswordToggle}
151
+ password={password}
152
+ setPassword={setPassword}
153
+ setIsValidPassword={setIsValidPassword}
154
+ // Editing rights
155
+ editingRights={editingRights}
156
+ setEditingRights={setEditingRights}
157
+ />
158
+ }
159
+ actions={
160
+ <>
161
+ {hasSharingLink && (
162
+ <Button
163
+ label={t('Share.permissionLink.deactivate')}
164
+ variant="secondary"
165
+ color="error"
166
+ startIcon={<Icon icon="trash" />}
167
+ onClick={handleRevokeLink}
168
+ busy={loading}
169
+ />
170
+ )}
171
+ <Button
172
+ label={t('ShareRestrictionModal.action.confirm')}
173
+ onClick={handleClick}
174
+ disabled={!isValidDate || !isValidPassword}
175
+ busy={loading}
176
+ />
177
+ </>
178
+ }
179
+ />
180
+ )
181
+ }
182
+
183
+ ShareRestrictionModal.propTypes = {
184
+ file: PropTypes.object.isRequired,
185
+ onClose: PropTypes.func
186
+ }