mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-26 10:20:01 +00:00
UBER-343 Multiple emails per contact (#3327)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
8ce6d005df
commit
da2f5f3ee4
@ -16,7 +16,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Channel, ChannelProvider } from '@hcengineering/contact'
|
import type { Channel, ChannelProvider } from '@hcengineering/contact'
|
||||||
import contact from '@hcengineering/contact'
|
import contact from '@hcengineering/contact'
|
||||||
import type { AttachedData, Doc, Ref } from '@hcengineering/core'
|
import { AttachedData, Doc, Ref, toIdMap } from '@hcengineering/core'
|
||||||
import notification, { DocUpdates } from '@hcengineering/notification'
|
import notification, { DocUpdates } from '@hcengineering/notification'
|
||||||
import { Asset, IntlString, getResource } from '@hcengineering/platform'
|
import { Asset, IntlString, getResource } from '@hcengineering/platform'
|
||||||
import presentation from '@hcengineering/presentation'
|
import presentation from '@hcengineering/presentation'
|
||||||
@ -36,7 +36,7 @@
|
|||||||
import { invokeAction } from '@hcengineering/view-resources'
|
import { invokeAction } from '@hcengineering/view-resources'
|
||||||
import { createEventDispatcher, tick } from 'svelte'
|
import { createEventDispatcher, tick } from 'svelte'
|
||||||
import { Writable, writable } from 'svelte/store'
|
import { Writable, writable } from 'svelte/store'
|
||||||
import { channelProviders, getChannelProviders } from '../utils'
|
import { channelProviders } from '../utils'
|
||||||
import ChannelEditor from './ChannelEditor.svelte'
|
import ChannelEditor from './ChannelEditor.svelte'
|
||||||
|
|
||||||
export let value: AttachedData<Channel>[] | Channel | null
|
export let value: AttachedData<Channel>[] | Channel | null
|
||||||
@ -106,8 +106,9 @@
|
|||||||
displayItems = []
|
displayItems = []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: Item[] = []
|
const result: Item[] = []
|
||||||
const map = getChannelProviders(channelProviders)
|
const map = toIdMap(channelProviders)
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
for (const item of value) {
|
for (const item of value) {
|
||||||
const provider = getProvider(item, map, docUpdates)
|
const provider = getProvider(item, map, docUpdates)
|
||||||
@ -139,27 +140,22 @@
|
|||||||
const focusManager = getFocusManager()
|
const focusManager = getFocusManager()
|
||||||
|
|
||||||
const updateMenu = (_displayItems: Item[], providers: ChannelProvider[]): void => {
|
const updateMenu = (_displayItems: Item[], providers: ChannelProvider[]): void => {
|
||||||
actions = []
|
actions = providers.map((pr) => {
|
||||||
providers.forEach((pr) => {
|
return {
|
||||||
if (_displayItems.filter((it) => it.provider === pr._id).length === 0) {
|
icon: pr.icon ?? contact.icon.SocialEdit,
|
||||||
actions.push({
|
label: pr.label,
|
||||||
icon: pr.icon ?? contact.icon.SocialEdit,
|
action: async () => {
|
||||||
label: pr.label,
|
const provider = getProvider({ provider: pr._id, value: '' }, toIdMap(providers), $docUpdates)
|
||||||
action: async () => {
|
if (provider !== undefined) {
|
||||||
const provider = getProvider({ provider: pr._id, value: '' }, getChannelProviders(providers), $docUpdates)
|
displayItems = [..._displayItems, provider]
|
||||||
if (provider !== undefined) {
|
if (focusIndex !== -1) {
|
||||||
if (_displayItems.filter((it) => it.provider === pr._id).length === 0) {
|
await tick()
|
||||||
displayItems = [..._displayItems, provider]
|
focusManager?.setFocusPos(focusIndex + displayItems.length)
|
||||||
if (focusIndex !== -1) {
|
await tick()
|
||||||
await tick()
|
editChannel(btns[displayItems.length - 1], displayItems.length - 1, provider)
|
||||||
focusManager?.setFocusPos(focusIndex + displayItems.length)
|
|
||||||
await tick()
|
|
||||||
editChannel(btns[displayItems.length - 1], displayItems.length - 1, provider)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -170,7 +166,6 @@
|
|||||||
}
|
}
|
||||||
const saveItems = (): void => {
|
const saveItems = (): void => {
|
||||||
value = filterUndefined(displayItems)
|
value = filterUndefined(displayItems)
|
||||||
dispatch('change', value)
|
|
||||||
updateMenu(displayItems, $channelProviders)
|
updateMenu(displayItems, $channelProviders)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +177,12 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function remove (n: number) {
|
||||||
|
const removed = displayItems[n]
|
||||||
|
displayItems = dropItem(n)
|
||||||
|
dispatch('remove', removed.channel)
|
||||||
|
}
|
||||||
|
|
||||||
const editChannel = (el: HTMLElement, n: number, item: Item): void => {
|
const editChannel = (el: HTMLElement, n: number, item: Item): void => {
|
||||||
if (opened !== n) {
|
if (opened !== n) {
|
||||||
opened = n
|
opened = n
|
||||||
@ -195,7 +196,9 @@
|
|||||||
},
|
},
|
||||||
el,
|
el,
|
||||||
(result) => {
|
(result) => {
|
||||||
if (result === undefined && item.value === '') displayItems = dropItem(n)
|
if (result === undefined && item.value === '') {
|
||||||
|
remove(n)
|
||||||
|
}
|
||||||
if (result === 'open') {
|
if (result === 'open') {
|
||||||
if (item.action) {
|
if (item.action) {
|
||||||
const doc = item.channel as Channel
|
const doc = item.channel as Channel
|
||||||
@ -205,12 +208,14 @@
|
|||||||
}
|
}
|
||||||
} else if (result != null) {
|
} else if (result != null) {
|
||||||
if (result === '') {
|
if (result === '') {
|
||||||
displayItems = dropItem(n)
|
remove(n)
|
||||||
} else {
|
} else {
|
||||||
item.value = result
|
item.value = result
|
||||||
if (displayItems.find((it) => item.value === it.value) === undefined) {
|
if (displayItems[n] === undefined) {
|
||||||
displayItems = [...displayItems, item]
|
displayItems = [...displayItems, item]
|
||||||
}
|
}
|
||||||
|
item.channel.value = item.value
|
||||||
|
dispatch('save', item.channel)
|
||||||
}
|
}
|
||||||
saveItems()
|
saveItems()
|
||||||
focusManager?.setFocusPos(focusIndex + 1 + n)
|
focusManager?.setFocusPos(focusIndex + 1 + n)
|
||||||
@ -220,11 +225,12 @@
|
|||||||
(result) => {
|
(result) => {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (result === '') {
|
if (result === '') {
|
||||||
displayItems = dropItem(n)
|
remove(n)
|
||||||
} else {
|
} else {
|
||||||
item.value = result
|
item.value = result
|
||||||
|
saveItems()
|
||||||
|
dispatch('save', item.channel)
|
||||||
}
|
}
|
||||||
saveItems()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Class, Doc, Ref, TxResult } from '@hcengineering/core'
|
import type { AttachedData, Class, Doc, Ref } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { ButtonKind, ButtonSize, closeTooltip } from '@hcengineering/ui'
|
import { ButtonKind, ButtonSize, closeTooltip } from '@hcengineering/ui'
|
||||||
|
|
||||||
@ -38,13 +38,6 @@
|
|||||||
|
|
||||||
let channels: Channel[] = []
|
let channels: Channel[] = []
|
||||||
|
|
||||||
function findValue (provider: Ref<ChannelProvider>): Channel | undefined {
|
|
||||||
for (let i = 0; i < channels.length; i++) {
|
|
||||||
if (channels[i].provider === provider) return channels[i]
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
$: attachedTo &&
|
$: attachedTo &&
|
||||||
query.query(
|
query.query(
|
||||||
@ -59,52 +52,25 @@
|
|||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
async function save (newValues: Channel[]): Promise<void> {
|
async function remove (value: Channel | AttachedData<Channel>): Promise<void> {
|
||||||
const currentProviders = new Set(channels.map((p) => p.provider))
|
if (!editable) return
|
||||||
const promises: Array<Promise<TxResult>> = []
|
if ('_id' in value) {
|
||||||
for (const value of newValues) {
|
await client.remove(value)
|
||||||
const oldChannel = findValue(value.provider)
|
|
||||||
if (oldChannel === undefined) {
|
|
||||||
if (value.value.length === 0) continue
|
|
||||||
promises.push(
|
|
||||||
client.addCollection(contact.class.Channel, contact.space.Contacts, attachedTo, attachedClass, 'channels', {
|
|
||||||
value: value.value,
|
|
||||||
provider: value.provider
|
|
||||||
})
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
currentProviders.delete(value.provider)
|
|
||||||
if (value.value === oldChannel.value) continue
|
|
||||||
promises.push(
|
|
||||||
client.updateCollection(
|
|
||||||
oldChannel._class,
|
|
||||||
oldChannel.space,
|
|
||||||
oldChannel._id,
|
|
||||||
oldChannel.attachedTo,
|
|
||||||
oldChannel.attachedToClass,
|
|
||||||
oldChannel.collection,
|
|
||||||
{
|
|
||||||
value: value.value
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (const value of currentProviders) {
|
}
|
||||||
const oldChannel = findValue(value)
|
|
||||||
if (oldChannel === undefined) continue
|
async function saveHandler (value: Channel | AttachedData<Channel>): Promise<void> {
|
||||||
promises.push(
|
if (!editable) return
|
||||||
client.removeCollection(
|
if ('_id' in value) {
|
||||||
oldChannel._class,
|
await client.update(value, {
|
||||||
oldChannel.space,
|
value: value.value
|
||||||
oldChannel._id,
|
})
|
||||||
oldChannel.attachedTo,
|
} else {
|
||||||
oldChannel.attachedToClass,
|
await client.addCollection(contact.class.Channel, contact.space.Contacts, attachedTo, attachedClass, 'channels', {
|
||||||
oldChannel.collection
|
value: value.value,
|
||||||
)
|
provider: value.provider
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
Promise.all(promises)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _open (ev: any) {
|
function _open (ev: any) {
|
||||||
@ -127,8 +93,11 @@
|
|||||||
{restricted}
|
{restricted}
|
||||||
{shape}
|
{shape}
|
||||||
{focusIndex}
|
{focusIndex}
|
||||||
on:change={(e) => {
|
on:remove={(e) => {
|
||||||
if (editable) save(e.detail)
|
remove(e.detail)
|
||||||
|
}}
|
||||||
|
on:save={(e) => {
|
||||||
|
saveHandler(e.detail)
|
||||||
}}
|
}}
|
||||||
on:open={_open}
|
on:open={_open}
|
||||||
/>
|
/>
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Channel, ChannelProvider } from '@hcengineering/contact'
|
import type { Channel, ChannelProvider } from '@hcengineering/contact'
|
||||||
import type { AttachedData, Doc, Ref } from '@hcengineering/core'
|
import { AttachedData, Doc, Ref, toIdMap } from '@hcengineering/core'
|
||||||
import notification, { DocUpdates } from '@hcengineering/notification'
|
import notification, { DocUpdates } from '@hcengineering/notification'
|
||||||
import { Asset, IntlString, getResource } from '@hcengineering/platform'
|
import { Asset, IntlString, getResource } from '@hcengineering/platform'
|
||||||
import type { AnyComponent } from '@hcengineering/ui'
|
import type { AnyComponent } from '@hcengineering/ui'
|
||||||
import { Button } from '@hcengineering/ui'
|
import { Button } from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { Writable, writable } from 'svelte/store'
|
import { Writable, writable } from 'svelte/store'
|
||||||
import { channelProviders, getChannelProviders } from '../utils'
|
import { channelProviders } from '../utils'
|
||||||
import ChannelsPopup from './ChannelsPopup.svelte'
|
import ChannelsPopup from './ChannelsPopup.svelte'
|
||||||
|
|
||||||
export let value: AttachedData<Channel>[] | Channel | null
|
export let value: AttachedData<Channel>[] | Channel | null
|
||||||
@ -81,7 +81,7 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const result: any[] = []
|
const result: any[] = []
|
||||||
const map = getChannelProviders(channels)
|
const map = toIdMap(channels)
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
for (const item of value) {
|
for (const item of value) {
|
||||||
const provider = getProvider(item, map, docUpdates)
|
const provider = getProvider(item, map, docUpdates)
|
||||||
|
@ -36,14 +36,6 @@ import { FilterQuery } from '@hcengineering/view-resources'
|
|||||||
import { get, writable } from 'svelte/store'
|
import { get, writable } from 'svelte/store'
|
||||||
import contact from './plugin'
|
import contact from './plugin'
|
||||||
|
|
||||||
export function getChannelProviders (providers: ChannelProvider[]): Map<Ref<ChannelProvider>, ChannelProvider> {
|
|
||||||
const map = new Map<Ref<ChannelProvider>, ChannelProvider>()
|
|
||||||
for (const provider of providers) {
|
|
||||||
map.set(provider._id, provider)
|
|
||||||
}
|
|
||||||
return map
|
|
||||||
}
|
|
||||||
|
|
||||||
export function formatDate (dueDateMs: Timestamp): string {
|
export function formatDate (dueDateMs: Timestamp): string {
|
||||||
return new Date(dueDateMs).toLocaleString('default', {
|
return new Date(dueDateMs).toLocaleString('default', {
|
||||||
month: 'short',
|
month: 'short',
|
||||||
|
Loading…
Reference in New Issue
Block a user