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