cozy-sharing 12.3.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.
- package/.storybook/preview.jsx +1 -0
- package/CHANGELOG.md +29 -0
- package/dist/components/ContactSuggestion.js +7 -3
- package/dist/components/ContactSuggestion.spec.js +7 -1
- package/dist/components/Recipient/GroupRecipient.js +14 -7
- package/dist/components/Recipient/GroupRecipientDetail.js +4 -2
- package/dist/components/Recipient/GroupRecipientDetailWithAccess.js +9 -11
- package/dist/components/Recipient/GroupRecipientDetailWithoutAccess.js +8 -4
- package/dist/components/Recipient/GroupRecipientPermissions.js +3 -6
- package/dist/components/Recipient/MemberRecipient.js +1 -2
- package/dist/components/Recipient/MemberRecipientPermissions.js +1 -1
- package/dist/components/ShareAutosuggest.js +16 -9
- package/dist/components/ShareAutosuggest.spec.js +38 -13
- package/dist/components/ShareAutosuggest.stories.js +61 -0
- package/dist/components/ShareByEmail.js +15 -15
- package/dist/components/ShareByEmail.spec.js +0 -6
- package/dist/components/ShareDialogCozyToCozy.js +1 -5
- package/dist/components/ShareDialogCozyToCozy.spec.js +0 -61
- package/dist/components/ShareDialogTwoStepsConfirmationContainer.js +1 -5
- package/dist/components/ShareDialogTwoStepsConfirmationContainer.spec.js +0 -61
- package/dist/components/ShareModal/EditableSharingModal.js +3 -10
- package/dist/components/ShareModal/EditableSharingModal.spec.js +0 -6
- package/dist/components/ShareModal.js +1 -8
- package/dist/components/ShareRecipientsInput.js +46 -49
- package/dist/components/ShareRecipientsInput.spec.js +120 -144
- package/dist/helpers/contacts.js +12 -1
- package/dist/helpers/recipients.js +16 -9
- package/dist/helpers/successMessage.js +58 -16
- package/dist/helpers/successMessage.spec.js +122 -57
- package/dist/queries/queries.js +37 -5
- package/dist/styles/autosuggest.styl +2 -1
- package/dist/stylesheet.css +2 -1
- package/locales/en.json +23 -10
- package/locales/fr.json +23 -8
- package/package.json +4 -4
- package/src/components/ContactSuggestion.jsx +9 -3
- package/src/components/ContactSuggestion.spec.jsx +10 -1
- package/src/components/Recipient/GroupRecipient.jsx +17 -10
- package/src/components/Recipient/GroupRecipientDetail.jsx +5 -2
- package/src/components/Recipient/GroupRecipientDetailWithAccess.jsx +9 -14
- package/src/components/Recipient/GroupRecipientDetailWithoutAccess.jsx +8 -3
- package/src/components/Recipient/GroupRecipientPermissions.jsx +3 -8
- package/src/components/Recipient/MemberRecipient.jsx +4 -3
- package/src/components/Recipient/MemberRecipientPermissions.jsx +1 -1
- package/src/components/ShareAutosuggest.jsx +16 -11
- package/src/components/ShareAutosuggest.spec.jsx +31 -10
- package/src/components/ShareAutosuggest.stories.jsx +63 -0
- package/src/components/ShareByEmail.jsx +11 -11
- package/src/components/ShareByEmail.spec.jsx +0 -4
- package/src/components/ShareDialogCozyToCozy.jsx +0 -4
- package/src/components/ShareDialogCozyToCozy.spec.jsx +0 -67
- package/src/components/ShareDialogTwoStepsConfirmationContainer.jsx +0 -4
- package/src/components/ShareDialogTwoStepsConfirmationContainer.spec.jsx +0 -67
- package/src/components/ShareModal/EditableSharingModal.jsx +3 -21
- package/src/components/ShareModal/EditableSharingModal.spec.jsx +0 -2
- package/src/components/ShareModal.jsx +1 -7
- package/src/components/ShareRecipientsInput.jsx +84 -52
- package/src/components/ShareRecipientsInput.spec.jsx +140 -145
- package/src/helpers/contacts.js +8 -0
- package/src/helpers/recipients.js +24 -15
- package/src/helpers/successMessage.js +71 -21
- package/src/helpers/successMessage.spec.js +129 -69
- package/src/queries/queries.js +36 -5
- package/src/styles/autosuggest.styl +2 -1
- package/test/AppLike.jsx +6 -3
|
@@ -284,57 +284,6 @@ const deferablePromise = () => {
|
|
|
284
284
|
|
|
285
285
|
const getMockProps = () => {
|
|
286
286
|
return {
|
|
287
|
-
contacts: {
|
|
288
|
-
id: 'contacts',
|
|
289
|
-
definition: {
|
|
290
|
-
doctype: 'io.cozy.contacts',
|
|
291
|
-
selector: {
|
|
292
|
-
_id: {
|
|
293
|
-
$gt: null
|
|
294
|
-
}
|
|
295
|
-
},
|
|
296
|
-
indexedFields: ['_id'],
|
|
297
|
-
partialFilter: {
|
|
298
|
-
trashed: {
|
|
299
|
-
$or: [
|
|
300
|
-
{
|
|
301
|
-
$eq: false
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
$exists: false
|
|
305
|
-
}
|
|
306
|
-
]
|
|
307
|
-
},
|
|
308
|
-
$or: [
|
|
309
|
-
{
|
|
310
|
-
cozy: {
|
|
311
|
-
$not: {
|
|
312
|
-
$size: 0
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
email: {
|
|
318
|
-
$not: {
|
|
319
|
-
$size: 0
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
]
|
|
324
|
-
},
|
|
325
|
-
limit: 1000
|
|
326
|
-
},
|
|
327
|
-
fetchStatus: 'pending',
|
|
328
|
-
lastFetch: null,
|
|
329
|
-
lastUpdate: null,
|
|
330
|
-
lastErrorUpdate: null,
|
|
331
|
-
lastError: null,
|
|
332
|
-
hasMore: false,
|
|
333
|
-
count: 0,
|
|
334
|
-
data: [],
|
|
335
|
-
bookmark: null,
|
|
336
|
-
options: null
|
|
337
|
-
},
|
|
338
287
|
document: {
|
|
339
288
|
id: 'SOME_DOCUMENT_ID',
|
|
340
289
|
name: 'SOME_DOCUMENT_NAME',
|
|
@@ -342,22 +291,6 @@ const getMockProps = () => {
|
|
|
342
291
|
_id: 'SOME_DOCUMENT_ID'
|
|
343
292
|
},
|
|
344
293
|
documentType: 'Organizations',
|
|
345
|
-
contactGroups: {
|
|
346
|
-
id: 'groups',
|
|
347
|
-
definition: {
|
|
348
|
-
doctype: 'io.cozy.contacts.groups'
|
|
349
|
-
},
|
|
350
|
-
fetchStatus: 'pending',
|
|
351
|
-
lastFetch: null,
|
|
352
|
-
lastUpdate: null,
|
|
353
|
-
lastErrorUpdate: null,
|
|
354
|
-
lastError: null,
|
|
355
|
-
hasMore: false,
|
|
356
|
-
count: 0,
|
|
357
|
-
data: [],
|
|
358
|
-
bookmark: null,
|
|
359
|
-
options: null
|
|
360
|
-
},
|
|
361
294
|
hasSharedParent: null,
|
|
362
295
|
isOwner: true,
|
|
363
296
|
link: null,
|
|
@@ -1,33 +1,17 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
-
import { useClient
|
|
4
|
+
import { useClient } from 'cozy-client'
|
|
5
5
|
|
|
6
6
|
import { useFetchDocumentPath } from '../../hooks/useFetchDocumentPath'
|
|
7
7
|
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
8
8
|
import { Contact } from '../../models'
|
|
9
|
-
import {
|
|
10
|
-
buildContactsQuery,
|
|
11
|
-
buildContactGroupsQuery
|
|
12
|
-
} from '../../queries/queries'
|
|
13
|
-
import { default as DumbShareModal } from '../ShareModal'
|
|
9
|
+
import { ShareModal } from '../ShareModal'
|
|
14
10
|
|
|
15
11
|
export const EditableSharingModal = ({ document, ...rest }) => {
|
|
16
12
|
const client = useClient()
|
|
17
13
|
const documentPath = useFetchDocumentPath(client, document)
|
|
18
14
|
|
|
19
|
-
const contactsQuery = buildContactsQuery()
|
|
20
|
-
const contactsResult = useQueryAll(
|
|
21
|
-
contactsQuery.definition,
|
|
22
|
-
contactsQuery.options
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
const contactGroupsQuery = buildContactGroupsQuery()
|
|
26
|
-
const contactGroupsResult = useQueryAll(
|
|
27
|
-
contactGroupsQuery.definition,
|
|
28
|
-
contactGroupsQuery.options
|
|
29
|
-
)
|
|
30
|
-
|
|
31
15
|
const {
|
|
32
16
|
documentType,
|
|
33
17
|
getDocumentPermissions,
|
|
@@ -46,9 +30,7 @@ export const EditableSharingModal = ({ document, ...rest }) => {
|
|
|
46
30
|
} = useSharingContext()
|
|
47
31
|
|
|
48
32
|
return (
|
|
49
|
-
<
|
|
50
|
-
contacts={contactsResult}
|
|
51
|
-
contactGroups={contactGroupsResult}
|
|
33
|
+
<ShareModal
|
|
52
34
|
createContact={contact => client.create(Contact.doctype, contact)}
|
|
53
35
|
document={document}
|
|
54
36
|
documentType={documentType}
|
|
@@ -5,10 +5,8 @@ import flag from 'cozy-flags'
|
|
|
5
5
|
|
|
6
6
|
import ShareDialogCozyToCozy from './ShareDialogCozyToCozy'
|
|
7
7
|
import ShareDialogOnlyByLink from './ShareDialogOnlyByLink'
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
export const ShareModal = ({
|
|
10
|
-
contacts,
|
|
11
|
-
contactGroups,
|
|
12
10
|
createContact,
|
|
13
11
|
document,
|
|
14
12
|
documentType = 'Document',
|
|
@@ -56,8 +54,6 @@ export const ShareModal = ({
|
|
|
56
54
|
/>
|
|
57
55
|
) : (
|
|
58
56
|
<ShareDialogCozyToCozy
|
|
59
|
-
contacts={contacts}
|
|
60
|
-
contactGroups={contactGroups}
|
|
61
57
|
createContact={createContact}
|
|
62
58
|
document={document}
|
|
63
59
|
documentType={documentType}
|
|
@@ -88,8 +84,6 @@ export const ShareModal = ({
|
|
|
88
84
|
export default ShareModal
|
|
89
85
|
|
|
90
86
|
ShareModal.propTypes = {
|
|
91
|
-
contacts: contactsResponseType.isRequired,
|
|
92
|
-
contactGroups: contactGroupsResponseType.isRequired,
|
|
93
87
|
createContact: PropTypes.func.isRequired,
|
|
94
88
|
document: PropTypes.object.isRequired,
|
|
95
89
|
documentType: PropTypes.string,
|
|
@@ -1,75 +1,109 @@
|
|
|
1
|
-
import get from 'lodash/get'
|
|
2
1
|
import PropTypes from 'prop-types'
|
|
3
|
-
import React
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { useQueryAll, isQueryLoading } from 'cozy-client'
|
|
5
|
+
import flag from 'cozy-flags'
|
|
4
6
|
|
|
5
7
|
import ShareAutosuggest from './ShareAutosuggest'
|
|
6
|
-
import {
|
|
8
|
+
import { getContactsFromGroupId } from '../helpers/contacts'
|
|
9
|
+
import {
|
|
10
|
+
buildReachableContactsQuery,
|
|
11
|
+
buildContactGroupsByIdsQuery,
|
|
12
|
+
buildUnreachableContactsWithGroupsQuery
|
|
13
|
+
} from '../queries/queries'
|
|
7
14
|
|
|
15
|
+
/**
|
|
16
|
+
* ShareRecipientsInput is responsible for fetching contacts and groups.
|
|
17
|
+
* We retrieve all the contacts that are reachable and the groups they belong to.
|
|
18
|
+
* In order to display the total number of members in each group, we also retrieve the contacts that are not reachable.
|
|
19
|
+
*/
|
|
8
20
|
const ShareRecipientsInput = ({
|
|
9
|
-
contacts,
|
|
10
|
-
contactGroups,
|
|
11
21
|
recipients,
|
|
12
22
|
placeholder,
|
|
13
23
|
onPick,
|
|
14
24
|
onRemove
|
|
15
25
|
}) => {
|
|
16
|
-
const
|
|
26
|
+
const reachableContactsQuery = buildReachableContactsQuery()
|
|
27
|
+
const reachableContactsResult = useQueryAll(
|
|
28
|
+
reachableContactsQuery.definition,
|
|
29
|
+
reachableContactsQuery.options
|
|
30
|
+
)
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
) {
|
|
26
|
-
setLoading(false)
|
|
32
|
+
const unreachableContactsWithGroupsQuery =
|
|
33
|
+
buildUnreachableContactsWithGroupsQuery()
|
|
34
|
+
const unreachableContactsWithGroupsResult = useQueryAll(
|
|
35
|
+
unreachableContactsWithGroupsQuery.definition,
|
|
36
|
+
{
|
|
37
|
+
...unreachableContactsWithGroupsQuery.options,
|
|
38
|
+
enabled: !!flag('sharing.show-recipient-groups')
|
|
27
39
|
}
|
|
28
|
-
|
|
40
|
+
)
|
|
29
41
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
const contactGroupsByIdsQuery = buildContactGroupsByIdsQuery([
|
|
43
|
+
...new Set(
|
|
44
|
+
(reachableContactsResult.data || []).flatMap(contact => {
|
|
45
|
+
return (contact.relationships?.groups?.data || []).map(
|
|
46
|
+
group => group._id
|
|
47
|
+
)
|
|
48
|
+
})
|
|
49
|
+
)
|
|
50
|
+
])
|
|
51
|
+
const contactGroupsByIdsResult = useQueryAll(
|
|
52
|
+
contactGroupsByIdsQuery.definition,
|
|
53
|
+
contactGroupsByIdsQuery.options
|
|
54
|
+
)
|
|
40
55
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
const isLoading =
|
|
57
|
+
isQueryLoading(reachableContactsResult) ||
|
|
58
|
+
reachableContactsResult.hasMore ||
|
|
59
|
+
isQueryLoading(contactGroupsByIdsResult) ||
|
|
60
|
+
contactGroupsByIdsResult.hasMore ||
|
|
61
|
+
(flag('sharing.show-recipient-groups') &&
|
|
62
|
+
(isQueryLoading(unreachableContactsWithGroupsResult) ||
|
|
63
|
+
unreachableContactsWithGroupsResult.hasMore))
|
|
64
|
+
|
|
65
|
+
const contactGroups = (contactGroupsByIdsResult.data || []).map(
|
|
66
|
+
contactGroup => {
|
|
67
|
+
const reachableMembers = getContactsFromGroupId(
|
|
68
|
+
reachableContactsResult.data,
|
|
69
|
+
contactGroup.id
|
|
70
|
+
).map(contact => ({
|
|
71
|
+
...contact,
|
|
72
|
+
isReachable: true
|
|
73
|
+
}))
|
|
74
|
+
|
|
75
|
+
if (flag('sharing.show-recipient-groups') !== true) {
|
|
76
|
+
return {
|
|
48
77
|
...contactGroup,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.map(group => group._id)
|
|
53
|
-
.includes(contactGroup._id)
|
|
54
|
-
) {
|
|
55
|
-
return total + 1
|
|
56
|
-
}
|
|
78
|
+
members: reachableMembers
|
|
79
|
+
}
|
|
80
|
+
}
|
|
57
81
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
const unreachableMembers = getContactsFromGroupId(
|
|
83
|
+
unreachableContactsWithGroupsResult.data,
|
|
84
|
+
contactGroup.id
|
|
85
|
+
).map(contact => ({
|
|
86
|
+
...contact,
|
|
87
|
+
isReachable: false
|
|
88
|
+
}))
|
|
62
89
|
|
|
63
|
-
return
|
|
90
|
+
return {
|
|
91
|
+
...contactGroup,
|
|
92
|
+
members: [...reachableMembers, ...unreachableMembers]
|
|
93
|
+
}
|
|
64
94
|
}
|
|
65
|
-
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
const contactsAndGroups = [
|
|
98
|
+
...(reachableContactsResult.data || []),
|
|
99
|
+
...contactGroups
|
|
100
|
+
]
|
|
66
101
|
|
|
67
102
|
return (
|
|
68
103
|
<ShareAutosuggest
|
|
69
|
-
loading={
|
|
70
|
-
contactsAndGroups={
|
|
104
|
+
loading={isLoading}
|
|
105
|
+
contactsAndGroups={contactsAndGroups}
|
|
71
106
|
recipients={recipients}
|
|
72
|
-
onFocus={onShareAutosuggestFocus}
|
|
73
107
|
onPick={onPick}
|
|
74
108
|
onRemove={onRemove}
|
|
75
109
|
placeholder={placeholder}
|
|
@@ -78,8 +112,6 @@ const ShareRecipientsInput = ({
|
|
|
78
112
|
}
|
|
79
113
|
|
|
80
114
|
ShareRecipientsInput.propTypes = {
|
|
81
|
-
contacts: contactsResponseType.isRequired,
|
|
82
|
-
contactGroups: contactGroupsResponseType.isRequired,
|
|
83
115
|
recipients: PropTypes.array,
|
|
84
116
|
placeholder: PropTypes.string,
|
|
85
117
|
onPick: PropTypes.func.isRequired,
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { render, screen } from '@testing-library/react'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
+
import { createMockClient } from 'cozy-client'
|
|
5
|
+
import flag from 'cozy-flags'
|
|
6
|
+
|
|
4
7
|
import ShareRecipientsInput from './ShareRecipientsInput'
|
|
8
|
+
import AppLike from './SharingBanner/test/AppLike'
|
|
9
|
+
|
|
10
|
+
jest.mock('cozy-flags', () => ({
|
|
11
|
+
__esModule: true,
|
|
12
|
+
default: jest.fn()
|
|
13
|
+
}))
|
|
5
14
|
|
|
6
15
|
jest.mock('./ShareAutosuggest', () => ({
|
|
7
16
|
__esModule: true,
|
|
@@ -16,7 +25,11 @@ jest.mock('./ShareAutosuggest', () => ({
|
|
|
16
25
|
</li>
|
|
17
26
|
)
|
|
18
27
|
} else {
|
|
19
|
-
return
|
|
28
|
+
return (
|
|
29
|
+
<li key={contactOrGroup.id}>
|
|
30
|
+
{contactOrGroup.name} - {contactOrGroup.members.length} members
|
|
31
|
+
</li>
|
|
32
|
+
)
|
|
20
33
|
}
|
|
21
34
|
})}
|
|
22
35
|
</ul>
|
|
@@ -25,176 +38,158 @@ jest.mock('./ShareAutosuggest', () => ({
|
|
|
25
38
|
}))
|
|
26
39
|
|
|
27
40
|
describe('ShareRecipientsInput component', () => {
|
|
28
|
-
const setup = ({ contacts, contactGroups }) => {
|
|
41
|
+
const setup = ({ contacts, contactGroups, unreachableContact }) => {
|
|
42
|
+
const mockClient = createMockClient({
|
|
43
|
+
queries: {
|
|
44
|
+
'io.cozy.contacts/reachable': {
|
|
45
|
+
doctype: 'io.cozy.contacts',
|
|
46
|
+
data: contacts
|
|
47
|
+
},
|
|
48
|
+
'io.cozy.contacts.groups/by-ids/fe86af20-c6c5': {
|
|
49
|
+
doctype: 'io.cozy.contacts.groups',
|
|
50
|
+
data: contactGroups
|
|
51
|
+
},
|
|
52
|
+
'io.cozy.contacts/unreachable-with-groups': {
|
|
53
|
+
doctype: 'io.cozy.contacts',
|
|
54
|
+
data: unreachableContact
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
})
|
|
29
58
|
render(
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
<AppLike client={mockClient}>
|
|
60
|
+
<ShareRecipientsInput
|
|
61
|
+
onPick={() => {}}
|
|
62
|
+
onRemove={() => {}}
|
|
63
|
+
placeholder="Enter recipients here"
|
|
64
|
+
/>
|
|
65
|
+
</AppLike>
|
|
37
66
|
)
|
|
38
67
|
}
|
|
39
68
|
|
|
40
69
|
it('should include groups and contacts when are loaded', async () => {
|
|
41
|
-
const contacts =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
const contacts = [
|
|
71
|
+
{
|
|
72
|
+
id: 'df563cc4-6440',
|
|
73
|
+
_id: 'df563cc4-6440',
|
|
74
|
+
_type: 'io.cozy.contacts',
|
|
75
|
+
name: {
|
|
76
|
+
givenName: 'Michale',
|
|
77
|
+
familyName: 'Russel'
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: '5a3b4ccf-c257',
|
|
82
|
+
_id: '5a3b4ccf-c257',
|
|
83
|
+
_type: 'io.cozy.contacts',
|
|
84
|
+
name: {
|
|
85
|
+
givenName: 'Teagan',
|
|
86
|
+
familyName: 'Wolf'
|
|
54
87
|
},
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
relationships: {
|
|
64
|
-
groups: {
|
|
65
|
-
data: [
|
|
66
|
-
{
|
|
67
|
-
_id: 'fe86af20-c6c5',
|
|
68
|
-
_type: 'io.cozy.contacts.groups'
|
|
69
|
-
}
|
|
70
|
-
]
|
|
71
|
-
}
|
|
88
|
+
relationships: {
|
|
89
|
+
groups: {
|
|
90
|
+
data: [
|
|
91
|
+
{
|
|
92
|
+
_id: 'fe86af20-c6c5',
|
|
93
|
+
_type: 'io.cozy.contacts.groups'
|
|
94
|
+
}
|
|
95
|
+
]
|
|
72
96
|
}
|
|
73
97
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
_type: 'io.cozy.contacts.groups'
|
|
86
|
-
}
|
|
87
|
-
]
|
|
88
|
-
}
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
const contactGroups = [
|
|
102
|
+
{
|
|
103
|
+
id: 'fe86af20-c6c5',
|
|
104
|
+
name: "The Night's Watch",
|
|
105
|
+
_id: 'fe86af20-c6c5',
|
|
106
|
+
_type: 'io.cozy.contacts.groups'
|
|
107
|
+
}
|
|
108
|
+
]
|
|
89
109
|
|
|
90
110
|
setup({ contacts, contactGroups })
|
|
91
111
|
|
|
92
112
|
expect(screen.getByText('Michale Russel')).toBeInTheDocument()
|
|
93
113
|
expect(screen.getByText('Teagan Wolf')).toBeInTheDocument()
|
|
94
|
-
expect(
|
|
114
|
+
expect(
|
|
115
|
+
screen.getByText("The Night's Watch - 1 members")
|
|
116
|
+
).toBeInTheDocument()
|
|
95
117
|
})
|
|
96
118
|
|
|
97
|
-
it('should include
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
it('should include unreachable members when flag sharing.show-recipient-groups is activated', async () => {
|
|
120
|
+
flag.mockReturnValue(true)
|
|
121
|
+
|
|
122
|
+
const contacts = [
|
|
123
|
+
{
|
|
124
|
+
id: 'df563cc4-6440',
|
|
125
|
+
_id: 'df563cc4-6440',
|
|
126
|
+
_type: 'io.cozy.contacts',
|
|
127
|
+
name: {
|
|
128
|
+
givenName: 'Michale',
|
|
129
|
+
familyName: 'Russel'
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: '5a3b4ccf-c257',
|
|
134
|
+
_id: '5a3b4ccf-c257',
|
|
135
|
+
_type: 'io.cozy.contacts',
|
|
136
|
+
name: {
|
|
137
|
+
givenName: 'Teagan',
|
|
138
|
+
familyName: 'Wolf'
|
|
111
139
|
},
|
|
112
|
-
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
relationships: {
|
|
121
|
-
groups: {
|
|
122
|
-
data: [
|
|
123
|
-
{
|
|
124
|
-
_id: 'fe86af20-c6c5',
|
|
125
|
-
_type: 'io.cozy.contacts.groups'
|
|
126
|
-
}
|
|
127
|
-
]
|
|
128
|
-
}
|
|
140
|
+
relationships: {
|
|
141
|
+
groups: {
|
|
142
|
+
data: [
|
|
143
|
+
{
|
|
144
|
+
_id: 'fe86af20-c6c5',
|
|
145
|
+
_type: 'io.cozy.contacts.groups'
|
|
146
|
+
}
|
|
147
|
+
]
|
|
129
148
|
}
|
|
130
149
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const contactGroups = {
|
|
134
|
-
id: 'groups',
|
|
135
|
-
fetchStatus: 'loaded',
|
|
136
|
-
hasMore: false,
|
|
137
|
-
data: [
|
|
138
|
-
{
|
|
139
|
-
id: 'fe86af20-c6c5',
|
|
140
|
-
name: "The Night's Watch",
|
|
141
|
-
_id: 'fe86af20-c6c5',
|
|
142
|
-
_type: 'io.cozy.contacts.groups'
|
|
143
|
-
}
|
|
144
|
-
]
|
|
145
|
-
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
146
152
|
|
|
147
|
-
|
|
153
|
+
const contactGroups = [
|
|
154
|
+
{
|
|
155
|
+
id: 'fe86af20-c6c5',
|
|
156
|
+
name: "The Night's Watch",
|
|
157
|
+
_id: 'fe86af20-c6c5',
|
|
158
|
+
_type: 'io.cozy.contacts.groups'
|
|
159
|
+
}
|
|
160
|
+
]
|
|
148
161
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
fetchStatus: 'loaded',
|
|
158
|
-
hasMore: false,
|
|
159
|
-
data: [
|
|
160
|
-
{
|
|
161
|
-
id: 'df563cc4-6440',
|
|
162
|
-
_id: 'df563cc4-6440',
|
|
163
|
-
_type: 'io.cozy.contacts',
|
|
164
|
-
name: {
|
|
165
|
-
givenName: 'Michale',
|
|
166
|
-
familyName: 'Russel'
|
|
167
|
-
}
|
|
162
|
+
const unreachableContact = [
|
|
163
|
+
{
|
|
164
|
+
id: 'df532cc4-6560',
|
|
165
|
+
_id: 'df532cc4-6560',
|
|
166
|
+
_type: 'io.cozy.contacts',
|
|
167
|
+
name: {
|
|
168
|
+
givenName: 'Tony',
|
|
169
|
+
familyName: 'Stark'
|
|
168
170
|
},
|
|
169
|
-
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
relationships: {
|
|
172
|
+
groups: {
|
|
173
|
+
data: [
|
|
174
|
+
{
|
|
175
|
+
_id: 'fe86af20-c6c5',
|
|
176
|
+
_type: 'io.cozy.contacts.groups'
|
|
177
|
+
}
|
|
178
|
+
]
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const contactGroups = {
|
|
181
|
-
id: 'groups',
|
|
182
|
-
fetchStatus: 'loaded',
|
|
183
|
-
hasMore: false,
|
|
184
|
-
data: [
|
|
185
|
-
{
|
|
186
|
-
id: 'fe86af20-c6c5',
|
|
187
|
-
name: "The Night's Watch",
|
|
188
|
-
_id: 'fe86af20-c6c5',
|
|
189
|
-
_type: 'io.cozy.contacts.groups'
|
|
190
|
-
}
|
|
191
|
-
]
|
|
192
|
-
}
|
|
181
|
+
}
|
|
182
|
+
]
|
|
193
183
|
|
|
194
|
-
setup({ contacts, contactGroups })
|
|
184
|
+
setup({ contacts, contactGroups, unreachableContact })
|
|
195
185
|
|
|
196
186
|
expect(screen.getByText('Michale Russel')).toBeInTheDocument()
|
|
197
187
|
expect(screen.getByText('Teagan Wolf')).toBeInTheDocument()
|
|
198
|
-
|
|
188
|
+
// 3 members because cozy-client replay the query with the new data
|
|
189
|
+
// so the unreachableContact is added to the reachable contact query
|
|
190
|
+
// TODO: improve createMockClient to handle this case
|
|
191
|
+
expect(
|
|
192
|
+
screen.getByText("The Night's Watch - 3 members")
|
|
193
|
+
).toBeInTheDocument()
|
|
199
194
|
})
|
|
200
195
|
})
|
package/src/helpers/contacts.js
CHANGED
|
@@ -39,3 +39,11 @@ export const getOrCreateFromArray = async (client, contacts, createContact) => {
|
|
|
39
39
|
})
|
|
40
40
|
)
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
export const getContactsFromGroupId = (contacts = [], groupId) => {
|
|
44
|
+
return contacts.filter(contact => {
|
|
45
|
+
return contact.relationships?.groups?.data?.some(
|
|
46
|
+
group => group._id === groupId
|
|
47
|
+
)
|
|
48
|
+
})
|
|
49
|
+
}
|