mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
Chunter: Direct messages (#1472)
Signed-off-by: Denis Bunakalya <denis.bunakalya@xored.com>
This commit is contained in:
parent
ed0a747330
commit
2efc19044e
@ -16,12 +16,14 @@
|
|||||||
import activity from '@anticrm/activity'
|
import activity from '@anticrm/activity'
|
||||||
import type {
|
import type {
|
||||||
Backlink,
|
Backlink,
|
||||||
|
ChunterSpace,
|
||||||
Channel,
|
Channel,
|
||||||
ChunterMessage,
|
ChunterMessage,
|
||||||
Comment,
|
Comment,
|
||||||
Message,
|
Message,
|
||||||
SavedMessages,
|
SavedMessages,
|
||||||
ThreadMessage
|
ThreadMessage,
|
||||||
|
DirectMessage
|
||||||
} from '@anticrm/chunter'
|
} from '@anticrm/chunter'
|
||||||
import contact, { Employee } from '@anticrm/contact'
|
import contact, { Employee } from '@anticrm/contact'
|
||||||
import type { Account, Class, Doc, Domain, Ref, Space, Timestamp } from '@anticrm/core'
|
import type { Account, Class, Doc, Domain, Ref, Space, Timestamp } from '@anticrm/core'
|
||||||
@ -50,20 +52,27 @@ import preference, { TPreference } from '@anticrm/model-preference'
|
|||||||
export const DOMAIN_CHUNTER = 'chunter' as Domain
|
export const DOMAIN_CHUNTER = 'chunter' as Domain
|
||||||
export const DOMAIN_COMMENT = 'comment' as Domain
|
export const DOMAIN_COMMENT = 'comment' as Domain
|
||||||
|
|
||||||
@Model(chunter.class.Channel, core.class.Space)
|
@Model(chunter.class.ChunterSpace, core.class.Space)
|
||||||
@UX(chunter.string.Channel, chunter.icon.Hashtag)
|
export class TChunterSpace extends TSpace implements ChunterSpace {
|
||||||
export class TChannel extends TSpace implements Channel {
|
|
||||||
@Prop(TypeTimestamp(), chunter.string.LastMessage)
|
@Prop(TypeTimestamp(), chunter.string.LastMessage)
|
||||||
lastMessage?: Timestamp
|
lastMessage?: Timestamp
|
||||||
|
|
||||||
@Prop(ArrOf(TypeRef(chunter.class.ChunterMessage)), chunter.string.PinnedMessages)
|
@Prop(ArrOf(TypeRef(chunter.class.ChunterMessage)), chunter.string.PinnedMessages)
|
||||||
pinned?: Ref<ChunterMessage>[]
|
pinned?: Ref<ChunterMessage>[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Model(chunter.class.Channel, chunter.class.ChunterSpace)
|
||||||
|
@UX(chunter.string.Channel, chunter.icon.Hashtag)
|
||||||
|
export class TChannel extends TChunterSpace implements Channel {
|
||||||
@Prop(TypeString(), chunter.string.Topic)
|
@Prop(TypeString(), chunter.string.Topic)
|
||||||
@Index(IndexKind.FullText)
|
@Index(IndexKind.FullText)
|
||||||
topic?: string
|
topic?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Model(chunter.class.DirectMessage, chunter.class.ChunterSpace)
|
||||||
|
@UX(chunter.string.DirectMessage, contact.icon.Person)
|
||||||
|
export class TDirectMessage extends TChunterSpace implements DirectMessage {}
|
||||||
|
|
||||||
@Model(chunter.class.ChunterMessage, core.class.AttachedDoc, DOMAIN_CHUNTER)
|
@Model(chunter.class.ChunterMessage, core.class.AttachedDoc, DOMAIN_CHUNTER)
|
||||||
export class TChunterMessage extends TAttachedDoc implements ChunterMessage {
|
export class TChunterMessage extends TAttachedDoc implements ChunterMessage {
|
||||||
@Prop(TypeMarkup(), chunter.string.Content)
|
@Prop(TypeMarkup(), chunter.string.Content)
|
||||||
@ -128,23 +137,49 @@ export class TSavedMessages extends TPreference implements SavedMessages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createModel (builder: Builder): void {
|
export function createModel (builder: Builder): void {
|
||||||
builder.createModel(TChannel, TMessage, TThreadMessage, TChunterMessage, TComment, TBacklink, TSavedMessages)
|
builder.createModel(
|
||||||
builder.mixin(chunter.class.Channel, core.class.Class, workbench.mixin.SpaceView, {
|
TChunterSpace,
|
||||||
|
TChannel,
|
||||||
|
TMessage,
|
||||||
|
TThreadMessage,
|
||||||
|
TChunterMessage,
|
||||||
|
TComment,
|
||||||
|
TBacklink,
|
||||||
|
TDirectMessage,
|
||||||
|
TSavedMessages
|
||||||
|
)
|
||||||
|
const spaceClasses = [chunter.class.Channel, chunter.class.DirectMessage]
|
||||||
|
|
||||||
|
spaceClasses.forEach((spaceClass) => {
|
||||||
|
builder.mixin(spaceClass, core.class.Class, workbench.mixin.SpaceView, {
|
||||||
view: {
|
view: {
|
||||||
class: chunter.class.Message
|
class: chunter.class.Message
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.mixin(spaceClass, core.class.Class, notification.mixin.SpaceLastEdit, {
|
||||||
|
lastEditField: 'lastMessage'
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.mixin(spaceClass, core.class.Class, view.mixin.ObjectEditor, {
|
||||||
|
editor: chunter.component.EditChannel
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.mixin(chunter.class.DirectMessage, core.class.Class, view.mixin.SpaceName, {
|
||||||
|
getName: chunter.function.GetDmName
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.mixin(chunter.class.DirectMessage, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
|
presenter: chunter.component.DmPresenter
|
||||||
|
})
|
||||||
|
|
||||||
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.AttributePresenter, {
|
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
presenter: chunter.component.ChannelPresenter
|
presenter: chunter.component.ChannelPresenter
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(chunter.class.Channel, core.class.Class, notification.mixin.SpaceLastEdit, {
|
builder.mixin(chunter.class.DirectMessage, core.class.Class, view.mixin.SpaceHeader, {
|
||||||
lastEditField: 'lastMessage'
|
header: chunter.component.DmHeader
|
||||||
})
|
|
||||||
|
|
||||||
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.ObjectEditor, {
|
|
||||||
editor: chunter.component.EditChannel
|
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.SpaceHeader, {
|
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.SpaceHeader, {
|
||||||
@ -302,6 +337,12 @@ export function createModel (builder: Builder): void {
|
|||||||
spaceClass: chunter.class.Channel,
|
spaceClass: chunter.class.Channel,
|
||||||
addSpaceLabel: chunter.string.CreateChannel,
|
addSpaceLabel: chunter.string.CreateChannel,
|
||||||
createComponent: chunter.component.CreateChannel
|
createComponent: chunter.component.CreateChannel
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: chunter.string.DirectMessages,
|
||||||
|
spaceClass: chunter.class.DirectMessage,
|
||||||
|
addSpaceLabel: chunter.string.NewDirectMessage,
|
||||||
|
createComponent: chunter.component.CreateDirectMessage
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
aside: chunter.component.ThreadView
|
aside: chunter.component.ThreadView
|
||||||
|
@ -26,6 +26,7 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
component: {
|
component: {
|
||||||
CommentPresenter: '' as AnyComponent,
|
CommentPresenter: '' as AnyComponent,
|
||||||
ChannelPresenter: '' as AnyComponent,
|
ChannelPresenter: '' as AnyComponent,
|
||||||
|
DmPresenter: '' as AnyComponent,
|
||||||
Threads: '' as AnyComponent,
|
Threads: '' as AnyComponent,
|
||||||
ThreadView: '' as AnyComponent,
|
ThreadView: '' as AnyComponent,
|
||||||
SavedMessages: '' as AnyComponent
|
SavedMessages: '' as AnyComponent
|
||||||
|
@ -20,7 +20,8 @@ import core, { TClass, TDoc } from '@anticrm/model-core'
|
|||||||
import type { Asset, IntlString, Resource, Status } from '@anticrm/platform'
|
import type { Asset, IntlString, Resource, Status } from '@anticrm/platform'
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
import type {
|
import type {
|
||||||
Action, ActionTarget,
|
Action,
|
||||||
|
ActionTarget,
|
||||||
AttributeEditor,
|
AttributeEditor,
|
||||||
AttributePresenter,
|
AttributePresenter,
|
||||||
HTMLPresenter,
|
HTMLPresenter,
|
||||||
@ -32,6 +33,7 @@ import type {
|
|||||||
ObjectValidator,
|
ObjectValidator,
|
||||||
PreviewPresenter,
|
PreviewPresenter,
|
||||||
SpaceHeader,
|
SpaceHeader,
|
||||||
|
SpaceName,
|
||||||
TextPresenter,
|
TextPresenter,
|
||||||
ViewAction,
|
ViewAction,
|
||||||
ViewContext,
|
ViewContext,
|
||||||
@ -67,7 +69,12 @@ export function createAction (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function actionTarget (builder: Builder, action: Ref<Action>, target: Ref<Class<Doc>>, context: ViewContext): void {
|
export function actionTarget (
|
||||||
|
builder: Builder,
|
||||||
|
action: Ref<Action>,
|
||||||
|
target: Ref<Class<Doc>>,
|
||||||
|
context: ViewContext
|
||||||
|
): void {
|
||||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||||
target,
|
target,
|
||||||
action,
|
action,
|
||||||
@ -116,6 +123,11 @@ export class TSpaceHeader extends TClass implements SpaceHeader {
|
|||||||
header!: AnyComponent
|
header!: AnyComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mixin(view.mixin.SpaceName, core.class.Class)
|
||||||
|
export class TSpaceName extends TClass implements SpaceName {
|
||||||
|
getName!: Resource<(client: Client, space: Space) => Promise<string>>
|
||||||
|
}
|
||||||
|
|
||||||
@Mixin(view.mixin.ObjectValidator, core.class.Class)
|
@Mixin(view.mixin.ObjectValidator, core.class.Class)
|
||||||
export class TObjectValidator extends TClass implements ObjectValidator {
|
export class TObjectValidator extends TClass implements ObjectValidator {
|
||||||
validator!: Resource<<T extends Doc>(doc: T, client: Client) => Promise<Status<{}>>>
|
validator!: Resource<<T extends Doc>(doc: T, client: Client) => Promise<Status<{}>>>
|
||||||
@ -189,6 +201,7 @@ export function createModel (builder: Builder): void {
|
|||||||
TObjectEditorHeader,
|
TObjectEditorHeader,
|
||||||
THTMLPresenter,
|
THTMLPresenter,
|
||||||
TSpaceHeader,
|
TSpaceHeader,
|
||||||
|
TSpaceName,
|
||||||
TTextPresenter,
|
TTextPresenter,
|
||||||
TIgnoreActions,
|
TIgnoreActions,
|
||||||
TPreviewPresenter
|
TPreviewPresenter
|
||||||
@ -214,20 +227,34 @@ export function createModel (builder: Builder): void {
|
|||||||
view.viewlet.Table
|
view.viewlet.Table
|
||||||
)
|
)
|
||||||
|
|
||||||
createAction(builder, view.action.Delete, view.string.Delete, view.actionImpl.Delete, { icon: view.icon.Delete, keyBinding: ['Meta + Backspace'] })
|
createAction(builder, view.action.Delete, view.string.Delete, view.actionImpl.Delete, {
|
||||||
|
icon: view.icon.Delete,
|
||||||
|
keyBinding: ['Meta + Backspace']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.Delete, core.class.Doc, { mode: ['context', 'browser'], group: 'tools' })
|
actionTarget(builder, view.action.Delete, core.class.Doc, { mode: ['context', 'browser'], group: 'tools' })
|
||||||
|
|
||||||
createAction(builder, view.action.Move, view.string.Move, view.actionImpl.Move, { icon: view.icon.Move, singleInput: true })
|
createAction(builder, view.action.Move, view.string.Move, view.actionImpl.Move, {
|
||||||
|
icon: view.icon.Move,
|
||||||
|
singleInput: true
|
||||||
|
})
|
||||||
|
|
||||||
// Keyboard actions.
|
// Keyboard actions.
|
||||||
createAction(builder, view.action.MoveUp, view.string.MoveUp, view.actionImpl.MoveUp, { keyBinding: ['ArrowUp', 'keyK'] })
|
createAction(builder, view.action.MoveUp, view.string.MoveUp, view.actionImpl.MoveUp, {
|
||||||
|
keyBinding: ['ArrowUp', 'keyK']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.MoveUp, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.MoveUp, core.class.Doc, { mode: 'browser' })
|
||||||
createAction(builder, view.action.MoveDown, view.string.MoveDown, view.actionImpl.MoveDown, { keyBinding: ['ArrowDown', 'keyJ'] })
|
createAction(builder, view.action.MoveDown, view.string.MoveDown, view.actionImpl.MoveDown, {
|
||||||
|
keyBinding: ['ArrowDown', 'keyJ']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.MoveDown, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.MoveDown, core.class.Doc, { mode: 'browser' })
|
||||||
|
|
||||||
createAction(builder, view.action.MoveLeft, view.string.MoveLeft, view.actionImpl.MoveLeft, { keyBinding: ['ArrowLeft'] })
|
createAction(builder, view.action.MoveLeft, view.string.MoveLeft, view.actionImpl.MoveLeft, {
|
||||||
|
keyBinding: ['ArrowLeft']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.MoveLeft, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.MoveLeft, core.class.Doc, { mode: 'browser' })
|
||||||
createAction(builder, view.action.MoveRight, view.string.MoveRight, view.actionImpl.MoveRight, { keyBinding: ['ArrowRight'] })
|
createAction(builder, view.action.MoveRight, view.string.MoveRight, view.actionImpl.MoveRight, {
|
||||||
|
keyBinding: ['ArrowRight']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.MoveRight, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.MoveRight, core.class.Doc, { mode: 'browser' })
|
||||||
|
|
||||||
builder.mixin(core.class.Space, core.class.Class, view.mixin.AttributePresenter, {
|
builder.mixin(core.class.Space, core.class.Class, view.mixin.AttributePresenter, {
|
||||||
@ -235,19 +262,32 @@ export function createModel (builder: Builder): void {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Selection stuff
|
// Selection stuff
|
||||||
createAction(builder, view.action.SelectItem, view.string.SelectItem, view.actionImpl.SelectItem, { keyBinding: ['keyX'] })
|
createAction(builder, view.action.SelectItem, view.string.SelectItem, view.actionImpl.SelectItem, {
|
||||||
|
keyBinding: ['keyX']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.SelectItem, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.SelectItem, core.class.Doc, { mode: 'browser' })
|
||||||
|
|
||||||
createAction(builder, view.action.SelectItemAll, view.string.SelectItemAll, view.actionImpl.SelectItemAll, { keyBinding: ['meta + keyA'] })
|
createAction(builder, view.action.SelectItemAll, view.string.SelectItemAll, view.actionImpl.SelectItemAll, {
|
||||||
|
keyBinding: ['meta + keyA']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.SelectItemAll, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.SelectItemAll, core.class.Doc, { mode: 'browser' })
|
||||||
|
|
||||||
createAction(builder, view.action.SelectItemNone, view.string.SelectItemNone, view.actionImpl.SelectItemNone, { keyBinding: ['escape'] })
|
createAction(builder, view.action.SelectItemNone, view.string.SelectItemNone, view.actionImpl.SelectItemNone, {
|
||||||
|
keyBinding: ['escape']
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.SelectItemNone, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.SelectItemNone, core.class.Doc, { mode: 'browser' })
|
||||||
|
|
||||||
createAction(builder, view.action.ShowActions, view.string.ShowActions, view.actionImpl.ShowActions, { keyBinding: ['meta + keyk'] })
|
createAction(builder, view.action.ShowActions, view.string.ShowActions, view.actionImpl.ShowActions, {
|
||||||
actionTarget(builder, view.action.ShowActions, core.class.Doc, { mode: ['workbench', 'browser', 'popup', 'panel', 'editor'] })
|
keyBinding: ['meta + keyk']
|
||||||
|
})
|
||||||
|
actionTarget(builder, view.action.ShowActions, core.class.Doc, {
|
||||||
|
mode: ['workbench', 'browser', 'popup', 'panel', 'editor']
|
||||||
|
})
|
||||||
|
|
||||||
createAction(builder, view.action.ShowPreview, view.string.ShowPreview, view.actionImpl.ShowPreview, { keyBinding: ['Space'], singleInput: true })
|
createAction(builder, view.action.ShowPreview, view.string.ShowPreview, view.actionImpl.ShowPreview, {
|
||||||
|
keyBinding: ['Space'],
|
||||||
|
singleInput: true
|
||||||
|
})
|
||||||
actionTarget(builder, view.action.ShowPreview, core.class.Doc, { mode: 'browser' })
|
actionTarget(builder, view.action.ShowPreview, core.class.Doc, { mode: 'browser' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model'
|
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model'
|
||||||
|
|
||||||
export const viewOperation: MigrateOperation = {
|
export const viewOperation: MigrateOperation = {
|
||||||
async migrate (client: MigrationClient): Promise<void> {
|
async migrate (client: MigrationClient): Promise<void> {},
|
||||||
|
async upgrade (client: MigrationUpgradeClient): Promise<void> {}
|
||||||
},
|
|
||||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,22 @@
|
|||||||
"ApplicationLabelChunter": "Chat",
|
"ApplicationLabelChunter": "Chat",
|
||||||
"LeftComment": "left a comment",
|
"LeftComment": "left a comment",
|
||||||
"Channels": "Channels",
|
"Channels": "Channels",
|
||||||
|
"DirectMessages": "Direct messages",
|
||||||
"CreateChannel": "New Channel",
|
"CreateChannel": "New Channel",
|
||||||
|
"NewDirectMessage": "New Direct Message",
|
||||||
"ChannelName": "Name",
|
"ChannelName": "Name",
|
||||||
"ChannelNamePlaceholder": "Channel",
|
"ChannelNamePlaceholder": "Channel",
|
||||||
"ChannelDescription": "Description",
|
"ChannelDescription": "Description",
|
||||||
"MakePrivate": "Make private",
|
"MakePrivate": "Make private",
|
||||||
"MakePrivateDescription": "Only members can see it",
|
"MakePrivateDescription": "Only members can see it",
|
||||||
"Channel": "Channel",
|
"Channel": "Channel",
|
||||||
|
"DirectMessage": "Direct message",
|
||||||
"EditUpdate": "Save...",
|
"EditUpdate": "Save...",
|
||||||
"EditCancel": "Cancel",
|
"EditCancel": "Cancel",
|
||||||
"Comments" : "Comments",
|
"Comments" : "Comments",
|
||||||
|
"About": "About",
|
||||||
"Members": "Members",
|
"Members": "Members",
|
||||||
|
"NoMembers": "No members",
|
||||||
"MentionedIn": "mentioned this ",
|
"MentionedIn": "mentioned this ",
|
||||||
"ContactInfo": "Contact Info",
|
"ContactInfo": "Contact Info",
|
||||||
"Content": "Content",
|
"Content": "Content",
|
||||||
|
@ -3,17 +3,22 @@
|
|||||||
"ApplicationLabelChunter": "Чат",
|
"ApplicationLabelChunter": "Чат",
|
||||||
"LeftComment": "оставил(а) комментарий",
|
"LeftComment": "оставил(а) комментарий",
|
||||||
"Channels": "Каналы",
|
"Channels": "Каналы",
|
||||||
|
"DirectMessages": "Личные сообщения",
|
||||||
"CreateChannel": "Создать канал",
|
"CreateChannel": "Создать канал",
|
||||||
|
"NewDirectMessage": "Создать личное сообщение",
|
||||||
"ChannelName": "Название",
|
"ChannelName": "Название",
|
||||||
"ChannelNamePlaceholder": "Канал",
|
"ChannelNamePlaceholder": "Канал",
|
||||||
"ChannelDescription": "Описание",
|
"ChannelDescription": "Описание",
|
||||||
"MakePrivate": "Сделать личным",
|
"MakePrivate": "Сделать личным",
|
||||||
"MakePrivateDescription": "Только пользователи могут видеть это",
|
"MakePrivateDescription": "Только пользователи могут видеть это",
|
||||||
"Channel": "Канал ",
|
"Channel": "Канал ",
|
||||||
|
"DirectMessage": "Личное сообщение",
|
||||||
"EditUpdate": "Сохранить...",
|
"EditUpdate": "Сохранить...",
|
||||||
"EditCancel": "Отменить",
|
"EditCancel": "Отменить",
|
||||||
"Comments" : "Комментарии",
|
"Comments" : "Комментарии",
|
||||||
|
"About": "Информация",
|
||||||
"Members": "Участники",
|
"Members": "Участники",
|
||||||
|
"NoMembers": "Нет участников",
|
||||||
"MentionedIn": "упомянул(а) ",
|
"MentionedIn": "упомянул(а) ",
|
||||||
"ContactInfo": "Контактная информация",
|
"ContactInfo": "Контактная информация",
|
||||||
"Content": "Содержимое",
|
"Content": "Содержимое",
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
(res) => {
|
(res) => {
|
||||||
messages = res
|
messages = res
|
||||||
newMessagesPos = newMessagesStart(messages)
|
newMessagesPos = newMessagesStart(messages)
|
||||||
notificationClient.updateLastView(space, chunter.class.Channel)
|
notificationClient.updateLastView(space, chunter.class.ChunterSpace)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
lookup: {
|
lookup: {
|
||||||
|
@ -14,26 +14,16 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Channel } from '@anticrm/chunter'
|
import type { Channel } from '@anticrm/chunter'
|
||||||
import { Ref, Space } from '@anticrm/core'
|
|
||||||
import { getClient } from '@anticrm/presentation'
|
import { getClient } from '@anticrm/presentation'
|
||||||
import { getCurrentLocation, Icon, locationToUrl } from '@anticrm/ui'
|
import { Icon } from '@anticrm/ui'
|
||||||
import chunter from '../plugin'
|
|
||||||
|
import { getSpaceLink } from '../utils'
|
||||||
|
|
||||||
export let value: Channel
|
export let value: Channel
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
$: icon = client.getHierarchy().getClass(value._class).icon
|
$: icon = client.getHierarchy().getClass(value._class).icon
|
||||||
|
$: link = getSpaceLink(value._id)
|
||||||
function getLink (id: Ref<Space>): string {
|
|
||||||
const loc = getCurrentLocation()
|
|
||||||
loc.path[1] = chunter.app.Chunter
|
|
||||||
loc.path[2] = id
|
|
||||||
loc.path.length = 3
|
|
||||||
loc.fragment = undefined
|
|
||||||
return locationToUrl(loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
$: link = getLink(value._id)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if value}
|
{#if value}
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
space,
|
space,
|
||||||
{
|
{
|
||||||
attachedTo: space,
|
attachedTo: space,
|
||||||
attachedToClass: chunter.class.Channel,
|
attachedToClass: chunter.class.ChunterSpace,
|
||||||
collection: 'messages',
|
collection: 'messages',
|
||||||
content: message,
|
content: message,
|
||||||
createOn: 0,
|
createOn: 0,
|
||||||
@ -50,11 +50,11 @@
|
|||||||
_id
|
_id
|
||||||
)
|
)
|
||||||
tx.attributes.createOn = tx.modifiedOn
|
tx.attributes.createOn = tx.modifiedOn
|
||||||
await notificationClient.updateLastView(space, chunter.class.Channel, tx.modifiedOn, true)
|
await notificationClient.updateLastView(space, chunter.class.ChunterSpace, tx.modifiedOn, true)
|
||||||
await client.tx(tx)
|
await client.tx(tx)
|
||||||
|
|
||||||
// Create an backlink to document
|
// Create an backlink to document
|
||||||
await createBacklinks(client, space, chunter.class.Channel, _id, message)
|
await createBacklinks(client, space, chunter.class.ChunterSpace, _id, message)
|
||||||
|
|
||||||
_id = generateId()
|
_id = generateId()
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@
|
|||||||
const pinnedQuery = createQuery()
|
const pinnedQuery = createQuery()
|
||||||
let pinnedIds: Ref<ChunterMessage>[] = []
|
let pinnedIds: Ref<ChunterMessage>[] = []
|
||||||
pinnedQuery.query(
|
pinnedQuery.query(
|
||||||
chunter.class.Channel,
|
chunter.class.ChunterSpace,
|
||||||
{ _id: space },
|
{ _id: space },
|
||||||
(res) => {
|
(res) => {
|
||||||
pinnedIds = res[0]?.pinned ?? []
|
pinnedIds = res[0]?.pinned ?? []
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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 { createEventDispatcher } from 'svelte'
|
||||||
|
|
||||||
|
import contact, { Employee } from '@anticrm/contact'
|
||||||
|
import core, { getCurrentAccount, Ref } from '@anticrm/core'
|
||||||
|
import { getClient, SpaceCreateCard, UserBoxList } from '@anticrm/presentation'
|
||||||
|
|
||||||
|
import chunter from '../plugin'
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
const client = getClient()
|
||||||
|
const myAccId = getCurrentAccount()._id
|
||||||
|
|
||||||
|
let employeeIds: Ref<Employee>[] = []
|
||||||
|
|
||||||
|
function createDirectMessage () {
|
||||||
|
client.findAll(contact.class.EmployeeAccount, { employee: { $in: employeeIds } }).then((employeeAccounts) => {
|
||||||
|
client.createDoc(chunter.class.DirectMessage, core.space.Space, {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
private: true,
|
||||||
|
archived: false,
|
||||||
|
members: [myAccId, ...employeeAccounts.filter((ea) => ea._id !== myAccId).map((ea) => ea._id)]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SpaceCreateCard
|
||||||
|
label={chunter.string.NewDirectMessage}
|
||||||
|
okAction={createDirectMessage}
|
||||||
|
canSave={employeeIds.length > 0}
|
||||||
|
on:close={() => {
|
||||||
|
dispatch('close')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<UserBoxList
|
||||||
|
_class={contact.class.Employee}
|
||||||
|
label={chunter.string.Members}
|
||||||
|
noItems={chunter.string.NoMembers}
|
||||||
|
on:update={(evt) => (employeeIds = evt.detail)}
|
||||||
|
/>
|
||||||
|
</SpaceCreateCard>
|
46
plugins/chunter-resources/src/components/DmHeader.svelte
Normal file
46
plugins/chunter-resources/src/components/DmHeader.svelte
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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">
|
||||||
|
import { DirectMessage } from '@anticrm/chunter'
|
||||||
|
import type { Ref } from '@anticrm/core'
|
||||||
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
|
import { showPanel } from '@anticrm/ui'
|
||||||
|
import chunter from '../plugin'
|
||||||
|
import { classIcon, getDmName } from '../utils'
|
||||||
|
import Header from './Header.svelte'
|
||||||
|
|
||||||
|
export let spaceId: Ref<DirectMessage> | undefined
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
const query = createQuery()
|
||||||
|
let dm: DirectMessage | undefined
|
||||||
|
|
||||||
|
$: query.query(chunter.class.DirectMessage, { _id: spaceId }, (result) => {
|
||||||
|
dm = result[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
async function onSpaceEdit (): Promise<void> {
|
||||||
|
if (dm === undefined) return
|
||||||
|
showPanel(chunter.component.EditChannel, dm._id, dm._class, 'right')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="ac-header divide full">
|
||||||
|
{#if dm}
|
||||||
|
{#await getDmName(client, dm) then name}
|
||||||
|
<Header icon={classIcon(client, dm._class)} label={name} description={''} on:click={onSpaceEdit} />
|
||||||
|
{/await}
|
||||||
|
{/if}
|
||||||
|
</div>
|
40
plugins/chunter-resources/src/components/DmPresenter.svelte
Normal file
40
plugins/chunter-resources/src/components/DmPresenter.svelte
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2022 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">
|
||||||
|
import type { DirectMessage } from '@anticrm/chunter'
|
||||||
|
import { getClient } from '@anticrm/presentation'
|
||||||
|
import { Icon } from '@anticrm/ui'
|
||||||
|
|
||||||
|
import { getSpaceLink, getDmName } from '../utils'
|
||||||
|
|
||||||
|
export let dm: DirectMessage
|
||||||
|
const client = getClient()
|
||||||
|
|
||||||
|
$: icon = client.getHierarchy().getClass(dm._class).icon
|
||||||
|
$: link = getSpaceLink(dm._id)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if dm}
|
||||||
|
{#await getDmName(client, dm) then name}
|
||||||
|
<a class="flex-presenter" href={link}>
|
||||||
|
<div class="icon">
|
||||||
|
{#if icon}
|
||||||
|
<Icon {icon} size={'small'} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<span class="label">{name}</span>
|
||||||
|
</a>
|
||||||
|
{/await}
|
||||||
|
{/if}
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Channel } from '@anticrm/chunter'
|
import { ChunterSpace } from '@anticrm/chunter'
|
||||||
import type { Class, Ref } from '@anticrm/core'
|
import type { Class, Ref } from '@anticrm/core'
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import { createQuery, getClient, Members } from '@anticrm/presentation'
|
import { createQuery, getClient, Members } from '@anticrm/presentation'
|
||||||
@ -25,10 +25,10 @@
|
|||||||
import EditChannelDescriptionTab from './EditChannelDescriptionTab.svelte'
|
import EditChannelDescriptionTab from './EditChannelDescriptionTab.svelte'
|
||||||
import EditChannelSettingsTab from './EditChannelSettingsTab.svelte'
|
import EditChannelSettingsTab from './EditChannelSettingsTab.svelte'
|
||||||
|
|
||||||
export let _id: Ref<Channel>
|
export let _id: Ref<ChunterSpace>
|
||||||
export let _class: Ref<Class<Channel>>
|
export let _class: Ref<Class<ChunterSpace>>
|
||||||
|
|
||||||
let channel: Channel | undefined
|
let channel: ChunterSpace
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@ -36,11 +36,15 @@
|
|||||||
const clazz = client.getHierarchy().getClass(_class)
|
const clazz = client.getHierarchy().getClass(_class)
|
||||||
|
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
$: query.query(chunter.class.Channel, { _id }, (result) => {
|
$: query.query(chunter.class.ChunterSpace, { _id }, (result) => {
|
||||||
channel = result[0]
|
channel = result[0]
|
||||||
})
|
})
|
||||||
|
|
||||||
const tabLabels: IntlString[] = [chunter.string.Channel, chunter.string.Members, chunter.string.Settings]
|
const tabLabels: IntlString[] = [
|
||||||
|
chunter.string.About,
|
||||||
|
chunter.string.Members,
|
||||||
|
...(_class === chunter.class.Channel ? [chunter.string.Settings] : [])
|
||||||
|
]
|
||||||
let selectedTabIndex = 0
|
let selectedTabIndex = 0
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -16,13 +16,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import attachment, { Attachment } from '@anticrm/attachment'
|
import attachment, { Attachment } from '@anticrm/attachment'
|
||||||
import { AttachmentPresenter } from '@anticrm/attachment-resources'
|
import { AttachmentPresenter } from '@anticrm/attachment-resources'
|
||||||
import { Channel } from '@anticrm/chunter'
|
import { ChunterSpace } from '@anticrm/chunter'
|
||||||
import { Doc, SortingOrder } from '@anticrm/core'
|
import { Doc, SortingOrder } from '@anticrm/core'
|
||||||
import { createQuery } from '@anticrm/presentation'
|
import { createQuery } from '@anticrm/presentation'
|
||||||
import { Menu } from '@anticrm/view-resources'
|
import { Menu } from '@anticrm/view-resources'
|
||||||
import { showPopup, IconMoreV, Label } from '@anticrm/ui'
|
import { showPopup, IconMoreV, Label } from '@anticrm/ui'
|
||||||
|
|
||||||
export let channel: Channel | undefined
|
export let channel: ChunterSpace | undefined
|
||||||
|
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
let visibleAttachments: Attachment[] | undefined
|
let visibleAttachments: Attachment[] | undefined
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Channel } from '@anticrm/chunter'
|
import { Channel, ChunterSpace } from '@anticrm/chunter'
|
||||||
import { getCurrentAccount } from '@anticrm/core'
|
import { getCurrentAccount } from '@anticrm/core'
|
||||||
import { getClient } from '@anticrm/presentation'
|
import { getClient } from '@anticrm/presentation'
|
||||||
import { Button, EditBox } from '@anticrm/ui'
|
import { Button, EditBox } from '@anticrm/ui'
|
||||||
@ -22,14 +22,21 @@
|
|||||||
import chunter from '../plugin'
|
import chunter from '../plugin'
|
||||||
import EditChannelDescriptionAttachments from './EditChannelDescriptionAttachments.svelte'
|
import EditChannelDescriptionAttachments from './EditChannelDescriptionAttachments.svelte'
|
||||||
|
|
||||||
export let channel: Channel
|
export let channel: ChunterSpace
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
function isCommonChannel (channel?: ChunterSpace): channel is Channel {
|
||||||
|
return channel?._class === chunter.class.Channel
|
||||||
|
}
|
||||||
|
|
||||||
function onTopicChange (ev: Event) {
|
function onTopicChange (ev: Event) {
|
||||||
|
if (!isCommonChannel(channel)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const newTopic = (ev.target as HTMLInputElement).value
|
const newTopic = (ev.target as HTMLInputElement).value
|
||||||
client.update(channel!, { topic: newTopic })
|
client.update(channel, { topic: newTopic })
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDescriptionChange (ev: Event) {
|
function onDescriptionChange (ev: Event) {
|
||||||
@ -47,6 +54,7 @@
|
|||||||
|
|
||||||
{#if channel}
|
{#if channel}
|
||||||
<div class="flex-col flex-gap-3">
|
<div class="flex-col flex-gap-3">
|
||||||
|
{#if isCommonChannel(channel)}
|
||||||
<EditBox
|
<EditBox
|
||||||
label={chunter.string.Topic}
|
label={chunter.string.Topic}
|
||||||
bind:value={channel.topic}
|
bind:value={channel.topic}
|
||||||
@ -71,6 +79,7 @@
|
|||||||
leaveChannel()
|
leaveChannel()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
{/if}
|
||||||
<EditChannelDescriptionAttachments {channel} />
|
<EditChannelDescriptionAttachments {channel} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
const pinnedQuery = createQuery()
|
const pinnedQuery = createQuery()
|
||||||
let pinnedIds: Ref<ChunterMessage>[] = []
|
let pinnedIds: Ref<ChunterMessage>[] = []
|
||||||
pinnedQuery.query(
|
pinnedQuery.query(
|
||||||
chunter.class.Channel,
|
chunter.class.ChunterSpace,
|
||||||
{ _id: space },
|
{ _id: space },
|
||||||
(res) => {
|
(res) => {
|
||||||
pinnedIds = res[0]?.pinned ?? []
|
pinnedIds = res[0]?.pinned ?? []
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import attachment from '@anticrm/attachment'
|
import attachment from '@anticrm/attachment'
|
||||||
import { AttachmentRefInput } from '@anticrm/attachment-resources'
|
import { AttachmentRefInput } from '@anticrm/attachment-resources'
|
||||||
import type { Channel, Message, ThreadMessage } from '@anticrm/chunter'
|
import type { ChunterSpace, Message, ThreadMessage } from '@anticrm/chunter'
|
||||||
import contact, { Employee, EmployeeAccount, formatName } from '@anticrm/contact'
|
import contact, { Employee, EmployeeAccount, formatName } from '@anticrm/contact'
|
||||||
import core, { FindOptions, generateId, getCurrentAccount, Ref, SortingOrder, TxFactory } from '@anticrm/core'
|
import core, { FindOptions, generateId, getCurrentAccount, Ref, SortingOrder, TxFactory } from '@anticrm/core'
|
||||||
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
||||||
@ -24,6 +24,7 @@
|
|||||||
import { createBacklinks } from '../backlinks'
|
import { createBacklinks } from '../backlinks'
|
||||||
import chunter from '../plugin'
|
import chunter from '../plugin'
|
||||||
import ChannelPresenter from './ChannelPresenter.svelte'
|
import ChannelPresenter from './ChannelPresenter.svelte'
|
||||||
|
import DmPresenter from './DmPresenter.svelte'
|
||||||
import MsgView from './Message.svelte'
|
import MsgView from './Message.svelte'
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
@ -152,22 +153,24 @@
|
|||||||
await client.tx(tx)
|
await client.tx(tx)
|
||||||
|
|
||||||
// Create an backlink to document
|
// Create an backlink to document
|
||||||
await createBacklinks(client, parent.space, chunter.class.Channel, commentId, message)
|
await createBacklinks(client, parent.space, chunter.class.ChunterSpace, commentId, message)
|
||||||
|
|
||||||
commentId = generateId()
|
commentId = generateId()
|
||||||
}
|
}
|
||||||
let comments: ThreadMessage[] = []
|
let comments: ThreadMessage[] = []
|
||||||
|
|
||||||
async function getChannel (_id: Ref<Channel>): Promise<Channel | undefined> {
|
async function getChannel (_id: Ref<ChunterSpace>): Promise<ChunterSpace | undefined> {
|
||||||
return await client.findOne(chunter.class.Channel, { _id })
|
return await client.findOne(chunter.class.ChunterSpace, { _id })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ml-8 mt-4">
|
<div class="ml-8 mt-4">
|
||||||
{#if parent}
|
{#if parent}
|
||||||
{#await getChannel(parent.space) then channel}
|
{#await getChannel(parent.space) then channel}
|
||||||
{#if channel}
|
{#if channel?._class === chunter.class.Channel}
|
||||||
<ChannelPresenter value={channel} />
|
<ChannelPresenter value={channel} />
|
||||||
|
{:else if channel}
|
||||||
|
<DmPresenter dm={channel} />
|
||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
{#await getParticipants(comments, parent, employees) then participants}
|
{#await getParticipants(comments, parent, employees) then participants}
|
||||||
@ -208,7 +211,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 1rem 1rem 0px;
|
margin: 1rem 1rem 0px;
|
||||||
background-color: var(--theme-border-modal);
|
background-color: var(--theme-border-modal);
|
||||||
border-radius: .75rem;
|
border-radius: 0.75rem;
|
||||||
border: 1px solid var(--theme-zone-border);
|
border: 1px solid var(--theme-zone-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
pinnedQuery.query(
|
pinnedQuery.query(
|
||||||
chunter.class.Channel,
|
chunter.class.ChunterSpace,
|
||||||
{ _id: currentSpace },
|
{ _id: currentSpace },
|
||||||
(res) => {
|
(res) => {
|
||||||
pinnedIds = res[0]?.pinned ?? []
|
pinnedIds = res[0]?.pinned ?? []
|
||||||
@ -153,7 +153,7 @@
|
|||||||
await client.tx(tx)
|
await client.tx(tx)
|
||||||
|
|
||||||
// Create an backlink to document
|
// Create an backlink to document
|
||||||
await createBacklinks(client, currentSpace, chunter.class.Channel, commentId, message)
|
await createBacklinks(client, currentSpace, chunter.class.ChunterSpace, commentId, message)
|
||||||
|
|
||||||
commentId = generateId()
|
commentId = generateId()
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import core from '@anticrm/core'
|
import core from '@anticrm/core'
|
||||||
import chunter, { Channel, ChunterMessage, Message, ThreadMessage } from '@anticrm/chunter'
|
import chunter, { ChunterSpace, Channel, ChunterMessage, Message, ThreadMessage } from '@anticrm/chunter'
|
||||||
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
||||||
import { Resources } from '@anticrm/platform'
|
import { Resources } from '@anticrm/platform'
|
||||||
import { getClient, MessageBox } from '@anticrm/presentation'
|
import { getClient, MessageBox } from '@anticrm/presentation'
|
||||||
@ -23,23 +23,28 @@ import TxBacklinkCreate from './components/activity/TxBacklinkCreate.svelte'
|
|||||||
import TxBacklinkReference from './components/activity/TxBacklinkReference.svelte'
|
import TxBacklinkReference from './components/activity/TxBacklinkReference.svelte'
|
||||||
import TxCommentCreate from './components/activity/TxCommentCreate.svelte'
|
import TxCommentCreate from './components/activity/TxCommentCreate.svelte'
|
||||||
import ChannelPresenter from './components/ChannelPresenter.svelte'
|
import ChannelPresenter from './components/ChannelPresenter.svelte'
|
||||||
|
import DmPresenter from './components/DmPresenter.svelte'
|
||||||
import ChannelView from './components/ChannelView.svelte'
|
import ChannelView from './components/ChannelView.svelte'
|
||||||
import ChannelHeader from './components/ChannelHeader.svelte'
|
import ChannelHeader from './components/ChannelHeader.svelte'
|
||||||
|
import DmHeader from './components/DmHeader.svelte'
|
||||||
import CommentInput from './components/CommentInput.svelte'
|
import CommentInput from './components/CommentInput.svelte'
|
||||||
import CommentPresenter from './components/CommentPresenter.svelte'
|
import CommentPresenter from './components/CommentPresenter.svelte'
|
||||||
import CommentsPresenter from './components/CommentsPresenter.svelte'
|
import CommentsPresenter from './components/CommentsPresenter.svelte'
|
||||||
import CreateChannel from './components/CreateChannel.svelte'
|
import CreateChannel from './components/CreateChannel.svelte'
|
||||||
|
import CreateDirectMessage from './components/CreateDirectMessage.svelte'
|
||||||
import EditChannel from './components/EditChannel.svelte'
|
import EditChannel from './components/EditChannel.svelte'
|
||||||
import ThreadView from './components/ThreadView.svelte'
|
import ThreadView from './components/ThreadView.svelte'
|
||||||
import Threads from './components/Threads.svelte'
|
import Threads from './components/Threads.svelte'
|
||||||
import SavedMessages from './components/SavedMessages.svelte'
|
import SavedMessages from './components/SavedMessages.svelte'
|
||||||
import preference from '@anticrm/preference'
|
import preference from '@anticrm/preference'
|
||||||
|
|
||||||
|
import { getDmName } from './utils'
|
||||||
|
|
||||||
export { CommentsPresenter }
|
export { CommentsPresenter }
|
||||||
|
|
||||||
async function MarkUnread (object: Message): Promise<void> {
|
async function MarkUnread (object: Message): Promise<void> {
|
||||||
const client = NotificationClientImpl.getClient()
|
const client = NotificationClientImpl.getClient()
|
||||||
await client.updateLastView(object.space, chunter.class.Channel, object.createOn - 1, true)
|
await client.updateLastView(object.space, chunter.class.ChunterSpace, object.createOn - 1, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function MarkCommentUnread (object: ThreadMessage): Promise<void> {
|
async function MarkCommentUnread (object: ThreadMessage): Promise<void> {
|
||||||
@ -70,7 +75,7 @@ async function UnsubscribeMessage (object: Message): Promise<void> {
|
|||||||
async function PinMessage (message: ChunterMessage): Promise<void> {
|
async function PinMessage (message: ChunterMessage): Promise<void> {
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
await client.updateDoc<Channel>(chunter.class.Channel, core.space.Space, message.space, {
|
await client.updateDoc<ChunterSpace>(chunter.class.ChunterSpace, core.space.Space, message.space, {
|
||||||
$push: { pinned: message._id }
|
$push: { pinned: message._id }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -78,7 +83,7 @@ async function PinMessage (message: ChunterMessage): Promise<void> {
|
|||||||
export async function UnpinMessage (message: ChunterMessage): Promise<void> {
|
export async function UnpinMessage (message: ChunterMessage): Promise<void> {
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
await client.updateDoc<Channel>(chunter.class.Channel, core.space.Space, message.space, {
|
await client.updateDoc<ChunterSpace>(chunter.class.ChunterSpace, core.space.Space, message.space, {
|
||||||
$pull: { pinned: message._id }
|
$pull: { pinned: message._id }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -149,16 +154,22 @@ export default async (): Promise<Resources> => ({
|
|||||||
component: {
|
component: {
|
||||||
CommentInput,
|
CommentInput,
|
||||||
CreateChannel,
|
CreateChannel,
|
||||||
|
CreateDirectMessage,
|
||||||
ChannelHeader,
|
ChannelHeader,
|
||||||
|
DmHeader,
|
||||||
ChannelView,
|
ChannelView,
|
||||||
CommentPresenter,
|
CommentPresenter,
|
||||||
CommentsPresenter,
|
CommentsPresenter,
|
||||||
ChannelPresenter,
|
ChannelPresenter,
|
||||||
|
DmPresenter,
|
||||||
EditChannel,
|
EditChannel,
|
||||||
Threads,
|
Threads,
|
||||||
ThreadView,
|
ThreadView,
|
||||||
SavedMessages
|
SavedMessages
|
||||||
},
|
},
|
||||||
|
function: {
|
||||||
|
GetDmName: getDmName
|
||||||
|
},
|
||||||
activity: {
|
activity: {
|
||||||
TxCommentCreate,
|
TxCommentCreate,
|
||||||
TxBacklinkCreate,
|
TxBacklinkCreate,
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import chunter, { chunterId } from '@anticrm/chunter'
|
import chunter, { chunterId } from '@anticrm/chunter'
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { Client, Space } from '@anticrm/core'
|
||||||
|
import type { IntlString, Resource } from '@anticrm/platform'
|
||||||
import { mergeIds } from '@anticrm/platform'
|
import { mergeIds } from '@anticrm/platform'
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
import { ViewAction } from '@anticrm/view'
|
import { ViewAction } from '@anticrm/view'
|
||||||
@ -22,10 +23,15 @@ import { ViewAction } from '@anticrm/view'
|
|||||||
export default mergeIds(chunterId, chunter, {
|
export default mergeIds(chunterId, chunter, {
|
||||||
component: {
|
component: {
|
||||||
CreateChannel: '' as AnyComponent,
|
CreateChannel: '' as AnyComponent,
|
||||||
|
CreateDirectMessage: '' as AnyComponent,
|
||||||
ChannelHeader: '' as AnyComponent,
|
ChannelHeader: '' as AnyComponent,
|
||||||
|
DmHeader: '' as AnyComponent,
|
||||||
ChannelView: '' as AnyComponent,
|
ChannelView: '' as AnyComponent,
|
||||||
EditChannel: '' as AnyComponent
|
EditChannel: '' as AnyComponent
|
||||||
},
|
},
|
||||||
|
function: {
|
||||||
|
GetDmName: '' as Resource<(client: Client, space: Space) => Promise<string>>
|
||||||
|
},
|
||||||
actionImpl: {
|
actionImpl: {
|
||||||
SubscribeMessage: '' as ViewAction,
|
SubscribeMessage: '' as ViewAction,
|
||||||
UnsubscribeMessage: '' as ViewAction,
|
UnsubscribeMessage: '' as ViewAction,
|
||||||
@ -36,14 +42,19 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
Channel: '' as IntlString,
|
Channel: '' as IntlString,
|
||||||
|
DirectMessage: '' as IntlString,
|
||||||
Channels: '' as IntlString,
|
Channels: '' as IntlString,
|
||||||
|
DirectMessages: '' as IntlString,
|
||||||
CreateChannel: '' as IntlString,
|
CreateChannel: '' as IntlString,
|
||||||
|
NewDirectMessage: '' as IntlString,
|
||||||
ChannelName: '' as IntlString,
|
ChannelName: '' as IntlString,
|
||||||
ChannelNamePlaceholder: '' as IntlString,
|
ChannelNamePlaceholder: '' as IntlString,
|
||||||
ChannelDescription: '' as IntlString,
|
ChannelDescription: '' as IntlString,
|
||||||
MakePrivate: '' as IntlString,
|
MakePrivate: '' as IntlString,
|
||||||
MakePrivateDescription: '' as IntlString,
|
MakePrivateDescription: '' as IntlString,
|
||||||
|
About: '' as IntlString,
|
||||||
Members: '' as IntlString,
|
Members: '' as IntlString,
|
||||||
|
NoMembers: '' as IntlString,
|
||||||
In: '' as IntlString,
|
In: '' as IntlString,
|
||||||
Replies: '' as IntlString,
|
Replies: '' as IntlString,
|
||||||
Topic: '' as IntlString,
|
Topic: '' as IntlString,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import contact, { EmployeeAccount } from '@anticrm/contact'
|
import contact, { EmployeeAccount, formatName } from '@anticrm/contact'
|
||||||
import { Account, Class, Client, Obj, Ref } from '@anticrm/core'
|
import { Account, Class, Client, Obj, Ref, Space, getCurrentAccount } from '@anticrm/core'
|
||||||
import { Asset } from '@anticrm/platform'
|
import { Asset } from '@anticrm/platform'
|
||||||
|
import { getCurrentLocation, locationToUrl } from '@anticrm/ui'
|
||||||
|
|
||||||
|
import chunter from './plugin'
|
||||||
|
|
||||||
export async function getUser (
|
export async function getUser (
|
||||||
client: Client,
|
client: Client,
|
||||||
@ -35,3 +38,28 @@ export function isToday (time: number): boolean {
|
|||||||
export function classIcon (client: Client, _class: Ref<Class<Obj>>): Asset | undefined {
|
export function classIcon (client: Client, _class: Ref<Class<Obj>>): Asset | undefined {
|
||||||
return client.getHierarchy().getClass(_class).icon
|
return client.getHierarchy().getClass(_class).icon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getDmName (client: Client, dm: Space): Promise<string> {
|
||||||
|
const myAccId = getCurrentAccount()._id
|
||||||
|
|
||||||
|
const employeeAccounts = await client.findAll(contact.class.EmployeeAccount, {
|
||||||
|
_id: { $in: dm.members as Array<Ref<EmployeeAccount>> }
|
||||||
|
})
|
||||||
|
|
||||||
|
const name = (dm.members.length > 1 ? employeeAccounts.filter((a) => a._id !== myAccId) : employeeAccounts)
|
||||||
|
.map((a) => formatName(a.name))
|
||||||
|
.join(', ')
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSpaceLink (id: Ref<Space>): string {
|
||||||
|
const loc = getCurrentLocation()
|
||||||
|
|
||||||
|
loc.path[1] = chunter.app.Chunter
|
||||||
|
loc.path[2] = id
|
||||||
|
loc.path.length = 3
|
||||||
|
loc.fragment = undefined
|
||||||
|
|
||||||
|
return locationToUrl(loc)
|
||||||
|
}
|
||||||
|
@ -23,12 +23,23 @@ import { AnyComponent } from '@anticrm/ui'
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface Channel extends Space {
|
export interface ChunterSpace extends Space {
|
||||||
lastMessage?: Timestamp
|
lastMessage?: Timestamp
|
||||||
pinned?: Ref<ChunterMessage>[]
|
pinned?: Ref<ChunterMessage>[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface Channel extends ChunterSpace {
|
||||||
topic?: string
|
topic?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface DirectMessage extends ChunterSpace {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -113,8 +124,10 @@ export default plugin(chunterId, {
|
|||||||
ThreadMessage: '' as Ref<Class<ThreadMessage>>,
|
ThreadMessage: '' as Ref<Class<ThreadMessage>>,
|
||||||
Backlink: '' as Ref<Class<Backlink>>,
|
Backlink: '' as Ref<Class<Backlink>>,
|
||||||
Comment: '' as Ref<Class<Comment>>,
|
Comment: '' as Ref<Class<Comment>>,
|
||||||
|
ChunterSpace: '' as Ref<Class<ChunterSpace>>,
|
||||||
Channel: '' as Ref<Class<Channel>>,
|
Channel: '' as Ref<Class<Channel>>,
|
||||||
SavedMessages: '' as Ref<Class<SavedMessages>>
|
SavedMessages: '' as Ref<Class<SavedMessages>>,
|
||||||
|
DirectMessage: '' as Ref<Class<DirectMessage>>
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
Backlinks: '' as Ref<Space>
|
Backlinks: '' as Ref<Space>
|
||||||
|
@ -59,6 +59,13 @@ export interface SpaceHeader extends Class<Doc> {
|
|||||||
header: AnyComponent
|
header: AnyComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface SpaceName extends Class<Doc> {
|
||||||
|
getName: Resource<(client: Client, space: Space) => Promise<string>>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -244,6 +251,7 @@ const view = plugin(viewId, {
|
|||||||
ObjectValidator: '' as Ref<Mixin<ObjectValidator>>,
|
ObjectValidator: '' as Ref<Mixin<ObjectValidator>>,
|
||||||
ObjectFactory: '' as Ref<Mixin<ObjectFactory>>,
|
ObjectFactory: '' as Ref<Mixin<ObjectFactory>>,
|
||||||
SpaceHeader: '' as Ref<Mixin<SpaceHeader>>,
|
SpaceHeader: '' as Ref<Mixin<SpaceHeader>>,
|
||||||
|
SpaceName: '' as Ref<Mixin<SpaceName>>,
|
||||||
IgnoreActions: '' as Ref<Mixin<IgnoreActions>>,
|
IgnoreActions: '' as Ref<Mixin<IgnoreActions>>,
|
||||||
HTMLPresenter: '' as Ref<Mixin<HTMLPresenter>>,
|
HTMLPresenter: '' as Ref<Mixin<HTMLPresenter>>,
|
||||||
TextPresenter: '' as Ref<Mixin<TextPresenter>>,
|
TextPresenter: '' as Ref<Mixin<TextPresenter>>,
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { Doc, Ref, SortingOrder, Space } from '@anticrm/core'
|
import core, { Doc, Ref, SortingOrder, Space, getCurrentAccount } from '@anticrm/core'
|
||||||
import { getResource } from '@anticrm/platform'
|
import { getResource } from '@anticrm/platform'
|
||||||
import { createQuery, getClient } from '@anticrm/presentation'
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
import { Scroller } from '@anticrm/ui'
|
import { Scroller } from '@anticrm/ui'
|
||||||
@ -34,6 +34,7 @@
|
|||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
const hierarchy = client.getHierarchy()
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
|
const myAccId = getCurrentAccount()._id
|
||||||
|
|
||||||
let spaces: Space[] = []
|
let spaces: Space[] = []
|
||||||
let starred: Space[] = []
|
let starred: Space[] = []
|
||||||
@ -77,7 +78,7 @@
|
|||||||
topSpecials = []
|
topSpecials = []
|
||||||
bottomSpecials = []
|
bottomSpecials = []
|
||||||
}
|
}
|
||||||
shownSpaces = spaces.filter((sp) => !sp.archived && !preferences.has(sp._id))
|
shownSpaces = spaces.filter((sp) => !sp.archived && !preferences.has(sp._id) && (!sp.members.length || sp.members.includes(myAccId)))
|
||||||
starred = spaces.filter((sp) => preferences.has(sp._id))
|
starred = spaces.filter((sp) => preferences.has(sp._id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +132,20 @@
|
|||||||
return lastView < value
|
return lastView < value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getName (space: Space) {
|
||||||
|
const clazz = hierarchy.getClass(space._class)
|
||||||
|
const nameMixin = hierarchy.as(clazz, view.mixin.SpaceName)
|
||||||
|
|
||||||
|
if (nameMixin.getName) {
|
||||||
|
const getSpaceName = await getResource(nameMixin.getName);
|
||||||
|
const name = await getSpaceName(client, space)
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
return space.name
|
||||||
|
}
|
||||||
|
|
||||||
function getParentActions(): Action[] {
|
function getParentActions(): Action[] {
|
||||||
return hasSpaceBrowser ? [browseSpaces, addSpace] : [addSpace]
|
return hasSpaceBrowser ? [browseSpaces, addSpace] : [addSpace]
|
||||||
}
|
}
|
||||||
@ -155,10 +169,11 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</TreeNode>
|
</TreeNode>
|
||||||
{:else}
|
{:else}
|
||||||
|
{#await getName(space) then name}
|
||||||
<TreeItem
|
<TreeItem
|
||||||
indent={'ml-4'}
|
indent={'ml-4'}
|
||||||
_id={space._id}
|
_id={space._id}
|
||||||
title={space.name}
|
title={name}
|
||||||
icon={classIcon(client, space._class)}
|
icon={classIcon(client, space._class)}
|
||||||
selected={currentSpace === space._id}
|
selected={currentSpace === space._id}
|
||||||
actions={() => getActions(space)}
|
actions={() => getActions(space)}
|
||||||
@ -167,6 +182,7 @@
|
|||||||
selectSpace(space._id)
|
selectSpace(space._id)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
{/await}
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</TreeNode>
|
</TreeNode>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import chunter, { Channel, Comment, Message, ThreadMessage } from '@anticrm/chunter'
|
import chunter, { ChunterSpace, Comment, Message, ThreadMessage } from '@anticrm/chunter'
|
||||||
import { EmployeeAccount } from '@anticrm/contact'
|
import { EmployeeAccount } from '@anticrm/contact'
|
||||||
import core, {
|
import core, {
|
||||||
Class,
|
Class,
|
||||||
@ -39,7 +39,7 @@ import workbench from '@anticrm/workbench'
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export function channelHTMLPresenter (doc: Doc): string {
|
export function channelHTMLPresenter (doc: Doc): string {
|
||||||
const channel = doc as Channel
|
const channel = doc as ChunterSpace
|
||||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||||
return `<a href="${front}/${workbench.component.WorkbenchApp}/${chunter.app.Chunter}/${channel._id}">${channel.name}</a>`
|
return `<a href="${front}/${workbench.component.WorkbenchApp}/${chunter.app.Chunter}/${channel._id}">${channel.name}</a>`
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ export function channelHTMLPresenter (doc: Doc): string {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export function channelTextPresenter (doc: Doc): string {
|
export function channelTextPresenter (doc: Doc): string {
|
||||||
const channel = doc as Channel
|
const channel = doc as ChunterSpace
|
||||||
return `${channel.name}`
|
return `${channel.name}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,12 +145,12 @@ export async function MessageCreate (tx: Tx, control: TriggerControl): Promise<T
|
|||||||
|
|
||||||
const message = doc as Message
|
const message = doc as Message
|
||||||
|
|
||||||
const channel = (await control.findAll(chunter.class.Channel, {
|
const channel = (await control.findAll(chunter.class.ChunterSpace, {
|
||||||
_id: message.space
|
_id: message.space
|
||||||
}, { limit: 1 }))[0]
|
}, { limit: 1 }))[0]
|
||||||
|
|
||||||
if (channel.lastMessage === undefined || channel.lastMessage < message.createOn) {
|
if (channel.lastMessage === undefined || channel.lastMessage < message.createOn) {
|
||||||
const res = control.txFactory.createTxUpdateDoc<Channel>(channel._class, channel.space, channel._id, {
|
const res = control.txFactory.createTxUpdateDoc<ChunterSpace>(channel._class, channel.space, channel._id, {
|
||||||
lastMessage: message.createOn
|
lastMessage: message.createOn
|
||||||
})
|
})
|
||||||
return [res]
|
return [res]
|
||||||
@ -165,7 +165,7 @@ export async function MessageDelete (tx: Tx, control: TriggerControl): Promise<T
|
|||||||
const hierarchy = control.hierarchy
|
const hierarchy = control.hierarchy
|
||||||
if (tx._class !== core.class.TxCollectionCUD) return []
|
if (tx._class !== core.class.TxCollectionCUD) return []
|
||||||
|
|
||||||
const rmTx = (tx as TxCollectionCUD<Channel, Message>).tx
|
const rmTx = (tx as TxCollectionCUD<ChunterSpace, Message>).tx
|
||||||
if (!hierarchy.isDerived(rmTx.objectClass, chunter.class.Message)) {
|
if (!hierarchy.isDerived(rmTx.objectClass, chunter.class.Message)) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ export async function MessageDelete (tx: Tx, control: TriggerControl): Promise<T
|
|||||||
|
|
||||||
const message = TxProcessor.createDoc2Doc(createTx as TxCreateDoc<Message>)
|
const message = TxProcessor.createDoc2Doc(createTx as TxCreateDoc<Message>)
|
||||||
|
|
||||||
const channel = (await control.findAll(chunter.class.Channel, {
|
const channel = (await control.findAll(chunter.class.ChunterSpace, {
|
||||||
_id: message.space
|
_id: message.space
|
||||||
}, { limit: 1 }))[0]
|
}, { limit: 1 }))[0]
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ export async function MessageDelete (tx: Tx, control: TriggerControl): Promise<T
|
|||||||
})
|
})
|
||||||
const lastMessageDate = messages.reduce((maxDate, mess) => mess.createOn > maxDate ? mess.createOn : maxDate, 0)
|
const lastMessageDate = messages.reduce((maxDate, mess) => mess.createOn > maxDate ? mess.createOn : maxDate, 0)
|
||||||
|
|
||||||
const updateTx = control.txFactory.createTxUpdateDoc<Channel>(channel._class, channel.space, channel._id, {
|
const updateTx = control.txFactory.createTxUpdateDoc<ChunterSpace>(channel._class, channel.space, channel._id, {
|
||||||
lastMessage: lastMessageDate > 0 ? lastMessageDate : undefined
|
lastMessage: lastMessageDate > 0 ? lastMessageDate : undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -31,7 +31,17 @@ export default plugin(serverChunterId, {
|
|||||||
ChunterTrigger: '' as Resource<TriggerFunc>
|
ChunterTrigger: '' as Resource<TriggerFunc>
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
CommentRemove: '' as Resource<(doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc> (clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>) => Promise<Doc[]>>,
|
CommentRemove: '' as Resource<
|
||||||
|
(
|
||||||
|
doc: Doc,
|
||||||
|
hiearachy: Hierarchy,
|
||||||
|
findAll: <T extends Doc>(
|
||||||
|
clazz: Ref<Class<T>>,
|
||||||
|
query: DocumentQuery<T>,
|
||||||
|
options?: FindOptions<T>
|
||||||
|
) => Promise<FindResult<T>>
|
||||||
|
) => Promise<Doc[]>
|
||||||
|
>,
|
||||||
ChannelHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
ChannelHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||||
ChannelTextPresenter: '' as Resource<(doc: Doc) => string>
|
ChannelTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user