mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-11 20:27:43 +02:00
Employee email channel (#2711)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -101,6 +101,37 @@ async function setCreate (client: MigrationClient): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function createEmployeeEmail (client: TxOperations): Promise<void> {
|
||||
const employees = await client.findAll(contact.class.Employee, {})
|
||||
const channels = await client.findAll(contact.class.Channel, {
|
||||
provider: contact.channelProvider.Email,
|
||||
attachedTo: { $in: employees.map((p) => p._id) }
|
||||
})
|
||||
const channelsMap = new Map(channels.map((p) => [p.attachedTo, p]))
|
||||
for (const employee of employees) {
|
||||
const acc = await client.findOne(contact.class.EmployeeAccount, { employee: employee._id })
|
||||
if (acc === undefined) continue
|
||||
const current = channelsMap.get(employee._id)
|
||||
if (current === undefined) {
|
||||
await client.addCollection(
|
||||
contact.class.Channel,
|
||||
contact.space.Contacts,
|
||||
employee._id,
|
||||
contact.class.Employee,
|
||||
'channels',
|
||||
{
|
||||
provider: contact.channelProvider.Email,
|
||||
value: acc.email.trim()
|
||||
},
|
||||
undefined,
|
||||
employee.modifiedOn
|
||||
)
|
||||
} else if (current.value !== acc.email.trim()) {
|
||||
await client.update(current, { value: acc.email.trim() }, false, current.modifiedOn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const contactOperation: MigrateOperation = {
|
||||
async migrate (client: MigrationClient): Promise<void> {
|
||||
await setCreate(client)
|
||||
@@ -108,5 +139,6 @@ export const contactOperation: MigrateOperation = {
|
||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
||||
const tx = new TxOperations(client, core.account.System)
|
||||
await createSpace(tx)
|
||||
await createEmployeeEmail(tx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -856,6 +856,19 @@ async function synchronizeUsers (
|
||||
employee: employeeId,
|
||||
role: AccountRole.User
|
||||
})
|
||||
if (u.EMAIL !== undefined && u.EMAIL !== null) {
|
||||
await ops.client.addCollection(
|
||||
contact.class.Channel,
|
||||
contact.space.Contacts,
|
||||
employeeId,
|
||||
contact.class.Employee,
|
||||
'channels',
|
||||
{
|
||||
provider: contact.channelProvider.Email,
|
||||
value: u.EMAIL.trim()
|
||||
}
|
||||
)
|
||||
}
|
||||
await ops.client.createMixin<Doc, BitrixSyncDoc>(
|
||||
employeeId,
|
||||
contact.class.Employee,
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
export let shape: 'circle' | undefined = undefined
|
||||
export let integrations: Set<Ref<Doc>> = new Set<Ref<Doc>>()
|
||||
export let focusIndex = -1
|
||||
export let restricted: Ref<ChannelProvider>[] = []
|
||||
|
||||
const notificationClient = NotificationClientImpl.getClient()
|
||||
const lastViews = notificationClient.getLastViews()
|
||||
@@ -263,7 +264,7 @@
|
||||
{shape}
|
||||
highlight={item.integration || item.notification}
|
||||
on:click={(ev) => {
|
||||
if (editable) {
|
||||
if (editable && !restricted.includes(item.provider)) {
|
||||
closeTooltip()
|
||||
editChannel(eventToHTMLElement(ev), i, item)
|
||||
} else {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
export let size: ButtonSize = 'small'
|
||||
export let length: 'short' | 'full' = 'full'
|
||||
export let shape: 'circle' | undefined = 'circle'
|
||||
export let restricted: Ref<ChannelProvider>[] = []
|
||||
|
||||
let channels: Channel[] = []
|
||||
|
||||
@@ -123,6 +124,7 @@
|
||||
{length}
|
||||
{integrations}
|
||||
{editable}
|
||||
{restricted}
|
||||
{shape}
|
||||
{focusIndex}
|
||||
on:change={(e) => {
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
const client = getClient()
|
||||
|
||||
async function createPerson () {
|
||||
changeEmail()
|
||||
const name = combineName(firstName, lastName)
|
||||
const person: Data<Employee> = {
|
||||
createOn: Date.now(),
|
||||
@@ -68,7 +69,12 @@
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
let channels: AttachedData<Channel>[] = []
|
||||
let channels: AttachedData<Channel>[] = [
|
||||
{
|
||||
provider: contact.channelProvider.Email,
|
||||
value: ''
|
||||
}
|
||||
]
|
||||
|
||||
let matches: Person[] = []
|
||||
$: findPerson(client, { ...object, name: combineName(firstName, lastName) }, channels).then((p) => {
|
||||
@@ -76,6 +82,19 @@
|
||||
})
|
||||
|
||||
const manager = createFocusManager()
|
||||
|
||||
function changeEmail () {
|
||||
const index = channels.findIndex((p) => p.provider === contact.channelProvider.Email)
|
||||
if (index !== -1) {
|
||||
channels[index].value = email.trim()
|
||||
} else {
|
||||
channels.push({
|
||||
provider: contact.channelProvider.Email,
|
||||
value: email.trim()
|
||||
})
|
||||
}
|
||||
channels = channels
|
||||
}
|
||||
</script>
|
||||
|
||||
<FocusHandler {manager} />
|
||||
@@ -115,7 +134,13 @@
|
||||
focusIndex={2}
|
||||
/>
|
||||
<div class="mt-1">
|
||||
<EditBox placeholder={contact.string.Email} bind:value={email} kind={'small-style'} focusIndex={3} />
|
||||
<EditBox
|
||||
placeholder={contact.string.Email}
|
||||
bind:value={email}
|
||||
kind={'small-style'}
|
||||
focusIndex={3}
|
||||
on:blur={changeEmail}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
@@ -123,6 +148,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<svelte:fragment slot="pool">
|
||||
<ChannelsDropdown bind:value={channels} focusIndex={10} kind={'no-border'} editable />
|
||||
<ChannelsDropdown
|
||||
bind:value={channels}
|
||||
focusIndex={10}
|
||||
kind={'no-border'}
|
||||
editable
|
||||
restricted={[contact.channelProvider.Email]}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
</Card>
|
||||
|
||||
@@ -128,7 +128,13 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="separator" />
|
||||
<ChannelsEditor attachedTo={employee._id} attachedClass={employee._class} focusIndex={10} allowOpen={false} />
|
||||
<ChannelsEditor
|
||||
attachedTo={employee._id}
|
||||
attachedClass={employee._class}
|
||||
focusIndex={10}
|
||||
allowOpen={false}
|
||||
restricted={[contact.channelProvider.Email]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -583,12 +583,16 @@ async function createEmployee (ops: TxOperations, name: string, email: string):
|
||||
avatar: `${AvatarType.COLOR}://${getAvatarColorForId(id)}`
|
||||
})
|
||||
}
|
||||
await ops.addCollection(contact.class.Channel, contact.space.Contacts, id, contact.class.Employee, 'channels', {
|
||||
provider: contact.channelProvider.Email,
|
||||
value: email.trim()
|
||||
})
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
async function createEmployeeAccount (account: Account, productId: string, workspace: string): Promise<void> {
|
||||
const connection = await connect(getTransactor(), getWorkspaceId(workspace, productId), account.email)
|
||||
const connection = await connect(getTransactor(), getWorkspaceId(workspace, productId))
|
||||
try {
|
||||
const ops = new TxOperations(connection, core.account.System)
|
||||
|
||||
|
||||
@@ -39,24 +39,26 @@ export class ModifiedMiddleware extends BaseMiddleware implements Middleware {
|
||||
}
|
||||
|
||||
async tx (ctx: SessionContext, tx: Tx): Promise<TxMiddlewareResult> {
|
||||
tx.modifiedOn = Date.now()
|
||||
if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) {
|
||||
const createTx = tx as TxCreateDoc<Doc & { createOn: Timestamp }>
|
||||
const hasCreateOn = this.storage.hierarchy.findAttribute(createTx.objectClass, 'createOn')
|
||||
if (hasCreateOn !== undefined) {
|
||||
createTx.attributes.createOn = tx.modifiedOn
|
||||
}
|
||||
}
|
||||
if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCollectionCUD)) {
|
||||
const coltx = tx as TxCollectionCUD<Doc, AttachedDoc>
|
||||
coltx.tx.modifiedOn = tx.modifiedOn
|
||||
if (this.storage.hierarchy.isDerived(coltx.tx._class, core.class.TxCreateDoc)) {
|
||||
const createTx = coltx.tx as TxCreateDoc<AttachedDoc & { createOn: Timestamp }>
|
||||
if (tx.modifiedBy !== core.account.System) {
|
||||
tx.modifiedOn = Date.now()
|
||||
if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) {
|
||||
const createTx = tx as TxCreateDoc<Doc & { createOn: Timestamp }>
|
||||
const hasCreateOn = this.storage.hierarchy.findAttribute(createTx.objectClass, 'createOn')
|
||||
if (hasCreateOn !== undefined) {
|
||||
createTx.attributes.createOn = tx.modifiedOn
|
||||
}
|
||||
}
|
||||
if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCollectionCUD)) {
|
||||
const coltx = tx as TxCollectionCUD<Doc, AttachedDoc>
|
||||
coltx.tx.modifiedOn = tx.modifiedOn
|
||||
if (this.storage.hierarchy.isDerived(coltx.tx._class, core.class.TxCreateDoc)) {
|
||||
const createTx = coltx.tx as TxCreateDoc<AttachedDoc & { createOn: Timestamp }>
|
||||
const hasCreateOn = this.storage.hierarchy.findAttribute(createTx.objectClass, 'createOn')
|
||||
if (hasCreateOn !== undefined) {
|
||||
createTx.attributes.createOn = tx.modifiedOn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return await this.provideTx(ctx, tx)
|
||||
}
|
||||
|
||||
@@ -25,14 +25,13 @@ test.describe('contact tests', () => {
|
||||
await page.fill('[placeholder="Location"]', 'LoPlaza')
|
||||
// Click .flex-center.icon-button
|
||||
|
||||
if ((await page.locator('[id="gmail:string:Email"]').count()) === 0) {
|
||||
if ((await page.locator('[id="contact:string:Phone"]').count()) === 0) {
|
||||
await page.click('[id="presentation:string:AddSocialLinks"]')
|
||||
await page.click('.popup button:has-text("Email")')
|
||||
await page.click('.popup button:has-text("Phone")')
|
||||
} else {
|
||||
await page.click('id=gmail:string:Email')
|
||||
await page.click('id=contact:string:Phone')
|
||||
}
|
||||
// await page.hover('[id="gmail:string:Email"]')
|
||||
await page.fill('[placeholder="john\\.appleseed\\@apple\\.com"]', 'wer@qwe.com')
|
||||
await page.fill('[placeholder="+1 555 333 7777"]', '+1 555 333 7777')
|
||||
// Click text=Apply
|
||||
await page.click('.editor-container button:nth-child(3)')
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user