mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
Messages search (#1935)
Signed-off-by: budaeva <irina.budaeva@xored.com>
This commit is contained in:
parent
5a99d0dd93
commit
6739ce302d
@ -93,6 +93,7 @@ export class TChunterMessage extends TAttachedDoc implements ChunterMessage {
|
||||
}
|
||||
|
||||
@Model(chunter.class.ThreadMessage, chunter.class.ChunterMessage)
|
||||
@UX(chunter.string.ThreadMessage)
|
||||
export class TThreadMessage extends TChunterMessage implements ThreadMessage {
|
||||
declare attachedTo: Ref<Message>
|
||||
|
||||
@ -100,6 +101,7 @@ export class TThreadMessage extends TChunterMessage implements ThreadMessage {
|
||||
}
|
||||
|
||||
@Model(chunter.class.Message, chunter.class.ChunterMessage)
|
||||
@UX(chunter.string.Message)
|
||||
export class TMessage extends TChunterMessage implements Message {
|
||||
declare attachedTo: Ref<Space>
|
||||
|
||||
@ -347,6 +349,12 @@ export function createModel (builder: Builder): void {
|
||||
componentProps: {
|
||||
requestedSpaceClasses: [chunter.class.Channel, chunter.class.DirectMessage]
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'messagesBrowser',
|
||||
label: chunter.string.MessagesBrowser,
|
||||
component: chunter.component.MessagesBrowser,
|
||||
visibleIf: chunter.function.MessageBrowserVisible
|
||||
}
|
||||
],
|
||||
spaces: [
|
||||
@ -437,6 +445,10 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
chunter.ids.TxBacklinkRemove
|
||||
)
|
||||
|
||||
builder.mixin(chunter.class.ChunterMessage, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: ['space', 'modifiedOn', 'createBy', '_class']
|
||||
})
|
||||
}
|
||||
|
||||
export { chunterOperation } from './migration'
|
||||
|
@ -16,8 +16,8 @@
|
||||
import type { TxViewlet } from '@anticrm/activity'
|
||||
import { Channel, chunterId } from '@anticrm/chunter'
|
||||
import chunter from '@anticrm/chunter-resources/src/plugin'
|
||||
import type { Ref } from '@anticrm/core'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import type { Ref, Space } from '@anticrm/core'
|
||||
import type { IntlString, Resource } from '@anticrm/platform'
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
import type { AnyComponent } from '@anticrm/ui'
|
||||
import type { Action, ActionCategory, ViewAction, ViewletDescriptor } from '@anticrm/view'
|
||||
@ -29,7 +29,8 @@ export default mergeIds(chunterId, chunter, {
|
||||
DmPresenter: '' as AnyComponent,
|
||||
Threads: '' as AnyComponent,
|
||||
ThreadView: '' as AnyComponent,
|
||||
SavedMessages: '' as AnyComponent
|
||||
SavedMessages: '' as AnyComponent,
|
||||
MessagesBrowser: '' as AnyComponent
|
||||
},
|
||||
action: {
|
||||
MarkCommentUnread: '' as Ref<Action>,
|
||||
@ -63,7 +64,8 @@ export default mergeIds(chunterId, chunter, {
|
||||
MarkUnread: '' as IntlString,
|
||||
LastMessage: '' as IntlString,
|
||||
PinnedMessages: '' as IntlString,
|
||||
SavedMessages: '' as IntlString
|
||||
SavedMessages: '' as IntlString,
|
||||
ThreadMessage: '' as IntlString
|
||||
},
|
||||
viewlet: {
|
||||
Chat: '' as Ref<ViewletDescriptor>
|
||||
@ -82,5 +84,8 @@ export default mergeIds(chunterId, chunter, {
|
||||
space: {
|
||||
General: '' as Ref<Channel>,
|
||||
Random: '' as Ref<Channel>
|
||||
},
|
||||
function: {
|
||||
MessageBrowserVisible: '' as Resource<(spaces: Space[]) => boolean>
|
||||
}
|
||||
})
|
||||
|
@ -59,6 +59,9 @@
|
||||
"ChannelBrowser": "Channel browser",
|
||||
"SavedItems": "Saved items",
|
||||
"AddMembersHeader": "Add members to {channel}:",
|
||||
"ConvertToPrivate": "Convert to private channel"
|
||||
"ConvertToPrivate": "Convert to private channel",
|
||||
"MessagesBrowser": "Messages browser",
|
||||
"CreateBy": "Create by",
|
||||
"ThreadMessage": "Thread message"
|
||||
}
|
||||
}
|
@ -58,6 +58,9 @@
|
||||
"ChannelBrowser": "Браузер каналов",
|
||||
"SavedItems": "Сохраненные объекты",
|
||||
"AddMembersHeader": "Добавить пользователей в {channel}:",
|
||||
"ConvertToPrivate": "Конвертировать в закрытый канал"
|
||||
"ConvertToPrivate": "Конвертировать в закрытый канал",
|
||||
"MessagesBrowser": "Браузер сообщений",
|
||||
"CreateBy": "Создано пользователем",
|
||||
"ThreadMessage": "Сообщение в обсуждении"
|
||||
}
|
||||
}
|
@ -43,7 +43,6 @@
|
||||
mode: 'space',
|
||||
space: dm._id
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,16 @@
|
||||
import { getCurrentAccount } from '@anticrm/core'
|
||||
import { createQuery, getClient, CombineAvatars } from '@anticrm/presentation'
|
||||
import contact, { EmployeeAccount } from '@anticrm/contact'
|
||||
import { showPanel } from '@anticrm/ui'
|
||||
import { getCurrentLocation, navigate, SearchEdit, showPanel } from '@anticrm/ui'
|
||||
import chunter from '../plugin'
|
||||
import { getDmName } from '../utils'
|
||||
import { userSearch } from '../index'
|
||||
|
||||
export let spaceId: Ref<DirectMessage> | undefined
|
||||
|
||||
let userSearch_: string = ''
|
||||
userSearch.subscribe((v) => (userSearch_ = v))
|
||||
|
||||
const client = getClient()
|
||||
const query = createQuery()
|
||||
const myAccId = getCurrentAccount()._id
|
||||
@ -62,6 +66,18 @@
|
||||
{/await}
|
||||
{/await}
|
||||
{/if}
|
||||
<SearchEdit
|
||||
value={userSearch_}
|
||||
on:change={(ev) => {
|
||||
userSearch.set(ev.detail)
|
||||
|
||||
if (ev.detail !== '') {
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = 'messagesBrowser'
|
||||
navigate(loc)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -14,11 +14,15 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { Asset } from '@anticrm/platform'
|
||||
import { AnySvelteComponent, Icon } from '@anticrm/ui'
|
||||
import { AnySvelteComponent, getCurrentLocation, Icon, navigate, SearchEdit } from '@anticrm/ui'
|
||||
import { userSearch } from '../index'
|
||||
|
||||
export let icon: Asset | AnySvelteComponent | undefined
|
||||
export let label: string
|
||||
export let description: string | undefined
|
||||
|
||||
let userSearch_: string
|
||||
userSearch.subscribe((v) => (userSearch_ = v))
|
||||
</script>
|
||||
|
||||
<div class="ac-header__wrap-description">
|
||||
@ -28,6 +32,18 @@
|
||||
</div>
|
||||
{#if description}<span class="ac-header__description">{description}</span>{/if}
|
||||
</div>
|
||||
<SearchEdit
|
||||
value={userSearch_}
|
||||
on:change={(ev) => {
|
||||
userSearch.set(ev.detail)
|
||||
|
||||
if (ev.detail !== '') {
|
||||
const loc = getCurrentLocation()
|
||||
loc.path[2] = 'messagesBrowser'
|
||||
navigate(loc)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<style lang="scss">
|
||||
.ac-header__wrap-title:hover {
|
||||
|
128
plugins/chunter-resources/src/components/MessagesBrowser.svelte
Normal file
128
plugins/chunter-resources/src/components/MessagesBrowser.svelte
Normal file
@ -0,0 +1,128 @@
|
||||
<script lang="ts">
|
||||
import attachment, { Attachment } from '@anticrm/attachment'
|
||||
import chunter, { ChunterMessage } from '@anticrm/chunter'
|
||||
import contact, { Employee } from '@anticrm/contact'
|
||||
import core, { DocumentQuery, Ref, SortingOrder } from '@anticrm/core'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import { Label, Scroller, SearchEdit } from '@anticrm/ui'
|
||||
import type { Filter } from '@anticrm/view'
|
||||
import { FilterBar, FilterButton } from '@anticrm/view-resources'
|
||||
import MessageComponent from './Message.svelte'
|
||||
import { userSearch } from '../index'
|
||||
import plugin from '../plugin'
|
||||
import { openMessageFromSpecial } from '../utils'
|
||||
|
||||
let userSearch_: string = ''
|
||||
userSearch.subscribe((v) => (userSearch_ = v))
|
||||
|
||||
let searchQuery: DocumentQuery<ChunterMessage> = { $search: userSearch_ }
|
||||
|
||||
let filters: Filter[] = []
|
||||
|
||||
function updateSearchQuery (search: string): void {
|
||||
searchQuery = { $search: search }
|
||||
}
|
||||
|
||||
$: updateSearchQuery(userSearch_)
|
||||
|
||||
const client = getClient()
|
||||
const _class = chunter.class.ChunterMessage
|
||||
let messages: ChunterMessage[] = []
|
||||
|
||||
let resultQuery: DocumentQuery<ChunterMessage> = { ...searchQuery }
|
||||
|
||||
async function updateMessages (resultQuery: DocumentQuery<ChunterMessage>) {
|
||||
messages = await client.findAll(
|
||||
_class,
|
||||
{
|
||||
...resultQuery
|
||||
},
|
||||
{
|
||||
sort: { createOn: SortingOrder.Descending },
|
||||
limit: 100,
|
||||
lookup: {
|
||||
_id: { attachments: attachment.class.Attachment },
|
||||
createBy: core.class.Account
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
$: updateMessages(resultQuery)
|
||||
|
||||
let employees: Map<Ref<Employee>, Employee> = new Map<Ref<Employee>, Employee>()
|
||||
const employeeQuery = createQuery()
|
||||
|
||||
employeeQuery.query(
|
||||
contact.class.Employee,
|
||||
{},
|
||||
(res) =>
|
||||
(employees = new Map(
|
||||
res.map((r) => {
|
||||
return [r._id, r]
|
||||
})
|
||||
)),
|
||||
{
|
||||
lookup: { _id: { statuses: contact.class.Status } }
|
||||
}
|
||||
)
|
||||
|
||||
const pinnedQuery = createQuery()
|
||||
const pinnedIds: Ref<ChunterMessage>[] = []
|
||||
|
||||
pinnedQuery.query(
|
||||
chunter.class.Channel,
|
||||
{},
|
||||
(res) => {
|
||||
res.forEach((ch) => {
|
||||
if (ch.pinned) {
|
||||
pinnedIds.push(...ch.pinned)
|
||||
}
|
||||
})
|
||||
},
|
||||
{}
|
||||
)
|
||||
let savedMessagesIds: Ref<ChunterMessage>[] = []
|
||||
let savedAttachmentsIds: Ref<Attachment>[] = []
|
||||
|
||||
const savedMessagesQuery = createQuery()
|
||||
const savedAttachmentsQuery = createQuery()
|
||||
|
||||
savedMessagesQuery.query(chunter.class.SavedMessages, {}, (res) => {
|
||||
savedMessagesIds = res.map((r) => r.attachedTo)
|
||||
})
|
||||
|
||||
savedAttachmentsQuery.query(attachment.class.SavedAttachments, {}, (res) => {
|
||||
savedAttachmentsIds = res.map((r) => r.attachedTo)
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="ac-header full divide">
|
||||
<div class="ac-header__wrap-title">
|
||||
<span class="ac-header__title"><Label label={plugin.string.MessagesBrowser} /></span>
|
||||
</div>
|
||||
<div class="ml-4"><FilterButton {_class} bind:filters /></div>
|
||||
<SearchEdit
|
||||
value={userSearch_}
|
||||
on:change={(ev) => {
|
||||
userSearch.set(ev.detail)
|
||||
updateSearchQuery(userSearch_)
|
||||
updateMessages(resultQuery)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<FilterBar {_class} query={searchQuery} bind:filters on:change={(e) => (resultQuery = e.detail)} />
|
||||
<Scroller>
|
||||
{#each messages as message}
|
||||
<div on:click={() => openMessageFromSpecial(message)}>
|
||||
<MessageComponent
|
||||
{message}
|
||||
{employees}
|
||||
on:openThread
|
||||
isPinned={pinnedIds.includes(message._id)}
|
||||
isSaved={savedMessagesIds.includes(message._id)}
|
||||
{savedAttachmentsIds}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</Scroller>
|
@ -4,12 +4,12 @@
|
||||
import { ChunterMessage } from '@anticrm/chunter'
|
||||
import core, { Ref, WithLookup } from '@anticrm/core'
|
||||
import contact, { Employee, EmployeeAccount, formatName } from '@anticrm/contact'
|
||||
import { getCurrentLocation, Label, navigate, Scroller } from '@anticrm/ui'
|
||||
import { Label, Scroller } from '@anticrm/ui'
|
||||
import AttachmentPreview from '@anticrm/attachment-resources/src/components/AttachmentPreview.svelte'
|
||||
import Bookmark from './icons/Bookmark.svelte'
|
||||
import Message from './Message.svelte'
|
||||
import chunter from '../plugin'
|
||||
import { getTime } from '../utils'
|
||||
import { getTime, openMessageFromSpecial } from '../utils'
|
||||
|
||||
const client = getClient()
|
||||
let savedMessagesIds: Ref<ChunterMessage>[] = []
|
||||
@ -83,29 +83,19 @@
|
||||
chunter.class.Channel,
|
||||
{},
|
||||
(res) => {
|
||||
res.forEach((ch) => pinnedIds.concat(ch?.pinned ?? []))
|
||||
res.forEach((ch) => {
|
||||
if (ch.pinned) {
|
||||
pinnedIds.push(...ch.pinned)
|
||||
}
|
||||
})
|
||||
},
|
||||
{ limit: 1 }
|
||||
{}
|
||||
)
|
||||
|
||||
function openMessage (message: ChunterMessage) {
|
||||
const loc = getCurrentLocation()
|
||||
|
||||
if (message.attachedToClass === chunter.class.ChunterSpace) {
|
||||
loc.path.length = 3
|
||||
loc.path[2] = message.attachedTo
|
||||
} else if (message.attachedToClass === chunter.class.Message) {
|
||||
loc.path.length = 4
|
||||
loc.path[2] = message.space
|
||||
loc.path[3] = message.attachedTo
|
||||
}
|
||||
navigate(loc)
|
||||
}
|
||||
|
||||
async function openAttachment (att: Attachment) {
|
||||
const messageId: Ref<ChunterMessage> = att.attachedTo as Ref<ChunterMessage>
|
||||
await client.findOne(chunter.class.ChunterMessage, { _id: messageId }).then((res) => {
|
||||
if (res !== undefined) openMessage(res)
|
||||
if (res !== undefined) openMessageFromSpecial(res)
|
||||
})
|
||||
}
|
||||
|
||||
@ -125,7 +115,7 @@
|
||||
<Scroller>
|
||||
{#if savedMessages.length > 0 || savedAttachments.length > 0}
|
||||
{#each savedMessages as message}
|
||||
<div on:click={() => openMessage(message)}>
|
||||
<div on:click={() => openMessageFromSpecial(message)}>
|
||||
<Message
|
||||
{message}
|
||||
{employees}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import core from '@anticrm/core'
|
||||
import core, { Space } from '@anticrm/core'
|
||||
import chunter, { ChunterSpace, Channel, ChunterMessage, Message, ThreadMessage, DirectMessage } from '@anticrm/chunter'
|
||||
import { NotificationClientImpl } from '@anticrm/notification-resources'
|
||||
import { Resources } from '@anticrm/platform'
|
||||
@ -34,12 +34,14 @@ import CommentsPresenter from './components/CommentsPresenter.svelte'
|
||||
import CreateChannel from './components/CreateChannel.svelte'
|
||||
import CreateDirectMessage from './components/CreateDirectMessage.svelte'
|
||||
import EditChannel from './components/EditChannel.svelte'
|
||||
import MessagesBrowser from './components/MessagesBrowser.svelte'
|
||||
import ThreadView from './components/ThreadView.svelte'
|
||||
import Threads from './components/Threads.svelte'
|
||||
import SavedMessages from './components/SavedMessages.svelte'
|
||||
import ConvertDmToPrivateChannelModal from './components/ConvertDmToPrivateChannel.svelte'
|
||||
|
||||
import { getDmName } from './utils'
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
export { default as Header } from './components/Header.svelte'
|
||||
export { classIcon } from './utils'
|
||||
@ -160,6 +162,12 @@ export async function DeleteMessageFromSaved (message: ChunterMessage): Promise<
|
||||
}
|
||||
}
|
||||
|
||||
export const userSearch = writable('')
|
||||
|
||||
export function messageBrowserVisible (spaces: Space[]): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
CommentInput,
|
||||
@ -173,12 +181,14 @@ export default async (): Promise<Resources> => ({
|
||||
ChannelPresenter,
|
||||
DmPresenter,
|
||||
EditChannel,
|
||||
MessagesBrowser,
|
||||
Threads,
|
||||
ThreadView,
|
||||
SavedMessages
|
||||
},
|
||||
function: {
|
||||
GetDmName: getDmName
|
||||
GetDmName: getDmName,
|
||||
MessageBrowserVisible: messageBrowserVisible
|
||||
},
|
||||
activity: {
|
||||
TxCommentCreate,
|
||||
|
@ -81,6 +81,7 @@ export default mergeIds(chunterId, chunter, {
|
||||
LeaveChannel: '' as IntlString,
|
||||
ChannelBrowser: '' as IntlString,
|
||||
SavedItems: '' as IntlString,
|
||||
AddMembersHeader: '' as IntlString
|
||||
AddMembersHeader: '' as IntlString,
|
||||
MessagesBrowser: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { ChunterMessage } from '@anticrm/chunter'
|
||||
import contact, { EmployeeAccount, formatName } from '@anticrm/contact'
|
||||
import { Account, Class, Client, Obj, Ref, Space, getCurrentAccount, Timestamp } from '@anticrm/core'
|
||||
import { Asset } from '@anticrm/platform'
|
||||
import { getCurrentLocation, locationToUrl } from '@anticrm/ui'
|
||||
import { getCurrentLocation, locationToUrl, navigate } from '@anticrm/ui'
|
||||
|
||||
import chunter from './plugin'
|
||||
|
||||
@ -69,3 +70,17 @@ export function getDay (time: Timestamp): Timestamp {
|
||||
date.setHours(0, 0, 0, 0)
|
||||
return date.getTime()
|
||||
}
|
||||
|
||||
export function openMessageFromSpecial (message: ChunterMessage): void {
|
||||
const loc = getCurrentLocation()
|
||||
|
||||
if (message.attachedToClass === chunter.class.ChunterSpace) {
|
||||
loc.path.length = 3
|
||||
loc.path[2] = message.attachedTo
|
||||
} else if (message.attachedToClass === chunter.class.Message) {
|
||||
loc.path.length = 4
|
||||
loc.path[2] = message.space
|
||||
loc.path[3] = message.attachedTo
|
||||
}
|
||||
navigate(loc)
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import ValueFilter from './components/filter/ValueFilter.svelte'
|
||||
import ObjectFilter from './components/filter/ObjectFilter.svelte'
|
||||
import TimestampFilter from './components/filter/TimestampFilter.svelte'
|
||||
import ClassPresenter from './components/ClassPresenter.svelte'
|
||||
import FilterBar from './components/filter/FilterBar.svelte'
|
||||
import EditBoxPopup from './components/EditBoxPopup.svelte'
|
||||
import BooleanTruePresenter from './components/BooleanTruePresenter.svelte'
|
||||
import EnumEditor from './components/EnumEditor.svelte'
|
||||
@ -75,6 +76,7 @@ export {
|
||||
SpacePresenter,
|
||||
UpDownNavigator,
|
||||
ViewletSetting,
|
||||
FilterBar,
|
||||
ClassAttributeBar
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user