INFRA-2867 | incident dashboard table changes
This commit is contained in:
@@ -54,13 +54,6 @@
|
||||
width: 458px !important;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.tooltipWrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -69,3 +62,17 @@
|
||||
line-height: 1;
|
||||
margin-top: -7px;
|
||||
}
|
||||
.moreToShow {
|
||||
color: var(--navi-color-blue-base);
|
||||
}
|
||||
.productTooltipItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
background-color: white;
|
||||
border-radius: 50%; /* Makes the div round */
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,10 @@ import { FETCH_INCIDENTS_DATA } from './constants';
|
||||
import SearchResultsTable from './partials/SearchResultsTable';
|
||||
import DashboardHeader from './partials/DashboardHeader';
|
||||
import styles from './Dashboard.module.scss';
|
||||
import { RootState } from '@src/store';
|
||||
|
||||
const Dashboard: FC = () => {
|
||||
const data = useSelector((state: any) => state.dashboard.data);
|
||||
const data = useSelector((state: RootState) => state.dashboard.data);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const [pageDetails, setPageDetails] = useState({
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
import { FC } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { AgTable, Pagination } from '@navi/web-ui/lib/components';
|
||||
import { Tag, Tooltip } from '@navi/web-ui/lib/primitives';
|
||||
import { Tag } from '@navi/web-ui/lib/primitives';
|
||||
import { returnFormattedDate } from '@src/services/globalUtils';
|
||||
import useClickStream from '@src/services/clickStream';
|
||||
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
|
||||
import styles from '../SearchResultsTable.module.scss';
|
||||
import { getSeverityColor } from '../constants';
|
||||
import cx from 'classnames';
|
||||
import { IncidentDashboard } from '@src/slices/dashboardSlice';
|
||||
import { Team } from '../type';
|
||||
import { Tooltip } from 'antd';
|
||||
interface SearchResultTableProps {
|
||||
currentPageData: any;
|
||||
currentPageData: IncidentDashboard[];
|
||||
pageDetails: any;
|
||||
currentPageSize: number;
|
||||
handlePageNumberChange: (pageNumber: number) => void;
|
||||
handlePageSizeChange: (pageSize: number) => void;
|
||||
fetchIncidentData: (props: any) => void;
|
||||
}
|
||||
const MAX_LENGTH = 12;
|
||||
|
||||
const defaultColDef = {
|
||||
cellStyle: { lineHeight: 2 },
|
||||
@@ -56,7 +60,9 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
|
||||
title: item?.title,
|
||||
statusName: item?.statusName,
|
||||
severityName: item?.severityName,
|
||||
teamName: item?.teamName,
|
||||
responder: item?.teamName,
|
||||
assignerTeam: item?.assignerTeam?.label,
|
||||
products: item?.products,
|
||||
createdAt: returnFormattedDate(item?.createdAt),
|
||||
createdBy: item?.createdBy,
|
||||
updatedBy: item?.updatedBy,
|
||||
@@ -65,6 +71,50 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
|
||||
};
|
||||
});
|
||||
|
||||
const wrappedTextHandler = (param: string) => {
|
||||
if (param?.length > MAX_LENGTH) {
|
||||
const wrappedText = param?.substring(0, MAX_LENGTH - 3) + '...';
|
||||
return (
|
||||
<div className={styles.tooltipWrapper}>
|
||||
<Tooltip title={param}>
|
||||
<div className={styles.tooltip}>{wrappedText}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return param;
|
||||
};
|
||||
|
||||
const productRendered = (products: Team[]): JSX.Element | string => {
|
||||
if (!products || products.length === 0) return '';
|
||||
const productNames = products
|
||||
.map((product: Team) => product.label)
|
||||
.sort((a, b) => a.length - b.length)
|
||||
.join(', ');
|
||||
if (productNames.length <= MAX_LENGTH) return productNames;
|
||||
|
||||
const truncatedProducts = productNames.substring(0, MAX_LENGTH - 3) + '...';
|
||||
const moreToShow = products.length - truncatedProducts.split(',').length;
|
||||
const tooltipContent = products.map((product: Team, index) => (
|
||||
<div className={styles['productTooltipItem']} key={index}>
|
||||
<div className={styles['dot']}></div>
|
||||
{product.label}
|
||||
</div>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className={styles.tooltipWrapper}>
|
||||
<Tooltip title={tooltipContent}>
|
||||
{truncatedProducts}
|
||||
{moreToShow > 0 && (
|
||||
<span className={styles.moreToShow}>{` +${moreToShow} More`}</span>
|
||||
)}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const columnData = [
|
||||
{
|
||||
field: 'incidentName',
|
||||
@@ -76,19 +126,8 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
|
||||
headerName: 'Title',
|
||||
suppressMovable: true,
|
||||
cellStyle: cellStyle,
|
||||
cellRenderer: params => {
|
||||
if (params.value?.length > 15) {
|
||||
return (
|
||||
<div className={styles.tooltipWrapper}>
|
||||
<Tooltip text={params?.value} withPointer position="right">
|
||||
<div className={styles.tooltip}>{params?.value}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return params?.value;
|
||||
},
|
||||
cellRenderer: params => wrappedTextHandler(params?.value),
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
field: 'statusName',
|
||||
@@ -102,7 +141,7 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
|
||||
cellStyle: {
|
||||
zIndex: -1,
|
||||
},
|
||||
width: 120,
|
||||
width: 100,
|
||||
cellRenderer: params => (
|
||||
<Tag
|
||||
color={getSeverityColor(params?.value)}
|
||||
@@ -112,31 +151,39 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'teamName',
|
||||
headerName: 'Team name',
|
||||
suppressMovable: true,
|
||||
},
|
||||
{
|
||||
field: 'createdBy',
|
||||
headerName: 'Created by',
|
||||
field: 'products',
|
||||
headerName: 'Product',
|
||||
suppressMovable: true,
|
||||
cellStyle: cellStyle,
|
||||
cellRenderer: params => productRendered(params?.value),
|
||||
},
|
||||
{
|
||||
field: 'assignerTeam',
|
||||
headerName: 'Assigner',
|
||||
suppressMovable: true,
|
||||
width: 130,
|
||||
cellRenderer: params => wrappedTextHandler(params?.value),
|
||||
},
|
||||
{
|
||||
field: 'responder',
|
||||
headerName: 'Responder',
|
||||
suppressMovable: true,
|
||||
width: 130,
|
||||
cellStyle: cellStyle,
|
||||
cellRenderer: params => wrappedTextHandler(params?.value),
|
||||
},
|
||||
{
|
||||
field: 'createdAt',
|
||||
headerName: 'Created on',
|
||||
suppressMovable: true,
|
||||
|
||||
width: 175,
|
||||
},
|
||||
{
|
||||
field: 'updatedAt',
|
||||
headerName: 'Updated on',
|
||||
suppressMovable: true,
|
||||
},
|
||||
{
|
||||
field: 'updatedBy',
|
||||
headerName: 'Updated by',
|
||||
suppressMovable: true,
|
||||
cellStyle: cellStyle,
|
||||
width: 175,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -6,7 +6,13 @@
|
||||
|
||||
.description-content-body {
|
||||
margin-top: 12px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.description-content-assigner {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.description-content-link {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@@ -7,15 +7,27 @@ import GoToLinkIcon from '@src/assets/GoToLinkIcon';
|
||||
import { IncidentPageState } from '@src/types';
|
||||
import JiraLinks from '../JiraLinks';
|
||||
import styles from './DescriptionContent.module.scss';
|
||||
import { generateMap, getCurrentData } from '../utils';
|
||||
|
||||
const DescriptionContent: React.FC = () => {
|
||||
const { description, slackChannel, incidentName, rcaLink } = useSelector(
|
||||
const {
|
||||
description,
|
||||
slackChannel,
|
||||
incidentName,
|
||||
rcaLink,
|
||||
assignerTeam,
|
||||
products,
|
||||
} = useSelector(
|
||||
(state: IncidentPageState) => state.incidentLog.incidentData || {},
|
||||
);
|
||||
const incidentParticipants = useSelector(
|
||||
(state: IncidentPageState) => state.incidentLog.participantsData,
|
||||
);
|
||||
|
||||
const headerData = useSelector(
|
||||
(state: IncidentPageState) => state.incidentLog.headerData,
|
||||
);
|
||||
const teamsMap = generateMap(headerData?.teams || []);
|
||||
const currentTeam = getCurrentData(assignerTeam, teamsMap, 'value');
|
||||
const renderParticipantList = (type: string): JSX.Element | JSX.Element[] => {
|
||||
const list =
|
||||
type === 'participants'
|
||||
@@ -46,6 +58,14 @@ const DescriptionContent: React.FC = () => {
|
||||
{description || '-'}
|
||||
</Typography>
|
||||
</div>
|
||||
<Typography variant="h6" color="var(--navi-color-gray-c3)">
|
||||
ASSIGNER
|
||||
</Typography>
|
||||
<div className={styles['description-content-assigner']}>
|
||||
<Typography variant="p3" color="var(--navi-color-gray-c2)">
|
||||
{currentTeam}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['horizontal-line']} />
|
||||
<div className={styles['description-content-link']}>
|
||||
|
||||
@@ -383,9 +383,9 @@ const AllDailogBox: FC = () => {
|
||||
>
|
||||
<div>
|
||||
<Typography variant="p3" color="var(--navi-color-gray-c2)">
|
||||
You are updating this incident‘s
|
||||
{"You are updating this incident's "}
|
||||
{UpdateData?.type || '..'}
|
||||
from
|
||||
{' from'}
|
||||
<Typography
|
||||
variant="h4"
|
||||
color="var(--navi-color-gray-c2)"
|
||||
@@ -393,7 +393,7 @@ const AllDailogBox: FC = () => {
|
||||
>
|
||||
{UpdateData?.from || '..'}
|
||||
</Typography>
|
||||
to
|
||||
{' to '}
|
||||
<Typography
|
||||
variant="h4"
|
||||
color="var(--navi-color-gray-c2)"
|
||||
|
||||
@@ -342,7 +342,7 @@ const Dropdowns: FC = () => {
|
||||
<div className={styles['dropdown-team']}>
|
||||
<div>
|
||||
<Typography variant="p5" color="var(--navi-color-gray-c2)">
|
||||
Team
|
||||
Responder
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refTeam}>
|
||||
|
||||
@@ -32,7 +32,7 @@ const stageColorMap = {
|
||||
const changeTypeToTitleMap = {
|
||||
SeverityId: 'Severity changed to',
|
||||
Status: 'Status changed to',
|
||||
TeamId: 'Team changed to',
|
||||
TeamId: 'Responder changed to',
|
||||
Default: 'Different Title',
|
||||
};
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ export const getCurrentData = (
|
||||
dataMap: { [key: string]: string },
|
||||
key: string,
|
||||
): string => {
|
||||
return dataMap && data[key] ? dataMap[data[key]] : '-';
|
||||
return dataMap && data?.[key] ? dataMap?.[data?.[key]] : '-';
|
||||
};
|
||||
|
||||
export const generateMap = (data: DataItem[]): { [key: number]: string } => {
|
||||
|
||||
@@ -152,14 +152,6 @@ const useTeamApis = (): useTeamApiProps => {
|
||||
.then(response => {
|
||||
toast.success(response?.data?.data);
|
||||
dispatch(fetchTeamDetails(teamId?.toString() || ''));
|
||||
// dispatchData({
|
||||
// type: actionTypes.SET_OPEN_ONCALL,
|
||||
// payload: false,
|
||||
// });
|
||||
// dispatchData({
|
||||
// type: actionTypes.SET_PSEC_OPEN_ONCALL,
|
||||
// payload: false,
|
||||
// });
|
||||
})
|
||||
.catch(error => {
|
||||
const toastMessage = `${
|
||||
|
||||
@@ -1,9 +1,46 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { Team } from '@src/Pages/Dashboard/type';
|
||||
|
||||
export interface IncidentDashboard {
|
||||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
status: number;
|
||||
statusName: string;
|
||||
severityId: number;
|
||||
severityName: string;
|
||||
incidentName: string;
|
||||
slackChannel: string;
|
||||
detectionTime: null;
|
||||
startTime: Date;
|
||||
endTime: Date | null;
|
||||
teamId: number;
|
||||
teamName: string;
|
||||
jiraLinks: null;
|
||||
confluenceId: null;
|
||||
severityTat: Date;
|
||||
remindMeAt: null;
|
||||
enableReminder: boolean;
|
||||
createdBy: string;
|
||||
updatedBy: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
rcaLink: string;
|
||||
assignerTeam: Team | null;
|
||||
products: Team[] | null;
|
||||
}
|
||||
|
||||
export interface Pages {
|
||||
totalElements: number;
|
||||
totalPages: number;
|
||||
pageSize: number;
|
||||
pageNumber: number;
|
||||
}
|
||||
|
||||
const dashboardSlice = createSlice({
|
||||
name: 'dashboard',
|
||||
initialState: {
|
||||
data: Array<any>(),
|
||||
data: Array<IncidentDashboard>(),
|
||||
},
|
||||
reducers: {
|
||||
setDashboardData: (state, action) => {
|
||||
|
||||
2
src/types/index.d.ts
vendored
2
src/types/index.d.ts
vendored
@@ -81,6 +81,8 @@ export interface IncidentDatatype {
|
||||
createdAt: Date | null;
|
||||
updatedAt: Date | null;
|
||||
rcaLink: string;
|
||||
assignerTeam: Team;
|
||||
products: Team[];
|
||||
}
|
||||
|
||||
interface Severity {
|
||||
|
||||
Reference in New Issue
Block a user