Telegram plugin (#357)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2021-11-25 17:05:00 +06:00 committed by GitHub
parent 5ea2d326b9
commit 581f5f0e96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 2134 additions and 1154 deletions

View File

@ -43,6 +43,7 @@ specifiers:
'@rush-temp/model-server-view': file:./projects/model-server-view.tgz
'@rush-temp/model-setting': file:./projects/model-setting.tgz
'@rush-temp/model-task': file:./projects/model-task.tgz
'@rush-temp/model-telegram': file:./projects/model-telegram.tgz
'@rush-temp/model-view': file:./projects/model-view.tgz
'@rush-temp/model-workbench': file:./projects/model-workbench.tgz
'@rush-temp/mongo': file:./projects/mongo.tgz
@ -71,6 +72,8 @@ specifiers:
'@rush-temp/task': file:./projects/task.tgz
'@rush-temp/task-assets': file:./projects/task-assets.tgz
'@rush-temp/task-resources': file:./projects/task-resources.tgz
'@rush-temp/telegram': file:./projects/telegram.tgz
'@rush-temp/telegram-resources': file:./projects/telegram-resources.tgz
'@rush-temp/text-editor': file:./projects/text-editor.tgz
'@rush-temp/theme': file:./projects/theme.tgz
'@rush-temp/tool': file:./projects/tool.tgz
@ -188,6 +191,7 @@ dependencies:
'@rush-temp/model-server-view': file:projects/model-server-view.tgz_typescript@4.4.3
'@rush-temp/model-setting': file:projects/model-setting.tgz_typescript@4.4.3
'@rush-temp/model-task': file:projects/model-task.tgz_typescript@4.4.3
'@rush-temp/model-telegram': file:projects/model-telegram.tgz_typescript@4.4.3
'@rush-temp/model-view': file:projects/model-view.tgz_typescript@4.4.3
'@rush-temp/model-workbench': file:projects/model-workbench.tgz_typescript@4.4.3
'@rush-temp/mongo': file:projects/mongo.tgz_typescript@4.4.3
@ -216,6 +220,8 @@ dependencies:
'@rush-temp/task': file:projects/task.tgz_typescript@4.4.3
'@rush-temp/task-assets': file:projects/task-assets.tgz
'@rush-temp/task-resources': file:projects/task-resources.tgz_e1367da94684b005adf08f025c517b1a
'@rush-temp/telegram': file:projects/telegram.tgz_typescript@4.4.3
'@rush-temp/telegram-resources': file:projects/telegram-resources.tgz_e1367da94684b005adf08f025c517b1a
'@rush-temp/text-editor': file:projects/text-editor.tgz_e1367da94684b005adf08f025c517b1a
'@rush-temp/theme': file:projects/theme.tgz_e1367da94684b005adf08f025c517b1a
'@rush-temp/tool': file:projects/tool.tgz_typescript@4.4.3
@ -9711,7 +9717,7 @@ packages:
dev: false
file:projects/contact.tgz_typescript@4.4.3:
resolution: {integrity: sha512-7ebi6ChLP/85fZ8FuxUgT+0bDqUk92MIoxjQ2diAfHncNNRifsv2gzwO4h7hy10Jy8lVH48SOr/DreW0Vo8PiQ==, tarball: file:projects/contact.tgz}
resolution: {integrity: sha512-KqnVWzHFYfhLQNkBzPYv6UFUcoarkgvMelFNaCVKiiKtKu1uDWaAryDzNHmplIoKyI83gfSJil3UfsQQQ4X0Kw==, tarball: file:projects/contact.tgz}
id: file:projects/contact.tgz
name: '@rush-temp/contact'
version: 0.0.0
@ -9989,7 +9995,7 @@ packages:
dev: false
file:projects/model-all.tgz_typescript@4.4.3:
resolution: {integrity: sha512-UP8PoaNuPoVGjUg1fAHenpbEjGRGwz4PHXGuadhXHzbglw5g2tGJbEGTvrIOkty28uh3K54OZ0EPhcz7it67nA==, tarball: file:projects/model-all.tgz}
resolution: {integrity: sha512-/YBYDWBfD4BpZAQvDlNw2yOV3jTaHlGEZ5RH9Y4egwcxlN75NbieVzy7bbM7UJoDE1aHYgz5lm8wU4QGh7CzIA==, tarball: file:projects/model-all.tgz}
id: file:projects/model-all.tgz
name: '@rush-temp/model-all'
version: 0.0.0
@ -10215,6 +10221,23 @@ packages:
- typescript
dev: false
file:projects/model-telegram.tgz_typescript@4.4.3:
resolution: {integrity: sha512-X4Ao5ADNaxuup/qZv0FeOLSEqXKHVqkqEEdUvHwcMHeHr1SvibSMhlumfTdPGCq70iX2AL2R37FI0DGlx0EnUw==, tarball: file:projects/model-telegram.tgz}
id: file:projects/model-telegram.tgz
name: '@rush-temp/model-telegram'
version: 0.0.0
dependencies:
'@typescript-eslint/eslint-plugin': 4.33.0_eslint@7.32.0+typescript@4.4.3
eslint: 7.32.0
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
transitivePeerDependencies:
- '@typescript-eslint/parser'
- supports-color
- typescript
dev: false
file:projects/model-view.tgz_typescript@4.4.3:
resolution: {integrity: sha512-sFAFEdeAaZtP2ey3GRljrgc/86bYTXIYh5d4Ge/7ztLebbDmyIQx9YAMfxEBc+1XugDRR7mLXDsDAZHC6t5m8Q==, tarball: file:projects/model-view.tgz}
id: file:projects/model-view.tgz
@ -10409,7 +10432,7 @@ packages:
dev: false
file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3:
resolution: {integrity: sha512-GCcPe++xT1m51ZmTKEX/KBB957pSUkO2CbgSa93yCs6XX8V4O6/fiG/w+EPTdhNP/3TSIf8Lk0Ys8pE2uwy20g==, tarball: file:projects/prod.tgz}
resolution: {integrity: sha512-ZgzyuEX4q/KCtkXfJOVOSHEBZEYI6FrJJO2tYxQaynmSq7AQpjIp3XB0uwoagnD3dyzH/S3qAXqvQ7ltgPXhbQ==, tarball: file:projects/prod.tgz}
id: file:projects/prod.tgz
name: '@rush-temp/prod'
version: 0.0.0
@ -10817,6 +10840,54 @@ packages:
- typescript
dev: false
file:projects/telegram-resources.tgz_e1367da94684b005adf08f025c517b1a:
resolution: {integrity: sha512-sbIaaqkc2pyh2dXKHF6S3gj+VZRzBjFngvY1b+RYQ+a0v7bF74kvA+uR7moeRYFf1p8VX3Rqg0kUvC3bSY2lWA==, tarball: file:projects/telegram-resources.tgz}
id: file:projects/telegram-resources.tgz
name: '@rush-temp/telegram-resources'
version: 0.0.0
dependencies:
'@typescript-eslint/eslint-plugin': 4.33.0_eslint@7.32.0+typescript@4.4.3
eslint: 7.32.0
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
sass: 1.42.1
svelte: 3.43.1
svelte-loader: 3.1.2_svelte@3.43.1
svelte-preprocess: 4.9.8_b1ccfb371c7d68f75291f5a547be0b14
transitivePeerDependencies:
- '@babel/core'
- '@typescript-eslint/parser'
- coffeescript
- less
- node-sass
- postcss
- postcss-load-config
- pug
- stylus
- sugarss
- supports-color
- typescript
dev: false
file:projects/telegram.tgz_typescript@4.4.3:
resolution: {integrity: sha512-tUpx+Ryw6IrNxyKxPL99sEfzDhXAy2Q8YAYrBro6lCNrvH12qLHZ3va5wZHtRT0mnvMg8oM0Q+zgaitWfCDQ8w==, tarball: file:projects/telegram.tgz}
id: file:projects/telegram.tgz
name: '@rush-temp/telegram'
version: 0.0.0
dependencies:
'@types/heft-jest': 1.0.2
'@typescript-eslint/eslint-plugin': 4.33.0_eslint@7.32.0+typescript@4.4.3
eslint: 7.32.0
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
transitivePeerDependencies:
- '@typescript-eslint/parser'
- supports-color
- typescript
dev: false
file:projects/text-editor.tgz_e1367da94684b005adf08f025c517b1a:
resolution: {integrity: sha512-1NjObTrxXMOl/tM6PvEf/BUoJFziPNgkbm58/Mriw4JGo7cd13euXyIrIDF/fU74nvlYjf+JKk6oshPawcoiXQ==, tarball: file:projects/text-editor.tgz}
id: file:projects/text-editor.tgz

View File

@ -75,6 +75,8 @@
"@anticrm/server-view-resources": "~0.6.0",
"@anticrm/activity": "~0.6.0",
"@anticrm/activity-assets": "~0.6.0",
"@anticrm/activity-resources": "~0.6.0"
"@anticrm/activity-resources": "~0.6.0",
"@anticrm/telegram": "~0.6.0",
"@anticrm/telegram-resources": "~0.6.0"
}
}

View File

@ -25,6 +25,7 @@ import { chunterId } from '@anticrm/chunter'
import { recruitId } from '@anticrm/recruit'
import { activityId } from '@anticrm/activity'
import { settingId } from '@anticrm/setting'
import { telegramId } from '@anticrm/telegram'
import { serverChunterId } from '@anticrm/server-chunter'
import { serverRecruitId } from '@anticrm/server-recruit'
@ -77,4 +78,5 @@ export function configurePlatform() {
addLocation(recruitId, () => import(/* webpackChunkName: "recruit" */ '@anticrm/recruit-resources'))
addLocation(activityId, () => import(/*webpackChunkName: "activity" */ '@anticrm/activity-resources'))
addLocation(settingId, () => import(/* webpackChunkName: "setting" */ '@anticrm/setting-resources'))
addLocation(telegramId, () => import(/* webpackChunkName: "telegram" */ '@anticrm/telegram-resources'))
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@
"@anticrm/model-chunter": "~0.6.0",
"@anticrm/model-recruit": "~0.6.0",
"@anticrm/model-setting": "~0.6.0",
"@anticrm/model-telegram": "~0.6.0",
"@anticrm/model-demo": "~0.6.0",
"@anticrm/model-server-core": "~0.6.0",
"@anticrm/model-server-chunter": "~0.6.0",

View File

@ -23,6 +23,7 @@ import { createModel as taskModel } from '@anticrm/model-task'
import { createModel as chunterModel } from '@anticrm/model-chunter'
import { createModel as recruitModel } from '@anticrm/model-recruit'
import { createModel as settingModel } from '@anticrm/model-setting'
import { createModel as telegramModel } from '@anticrm/model-telegram'
import { createModel as serverCoreModel } from '@anticrm/model-server-core'
import { createModel as serverChunterModel } from '@anticrm/model-server-chunter'
@ -43,6 +44,7 @@ chunterModel(builder)
taskModel(builder)
recruitModel(builder)
settingModel(builder)
telegramModel(builder)
serverCoreModel(builder)
serverChunterModel(builder)

View File

@ -107,12 +107,6 @@ export function createModel (builder: Builder): void {
placeholder: '@appleseed'
}, contact.channelProvider.Twitter)
builder.createDoc(contact.class.ChannelProvider, core.space.Model, {
label: 'Telegram' as IntlString,
icon: contact.icon.Telegram,
placeholder: '@appleseed'
}, contact.channelProvider.Telegram)
builder.createDoc(core.class.Space, core.space.Model, {
name: 'Employees',
description: 'Employees',

View File

@ -16,19 +16,11 @@
import { mergeIds } from '@anticrm/platform'
import type { Ref, Class, Type } from '@anticrm/core'
import contact, { contactId } from '@anticrm/contact'
import type { ChannelProvider, Channel } from '@anticrm/contact'
import type { Channel } from '@anticrm/contact'
import type { AnyComponent } from '@anticrm/ui'
import {} from '@anticrm/core'
export const ids = mergeIds(contactId, contact, {
channelProvider: {
Email: '' as Ref<ChannelProvider>,
Phone: '' as Ref<ChannelProvider>,
LinkedIn: '' as Ref<ChannelProvider>,
Twitter: '' as Ref<ChannelProvider>,
Telegram: '' as Ref<ChannelProvider>
// GitHub: '' as Ref<ChannelProvider>,
},
component: {
PersonPresenter: '' as AnyComponent,
ChannelsPresenter: '' as AnyComponent

View File

@ -83,13 +83,6 @@ export function createModel (builder: Builder): void {
}
}, setting.ids.SettingApp)
builder.createDoc(setting.class.IntegrationType, core.space.Model, {
label: 'Telegram',
description: 'Use telegram integration' as IntlString,
icon: setting.component.IconTelegram,
createComponent: setting.component.ConnectTelegram
})
builder.createDoc(setting.class.IntegrationType, core.space.Model, {
label: 'Email',
description: 'Use email integration' as IntlString,

View File

@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}

View File

@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/

View File

@ -0,0 +1,18 @@
// The "rig.json" file directs tools to look for their config files in an external package.
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
/**
* (Required) The name of the rig package to inherit from.
* It should be an NPM package name with the "-rig" suffix.
*/
"rigPackageName": "@anticrm/model-rig"
/**
* (Optional) Selects a config profile from the rig package. The name must consist of
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
* If omitted, then the "default" profile will be used."
*/
// "rigProfile": "your-profile-name"
}

View File

@ -0,0 +1,29 @@
{
"name": "@anticrm/model-telegram",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"build:watch": "tsc",
"lint:fix": "eslint --fix src"
},
"devDependencies": {
"@anticrm/model-rig":"~0.6.0",
"@typescript-eslint/eslint-plugin":"4",
"eslint-plugin-import":"2",
"eslint-plugin-promise":"4",
"eslint-plugin-node":"11",
"eslint":"^7.32.0"
},
"dependencies": {
"@anticrm/model": "~0.6.0",
"@anticrm/core": "~0.6.0",
"@anticrm/platform": "~0.6.5",
"@anticrm/model-core": "~0.6.0",
"@anticrm/model-contact": "~0.6.1",
"@anticrm/telegram": "~0.6.0",
"@anticrm/setting": "~0.6.0"
}
}

View File

@ -0,0 +1,58 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import type { IntlString } from '@anticrm/platform'
import { Builder, Model, TypeString, TypeBoolean, Prop } from '@anticrm/model'
import core, { TDoc } from '@anticrm/model-core'
import contact from '@anticrm/model-contact'
import telegram from '@anticrm/telegram'
import type { TelegramMessage } from '@anticrm/telegram'
import type { Domain } from '@anticrm/core'
import setting from '@anticrm/setting'
export const DOMAIN_TELEGRAM = 'telegram' as Domain
@Model(telegram.class.Message, core.class.Doc, DOMAIN_TELEGRAM)
export class TTelegramMessage extends TDoc 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
}
export function createModel (builder: Builder): void {
builder.createModel(TTelegramMessage)
builder.createDoc(contact.class.ChannelProvider, core.space.Model, {
label: 'Telegram' as IntlString,
icon: contact.icon.Telegram,
placeholder: '@appleseed',
presenter: telegram.component.Chat
}, contact.channelProvider.Telegram)
builder.createDoc(setting.class.IntegrationType, core.space.Model, {
label: 'Telegram',
description: 'Use telegram integration' as IntlString,
icon: telegram.component.IconTelegram,
createComponent: telegram.component.Connect
}, telegram.integrationType.Telegram)
}

View File

@ -0,0 +1,8 @@
{
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
}
}

View File

@ -18,13 +18,14 @@
import activity from '@anticrm/activity'
import type { Doc } from '@anticrm/core';
import type { Asset } from '@anticrm/platform';
import type { AnySvelteComponent } from '@anticrm/ui';
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui';
import { Icon,IconClose,IconExpand, Component } from '@anticrm/ui';
import { createEventDispatcher } from 'svelte';
export let title: string
export let icon: Asset | AnySvelteComponent
export let fullSize: boolean = false
export let rightSection: AnyComponent | undefined
export let object: Doc
const dispatch = createEventDispatcher()
@ -53,7 +54,7 @@
</div>
</div>
<div class="rightSection">
<Component is={activity.component.Activity} props={{object, fullSize}}/>
<Component is={rightSection ?? activity.component.Activity} props={{object, fullSize}}/>
</div>
{:else}
<div class="unionSection">

View File

@ -20,10 +20,11 @@
import type { Channel, ChannelProvider } from '@anticrm/contact'
import { getClient } from '..'
import { Icon } from '@anticrm/ui'
import { AnyComponent, Icon } from '@anticrm/ui'
import IconCopy from './icons/Copy.svelte'
import contact from '@anticrm/contact'
import { createEventDispatcher } from 'svelte'
export let value: Channel[] | null
export let size: 'small' | 'medium' = 'medium'
@ -32,10 +33,12 @@
interface Item {
label: IntlString,
icon: Asset,
value: string
value: string,
presenter?: AnyComponent
}
const client = getClient()
const dispatch = createEventDispatcher()
async function getProviders(): Promise<Map<Ref<ChannelProvider>, ChannelProvider>> {
const providers = await client.findAll(contact.class.ChannelProvider, {})
@ -54,6 +57,7 @@
label: provider.label as IntlString,
icon: provider.icon as Asset,
value: item.value,
presenter: provider.presenter
})
} else {
console.log('provider not found: ', item.provider)
@ -67,23 +71,25 @@
let displayItems: Item[] = []
</script>
<div class="container" class:reverse on:click|stopPropagation={() => {}}>
<div class="container" class:reverse>
{#each displayItems as item}
<div class="circle list list-{size}">
<div class="icon" class:small={size === 'small'}>
<Icon icon={item.icon} size={'small'}/>
<div on:click|stopPropagation={() => {dispatch('click', item)}}>
<div class="circle list list-{size}">
<div class="icon" class:small={size === 'small'}>
<Icon icon={item.icon} size={'small'}/>
</div>
</div>
</div>
<div class="window {reverse ? 'right' : 'left'}">
<div class="circle circle-icon">
<div class="icon"><Icon icon={item.icon} size={'small'}/></div>
</div>
<div class="flex-grow flex-col caption-color">
<div class="overflow-label label">{item.label}</div>
<div class="overflow-label">{item.value}</div>
</div>
<div class="button" on:click|preventDefault={() => { alert('Copied: ' + item.value) }}>
<IconCopy size={'small'}/>
<div class="window {reverse ? 'right' : 'left'}">
<div class="circle circle-icon">
<div class="icon"><Icon icon={item.icon} size={'small'}/></div>
</div>
<div class="flex-grow flex-col caption-color">
<div class="overflow-label label">{item.label}</div>
<div class="overflow-label">{item.value}</div>
</div>
<div class="button" on:click|preventDefault={() => { alert('Copied: ' + item.value) }}>
<IconCopy size={'small'}/>
</div>
</div>
</div>
{/each}

View File

@ -20,6 +20,7 @@
},
"dependencies": {
"@anticrm/platform":"~0.6.5",
"@anticrm/ui":"~0.6.0",
"@anticrm/core":"~0.6.11"
}
}

View File

@ -16,12 +16,14 @@
import { plugin } from '@anticrm/platform'
import type { Plugin, Asset } from '@anticrm/platform'
import type { Doc, Ref, Class, UXObject, Space, Account } from '@anticrm/core'
import type { AnyComponent } from '@anticrm/ui'
/**
* @public
*/
export interface ChannelProvider extends Doc, UXObject {
placeholder: string
presenter?: AnyComponent
}
/**
@ -114,6 +116,13 @@ export default plugin(contactId, {
Employee: '' as Ref<Class<Employee>>,
EmployeeAccount: '' as Ref<Class<EmployeeAccount>>
},
channelProvider: {
Email: '' as Ref<ChannelProvider>,
Phone: '' as Ref<ChannelProvider>,
LinkedIn: '' as Ref<ChannelProvider>,
Twitter: '' as Ref<ChannelProvider>,
Telegram: '' as Ref<ChannelProvider>
},
icon: {
Phone: '' as Asset,
Email: '' as Asset,

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import type { Ref, Space, Doc, Class } from '@anticrm/core'
import { CircleButton, EditBox, Link, showPopup, IconFile as FileIcon, IconAdd, Label } from '@anticrm/ui'
import { CircleButton, EditBox, Link, showPopup, IconFile as FileIcon, IconAdd, Label, AnyComponent } from '@anticrm/ui'
import type { Attachment } from '@anticrm/chunter'
import FileUpload from './icons/FileUpload.svelte'
import { getClient, createQuery, Channels, AttributeEditor, PDFViewer, Avatar } from '@anticrm/presentation'
@ -32,14 +32,14 @@
import { Table } from '@anticrm/view-resources'
import core from '@anticrm/core'
import recruit from '../plugin'
import { combineName, formatName, getFirstName, getLastName } from '@anticrm/contact'
export let _id: Ref<Candidate>
let object: Candidate
let rightSection: AnyComponent | undefined
let fullSize: boolean = false
let firstName = ''
let lastName = ''
@ -68,7 +68,7 @@
</script>
{#if object !== undefined}
<Panel icon={Contact} title={formatName(object.name)} {object} on:close={() => { dispatch('close') }}>
<Panel icon={Contact} title={formatName(object.name)} {rightSection} {fullSize} {object} on:close={() => { dispatch('close') }}>
<AttributesBar {object} keys={['city', 'onsite', 'remote']} slot="subtitle" />
<div class="flex-row-center">
@ -85,7 +85,12 @@
<CircleButton icon={IconAdd} size={'small'} selected on:click={(ev) => showPopup(SocialEditor, { values: object.channels ?? [] }, ev.target, (result) => { saveChannels(result) })} />
<span><Label label={'Add social links'} /></span>
{:else}
<Channels value={object.channels} size={'small'} />
<Channels value={object.channels} size={'small'} on:click={(ev) => {
if (ev.detail.presenter) {
fullSize = true
rightSection = ev.detail.presenter
}
}} />
<CircleButton icon={Edit} size={'small'} selected on:click={(ev) => showPopup(SocialEditor, { values: object.channels ?? [] }, ev.target, (result) => { saveChannels(result) })} />
{/if}
</div>

View File

@ -14,17 +14,13 @@
//
import Integrations from './components/Integrations.svelte'
import ConnectTelegram from './components/integrations/ConnectTelegram.svelte'
import ConnectEmail from './components/integrations/ConnectEmail.svelte'
import IconTelegram from './components/icons/Telegram.svelte'
import IconGmail from './components/icons/Gmail.svelte'
export default async () => ({
component: {
Integrations,
ConnectTelegram,
ConnectEmail,
IconTelegram,
IconGmail
}
})

View File

@ -55,9 +55,7 @@ export default plugin(settingId, {
Support: '' as AnyComponent,
Privacy: '' as AnyComponent,
Terms: '' as AnyComponent,
ConnectTelegram: '' as AnyComponent,
ConnectEmail: '' as AnyComponent,
IconTelegram: '' as AnyComponent,
IconGmail: '' as AnyComponent
},
string: {

View File

@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}

View File

@ -0,0 +1,37 @@
{
"name": "@anticrm/telegram-resources",
"version": "0.6.0",
"main": "src/index.ts",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "",
"build:docs": "api-extractor run --local",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format": "prettier --write 'src/**/*.{ts*,js*,yml}' && eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig":"~0.6.0",
"svelte-loader":"^3.1.2",
"sass":"^1.37.5",
"svelte-preprocess":"^4.7.4",
"@typescript-eslint/eslint-plugin":"4",
"eslint-plugin-import":"2",
"eslint-plugin-promise":"4",
"eslint-plugin-node":"11",
"eslint":"^7.32.0"
},
"dependencies": {
"@anticrm/platform": "~0.6.5",
"svelte": "^3.37.0",
"@anticrm/telegram": "~0.6.0",
"@anticrm/ui": "~0.6.0",
"@anticrm/presentation": "~0.6.2",
"@anticrm/text-editor": "~0.6.0",
"@anticrm/contact": "~0.6.0",
"@anticrm/setting": "~0.6.0",
"@anticrm/login": "~0.6.1",
"@anticrm/core": "~0.6.11"
}
}

View File

@ -0,0 +1,5 @@
module.exports = {
plugins: [
require('autoprefixer')
]
}

View File

@ -0,0 +1,142 @@
<!--
// Copyright © 2021 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { ReferenceInput } from '@anticrm/text-editor'
import { createQuery, getClient } from '@anticrm/presentation'
import telegram from '@anticrm/telegram'
import type { TelegramMessage } from '@anticrm/telegram'
import type { Contact, EmployeeAccount } from '@anticrm/contact'
import contact from '@anticrm/contact'
import { Grid, ScrollBox } from '@anticrm/ui'
import Message from './Message.svelte'
import TelegramIcon from './icons/Telegram.svelte'
import { Ref, Space } from '@anticrm/core'
import DateView from './Date.svelte'
import setting from '@anticrm/setting'
import login from '@anticrm/login'
import { getMetadata } from '@anticrm/platform'
export let object: Contact
$: contactString = object.channels.find((p) => p.provider === contact.channelProvider.Telegram)
let messages: TelegramMessage[] = []
let accounts: EmployeeAccount[] = []
let enabled: boolean
const client = getClient()
const messagesQuery = createQuery()
const accauntsQuery = createQuery()
const settingsQuery = createQuery()
$: query = contactString?.value.startsWith('+') ? { contactPhone: contactString.value } : { contactUserName: contactString?.value }
$: messagesQuery.query(telegram.class.Message, query, (res) => {
messages = res
})
$: accountsIds = messages.map((p) => p.modifiedBy as Ref<EmployeeAccount>)
$: accauntsQuery.query(contact.class.EmployeeAccount, { _id: { $in: accountsIds }}, (result) => {
accounts = result
})
const accountId = getMetadata(login.metadata.LoginEmail)
$: settingsQuery.query(setting.class.Integration, { type: telegram.integrationType.Telegram, space: accountId as Ref<Space> }, (res) => {
enabled = res.length > 0
})
function onMessage(event: CustomEvent) {
client.createDoc(telegram.class.Message, object.space, {
content: event.detail,
incoming: Boolean(Math.round(Math.random())),
...query
})
}
function isNewDate (messages: TelegramMessage[], i: number): boolean {
if (i === 0) return true
const current = new Date(messages[i].modifiedOn).toLocaleDateString()
const prev = new Date(messages[i-1].modifiedOn).toLocaleDateString()
return current !== prev
}
function needName (messages: TelegramMessage[], i: number): boolean {
if (i === 0) return true
const current = messages[i]
const prev = messages[i-1]
return current.incoming !== prev.incoming || current.modifiedBy !== prev.modifiedBy
}
function getName (messages: TelegramMessage[], accounts: EmployeeAccount[], i: number): string | undefined {
if (!needName(messages, i)) return undefined
const message = messages[i]
return message.incoming ? object.name : accounts.find((p) => p._id === message.modifiedBy)?.name
}
</script>
<div class="flex-row-center header">
<div class="icon"><TelegramIcon size={'small'} /></div>
<div class="title">Telegram</div>
</div>
<div class="flex-col h-full right-content">
<ScrollBox vertical stretch>
{#if messages}
<Grid column={1} rowGap={.3}>
{#each messages as message, i (message._id)}
{#if isNewDate(messages, i)}
<DateView {message} />
{/if}
<Message {message} name={getName(messages, accounts, i)} />
{/each}
</Grid>
{/if}
</ScrollBox>
</div>
{#if enabled}
<div class="ref-input">
<ReferenceInput on:message={onMessage}/>
</div>
{/if}
<style lang="scss">
.header {
flex-shrink: 0;
padding: 0 2.5rem;
height: 4.5rem;
border-bottom: 1px solid var(--theme-card-divider);
.icon {
opacity: 0.6;
}
.title {
flex-grow: 1;
margin-left: 0.5rem;
font-weight: 500;
font-size: 1rem;
color: var(--theme-caption-color);
user-select: none;
}
}
.ref-input {
padding: 1.5rem 2.5rem;
}
.right-content {
flex-grow: 1;
padding: 2.5rem 2.5rem 0;
}
</style>

View File

@ -17,7 +17,7 @@
import { Button, EditBox, IconClose, Label } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import login from '@anticrm/login'
import PinPad from '../PinPad.svelte'
import PinPad from './PinPad.svelte'
const dispatch = createEventDispatcher()
@ -29,10 +29,11 @@
const url = getMetadata(login.metadata.TelegramUrl)
async function requestCode(): Promise<void> {
const res = await sendRequest('/auth', { phone: phone })
if (res.next === 'code') {
requested = true
}
dispatch('close', { value: phone }) //todo, remove after enable service
// const res = await sendRequest('/auth', { phone: phone })
// if (res.next === 'code') {
// requested = true
// }
}
async function sendPassword(): Promise<void> {

View File

@ -0,0 +1,37 @@
<!--
// Copyright © 2021 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import type { TelegramMessage } from '@anticrm/telegram'
export let message: TelegramMessage
</script>
<div class="message">
{new Intl.DateTimeFormat('default', { day: 'numeric', month: 'long' }).format(message.modifiedOn)}
</div>
<style lang="scss">
.message {
background-color: var(--theme-menu-divider);
border-radius: .75rem;
padding: .5rem;
width: fit-content;
justify-self: center;
text-transform: capitalize;
}
</style>

View File

@ -0,0 +1,76 @@
<!--
// Copyright © 2021 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import type { TelegramMessage } from '@anticrm/telegram'
import { MessageViewer } from '@anticrm/presentation'
import { formatName } from '@anticrm/contact'
export let message: TelegramMessage
export let name: string | undefined = undefined
export let colors: string[] = ['#A5D179', '#77C07B', '#60B96E', '#45AEA3', '#46CBDE', '#47BDF6',
'#5AADF6', '#73A6CD', '#B977CB', '#7C6FCD', '#6F7BC5', '#F28469']
function getNameColor (name: string): string {
let hash = 0, i, 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]
}
</script>
<div class="message" class:incoming={message.incoming}>
{#if name}
<div class="name" style="color: {getNameColor(name)}">{formatName(name)}</div>
{/if}
<div class="flex">
<div class="text"><MessageViewer message={message.content}/></div>
<div class="time">{new Date(message.modifiedOn).toLocaleString('default', { hour: 'numeric', minute: 'numeric'})}</div>
</div>
</div>
<style lang="scss">
.message {
max-width: 66%;
border-radius: .75rem;
padding: .75rem;
width: fit-content;
justify-self: flex-end;
background-color: rgba(67, 67, 72, .6);
&.incoming {
background-color: rgba(67, 67, 72, .3);
justify-self: flex-start;
}
.text {
color: var(--theme-caption-color);
margin-right: 1.25rem;
}
.time {
align-self: flex-end;
margin-left: auto;
color: var(--theme-content-trans-color);
font-size: .75rem;
font-style: italic;
}
}
</style>

View File

@ -0,0 +1,24 @@
<!--
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
export let size: 'small' | 'medium' | 'large'
const fill: string = 'var(--theme-caption-color)'
</script>
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M16,2.2c0.1-0.8-0.7-1.4-1.4-1.1L0.4,7.2c-0.6,0.3-0.4,1,0,1.1l3,1C3.9,9.5,4.5,9.5,5,9.1l6.6-4.6c0.1-0.1,0.4,0.1,0.3,0.3 L7.1,9.8c-0.4,0.4-0.4,1.3,0.1,1.7l5.3,3.4c0.6,0.4,1.4,0,1.5-0.7L16,2.2z"/>
</svg>

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,28 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { Resources } from '@anticrm/platform'
import Chat from './components/Chat.svelte'
import Connect from './components/Connect.svelte'
import IconTelegram from './components/icons/TelegramColor.svelte'
export default async (): Promise<Resources> => ({
component: {
Chat,
Connect,
IconTelegram
}
})

View File

@ -0,0 +1,5 @@
const sveltePreprocess = require('svelte-preprocess')
module.exports = {
preprocess: sveltePreprocess()
};

View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"moduleResolution": "node",
"target": "esnext",
"module": "esnext",
"declaration": true,
"outDir": "./lib",
"strict": true,
"esModuleInterop": true,
"lib": [
"esnext",
"dom"
]
}
}

View File

@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}

View File

@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/

View File

@ -0,0 +1,18 @@
// The "rig.json" file directs tools to look for their config files in an external package.
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
/**
* (Required) The name of the rig package to inherit from.
* It should be an NPM package name with the "-rig" suffix.
*/
"rigPackageName": "@anticrm/platform-rig"
/**
* (Optional) Selects a config profile from the rig package. The name must consist of
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
* If omitted, then the "default" profile will be used."
*/
// "rigProfile": "your-profile-name"
}

View File

@ -0,0 +1,28 @@
{
"name": "@anticrm/telegram",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"build:watch": "tsc",
"lint:fix": "eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig":"~0.6.0",
"@types/heft-jest":"^1.0.2",
"@typescript-eslint/eslint-plugin":"4",
"eslint-plugin-import":"2",
"eslint-plugin-promise":"4",
"eslint-plugin-node":"11",
"eslint":"^7.32.0"
},
"dependencies": {
"@anticrm/platform":"~0.6.5",
"@anticrm/core":"~0.6.11",
"@anticrm/ui":"~0.6.0",
"@anticrm/contact": "~0.6.0",
"@anticrm/setting": "~0.6.0"
}
}

View File

@ -0,0 +1,49 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { plugin } from '@anticrm/platform'
import type { Plugin } from '@anticrm/platform'
import type { Doc, Ref, Class } from '@anticrm/core'
import type { AnyComponent } from '@anticrm/ui'
import type { IntegrationType } from '@anticrm/setting'
/**
* @public
*/
export interface TelegramMessage extends Doc {
content: string
incoming: boolean
contactPhone?: string
contactUserName?: string
}
/**
* @public
*/
export const telegramId = 'telegram' as Plugin
export default plugin(telegramId, {
component: {
Chat: '' as AnyComponent,
Connect: '' as AnyComponent,
IconTelegram: '' as AnyComponent
},
integrationType: {
Telegram: '' as Ref<IntegrationType>
},
class: {
Message: '' as Ref<Class<TelegramMessage>>
}
})

View File

@ -0,0 +1,9 @@
{
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"lib": ["esnext", "dom"]
}
}

View File

@ -835,6 +835,21 @@
"packageName": "@anticrm/model-setting",
"projectFolder": "models/setting",
"shouldPublish": true
},
{
"packageName": "@anticrm/telegram",
"projectFolder": "plugins/telegram",
"shouldPublish": true
},
{
"packageName": "@anticrm/telegram-resources",
"projectFolder": "plugins/telegram-resources",
"shouldPublish": true
},
{
"packageName": "@anticrm/model-telegram",
"projectFolder": "models/telegram",
"shouldPublish": true
}
]
}

File diff suppressed because it is too large Load Diff