mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-21 09:20:33 +01:00
Compare commits
1 Commits
chore/butt
...
chore/dash
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2775a0055 |
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { FullScreenHandle } from 'react-full-screen';
|
||||
import { Layout } from 'react-grid-layout';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -14,15 +14,18 @@ import {
|
||||
LockKeyhole,
|
||||
PenLine,
|
||||
Plus,
|
||||
Trash2,
|
||||
X,
|
||||
} from '@signozhq/icons';
|
||||
import { Card, Input, Modal, Popover, Tag, Tooltip } from 'antd';
|
||||
import { Card, Input, Modal, Tag, Tooltip } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import type { MenuItem } from '@signozhq/ui/dropdown-menu';
|
||||
import { DropdownMenuSimple as Dropdown } from '@signozhq/ui/dropdown-menu';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ConfigureIcon from 'assets/Integrations/ConfigureIcon';
|
||||
import { PANEL_GROUP_TYPES, PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { DeleteButton } from 'container/ListOfDashboard/TableComponents/DeleteButton';
|
||||
import { useDeleteDashboardDialog } from 'container/ListOfDashboard/TableComponents/DeleteButton';
|
||||
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
|
||||
import { useDashboardVariables } from 'hooks/dashboard/useDashboardVariables';
|
||||
import { useGetPublicDashboardMeta } from 'hooks/dashboard/useGetPublicDashboardMeta';
|
||||
@@ -90,12 +93,16 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
|
||||
const isPublicDashboardEnabled = isCloudUser || isEnterpriseSelfHostedUser;
|
||||
|
||||
const selectedData = dashboardData
|
||||
? {
|
||||
...dashboardData.data,
|
||||
uuid: dashboardData.id,
|
||||
}
|
||||
: ({} as DashboardData);
|
||||
const selectedData = useMemo(
|
||||
() =>
|
||||
dashboardData
|
||||
? {
|
||||
...dashboardData.data,
|
||||
uuid: dashboardData.id,
|
||||
}
|
||||
: ({} as DashboardData),
|
||||
[dashboardData],
|
||||
);
|
||||
const { dashboardVariables } = useDashboardVariables();
|
||||
|
||||
const {
|
||||
@@ -113,8 +120,6 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
|
||||
const { user } = useAppContext();
|
||||
const [editDashboard] = useComponentPermission(['edit_dashboard'], user.role);
|
||||
const [isDashboardSettingsOpen, setIsDashbordSettingsOpen] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const [isRenameDashboardOpen, setIsRenameDashboardOpen] =
|
||||
useState<boolean>(false);
|
||||
@@ -155,10 +160,9 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setIsPanelTypeSelectionModalOpen]);
|
||||
|
||||
const handleLockDashboardToggle = (): void => {
|
||||
setIsDashbordSettingsOpen(false);
|
||||
const handleLockDashboardToggle = useCallback((): void => {
|
||||
handleDashboardLockToggle(!isDashboardLocked);
|
||||
};
|
||||
}, [handleDashboardLockToggle, isDashboardLocked]);
|
||||
|
||||
const onNameChangeHandler = (): void => {
|
||||
if (!dashboardData) {
|
||||
@@ -192,6 +196,124 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
|
||||
const { t } = useTranslation(['dashboard', 'common']);
|
||||
|
||||
const {
|
||||
openConfirmation: openDeleteConfirmation,
|
||||
isDisabled: isDeleteDisabled,
|
||||
tooltipContent: deleteTooltipContent,
|
||||
contextHolder: deleteContextHolder,
|
||||
} = useDeleteDashboardDialog({
|
||||
createdBy: dashboardData?.createdBy || '',
|
||||
name: dashboardData?.data.title || '',
|
||||
id: String(dashboardData?.id) || '',
|
||||
isLocked: isDashboardLocked,
|
||||
routeToListPage: true,
|
||||
});
|
||||
|
||||
const isIntegrationDashboard = dashboardData?.createdBy === 'integration';
|
||||
|
||||
const dashboardMenuItems: MenuItem[] = useMemo(() => {
|
||||
const items: MenuItem[] = [];
|
||||
|
||||
if (isAuthor || user.role === USER_ROLES.ADMIN) {
|
||||
items.push({
|
||||
key: 'lock-unlock-dashboard',
|
||||
icon: <LockKeyhole size={14} />,
|
||||
label: isIntegrationDashboard ? (
|
||||
<Tooltip title="Dashboards created by integrations cannot be unlocked">
|
||||
<span>{isDashboardLocked ? 'Unlock Dashboard' : 'Lock Dashboard'}</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span>{isDashboardLocked ? 'Unlock Dashboard' : 'Lock Dashboard'}</span>
|
||||
),
|
||||
disabled: isIntegrationDashboard,
|
||||
onClick: handleLockDashboardToggle,
|
||||
});
|
||||
}
|
||||
|
||||
if (!isDashboardLocked && editDashboard) {
|
||||
items.push({
|
||||
key: 'rename-dashboard',
|
||||
icon: <PenLine size={14} />,
|
||||
label: 'Rename',
|
||||
onClick: () => setIsRenameDashboardOpen(true),
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
key: 'fullscreen',
|
||||
icon: <Fullscreen size={14} />,
|
||||
label: 'Full screen',
|
||||
onClick: () => {
|
||||
handle.enter();
|
||||
},
|
||||
});
|
||||
|
||||
items.push({ type: 'divider', key: 'sep-1' });
|
||||
|
||||
if (!isDashboardLocked && addPanelPermission) {
|
||||
items.push({
|
||||
key: 'new-section',
|
||||
icon: <FolderKanban size={14} />,
|
||||
label: 'New section',
|
||||
onClick: () => setIsPanelNameModalOpen(true),
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
key: 'export-json',
|
||||
icon: <FileJson size={14} />,
|
||||
label: 'Export JSON',
|
||||
onClick: () => {
|
||||
downloadObjectAsJson(
|
||||
sanitizeDashboardData(selectedData),
|
||||
selectedData.title,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
items.push({
|
||||
key: 'copy-json',
|
||||
icon: <ClipboardCopy size={14} />,
|
||||
label: 'Copy as JSON',
|
||||
onClick: () => {
|
||||
setCopy(JSON.stringify(sanitizeDashboardData(selectedData), null, 2));
|
||||
},
|
||||
});
|
||||
|
||||
items.push({ type: 'divider', key: 'sep-2' });
|
||||
|
||||
items.push({
|
||||
key: 'delete-dashboard',
|
||||
icon: <Trash2 size={14} />,
|
||||
label: deleteTooltipContent ? (
|
||||
<Tooltip placement="left" title={deleteTooltipContent}>
|
||||
<span>Delete Dashboard</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span>Delete Dashboard</span>
|
||||
),
|
||||
danger: true,
|
||||
disabled: isDeleteDisabled,
|
||||
onClick: openDeleteConfirmation,
|
||||
});
|
||||
|
||||
return items;
|
||||
}, [
|
||||
isAuthor,
|
||||
user.role,
|
||||
isIntegrationDashboard,
|
||||
isDashboardLocked,
|
||||
editDashboard,
|
||||
addPanelPermission,
|
||||
handleLockDashboardToggle,
|
||||
handle,
|
||||
selectedData,
|
||||
setCopy,
|
||||
deleteTooltipContent,
|
||||
isDeleteDisabled,
|
||||
openDeleteConfirmation,
|
||||
]);
|
||||
|
||||
// used to set the initial value for the updatedTitle
|
||||
// the context value is sometimes not available during the initial render
|
||||
// due to which the updatedTitle is set to some previous value
|
||||
@@ -360,114 +482,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
</div>
|
||||
<div className="right-section">
|
||||
<DateTimeSelectionV2 showAutoRefresh hideShareModal />
|
||||
<Popover
|
||||
open={isDashboardSettingsOpen}
|
||||
arrow={false}
|
||||
onOpenChange={(visible): void => setIsDashbordSettingsOpen(visible)}
|
||||
rootClassName="dashboard-settings"
|
||||
content={
|
||||
<div className="menu-content">
|
||||
<section className="section-1">
|
||||
{(isAuthor || user.role === USER_ROLES.ADMIN) && (
|
||||
<Tooltip
|
||||
title={
|
||||
dashboardData?.createdBy === 'integration' &&
|
||||
'Dashboards created by integrations cannot be unlocked'
|
||||
}
|
||||
>
|
||||
<Button
|
||||
disabled={dashboardData?.createdBy === 'integration'}
|
||||
onClick={handleLockDashboardToggle}
|
||||
data-testid="lock-unlock-dashboard"
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<LockKeyhole size={14} />}
|
||||
>
|
||||
{isDashboardLocked ? 'Unlock Dashboard' : 'Lock Dashboard'}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{!isDashboardLocked && editDashboard && (
|
||||
<Button
|
||||
onClick={(): void => {
|
||||
setIsRenameDashboardOpen(true);
|
||||
setIsDashbordSettingsOpen(false);
|
||||
}}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<PenLine size={14} />}
|
||||
>
|
||||
Rename
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
onClick={handle.enter}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<Fullscreen size={14} />}
|
||||
>
|
||||
Full screen
|
||||
</Button>
|
||||
</section>
|
||||
<section className="section-2">
|
||||
{!isDashboardLocked && addPanelPermission && (
|
||||
<Button
|
||||
onClick={(): void => {
|
||||
setIsPanelNameModalOpen(true);
|
||||
setIsDashbordSettingsOpen(false);
|
||||
}}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<FolderKanban size={14} />}
|
||||
>
|
||||
New section
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
onClick={(): void => {
|
||||
downloadObjectAsJson(
|
||||
sanitizeDashboardData(selectedData),
|
||||
selectedData.title,
|
||||
);
|
||||
setIsDashbordSettingsOpen(false);
|
||||
}}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<FileJson size={14} />}
|
||||
>
|
||||
Export JSON
|
||||
</Button>
|
||||
<Button
|
||||
onClick={(): void => {
|
||||
setCopy(
|
||||
JSON.stringify(sanitizeDashboardData(selectedData), null, 2),
|
||||
);
|
||||
setIsDashbordSettingsOpen(false);
|
||||
}}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<ClipboardCopy size={14} />}
|
||||
>
|
||||
Copy as JSON
|
||||
</Button>
|
||||
</section>
|
||||
<section className="delete-dashboard">
|
||||
<DeleteButton
|
||||
createdBy={dashboardData?.createdBy || ''}
|
||||
name={dashboardData?.data.title || ''}
|
||||
id={String(dashboardData?.id) || ''}
|
||||
isLocked={isDashboardLocked}
|
||||
routeToListPage
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
}
|
||||
trigger="click"
|
||||
placement="bottomRight"
|
||||
>
|
||||
<Dropdown menu={{ items: dashboardMenuItems }} align="end">
|
||||
<Button
|
||||
className="icons"
|
||||
data-testid="options"
|
||||
@@ -476,7 +491,8 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
size="icon"
|
||||
prefix={<Ellipsis size={14} />}
|
||||
/>
|
||||
</Popover>
|
||||
</Dropdown>
|
||||
{deleteContextHolder}
|
||||
{!isDashboardLocked && editDashboard && (
|
||||
<>
|
||||
<Button
|
||||
|
||||
@@ -37,10 +37,6 @@ import cx from 'classnames';
|
||||
import { ENTITY_VERSION_V5 } from 'constants/app';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import ROUTES from 'constants/routes';
|
||||
import {
|
||||
downloadObjectAsJson,
|
||||
sanitizeDashboardData,
|
||||
} from 'container/DashboardContainer/DashboardDescription/utils';
|
||||
import { Base64Icons } from 'container/DashboardContainer/DashboardSettings/General/utils';
|
||||
// #TODO: lucide will be removing brand icons like Github in future, in that case we can use simple icons
|
||||
// see more: https://github.com/lucide-icons/lucide/issues/94
|
||||
@@ -60,19 +56,14 @@ import {
|
||||
Check,
|
||||
Clock4,
|
||||
Ellipsis,
|
||||
EllipsisVertical,
|
||||
Expand,
|
||||
ExternalLink,
|
||||
FileJson,
|
||||
Github,
|
||||
HdmiPort,
|
||||
LayoutGrid,
|
||||
Link2,
|
||||
Plus,
|
||||
Radius,
|
||||
RotateCw,
|
||||
Search,
|
||||
SquareArrowOutUpRight,
|
||||
} from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||
@@ -85,8 +76,6 @@ import {
|
||||
} from 'types/api/dashboard/getAll';
|
||||
import APIError from 'types/api/error';
|
||||
import { isModifierKeyPressed } from 'utils/app';
|
||||
import { getAbsoluteUrl } from 'utils/basePath';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
|
||||
import awwSnapUrl from '@/assets/Icons/awwSnap.svg';
|
||||
import dashboardsUrl from '@/assets/Icons/dashboards.svg';
|
||||
@@ -94,7 +83,7 @@ import emptyStateUrl from '@/assets/Icons/emptyState.svg';
|
||||
|
||||
import ImportJSON from './ImportJSON';
|
||||
import { RequestDashboardBtn } from './RequestDashboardBtn';
|
||||
import { DeleteButton } from './TableComponents/DeleteButton';
|
||||
import { DashboardRowActions } from './TableComponents/DashboardRowActions';
|
||||
import {
|
||||
DashboardDynamicColumns,
|
||||
DynamicColumns,
|
||||
@@ -377,15 +366,6 @@ function DashboardsList(): JSX.Element {
|
||||
});
|
||||
};
|
||||
|
||||
const handleJsonExport = (event: React.MouseEvent<HTMLElement>): void => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
downloadObjectAsJson(
|
||||
sanitizeDashboardData({ ...dashboard, title: dashboard.name }),
|
||||
dashboard.name,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dashboard-list-item" onClick={onClickHandler}>
|
||||
<div className="title-with-action">
|
||||
@@ -430,80 +410,11 @@ function DashboardsList(): JSX.Element {
|
||||
</div>
|
||||
|
||||
{action && (
|
||||
<Popover
|
||||
content={
|
||||
<div className="dashboard-action-content">
|
||||
<section className="section-1">
|
||||
<Button
|
||||
className="action-btn"
|
||||
onClick={onClickHandler}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<Expand size={12} />}
|
||||
>
|
||||
View
|
||||
</Button>
|
||||
<Button
|
||||
className="action-btn"
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
openInNewTab(getLink());
|
||||
}}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<SquareArrowOutUpRight size={12} />}
|
||||
>
|
||||
Open in New Tab
|
||||
</Button>
|
||||
<Button
|
||||
className="action-btn"
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
setCopy(getAbsoluteUrl(getLink()));
|
||||
}}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<Link2 size={12} />}
|
||||
>
|
||||
Copy Link
|
||||
</Button>
|
||||
<Button
|
||||
className="action-btn"
|
||||
onClick={handleJsonExport}
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
prefix={<FileJson size={12} />}
|
||||
>
|
||||
Export JSON
|
||||
</Button>
|
||||
</section>
|
||||
<section className="section-2">
|
||||
<DeleteButton
|
||||
name={dashboard.name}
|
||||
id={dashboard.id}
|
||||
isLocked={dashboard.isLocked}
|
||||
createdBy={dashboard.createdBy}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
}
|
||||
placement="bottomRight"
|
||||
arrow={false}
|
||||
rootClassName="dashboard-actions"
|
||||
trigger="click"
|
||||
>
|
||||
<EllipsisVertical
|
||||
className="dashboard-action-icon"
|
||||
size={14}
|
||||
data-testid="dashboard-action-icon"
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
<DashboardRowActions
|
||||
dashboard={dashboard}
|
||||
setCopy={setCopy}
|
||||
safeNavigate={(linkTo): void => safeNavigate(linkTo)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="dashboard-details">
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
EllipsisVertical,
|
||||
Expand,
|
||||
FileJson,
|
||||
Link2,
|
||||
SquareArrowOutUpRight,
|
||||
Trash2,
|
||||
} from '@signozhq/icons';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import type { MenuItem } from '@signozhq/ui/dropdown-menu';
|
||||
import { DropdownMenuSimple } from '@signozhq/ui/dropdown-menu';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ROUTES from 'constants/routes';
|
||||
import {
|
||||
downloadObjectAsJson,
|
||||
sanitizeDashboardData,
|
||||
} from 'container/DashboardContainer/DashboardDescription/utils';
|
||||
import { getAbsoluteUrl } from 'utils/basePath';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
|
||||
import { Data } from '../DashboardsList';
|
||||
import { useDeleteDashboardDialog } from './DeleteButton';
|
||||
|
||||
interface DashboardRowActionsProps {
|
||||
dashboard: Data;
|
||||
setCopy: (s: string) => void;
|
||||
safeNavigate: (link: string) => void;
|
||||
}
|
||||
|
||||
export function DashboardRowActions({
|
||||
dashboard,
|
||||
setCopy,
|
||||
safeNavigate,
|
||||
}: DashboardRowActionsProps): JSX.Element {
|
||||
const link = `${ROUTES.ALL_DASHBOARD}/${dashboard.id}`;
|
||||
|
||||
const {
|
||||
openConfirmation,
|
||||
isDisabled: isDeleteDisabled,
|
||||
tooltipContent: deleteTooltipContent,
|
||||
contextHolder,
|
||||
} = useDeleteDashboardDialog({
|
||||
createdBy: dashboard.createdBy,
|
||||
name: dashboard.name,
|
||||
id: dashboard.id,
|
||||
isLocked: dashboard.isLocked,
|
||||
});
|
||||
|
||||
const items: MenuItem[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
key: 'view',
|
||||
icon: <Expand size={12} />,
|
||||
label: 'View',
|
||||
onClick: (): void => {
|
||||
safeNavigate(link);
|
||||
logEvent('Dashboard List: Clicked on dashboard', {
|
||||
dashboardId: dashboard.id,
|
||||
dashboardName: dashboard.name,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'open-new-tab',
|
||||
icon: <SquareArrowOutUpRight size={12} />,
|
||||
label: 'Open in New Tab',
|
||||
onClick: (): void => openInNewTab(link),
|
||||
},
|
||||
{
|
||||
key: 'copy-link',
|
||||
icon: <Link2 size={12} />,
|
||||
label: 'Copy Link',
|
||||
onClick: (): void => setCopy(getAbsoluteUrl(link)),
|
||||
},
|
||||
{
|
||||
key: 'export-json',
|
||||
icon: <FileJson size={12} />,
|
||||
label: 'Export JSON',
|
||||
onClick: (): void =>
|
||||
downloadObjectAsJson(
|
||||
sanitizeDashboardData({ ...dashboard, title: dashboard.name }),
|
||||
dashboard.name,
|
||||
),
|
||||
},
|
||||
{ type: 'divider', key: 'sep' },
|
||||
{
|
||||
key: 'delete',
|
||||
icon: <Trash2 size={12} />,
|
||||
label: deleteTooltipContent ? (
|
||||
<Tooltip placement="left" title={deleteTooltipContent}>
|
||||
<span>Delete Dashboard</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span>Delete Dashboard</span>
|
||||
),
|
||||
danger: true,
|
||||
disabled: isDeleteDisabled,
|
||||
onClick: openConfirmation,
|
||||
},
|
||||
],
|
||||
[
|
||||
dashboard,
|
||||
link,
|
||||
safeNavigate,
|
||||
setCopy,
|
||||
deleteTooltipContent,
|
||||
isDeleteDisabled,
|
||||
openConfirmation,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuSimple menu={{ items }} align="end">
|
||||
<Button
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
className="dashboard-action-icon"
|
||||
data-testid="dashboard-action-icon"
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
prefix={<EllipsisVertical size={14} />}
|
||||
/>
|
||||
</DropdownMenuSimple>
|
||||
{contextHolder}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import { USER_ROLES } from 'types/roles';
|
||||
import styles from '../DashboardActions.module.scss';
|
||||
import { Data } from '../DashboardsList';
|
||||
|
||||
interface DeleteButtonProps {
|
||||
interface UseDeleteDashboardDialogArgs {
|
||||
createdBy: string;
|
||||
name: string;
|
||||
id: string;
|
||||
@@ -23,26 +23,30 @@ interface DeleteButtonProps {
|
||||
routeToListPage?: boolean;
|
||||
}
|
||||
|
||||
export function DeleteButton({
|
||||
interface UseDeleteDashboardDialogResult {
|
||||
openConfirmation: () => void;
|
||||
isDisabled: boolean;
|
||||
tooltipContent: string;
|
||||
contextHolder: React.ReactElement;
|
||||
}
|
||||
|
||||
export function useDeleteDashboardDialog({
|
||||
createdBy,
|
||||
name,
|
||||
id,
|
||||
isLocked,
|
||||
routeToListPage,
|
||||
}: DeleteButtonProps): JSX.Element {
|
||||
routeToListPage = false,
|
||||
}: UseDeleteDashboardDialogArgs): UseDeleteDashboardDialogResult {
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
const { user } = useAppContext();
|
||||
const isAuthor = user?.email === createdBy;
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
const { t } = useTranslation(['dashboard']);
|
||||
|
||||
const deleteDashboardMutation = useDeleteDashboard(id);
|
||||
|
||||
const openConfirmationDialog = useCallback((): void => {
|
||||
const openConfirmation = useCallback((): void => {
|
||||
const { destroy } = modal.confirm({
|
||||
title: (
|
||||
<Typography.Title level={5}>
|
||||
@@ -95,23 +99,47 @@ export function DeleteButton({
|
||||
routeToListPage,
|
||||
]);
|
||||
|
||||
const getDeleteTooltipContent = (): string => {
|
||||
if (isLocked) {
|
||||
if (user.role === USER_ROLES.ADMIN || isAuthor) {
|
||||
return t('dashboard:locked_dashboard_delete_tooltip_admin_author');
|
||||
}
|
||||
|
||||
return t('dashboard:locked_dashboard_delete_tooltip_editor');
|
||||
let tooltipContent = '';
|
||||
if (isLocked) {
|
||||
if (user.role === USER_ROLES.ADMIN || isAuthor) {
|
||||
tooltipContent = t('dashboard:locked_dashboard_delete_tooltip_admin_author');
|
||||
} else {
|
||||
tooltipContent = t('dashboard:locked_dashboard_delete_tooltip_editor');
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
}
|
||||
|
||||
const isDisabled = isLocked || (user.role === USER_ROLES.VIEWER && !isAuthor);
|
||||
|
||||
return { openConfirmation, isDisabled, tooltipContent, contextHolder };
|
||||
}
|
||||
|
||||
interface DeleteButtonProps {
|
||||
createdBy: string;
|
||||
name: string;
|
||||
id: string;
|
||||
isLocked: boolean;
|
||||
routeToListPage?: boolean;
|
||||
}
|
||||
|
||||
export function DeleteButton({
|
||||
createdBy,
|
||||
name,
|
||||
id,
|
||||
isLocked,
|
||||
routeToListPage,
|
||||
}: DeleteButtonProps): JSX.Element {
|
||||
const { openConfirmation, isDisabled, tooltipContent, contextHolder } =
|
||||
useDeleteDashboardDialog({
|
||||
createdBy,
|
||||
name,
|
||||
id,
|
||||
isLocked,
|
||||
routeToListPage,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip placement="left" title={getDeleteTooltipContent()}>
|
||||
<Tooltip placement="left" title={tooltipContent}>
|
||||
<Button
|
||||
type="text"
|
||||
className={styles.deleteBtn}
|
||||
@@ -121,7 +149,7 @@ export function DeleteButton({
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (!isLocked) {
|
||||
openConfirmationDialog();
|
||||
openConfirmation();
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user