TP-52973 | minor refinement

This commit is contained in:
AyushRanjan
2024-01-23 23:11:59 +05:30
parent aee164ad42
commit 89041c0b27
12 changed files with 227 additions and 452 deletions

View File

@@ -1,15 +1,24 @@
import { FC } from 'react';
import { useSelector } from 'react-redux';
import Typography from '@navi/web-ui/lib/primitives/Typography';
import IncidentCreated from '../StepperAssets/IncidentCreated';
import IncidentChange from '../StepperAssets/IncidentChange';
import styles from './ActivityLog.module.scss';
import { useDispatch, useSelector } from 'react-redux';
const ActivityLog: FC = () => {
//To do: add type here
const incidentLog = useSelector(
(state: any) => state.incidentLog.incidentLogData,
);
const totalLog = incidentLog?.data?.logs?.length;
const lastChangeIndex = (incidentLog?.data?.logs || [])
.slice()
.reverse()
.findIndex(log =>
log.changes.some(change =>
['Status', 'SeverityId', 'TeamId'].includes(change.attribute),
),
);
const totalLog = incidentLog?.data?.logs?.length - lastChangeIndex;
return (
<div>

View File

@@ -1,70 +1,25 @@
import React, { FC, useState, useReducer, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
setIncidentData,
setIncidentLogData,
setHeaderData,
setParticipantsData,
} from '@src/slices/IncidentSlice';
import {
Typography,
Avatar,
BorderLessInput,
} from '@navi/web-ui/lib/primitives';
import {
CloseIcon,
DeleteIconOutlined,
ArrowUpSolidIcon,
ArrowDownSolidIcon,
} from '@navi/web-ui/lib/icons';
import { toast } from '@navi/web-ui/lib/primitives/Toast';
import React from 'react';
import { useSelector } from 'react-redux';
import { Typography, Avatar } from '@navi/web-ui/lib/primitives';
import SlackIcon from '@src/assets/SlackIcon';
import LoadingIcon from '@src/assets/LoadingIcon';
import ConfluenceIcon from '@src/assets/ConfluenceIcon';
import GoToLinkIcon from '@src/assets/GoToLinkIcon';
import { ApiService } from '@src/services/api';
import {
ActionType,
initialState,
reducer,
JIRA_VALIDATION,
} from './DescriptionContentProps';
import styles from './DescriptionContent.module.scss';
import {
LINK_JIRA_INCIDENT,
UNLINK_JIRA_INCIDENT,
FETCH_INCIDENT_DATA,
} from '../constants';
import { truncateText, linkSanitization } from '../utils';
import JiraLinks from '../JiraLinks';
import styles from './DescriptionContent.module.scss';
const DescriptionContent: React.FC = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const { id, description, jiraIds, slackChannel, incidentName, rcaLink } =
useSelector((state: any) => state.incidentLog.incidentData);
const { description, slackChannel, incidentName, rcaLink } = useSelector(
(state: any) => state.incidentLog.incidentData,
);
const incidentParticipants = useSelector(
(state: any) => state.incidentLog.participantsData,
);
// console.log('incident participants desc', incidentParticipants);
const reduxDispatch = useDispatch();
//move to hooks
const storedEmail = localStorage.getItem('email-id');
//import scss
const goToLinkBlueColor = '#0276FE';
//use from hooks below three functions
//move to utils
// console.log('incident participants', incidentParticipants);
const renderParticipantList = (type: string): JSX.Element => {
const list =
type === 'participants'
? incidentParticipants?.participants
: incidentParticipants?.others;
return list?.length ? (
list.map(participant => (
<div key={participant?.id} className={styles['team-details-wrapper']}>
@@ -127,7 +82,7 @@ const DescriptionContent: React.FC = () => {
rel="noreferrer"
className={styles['rca-text']}
>
<GoToLinkIcon color={goToLinkBlueColor} />
<GoToLinkIcon color="var(--navi-color-blue-base)" />
<Typography variant="h4" color="var(--navi-color-blue-base)">
Go to document
</Typography>

View File

@@ -1,8 +1,6 @@
import { FC, useEffect, useReducer } from 'react';
import { useMatch } from 'react-router-dom';
import { FC, useReducer } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Tabs } from 'antd';
import { ArrowDownIcon, AlertOutlineIcon } from '@navi/web-ui/lib/icons';
import { AlertOutlineIcon } from '@navi/web-ui/lib/icons';
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
import {
BorderedInput,
@@ -11,9 +9,7 @@ import {
Button,
} from '@navi/web-ui/lib/primitives';
import { toast } from '@navi/web-ui/lib/primitives/Toast';
import GoToLinkIcon from '@src/assets/GoToLinkIcon';
import styles from '../Incidents.module.scss';
import LoadingIcon from '@src/assets/LoadingIcon';
import {
setOpenDialognotParticipants,
@@ -22,7 +18,6 @@ import {
setOpenDialogUpdate,
} from '@src/slices/IncidentSlice';
import { ApiService } from '@src/services/api';
import {
actionTypes,
SLACK_BASE_URL,
@@ -32,17 +27,13 @@ import {
ResponseType,
DUPLICATE_STATUS,
UPDATE_INCIDENT,
SeverityType,
StatusType,
TeamType,
RESOLVE_STATUS,
} from '../constants';
import useIncidentApis from '../useIncidentApis';
import styles from '../Incidents.module.scss';
const AllDailogBox: FC = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const openNotParticipants = useSelector(
(state: any) => state.incidentLog.openDialognotParticipants,
);
@@ -61,32 +52,13 @@ const AllDailogBox: FC = () => {
const selectedOption = useSelector(
(state: any) => state.incidentLog.selectedOptions,
);
//console.log('updatedata', UpdateData);
const incidentData = useSelector(
(state: any) => state.incidentLog.incidentData,
);
const headerData = useSelector((state: any) => state.incidentLog.headerData);
const severityMap = headerData?.severities?.reduce((map, severity) => {
map[severity.value] = severity.label;
return map;
}, {});
const statusMap = headerData?.incidentStatuses?.reduce((map, status) => {
map[status.value] = status.label;
return map;
}, {});
const teamsMap = headerData?.teams?.reduce((map, Incidentteam) => {
map[Incidentteam.value] = Incidentteam.label;
return map;
}, {});
const { updateIncident, fetchIncidentLog, startIncidentSearch } =
useIncidentApis();
0;
const { updateIncident, startIncidentSearch } = useIncidentApis();
const incidentId = incidentData?.id?.toString();
console.log('incidentId', incidentId);
const reduxDispatch = useDispatch();
const incidentName = incidentData?.incidentName;
@@ -94,7 +66,7 @@ const AllDailogBox: FC = () => {
reduxDispatch(setOpenDialognotParticipants(false));
};
const handleGoToSlackChannel = () => {
const handleGoToSlackChannel = (): void => {
const slackChannelURL = `${SLACK_BASE_URL}/archives/${incidentData?.slackChannel}`;
window.open(slackChannelURL, '_blank');
handleopenNotParticipants();
@@ -231,7 +203,6 @@ const AllDailogBox: FC = () => {
const handleTeamSelectionChange = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
): void => {
console.log('selectedOption', selectedOption);
if (selectedOption) {
dispatch({ type: actionTypes.SET_IS_TEAM_PICKER_OPEN, payload: false });
toast('Updating ticket. Please wait a moment.', {
@@ -248,10 +219,10 @@ const AllDailogBox: FC = () => {
};
const handleCloseConfirmationDialog = () => {
if (UpdateData?.type === SeverityType) {
if (UpdateData?.type == 'severity') {
handleSeveritySelectionChange(selectedOption);
} else {
if (UpdateData?.type === StatusType) {
if (UpdateData?.type == 'status') {
handleStatusSelectionChange(selectedOption);
} else {
handleTeamSelectionChange(selectedOption);
@@ -263,7 +234,6 @@ const AllDailogBox: FC = () => {
<div>
{openNotParticipants && (
<ModalDialog
// add open to use reducer
open={openNotParticipants}
footerButtons={[
{
@@ -321,7 +291,6 @@ const AllDailogBox: FC = () => {
Icon={<AlertOutlineIcon color="var(--navi-color-red-base)" />}
/>
</div>
<Button
className={styles['hint-text']}
variant="text"
@@ -386,9 +355,9 @@ const AllDailogBox: FC = () => {
>
<div>
<Typography variant="p3" color="var(--navi-color-gray-c2)">
You are updating this incident&lsquo;s
You are updating this incident&lsquo;s &nbsp;
{UpdateData?.type || '..'}
from
&nbsp; from
<Typography
variant="h4"
color="var(--navi-color-gray-c2)"

View File

@@ -1,26 +1,12 @@
import { FC, useEffect, useReducer, useState, MutableRefObject } from 'react';
import { useMatch } from 'react-router-dom';
import { FC, useReducer, MutableRefObject } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import classnames from 'classnames';
import {
BorderedInput,
ModalDialog,
Typography,
Button,
} from '@navi/web-ui/lib/primitives';
import { toast } from '@navi/web-ui/lib/primitives/Toast';
import { ArrowDownIcon, AlertOutlineIcon } from '@navi/web-ui/lib/icons';
import { Typography } from '@navi/web-ui/lib/primitives';
import { ArrowDownIcon } from '@navi/web-ui/lib/icons';
import { SelectPicker } from '@navi/web-ui/lib/components';
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
import LoadingIcon from '@src/assets/LoadingIcon';
import useOutsideClick from '@src/services/hooks/useOustideClick';
import { getUpdateTypeText } from '../utils';
import { ApiService } from '@src/services/api';
import {
setIncidentData,
setIncidentLogData,
setHeaderData,
setParticipantsData,
setOpenDialogDuplicate,
setOpenDialogResolve,
setOpenDialogUpdate,
@@ -29,8 +15,7 @@ import {
setSelectedOptions,
} from '@src/slices/IncidentSlice';
import AllDailogBox from './AllDailogBox';
import useIncidentApis from '../useIncidentApis';
import { generateOptions, getCurrentData, isUserParticipant } from '../utils';
import { generateOptions, getCurrentData, getUpdateTypeText } from '../utils';
import {
reducer,
actionTypes,
@@ -40,17 +25,12 @@ import {
SeverityType,
StatusType,
TeamType,
SLACK_BASE_URL,
incidentRegrex,
ResponseType,
UPDATE_INCIDENT,
} from '../constants';
import styles from '../Incidents.module.scss';
const Dropdowns: FC = () => {
const { updateIncident, fetchIncidentLog, startIncidentSearch } =
useIncidentApis();
const reduxDispatch = useDispatch();
//To do: add types here
const incidentData = useSelector(
(state: any) => state.incidentLog.incidentData,
);
@@ -58,50 +38,36 @@ const Dropdowns: FC = () => {
(state: any) => state.incidentLog?.participantsData,
);
const headerData = useSelector((state: any) => state.incidentLog.headerData);
const incidentId = incidentData?.incidentId?.toString();
const [state, dispatch] = useReducer(reducer, initialState);
const incidentName = state.incidentName;
const updatedSeverities = generateOptions(headerData?.severities);
const updatedStatuses = generateOptions(headerData?.incidentStatuses);
const updatedTeams = generateOptions(headerData?.teams);
useEffect(() => {
dispatch({
type: actionTypes.SET_SLACK_CHANNEL,
payload: incidentData?.slackChannel,
});
dispatch({
type: actionTypes.SET_SEVERITY,
payload: {
label: incidentData?.severityName,
value: incidentData?.severityId,
},
});
dispatch({
type: actionTypes.SET_STATUS,
payload: {
label: incidentData?.statusName,
value: incidentData?.status,
},
});
dispatch({
type: actionTypes.SET_TEAM,
payload: {
label: incidentData?.teamName,
value: incidentData?.teamId,
},
});
}, [incidentData]);
const initialSeverity = {
label: incidentData?.severityName,
value: incidentData?.severityId,
};
const userData = JSON.parse(localStorage.getItem('user-data') || '{}');
const userEmail = userData?.emailId || [];
const initialStatus = {
label: incidentData?.statusName,
value: incidentData?.status,
};
const isUserParticipantList = isUserParticipant(
userEmail,
incidentParticipants,
const initialTeam = {
label: incidentData?.teamName,
value: incidentData?.teamId,
};
const { emailId: userEmail } =
JSON.parse(localStorage.getItem('user-data') || '{}') || {};
const participantsList = [
...(incidentParticipants?.participants || []),
...(incidentParticipants?.others || []),
];
//To do: add types here
const isUserParticipantList = participantsList?.some(
(participant: any) => participant.email === userEmail,
);
const severityMap = headerData?.severities?.reduce((map, severity) => {
@@ -117,6 +83,10 @@ const Dropdowns: FC = () => {
return map;
}, {});
const currentSev = getCurrentData(incidentData, severityMap, 'severityId');
const currentStatus = getCurrentData(incidentData, statusMap, 'status');
const currentTeam = getCurrentData(incidentData, teamsMap, 'teamId');
const combinedSevClassNames = classnames(
styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'],
{
@@ -142,6 +112,121 @@ const Dropdowns: FC = () => {
},
);
const handleDropdownClick = (changeType: string) => {
if (isUserParticipantList) {
switch (changeType) {
case 'severity':
return () => handleSeverityDropdownClick();
case 'status':
return () => handleStatusDropdownClick();
case 'team':
return () => handleTeamDropdownClick();
}
} else {
return handleDisabledDropdownClick;
}
};
const handleSeverityDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
payload: !state.isSeverityPickerOpen,
});
};
const handleStatusDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_IS_STATUS_PICKER_OPEN,
payload: !state.isStatusPickerOpen,
});
};
const handleTeamDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_IS_TEAM_PICKER_OPEN,
payload: !state.isTeamPickerOpen,
});
};
const handleDisabledDropdownClick = (): void => {
reduxDispatch(setOpenDialognotParticipants(true));
};
const handleOpenConfirmationDailog = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
updateType: number,
): void => {
const currentValue =
updateType === SeverityType
? initialSeverity?.value
: updateType === StatusType
? initialStatus?.value
: initialTeam?.value;
const currentState = currentValue.toString();
const selectedvalue = Array.isArray(selectedOption)
? selectedOption[0].value
: selectedOption.value;
if (currentState !== selectedvalue) {
dispatch({ type: actionTypes.SET_IS_STATUS_PICKER_OPEN, payload: false });
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
payload: false,
});
dispatch({ type: actionTypes.SET_IS_TEAM_PICKER_OPEN, payload: false });
if (updateType === StatusType && selectedvalue === RESOLVE_STATUS) {
dispatch({
type: actionTypes.SET_IS_STATUS_PICKER_OPEN,
payload: false,
});
reduxDispatch(setOpenDialogResolve(true));
} else if (
updateType === StatusType &&
selectedvalue === DUPLICATE_STATUS
) {
dispatch({
type: actionTypes.SET_DUPLICATE_DIALOG,
payload: true,
});
reduxDispatch(setOpenDialogDuplicate(true));
} else {
reduxDispatch(
setUpdateDetails({
type: getUpdateTypeText(updateType),
to: selectedOption,
from: getUpdateValueText(updateType),
}),
);
reduxDispatch(setSelectedOptions(selectedOption));
reduxDispatch(setOpenDialogUpdate(true));
}
}
};
const getUpdateValueText = updateType => {
switch (updateType) {
case SeverityType:
return ` ${
severityMap && initialSeverity?.value
? severityMap[initialSeverity.value]
: '-'
} `;
case StatusType:
return ` ${
statusMap && initialStatus?.value
? statusMap[initialStatus.value]
: '-'
} `;
case TeamType:
return ` ${
teamsMap && initialTeam?.value ? teamsMap[initialTeam.value] : '-'
} `;
default:
return ` ${
severityMap && initialSeverity?.value
? severityMap[initialSeverity.value]
: '-'
} `;
}
};
const handleSevClickOutside = () => {
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
@@ -175,209 +260,6 @@ const Dropdowns: FC = () => {
callback: handleTeamClickOutside,
}) as MutableRefObject<HTMLDivElement>;
const handleSeverityDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
payload: !state.isSeverityPickerOpen,
});
};
const handleStatusDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_IS_STATUS_PICKER_OPEN,
payload: !state.isStatusPickerOpen,
});
};
const handleTeamDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_IS_TEAM_PICKER_OPEN,
payload: !state.isTeamPickerOpen,
});
};
const handleSevClick = () => {
if (isUserParticipantList) {
handleSeverityDropdownClick();
} else {
handleDisabledDropdownClick();
}
};
const handleStatusClick = () => {
if (isUserParticipantList) {
handleStatusDropdownClick();
} else {
handleDisabledDropdownClick();
}
};
const handleTeamClick = () => {
if (isUserParticipantList) {
handleTeamDropdownClick();
} else {
handleDisabledDropdownClick();
}
};
const handleDisabledDropdownClick = (): void => {
reduxDispatch(setOpenDialognotParticipants(true));
};
const getUpdateValueText = updateType => {
switch (updateType) {
case SeverityType:
return ` ${
severityMap && state.severity?.value
? severityMap[state.severity.value]
: '-'
} `;
case StatusType:
return ` ${
statusMap && state.status?.value ? statusMap[state.status.value] : '-'
} `;
case TeamType:
return ` ${
teamsMap && state.team?.value ? teamsMap[state.team.value] : '-'
} `;
default:
return ` ${
severityMap && state.severity?.value
? severityMap[state.severity.value]
: '-'
} `;
}
};
const handleOpenConfirmationDailog = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
updateType: number,
): void => {
const currentValue =
updateType === SeverityType
? state.severity?.value
: updateType === StatusType
? state.status?.value
: state.team?.value;
const currentState = currentValue.toString();
const selectedvalue = Array.isArray(selectedOption)
? selectedOption[0].value
: selectedOption.value;
if (currentState !== selectedvalue) {
dispatch({ type: actionTypes.SET_IS_STATUS_PICKER_OPEN, payload: false });
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
payload: false,
});
dispatch({ type: actionTypes.SET_IS_TEAM_PICKER_OPEN, payload: false });
if (updateType === StatusType && selectedvalue === RESOLVE_STATUS) {
handleStatusSelectionChange(selectedOption);
} else if (
updateType === StatusType &&
selectedvalue === DUPLICATE_STATUS
) {
dispatch({
type: actionTypes.SET_DUPLICATE_DIALOG,
payload: true,
});
reduxDispatch(setOpenDialogDuplicate(true));
} else {
console.log('type', updateType);
console.log('to', selectedOption);
console.log('from', getUpdateValueText);
reduxDispatch(
setUpdateDetails({
type: getUpdateTypeText(updateType),
to: selectedOption,
from: getUpdateValueText(updateType),
}),
);
reduxDispatch(setSelectedOptions(selectedOption));
reduxDispatch(setOpenDialogUpdate(true));
}
}
};
const handleCloseConfirmationDialog = () => {
if (state.updateType === SeverityType) {
handleSeveritySelectionChange(state.selectedOption);
} else {
if (state.updateType === StatusType) {
handleStatusSelectionChange(state.selectedOption);
} else {
handleTeamSelectionChange(state.selectedOption);
}
}
};
const handleSeveritySelectionChange = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
): void => {
if (selectedOption) {
toast('Updating ticket. Please wait a moment.', {
icon: <LoadingIcon />,
});
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
payload: false,
});
const value = Array.isArray(selectedOption)
? selectedOption[0].value
: selectedOption.value;
updateIncident({
id: parseInt(incidentId, 10),
severityId: value.toString(),
});
}
};
const handleStatusSelectionChange = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
): void => {
if (selectedOption) {
dispatch({ type: actionTypes.SET_IS_STATUS_PICKER_OPEN, payload: false });
const value = Array.isArray(selectedOption)
? selectedOption[0].value
: selectedOption.value;
if (value === RESOLVE_STATUS) {
dispatch({
type: actionTypes.SET_DIALOG_TEXT,
payload: 'Resolve incident',
});
dispatch({
type: actionTypes.SET_DIALOG_BODY_TEXT,
payload: 'resolved',
});
reduxDispatch(setOpenDialogResolve(true));
} else {
toast('Updating ticket. Please wait a moment.', {
icon: <LoadingIcon />,
});
updateIncident({
id: parseInt(incidentId, 10),
status: value.toString(),
});
}
}
};
const handleTeamSelectionChange = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
): void => {
if (selectedOption) {
dispatch({ type: actionTypes.SET_IS_TEAM_PICKER_OPEN, payload: false });
toast('Updating ticket. Please wait a moment.', {
icon: <LoadingIcon />,
});
const value = Array.isArray(selectedOption)
? selectedOption[0].value
: selectedOption.value;
updateIncident({
id: parseInt(incidentId, 10),
teamId: value.toString(),
});
}
};
const currentSev = getCurrentData(incidentData, severityMap, 'severityId');
const currentStatus = getCurrentData(incidentData, statusMap, 'status');
const currentTeam = getCurrentData(incidentData, teamsMap, 'teamId');
return (
<div>
<div className={styles['log-update-dropdown']}>
@@ -387,8 +269,11 @@ const Dropdowns: FC = () => {
Severity
</Typography>
</div>
<div>
<div className={combinedSevClassNames} onClick={handleSevClick}>
<div ref={refSeverity}>
<div
className={combinedSevClassNames}
onClick={handleDropdownClick('severity')}
>
<div>
<Typography
variant="p4"
@@ -414,7 +299,7 @@ const Dropdowns: FC = () => {
handleOpenConfirmationDailog(selectedOption, SeverityType)
}
options={updatedSeverities}
selectedValue={state.severity?.value.toString()}
selectedValue={incidentData?.severityId?.toString()}
/>
</div>
)}
@@ -431,7 +316,7 @@ const Dropdowns: FC = () => {
<div ref={refStatus}>
<div
className={combinedStatusClassNames}
onClick={handleStatusClick}
onClick={handleDropdownClick('status')}
>
<div>
<Typography
@@ -458,7 +343,7 @@ const Dropdowns: FC = () => {
handleOpenConfirmationDailog(selectedOption, StatusType)
}
options={updatedStatuses}
selectedValue={state.status?.value.toString()}
selectedValue={incidentData?.status?.toString()}
/>
</div>
)}
@@ -473,7 +358,10 @@ const Dropdowns: FC = () => {
</Typography>
</div>
<div ref={refTeam}>
<div className={combinedTeamClassNames} onClick={handleTeamClick}>
<div
className={combinedTeamClassNames}
onClick={handleDropdownClick('team')}
>
<div>
<Typography
variant="p4"
@@ -501,7 +389,7 @@ const Dropdowns: FC = () => {
handleOpenConfirmationDailog(selectedOption, TeamType)
}
options={updatedTeams}
selectedValue={state.team?.value.toString()}
selectedValue={incidentData?.teamId?.toString()}
/>
</div>
)}

View File

@@ -14,8 +14,7 @@ const Header: FC = () => {
const handleBacktoDashboard = (): void => {
navigate(-1);
};
//add type here and color to centralize
//To do: add type here
const incidentData = useSelector(
(state: any) => state.incidentLog.incidentData,
);
@@ -26,7 +25,11 @@ const Header: FC = () => {
<div className={styles['back-btn']}>
<div className={styles['back-btn-wrapper']}>
<div className={styles['back-btn-icon']}>
<ArrowBackIcon color="#0276FE" width={20} height={20} />
<ArrowBackIcon
color="var(--navi-color-blue-base)"
width={20}
height={20}
/>
</div>
<div className={styles['back-btn-text']}>
<Typography variant="h4" color="var(--navi-color-blue-base)">

View File

@@ -1,18 +1,6 @@
import { FC, useReducer, useEffect } from 'react';
import { truncateText, linkSanitization } from '../utils';
import styles from '../DescriptionContent/DescriptionContent.module.scss';
import { useSelector, useDispatch } from 'react-redux';
import {
setIncidentData,
setIncidentLogData,
setHeaderData,
setParticipantsData,
} from '@src/slices/IncidentSlice';
import {
Typography,
Avatar,
BorderLessInput,
} from '@navi/web-ui/lib/primitives';
import { useSelector } from 'react-redux';
import { Typography, BorderLessInput } from '@navi/web-ui/lib/primitives';
import {
CloseIcon,
DeleteIconOutlined,
@@ -20,67 +8,40 @@ import {
ArrowDownSolidIcon,
} from '@navi/web-ui/lib/icons';
import { toast } from '@navi/web-ui/lib/primitives/Toast';
import SlackIcon from '@src/assets/SlackIcon';
import LinkIcon from '@src/assets/LinkIcon';
import JiraLogo from '@src/assets/JiraLogo';
import CopyIcon from '@src/assets/CopyIcon';
import LoadingIcon from '@src/assets/LoadingIcon';
import ConfluenceIcon from '@src/assets/ConfluenceIcon';
import GoToLinkIcon from '@src/assets/GoToLinkIcon';
import { ApiService } from '@src/services/api';
import { handleCopyClick } from '@src/services/globalUtils';
import { truncateText, linkSanitization } from '../utils';
import useIncidentApis from '../useIncidentApis';
import {
ActionType,
initialState,
reducer,
JIRA_VALIDATION,
} from '../DescriptionContent/DescriptionContentProps';
import {
LINK_JIRA_INCIDENT,
UNLINK_JIRA_INCIDENT,
FETCH_INCIDENT_DATA,
} from '../constants';
import { LINK_JIRA_INCIDENT, UNLINK_JIRA_INCIDENT } from '../constants';
import styles from '../DescriptionContent/DescriptionContent.module.scss';
const JiraLinks: FC = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const { id, description, jiraIds, slackChannel, incidentName, rcaLink } =
useSelector((state: any) => state.incidentLog.incidentData);
const incidentParticipants = useSelector(
(state: any) => state.incidentLog.participantsData,
const { id, jiraLinks } = useSelector(
(state: any) => state.incidentLog.incidentData,
);
const reduxDispatch = useDispatch();
//move to hooks
const storedEmail = localStorage.getItem('email-id');
//import scss
const goToLinkBlueColor = '#0276FE';
useEffect(() => {
dispatch({ type: ActionType.SET_JIRA_LINKS, payload: jiraIds || [] });
}, [jiraIds]);
dispatch({ type: ActionType.SET_JIRA_LINKS, payload: jiraLinks || [] });
}, [jiraLinks]);
//move to constant or utils
const handleApiError = (error: any): void => {
const errorMessage =
error?.response?.data?.error?.message || 'An error occurred.';
toast.error(errorMessage);
};
//use from hooks below three functions
const startIncidentSearch = (): void => {
const endPoint = FETCH_INCIDENT_DATA(id);
ApiService.get(endPoint)
.then(response => {
reduxDispatch(setIncidentData(response?.data?.data));
dispatch({
type: ActionType.SET_JIRA_LINKS,
payload: response?.data?.data?.jiraLinks || [],
});
})
.catch(handleApiError);
};
const { startIncidentSearch } = useIncidentApis();
const addJiraLink = (payload: any): void => {
handleCloseIconClick();
@@ -89,7 +50,7 @@ const JiraLinks: FC = () => {
ApiService.post(endPoint, payload)
.then(response => {
toast.success(`${response?.data?.data}`);
startIncidentSearch();
startIncidentSearch(id);
})
.catch(handleApiError);
};
@@ -99,13 +60,12 @@ const JiraLinks: FC = () => {
ApiService.post(endPoint, payload)
.then(response => {
toast.info(`${response?.data?.data}`);
startIncidentSearch();
startIncidentSearch(id);
})
.catch(handleApiError);
};
const validateLink = (value: string): void => {
//move to constants
const urlPattern = /^https:\/\/navihq\.atlassian\.net\/browse\/.*/;
const invalidChars = /,|\s/;
if (value === '') {

View File

@@ -1,27 +1,22 @@
import { FC } from 'react';
import { useSelector } from 'react-redux';
import styles from '../Incidents.module.scss';
import { Tooltip, Typography } from '@navi/web-ui/lib/primitives';
import { AlertOutlineIcon } from '@navi/web-ui/lib/icons';
import Dropdowns from '../Dropdowns';
import styles from '../Incidents.module.scss';
const UpdateIncidentBox: FC = () => {
//add type here and color to centralize
const incidentData = useSelector(
(state: any) => state.incidentLog.incidentData,
);
//To do: add types here
const incidentParticipants = useSelector(
(state: any) => state.incidentLog.incidentParticipants,
(state: any) => state.incidentLog.participantsData,
);
// use custom hook to fetch data
const userData = JSON.parse(localStorage.getItem('user-data') || '{}');
const userEmail = userData?.emailId || [];
const participants = incidentParticipants?.participants;
const others = incidentParticipants?.others;
const participantsList = (participants || []).concat(others || []);
const { emailId: userEmail } =
JSON.parse(localStorage.getItem('user-data') || '{}') || {};
const participantsList = [
...(incidentParticipants?.participants || []),
...(incidentParticipants?.others || []),
];
//To do: add types here
const isUserParticipantList = participantsList?.some(
(participant: any) => participant.email === userEmail,
);
@@ -46,7 +41,6 @@ const UpdateIncidentBox: FC = () => {
</div>
)}
</div>
<Dropdowns />
</div>
);

View File

@@ -16,8 +16,7 @@ const Incident: FC = () => {
});
const incidentId = match?.params?.incidentId || '';
const { fetchIncidentLog, startIncidentSearch, fetchHeaderDetails } =
useIncidentApis();
const { startIncidentSearch, fetchHeaderDetails } = useIncidentApis();
useEffect(() => {
startIncidentSearch(incidentId);
@@ -36,14 +35,12 @@ const Incident: FC = () => {
key: '1',
label: 'Details',
children: (
<div>
<div className={styles['content-wrapper']}>
<div className={styles['audit-log']}>
<UpdateIncidentBox />
<ActivityLog />
</div>
<DescriptionContent />
<div className={styles['content-wrapper']}>
<div className={styles['audit-log']}>
<UpdateIncidentBox />
<ActivityLog />
</div>
<DescriptionContent />
</div>
),
},

View File

@@ -97,7 +97,7 @@ const useIncidentApis = () => {
const updateIncident = (payload: any): void => {
const endPoint = UPDATE_INCIDENT;
console.log('payload', payload);
//console.log('payload', payload);
ApiService.post(endPoint, payload)
.then(response => {
toast.success('Incident updated successfully');

View File

@@ -3,13 +3,13 @@ import { useMatch } from 'react-router-dom';
export const getUpdateTypeText = (updateType: number): string => {
switch (updateType) {
case SeverityType:
return ' severity ';
return 'severity';
case StatusType:
return ' status ';
return 'status';
case TeamType:
return ' team ';
return 'team';
default:
return ' severity ';
return 'severity';
}
};