NavBar: app chrome state wrongly overwritten when ds modal is opened (#67952)

This commit is contained in:
Juan Cabanas
2023-05-08 16:51:42 -03:00
committed by GitHub
parent da21473527
commit 24668137f8
9 changed files with 67 additions and 50 deletions

View File

@@ -1,5 +1,5 @@
import { css } from '@emotion/css';
import React, { FC, ReactNode, useContext, useEffect } from 'react';
import React, { FC, ReactNode } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { useLocation } from 'react-router-dom';
@@ -13,7 +13,6 @@ import {
useForceUpdate,
Tag,
ToolbarButtonRow,
ModalsContext,
ConfirmModal,
} from '@grafana/ui';
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
@@ -26,7 +25,6 @@ import { t, Trans } from 'app/core/internationalization';
import { setStarred } from 'app/core/reducers/navBarTree';
import { AddPanelButton } from 'app/features/dashboard/components/AddPanelButton/AddPanelButton';
import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer';
import { ShareModal } from 'app/features/dashboard/components/ShareModal';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { DashboardModel } from 'app/features/dashboard/state';
import { playlistSrv } from 'app/features/playlist/PlaylistSrv';
@@ -36,6 +34,7 @@ import { DashboardMetaChangedEvent, ShowModalReactEvent } from 'app/types/events
import { DashNavButton } from './DashNavButton';
import { DashNavTimeControls } from './DashNavTimeControls';
import { ShareButton } from './ShareButton';
const mapDispatchToProps = {
setStarred,
@@ -53,7 +52,6 @@ export interface OwnProps {
hideTimePicker: boolean;
folderTitle?: string;
title: string;
shareModalActiveTab?: string;
onAddPanel: () => void;
}
@@ -80,7 +78,6 @@ export const DashNav = React.memo<Props>((props) => {
// this ensures the component rerenders when the location changes
useLocation();
const forceUpdate = useForceUpdate();
const { showModal, hideModal } = useContext(ModalsContext);
// We don't really care about the event payload here only that it triggeres a re-render of this component
useBusEvent(props.dashboard.events, DashboardMetaChangedEvent);
@@ -164,25 +161,6 @@ export const DashNav = React.memo<Props>((props) => {
return playlistSrv.isPlaying;
};
// Open/Close
useEffect(() => {
const dashboard = props.dashboard;
const shareModalActiveTab = props.shareModalActiveTab;
const { canShare } = dashboard.meta;
if (canShare && shareModalActiveTab) {
// automagically open modal
showModal(ShareModal, {
dashboard,
onDismiss: hideModal,
activeTab: shareModalActiveTab,
});
}
return () => {
hideModal();
};
}, [showModal, hideModal, props.dashboard, props.shareModalActiveTab]);
const renderLeftActions = () => {
const { dashboard, kioskMode } = props;
const { canStar, canShare, isStarred } = dashboard.meta;
@@ -209,23 +187,7 @@ export const DashNav = React.memo<Props>((props) => {
}
if (canShare) {
buttons.push(
<ModalsController key="button-share">
{({ showModal, hideModal }) => (
<DashNavButton
tooltip={t('dashboard.toolbar.share', 'Share dashboard or panel')}
icon="share-alt"
iconSize="lg"
onClick={() => {
showModal(ShareModal, {
dashboard,
onDismiss: hideModal,
});
}}
/>
)}
</ModalsController>
);
buttons.push(<ShareButton key="button-share" dashboard={dashboard} />);
}
if (dashboard.meta.publicDashboardEnabled) {

View File

@@ -0,0 +1,42 @@
import React, { useContext, useEffect } from 'react';
import { ModalsContext } from '@grafana/ui';
import { useQueryParams } from 'app/core/hooks/useQueryParams';
import { t } from 'app/core/internationalization';
import { DashboardModel } from 'app/features/dashboard/state';
import { ShareModal } from '../ShareModal';
import { DashNavButton } from './DashNavButton';
export const ShareButton = ({ dashboard }: { dashboard: DashboardModel }) => {
const [queryParams] = useQueryParams();
const { showModal, hideModal } = useContext(ModalsContext);
useEffect(() => {
if (!!queryParams.shareView) {
showModal(ShareModal, {
dashboard,
onDismiss: hideModal,
activeTab: String(queryParams.shareView),
});
}
return () => {
hideModal();
};
}, [showModal, hideModal, dashboard, queryParams.shareView]);
return (
<DashNavButton
tooltip={t('dashboard.toolbar.share', 'Share dashboard or panel')}
icon="share-alt"
iconSize="lg"
onClick={() => {
showModal(ShareModal, {
dashboard,
onDismiss: hideModal,
});
}}
/>
);
};

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { reportInteraction } from '@grafana/runtime/src';
import { locationService, reportInteraction } from '@grafana/runtime/src';
import { Modal, ModalTabsHeader, TabContent } from '@grafana/ui';
import { config } from 'app/core/config';
import { contextSrv } from 'app/core/core';
@@ -52,7 +52,7 @@ function getTabs(panel?: PanelModel, activeTab?: string) {
}
if (Boolean(config.featureToggles['publicDashboards'])) {
tabs.push({ label: 'Public dashboard', value: 'share', component: SharePublicDashboard });
tabs.push({ label: 'Public dashboard', value: 'public-dashboard', component: SharePublicDashboard });
}
const at = tabs.find((t) => t.value === activeTab);
@@ -95,6 +95,10 @@ export class ShareModal extends React.Component<Props, State> {
reportInteraction('grafana_dashboards_share_modal_viewed');
}
componentWillUnmount() {
locationService.partial({ shareView: null });
}
onSelectTab: React.ComponentProps<typeof ModalTabsHeader>['onChangeTab'] = (t) => {
this.setState((prevState) => ({ ...prevState, activeTab: t.value }));
};

View File

@@ -76,4 +76,8 @@ export const generatePublicDashboardUrl = (accessToken: string): string => {
return `${getConfig().appUrl}public-dashboards/${accessToken}`;
};
export const generatePublicDashboardConfigUrl = (dashboardUid: string): string => {
return `/d/${dashboardUid}?shareView=public-dashboard`;
};
export const validEmailRegex = /^[A-Z\d._%+-]+@[A-Z\d.-]+\.[A-Z]{2,}$/i;