mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 17:35:53 +08:00
feat: [SIG-546]: user with viewer roles can only view saved views (#4663)
* feat: [SIG-543]: Users with VIEWER access can create/edit/delete views for logs and traces * feat: [SIG-543]: remove extra code * feat: [SIG-543]: role changes in the save views toolbar * feat: [SIG-543]: role changes in the save views toolbar * feat: remove the save feature / dashboard / alert feature for viewer roles * feat: remove the save feature / dashboard / alert feature for viewer roles * fix: address review comments
This commit is contained in:
parent
49aba4fb1c
commit
6b87118fc6
@ -1,3 +1,6 @@
|
||||
.hide-update {
|
||||
left: calc(50% - 41px) !important;
|
||||
}
|
||||
.explorer-update {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
@ -23,6 +26,10 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-divider {
|
||||
margin: 0;
|
||||
height: 28px;
|
||||
@ -55,6 +62,10 @@
|
||||
|
||||
.view-options,
|
||||
.actions {
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@ -102,6 +113,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.app-content {
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import axios from 'axios';
|
||||
import cx from 'classnames';
|
||||
import { getViewDetailsUsingViewKey } from 'components/ExplorerCard/utils';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { QueryParams } from 'constants/query';
|
||||
@ -31,10 +32,14 @@ import { useNotifications } from 'hooks/useNotifications';
|
||||
import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery';
|
||||
import { Check, ConciergeBell, Disc3, Plus, X, XCircle } from 'lucide-react';
|
||||
import { CSSProperties, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
import {
|
||||
DATASOURCE_VS_ROUTES,
|
||||
@ -43,6 +48,9 @@ import {
|
||||
saveNewViewHandler,
|
||||
} from './utils';
|
||||
|
||||
const allowedRoles = [USER_ROLES.ADMIN, USER_ROLES.AUTHOR, USER_ROLES.EDITOR];
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
function ExplorerOptions({
|
||||
disabled,
|
||||
isLoading,
|
||||
@ -71,6 +79,8 @@ function ExplorerOptions({
|
||||
setIsSaveModalOpen(false);
|
||||
};
|
||||
|
||||
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
|
||||
const onCreateAlertsHandler = useCallback(() => {
|
||||
history.push(
|
||||
`${ROUTES.ALERTS_NEW}?${QueryParams.compositeQuery}=${encodeURIComponent(
|
||||
@ -247,10 +257,17 @@ function ExplorerOptions({
|
||||
[isDarkMode],
|
||||
);
|
||||
|
||||
const isEditDeleteSupported = allowedRoles.includes(role as string);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isQueryUpdated && (
|
||||
<div className="explorer-update">
|
||||
<div
|
||||
className={cx(
|
||||
isEditDeleteSupported ? '' : 'hide-update',
|
||||
'explorer-update',
|
||||
)}
|
||||
>
|
||||
<Tooltip title="Clear this view" placement="top">
|
||||
<Button
|
||||
className="action-icon"
|
||||
@ -258,10 +275,13 @@ function ExplorerOptions({
|
||||
icon={<X size={14} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider type="vertical" />
|
||||
<Divider
|
||||
type="vertical"
|
||||
className={isEditDeleteSupported ? '' : 'hidden'}
|
||||
/>
|
||||
<Tooltip title="Update this view" placement="top">
|
||||
<Button
|
||||
className="action-icon"
|
||||
className={cx('action-icon', isEditDeleteSupported ? ' ' : 'hidden')}
|
||||
disabled={isViewUpdating}
|
||||
onClick={onUpdateQueryHandler}
|
||||
icon={<Disc3 size={14} />}
|
||||
@ -323,15 +343,16 @@ function ExplorerOptions({
|
||||
<Button
|
||||
shape="round"
|
||||
onClick={handleSaveViewModalToggle}
|
||||
className={isEditDeleteSupported ? '' : 'hidden'}
|
||||
disabled={viewsIsLoading || isRefetching}
|
||||
>
|
||||
<Disc3 size={16} /> Save this view
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<hr className={isEditDeleteSupported ? '' : 'hidden'} />
|
||||
|
||||
<div className="actions">
|
||||
<div className={cx('actions', isEditDeleteSupported ? '' : 'hidden')}>
|
||||
<Tooltip title="Create Alerts">
|
||||
<Button
|
||||
disabled={disabled}
|
||||
|
@ -309,49 +309,52 @@ function DashboardsList(): JSX.Element {
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col
|
||||
span={6}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<ButtonContainer>
|
||||
<TextToolTip
|
||||
{...{
|
||||
text: `More details on how to create dashboards`,
|
||||
url: 'https://signoz.io/docs/userguide/dashboards',
|
||||
}}
|
||||
/>
|
||||
</ButtonContainer>
|
||||
|
||||
<Dropdown
|
||||
menu={{ items: getMenuItems }}
|
||||
disabled={isDashboardListLoading}
|
||||
placement="bottomRight"
|
||||
{createNewDashboard && (
|
||||
<Col
|
||||
span={6}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<NewDashboardButton
|
||||
icon={<PlusOutlined />}
|
||||
type="primary"
|
||||
data-testid="create-new-dashboard"
|
||||
loading={newDashboardState.loading}
|
||||
danger={newDashboardState.error}
|
||||
<ButtonContainer>
|
||||
<TextToolTip
|
||||
{...{
|
||||
text: `More details on how to create dashboards`,
|
||||
url: 'https://signoz.io/docs/userguide/dashboards',
|
||||
}}
|
||||
/>
|
||||
</ButtonContainer>
|
||||
|
||||
<Dropdown
|
||||
menu={{ items: getMenuItems }}
|
||||
disabled={isDashboardListLoading}
|
||||
placement="bottomRight"
|
||||
>
|
||||
{getText()}
|
||||
</NewDashboardButton>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
<NewDashboardButton
|
||||
icon={<PlusOutlined />}
|
||||
type="primary"
|
||||
data-testid="create-new-dashboard"
|
||||
loading={newDashboardState.loading}
|
||||
danger={newDashboardState.error}
|
||||
>
|
||||
{getText()}
|
||||
</NewDashboardButton>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
),
|
||||
[
|
||||
isDashboardListLoading,
|
||||
handleSearch,
|
||||
isFilteringDashboards,
|
||||
searchString,
|
||||
createNewDashboard,
|
||||
getMenuItems,
|
||||
newDashboardState.loading,
|
||||
newDashboardState.error,
|
||||
getText,
|
||||
searchString,
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -1,171 +1,170 @@
|
||||
.save-view-container {
|
||||
margin-top: 70px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-top: 70px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
|
||||
.save-view-content {
|
||||
width: calc(100% - 30px);
|
||||
max-width: 736px;
|
||||
.save-view-content {
|
||||
width: calc(100% - 30px);
|
||||
max-width: 736px;
|
||||
|
||||
|
||||
.title {
|
||||
color: var(--bg-vanilla-100);
|
||||
font-size: var(--font-size-lg);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 28px; /* 155.556% */
|
||||
letter-spacing: -0.09px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: var(---bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.title {
|
||||
color: var(--bg-vanilla-100);
|
||||
font-size: var(--font-size-lg);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 28px; /* 155.556% */
|
||||
letter-spacing: -0.09px;
|
||||
}
|
||||
|
||||
.ant-table-row {
|
||||
.ant-table-cell {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: var(--bg-ink-500);
|
||||
|
||||
}
|
||||
.column-render {
|
||||
margin: 8px 0 !important;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--bg-slate-500);
|
||||
background: var(--bg-ink-400);
|
||||
.subtitle {
|
||||
color: var(---bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.title-with-action {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.ant-input-affix-wrapper {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.save-view-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
.dot {
|
||||
min-height: 6px;
|
||||
min-width: 6px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.ant-typography {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
.ant-table-row {
|
||||
.ant-table-cell {
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: var(--bg-ink-500);
|
||||
}
|
||||
.column-render {
|
||||
margin: 8px 0 !important;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--bg-slate-500);
|
||||
background: var(--bg-ink-400);
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.title-with-action {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
.view-details {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.save-view-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
.dot {
|
||||
min-height: 6px;
|
||||
min-width: 6px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.ant-typography {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
|
||||
.view-tag {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50px;
|
||||
background: var(--bg-slate-300);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
cursor: pointer;
|
||||
|
||||
.tag-text {
|
||||
color: var(--bg-vanilla-400);
|
||||
leading-trim: both;
|
||||
text-edge: cap;
|
||||
font-size: 10px;
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: normal;
|
||||
letter-spacing: -0.05px;
|
||||
}
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.view-details {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.view-created-by {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.view-tag {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50px;
|
||||
background: var(--bg-slate-300);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.view-created-at {
|
||||
margin-left: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ant-typography {
|
||||
margin-left: 6px;
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tag-text {
|
||||
color: var(--bg-vanilla-400);
|
||||
leading-trim: both;
|
||||
text-edge: cap;
|
||||
font-size: 10px;
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: normal;
|
||||
letter-spacing: -0.05px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pagination-item {
|
||||
.view-created-by {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.view-created-at {
|
||||
margin-left: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ant-typography {
|
||||
margin-left: 6px;
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-variant-numeric: lining-nums tabular-nums slashed-zero;
|
||||
font-feature-settings: 'dlig' on, 'salt' on, 'case' on, 'cpsp' on;
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 20px; /* 142.857% */
|
||||
}
|
||||
.ant-pagination-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
> a {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-variant-numeric: lining-nums tabular-nums slashed-zero;
|
||||
font-feature-settings: 'dlig' on, 'salt' on, 'case' on, 'cpsp' on;
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 20px; /* 142.857% */
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pagination-item-active {
|
||||
background-color: var(--bg-robin-500);
|
||||
> a {
|
||||
color: var(--bg-ink-500) !important;
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-pagination-item-active {
|
||||
background-color: var(--bg-robin-500);
|
||||
> a {
|
||||
color: var(--bg-ink-500) !important;
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-view-modal {
|
||||
width: calc(100% - 30px) !important; /* Adjust the 20px as needed */
|
||||
max-width: 384px;
|
||||
width: calc(100% - 30px) !important; /* Adjust the 20px as needed */
|
||||
max-width: 384px;
|
||||
.ant-modal-content {
|
||||
padding: 0;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--bg-slate-500);
|
||||
background: var(--bg-ink-400);
|
||||
box-shadow: 0px -4px 16px 2px rgba(0, 0, 0, 0.20);
|
||||
box-shadow: 0px -4px 16px 2px rgba(0, 0, 0, 0.2);
|
||||
|
||||
.ant-modal-header {
|
||||
padding: 16px;
|
||||
@ -177,11 +176,11 @@
|
||||
|
||||
.ant-typography {
|
||||
color: var(--bg-vanilla-400);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.07px;
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.save-view-input {
|
||||
@ -211,7 +210,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.ant-modal-footer {
|
||||
@ -223,127 +221,126 @@
|
||||
.cancel-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: none;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
background: var(--bg-slate-500);
|
||||
background: var(--bg-slate-500);
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
display: flex;
|
||||
.delete-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
background: var(--bg-cherry-500);
|
||||
margin-left: 12px;
|
||||
}
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
background: var(--bg-cherry-500);
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
color: var(--bg-vanilla-100);
|
||||
background: var(--bg-cherry-600);
|
||||
}
|
||||
.delete-btn:hover {
|
||||
color: var(--bg-vanilla-100);
|
||||
background: var(--bg-cherry-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
color: var(--bg-vanilla-100);
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 20px; /* 142.857% */
|
||||
font-size: var(--font-size-sm);
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: 20px; /* 142.857% */
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.save-view-container {
|
||||
.save-view-content {
|
||||
.save-view-container {
|
||||
.save-view-content {
|
||||
.title {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
.ant-table-row {
|
||||
.ant-table-cell {
|
||||
background: var(--bg-vanilla-200);
|
||||
}
|
||||
|
||||
.ant-table-row {
|
||||
.ant-table-cell {
|
||||
background: var(--bg-vanilla-200);
|
||||
}
|
||||
&:hover {
|
||||
.ant-table-cell {
|
||||
background: var(--bg-vanilla-200) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ant-table-cell {
|
||||
background: var(--bg-vanilla-200) !important;
|
||||
}
|
||||
}
|
||||
.column-render {
|
||||
border: 1px solid var(--bg-vanilla-200);
|
||||
background: var(--bg-vanilla-100);
|
||||
|
||||
.column-render {
|
||||
border: 1px solid var(--bg-vanilla-200);
|
||||
background: var(--bg-vanilla-100);
|
||||
.title-with-action {
|
||||
.save-view-title {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
|
||||
.title-with-action {
|
||||
.save-view-title {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
.action-btn {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
.view-details {
|
||||
.view-tag {
|
||||
background: var(--bg-vanilla-200);
|
||||
.tag-text {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
|
||||
.view-details {
|
||||
.view-tag {
|
||||
background: var(--bg-vanilla-200);
|
||||
.tag-text {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
.view-created-by {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
|
||||
.view-created-by {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
.view-created-at {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view-created-at {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.delete-view-modal {
|
||||
.ant-modal-content {
|
||||
border: 1px solid var(--bg-vanilla-200);
|
||||
background: var(--bg-vanilla-100);
|
||||
|
||||
.delete-view-modal {
|
||||
.ant-modal-content {
|
||||
border: 1px solid var(--bg-vanilla-200);
|
||||
background: var(--bg-vanilla-100);
|
||||
.ant-modal-header {
|
||||
background: var(--bg-vanilla-100);
|
||||
|
||||
.ant-modal-header {
|
||||
background: var(--bg-vanilla-100);
|
||||
.title {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
.ant-modal-body {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
|
||||
.ant-modal-body {
|
||||
.ant-typography {
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
.save-view-input {
|
||||
.ant-input {
|
||||
background: var(--bg-vanilla-200);
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.save-view-input {
|
||||
.ant-input {
|
||||
background: var(--bg-vanilla-200);
|
||||
color: var(--bg-ink-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-modal-footer {
|
||||
.cancel-btn {
|
||||
background: var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-modal-footer {
|
||||
.cancel-btn {
|
||||
background: var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,20 @@ import {
|
||||
} from 'lucide-react';
|
||||
import { ChangeEvent, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { ICompositeMetricQuery } from 'types/api/alerts/compositeQuery';
|
||||
import { ViewProps } from 'types/api/saveViews/types';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
import { ROUTES_VS_SOURCEPAGE, SOURCEPAGE_VS_ROUTES } from './constants';
|
||||
import { deleteViewHandler } from './utils';
|
||||
|
||||
const allowedRoles = [USER_ROLES.ADMIN, USER_ROLES.AUTHOR, USER_ROLES.EDITOR];
|
||||
|
||||
function SaveView(): JSX.Element {
|
||||
const { pathname } = useLocation();
|
||||
const sourcepage = ROUTES_VS_SOURCEPAGE[pathname];
|
||||
@ -61,6 +67,8 @@ function SaveView(): JSX.Element {
|
||||
setIsDeleteModalOpen(false);
|
||||
};
|
||||
|
||||
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
|
||||
const handleDeleteModelOpen = (uuid: string, name: string): void => {
|
||||
setActiveViewKey(uuid);
|
||||
setActiveViewName(name);
|
||||
@ -217,6 +225,9 @@ function SaveView(): JSX.Element {
|
||||
|
||||
// Combine time and date
|
||||
const formattedDateAndTime = `${formattedTime} ⎯ ${formattedDate}`;
|
||||
|
||||
const isEditDeleteSupported = allowedRoles.includes(role as string);
|
||||
|
||||
return (
|
||||
<div className="column-render">
|
||||
<div className="title-with-action">
|
||||
@ -234,11 +245,13 @@ function SaveView(): JSX.Element {
|
||||
<div className="action-btn">
|
||||
<PenLine
|
||||
size={14}
|
||||
className={isEditDeleteSupported ? '' : 'hidden'}
|
||||
onClick={(): void => handleEditModelOpen(view, bgColor)}
|
||||
/>
|
||||
<Compass size={14} onClick={(): void => handleRedirectQuery(view)} />
|
||||
<Trash2
|
||||
size={14}
|
||||
className={isEditDeleteSupported ? '' : 'hidden'}
|
||||
color={Color.BG_CHERRY_500}
|
||||
onClick={(): void => handleDeleteModelOpen(view.uuid, view.name)}
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user