mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +03:00
Adaptive aSide in Settings (#7130)
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
parent
97412400ff
commit
ad54f56f4c
@ -38,7 +38,7 @@ import {
|
||||
import templates from '@hcengineering/templates'
|
||||
import setting from './plugin'
|
||||
|
||||
import workbench from '@hcengineering/model-workbench'
|
||||
import workbench, { WidgetType } from '@hcengineering/model-workbench'
|
||||
import { type AnyComponent } from '@hcengineering/ui/src/types'
|
||||
|
||||
export { settingId } from '@hcengineering/setting'
|
||||
@ -133,6 +133,18 @@ export function createModel (builder: Builder): void {
|
||||
TSpaceTypeCreator
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
workbench.class.Widget,
|
||||
core.space.Model,
|
||||
{
|
||||
label: setting.string.Settings,
|
||||
type: WidgetType.Flexible,
|
||||
icon: setting.icon.Setting,
|
||||
component: setting.component.SettingsWidget
|
||||
},
|
||||
setting.ids.SettingsWidget
|
||||
)
|
||||
|
||||
builder.mixin(setting.class.Integration, core.class.Class, notification.mixin.ClassCollaborators, {
|
||||
fields: ['modifiedBy']
|
||||
})
|
||||
|
@ -46,7 +46,8 @@ export default mergeIds(settingId, setting, {
|
||||
InviteSetting: '' as AnyComponent,
|
||||
ArrayEditor: '' as AnyComponent,
|
||||
IntegrationPanel: '' as AnyComponent,
|
||||
Configure: '' as AnyComponent
|
||||
Configure: '' as AnyComponent,
|
||||
SettingsWidget: '' as AnyComponent
|
||||
},
|
||||
category: {
|
||||
Settings: '' as Ref<ActionCategory>
|
||||
|
@ -41,7 +41,8 @@ import workbench from './plugin'
|
||||
|
||||
export { workbenchId } from '@hcengineering/workbench'
|
||||
export { workbenchOperation } from './migration'
|
||||
export type { Application }
|
||||
export type { Application, Widget }
|
||||
export { WidgetType } from '@hcengineering/workbench'
|
||||
|
||||
@Model(workbench.class.Application, core.class.Doc, DOMAIN_MODEL)
|
||||
@UX(workbench.string.Application)
|
||||
|
@ -62,6 +62,7 @@
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
&__container {
|
||||
justify-content: stretch;
|
||||
height: 100%;
|
||||
}
|
||||
&__container:not(.columns),
|
||||
|
@ -282,4 +282,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.short .hulyTableAttr-content.withTitle {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
.hulyTableAttr-content__wrapper:empty { display: none; }
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
export let padding: string | undefined = undefined
|
||||
export let hidden: boolean = false
|
||||
export let allowFullsize: boolean = false
|
||||
export let noTopIndent: boolean = false
|
||||
export let hideFooter: boolean = false
|
||||
export let adaptive: 'default' | 'freezeActions' | 'doubleRow' | 'disabled' = 'disabled'
|
||||
export let showCancelButton: boolean = true
|
||||
@ -56,7 +57,7 @@
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
|
||||
<div class="hulyModal-container {type}" class:hidden>
|
||||
<div class="hulyModal-container {type}" class:hidden class:noTopIndent>
|
||||
<Header
|
||||
{type}
|
||||
{allowFullsize}
|
||||
|
@ -164,6 +164,11 @@ export const settingsSeparators: DefSeparators = [
|
||||
{ minSize: 19, size: 30, maxSize: 32, float: 'aside' }
|
||||
]
|
||||
|
||||
export const twoPanelsSeparators: DefSeparators = [
|
||||
{ minSize: 12.5, size: 17.5, maxSize: 22.5, float: 'navigator' },
|
||||
null
|
||||
]
|
||||
|
||||
export const mainSeparators: DefSeparators = [
|
||||
{ minSize: 30, size: 'auto', maxSize: 'auto' },
|
||||
{ minSize: 25, size: 30, maxSize: 80, float: 'sidebar' }
|
||||
|
@ -35,7 +35,7 @@
|
||||
resolvedLocationStore,
|
||||
Scroller,
|
||||
Separator,
|
||||
settingsSeparators
|
||||
twoPanelsSeparators
|
||||
} from '@hcengineering/ui'
|
||||
|
||||
import notification from '../../plugin'
|
||||
@ -93,7 +93,7 @@
|
||||
unsubscribeTypeSetting()
|
||||
unsubscribeProviderSetting()
|
||||
})
|
||||
defineSeparators('notificationSettings', settingsSeparators)
|
||||
defineSeparators('notificationSettings', twoPanelsSeparators)
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent">
|
||||
|
@ -26,7 +26,9 @@
|
||||
getEventPositionElement,
|
||||
showPopup,
|
||||
IconSettings,
|
||||
ModernButton
|
||||
ModernButton,
|
||||
resizeObserver,
|
||||
deviceWidths
|
||||
} from '@hcengineering/ui'
|
||||
import { ObjectPresenter } from '@hcengineering/view-resources'
|
||||
import settings from '../plugin'
|
||||
@ -144,7 +146,13 @@
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
<div class="hulyTableAttr-container">
|
||||
<div
|
||||
class="hulyTableAttr-container"
|
||||
use:resizeObserver={(el) => {
|
||||
if (el.clientWidth < deviceWidths[0] && !el.classList.contains('short')) el.classList.add('short')
|
||||
else if (el.clientWidth >= deviceWidths[0] && el.classList.contains('short')) el.classList.remove('short')
|
||||
}}
|
||||
>
|
||||
<div class="hulyTableAttr-header font-medium-12" class:withButton={showHierarchy}>
|
||||
{#if showHierarchy}
|
||||
<ModernButton icon={IconSettings} kind={'secondary'} size={'small'} {disabled} hasMenu>
|
||||
|
@ -27,7 +27,7 @@
|
||||
Header,
|
||||
Breadcrumb,
|
||||
defineSeparators,
|
||||
settingsSeparators,
|
||||
twoPanelsSeparators,
|
||||
Separator,
|
||||
NavGroup
|
||||
} from '@hcengineering/ui'
|
||||
@ -97,7 +97,7 @@
|
||||
$: if (ofClass !== undefined && _class !== undefined && !client.getHierarchy().isDerived(_class, ofClass)) {
|
||||
_class = ofClass
|
||||
}
|
||||
defineSeparators('workspaceSettings', settingsSeparators)
|
||||
defineSeparators('workspaceSettings', twoPanelsSeparators)
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent">
|
||||
|
@ -35,6 +35,7 @@
|
||||
export let attribute: AnyAttribute
|
||||
export let exist: boolean
|
||||
export let disabled: boolean = true
|
||||
export let noTopIndent: boolean = false
|
||||
|
||||
let name: string
|
||||
let type: Type<PropertyType> | undefined = attribute.type
|
||||
@ -133,9 +134,8 @@
|
||||
okLabel={presentation.string.Save}
|
||||
okAction={save}
|
||||
canSave={!(name === undefined || name.trim().length === 0) && !disabled}
|
||||
onCancel={() => {
|
||||
clearSettingsStore()
|
||||
}}
|
||||
onCancel={clearSettingsStore}
|
||||
{noTopIndent}
|
||||
>
|
||||
<svelte:fragment slot="actions">
|
||||
{#if !disabled}
|
||||
|
@ -27,7 +27,7 @@
|
||||
Scroller,
|
||||
Separator,
|
||||
defineSeparators,
|
||||
settingsSeparators,
|
||||
twoPanelsSeparators,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
import { showMenu } from '@hcengineering/view-resources'
|
||||
@ -51,7 +51,7 @@
|
||||
showPopup(setting.component.EditEnum, { title: setting.string.CreateEnum }, 'top')
|
||||
}
|
||||
|
||||
defineSeparators('workspaceSettings', settingsSeparators)
|
||||
defineSeparators('workspaceSettings', twoPanelsSeparators)
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent">
|
||||
|
@ -17,7 +17,8 @@
|
||||
import { AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
|
||||
import login, { loginId } from '@hcengineering/login'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import presentation, { closeClient, createQuery } from '@hcengineering/presentation'
|
||||
import presentation, { closeClient, getClient, createQuery } from '@hcengineering/presentation'
|
||||
import settingPlg from '../plugin'
|
||||
import setting, { SettingsCategory, SettingsEvents } from '@hcengineering/setting'
|
||||
import {
|
||||
Component,
|
||||
@ -35,13 +36,18 @@
|
||||
settingsSeparators,
|
||||
showPopup,
|
||||
type AnyComponent,
|
||||
deviceOptionsStore as deviceInfo
|
||||
deviceOptionsStore as deviceInfo,
|
||||
resizeObserver,
|
||||
deviceWidths
|
||||
} from '@hcengineering/ui'
|
||||
import { NavFooter } from '@hcengineering/workbench-resources'
|
||||
import { closeWidget, NavFooter, openWidget, minimizeSidebar } from '@hcengineering/workbench-resources'
|
||||
import workbench from '@hcengineering/workbench'
|
||||
import { ComponentType, onDestroy, onMount } from 'svelte'
|
||||
import { clearSettingsStore, settingsStore, type SettingsStore } from '../store'
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
|
||||
const client = getClient()
|
||||
|
||||
let category: SettingsCategory | undefined
|
||||
let categoryId: string = ''
|
||||
|
||||
@ -122,11 +128,26 @@
|
||||
return ss.component === undefined ? null : ss.component
|
||||
}
|
||||
$: asideComponent = updatedStore($settingsStore)
|
||||
let moveASide: boolean = false
|
||||
const widget = client.getModel().findAllSync(workbench.class.Widget, { _id: settingPlg.ids.SettingsWidget })[0]
|
||||
$: if (moveASide && asideComponent != null) {
|
||||
openWidget(widget, { component: asideComponent, ...asideProps }, { active: true, openedByUser: true })
|
||||
$deviceInfo.aside.visible = true
|
||||
} else if ((moveASide && asideComponent == null) || (!moveASide && asideComponent != null)) {
|
||||
closeWidget(widget._id)
|
||||
minimizeSidebar()
|
||||
}
|
||||
|
||||
defineSeparators('setting', settingsSeparators)
|
||||
</script>
|
||||
|
||||
<div class="hulyPanels-container">
|
||||
<div
|
||||
class="hulyPanels-container"
|
||||
use:resizeObserver={(el) => {
|
||||
if (el.clientWidth < deviceWidths[2] && !moveASide) moveASide = true
|
||||
else if (el.clientWidth >= deviceWidths[2] && moveASide) moveASide = false
|
||||
}}
|
||||
>
|
||||
{#if $deviceInfo.navigator.visible}
|
||||
<div
|
||||
class="antiPanel-navigator {$deviceInfo.navigator.direction === 'horizontal'
|
||||
@ -208,7 +229,7 @@
|
||||
<Component is={category.component} props={{ kind: 'content' }} />
|
||||
{/if}
|
||||
</div>
|
||||
{#if asideComponent != null}
|
||||
{#if asideComponent != null && !moveASide}
|
||||
<Separator name={'setting'} index={1} color={'transparent'} separatorSize={0} short />
|
||||
<div class="hulySidePanel-container">
|
||||
{#key asideProps}
|
||||
|
@ -0,0 +1,32 @@
|
||||
<!--
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { WidgetState } from '@hcengineering/workbench-resources'
|
||||
import { type AnyComponent, Component } from '@hcengineering/ui'
|
||||
import { ComponentType } from 'svelte'
|
||||
|
||||
export let widgetState: WidgetState | undefined
|
||||
|
||||
$: asideProps = widgetState?.data
|
||||
$: asideComponent = asideProps?.component as AnyComponent | ComponentType
|
||||
</script>
|
||||
|
||||
{#key asideProps}
|
||||
{#if typeof asideComponent === 'string'}
|
||||
<Component is={asideComponent} props={{ ...asideProps, noTopIndent: true }} />
|
||||
{:else}
|
||||
<svelte:component this={asideComponent} {...asideProps} noTopIndent />
|
||||
{/if}
|
||||
{/key}
|
@ -58,6 +58,7 @@ import RefEditor from './components/typeEditors/RefEditor.svelte'
|
||||
import RoleAssignmentEditor from './components/typeEditors/RoleAssignmentEditor.svelte'
|
||||
import StringTypeEditor from './components/typeEditors/StringTypeEditor.svelte'
|
||||
import WorkspaceSettings from './components/WorkspaceSettings.svelte'
|
||||
import SettingsWidget from './components/SettingsWidget.svelte'
|
||||
import setting from './plugin'
|
||||
import { filterDescendants, getOwnerFirstName, getOwnerLastName, getOwnerPosition, getValue } from './utils'
|
||||
|
||||
@ -121,7 +122,8 @@ export default async (): Promise<Resources> => ({
|
||||
SpaceTypePropertiesSectionEditor,
|
||||
SpaceTypeRolesSectionEditor,
|
||||
RoleEditor,
|
||||
RoleAssignmentEditor
|
||||
RoleAssignmentEditor,
|
||||
SettingsWidget
|
||||
},
|
||||
actionImpl: {
|
||||
DeleteMixin
|
||||
|
@ -13,12 +13,17 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type Ref } from '@hcengineering/core'
|
||||
import type { IntlString } from '@hcengineering/platform'
|
||||
import { mergeIds } from '@hcengineering/platform'
|
||||
import setting, { settingId } from '@hcengineering/setting'
|
||||
import { type AnyComponent } from '@hcengineering/ui'
|
||||
import { type Widget } from '@hcengineering/workbench'
|
||||
|
||||
export default mergeIds(settingId, setting, {
|
||||
ids: {
|
||||
SettingsWidget: '' as Ref<Widget>
|
||||
},
|
||||
component: {
|
||||
EditEnum: '' as AnyComponent,
|
||||
ManageSpaceTypes: '' as AnyComponent,
|
||||
|
@ -17,7 +17,7 @@
|
||||
Breadcrumb,
|
||||
Separator,
|
||||
defineSeparators,
|
||||
settingsSeparators,
|
||||
twoPanelsSeparators,
|
||||
Scroller
|
||||
} from '@hcengineering/ui'
|
||||
import { getActions as getContributedActions, TreeItem, TreeNode } from '@hcengineering/view-resources'
|
||||
@ -147,7 +147,7 @@
|
||||
}
|
||||
|
||||
let space: Ref<TemplateCategory> | undefined = undefined
|
||||
defineSeparators('workspaceSettings', settingsSeparators)
|
||||
defineSeparators('workspaceSettings', twoPanelsSeparators)
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent">
|
||||
|
@ -79,7 +79,7 @@
|
||||
overflow: hidden;
|
||||
flex-direction: row;
|
||||
min-width: 25rem;
|
||||
border-radius: var(--medium-BorderRadius);
|
||||
border-radius: 0 var(--medium-BorderRadius) var(--medium-BorderRadius) 0;
|
||||
|
||||
&.mini:not(.float) {
|
||||
width: 3.5rem !important;
|
||||
@ -89,6 +89,9 @@
|
||||
&.mini.float {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
&.float > :global(.sidebar-content) {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.sidebar-container {
|
||||
|
@ -96,7 +96,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="content">
|
||||
<div class="sidebar-content">
|
||||
{#if widget?.component}
|
||||
<div class="component" use:resizeObserver={resize}>
|
||||
{#if widget.headerLabel}
|
||||
@ -145,7 +145,7 @@
|
||||
<WidgetsBar {widgets} {preferences} selected={widgetId} />
|
||||
|
||||
<style lang="scss">
|
||||
.content {
|
||||
.sidebar-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
@ -334,6 +334,8 @@ 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 } })
|
||||
}
|
||||
|
||||
export function updateTabData (widget: Ref<Widget>, tabId: string, data: Record<string, any>): void {
|
||||
|
@ -12,7 +12,7 @@ export class SidebarPage extends CommonPage {
|
||||
}
|
||||
|
||||
sidebar = (): Locator => this.page.locator('#sidebar')
|
||||
content = (): Locator => this.sidebar().locator('.content')
|
||||
content = (): Locator => this.sidebar().locator('.sidebar-content')
|
||||
contentHeaderByTitle = (title: string): Locator =>
|
||||
this.content().locator(`.hulyHeader-titleGroup:has-text("${title}")`)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user