cozy-sharing 40.1.8 → 40.2.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 +16 -0
- package/README.md +1 -0
- package/dist/SharingProvider.js +3 -1
- package/dist/components/Recipient/PermissionTypeMenuWrapper.spec.js +3 -1
- package/dist/components/ShareAutosuggest.js +87 -14
- package/dist/components/ShareAutosuggest.spec.js +123 -3
- package/dist/components/ShareAutosuggestWrapper.js +61 -5
- package/dist/components/ShareAutosuggestWrapper.spec.js +113 -11
- package/dist/components/ShareRestrictionModal/helpers.js +2 -1
- package/dist/components/ShareRestrictionModal/helpers.spec.js +2 -2
- package/dist/helpers/contacts.js +75 -16
- package/dist/helpers/contacts.spec.js +150 -1
- package/dist/hooks/useResolveRecipients.js +6 -2
- package/dist/hooks/useResolveRecipients.spec.js +11 -2
- package/dist/queries/queries.js +16 -3
- package/package.json +3 -3
- package/src/SharingProvider.jsx +6 -1
- package/src/components/Recipient/PermissionTypeMenuWrapper.spec.jsx +3 -1
- package/src/components/ShareAutosuggest.jsx +45 -7
- package/src/components/ShareAutosuggest.spec.jsx +59 -2
- package/src/components/ShareAutosuggestWrapper.jsx +34 -4
- package/src/components/ShareAutosuggestWrapper.spec.jsx +78 -5
- package/src/components/ShareRestrictionModal/helpers.js +2 -1
- package/src/components/ShareRestrictionModal/helpers.spec.js +2 -2
- package/src/helpers/contacts.js +31 -1
- package/src/helpers/contacts.spec.js +102 -1
- package/src/hooks/useResolveRecipients.js +5 -2
- package/src/hooks/useResolveRecipients.spec.js +8 -2
- package/src/queries/queries.js +6 -3
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
-
import { useQueryAll, isQueryLoading } from 'cozy-client'
|
|
4
|
+
import { useClient, useQueryAll, isQueryLoading } from 'cozy-client'
|
|
5
|
+
import { models } from 'cozy-client'
|
|
5
6
|
import flag from 'cozy-flags'
|
|
6
7
|
|
|
7
8
|
import ShareAutosuggest from './ShareAutosuggest'
|
|
8
|
-
import { computeContactsAndGroups } from '../helpers/contacts'
|
|
9
|
+
import { computeContactsAndGroups, suggestContacts } from '../helpers/contacts'
|
|
10
|
+
import { useSharingContext } from '../hooks/useSharingContext'
|
|
11
|
+
import { DOCTYPE_GROUPS } from '../models'
|
|
9
12
|
import {
|
|
10
13
|
buildReachableContactsQuery,
|
|
11
14
|
buildContactGroupsQuery,
|
|
12
15
|
buildUnreachableContactsWithGroupsQuery
|
|
13
16
|
} from '../queries/queries'
|
|
14
17
|
|
|
18
|
+
const ContactModel = models.contact
|
|
19
|
+
|
|
15
20
|
/**
|
|
16
21
|
* ShareAutosuggestWrapper is responsible for fetching contacts and groups.
|
|
17
22
|
* We retrieve all the contacts that are reachable and the groups they belong to.
|
|
18
23
|
* In order to display the total number of members in each group, we also retrieve the contacts that are not reachable.
|
|
24
|
+
* With contactsSuggestEnabled, the stack suggests the contacts and we only retrieve the group members.
|
|
19
25
|
*/
|
|
20
26
|
const ShareAutosuggestWrapper = ({
|
|
21
27
|
currentRecipients,
|
|
@@ -28,7 +34,12 @@ const ShareAutosuggestWrapper = ({
|
|
|
28
34
|
autoFocus,
|
|
29
35
|
endAdornment
|
|
30
36
|
}) => {
|
|
31
|
-
const
|
|
37
|
+
const client = useClient()
|
|
38
|
+
const contactsSuggestEnabled = useSharingContext()?.contactsSuggestEnabled
|
|
39
|
+
|
|
40
|
+
const reachableContactsQuery = buildReachableContactsQuery({
|
|
41
|
+
inGroups: contactsSuggestEnabled
|
|
42
|
+
})
|
|
32
43
|
const reachableContactsResult = useQueryAll(
|
|
33
44
|
reachableContactsQuery.definition,
|
|
34
45
|
reachableContactsQuery.options
|
|
@@ -59,7 +70,7 @@ const ShareAutosuggestWrapper = ({
|
|
|
59
70
|
(isQueryLoading(unreachableContactsWithGroupsResult) ||
|
|
60
71
|
unreachableContactsWithGroupsResult.hasMore))
|
|
61
72
|
|
|
62
|
-
const
|
|
73
|
+
const suggestedContactsAndGroups = computeContactsAndGroups({
|
|
63
74
|
reachableContacts: reachableContactsResult.data || [],
|
|
64
75
|
unreachableContactsWithGroups:
|
|
65
76
|
unreachableContactsWithGroupsResult.data || [],
|
|
@@ -68,6 +79,24 @@ const ShareAutosuggestWrapper = ({
|
|
|
68
79
|
pendingRecipients: recipients
|
|
69
80
|
})
|
|
70
81
|
|
|
82
|
+
const contactsAndGroups = contactsSuggestEnabled
|
|
83
|
+
? suggestedContactsAndGroups.filter(({ _type }) => _type === DOCTYPE_GROUPS)
|
|
84
|
+
: suggestedContactsAndGroups
|
|
85
|
+
|
|
86
|
+
// The stack matches the emails whatever their case
|
|
87
|
+
const normalizeEmail = email => email?.trim().toLowerCase()
|
|
88
|
+
const isRecipient = email =>
|
|
89
|
+
currentRecipients.some(r => normalizeEmail(r.email) === email) ||
|
|
90
|
+
recipients.some(
|
|
91
|
+
r => normalizeEmail(ContactModel.getPrimaryEmail(r)) === email
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
const fetchContacts = async q =>
|
|
95
|
+
(await suggestContacts(client, q)).filter(
|
|
96
|
+
contact =>
|
|
97
|
+
!isRecipient(normalizeEmail(ContactModel.getPrimaryEmail(contact)))
|
|
98
|
+
)
|
|
99
|
+
|
|
71
100
|
return (
|
|
72
101
|
<ShareAutosuggest
|
|
73
102
|
loading={isLoading}
|
|
@@ -80,6 +109,7 @@ const ShareAutosuggestWrapper = ({
|
|
|
80
109
|
placeholder={placeholder}
|
|
81
110
|
autoFocus={autoFocus}
|
|
82
111
|
endAdornment={endAdornment}
|
|
112
|
+
fetchContacts={contactsSuggestEnabled ? fetchContacts : undefined}
|
|
83
113
|
/>
|
|
84
114
|
)
|
|
85
115
|
}
|
|
@@ -12,9 +12,12 @@ jest.mock('cozy-flags', () => ({
|
|
|
12
12
|
default: jest.fn(() => null)
|
|
13
13
|
}))
|
|
14
14
|
|
|
15
|
+
let mockAutosuggestProps
|
|
15
16
|
jest.mock('./ShareAutosuggest', () => ({
|
|
16
17
|
__esModule: true,
|
|
17
|
-
default:
|
|
18
|
+
default: props => {
|
|
19
|
+
mockAutosuggestProps = props
|
|
20
|
+
const { contactsAndGroups } = props
|
|
18
21
|
return (
|
|
19
22
|
<ul>
|
|
20
23
|
{contactsAndGroups.map(contactOrGroup => {
|
|
@@ -39,8 +42,8 @@ jest.mock('./ShareAutosuggest', () => ({
|
|
|
39
42
|
|
|
40
43
|
describe('ShareAutosuggestWrapper component', () => {
|
|
41
44
|
const setup = (
|
|
42
|
-
{ contacts, contactGroups, unreachableContact },
|
|
43
|
-
{ currentRecipients, recipients } = {}
|
|
45
|
+
{ contacts, contactGroups, unreachableContact, groupMembers },
|
|
46
|
+
{ currentRecipients, recipients, contactsSuggestEnabled } = {}
|
|
44
47
|
) => {
|
|
45
48
|
const mockClient = createMockClient({
|
|
46
49
|
queries: {
|
|
@@ -55,11 +58,18 @@ describe('ShareAutosuggestWrapper component', () => {
|
|
|
55
58
|
'io.cozy.contacts/unreachable-with-groups': {
|
|
56
59
|
doctype: 'io.cozy.contacts',
|
|
57
60
|
data: unreachableContact
|
|
61
|
+
},
|
|
62
|
+
'io.cozy.contacts/reachable-with-groups': {
|
|
63
|
+
doctype: 'io.cozy.contacts',
|
|
64
|
+
data: groupMembers
|
|
58
65
|
}
|
|
59
66
|
}
|
|
60
67
|
})
|
|
61
68
|
render(
|
|
62
|
-
<AppLike
|
|
69
|
+
<AppLike
|
|
70
|
+
client={mockClient}
|
|
71
|
+
sharingContextValue={{ contactsSuggestEnabled }}
|
|
72
|
+
>
|
|
63
73
|
<ShareAutosuggestWrapper
|
|
64
74
|
onPick={() => {}}
|
|
65
75
|
onRemove={() => {}}
|
|
@@ -69,6 +79,7 @@ describe('ShareAutosuggestWrapper component', () => {
|
|
|
69
79
|
/>
|
|
70
80
|
</AppLike>
|
|
71
81
|
)
|
|
82
|
+
return mockClient
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
it('should include groups and contacts when are loaded', async () => {
|
|
@@ -219,7 +230,7 @@ describe('ShareAutosuggestWrapper component', () => {
|
|
|
219
230
|
})
|
|
220
231
|
|
|
221
232
|
it('should include unreachable members when flag sharing.show-recipient-groups is activated', async () => {
|
|
222
|
-
flag.
|
|
233
|
+
flag.mockImplementation(name => name === 'sharing.show-recipient-groups')
|
|
223
234
|
|
|
224
235
|
const contacts = [
|
|
225
236
|
{
|
|
@@ -294,4 +305,66 @@ describe('ShareAutosuggestWrapper component', () => {
|
|
|
294
305
|
screen.getByText("The Night's Watch - 3 members")
|
|
295
306
|
).toBeInTheDocument()
|
|
296
307
|
})
|
|
308
|
+
|
|
309
|
+
describe('with contactsSuggestEnabled', () => {
|
|
310
|
+
beforeEach(() => {
|
|
311
|
+
flag.mockReset()
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
it('should suggest only groups, with the count of their members', () => {
|
|
315
|
+
const groupMembers = [
|
|
316
|
+
{
|
|
317
|
+
id: '5a3b4ccf-c257',
|
|
318
|
+
_id: '5a3b4ccf-c257',
|
|
319
|
+
_type: 'io.cozy.contacts',
|
|
320
|
+
name: { givenName: 'Teagan', familyName: 'Wolf' },
|
|
321
|
+
relationships: {
|
|
322
|
+
groups: {
|
|
323
|
+
data: [{ _id: 'fe86af20-c6c5', _type: 'io.cozy.contacts.groups' }]
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
const contactGroups = [
|
|
329
|
+
{
|
|
330
|
+
id: 'fe86af20-c6c5',
|
|
331
|
+
_id: 'fe86af20-c6c5',
|
|
332
|
+
_type: 'io.cozy.contacts.groups',
|
|
333
|
+
name: 'Friends'
|
|
334
|
+
}
|
|
335
|
+
]
|
|
336
|
+
|
|
337
|
+
setup({ contactGroups, groupMembers }, { contactsSuggestEnabled: true })
|
|
338
|
+
|
|
339
|
+
expect(screen.getByText('Friends - 1 members')).toBeInTheDocument()
|
|
340
|
+
expect(screen.queryByText('Teagan Wolf')).not.toBeInTheDocument()
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
it('should fetch suggestions without the current and pending recipients, whatever the case of their email', async () => {
|
|
344
|
+
const suggestion = email => ({
|
|
345
|
+
type: 'io.cozy.contacts',
|
|
346
|
+
attributes: { fullname: email, email: [{ address: email }] }
|
|
347
|
+
})
|
|
348
|
+
const mockClient = setup(
|
|
349
|
+
{ contactGroups: [], groupMembers: [] },
|
|
350
|
+
{
|
|
351
|
+
currentRecipients: [{ email: 'Current@Cozy.cc' }],
|
|
352
|
+
recipients: [{ email: 'pending@cozy.cc' }],
|
|
353
|
+
contactsSuggestEnabled: true
|
|
354
|
+
}
|
|
355
|
+
)
|
|
356
|
+
const fetchJSON = jest.fn().mockResolvedValue({
|
|
357
|
+
data: [
|
|
358
|
+
suggestion('current@cozy.cc'),
|
|
359
|
+
suggestion('PENDING@cozy.cc'),
|
|
360
|
+
suggestion('new@cozy.cc')
|
|
361
|
+
]
|
|
362
|
+
})
|
|
363
|
+
jest.spyOn(mockClient, 'getStackClient').mockReturnValue({ fetchJSON })
|
|
364
|
+
|
|
365
|
+
const contacts = await mockAutosuggestProps.fetchContacts('coz')
|
|
366
|
+
|
|
367
|
+
expect(contacts.map(c => c.fullname)).toEqual(['new@cozy.cc'])
|
|
368
|
+
})
|
|
369
|
+
})
|
|
297
370
|
})
|
|
@@ -206,7 +206,8 @@ export const getLinkAccessOptions = ({
|
|
|
206
206
|
verbs: editingRights === 'write' ? WRITE_PERMS : READ_ONLY_PERMS,
|
|
207
207
|
expiresAt: expirationDate?.toISOString() || '',
|
|
208
208
|
ttl: expirationDate ? makeTTL(expirationDate) : undefined,
|
|
209
|
-
|
|
209
|
+
// An empty field means "unchanged": undefined is left out of the request
|
|
210
|
+
password: passwordEnabled ? password || undefined : ''
|
|
210
211
|
}
|
|
211
212
|
}
|
|
212
213
|
|
|
@@ -124,7 +124,7 @@ describe('ShareRestrictionModal/helpers', () => {
|
|
|
124
124
|
})
|
|
125
125
|
})
|
|
126
126
|
|
|
127
|
-
it('should call updateDocumentPermissions with empty date
|
|
127
|
+
it('should call updateDocumentPermissions with an empty date and keep the password if enabled without values', async () => {
|
|
128
128
|
const updateDocumentPermissions = jest.fn()
|
|
129
129
|
const file = { _id: '123' }
|
|
130
130
|
|
|
@@ -143,7 +143,7 @@ describe('ShareRestrictionModal/helpers', () => {
|
|
|
143
143
|
|
|
144
144
|
expect(updateDocumentPermissions).toHaveBeenCalledWith(file, {
|
|
145
145
|
expiresAt: '',
|
|
146
|
-
password:
|
|
146
|
+
password: undefined,
|
|
147
147
|
verbs: ['GET']
|
|
148
148
|
})
|
|
149
149
|
})
|
package/src/helpers/contacts.js
CHANGED
|
@@ -2,13 +2,30 @@ import { models } from 'cozy-client'
|
|
|
2
2
|
import flag from 'cozy-flags'
|
|
3
3
|
|
|
4
4
|
import { validateEmail } from '../helpers/email'
|
|
5
|
+
import { DOCTYPE_CONTACTS, DOCTYPE_GROUPS } from '../models'
|
|
5
6
|
|
|
6
7
|
const ContactModel = models.contact
|
|
7
8
|
|
|
8
9
|
// Return the contact object if present
|
|
9
10
|
// Else check if a contact exist with this email address, if yes return it
|
|
10
11
|
// if not create it
|
|
11
|
-
|
|
12
|
+
// With contactsSuggestEnabled, people are sent by email and the
|
|
13
|
+
// stack finds or creates the contact: an org member's id is not on this instance
|
|
14
|
+
export const getOrCreateFromArray = async (
|
|
15
|
+
client,
|
|
16
|
+
contacts,
|
|
17
|
+
createContact,
|
|
18
|
+
contactsSuggestEnabled
|
|
19
|
+
) => {
|
|
20
|
+
if (contactsSuggestEnabled) {
|
|
21
|
+
return contacts.map(contact => {
|
|
22
|
+
if (contact._type === DOCTYPE_GROUPS) return contact
|
|
23
|
+
const email = ContactModel.getPrimaryEmail(contact)
|
|
24
|
+
if (validateEmail(email)) return { _type: DOCTYPE_CONTACTS, email }
|
|
25
|
+
return contact._id ? contact : undefined
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
return await Promise.all(
|
|
13
30
|
contacts.map(async contact => {
|
|
14
31
|
if (contact.id) {
|
|
@@ -45,6 +62,19 @@ export const getOrCreateFromArray = async (client, contacts, createContact) => {
|
|
|
45
62
|
)
|
|
46
63
|
}
|
|
47
64
|
|
|
65
|
+
// A suggestion without id has no contact document, and only a fullname,
|
|
66
|
+
// which getDisplayName does not read
|
|
67
|
+
export const suggestContacts = async (client, q) => {
|
|
68
|
+
const { data } = await client
|
|
69
|
+
.getStackClient()
|
|
70
|
+
.fetchJSON('GET', `/contacts/suggest?q=${encodeURIComponent(q)}`)
|
|
71
|
+
return data.map(({ id, type, attributes }) => ({
|
|
72
|
+
...attributes,
|
|
73
|
+
...(id ? { _id: id, id } : { displayName: attributes.fullname }),
|
|
74
|
+
_type: type
|
|
75
|
+
}))
|
|
76
|
+
}
|
|
77
|
+
|
|
48
78
|
export const getContactsFromGroupId = (contacts = [], groupId) => {
|
|
49
79
|
return contacts.filter(contact => {
|
|
50
80
|
return contact.relationships?.groups?.data?.some(
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import flag from 'cozy-flags'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
computeContactsAndGroups,
|
|
5
|
+
getOrCreateFromArray,
|
|
6
|
+
suggestContacts
|
|
7
|
+
} from './contacts'
|
|
4
8
|
|
|
5
9
|
jest.mock('cozy-flags', () => ({
|
|
6
10
|
__esModule: true,
|
|
@@ -128,3 +132,100 @@ describe('computeContactsAndGroups', () => {
|
|
|
128
132
|
expect(contactsAndGroups.map(c => c._id)).toEqual(['alice', 'bob'])
|
|
129
133
|
})
|
|
130
134
|
})
|
|
135
|
+
|
|
136
|
+
describe('getOrCreateFromArray with contactsSuggestEnabled', () => {
|
|
137
|
+
it('should send people by email and keep groups, without creating contacts', async () => {
|
|
138
|
+
const createContact = jest.fn()
|
|
139
|
+
const group = { _id: 'group-1', _type: 'io.cozy.contacts.groups' }
|
|
140
|
+
|
|
141
|
+
const recipients = await getOrCreateFromArray(
|
|
142
|
+
mockClient,
|
|
143
|
+
[
|
|
144
|
+
{
|
|
145
|
+
_id: 'org-member-1',
|
|
146
|
+
_type: 'io.cozy.contacts',
|
|
147
|
+
email: [{ address: 'member@org.example', primary: true }],
|
|
148
|
+
meta: { kind: 'member' }
|
|
149
|
+
},
|
|
150
|
+
{ email: 'unknown@friends.example' },
|
|
151
|
+
group
|
|
152
|
+
],
|
|
153
|
+
createContact,
|
|
154
|
+
true
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
expect(recipients).toEqual([
|
|
158
|
+
{ _type: 'io.cozy.contacts', email: 'member@org.example' },
|
|
159
|
+
{ _type: 'io.cozy.contacts', email: 'unknown@friends.example' },
|
|
160
|
+
group
|
|
161
|
+
])
|
|
162
|
+
expect(createContact).not.toHaveBeenCalled()
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('should keep a contact without email by id, and drop a recipient with neither', async () => {
|
|
166
|
+
const cozyOnlyContact = {
|
|
167
|
+
_id: 'contact-1',
|
|
168
|
+
_type: 'io.cozy.contacts',
|
|
169
|
+
cozy: [{ url: 'https://bob.example' }]
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const recipients = await getOrCreateFromArray(
|
|
173
|
+
mockClient,
|
|
174
|
+
[cozyOnlyContact, { instance: 'https://alice.example' }],
|
|
175
|
+
jest.fn(),
|
|
176
|
+
true
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
expect(recipients).toEqual([cozyOnlyContact, undefined])
|
|
180
|
+
})
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
describe('suggestContacts', () => {
|
|
184
|
+
it('should map the suggestions of the stack to contacts', async () => {
|
|
185
|
+
const fetchJSON = jest.fn().mockResolvedValue({
|
|
186
|
+
data: [
|
|
187
|
+
{
|
|
188
|
+
type: 'io.cozy.contacts',
|
|
189
|
+
id: 'org-member-1',
|
|
190
|
+
attributes: {
|
|
191
|
+
fullname: 'Jean Dupont',
|
|
192
|
+
name: { givenName: 'Jean', familyName: 'Dupont' },
|
|
193
|
+
email: [{ address: 'jean@org.example', primary: true }]
|
|
194
|
+
},
|
|
195
|
+
meta: { kind: 'member' }
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
type: 'io.cozy.contacts',
|
|
199
|
+
attributes: {
|
|
200
|
+
fullname: 'Paul Dupuis',
|
|
201
|
+
email: [{ address: 'paul@friends.example', primary: true }]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
})
|
|
206
|
+
const client = { getStackClient: () => ({ fetchJSON }) }
|
|
207
|
+
|
|
208
|
+
const contacts = await suggestContacts(client, 'dup & co')
|
|
209
|
+
|
|
210
|
+
expect(fetchJSON).toHaveBeenCalledWith(
|
|
211
|
+
'GET',
|
|
212
|
+
'/contacts/suggest?q=dup%20%26%20co'
|
|
213
|
+
)
|
|
214
|
+
expect(contacts).toEqual([
|
|
215
|
+
{
|
|
216
|
+
_id: 'org-member-1',
|
|
217
|
+
id: 'org-member-1',
|
|
218
|
+
_type: 'io.cozy.contacts',
|
|
219
|
+
fullname: 'Jean Dupont',
|
|
220
|
+
name: { givenName: 'Jean', familyName: 'Dupont' },
|
|
221
|
+
email: [{ address: 'jean@org.example', primary: true }]
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
_type: 'io.cozy.contacts',
|
|
225
|
+
fullname: 'Paul Dupuis',
|
|
226
|
+
displayName: 'Paul Dupuis',
|
|
227
|
+
email: [{ address: 'paul@friends.example', primary: true }]
|
|
228
|
+
}
|
|
229
|
+
])
|
|
230
|
+
})
|
|
231
|
+
})
|
|
@@ -2,6 +2,7 @@ import { useCallback } from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { useClient } from 'cozy-client'
|
|
4
4
|
|
|
5
|
+
import { useSharingContext } from './useSharingContext'
|
|
5
6
|
import { getOrCreateFromArray } from '../helpers/contacts'
|
|
6
7
|
import { DOCTYPE_CONTACTS } from '../models'
|
|
7
8
|
|
|
@@ -14,6 +15,7 @@ import { DOCTYPE_CONTACTS } from '../models'
|
|
|
14
15
|
*/
|
|
15
16
|
export const useResolveRecipients = () => {
|
|
16
17
|
const client = useClient()
|
|
18
|
+
const contactsSuggestEnabled = useSharingContext()?.contactsSuggestEnabled
|
|
17
19
|
|
|
18
20
|
return useCallback(
|
|
19
21
|
async (
|
|
@@ -24,7 +26,8 @@ export const useResolveRecipients = () => {
|
|
|
24
26
|
const contacts = await getOrCreateFromArray(
|
|
25
27
|
client,
|
|
26
28
|
pendingRecipients,
|
|
27
|
-
createContact
|
|
29
|
+
createContact,
|
|
30
|
+
contactsSuggestEnabled
|
|
28
31
|
)
|
|
29
32
|
const isReadOnly = selectedOption === 'readOnly'
|
|
30
33
|
|
|
@@ -33,6 +36,6 @@ export const useResolveRecipients = () => {
|
|
|
33
36
|
readOnlyRecipients: isReadOnly ? contacts : []
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
|
-
[client]
|
|
39
|
+
[client, contactsSuggestEnabled]
|
|
37
40
|
)
|
|
38
41
|
}
|
|
@@ -13,6 +13,10 @@ jest.mock('../helpers/contacts', () => ({
|
|
|
13
13
|
getOrCreateFromArray: jest.fn()
|
|
14
14
|
}))
|
|
15
15
|
|
|
16
|
+
jest.mock('./useSharingContext', () => ({
|
|
17
|
+
useSharingContext: () => ({ contactsSuggestEnabled: true })
|
|
18
|
+
}))
|
|
19
|
+
|
|
16
20
|
const contacts = [{ _id: 'alice' }, { _id: 'bob' }]
|
|
17
21
|
|
|
18
22
|
describe('useResolveRecipients', () => {
|
|
@@ -48,7 +52,8 @@ describe('useResolveRecipients', () => {
|
|
|
48
52
|
expect(getOrCreateFromArray).toHaveBeenCalledWith(
|
|
49
53
|
mockClient,
|
|
50
54
|
pendingRecipients,
|
|
51
|
-
expect.any(Function)
|
|
55
|
+
expect.any(Function),
|
|
56
|
+
true
|
|
52
57
|
)
|
|
53
58
|
expect(mockClient.create).toHaveBeenCalledWith('io.cozy.contacts', {
|
|
54
59
|
email: [{ address: 'alice@cozy.cc' }]
|
|
@@ -64,7 +69,8 @@ describe('useResolveRecipients', () => {
|
|
|
64
69
|
expect(getOrCreateFromArray).toHaveBeenCalledWith(
|
|
65
70
|
mockClient,
|
|
66
71
|
[],
|
|
67
|
-
createContact
|
|
72
|
+
createContact,
|
|
73
|
+
true
|
|
68
74
|
)
|
|
69
75
|
})
|
|
70
76
|
})
|
package/src/queries/queries.js
CHANGED
|
@@ -16,7 +16,7 @@ export const buildSharingsByIdQuery = sharingId => ({
|
|
|
16
16
|
}
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
export const buildReachableContactsQuery = () => ({
|
|
19
|
+
export const buildReachableContactsQuery = ({ inGroups } = {}) => ({
|
|
20
20
|
definition: Q(DOCTYPE_CONTACTS)
|
|
21
21
|
.where({
|
|
22
22
|
_id: {
|
|
@@ -42,12 +42,15 @@ export const buildReachableContactsQuery = () => ({
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
]
|
|
45
|
+
],
|
|
46
|
+
...(inGroups && { 'relationships.groups.data': { $exists: true } })
|
|
46
47
|
})
|
|
47
48
|
.indexFields(['_id'])
|
|
48
49
|
.limitBy(1000),
|
|
49
50
|
options: {
|
|
50
|
-
as:
|
|
51
|
+
as: inGroups
|
|
52
|
+
? 'io.cozy.contacts/reachable-with-groups'
|
|
53
|
+
: 'io.cozy.contacts/reachable'
|
|
51
54
|
}
|
|
52
55
|
})
|
|
53
56
|
|