Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions apps/sensenet/src/components/command-palette/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Autosuggest, { SuggestionSelectedEventData, SuggestionsFetchRequestedPara
import { useHistory } from 'react-router-dom'
import { ResponsiveContext, ResponsivePersonalSettings } from '../../context'
import { globals } from '../../globalStyles'
import { useLocalization, useSnRoute, useTheme } from '../../hooks'
import { useLocalization, useSelectionService, useSnRoute, useTheme } from '../../hooks'
import { CommandProviderManager } from '../../services'
import { ContentContextMenu } from '../context-menu/content-context-menu'
import { CommandPaletteHitsContainer } from './CommandPaletteHitsContainer'
Expand Down Expand Up @@ -65,6 +65,19 @@ const useStyles = makeStyles(() => {
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
},
actionContextHeader: {
padding: '8px 12px',
borderBottom: '1px solid rgba(0, 0, 0, 0.12)',
color: '#3c4654',
fontSize: '12px',
lineHeight: '16px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
actionContextTarget: {
fontWeight: 600,
},
})
})

Expand All @@ -91,6 +104,16 @@ export const CommandPalette = () => {
const cpm = useMemo(() => injector.getInstance(CommandProviderManager), [injector])
const snRoute = useSnRoute()
const isContextMenuInteractingRef = useRef(false)
const selectionService = useSelectionService()
const [activeContent, setActiveContent] = useState(selectionService.activeContent.getValue())

useEffect(() => {
const activeContentObserver = selectionService.activeContent.subscribe((content) => {
setActiveContent(content)
})

return () => activeContentObserver.dispose()
}, [selectionService.activeContent])

useEffect(() => {
const handleKeyUp = (ev: KeyboardEvent) => {
Expand Down Expand Up @@ -213,6 +236,23 @@ export const CommandPalette = () => {
setIsOpened(false)
}

const actionMode = inputValue.startsWith('>')
const actionContextHeader = actionMode ? (
<div className={classes.actionContextHeader} data-test="command-palette-action-context">
{activeContent ? (
<>
{localization.actionContext}
<span className={classes.actionContextTarget} title={activeContent.Path}>
{activeContent.DisplayName || activeContent.Name}
</span>
{activeContent.Path ? ` (${activeContent.Path})` : ''}
</>
) : (
localization.noActionContext
)}
</div>
) : undefined

return (
<div className={classes.buttonWrapper}>
<div ref={containerRef} className={classes.comboBox} data-test="command-box">
Expand Down Expand Up @@ -241,7 +281,9 @@ export const CommandPalette = () => {
onOpenContextMenu={handleOpenSuggestionContextMenu}
/>
)}
renderSuggestionsContainer={(params) => <CommandPaletteHitsContainer {...params} />}
renderSuggestionsContainer={(params) => (
<CommandPaletteHitsContainer {...params} header={actionContextHeader} />
)}
inputProps={{
className: `${classes.input} ${inputValue ? classes.inputOpened : ''}`,
value: inputValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { RenderSuggestionsContainerParams } from 'react-autosuggest'
import { ResponsiveContext } from '../../context'
import { useLocalization } from '../../hooks'

export const CommandPaletteHitsContainer: FunctionComponent<RenderSuggestionsContainerParams> = (options) => {
export const CommandPaletteHitsContainer: FunctionComponent<
RenderSuggestionsContainerParams & { header?: React.ReactNode }
> = (options) => {
const device = useContext(ResponsiveContext)
const localization = useLocalization()

Expand All @@ -18,15 +20,18 @@ export const CommandPaletteHitsContainer: FunctionComponent<RenderSuggestionsCon
left: device === 'mobile' ? '64px' : undefined,
width: device === 'mobile' ? 'calc(100% - 80px)' : '100%',
}}>
<List
aria-label={localization.commandPalette.searchSuggestionList}
dense={device === 'desktop' ? false : true}
component="nav"
data-test="search-suggestion-list"
{...options.containerProps}
style={{ padding: 0 }}>
{options.children}
</List>
<>
{options.header}
<List
aria-label={localization.commandPalette.searchSuggestionList}
dense={device === 'desktop' ? false : true}
component="nav"
data-test="search-suggestion-list"
{...options.containerProps}
style={{ padding: 0 }}>
{options.children}
</List>
</>
</Paper>
)
}
18 changes: 17 additions & 1 deletion apps/sensenet/src/components/content/Explore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { ColumnSetting } from '@sensenet/list-controls-react/src/ContentList/content-list-base-props'
import { ColDef } from 'ag-grid-community'
import { clsx } from 'clsx'
import React, { useContext, useMemo, useRef, useState } from 'react'
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'
import { useHistory } from 'react-router'
import { GridKeyEnum } from '../../../src/components/grid/enums/GridKey.enum'
import { ResponsivePersonalSettings } from '../../context'
Expand Down Expand Up @@ -178,6 +178,21 @@ type ExploreGridOrApplicationProps = {
onActivateItem: (activeItem: GenericContent) => Promise<void>
}

const ActiveContentRouteSync: React.FC = () => {
const currentContent = useContext(CurrentContentContext)
const selectionService = useSelectionService()

useEffect(() => {
const activeContent = selectionService.activeContent.getValue()

if (currentContent && (!activeContent || !PathHelper.isInSubTree(activeContent.Path, currentContent.Path))) {
selectionService.activeContent.setValue(currentContent)
}
}, [currentContent, selectionService.activeContent])

return null
}

const ExploreGridOrApplication: React.FC<ExploreGridOrApplicationProps> = ({
currentPath,
fieldsToDisplay,
Expand Down Expand Up @@ -360,6 +375,7 @@ export function Explore({
key={JSON.stringify(currentChildrenLoadSettings)}
loadChildrenSettings={currentChildrenLoadSettings}>
<CurrentContentProvider idOrPath={currentPath}>
<ActiveContentRouteSync />
<CurrentChildrenProvider loadSettings={loadChildrenSettings} alwaysRefresh={alwaysRefreshChildren}>
<CurrentAncestorsProvider root={rootPath}>
<div className={clsx(classes.breadcrumbsWrapper, globalClasses.centeredVertical)}>
Expand Down
12 changes: 12 additions & 0 deletions apps/sensenet/src/components/grid/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ColumnApi,
GridApi,
GridReadyEvent,
RowClickedEvent,
RowDoubleClickedEvent,
SelectionChangedEvent,
} from 'ag-grid-community'
Expand Down Expand Up @@ -86,10 +87,19 @@ export function Grid<T extends GenericContent = GenericContent>(props: GridProps
}, [children, isGridLoading, setLoadingWithMinDuration])

const onRowDoubleClicked = (item: RowDoubleClickedEvent) => {
if (item.data) {
props.onActiveItemChange?.(item.data)
}
setLoadingWithMinDuration(true)
item.data.isFolder ? props.onParentChange(item.data) : props.onActivateItem(item.data)
}

const onRowClicked = (item: RowClickedEvent) => {
if (item.data) {
props.onActiveItemChange?.(item.data)
}
}

const onSelectionChanged = (params: SelectionChangedEvent) => {
const selectedIds = params.api.getSelectedRows().map((c) => c.Id)
const selectedItems: GenericContent[] = children.filter((item) => selectedIds.includes(item.Id))
Expand All @@ -102,6 +112,7 @@ export function Grid<T extends GenericContent = GenericContent>(props: GridProps
if (!event.node || !event.event) return
const mouseEvent = event.event as MouseEvent
setContextMenuItem(event.data)
event.data && props.onActiveItemChange?.(event.data)
setContextMenuAnchorPos({ top: mouseEvent.clientY, left: mouseEvent.clientX })
setIsContextMenuOpened(true)
}
Expand Down Expand Up @@ -231,6 +242,7 @@ export function Grid<T extends GenericContent = GenericContent>(props: GridProps
rowSelection={'multiple'}
suppressReactUi={true}
tooltipShowDelay={100}
onRowClicked={onRowClicked}
onRowDoubleClicked={onRowDoubleClicked}
preventDefaultOnContextMenu={true}
onGridReady={onGridReady}
Expand Down
9 changes: 7 additions & 2 deletions apps/sensenet/src/components/tree/StyledTreeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useRepository } from '@sensenet/hooks-react'
import React, { MouseEventHandler, useCallback, useContext, useEffect, useRef, useState } from 'react'
import { useHistory } from 'react-router'
import { ResponsivePersonalSettings } from '../../context'
import { useQuery, useSnRoute } from '../../hooks'
import { useQuery, useSelectionService, useSnRoute } from '../../hooks'
import { getPrimaryActionUrl, navigateToAction } from '../../services'
import { ContentContextMenu } from '../context-menu/content-context-menu'
import { Icon } from '../Icon'
Expand Down Expand Up @@ -37,6 +37,7 @@ export const StyledTreeItem = ({
const repository = useRepository()
const snRoute = useSnRoute()
const uiSettings = useContext(ResponsivePersonalSettings)
const selectionService = useSelectionService()

const currentPath = useQuery().get('path')
const mountedRef = useRef(true)
Expand Down Expand Up @@ -141,20 +142,23 @@ export const StyledTreeItem = ({
const displayName = contentvalue.DisplayName

if (displayName?.endsWith('.settings') || displayName?.endsWith('.xml')) {
selectionService.activeContent.setValue(contentvalue)
history.push(
getPrimaryActionUrl({ content: contentvalue, repository, uiSettings, location: history.location, snRoute }),
)
return
}

if (editMode) {
selectionService.activeContent.setValue(contentvalue)
navigateToAction({
history,
routeMatch: snRoute.match!,
action: 'edit',
queryParams: { content: contentvalue.Path.replace(snRoute.path, '') },
})
} else {
selectionService.activeContent.setValue(contentvalue)
const itemPath = (event.target as HTMLElement).closest('[data-path]')?.getAttribute('data-path')
setExpandItems((prev) => {
const updated = new Set(prev)
Expand All @@ -176,11 +180,12 @@ export const StyledTreeItem = ({
if (isDisabled) return
event.preventDefault()
event.stopPropagation()
selectionService.activeContent.setValue(contentvalue)
setContextMenuItem(contentvalue)
setContextMenuAnchorPos({ top: event.clientY, left: event.clientX })
setIsContextMenuOpened(true)
},
[contentvalue, isDisabled],
[contentvalue, isDisabled, selectionService.activeContent],
)

return (
Expand Down
5 changes: 4 additions & 1 deletion apps/sensenet/src/hooks/use-tree-navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ import { useCallback, useEffect, useState } from 'react'
import { useHistory, useRouteMatch } from 'react-router'
import { resolvePathParams } from '../application-paths'
import { useQuery } from '../hooks/use-query'
import { useSelectionService } from '../hooks/use-selection-service'
import { pathWithQueryParams } from '../services/query-string-builder'

export const useTreeNavigation = (defaultPath: string) => {
const history = useHistory()
const match = useRouteMatch<{ browseType: string }>()
const selectionService = useSelectionService()
const pathFromQuery = useQuery().get('path')
const [currentPath, setCurrentPath] = useState(pathFromQuery ? decodeURIComponent(pathFromQuery) : '')

const onNavigate = useCallback(
(content: GenericContent) => {
selectionService.activeContent.setValue(content)
const searchParams = new URLSearchParams(history.location.search)
searchParams.delete('content')
const newPath = content.Path.replace(defaultPath, '')
Expand All @@ -26,7 +29,7 @@ export const useTreeNavigation = (defaultPath: string) => {
)
setCurrentPath(newPath)
},
[history, match.path, match.params, defaultPath],
[history, match.path, match.params, defaultPath, selectionService.activeContent],
)

useEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions apps/sensenet/src/localization/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const values = {
title: 'Search',
clear: 'Clear',
actions: 'Actions',
actionContext: 'Actions for: ',
noActionContext: 'No content selected for actions.',
help: {
readMeTitle: 'ReadMe',
readMeDescription: 'Opens the latest readme.md file from GitHub in a new window',
Expand Down
2 changes: 2 additions & 0 deletions apps/sensenet/src/localization/hungarian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const values: Localization = {
commandPalette: {
title: 'Command palette megnyitása',
actions: 'Műveletek',
actionContext: 'Műveletek ezen: ',
noActionContext: 'Nincs kiválasztott tartalom a műveletekhez.',
searchSuggestionList: 'Keresési javaslatok listája',
},
contentInfoDialog: {
Expand Down
Loading