mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 21:50:34 +03:00
Telegram attached messages (#902)
Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
parent
a34150221b
commit
fa3b298af9
@ -16,7 +16,7 @@
|
||||
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { Builder, Model, TypeString, TypeBoolean, Prop, ArrOf } from '@anticrm/model'
|
||||
import core, { TAttachedDoc, TDoc } from '@anticrm/model-core'
|
||||
import core, { TAttachedDoc } from '@anticrm/model-core'
|
||||
import contact from '@anticrm/model-contact'
|
||||
import telegram from './plugin'
|
||||
import type { TelegramMessage, SharedTelegramMessage, SharedTelegramMessages } from '@anticrm/telegram'
|
||||
@ -30,17 +30,11 @@ function TypeSharedMessage (): Type<SharedTelegramMessage> {
|
||||
return { _class: telegram.class.SharedMessage, label: 'Shared message' as IntlString }
|
||||
}
|
||||
|
||||
@Model(telegram.class.Message, core.class.Doc, DOMAIN_TELEGRAM)
|
||||
export class TTelegramMessage extends TDoc implements TelegramMessage {
|
||||
@Model(telegram.class.Message, core.class.AttachedDoc, DOMAIN_TELEGRAM)
|
||||
export class TTelegramMessage extends TAttachedDoc implements TelegramMessage {
|
||||
@Prop(TypeString(), 'Content' as IntlString)
|
||||
content!: string
|
||||
|
||||
@Prop(TypeString(), 'Phone' as IntlString)
|
||||
contactPhone!: string
|
||||
|
||||
@Prop(TypeString(), 'User name' as IntlString)
|
||||
contactUserName!: string
|
||||
|
||||
@Prop(TypeBoolean(), 'Incoming' as IntlString)
|
||||
incoming!: boolean
|
||||
}
|
||||
|
@ -1,5 +1,19 @@
|
||||
{
|
||||
"string": {
|
||||
"SharedMessages": "shared Telegram messages"
|
||||
"SharedMessages": "shared Telegram messages",
|
||||
"Next": "Next",
|
||||
"Back": "Back",
|
||||
"Connect": "Connect",
|
||||
"Connecting": "Connecting...",
|
||||
"ConnectFull": "Connect Telegram account",
|
||||
"Password": "Password",
|
||||
"Phone": "Phone",
|
||||
"PhonePlaceholder": "+1 555 333 7777",
|
||||
"PhoneDescr": "Enter your Telegram phone number to connect your account.",
|
||||
"PasswordDescr": "Enter your second factor password",
|
||||
"CodeDescr": "Enter the 5-digit code you received on your Telegram account.",
|
||||
"Cancel": "Cancel",
|
||||
"Share": "Share messages",
|
||||
"PublishSelected": "Publish selected"
|
||||
}
|
||||
}
|
@ -14,45 +14,48 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { ReferenceInput } from '@anticrm/text-editor'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import telegram, { SharedTelegramMessage } from '@anticrm/telegram'
|
||||
import type { TelegramMessage } from '@anticrm/telegram'
|
||||
import { Channel, Contact, EmployeeAccount, formatName } from '@anticrm/contact'
|
||||
import contact from '@anticrm/contact'
|
||||
import { ActionIcon, IconShare, Button, ScrollBox, showPopup } from '@anticrm/ui'
|
||||
import TelegramIcon from './icons/Telegram.svelte'
|
||||
import { getCurrentAccount, Ref, Space } from '@anticrm/core'
|
||||
import setting from '@anticrm/setting'
|
||||
import contact,{ Channel,Contact,EmployeeAccount,formatName } from '@anticrm/contact'
|
||||
import { getCurrentAccount,Ref,SortingOrder,Space } from '@anticrm/core'
|
||||
import login from '@anticrm/login'
|
||||
import { getMetadata } from '@anticrm/platform'
|
||||
import { createQuery,getClient } from '@anticrm/presentation'
|
||||
import setting from '@anticrm/setting'
|
||||
import type { SharedTelegramMessage, TelegramMessage } from '@anticrm/telegram'
|
||||
import { ReferenceInput } from '@anticrm/text-editor'
|
||||
import { ActionIcon,Button,IconShare,ScrollBox,showPopup } from '@anticrm/ui'
|
||||
import telegram from '../plugin'
|
||||
import Connect from './Connect.svelte'
|
||||
import TelegramIcon from './icons/Telegram.svelte'
|
||||
import Messages from './Messages.svelte'
|
||||
|
||||
export let object: Contact
|
||||
let channel: Channel | undefined = undefined
|
||||
const client = getClient()
|
||||
|
||||
client.findOne(contact.class.Channel, {
|
||||
attachedTo: object._id,
|
||||
provider: contact.channelProvider.Telegram
|
||||
}).then((res) => channel = res)
|
||||
|
||||
let messages: TelegramMessage[] = []
|
||||
let account: EmployeeAccount | undefined
|
||||
let accounts: EmployeeAccount[] = []
|
||||
let enabled: boolean
|
||||
let selected: Set<Ref<SharedTelegramMessage>> = new Set<Ref<SharedTelegramMessage>>()
|
||||
let selectable = false
|
||||
const url = getMetadata(login.metadata.TelegramUrl) ?? ''
|
||||
|
||||
const messagesQuery = createQuery()
|
||||
const accauntQuery = createQuery()
|
||||
const accauntsQuery = createQuery()
|
||||
const settingsQuery = createQuery()
|
||||
const accountId = getCurrentAccount()._id
|
||||
|
||||
$: query = channel && (channel.value.startsWith('+')
|
||||
? { contactPhone: channel.value }
|
||||
: { contactUserName: channel.value })
|
||||
$: query && messagesQuery.query(telegram.class.Message, { modifiedBy: accountId, ...query }, (res) => {
|
||||
$: channel && messagesQuery.query(telegram.class.Message, { modifiedBy: accountId, attachedTo: channel._id }, (res) => {
|
||||
messages = res
|
||||
})
|
||||
}, { sort: { modifiedOn: SortingOrder.Ascending }})
|
||||
|
||||
$: accauntQuery.query(contact.class.EmployeeAccount, { _id: accountId as Ref<EmployeeAccount> }, (result) => {
|
||||
account = result[0]
|
||||
$: accountsIds = messages.map((p) => p.modifiedBy as Ref<EmployeeAccount>)
|
||||
$: accauntsQuery.query(contact.class.EmployeeAccount, { _id: { $in: accountsIds }}, (result) => {
|
||||
accounts = result
|
||||
})
|
||||
|
||||
$: settingsQuery.query(
|
||||
@ -62,12 +65,6 @@
|
||||
enabled = res.length > 0
|
||||
}
|
||||
)
|
||||
const client = getClient()
|
||||
|
||||
client.findOne(contact.class.Channel, {
|
||||
attachedTo: object._id,
|
||||
provider: contact.channelProvider.Telegram
|
||||
}).then((res) => channel = res)
|
||||
|
||||
async function sendMsg (to: string, msg: string) {
|
||||
return await fetch(url + '/send-msg', {
|
||||
@ -124,20 +121,20 @@
|
||||
await sendMsg(to, event.detail)
|
||||
}
|
||||
|
||||
function getName (message: TelegramMessage, account: EmployeeAccount | undefined): string {
|
||||
return message.incoming ? object.name : account?.name ?? ''
|
||||
function getName (message: TelegramMessage, accounts: EmployeeAccount[]): string {
|
||||
return message.incoming ? object.name : accounts.find((p) => p._id === message.modifiedBy)?.name ?? ''
|
||||
}
|
||||
|
||||
async function share (): Promise<void> {
|
||||
const selectedMessages = messages.filter((m) => selected.has(m._id as Ref<SharedTelegramMessage>))
|
||||
const selectedMessages = messages.filter((m) => selected.has(m._id as unknown as Ref<SharedTelegramMessage>))
|
||||
await client.addCollection(
|
||||
telegram.class.SharedMessages,
|
||||
object.space,
|
||||
object._id,
|
||||
object._class,
|
||||
'telegramMessages',
|
||||
'sharedTelegramMessages',
|
||||
{
|
||||
messages: convertMessages(selectedMessages)
|
||||
messages: convertMessages(selectedMessages, accounts)
|
||||
}
|
||||
)
|
||||
clear()
|
||||
@ -149,12 +146,12 @@
|
||||
selected = selected
|
||||
}
|
||||
|
||||
function convertMessages (messages: TelegramMessage[]): SharedTelegramMessage[] {
|
||||
function convertMessages (messages: TelegramMessage[], accounts: EmployeeAccount[]): SharedTelegramMessage[] {
|
||||
return messages.map((m) => {
|
||||
return {
|
||||
...m,
|
||||
_id: m._id as Ref<SharedTelegramMessage>,
|
||||
sender: getName(m, account)
|
||||
_id: m._id as unknown as Ref<SharedTelegramMessage>,
|
||||
sender: getName(m, accounts)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -178,7 +175,7 @@
|
||||
<ActionIcon
|
||||
icon={IconShare}
|
||||
size={'medium'}
|
||||
label={'Share messages'}
|
||||
label={telegram.string.Share}
|
||||
direction={'bottom'}
|
||||
action={async () => {
|
||||
selectable = !selectable
|
||||
@ -187,8 +184,8 @@
|
||||
</div>
|
||||
<div class="h-full right-content">
|
||||
<ScrollBox vertical stretch>
|
||||
{#if messages}
|
||||
<Messages messages={convertMessages(messages)} {selectable} bind:selected />
|
||||
{#if messages && accounts}
|
||||
<Messages messages={convertMessages(messages, accounts)} {selectable} bind:selected />
|
||||
{/if}
|
||||
</ScrollBox>
|
||||
</div>
|
||||
@ -199,10 +196,10 @@
|
||||
<span>{selected.size} messages selected</span>
|
||||
<div class="flex">
|
||||
<div>
|
||||
<Button label={'Cancel'} size={'small'} on:click={clear} />
|
||||
<Button label={telegram.string.Cancel} size={'small'} on:click={clear} />
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<Button label={'Publish selected'} size={'small'} primary disabled={!selected.size} on:click={share} />
|
||||
<Button label={telegram.string.PublishSelected} size={'small'} primary disabled={!selected.size} on:click={share} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -211,7 +208,7 @@
|
||||
{:else}
|
||||
<div class="flex-center">
|
||||
<Button
|
||||
label={'Connect'}
|
||||
label={telegram.string.Connect}
|
||||
primary
|
||||
on:click={(e) => {
|
||||
showPopup(Connect, {}, e.target, onConnectClose)
|
||||
|
@ -18,6 +18,7 @@
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import login from '@anticrm/login'
|
||||
import PinPad from './PinPad.svelte'
|
||||
import telegram from '../plugin'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -89,7 +90,7 @@
|
||||
secondFactor = false
|
||||
}
|
||||
|
||||
$: label = connecting ? 'Connecting...' : requested || secondFactor ? 'Connect' : 'Next'
|
||||
$: label = connecting ? telegram.string.Connecting : requested || secondFactor ? telegram.string.Connect : telegram.string.Next
|
||||
|
||||
$: disabled = checkDisabled(connecting, secondFactor, password, requested, error, code, phone)
|
||||
|
||||
@ -120,7 +121,7 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="flex-between header">
|
||||
<div class="overflow-label fs-title"><Label label={'Connect Telegram account'} /></div>
|
||||
<div class="overflow-label fs-title"><Label label={telegram.string.ConnectFull} /></div>
|
||||
<div
|
||||
class="tool"
|
||||
on:click={() => {
|
||||
@ -132,19 +133,19 @@
|
||||
</div>
|
||||
<div class="content">
|
||||
{#if secondFactor}
|
||||
<p><Label label={'Enter your second factor password'} /></p>
|
||||
<EditBox label={'Password'} password placeholder={'password'} bind:value={password} />
|
||||
<p><Label label={telegram.string.PasswordDescr} /></p>
|
||||
<EditBox label={telegram.string.Password} maxWidth="10rem" password placeholder={telegram.string.Password} bind:value={password} />
|
||||
{:else if requested}
|
||||
<p><Label label={'Enter the 5-digit code you received on your Telegram account.'} /></p>
|
||||
<p><Label label={telegram.string.CodeDescr} /></p>
|
||||
<PinPad length={5} bind:value={code} bind:error />
|
||||
{:else}
|
||||
<p><Label label={'Enter your Telegram phone number to connect your account.'} /></p>
|
||||
<EditBox label={'Phone number'} placeholder={'+1 555 333 7777'} bind:value={phone} />
|
||||
<p><Label label={telegram.string.PhoneDescr} /></p>
|
||||
<EditBox label={telegram.string.Phone} maxWidth="10rem" placeholder={telegram.string.PhonePlaceholder} bind:value={phone} />
|
||||
{/if}
|
||||
<div class="footer">
|
||||
<Button {label} primary {disabled} on:click={click} />
|
||||
{#if requested || secondFactor}
|
||||
<a class="link" href={'#'} on:click={back}><Label label={'Back'} /></a>
|
||||
<a class="link" href={'#'} on:click={back}><Label label={telegram.string.Back} /></a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { TelegramMessage } from '@anticrm/telegram'
|
||||
import type { SharedTelegramMessage } from '@anticrm/telegram'
|
||||
|
||||
export let message: TelegramMessage
|
||||
export let message: SharedTelegramMessage
|
||||
</script>
|
||||
|
||||
<div class="datetime-container">
|
||||
|
@ -19,39 +19,13 @@
|
||||
import { formatName } from '@anticrm/contact'
|
||||
import { CheckBox } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { getPlatformColorForText } from '@anticrm/ui'
|
||||
|
||||
export let message: SharedTelegramMessage
|
||||
export let showName: boolean = false
|
||||
export let selected: boolean = false
|
||||
export let selectable: boolean = false
|
||||
|
||||
export let colors: string[] = [
|
||||
'#A5D179',
|
||||
'#77C07B',
|
||||
'#60B96E',
|
||||
'#45AEA3',
|
||||
'#46CBDE',
|
||||
'#47BDF6',
|
||||
'#5AADF6',
|
||||
'#73A6CD',
|
||||
'#B977CB',
|
||||
'#7C6FCD',
|
||||
'#6F7BC5',
|
||||
'#F28469'
|
||||
]
|
||||
|
||||
function getNameColor (name: string): string {
|
||||
let hash = 0
|
||||
let i
|
||||
let chr
|
||||
for (i = 0; i < name.length; i++) {
|
||||
chr = name.charCodeAt(i)
|
||||
hash = (hash << 5) - hash + chr
|
||||
hash |= 0
|
||||
}
|
||||
return colors[Math.abs(hash) % colors.length]
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
@ -65,7 +39,7 @@
|
||||
<div class="flex-grow ml-6 flex" class:mr-6={!selectable} class:justify-end={!message.incoming}>
|
||||
<div class="message" class:outcoming={!message.incoming} class:selected>
|
||||
{#if showName}
|
||||
<div class="name" style="color: {getNameColor(message.sender)}">{formatName(message.sender)}</div>
|
||||
<div class="name" style="color: {getPlatformColorForText(message.sender)}">{formatName(message.sender)}</div>
|
||||
{/if}
|
||||
<div class="flex">
|
||||
<div class="caption-color mr-4"><MessageViewer message={message.content} /></div>
|
||||
@ -87,6 +61,7 @@
|
||||
width: fit-content;
|
||||
background-color: var(--theme-incoming-msg);
|
||||
border-radius: 0.75rem;
|
||||
overflow-wrap: anywhere;
|
||||
|
||||
&.outcoming {
|
||||
background-color: var(--theme-outcoming-msg);
|
||||
|
@ -14,8 +14,25 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
import { IntlString, mergeIds } from '@anticrm/platform'
|
||||
|
||||
import telegram, { telegramId } from '@anticrm/telegram'
|
||||
|
||||
export default mergeIds(telegramId, telegram, {})
|
||||
export default mergeIds(telegramId, telegram, {
|
||||
string: {
|
||||
Next: '' as IntlString,
|
||||
Back: '' as IntlString,
|
||||
Connect: '' as IntlString,
|
||||
Connecting: '' as IntlString,
|
||||
ConnectFull: '' as IntlString,
|
||||
Password: '' as IntlString,
|
||||
Phone: '' as IntlString,
|
||||
PhonePlaceholder: '' as IntlString,
|
||||
PhoneDescr: '' as IntlString,
|
||||
PasswordDescr: '' as IntlString,
|
||||
CodeDescr: '' as IntlString,
|
||||
Cancel: '' as IntlString,
|
||||
Share: '' as IntlString,
|
||||
PublishSelected: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -22,11 +22,9 @@ import type { IntegrationType, Handler } from '@anticrm/setting'
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TelegramMessage extends Doc {
|
||||
export interface TelegramMessage extends AttachedDoc {
|
||||
content: string
|
||||
incoming: boolean
|
||||
contactPhone?: string
|
||||
contactUserName?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user