Files
huly-platform/plugins/chunter-resources/src/utils.ts
T
2023-04-21 23:24:45 +07:00

263 lines
7.3 KiB
TypeScript

import { chunterId, ChunterMessage, Comment, ThreadMessage } from '@hcengineering/chunter'
import contact, { Employee, EmployeeAccount, getName } from '@hcengineering/contact'
import { employeeByIdStore } from '@hcengineering/contact-resources'
import { Class, Client, Doc, getCurrentAccount, IdMap, Obj, Ref, Space, Timestamp } from '@hcengineering/core'
import { Asset } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
import {
getPanelURI,
location,
Location,
navigate,
ResolvedLocation,
getCurrentResolvedLocation
} from '@hcengineering/ui'
import view from '@hcengineering/view'
import { workbenchId } from '@hcengineering/workbench'
import { get, Unsubscriber, writable } from 'svelte/store'
import chunter from './plugin'
export function getTime (time: number): string {
let options: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric' }
if (!isToday(time)) {
options = {
month: 'numeric',
day: 'numeric',
...options
}
}
return new Date(time).toLocaleString('default', options)
}
export function isToday (time: number): boolean {
const current = new Date()
const target = new Date(time)
return (
current.getDate() === target.getDate() &&
current.getMonth() === target.getMonth() &&
current.getFullYear() === target.getFullYear()
)
}
export function classIcon (client: Client, _class: Ref<Class<Obj>>): Asset | undefined {
return client.getHierarchy().getClass(_class).icon
}
export async function getDmName (client: Client, dm: Space): Promise<string> {
const myAccId = getCurrentAccount()._id
let employeeAccounts: EmployeeAccount[] = await client.findAll(contact.class.EmployeeAccount, {
_id: { $in: dm.members as Array<Ref<EmployeeAccount>> }
})
if (dm.members.length > 1) {
employeeAccounts = employeeAccounts.filter((p) => p._id !== myAccId)
}
let unsub: Unsubscriber | undefined
const promise = new Promise<IdMap<Employee>>((resolve) => {
unsub = employeeByIdStore.subscribe((p) => {
if (p.size !== 0) {
resolve(p)
}
})
})
const map = await promise
unsub?.()
const names: string[] = []
for (const acc of employeeAccounts) {
const employee = map.get(acc.employee)
if (employee !== undefined) {
names.push(getName(employee))
}
}
const name = names.join(', ')
return name
}
export function getDay (time: Timestamp): Timestamp {
const date: Date = new Date(time)
date.setHours(0, 0, 0, 0)
return date.getTime()
}
export function openMessageFromSpecial (message: ChunterMessage): void {
const loc = get(location)
if (message.attachedToClass === chunter.class.ChunterSpace) {
loc.path.length = 4
loc.path[3] = message.attachedTo
} else if (message.attachedToClass === chunter.class.Message) {
loc.path.length = 5
loc.path[3] = message.space
loc.path[4] = message.attachedTo
}
navigate(loc)
}
export function navigateToSpecial (specialId: string): void {
const loc = get(location)
loc.path[3] = specialId
navigate(loc)
}
export enum SearchType {
Messages,
Channels,
Files,
Contacts
}
export const messageIdForScroll = writable('')
export const shouldScrollToMessage = writable(false)
export const isMessageHighlighted = writable(false)
let highlightFinishTaskId: number
export function scrollAndHighLight (): void {
const messageElement = document.getElementById(get(messageIdForScroll))
if (messageElement == null) {
return
}
messageElement.scrollIntoView()
shouldScrollToMessage.set(false)
clearTimeout(highlightFinishTaskId)
isMessageHighlighted.set(true)
highlightFinishTaskId = window.setTimeout(() => {
isMessageHighlighted.set(false)
}, 2000)
}
export async function getLink (doc: Doc): Promise<string> {
const fragment = await getTitle(doc)
const location = getCurrentResolvedLocation()
return await Promise.resolve(
`${window.location.protocol}//${window.location.host}/${workbenchId}/${location.path[1]}/${chunterId}#${fragment}`
)
}
export async function getFragment (doc: Doc): Promise<Location> {
const loc = getCurrentResolvedLocation()
loc.path.length = 2
loc.fragment = undefined
loc.query = undefined
loc.path[2] = chunterId
loc.fragment = await getTitle(doc)
return loc
}
export async function getTitle (doc: Doc): Promise<string> {
const client = getClient()
const hierarchy = client.getHierarchy()
let clazz = hierarchy.getClass(doc._class)
let label = clazz.shortLabel
while (label === undefined && clazz.extends !== undefined) {
clazz = hierarchy.getClass(clazz.extends)
label = clazz.shortLabel
}
label = label ?? doc._class
return `${label}-${doc._id}`
}
export async function resolveLocation (loc: Location): Promise<ResolvedLocation | undefined> {
if (loc.path[2] !== chunterId) {
return undefined
}
const shortLink = loc.fragment
// shortlink
if (shortLink !== undefined && isShortId(shortLink)) {
return await generateLocation(loc, shortLink)
}
return undefined
}
async function generateLocation (loc: Location, shortLink: string): Promise<ResolvedLocation | undefined> {
const tokens = shortLink.split('-')
if (tokens.length < 2) {
return undefined
}
const classLabel = tokens[0]
const lastId = tokens[1] as Ref<Doc>
const client = getClient()
const hierarchy = client.getHierarchy()
const classes = [chunter.class.Message, chunter.class.ThreadMessage, chunter.class.Comment]
let _class: Ref<Class<Doc>> | undefined
for (const clazz of classes) {
if (hierarchy.getClass(clazz).shortLabel === classLabel) {
_class = clazz
break
}
}
if (_class === undefined) {
console.error(`Could not find class ${classLabel}.`)
return undefined
}
const doc = await client.findOne(_class, { _id: lastId })
if (doc === undefined) {
console.error(`Could not find message ${lastId}.`)
return undefined
}
const appComponent = loc.path[0] ?? ''
const workspace = loc.path[1] ?? ''
if (hierarchy.isDerived(doc._class, chunter.class.Message)) {
return {
loc: {
path: [appComponent, workspace, chunterId, doc.space],
fragment: doc._id
},
defaultLocation: {
path: [appComponent, workspace, chunterId, doc.space],
fragment: doc._id
}
}
}
if (hierarchy.isDerived(doc._class, chunter.class.Comment)) {
const comment = doc as Comment
const targetClass = hierarchy.getClass(comment.attachedToClass)
const panelComponent = hierarchy.as(targetClass, view.mixin.ObjectPanel)
const component = panelComponent.component ?? view.component.EditDoc
return {
loc: {
path: [appComponent, workspace],
fragment: getPanelURI(component, comment.attachedTo, comment.attachedToClass, 'content')
},
defaultLocation: {
path: [appComponent, workspace],
fragment: getPanelURI(component, comment.attachedTo, comment.attachedToClass, 'content')
}
}
}
if (hierarchy.isDerived(doc._class, chunter.class.ThreadMessage)) {
const msg = doc as ThreadMessage
return {
loc: {
path: [appComponent, workspace, chunterId, doc.space, msg.attachedTo],
fragment: doc._id
},
defaultLocation: {
path: [appComponent, workspace, chunterId, doc.space],
fragment: doc._id
}
}
}
}
function isShortId (shortLink: string): boolean {
return /^\w+-\w+$/.test(shortLink)
}