Compare commits
4 Commits
ash/react-
...
restore-da
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0821ad9beb | ||
|
|
9cb0a8fe93 | ||
|
|
8caa52ca0f | ||
|
|
eba4c8ecc2 |
@@ -408,7 +408,7 @@ func (s *ServiceImpl) buildDashboardNavLinks(c *contextmodel.ReqContext) []*navt
|
||||
}
|
||||
|
||||
//nolint:staticcheck // not yet migrated to OpenFeature
|
||||
if s.features.IsEnabled(c.Req.Context(), featuremgmt.FlagRestoreDashboards) && (c.GetOrgRole() == org.RoleAdmin || c.IsGrafanaAdmin) {
|
||||
if s.features.IsEnabled(c.Req.Context(), featuremgmt.FlagRestoreDashboards) && hasAccess(ac.EvalPermission(dashboards.ActionDashboardsDelete)) {
|
||||
dashboardChildNavs = append(dashboardChildNavs, &navtree.NavLink{
|
||||
Text: "Recently deleted",
|
||||
SubTitle: "Any items listed here for more than 30 days will be automatically deleted.",
|
||||
|
||||
@@ -55,6 +55,13 @@ jest.mock('@grafana/runtime', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@grafana/runtime/internal', () => {
|
||||
return {
|
||||
...jest.requireActual('@grafana/runtime/internal'),
|
||||
evaluateBooleanFlag: jest.fn().mockReturnValue(false),
|
||||
};
|
||||
});
|
||||
|
||||
function render(ui: Parameters<typeof testRender>[0], options: Parameters<typeof testRender>[1] = {}) {
|
||||
return testRender(ui, {
|
||||
preloadedState: {
|
||||
@@ -113,6 +120,30 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
expect(await screen.findByRole('button', { name: 'New' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the "Recently deleted" button when restore is enabled and user can delete dashboards', async () => {
|
||||
const previousFlag = config.featureToggles.restoreDashboards;
|
||||
config.featureToggles.restoreDashboards = true;
|
||||
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
await screen.findByPlaceholderText('Search for dashboards and folders');
|
||||
expect(await screen.findByRole('link', { name: 'Recently deleted' })).toBeInTheDocument();
|
||||
|
||||
config.featureToggles.restoreDashboards = previousFlag;
|
||||
});
|
||||
|
||||
it('does not show the "Recently deleted" button when user cannot delete dashboards', async () => {
|
||||
const previousFlag = config.featureToggles.restoreDashboards;
|
||||
config.featureToggles.restoreDashboards = true;
|
||||
mockPermissions.canDeleteDashboards = false;
|
||||
jest.spyOn(contextSrv, 'hasPermission').mockReturnValue(false);
|
||||
|
||||
render(<BrowseDashboardsPage queryParams={{}} />);
|
||||
await screen.findByPlaceholderText('Search for dashboards and folders');
|
||||
expect(screen.queryByRole('link', { name: 'Recently deleted' })).not.toBeInTheDocument();
|
||||
|
||||
config.featureToggles.restoreDashboards = previousFlag;
|
||||
});
|
||||
|
||||
it('does not show the "New" button if the user does not have permissions', async () => {
|
||||
mockPermissions.canCreateDashboards = false;
|
||||
mockPermissions.canCreateFolders = false;
|
||||
|
||||
@@ -11,6 +11,7 @@ import { LinkButton, FilterInput, useStyles2, Text, Stack } from '@grafana/ui';
|
||||
import { useGetFolderQueryFacade, useUpdateFolder } from 'app/api/clients/folder/v1beta1/hooks';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import { getConfig } from 'app/core/config';
|
||||
import { AccessControlAction } from 'app/types/accessControl';
|
||||
import { useDispatch } from 'app/types/store';
|
||||
|
||||
import { FolderRepo } from '../../core/components/NestedFolderPicker/FolderRepo';
|
||||
@@ -123,7 +124,6 @@ const BrowseDashboardsPage = memo(({ queryParams }: { queryParams: Record<string
|
||||
canCreateDashboards,
|
||||
canCreateFolders,
|
||||
} = getFolderPermissions(folder);
|
||||
const hasAdminRights = contextSrv.hasRole('Admin') || contextSrv.isGrafanaAdmin;
|
||||
const isProvisionedFolder = folder?.managedBy === ManagerKind.Repo;
|
||||
const showEditTitle = canEditFolders && folderUID && !isProvisionedFolder;
|
||||
const permissions = {
|
||||
@@ -174,15 +174,16 @@ const BrowseDashboardsPage = memo(({ queryParams }: { queryParams: Record<string
|
||||
renderTitle={renderTitle}
|
||||
actions={
|
||||
<>
|
||||
{config.featureToggles.restoreDashboards && hasAdminRights && (
|
||||
<LinkButton
|
||||
variant="secondary"
|
||||
href={getConfig().appSubUrl + '/dashboard/recently-deleted'}
|
||||
onClick={handleButtonClickToRecentlyDeleted}
|
||||
>
|
||||
<Trans i18nKey="browse-dashboards.actions.button-to-recently-deleted">Recently deleted</Trans>
|
||||
</LinkButton>
|
||||
)}
|
||||
{config.featureToggles.restoreDashboards &&
|
||||
(canDeleteDashboards || contextSrv.hasPermission(AccessControlAction.DashboardsDelete)) && (
|
||||
<LinkButton
|
||||
variant="secondary"
|
||||
href={getConfig().appSubUrl + '/dashboard/recently-deleted'}
|
||||
onClick={handleButtonClickToRecentlyDeleted}
|
||||
>
|
||||
<Trans i18nKey="browse-dashboards.actions.button-to-recently-deleted">Recently deleted</Trans>
|
||||
</LinkButton>
|
||||
)}
|
||||
{folderDTO && <FolderActionsButton folder={folderDTO} repoType={repoType} isReadOnlyRepo={isReadOnlyRepo} />}
|
||||
{(canCreateDashboards || canCreateFolders) && (
|
||||
<CreateNewButton
|
||||
|
||||
@@ -59,9 +59,9 @@ export const DeleteModal = ({ onConfirm, onDismiss, selectedItems, ...props }: P
|
||||
<Text element="p">
|
||||
<Trans i18nKey="browse-dashboards.action.delete-modal-restore-dashboards-text">
|
||||
This action will delete the selected folders immediately. Deleted dashboards will be kept in the
|
||||
history for up to 12 months and can be restored by your organization administrator during that time.
|
||||
The history is limited to 1000 dashboards — older ones may be removed sooner if the limit is reached.
|
||||
Folders cannot be restored.
|
||||
history for up to 12 months. Users with delete permissions can restore the dashboards they deleted,
|
||||
and admins can restore any user's deleted dashboards. The history is limited to 1000 dashboards — older
|
||||
ones may be removed sooner if the limit is reached. Folders cannot be restored.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Space v={2} />
|
||||
|
||||
@@ -19,8 +19,8 @@ export const RecentlyDeletedEmptyState = ({ searchState }: RecentlyDeletedEmptyS
|
||||
role="alert"
|
||||
>
|
||||
<Trans i18nKey={'recently-deleted.page.no-deleted-dashboards-text'}>
|
||||
When you delete a dashboard, it will appear here for 30 days before being permanently deleted. Your organization
|
||||
administrator can restore recently-deleted dashboards.
|
||||
When you delete a dashboard, it will appear here for 30 days before being permanently deleted. Users with delete
|
||||
permissions can restore the dashboards they deleted, and admins can restore any user's deleted dashboards.
|
||||
</Trans>
|
||||
</EmptyState>
|
||||
);
|
||||
|
||||
@@ -81,8 +81,9 @@ export function DeleteDashboardModal({ dashboardTitle, onConfirm, onClose }: Del
|
||||
<Text element="p">
|
||||
<Trans i18nKey="dashboard-settings.delete-modal-restore-dashboards-text">
|
||||
This action will delete the dashboard. Deleted dashboards will be kept in the history for up to 12
|
||||
months and can be restored by your organization administrator during that time. The history is limited
|
||||
to 1000 dashboards—older ones will be removed sooner if the limit is reached.
|
||||
months. Users with delete permissions can restore the dashboards they deleted, and admins can restore
|
||||
any user's deleted dashboards. The history is limited to 1000 dashboards—older ones will be removed
|
||||
sooner if the limit is reached.
|
||||
</Trans>
|
||||
</Text>
|
||||
<Space v={1} />
|
||||
|
||||
@@ -534,7 +534,7 @@ export function getAppRoutes(): RouteDescriptor[] {
|
||||
},
|
||||
config.featureToggles.restoreDashboards && {
|
||||
path: '/dashboard/recently-deleted',
|
||||
roles: () => ['Admin', 'ServerAdmin'],
|
||||
roles: () => contextSrv.evaluatePermission([AccessControlAction.DashboardsDelete]),
|
||||
component: SafeDynamicImport(
|
||||
() => import(/* webpackChunkName: "RecentlyDeletedPage" */ 'app/features/browse-dashboards/RecentlyDeletedPage')
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user