mirror of https://github.com/grafana/grafana
DashboardScene: Support dashboard links (#77855)
* MenuItem: Allow react node as label * LinkButton: Expose ButtonLinkProps * Typecheck fix * DashboardLinks: Refactor and use LinkButton and menu * DashbaordLinks scene object * Use flex layout for dashboard controls * Update public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> * fix keepTime and includeVars * Add ellipsis to menu item label and description * Use DashboardLink type from grafana/schema * Update dashboard scene controls layout * Fix e2e * Test fix * Bring back keyboard navigation * Remove unused code * One more fix --------- Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com>pull/78179/head^2
parent
dfa506857a
commit
0122f7ccad
@ -0,0 +1,42 @@ |
|||||||
|
import React from 'react'; |
||||||
|
|
||||||
|
import { SceneObjectState, SceneObject, SceneObjectBase, SceneComponentProps } from '@grafana/scenes'; |
||||||
|
import { Box, Stack } from '@grafana/ui'; |
||||||
|
|
||||||
|
import { DashboardLinksControls } from './DashboardLinksControls'; |
||||||
|
|
||||||
|
interface DashboardControlsState extends SceneObjectState { |
||||||
|
variableControls: SceneObject[]; |
||||||
|
timeControls: SceneObject[]; |
||||||
|
linkControls: DashboardLinksControls; |
||||||
|
} |
||||||
|
export class DashboardControls extends SceneObjectBase<DashboardControlsState> { |
||||||
|
static Component = DashboardControlsRenderer; |
||||||
|
} |
||||||
|
|
||||||
|
function DashboardControlsRenderer({ model }: SceneComponentProps<DashboardControls>) { |
||||||
|
const { variableControls, linkControls, timeControls } = model.useState(); |
||||||
|
|
||||||
|
return ( |
||||||
|
<Stack |
||||||
|
grow={1} |
||||||
|
direction={{ |
||||||
|
md: 'row', |
||||||
|
xs: 'column', |
||||||
|
}} |
||||||
|
> |
||||||
|
<Stack grow={1} wrap={'wrap'}> |
||||||
|
{variableControls.map((c) => ( |
||||||
|
<c.Component model={c} key={c.state.key} /> |
||||||
|
))} |
||||||
|
<Box grow={1} /> |
||||||
|
<linkControls.Component model={linkControls} /> |
||||||
|
</Stack> |
||||||
|
<Stack justifyContent={'flex-end'}> |
||||||
|
{timeControls.map((c) => ( |
||||||
|
<c.Component model={c} key={c.state.key} /> |
||||||
|
))} |
||||||
|
</Stack> |
||||||
|
</Stack> |
||||||
|
); |
||||||
|
} |
||||||
@ -0,0 +1,58 @@ |
|||||||
|
import React from 'react'; |
||||||
|
|
||||||
|
import { sanitizeUrl } from '@grafana/data/src/text/sanitize'; |
||||||
|
import { selectors } from '@grafana/e2e-selectors'; |
||||||
|
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; |
||||||
|
import { DashboardLink } from '@grafana/schema'; |
||||||
|
import { Tooltip } from '@grafana/ui'; |
||||||
|
import { linkIconMap } from 'app/features/dashboard/components/LinksSettings/LinkSettingsEdit'; |
||||||
|
import { |
||||||
|
DashboardLinkButton, |
||||||
|
DashboardLinksDashboard, |
||||||
|
} from 'app/features/dashboard/components/SubMenu/DashboardLinksDashboard'; |
||||||
|
import { getLinkSrv } from 'app/features/panel/panellinks/link_srv'; |
||||||
|
|
||||||
|
interface DashboardLinksControlsState extends SceneObjectState { |
||||||
|
links: DashboardLink[]; |
||||||
|
dashboardUID: string; |
||||||
|
} |
||||||
|
|
||||||
|
export class DashboardLinksControls extends SceneObjectBase<DashboardLinksControlsState> { |
||||||
|
static Component = DashboardLinksControlsRenderer; |
||||||
|
} |
||||||
|
|
||||||
|
function DashboardLinksControlsRenderer({ model }: SceneComponentProps<DashboardLinksControls>) { |
||||||
|
const { links, dashboardUID } = model.useState(); |
||||||
|
return ( |
||||||
|
<> |
||||||
|
{links.map((link: DashboardLink, index: number) => { |
||||||
|
const linkInfo = getLinkSrv().getAnchorInfo(link); |
||||||
|
const key = `${link.title}-$${index}`; |
||||||
|
|
||||||
|
if (link.type === 'dashboards') { |
||||||
|
return <DashboardLinksDashboard key={key} link={link} linkInfo={linkInfo} dashboardUID={dashboardUID} />; |
||||||
|
} |
||||||
|
|
||||||
|
const icon = linkIconMap[link.icon]; |
||||||
|
|
||||||
|
const linkElement = ( |
||||||
|
<DashboardLinkButton |
||||||
|
icon={icon} |
||||||
|
href={sanitizeUrl(linkInfo.href)} |
||||||
|
target={link.targetBlank ? '_blank' : undefined} |
||||||
|
rel="noreferrer" |
||||||
|
data-testid={selectors.components.DashboardLinks.link} |
||||||
|
> |
||||||
|
{linkInfo.title} |
||||||
|
</DashboardLinkButton> |
||||||
|
); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div key={key} data-testid={selectors.components.DashboardLinks.container}> |
||||||
|
{link.tooltip ? <Tooltip content={linkInfo.tooltip}>{linkElement}</Tooltip> : linkElement} |
||||||
|
</div> |
||||||
|
); |
||||||
|
})} |
||||||
|
</> |
||||||
|
); |
||||||
|
} |
||||||
Loading…
Reference in new issue