[Part 1]: Sidebar fixes (#6640)

This commit is contained in:
Kristina 2024-09-20 09:12:06 +04:00 committed by GitHub
parent 14937d13bf
commit 7b98fbc3d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 71 additions and 51 deletions

View File

@ -308,14 +308,4 @@ function defineChannelActions (builder: Builder): void {
target: notification.class.DocNotifyContext, target: notification.class.DocNotifyContext,
context: { mode: ['context', 'browser'], group: 'tools' } context: { mode: ['context', 'browser'], group: 'tools' }
}) })
createAction(builder, {
action: chunter.actionImpl.OpenInSidebarTab,
label: workbench.string.OpenInSidebarNewTab,
icon: view.icon.DetailsFilled,
input: 'focus',
category: chunter.category.Chunter,
target: notification.class.DocNotifyContext,
context: { mode: ['context', 'browser'], group: 'tools' }
})
} }

View File

@ -52,7 +52,6 @@ export default mergeIds(chunterId, chunter, {
DeleteChatMessage: '' as ViewAction, DeleteChatMessage: '' as ViewAction,
ReplyToThread: '' as ViewAction, ReplyToThread: '' as ViewAction,
OpenInSidebar: '' as ViewAction, OpenInSidebar: '' as ViewAction,
OpenInSidebarTab: '' as ViewAction,
TranslateMessage: '' as ViewAction, TranslateMessage: '' as ViewAction,
ShowOriginalMessage: '' as ViewAction ShowOriginalMessage: '' as ViewAction
}, },

View File

@ -35,6 +35,7 @@
export let withSearch: boolean = true export let withSearch: boolean = true
export let isAsideShown: boolean = false export let isAsideShown: boolean = false
export let filters: Ref<ActivityMessagesFilter>[] = [] export let filters: Ref<ActivityMessagesFilter>[] = []
export let canOpenInSidebar: boolean = false
const client = getClient() const client = getClient()
const hierarchy = client.getHierarchy() const hierarchy = client.getHierarchy()
@ -78,6 +79,7 @@
{withAside} {withAside}
{isAsideShown} {isAsideShown}
{withSearch} {withSearch}
{canOpenInSidebar}
on:aside-toggled on:aside-toggled
on:close on:close
> >

View File

@ -61,7 +61,6 @@
</script> </script>
{#if object} {#if object}
{#key object._id}
<div class="channel" class:invisible={threadId !== undefined} style:height style:width> <div class="channel" class:invisible={threadId !== undefined} style:height style:width>
<ChannelHeader <ChannelHeader
_id={object._id} _id={object._id}
@ -71,11 +70,13 @@
withSearch={false} withSearch={false}
canOpen={true} canOpen={true}
allowClose={true} allowClose={true}
canOpenInSidebar={false}
on:close on:close
/> />
{#key object._id}
<Channel {object} {context} syncLocation={false} /> <Channel {object} {context} syncLocation={false} />
</div>
{/key} {/key}
</div>
{/if} {/if}
{#if threadId} {#if threadId}
<div class="thread" style:height style:width> <div class="thread" style:height style:width>

View File

@ -103,6 +103,7 @@
canOpen={isDocChat} canOpen={isDocChat}
allowClose={embedded} allowClose={embedded}
{isAsideShown} {isAsideShown}
canOpenInSidebar={true}
on:close on:close
on:select={handleMessageSelect} on:select={handleMessageSelect}
on:aside-toggled={() => { on:aside-toggled={() => {

View File

@ -19,11 +19,12 @@
Breadcrumbs, Breadcrumbs,
Button, Button,
Icon, Icon,
IconDetails,
Label, Label,
SearchInput, SearchInput,
Header, Header,
HeaderAdaptive HeaderAdaptive,
IconSettings,
IconDetailsFilled
} from '@hcengineering/ui' } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import view from '@hcengineering/view' import view from '@hcengineering/view'
@ -31,9 +32,11 @@
import { getClient } from '@hcengineering/presentation' import { getClient } from '@hcengineering/presentation'
import { Doc, Ref } from '@hcengineering/core' import { Doc, Ref } from '@hcengineering/core'
import { ActivityMessagesFilter } from '@hcengineering/activity' import { ActivityMessagesFilter } from '@hcengineering/activity'
import workbench from '@hcengineering/workbench'
import { userSearch } from '../index' import { userSearch } from '../index'
import { navigateToSpecial } from '../navigation' import chunter from '../plugin'
import { navigateToSpecial, openChannelInSidebar } from '../navigation'
import ChannelMessagesFilter from './ChannelMessagesFilter.svelte' import ChannelMessagesFilter from './ChannelMessagesFilter.svelte'
export let object: Doc | undefined = undefined export let object: Doc | undefined = undefined
@ -53,6 +56,7 @@
export let filters: Ref<ActivityMessagesFilter>[] = [] export let filters: Ref<ActivityMessagesFilter>[] = []
export let adaptive: HeaderAdaptive = 'default' export let adaptive: HeaderAdaptive = 'default'
export let hideActions: boolean = false export let hideActions: boolean = false
export let canOpenInSidebar: boolean = false
const client = getClient() const client = getClient()
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -131,23 +135,40 @@
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="actions" let:doubleRow> <svelte:fragment slot="actions" let:doubleRow>
<slot name="actions" {doubleRow} /> <slot name="actions" {doubleRow} />
{#if canOpenInSidebar}
<Button
icon={IconDetailsFilled}
iconProps={{ size: 'small' }}
kind={'icon'}
showTooltip={{ label: workbench.string.OpenInSidebar }}
dataId="open-in-sidebar"
on:click={() => {
if (object !== undefined) {
void openChannelInSidebar(object._id, object._class, object, undefined, true)
}
}}
/>
{/if}
{#if canOpen && object} {#if canOpen && object}
<Button <Button
icon={view.icon.Open} icon={view.icon.Open}
iconProps={{ size: 'small' }} iconProps={{ size: 'small' }}
kind={'icon'} kind={'icon'}
showTooltip={{ label: view.string.Open }}
on:click={() => { on:click={() => {
if (object) { if (object !== undefined) {
openDoc(client.getHierarchy(), object) void openDoc(client.getHierarchy(), object)
} }
}} }}
/> />
{/if} {/if}
{#if withAside} {#if withAside}
<Button <Button
icon={IconDetails} icon={IconSettings}
iconProps={{ size: 'medium', filled: isAsideShown }} iconProps={{ size: 'medium' }}
kind={'icon'} kind={'icon'}
dataId="aside-toggle"
showTooltip={{ label: chunter.string.Settings }}
selected={isAsideShown} selected={isAsideShown}
on:click={() => dispatch('aside-toggled')} on:click={() => dispatch('aside-toggled')}
/> />

View File

@ -23,11 +23,9 @@
</script> </script>
{#if tab.data.thread} {#if tab.data.thread}
{#key tab.data.thread}
<div class="root" style:height style:width> <div class="root" style:height style:width>
<ThreadView _id={tab.data.thread} on:close /> <ThreadView _id={tab.data.thread} on:close />
</div> </div>
{/key}
{/if} {/if}
<style lang="scss"> <style lang="scss">

View File

@ -61,7 +61,6 @@ import {
getThreadLink, getThreadLink,
openChannelInSidebar, openChannelInSidebar,
openChannelInSidebarAction, openChannelInSidebarAction,
openChannelInSidebarTabAction,
replyToThread replyToThread
} from './navigation' } from './navigation'
import { import {
@ -211,7 +210,6 @@ export default async (): Promise<Resources> => ({
RemoveChannel: removeChannelAction, RemoveChannel: removeChannelAction,
ReplyToThread: replyToThread, ReplyToThread: replyToThread,
OpenInSidebar: openChannelInSidebarAction, OpenInSidebar: openChannelInSidebarAction,
OpenInSidebarTab: openChannelInSidebarTabAction,
TranslateMessage: translateMessage, TranslateMessage: translateMessage,
ShowOriginalMessage: showOriginalMessage ShowOriginalMessage: showOriginalMessage
} }

View File

@ -276,17 +276,9 @@ export async function openChannelInSidebar (
export async function openChannelInSidebarAction ( export async function openChannelInSidebarAction (
context: DocNotifyContext, context: DocNotifyContext,
_: Event, _: Event,
props?: { object?: Doc, newTab?: boolean }
): Promise<void> {
await openChannelInSidebar(context.objectId, context.objectClass, props?.object, undefined, props?.newTab ?? false)
}
export async function openChannelInSidebarTabAction (
context: DocNotifyContext,
event: Event,
props?: { object?: Doc } props?: { object?: Doc }
): Promise<void> { ): Promise<void> {
await openChannelInSidebarAction(context, event, { newTab: true, object: props?.object }) await openChannelInSidebar(context.objectId, context.objectClass, props?.object, undefined, true)
} }
export async function openThreadInSidebarChannel ( export async function openThreadInSidebarChannel (
@ -326,12 +318,29 @@ export async function openThreadInSidebar (_id: Ref<ActivityMessage>, msg?: Acti
const name = (await getChannelName(object._id, object._class, object)) ?? (await translate(titleIntl, {})) const name = (await getChannelName(object._id, object._class, object)) ?? (await translate(titleIntl, {}))
const tabName = await translate(chunter.string.ThreadIn, { name }) const tabName = await translate(chunter.string.ThreadIn, { name })
const loc = getCurrentLocation() const loc = getCurrentLocation()
const allowedPath = loc.path.join('/')
const currentTAbs = get(sidebarStore).widgetsState.get(widget._id)?.tabs ?? []
const tabsToClose = currentTAbs
.filter((t) => t.isPinned !== true && t.allowedPath === allowedPath && (t as ChatWidgetTab).type === 'thread')
.map((t) => t.id)
if (tabsToClose.length > 0) {
sidebarStore.update((s) => {
const widgetState = s.widgetsState.get(widget._id)
if (widgetState === undefined) return s
const tabs = widgetState.tabs.filter((it) => !tabsToClose.includes(it.id))
s.widgetsState.set(widget._id, { ...widgetState, tabs })
return { ...s }
})
}
const tab: ChatWidgetTab = { const tab: ChatWidgetTab = {
id: 'thread_' + _id, id: 'thread_' + _id,
name: tabName, name: tabName,
icon: chunter.icon.Thread, icon: chunter.icon.Thread,
allowedPath: loc.path.join('/'), allowedPath,
type: 'thread', type: 'thread',
data: { data: {
_id: object?._id, _id: object?._id,

View File

@ -43,5 +43,6 @@
flex: 1; flex: 1;
align-items: center; align-items: center;
background-color: var(--theme-statusbar-color); background-color: var(--theme-statusbar-color);
overflow: hidden;
} }
</style> </style>

View File

@ -239,7 +239,7 @@ export function pinWidgetTab (widget: Widget, tabId: string): void {
if (widgetState === undefined) return if (widgetState === undefined) return
const tabs = widgetState.tabs const tabs = widgetState.tabs
.map((it) => (it.id === tabId ? { ...it, isPinned: true } : it)) .map((it) => (it.id === tabId ? { ...it, isPinned: true, allowedPath: undefined } : it))
.sort((a, b) => (a.isPinned === b.isPinned ? 0 : a.isPinned === true ? -1 : 1)) .sort((a, b) => (a.isPinned === b.isPinned ? 0 : a.isPinned === true ? -1 : 1))
widgetsState.set(widget._id, { ...widgetState, tabs }) widgetsState.set(widget._id, { ...widgetState, tabs })

View File

@ -62,7 +62,7 @@ export class ChannelPage extends CommonPage {
readonly copyLinkButton = (): Locator => this.page.getByRole('button', { name: 'Copy link' }) readonly copyLinkButton = (): Locator => this.page.getByRole('button', { name: 'Copy link' })
readonly deleteMessageButton = (): Locator => this.page.getByRole('button', { name: 'Delete' }) readonly deleteMessageButton = (): Locator => this.page.getByRole('button', { name: 'Delete' })
readonly updateButton = (): Locator => this.page.getByRole('button', { name: 'Update' }) readonly updateButton = (): Locator => this.page.getByRole('button', { name: 'Update' })
readonly openChannelDetails = (): Locator => this.page.locator('.hulyHeader-buttonsGroup > .antiButton') readonly openChannelDetails = (): Locator => this.page.getByTestId('aside-toggle')
readonly changeChannelNameConfirm = (): Locator => this.page.locator('.selectPopup button') readonly changeChannelNameConfirm = (): Locator => this.page.locator('.selectPopup button')
readonly privateOrPublicChangeButton = (change: string, autoJoin: boolean): Locator => readonly privateOrPublicChangeButton = (change: string, autoJoin: boolean): Locator =>
this.page this.page