cozy-sharing 33.5.0 → 33.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +1 -4
- package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +3 -1
- package/dist/components/Recipient/LinkRecipient.js +40 -17
- package/dist/components/Recipient/LinkRecipientPermissions.js +7 -6
- package/dist/components/Recipient/MemberRecipient.js +4 -5
- package/dist/components/Recipient/MemberRecipientLite.js +2 -0
- package/dist/components/Recipient/MemberRecipientPermissions.js +4 -6
- package/dist/components/Recipient/MemberRecipientStatus.js +19 -16
- package/dist/components/Recipient/MemberRecipientStatus.spec.js +102 -0
- package/dist/components/Recipient/RecipientConfirm.js +1 -4
- package/dist/components/Recipient/RecipientList.js +2 -0
- package/dist/components/ShareByEmail.js +1 -4
- package/dist/components/ShareDialogCozyToCozy.js +1 -4
- package/dist/components/ShareModal/ShareModal.js +1 -5
- package/dist/components/ShareModal/SharingDetailsModal.js +6 -38
- package/dist/components/SharedDrive/EditSharedDriveModal.js +1 -4
- package/dist/components/WhoHasAccess.js +4 -0
- package/dist/state.js +1 -1
- package/dist/styles/share.styl +0 -21
- package/dist/stylesheet.css +0 -22
- package/locales/en.json +1 -2
- package/locales/fr.json +1 -2
- package/locales/ru.json +1 -2
- package/locales/vi.json +1 -2
- package/package.json +2 -2
- package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +2 -0
- package/src/components/Recipient/LinkRecipient.jsx +50 -15
- package/src/components/Recipient/LinkRecipientPermissions.jsx +27 -20
- package/src/components/Recipient/MemberRecipient.jsx +3 -1
- package/src/components/Recipient/MemberRecipientLite.jsx +2 -0
- package/src/components/Recipient/MemberRecipientPermissions.jsx +10 -5
- package/src/components/Recipient/MemberRecipientStatus.jsx +27 -18
- package/src/components/Recipient/MemberRecipientStatus.spec.jsx +97 -0
- package/src/components/Recipient/RecipientList.jsx +2 -0
- package/src/components/ShareModal/ShareModal.jsx +1 -5
- package/src/components/ShareModal/SharingDetailsModal.jsx +3 -47
- package/src/components/WhoHasAccess.jsx +3 -0
- package/src/state.js +1 -1
- package/src/styles/share.styl +0 -21
package/dist/stylesheet.css
CHANGED
|
@@ -339,28 +339,6 @@
|
|
|
339
339
|
input[type=text] {
|
|
340
340
|
width: 100%;
|
|
341
341
|
}
|
|
342
|
-
.share__share-details-created___z3nvO,
|
|
343
|
-
.share__share-details-perm___3HjxK {
|
|
344
|
-
font-size: 1rem;
|
|
345
|
-
margin: 0.5rem 0 0.5rem 3.5rem;
|
|
346
|
-
padding-left: 1.5rem;
|
|
347
|
-
background-position: 0 center;
|
|
348
|
-
background-repeat: no-repeat;
|
|
349
|
-
}
|
|
350
|
-
.share__share-details-created___z3nvO {
|
|
351
|
-
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTZweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8ZGVmcz48L2RlZnM+CiAgICA8ZyBpZD0iMTZweCIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTIyNC4wMDAwMDAsIC0xOTIuMDAwMDAwKSI+CiAgICAgICAgPGcgaWQ9InNsaWNlcyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzIuMDAwMDAwLCAzMi4wMDAwMDApIj48L2c+CiAgICAgICAgPHBhdGggZD0iTTIzNywxOTMgTDI0MCwxOTMgTDI0MCwxOTUgTDIyNCwxOTUgTDIyNCwxOTMgTDIyNywxOTMgTDIyNywxOTIgTDIyOSwxOTIgTDIyOSwxOTMgTDIzNSwxOTMgTDIzNSwxOTIgTDIzNywxOTIgTDIzNywxOTMgWiBNMjI0LDE5NiBMMjQwLDE5NiBMMjQwLDIwNi45OTc1MjcgQzI0MCwyMDcuNTUxMTc3IDIzOS41NTUzNjksMjA4IDIzOC45OTkxMjgsMjA4IEwyMjUuMDAwODcyLDIwOCBDMjI0LjQ0ODEwNiwyMDggMjI0LDIwNy41NDQyMzkgMjI0LDIwNi45OTc1MjcgTDIyNCwxOTYgWiBNMjI2LDE5OCBMMjI2LDIwNiBMMjM4LDIwNiBMMjM4LDE5OCBMMjI2LDE5OCBaIE0yMzIsMjAxIEwyMzcsMjAxIEwyMzcsMjA1IEwyMzIsMjA1IEwyMzIsMjAxIFoiIGlkPSJjYWxlbmRhciIgZmlsbD0iIzk1OTk5RCI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4=");
|
|
352
|
-
}
|
|
353
|
-
.share__share-details-perm___3HjxK {
|
|
354
|
-
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBmaWxsPSIjOTU5OTlEIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMDEuNSw5OS41IEwxOTIsMTA5LjAyNTM5MSBMMTkyLDExMiBMMTk1LjAzNzcyLDExMiBMMjA0LjUsMTAyLjUgTDIwMS41LDk5LjUgWiBNMjA2LjkxMjE1NCw5Ni45MTIxNTQxIEMyMDYuMTMyMjQzLDk2LjEzMjI0MjkgMjA0Ljg2OTE0NCw5Ni4xMzA4NTU2IDIwNC4wODkyNjQsOTYuOTEwNzM2MSBMMjAzLDk4IEwyMDYuMDMwNzYyLDEwMSBMMjA3LjA5MjI3MSw5OS45MjUyNjYzIEMyMDcuODY5NzM4LDk5LjEzODExMzQgMjA3Ljg2Mzc3Nyw5Ny44NjM3NzcyIDIwNy4wODc4NDYsOTcuMDg3ODQ1OSBMMjA2LjkxMjE1NCw5Ni45MTIxNTQxIFogTTE5OSwxMTAgTDIwNC45OTcwNzEsMTEwIEMyMDUuNTUwOTczLDExMCAyMDYsMTEwLjQ0Mzg2NSAyMDYsMTExIEMyMDYsMTExLjU1MjI4NSAyMDUuNTUzNjg5LDExMiAyMDUuMDAyNDU1LDExMiBMMTk3LDExMiBMMTk5LDExMCBaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTkyIC05NikiLz4KPC9zdmc+Cg==");
|
|
355
|
-
margin-bottom: 0.2rem;
|
|
356
|
-
}
|
|
357
|
-
.share__share-details-perm-desc___3HyHu {
|
|
358
|
-
font-size: 0.875rem;
|
|
359
|
-
margin: 0 0 0.5rem 3.5rem;
|
|
360
|
-
padding-left: 1.5rem;
|
|
361
|
-
line-height: 1.5;
|
|
362
|
-
color: var(--secondaryTextColor);
|
|
363
|
-
}
|
|
364
342
|
/* imported from autosuggest.styl */
|
|
365
343
|
|
|
366
344
|
.autosuggest__container___1Yro7 {
|
package/locales/en.json
CHANGED
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
"you": "You",
|
|
24
24
|
"anyoneWithTheLink": "Anyone with the link",
|
|
25
25
|
"linkWithPassword": "Anyone with a password",
|
|
26
|
-
"expires": "Until %{date}"
|
|
27
|
-
"accessCount": "%{count} people have access"
|
|
26
|
+
"expires": "Until %{date}"
|
|
28
27
|
},
|
|
29
28
|
"create-cozy": "Create |||| Create my Twake",
|
|
30
29
|
"members": {
|
package/locales/fr.json
CHANGED
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
"you": "Vous",
|
|
24
24
|
"anyoneWithTheLink": "Tous les utilisateurs qui ont le lien",
|
|
25
25
|
"linkWithPassword": "Tous les utilisateurs avec le mot de passe",
|
|
26
|
-
"expires": "Jusqu'au %{date}"
|
|
27
|
-
"accessCount": "%{count} personnes y ont accès"
|
|
26
|
+
"expires": "Jusqu'au %{date}"
|
|
28
27
|
},
|
|
29
28
|
"create-cozy": "Créer |||| Créer mon Twake",
|
|
30
29
|
"members": {
|
package/locales/ru.json
CHANGED
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
"you": "Вы",
|
|
24
24
|
"anyoneWithTheLink": "Любой, у кого есть ссылка",
|
|
25
25
|
"linkWithPassword": "Любой с паролем",
|
|
26
|
-
"expires": "До %{date}"
|
|
27
|
-
"accessCount": "%{count} человек имеют доступ"
|
|
26
|
+
"expires": "До %{date}"
|
|
28
27
|
},
|
|
29
28
|
"create-cozy": "Создать |||| Создать мой Twake",
|
|
30
29
|
"members": {
|
package/locales/vi.json
CHANGED
|
@@ -23,8 +23,7 @@
|
|
|
23
23
|
"you": "Bạn",
|
|
24
24
|
"anyoneWithTheLink": "Bất kỳ ai có liên kết",
|
|
25
25
|
"linkWithPassword": "Bất kỳ ai có mật khẩu",
|
|
26
|
-
"expires": "Cho đến %{date}"
|
|
27
|
-
"accessCount": "%{count} người có quyền truy cập"
|
|
26
|
+
"expires": "Cho đến %{date}"
|
|
28
27
|
},
|
|
29
28
|
"create-cozy": "Tạo |||| Tạo Twake của tôi",
|
|
30
29
|
"members": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "33.
|
|
3
|
+
"version": "33.6.0",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"sideEffects": [
|
|
84
84
|
"*.css"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "fc451fb2e649fffe6bfc8f16ff812ba4c31531cf"
|
|
87
87
|
}
|
|
@@ -24,16 +24,51 @@ import { FADE_IN_DURATION } from '../../helpers/recipients'
|
|
|
24
24
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
25
25
|
import { ShareRestrictionModal } from '../ShareRestrictionModal/ShareRestrictionModal'
|
|
26
26
|
|
|
27
|
+
const LinkRecipientTextReadOnly = ({ textPrimary, textSecondary }) => {
|
|
28
|
+
return (
|
|
29
|
+
<ListItemText
|
|
30
|
+
primary={
|
|
31
|
+
<div className="u-flex u-flex-items-center">
|
|
32
|
+
<Typography>{textPrimary}</Typography>
|
|
33
|
+
</div>
|
|
34
|
+
}
|
|
35
|
+
secondary={textSecondary}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const LinkRecipientText = ({ onClick, textPrimary, textSecondary }) => {
|
|
41
|
+
return (
|
|
42
|
+
<ListItemText
|
|
43
|
+
onClick={onClick}
|
|
44
|
+
primary={
|
|
45
|
+
<div className="u-flex u-flex-items-center">
|
|
46
|
+
<Typography className="u-c-pointer ">{textPrimary}</Typography>
|
|
47
|
+
<IconButton size="small" className="u-ml-half">
|
|
48
|
+
<Icon icon={Gear} />
|
|
49
|
+
</IconButton>
|
|
50
|
+
</div>
|
|
51
|
+
}
|
|
52
|
+
secondary={textSecondary}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
27
57
|
const LinkRecipient = props => {
|
|
28
58
|
const { t, f, lang } = useI18n()
|
|
29
59
|
const { isMobile } = useBreakpoints()
|
|
30
60
|
const { getDocumentPermissions } = useSharingContext()
|
|
31
61
|
|
|
32
|
-
const {
|
|
62
|
+
const {
|
|
63
|
+
recipientConfirmationData,
|
|
64
|
+
verifyRecipient,
|
|
65
|
+
fadeIn,
|
|
66
|
+
document,
|
|
67
|
+
isReadOnly
|
|
68
|
+
} = props
|
|
33
69
|
|
|
34
70
|
const [openShareRestrictionModal, setOpenShareRestrictionModal] =
|
|
35
71
|
useState(false)
|
|
36
|
-
|
|
37
72
|
const permissions = getDocumentPermissions(document?._id)
|
|
38
73
|
const hasPassword = checkIsPermissionHasPassword(permissions)
|
|
39
74
|
const expiresDate = getPermissionExpiresDate(permissions)
|
|
@@ -57,7 +92,7 @@ const LinkRecipient = props => {
|
|
|
57
92
|
verifyRecipient={verifyRecipient}
|
|
58
93
|
/>
|
|
59
94
|
) : (
|
|
60
|
-
<LinkRecipientPermissions {...props}
|
|
95
|
+
<LinkRecipientPermissions {...props} />
|
|
61
96
|
)
|
|
62
97
|
|
|
63
98
|
return (
|
|
@@ -68,18 +103,18 @@ const LinkRecipient = props => {
|
|
|
68
103
|
<Icon icon={LinkIcon} />
|
|
69
104
|
</Avatar>
|
|
70
105
|
</ListItemIcon>
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
106
|
+
{isReadOnly ? (
|
|
107
|
+
<LinkRecipientTextReadOnly
|
|
108
|
+
textPrimary={textPrimary}
|
|
109
|
+
textSecondary={textSecondary}
|
|
110
|
+
/>
|
|
111
|
+
) : (
|
|
112
|
+
<LinkRecipientText
|
|
113
|
+
onClick={() => setOpenShareRestrictionModal(true)}
|
|
114
|
+
textPrimary={textPrimary}
|
|
115
|
+
textSecondary={textSecondary}
|
|
116
|
+
/>
|
|
117
|
+
)}
|
|
83
118
|
{RightPart}
|
|
84
119
|
{openShareRestrictionModal && (
|
|
85
120
|
<ShareRestrictionModal
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
divider
|
|
8
8
|
} from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
|
|
9
9
|
import DropdownButton from 'cozy-ui/transpiled/react/DropdownButton'
|
|
10
|
+
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
10
11
|
import { useI18n } from 'twake-i18n'
|
|
11
12
|
|
|
12
13
|
import { revokeLink } from './actions/revokeLink'
|
|
@@ -17,7 +18,7 @@ import { checkIsReadOnlyPermissions } from '../../helpers/permissions'
|
|
|
17
18
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
18
19
|
import { WRITE_PERMS, READ_ONLY_PERMS } from '../ShareRestrictionModal/helpers'
|
|
19
20
|
|
|
20
|
-
const LinkRecipientPermissions = ({
|
|
21
|
+
const LinkRecipientPermissions = ({ document, isReadOnly }) => {
|
|
21
22
|
const { t } = useI18n()
|
|
22
23
|
const buttonRef = useRef()
|
|
23
24
|
const [isMenuDisplayed, setMenuDisplayed] = useState(false)
|
|
@@ -56,30 +57,36 @@ const LinkRecipientPermissions = ({ className, document }) => {
|
|
|
56
57
|
handleRevocation
|
|
57
58
|
})
|
|
58
59
|
|
|
60
|
+
const shouldShowMenu = !isReadOnly
|
|
61
|
+
|
|
59
62
|
return (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
<>
|
|
64
|
+
{!shouldShowMenu && (
|
|
65
|
+
<Typography variant="body2">{t(`Share.type.${type}`)}</Typography>
|
|
66
|
+
)}
|
|
67
|
+
{shouldShowMenu && (
|
|
68
|
+
<>
|
|
69
|
+
<DropdownButton
|
|
70
|
+
ref={buttonRef}
|
|
71
|
+
textVariant="body2"
|
|
72
|
+
onClick={toggleMenu}
|
|
73
|
+
>
|
|
74
|
+
{t(`Share.type.${type}`)}
|
|
75
|
+
</DropdownButton>
|
|
76
|
+
<ActionsMenu
|
|
77
|
+
ref={buttonRef}
|
|
78
|
+
open={isMenuDisplayed}
|
|
79
|
+
actions={actions}
|
|
80
|
+
autoClose
|
|
81
|
+
onClose={hideMenu}
|
|
82
|
+
/>
|
|
83
|
+
</>
|
|
84
|
+
)}
|
|
85
|
+
</>
|
|
78
86
|
)
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
LinkRecipientPermissions.propTypes = {
|
|
82
|
-
className: PropTypes.string,
|
|
83
90
|
document: PropTypes.object.isRequired
|
|
84
91
|
}
|
|
85
92
|
|
|
@@ -46,7 +46,7 @@ const MemberRecipient = props => {
|
|
|
46
46
|
verifyRecipient={verifyRecipient}
|
|
47
47
|
/>
|
|
48
48
|
) : (
|
|
49
|
-
<MemberRecipientPermissions {...props}
|
|
49
|
+
<MemberRecipientPermissions {...props} />
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
return (
|
|
@@ -66,6 +66,8 @@ const MemberRecipient = props => {
|
|
|
66
66
|
status={status}
|
|
67
67
|
isMe={isMe}
|
|
68
68
|
instance={instance}
|
|
69
|
+
email={rest.email}
|
|
70
|
+
name={rest.name || rest.public_name}
|
|
69
71
|
/>
|
|
70
72
|
}
|
|
71
73
|
/>
|
|
@@ -38,6 +38,8 @@ const MemberRecipientLite = ({ recipient, isOwner, ...props }) => {
|
|
|
38
38
|
status={recipient.status}
|
|
39
39
|
isMe={isMe}
|
|
40
40
|
instance={recipient.instance}
|
|
41
|
+
email={recipient.email}
|
|
42
|
+
name={recipient.name || recipient.public_name}
|
|
41
43
|
typographyProps={{ noWrap: true }}
|
|
42
44
|
/>
|
|
43
45
|
}
|
|
@@ -21,11 +21,11 @@ const log = minilog('MemberRecipientPermissions')
|
|
|
21
21
|
|
|
22
22
|
const MemberRecipientPermissions = ({
|
|
23
23
|
isOwner,
|
|
24
|
+
isReadOnly,
|
|
24
25
|
status,
|
|
25
26
|
instance,
|
|
26
27
|
type,
|
|
27
28
|
document,
|
|
28
|
-
className,
|
|
29
29
|
onRevoke,
|
|
30
30
|
onRevokeSelf,
|
|
31
31
|
sharingId,
|
|
@@ -44,6 +44,7 @@ const MemberRecipientPermissions = ({
|
|
|
44
44
|
instance !== undefined && instance === client.options.uri
|
|
45
45
|
const contactIsOwner = status === 'owner'
|
|
46
46
|
const shouldShowMenu =
|
|
47
|
+
!isReadOnly &&
|
|
47
48
|
!revoking &&
|
|
48
49
|
!contactIsOwner &&
|
|
49
50
|
((instanceMatchesClient && !isOwner) || isOwner)
|
|
@@ -107,10 +108,14 @@ const MemberRecipientPermissions = ({
|
|
|
107
108
|
)
|
|
108
109
|
|
|
109
110
|
return (
|
|
110
|
-
|
|
111
|
+
<>
|
|
111
112
|
{revoking && <Spinner />}
|
|
112
|
-
{!shouldShowMenu &&
|
|
113
|
-
<Typography variant="body2">
|
|
113
|
+
{!shouldShowMenu && (
|
|
114
|
+
<Typography variant="body2">
|
|
115
|
+
{contactIsOwner
|
|
116
|
+
? t(`Share.status.${status}`)
|
|
117
|
+
: t(`Share.type.${type}`)}
|
|
118
|
+
</Typography>
|
|
114
119
|
)}
|
|
115
120
|
{shouldShowMenu && (
|
|
116
121
|
<>
|
|
@@ -140,7 +145,7 @@ const MemberRecipientPermissions = ({
|
|
|
140
145
|
</IconButton>
|
|
141
146
|
</>
|
|
142
147
|
)}
|
|
143
|
-
|
|
148
|
+
</>
|
|
144
149
|
)
|
|
145
150
|
}
|
|
146
151
|
|
|
@@ -1,42 +1,51 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
1
2
|
import React from 'react'
|
|
2
3
|
|
|
3
|
-
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
4
|
-
import EyeIcon from 'cozy-ui/transpiled/react/Icons/Eye'
|
|
5
|
-
import PaperplaneIcon from 'cozy-ui/transpiled/react/Icons/Paperplane'
|
|
6
|
-
import ToTheCloudIcon from 'cozy-ui/transpiled/react/Icons/ToTheCloud'
|
|
7
4
|
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
8
5
|
import { useI18n } from 'twake-i18n'
|
|
9
6
|
|
|
10
|
-
const MemberRecipientStatus = ({
|
|
7
|
+
const MemberRecipientStatus = ({
|
|
8
|
+
status,
|
|
9
|
+
isMe,
|
|
10
|
+
instance,
|
|
11
|
+
email,
|
|
12
|
+
name,
|
|
13
|
+
typographyProps
|
|
14
|
+
}) => {
|
|
11
15
|
const { t } = useI18n()
|
|
12
16
|
|
|
13
17
|
const isSendingEmail = !isMe && status === 'mail-not-sent'
|
|
14
18
|
const isReady = isMe || status === 'ready' || status === 'owner'
|
|
15
|
-
let text
|
|
19
|
+
let text
|
|
16
20
|
if (isReady) {
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
// Hide the email when the parent already uses it as the primary text
|
|
22
|
+
// (getDisplayName falls back to email when the recipient has no name).
|
|
23
|
+
// Keep the instance visible when there is no email at all, so the user
|
|
24
|
+
// can still tell the recipient lives on a different Cozy instance.
|
|
25
|
+
text = isMe || name || !email ? email || instance : ''
|
|
19
26
|
} else if (isSendingEmail) {
|
|
20
27
|
text = t('Share.status.mail-not-sent')
|
|
21
|
-
icon = PaperplaneIcon
|
|
22
28
|
} else {
|
|
23
29
|
const supportedStatus = ['pending', 'seen']
|
|
24
30
|
text = supportedStatus.includes(status)
|
|
25
31
|
? t(`Share.status.${status}`)
|
|
26
32
|
: t('Share.status.pending')
|
|
27
|
-
|
|
28
|
-
icon = status === 'seen' ? EyeIcon : PaperplaneIcon
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
return (
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<Typography variant="caption" color="textSecondary" {...typographyProps}>
|
|
36
|
-
{text}
|
|
37
|
-
</Typography>
|
|
38
|
-
</div>
|
|
36
|
+
<Typography variant="caption" color="textSecondary" {...typographyProps}>
|
|
37
|
+
{text}
|
|
38
|
+
</Typography>
|
|
39
39
|
)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
MemberRecipientStatus.propTypes = {
|
|
43
|
+
status: PropTypes.string,
|
|
44
|
+
isMe: PropTypes.bool,
|
|
45
|
+
instance: PropTypes.string,
|
|
46
|
+
email: PropTypes.string,
|
|
47
|
+
name: PropTypes.string,
|
|
48
|
+
typographyProps: PropTypes.object
|
|
49
|
+
}
|
|
50
|
+
|
|
42
51
|
export default MemberRecipientStatus
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { render } from '@testing-library/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import MemberRecipientStatus from './MemberRecipientStatus'
|
|
5
|
+
import AppLike from '../../../test/AppLike'
|
|
6
|
+
|
|
7
|
+
describe('MemberRecipientStatus component', () => {
|
|
8
|
+
const setup = props =>
|
|
9
|
+
render(
|
|
10
|
+
<AppLike>
|
|
11
|
+
<MemberRecipientStatus {...props} />
|
|
12
|
+
</AppLike>
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
it('should show email when status is ready and recipient has a name', () => {
|
|
16
|
+
const { getByText } = setup({
|
|
17
|
+
status: 'ready',
|
|
18
|
+
isMe: false,
|
|
19
|
+
email: 'other@example.com',
|
|
20
|
+
instance: 'foo.mycozy.cloud',
|
|
21
|
+
name: 'Other Person'
|
|
22
|
+
})
|
|
23
|
+
expect(getByText('other@example.com')).toBeTruthy()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should render nothing when recipient has no name and status is ready', () => {
|
|
27
|
+
const { queryByText } = setup({
|
|
28
|
+
status: 'ready',
|
|
29
|
+
isMe: false,
|
|
30
|
+
email: 'other@example.com',
|
|
31
|
+
instance: 'foo.mycozy.cloud'
|
|
32
|
+
})
|
|
33
|
+
expect(queryByText('other@example.com')).toBe(null)
|
|
34
|
+
expect(queryByText('foo.mycozy.cloud')).toBe(null)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should show email when isMe is true regardless of status', () => {
|
|
38
|
+
const { getByText } = setup({
|
|
39
|
+
status: 'pending',
|
|
40
|
+
isMe: true,
|
|
41
|
+
email: 'me@example.com'
|
|
42
|
+
})
|
|
43
|
+
expect(getByText('me@example.com')).toBeTruthy()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('should fallback to instance when email is missing and status is ready', () => {
|
|
47
|
+
const { getByText } = setup({
|
|
48
|
+
status: 'ready',
|
|
49
|
+
isMe: false,
|
|
50
|
+
instance: 'foo.mycozy.cloud'
|
|
51
|
+
})
|
|
52
|
+
expect(getByText('foo.mycozy.cloud')).toBeTruthy()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('should show email when status is owner, not isMe, and recipient has a name', () => {
|
|
56
|
+
const { getByText } = setup({
|
|
57
|
+
status: 'owner',
|
|
58
|
+
isMe: false,
|
|
59
|
+
email: 'owner@example.com',
|
|
60
|
+
instance: 'foo.mycozy.cloud',
|
|
61
|
+
name: 'Owner Person'
|
|
62
|
+
})
|
|
63
|
+
expect(getByText('owner@example.com')).toBeTruthy()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('should show "Sending invitation mail..." when status is mail-not-sent and not isMe', () => {
|
|
67
|
+
const { getByText } = setup({
|
|
68
|
+
status: 'mail-not-sent',
|
|
69
|
+
isMe: false
|
|
70
|
+
})
|
|
71
|
+
expect(getByText('Sending invitation mail...')).toBeTruthy()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('should show "Invitation sent" when status is pending', () => {
|
|
75
|
+
const { getByText } = setup({
|
|
76
|
+
status: 'pending',
|
|
77
|
+
isMe: false
|
|
78
|
+
})
|
|
79
|
+
expect(getByText('Invitation sent')).toBeTruthy()
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('should show "Invitation seen" when status is seen', () => {
|
|
83
|
+
const { getByText } = setup({
|
|
84
|
+
status: 'seen',
|
|
85
|
+
isMe: false
|
|
86
|
+
})
|
|
87
|
+
expect(getByText('Invitation seen')).toBeTruthy()
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should fallback to "Invitation sent" for unknown status', () => {
|
|
91
|
+
const { getByText } = setup({
|
|
92
|
+
status: 'unknown-status',
|
|
93
|
+
isMe: false
|
|
94
|
+
})
|
|
95
|
+
expect(getByText('Invitation sent')).toBeTruthy()
|
|
96
|
+
})
|
|
97
|
+
})
|
|
@@ -10,6 +10,7 @@ const RecipientList = ({
|
|
|
10
10
|
recipientsToBeConfirmed,
|
|
11
11
|
isOwner,
|
|
12
12
|
isSharedDrive,
|
|
13
|
+
isReadOnly,
|
|
13
14
|
document,
|
|
14
15
|
documentType,
|
|
15
16
|
onRevoke,
|
|
@@ -49,6 +50,7 @@ const RecipientList = ({
|
|
|
49
50
|
key={recipient.index}
|
|
50
51
|
isOwner={isOwner}
|
|
51
52
|
isSharedDrive={isSharedDrive}
|
|
53
|
+
isReadOnly={isReadOnly}
|
|
52
54
|
document={document}
|
|
53
55
|
documentType={documentType}
|
|
54
56
|
onRevoke={onRevoke}
|
|
@@ -22,8 +22,6 @@ export const ShareModal = withLocales(props => {
|
|
|
22
22
|
isOwner,
|
|
23
23
|
canReshare,
|
|
24
24
|
documentType,
|
|
25
|
-
getOwner,
|
|
26
|
-
getSharingType,
|
|
27
25
|
getRecipients,
|
|
28
26
|
revokeSelf,
|
|
29
27
|
allLoaded
|
|
@@ -48,11 +46,9 @@ export const ShareModal = withLocales(props => {
|
|
|
48
46
|
|
|
49
47
|
return (
|
|
50
48
|
<SharingDetailsModal
|
|
49
|
+
recipients={getRecipients(document.id)}
|
|
51
50
|
document={document}
|
|
52
51
|
documentType={documentType}
|
|
53
|
-
owner={getOwner(document.id)}
|
|
54
|
-
sharingType={getSharingType(document.id)}
|
|
55
|
-
recipients={getRecipients(document.id)}
|
|
56
52
|
onRevoke={revokeSelf}
|
|
57
53
|
onRevokeSelf={handleRevokeSelf}
|
|
58
54
|
{...rest}
|
|
@@ -1,29 +1,21 @@
|
|
|
1
|
-
import cx from 'classnames'
|
|
2
1
|
import PropTypes from 'prop-types'
|
|
3
2
|
import React from 'react'
|
|
4
3
|
|
|
5
4
|
import { Dialog } from 'cozy-ui/transpiled/react/CozyDialogs'
|
|
6
|
-
import Divider from 'cozy-ui/transpiled/react/Divider'
|
|
7
|
-
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
|
|
8
5
|
import { useI18n } from 'twake-i18n'
|
|
9
6
|
|
|
10
|
-
import { getDisplayName } from '../../models'
|
|
11
7
|
import styles from '../../styles/share.styl'
|
|
12
|
-
import OwnerIdentity from '../Identity/OwnerIdentity'
|
|
13
8
|
import WhoHasAccess from '../WhoHasAccess'
|
|
14
9
|
|
|
15
10
|
export const SharingDetailsModal = ({
|
|
16
11
|
onClose,
|
|
17
|
-
sharingType,
|
|
18
|
-
owner,
|
|
19
12
|
recipients,
|
|
20
13
|
document,
|
|
21
14
|
documentType = 'Document',
|
|
22
15
|
onRevoke,
|
|
23
16
|
onRevokeSelf
|
|
24
17
|
}) => {
|
|
25
|
-
const { t
|
|
26
|
-
const { isMobile } = useBreakpoints()
|
|
18
|
+
const { t } = useI18n()
|
|
27
19
|
|
|
28
20
|
return (
|
|
29
21
|
<Dialog
|
|
@@ -34,50 +26,14 @@ export const SharingDetailsModal = ({
|
|
|
34
26
|
title={t(`${documentType}.share.details.title`)}
|
|
35
27
|
content={
|
|
36
28
|
<div className={styles['share-modal-content']}>
|
|
37
|
-
<div
|
|
38
|
-
className={cx(
|
|
39
|
-
styles['share-details'],
|
|
40
|
-
isMobile ? 'u-ph-1 u-pt-1-half' : 'u-ph-2 u-pt-1'
|
|
41
|
-
)}
|
|
42
|
-
>
|
|
43
|
-
{owner ? (
|
|
44
|
-
<OwnerIdentity
|
|
45
|
-
name={t(`${documentType}.share.sharedBy`, {
|
|
46
|
-
name: getDisplayName(owner)
|
|
47
|
-
})}
|
|
48
|
-
url={owner.instance}
|
|
49
|
-
/>
|
|
50
|
-
) : null}
|
|
51
|
-
<div className={styles['share-details-created']}>
|
|
52
|
-
{t(`${documentType}.share.details.createdAt`, {
|
|
53
|
-
date: f(document.created_at || null, 'do LLLL yyyy')
|
|
54
|
-
})}
|
|
55
|
-
</div>
|
|
56
|
-
<div className={styles['share-details-perm']}>
|
|
57
|
-
{t(
|
|
58
|
-
`${documentType}.share.details.${
|
|
59
|
-
sharingType === 'one-way' ? 'ro' : 'rw'
|
|
60
|
-
}`
|
|
61
|
-
)}
|
|
62
|
-
</div>
|
|
63
|
-
<div className={styles['share-details-perm-desc']}>
|
|
64
|
-
{t(
|
|
65
|
-
`${documentType}.share.details.desc.${
|
|
66
|
-
sharingType === 'one-way' ? 'ro' : 'rw'
|
|
67
|
-
}`
|
|
68
|
-
)}
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
<Divider className="u-mv-1" />
|
|
72
29
|
<WhoHasAccess
|
|
73
|
-
|
|
74
|
-
count: recipients.length
|
|
75
|
-
})}
|
|
30
|
+
isReadOnly
|
|
76
31
|
recipients={recipients}
|
|
77
32
|
document={document}
|
|
78
33
|
documentType={documentType}
|
|
79
34
|
onRevoke={onRevoke}
|
|
80
35
|
onRevokeSelf={onRevokeSelf}
|
|
36
|
+
link="ok"
|
|
81
37
|
/>
|
|
82
38
|
</div>
|
|
83
39
|
}
|
|
@@ -29,6 +29,7 @@ const RecipientWaitingForConfirmationAlert = ({ recipientsToBeConfirmed }) => {
|
|
|
29
29
|
const WhoHasAccess = ({
|
|
30
30
|
isOwner = false,
|
|
31
31
|
isSharedDrive = false,
|
|
32
|
+
isReadOnly = false,
|
|
32
33
|
showOwner = true,
|
|
33
34
|
recipients,
|
|
34
35
|
recipientsToBeConfirmed = [],
|
|
@@ -53,6 +54,7 @@ const WhoHasAccess = ({
|
|
|
53
54
|
<List>
|
|
54
55
|
{link && (
|
|
55
56
|
<LinkRecipient
|
|
57
|
+
isReadOnly={isReadOnly}
|
|
56
58
|
document={document}
|
|
57
59
|
documentType={documentType}
|
|
58
60
|
onRevoke={onRevoke}
|
|
@@ -69,6 +71,7 @@ const WhoHasAccess = ({
|
|
|
69
71
|
recipientsToBeConfirmed={recipientsToBeConfirmed}
|
|
70
72
|
isOwner={isOwner}
|
|
71
73
|
isSharedDrive={isSharedDrive}
|
|
74
|
+
isReadOnly={isReadOnly}
|
|
72
75
|
document={document}
|
|
73
76
|
documentType={documentType}
|
|
74
77
|
onRevoke={onRevoke}
|
package/src/state.js
CHANGED
|
@@ -351,7 +351,7 @@ export const canReshare = (state, docId, instanceUri) => {
|
|
|
351
351
|
const sharing = getDocumentSharing(state, docId)
|
|
352
352
|
const me = sharing.attributes.members.find(matchingInstanceName(instanceUri))
|
|
353
353
|
if (sharing.drive) {
|
|
354
|
-
return me && !me.read_only
|
|
354
|
+
return !sharing.org_drive && me && !me.read_only
|
|
355
355
|
} else {
|
|
356
356
|
return sharing.attributes.open_sharing === true && me && !me.read_only
|
|
357
357
|
}
|