Add chat UI fixes (#5632)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-05-22 11:32:45 +04:00 committed by GitHub
parent f956b8d98e
commit 930d13b2a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 52 additions and 19 deletions

View File

@ -38,8 +38,7 @@ import {
type Ref, type Ref,
type Space, type Space,
type Timestamp, type Timestamp,
IndexKind, IndexKind
SortingOrder
} from '@hcengineering/core' } from '@hcengineering/core'
import { import {
ArrOf, ArrOf,
@ -77,9 +76,6 @@ export const DOMAIN_CHUNTER = 'chunter' as Domain
export class TChunterSpace extends TSpace implements ChunterSpace { export class TChunterSpace extends TSpace implements ChunterSpace {
@Prop(TypeTimestamp(), chunter.string.LastMessage) @Prop(TypeTimestamp(), chunter.string.LastMessage)
lastMessage?: Timestamp lastMessage?: Timestamp
@Prop(ArrOf(TypeRef(chunter.class.ChunterMessage)), chunter.string.PinnedMessages)
pinned?: Ref<ChunterMessage>[]
} }
@Model(chunter.class.Channel, chunter.class.ChunterSpace) @Model(chunter.class.Channel, chunter.class.ChunterSpace)
@ -352,15 +348,11 @@ export function createModel (builder: Builder): void {
{ {
attachTo: chunter.class.Channel, attachTo: chunter.class.Channel,
descriptor: view.viewlet.Table, descriptor: view.viewlet.Table,
viewOptions: {
orderBy: [['modifiedOn', SortingOrder.Descending]],
groupBy: [],
other: []
},
configOptions: { configOptions: {
strict: true strict: true
}, },
config: ['', 'topic', 'private', 'archived', 'members'] config: ['', 'topic', 'private', 'archived', 'members'],
props: { enableChecking: false }
}, },
chunter.viewlet.Channels chunter.viewlet.Channels
) )
@ -738,6 +730,11 @@ export function createModel (builder: Builder): void {
}, },
chunter.action.ReplyToThreadAction chunter.action.ReplyToThreadAction
) )
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.ClassFilters, {
filters: ['name', 'topic', 'private', 'archived', 'members'],
strict: true
})
} }
export default chunter export default chunter

View File

@ -300,6 +300,7 @@ export class TViewlet extends TDoc implements Viewlet {
config!: (BuildModelKey | string)[] config!: (BuildModelKey | string)[]
hiddenKeys?: string[] hiddenKeys?: string[]
viewOptions?: ViewOptionsModel viewOptions?: ViewOptionsModel
props?: Record<string, any>
} }
@Model(view.class.Action, core.class.Doc, DOMAIN_MODEL) @Model(view.class.Action, core.class.Doc, DOMAIN_MODEL)

View File

@ -1524,8 +1524,12 @@
th, td { th, td {
padding: .5rem 1.5rem; padding: .5rem 1.5rem;
text-align: left; text-align: left;
&:first-child { padding-left: 0; } &:first-child { .metaColumn {
&:last-child { padding-right: 0; } padding-left: 0; }
}
&:last-child { .metaColumn {
padding-right: 0; }
}
} }
th { th {
height: 3rem; height: 3rem;

View File

@ -61,7 +61,10 @@
}) })
openedChannelStore.subscribe((data) => { openedChannelStore.subscribe((data) => {
if (data && selectedData?._id !== data._id) { if (data === undefined) {
selectedData = undefined
object = undefined
} else if (selectedData?._id !== data._id) {
selectedData = data selectedData = data
openChannel(data._id, data._class, data.thread) openChannel(data._id, data._class, data.thread)
} }
@ -94,6 +97,8 @@
const id = loc.path[3] const id = loc.path[3]
if (!id) { if (!id) {
currentSpecial = undefined
clearChannel()
return return
} }

View File

@ -12,7 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// //
import { type Channel, type ChatMessage, type DirectMessage, type ThreadMessage } from '@hcengineering/chunter' import {
type Channel,
type ChatMessage,
chunterId,
type DirectMessage,
type ThreadMessage
} from '@hcengineering/chunter'
import contact, { type Employee, getName, type Person, type PersonAccount } from '@hcengineering/contact' import contact, { type Employee, getName, type Person, type PersonAccount } from '@hcengineering/contact'
import { employeeByIdStore, PersonIcon } from '@hcengineering/contact-resources' import { employeeByIdStore, PersonIcon } from '@hcengineering/contact-resources'
import { import {
@ -28,7 +34,7 @@ import {
type Timestamp type Timestamp
} from '@hcengineering/core' } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation' import { getClient } from '@hcengineering/presentation'
import { type AnySvelteComponent } from '@hcengineering/ui' import { type AnySvelteComponent, getCurrentLocation, navigate } from '@hcengineering/ui'
import { type Asset, translate } from '@hcengineering/platform' import { type Asset, translate } from '@hcengineering/platform'
import { classIcon, getDocLinkTitle, getDocTitle } from '@hcengineering/view-resources' import { classIcon, getDocLinkTitle, getDocTitle } from '@hcengineering/view-resources'
import activity, { import activity, {
@ -49,6 +55,7 @@ import { get, type Unsubscriber } from 'svelte/store'
import chunter from './plugin' import chunter from './plugin'
import DirectIcon from './components/DirectIcon.svelte' import DirectIcon from './components/DirectIcon.svelte'
import ChannelIcon from './components/ChannelIcon.svelte' import ChannelIcon from './components/ChannelIcon.svelte'
import { decodeChannelURI } from './navigation'
export async function getDmName (client: Client, space?: Space): Promise<string> { export async function getDmName (client: Client, space?: Space): Promise<string> {
if (space === undefined) { if (space === undefined) {
@ -395,6 +402,21 @@ export async function readChannelMessages (
} }
} }
function resetChunterLoc (objectId: Ref<Doc>): void {
const loc = getCurrentLocation()
const [_id] = decodeChannelURI(loc.path[3])
if (loc.path[2] !== chunterId || _id !== objectId) {
return
}
loc.path[3] = ''
loc.path[4] = ''
loc.query = {}
loc.path.length = 3
navigate(loc)
}
export async function leaveChannelAction (context?: DocNotifyContext): Promise<void> { export async function leaveChannelAction (context?: DocNotifyContext): Promise<void> {
if (context === undefined) { if (context === undefined) {
return return
@ -407,6 +429,7 @@ export async function leaveChannelAction (context?: DocNotifyContext): Promise<v
} }
await leaveChannel(channel, getCurrentAccount()._id) await leaveChannel(channel, getCurrentAccount()._id)
resetChunterLoc(channel._id)
} }
export async function removeChannelAction (context?: DocNotifyContext): Promise<void> { export async function removeChannelAction (context?: DocNotifyContext): Promise<void> {
@ -418,6 +441,8 @@ export async function removeChannelAction (context?: DocNotifyContext): Promise<
await archiveContextNotifications(context) await archiveContextNotifications(context)
await client.remove(context) await client.remove(context)
resetChunterLoc(context.attachedTo)
} }
export function isThreadMessage (message: ActivityMessage): message is ThreadMessage { export function isThreadMessage (message: ActivityMessage): message is ThreadMessage {

View File

@ -27,7 +27,6 @@ import { Action } from '@hcengineering/view'
*/ */
export interface ChunterSpace extends Space { export interface ChunterSpace extends Space {
lastMessage?: Timestamp lastMessage?: Timestamp
pinned?: Ref<ChunterMessage>[]
} }
/** /**

View File

@ -410,6 +410,7 @@ export interface Viewlet extends Doc {
configOptions?: ViewletConfigOptions configOptions?: ViewletConfigOptions
viewOptions?: ViewOptionsModel viewOptions?: ViewOptionsModel
variant?: string variant?: string
props?: Record<string, any>
} }
/** /**

View File

@ -129,7 +129,8 @@
createItemDialog: createComponent, createItemDialog: createComponent,
createItemLabel: createLabel, createItemLabel: createLabel,
query: resultQuery, query: resultQuery,
totalQuery: query totalQuery: query,
...viewlet.props
}} }}
/> />
{/if} {/if}

View File

@ -12,7 +12,7 @@ export class ChannelPage {
readonly textMessage = (): Locator => this.page.getByText('Test message') readonly textMessage = (): Locator => this.page.getByText('Test message')
readonly channelName = (channel: string): Locator => this.page.getByText('general random').getByText(channel) readonly channelName = (channel: string): Locator => this.page.getByText('general random').getByText(channel)
readonly channelTab = (): Locator => this.page.getByRole('link', { name: 'Channels' }).getByRole('button') readonly channelTab = (): Locator => this.page.getByRole('link', { name: 'Channels' }).getByRole('button')
readonly channelTable = (): Locator => this.page.locator('[class="antiTable metaColumn highlightRows"]') readonly channelTable = (): Locator => this.page.getByRole('table')
readonly channel = (channel: string): Locator => this.page.getByRole('button', { name: channel }) readonly channel = (channel: string): Locator => this.page.getByRole('button', { name: channel })
async sendMessage (message: string): Promise<void> { async sendMessage (message: string): Promise<void> {