mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-18 16:31:57 +03:00
Updated the Test Management layout and adaptability (#7234)
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
parent
d9a11e57d2
commit
61f7770a02
@ -277,7 +277,7 @@ module.exports = [
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
meta: {
|
||||
viewport: 'width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=1'
|
||||
viewport: 'width=device-width, initial-scale=1.0'
|
||||
}
|
||||
}),
|
||||
...(prod ? [new CompressionPlugin()] : []),
|
||||
|
@ -350,11 +350,13 @@ function defineTestCase (builder: Builder): void {
|
||||
hiddenKeys: ['title']
|
||||
},
|
||||
config: [
|
||||
{ key: '', displayProps: { fixed: 'left', key: 'lead' } },
|
||||
{
|
||||
key: 'status',
|
||||
props: { kind: 'list', size: 'small', shouldShowName: false }
|
||||
props: { kind: 'list', size: 'small', shouldShowName: false },
|
||||
displayProps: { key: 'status', fixed: 'left' }
|
||||
},
|
||||
{ key: '', displayProps: { fixed: 'left', key: 'lead' } },
|
||||
{ key: '', displayProps: { grow: true } },
|
||||
{ key: 'modifiedOn', displayProps: { key: 'modified', fixed: 'right', dividerBefore: true } },
|
||||
{
|
||||
key: 'assignee',
|
||||
|
@ -127,7 +127,7 @@ p:last-child { margin-block-end: 0; }
|
||||
.p-inline {
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
hyphens: auto;
|
||||
// hyphens: auto;
|
||||
line-height: 150%;
|
||||
|
||||
&.contrast { color: var(--global-primary-TextColor); }
|
||||
|
@ -141,20 +141,38 @@
|
||||
}
|
||||
.antiPanel-navigator {
|
||||
position: relative;
|
||||
background-color: var(--theme-navpanel-color);
|
||||
|
||||
|
||||
&:not(.second) { background-color: var(--theme-navpanel-color); }
|
||||
&:not(.right) {
|
||||
min-width: 12.5rem;
|
||||
max-width: 22.5rem;
|
||||
width: 17.5rem;
|
||||
}
|
||||
&.right {
|
||||
border-radius: var(--medium-BorderRadius);
|
||||
}
|
||||
}
|
||||
&.right { border-radius: var(--medium-BorderRadius); }
|
||||
&.second.float {
|
||||
background-color: var(--theme-navpanel-color);
|
||||
filter: drop-shadow(2px 0 5px rgba(0, 0, 0, .2));
|
||||
z-index: 460;
|
||||
|
||||
&:not(.inner) {
|
||||
position: fixed;
|
||||
top: calc(var(--status-bar-height) + 3.5rem + 1px);
|
||||
height: calc(100% - var(--status-bar-height) - 3.5rem - 2px);
|
||||
border-left: 1px solid var(--theme-divider-color);
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.antiPanel-navigator {
|
||||
&.portrait { left: 0; }
|
||||
&.landscape { left: var(--app-panel-width); }
|
||||
}
|
||||
|
||||
&.inner {
|
||||
position: absolute;
|
||||
top: 3.5rem;
|
||||
left: 0;
|
||||
height: calc(100% - 3.5rem);
|
||||
}
|
||||
}
|
||||
|
||||
&.fly:not(.second) {
|
||||
position: fixed;
|
||||
background-color: var(--theme-navpanel-color);
|
||||
z-index: 450;
|
||||
@ -176,6 +194,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.mobile-theme {
|
||||
.mobile-wrapper,
|
||||
|
@ -326,6 +326,13 @@
|
||||
height: calc(100vh - 4rem);
|
||||
max-width: calc(100vw - 3rem);
|
||||
max-height: calc(100vh - 4rem);
|
||||
|
||||
.mobile-theme & {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
|
@ -41,6 +41,7 @@
|
||||
export let shrink: boolean = false
|
||||
export let divScroll: HTMLElement | undefined | null = undefined
|
||||
export let divBox: HTMLElement | undefined | null = undefined
|
||||
export let scrollSnap: boolean = false
|
||||
export let checkForHeaders: boolean = false
|
||||
export let stickedScrollBars: boolean = false
|
||||
export let thinScrollBars: boolean = false
|
||||
@ -571,6 +572,8 @@
|
||||
class="scroll relative flex-shrink flex-col"
|
||||
style:flex-direction={scrollDirection === 'vertical-reverse' ? 'column-reverse' : 'column'}
|
||||
class:disableOverscroll
|
||||
class:scrollSnapX={scrollSnap && contentDirection === 'horizontal'}
|
||||
class:scrollSnapY={scrollSnap && contentDirection === 'vertical'}
|
||||
style:overflow-x={horizontal ? 'auto' : 'hidden'}
|
||||
on:scroll={() => {
|
||||
if (onScroll) {
|
||||
@ -879,6 +882,16 @@
|
||||
&.disableOverscroll {
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
&.scrollSnapY {
|
||||
scroll-snap-type: y mandatory;
|
||||
}
|
||||
&.scrollSnapX {
|
||||
scroll-snap-type: x mandatory;
|
||||
}
|
||||
&.scrollSnapX,
|
||||
&.scrollSnapY {
|
||||
scroll-padding-inline: var(--spacing-1);
|
||||
}
|
||||
&::-webkit-scrollbar:vertical {
|
||||
display: none;
|
||||
width: 0;
|
||||
|
@ -13,7 +13,8 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { IconSize } from '@hcengineering/ui'
|
||||
import type { IconSize } from '../../types'
|
||||
|
||||
export let size: IconSize = 'small'
|
||||
const fill: string = 'currentColor'
|
||||
</script>
|
@ -13,7 +13,8 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { IconSize } from '@hcengineering/ui'
|
||||
import type { IconSize } from '../../types'
|
||||
|
||||
export let size: IconSize = 'small'
|
||||
const fill: string = 'currentColor'
|
||||
</script>
|
@ -140,7 +140,7 @@
|
||||
updateDeviceSize()
|
||||
|
||||
$: secondRow = checkAdaptiveMatching($deviceInfo.size, 'xs')
|
||||
$: asideFloat = $deviceInfo.navigator.float
|
||||
$: asideFloat = $deviceInfo.aside.float
|
||||
$: asideOpen = $deviceInfo.aside.visible
|
||||
$: appsMini =
|
||||
$deviceInfo.isMobile &&
|
||||
|
@ -242,6 +242,8 @@ export { default as IconCheckmark } from './components/icons/Checkmark.svelte'
|
||||
export { default as IconToDetails } from './components/icons/ToDetails.svelte'
|
||||
export { default as IconHistory } from './components/icons/History.svelte'
|
||||
export { default as IconScribble } from './components/icons/Scribble.svelte'
|
||||
export { default as IconMenuOpen } from './components/icons/MenuOpen.svelte'
|
||||
export { default as IconMenuClose } from './components/icons/MenuClose.svelte'
|
||||
|
||||
export { default as PanelInstance } from './components/PanelInstance.svelte'
|
||||
export { default as Panel } from './components/Panel.svelte'
|
||||
@ -317,7 +319,7 @@ export const deviceOptionsStore = writable<DeviceOptions>({
|
||||
isPortrait: false,
|
||||
isMobile: false,
|
||||
navigator: { visible: true, float: false, direction: 'vertical' },
|
||||
aside: { visible: true },
|
||||
aside: { visible: true, float: false },
|
||||
fontSize: 0,
|
||||
size: null,
|
||||
sizes: { xs: false, sm: false, md: false, lg: false, xl: false, xxl: false },
|
||||
|
@ -381,7 +381,7 @@ export interface DeviceOptions {
|
||||
isPortrait: boolean
|
||||
isMobile: boolean
|
||||
navigator: { visible: boolean, float: boolean, direction: 'vertical' | 'horizontal' }
|
||||
aside: { visible: boolean }
|
||||
aside: { visible: boolean, float: boolean }
|
||||
fontSize: number
|
||||
size: WidthType | null
|
||||
sizes: Record<WidthType, boolean>
|
||||
|
@ -27,7 +27,7 @@
|
||||
</script>
|
||||
|
||||
{#if attachments.length}
|
||||
<Scroller contentDirection={'horizontal'} horizontal gap={'gap-3'}>
|
||||
<Scroller contentDirection={'horizontal'} horizontal gap={'gap-3'} scrollSnap>
|
||||
{#each attachments as attachment}
|
||||
<AttachmentPreview
|
||||
value={attachment}
|
||||
|
@ -109,5 +109,6 @@
|
||||
.content {
|
||||
max-width: 20rem;
|
||||
max-height: 20rem;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
</style>
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Breadcrumbs, Header } from '@hcengineering/ui'
|
||||
import { Breadcrumbs, Header, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
|
||||
import { CalendarMode } from '../index'
|
||||
@ -43,6 +43,7 @@
|
||||
adaptive="autoExtra"
|
||||
doubleRowWidth={350}
|
||||
closeOnEscape={false}
|
||||
topIndent={$deviceInfo.navigator.float && !$deviceInfo.aside.float}
|
||||
on:close
|
||||
>
|
||||
<div class="title">
|
||||
|
@ -170,6 +170,7 @@
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal'
|
||||
? 'portrait'
|
||||
: 'landscape'} border-left"
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
<ChatNavigator {object} {currentSpecial} on:select={handleChannelSelected} />
|
||||
|
@ -56,6 +56,7 @@
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal'
|
||||
? 'portrait'
|
||||
: 'landscape'} border-left will-change-opacity"
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
<div class="hulyNavPanel-header" class:withButton={editable}>
|
||||
|
@ -405,6 +405,7 @@
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal'
|
||||
? 'portrait'
|
||||
: 'landscape'} border-left"
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
<div class="hulyNavPanel-header withButton small">
|
||||
|
@ -264,14 +264,6 @@
|
||||
`
|
||||
|
||||
let frame: HTMLIFrameElement | undefined = undefined
|
||||
const applyStyles = (): void => {
|
||||
const head = frame?.contentDocument?.querySelector('head')
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
||||
if (css !== undefined && head !== undefined && head !== null) {
|
||||
head.appendChild(document.createElement('style')).textContent = css
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
|
||||
$: if (css !== undefined && frame !== undefined && frame !== null) {
|
||||
|
@ -154,6 +154,7 @@
|
||||
? 'portrait'
|
||||
: 'landscape'} border-left"
|
||||
class:border-right={category?.component === undefined}
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
<div class="hulyNavPanel-header">
|
||||
|
@ -133,7 +133,6 @@
|
||||
}
|
||||
return []
|
||||
}
|
||||
$: console.log('[!!!] question: ', question)
|
||||
</script>
|
||||
|
||||
<div class="question-answer-container flex-col flex-gap-3">
|
||||
|
@ -18,7 +18,7 @@
|
||||
import { type Class, type Ref } from '@hcengineering/core'
|
||||
import { TestCase } from '@hcengineering/test-management'
|
||||
import { Panel } from '@hcengineering/panel'
|
||||
import { EditBox } from '@hcengineering/ui'
|
||||
import { EditBox, Breadcrumb } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import testManagement from '../../plugin'
|
||||
|
||||
@ -65,14 +65,17 @@
|
||||
<ActionContext context={{ mode: 'editor' }} />
|
||||
<Panel
|
||||
{object}
|
||||
title={object.name}
|
||||
isHeader={false}
|
||||
isAside={true}
|
||||
isAside={false}
|
||||
isSub={false}
|
||||
adaptive={'default'}
|
||||
adaptive={'disabled'}
|
||||
on:open
|
||||
on:close={() => dispatch('close')}
|
||||
>
|
||||
<svelte:fragment slot="title">
|
||||
<Breadcrumb icon={testManagement.icon.TestCase} title={object.name} size={'large'} isCurrent />
|
||||
</svelte:fragment>
|
||||
|
||||
<EditBox
|
||||
bind:value={rawLabel}
|
||||
placeholder={testManagement.string.NamePlaceholder}
|
||||
|
@ -18,7 +18,7 @@
|
||||
import { TestSuite } from '@hcengineering/test-management'
|
||||
import { StyledTextArea } from '@hcengineering/text-editor-resources'
|
||||
import { Panel } from '@hcengineering/panel'
|
||||
import { EditBox } from '@hcengineering/ui'
|
||||
import { EditBox, Breadcrumb } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
|
||||
import TestCasesList from './TestCasesList.svelte'
|
||||
@ -61,14 +61,17 @@
|
||||
<ActionContext context={{ mode: 'editor' }} />
|
||||
<Panel
|
||||
{object}
|
||||
title={object.name}
|
||||
isHeader={false}
|
||||
isAside={true}
|
||||
isAside={false}
|
||||
isSub={false}
|
||||
adaptive={'default'}
|
||||
adaptive={'disabled'}
|
||||
on:open
|
||||
on:close={() => dispatch('close')}
|
||||
>
|
||||
<svelte:fragment slot="title">
|
||||
<Breadcrumb icon={testManagement.icon.TestSuite} title={object.name} size={'large'} isCurrent />
|
||||
</svelte:fragment>
|
||||
|
||||
<EditBox
|
||||
bind:value={rawLabel}
|
||||
placeholder={testManagement.string.NamePlaceholder}
|
||||
|
@ -29,6 +29,8 @@
|
||||
Header,
|
||||
ButtonIcon,
|
||||
Label,
|
||||
IconMenuOpen,
|
||||
IconMenuClose,
|
||||
deviceOptionsStore as deviceInfo
|
||||
} from '@hcengineering/ui'
|
||||
import { getCurrentAccount, toIdMap, SortingOrder } from '@hcengineering/core'
|
||||
@ -39,8 +41,6 @@
|
||||
import { getNearest } from '../utils'
|
||||
import CreateToDo from './CreateToDo.svelte'
|
||||
import ToDoGroup from './ToDoGroup.svelte'
|
||||
import MenuClose from './icons/MenuClose.svelte'
|
||||
import MenuOpen from './icons/MenuOpen.svelte'
|
||||
import time from '../plugin'
|
||||
|
||||
export let mode: ToDosMode
|
||||
@ -292,7 +292,7 @@
|
||||
<div class="toDos-container">
|
||||
<Header type={'type-panel'} hideSeparator adaptive={'disabled'}>
|
||||
<ButtonIcon
|
||||
icon={$deviceInfo.navigator.visible ? MenuClose : MenuOpen}
|
||||
icon={$deviceInfo.navigator.visible ? IconMenuClose : IconMenuOpen}
|
||||
kind={'tertiary'}
|
||||
size={'small'}
|
||||
pressed={!$deviceInfo.navigator.visible}
|
||||
|
@ -105,6 +105,7 @@
|
||||
|
||||
<div
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal' ? 'portrait' : 'landscape'} border-left"
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
<div class="hulyNavPanel-header">
|
||||
@ -209,7 +210,7 @@
|
||||
float={$deviceInfo.navigator.float ? 'navigator' : true}
|
||||
index={0}
|
||||
disabledWhen={['panel-aside']}
|
||||
color={'var(--theme-navpanel-border)'}
|
||||
color={'var(--theme-divider-color)'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -16,13 +16,11 @@
|
||||
import { Ref, getCurrentAccount } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import task, { Project } from '@hcengineering/task'
|
||||
import { Label, Separator, Scroller, NavItem } from '@hcengineering/ui'
|
||||
import { Label, Separator, Scroller, NavItem, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||
import { ObjectPresenter, TreeNode } from '@hcengineering/view-resources'
|
||||
import { NavFooter, NavHeader } from '@hcengineering/workbench-resources'
|
||||
import time from '../../plugin'
|
||||
|
||||
export let navFloat: boolean = false
|
||||
export let appsDirection: 'vertical' | 'horizontal' = 'horizontal'
|
||||
export let selected: Ref<Project> | undefined = (localStorage.getItem('team_last_mode') as Ref<Project>) ?? undefined
|
||||
|
||||
let projects: Project[] = []
|
||||
@ -41,7 +39,10 @@
|
||||
$: selectedItem = projects.find((pr) => pr._id === selected)
|
||||
</script>
|
||||
|
||||
<div class="antiPanel-navigator {appsDirection === 'horizontal' ? 'portrait' : 'landscape'} border-left">
|
||||
<div
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal' ? 'portrait' : 'landscape'} border-left"
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
<NavHeader label={time.string.TeamPlanner} />
|
||||
|
||||
@ -89,9 +90,9 @@
|
||||
</div>
|
||||
<Separator
|
||||
name={'time'}
|
||||
float={navFloat ? 'navigator' : true}
|
||||
index={0}
|
||||
float={$deviceInfo.navigator.float ? 'navigator' : true}
|
||||
index={1}
|
||||
disabledWhen={['panel-aside']}
|
||||
color={'var(--theme-navpanel-border)'}
|
||||
color={'var(--theme-divider-color)'}
|
||||
/>
|
||||
</div>
|
||||
|
@ -80,6 +80,8 @@
|
||||
}
|
||||
|
||||
$: mobile = $deviceInfo.isMobile
|
||||
$: needCompact =
|
||||
model.filter((m) => m.displayProps?.optional || m.displayProps?.compression || m.displayProps?.suffix).length > 0
|
||||
|
||||
onMount(() => {
|
||||
dispatch('on-mount')
|
||||
@ -191,7 +193,7 @@
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
{#if compactMode}
|
||||
{#if compactMode && needCompact}
|
||||
<div class="panel-trigger" tabindex="-1">
|
||||
<IconCircles size={'small'} />
|
||||
</div>
|
||||
|
@ -22,6 +22,9 @@
|
||||
Breadcrumb,
|
||||
Component,
|
||||
IconAdd,
|
||||
IconMenuOpen,
|
||||
IconMenuClose,
|
||||
ButtonIcon,
|
||||
Header,
|
||||
Separator,
|
||||
showPopup,
|
||||
@ -29,7 +32,8 @@
|
||||
resolvedLocationStore,
|
||||
deviceOptionsStore as deviceInfo,
|
||||
defineSeparators,
|
||||
workbenchSeparators
|
||||
twoPanelsSeparators,
|
||||
resizeObserver
|
||||
} from '@hcengineering/ui'
|
||||
import { Doc, DocumentQuery, Ref, Space, mergeQueries } from '@hcengineering/core'
|
||||
import { IntlString, Asset } from '@hcengineering/platform'
|
||||
@ -48,6 +52,9 @@
|
||||
export let mainComponent: AnyComponent | AnySvelteComponent
|
||||
export let mainComponentProps = {}
|
||||
|
||||
const FLOAT_LIMIT = 760
|
||||
let container: HTMLDivElement
|
||||
|
||||
let locationQuery: DocumentQuery<Doc> = {}
|
||||
let resultQuery: DocumentQuery<Doc> = {}
|
||||
let spaceQuery: DocumentQuery<Doc> = {}
|
||||
@ -67,24 +74,60 @@
|
||||
if (createComponent === undefined) return
|
||||
showPopup(createComponent, { ...createComponentProps, space }, 'top')
|
||||
}
|
||||
defineSeparators('parentsNavigator', workbenchSeparators)
|
||||
|
||||
defineSeparators('parentsNavigator', twoPanelsSeparators)
|
||||
|
||||
const getVisibleNavigator = (): boolean => !(localStorage.getItem('componentNavigator') === 'hidden')
|
||||
let visibleNavigator: boolean = getVisibleNavigator()
|
||||
let floatNavigator: boolean = false
|
||||
|
||||
const toggleNavigator = (): void => {
|
||||
visibleNavigator = !visibleNavigator
|
||||
if (visibleNavigator) {
|
||||
if (!floatNavigator && container.getBoundingClientRect().width < FLOAT_LIMIT) {
|
||||
floatNavigator = true
|
||||
}
|
||||
localStorage.removeItem('componentNavigator')
|
||||
} else localStorage.setItem('componentNavigator', 'hidden')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent-content__container columns">
|
||||
{#if $deviceInfo.navigator.visible}
|
||||
<div
|
||||
bind:this={container}
|
||||
class="hulyComponent-content__container columns relative"
|
||||
use:resizeObserver={(element) => {
|
||||
if (visibleNavigator && !floatNavigator && element.clientWidth < FLOAT_LIMIT) {
|
||||
floatNavigator = true
|
||||
visibleNavigator = false
|
||||
} else if (floatNavigator && element.clientWidth >= FLOAT_LIMIT) {
|
||||
floatNavigator = false
|
||||
visibleNavigator = getVisibleNavigator()
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if visibleNavigator}
|
||||
{#if floatNavigator}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="cover" class:mobile={$deviceInfo.isMobile} on:click={toggleNavigator} />
|
||||
{/if}
|
||||
<div
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal'
|
||||
? 'portrait'
|
||||
: 'landscape'} border-left"
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal' ? 'portrait' : 'landscape'} second"
|
||||
class:float={floatNavigator}
|
||||
class:inner={!$deviceInfo.navigator.float}
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="hulyComponent-content__column">
|
||||
<Header adaptive={'disabled'}>
|
||||
<Breadcrumb icon={navigationComponentIcon} label={navigationComponentLabel} size={'large'} />
|
||||
<Breadcrumb icon={navigationComponentIcon} label={navigationComponentLabel} size={'large'} isCurrent />
|
||||
<svelte:fragment slot="actions">
|
||||
{#if createComponent}
|
||||
<Button
|
||||
icon={IconAdd}
|
||||
kind={'icon'}
|
||||
showTooltip={navigationComponentProps?.createLabel !== undefined
|
||||
? { label: navigationComponentProps.createLabel }
|
||||
: undefined}
|
||||
on:click={() => {
|
||||
showCreateDialog()
|
||||
}}
|
||||
@ -102,24 +145,26 @@
|
||||
</div>
|
||||
<Separator
|
||||
name={'parentsNavigator'}
|
||||
float={$deviceInfo.navigator.float ? 'navigator' : true}
|
||||
float={floatNavigator ? 'navigator' : true}
|
||||
index={0}
|
||||
color={'transparent'}
|
||||
color={'var(--theme-divider-color)'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Separator
|
||||
name={'parentsNavigator'}
|
||||
float={$deviceInfo.navigator.float}
|
||||
index={0}
|
||||
color={'transparent'}
|
||||
separatorSize={0}
|
||||
short
|
||||
/>
|
||||
<Separator name={'parentsNavigator'} float={floatNavigator} index={0} color={'var(--theme-divider-color)'} />
|
||||
{/if}
|
||||
<div class="hulyComponent-content__column">
|
||||
<Header adaptive={'disabled'}>
|
||||
<Breadcrumb icon={mainComponentIcon} label={mainComponentLabel} size={'large'} />
|
||||
<svelte:fragment slot="beforeTitle">
|
||||
<ButtonIcon
|
||||
icon={visibleNavigator ? IconMenuClose : IconMenuOpen}
|
||||
kind={'tertiary'}
|
||||
size={'small'}
|
||||
pressed={!visibleNavigator}
|
||||
on:click={toggleNavigator}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
|
||||
<Breadcrumb icon={mainComponentIcon} label={mainComponentLabel} size={'large'} isCurrent />
|
||||
</Header>
|
||||
<Component
|
||||
is={mainComponent}
|
||||
@ -131,3 +176,19 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.cover {
|
||||
position: fixed;
|
||||
display: block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 10;
|
||||
|
||||
&.mobile {
|
||||
background-color: var(--theme-overlay-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -77,7 +77,8 @@
|
||||
setResolvedLocation,
|
||||
showPopup,
|
||||
TooltipInstance,
|
||||
workbenchSeparators
|
||||
workbenchSeparators,
|
||||
resizeObserver
|
||||
} from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import {
|
||||
@ -631,21 +632,31 @@
|
||||
|
||||
let aside: HTMLElement
|
||||
let cover: HTMLElement
|
||||
let workbenchWidth: number = $deviceInfo.docWidth
|
||||
|
||||
$deviceInfo.navigator.float = !($deviceInfo.docWidth < 1024)
|
||||
$: if ($deviceInfo.docWidth <= 1024 && !$deviceInfo.navigator.float) {
|
||||
$deviceInfo.navigator.visible = false
|
||||
$deviceInfo.navigator.float = true
|
||||
$deviceInfo.navigator.float = !(workbenchWidth < 1024)
|
||||
const checkWorkbenchWidth = (): void => {
|
||||
if (workbenchWidth <= 1024 && !$deviceInfo.navigator.float && $deviceInfo.navigator.visible) {
|
||||
$deviceInfo.navigator.visible = false
|
||||
$deviceInfo.navigator.float = true
|
||||
} else if (workbenchWidth > 1024 && $deviceInfo.navigator.float) {
|
||||
if (getMetadata(workbench.metadata.NavigationExpandedDefault) === undefined) {
|
||||
$deviceInfo.navigator.float = false
|
||||
$deviceInfo.navigator.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
$: if ($deviceInfo.docWidth <= 1024 && !$deviceInfo.aside.float) {
|
||||
$deviceInfo.aside.visible = false
|
||||
} else if ($deviceInfo.docWidth > 1024 && $deviceInfo.navigator.float) {
|
||||
$deviceInfo.aside.float = true
|
||||
} else if ($deviceInfo.docWidth > 1024 && $deviceInfo.aside.float) {
|
||||
if (getMetadata(workbench.metadata.NavigationExpandedDefault) === undefined) {
|
||||
$deviceInfo.navigator.float = false
|
||||
$deviceInfo.navigator.visible = true
|
||||
$deviceInfo.aside.float = false
|
||||
$deviceInfo.aside.visible = true
|
||||
}
|
||||
}
|
||||
const checkOnHide = (): void => {
|
||||
if ($deviceInfo.navigator.visible && $deviceInfo.docWidth <= 1024) $deviceInfo.navigator.visible = false
|
||||
if ($deviceInfo.navigator.visible && workbenchWidth <= 1024) $deviceInfo.navigator.visible = false
|
||||
}
|
||||
let oldNavVisible: boolean = $deviceInfo.navigator.visible
|
||||
let oldASideVisible: boolean = $deviceInfo.aside.visible
|
||||
@ -889,7 +900,14 @@
|
||||
application: currentApplication?._id
|
||||
}}
|
||||
/>
|
||||
<div class="workbench-container inner" class:rounded={$sidebarStore.variant === SidebarVariant.EXPANDED}>
|
||||
<div
|
||||
class="workbench-container inner"
|
||||
class:rounded={$sidebarStore.variant === SidebarVariant.EXPANDED}
|
||||
use:resizeObserver={(element) => {
|
||||
workbenchWidth = element.clientWidth
|
||||
checkWorkbenchWidth()
|
||||
}}
|
||||
>
|
||||
{#if mainNavigator}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
@ -900,6 +918,7 @@
|
||||
class="antiPanel-navigator no-print {$deviceInfo.navigator.direction === 'horizontal'
|
||||
? 'portrait'
|
||||
: 'landscape'} border-left"
|
||||
class:fly={$deviceInfo.navigator.float}
|
||||
>
|
||||
<div class="antiPanel-wrap__content hulyNavPanel-container">
|
||||
{#if currentApplication}
|
||||
@ -996,7 +1015,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if !$deviceInfo.navigator.float}
|
||||
{#if !$deviceInfo.aside.float}
|
||||
{#if $sidebarStore.variant === SidebarVariant.EXPANDED}
|
||||
<Separator name={'main'} index={0} color={'transparent'} separatorSize={0} short />
|
||||
{/if}
|
||||
@ -1004,8 +1023,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
<Dock />
|
||||
<div bind:this={cover} class="cover" />
|
||||
{#if $deviceInfo.navigator.float}
|
||||
{#if $deviceInfo.aside.float}
|
||||
<div
|
||||
class="antiPanel-navigator right no-print {$deviceInfo.navigator.direction === 'horizontal'
|
||||
? 'portrait'
|
||||
@ -1018,6 +1036,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div bind:this={cover} class="cover" />
|
||||
<TooltipInstance />
|
||||
<PanelInstance bind:this={panelInstance} contentPanel={elementPanel}>
|
||||
<svelte:fragment slot="panel-header">
|
||||
|
@ -65,7 +65,7 @@
|
||||
id="sidebar"
|
||||
class="antiPanel-application vertical sidebar-container"
|
||||
class:mini
|
||||
class:float={$deviceInfo.navigator.float}
|
||||
class:float={$deviceInfo.aside.float}
|
||||
>
|
||||
{#if mini}
|
||||
<SidebarMini {widgets} {preferences} />
|
||||
|
@ -22,7 +22,8 @@
|
||||
Location,
|
||||
Header,
|
||||
Breadcrumbs,
|
||||
getCurrentLocation
|
||||
getCurrentLocation,
|
||||
deviceOptionsStore as deviceInfo
|
||||
} from '@hcengineering/ui'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
|
||||
@ -108,6 +109,7 @@
|
||||
hideDescription={true}
|
||||
adaptive="disabled"
|
||||
closeOnEscape={false}
|
||||
topIndent={$deviceInfo.navigator.float && !$deviceInfo.aside.float}
|
||||
on:close={() => {
|
||||
if (widget !== undefined) {
|
||||
closeWidget(widget._id)
|
||||
|
@ -256,7 +256,9 @@ export function createWidgetTab (widget: Widget, tab: WidgetTab, newTab = false)
|
||||
variant: SidebarVariant.EXPANDED
|
||||
})
|
||||
const devInfo = get(deviceInfo)
|
||||
if (devInfo.navigator.float && !devInfo.aside.visible) deviceInfo.set({ ...devInfo, aside: { visible: true } })
|
||||
if (devInfo.aside.float && !devInfo.aside.visible) {
|
||||
deviceInfo.set({ ...devInfo, aside: { visible: true, float: true } })
|
||||
}
|
||||
}
|
||||
|
||||
export function pinWidgetTab (widget: Widget, tabId: string): void {
|
||||
@ -337,7 +339,9 @@ export function minimizeSidebar (closedByUser = false): void {
|
||||
|
||||
sidebarStore.set({ ...state, ...widgetsState, widget: undefined, variant: SidebarVariant.MINI })
|
||||
const devInfo = get(deviceInfo)
|
||||
if (devInfo.navigator.float && devInfo.aside.visible) deviceInfo.set({ ...devInfo, aside: { visible: false } })
|
||||
if (devInfo.navigator.float && devInfo.aside.visible) {
|
||||
deviceInfo.set({ ...devInfo, aside: { visible: false, float: true } })
|
||||
}
|
||||
}
|
||||
|
||||
export function updateTabData (widget: Ref<Widget>, tabId: string, data: Record<string, any>): void {
|
||||
|
@ -548,7 +548,7 @@ test.describe('Channel tests', () => {
|
||||
})
|
||||
|
||||
await test.step('Open general in sidebar too', async () => {
|
||||
await channelPage.makeActionWithChannelInMenu('general', 'Open in sidebar')
|
||||
await channelPage.makeActionWithChannelInMenu('general', 'Open in sidebar', true)
|
||||
await sidebarPage.checkIfSidebarHasVerticalTab(true, data.channelName)
|
||||
await sidebarPage.checkIfSidebarHasVerticalTab(true, 'general')
|
||||
await sidebarPage.checkIfChatSidebarTabIsOpen(true, 'general')
|
||||
@ -606,6 +606,7 @@ test.describe('Channel tests', () => {
|
||||
})
|
||||
|
||||
await test.step('User go to another chat and Sidebar with tread disappears', async () => {
|
||||
await channelPage.appsMenuButton().click()
|
||||
await channelPage.clickChannel('random')
|
||||
await sidebarPage.checkIfSidebarIsOpen(false)
|
||||
})
|
||||
|
@ -302,7 +302,12 @@ export class ChannelPage extends CommonPage {
|
||||
await expect(this.buttonBreadcrumb(channel)).toBeVisible()
|
||||
}
|
||||
|
||||
async makeActionWithChannelInMenu (channelName: string, action: string): Promise<void> {
|
||||
async makeActionWithChannelInMenu (
|
||||
channelName: string,
|
||||
action: string,
|
||||
openNavigator: boolean = false
|
||||
): Promise<void> {
|
||||
if (openNavigator) await this.appsMenuButton().click()
|
||||
await this.channelContainers().filter({ hasText: channelName }).hover()
|
||||
await this.channelContainers().filter({ hasText: channelName }).locator('.hulyNavItem-actions').click()
|
||||
await this.selectFromDropdown(this.page, action)
|
||||
|
@ -91,6 +91,7 @@ export class CommonPage {
|
||||
|
||||
submitButton = (): Locator => this.page.locator('div.date-popup-container button[type="submit"]')
|
||||
buttonBreadcrumb = (hasText?: string): Locator => this.page.locator('button.hulyBreadcrumb-container', { hasText })
|
||||
appsMenuButton = (): Locator => this.page.locator('[id="app-workbench\\:string\\:ShowMenu"]')
|
||||
|
||||
async selectMenuItem (page: Page, name: string, fullWordFilter: boolean = false): Promise<void> {
|
||||
if (name !== 'first') {
|
||||
|
Loading…
Reference in New Issue
Block a user