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:
Vikrant Gupta 2024-03-11 14:49:10 +05:30 committed by GitHub
parent 49aba4fb1c
commit 6b87118fc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 331 additions and 283 deletions

View File

@ -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 {

View File

@ -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}

View File

@ -309,6 +309,7 @@ function DashboardsList(): JSX.Element {
/>
</Col>
{createNewDashboard && (
<Col
span={6}
style={{
@ -341,17 +342,19 @@ function DashboardsList(): JSX.Element {
</NewDashboardButton>
</Dropdown>
</Col>
)}
</Row>
),
[
isDashboardListLoading,
handleSearch,
isFilteringDashboards,
searchString,
createNewDashboard,
getMenuItems,
newDashboardState.loading,
newDashboardState.error,
getText,
searchString,
],
);

View File

@ -8,7 +8,6 @@
width: calc(100% - 30px);
max-width: 736px;
.title {
color: var(--bg-vanilla-100);
font-size: var(--font-size-lg);
@ -37,7 +36,6 @@
padding: 0;
border: none;
background: var(--bg-ink-500);
}
.column-render {
margin: 8px 0 !important;
@ -75,8 +73,11 @@
align-items: center;
gap: 20px;
cursor: pointer;
}
.hidden {
display: none;
}
}
}
.view-details {
margin-top: 8px;
@ -127,7 +128,6 @@
}
.ant-pagination-item {
display: flex;
justify-content: center;
align-items: center;
@ -141,7 +141,6 @@
font-weight: var(--font-weight-normal);
line-height: 20px; /* 142.857% */
}
}
.ant-pagination-item-active {
@ -165,7 +164,7 @@
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;
@ -211,7 +210,6 @@
}
}
}
}
.ant-modal-footer {
@ -255,7 +253,6 @@
.lightMode {
.save-view-container {
.save-view-content {
.title {
color: var(--bg-ink-500);
}

View File

@ -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)}
/>