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
3 changed files with 43 additions and 33 deletions
@@ -35,11 +35,12 @@ export const ResultItem = React.forwardRef(
let name = action.name; let name = action.name;
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions const hasCommandOrLink = (action: ActionImpl) =>
const hasAction = Boolean(action.command?.perform || (action as ActionImpl & { url?: string }).url); // 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? // TODO: does this needs adjusting for i18n?
if (action.children.length && !hasAction && !name.endsWith('...')) { if (action.children.length && !hasCommandOrLink(action) && !name.endsWith('...')) {
name += '...'; name += '...';
} }
@@ -48,16 +49,17 @@ export const ResultItem = React.forwardRef(
<div className={styles.actionContainer}> <div className={styles.actionContainer}>
{action.icon} {action.icon}
<div className={styles.textContainer}> <div className={styles.textContainer}>
<div> {ancestors.map((ancestor) => (
{ancestors.length > 0 && <React.Fragment key={ancestor.id}>
ancestors.map((ancestor) => ( {!hasCommandOrLink(ancestor) && (
<React.Fragment key={ancestor.id}> <>
<span className={styles.breadcrumbAncestor}>{ancestor.name}</span> <span className={styles.breadcrumbAncestor}>{ancestor.name}</span>
<span className={styles.breadcrumbAncestor}>&rsaquo;</span> <span className={styles.breadcrumbSeparator}>&rsaquo;</span>
</React.Fragment> </>
))} )}
<span>{name}</span> </React.Fragment>
</div> ))}
<span>{name}</span>
</div> </div>
{action.subtitle && <span className={styles.subtitleText}>{action.subtitle}</span>} {action.subtitle && <span className={styles.subtitleText}>{action.subtitle}</span>}
</div> </div>
@@ -98,30 +100,35 @@ const getResultItemStyles = (theme: GrafanaTheme2) => {
actionContainer: css({ actionContainer: css({
display: 'flex', display: 'flex',
gap: theme.spacing(1), gap: theme.spacing(1),
alignItems: 'center', alignItems: 'baseline',
fontSize: theme.typography.fontSize, fontSize: theme.typography.fontSize,
width: '100%',
}), }),
textContainer: css({ textContainer: css({
display: 'flex', display: 'block',
flexDirection: 'column', overflow: 'hidden',
}), textOverflow: 'ellipsis',
shortcut: css({ whiteSpace: 'nowrap',
padding: theme.spacing(0, 1),
background: theme.colors.background.secondary,
borderRadius: theme.shape.borderRadius(),
fontSize: theme.typography.fontSize,
}), }),
breadcrumbAncestor: css({ breadcrumbAncestor: css({
marginRight: theme.spacing(1),
color: theme.colors.text.secondary, color: theme.colors.text.secondary,
}), }),
subtitleText: css({ breadcrumbSeparator: css({
fontSize: theme.typography.fontSize - 2, color: theme.colors.text.secondary,
marginLeft: theme.spacing(1),
marginRight: theme.spacing(1),
}), }),
shortcutContainer: css({ subtitleText: css({
display: 'grid', ...theme.typography.bodySmall,
gridAutoFlow: 'column', color: theme.colors.text.secondary,
gap: theme.spacing(1), display: 'block',
flexBasis: '20%',
flexGrow: 1,
flexShrink: 0,
maxWidth: 'fit-content',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}), }),
}; };
}; };
@@ -57,7 +57,7 @@ export async function getSearchResultActions(searchQuery: string): Promise<Comma
}); });
const goToSearchResultActions: CommandPaletteAction[] = data.view.map((item) => { 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 { return {
id: `go/${kind}${url}`, id: `go/${kind}${url}`,
name: `${name}`, name: `${name}`,
@@ -67,6 +67,7 @@ export async function getSearchResultActions(searchQuery: string): Promise<Comma
: t('command-palette.section.folder-search-results', 'Folders'), : t('command-palette.section.folder-search-results', 'Folders'),
priority: SEARCH_RESULTS_PRORITY, priority: SEARCH_RESULTS_PRORITY,
url: locationUtil.stripBaseFromUrl(url), url: locationUtil.stripBaseFromUrl(url),
subtitle: data.view.dataFrame.meta?.custom?.locationInfo[location]?.name,
}; };
}); });
@@ -10,7 +10,7 @@ function idForNavItem(navItem: NavModelItem) {
return 'navModel.' + navItem.id ?? navItem.url ?? navItem.text ?? navItem.subTitle; 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[] = []; const navActions: CommandPaletteAction[] = [];
for (const navItem of navTree) { for (const navItem of navTree) {
@@ -27,19 +27,21 @@ function navTreeToActions(navTree: NavModelItem[], parent?: NavModelItem): Comma
const priority = isCreateAction ? ACTIONS_PRIORITY : DEFAULT_PRIORITY; const priority = isCreateAction ? ACTIONS_PRIORITY : DEFAULT_PRIORITY;
const subtitle = parents.map((parent) => parent.text).join(' > ');
const action = { const action = {
id: idForNavItem(navItem), id: idForNavItem(navItem),
name: text, // TODO: translate name: text,
section: section, section: section,
url: url && locationUtil.stripBaseFromUrl(url), url: url && locationUtil.stripBaseFromUrl(url),
parent: parent && !isCreateAction && idForNavItem(parent), parent: parents.length > 0 && !isCreateAction ? idForNavItem(parents[parents.length - 1]) : undefined,
priority: priority, priority: priority,
subtitle: isCreateAction ? undefined : subtitle,
}; };
navActions.push(action); navActions.push(action);
if (children?.length) { if (children?.length) {
const childActions = navTreeToActions(children, navItem); const childActions = navTreeToActions(children, [...parents, navItem]);
navActions.push(...childActions); navActions.push(...childActions);
} }
} }