diff --git a/packages/theme/styles/_layouts.scss b/packages/theme/styles/_layouts.scss index bfaa5f08d3..c7803099ce 100644 --- a/packages/theme/styles/_layouts.scss +++ b/packages/theme/styles/_layouts.scss @@ -360,6 +360,7 @@ input.search { color: var(--theme-content-color); } } + &.colorInherit .label { color: inherit; } } .flex-presenter { display: flex; diff --git a/packages/theme/styles/_vars.scss b/packages/theme/styles/_vars.scss index 1446c6bc14..97df9737e3 100644 --- a/packages/theme/styles/_vars.scss +++ b/packages/theme/styles/_vars.scss @@ -24,6 +24,7 @@ --spacing-1_5: 0.75rem; --spacing-1_75: 0.875rem; --spacing-2: 1rem; + --spacing-2_25: 1.125rem; --spacing-2_5: 1.25rem; --spacing-2_75: 1.375rem; --spacing-3: 1.5rem; diff --git a/packages/theme/styles/common.scss b/packages/theme/styles/common.scss index 7788060e7b..abc02541ee 100644 --- a/packages/theme/styles/common.scss +++ b/packages/theme/styles/common.scss @@ -315,7 +315,7 @@ } .antiNav-divider { flex-shrink: 0; - margin: .5rem 0; + margin: .75rem 0; height: 1px; &.line { background-color: var(--theme-navpanel-divider); } diff --git a/packages/theme/styles/components.scss b/packages/theme/styles/components.scss index 914ed75f87..9a7e0fae41 100644 --- a/packages/theme/styles/components.scss +++ b/packages/theme/styles/components.scss @@ -747,7 +747,7 @@ &:is(.small, .large) .hulyAccordionItem-header__chevron > * { transform: rotate(90deg); } - } + } } .hulyAccordionItem-content { overflow: hidden; diff --git a/packages/theme/styles/panel.scss b/packages/theme/styles/panel.scss index eb04ec1cdf..70a496e7b4 100644 --- a/packages/theme/styles/panel.scss +++ b/packages/theme/styles/panel.scss @@ -39,12 +39,10 @@ button.type-link { width: 100%; } } .hulyNavPanel-container .hulyNavItem-container, -.hulyNavPanel-container .hulyTaskNavLink-container { +.hulyNavPanel-container .hulyTaskNavLink-container, +.parentSelector .hulyNavItem-container { margin: 0 0.75rem; } -.hulyNavPanel-container .hulyNavItem-container + .hulyAccordionItem-container { - margin-top: 0.75rem; -} .hulyNavPanel-header { display: flex; justify-content: space-between; @@ -65,6 +63,156 @@ } &.small { padding-bottom: .75rem; } } + +.hulyNavGroup-container { + display: flex; + flex-direction: column; + flex-shrink: 0; + width: 100%; + min-width: 0; + min-height: 0; + + .hulyNavGroup-header { + display: flex; + justify-content: space-between; + align-items: center; + flex-shrink: 0; + margin: 0; + padding: var(--spacing-1) var(--spacing-2_25) var(--spacing-1) var(--spacing-2); + min-height: var(--global-medium-Size); + border: none; + outline: none; + + &.disabled { cursor: default; } + &__chevron, + &__arrow, + &__icon { + display: flex; + justify-content: center; + align-items: center; + flex-shrink: 0; + } + &__chevron { + margin: 0 0.125rem; + width: 1.25rem; + height: 1.25rem; + color: var(--global-disabled-TextColor); + border: 1px solid transparent; + border-radius: var(--extra-small-BorderRadius); + + & > * { + transform-origin: center; + transform: rotate(0deg); + transition: transform 0.1s ease-in-out; + } + &.collapsed > * { transform: rotate(-90deg); } + } + &__icon { + margin: 0 0.125rem; + width: 1.5rem; + height: 1.5rem; + color: var(--global-primary-TextColor); + background-color: var(--theme-navpanel-selected); + border: 1px solid var(--global-subtle-ui-BorderColor); + border-radius: var(--extra-small-BorderRadius); + + &.folder { + background-color: var(--theme-statusbar-color); + border-color: var(--global-surface-01-BorderColor); + } + } + &__label { + display: inline-flex; + align-items: center; + gap: var(--spacing-0_5); + padding: var(--spacing-0_25) var(--spacing-0_5); + min-width: 0; + text-transform: uppercase; + color: var(--global-tertiary-TextColor); + border-radius: var(--extra-small-BorderRadius); + } + &__tools { + display: none; + align-items: center; + flex-shrink: 0; + gap: var(--spacing-0_5); + margin-left: var(--spacing-1); + min-width: 0; + max-width: 50%; + } + &__arrow { + margin-left: var(--spacing-0_5); + width: var(--global-min-Size); + height: var(--global-min-Size); + color: var(--global-accent-IconColor); + } + + &.showMenu, + &.highlighted, + &.selected, + &:hover { + .hulyNavGroup-header__tools { display: flex; } + } + &.showMenu, + &.highlighted, + &.selected { + .hulyNavGroup-header__label { background-color: var(--global-ui-BackgroundColor); } + .hulyNavGroup-header__chevron { color: var(--global-tertiary-TextColor); } + .hulyNavGroup-header__label { color: var(--global-secondary-TextColor); } + } + &.selected { background-color: var(--global-ui-highlight-BackgroundColor); } + &.isOpen + .hulyNavGroup-content { + max-height: 100%; + + &:not(:has(.nested)) { margin-bottom: var(--spacing-1_5); } + } + } + &.nested .hulyNavGroup-header { + .hulyNavGroup-header__icon { margin: 0 var(--spacing-0_25) 0 0; } + .hulyNavGroup-header__label { padding: 0 var(--spacing-0_75) 0 0; } + &.isOpen .hulyNavGroup-header__label { background-color: var(--global-ui-BackgroundColor); } + } + .hulyNavGroup-header:hover, + &.nested .hulyNavGroup-header:hover { + .hulyNavGroup-header__chevron { background-color: var(--global-ui-BackgroundColor); } + .hulyNavGroup-header__label { background-color: var(--global-ui-hover-BackgroundColor); } + .hulyNavGroup-header__chevron { color: var(--button-subtle-IconColor); } + .hulyNavGroup-header__label { color: var(--global-primary-TextColor); } + } + &.nested.selectable .hulyNavGroup-header { + margin: 0 var(--spacing-1_5) var(--spacing-1_5); + padding: var(--spacing-0_5) var(--spacing-0_75) var(--spacing-0_5) var(--spacing-0_5); + min-height: var(--global-small-Size); + border-radius: var(--small-BorderRadius); + + &.selected { padding-right: var(--spacing-0_75); } + &.isOpen { margin-bottom: 0; } + } + + &:not(.nested, .noDivider), + &.noDivider + &.noDivider { border-top: 1px solid var(--theme-navpanel-divider); } + + .hulyNavGroup-content { + overflow: hidden; + display: flex; + flex-direction: column; + padding: 0; + min-width: 0; + max-height: 0; + } +} +.hulyNavItem-container + .hulyNavGroup-container, +.hulyNavPanel-container a.noUnderline + .hulyNavGroup-container { margin-top: .75rem; } + +.hulyNavItem-container .hulyNavItem-chevron:enabled { + & > * { + transform-origin: center; + transform: rotate(-90deg); + transition: transform 0.1s ease-in-out; + } + &.isOpen > * { transform: rotate(0deg); } +} + .hulySidePanel-container { display: flex; flex-direction: column; diff --git a/packages/ui/src/components/ButtonBase.svelte b/packages/ui/src/components/ButtonBase.svelte index 5b3fba81e5..09862cadf1 100644 --- a/packages/ui/src/components/ButtonBase.svelte +++ b/packages/ui/src/components/ButtonBase.svelte @@ -49,6 +49,7 @@ } else if (type === 'type-button' && !hasMenu) { actualIconSize = 'medium' } + $: iconOnly = title === undefined && label === undefined && $$slots.default === undefined && icon !== undefined export function focus () { element?.focus() @@ -94,6 +95,7 @@ class:inheritColor class:inheritFont class:menu={hasMenu} + class:iconOnly disabled={loading || disabled} use:tp={tooltip} on:click|stopPropagation @@ -153,9 +155,10 @@ height: var(--global-large-Size); border-radius: var(--medium-BorderRadius); - &.type-button { + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-2); } + &.iconOnly, &.type-button-icon { width: var(--global-large-Size); } @@ -164,9 +167,10 @@ height: var(--global-medium-Size); border-radius: var(--medium-BorderRadius); - &.type-button { + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-2); } + &.iconOnly, &.type-button-icon { width: var(--global-medium-Size); } @@ -176,9 +180,10 @@ gap: var(--spacing-0_5); border-radius: var(--small-BorderRadius); - &.type-button { + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-1); } + &.iconOnly, &.type-button-icon { width: var(--global-small-Size); } @@ -187,9 +192,10 @@ height: var(--global-extra-small-Size); border-radius: var(--extra-small-BorderRadius); - &.type-button { + &.type-button:not(.iconOnly) { padding: 0 var(--spacing-1); } + &.iconOnly, &.type-button-icon { width: var(--global-extra-small-Size); } diff --git a/packages/ui/src/components/ButtonIcon.svelte b/packages/ui/src/components/ButtonIcon.svelte index 27a426e49a..ab54451810 100644 --- a/packages/ui/src/components/ButtonIcon.svelte +++ b/packages/ui/src/components/ButtonIcon.svelte @@ -30,6 +30,7 @@ export let inheritColor: boolean = false export let tooltip: LabelAndProps | undefined = undefined export let focusIndex = -1 + export let id: string | undefined = undefined let element: ButtonBase | undefined @@ -53,6 +54,7 @@ {hasMenu} {tooltip} {focusIndex} + {id} on:click on:keydown /> diff --git a/packages/ui/src/components/ButtonMenu.svelte b/packages/ui/src/components/ButtonMenu.svelte index 151cd70df2..e696436f08 100644 --- a/packages/ui/src/components/ButtonMenu.svelte +++ b/packages/ui/src/components/ButtonMenu.svelte @@ -16,7 +16,7 @@ import type { Asset, IntlString } from '@hcengineering/platform' import { deepEqual } from 'fast-equals' import { ComponentType, createEventDispatcher } from 'svelte' - import { closePopup, showPopup } from '..' + import { closePopup, showPopup, type LabelAndProps, closeTooltip } from '..' import { AnySvelteComponent, DropdownIntlItem } from '../types' import ButtonBase from './ButtonBase.svelte' import ModernPopup from './ModernPopup.svelte' @@ -32,6 +32,8 @@ export let loading: boolean = false export let inheritColor: boolean = false export let noSelection: boolean = false + export let autoSelectionIfOne: boolean = false + export let tooltip: LabelAndProps | undefined = undefined export let items: DropdownIntlItem[] export let params: Record = {} @@ -46,7 +48,13 @@ function openPopup () { if (!opened) { + if (autoSelectionIfOne && items.length === 1) { + selected = items[0].id + dispatch('selected', selected) + return + } opened = true + closeTooltip() showPopup(ModernPopup, { items, selected: noSelection ? undefined : selected, params }, element, (result) => { if (result) { selected = result @@ -86,5 +94,6 @@ pressed={opened} {focusIndex} {id} + {tooltip} on:click={openPopup} /> diff --git a/packages/ui/src/components/Fold.svelte b/packages/ui/src/components/Fold.svelte index 225630ae4b..cf21229547 100644 --- a/packages/ui/src/components/Fold.svelte +++ b/packages/ui/src/components/Fold.svelte @@ -15,10 +15,10 @@ -
+
{#if empty} diff --git a/packages/ui/src/components/NavGroup.svelte b/packages/ui/src/components/NavGroup.svelte index 03364365e6..8ead2b7d2d 100644 --- a/packages/ui/src/components/NavGroup.svelte +++ b/packages/ui/src/components/NavGroup.svelte @@ -13,58 +13,119 @@ // limitations under the License. --> -
- {/if} -
- - + + +
+ {#if visibleIcon} +
+ +
+ {/if} {#if label} + {#if actions.length > 0} + + {/if}
- {#if isFold}
{/if} +
+ {#if $$slots.extra}{/if} {#if tools || $$slots.tools} -
+
{#if tools}
{/if} + {#if selected && type === 'nested-selectable'} +
+ {/if} -
- -
+ {#if !empty} +
+ {#if (!isOpen && visible) || forciblyСollapsed} + + {:else} + + {/if} +
+ {/if}
diff --git a/packages/ui/src/components/NavItem.svelte b/packages/ui/src/components/NavItem.svelte index 9ced70118b..c22ce2e7de 100644 --- a/packages/ui/src/components/NavItem.svelte +++ b/packages/ui/src/components/NavItem.svelte @@ -14,9 +14,23 @@ --> + {/if} - {#if icon || (type === 'type-tag' && color)} + {#if visibleIcon || (type === 'type-tag' && color)}
- {#if type !== 'type-tag' && icon} - + {#if type !== 'type-tag' && visibleIcon} + {:else if type === 'type-tag'}
{/if}
{/if} - {#if label} - {#if description} - {description} - {/if} + {#if $$slots.extra}{/if} {#if showMenu || $$slots.actions}
@@ -81,13 +146,23 @@ {/if} - {#if selected && (type === 'type-link' || type === 'type-object')} + {#if showArrow}
{/if} +{#if (isFold && (isOpen || (!isOpen && visible)) && !empty) || forciblyСollapsed} +
+ {#if (!isOpen && visible) || forciblyСollapsed} + + {:else} + + {/if} +
+{/if} diff --git a/packages/ui/src/components/icons/Down.svelte b/packages/ui/src/components/icons/Down.svelte index 7ac9562fad..2deedad131 100644 --- a/packages/ui/src/components/icons/Down.svelte +++ b/packages/ui/src/components/icons/Down.svelte @@ -1,5 +1,5 @@ diff --git a/packages/ui/src/components/icons/DownOutline.svelte b/packages/ui/src/components/icons/DownOutline.svelte index b8dcda616e..1156a53581 100644 --- a/packages/ui/src/components/icons/DownOutline.svelte +++ b/packages/ui/src/components/icons/DownOutline.svelte @@ -1,5 +1,5 @@ diff --git a/packages/ui/src/components/icons/FolderCollapsed.svelte b/packages/ui/src/components/icons/FolderCollapsed.svelte new file mode 100644 index 0000000000..3a1965c375 --- /dev/null +++ b/packages/ui/src/components/icons/FolderCollapsed.svelte @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/packages/ui/src/components/icons/FolderExpanded.svelte b/packages/ui/src/components/icons/FolderExpanded.svelte new file mode 100644 index 0000000000..6e368c4ac7 --- /dev/null +++ b/packages/ui/src/components/icons/FolderExpanded.svelte @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/packages/ui/src/components/icons/OpenedArrow.svelte b/packages/ui/src/components/icons/OpenedArrow.svelte index 97d47d6391..0f7ffd7014 100644 --- a/packages/ui/src/components/icons/OpenedArrow.svelte +++ b/packages/ui/src/components/icons/OpenedArrow.svelte @@ -13,7 +13,7 @@ // limitations under the License. --> diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index c01e35f90c..beef9bc0c7 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -226,6 +226,8 @@ export { default as IconDropdownRight } from './components/icons/DropdownRight.s export { default as IconKeyCommand } from './components/icons/KeyCommand.svelte' export { default as IconKeyOption } from './components/icons/KeyOption.svelte' export { default as IconKeyShift } from './components/icons/KeyShift.svelte' +export { default as IconFolderCollapsed } from './components/icons/FolderCollapsed.svelte' +export { default as IconFolderExpanded } from './components/icons/FolderExpanded.svelte' export { default as IconCheckmark } from './components/icons/Checkmark.svelte' export { default as PanelInstance } from './components/PanelInstance.svelte' diff --git a/packages/ui/src/location.ts b/packages/ui/src/location.ts index dc6b15f4ab..44b8db5a46 100644 --- a/packages/ui/src/location.ts +++ b/packages/ui/src/location.ts @@ -197,16 +197,17 @@ export function navigate (location: PlatformLocation, replace = false): boolean } const COLLAPSED = 'COLLAPSED' -export const getCollapsedKey = (_id: string): string => `${getCurrentLocation().path[1]}_${_id}_collapsed` +export const getCollapsedKey = (_id: string, prefix?: string): string => + `${getCurrentLocation().path[1]}_${prefix !== undefined && prefix !== '' ? prefix + '_###_' + _id : _id}_collapsed` -export const getTreeCollapsed = (_id: any): boolean => { +export const getTreeCollapsed = (_id: any, prefix?: string): boolean => { if (_id === undefined || _id === 'undefined') return false - return localStorage.getItem(getCollapsedKey(_id as string)) === COLLAPSED + return localStorage.getItem(getCollapsedKey(_id as string, prefix)) === COLLAPSED } -export const setTreeCollapsed = (_id: any, collapsed: boolean): void => { +export const setTreeCollapsed = (_id: any, collapsed: boolean, prefix?: string): void => { if (_id === undefined || _id === 'undefined') return - const key = getCollapsedKey(_id) + const key = getCollapsedKey(_id, prefix) collapsed ? localStorage.setItem(key, COLLAPSED) : localStorage.removeItem(key) } diff --git a/plugins/chunter-resources/src/components/chat/Chat.svelte b/plugins/chunter-resources/src/components/chat/Chat.svelte index 4e36f82ca4..108197447b 100644 --- a/plugins/chunter-resources/src/components/chat/Chat.svelte +++ b/plugins/chunter-resources/src/components/chat/Chat.svelte @@ -107,6 +107,11 @@ } function handleChannelSelected (event: CustomEvent): void { + if (event.detail === null) { + selectedData = undefined + return + } + const detail = (event.detail ?? {}) as SelectChannelEvent selectedData = { _id: detail.object._id, _class: detail.object._class } diff --git a/plugins/chunter-resources/src/components/chat/navigator/ChatNavItem.svelte b/plugins/chunter-resources/src/components/chat/navigator/ChatNavItem.svelte index 2a153c4206..b0c33ed6cd 100644 --- a/plugins/chunter-resources/src/components/chat/navigator/ChatNavItem.svelte +++ b/plugins/chunter-resources/src/components/chat/navigator/ChatNavItem.svelte @@ -115,7 +115,7 @@ { items = res }) @@ -137,49 +133,48 @@ return result } + $: visibleItem = visibleItems.find(({ id }) => id === objectId) {#if visibleItems.length > 0 && contexts.length > 0} it.id === objectId)} isFold - second - on:toggle={() => { - toggleSections(id) - }} + empty={visibleItems.length === 0} + visible={visibleItem !== undefined} + noDivider > - {#if !isCollapsed} - {#each visibleItems as item (item.id)} - {@const context = contexts.find(({ attachedTo }) => attachedTo === item.id)} - - {/each} - {#if canShowMore} -
- -
- {/if} - {:else if objectId} - {@const item = visibleItems.find(({ id }) => id === objectId)} - {#if item} - {@const context = contexts.find(({ attachedTo }) => attachedTo === item.id)} - - {/if} + {#each visibleItems as item (item.id)} + {@const context = contexts.find(({ attachedTo }) => attachedTo === item.id)} + + {/each} + {#if canShowMore} +
+ +
{/if} + + {#if visibleItem !== undefined && !isOpen} + {@const context = contexts.find(({ attachedTo }) => attachedTo === visibleItem?.id)} + + {/if} +
{/if} diff --git a/plugins/chunter-resources/src/components/chat/navigator/ChatNavigator.svelte b/plugins/chunter-resources/src/components/chat/navigator/ChatNavigator.svelte index 847b525647..d52292d264 100644 --- a/plugins/chunter-resources/src/components/chat/navigator/ChatNavigator.svelte +++ b/plugins/chunter-resources/src/components/chat/navigator/ChatNavigator.svelte @@ -18,7 +18,7 @@ import { DocNotifyContext } from '@hcengineering/notification' import { SpecialNavModel } from '@hcengineering/workbench' import { NavLink } from '@hcengineering/view-resources' - import { TreeSeparator } from '@hcengineering/workbench-resources' + import { TreeSeparator, NavFooter } from '@hcengineering/workbench-resources' import { getResource } from '@hcengineering/platform' import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources' @@ -35,6 +35,7 @@ const notificationClient = InboxNotificationsClientImpl.getClient() const contextsStore = notificationClient.contexts + let pressed: boolean = false const globalActions = [ { @@ -66,16 +67,19 @@ } function addButtonClicked (ev: MouseEvent): void { - showPopup(Menu, { actions: globalActions }, ev.target as HTMLElement) + pressed = true + showPopup(Menu, { actions: globalActions }, ev.target as HTMLElement, () => { + pressed = false + }) } -
+
{#if hasAccountRole(getCurrentAccount(), AccountRole.User)} - + {/if}
@@ -86,7 +90,7 @@ {#await isSpecialVisible(special, $contextsStore) then isVisible} {#if isVisible} - + {/if} {/await} @@ -106,16 +110,16 @@ }} />
- + {#each chatNavGroupModels as model} {/each} -
+ diff --git a/plugins/chunter-resources/src/components/chat/navigator/ChatSpecialElement.svelte b/plugins/chunter-resources/src/components/chat/navigator/ChatSpecialElement.svelte index 564dd5fab2..1deea5c985 100644 --- a/plugins/chunter-resources/src/components/chat/navigator/ChatSpecialElement.svelte +++ b/plugins/chunter-resources/src/components/chat/navigator/ChatSpecialElement.svelte @@ -13,6 +13,7 @@ // limitations under the License. --> dispatch('select', null)} /> diff --git a/plugins/chunter-resources/src/components/chat/navigator/NavItem.svelte b/plugins/chunter-resources/src/components/chat/navigator/NavItem.svelte index 8dbbb980a7..02a2c21eef 100644 --- a/plugins/chunter-resources/src/components/chat/navigator/NavItem.svelte +++ b/plugins/chunter-resources/src/components/chat/navigator/NavItem.svelte @@ -27,7 +27,7 @@ import { NotifyMarker } from '@hcengineering/notification-resources' import { Asset, IntlString } from '@hcengineering/platform' - export let id: string + export let _id: string export let icon: Asset | AnySvelteComponent | undefined export let iconProps: any | undefined = undefined export let iconSize: IconSize = 'small' @@ -50,7 +50,7 @@ $: menuActions = actions.filter(({ inline }) => inline !== true) function handleMenuClicked (ev: MouseEvent): void { - showPopup(Menu, { actions: menuActions, ctx: id }, ev.target as HTMLElement, () => { + showPopup(Menu, { actions: menuActions, ctx: _id }, ev.target as HTMLElement, () => { menuOpened = false }) menuOpened = true @@ -62,6 +62,7 @@ , Array> export let selected: Ref | undefined - export let level = 1 + export let level: number = 0 export let getMoreActions: ((obj: Doc, originalEvent?: MouseEvent) => Promise) | undefined = undefined export let collapsedPrefix: string = '' @@ -111,33 +110,36 @@ {#if doc} {@const children = childrenByParent[doc.attachedTo] ?? []} - 0} - getMoreActions={getMoreActions !== undefined ? () => getDocMoreActions(prjdoc) : undefined} + selected={selected === doc._id || selected === prjdoc._id} + isFold + empty={children.length === 0 || children === undefined} + actions={getMoreActions !== undefined ? () => getDocMoreActions(prjdoc) : undefined} {level} {collapsedPrefix} on:click={() => { dispatch('selected', prjdoc) }} > - {#if children.length} - - {/if} - + + {#if children.length} + + {/if} + + {/if} {/each} diff --git a/plugins/controlled-documents-resources/src/components/hierarchy/DocHierarchyRootElement.svelte b/plugins/controlled-documents-resources/src/components/hierarchy/DocHierarchyRootElement.svelte deleted file mode 100644 index 2786d4c34c..0000000000 --- a/plugins/controlled-documents-resources/src/components/hierarchy/DocHierarchyRootElement.svelte +++ /dev/null @@ -1,102 +0,0 @@ - - - - - -
{ - collapsed = !collapsed - dispatch('click') - }} -> - {#if icon} -
- -
- {/if} - - - {title} - - - - -
- - - -
-
- -
-
-
- -{#if !collapsed} -
-{/if} diff --git a/plugins/controlled-documents-resources/src/components/hierarchy/DocHierarchyTreeElement.svelte b/plugins/controlled-documents-resources/src/components/hierarchy/DocHierarchyTreeElement.svelte deleted file mode 100644 index 641f539fea..0000000000 --- a/plugins/controlled-documents-resources/src/components/hierarchy/DocHierarchyTreeElement.svelte +++ /dev/null @@ -1,103 +0,0 @@ - - - - - -
0 ? level * 1.25 + 0.125 : 0.75}rem`} - on:click -> -
{ - if (hasLeftCollapser) collapsed = !collapsed - }} - > - {#if hasLeftCollapser}{/if} -
- - {#if icon} -
- -
- {/if} - - {title} - - {#if parent && folder} - - {/if} -
- - {#if hasActions} -
- -
- {/if} -
- -{#if parent && !collapsed} -
-{/if} diff --git a/plugins/controlled-documents-resources/src/components/hierarchy/DocumentParentSelector.svelte b/plugins/controlled-documents-resources/src/components/hierarchy/DocumentParentSelector.svelte index 8fcd7645d6..695209da91 100644 --- a/plugins/controlled-documents-resources/src/components/hierarchy/DocumentParentSelector.svelte +++ b/plugins/controlled-documents-resources/src/components/hierarchy/DocumentParentSelector.svelte @@ -16,19 +16,17 @@ import { createEventDispatcher } from 'svelte' import { WithLookup, type Doc, type Ref } from '@hcengineering/core' import { createQuery } from '@hcengineering/presentation' - import { getPlatformColorForTextDef, themeStore } from '@hcengineering/ui' + import { getPlatformColorForTextDef, themeStore, getTreeCollapsed } from '@hcengineering/ui' import documents, { type DocumentMeta, type DocumentSpace, type Project, type ProjectMeta } from '@hcengineering/controlled-documents' + import { TreeNode } from '@hcengineering/view-resources' - import FolderCollapsed from '../icons/FolderCollapsed.svelte' - import FolderExpanded from '../icons/FolderExpanded.svelte' import DocHierarchyLevel from './DocHierarchyLevel.svelte' - import DocHierarchyTreeElement from './DocHierarchyTreeElement.svelte' - import { getPrefixedTreeCollapsed, setPrefixedTreeCollapsed, getProjectDocsHierarchy } from '../../utils' + import { getProjectDocsHierarchy } from '../../utils' export let space: DocumentSpace export let project: Ref | undefined @@ -36,9 +34,9 @@ export let collapsedPrefix: string = '' const dispatch = createEventDispatcher() - let collapsed: boolean = getPrefixedTreeCollapsed(space._id, collapsedPrefix) - $: setPrefixedTreeCollapsed(space._id, collapsedPrefix, collapsed) - $: folderIcon = collapsed ? FolderCollapsed : FolderExpanded + // let collapsed: boolean = getPrefixedTreeCollapsed(space._id, collapsedPrefix) + // $: setPrefixedTreeCollapsed(space._id, collapsedPrefix, collapsed) + // $: folderIcon = collapsed ? FolderCollapsed : FolderExpanded let rootDocs: Array> = [] let childrenByParent: Record, Array>> = {} @@ -56,29 +54,21 @@ ) -
- 0} - {collapsedPrefix} - on:click={() => { - dispatch('selected', space) - }} - > - - -
- - + { + dispatch('selected', space) + }} +> + + diff --git a/plugins/controlled-documents-resources/src/components/hierarchy/DocumentSpacePresenter.svelte b/plugins/controlled-documents-resources/src/components/hierarchy/DocumentSpacePresenter.svelte index cf292df701..bcbc6a5d82 100644 --- a/plugins/controlled-documents-resources/src/components/hierarchy/DocumentSpacePresenter.svelte +++ b/plugins/controlled-documents-resources/src/components/hierarchy/DocumentSpacePresenter.svelte @@ -16,32 +16,22 @@ import { WithLookup, type Doc, type Ref, type Space } from '@hcengineering/core' import { createQuery, getClient } from '@hcengineering/presentation' import { getResource } from '@hcengineering/platform' - import { - type Action, - getTreeCollapsed, - setTreeCollapsed, - getPlatformColorForTextDef, - themeStore, - navigate, - IconEdit, - Label - } from '@hcengineering/ui' - import { getActions as getContributedActions } from '@hcengineering/view-resources' + import { type Action, getPlatformColorForTextDef, themeStore, navigate, IconEdit, Label } from '@hcengineering/ui' + import { getActions as getContributedActions, TreeNode, TreeItem } from '@hcengineering/view-resources' import { ActionGroup } from '@hcengineering/view' import { + type ControlledDocument, type DocumentMeta, type DocumentSpace, type DocumentSpaceType, type Project, type ProjectDocument, - type ProjectMeta + type ProjectMeta, + getDocumentName } from '@hcengineering/controlled-documents' - import FolderCollapsed from '../icons/FolderCollapsed.svelte' - import FolderExpanded from '../icons/FolderExpanded.svelte' import ProjectSelector from '../project/ProjectSelector.svelte' import DocHierarchyLevel from './DocHierarchyLevel.svelte' - import DocHierarchyRootElement from './DocHierarchyRootElement.svelte' import { getDocumentIdFromFragment, getProjectDocumentLink } from '../../navigation' import { getCurrentProject, @@ -55,12 +45,16 @@ import documents from '../../plugin' export let space: DocumentSpace + export let currentSpace: Ref | undefined export let currentFragment: string | undefined export let getActions: (space: Space) => Promise = async () => [] + export let deselect: boolean = false + export let forciblyСollapsed: boolean = false const client = getClient() let spaceType: DocumentSpaceType | undefined + let pressed: boolean = false const spaceTypeQuery = createQuery() $: spaceTypeQuery.query(documents.class.DocumentSpaceType, { _id: space.type }, (result) => { @@ -69,10 +63,6 @@ $: selected = getDocumentIdFromFragment(currentFragment ?? '') - let collapsed: boolean = getTreeCollapsed(space._id) - $: setTreeCollapsed(space._id, collapsed) - $: folderIcon = collapsed ? FolderCollapsed : FolderExpanded - let project: Ref = documents.ids.NoProject $: void selectProject(space) @@ -96,6 +86,35 @@ } ) + let selectedControlledDoc: ControlledDocument | undefined = undefined + + $: if (selected !== undefined) { + void client + .findOne( + documents.class.ProjectDocument, + { _id: selected }, + { + lookup: { + document: documents.class.ControlledDocument + } + } + ) + .then((result) => { + if (result !== undefined) { + selectedControlledDoc = result.$lookup?.document as ControlledDocument + } else { + // There's some issue with resolving which needs to be fixed later + void client + .findOne(documents.class.ControlledDocument, { _id: selected as unknown as Ref }) + .then((result) => { + selectedControlledDoc = result + }) + } + }) + } else { + selectedControlledDoc = undefined + } + async function selectProject (space: DocumentSpace): Promise { project = getCurrentProject(space._id) ?? (await getLatestProjectId(space._id)) ?? documents.ids.NoProject } @@ -161,17 +180,21 @@ } - getSpaceActions(space)} + highlighted={space._id === currentSpace && currentFragment !== undefined && !deselect} + visible={(space._id === currentSpace && currentFragment !== undefined && !deselect) || forciblyСollapsed} + showMenu={pressed} + {forciblyСollapsed} + actions={() => getSpaceActions(space)} + type={'nested'} > -
+ {#if spaceType?.projects === true} { project = evt.detail setCurrentProject(space._id, project) }} /> {/if} -
+ {#if rootDocs.length > 0}
{/if} - + + + {#if (selected || forciblyСollapsed) && selectedControlledDoc} + {@const doc = selectedControlledDoc} + getDocumentActions(doc)} + selected + isFold + empty + forciblyСollapsed + /> + {/if} + + diff --git a/plugins/time-resources/src/components/team/TeamNavigator.svelte b/plugins/time-resources/src/components/team/TeamNavigator.svelte index be6e7c994a..9ad3eba478 100644 --- a/plugins/time-resources/src/components/team/TeamNavigator.svelte +++ b/plugins/time-resources/src/components/team/TeamNavigator.svelte @@ -16,8 +16,9 @@ import { Ref, getCurrentAccount } from '@hcengineering/core' import { createQuery } from '@hcengineering/presentation' import task, { Project } from '@hcengineering/task' - import { Label, Separator } from '@hcengineering/ui' + import { Label, Separator, Scroller, NavItem } from '@hcengineering/ui' import { ObjectPresenter, TreeNode } from '@hcengineering/view-resources' + import { NavFooter } from '@hcengineering/workbench-resources' import time from '../../plugin' export let navFloat: boolean = false @@ -37,30 +38,55 @@ projects = result } ) + $: selectedItem = projects.find((pr) => pr._id === selected)
-
-
-