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
@@ -3,6 +3,7 @@ import React from "react";
3
3
  import 'cozy-ui/dist/cozy-ui.min.css'
4
4
  import 'cozy-ui/dist/cozy-ui.utils.min.css'
5
5
  import 'cozy-ui/transpiled/react/stylesheet.css'
6
+ import '../dist/stylesheet.css'
6
7
 
7
8
  import I18n from 'cozy-ui/transpiled/react/providers/I18n'
8
9
  import { BreakpointsProvider } from 'cozy-ui/transpiled/react/providers/Breakpoints'
package/CHANGELOG.md CHANGED
@@ -3,6 +3,46 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [13.0.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@12.3.0...cozy-sharing@13.0.0) (2024-04-08)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **GroupRecipientDetail:** Improve member display ([2bb65cf](https://github.com/cozy/cozy-libs/commit/2bb65cf5218781845a5587433952437b3c764b97))
12
+ * Improve secondary text of GroupRecipient ([d747f9c](https://github.com/cozy/cozy-libs/commit/d747f9c6ad30701c16b9f888d4aee7729a5fc28b))
13
+ * Remove translation error when there is no type like for owner ([830d5fa](https://github.com/cozy/cozy-libs/commit/830d5faaaea118189f574d6cec859ba361ee4cd5))
14
+ * **ShareAutosuggest:** Align correctly loading state ([9d93952](https://github.com/cozy/cozy-libs/commit/9d93952b1740c6974da0ced62bd81d1990311b40))
15
+ * Show all the members from a group even unreachable ones ([e62ec59](https://github.com/cozy/cozy-libs/commit/e62ec5980bcb037a2af28cb64d522abdc9fa0408))
16
+ * Show group avatar into share input ([632658a](https://github.com/cozy/cozy-libs/commit/632658af64a8b8f1bcd4ba72d9b0e563d9a8dfdd))
17
+ * Show permissions when the current user is inside members ([d28d4b4](https://github.com/cozy/cozy-libs/commit/d28d4b46938aafddb39884511e7859d800e953b8))
18
+
19
+
20
+ ### Features
21
+
22
+ * Improve the message of success to integrate the notion of groups ([f0945b7](https://github.com/cozy/cozy-libs/commit/f0945b7e054a14d35e5d689f9db65c53df0286c6))
23
+ * **ShareRecipientsInput:** Simplify loading state ([e2ec136](https://github.com/cozy/cozy-libs/commit/e2ec136363df578bec338fde9336ac09ed573bb1))
24
+ * Update cozy-ui from 103.8.2 to 105.3.1 ([e1b21f8](https://github.com/cozy/cozy-libs/commit/e1b21f887fb55e5ddab7348f3f5fd41631318cdf))
25
+
26
+
27
+ ### BREAKING CHANGES
28
+
29
+ * you must have `cozy-ui >= 105.3.1`
30
+
31
+
32
+
33
+
34
+
35
+ # [12.3.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@12.2.0...cozy-sharing@12.3.0) (2024-03-25)
36
+
37
+
38
+ ### Features
39
+
40
+ * Add GroupAvatar into AvatarList ([1c66999](https://github.com/cozy/cozy-libs/commit/1c669995b08d84a3aa8d6dd950fa4abf22566395))
41
+
42
+
43
+
44
+
45
+
6
46
  # [12.2.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@12.1.0...cozy-sharing@12.2.0) (2024-03-22)
7
47
 
8
48
 
@@ -5,6 +5,7 @@ import { useClient } from 'cozy-client';
5
5
  import Avatar from 'cozy-ui/transpiled/react/Avatar';
6
6
  import LinkIcon from 'cozy-ui/transpiled/react/Icons/Link';
7
7
  import { ExtraAvatar } from './ExtraAvatar';
8
+ import { GroupAvatar } from './GroupAvatar';
8
9
  import { MemberAvatar } from './MemberAvatar';
9
10
  import { getDisplayName } from '../../models';
10
11
  var styles = {
@@ -83,10 +84,20 @@ var AvatarList = function AvatarList(_ref2) {
83
84
  className: styles['recipients-avatars--plusX'],
84
85
  extraRecipients: extraRecipients,
85
86
  size: size
86
- })), shownRecipients.map(function (recipient, idx) {
87
+ })), shownRecipients.map(function (recipient) {
88
+ if (recipient.members) {
89
+ return /*#__PURE__*/React.createElement("span", {
90
+ "data-testid": "AvatarList-avatar".concat(recipient.status === 'owner' ? '-owner' : ''),
91
+ key: recipient.index
92
+ }, /*#__PURE__*/React.createElement(GroupAvatar, {
93
+ size: size,
94
+ className: cx(styles['recipients-avatars--avatar'])
95
+ }));
96
+ }
97
+
87
98
  return /*#__PURE__*/React.createElement("span", {
88
99
  "data-testid": "AvatarList-avatar".concat(recipient.status === 'owner' ? '-owner' : ''),
89
- key: idx
100
+ key: recipient.index
90
101
  }, /*#__PURE__*/React.createElement(MemberAvatar, {
91
102
  recipient: recipient,
92
103
  size: size,
@@ -9,20 +9,25 @@ import { AvatarList, MAX_DISPLAYED_RECIPIENTS, excludeMeAsOwnerFromRecipients }
9
9
  import AppLike from '../../../test/AppLike';
10
10
  var mockRecipients = new Array(MAX_DISPLAYED_RECIPIENTS - 1).fill({
11
11
  status: 'owner',
12
- public_name: 'cozy'
12
+ public_name: 'cozy',
13
+ index: 'sharing-123-member-0'
13
14
  }, 0, 1).fill({
14
15
  status: 'pending',
15
- name: 'Mitch Young'
16
+ name: 'Mitch Young',
17
+ index: 'sharing-123-member-1'
16
18
  }, 1);
17
19
  var mockMoreRecipientsThanMaxDisplayed = [].concat(_toConsumableArray(mockRecipients), [{
18
20
  status: 'mail-not-send',
19
- name: 'Lyn Webster'
21
+ name: 'Lyn Webster',
22
+ index: 'sharing-123-member-2'
20
23
  }, {
21
24
  status: 'ready',
22
- name: 'Richelle Young'
25
+ name: 'Richelle Young',
26
+ index: 'sharing-123-member-3'
23
27
  }, {
24
28
  status: 'ready',
25
- name: 'John Connor'
29
+ name: 'John Connor',
30
+ index: 'sharing-123-member-4'
26
31
  }]);
27
32
  describe('AvatarList', function () {
28
33
  var client = createMockClient({});
@@ -103,7 +108,7 @@ describe('AvatarList', function () {
103
108
  });
104
109
  });
105
110
  describe('excludeMeAsOwnerFromRecipients', function () {
106
- test('excludeMeAsOwnerFromRecipients behavior', function () {
111
+ it('excludeMeAsOwnerFromRecipients behavior', function () {
107
112
  var recipients = [{
108
113
  status: 'owner',
109
114
  instance: 'http://foo1.cozy.bar'
@@ -4,11 +4,23 @@ import { recipients } from '../../../.storybook/fixtures/recipients';
4
4
  var meta = {
5
5
  component: AvatarList,
6
6
  args: {
7
- recipients: [].concat(_toConsumableArray(recipients), _toConsumableArray(recipients))
7
+ recipients: _toConsumableArray(recipients)
8
8
  }
9
9
  };
10
10
  export default meta;
11
11
  export var Default = {
12
12
  name: 'Default',
13
13
  args: {}
14
+ };
15
+ export var WithGroups = {
16
+ name: 'With groups',
17
+ args: {
18
+ recipients: [].concat(_toConsumableArray(recipients), [{
19
+ name: 'Group 1',
20
+ type: 'group',
21
+ members: [{
22
+ public_name: 'Alice'
23
+ }]
24
+ }])
25
+ }
14
26
  };
@@ -3,10 +3,12 @@ import Avatar from 'cozy-ui/transpiled/react/Avatar';
3
3
  import TeamIcon from 'cozy-ui/transpiled/react/Icons/Team';
4
4
 
5
5
  var GroupAvatar = function GroupAvatar(_ref) {
6
- var size = _ref.size;
6
+ var size = _ref.size,
7
+ className = _ref.className;
7
8
  return /*#__PURE__*/React.createElement(Avatar, {
8
9
  icon: TeamIcon,
9
- size: size
10
+ size: size,
11
+ className: className
10
12
  });
11
13
  };
12
14
 
@@ -6,6 +6,7 @@ import ListItem from 'cozy-ui/transpiled/react/ListItem';
6
6
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon';
7
7
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText';
8
8
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
9
+ import { GroupAvatar } from './Avatar/GroupAvatar';
9
10
  import { Contact, Group, getDisplayName, getInitials } from '../models';
10
11
  var ContactModel = models.contact;
11
12
  export var ContactSuggestion = function ContactSuggestion(_ref) {
@@ -15,12 +16,13 @@ export var ContactSuggestion = function ContactSuggestion(_ref) {
15
16
  t = _useI18n.t;
16
17
 
17
18
  var avatarText, name, details;
19
+ var isContactGroup = contactOrGroup._type === Group.doctype;
18
20
 
19
- if (contactOrGroup._type === Group.doctype) {
21
+ if (isContactGroup) {
20
22
  name = contactOrGroup.name;
21
23
  avatarText = 'G';
22
24
  details = t('Share.members.count', {
23
- smart_count: contactOrGroup.membersCount.toString()
25
+ smart_count: contactOrGroup.members.length.toString()
24
26
  });
25
27
  } else {
26
28
  name = getDisplayName(contactOrGroup);
@@ -30,7 +32,9 @@ export var ContactSuggestion = function ContactSuggestion(_ref) {
30
32
 
31
33
  return /*#__PURE__*/React.createElement(ListItem, {
32
34
  button: true
33
- }, /*#__PURE__*/React.createElement(ListItemIcon, null, /*#__PURE__*/React.createElement(Avatar, {
35
+ }, /*#__PURE__*/React.createElement(ListItemIcon, null, isContactGroup ? /*#__PURE__*/React.createElement(GroupAvatar, {
36
+ size: "small"
37
+ }) : /*#__PURE__*/React.createElement(Avatar, {
34
38
  text: avatarText,
35
39
  size: "small"
36
40
  })), /*#__PURE__*/React.createElement(ListItemText, {
@@ -57,7 +57,13 @@ describe('ContactSuggestion component', function () {
57
57
  _id: '610718e6-2d7a',
58
58
  name: "The Night's Watch",
59
59
  _type: 'io.cozy.contacts.groups',
60
- membersCount: 2
60
+ members: [{
61
+ _id: 'f3a4e501-abbd',
62
+ fullname: 'Jon Snow'
63
+ }, {
64
+ _id: 'ab23a451-tzas',
65
+ fullname: 'Samwell Tarly'
66
+ }]
61
67
  };
62
68
  setup({
63
69
  contactOrGroup: theNightsWatch
@@ -1,3 +1,4 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
1
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
3
  import React, { useState } from 'react';
3
4
  import { useClient } from 'cozy-client';
@@ -11,14 +12,15 @@ import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints';
11
12
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
12
13
  import { GroupRecipientDetail } from './GroupRecipientDetail';
13
14
  import { GroupRecipientPermissions } from './GroupRecipientPermissions';
14
- import { FADE_IN_DURATION } from '../../helpers/recipients';
15
+ import { FADE_IN_DURATION, getGroupRecipientSecondaryText } from '../../helpers/recipients';
15
16
  import { GroupAvatar } from '../Avatar/GroupAvatar';
16
17
 
17
18
  var GroupRecipient = function GroupRecipient(props) {
18
19
  var name = props.name,
19
20
  members = props.members,
20
21
  fadeIn = props.fadeIn,
21
- owner = props.owner;
22
+ owner = props.owner,
23
+ isOwner = props.isOwner;
22
24
 
23
25
  var _useI18n = useI18n(),
24
26
  t = _useI18n.t;
@@ -37,7 +39,7 @@ var GroupRecipient = function GroupRecipient(props) {
37
39
  var nbMemberReady = members.filter(function (member) {
38
40
  return !['revoked', 'mail-not-sent'].includes(member.status);
39
41
  }).length;
40
- var isCurrentInstanceInsideMembers = members.some(function (member) {
42
+ var isUserInsideMembers = members.some(function (member) {
41
43
  return member.instance === client.options.uri;
42
44
  });
43
45
 
@@ -63,13 +65,18 @@ var GroupRecipient = function GroupRecipient(props) {
63
65
  className: "u-ellipsis",
64
66
  variant: "body1"
65
67
  }, name),
66
- secondary: t('GroupRecipient.secondary', {
68
+ secondary: getGroupRecipientSecondaryText({
69
+ t: t,
67
70
  nbMember: nbMember,
68
- nbMemberReady: nbMemberReady
69
- }) + (isCurrentInstanceInsideMembers ? " (".concat(t('GroupRecipient.secondary_you'), ")") : '')
71
+ nbMemberReady: nbMemberReady,
72
+ isUserInsideMembers: isUserInsideMembers
73
+ })
70
74
  }), /*#__PURE__*/React.createElement(ListItemSecondaryAction, {
71
75
  className: isMobile ? 'u-mr-1' : 'u-mr-2'
72
- }, /*#__PURE__*/React.createElement(GroupRecipientPermissions, props)))), isDetailOpened ? /*#__PURE__*/React.createElement(GroupRecipientDetail, {
76
+ }, /*#__PURE__*/React.createElement(GroupRecipientPermissions, _extends({
77
+ isUserInsideMembers: isUserInsideMembers
78
+ }, props))))), isDetailOpened ? /*#__PURE__*/React.createElement(GroupRecipientDetail, {
79
+ isOwner: isOwner,
73
80
  owner: owner,
74
81
  name: name,
75
82
  members: members,
@@ -9,7 +9,8 @@ var GroupRecipientDetail = function GroupRecipientDetail(_ref) {
9
9
  var name = _ref.name,
10
10
  owner = _ref.owner,
11
11
  members = _ref.members,
12
- onClose = _ref.onClose;
12
+ onClose = _ref.onClose,
13
+ isOwner = _ref.isOwner;
13
14
 
14
15
  var _useI18n = useI18n(),
15
16
  t = _useI18n.t;
@@ -35,7 +36,8 @@ var GroupRecipientDetail = function GroupRecipientDetail(_ref) {
35
36
  }, withAccess.length > 0 ? /*#__PURE__*/React.createElement(GroupRecipientDetailWithAccess, {
36
37
  withAccess: withAccess
37
38
  }) : null, withoutAccess.length > 0 ? /*#__PURE__*/React.createElement(GroupRecipientDetailWithoutAccess, {
38
- withoutAccess: withoutAccess
39
+ withoutAccess: withoutAccess,
40
+ isOwner: isOwner
39
41
  }) : null)
40
42
  });
41
43
  };
@@ -1,13 +1,13 @@
1
1
  import React from 'react';
2
+ import { useClient } from 'cozy-client';
2
3
  import Avatar from 'cozy-ui/transpiled/react/Avatar';
3
- import Icon from 'cozy-ui/transpiled/react/Icon';
4
- import ToTheCloudIcon from 'cozy-ui/transpiled/react/Icons/ToTheCloud';
5
4
  import List from 'cozy-ui/transpiled/react/List';
6
5
  import ListItem from 'cozy-ui/transpiled/react/ListItem';
7
6
  import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon';
8
7
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText';
9
8
  import Typography from 'cozy-ui/transpiled/react/Typography';
10
9
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
10
+ import MemberRecipientStatus from './MemberRecipientStatus';
11
11
  import { getInitials, getDisplayName } from '../../models';
12
12
 
13
13
  var GroupRecipientDetailWithAccess = function GroupRecipientDetailWithAccess(_ref) {
@@ -16,10 +16,12 @@ var GroupRecipientDetailWithAccess = function GroupRecipientDetailWithAccess(_re
16
16
  var _useI18n = useI18n(),
17
17
  t = _useI18n.t;
18
18
 
19
+ var client = useClient();
19
20
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Typography, {
20
21
  variant: "subtitle2"
21
22
  }, t('GroupRecipientDetail.withAccess.title')), /*#__PURE__*/React.createElement(List, null, withAccess.map(function (recipient) {
22
23
  var name = getDisplayName(recipient);
24
+ var isMe = recipient.instance === client.options.uri;
23
25
  return /*#__PURE__*/React.createElement(ListItem, {
24
26
  disableGutters: true,
25
27
  key: recipient.index
@@ -28,15 +30,11 @@ var GroupRecipientDetailWithAccess = function GroupRecipientDetailWithAccess(_re
28
30
  textId: name
29
31
  })), /*#__PURE__*/React.createElement(ListItemText, {
30
32
  primary: name,
31
- secondary: recipient.instance ? /*#__PURE__*/React.createElement("div", {
32
- className: "u-flex u-flex-items-center"
33
- }, /*#__PURE__*/React.createElement(Icon, {
34
- icon: ToTheCloudIcon,
35
- size: 10,
36
- style: {
37
- marginRight: '0.25rem'
38
- }
39
- }), recipient.instance) : null
33
+ secondary: /*#__PURE__*/React.createElement(MemberRecipientStatus, {
34
+ status: recipient.status,
35
+ isMe: isMe,
36
+ instance: recipient.instance
37
+ })
40
38
  }));
41
39
  })));
42
40
  };
@@ -8,10 +8,12 @@ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon';
8
8
  import ListItemText from 'cozy-ui/transpiled/react/ListItemText';
9
9
  import Typography from 'cozy-ui/transpiled/react/Typography';
10
10
  import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
11
+ import { DEFAULT_DISPLAY_NAME } from '../../helpers/recipients';
11
12
  import { getInitials, getDisplayName } from '../../models';
12
13
 
13
14
  var GroupRecipientDetailWithoutAccess = function GroupRecipientDetailWithoutAccess(_ref) {
14
- var withoutAccess = _ref.withoutAccess;
15
+ var withoutAccess = _ref.withoutAccess,
16
+ isOwner = _ref.isOwner;
15
17
 
16
18
  var _useI18n = useI18n(),
17
19
  t = _useI18n.t;
@@ -20,10 +22,12 @@ var GroupRecipientDetailWithoutAccess = function GroupRecipientDetailWithoutAcce
20
22
  variant: "subtitle2"
21
23
  }, t('GroupRecipientDetail.withoutAccess.title')), /*#__PURE__*/React.createElement(List, null, withoutAccess.map(function (recipient) {
22
24
  var icon = recipient.status === 'revoked' ? ForbiddenIcon : null;
23
- var name = getDisplayName(recipient);
25
+ var defaultDisplayName = t(DEFAULT_DISPLAY_NAME);
26
+ var name = getDisplayName(recipient, defaultDisplayName);
24
27
  return /*#__PURE__*/React.createElement(ListItem, {
25
28
  disableGutters: true,
26
- key: recipient.index
29
+ key: recipient.index,
30
+ ellipsis: false
27
31
  }, /*#__PURE__*/React.createElement(ListItemIcon, null, /*#__PURE__*/React.createElement(Avatar, {
28
32
  text: getInitials(recipient),
29
33
  textId: name
@@ -37,7 +41,7 @@ var GroupRecipientDetailWithoutAccess = function GroupRecipientDetailWithoutAcce
37
41
  style: {
38
42
  marginRight: '0.25rem'
39
43
  }
40
- }) : null, t("GroupRecipientDetail.withoutAccess.status.".concat(recipient.status)))
44
+ }) : null, t("GroupRecipientDetail.withoutAccess.status.".concat(recipient.status)), isOwner ? " - ".concat(t('GroupRecipientDetail.withoutAccess.addEmail')) : null)
41
45
  }));
42
46
  })));
43
47
  };
@@ -2,7 +2,6 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _regeneratorRuntime from "@babel/runtime/regenerator";
4
4
  import React, { useState, useRef } from 'react';
5
- import { useClient } from 'cozy-client';
6
5
  import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu';
7
6
  import { makeActions, divider } from 'cozy-ui/transpiled/react/ActionsMenu/Actions';
8
7
  import ActionsMenuMobileHeader from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuMobileHeader';
@@ -19,18 +18,17 @@ import { GroupAvatar } from '../Avatar/GroupAvatar';
19
18
  var GroupRecipientPermissions = function GroupRecipientPermissions(_ref) {
20
19
  var name = _ref.name,
21
20
  isOwner = _ref.isOwner,
22
- instance = _ref.instance,
23
21
  sharingId = _ref.sharingId,
24
22
  groupIndex = _ref.groupIndex,
25
23
  _ref$read_only = _ref.read_only,
26
24
  isReadOnly = _ref$read_only === void 0 ? false : _ref$read_only,
27
- className = _ref.className;
25
+ className = _ref.className,
26
+ isUserInsideMembers = _ref.isUserInsideMembers;
28
27
 
29
28
  var _useI18n = useI18n(),
30
29
  t = _useI18n.t;
31
30
 
32
31
  var buttonRef = useRef();
33
- var client = useClient();
34
32
 
35
33
  var _useSharingContext = useSharingContext(),
36
34
  revokeGroup = _useSharingContext.revokeGroup,
@@ -46,8 +44,7 @@ var GroupRecipientPermissions = function GroupRecipientPermissions(_ref) {
46
44
  revoking = _useState4[0],
47
45
  setRevoking = _useState4[1];
48
46
 
49
- var instanceMatchesClient = instance !== undefined && instance === client.options.uri;
50
- var shouldShowMenu = !revoking && (instanceMatchesClient && !isOwner || isOwner);
47
+ var shouldShowMenu = !revoking && (isOwner || isUserInsideMembers);
51
48
 
52
49
  var toggleMenu = function toggleMenu() {
53
50
  return setMenuDisplayed(!isMenuDisplayed);
@@ -14,10 +14,9 @@ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n';
14
14
  import MemberRecipientPermissions from './MemberRecipientPermissions';
15
15
  import MemberRecipientStatus from './MemberRecipientStatus';
16
16
  import RecipientConfirm from './RecipientConfirm';
17
- import { FADE_IN_DURATION } from '../../helpers/recipients';
17
+ import { FADE_IN_DURATION, DEFAULT_DISPLAY_NAME } from '../../helpers/recipients';
18
18
  import { getDisplayName } from '../../models';
19
19
  import { MemberAvatar } from '../Avatar/MemberAvatar';
20
- var DEFAULT_DISPLAY_NAME = 'Share.contacts.defaultDisplayName';
21
20
 
22
21
  var MemberRecipient = function MemberRecipient(props) {
23
22
  var _useI18n = useI18n(),
@@ -85,7 +85,7 @@ var MemberRecipientPermissions = function MemberRecipientPermissions(_ref) {
85
85
  })), [isOwner, onRevoke, onRevokeSelf, document, sharingId, memberIndex]);
86
86
  var actions = makeActions([permission, divider, revokeMember], {
87
87
  t: t,
88
- type: type,
88
+ type: type !== null && type !== void 0 ? type : 'one-way',
89
89
  isOwner: isOwner,
90
90
  handleRevocation: handleRevocation
91
91
  });
@@ -7,9 +7,10 @@ import Avatar from 'cozy-ui/transpiled/react/Avatar';
7
7
  import Chip from 'cozy-ui/transpiled/react/Chips';
8
8
  import { Spinner } from 'cozy-ui/transpiled/react/Spinner';
9
9
  import palette from 'cozy-ui/transpiled/react/palette';
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
  var styles = {
14
15
  "container": "autosuggest__container___1Yro7",
15
16
  "suggestionsContainer": "autosuggest__suggestionsContainer___3EDuG",
@@ -26,7 +27,6 @@ var ShareAutocomplete = function ShareAutocomplete(_ref) {
26
27
  var loading = _ref.loading,
27
28
  contactsAndGroups = _ref.contactsAndGroups,
28
29
  recipients = _ref.recipients,
29
- onFocus = _ref.onFocus,
30
30
  onPick = _ref.onPick,
31
31
  onRemove = _ref.onRemove,
32
32
  placeholder = _ref.placeholder;
@@ -46,6 +46,11 @@ var ShareAutocomplete = function ShareAutocomplete(_ref) {
46
46
  isPasted = _useState6[0],
47
47
  setIsPasted = _useState6[1];
48
48
 
49
+ var _useState7 = useState(false),
50
+ _useState8 = _slicedToArray(_useState7, 2),
51
+ isLoadingDisplayed = _useState8[0],
52
+ setLoadingDisplayed = _useState8[1];
53
+
49
54
  var autosuggestRef = useRef(null);
50
55
 
51
56
  var computeSuggestions = function computeSuggestions(value) {
@@ -118,7 +123,8 @@ var ShareAutocomplete = function ShareAutocomplete(_ref) {
118
123
  };
119
124
 
120
125
  var onAutosuggestFocus = function onAutosuggestFocus() {
121
- onFocus();
126
+ // We only show the loading state when the user has focus on the input
127
+ setLoadingDisplayed(true);
122
128
  };
123
129
 
124
130
  var onAutosuggestBlur = function onAutosuggestBlur() {
@@ -148,12 +154,15 @@ var ShareAutocomplete = function ShareAutocomplete(_ref) {
148
154
  return /*#__PURE__*/React.createElement("div", {
149
155
  className: styles['recipientsContainer']
150
156
  }, recipients.map(function (recipient, idx) {
157
+ var isContactGroup = recipient._type === Group.doctype;
151
158
  var avatarText = getInitials(recipient);
152
159
  var name = getDisplayName(recipient);
153
160
  return /*#__PURE__*/React.createElement(Chip, {
154
161
  id: "recipient_".concat(idx),
155
162
  key: "key_recipient_".concat(idx),
156
- avatar: /*#__PURE__*/React.createElement(Avatar, {
163
+ avatar: isContactGroup ? /*#__PURE__*/React.createElement(GroupAvatar, {
164
+ size: "xsmall"
165
+ }) : /*#__PURE__*/React.createElement(Avatar, {
157
166
  text: avatarText,
158
167
  size: "xsmall"
159
168
  }),
@@ -166,10 +175,9 @@ var ShareAutocomplete = function ShareAutocomplete(_ref) {
166
175
  }), /*#__PURE__*/React.createElement("input", _extends({}, inputProps, {
167
176
  onKeyPress: onKeyPress,
168
177
  onKeyUp: onKeyUp
169
- })), loading && /*#__PURE__*/React.createElement(Spinner, {
170
- color: palette.dodgerBlue,
171
- className: "u-flex u-flex-items-center"
172
- }));
178
+ })), loading && isLoadingDisplayed ? /*#__PURE__*/React.createElement(Spinner, {
179
+ color: palette.dodgerBlue
180
+ }) : null);
173
181
  };
174
182
 
175
183
  var renderSuggestion = function renderSuggestion(contactOrGroup) {
@@ -206,7 +214,6 @@ ShareAutocomplete.propTypes = {
206
214
  loading: PropTypes.bool,
207
215
  contactsAndGroups: PropTypes.array,
208
216
  recipients: PropTypes.array.isRequired,
209
- onFocus: PropTypes.func.isRequired,
210
217
  onPick: PropTypes.func.isRequired,
211
218
  onRemove: PropTypes.func.isRequired,
212
219
  placeholder: PropTypes.string
@@ -1,26 +1,38 @@
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
  import ShareAutosuggest from './ShareAutosuggest';
4
4
  import AppLike from '../../test/AppLike';
5
+ jest.mock('cozy-ui/transpiled/react/Spinner', function () {
6
+ return {
7
+ Spinner: function Spinner() {
8
+ return /*#__PURE__*/React.createElement("div", null, "loading");
9
+ }
10
+ };
11
+ });
5
12
  describe('ShareAutosuggest', function () {
6
- it('tests if ShareAutosuggest calls onFocus and onPick', function () {
7
- var onPick = jest.fn();
8
- var onFocus = jest.fn();
9
- var onRemove = jest.fn();
10
-
11
- var _render = render( /*#__PURE__*/React.createElement(AppLike, null, /*#__PURE__*/React.createElement(ShareAutosuggest, {
13
+ var setup = function setup(_ref) {
14
+ var onPick = _ref.onPick,
15
+ onRemove = _ref.onRemove,
16
+ _ref$loading = _ref.loading,
17
+ loading = _ref$loading === void 0 ? false : _ref$loading;
18
+ render( /*#__PURE__*/React.createElement(AppLike, null, /*#__PURE__*/React.createElement(ShareAutosuggest, {
19
+ loading: loading,
12
20
  contactsAndGroups: [],
13
21
  placeholder: "myPlaceHolder",
14
22
  onPick: onPick,
15
- onFocus: onFocus,
16
23
  recipients: [],
17
24
  onRemove: onRemove
18
- }))),
19
- getByPlaceholderText = _render.getByPlaceholderText;
25
+ })));
26
+ };
20
27
 
21
- var inputNode = getByPlaceholderText('myPlaceHolder');
22
- inputNode.focus();
23
- expect(onFocus).toHaveBeenCalled(); // It should not call onPick if the value is not an email
28
+ it('tests if ShareAutosuggest calls onPick', function () {
29
+ var onPick = jest.fn();
30
+ var onRemove = jest.fn();
31
+ setup({
32
+ onPick: onPick,
33
+ onRemove: onRemove
34
+ });
35
+ var inputNode = screen.getByPlaceholderText('myPlaceHolder'); // It should not call onPick if the value is not an email
24
36
 
25
37
  fireEvent.change(inputNode, {
26
38
  target: {
@@ -66,4 +78,17 @@ describe('ShareAutosuggest', function () {
66
78
  email: 'quentin.valmori@cozycloud.cc'
67
79
  });
68
80
  });
81
+ it('should show loading only after user focus input', function () {
82
+ var onPick = jest.fn();
83
+ var onRemove = jest.fn();
84
+ setup({
85
+ onPick: onPick,
86
+ onRemove: onRemove,
87
+ loading: true
88
+ });
89
+ var inputNode = screen.getByPlaceholderText('myPlaceHolder');
90
+ expect(screen.queryByText('loading')).toBeNull();
91
+ fireEvent.focus(inputNode);
92
+ expect(screen.getByText('loading')).toBeInTheDocument();
93
+ });
69
94
  });
@@ -0,0 +1,61 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+ import React, { useState } from 'react';
5
+ import ShareAutosuggest from './ShareAutosuggest';
6
+ var meta = {
7
+ component: ShareAutosuggest,
8
+ args: {}
9
+ };
10
+ export default meta;
11
+
12
+ var ShareAutosuggestRender = function ShareAutosuggestRender(props) {
13
+ var _useState = useState([]),
14
+ _useState2 = _slicedToArray(_useState, 2),
15
+ recipients = _useState2[0],
16
+ setRecipients = _useState2[1];
17
+
18
+ var onPick = function onPick(contactOrGroup) {
19
+ setRecipients([].concat(_toConsumableArray(recipients), [contactOrGroup]));
20
+ };
21
+
22
+ var onRemove = function onRemove(contactOrGroup) {
23
+ setRecipients(recipients.filter(function (r) {
24
+ return r.id !== contactOrGroup.id;
25
+ }));
26
+ };
27
+
28
+ return /*#__PURE__*/React.createElement(ShareAutosuggest, _extends({}, props, {
29
+ recipients: recipients,
30
+ onPick: onPick,
31
+ onRemove: onRemove
32
+ }));
33
+ };
34
+
35
+ export var Default = {
36
+ name: 'Default',
37
+ render: ShareAutosuggestRender,
38
+ args: {
39
+ loading: false,
40
+ contactsAndGroups: [{
41
+ id: 'group1',
42
+ name: 'Family',
43
+ _type: 'io.cozy.contacts.groups',
44
+ members: [{
45
+ id: 'contact1',
46
+ name: 'John Doe',
47
+ _type: 'io.cozy.contacts'
48
+ }, {
49
+ id: 'contact2',
50
+ name: 'Jane Doe',
51
+ _type: 'io.cozy.contacts'
52
+ }]
53
+ }, {
54
+ id: 'contact3',
55
+ name: 'Alice Wonderland',
56
+ _type: 'io.cozy.contacts',
57
+ email: 'alice@wonder.land'
58
+ }],
59
+ placeholder: 'Type a name or email address'
60
+ }
61
+ };