mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-10 01:15:03 +00:00
Fix contact check
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
dc03a1e89d
commit
99d56a3b6a
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { AttachedData, Class, Client, Doc, FindResult, Hierarchy, Ref } from '@hcengineering/core'
|
||||
import { AttachedData, Class, Client, Doc, Hierarchy, Ref } from '@hcengineering/core'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import { ColorDefinition } from '@hcengineering/ui'
|
||||
import { AvatarProvider, AvatarType, Channel, Contact, Person, contactPlugin } from '.'
|
||||
@ -95,68 +95,57 @@ export async function findContacts (
|
||||
return { contacts: [], channels: [] }
|
||||
}
|
||||
// Take only first part of first name for match.
|
||||
const values = channels.map((it) => it.value)
|
||||
const values = channels.map((it) => it.value.trim()).filter((it) => it.length > 0)
|
||||
|
||||
// Same name persons
|
||||
|
||||
const potentialChannels = await client.findAll(
|
||||
contactPlugin.class.Channel,
|
||||
{ value: { $in: values } },
|
||||
{ limit: 1000 }
|
||||
)
|
||||
let potentialContactIds = Array.from(new Set(potentialChannels.map((it) => it.attachedTo as Ref<Contact>)).values())
|
||||
|
||||
const potentialChannels =
|
||||
values.length === 0
|
||||
? []
|
||||
: await client.findAll(contactPlugin.class.Channel, { value: { $in: values } }, { limit: 1000 })
|
||||
const channelsMap = new Map<Ref<Contact>, Channel[]>()
|
||||
for (const ch of potentialChannels) {
|
||||
const arr = channelsMap.get(ch.attachedTo as Ref<Contact>) ?? []
|
||||
channelsMap.set(ch.attachedTo as Ref<Contact>, [...arr, ch])
|
||||
}
|
||||
const potentialContactIds = Array.from(channelsMap.keys())
|
||||
let potentialPersons: Contact[] = []
|
||||
if (potentialContactIds.length === 0) {
|
||||
if (client.getHierarchy().isDerived(_class, contactPlugin.class.Person)) {
|
||||
const firstName = getFirstName(name).split(' ').shift() ?? ''
|
||||
const lastName = getLastName(name)
|
||||
// try match using just first/last name
|
||||
potentialContactIds = (
|
||||
await client.findAll(
|
||||
contactPlugin.class.Contact,
|
||||
{ name: { $like: `${lastName}%${firstName}%` } },
|
||||
{ limit: 100 }
|
||||
)
|
||||
).map((it) => it._id)
|
||||
if (potentialContactIds.length === 0) {
|
||||
return { contacts: [], channels: [] }
|
||||
}
|
||||
potentialPersons = await client.findAll(
|
||||
contactPlugin.class.Contact,
|
||||
{ name: { $like: `${lastName}%${firstName}%` } },
|
||||
{ limit: 100 }
|
||||
)
|
||||
} else if (client.getHierarchy().isDerived(_class, contactPlugin.class.Organization)) {
|
||||
// try match using just first/last name
|
||||
potentialContactIds = (
|
||||
await client.findAll(contactPlugin.class.Contact, { name: { $like: `${name}` } }, { limit: 100 })
|
||||
).map((it) => it._id)
|
||||
if (potentialContactIds.length === 0) {
|
||||
return { contacts: [], channels: [] }
|
||||
}
|
||||
potentialPersons = await client.findAll(
|
||||
contactPlugin.class.Contact,
|
||||
{ name: { $like: `${name}` } },
|
||||
{ limit: 100 }
|
||||
)
|
||||
}
|
||||
} else {
|
||||
potentialPersons = await client.findAll(contactPlugin.class.Contact, { _id: { $in: potentialContactIds } })
|
||||
}
|
||||
|
||||
const potentialPersons: FindResult<Contact> = await client.findAll(
|
||||
contactPlugin.class.Contact,
|
||||
{ _id: { $in: potentialContactIds } },
|
||||
{
|
||||
lookup: {
|
||||
_id: {
|
||||
channels: contactPlugin.class.Channel
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const result: Contact[] = []
|
||||
const resChannels: AttachedData<Channel>[] = []
|
||||
for (const c of potentialPersons) {
|
||||
let matches = 0
|
||||
if (c.name === name) {
|
||||
if (c.name.trim().toLowerCase() === name.trim().toLowerCase()) {
|
||||
matches++
|
||||
}
|
||||
for (const ch of (c.$lookup?.channels as Channel[]) ?? []) {
|
||||
const contactChannels = channelsMap.get(c._id) ?? []
|
||||
for (const ch of contactChannels) {
|
||||
for (const chc of channels) {
|
||||
if (chc.provider === ch.provider && chc.value === ch.value.trim()) {
|
||||
if (chc.provider === ch.provider && chc.value.trim().toLowerCase() === ch.value.trim().toLowerCase()) {
|
||||
// We have matched value
|
||||
resChannels.push(chc)
|
||||
matches += 2
|
||||
matches++
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +525,12 @@
|
||||
]
|
||||
}
|
||||
|
||||
$: if (object.firstName != null && object.lastName != null) {
|
||||
$: if (
|
||||
object.firstName != null &&
|
||||
object.firstName.trim().length > 0 &&
|
||||
object.lastName != null &&
|
||||
object.lastName.trim().length > 0
|
||||
) {
|
||||
void findContacts(
|
||||
client,
|
||||
contact.class.Person,
|
||||
@ -748,69 +753,78 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<div
|
||||
class="flex-center resume"
|
||||
class:solid={dragover || object.resumeUuid}
|
||||
on:dragover|preventDefault={() => {
|
||||
dragover = true
|
||||
}}
|
||||
on:dragleave={() => {
|
||||
dragover = false
|
||||
}}
|
||||
on:drop|preventDefault|stopPropagation={drop}
|
||||
>
|
||||
{#if loading && object.resumeUuid}
|
||||
<Button label={recruit.string.Parsing} icon={Spinner} disabled />
|
||||
{:else}
|
||||
{#if loading}
|
||||
<Button label={recruit.string.Uploading} icon={Spinner} disabled />
|
||||
{:else if object.resumeUuid}
|
||||
<Button
|
||||
disabled={loading}
|
||||
focusIndex={103}
|
||||
icon={FileIcon}
|
||||
on:click={() => {
|
||||
showPopup(
|
||||
FilePreviewPopup,
|
||||
{
|
||||
file: object.resumeUuid,
|
||||
contentType: object.resumeType,
|
||||
name: object.resumeName
|
||||
},
|
||||
object.resumeType?.startsWith('image/') ? 'centered' : 'float'
|
||||
)
|
||||
}}
|
||||
>
|
||||
<svelte:fragment slot="content">
|
||||
<span class="overflow-label disabled">{object.resumeName}</span>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
{#if matches.length === 0}
|
||||
<div
|
||||
class="flex-center resume"
|
||||
class:solid={dragover || object.resumeUuid}
|
||||
on:dragover|preventDefault={() => {
|
||||
dragover = true
|
||||
}}
|
||||
on:dragleave={() => {
|
||||
dragover = false
|
||||
}}
|
||||
on:drop|preventDefault|stopPropagation={drop}
|
||||
>
|
||||
{#if loading && object.resumeUuid}
|
||||
<Button label={recruit.string.Parsing} icon={Spinner} disabled />
|
||||
{:else}
|
||||
<Button
|
||||
focusIndex={103}
|
||||
label={recruit.string.AddDropHere}
|
||||
icon={IconAttachment}
|
||||
notSelected
|
||||
on:click={() => {
|
||||
inputFile.click()
|
||||
}}
|
||||
{#if loading}
|
||||
<Button label={recruit.string.Uploading} icon={Spinner} disabled />
|
||||
{:else if object.resumeUuid}
|
||||
<Button
|
||||
disabled={loading}
|
||||
focusIndex={103}
|
||||
icon={FileIcon}
|
||||
on:click={() => {
|
||||
showPopup(
|
||||
FilePreviewPopup,
|
||||
{
|
||||
file: object.resumeUuid,
|
||||
contentType: object.resumeType,
|
||||
name: object.resumeName
|
||||
},
|
||||
object.resumeType?.startsWith('image/') ? 'centered' : 'float'
|
||||
)
|
||||
}}
|
||||
>
|
||||
<svelte:fragment slot="content">
|
||||
<span class="overflow-label disabled">{object.resumeName}</span>
|
||||
</svelte:fragment>
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
focusIndex={103}
|
||||
label={recruit.string.AddDropHere}
|
||||
icon={IconAttachment}
|
||||
notSelected
|
||||
on:click={() => {
|
||||
inputFile.click()
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
<input
|
||||
bind:this={inputFile}
|
||||
type="file"
|
||||
name="file"
|
||||
id="file"
|
||||
style="display: none"
|
||||
on:change={fileSelected}
|
||||
/>
|
||||
{/if}
|
||||
<input bind:this={inputFile} type="file" name="file" id="file" style="display: none" on:change={fileSelected} />
|
||||
{/if}
|
||||
<div class="ml-1">
|
||||
<MiniToggle bind:on={shouldCreateNewSkills} label={recruit.string.CreateNewSkills} />
|
||||
</div>
|
||||
</div>
|
||||
{#if matches.length > 0}
|
||||
<div class="flex-col-stretch flex-grow error-color">
|
||||
<div class="flex mb-1">
|
||||
<IconInfo size={'medium'} />
|
||||
<span class="text-sm overflow-label ml-2">
|
||||
<Label label={contact.string.PersonAlreadyExists} />
|
||||
</span>
|
||||
<div class="ml-1">
|
||||
<MiniToggle bind:on={shouldCreateNewSkills} label={recruit.string.CreateNewSkills} />
|
||||
</div>
|
||||
<PersonPresenter value={matches[0]} avatarSize={'tiny'} />
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="error">
|
||||
{#if matches.length > 0}
|
||||
<div class="flex-row-center error-color">
|
||||
<IconInfo size={'small'} />
|
||||
<span class="text-sm overflow-label ml-2">
|
||||
<Label label={contact.string.PersonAlreadyExists} />
|
||||
</span>
|
||||
<div class="ml-4"><PersonPresenter value={matches[0]} /></div>
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
Loading…
Reference in New Issue
Block a user