mirror of https://github.com/grafana/grafana.git
Share: Remove new share drawer feature flag (#111048)
This commit is contained in:
parent
0baacd8d5a
commit
6811cc1aa9
|
@ -56,7 +56,6 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general-
|
|||
| `newPDFRendering` | New implementation for the dashboard-to-PDF rendering | Yes |
|
||||
| `tlsMemcached` | Use TLS-enabled memcached in the enterprise caching feature | Yes |
|
||||
| `cloudWatchNewLabelParsing` | Updates CloudWatch label parsing to be more accurate | Yes |
|
||||
| `newDashboardSharingComponent` | Enables the new sharing drawer design | Yes |
|
||||
| `pluginProxyPreserveTrailingSlash` | Preserve plugin proxy trailing slash. | |
|
||||
| `azureMonitorPrometheusExemplars` | Allows configuration of Azure Monitor as a data source that can provide Prometheus exemplars | Yes |
|
||||
| `pinNavItems` | Enables pinning of nav items | Yes |
|
||||
|
|
|
@ -5,7 +5,6 @@ const DASHBOARD_UID = 'ZqZnVvFZz';
|
|||
test.use({
|
||||
featureToggles: {
|
||||
scenes: true,
|
||||
newDashboardSharingComponent: true,
|
||||
sharingDashboardImage: true, // Enable the export image feature
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
},
|
||||
|
|
|
@ -2,8 +2,8 @@ import { test, expect } from '@grafana/plugin-e2e';
|
|||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
newDashboardSharingComponent: false,
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
dashboardScene: false, // this test is for the old sharing modal only used when scenes is turned off
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -18,10 +18,10 @@ test.describe(
|
|||
let dashboardPage = await gotoDashboardPage({ uid: 'ZqZnVvFZz' });
|
||||
|
||||
// Open sharing modal
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.shareDashboard).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.DashNav.shareButton).click();
|
||||
|
||||
// Select public dashboards tab
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public Dashboard')).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public dashboard')).click();
|
||||
|
||||
// Create button should be disabled
|
||||
await expect(
|
||||
|
@ -120,10 +120,10 @@ test.describe(
|
|||
).toBeVisible();
|
||||
|
||||
// Open sharing modal
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.shareDashboard).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.DashNav.shareButton).click();
|
||||
|
||||
// Select public dashboards tab
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public Dashboard')).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public dashboard')).click();
|
||||
|
||||
await expect(
|
||||
dashboardPage.getByGrafanaSelector(selectors.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput)
|
||||
|
@ -171,10 +171,10 @@ test.describe(
|
|||
dashboardPage = await gotoDashboardPage({ uid: 'ZqZnVvFZz' });
|
||||
|
||||
// Open sharing modal
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.shareDashboard).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.DashNav.shareButton).click();
|
||||
|
||||
// Select public dashboards tab
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public Dashboard')).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public dashboard')).click();
|
||||
|
||||
// Save url before disabling public dashboard
|
||||
copyUrlInput = dashboardPage.getByGrafanaSelector(
|
||||
|
|
|
@ -2,8 +2,8 @@ import { test, expect } from '@grafana/plugin-e2e';
|
|||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
newDashboardSharingComponent: false,
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
dashboardScene: false, // this test is for the old sharing modal only used when scenes is turned off
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -23,10 +23,10 @@ test.describe(
|
|||
});
|
||||
|
||||
// Open sharing modal
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.shareDashboard).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.DashNav.shareButton).click();
|
||||
|
||||
// Select public dashboards tab
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public Dashboard')).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Public dashboard')).click();
|
||||
|
||||
// Warning Alert dashboard cannot be made public because it has template variables
|
||||
await expect(
|
||||
|
|
|
@ -3,7 +3,6 @@ import { test, expect } from '@grafana/plugin-e2e';
|
|||
test.use({
|
||||
featureToggles: {
|
||||
scenes: true,
|
||||
newDashboardSharingComponent: true,
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,7 +3,6 @@ import { test, expect } from '@grafana/plugin-e2e';
|
|||
test.use({
|
||||
featureToggles: {
|
||||
scenes: true,
|
||||
newDashboardSharingComponent: true,
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -5,7 +5,6 @@ import { SnapshotCreateResponse } from '../../public/app/features/dashboard/serv
|
|||
test.use({
|
||||
featureToggles: {
|
||||
scenes: true,
|
||||
newDashboardSharingComponent: true,
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
},
|
||||
});
|
||||
|
|
|
@ -4,8 +4,8 @@ const DASHBOARD_UID = 'ZqZnVvFZz';
|
|||
|
||||
test.use({
|
||||
featureToggles: {
|
||||
newDashboardSharingComponent: false, // Use legacy sharing component for this test
|
||||
kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true',
|
||||
dashboardScene: false, // this test is for the old sharing modal only used when scenes is turned off
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -29,7 +29,7 @@ test.describe(
|
|||
];
|
||||
|
||||
// Open the sharing modal
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.shareDashboard).click();
|
||||
await dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.DashNav.shareButton).click();
|
||||
|
||||
// Select the snapshot tab
|
||||
await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Snapshot')).click();
|
||||
|
@ -54,9 +54,6 @@ test.describe(
|
|||
const snapshotKey = getSnapshotKey(snapshotUrl);
|
||||
await page.goto(`/dashboard/snapshot/${snapshotKey}`);
|
||||
|
||||
// Validate the dashboard controls are rendered
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.Controls)).toBeVisible();
|
||||
|
||||
// Validate the panels are rendered
|
||||
for (const title of panelsToCheck) {
|
||||
await expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(title))).toBeVisible();
|
||||
|
|
|
@ -3,6 +3,7 @@ import { e2e } from '../utils';
|
|||
describe('Public dashboards', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
cy.setLocalStorage('grafana.featureToggles', 'dashboardScene=false'); // this test is for the old sharing modal only used when scenes is turned off
|
||||
});
|
||||
|
||||
it('Create a public dashboard', () => {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { e2e } from '../utils';
|
|||
describe('Create a public dashboard with template variables shows a template variable warning', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
cy.setLocalStorage('grafana.featureToggles', 'dashboardScene=false'); // this test is for the old sharing modal only used when scenes is turned off
|
||||
});
|
||||
|
||||
it('Create a public dashboard with template variables shows a template variable warning', () => {
|
||||
|
|
|
@ -553,11 +553,6 @@ export interface FeatureToggles {
|
|||
*/
|
||||
logsExploreTableDefaultVisualization?: boolean;
|
||||
/**
|
||||
* Enables the new sharing drawer design
|
||||
* @default true
|
||||
*/
|
||||
newDashboardSharingComponent?: boolean;
|
||||
/**
|
||||
* Enables the new alert list view design
|
||||
*/
|
||||
alertingListViewV2?: boolean;
|
||||
|
|
|
@ -947,14 +947,6 @@ var (
|
|||
Owner: grafanaObservabilityLogsSquad,
|
||||
FrontendOnly: true,
|
||||
},
|
||||
{
|
||||
Name: "newDashboardSharingComponent",
|
||||
Description: "Enables the new sharing drawer design",
|
||||
Stage: FeatureStageGeneralAvailability,
|
||||
Owner: grafanaSharingSquad,
|
||||
FrontendOnly: true,
|
||||
Expression: "true", // enabled by default
|
||||
},
|
||||
{
|
||||
Name: "alertingListViewV2",
|
||||
Description: "Enables the new alert list view design",
|
||||
|
|
|
@ -123,7 +123,6 @@ grafanaManagedRecordingRules,experimental,@grafana/alerting-squad,false,false,fa
|
|||
queryLibrary,privatePreview,@grafana/sharing-squad,false,false,false
|
||||
savedQueries,preview,@grafana/sharing-squad,false,false,false
|
||||
logsExploreTableDefaultVisualization,experimental,@grafana/observability-logs,false,false,true
|
||||
newDashboardSharingComponent,GA,@grafana/sharing-squad,false,false,true
|
||||
alertingListViewV2,privatePreview,@grafana/alerting-squad,false,false,true
|
||||
alertingDisableSendAlertsExternal,experimental,@grafana/alerting-squad,false,false,false
|
||||
preserveDashboardStateWhenNavigating,experimental,@grafana/dashboards-squad,false,false,false
|
||||
|
|
|
|
@ -503,10 +503,6 @@ const (
|
|||
// Sets the logs table as default visualisation in logs explore
|
||||
FlagLogsExploreTableDefaultVisualization = "logsExploreTableDefaultVisualization"
|
||||
|
||||
// FlagNewDashboardSharingComponent
|
||||
// Enables the new sharing drawer design
|
||||
FlagNewDashboardSharingComponent = "newDashboardSharingComponent"
|
||||
|
||||
// FlagAlertingListViewV2
|
||||
// Enables the new alert list view design
|
||||
FlagAlertingListViewV2 = "alertingListViewV2"
|
||||
|
|
|
@ -2410,7 +2410,8 @@
|
|||
"metadata": {
|
||||
"name": "newDashboardSharingComponent",
|
||||
"resourceVersion": "1753448760331",
|
||||
"creationTimestamp": "2024-05-03T15:02:18Z"
|
||||
"creationTimestamp": "2024-05-03T15:02:18Z",
|
||||
"deletionTimestamp": "2025-09-12T17:27:39Z"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Enables the new sharing drawer design",
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
// Maps the ID of the nav item to a translated phrase to later pass to <Trans />
|
||||
// Because the navigation content is dynamic (defined in the backend), we can not use
|
||||
// the normal inline message definition method.
|
||||
|
@ -46,9 +44,7 @@ export function getNavTitle(navId: string | undefined) {
|
|||
case 'reports':
|
||||
return t('nav.reporting.title', 'Reporting');
|
||||
case 'dashboards/public':
|
||||
return config.featureToggles.newDashboardSharingComponent
|
||||
? t('nav.shared-dashboard.title', 'Shared dashboards')
|
||||
: t('nav.public.title', 'Public dashboards');
|
||||
return t('nav.shared-dashboard.title', 'Shared dashboards');
|
||||
case 'dashboards/recently-deleted':
|
||||
return t('nav.recently-deleted.title', 'Recently deleted');
|
||||
case 'dashboards/new':
|
||||
|
@ -218,9 +214,7 @@ export function getNavSubTitle(navId: string | undefined) {
|
|||
'Interactive, publically available, point-in-time representations of dashboards and panels'
|
||||
);
|
||||
case 'dashboards/public':
|
||||
return config.featureToggles.newDashboardSharingComponent
|
||||
? t('nav.shared-dashboard.subtitle', "Manage your organization's externally shared dashboards")
|
||||
: undefined;
|
||||
t('nav.shared-dashboard.subtitle', "Manage your organization's externally shared dashboards");
|
||||
case 'dashboards/library-panels':
|
||||
return t('nav.library-panels.subtitle', 'Reusable panels that can be added to multiple dashboards');
|
||||
case 'dashboards/recently-deleted':
|
||||
|
|
|
@ -30,11 +30,7 @@ const selectors = e2eSelectors.pages.UserListPage;
|
|||
const PublicDashboardsTab = ({ view, setView }: { view: TabView | null; setView: (v: TabView | null) => void }) => {
|
||||
return (
|
||||
<Tab
|
||||
label={
|
||||
config.featureToggles.newDashboardSharingComponent
|
||||
? t('users-access-list.tabs.shared-dashboard-users-tab-title', 'Shared dashboard users')
|
||||
: t('users-access-list.tabs.public-dashboard-users-tab-title', 'Public dashboard users')
|
||||
}
|
||||
label={t('users-access-list.tabs.shared-dashboard-users-tab-title', 'Shared dashboard users')}
|
||||
active={view === TabView.PUBLIC_DASHBOARDS}
|
||||
onChangeTab={() => setView(TabView.PUBLIC_DASHBOARDS)}
|
||||
data-testid={selectors.tabs.publicDashboardsUsers}
|
||||
|
|
|
@ -3,7 +3,6 @@ import { css, cx } from '@emotion/css';
|
|||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Button, LoadingPlaceholder, Modal, ModalsController, useStyles2 } from '@grafana/ui';
|
||||
import {
|
||||
generatePublicDashboardConfigUrl,
|
||||
|
@ -22,11 +21,7 @@ export const DashboardsListModal = ({ email, onDismiss }: { email: string; onDis
|
|||
<Modal
|
||||
className={styles.modal}
|
||||
isOpen
|
||||
title={
|
||||
config.featureToggles.newDashboardSharingComponent
|
||||
? t('public-dashboard-users-access-list.modal.shared-dashboard-modal-title', 'Shared dashboards')
|
||||
: t('public-dashboard-users-access-list.modal.dashboard-modal-title', 'Public dashboards')
|
||||
}
|
||||
title={t('public-dashboard-users-access-list.modal.shared-dashboard-modal-title', 'Shared dashboards')}
|
||||
onDismiss={onDismiss}
|
||||
>
|
||||
{isLoading ? (
|
||||
|
@ -47,15 +42,7 @@ export const DashboardsListModal = ({ email, onDismiss }: { email: string; onDis
|
|||
href={generatePublicDashboardUrl(dash.publicDashboardAccessToken)}
|
||||
onClick={onDismiss}
|
||||
>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Trans i18nKey="public-dashboard-users-access-list.dashboard-modal.external-link">
|
||||
External link
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="public-dashboard-users-access-list.dashboard-modal.public-dashboard-link">
|
||||
Public dashboard URL
|
||||
</Trans>
|
||||
)}
|
||||
<Trans i18nKey="public-dashboard-users-access-list.dashboard-modal.external-link">External link</Trans>
|
||||
</a>
|
||||
<span className={styles.urlsDivider}>{'•'}</span>
|
||||
<a
|
||||
|
@ -63,15 +50,9 @@ export const DashboardsListModal = ({ email, onDismiss }: { email: string; onDis
|
|||
href={generatePublicDashboardConfigUrl(dash.dashboardUid, dash.slug)}
|
||||
onClick={onDismiss}
|
||||
>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Trans i18nKey="public-dashboard-users-access-list.dashboard-modal.sharing-setting">
|
||||
Sharing settings
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="public-dashboard-users-access-list.dashboard-modal.public-dashboard-setting">
|
||||
Public dashboard settings
|
||||
</Trans>
|
||||
)}
|
||||
<Trans i18nKey="public-dashboard-users-access-list.dashboard-modal.sharing-setting">
|
||||
Sharing settings
|
||||
</Trans>
|
||||
</a>
|
||||
</div>
|
||||
<hr className={styles.divider} />
|
||||
|
|
|
@ -2,7 +2,6 @@ import { css } from '@emotion/css';
|
|||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Button, Modal, ModalsController, useStyles2 } from '@grafana/ui';
|
||||
import { SessionUser } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
|
||||
|
@ -30,21 +29,12 @@ const DeleteUserModal = ({ user, hideModal }: { user: SessionUser; hideModal: ()
|
|||
</Trans>
|
||||
</p>
|
||||
<p className={styles.description}>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Trans
|
||||
i18nKey="public-dashboard-users-access-list.delete-user-shared-dashboards-modal.revoke-user-access-modal-desc-line2"
|
||||
shouldUnescape
|
||||
>
|
||||
This action will immediately revoke {{ email: user.email }}'s access to all shared dashboards.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans
|
||||
i18nKey="public-dashboard-users-access-list.delete-user-modal.revoke-user-access-modal-desc-line2"
|
||||
shouldUnescape
|
||||
>
|
||||
This action will immediately revoke {{ email: user.email }}'s access to all public dashboards.
|
||||
</Trans>
|
||||
)}
|
||||
<Trans
|
||||
i18nKey="public-dashboard-users-access-list.delete-user-shared-dashboards-modal.revoke-user-access-modal-desc-line2"
|
||||
shouldUnescape
|
||||
>
|
||||
This action will immediately revoke {{ email: user.email }}'s access to all shared dashboards.
|
||||
</Trans>
|
||||
</p>
|
||||
<Modal.ButtonRow>
|
||||
<Button type="button" variant="secondary" onClick={hideModal} fill="outline">
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { config } from '@grafana/runtime';
|
||||
import { SceneObjectUrlSyncHandler, SceneObjectUrlValues, VizPanel } from '@grafana/scenes';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { KioskMode } from 'app/types/dashboard';
|
||||
|
@ -6,7 +5,6 @@ import { KioskMode } from 'app/types/dashboard';
|
|||
import { buildPanelEditScene } from '../panel-edit/PanelEditor';
|
||||
import { createDashboardEditViewFor } from '../settings/utils';
|
||||
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
|
||||
import { ShareModal } from '../sharing/ShareModal';
|
||||
import { findEditPanel, getLibraryPanelBehavior } from '../utils/utils';
|
||||
|
||||
import { DashboardScene, DashboardSceneState } from './DashboardScene';
|
||||
|
@ -102,13 +100,9 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
|
|||
|
||||
if (typeof values.shareView === 'string') {
|
||||
update.shareView = values.shareView;
|
||||
update.overlay = config.featureToggles.newDashboardSharingComponent
|
||||
? new ShareDrawer({
|
||||
shareView: values.shareView,
|
||||
})
|
||||
: new ShareModal({
|
||||
activeTab: values.shareView,
|
||||
});
|
||||
update.overlay = new ShareDrawer({
|
||||
shareView: values.shareView,
|
||||
});
|
||||
} else if (shareView && values.shareView === null) {
|
||||
update.overlay = undefined;
|
||||
update.shareView = undefined;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { TestProvider } from 'test/helpers/TestProvider';
|
|||
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { LocationServiceProvider, config, locationService } from '@grafana/runtime';
|
||||
import { LocationServiceProvider, locationService } from '@grafana/runtime';
|
||||
import { SceneQueryRunner, SceneTimeRange, UrlSyncContextProvider, VizPanel } from '@grafana/scenes';
|
||||
import { playlistSrv } from 'app/features/playlist/PlaylistSrv';
|
||||
import { DashboardMeta } from 'app/types/dashboard';
|
||||
|
@ -145,25 +145,14 @@ describe('NavToolbarActions', () => {
|
|||
});
|
||||
|
||||
describe('Given new sharing button', () => {
|
||||
it('Should show old share button when newDashboardSharingComponent FF is disabled', async () => {
|
||||
setup();
|
||||
|
||||
expect(await screen.findByText('Share')).toBeInTheDocument();
|
||||
const newShareButton = screen.queryByTestId(selectors.pages.Dashboard.DashNav.newShareButton.container);
|
||||
expect(newShareButton).not.toBeInTheDocument();
|
||||
const newExportButton = screen.queryByRole('button', { name: /export dashboard/i });
|
||||
expect(newExportButton).not.toBeInTheDocument();
|
||||
});
|
||||
it('Should show new share button when newDashboardSharingComponent FF is enabled', async () => {
|
||||
config.featureToggles.newDashboardSharingComponent = true;
|
||||
it('Should show new share button', async () => {
|
||||
setup();
|
||||
|
||||
expect(await screen.queryByTestId(selectors.pages.Dashboard.DashNav.shareButton)).not.toBeInTheDocument();
|
||||
const newShareButton = screen.getByTestId(selectors.pages.Dashboard.DashNav.newShareButton.container);
|
||||
expect(newShareButton).toBeInTheDocument();
|
||||
});
|
||||
it('Should show new export button when newDashboardSharingComponent FF is enabled', async () => {
|
||||
config.featureToggles.newDashboardSharingComponent = true;
|
||||
it('Should show new export button', async () => {
|
||||
setup();
|
||||
const newExportButton = screen.getByRole('button', { name: /export dashboard/i });
|
||||
expect(newExportButton).toBeInTheDocument();
|
||||
|
|
|
@ -26,7 +26,6 @@ import { useGetResourceRepositoryView } from 'app/features/provisioning/hooks/us
|
|||
import { getReadOnlyTooltipText } from 'app/features/provisioning/utils/repository';
|
||||
import { useSelector } from 'app/types/store';
|
||||
|
||||
import { shareDashboardType } from '../../dashboard/components/ShareModal/utils';
|
||||
import { selectFolderRepository } from '../../provisioning/utils/selectors';
|
||||
import { PanelEditor, buildPanelEditScene } from '../panel-edit/PanelEditor';
|
||||
import ExportButton from '../sharing/ExportButton/ExportButton';
|
||||
|
@ -47,7 +46,7 @@ interface Props {
|
|||
}
|
||||
|
||||
export const NavToolbarActions = memo<Props>(({ dashboard }) => {
|
||||
const hasNewToolbar = config.featureToggles.dashboardNewLayouts && config.featureToggles.newDashboardSharingComponent;
|
||||
const hasNewToolbar = config.featureToggles.dashboardNewLayouts;
|
||||
|
||||
return hasNewToolbar ? (
|
||||
<AppChromeUpdate
|
||||
|
@ -322,26 +321,6 @@ export function ToolbarActions({ dashboard }: Props) {
|
|||
});
|
||||
|
||||
const showShareButton = uid && !isEditing && !meta.isSnapshot && !isPlaying;
|
||||
toolbarActions.push({
|
||||
group: 'main-buttons',
|
||||
condition: !config.featureToggles.newDashboardSharingComponent && showShareButton,
|
||||
render: () => (
|
||||
<Button
|
||||
key="share-dashboard-button"
|
||||
tooltip={t('dashboard.toolbar.share.tooltip', 'Share dashboard')}
|
||||
size="sm"
|
||||
className={styles.buttonWithExtraMargin}
|
||||
fill="outline"
|
||||
onClick={() => {
|
||||
DashboardInteractions.toolbarShareClick();
|
||||
locationService.partial({ shareView: shareDashboardType.link });
|
||||
}}
|
||||
data-testid={selectors.components.NavToolbar.shareDashboard}
|
||||
>
|
||||
<Trans i18nKey="dashboard.toolbar.share.label">Share</Trans>
|
||||
</Button>
|
||||
),
|
||||
});
|
||||
|
||||
toolbarActions.push({
|
||||
group: 'main-buttons',
|
||||
|
@ -358,7 +337,7 @@ export function ToolbarActions({ dashboard }: Props) {
|
|||
}
|
||||
key="edit"
|
||||
className={styles.buttonWithExtraMargin}
|
||||
variant={config.featureToggles.newDashboardSharingComponent ? 'secondary' : 'primary'}
|
||||
variant={'secondary'}
|
||||
size="sm"
|
||||
data-testid={selectors.components.NavToolbar.editDashboard.editButton}
|
||||
disabled={isReadOnlyRepo}
|
||||
|
@ -391,13 +370,13 @@ export function ToolbarActions({ dashboard }: Props) {
|
|||
|
||||
toolbarActions.push({
|
||||
group: 'new-share-dashboard-buttons',
|
||||
condition: config.featureToggles.newDashboardSharingComponent && showShareButton,
|
||||
condition: showShareButton,
|
||||
render: () => <ExportButton key="new-export-dashboard-button" dashboard={dashboard} />,
|
||||
});
|
||||
|
||||
toolbarActions.push({
|
||||
group: 'new-share-dashboard-buttons',
|
||||
condition: config.featureToggles.newDashboardSharingComponent && showShareButton,
|
||||
condition: showShareButton,
|
||||
render: () => <ShareButton key="new-share-dashboard-button" dashboard={dashboard} />,
|
||||
});
|
||||
|
||||
|
|
|
@ -534,7 +534,7 @@ describe('panelMenuBehavior', () => {
|
|||
expect(menu.state.items?.find((i) => i.text === 'Remove')).toBeDefined();
|
||||
const moreMenu = menu.state.items?.find((i) => i.text === 'More...')?.subMenu;
|
||||
expect(moreMenu?.find((i) => i.text === 'Duplicate')).toBeDefined();
|
||||
expect(moreMenu?.find((i) => i.text === 'Create library panel')).toBeDefined();
|
||||
expect(moreMenu?.find((i) => i.text === 'New library panel')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should only contain explore when embedded', async () => {
|
||||
|
|
|
@ -35,7 +35,6 @@ import { ShowConfirmModalEvent } from 'app/types/events';
|
|||
|
||||
import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer';
|
||||
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
|
||||
import { ShareModal } from '../sharing/ShareModal';
|
||||
import { isRepeatCloneOrChildOf } from '../utils/clone';
|
||||
import { DashboardInteractions } from '../utils/interactions';
|
||||
import { getEditPanelUrl, tryGetExploreUrlForPanel } from '../utils/urlBuilders';
|
||||
|
@ -109,90 +108,79 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
|||
});
|
||||
}
|
||||
|
||||
if (config.featureToggles.newDashboardSharingComponent) {
|
||||
const subMenu: PanelMenuItem[] = [];
|
||||
const subMenu: PanelMenuItem[] = [];
|
||||
subMenu.push({
|
||||
text: t('share-panel.menu.share-link-title', 'Share link'),
|
||||
iconClassName: 'link',
|
||||
shortcut: 'p u',
|
||||
onClick: () => {
|
||||
DashboardInteractions.sharingCategoryClicked({
|
||||
item: shareDashboardType.link,
|
||||
shareResource: getTrackingSource(panel?.getRef()),
|
||||
});
|
||||
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.link,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
subMenu.push({
|
||||
text: t('share-panel.menu.share-embed-title', 'Share embed'),
|
||||
iconClassName: 'arrow',
|
||||
shortcut: 'p e',
|
||||
onClick: () => {
|
||||
DashboardInteractions.sharingCategoryClicked({
|
||||
item: shareDashboardType.embed,
|
||||
shareResource: getTrackingSource(panel.getRef()),
|
||||
});
|
||||
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.embed,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
contextSrv.isSignedIn &&
|
||||
config.snapshotEnabled &&
|
||||
contextSrv.hasPermission(AccessControlAction.SnapshotsCreate)
|
||||
) {
|
||||
subMenu.push({
|
||||
text: t('share-panel.menu.share-link-title', 'Share link'),
|
||||
iconClassName: 'link',
|
||||
shortcut: 'p u',
|
||||
text: t('share-panel.menu.share-snapshot-title', 'Share snapshot'),
|
||||
iconClassName: 'camera',
|
||||
shortcut: 'p s',
|
||||
onClick: () => {
|
||||
DashboardInteractions.sharingCategoryClicked({
|
||||
item: shareDashboardType.link,
|
||||
shareResource: getTrackingSource(panel?.getRef()),
|
||||
});
|
||||
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.link,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
subMenu.push({
|
||||
text: t('share-panel.menu.share-embed-title', 'Share embed'),
|
||||
iconClassName: 'arrow',
|
||||
shortcut: 'p e',
|
||||
onClick: () => {
|
||||
DashboardInteractions.sharingCategoryClicked({
|
||||
item: shareDashboardType.embed,
|
||||
item: shareDashboardType.snapshot,
|
||||
shareResource: getTrackingSource(panel.getRef()),
|
||||
});
|
||||
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.embed,
|
||||
shareView: shareDashboardType.snapshot,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
contextSrv.isSignedIn &&
|
||||
config.snapshotEnabled &&
|
||||
contextSrv.hasPermission(AccessControlAction.SnapshotsCreate)
|
||||
) {
|
||||
subMenu.push({
|
||||
text: t('share-panel.menu.share-snapshot-title', 'Share snapshot'),
|
||||
iconClassName: 'camera',
|
||||
shortcut: 'p s',
|
||||
onClick: () => {
|
||||
DashboardInteractions.sharingCategoryClicked({
|
||||
item: shareDashboardType.snapshot,
|
||||
shareResource: getTrackingSource(panel.getRef()),
|
||||
});
|
||||
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.snapshot,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
type: 'submenu',
|
||||
text: t('panel.header-menu.share', 'Share'),
|
||||
iconClassName: 'share-alt',
|
||||
subMenu,
|
||||
onClick: (e) => {
|
||||
e.preventDefault();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
text: t('panel.header-menu.share', 'Share'),
|
||||
iconClassName: 'share-alt',
|
||||
onClick: () => {
|
||||
dashboard.showModal(new ShareModal({ panelRef: panel.getRef() }));
|
||||
},
|
||||
shortcut: 'p s',
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
type: 'submenu',
|
||||
text: t('panel.header-menu.share', 'Share'),
|
||||
iconClassName: 'share-alt',
|
||||
subMenu,
|
||||
onClick: (e) => {
|
||||
e.preventDefault();
|
||||
},
|
||||
});
|
||||
|
||||
if (dashboard.state.isEditing && !isReadOnlyRepeat && !isEditingPanel) {
|
||||
moreSubMenu.push({
|
||||
text: t('panel.header-menu.duplicate', `Duplicate`),
|
||||
|
@ -236,32 +224,18 @@ export function panelMenuBehavior(menu: VizPanelMenu) {
|
|||
},
|
||||
});
|
||||
} else {
|
||||
if (config.featureToggles.newDashboardSharingComponent) {
|
||||
moreSubMenu.push({
|
||||
text: t('share-panel.menu.new-library-panel-title', 'New library panel'),
|
||||
iconClassName: 'plus-square',
|
||||
onClick: () => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.libraryPanel,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
moreSubMenu.push({
|
||||
text: t('share-panel.menu.new-library-panel-title', 'New library panel'),
|
||||
iconClassName: 'plus-square',
|
||||
onClick: () => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.libraryPanel,
|
||||
panelRef: panel.getRef(),
|
||||
});
|
||||
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
moreSubMenu.push({
|
||||
text: t('panel.header-menu.create-library-panel', `Create library panel`),
|
||||
onClick: () => {
|
||||
dashboard.showModal(
|
||||
new ShareModal({
|
||||
panelRef: panel.getRef(),
|
||||
activeTab: shareDashboardType.libraryPanel,
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
dashboard.showModal(drawer);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import { AccessControlAction } from 'app/types/accessControl';
|
|||
import { shareDashboardType } from '../../dashboard/components/ShareModal/utils';
|
||||
import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer';
|
||||
import { ShareDrawer } from '../sharing/ShareDrawer/ShareDrawer';
|
||||
import { ShareModal } from '../sharing/ShareModal';
|
||||
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
||||
import { findVizPanelByPathId } from '../utils/pathId';
|
||||
import { getEditPanelUrl, tryGetExploreUrlForPanel } from '../utils/urlBuilders';
|
||||
|
@ -59,52 +58,43 @@ export function setupKeyboardShortcuts(scene: DashboardScene) {
|
|||
});
|
||||
|
||||
// Panel share
|
||||
if (config.featureToggles.newDashboardSharingComponent) {
|
||||
keybindings.addBinding({
|
||||
key: 'p u',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.link,
|
||||
panelRef: vizPanel.getRef(),
|
||||
});
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
keybindings.addBinding({
|
||||
key: 'p e',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.embed,
|
||||
panelRef: vizPanel.getRef(),
|
||||
});
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
|
||||
if (
|
||||
contextSrv.isSignedIn &&
|
||||
config.snapshotEnabled &&
|
||||
contextSrv.hasPermission(AccessControlAction.SnapshotsCreate)
|
||||
) {
|
||||
keybindings.addBinding({
|
||||
key: 'p s',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.snapshot,
|
||||
panelRef: vizPanel.getRef(),
|
||||
});
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
keybindings.addBinding({
|
||||
key: 'p u',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.link,
|
||||
panelRef: vizPanel.getRef(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
keybindings.addBinding({
|
||||
key: 'p e',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.embed,
|
||||
panelRef: vizPanel.getRef(),
|
||||
});
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
|
||||
if (
|
||||
contextSrv.isSignedIn &&
|
||||
config.snapshotEnabled &&
|
||||
contextSrv.hasPermission(AccessControlAction.SnapshotsCreate)
|
||||
) {
|
||||
keybindings.addBinding({
|
||||
key: 'p s',
|
||||
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
||||
scene.showModal(new ShareModal({ panelRef: vizPanel.getRef() }));
|
||||
const drawer = new ShareDrawer({
|
||||
shareView: shareDashboardType.snapshot,
|
||||
panelRef: vizPanel.getRef(),
|
||||
});
|
||||
|
||||
scene.showModal(drawer);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { render } from 'test/test-utils';
|
|||
import { getDefaultTimeRange, LoadingState } from '@grafana/data';
|
||||
import { getPanelPlugin } from '@grafana/data/test';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
||||
import { config, setPluginImportUtils } from '@grafana/runtime';
|
||||
import { setPluginImportUtils } from '@grafana/runtime';
|
||||
import {
|
||||
CustomVariable,
|
||||
SceneQueryRunner,
|
||||
|
@ -31,7 +31,6 @@ setPluginImportUtils({
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
config.featureToggles.newDashboardSharingComponent = true;
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(true);
|
||||
jest.spyOn(contextSrv, 'hasRole').mockReturnValue(true);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectRef, VizPanel } from '@grafana/scenes';
|
||||
import { LibraryPanel } from '@grafana/schema/dist/esm/index.gen';
|
||||
import { ShareLibraryPanel } from 'app/features/dashboard/components/ShareModal/ShareLibraryPanel';
|
||||
|
@ -22,9 +21,7 @@ export class ShareLibraryPanelTab extends SceneObjectBase<ShareLibraryPanelTabSt
|
|||
static Component = ShareLibraryPanelTabRenderer;
|
||||
|
||||
public getTabLabel() {
|
||||
return config.featureToggles.newDashboardSharingComponent
|
||||
? t('share-panel.drawer.new-library-panel-title', 'New library panel')
|
||||
: t('share-modal.tab-title.library-panel', 'Library panel');
|
||||
return t('share-panel.drawer.new-library-panel-title', 'New library panel');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
import { ComponentProps } from 'react';
|
||||
|
||||
import { t } from '@grafana/i18n';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectRef, SceneObjectState, VizPanel } from '@grafana/scenes';
|
||||
import { Modal, ModalTabsHeader, TabContent } from '@grafana/ui';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { isPublicDashboardsEnabled } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
import { AccessControlAction } from 'app/types/accessControl';
|
||||
|
||||
import { getTrackingSource } from '../../dashboard/components/ShareModal/utils';
|
||||
import { DashboardInteractions } from '../utils/interactions';
|
||||
import { getDashboardSceneFor, isLibraryPanel } from '../utils/utils';
|
||||
|
||||
import { ShareExportTab } from './ShareExportTab';
|
||||
import { ShareLibraryPanelTab } from './ShareLibraryPanelTab';
|
||||
import { ShareLinkTab } from './ShareLinkTab';
|
||||
import { SharePanelEmbedTab } from './SharePanelEmbedTab';
|
||||
import { ShareSnapshotTab } from './ShareSnapshotTab';
|
||||
import { SharePublicDashboardTab } from './public-dashboards/SharePublicDashboardTab';
|
||||
import { ModalSceneObjectLike, SceneShareTab, SceneShareTabState } from './types';
|
||||
|
||||
interface ShareModalState extends SceneObjectState {
|
||||
panelRef?: SceneObjectRef<VizPanel>;
|
||||
tabs?: SceneShareTab[];
|
||||
activeTab: string;
|
||||
}
|
||||
|
||||
type customDashboardTabType = new (...args: SceneShareTabState[]) => SceneShareTab;
|
||||
const customDashboardTabs: customDashboardTabType[] = [];
|
||||
|
||||
export function addDashboardShareTab(tab: customDashboardTabType) {
|
||||
customDashboardTabs.push(tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for full dashboard share modal and the panel level share modal
|
||||
*/
|
||||
export class ShareModal extends SceneObjectBase<ShareModalState> implements ModalSceneObjectLike {
|
||||
static Component = SharePanelModalRenderer;
|
||||
|
||||
constructor(state: Omit<ShareModalState, 'activeTab'> & { activeTab?: string }) {
|
||||
super({
|
||||
activeTab: 'link',
|
||||
...state,
|
||||
});
|
||||
|
||||
this.addActivationHandler(() => this.buildTabs(state.activeTab));
|
||||
}
|
||||
|
||||
private buildTabs(activeTab?: string) {
|
||||
const { panelRef } = this.state;
|
||||
const modalRef = this.getRef();
|
||||
|
||||
const tabs: SceneShareTab[] = [new ShareLinkTab({ panelRef, modalRef })];
|
||||
const dashboard = getDashboardSceneFor(this);
|
||||
|
||||
if (!panelRef) {
|
||||
tabs.push(new ShareExportTab({ modalRef }));
|
||||
}
|
||||
|
||||
if (
|
||||
contextSrv.isSignedIn &&
|
||||
config.snapshotEnabled &&
|
||||
contextSrv.hasPermission(AccessControlAction.SnapshotsCreate)
|
||||
) {
|
||||
tabs.push(new ShareSnapshotTab({ panelRef, dashboardRef: dashboard.getRef(), modalRef }));
|
||||
}
|
||||
|
||||
if (panelRef) {
|
||||
tabs.push(new SharePanelEmbedTab({ panelRef }));
|
||||
const panel = panelRef.resolve();
|
||||
if (panel instanceof VizPanel) {
|
||||
if (!isLibraryPanel(panel)) {
|
||||
tabs.push(new ShareLibraryPanelTab({ panelRef, modalRef }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!panelRef) {
|
||||
tabs.push(...customDashboardTabs.map((Tab) => new Tab({ modalRef })));
|
||||
|
||||
if (isPublicDashboardsEnabled()) {
|
||||
tabs.push(new SharePublicDashboardTab({ modalRef }));
|
||||
}
|
||||
}
|
||||
|
||||
const at = tabs.find((t) => t.tabId === activeTab);
|
||||
|
||||
this.setState({ activeTab: at?.tabId ?? tabs[0].tabId, tabs });
|
||||
}
|
||||
|
||||
onDismiss = () => {
|
||||
if (this.state.panelRef) {
|
||||
const dashboard = getDashboardSceneFor(this);
|
||||
dashboard.closeModal();
|
||||
} else {
|
||||
locationService.partial({ shareView: null });
|
||||
}
|
||||
};
|
||||
|
||||
onChangeTab: ComponentProps<typeof ModalTabsHeader>['onChangeTab'] = (tab) => {
|
||||
DashboardInteractions.sharingCategoryClicked({
|
||||
item: tab.value,
|
||||
shareResource: getTrackingSource(this.state.panelRef),
|
||||
});
|
||||
this.setState({ activeTab: tab.value });
|
||||
};
|
||||
}
|
||||
|
||||
function SharePanelModalRenderer({ model }: SceneComponentProps<ShareModal>) {
|
||||
const { panelRef, tabs, activeTab } = model.useState();
|
||||
const title = panelRef ? t('share-modal.panel.title', 'Share Panel') : t('share-modal.dashboard.title', 'Share');
|
||||
|
||||
if (!tabs) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modalTabs = tabs?.map((tab) => ({
|
||||
label: tab.getTabLabel(),
|
||||
value: tab.tabId,
|
||||
}));
|
||||
|
||||
const header = (
|
||||
<ModalTabsHeader
|
||||
title={title}
|
||||
icon="share-alt"
|
||||
tabs={modalTabs}
|
||||
activeTab={activeTab}
|
||||
onChangeTab={model.onChangeTab}
|
||||
/>
|
||||
);
|
||||
|
||||
const currentTab = tabs.find((t) => t.tabId === activeTab);
|
||||
|
||||
return (
|
||||
<Modal isOpen={true} title={header} onDismiss={model.onDismiss}>
|
||||
<TabContent>{currentTab && <currentTab.Component model={currentTab} />}</TabContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import { TimeRange } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { SceneComponentProps, sceneGraph, SceneObjectBase, SceneObjectRef, VizPanel } from '@grafana/scenes';
|
||||
import { ShareEmbed } from 'app/features/dashboard/components/ShareModal/ShareEmbed';
|
||||
import { buildParams, shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils';
|
||||
|
@ -25,9 +24,7 @@ export class SharePanelEmbedTab extends SceneObjectBase<SharePanelEmbedTabState>
|
|||
}
|
||||
|
||||
public getTabLabel() {
|
||||
return config.featureToggles.newDashboardSharingComponent
|
||||
? t('share-panel.drawer.share-embed-title', 'Share embed')
|
||||
: t('share-modal.tab-title.panel-embed', 'Embed');
|
||||
return t('share-panel.drawer.share-embed-title', 'Share embed');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { SceneComponentProps, sceneGraph } from '@grafana/scenes';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { useDeletePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi';
|
||||
import { ConfigPublicDashboardBase } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/ConfigPublicDashboard/ConfigPublicDashboard';
|
||||
import { PublicDashboard } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
import { AccessControlAction } from 'app/types/accessControl';
|
||||
|
||||
import { shareDashboardType } from '../../../dashboard/components/ShareModal/utils';
|
||||
import { getDashboardSceneFor } from '../../utils/utils';
|
||||
import { ShareModal } from '../ShareModal';
|
||||
|
||||
import { ConfirmModal } from './ConfirmModal';
|
||||
import { SharePublicDashboardTab } from './SharePublicDashboardTab';
|
||||
import { useUnsupportedDatasources } from './hooks';
|
||||
|
||||
interface Props extends SceneComponentProps<SharePublicDashboardTab> {
|
||||
publicDashboard?: PublicDashboard;
|
||||
isGetLoading?: boolean;
|
||||
}
|
||||
|
||||
export function ConfigPublicDashboard({ model, publicDashboard, isGetLoading }: Props) {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const hasWritePermissions = contextSrv.hasPermission(AccessControlAction.DashboardsPublicWrite);
|
||||
|
||||
const dashboard = getDashboardSceneFor(model);
|
||||
const { isDirty } = dashboard.useState();
|
||||
const [deletePublicDashboard] = useDeletePublicDashboardMutation();
|
||||
const hasTemplateVariables = (dashboard.state.$variables?.state.variables.length ?? 0) > 0;
|
||||
const unsupportedDataSources = useUnsupportedDatasources(dashboard);
|
||||
const timeRangeState = sceneGraph.getTimeRange(model);
|
||||
const timeRange = timeRangeState.useState();
|
||||
|
||||
return (
|
||||
<ConfigPublicDashboardBase
|
||||
dashboard={dashboard}
|
||||
publicDashboard={publicDashboard}
|
||||
unsupportedDatasources={unsupportedDataSources}
|
||||
onRevoke={() => {
|
||||
dashboard.showModal(
|
||||
new ConfirmModal({
|
||||
isOpen: true,
|
||||
title: t('dashboard-scene.config-public-dashboard.title.revoke-public-url', 'Revoke public URL'),
|
||||
icon: 'trash-alt',
|
||||
confirmText: t(
|
||||
'dashboard-scene.config-public-dashboard.confirmText.revoke-public-url',
|
||||
'Revoke public URL'
|
||||
),
|
||||
body: (
|
||||
<p className={styles.description}>
|
||||
<Trans i18nKey="public-dashboard.config.revoke-body">
|
||||
Are you sure you want to revoke this URL? The dashboard will no longer be public.
|
||||
</Trans>
|
||||
</p>
|
||||
),
|
||||
onDismiss: () => {
|
||||
dashboard.showModal(new ShareModal({ activeTab: shareDashboardType.publicDashboard }));
|
||||
},
|
||||
onConfirm: () => {
|
||||
deletePublicDashboard({ dashboard, dashboardUid: dashboard.state.uid!, uid: publicDashboard!.uid });
|
||||
dashboard.closeModal();
|
||||
},
|
||||
})
|
||||
);
|
||||
}}
|
||||
timeRange={timeRange.value}
|
||||
showSaveChangesAlert={hasWritePermissions && isDirty}
|
||||
hasTemplateVariables={hasTemplateVariables}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
description: css({
|
||||
fontSize: theme.typography.body.fontSize,
|
||||
}),
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
import { SceneComponentProps } from '@grafana/scenes';
|
||||
import { CreatePublicDashboardBase } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/CreatePublicDashboard/CreatePublicDashboard';
|
||||
|
||||
import { getDashboardSceneFor } from '../../utils/utils';
|
||||
|
||||
import { SharePublicDashboardTab } from './SharePublicDashboardTab';
|
||||
import { useUnsupportedDatasources } from './hooks';
|
||||
|
||||
export function CreatePublicDashboard({ model }: SceneComponentProps<SharePublicDashboardTab>) {
|
||||
const dashboard = getDashboardSceneFor(model);
|
||||
const unsupportedDataSources = useUnsupportedDatasources(dashboard);
|
||||
const hasTemplateVariables = (dashboard.state.$variables?.state.variables.length ?? 0) > 0;
|
||||
|
||||
return (
|
||||
<CreatePublicDashboardBase
|
||||
dashboard={dashboard}
|
||||
unsupportedDatasources={unsupportedDataSources}
|
||||
unsupportedTemplateVariables={hasTemplateVariables}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
import { t } from '@grafana/i18n';
|
||||
import { SceneComponentProps, SceneObjectBase } from '@grafana/scenes';
|
||||
import { useGetPublicDashboardQuery } from 'app/features/dashboard/api/publicDashboardApi';
|
||||
import { Loader } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard';
|
||||
import { publicDashboardPersisted } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils';
|
||||
import { shareDashboardType } from 'app/features/dashboard/components/ShareModal/utils';
|
||||
|
||||
import { getDashboardSceneFor } from '../../utils/utils';
|
||||
import { SceneShareTabState } from '../types';
|
||||
|
||||
import { ConfigPublicDashboard } from './ConfigPublicDashboard';
|
||||
import { CreatePublicDashboard } from './CreatePublicDashboard';
|
||||
|
||||
export class SharePublicDashboardTab extends SceneObjectBase<SceneShareTabState> {
|
||||
public tabId = shareDashboardType.publicDashboard;
|
||||
static Component = SharePublicDashboardTabRenderer;
|
||||
|
||||
public getTabLabel() {
|
||||
return t('share-modal.tab-title.public-dashboard', 'Public Dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
function SharePublicDashboardTabRenderer({ model }: SceneComponentProps<SharePublicDashboardTab>) {
|
||||
const { data: publicDashboard, isLoading: isGetLoading } = useGetPublicDashboardQuery(
|
||||
getDashboardSceneFor(model).state.uid!
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isGetLoading ? (
|
||||
<Loader />
|
||||
) : !publicDashboardPersisted(publicDashboard) ? (
|
||||
<CreatePublicDashboard model={model} />
|
||||
) : (
|
||||
<ConfigPublicDashboard model={model} publicDashboard={publicDashboard} isGetLoading={isGetLoading} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -64,13 +64,10 @@ export const publicDashboardApi = createApi({
|
|||
},
|
||||
async onQueryStarted({ dashboard, payload: { share } }, { dispatch, queryFulfilled }) {
|
||||
const { data } = await queryFulfilled;
|
||||
let message = t('public-dashboard.sharing.success-creation', 'Dashboard is public!');
|
||||
if (config.featureToggles.newDashboardSharingComponent) {
|
||||
message =
|
||||
share === PublicDashboardShareType.PUBLIC
|
||||
? t('public-dashboard.public-sharing.success-creation', 'Your dashboard is now publicly accessible')
|
||||
: t('public-dashboard.email-sharing.success-creation', 'Your dashboard is ready for external sharing');
|
||||
}
|
||||
const message =
|
||||
share === PublicDashboardShareType.PUBLIC
|
||||
? t('public-dashboard.public-sharing.success-creation', 'Your dashboard is now publicly accessible')
|
||||
: t('public-dashboard.email-sharing.success-creation', 'Your dashboard is ready for external sharing');
|
||||
dispatch(notifyApp(createSuccessNotification(message)));
|
||||
|
||||
if (dashboard instanceof DashboardScene) {
|
||||
|
@ -107,9 +104,7 @@ export const publicDashboardApi = createApi({
|
|||
dispatch(
|
||||
notifyApp(
|
||||
createSuccessNotification(
|
||||
config.featureToggles.newDashboardSharingComponent
|
||||
? t('public-dashboard.configuration.success-update', 'Settings have been successfully updated')
|
||||
: t('public-dashboard.configuration.success-update-old', 'Public dashboard updated!')
|
||||
t('public-dashboard.configuration.success-update', 'Settings have been successfully updated')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -136,12 +131,9 @@ export const publicDashboardApi = createApi({
|
|||
},
|
||||
async onQueryStarted({ dashboard, payload: { isEnabled } }, { dispatch, queryFulfilled }) {
|
||||
const { data } = await queryFulfilled;
|
||||
let message = t('public-dashboard.configuration.success-update-old', 'Public dashboard updated!');
|
||||
if (config.featureToggles.newDashboardSharingComponent) {
|
||||
message = isEnabled
|
||||
? t('public-dashboard.configuration.success-resume', 'Your dashboard access has been resumed')
|
||||
: t('public-dashboard.configuration.success-pause', 'Your dashboard access has been paused');
|
||||
}
|
||||
const message = isEnabled
|
||||
? t('public-dashboard.configuration.success-resume', 'Your dashboard access has been resumed')
|
||||
: t('public-dashboard.configuration.success-pause', 'Your dashboard access has been paused');
|
||||
dispatch(notifyApp(createSuccessNotification(message)));
|
||||
|
||||
if (dashboard instanceof DashboardScene) {
|
||||
|
@ -176,20 +168,16 @@ export const publicDashboardApi = createApi({
|
|||
},
|
||||
async onQueryStarted({ dashboard, payload: { share } }, { dispatch, queryFulfilled }) {
|
||||
await queryFulfilled;
|
||||
let message = t('public-dashboard.configuration.success-update-old', 'Public dashboard updated!');
|
||||
|
||||
if (config.featureToggles.newDashboardSharingComponent) {
|
||||
message =
|
||||
share === PublicDashboardShareType.PUBLIC
|
||||
? t(
|
||||
'public-dashboard.public-sharing.success-share-type-change',
|
||||
'Dashboard access updated: Anyone with the link can now access'
|
||||
)
|
||||
: t(
|
||||
'public-dashboard.email-sharing.success-share-type-change',
|
||||
'Dashboard access updated: Only specific people can now access with the link'
|
||||
);
|
||||
}
|
||||
const message =
|
||||
share === PublicDashboardShareType.PUBLIC
|
||||
? t(
|
||||
'public-dashboard.public-sharing.success-share-type-change',
|
||||
'Dashboard access updated: Anyone with the link can now access'
|
||||
)
|
||||
: t(
|
||||
'public-dashboard.email-sharing.success-share-type-change',
|
||||
'Dashboard access updated: Only specific people can now access with the link'
|
||||
);
|
||||
dispatch(notifyApp(createSuccessNotification(message)));
|
||||
},
|
||||
invalidatesTags: (result, error, { payload }) => [
|
||||
|
@ -250,9 +238,7 @@ export const publicDashboardApi = createApi({
|
|||
dispatch(
|
||||
notifyApp(
|
||||
createSuccessNotification(
|
||||
config.featureToggles.newDashboardSharingComponent
|
||||
? t('public-dashboard.share.success-delete', 'Your dashboard is no longer shareable')
|
||||
: t('public-dashboard.share.success-delete-old', 'Public dashboard deleted!')
|
||||
t('public-dashboard.share.success-delete', 'Your dashboard is no longer shareable')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -2,8 +2,7 @@ import { FormEvent, useEffect, useState } from 'react';
|
|||
|
||||
import { RawTimeRange, TimeRange } from '@grafana/data';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Button, ClipboardButton, Field, Label, Modal, Stack, Switch, TextArea } from '@grafana/ui';
|
||||
import { Button, ClipboardButton, Field, Label, Stack, Switch, TextArea } from '@grafana/ui';
|
||||
import { DashboardInteractions } from 'app/features/dashboard-scene/utils/interactions';
|
||||
|
||||
import { ThemePicker } from './ThemePicker';
|
||||
|
@ -104,16 +103,12 @@ export function ShareEmbed({
|
|||
onChange={onIframeHtmlChange}
|
||||
/>
|
||||
</Field>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Stack gap={1} justifyContent={'start'}>
|
||||
{clipboardButton}
|
||||
<Button variant="secondary" fill="outline" onClick={onCancelClick}>
|
||||
<Trans i18nKey="snapshot.share.cancel-button">Cancel</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
) : (
|
||||
<Modal.ButtonRow>{clipboardButton}</Modal.ButtonRow>
|
||||
)}
|
||||
<Stack gap={1} justifyContent={'start'}>
|
||||
{clipboardButton}
|
||||
<Button variant="secondary" fill="outline" onClick={onCancelClick}>
|
||||
<Trans i18nKey="snapshot.share.cancel-button">Cancel</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,34 +1,21 @@
|
|||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Alert } from '@grafana/ui';
|
||||
|
||||
const selectors = e2eSelectors.pages.ShareDashboardModal.PublicDashboard;
|
||||
|
||||
export const NoUpsertPermissionsAlert = ({ mode }: { mode: 'create' | 'edit' }) => {
|
||||
const title = config.featureToggles.newDashboardSharingComponent
|
||||
? t(
|
||||
'public-dashboard.share-externally.no-upsert-perm-alert-title',
|
||||
'You don’t have permission to {{ action }} a shared dashboard',
|
||||
{ action: mode }
|
||||
)
|
||||
: t(
|
||||
'public-dashboard.modal-alerts.no-upsert-perm-alert-title',
|
||||
'You don’t have permission to {{ action }} a public dashboard',
|
||||
{ action: mode }
|
||||
);
|
||||
const title = t(
|
||||
'public-dashboard.share-externally.no-upsert-perm-alert-title',
|
||||
'You don’t have permission to {{ action }} a shared dashboard',
|
||||
{ action: mode }
|
||||
);
|
||||
|
||||
return (
|
||||
<Alert severity="warning" title={title} data-testid={selectors.NoUpsertPermissionsWarningAlert} bottomSpacing={0}>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Trans i18nKey="public-dashboard.share-externally.no-upsert-perm-alert-desc">
|
||||
Contact your admin to get permission to {{ action: mode }} shared dashboards
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="public-dashboard.modal-alerts.no-upsert-perm-alert-desc">
|
||||
Contact your admin to get permission to {{ action: mode }} public dashboards
|
||||
</Trans>
|
||||
)}
|
||||
<Trans i18nKey="public-dashboard.share-externally.no-upsert-perm-alert-desc">
|
||||
Contact your admin to get permission to {{ action: mode }} shared dashboards
|
||||
</Trans>
|
||||
</Alert>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@ import cx from 'classnames';
|
|||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Alert, useStyles2 } from '@grafana/ui';
|
||||
|
||||
const selectors = e2eSelectors.pages.ShareDashboardModal.PublicDashboard;
|
||||
|
@ -20,23 +19,14 @@ export const UnsupportedDataSourcesAlert = ({ unsupportedDataSources }: { unsupp
|
|||
bottomSpacing={0}
|
||||
>
|
||||
<p className={styles.unsupportedDataSourceDescription}>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Trans i18nKey="public-dashboard.share-externally.unsupported-data-source-alert-desc">
|
||||
There are data sources in this dashboard that are unsupported for shared dashboards. Panels that use these
|
||||
data sources may not function properly: {{ unsupportedDataSources }}.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans i18nKey="public-dashboard.modal-alerts.unsupported-data-source-alert-desc">
|
||||
There are data sources in this dashboard that are unsupported for public dashboards. Panels that use these
|
||||
data sources may not function properly: {{ unsupportedDataSources }}.
|
||||
</Trans>
|
||||
)}
|
||||
<Trans i18nKey="public-dashboard.share-externally.unsupported-data-source-alert-desc">
|
||||
There are data sources in this dashboard that are unsupported for shared dashboards. Panels that use these
|
||||
data sources may not function properly: {{ unsupportedDataSources }}.
|
||||
</Trans>
|
||||
</p>
|
||||
<a
|
||||
href={
|
||||
config.featureToggles.newDashboardSharingComponent
|
||||
? 'https://grafana.com/docs/grafana/next/dashboards/share-dashboards-panels/shared-dashboards/#supported-data-sources'
|
||||
: 'https://grafana.com/docs/grafana/v11.2/dashboards/dashboard-public/#supported-data-sources'
|
||||
'https://grafana.com/docs/grafana/next/dashboards/share-dashboards-panels/shared-dashboards/#supported-data-sources'
|
||||
}
|
||||
target="blank"
|
||||
className={cx('text-link', styles.unsupportedDataSourceDescription)}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { PureComponent } from 'react';
|
|||
import * as React from 'react';
|
||||
|
||||
import { isEmptyObject, SelectableValue, VariableRefresh } from '@grafana/data';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { Button, ClipboardButton, Field, Input, LinkButton, Modal, Select, Spinner, Stack } from '@grafana/ui';
|
||||
|
@ -30,6 +31,8 @@ interface State {
|
|||
sharingButtonText: string;
|
||||
}
|
||||
|
||||
const selectors = e2eSelectors.pages.ShareDashboardModal.SnapshotScene;
|
||||
|
||||
export class ShareSnapshot extends PureComponent<Props, State> {
|
||||
private dashboard: DashboardModel;
|
||||
private expireOptions: Array<SelectableValue<number>>;
|
||||
|
@ -280,7 +283,12 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
|||
{sharingButtonText}
|
||||
</Button>
|
||||
)}
|
||||
<Button variant="primary" disabled={isLoading} onClick={this.createSnapshot()}>
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={isLoading}
|
||||
onClick={this.createSnapshot()}
|
||||
data-testid={selectors.PublishSnapshot}
|
||||
>
|
||||
<Trans i18nKey="share-modal.snapshot.local-button">Publish Snapshot</Trans>
|
||||
</Button>
|
||||
</Modal.ButtonRow>
|
||||
|
@ -297,9 +305,15 @@ export class ShareSnapshot extends PureComponent<Props, State> {
|
|||
<Input
|
||||
id="snapshot-url-input"
|
||||
value={snapshotUrl}
|
||||
data-testid={selectors.CopyUrlInput}
|
||||
readOnly
|
||||
addonAfter={
|
||||
<ClipboardButton icon="copy" variant="primary" getText={this.getSnapshotUrl}>
|
||||
<ClipboardButton
|
||||
icon="copy"
|
||||
variant="primary"
|
||||
getText={this.getSnapshotUrl}
|
||||
data-testid={selectors.CopyUrlButton}
|
||||
>
|
||||
<Trans i18nKey="share-modal.snapshot.copy-link-button">Copy</Trans>
|
||||
</ClipboardButton>
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from 'react';
|
|||
import { useAsync, useDebounce } from 'react-use';
|
||||
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config, FetchError, isFetchError } from '@grafana/runtime';
|
||||
import { FetchError, isFetchError } from '@grafana/runtime';
|
||||
import { LibraryPanel } from '@grafana/schema/dist/esm/index.gen';
|
||||
import { Button, Field, Input, Modal, Stack } from '@grafana/ui';
|
||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||
|
@ -86,25 +86,14 @@ export const AddLibraryPanelContents = ({
|
|||
>
|
||||
<FolderPicker onChange={(uid) => setFolderUid(uid)} value={folderUid} />
|
||||
</Field>
|
||||
{config.featureToggles.newDashboardSharingComponent ? (
|
||||
<Stack gap={1} justifyContent={'start'}>
|
||||
<Button onClick={onCreate} disabled={invalidInput}>
|
||||
<Trans i18nKey="share-panel.new-library-panel.create-button">Create library panel</Trans>
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onDismiss} fill="outline">
|
||||
<Trans i18nKey="share-panel.new-library-panel.cancel-button">Cancel</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
) : (
|
||||
<Modal.ButtonRow>
|
||||
<Button variant="secondary" onClick={onDismiss} fill="outline">
|
||||
<Trans i18nKey="library-panel.add-modal.cancel">Cancel</Trans>
|
||||
</Button>
|
||||
<Button onClick={onCreate} disabled={invalidInput}>
|
||||
<Trans i18nKey="library-panel.add-modal.create">Create library panel</Trans>
|
||||
</Button>
|
||||
</Modal.ButtonRow>
|
||||
)}
|
||||
<Stack gap={1} justifyContent={'start'}>
|
||||
<Button onClick={onCreate} disabled={invalidInput}>
|
||||
<Trans i18nKey="share-panel.new-library-panel.create-button">Create library panel</Trans>
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onDismiss} fill="outline">
|
||||
<Trans i18nKey="share-panel.new-library-panel.cancel-button">Cancel</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Button, ModalsController, ButtonProps } from '@grafana/ui';
|
||||
import { useDeletePublicDashboardMutation } from 'app/features/dashboard/api/publicDashboardApi';
|
||||
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
||||
|
@ -42,9 +41,7 @@ export const DeletePublicDashboardButton = ({
|
|||
return (
|
||||
<ModalsController>
|
||||
{({ showModal, hideModal }) => {
|
||||
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');
|
||||
const translatedRevocationButtonText = t('shared-dashboard-list.button.revoke-button-text', 'Revoke access');
|
||||
return (
|
||||
<Button
|
||||
aria-label={translatedRevocationButtonText}
|
||||
|
|
|
@ -2,7 +2,6 @@ import { css } from '@emotion/css';
|
|||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { ConfirmModal, useStyles2 } from '@grafana/ui';
|
||||
|
||||
const Body = () => {
|
||||
|
@ -10,15 +9,10 @@ const Body = () => {
|
|||
|
||||
return (
|
||||
<p className={styles.description}>
|
||||
{config.featureToggles.newDashboardSharingComponent
|
||||
? t(
|
||||
'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-body-text',
|
||||
'Are you sure you want to revoke this URL? The dashboard will no longer be public.'
|
||||
)}
|
||||
{t(
|
||||
'shared-dashboard.delete-modal.revoke-body-text',
|
||||
'Are you sure you want to revoke this access? The dashboard can no longer be shared.'
|
||||
)}
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
@ -30,9 +24,7 @@ export const DeletePublicDashboardModal = ({
|
|||
onConfirm: () => void;
|
||||
onDismiss: () => void;
|
||||
}) => {
|
||||
const translatedRevocationModalText = config.featureToggles.newDashboardSharingComponent
|
||||
? t('shared-dashboard.delete-modal.revoke-title', 'Revoke access')
|
||||
: t('public-dashboard.delete-modal.revoke-title', 'Revoke public URL');
|
||||
const translatedRevocationModalText = t('shared-dashboard.delete-modal.revoke-title', 'Revoke access');
|
||||
return (
|
||||
<ConfirmModal
|
||||
isOpen
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useMedia } from 'react-use';
|
|||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config, reportInteraction } from '@grafana/runtime';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import {
|
||||
Card,
|
||||
EmptyState,
|
||||
|
@ -57,11 +57,7 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
|
|||
|
||||
const CardActions = useMemo(() => (isMobile ? Card.Actions : Card.SecondaryActions), [isMobile]);
|
||||
|
||||
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');
|
||||
|
||||
const translatedPauseSharingText = t('shared-dashboard-list.toggle.pause-sharing-toggle-text', 'Pause access');
|
||||
return (
|
||||
<Card className={styles.card} href={`/d/${pd.dashboardUid}`}>
|
||||
<Card.Heading className={styles.heading}>
|
||||
|
@ -91,11 +87,7 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
|
|||
color={theme.colors.warning.text}
|
||||
href={generatePublicDashboardUrl(pd.accessToken)}
|
||||
key="public-dashboard-url"
|
||||
tooltip={
|
||||
isNewSharingComponentEnabled
|
||||
? t('shared-dashboard-list.button.view-button-tooltip', 'View shared dashboard')
|
||||
: t('public-dashboard-list.button.view-button-tooltip', 'View public dashboard')
|
||||
}
|
||||
tooltip={t('shared-dashboard-list.button.view-button-tooltip', 'View shared dashboard')}
|
||||
data-testid={selectors.ListItem.linkButton}
|
||||
/>
|
||||
<LinkButton
|
||||
|
@ -105,11 +97,7 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
|
|||
color={theme.colors.warning.text}
|
||||
href={generatePublicDashboardConfigUrl(pd.dashboardUid, pd.slug)}
|
||||
key="public-dashboard-config-url"
|
||||
tooltip={
|
||||
isNewSharingComponentEnabled
|
||||
? t('shared-dashboard-list.button.config-button-tooltip', 'Configure shared dashboard')
|
||||
: t('public-dashboard-list.button.config-button-tooltip', 'Configure public dashboard')
|
||||
}
|
||||
tooltip={t('shared-dashboard-list.button.config-button-tooltip', 'Configure shared dashboard')}
|
||||
data-testid={selectors.ListItem.configButton}
|
||||
/>
|
||||
{hasWritePermissions && (
|
||||
|
@ -118,11 +106,7 @@ const PublicDashboardCard = ({ pd }: { pd: PublicDashboardListResponse }) => {
|
|||
icon="trash-alt"
|
||||
variant="secondary"
|
||||
publicDashboard={pd}
|
||||
tooltip={
|
||||
isNewSharingComponentEnabled
|
||||
? t('shared-dashboard-list.button.revoke-button-tooltip', 'Revoke access')
|
||||
: t('public-dashboard-list.button.revoke-button-tooltip', 'Revoke public dashboard URL')
|
||||
}
|
||||
tooltip={t('shared-dashboard-list.button.revoke-button-tooltip', 'Revoke access')}
|
||||
loader={<Spinner />}
|
||||
data-testid={selectors.ListItem.trashcanButton}
|
||||
/>
|
||||
|
@ -144,43 +128,23 @@ export const PublicDashboardListTable = () => {
|
|||
{!isLoading && !isError && !!paginatedPublicDashboards && (
|
||||
<div>
|
||||
{paginatedPublicDashboards.publicDashboards.length === 0 ? (
|
||||
config.featureToggles.newDashboardSharingComponent ? (
|
||||
<EmptyState
|
||||
variant="call-to-action"
|
||||
message={t(
|
||||
'shared-dashboard-list.empty-state.message',
|
||||
"You haven't created any shared dashboards yet"
|
||||
)}
|
||||
>
|
||||
<Trans i18nKey="shared-dashboard-list.empty-state.more-info">
|
||||
Create a shared dashboard from any existing dashboard through the <b>Share</b> modal.{' '}
|
||||
<TextLink
|
||||
external
|
||||
href="https://grafana.com/docs/grafana/latest/dashboards/share-dashboards-panels/shared-dashboards"
|
||||
>
|
||||
Learn more
|
||||
</TextLink>
|
||||
</Trans>
|
||||
</EmptyState>
|
||||
) : (
|
||||
<EmptyState
|
||||
variant="call-to-action"
|
||||
message={t(
|
||||
'public-dashboard-list.empty-state.message',
|
||||
"You haven't created any public dashboards yet"
|
||||
)}
|
||||
>
|
||||
<Trans i18nKey="public-dashboard-list.empty-state.more-info">
|
||||
Create a public dashboard from any existing dashboard through the <b>Share</b> modal.{' '}
|
||||
<TextLink
|
||||
external
|
||||
href="https://grafana.com/docs/grafana/latest/dashboards/dashboard-public/#make-a-dashboard-public"
|
||||
>
|
||||
Learn more
|
||||
</TextLink>
|
||||
</Trans>
|
||||
</EmptyState>
|
||||
)
|
||||
<EmptyState
|
||||
variant="call-to-action"
|
||||
message={t(
|
||||
'shared-dashboard-list.empty-state.message',
|
||||
"You haven't created any shared dashboards yet"
|
||||
)}
|
||||
>
|
||||
<Trans i18nKey="shared-dashboard-list.empty-state.more-info">
|
||||
Create a shared dashboard from any existing dashboard through the <b>Share</b> modal.{' '}
|
||||
<TextLink
|
||||
external
|
||||
href="https://grafana.com/docs/grafana/latest/dashboards/share-dashboards-panels/shared-dashboards"
|
||||
>
|
||||
Learn more
|
||||
</TextLink>
|
||||
</Trans>
|
||||
</EmptyState>
|
||||
) : (
|
||||
<>
|
||||
<ul className={styles.list}>
|
||||
|
|
|
@ -5407,10 +5407,6 @@
|
|||
"save-dashboard-short": "Save",
|
||||
"save-library-panel": "Save library panel",
|
||||
"settings": "Dashboard settings",
|
||||
"share": {
|
||||
"label": "Share",
|
||||
"tooltip": "Share dashboard"
|
||||
},
|
||||
"share-button": "Share",
|
||||
"unlink-library-panel": "Unlink library panel",
|
||||
"unmark-favorite": "Unmark as favorite"
|
||||
|
@ -5663,14 +5659,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"config-public-dashboard": {
|
||||
"confirmText": {
|
||||
"revoke-public-url": "Revoke public URL"
|
||||
},
|
||||
"title": {
|
||||
"revoke-public-url": "Revoke public URL"
|
||||
}
|
||||
},
|
||||
"constant-variable-form": {
|
||||
"constant-options": "Constant options",
|
||||
"label-value": "Value",
|
||||
|
@ -9273,8 +9261,6 @@
|
|||
},
|
||||
"library-panel": {
|
||||
"add-modal": {
|
||||
"cancel": "Cancel",
|
||||
"create": "Create library panel",
|
||||
"error": "Library panel with this name already exists",
|
||||
"folder": "Save in folder",
|
||||
"folder-description": "Library panel permissions are derived from the folder permissions",
|
||||
|
@ -10343,9 +10329,6 @@
|
|||
"profiles": {
|
||||
"title": "Profiles"
|
||||
},
|
||||
"public": {
|
||||
"title": "Public dashboards"
|
||||
},
|
||||
"recently-deleted": {
|
||||
"subtitle": "Any items listed here for more than 30 days will be automatically deleted.",
|
||||
"title": "Recently deleted"
|
||||
|
@ -11765,7 +11748,6 @@
|
|||
"email-share-type-option-label": "Only specified people",
|
||||
"pause-sharing-dashboard-label": "Pause sharing dashboard",
|
||||
"public-share-type-option-label": "Anyone with a link",
|
||||
"revoke-body": "Are you sure you want to revoke this URL? The dashboard will no longer be public.",
|
||||
"revoke-public-URL-button": "Revoke public URL",
|
||||
"revoke-public-URL-button-title": "Revoke public URL",
|
||||
"settings-title": "Settings"
|
||||
|
@ -11779,7 +11761,6 @@
|
|||
"success-pause": "Your dashboard access has been paused",
|
||||
"success-resume": "Your dashboard access has been resumed",
|
||||
"success-update": "Settings have been successfully updated",
|
||||
"success-update-old": "Public dashboard updated!",
|
||||
"time-range-label": "Time range",
|
||||
"time-range-tooltip": "The shared dashboard uses the default time range settings of the dashboard"
|
||||
},
|
||||
|
@ -11788,10 +11769,6 @@
|
|||
"unsupported-features-desc": "Currently, we don’t support template variables or frontend data sources",
|
||||
"welcome-title": "Welcome to public dashboards!"
|
||||
},
|
||||
"delete-modal": {
|
||||
"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": {
|
||||
"accept-button": "Accept",
|
||||
"alert-text": "Sharing dashboards by email is billed per user for the duration of the 30-day token, regardless of how many dashboards are shared. Billing stops after 30 days unless you renew the token.",
|
||||
|
@ -11821,11 +11798,8 @@
|
|||
"success-share-type-change": "Dashboard access updated: Only specific people can now access with the link"
|
||||
},
|
||||
"modal-alerts": {
|
||||
"no-upsert-perm-alert-desc": "Contact your admin to get permission to {{action}} public dashboards",
|
||||
"no-upsert-perm-alert-title": "You don’t have permission to {{ action }} a public dashboard",
|
||||
"save-dashboard-changes-alert-title": "Please save your dashboard changes before updating the public configuration",
|
||||
"unsupport-data-source-alert-readmore-link": "Read more about supported data sources",
|
||||
"unsupported-data-source-alert-desc": "There are data sources in this dashboard that are unsupported for public dashboards. Panels that use these data sources may not function properly: {{unsupportedDataSources}}.",
|
||||
"unsupported-data-source-alert-title": "Unsupported data sources",
|
||||
"unsupported-template-variable-alert-desc": "This public dashboard may not work since it uses template variables",
|
||||
"unsupported-template-variable-alert-title": "Template variables are not supported"
|
||||
|
@ -11859,8 +11833,7 @@
|
|||
"time-range-text": "Time range = "
|
||||
},
|
||||
"share": {
|
||||
"success-delete": "Your dashboard is no longer shareable",
|
||||
"success-delete-old": "Public dashboard deleted!"
|
||||
"success-delete": "Your dashboard is no longer shareable"
|
||||
},
|
||||
"share-configuration": {
|
||||
"share-type-label": "Link access"
|
||||
|
@ -11879,24 +11852,6 @@
|
|||
"revoke-access-button": "Revoke access",
|
||||
"revoke-access-description": "Are you sure you want to revoke this access? The dashboard can no longer be shared.",
|
||||
"unsupported-data-source-alert-desc": "There are data sources in this dashboard that are unsupported for shared dashboards. Panels that use these data sources may not function properly: {{unsupportedDataSources}}."
|
||||
},
|
||||
"sharing": {
|
||||
"success-creation": "Dashboard is public!"
|
||||
}
|
||||
},
|
||||
"public-dashboard-list": {
|
||||
"button": {
|
||||
"config-button-tooltip": "Configure public dashboard",
|
||||
"revoke-button-text": "Revoke public URL",
|
||||
"revoke-button-tooltip": "Revoke public dashboard URL",
|
||||
"view-button-tooltip": "View public dashboard"
|
||||
},
|
||||
"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>"
|
||||
},
|
||||
"toggle": {
|
||||
"pause-sharing-toggle-text": "Pause sharing"
|
||||
}
|
||||
},
|
||||
"public-dashboard-users-access-list": {
|
||||
|
@ -11904,8 +11859,6 @@
|
|||
"external-link": "External link",
|
||||
"loading-text": "Loading...",
|
||||
"open-dashboard-list-text": "Open dashboards list",
|
||||
"public-dashboard-link": "Public dashboard URL",
|
||||
"public-dashboard-setting": "Public dashboard settings",
|
||||
"sharing-setting": "Sharing settings"
|
||||
},
|
||||
"delete-user-modal": {
|
||||
|
@ -11913,14 +11866,12 @@
|
|||
"delete-user-cancel-button": "Cancel",
|
||||
"delete-user-revoke-access-button": "Revoke access",
|
||||
"revoke-access-title": "Revoke access",
|
||||
"revoke-user-access-modal-desc-line1": "Are you sure you want to revoke access for {{email}}?",
|
||||
"revoke-user-access-modal-desc-line2": "This action will immediately revoke {{email}}'s access to all public dashboards."
|
||||
"revoke-user-access-modal-desc-line1": "Are you sure you want to revoke access for {{email}}?"
|
||||
},
|
||||
"delete-user-shared-dashboards-modal": {
|
||||
"revoke-user-access-modal-desc-line2": "This action will immediately revoke {{email}}'s access to all shared dashboards."
|
||||
},
|
||||
"modal": {
|
||||
"dashboard-modal-title": "Public dashboards",
|
||||
"shared-dashboard-modal-title": "Shared dashboards"
|
||||
},
|
||||
"table-body": {
|
||||
|
@ -12422,8 +12373,6 @@
|
|||
"export": "Export",
|
||||
"library-panel": "Library panel",
|
||||
"link": "Link",
|
||||
"panel-embed": "Embed",
|
||||
"public-dashboard": "Public Dashboard",
|
||||
"public-dashboard-title": "Public dashboard",
|
||||
"snapshot": "Snapshot"
|
||||
},
|
||||
|
@ -14019,7 +13968,6 @@
|
|||
},
|
||||
"users-access-list": {
|
||||
"tabs": {
|
||||
"public-dashboard-users-tab-title": "Public dashboard users",
|
||||
"shared-dashboard-users-tab-title": "Shared dashboard users"
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue