UI: New share button and toolbar reorganize (#77563)

This commit is contained in:
Ezequiel Victorero 2024-01-08 10:42:24 -03:00 committed by GitHub
parent eae6adf002
commit 25ff4baa76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 83 additions and 94 deletions

View File

@ -14,7 +14,7 @@ describe('Public dashboards', () => {
cy.wait('@query'); cy.wait('@query');
// Open sharing modal // Open sharing modal
e2e.pages.ShareDashboardModal.shareButton().click(); e2e.pages.Dashboard.DashNav.shareButton().click();
// Select public dashboards tab // Select public dashboards tab
e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click(); e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click();
@ -74,7 +74,7 @@ describe('Public dashboards', () => {
e2e.pages.Dashboard.DashNav.publicDashboardTag().should('exist'); e2e.pages.Dashboard.DashNav.publicDashboardTag().should('exist');
// Open sharing modal // Open sharing modal
e2e.pages.ShareDashboardModal.shareButton().click(); e2e.pages.Dashboard.DashNav.shareButton().click();
// Select public dashboards tab // Select public dashboards tab
cy.intercept('GET', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('query-public-dashboard'); cy.intercept('GET', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('query-public-dashboard');
@ -114,7 +114,7 @@ describe('Public dashboards', () => {
cy.wait('@query'); cy.wait('@query');
// Open sharing modal // Open sharing modal
e2e.pages.ShareDashboardModal.shareButton().click(); e2e.pages.Dashboard.DashNav.shareButton().click();
// Select public dashboards tab // Select public dashboards tab
cy.intercept('GET', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('query-public-dashboard'); cy.intercept('GET', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('query-public-dashboard');

View File

@ -10,7 +10,7 @@ describe('Create a public dashboard with template variables shows a template var
e2e.flows.openDashboard({ uid: 'HYaGDGIMk' }); e2e.flows.openDashboard({ uid: 'HYaGDGIMk' });
// Open sharing modal // Open sharing modal
e2e.pages.ShareDashboardModal.shareButton().click(); e2e.pages.Dashboard.DashNav.shareButton().click();
// Select public dashboards tab // Select public dashboards tab
e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click(); e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click();

View File

@ -56,6 +56,7 @@ export const Pages = {
nav: 'Dashboard navigation', nav: 'Dashboard navigation',
navV2: 'data-testid Dashboard navigation', navV2: 'data-testid Dashboard navigation',
publicDashboardTag: 'data-testid public dashboard tag', publicDashboardTag: 'data-testid public dashboard tag',
shareButton: 'data-testid share-button',
}, },
SubMenu: { SubMenu: {
submenu: 'Dashboard submenu', submenu: 'Dashboard submenu',
@ -208,7 +209,6 @@ export const Pages = {
linkToRenderedImage: 'Link to rendered image', linkToRenderedImage: 'Link to rendered image',
}, },
ShareDashboardModal: { ShareDashboardModal: {
shareButton: 'Share dashboard',
PublicDashboard: { PublicDashboard: {
Tab: 'Tab Public dashboard', Tab: 'Tab Public dashboard',
WillBePublicCheckbox: 'data-testid public dashboard will be public checkbox', WillBePublicCheckbox: 'data-testid public dashboard will be public checkbox',

View File

@ -1,9 +1,7 @@
import { css, cx } from '@emotion/css';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { Dropdown, Button, useTheme2, Icon } from '@grafana/ui'; import { Dropdown, Button, Icon } from '@grafana/ui';
import { Trans } from 'app/core/internationalization'; import { Trans } from 'app/core/internationalization';
import { DashboardModel } from 'app/features/dashboard/state'; import { DashboardModel } from 'app/features/dashboard/state';
@ -15,7 +13,6 @@ export interface Props {
} }
const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen }: Props) => { const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen }: Props) => {
const styles = getStyles(useTheme2());
const [isMenuOpen, setIsMenuOpen] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false);
useEffect(() => { useEffect(() => {
@ -32,10 +29,9 @@ const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen }: Props) => {
onVisibleChange={setIsMenuOpen} onVisibleChange={setIsMenuOpen}
> >
<Button <Button
icon="panel-add" variant="secondary"
size="lg" size="sm"
fill="text" fill="outline"
className={cx(styles.button, styles.buttonIcon, styles.buttonText)}
data-testid={selectors.components.PageToolbar.itemButton('Add button')} data-testid={selectors.components.PageToolbar.itemButton('Add button')}
> >
<Trans i18nKey="dashboard.toolbar.add">Add</Trans> <Trans i18nKey="dashboard.toolbar.add">Add</Trans>
@ -46,26 +42,3 @@ const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen }: Props) => {
}; };
export default AddPanelButton; export default AddPanelButton;
function getStyles(theme: GrafanaTheme2) {
return {
button: css({
label: 'add-panel-button',
padding: theme.spacing(0.5, 0.5, 0.5, 0.75),
height: theme.spacing((theme.components.height.sm + theme.components.height.md) / 2),
borderRadius: theme.shape.radius.default,
}),
buttonIcon: css({
svg: {
margin: 0,
},
}),
buttonText: css({
label: 'add-panel-button-text',
fontSize: theme.typography.body.fontSize,
span: {
marginLeft: theme.spacing(0.67),
},
}),
};
}

View File

@ -11,9 +11,9 @@ import {
ModalsController, ModalsController,
ToolbarButton, ToolbarButton,
useForceUpdate, useForceUpdate,
Tag,
ToolbarButtonRow, ToolbarButtonRow,
ConfirmModal, ConfirmModal,
Badge,
} from '@grafana/ui'; } from '@grafana/ui';
import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate'; import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator'; import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator';
@ -163,7 +163,7 @@ export const DashNav = React.memo<Props>((props) => {
const renderLeftActions = () => { const renderLeftActions = () => {
const { dashboard, kioskMode } = props; const { dashboard, kioskMode } = props;
const { canStar, canShare, isStarred } = dashboard.meta; const { canStar, isStarred } = dashboard.meta;
const buttons: ReactNode[] = []; const buttons: ReactNode[] = [];
if (kioskMode || isPlaylistRunning()) { if (kioskMode || isPlaylistRunning()) {
@ -186,13 +186,10 @@ export const DashNav = React.memo<Props>((props) => {
); );
} }
if (canShare) {
buttons.push(<ShareButton key="button-share" dashboard={dashboard} />);
}
if (dashboard.meta.publicDashboardEnabled) { if (dashboard.meta.publicDashboardEnabled) {
// TODO: This will be replaced with the new badge component. Color is required but gets override by css
buttons.push( buttons.push(
<Tag key="public-dashboard" name="Public" colorIndex={5} data-testid={selectors.publicDashboardTag}></Tag> <Badge color="blue" text="Public" className={publicBadgeStyle} data-testid={selectors.publicDashboardTag} />
); );
} }
@ -255,7 +252,7 @@ export const DashNav = React.memo<Props>((props) => {
const renderRightActions = () => { const renderRightActions = () => {
const { dashboard, onAddPanel, isFullscreen, kioskMode } = props; const { dashboard, onAddPanel, isFullscreen, kioskMode } = props;
const { canSave, canEdit, showSettings } = dashboard.meta; const { canSave, canEdit, showSettings, canShare } = dashboard.meta;
const { snapshot } = dashboard; const { snapshot } = dashboard;
const snapshotUrl = snapshot && snapshot.originalUrl; const snapshotUrl = snapshot && snapshot.originalUrl;
const buttons: ReactNode[] = []; const buttons: ReactNode[] = [];
@ -268,6 +265,50 @@ export const DashNav = React.memo<Props>((props) => {
return [renderTimeControls()]; return [renderTimeControls()];
} }
if (snapshotUrl) {
buttons.push(
<ToolbarButton
tooltip={t('dashboard.toolbar.open-original', 'Open original dashboard')}
onClick={onOpenSnapshotOriginal}
icon="link"
key="button-snapshot"
/>
);
}
if (canSave && !isFullscreen) {
buttons.push(
<ModalsController key="button-save">
{({ showModal, hideModal }) => (
<ToolbarButton
tooltip={t('dashboard.toolbar.save', 'Save dashboard')}
icon="save"
onClick={() => {
DashboardInteractions.toolbarSaveClick();
showModal(SaveDashboardDrawer, {
dashboard,
onDismiss: hideModal,
});
}}
/>
)}
</ModalsController>
);
}
addCustomContent(dynamicDashNavActions.right, buttons);
if (showSettings) {
buttons.push(
<ToolbarButton
tooltip={t('dashboard.toolbar.settings', 'Dashboard settings')}
icon="cog"
onClick={onOpenSettings}
key="button-settings"
/>
);
}
if (canEdit && !isFullscreen) { if (canEdit && !isFullscreen) {
if (config.featureToggles.emptyDashboardPage) { if (config.featureToggles.emptyDashboardPage) {
buttons.push( buttons.push(
@ -290,49 +331,11 @@ export const DashNav = React.memo<Props>((props) => {
} }
} }
if (canSave && !isFullscreen) { if (canShare) {
buttons.push( buttons.push(<ShareButton key="button-share" dashboard={dashboard} />);
<ModalsController key="button-save">
{({ showModal, hideModal }) => (
<ToolbarButton
tooltip={t('dashboard.toolbar.save', 'Save dashboard')}
icon="save"
onClick={() => {
DashboardInteractions.toolbarSaveClick();
showModal(SaveDashboardDrawer, {
dashboard,
onDismiss: hideModal,
});
}}
/>
)}
</ModalsController>
);
} }
if (snapshotUrl) { buttons.push(<NavToolbarSeparator key="toolbar-separator" />);
buttons.push(
<ToolbarButton
tooltip={t('dashboard.toolbar.open-original', 'Open original dashboard')}
onClick={onOpenSnapshotOriginal}
icon="link"
key="button-snapshot"
/>
);
}
if (showSettings) {
buttons.push(
<ToolbarButton
tooltip={t('dashboard.toolbar.settings', 'Dashboard settings')}
icon="cog"
onClick={onOpenSettings}
key="button-settings"
/>
);
}
addCustomContent(dynamicDashNavActions.right, buttons);
buttons.push(renderTimeControls()); buttons.push(renderTimeControls());
@ -360,3 +363,9 @@ const modalStyles = css({
width: 'max-content', width: 'max-content',
maxWidth: '80vw', maxWidth: '80vw',
}); });
const publicBadgeStyle = css({
color: 'grey',
backgroundColor: 'transparent',
border: '1px solid',
});

View File

@ -1,15 +1,14 @@
import React, { useContext, useEffect } from 'react'; import React, { useContext, useEffect } from 'react';
import { ModalsContext } from '@grafana/ui'; import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
import { ModalsContext, Button } from '@grafana/ui';
import { useQueryParams } from 'app/core/hooks/useQueryParams'; import { useQueryParams } from 'app/core/hooks/useQueryParams';
import { t } from 'app/core/internationalization'; import { Trans } from 'app/core/internationalization';
import { DashboardModel } from 'app/features/dashboard/state'; import { DashboardModel } from 'app/features/dashboard/state';
import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions'; import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions';
import { ShareModal } from '../ShareModal'; import { ShareModal } from '../ShareModal';
import { DashNavButton } from './DashNavButton';
export const ShareButton = ({ dashboard }: { dashboard: DashboardModel }) => { export const ShareButton = ({ dashboard }: { dashboard: DashboardModel }) => {
const [queryParams] = useQueryParams(); const [queryParams] = useQueryParams();
const { showModal, hideModal } = useContext(ModalsContext); const { showModal, hideModal } = useContext(ModalsContext);
@ -28,10 +27,10 @@ export const ShareButton = ({ dashboard }: { dashboard: DashboardModel }) => {
}, [showModal, hideModal, dashboard, queryParams.shareView]); }, [showModal, hideModal, dashboard, queryParams.shareView]);
return ( return (
<DashNavButton <Button
tooltip={t('dashboard.toolbar.share', 'Share dashboard')} data-testid={e2eSelectors.pages.Dashboard.DashNav.shareButton}
icon="share-alt" variant="primary"
iconSize="lg" size="sm"
onClick={() => { onClick={() => {
DashboardInteractions.toolbarShareClick(); DashboardInteractions.toolbarShareClick();
showModal(ShareModal, { showModal(ShareModal, {
@ -39,6 +38,8 @@ export const ShareButton = ({ dashboard }: { dashboard: DashboardModel }) => {
onDismiss: hideModal, onDismiss: hideModal,
}); });
}} }}
/> >
<Trans i18nKey="dashboard.toolbar.share-button">Share</Trans>
</Button>
); );
}; };

View File

@ -311,6 +311,7 @@
"save": "Dashboard speichern", "save": "Dashboard speichern",
"settings": "Dashboard-Einstellungen", "settings": "Dashboard-Einstellungen",
"share": "Dashboard oder Panel teilen", "share": "Dashboard oder Panel teilen",
"share-button": "",
"unmark-favorite": "Markierung als Favorit entfernen" "unmark-favorite": "Markierung als Favorit entfernen"
}, },
"validation": { "validation": {

View File

@ -311,6 +311,7 @@
"save": "Save dashboard", "save": "Save dashboard",
"settings": "Dashboard settings", "settings": "Dashboard settings",
"share": "Share dashboard", "share": "Share dashboard",
"share-button": "Share",
"unmark-favorite": "Unmark as favorite" "unmark-favorite": "Unmark as favorite"
}, },
"validation": { "validation": {

View File

@ -316,6 +316,7 @@
"save": "Guardar panel de control", "save": "Guardar panel de control",
"settings": "Ajustes del panel de control", "settings": "Ajustes del panel de control",
"share": "Compartir panel o panel de control", "share": "Compartir panel o panel de control",
"share-button": "",
"unmark-favorite": "Deshacer marca como favorito" "unmark-favorite": "Deshacer marca como favorito"
}, },
"validation": { "validation": {

View File

@ -316,6 +316,7 @@
"save": "Enregistrer le tableau de bord", "save": "Enregistrer le tableau de bord",
"settings": "Paramètres du tableau de bord", "settings": "Paramètres du tableau de bord",
"share": "Partager le tableau de bord ou le panneau", "share": "Partager le tableau de bord ou le panneau",
"share-button": "",
"unmark-favorite": "Supprimer des favoris" "unmark-favorite": "Supprimer des favoris"
}, },
"validation": { "validation": {

View File

@ -311,6 +311,7 @@
"save": "Ŝävę đäşĥþőäřđ", "save": "Ŝävę đäşĥþőäřđ",
"settings": "Đäşĥþőäřđ şęŧŧįʼnģş", "settings": "Đäşĥþőäřđ şęŧŧįʼnģş",
"share": "Ŝĥäřę đäşĥþőäřđ", "share": "Ŝĥäřę đäşĥþőäřđ",
"share-button": "Ŝĥäřę",
"unmark-favorite": "Ůʼnmäřĸ äş ƒävőřįŧę" "unmark-favorite": "Ůʼnmäřĸ äş ƒävőřįŧę"
}, },
"validation": { "validation": {

View File

@ -306,6 +306,7 @@
"save": "保存仪表板", "save": "保存仪表板",
"settings": "仪表板设置", "settings": "仪表板设置",
"share": "分享仪表板或面板", "share": "分享仪表板或面板",
"share-button": "",
"unmark-favorite": "取消标记为收藏" "unmark-favorite": "取消标记为收藏"
}, },
"validation": { "validation": {