ShareExternally: Rename public dashboard section (#91928)

This commit is contained in:
Juan Cabanas 2024-08-14 17:03:19 -03:00 committed by GitHub
parent 34ab5fe1f3
commit 07500e11be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 94 additions and 105 deletions

View File

@ -1,3 +1,4 @@
import { config } from '@grafana/runtime';
import { t } from 'app/core/internationalization';
// Maps the ID of the nav item to a translated phrase to later pass to <Trans />
@ -43,7 +44,9 @@ export function getNavTitle(navId: string | undefined) {
case 'reports':
return t('nav.reporting.title', 'Reporting');
case 'dashboards/public':
return t('nav.public.title', 'Public dashboards');
return config.featureToggles.newDashboardSharingComponent
? t('nav.shared-dashboard.title', 'Shared dashboards')
: t('nav.public.title', 'Public dashboards');
case 'dashboards/recently-deleted':
return t('nav.recently-deleted.title', 'Recently deleted');
case 'dashboards/new':
@ -210,6 +213,10 @@ export function getNavSubTitle(navId: string | undefined) {
'nav.snapshots.subtitle',
'Interactive, publically available, point-in-time representations of dashboards'
);
case 'dashboards/public':
return config.featureToggles.newDashboardSharingComponent
? t('nav.shared-dashboard.subtitle', "Manage your organization's externally shared dashboards")
: undefined;
case 'dashboards/library-panels':
return t('nav.library-panels.subtitle', 'Reusable panels that can be added to multiple dashboards');
case 'dashboards/recently-deleted':

View File

@ -264,7 +264,6 @@ export function ConfigPublicDashboard({ publicDashboard, unsupportedDatasources
onRevoke={() => {
DashboardInteractions.revokePublicDashboardClicked();
showModal(DeletePublicDashboardModal, {
dashboardTitle: dashboard.title,
onConfirm: () => onDeletePublicDashboardClick(hideModal),
onDismiss: () => {
showModal(ShareModal, {

View File

@ -1,5 +1,6 @@
import * as React from 'react';
import { config } from '@grafana/runtime';
import { Button, ModalsController, ButtonProps } from '@grafana/ui/src';
import { t } from 'app/core/internationalization';
import { useDeletePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi';
@ -41,17 +42,15 @@ export const DeletePublicDashboardButton = ({
return (
<ModalsController>
{({ showModal, hideModal }) => {
const translatedRevocationButtonText = t(
'public-dashboard-list.button.revoke-button-text',
'Revoke public URL'
);
const translatedRevocationButtonText = config.featureToggles.newDashboardSharingComponent
? t('shared-dashboard-list.button.revoke-button-text', 'Revoke access')
: t('public-dashboard-list.button.revoke-button-text', 'Revoke public URL');
return (
<Button
aria-label={translatedRevocationButtonText}
title={translatedRevocationButtonText}
onClick={() =>
showModal(DeletePublicDashboardModal, {
dashboardTitle: publicDashboard.title,
onConfirm: () => onDeletePublicDashboardClick(publicDashboard, hideModal),
onDismiss: () => {
onDismiss ? onDismiss() : hideModal();

View File

@ -1,41 +1,42 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data/src';
import { config } from '@grafana/runtime';
import { ConfirmModal, useStyles2 } from '@grafana/ui/src';
import { t } from 'app/core/internationalization';
const Body = ({ title }: { title?: string }) => {
const Body = () => {
const styles = useStyles2(getStyles);
return (
<p className={styles.description}>
{title
{config.featureToggles.newDashboardSharingComponent
? t(
'public-dashboard.delete-modal.revoke-nonorphaned-body-text',
'Are you sure you want to revoke this URL? The dashboard will no longer be public.'
'shared-dashboard.delete-modal.revoke-body-text',
'Are you sure you want to revoke this access? The dashboard can no longer be shared.'
)
: t(
'public-dashboard.delete-modal.revoke-orphaned-body-text',
'Orphaned public dashboard will no longer be public.'
'public-dashboard.delete-modal.revoke-body-text',
'Are you sure you want to revoke this URL? The dashboard will no longer be public.'
)}
</p>
);
};
export const DeletePublicDashboardModal = ({
dashboardTitle,
onConfirm,
onDismiss,
}: {
dashboardTitle?: string;
onConfirm: () => void;
onDismiss: () => void;
}) => {
const translatedRevocationModalText = t('public-dashboard.delete-modal.revoke-title', 'Revoke public URL');
const translatedRevocationModalText = config.featureToggles.newDashboardSharingComponent
? t('shared-dashboard.delete-modal.revoke-title', 'Revoke access')
: t('public-dashboard.delete-modal.revoke-title', 'Revoke public URL');
return (
<ConfirmModal
isOpen
body={<Body title={dashboardTitle} />}
body={<Body />}
onConfirm={onConfirm}
onDismiss={onDismiss}
title={translatedRevocationModalText}

View File

@ -32,25 +32,6 @@ const publicDashboardListResponse: PublicDashboardListResponse[] = [
},
];
const orphanedDashboardListResponse: PublicDashboardListResponse[] = [
{
uid: 'SdZwuCZVz2',
accessToken: 'beeaf92f6ab3467f80b2be922c7741ab',
title: '',
dashboardUid: '',
isEnabled: false,
slug: '',
},
{
uid: 'EuiEbd3nz2',
accessToken: '8687b0498ccf4babb2f92810d8563b33',
title: '',
dashboardUid: '',
isEnabled: true,
slug: '',
},
];
const paginationResponse: Omit<PublicDashboardListWithPaginationResponse, 'publicDashboards'> = {
page: 1,
perPage: 50,
@ -165,26 +146,6 @@ describe('Delete public dashboard', () => {
});
});
describe('Orphaned public dashboard', () => {
it('renders orphaned and non orphaned public dashboards items correctly', async () => {
const response: PublicDashboardListWithPaginationResponse = {
...paginationResponse,
publicDashboards: [...publicDashboardListResponse, ...orphanedDashboardListResponse],
};
server.use(
http.get('/api/dashboards/public-dashboards', () => {
return HttpResponse.json(response);
})
);
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
await renderPublicDashboardTable(true);
response.publicDashboards.forEach((pd, idx) => {
renderPublicDashboardItemCorrectly(pd, idx, true);
});
});
});
const renderPublicDashboardItemCorrectly = (pd: PublicDashboardListResponse, idx: number, hasWriteAccess: boolean) => {
const isOrphaned = !pd.dashboardUid;

View File

@ -4,23 +4,21 @@ import { useMedia } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
import { reportInteraction } from '@grafana/runtime';
import { config, reportInteraction } from '@grafana/runtime';
import {
LinkButton,
useStyles2,
Spinner,
Card,
useTheme2,
Tooltip,
Icon,
Switch,
Pagination,
HorizontalGroup,
EmptyState,
HorizontalGroup,
LinkButton,
Pagination,
Spinner,
Switch,
TextLink,
useStyles2,
useTheme2,
} from '@grafana/ui';
import { Page } from 'app/core/components/Page/Page';
import { Trans, t } from 'app/core/internationalization';
import { t, Trans } from 'app/core/internationalization';
import { contextSrv } from 'app/core/services/context_srv';
import {
useListPublicDashboardsQuery,
@ -45,7 +43,6 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
const selectors = e2eSelectors.pages.PublicDashboards;
const hasWritePermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPublicWrite);
const isOrphaned = !pd.dashboardUid;
const onTogglePause = (pd: PublicDashboardListResponse, isPaused: boolean) => {
const req = {
@ -60,29 +57,16 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
};
const CardActions = useMemo(() => (isMobile ? Card.Actions : Card.SecondaryActions), [isMobile]);
const translatedPauseSharingText = t('public-dashboard-list.toggle.pause-sharing-toggle-text', 'Pause sharing');
const isNewSharingComponentEnabled = config.featureToggles.newDashboardSharingComponent;
const translatedPauseSharingText = isNewSharingComponentEnabled
? t('shared-dashboard-list.toggle.pause-sharing-toggle-text', 'Pause access')
: t('public-dashboard-list.toggle.pause-sharing-toggle-text', 'Pause sharing');
return (
<Card className={styles.card} href={!isOrphaned ? `/d/${pd.dashboardUid}` : undefined}>
<Card className={styles.card} href={`/d/${pd.dashboardUid}`}>
<Card.Heading className={styles.heading}>
{!isOrphaned ? (
<span>{pd.title}</span>
) : (
<Tooltip
content={t(
'public-dashboard-list.dashboard-title.orphaned-tooltip',
'The linked dashboard has already been deleted'
)}
placement="top"
>
<div className={styles.orphanedTitle}>
<Trans i18nKey="public-dashboard-list.dashboard-title.orphaned-title">
<span>Orphaned public dashboard</span>
</Trans>
<Icon name="info-circle" />
</div>
</Tooltip>
)}
<span>{pd.title}</span>
</Card.Heading>
<CardActions className={styles.actions}>
<div className={styles.pauseSwitch}>
@ -101,7 +85,6 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
<span>{translatedPauseSharingText}</span>
</div>
<LinkButton
disabled={isOrphaned}
fill="text"
icon="external-link-alt"
variant="secondary"
@ -109,18 +92,25 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
color={theme.colors.warning.text}
href={generatePublicDashboardUrl(pd.accessToken)}
key="public-dashboard-url"
tooltip={t('public-dashboard-list.button.view-button-tooltip', 'View public dashboard')}
tooltip={
isNewSharingComponentEnabled
? t('shared-dashboard-list.button.view-button-tooltip', 'View shared dashboard')
: t('public-dashboard-list.button.view-button-tooltip', 'View public dashboard')
}
data-testid={selectors.ListItem.linkButton}
/>
<LinkButton
disabled={isOrphaned}
fill="text"
icon="cog"
variant="secondary"
color={theme.colors.warning.text}
href={generatePublicDashboardConfigUrl(pd.dashboardUid, pd.slug)}
key="public-dashboard-config-url"
tooltip={t('public-dashboard-list.button.config-button-tooltip', 'Configure public dashboard')}
tooltip={
isNewSharingComponentEnabled
? t('shared-dashboard-list.button.config-button-tooltip', 'Configure shared dashboard')
: t('public-dashboard-list.button.config-button-tooltip', 'Configure public dashboard')
}
data-testid={selectors.ListItem.configButton}
/>
{hasWritePermissions && (
@ -129,7 +119,11 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
icon="trash-alt"
variant="secondary"
publicDashboard={pd}
tooltip={t('public-dashboard-list.button.revoke-button-tooltip', 'Revoke public dashboard URL')}
tooltip={
isNewSharingComponentEnabled
? t('shared-dashboard-list.button.revoke-button-tooltip', 'Revoke access')
: t('public-dashboard-list.button.revoke-button-tooltip', 'Revoke public dashboard URL')
}
loader={<Spinner />}
data-testid={selectors.ListItem.trashcanButton}
/>

View File

@ -1519,6 +1519,10 @@
"subtitle": "Use service accounts to run automated workloads in Grafana",
"title": "Service accounts"
},
"shared-dashboard": {
"subtitle": "Manage your organization's externally shared dashboards",
"title": "Shared dashboards"
},
"sign-out": {
"title": "Sign out"
},
@ -1744,8 +1748,7 @@
"welcome-title": "Welcome to public dashboards!"
},
"delete-modal": {
"revoke-nonorphaned-body-text": "Are you sure you want to revoke this URL? The dashboard will no longer be public.",
"revoke-orphaned-body-text": "Orphaned public dashboard will no longer be public.",
"revoke-body-text": "Are you sure you want to revoke this URL? The dashboard will no longer be public.",
"revoke-title": "Revoke public URL"
},
"email-sharing": {
@ -1844,10 +1847,6 @@
"revoke-button-tooltip": "Revoke public dashboard URL",
"view-button-tooltip": "View public dashboard"
},
"dashboard-title": {
"orphaned-title": "<0>Orphaned public dashboard</0>",
"orphaned-tooltip": "The linked dashboard has already been deleted"
},
"empty-state": {
"message": "You haven't created any public dashboards yet",
"more-info": "Create a public dashboard from any existing dashboard through the <1>Share</1> modal. <4>Learn more</4>"
@ -2160,10 +2159,25 @@
}
},
"shared-dashboard": {
"delete-modal": {
"revoke-body-text": "Are you sure you want to revoke this access? The dashboard can no longer be shared.",
"revoke-title": "Revoke access"
},
"fields": {
"timezone-label": "Timezone"
}
},
"shared-dashboard-list": {
"button": {
"config-button-tooltip": "Configure shared dashboard",
"revoke-button-text": "Revoke access",
"revoke-button-tooltip": "Revoke access",
"view-button-tooltip": "View shared dashboard"
},
"toggle": {
"pause-sharing-toggle-text": "Pause access"
}
},
"shared-preferences": {
"fields": {
"home-dashboard-label": "Home Dashboard",

View File

@ -1519,6 +1519,10 @@
"subtitle": "Ůşę şęřvįčę äččőūʼnŧş ŧő řūʼn äūŧőmäŧęđ ŵőřĸľőäđş įʼn Ğřäƒäʼnä",
"title": "Ŝęřvįčę äččőūʼnŧş"
},
"shared-dashboard": {
"subtitle": "Mäʼnäģę yőūř őřģäʼnįžäŧįőʼn'ş ęχŧęřʼnäľľy şĥäřęđ đäşĥþőäřđş",
"title": "Ŝĥäřęđ đäşĥþőäřđş"
},
"sign-out": {
"title": "Ŝįģʼn őūŧ"
},
@ -1744,8 +1748,7 @@
"welcome-title": "Ŵęľčőmę ŧő pūþľįč đäşĥþőäřđş!"
},
"delete-modal": {
"revoke-nonorphaned-body-text": "Åřę yőū şūřę yőū ŵäʼnŧ ŧő řęvőĸę ŧĥįş ŮŖĿ? Ŧĥę đäşĥþőäřđ ŵįľľ ʼnő ľőʼnģęř þę pūþľįč.",
"revoke-orphaned-body-text": "Øřpĥäʼnęđ pūþľįč đäşĥþőäřđ ŵįľľ ʼnő ľőʼnģęř þę pūþľįč.",
"revoke-body-text": "Åřę yőū şūřę yőū ŵäʼnŧ ŧő řęvőĸę ŧĥįş ŮŖĿ? Ŧĥę đäşĥþőäřđ ŵįľľ ʼnő ľőʼnģęř þę pūþľįč.",
"revoke-title": "Ŗęvőĸę pūþľįč ŮŖĿ"
},
"email-sharing": {
@ -1844,10 +1847,6 @@
"revoke-button-tooltip": "Ŗęvőĸę pūþľįč đäşĥþőäřđ ŮŖĿ",
"view-button-tooltip": "Vįęŵ pūþľįč đäşĥþőäřđ"
},
"dashboard-title": {
"orphaned-title": "<0>Øřpĥäʼnęđ pūþľįč đäşĥþőäřđ</0>",
"orphaned-tooltip": "Ŧĥę ľįʼnĸęđ đäşĥþőäřđ ĥäş äľřęäđy þęęʼn đęľęŧęđ"
},
"empty-state": {
"message": "Ÿőū ĥävęʼn'ŧ čřęäŧęđ äʼny pūþľįč đäşĥþőäřđş yęŧ",
"more-info": "Cřęäŧę ä pūþľįč đäşĥþőäřđ ƒřőm äʼny ęχįşŧįʼnģ đäşĥþőäřđ ŧĥřőūģĥ ŧĥę <1>Ŝĥäřę</1> mőđäľ. <4>Ŀęäřʼn mőřę</4>"
@ -2160,10 +2159,25 @@
}
},
"shared-dashboard": {
"delete-modal": {
"revoke-body-text": "Åřę yőū şūřę yőū ŵäʼnŧ ŧő řęvőĸę ŧĥįş äččęşş? Ŧĥę đäşĥþőäřđ čäʼn ʼnő ľőʼnģęř þę şĥäřęđ.",
"revoke-title": "Ŗęvőĸę äččęşş"
},
"fields": {
"timezone-label": "Ŧįmęžőʼnę"
}
},
"shared-dashboard-list": {
"button": {
"config-button-tooltip": "Cőʼnƒįģūřę şĥäřęđ đäşĥþőäřđ",
"revoke-button-text": "Ŗęvőĸę äččęşş",
"revoke-button-tooltip": "Ŗęvőĸę äččęşş",
"view-button-tooltip": "Vįęŵ şĥäřęđ đäşĥþőäřđ"
},
"toggle": {
"pause-sharing-toggle-text": "Päūşę äččęşş"
}
},
"shared-preferences": {
"fields": {
"home-dashboard-label": "Ħőmę Đäşĥþőäřđ",