123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- import React, { FC, ReactNode } from 'react';
- import { connect, ConnectedProps } from 'react-redux';
- import { useLocation } from 'react-router-dom';
- import { locationUtil, textUtil } from '@grafana/data';
- import { locationService } from '@grafana/runtime';
- import { ButtonGroup, ModalsController, ToolbarButton, PageToolbar, useForceUpdate } from '@grafana/ui';
- import config from 'app/core/config';
- import { toggleKioskMode } from 'app/core/navigation/kiosk';
- import { DashboardCommentsModal } from 'app/features/dashboard/components/DashboardComments/DashboardCommentsModal';
- import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer';
- import { ShareModal } from 'app/features/dashboard/components/ShareModal';
- import { playlistSrv } from 'app/features/playlist/PlaylistSrv';
- import { updateTimeZoneForSession } from 'app/features/profile/state/reducers';
- import { KioskMode } from 'app/types';
- import { setStarred } from '../../../../core/reducers/navBarTree';
- import { getDashboardSrv } from '../../services/DashboardSrv';
- import { DashboardModel } from '../../state';
- import { DashNavButton } from './DashNavButton';
- import { DashNavTimeControls } from './DashNavTimeControls';
- const mapDispatchToProps = {
- setStarred,
- updateTimeZoneForSession,
- };
- const connector = connect(null, mapDispatchToProps);
- export interface OwnProps {
- dashboard: DashboardModel;
- isFullscreen: boolean;
- kioskMode: KioskMode;
- hideTimePicker: boolean;
- folderTitle?: string;
- title: string;
- onAddPanel: () => void;
- }
- interface DashNavButtonModel {
- show: (props: Props) => boolean;
- component: FC<Partial<Props>>;
- index?: number | 'end';
- }
- const customLeftActions: DashNavButtonModel[] = [];
- const customRightActions: DashNavButtonModel[] = [];
- export function addCustomLeftAction(content: DashNavButtonModel) {
- customLeftActions.push(content);
- }
- export function addCustomRightAction(content: DashNavButtonModel) {
- customRightActions.push(content);
- }
- type Props = OwnProps & ConnectedProps<typeof connector>;
- export const DashNav = React.memo<Props>((props) => {
- const forceUpdate = useForceUpdate();
- const onStarDashboard = () => {
- const dashboardSrv = getDashboardSrv();
- const { dashboard, setStarred } = props;
- dashboardSrv.starDashboard(dashboard.id, dashboard.meta.isStarred).then((newState: any) => {
- setStarred({ id: dashboard.uid, title: dashboard.title, url: dashboard.meta.url ?? '', isStarred: newState });
- dashboard.meta.isStarred = newState;
- forceUpdate();
- });
- };
- const onClose = () => {
- locationService.partial({ viewPanel: null });
- };
- const onToggleTVMode = () => {
- toggleKioskMode();
- };
- const onOpenSettings = () => {
- locationService.partial({ editview: 'settings' });
- };
- const onPlaylistPrev = () => {
- playlistSrv.prev();
- };
- const onPlaylistNext = () => {
- playlistSrv.next();
- };
- const onPlaylistStop = () => {
- playlistSrv.stop();
- forceUpdate();
- };
- const addCustomContent = (actions: DashNavButtonModel[], buttons: ReactNode[]) => {
- actions.map((action, index) => {
- const Component = action.component;
- const element = <Component {...props} key={`button-custom-${index}`} />;
- typeof action.index === 'number' ? buttons.splice(action.index, 0, element) : buttons.push(element);
- });
- };
- const isPlaylistRunning = () => {
- return playlistSrv.isPlaying;
- };
- const renderLeftActionsButton = () => {
- const { dashboard, kioskMode } = props;
- const { canStar, canShare, isStarred } = dashboard.meta;
- const buttons: ReactNode[] = [];
- if (kioskMode !== KioskMode.Off || isPlaylistRunning()) {
- return [];
- }
- if (canStar) {
- let desc = isStarred ? 'Unmark as favorite' : 'Mark as favorite';
- buttons.push(
- <DashNavButton
- tooltip={desc}
- icon={isStarred ? 'favorite' : 'star'}
- iconType={isStarred ? 'mono' : 'default'}
- iconSize="lg"
- onClick={onStarDashboard}
- key="button-star"
- />
- );
- }
- if (canShare) {
- let desc = 'Share dashboard or panel';
- buttons.push(
- <ModalsController key="button-share">
- {({ showModal, hideModal }) => (
- <DashNavButton
- tooltip={desc}
- icon="share-alt"
- iconSize="lg"
- onClick={() => {
- showModal(ShareModal, {
- dashboard,
- onDismiss: hideModal,
- });
- }}
- />
- )}
- </ModalsController>
- );
- }
- if (dashboard.uid && config.featureToggles.dashboardComments) {
- buttons.push(
- <ModalsController key="button-dashboard-comments">
- {({ showModal, hideModal }) => (
- <DashNavButton
- tooltip="Show dashboard comments"
- icon="comment-alt-message"
- iconSize="lg"
- onClick={() => {
- showModal(DashboardCommentsModal, {
- dashboard,
- onDismiss: hideModal,
- });
- }}
- />
- )}
- </ModalsController>
- );
- }
- addCustomContent(customLeftActions, buttons);
- return buttons;
- };
- const renderPlaylistControls = () => {
- return (
- <ButtonGroup key="playlist-buttons">
- <ToolbarButton tooltip="Go to previous dashboard" icon="backward" onClick={onPlaylistPrev} narrow />
- <ToolbarButton onClick={onPlaylistStop}>Stop playlist</ToolbarButton>
- <ToolbarButton tooltip="Go to next dashboard" icon="forward" onClick={onPlaylistNext} narrow />
- </ButtonGroup>
- );
- };
- const renderTimeControls = () => {
- const { dashboard, updateTimeZoneForSession, hideTimePicker } = props;
- if (hideTimePicker) {
- return null;
- }
- return (
- <DashNavTimeControls dashboard={dashboard} onChangeTimeZone={updateTimeZoneForSession} key="time-controls" />
- );
- };
- const renderRightActionsButton = () => {
- const { dashboard, onAddPanel, isFullscreen, kioskMode } = props;
- const { canSave, canEdit, showSettings } = dashboard.meta;
- const { snapshot } = dashboard;
- const snapshotUrl = snapshot && snapshot.originalUrl;
- const buttons: ReactNode[] = [];
- const tvButton = (
- <ToolbarButton tooltip="Cycle view mode" icon="monitor" onClick={onToggleTVMode} key="tv-button" />
- );
- if (isPlaylistRunning()) {
- return [renderPlaylistControls(), renderTimeControls()];
- }
- if (kioskMode === KioskMode.TV) {
- return [renderTimeControls(), tvButton];
- }
- if (canEdit && !isFullscreen) {
- buttons.push(<ToolbarButton tooltip="Add panel" icon="panel-add" onClick={onAddPanel} key="button-panel-add" />);
- }
- if (canSave && !isFullscreen) {
- buttons.push(
- <ModalsController key="button-save">
- {({ showModal, hideModal }) => (
- <ToolbarButton
- tooltip="Save dashboard"
- icon="save"
- onClick={() => {
- showModal(SaveDashboardDrawer, {
- dashboard,
- onDismiss: hideModal,
- });
- }}
- />
- )}
- </ModalsController>
- );
- }
- if (snapshotUrl) {
- buttons.push(
- <ToolbarButton
- tooltip="Open original dashboard"
- onClick={() => gotoSnapshotOrigin(snapshotUrl)}
- icon="link"
- key="button-snapshot"
- />
- );
- }
- if (showSettings) {
- buttons.push(
- <ToolbarButton tooltip="Dashboard settings" icon="cog" onClick={onOpenSettings} key="button-settings" />
- );
- }
- addCustomContent(customRightActions, buttons);
- buttons.push(renderTimeControls());
- buttons.push(tvButton);
- return buttons;
- };
- const gotoSnapshotOrigin = (snapshotUrl: string) => {
- window.location.href = textUtil.sanitizeUrl(snapshotUrl);
- };
- const { isFullscreen, title, folderTitle } = props;
- // this ensures the component rerenders when the location changes
- const location = useLocation();
- const titleHref = locationUtil.getUrlForPartial(location, { search: 'open' });
- const parentHref = locationUtil.getUrlForPartial(location, { search: 'open', folder: 'current' });
- const onGoBack = isFullscreen ? onClose : undefined;
- return (
- <PageToolbar
- pageIcon={isFullscreen ? undefined : 'apps'}
- title={title}
- parent={folderTitle}
- titleHref={titleHref}
- parentHref={parentHref}
- onGoBack={onGoBack}
- leftItems={renderLeftActionsButton()}
- >
- {renderRightActionsButton()}
- </PageToolbar>
- );
- });
- DashNav.displayName = 'DashNav';
- export default connector(DashNav);
|