Command Palette: Display dashboard location (#63807)

* show folder for dashboard, adjust how ancestors are displayed, clamp to single line

* fix keys

* better responsiveness

* use subtitle consistently

* use span instead of div
This commit is contained in:
Ashley Harrison 2023-03-01 09:46:46 +00:00 committed by GitHub
parent b009ba6cd4
commit 27635e6f7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 33 deletions

View File

@ -35,11 +35,12 @@ export const ResultItem = React.forwardRef(
let name = action.name;
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const hasAction = Boolean(action.command?.perform || (action as ActionImpl & { url?: string }).url);
const hasCommandOrLink = (action: ActionImpl) =>
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
Boolean(action.command?.perform || (action as ActionImpl & { url?: string }).url);
// TODO: does this needs adjusting for i18n?
if (action.children.length && !hasAction && !name.endsWith('...')) {
if (action.children.length && !hasCommandOrLink(action) && !name.endsWith('...')) {
name += '...';
}
@ -48,16 +49,17 @@ export const ResultItem = React.forwardRef(
<div className={styles.actionContainer}>
{action.icon}
<div className={styles.textContainer}>
<div>
{ancestors.length > 0 &&
ancestors.map((ancestor) => (
<React.Fragment key={ancestor.id}>
{ancestors.map((ancestor) => (
<React.Fragment key={ancestor.id}>
{!hasCommandOrLink(ancestor) && (
<>
<span className={styles.breadcrumbAncestor}>{ancestor.name}</span>
<span className={styles.breadcrumbAncestor}>&rsaquo;</span>
</React.Fragment>
))}
<span>{name}</span>
</div>
<span className={styles.breadcrumbSeparator}>&rsaquo;</span>
</>
)}
</React.Fragment>
))}
<span>{name}</span>
</div>
{action.subtitle && <span className={styles.subtitleText}>{action.subtitle}</span>}
</div>
@ -98,30 +100,35 @@ const getResultItemStyles = (theme: GrafanaTheme2) => {
actionContainer: css({
display: 'flex',
gap: theme.spacing(1),
alignItems: 'center',
alignItems: 'baseline',
fontSize: theme.typography.fontSize,
width: '100%',
}),
textContainer: css({
display: 'flex',
flexDirection: 'column',
}),
shortcut: css({
padding: theme.spacing(0, 1),
background: theme.colors.background.secondary,
borderRadius: theme.shape.borderRadius(),
fontSize: theme.typography.fontSize,
display: 'block',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}),
breadcrumbAncestor: css({
marginRight: theme.spacing(1),
color: theme.colors.text.secondary,
}),
subtitleText: css({
fontSize: theme.typography.fontSize - 2,
breadcrumbSeparator: css({
color: theme.colors.text.secondary,
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
}),
shortcutContainer: css({
display: 'grid',
gridAutoFlow: 'column',
gap: theme.spacing(1),
subtitleText: css({
...theme.typography.bodySmall,
color: theme.colors.text.secondary,
display: 'block',
flexBasis: '20%',
flexGrow: 1,
flexShrink: 0,
maxWidth: 'fit-content',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}),
};
};

View File

@ -57,7 +57,7 @@ export async function getSearchResultActions(searchQuery: string): Promise<Comma
});
const goToSearchResultActions: CommandPaletteAction[] = data.view.map((item) => {
const { url, name, kind } = item; // items are backed by DataFrameView, so must hold the url in a closure
const { url, name, kind, location } = item; // items are backed by DataFrameView, so must hold the url in a closure
return {
id: `go/${kind}${url}`,
name: `${name}`,
@ -67,6 +67,7 @@ export async function getSearchResultActions(searchQuery: string): Promise<Comma
: t('command-palette.section.folder-search-results', 'Folders'),
priority: SEARCH_RESULTS_PRORITY,
url: locationUtil.stripBaseFromUrl(url),
subtitle: data.view.dataFrame.meta?.custom?.locationInfo[location]?.name,
};
});

View File

@ -10,7 +10,7 @@ function idForNavItem(navItem: NavModelItem) {
return 'navModel.' + navItem.id ?? navItem.url ?? navItem.text ?? navItem.subTitle;
}
function navTreeToActions(navTree: NavModelItem[], parent?: NavModelItem): CommandPaletteAction[] {
function navTreeToActions(navTree: NavModelItem[], parents: NavModelItem[] = []): CommandPaletteAction[] {
const navActions: CommandPaletteAction[] = [];
for (const navItem of navTree) {
@ -27,19 +27,21 @@ function navTreeToActions(navTree: NavModelItem[], parent?: NavModelItem): Comma
const priority = isCreateAction ? ACTIONS_PRIORITY : DEFAULT_PRIORITY;
const subtitle = parents.map((parent) => parent.text).join(' > ');
const action = {
id: idForNavItem(navItem),
name: text, // TODO: translate
name: text,
section: section,
url: url && locationUtil.stripBaseFromUrl(url),
parent: parent && !isCreateAction && idForNavItem(parent),
parent: parents.length > 0 && !isCreateAction ? idForNavItem(parents[parents.length - 1]) : undefined,
priority: priority,
subtitle: isCreateAction ? undefined : subtitle,
};
navActions.push(action);
if (children?.length) {
const childActions = navTreeToActions(children, navItem);
const childActions = navTreeToActions(children, [...parents, navItem]);
navActions.push(...childActions);
}
}