mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 11:42:19 +08:00

* Add pills in search bar for context * Add scope actions * Add selection functionality * Show selected scope on secondary row * Fix selected scope titles * Add some basic tests * Test for toggle by name * Remove unnecessary mocking * Small cleanups * Lint fixes * Fix test * Update public/app/features/scopes/selector/ScopesSelectorService.ts Co-authored-by: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> * Bump input and breadcrumbs test * Change breadcrumbs color * Makes the breacrumb spacing consistent * Add basic global search * Change scope selector data structures * Fix scope selector functionality * Fix errors in selector and cmdk actions * Fix cmdk actions * Fix global search in cmdk * Fix some merge edits * merge diffs * Small merge fixes * Fix ScopesSelectorService.test.ts * Fix tests * Remove unrelated lint fixes * Move ScopesTreeItemList.tsx into separate file * Simplify if condition * Use node.title in the scopesRow * Use better dependency array for actions * Make recentScopes more robust * Fix beterrer * Update betterer file * Add test for changeScopes early return * Fix input tooltip title access --------- Co-authored-by: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com>
95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { css } from '@emotion/css';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { Trans } from '@grafana/i18n';
|
|
import { Button, FilterPill, Stack, Text, useStyles2 } from '@grafana/ui';
|
|
|
|
import { getModKey } from '../../core/utils/browser';
|
|
import { NodesMap, ScopesMap, SelectedScope } from '../scopes/selector/types';
|
|
|
|
type Props = {
|
|
selectedScopes: SelectedScope[];
|
|
isDirty: boolean;
|
|
apply: () => void;
|
|
deselectScope: (id: string) => void;
|
|
scopes: ScopesMap;
|
|
nodes: NodesMap;
|
|
};
|
|
|
|
/**
|
|
* Shows scopes that are already selected and applied or the ones user just selected in the palette, with an apply
|
|
* button if the selection is dirty.
|
|
*/
|
|
export function ScopesRow({ selectedScopes, isDirty, apply, deselectScope, scopes, nodes }: Props) {
|
|
const styles = useStyles2(getStyles);
|
|
return (
|
|
<>
|
|
<Stack alignItems={'center'}>
|
|
<span className={styles.scopesText}>
|
|
<Trans i18nKey={'command-palette.scopes.selected-scopes-label'}>Scopes: </Trans>
|
|
</span>
|
|
<Stack wrap={'wrap'}>
|
|
{selectedScopes?.map((scope) => {
|
|
// We need to load scope data when an item is selected, so there may be a delay until we have it. We fallback
|
|
// to node.title if we have it and if not, show just a scopeId. node.title and scope.title should probably be
|
|
// the same, but it's not guaranteed
|
|
const label =
|
|
scopes[scope.scopeId]?.spec.title ||
|
|
(scope.scopeNodeId && nodes[scope.scopeNodeId]?.spec.title) ||
|
|
scope.scopeId;
|
|
|
|
return (
|
|
<FilterPill
|
|
key={scope.scopeId}
|
|
selected={true}
|
|
icon={'times'}
|
|
label={label}
|
|
onClick={() => {
|
|
deselectScope(scope.scopeNodeId || scope.scopeId);
|
|
}}
|
|
/>
|
|
);
|
|
})}
|
|
</Stack>
|
|
</Stack>
|
|
{isDirty && (
|
|
<Button
|
|
onClick={() => {
|
|
apply();
|
|
}}
|
|
>
|
|
<Trans i18nKey={'command-palette.scopes.apply-selected-scopes'}>Apply</Trans>
|
|
<Text variant="bodySmall">{`${getModKey()}+↵`}</Text>
|
|
</Button>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
scopesText: css({
|
|
label: 'scopesText',
|
|
fontSize: theme.typography.bodySmall.fontSize,
|
|
fontWeight: theme.typography.fontWeightMedium,
|
|
lineHeight: theme.typography.bodySmall.lineHeight,
|
|
color: theme.colors.text.secondary,
|
|
}),
|
|
selectedScope: css({
|
|
background: theme.colors.background.secondary,
|
|
borderRadius: theme.shape.radius.default,
|
|
padding: theme.spacing(0, 0.5),
|
|
fontSize: theme.typography.bodySmall.fontSize,
|
|
fontWeight: theme.typography.fontWeightMedium,
|
|
lineHeight: theme.typography.bodySmall.lineHeight,
|
|
color: theme.colors.text.secondary,
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
position: 'relative',
|
|
border: `1px solid ${theme.colors.background.secondary}`,
|
|
whiteSpace: 'nowrap',
|
|
marginRight: theme.spacing(0.5),
|
|
}),
|
|
};
|
|
};
|