cozy-sharing 12.2.0 → 13.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 (73) hide show
  1. package/.storybook/preview.jsx +1 -0
  2. package/CHANGELOG.md +40 -0
  3. package/dist/components/Avatar/AvatarList.js +13 -2
  4. package/dist/components/Avatar/AvatarList.spec.js +11 -6
  5. package/dist/components/Avatar/AvatarList.stories.js +13 -1
  6. package/dist/components/Avatar/GroupAvatar.js +4 -2
  7. package/dist/components/ContactSuggestion.js +7 -3
  8. package/dist/components/ContactSuggestion.spec.js +7 -1
  9. package/dist/components/Recipient/GroupRecipient.js +14 -7
  10. package/dist/components/Recipient/GroupRecipientDetail.js +4 -2
  11. package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +9 -11
  12. package/dist/components/Recipient/GroupRecipientDetailWithoutAccess.js +8 -4
  13. package/dist/components/Recipient/GroupRecipientPermissions.js +3 -6
  14. package/dist/components/Recipient/MemberRecipient.js +1 -2
  15. package/dist/components/Recipient/MemberRecipientPermissions.js +1 -1
  16. package/dist/components/ShareAutosuggest.js +16 -9
  17. package/dist/components/ShareAutosuggest.spec.js +38 -13
  18. package/dist/components/ShareAutosuggest.stories.js +61 -0
  19. package/dist/components/ShareByEmail.js +15 -15
  20. package/dist/components/ShareByEmail.spec.js +0 -6
  21. package/dist/components/ShareDialogCozyToCozy.js +1 -5
  22. package/dist/components/ShareDialogCozyToCozy.spec.js +0 -61
  23. package/dist/components/ShareDialogTwoStepsConfirmationContainer.js +1 -5
  24. package/dist/components/ShareDialogTwoStepsConfirmationContainer.spec.js +0 -61
  25. package/dist/components/ShareModal/EditableSharingModal.js +3 -10
  26. package/dist/components/ShareModal/EditableSharingModal.spec.js +0 -6
  27. package/dist/components/ShareModal.js +1 -8
  28. package/dist/components/ShareRecipientsInput.js +46 -49
  29. package/dist/components/ShareRecipientsInput.spec.js +120 -144
  30. package/dist/helpers/contacts.js +12 -1
  31. package/dist/helpers/recipients.js +16 -9
  32. package/dist/helpers/successMessage.js +58 -16
  33. package/dist/helpers/successMessage.spec.js +122 -57
  34. package/dist/queries/queries.js +37 -5
  35. package/dist/styles/autosuggest.styl +2 -1
  36. package/dist/stylesheet.css +2 -1
  37. package/locales/en.json +23 -10
  38. package/locales/fr.json +23 -8
  39. package/package.json +4 -4
  40. package/src/components/Avatar/AvatarList.jsx +33 -14
  41. package/src/components/Avatar/AvatarList.spec.jsx +11 -6
  42. package/src/components/Avatar/AvatarList.stories.jsx +19 -1
  43. package/src/components/Avatar/GroupAvatar.jsx +2 -2
  44. package/src/components/ContactSuggestion.jsx +9 -3
  45. package/src/components/ContactSuggestion.spec.jsx +10 -1
  46. package/src/components/Recipient/GroupRecipient.jsx +17 -10
  47. package/src/components/Recipient/GroupRecipientDetail.jsx +5 -2
  48. package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +9 -14
  49. package/src/components/Recipient/GroupRecipientDetailWithoutAccess.jsx +8 -3
  50. package/src/components/Recipient/GroupRecipientPermissions.jsx +3 -8
  51. package/src/components/Recipient/MemberRecipient.jsx +4 -3
  52. package/src/components/Recipient/MemberRecipientPermissions.jsx +1 -1
  53. package/src/components/ShareAutosuggest.jsx +16 -11
  54. package/src/components/ShareAutosuggest.spec.jsx +31 -10
  55. package/src/components/ShareAutosuggest.stories.jsx +63 -0
  56. package/src/components/ShareByEmail.jsx +11 -11
  57. package/src/components/ShareByEmail.spec.jsx +0 -4
  58. package/src/components/ShareDialogCozyToCozy.jsx +0 -4
  59. package/src/components/ShareDialogCozyToCozy.spec.jsx +0 -67
  60. package/src/components/ShareDialogTwoStepsConfirmationContainer.jsx +0 -4
  61. package/src/components/ShareDialogTwoStepsConfirmationContainer.spec.jsx +0 -67
  62. package/src/components/ShareModal/EditableSharingModal.jsx +3 -21
  63. package/src/components/ShareModal/EditableSharingModal.spec.jsx +0 -2
  64. package/src/components/ShareModal.jsx +1 -7
  65. package/src/components/ShareRecipientsInput.jsx +84 -52
  66. package/src/components/ShareRecipientsInput.spec.jsx +140 -145
  67. package/src/helpers/contacts.js +8 -0
  68. package/src/helpers/recipients.js +24 -15
  69. package/src/helpers/successMessage.js +71 -21
  70. package/src/helpers/successMessage.spec.js +129 -69
  71. package/src/queries/queries.js +36 -5
  72. package/src/styles/autosuggest.styl +2 -1
  73. package/test/AppLike.jsx +6 -3
@@ -4,7 +4,7 @@ import { recipients } from '../../../.storybook/fixtures/recipients'
4
4
  const meta = {
5
5
  component: AvatarList,
6
6
  args: {
7
- recipients: [...recipients, ...recipients]
7
+ recipients: [...recipients]
8
8
  }
9
9
  }
10
10
 
@@ -14,3 +14,21 @@ export const Default = {
14
14
  name: 'Default',
15
15
  args: {}
16
16
  }
17
+
18
+ export const WithGroups = {
19
+ name: 'With groups',
20
+ args: {
21
+ recipients: [
22
+ ...recipients,
23
+ {
24
+ name: 'Group 1',
25
+ type: 'group',
26
+ members: [
27
+ {
28
+ public_name: 'Alice'
29
+ }
30
+ ]
31
+ }
32
+ ]
33
+ }
34
+ }
@@ -3,8 +3,8 @@ import React from 'react'
3
3
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
4
4
  import TeamIcon from 'cozy-ui/transpiled/react/Icons/Team'
5
5
 
6
- const GroupAvatar = ({ size }) => {
7
- return <Avatar icon={TeamIcon} size={size} />
6
+ const GroupAvatar = ({ size, className }) => {
7
+ return <Avatar icon={TeamIcon} size={size} className={className} />
8
8
  }
9
9
 
10
10
  export { GroupAvatar }
@@ -8,6 +8,7 @@ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
8
8
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
9
9
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
10
10
 
11
+ import { GroupAvatar } from './Avatar/GroupAvatar'
11
12
  import { Contact, Group, getDisplayName, getInitials } from '../models'
12
13
 
13
14
  const ContactModel = models.contact
@@ -15,11 +16,12 @@ const ContactModel = models.contact
15
16
  export const ContactSuggestion = ({ contactOrGroup }) => {
16
17
  const { t } = useI18n()
17
18
  let avatarText, name, details
18
- if (contactOrGroup._type === Group.doctype) {
19
+ const isContactGroup = contactOrGroup._type === Group.doctype
20
+ if (isContactGroup) {
19
21
  name = contactOrGroup.name
20
22
  avatarText = 'G'
21
23
  details = t('Share.members.count', {
22
- smart_count: contactOrGroup.membersCount.toString()
24
+ smart_count: contactOrGroup.members.length.toString()
23
25
  })
24
26
  } else {
25
27
  name = getDisplayName(contactOrGroup)
@@ -30,7 +32,11 @@ export const ContactSuggestion = ({ contactOrGroup }) => {
30
32
  return (
31
33
  <ListItem button>
32
34
  <ListItemIcon>
33
- <Avatar text={avatarText} size="small" />
35
+ {isContactGroup ? (
36
+ <GroupAvatar size="small" />
37
+ ) : (
38
+ <Avatar text={avatarText} size="small" />
39
+ )}
34
40
  </ListItemIcon>
35
41
  <ListItemText
36
42
  primary={name}
@@ -60,7 +60,16 @@ describe('ContactSuggestion component', () => {
60
60
  _id: '610718e6-2d7a',
61
61
  name: "The Night's Watch",
62
62
  _type: 'io.cozy.contacts.groups',
63
- membersCount: 2
63
+ members: [
64
+ {
65
+ _id: 'f3a4e501-abbd',
66
+ fullname: 'Jon Snow'
67
+ },
68
+ {
69
+ _id: 'ab23a451-tzas',
70
+ fullname: 'Samwell Tarly'
71
+ }
72
+ ]
64
73
  }
65
74
  setup({ contactOrGroup: theNightsWatch })
66
75
  expect(screen.getByText("The Night's Watch")).toBeInTheDocument()
@@ -12,11 +12,14 @@ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
12
12
 
13
13
  import { GroupRecipientDetail } from './GroupRecipientDetail'
14
14
  import { GroupRecipientPermissions } from './GroupRecipientPermissions'
15
- import { FADE_IN_DURATION } from '../../helpers/recipients'
15
+ import {
16
+ FADE_IN_DURATION,
17
+ getGroupRecipientSecondaryText
18
+ } from '../../helpers/recipients'
16
19
  import { GroupAvatar } from '../Avatar/GroupAvatar'
17
20
 
18
21
  const GroupRecipient = props => {
19
- const { name, members, fadeIn, owner } = props
22
+ const { name, members, fadeIn, owner, isOwner } = props
20
23
  const { t } = useI18n()
21
24
  const client = useClient()
22
25
  const { isMobile } = useBreakpoints()
@@ -27,7 +30,7 @@ const GroupRecipient = props => {
27
30
  const nbMemberReady = members.filter(
28
31
  member => !['revoked', 'mail-not-sent'].includes(member.status)
29
32
  ).length
30
- const isCurrentInstanceInsideMembers = members.some(
33
+ const isUserInsideMembers = members.some(
31
34
  member => member.instance === client.options.uri
32
35
  )
33
36
 
@@ -56,20 +59,24 @@ const GroupRecipient = props => {
56
59
  {name}
57
60
  </Typography>
58
61
  }
59
- secondary={
60
- t('GroupRecipient.secondary', { nbMember, nbMemberReady }) +
61
- (isCurrentInstanceInsideMembers
62
- ? ` (${t('GroupRecipient.secondary_you')})`
63
- : '')
64
- }
62
+ secondary={getGroupRecipientSecondaryText({
63
+ t,
64
+ nbMember,
65
+ nbMemberReady,
66
+ isUserInsideMembers
67
+ })}
65
68
  />
66
69
  <ListItemSecondaryAction className={isMobile ? 'u-mr-1' : 'u-mr-2'}>
67
- <GroupRecipientPermissions {...props} />
70
+ <GroupRecipientPermissions
71
+ isUserInsideMembers={isUserInsideMembers}
72
+ {...props}
73
+ />
68
74
  </ListItemSecondaryAction>
69
75
  </ListItem>
70
76
  </Fade>
71
77
  {isDetailOpened ? (
72
78
  <GroupRecipientDetail
79
+ isOwner={isOwner}
73
80
  owner={owner}
74
81
  name={name}
75
82
  members={members}
@@ -7,7 +7,7 @@ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
7
7
  import { GroupRecipientDetailWithAccess } from './GroupRecipientDetailWithAccess'
8
8
  import { GroupRecipientDetailWithoutAccess } from './GroupRecipientDetailWithoutAccess'
9
9
 
10
- const GroupRecipientDetail = ({ name, owner, members, onClose }) => {
10
+ const GroupRecipientDetail = ({ name, owner, members, onClose, isOwner }) => {
11
11
  const { t } = useI18n()
12
12
  const withAccess = members.filter(
13
13
  member => !['revoked', 'mail-not-sent'].includes(member.status)
@@ -39,7 +39,10 @@ const GroupRecipientDetail = ({ name, owner, members, onClose }) => {
39
39
  <GroupRecipientDetailWithAccess withAccess={withAccess} />
40
40
  ) : null}
41
41
  {withoutAccess.length > 0 ? (
42
- <GroupRecipientDetailWithoutAccess withoutAccess={withoutAccess} />
42
+ <GroupRecipientDetailWithoutAccess
43
+ withoutAccess={withoutAccess}
44
+ isOwner={isOwner}
45
+ />
43
46
  ) : null}
44
47
  </div>
45
48
  }
@@ -1,8 +1,7 @@
1
1
  import React from 'react'
2
2
 
3
+ import { useClient } from 'cozy-client'
3
4
  import Avatar from 'cozy-ui/transpiled/react/Avatar'
4
- import Icon from 'cozy-ui/transpiled/react/Icon'
5
- import ToTheCloudIcon from 'cozy-ui/transpiled/react/Icons/ToTheCloud'
6
5
  import List from 'cozy-ui/transpiled/react/List'
7
6
  import ListItem from 'cozy-ui/transpiled/react/ListItem'
8
7
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
@@ -10,10 +9,12 @@ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
10
9
  import Typography from 'cozy-ui/transpiled/react/Typography'
11
10
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
12
11
 
12
+ import MemberRecipientStatus from './MemberRecipientStatus'
13
13
  import { getInitials, getDisplayName } from '../../models'
14
14
 
15
15
  const GroupRecipientDetailWithAccess = ({ withAccess }) => {
16
16
  const { t } = useI18n()
17
+ const client = useClient()
17
18
 
18
19
  return (
19
20
  <div>
@@ -23,6 +24,7 @@ const GroupRecipientDetailWithAccess = ({ withAccess }) => {
23
24
  <List>
24
25
  {withAccess.map(recipient => {
25
26
  const name = getDisplayName(recipient)
27
+ const isMe = recipient.instance === client.options.uri
26
28
 
27
29
  return (
28
30
  <ListItem disableGutters key={recipient.index}>
@@ -32,18 +34,11 @@ const GroupRecipientDetailWithAccess = ({ withAccess }) => {
32
34
  <ListItemText
33
35
  primary={name}
34
36
  secondary={
35
- recipient.instance ? (
36
- <div className="u-flex u-flex-items-center">
37
- <Icon
38
- icon={ToTheCloudIcon}
39
- size={10}
40
- style={{
41
- marginRight: '0.25rem'
42
- }}
43
- />
44
- {recipient.instance}
45
- </div>
46
- ) : null
37
+ <MemberRecipientStatus
38
+ status={recipient.status}
39
+ isMe={isMe}
40
+ instance={recipient.instance}
41
+ />
47
42
  }
48
43
  />
49
44
  </ListItem>
@@ -10,9 +10,10 @@ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
10
10
  import Typography from 'cozy-ui/transpiled/react/Typography'
11
11
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
12
12
 
13
+ import { DEFAULT_DISPLAY_NAME } from '../../helpers/recipients'
13
14
  import { getInitials, getDisplayName } from '../../models'
14
15
 
15
- const GroupRecipientDetailWithoutAccess = ({ withoutAccess }) => {
16
+ const GroupRecipientDetailWithoutAccess = ({ withoutAccess, isOwner }) => {
16
17
  const { t } = useI18n()
17
18
 
18
19
  return (
@@ -23,10 +24,11 @@ const GroupRecipientDetailWithoutAccess = ({ withoutAccess }) => {
23
24
  <List>
24
25
  {withoutAccess.map(recipient => {
25
26
  const icon = recipient.status === 'revoked' ? ForbiddenIcon : null
26
- const name = getDisplayName(recipient)
27
+ const defaultDisplayName = t(DEFAULT_DISPLAY_NAME)
28
+ const name = getDisplayName(recipient, defaultDisplayName)
27
29
 
28
30
  return (
29
- <ListItem disableGutters key={recipient.index}>
31
+ <ListItem disableGutters key={recipient.index} ellipsis={false}>
30
32
  <ListItemIcon>
31
33
  <Avatar text={getInitials(recipient)} textId={name} />
32
34
  </ListItemIcon>
@@ -46,6 +48,9 @@ const GroupRecipientDetailWithoutAccess = ({ withoutAccess }) => {
46
48
  {t(
47
49
  `GroupRecipientDetail.withoutAccess.status.${recipient.status}`
48
50
  )}
51
+ {isOwner
52
+ ? ` - ${t('GroupRecipientDetail.withoutAccess.addEmail')}`
53
+ : null}
49
54
  </div>
50
55
  }
51
56
  />
@@ -1,6 +1,5 @@
1
1
  import React, { useState, useRef } from 'react'
2
2
 
3
- import { useClient } from 'cozy-client'
4
3
  import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
5
4
  import {
6
5
  makeActions,
@@ -21,24 +20,20 @@ import { GroupAvatar } from '../Avatar/GroupAvatar'
21
20
  const GroupRecipientPermissions = ({
22
21
  name,
23
22
  isOwner,
24
- instance,
25
23
  sharingId,
26
24
  groupIndex,
27
25
  read_only: isReadOnly = false,
28
- className
26
+ className,
27
+ isUserInsideMembers
29
28
  }) => {
30
29
  const { t } = useI18n()
31
30
  const buttonRef = useRef()
32
- const client = useClient()
33
31
  const { revokeGroup, revokeSelf } = useSharingContext()
34
32
 
35
33
  const [isMenuDisplayed, setMenuDisplayed] = useState(false)
36
34
  const [revoking, setRevoking] = useState(false)
37
35
 
38
- const instanceMatchesClient =
39
- instance !== undefined && instance === client.options.uri
40
- const shouldShowMenu =
41
- !revoking && ((instanceMatchesClient && !isOwner) || isOwner)
36
+ const shouldShowMenu = !revoking && (isOwner || isUserInsideMembers)
42
37
 
43
38
  const toggleMenu = () => setMenuDisplayed(!isMenuDisplayed)
44
39
  const hideMenu = () => setMenuDisplayed(false)
@@ -13,12 +13,13 @@ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
13
13
  import MemberRecipientPermissions from './MemberRecipientPermissions'
14
14
  import MemberRecipientStatus from './MemberRecipientStatus'
15
15
  import RecipientConfirm from './RecipientConfirm'
16
- import { FADE_IN_DURATION } from '../../helpers/recipients'
16
+ import {
17
+ FADE_IN_DURATION,
18
+ DEFAULT_DISPLAY_NAME
19
+ } from '../../helpers/recipients'
17
20
  import { getDisplayName } from '../../models'
18
21
  import { MemberAvatar } from '../Avatar/MemberAvatar'
19
22
 
20
- const DEFAULT_DISPLAY_NAME = 'Share.contacts.defaultDisplayName'
21
-
22
23
  const MemberRecipient = props => {
23
24
  const { t } = useI18n()
24
25
  const client = useClient()
@@ -56,7 +56,7 @@ const MemberRecipientPermissions = ({
56
56
 
57
57
  const actions = makeActions([permission, divider, revokeMember], {
58
58
  t,
59
- type,
59
+ type: type ?? 'one-way',
60
60
  isOwner,
61
61
  handleRevocation
62
62
  })
@@ -7,9 +7,10 @@ import Chip from 'cozy-ui/transpiled/react/Chips'
7
7
  import { Spinner } from 'cozy-ui/transpiled/react/Spinner'
8
8
  import palette from 'cozy-ui/transpiled/react/palette'
9
9
 
10
+ import { GroupAvatar } from './Avatar/GroupAvatar'
10
11
  import ContactSuggestion from './ContactSuggestion'
11
12
  import { extractEmails, validateEmail } from '../helpers/email'
12
- import { getDisplayName, getInitials, Contact } from '../models'
13
+ import { getDisplayName, getInitials, Contact, Group } from '../models'
13
14
  import styles from '../styles/autosuggest.styl'
14
15
  import {
15
16
  cozyUrlMatch,
@@ -22,7 +23,6 @@ const ShareAutocomplete = ({
22
23
  loading,
23
24
  contactsAndGroups,
24
25
  recipients,
25
- onFocus,
26
26
  onPick,
27
27
  onRemove,
28
28
  placeholder
@@ -30,6 +30,7 @@ const ShareAutocomplete = ({
30
30
  const [inputValue, setInputValue] = useState('')
31
31
  const [suggestions, setSuggestions] = useState([])
32
32
  const [isPasted, setIsPasted] = useState(false)
33
+ const [isLoadingDisplayed, setLoadingDisplayed] = useState(false)
33
34
 
34
35
  const autosuggestRef = useRef(null)
35
36
 
@@ -116,7 +117,8 @@ const ShareAutocomplete = ({
116
117
  }
117
118
 
118
119
  const onAutosuggestFocus = () => {
119
- onFocus()
120
+ // We only show the loading state when the user has focus on the input
121
+ setLoadingDisplayed(true)
120
122
  }
121
123
 
122
124
  const onAutosuggestBlur = () => {
@@ -139,13 +141,20 @@ const ShareAutocomplete = ({
139
141
  const renderInput = inputProps => (
140
142
  <div className={styles['recipientsContainer']}>
141
143
  {recipients.map((recipient, idx) => {
144
+ const isContactGroup = recipient._type === Group.doctype
142
145
  const avatarText = getInitials(recipient)
143
146
  const name = getDisplayName(recipient)
144
147
  return (
145
148
  <Chip
146
149
  id={`recipient_${idx}`}
147
150
  key={`key_recipient_${idx}`}
148
- avatar={<Avatar text={avatarText} size="xsmall" />}
151
+ avatar={
152
+ isContactGroup ? (
153
+ <GroupAvatar size="xsmall" />
154
+ ) : (
155
+ <Avatar text={avatarText} size="xsmall" />
156
+ )
157
+ }
149
158
  label={name}
150
159
  onDelete={() => {
151
160
  onAutosuggestRemove(recipient)
@@ -155,12 +164,9 @@ const ShareAutocomplete = ({
155
164
  )
156
165
  })}
157
166
  <input {...inputProps} onKeyPress={onKeyPress} onKeyUp={onKeyUp} />
158
- {loading && (
159
- <Spinner
160
- color={palette.dodgerBlue}
161
- className="u-flex u-flex-items-center"
162
- />
163
- )}
167
+ {loading && isLoadingDisplayed ? (
168
+ <Spinner color={palette.dodgerBlue} />
169
+ ) : null}
164
170
  </div>
165
171
  )
166
172
 
@@ -196,7 +202,6 @@ ShareAutocomplete.propTypes = {
196
202
  loading: PropTypes.bool,
197
203
  contactsAndGroups: PropTypes.array,
198
204
  recipients: PropTypes.array.isRequired,
199
- onFocus: PropTypes.func.isRequired,
200
205
  onPick: PropTypes.func.isRequired,
201
206
  onRemove: PropTypes.func.isRequired,
202
207
  placeholder: PropTypes.string
@@ -1,29 +1,36 @@
1
- import { render, fireEvent } from '@testing-library/react'
1
+ import { render, fireEvent, screen } from '@testing-library/react'
2
2
  import React from 'react'
3
3
 
4
4
  import ShareAutosuggest from './ShareAutosuggest'
5
5
  import AppLike from '../../test/AppLike'
6
6
 
7
+ jest.mock('cozy-ui/transpiled/react/Spinner', () => ({
8
+ Spinner: () => <div>loading</div>
9
+ }))
10
+
7
11
  describe('ShareAutosuggest', () => {
8
- it('tests if ShareAutosuggest calls onFocus and onPick', () => {
9
- const onPick = jest.fn()
10
- const onFocus = jest.fn()
11
- const onRemove = jest.fn()
12
- const { getByPlaceholderText } = render(
12
+ const setup = ({ onPick, onRemove, loading = false }) => {
13
+ render(
13
14
  <AppLike>
14
15
  <ShareAutosuggest
16
+ loading={loading}
15
17
  contactsAndGroups={[]}
16
18
  placeholder="myPlaceHolder"
17
19
  onPick={onPick}
18
- onFocus={onFocus}
19
20
  recipients={[]}
20
21
  onRemove={onRemove}
21
22
  />
22
23
  </AppLike>
23
24
  )
24
- const inputNode = getByPlaceholderText('myPlaceHolder')
25
- inputNode.focus()
26
- expect(onFocus).toHaveBeenCalled()
25
+ }
26
+
27
+ it('tests if ShareAutosuggest calls onPick', () => {
28
+ const onPick = jest.fn()
29
+ const onRemove = jest.fn()
30
+
31
+ setup({ onPick, onRemove })
32
+
33
+ const inputNode = screen.getByPlaceholderText('myPlaceHolder')
27
34
  // It should not call onPick if the value is not an email
28
35
  fireEvent.change(inputNode, { target: { value: 'quentin@qq' } })
29
36
  fireEvent.keyPress(inputNode, { key: 'Enter', keyCode: 13, charCode: 13 })
@@ -43,4 +50,18 @@ describe('ShareAutosuggest', () => {
43
50
  email: 'quentin.valmori@cozycloud.cc'
44
51
  })
45
52
  })
53
+
54
+ it('should show loading only after user focus input', () => {
55
+ const onPick = jest.fn()
56
+ const onRemove = jest.fn()
57
+
58
+ setup({ onPick, onRemove, loading: true })
59
+
60
+ const inputNode = screen.getByPlaceholderText('myPlaceHolder')
61
+
62
+ expect(screen.queryByText('loading')).toBeNull()
63
+ fireEvent.focus(inputNode)
64
+
65
+ expect(screen.getByText('loading')).toBeInTheDocument()
66
+ })
46
67
  })
@@ -0,0 +1,63 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import ShareAutosuggest from './ShareAutosuggest'
4
+
5
+ const meta = {
6
+ component: ShareAutosuggest,
7
+ args: {}
8
+ }
9
+
10
+ export default meta
11
+
12
+ const ShareAutosuggestRender = props => {
13
+ const [recipients, setRecipients] = useState([])
14
+ const onPick = contactOrGroup => {
15
+ setRecipients([...recipients, contactOrGroup])
16
+ }
17
+
18
+ const onRemove = contactOrGroup => {
19
+ setRecipients(recipients.filter(r => r.id !== contactOrGroup.id))
20
+ }
21
+ return (
22
+ <ShareAutosuggest
23
+ {...props}
24
+ recipients={recipients}
25
+ onPick={onPick}
26
+ onRemove={onRemove}
27
+ />
28
+ )
29
+ }
30
+
31
+ export const Default = {
32
+ name: 'Default',
33
+ render: ShareAutosuggestRender,
34
+ args: {
35
+ loading: false,
36
+ contactsAndGroups: [
37
+ {
38
+ id: 'group1',
39
+ name: 'Family',
40
+ _type: 'io.cozy.contacts.groups',
41
+ members: [
42
+ {
43
+ id: 'contact1',
44
+ name: 'John Doe',
45
+ _type: 'io.cozy.contacts'
46
+ },
47
+ {
48
+ id: 'contact2',
49
+ name: 'Jane Doe',
50
+ _type: 'io.cozy.contacts'
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ id: 'contact3',
56
+ name: 'Alice Wonderland',
57
+ _type: 'io.cozy.contacts',
58
+ email: 'alice@wonder.land'
59
+ }
60
+ ],
61
+ placeholder: 'Type a name or email address'
62
+ }
63
+ }
@@ -4,6 +4,7 @@ import React, { useState } from 'react'
4
4
  import { useClient } from 'cozy-client'
5
5
  import flag from 'cozy-flags'
6
6
  import Alerter from 'cozy-ui/transpiled/react/deprecated/Alerter'
7
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
7
8
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
8
9
 
9
10
  import ShareRecipientsInput from './ShareRecipientsInput'
@@ -17,13 +18,10 @@ import {
17
18
  hasReachRecipientsLimit
18
19
  } from '../helpers/recipients'
19
20
  import { getSuccessMessage } from '../helpers/successMessage'
20
- import { contactsResponseType, contactGroupsResponseType } from '../propTypes'
21
21
  import { isReadOnlySharing } from '../state'
22
22
  import styles from '../styles/share.styl'
23
23
 
24
24
  export const ShareByEmail = ({
25
- contacts,
26
- contactGroups,
27
25
  document,
28
26
  sharingDesc,
29
27
  onShare,
@@ -34,6 +32,8 @@ export const ShareByEmail = ({
34
32
  }) => {
35
33
  const client = useClient()
36
34
  const { t } = useI18n()
35
+ const { showAlert } = useAlert()
36
+
37
37
  const [recipients, setRecipients] = useState([])
38
38
  const [loading, setLoading] = useState(false)
39
39
  const [selectedOption, setSelectedOption] = useState()
@@ -51,7 +51,7 @@ export const ShareByEmail = ({
51
51
  const onRecipientPick = recipient => {
52
52
  const mergedRecipients = flag('sharing.show-recipient-groups')
53
53
  ? mergeRecipients(recipients, recipient)
54
- : spreadGroupAndMergeRecipients(recipients, recipient, contacts)
54
+ : spreadGroupAndMergeRecipients(recipients, recipient)
55
55
  setRecipients(mergedRecipients)
56
56
  }
57
57
 
@@ -96,9 +96,13 @@ export const ShareByEmail = ({
96
96
  openSharing: readWriteRecipients.length > 0
97
97
  })
98
98
 
99
- Alerter.success(
100
- t(...getSuccessMessage(recipientsBefore, contacts, documentType))
101
- )
99
+ showAlert({
100
+ message: t(
101
+ ...getSuccessMessage(recipientsBefore, contacts, documentType)
102
+ ),
103
+ severity: 'success',
104
+ variant: 'filled'
105
+ })
102
106
  reset()
103
107
  } catch (err) {
104
108
  Alerter.error('Error.generic')
@@ -139,8 +143,6 @@ export const ShareByEmail = ({
139
143
  }
140
144
  onPick={recipient => onRecipientPick(recipient)}
141
145
  onRemove={recipient => onRecipientRemove(recipient)}
142
- contacts={contacts}
143
- contactGroups={contactGroups}
144
146
  recipients={recipients}
145
147
  />
146
148
  </div>
@@ -167,8 +169,6 @@ export const ShareByEmail = ({
167
169
 
168
170
  ShareByEmail.propTypes = {
169
171
  currentRecipients: PropTypes.arrayOf(PropTypes.object),
170
- contacts: contactsResponseType.isRequired,
171
- contactGroups: contactGroupsResponseType.isRequired,
172
172
  document: PropTypes.object.isRequired,
173
173
  documentType: PropTypes.string.isRequired,
174
174
  sharingDesc: PropTypes.string.isRequired,
@@ -27,10 +27,6 @@ describe('ShareByEmailComponent', () => {
27
27
  currentRecipients = []
28
28
  } = {}) => {
29
29
  const props = {
30
- contacts: {
31
- data: []
32
- },
33
- contactGroups: { data: [] },
34
30
  documentType: 'Files',
35
31
  onShare,
36
32
  document,
@@ -15,8 +15,6 @@ import styles from '../styles/share.styl'
15
15
  * Displays the sharing interface that can be used when ShareDialogCozyToCozy is in sharing state
16
16
  */
17
17
  const SharingContent = ({
18
- contacts,
19
- contactGroups,
20
18
  createContact,
21
19
  document,
22
20
  documentType,
@@ -68,8 +66,6 @@ const SharingContent = ({
68
66
  </Typography>
69
67
  {showShareByEmail && (
70
68
  <DumbShareByEmail
71
- contacts={contacts}
72
- contactGroups={contactGroups}
73
69
  createContact={createContact}
74
70
  currentRecipients={recipients}
75
71
  document={document}