mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 02:51:54 +03:00
UBER-984: UI fixes, Panel auto resize (#3818)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
1ca3c7ba39
commit
b2576d718f
@ -6,10 +6,11 @@
|
||||
|
||||
<title>Platform</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="icon" type="image/svg+xml" sizes="any" href="favicon.svg">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="favicon_16.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon_32.png">
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="favicon_192.png">
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; overflow: hidden;">
|
||||
|
@ -58,6 +58,7 @@
|
||||
export let readonly = false
|
||||
export let disallowDeselect: Ref<Doc>[] | undefined = undefined
|
||||
export let created: Doc[] = []
|
||||
export let embedded: boolean = false
|
||||
|
||||
let search: string = ''
|
||||
|
||||
@ -158,6 +159,7 @@
|
||||
class:full-width={width === 'full'}
|
||||
class:plainContainer={!shadows}
|
||||
class:width-40={width === 'large'}
|
||||
class:embedded
|
||||
on:keydown={onKeydown}
|
||||
use:resizeObserver={() => {
|
||||
dispatch('changeContent')
|
||||
@ -230,7 +232,7 @@
|
||||
</ListView>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
{#if !embedded}<div class="menu-space" />{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -58,7 +58,7 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<span
|
||||
class:cursor-pointer={!disabled}
|
||||
class:noUnderline
|
||||
class:noUnderline={noUnderline || disabled}
|
||||
class:noOverflow
|
||||
class:inline
|
||||
class:colorInherit
|
||||
@ -71,7 +71,7 @@
|
||||
{:else}
|
||||
<a
|
||||
{href}
|
||||
class:noUnderline
|
||||
class:noUnderline={noUnderline || disabled}
|
||||
class:noOverflow
|
||||
class:inline
|
||||
class:colorInherit
|
||||
|
@ -46,6 +46,7 @@
|
||||
export let create: ObjectCreate | undefined = undefined
|
||||
export let readonly = false
|
||||
export let disallowDeselect: Ref<Doc>[] | undefined = undefined
|
||||
export let embedded: boolean = false
|
||||
|
||||
export let filter: (it: Doc) => boolean = () => {
|
||||
return true
|
||||
@ -108,6 +109,7 @@
|
||||
{create}
|
||||
{readonly}
|
||||
{disallowDeselect}
|
||||
{embedded}
|
||||
on:update
|
||||
on:close
|
||||
on:changeContent
|
||||
|
@ -240,8 +240,7 @@
|
||||
&__aside {
|
||||
width: 25%;
|
||||
min-width: var(--panel-aside-width);
|
||||
border-left: 1px solid var(--theme-divider-color);
|
||||
|
||||
|
||||
&.float {
|
||||
position: absolute;
|
||||
flex-shrink: 0;
|
||||
@ -252,6 +251,7 @@
|
||||
max-width: var(--panel-aside-width);
|
||||
height: 100%;
|
||||
background-color: var(--theme-panel-color);
|
||||
border-left: 1px solid var(--theme-divider-color);
|
||||
border-bottom-right-radius: .45rem;
|
||||
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
|
||||
transition: box-shadow 150ms ease 0s, transform 150ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
|
@ -23,12 +23,15 @@
|
||||
max-width: 17rem;
|
||||
max-height: 22rem;
|
||||
|
||||
background: var(--theme-popup-color);
|
||||
border: 1px solid var(--theme-popup-divider);
|
||||
border-radius: .5rem;
|
||||
box-shadow: var(--theme-popup-shadow);
|
||||
&:not(.embedded) {
|
||||
background: var(--theme-popup-color);
|
||||
border: 1px solid var(--theme-popup-divider);
|
||||
border-radius: .5rem;
|
||||
box-shadow: var(--theme-popup-shadow);
|
||||
}
|
||||
|
||||
&.noShadow {
|
||||
&.noShadow,
|
||||
&.embedded {
|
||||
background: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
import { closePanel, PanelProps, panelstore } from '../panelup'
|
||||
import { fitPopupElement, popupstore } from '../popups'
|
||||
import { deviceOptionsStore as deviceInfo } from '..'
|
||||
import { deviceOptionsStore as deviceInfo, resizeObserver } from '..'
|
||||
import type { AnySvelteComponent, PopupOptions, DeviceOptions } from '../types'
|
||||
import Spinner from './Spinner.svelte'
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
}
|
||||
|
||||
let component: AnySvelteComponent | undefined
|
||||
let keepSize: boolean = false
|
||||
|
||||
let props: PanelProps | undefined
|
||||
function _close () {
|
||||
@ -107,8 +108,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
const checkResize = (el: Element) => {
|
||||
if (props) fitPopup(props, contentPanel)
|
||||
}
|
||||
|
||||
afterUpdate(() => {
|
||||
if (props) fitPopup(props, contentPanel)
|
||||
if (!keepSize && props?.element === 'content' && contentPanel !== undefined) {
|
||||
keepSize = true
|
||||
resizeObserver(contentPanel, checkResize)
|
||||
}
|
||||
})
|
||||
export function fitPopupInstance (): void {
|
||||
if (props) fitPopup(props, contentPanel)
|
||||
|
@ -52,6 +52,7 @@
|
||||
export let size: 'small' | 'medium' | 'large' = 'small'
|
||||
export let onSelect: ((value: ValueType['id']) => void) | undefined = undefined
|
||||
export let showShadow: boolean = true
|
||||
export let embedded: boolean = false
|
||||
|
||||
let search: string = ''
|
||||
|
||||
@ -101,6 +102,7 @@
|
||||
class:noShadow={showShadow === false}
|
||||
class:full-width={width === 'full'}
|
||||
class:max-width-40={width === 'large'}
|
||||
class:embedded
|
||||
use:resizeObserver={() => {
|
||||
dispatch('changeContent')
|
||||
}}
|
||||
@ -179,5 +181,5 @@
|
||||
</ListView>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-space" />
|
||||
{#if !embedded}<div class="menu-space" />{/if}
|
||||
</div>
|
||||
|
@ -26,7 +26,7 @@
|
||||
export let prevElementSize: SeparatedItem | undefined = undefined
|
||||
export let nextElementSize: SeparatedItem | undefined = undefined
|
||||
export let separatorSize: number = 1
|
||||
export let color: string = 'var(--theme-navpanel-border)'
|
||||
export let color: string = 'var(--theme-divider-color)'
|
||||
export let name: string
|
||||
export let index: number // index = -1 ; for custom sizes without saving to a localStorage
|
||||
|
||||
@ -412,7 +412,7 @@
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
z-index: 10;
|
||||
z-index: 402;
|
||||
}
|
||||
&::after {
|
||||
background-color: var(--theme-primary-default);
|
||||
|
@ -132,7 +132,7 @@
|
||||
departmentById={departments}
|
||||
on:selected={(e) => departmentSelected(e.detail)}
|
||||
/>
|
||||
<Separator name={'workbench'} index={0} />
|
||||
<Separator name={'workbench'} index={0} color={'var(--theme-navpanel-border)'} />
|
||||
{/if}
|
||||
|
||||
<div class="antiPanel-component filled">
|
||||
|
@ -139,7 +139,7 @@
|
||||
|
||||
<div class="flex-row-top h-full">
|
||||
{#if visibileNav}
|
||||
<div class="antiPanel-component header border-right aside min-w-100 flex-no-shrink">
|
||||
<div class="antiPanel-component header aside min-w-100 flex-no-shrink">
|
||||
<Tabs
|
||||
bind:selected={selectedTab}
|
||||
model={tabs}
|
||||
|
@ -46,9 +46,9 @@
|
||||
{:else}
|
||||
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
<div class="icon"><Icon icon={recruit.icon.Vacancy} size={'small'} /></div>
|
||||
<span class="label nowrap" class:no-underline={noUnderline || disabled} class:fs-bold={accent}
|
||||
>{value.name}</span
|
||||
>
|
||||
<span class="label nowrap" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
||||
{value.name}
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</DocNavLink>
|
||||
|
@ -10,9 +10,11 @@
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
|
||||
export let value: Task | Task[]
|
||||
export let width: 'medium' | 'large' | 'full' = 'medium'
|
||||
export let placeholder: IntlString
|
||||
export let ofAttribute: Ref<Attribute<Status>>
|
||||
export let _class: Ref<Class<Status>>
|
||||
export let embedded: boolean = false
|
||||
|
||||
const queryOptions: FindOptions<Status> = {
|
||||
lookup: {
|
||||
@ -91,6 +93,8 @@
|
||||
changeStatus(evt.detail === null ? null : evt.detail?._id)
|
||||
}}
|
||||
{placeholder}
|
||||
{width}
|
||||
{embedded}
|
||||
on:changeContent
|
||||
>
|
||||
<svelte:fragment slot="item" let:item>
|
||||
|
@ -31,6 +31,7 @@
|
||||
export let justify: 'left' | 'center' = 'center'
|
||||
export let shouldShowName: boolean = true
|
||||
export let shrink: number = 0
|
||||
export let disabled: boolean = false
|
||||
|
||||
$: state = $statusStore.get(value)
|
||||
let opened: boolean = false
|
||||
@ -50,13 +51,13 @@
|
||||
</script>
|
||||
|
||||
{#if kind === 'list' || kind === 'list-header'}
|
||||
<StatePresenter value={state} {shouldShowName} shouldShowTooltip on:click={handleClick} />
|
||||
<StatePresenter value={state} {shouldShowName} {disabled} shouldShowTooltip on:click={handleClick} />
|
||||
{:else}
|
||||
<Button {kind} {size} {width} {justify} {shrink} on:click={handleClick}>
|
||||
<svelte:fragment slot="content">
|
||||
{#if state}
|
||||
<div class="pointer-events-none clear-mins">
|
||||
<StatePresenter value={state} {shouldShowName} />
|
||||
<StatePresenter value={state} {shouldShowName} {disabled} />
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
@ -32,6 +32,7 @@
|
||||
export let shouldShowName: boolean = true
|
||||
export let shouldShowTooltip: boolean = false
|
||||
export let noUnderline: boolean = false
|
||||
export let shrink: number = 0
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -47,7 +48,12 @@
|
||||
|
||||
{#if value}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="flex-presenter" class:inline-presenter={inline} on:click>
|
||||
<div
|
||||
class="flex-presenter"
|
||||
class:inline-presenter={inline}
|
||||
class:flex-no-shrink={!shouldShowName || shrink === 0}
|
||||
on:click
|
||||
>
|
||||
{#if shouldShowAvatar}
|
||||
<div
|
||||
class="state-container"
|
||||
@ -58,9 +64,9 @@
|
||||
/>
|
||||
{/if}
|
||||
{#if shouldShowName}
|
||||
<span class="overflow-label label" class:nowrap={oneLine} class:no-underline={noUnderline || disabled}
|
||||
>{value.name}</span
|
||||
>
|
||||
<span class="overflow-label label" class:nowrap={oneLine} class:no-underline={noUnderline || disabled}>
|
||||
{value.name}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -28,14 +28,15 @@
|
||||
export let size: ButtonSize = 'medium'
|
||||
export let shouldShowName: boolean = true
|
||||
export let shrink: number = 0
|
||||
export let disabled: boolean = false
|
||||
|
||||
$: state = $statusStore.get(typeof value === 'string' ? value : (value?.values?.[0]?._id as Ref<Status>))
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{#if onChange !== undefined && state !== undefined}
|
||||
<StateEditor value={state._id} {space} {onChange} {kind} {size} {shouldShowName} {shrink} />
|
||||
<StateEditor value={state._id} {space} {onChange} {kind} {size} {shouldShowName} {shrink} {disabled} />
|
||||
{:else}
|
||||
<StatePresenter value={state} {shouldShowName} on:accent-color />
|
||||
<StatePresenter value={state} {shouldShowName} {disabled} {shrink} on:accent-color />
|
||||
{/if}
|
||||
{/if}
|
||||
|
@ -24,7 +24,7 @@
|
||||
export let value: WithLookup<Component> | undefined
|
||||
export let shouldShowAvatar = true
|
||||
export let onClick: (() => void) | undefined = undefined
|
||||
export let disabled = false
|
||||
export let disabled: boolean = false
|
||||
export let inline: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let noUnderline = false
|
||||
|
@ -21,10 +21,12 @@
|
||||
|
||||
export let value: Ref<Component> | AggregateValue | undefined
|
||||
export let kind: 'list' | undefined = undefined
|
||||
export let disabled: boolean = false
|
||||
export let accent: boolean = false
|
||||
|
||||
$: componentValue = $componentStore.get(
|
||||
typeof value === 'string' ? value : (value?.values?.[0]?._id as Ref<Component>)
|
||||
)
|
||||
</script>
|
||||
|
||||
<ComponentPresenter value={componentValue} {kind} on:accent-color />
|
||||
<ComponentPresenter value={componentValue} {kind} {disabled} {accent} on:accent-color />
|
||||
|
@ -37,7 +37,7 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="flex-presenter cursor-default">
|
||||
<div class="flex-presenter">
|
||||
{#if !inline && icon}
|
||||
<Icon {icon} {size} fill={'var(--theme-caption-color)'} />
|
||||
{/if}
|
||||
|
@ -27,7 +27,7 @@
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class="flex-presenter cursor-default" style:color={'inherit'}>
|
||||
<div class="flex-presenter" style:color={'inherit'}>
|
||||
{#if !inline}
|
||||
<IssueStatusIcon {value} {size} {space} on:accent-color />
|
||||
{/if}
|
||||
|
@ -31,6 +31,7 @@
|
||||
"SelectItem": "Select focused item",
|
||||
"SelectItemAll": "Select all items",
|
||||
"SelectItemNone": "Deselect all items",
|
||||
"NumberItems": "{count, plural, =0 {no items} =1 {1 item} other {# items}}",
|
||||
|
||||
"Assigned": "Assigned",
|
||||
"Created": "Created",
|
||||
|
@ -35,6 +35,7 @@
|
||||
"SelectItem": "Выбрать",
|
||||
"SelectItemAll": "Выбрать все",
|
||||
"SelectItemNone": "Снять все выделения",
|
||||
"NumberItems": "{count, plural, =0 {нет объектов} one {# объект} few {# объекта} other {# объектов}}",
|
||||
"Assigned": "Назначенные",
|
||||
"Created": "Созданные",
|
||||
"Subscribed": "Отслеживаемые",
|
||||
|
@ -194,10 +194,10 @@
|
||||
use:resizeObserver={() => dispatch('changeContent')}
|
||||
>
|
||||
{#if $selectionStore.length > 0 || $focusStore.focus !== undefined || (activeAction && activeAction?.actionPopup !== undefined)}
|
||||
<div class="mt-2 ml-2 flex-between">
|
||||
<div class="mt-2 ml-2 flex-between flex-no-shrink">
|
||||
{#if $selectionStore.length > 0}
|
||||
<div class="item-box">
|
||||
{$selectionStore.length} items
|
||||
<Label label={view.string.NumberItems} params={{ count: $selectionStore.length }} />
|
||||
</div>
|
||||
{:else if $focusStore.focus !== undefined}
|
||||
<div class="item-box">
|
||||
@ -205,15 +205,17 @@
|
||||
objectId={$focusStore.focus._id}
|
||||
_class={$focusStore.focus._class}
|
||||
value={$focusStore.focus}
|
||||
props={{ inline: true }}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if activeAction && activeAction?.actionPopup !== undefined}
|
||||
<div class="mt-2 mb-2 mr-2">
|
||||
<div class="mr-2">
|
||||
<Button
|
||||
icon={IconArrowLeft}
|
||||
label={ui.string.Back}
|
||||
kind={'ghost'}
|
||||
size={'small'}
|
||||
on:click={() => {
|
||||
activeAction = undefined
|
||||
}}
|
||||
@ -230,7 +232,8 @@
|
||||
...activeAction.actionProps,
|
||||
value: getSelection($focusStore, $selectionStore),
|
||||
width: 'full',
|
||||
size: 'medium'
|
||||
size: 'medium',
|
||||
embedded: true
|
||||
}}
|
||||
on:close={async () => {
|
||||
activeAction = undefined
|
||||
@ -305,6 +308,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
@ -53,6 +53,6 @@
|
||||
$: if (object !== undefined) getHref(object)
|
||||
</script>
|
||||
|
||||
<NavLink {disabled} {onClick} {noUnderline} {inline} {shrink} {href} {colorInherit} {accent} {noOverflow}
|
||||
><slot /></NavLink
|
||||
>
|
||||
<NavLink {disabled} {onClick} {noUnderline} {inline} {shrink} {href} {colorInherit} {accent} {noOverflow}>
|
||||
<slot />
|
||||
</NavLink>
|
||||
|
@ -26,6 +26,9 @@
|
||||
export let accent: boolean = false
|
||||
export let shouldShowAvatar: boolean = true
|
||||
export let noUnderline: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let shouldShowName: boolean = true
|
||||
export let shrink: number = 0
|
||||
|
||||
const client = getClient()
|
||||
let presenter: AttributeModel | undefined
|
||||
@ -73,7 +76,10 @@
|
||||
{inline}
|
||||
{accent}
|
||||
{shouldShowAvatar}
|
||||
{shouldShowName}
|
||||
{noUnderline}
|
||||
{disabled}
|
||||
{shrink}
|
||||
{...props}
|
||||
on:accent-color
|
||||
on:close
|
||||
|
@ -17,6 +17,24 @@
|
||||
import { ObjectPresenter } from '..'
|
||||
|
||||
export let value: Ref<Space>
|
||||
export let inline: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let shouldShowAvatar: boolean = true
|
||||
export let noUnderline: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let shouldShowName: boolean = true
|
||||
export let shrink: number = 0
|
||||
</script>
|
||||
|
||||
<ObjectPresenter objectId={value} _class={core.class.Space} on:accent-color />
|
||||
<ObjectPresenter
|
||||
objectId={value}
|
||||
_class={core.class.Space}
|
||||
{shouldShowAvatar}
|
||||
{shouldShowName}
|
||||
{disabled}
|
||||
{inline}
|
||||
{noUnderline}
|
||||
{shrink}
|
||||
{accent}
|
||||
on:accent-color
|
||||
/>
|
||||
|
@ -30,6 +30,7 @@
|
||||
export let placeholder: IntlString | undefined
|
||||
export let width: 'medium' | 'large' | 'full' = 'medium'
|
||||
export let size: 'small' | 'medium' | 'large' = 'small'
|
||||
export let embedded: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
@ -133,6 +134,7 @@
|
||||
searchable
|
||||
{width}
|
||||
{size}
|
||||
{embedded}
|
||||
on:changeContent
|
||||
/>
|
||||
{:else if _class !== undefined}
|
||||
@ -149,6 +151,7 @@
|
||||
placeholder={placeholder ?? view.string.Filter}
|
||||
{width}
|
||||
{size}
|
||||
{embedded}
|
||||
on:changeContent
|
||||
>
|
||||
<svelte:fragment slot="item" let:item>
|
||||
|
@ -96,6 +96,7 @@
|
||||
class:collapsed
|
||||
class:subLevel={level !== 0}
|
||||
class:lastCat
|
||||
class:cursor-pointer={items.length > 0}
|
||||
on:focus={() => {
|
||||
mouseOver = true
|
||||
}}
|
||||
@ -131,6 +132,7 @@
|
||||
kind={'list-header'}
|
||||
colorInherit={!$themeStore.dark && level === 0}
|
||||
accent={level === 0}
|
||||
disabled
|
||||
on:accent-color={(evt) => {
|
||||
accentColor = evt.detail
|
||||
}}
|
||||
|
@ -98,7 +98,8 @@ export default mergeIds(viewId, view, {
|
||||
ChooseIcon: '' as IntlString,
|
||||
IconColor: '' as IntlString,
|
||||
IconCategory: '' as IntlString,
|
||||
EmojiCategory: '' as IntlString
|
||||
EmojiCategory: '' as IntlString,
|
||||
NumberItems: '' as IntlString
|
||||
},
|
||||
function: {
|
||||
CreateDocMiddleware: '' as Resource<PresentationMiddlewareCreator>
|
||||
|
@ -723,7 +723,7 @@
|
||||
{/if}
|
||||
</NavFooter>
|
||||
</div>
|
||||
<Separator name={'workbench'} index={0} />
|
||||
<Separator name={'workbench'} index={0} color={'var(--theme-navpanel-border)'} />
|
||||
{/if}
|
||||
<div
|
||||
class="antiPanel-component antiComponent"
|
||||
|
Loading…
Reference in New Issue
Block a user