From 5d5d1a9acfe9e45dd78aae8687fbea1c17338272 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Fri, 25 Feb 2022 20:23:50 +0700 Subject: [PATCH] Show Person Already Exists for Person/Candidates (#1059) Signed-off-by: Andrey Sobolev --- plugins/contact-assets/lang/en.json | 3 +- plugins/contact-assets/lang/ru.json | 3 +- .../src/components/CreatePerson.svelte | 68 ++++++++++--- plugins/contact/src/index.ts | 74 +++++++++++++- .../src/components/CreateCandidate.svelte | 96 +++++++++++++++---- 5 files changed, 210 insertions(+), 34 deletions(-) diff --git a/plugins/contact-assets/lang/en.json b/plugins/contact-assets/lang/en.json index 6cc6c2dea8..e2bb35aeed 100644 --- a/plugins/contact-assets/lang/en.json +++ b/plugins/contact-assets/lang/en.json @@ -44,6 +44,7 @@ "FacebookPlaceholder": "https://fb.com/jappleseed", "Facebook": "Facebook", "SocialLinks": "Socail links", - "ViewActivity": "View activity" + "ViewActivity": "View activity", + "PersonAlreadyExists": "Person already exists..." } } \ No newline at end of file diff --git a/plugins/contact-assets/lang/ru.json b/plugins/contact-assets/lang/ru.json index 25cdcd4e7b..208952ff55 100644 --- a/plugins/contact-assets/lang/ru.json +++ b/plugins/contact-assets/lang/ru.json @@ -44,6 +44,7 @@ "FacebookPlaceholder": "https://fb.com/jappleseed", "Facebook": "Facebook", "SocialLinks": "Контактная информация", - "ViewActivity": "Посмотреть активность" + "ViewActivity": "Посмотреть активность", + "PersonAlreadyExists": "Контакт уже существует..." } } \ No newline at end of file diff --git a/plugins/contact-resources/src/components/CreatePerson.svelte b/plugins/contact-resources/src/components/CreatePerson.svelte index ae8714b081..b0475d2229 100644 --- a/plugins/contact-resources/src/components/CreatePerson.svelte +++ b/plugins/contact-resources/src/components/CreatePerson.svelte @@ -1,4 +1,3 @@ - 0 && lastName.length > 0} + canSave={firstName.length > 0 && lastName.length > 0 && matches.length === 0} bind:space={contact.space.Contacts} on:close={() => { dispatch('close') }} > + {#if matches.length > 0} +
+
+ +
+
+
+ +
+ {/if}
-
-
-
+
+ +
+
+ +
+
+ +
- { channels = e.detail }} /> + { + channels = e.detail + }} + />
@@ -105,4 +130,23 @@ .channels { margin-top: 1.25rem; } + .update-container { + margin-left: -1rem; + margin-right: -1rem; + padding: 1rem; + margin-bottom: 1rem; + user-select: none; + font-size: 14px; + color: var(--theme-content-color); + &.WARNING { + color: yellow; + } + &.ERROR { + color: var(--system-error-color); + } + + border: 1px dashed var(--theme-zone-border); + border-radius: 0.5rem; + backdrop-filter: blur(10px); + } diff --git a/plugins/contact/src/index.ts b/plugins/contact/src/index.ts index 821fd808ea..f8a92c2e19 100644 --- a/plugins/contact/src/index.ts +++ b/plugins/contact/src/index.ts @@ -13,9 +13,9 @@ // limitations under the License. // +import type { Account, AttachedData, AttachedDoc, Class, Client, Data, Doc, FindResult, Ref, Space, UXObject } from '@anticrm/core' +import type { Asset, Plugin } from '@anticrm/platform' import { IntlString, plugin } from '@anticrm/platform' -import type { Plugin, Asset } from '@anticrm/platform' -import type { Doc, Ref, Class, UXObject, Space, Account, AttachedDoc } from '@anticrm/core' import type { AnyComponent } from '@anticrm/ui' /** @@ -119,7 +119,10 @@ export function formatName (name: string): string { */ export const contactId = 'contact' as Plugin -export default plugin(contactId, { +/** + * @public + */ +const contactPlugin = plugin(contactId, { class: { ChannelProvider: '' as Ref>, Channel: '' as Ref>, @@ -166,5 +169,70 @@ export default plugin(contactId, { }, app: { Contacts: '' as Ref + }, + string: { + PersonAlreadyExists: '' as IntlString } }) + +export default contactPlugin + +/** + * @public + */ +export async function findPerson (client: Client, person: Data, channels: AttachedData[]): Promise> { + if (channels.length === 0 || person.name.length === 0) { + return [] + } + // Take only first part of first name for match. + const values = channels.map(it => it.value) + + // Same name persons + + const potentialChannels = await client.findAll(contactPlugin.class.Channel, { value: { $in: values } }) + let potentialPersonIds = Array.from(new Set(potentialChannels.map(it => it.attachedTo as Ref)).values()) + + if (potentialPersonIds.length === 0) { + const firstName = getFirstName(person.name).split(' ').shift() ?? '' + const lastName = getLastName(person.name) + // try match using just first/last name + potentialPersonIds = (await client.findAll(contactPlugin.class.Person, { name: { $like: `${lastName}%${firstName}%` } })).map(it => it._id) + if (potentialPersonIds.length === 0) { + return [] + } + } + + const potentialPersons: FindResult = await client.findAll(contactPlugin.class.Person, { _id: { $in: potentialPersonIds } }, { + lookup: { + _id: { + channels: contactPlugin.class.Channel + } + } + }) + + const result: FindResult = [] + + for (const c of potentialPersons) { + let matches = 0 + if (c.name === person.name) { + matches++ + } + if (c.city === person.city) { + matches++ + } + for (const ch of c.$lookup?.channels as Channel[] ?? []) { + for (const chc of channels) { + if (chc.provider === ch.provider && chc.value === ch.value.trim()) { + // We have matched value + matches += 2 + break + } + } + } + + if (matches >= 2) { + result.push(c) + } + } + return result +} diff --git a/plugins/recruit-resources/src/components/CreateCandidate.svelte b/plugins/recruit-resources/src/components/CreateCandidate.svelte index f8d2341a00..130b8b9e44 100644 --- a/plugins/recruit-resources/src/components/CreateCandidate.svelte +++ b/plugins/recruit-resources/src/components/CreateCandidate.svelte @@ -14,12 +14,24 @@ --> - + let matches: FindResult = [] + $: findPerson(client, { ...object, name: combineName(firstName, lastName) }, channels).then((p) => { + matches = p + }) + 0 && lastName.length > 0} + canSave={firstName.length > 0 && lastName.length > 0 && matches.length === 0} space={contact.space.Contacts} on:close={() => { dispatch('close') }} > - + {#if matches.length > 0} +
+
+ +
+
+
+ +
+ {/if}
-
-
-
-
+
+ +
+
+ +
+
+ +
+
+ +
@@ -490,4 +533,23 @@ border-style: solid; } } + .update-container { + margin-left: -1rem; + margin-right: -1rem; + padding: 1rem; + margin-bottom: 1rem; + user-select: none; + font-size: 14px; + color: var(--theme-content-color); + &.WARNING { + color: yellow; + } + &.ERROR { + color: var(--system-error-color); + } + + border: 1px dashed var(--theme-zone-border); + border-radius: 0.5rem; + backdrop-filter: blur(10px); + }