mirror of
https://github.com/grafana/grafana.git
synced 2025-08-03 04:22:13 +08:00
BrowseDashboardsPage: added new pull request banner on new folder creation (#107596)
* BrowseDashboardsPage: added ProvisionedFolderPreviewBanner to display new provisioned folder on branch alert * add comment * fix test * i18n * Added test for PreviewBannerViewPR * fix test, i18n fix
This commit is contained in:
@ -163,17 +163,17 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
|
||||
describe('at the root level', () => {
|
||||
it('displays "Dashboards" as the page title', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: 'Dashboards' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays a search input', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByPlaceholderText('Search for dashboards and folders')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the "New" button', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('button', { name: 'New' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@ -185,25 +185,25 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
canCreateFolders: false,
|
||||
};
|
||||
});
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: 'Dashboards' })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'New' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show "Folder actions"', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: 'Dashboards' })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Folder actions' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show an "Edit title" button', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: 'Dashboards' })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Edit title' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show any tabs', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: 'Dashboards' })).toBeInTheDocument();
|
||||
|
||||
expect(screen.queryByRole('tab', { name: 'Dashboards' })).not.toBeInTheDocument();
|
||||
@ -212,7 +212,7 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
});
|
||||
|
||||
it('displays the filters and hides the actions initially', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
await screen.findByPlaceholderText('Search for dashboards and folders');
|
||||
|
||||
expect(await screen.findByText('Sort')).toBeInTheDocument();
|
||||
@ -223,7 +223,7 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
});
|
||||
|
||||
it('selecting an item hides the filters and shows the actions instead', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
|
||||
const checkbox = await screen.findByTestId(selectors.pages.BrowseDashboards.table.checkbox(dashbdD.item.uid));
|
||||
await userEvent.click(checkbox);
|
||||
@ -238,7 +238,7 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
});
|
||||
|
||||
it('navigating into a child item resets the selected state', async () => {
|
||||
const { rerender } = render(<BrowseDashboardsPage />);
|
||||
const { rerender } = render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
|
||||
const checkbox = await screen.findByTestId(selectors.pages.BrowseDashboards.table.checkbox(folderA.item.uid));
|
||||
await userEvent.click(checkbox);
|
||||
@ -248,7 +248,7 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
expect(screen.getByRole('button', { name: 'Delete' })).toBeInTheDocument();
|
||||
|
||||
(useParams as jest.Mock).mockReturnValue({ uid: folderA.item.uid });
|
||||
rerender(<BrowseDashboardsPage />);
|
||||
rerender(<BrowseDashboardsPage queryParams={{}} />);
|
||||
|
||||
// Check the filters are now visible again
|
||||
expect(await screen.findByText('Filter by tag')).toBeInTheDocument();
|
||||
@ -266,17 +266,17 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
});
|
||||
|
||||
it('shows the folder name as the page title', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: folderA.item.title })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays a search input', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByPlaceholderText('Search for dashboards and folders')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the "New" button', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('button', { name: 'New' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@ -288,13 +288,13 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
canCreateFolders: false,
|
||||
};
|
||||
});
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: folderA.item.title })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'New' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the "Folder actions" button', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('button', { name: 'Folder actions' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@ -308,13 +308,13 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
canViewPermissions: false,
|
||||
};
|
||||
});
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: folderA.item.title })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Folder actions' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows an "Edit title" button', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('button', { name: 'Edit title' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@ -325,13 +325,13 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
canEditFolders: false,
|
||||
};
|
||||
});
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('heading', { name: folderA.item.title })).toBeInTheDocument();
|
||||
expect(screen.queryByRole('button', { name: 'Edit title' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('displays all the folder tabs and shows the "Dashboards" tab as selected', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
expect(await screen.findByRole('tab', { name: 'Dashboards' })).toBeInTheDocument();
|
||||
expect(await screen.findByRole('tab', { name: 'Dashboards' })).toHaveAttribute('aria-selected', 'true');
|
||||
|
||||
@ -343,7 +343,7 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
});
|
||||
|
||||
it('displays the filters and hides the actions initially', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
await screen.findByPlaceholderText('Search for dashboards and folders');
|
||||
|
||||
expect(await screen.findByText('Sort')).toBeInTheDocument();
|
||||
@ -354,7 +354,7 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
});
|
||||
|
||||
it('selecting an item hides the filters and shows the actions instead', async () => {
|
||||
render(<BrowseDashboardsPage />);
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
|
||||
const checkbox = await screen.findByTestId(
|
||||
selectors.pages.BrowseDashboards.table.checkbox(folderA_folderA.item.uid)
|
||||
|
@ -25,13 +25,14 @@ import { BrowseFilters } from './components/BrowseFilters';
|
||||
import { BrowseView } from './components/BrowseView';
|
||||
import CreateNewButton from './components/CreateNewButton';
|
||||
import { FolderActionsButton } from './components/FolderActionsButton';
|
||||
import { ProvisionedFolderPreviewBanner } from './components/ProvisionedFolderPreviewBanner';
|
||||
import { SearchView } from './components/SearchView';
|
||||
import { getFolderPermissions } from './permissions';
|
||||
import { useHasSelection } from './state/hooks';
|
||||
import { setAllSelection } from './state/slice';
|
||||
|
||||
// New Browse/Manage/Search Dashboards views for nested folders
|
||||
const BrowseDashboardsPage = memo(() => {
|
||||
const BrowseDashboardsPage = memo(({ queryParams }: { queryParams: Record<string, string> }) => {
|
||||
const { uid: folderUID } = useParams();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@ -159,6 +160,7 @@ const BrowseDashboardsPage = memo(() => {
|
||||
}
|
||||
>
|
||||
<Page.Contents className={styles.pageContents}>
|
||||
<ProvisionedFolderPreviewBanner queryParams={queryParams} />
|
||||
<div>
|
||||
<FilterInput
|
||||
placeholder={getSearchPlaceholder(searchState.includePanels)}
|
||||
|
@ -161,7 +161,7 @@ describe('NewProvisionedFolderForm', () => {
|
||||
(getAppEvents as jest.Mock).mockReturnValue(mockAppEvents);
|
||||
|
||||
// Mock usePullRequestParam
|
||||
(usePullRequestParam as jest.Mock).mockReturnValue(null);
|
||||
(usePullRequestParam as jest.Mock).mockReturnValue({});
|
||||
|
||||
// Mock useCreateRepositoryFilesWithPathMutation
|
||||
const mockCreate = jest.fn();
|
||||
@ -409,7 +409,7 @@ describe('NewProvisionedFolderForm', () => {
|
||||
});
|
||||
|
||||
it('should show PR link when PR URL is available', () => {
|
||||
(usePullRequestParam as jest.Mock).mockReturnValue('https://github.com/grafana/grafana/pull/1234');
|
||||
(usePullRequestParam as jest.Mock).mockReturnValue({ prURL: 'https://github.com/grafana/grafana/pull/1234' });
|
||||
|
||||
setup();
|
||||
|
||||
|
@ -30,7 +30,7 @@ interface Props {
|
||||
}
|
||||
|
||||
function FormContent({ initialValues, repository, workflowOptions, folder, isGitHub, onDismiss }: FormProps) {
|
||||
const prURL = usePullRequestParam();
|
||||
const { prURL } = usePullRequestParam();
|
||||
const navigate = useNavigate();
|
||||
const [create, request] = useCreateRepositoryFilesWithPathMutation();
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
import { config } from '@grafana/runtime';
|
||||
import { CommonBannerProps } from 'app/features/dashboard-scene/saving/provisioned/DashboardPreviewBanner';
|
||||
import { PreviewBannerViewPR } from 'app/features/dashboard-scene/saving/provisioned/PreviewBannerViewPR';
|
||||
import { usePullRequestParam } from 'app/features/provisioning/hooks/usePullRequestParam';
|
||||
|
||||
export function ProvisionedFolderPreviewBanner({ queryParams }: CommonBannerProps) {
|
||||
const provisioningEnabled = config.featureToggles.provisioning;
|
||||
const { prURL, newPrURL } = usePullRequestParam();
|
||||
|
||||
if (!provisioningEnabled || 'kiosk' in queryParams) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (prURL) {
|
||||
return <PreviewBannerViewPR prParam={prURL} isFolder />;
|
||||
}
|
||||
|
||||
if (newPrURL) {
|
||||
return <PreviewBannerViewPR prParam={newPrURL} isFolder isNewPr />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
import { textUtil } from '@grafana/data';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Alert, Icon, Stack } from '@grafana/ui';
|
||||
import { Alert } from '@grafana/ui';
|
||||
import { useGetRepositoryFilesWithPathQuery } from 'app/api/clients/provisioning/v0alpha1';
|
||||
import { DashboardPageRouteSearchParams } from 'app/features/dashboard/containers/types';
|
||||
import { usePullRequestParam } from 'app/features/provisioning/hooks/usePullRequestParam';
|
||||
import { DashboardRoutes } from 'app/types';
|
||||
|
||||
interface CommonBannerProps {
|
||||
import { PreviewBannerViewPR } from './PreviewBannerViewPR';
|
||||
|
||||
export interface CommonBannerProps {
|
||||
queryParams: DashboardPageRouteSearchParams;
|
||||
path?: string;
|
||||
slug?: string;
|
||||
@ -19,13 +20,13 @@ interface DashboardPreviewBannerProps extends CommonBannerProps {
|
||||
|
||||
interface DashboardPreviewBannerContentProps extends Required<Omit<CommonBannerProps, 'route'>> {}
|
||||
|
||||
const commonAlertProps = {
|
||||
export const commonAlertProps = {
|
||||
severity: 'info' as const,
|
||||
style: { flex: 0 } as const,
|
||||
};
|
||||
|
||||
function DashboardPreviewBannerContent({ queryParams, slug, path }: DashboardPreviewBannerContentProps) {
|
||||
const prParam = usePullRequestParam();
|
||||
const { prURL } = usePullRequestParam();
|
||||
const file = useGetRepositoryFilesWithPathQuery({ name: slug, path, ref: queryParams.ref });
|
||||
|
||||
if (file.data?.errors) {
|
||||
@ -43,56 +44,14 @@ function DashboardPreviewBannerContent({ queryParams, slug, path }: DashboardPre
|
||||
}
|
||||
|
||||
// This page was loaded with a `pull_request_url` in the URL
|
||||
if (prParam?.length) {
|
||||
return (
|
||||
<Alert
|
||||
{...commonAlertProps}
|
||||
title={t(
|
||||
'dashboard-scene.dashboard-preview-banner.title-dashboard-loaded-request-git-hub',
|
||||
'This dashboard is loaded from a pull request in GitHub.'
|
||||
)}
|
||||
buttonContent={
|
||||
<Stack alignItems="center">
|
||||
<Trans i18nKey="dashboard-scene.dashboard-preview-banner.view-pull-request-in-git-hub">
|
||||
View pull request in GitHub
|
||||
</Trans>
|
||||
<Icon name="external-link-alt" />
|
||||
</Stack>
|
||||
}
|
||||
onRemove={() => window.open(textUtil.sanitizeUrl(prParam), '_blank')}
|
||||
>
|
||||
<Trans i18nKey="dashboard-scene.dashboard-preview-banner.value-not-saved">
|
||||
The value is not yet saved in the Grafana database
|
||||
</Trans>
|
||||
</Alert>
|
||||
);
|
||||
if (prURL?.length) {
|
||||
return <PreviewBannerViewPR prParam={prURL} />;
|
||||
}
|
||||
|
||||
// Check if this is a GitHub link
|
||||
const githubURL = file.data?.urls?.newPullRequestURL ?? file.data?.urls?.compareURL;
|
||||
if (githubURL) {
|
||||
return (
|
||||
<Alert
|
||||
{...commonAlertProps}
|
||||
title={t(
|
||||
'dashboard-scene.dashboard-preview-banner.title-dashboard-loaded-branch-git-hub',
|
||||
'This dashboard is loaded from a branch in GitHub.'
|
||||
)}
|
||||
buttonContent={
|
||||
<Stack alignItems="center">
|
||||
<Trans i18nKey="dashboard-scene.dashboard-preview-banner.open-pull-request-in-git-hub">
|
||||
Open pull request in GitHub
|
||||
</Trans>
|
||||
<Icon name="external-link-alt" />
|
||||
</Stack>
|
||||
}
|
||||
onRemove={() => window.open(textUtil.sanitizeUrl(githubURL), '_blank')}
|
||||
>
|
||||
<Trans i18nKey="dashboard-scene.dashboard-preview-banner.not-saved">
|
||||
The value is not yet saved in the Grafana database
|
||||
</Trans>
|
||||
</Alert>
|
||||
);
|
||||
return <PreviewBannerViewPR prParam={githubURL} isNewPr />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -0,0 +1,125 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { textUtil } from '@grafana/data';
|
||||
|
||||
import { PreviewBannerViewPR } from './PreviewBannerViewPR';
|
||||
|
||||
jest.mock('@grafana/data', () => ({
|
||||
...jest.requireActual('@grafana/data'),
|
||||
textUtil: {
|
||||
sanitizeUrl: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@grafana/i18n', () => ({
|
||||
t: jest.fn((key: string, defaultValue: string) => defaultValue),
|
||||
Trans: ({ children }: { children: React.ReactNode }) => children,
|
||||
}));
|
||||
|
||||
const mockTextUtil = jest.mocked(textUtil);
|
||||
|
||||
function setup(props: { prParam: string; isFolder?: boolean; isNewPr?: boolean } = { prParam: 'test-url' }) {
|
||||
const defaultProps = {
|
||||
isFolder: false,
|
||||
isNewPr: false,
|
||||
...props,
|
||||
};
|
||||
|
||||
const renderResult = render(<PreviewBannerViewPR {...defaultProps} />);
|
||||
|
||||
return { renderResult, props: defaultProps };
|
||||
}
|
||||
|
||||
describe('PreviewBannerViewPR', () => {
|
||||
let windowOpenSpy: jest.SpyInstance;
|
||||
|
||||
beforeAll(() => {
|
||||
Object.defineProperty(window, 'open', {
|
||||
writable: true,
|
||||
value: jest.fn(),
|
||||
});
|
||||
windowOpenSpy = jest.spyOn(window, 'open');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockTextUtil.sanitizeUrl.mockImplementation((url) => url);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
windowOpenSpy.mockRestore();
|
||||
});
|
||||
|
||||
describe('Dashboard scenarios', () => {
|
||||
it('should render correct text for new PR dashboard', () => {
|
||||
setup({ prParam: 'test-url', isFolder: false, isNewPr: true });
|
||||
|
||||
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||
expect(screen.getByText('This dashboard is loaded from a branch in GitHub.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render correct text for existing PR dashboard', () => {
|
||||
setup({ prParam: 'test-url', isFolder: false, isNewPr: false });
|
||||
|
||||
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||
expect(screen.getByText('This dashboard is loaded from a pull request in GitHub.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render correct button text for new PR dashboard', () => {
|
||||
setup({ prParam: 'test-url', isFolder: false, isNewPr: true });
|
||||
|
||||
expect(screen.getByText('Open pull request in GitHub')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render correct button text for existing PR dashboard', () => {
|
||||
setup({ prParam: 'test-url', isFolder: false, isNewPr: false });
|
||||
|
||||
expect(screen.getByText('View pull request in GitHub')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Folder scenarios', () => {
|
||||
it('should render correct text for new PR folder', () => {
|
||||
setup({ prParam: 'test-url', isFolder: true, isNewPr: true });
|
||||
|
||||
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||
expect(screen.getByText('A new folder has been created in a branch in GitHub.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render correct text for existing PR folder', () => {
|
||||
setup({ prParam: 'test-url', isFolder: true, isNewPr: false });
|
||||
|
||||
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||
expect(screen.getByText('A new folder has been created in a pull request in GitHub.')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render correct button text for new PR folder', () => {
|
||||
setup({ prParam: 'test-url', isFolder: true, isNewPr: true });
|
||||
|
||||
expect(screen.getByText('Open pull request in GitHub')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render correct button text for existing PR folder', () => {
|
||||
setup({ prParam: 'test-url', isFolder: true, isNewPr: false });
|
||||
|
||||
expect(screen.getByText('View pull request in GitHub')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Button functionality', () => {
|
||||
it('should open URL in new tab when button is clicked', async () => {
|
||||
const testUrl = 'https://github.com/test/repo/pull/123';
|
||||
setup({ prParam: testUrl });
|
||||
|
||||
const button = screen.getByRole('button', { name: /close alert/i });
|
||||
await userEvent.click(button);
|
||||
|
||||
expect(windowOpenSpy).toHaveBeenCalledWith(testUrl, '_blank');
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,64 @@
|
||||
import { textUtil } from '@grafana/data';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { Alert, Icon, Stack } from '@grafana/ui';
|
||||
|
||||
import { commonAlertProps } from './DashboardPreviewBanner';
|
||||
|
||||
// TODO: We have this https://github.com/grafana/git-ui-sync-project/issues/166 to add more details about the PR.
|
||||
|
||||
interface Props {
|
||||
prParam: string;
|
||||
isFolder?: boolean;
|
||||
isNewPr?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description This component is used to display a banner when a provisioned dashboard/folder is created or loaded from a new branch in Github.
|
||||
*/
|
||||
export function PreviewBannerViewPR({ prParam, isFolder = false, isNewPr }: Props) {
|
||||
const titleText = isFolder
|
||||
? isNewPr
|
||||
? t(
|
||||
'provisioned-resource-preview-banner.title-folder-created-branch-git-hub',
|
||||
'A new folder has been created in a branch in GitHub.'
|
||||
)
|
||||
: t(
|
||||
'provisioned-resource-preview-banner.title-folder-created-pull-request-git-hub',
|
||||
'A new folder has been created in a pull request in GitHub.'
|
||||
)
|
||||
: isNewPr
|
||||
? t(
|
||||
'provisioned-resource-preview-banner.title-dashboard-loaded-branch-git-hub',
|
||||
'This dashboard is loaded from a branch in GitHub.'
|
||||
)
|
||||
: t(
|
||||
'provisioned-resource-preview-banner.title-dashboard-loaded-pull-request-git-hub',
|
||||
'This dashboard is loaded from a pull request in GitHub.'
|
||||
);
|
||||
|
||||
return (
|
||||
<Alert
|
||||
{...commonAlertProps}
|
||||
title={titleText}
|
||||
buttonContent={
|
||||
<Stack alignItems="center">
|
||||
{isNewPr
|
||||
? t(
|
||||
'provisioned-resource-preview-banner.preview-banner.open-pull-request-in-git-hub',
|
||||
'Open pull request in GitHub'
|
||||
)
|
||||
: t(
|
||||
'provisioned-resource-preview-banner.preview-banner.view-pull-request-in-git-hub',
|
||||
'View pull request in GitHub'
|
||||
)}
|
||||
<Icon name="external-link-alt" />
|
||||
</Stack>
|
||||
}
|
||||
onRemove={() => window.open(textUtil.sanitizeUrl(prParam), '_blank')}
|
||||
>
|
||||
<Trans i18nKey="provisioned-resource-preview-banner.preview-banner.not-saved">
|
||||
The value is not yet saved in the Grafana database
|
||||
</Trans>
|
||||
</Alert>
|
||||
);
|
||||
}
|
@ -4,10 +4,10 @@ import { useUrlParams } from 'app/core/navigation/hooks';
|
||||
export const usePullRequestParam = () => {
|
||||
const [params] = useUrlParams();
|
||||
const prParam = params.get('pull_request_url');
|
||||
const newPrParam = params.get('new_pull_request_url');
|
||||
|
||||
if (!prParam) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return textUtil.sanitizeUrl(decodeURIComponent(prParam));
|
||||
return {
|
||||
prURL: prParam ? textUtil.sanitizeUrl(prParam) : undefined,
|
||||
newPrURL: newPrParam ? textUtil.sanitizeUrl(newPrParam) : undefined,
|
||||
};
|
||||
};
|
||||
|
@ -5472,15 +5472,9 @@
|
||||
"type": "Type"
|
||||
},
|
||||
"dashboard-preview-banner": {
|
||||
"not-saved": "The value is not yet saved in the Grafana database",
|
||||
"not-yet-saved": "The value is not saved in the Grafana database",
|
||||
"open-pull-request-in-git-hub": "Open pull request in GitHub",
|
||||
"title-dashboard-loaded-branch-git-hub": "This dashboard is loaded from a branch in GitHub.",
|
||||
"title-dashboard-loaded-external-repository": "This dashboard is loaded from an external repository",
|
||||
"title-dashboard-loaded-request-git-hub": "This dashboard is loaded from a pull request in GitHub.",
|
||||
"title-error-loading-dashboard": "Error loading dashboard",
|
||||
"value-not-saved": "The value is not yet saved in the Grafana database",
|
||||
"view-pull-request-in-git-hub": "View pull request in GitHub"
|
||||
"title-error-loading-dashboard": "Error loading dashboard"
|
||||
},
|
||||
"dashboard-scene": {
|
||||
"text": {
|
||||
@ -10312,6 +10306,17 @@
|
||||
"label-workflow": "Workflow"
|
||||
}
|
||||
},
|
||||
"provisioned-resource-preview-banner": {
|
||||
"preview-banner": {
|
||||
"not-saved": "The value is not yet saved in the Grafana database",
|
||||
"open-pull-request-in-git-hub": "Open pull request in GitHub",
|
||||
"view-pull-request-in-git-hub": "View pull request in GitHub"
|
||||
},
|
||||
"title-dashboard-loaded-branch-git-hub": "This dashboard is loaded from a branch in GitHub.",
|
||||
"title-dashboard-loaded-pull-request-git-hub": "This dashboard is loaded from a pull request in GitHub.",
|
||||
"title-folder-created-branch-git-hub": "A new folder has been created in a branch in GitHub.",
|
||||
"title-folder-created-pull-request-git-hub": "A new folder has been created in a pull request in GitHub."
|
||||
},
|
||||
"provisioning": {
|
||||
"banner": {
|
||||
"message": "This feature is currently under active development. For the best experience and latest improvements, we recommend using the <2>nightly build</2> of Grafana."
|
||||
|
Reference in New Issue
Block a user