INFRA-2867 | add modal for product change

This commit is contained in:
dhruvjoshi
2024-03-12 19:54:23 +05:30
parent d5c2930c2a
commit e3c47724e1
13 changed files with 444 additions and 116 deletions

View File

@@ -72,7 +72,7 @@
width: 7px;
height: 7px;
background-color: white;
border-radius: 50%; /* Makes the div round */
border-radius: 50%;
margin-right: 4px;
}
}

View File

@@ -147,6 +147,7 @@
.create-incident-product-selector {
width: 335px !important;
min-height: unset;
> div > div {
span {
color: var(--navi-color-blue-base) !important;
@@ -155,4 +156,5 @@
}
.create-incident-single-selector {
width: 321px !important;
min-height: unset;
}

View File

@@ -2,15 +2,16 @@ import { FC } from 'react';
import { useNavigate } from 'react-router-dom';
import { AgTable, Pagination } from '@navi/web-ui/lib/components';
import { Tag } from '@navi/web-ui/lib/primitives';
import { Tooltip } from 'antd';
import cx from 'classnames';
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 { getSeverityColor } from '@src/Pages/Dashboard/constants';
import { IncidentDashboard } from '@src/slices/dashboardSlice';
import { Team } from '../type';
import { Tooltip } from 'antd';
import { Team } from '@src/Pages/Dashboard/type';
import styles from '@src/Pages/Dashboard/partials/CreateIncident.module.scss';
interface SearchResultTableProps {
currentPageData: IncidentDashboard[];
pageDetails: any;
@@ -76,9 +77,7 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
const wrappedText = param?.substring(0, MAX_LENGTH - 3) + '...';
return (
<div className={styles.tooltipWrapper}>
<Tooltip title={param}>
<div className={styles.tooltip}>{wrappedText}</div>
</Tooltip>
<Tooltip title={param}>{wrappedText}</Tooltip>
</div>
);
}

View File

@@ -1,7 +1,10 @@
import { FC, useReducer } from 'react';
import { FC, useEffect, useReducer } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { AlertOutlineIcon } from '@navi/web-ui/lib/icons';
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
import { AlertOutlineIcon, InfoIcon } from '@navi/web-ui/lib/icons';
import {
SelectPickerOptionProps,
SelectPickerValue,
} from '@navi/web-ui/lib/components/SelectPicker/types';
import {
BorderedInput,
ModalDialog,
@@ -29,6 +32,11 @@ import {
getSeverityValue,
} from '../constants';
import useIncidentApis from '../useIncidentApis';
import { FETCH_ASSIGNER_AND_RESPONDER } from '@src/Pages/Dashboard/constants';
import { ApiService } from '@src/services/api';
import IncidentSingleSelector from '@src/Pages/Dashboard/partials/IncidentSingleSelector';
import { Team } from '@src/Pages/Dashboard/type';
import styles from '../Incidents.module.scss';
const AllDailogBox: FC = () => {
@@ -59,6 +67,35 @@ const AllDailogBox: FC = () => {
const incidentId = incidentData?.id?.toString() || '';
const reduxDispatch = useDispatch();
useEffect(() => {
if (UpdateData?.type == 'product') {
const product = UpdateData?.to as SelectPickerOptionProps[];
const productIds = product?.map(option => option.value as number);
ApiService.get(FETCH_ASSIGNER_AND_RESPONDER(productIds))?.then(
response => {
const responderTeams = response?.data?.data?.responderTeam?.teams;
dispatch({
type: actionTypes.SET_RESPONDERS,
payload: responderTeams,
});
},
);
}
}, [UpdateData]);
useEffect(() => {
if (state?.responderList) {
const responderTeams = state?.responderList?.map(
(team: Team) => team.value as number,
);
if (!responderTeams.includes(incidentData.teamId)) return;
dispatch({
type: actionTypes.SET_TEAM,
payload: incidentData?.teamId,
});
}
}, [incidentData, state.responderList]);
const updateDetailsFrom = getSeverityValue(UpdateData?.from?.trim() || '');
const updateDetailsTo = (
UpdateData as { to?: { value: string; label: string } }
@@ -205,6 +242,7 @@ const AllDailogBox: FC = () => {
}
}
};
const handleTeamSelectionChange = (
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[] | null,
): void => {
@@ -223,15 +261,35 @@ const AllDailogBox: FC = () => {
}
};
const handleProductSelectionChange = (
selectedOption: SelectPickerOptionProps[] | null,
): void => {
if (selectedOption) {
dispatch({
type: actionTypes.SET_IS_PRODUCT_PICKER_OPEN,
payload: false,
});
toast('Updating ticket. Please wait a moment.', {
icon: <LoadingIcon />,
});
const value = selectedOption.map(option => option.value as number);
updateIncident({
id: parseInt(incidentId, 10),
productIds: value,
teamId: state?.team?.toString(),
});
}
};
const handleCloseConfirmationDialog = () => {
if (UpdateData?.type == 'severity') {
handleSeveritySelectionChange(selectedOption);
} else {
if (UpdateData?.type == 'status') {
} else if (UpdateData?.type == 'status') {
handleStatusSelectionChange(selectedOption);
} else {
} else if (UpdateData?.type == 'team') {
handleTeamSelectionChange(selectedOption);
}
} else {
handleProductSelectionChange(selectedOption as SelectPickerOptionProps[]);
}
};
@@ -239,7 +297,7 @@ const AllDailogBox: FC = () => {
option: SelectPickerOptionProps | SelectPickerOptionProps[] | null,
): string | undefined => {
if (Array.isArray(option)) {
return option[0]?.label;
return option?.map(opt => opt.label).join(', ');
} else {
return option?.label;
}
@@ -358,19 +416,59 @@ const AllDailogBox: FC = () => {
</div>
);
const customFooter = (): JSX.Element => (
<div className={styles['modal-footer']}>
{UpdateData.type === 'severity' &&
const customFooter = (): JSX.Element => {
const isSeverityAndDisabled =
UpdateData.type === 'severity' &&
showJustificationBox &&
state.reason.length <= 5 ? (
state.reason.length <= 5;
return (
<div className={styles['modal-footer']}>
{isSeverityAndDisabled ? (
<Tooltip text="Please enter atleast 5 characters" position="left">
<Button disabled>Update incident</Button>
</Tooltip>
) : (
<Button onClick={handleUpdateIncidentClick}>Update incident</Button>
<Button
onClick={handleUpdateIncidentClick}
disabled={UpdateData.type === 'product' && !state.team}
>
Update incident
</Button>
)}
</div>
);
};
const renderResponderChange = () => {
const handleResponderChange = (val: SelectPickerValue) => {
dispatch({ type: actionTypes.SET_TEAM, payload: val });
};
return (
<div className={styles['product-selector']}>
<Typography variant="p3" color="var(--navi-color-gray-c2)">
Please review the responder for this incident and change if necessary.
</Typography>
<div className={styles['product-header-wrapper']}>
<Typography variant="p4" className={styles['responder']}>
{' '}
Responder
</Typography>
<Tooltip
position="right"
text="If no responder selected, the team was not mapped to the updated product"
withPointer
>
<InfoIcon />
</Tooltip>
</div>
<IncidentSingleSelector
options={state.responderList}
handleSelectionChange={handleResponderChange}
selected={state.team}
/>
</div>
);
};
const renderUpdateDialog = (): JSX.Element => (
<div>
@@ -402,7 +500,7 @@ const AllDailogBox: FC = () => {
{getLabelFromOption(UpdateData?.to) || '..'}
</Typography>
</Typography>
{UpdateData.type === 'severity' && showJustificationBox ? (
{UpdateData.type === 'severity' && showJustificationBox && (
<div>
<textarea
placeholder="Enter reason for de-escalation"
@@ -420,7 +518,8 @@ const AllDailogBox: FC = () => {
{state.reason.length} / 100 characters
</Typography>
</div>
) : null}
)}
{UpdateData.type === 'product' && renderResponderChange()}
</div>
</ModalDialog>
) : null}

View File

@@ -0,0 +1,31 @@
import { Typography } from '@navi/web-ui/lib/primitives';
import { Team } from '@src/Pages/Dashboard/type';
import styles from '../Incidents.module.scss';
export const getProduct = (initialProducts: Team[] | null) => {
return initialProducts?.map(product => product?.label).join(', ') || '';
};
export const getTruncatedProduct = (initialProducts: Team[] | null) => {
const product = getProduct(initialProducts);
const TRUNCATE_PRODUCT_LIMIT = 30;
const truncatedProduct =
product?.length > TRUNCATE_PRODUCT_LIMIT
? `${product?.slice(0, TRUNCATE_PRODUCT_LIMIT)}...`
: product;
const showMore = product?.length > TRUNCATE_PRODUCT_LIMIT ? true : false;
const remaining =
initialProducts?.length ?? 0 - truncatedProduct?.split(',')?.length;
return (
<div className={styles['product-text']}>
<Typography variant="p4">{truncatedProduct}</Typography>
{showMore && (
<Typography variant="p4" color="var(--navi-color-blue-base)">
{' '}
+ {remaining} more
</Typography>
)}
</div>
);
};

View File

@@ -1,11 +1,14 @@
import { FC, useReducer, MutableRefObject } from 'react';
import { FC, useReducer, MutableRefObject, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import classnames from 'classnames';
import { Typography } from '@navi/web-ui/lib/primitives';
import { Tooltip, Typography } from '@navi/web-ui/lib/primitives';
import { ArrowDownIcon } from '@navi/web-ui/lib/icons';
import { Button, Drawer } from '@navi/web-ui/lib/primitives';
import { Drawer } from '@navi/web-ui/lib/primitives';
import { SelectPicker } from '@navi/web-ui/lib/components';
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
import {
SelectPickerOptionProps,
SelectPickerValue,
} from '@navi/web-ui/lib/components/SelectPicker/types';
import useOutsideClick from '@src/services/hooks/useOustideClick';
import { Participant } from '@src/types';
import {
@@ -36,7 +39,14 @@ import {
SeverityType,
StatusType,
TeamType,
ProductType,
} from '../constants';
import { getProduct, getTruncatedProduct } from './DropDownHelper';
import {
selectAssignerResponderData,
selectProductListData,
} from '@src/slices/createIncidentSlice';
import styles from '../Incidents.module.scss';
const Dropdowns: FC = () => {
@@ -46,6 +56,7 @@ const Dropdowns: FC = () => {
const incidentData = useSelector(
(state: IncidentPageState) => state.incidentLog.incidentData,
);
const currentIncidentId = incidentData?.id;
const slackChannel = incidentData?.slackChannel;
const incidentParticipants = useSelector(
@@ -54,11 +65,13 @@ const Dropdowns: FC = () => {
const headerData = useSelector(
(state: IncidentPageState) => state.incidentLog.headerData,
);
const productOptions = useSelector(selectProductListData)?.products;
const [state, dispatch] = useReducer(reducer, initialState);
const updatedSeverities = generateOptions(headerData?.severities);
const updatedStatuses = generateOptions(headerData?.incidentStatuses);
const updatedTeams = generateOptions(headerData?.teams);
const updatedTeams = useSelector(selectAssignerResponderData)?.assignerTeam
?.teams;
const initialSeverity = {
label: incidentData?.severityName,
value: incidentData?.severityId,
@@ -71,6 +84,15 @@ const Dropdowns: FC = () => {
label: incidentData?.teamName,
value: incidentData?.teamId,
};
const initialProducts = incidentData?.products;
useEffect(() => {
dispatch({
type: actionTypes.SET_SELECTED_PRODUCTS,
payload: initialProducts,
});
}, [initialProducts]);
useEffect(() => {}, [incidentData]);
const { emailId: userEmail } =
JSON.parse(localStorage.getItem('user-data') || '{}') || {};
const participantsList = [
@@ -85,34 +107,39 @@ const Dropdowns: FC = () => {
const severityMap = generateMap(headerData?.severities || []);
const statusMap = generateMap(headerData?.incidentStatuses || []);
const teamsMap = generateMap(headerData?.teams || []);
const productMap = generateMap(productOptions || []);
const currentSev = getCurrentData(incidentData, severityMap, 'severityId');
const currentStatus = getCurrentData(incidentData, statusMap, 'status');
const currentTeam = getCurrentData(incidentData, teamsMap, 'teamId');
const combinedSevClassNames = classnames(
const getCombinedClassNames = (
isOpen: boolean,
isUserParticipantList: boolean,
) =>
classnames(
styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'],
{
[styles['open-box']]: state.isSeverityPickerOpen,
[styles['open-box-disabled']]:
state.isSeverityPickerOpen && !isUserParticipantList,
[styles['open-box']]: isOpen,
[styles['open-box-disabled']]: isOpen && !isUserParticipantList,
},
);
const combinedStatusClassNames = classnames(
styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'],
{
[styles['open-box']]: state.isStatusPickerOpen,
[styles['open-box-disabled']]:
state.isStatusPickerOpen && !isUserParticipantList,
},
const combinedSevClassNames = getCombinedClassNames(
state.isSeverityPickerOpen,
isUserParticipantList,
);
const combinedTeamClassNames = classnames(
styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'],
{
[styles['open-box']]: state.isTeamPickerOpen,
[styles['open-box-disabled']]:
state.isTeamPickerOpen && !isUserParticipantList,
},
const combinedStatusClassNames = getCombinedClassNames(
state.isStatusPickerOpen,
isUserParticipantList,
);
const combinedTeamClassNames = getCombinedClassNames(
state.isTeamPickerOpen,
isUserParticipantList,
);
const combinedProductClassNames = getCombinedClassNames(
state.isProductPickerOpen,
isUserParticipantList,
);
const handleDropdownClick = (changeType: string): (() => void) => {
@@ -124,6 +151,8 @@ const Dropdowns: FC = () => {
return () => handleStatusDropdownClick();
case 'team':
return () => handleTeamDropdownClick();
case 'product':
return () => handleProductDropdownClick();
default:
throw new Error('Invalid change type');
}
@@ -150,10 +179,38 @@ const Dropdowns: FC = () => {
payload: !state.isTeamPickerOpen,
});
};
const handleProductDropdownClick = (): void => {
dispatch({
type: actionTypes.SET_SELECTED_PRODUCTS,
payload: initialProducts,
});
dispatch({
type: actionTypes.SET_IS_PRODUCT_PICKER_OPEN,
payload: !state.isProductPickerOpen,
});
};
const handleDisabledDropdownClick = (): void => {
reduxDispatch(setOpenDialognotParticipants(true));
};
const handleProductPickerCancelClick = (): void => {
dispatch({ type: actionTypes.SET_IS_PRODUCT_PICKER_OPEN, payload: false });
dispatch({
type: actionTypes.SET_SELECTED_PRODUCTS,
payload: initialProducts,
});
};
const handleProductSelectionChange = (
options: SelectPickerOptionProps | SelectPickerOptionProps[],
) => {
dispatch({ type: actionTypes.SET_SELECTED_PRODUCTS, payload: options });
};
const handleApplyProductSelection = (
selectedOption: SelectPickerOptionProps[],
) => {
dispatch({ type: actionTypes.SET_IS_PRODUCT_PICKER_OPEN, payload: false });
handleOpenConfirmationDailog(selectedOption, ProductType);
};
const handleDispatch = (
updateType: number,
selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[],
@@ -164,8 +221,13 @@ const Dropdowns: FC = () => {
to: selectedOption,
from: getUpdateValueText({
updateType: updateType,
maps: { severityMap, statusMap, teamsMap },
initialValues: { initialSeverity, initialStatus, initialTeam },
maps: { severityMap, statusMap, teamsMap, productMap },
initialValues: {
initialSeverity,
initialStatus,
initialTeam,
initialProducts,
},
}),
}),
);
@@ -173,25 +235,37 @@ const Dropdowns: FC = () => {
reduxDispatch(setOpenDialogUpdate(true));
};
const getCurrentValue = (updateType: number) => {
switch (updateType) {
case SeverityType:
return initialSeverity?.value;
case StatusType:
return initialStatus?.value;
case TeamType:
return initialTeam?.value;
case ProductType:
return initialProducts?.map(
product => product?.value as SelectPickerValue,
);
default:
return null;
}
};
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
const currentValue = getCurrentValue(updateType);
const selectedValue = Array.isArray(selectedOption)
? selectedOption?.map(option => option.value)
: selectedOption.value;
if (currentState !== selectedvalue) {
if (currentValue != selectedValue) {
fireEvent(EVENT_NAME.Houston_Resolve_Incident_initiate, {
screen_name: SCREEN_NAME.INCIDENT_PAGE,
});
if (updateType === StatusType && selectedvalue === RESOLVE_STATUS) {
if (updateType === StatusType && selectedValue === RESOLVE_STATUS) {
dispatch({
type: actionTypes.SET_IS_INCIDENT_RESOLVED,
payload: true,
@@ -202,13 +276,15 @@ const Dropdowns: FC = () => {
});
} else if (
updateType === StatusType &&
selectedvalue === DUPLICATE_STATUS
selectedValue === DUPLICATE_STATUS
) {
dispatch({
type: actionTypes.SET_DUPLICATE_DIALOG,
payload: true,
});
reduxDispatch(setOpenDialogDuplicate(true));
} else if (updateType === ProductType) {
handleDispatch(updateType, selectedOption);
} else {
handleDispatch(updateType, selectedOption);
}
@@ -220,35 +296,23 @@ const Dropdowns: FC = () => {
payload: false,
});
};
const handleSevClickOutside = (): void => {
const handlePickerClickOutside = (pickerType: string) => {
dispatch({
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
type: pickerType,
payload: false,
});
};
const handleStatusClickOutside = (): void => {
dispatch({
type: actionTypes.SET_IS_STATUS_PICKER_OPEN,
payload: false,
});
};
const handleTeamClickOutside = (): void => {
dispatch({
type: actionTypes.SET_IS_TEAM_PICKER_OPEN,
payload: false,
});
};
const refStatus = useOutsideClick({
callback: handleStatusClickOutside,
}) as MutableRefObject<HTMLDivElement>;
const refSeverity = useOutsideClick({
callback: handleSevClickOutside,
const RefPicker = (pickerType: string) => {
return useOutsideClick({
callback: () => handlePickerClickOutside(pickerType),
}) as MutableRefObject<HTMLDivElement>;
};
const refTeam = useOutsideClick({
callback: handleTeamClickOutside,
}) as MutableRefObject<HTMLDivElement>;
const refStatus = RefPicker(actionTypes.SET_IS_STATUS_PICKER_OPEN);
const refSeverity = RefPicker(actionTypes.SET_IS_SEVERITY_PICKER_OPEN);
const refTeam = RefPicker(actionTypes.SET_IS_TEAM_PICKER_OPEN);
const refProduct = RefPicker(actionTypes.SET_IS_PRODUCT_PICKER_OPEN);
return (
<div>
@@ -369,7 +433,6 @@ const Dropdowns: FC = () => {
</div>
<div className={styles['team-selectpicker']}>
{state.isTeamPickerOpen && (
<div className={styles['team-selectpicker-style']}>
<SelectPicker
multiSelect={false}
onSelectionChange={selectedOption =>
@@ -377,8 +440,56 @@ const Dropdowns: FC = () => {
}
options={updatedTeams}
selectedValue={incidentData?.teamId?.toString()}
wrapperClasses={styles['team-selectpicker-style']}
/>
)}
</div>
</div>
</div>
<div className={styles['dropdown-product']}>
<div>
<Typography variant="p5" color="var(--navi-color-gray-c2)">
Product
</Typography>
</div>
<div ref={refProduct}>
<div
className={combinedProductClassNames}
onClick={handleDropdownClick('product')}
>
<Tooltip
text={getProduct(initialProducts)}
position="top"
withPointer
>
<Typography
variant="p4"
color={
isUserParticipantList
? 'var(--navi-color-gray-c1)'
: 'var(--navi-color-gray-c3)'
}
>
{getTruncatedProduct(initialProducts)}
</Typography>
</Tooltip>
<div>
<ArrowDownIcon className={styles['arrowdown-style']} />
</div>
</div>
<div className={styles['product-selectpicker']}>
{state.isProductPickerOpen && (
<SelectPicker
multiSelect={true}
onSelectionChange={handleProductSelectionChange}
options={productOptions}
selectedValues={state.selectedProducts?.map(
product => product?.value as SelectPickerValue,
)}
wrapperClasses={styles['product-selectpicker-style']}
handleCancelClick={handleProductPickerCancelClick}
handleApplyClick={handleApplyProductSelection}
/>
)}
</div>
</div>

View File

@@ -62,7 +62,10 @@
}
.dropdown-team {
width: 240px;
width: 210px;
}
.dropdown-product {
width: 287px;
}
.dropdown-box {
@@ -102,6 +105,14 @@
position: absolute;
z-index: 1;
}
.product-selectpicker {
position: absolute;
z-index: 1;
.product-selectpicker-style {
min-width: unset;
width: 285px;
}
}
.severity-selectpicker-style {
width: 100px;
@@ -131,6 +142,10 @@
.team-selectpicker {
position: absolute;
z-index: 1;
.team-selectpicker-style {
min-width: unset;
width: 208px;
}
}
.incidentChange-wrapper {
@@ -257,3 +272,28 @@
display: flex;
justify-content: flex-end;
}
.product-selector {
padding-top: 24px;
.product-header-wrapper {
padding-top: 24px;
display: flex;
align-items: center;
.responder {
margin-top: -5px;
padding-right: 5px;
.responder-tooltip {
width: 100px;
position: absolute;
z-index: 10000;
}
}
}
:last-child {
:first-child {
width: unset !important;
}
}
}
.product-text {
display: flex;
}

View File

@@ -1,15 +1,31 @@
import { FC } from 'react';
import { FC, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { Tooltip, Typography } from '@navi/web-ui/lib/primitives';
import { AlertOutlineIcon } from '@navi/web-ui/lib/icons';
import { IncidentPageState } from '@src/types';
import Dropdowns from '../Dropdowns';
import styles from '../Incidents.module.scss';
import useIncidentFormApi from '@src/Pages/Dashboard/useDashboardApi';
import { Team } from '@src/Pages/Dashboard/type';
import { RootState } from '@src/store';
const UpdateIncidentBox: FC = () => {
const { fetchAssignerAndResponder } = useIncidentFormApi();
const incidentParticipants = useSelector(
(state: IncidentPageState) => state.incidentLog.participantsData,
);
const productOptions = useSelector(
(state: RootState) => state.incidentLog.incidentData.products,
);
useEffect(() => {
if (productOptions) {
fetchAssignerAndResponder(
productOptions?.map((product: Team) => product.value),
);
}
}, [productOptions]);
const { emailId: userEmail } =
JSON.parse(localStorage.getItem('user-data') || '{}') || {};
const participantsList = [

View File

@@ -51,10 +51,12 @@ export const actionTypes = {
SET_OPEN_DIALOG: 'SET_OPEN_DIALOG',
SET_OPEN_CONFIRMATION_DIALOG: 'SET_OPEN_CONFIRMATION_DIALOG',
SET_SELECTED_OPTION: 'SET_SELECTED_OPTION',
SET_SELECTED_PRODUCTS: 'SET_SELECTED_PRODUCTS',
SET_UPDATE_TYPE: 'SET_UPDATE_TYPE',
SET_DIALOG_TEXT: 'SET_DIALOG_TEXT',
SET_DIALOG_BODY_TEXT: 'SET_DIALOG_BODY_TEXT',
SET_IS_SEVERITY_PICKER_OPEN: 'SET_IS_SEVERITY_PICKER_OPEN',
SET_IS_PRODUCT_PICKER_OPEN: 'SET_IS_PRODUCT_PICKER_OPEN',
SET_IS_STATUS_PICKER_OPEN: 'SET_IS_STATUS_PICKER_OPEN',
SET_IS_TEAM_PICKER_OPEN: 'SET_IS_TEAM_PICKER_OPEN',
SET_DUPLICATE_DIALOG: 'SET_DUPLICATE_DIALOG',
@@ -63,6 +65,7 @@ export const actionTypes = {
RESET_DUPLICATE_DIALOG: 'RESET_DUPLICATE_DIALOG',
SET_IS_INCIDENT_RESOLVED: 'SET_IS_INCIDENT_RESOLVED',
SET_REASON: 'SET_REASON',
SET_RESPONDERS: 'SET_RESPONDERS',
};
export const reducer = (state, action) => {
@@ -93,6 +96,8 @@ export const reducer = (state, action) => {
return { ...state, openConfirmationDialog: action.payload };
case actionTypes.SET_SELECTED_OPTION:
return { ...state, selectedOption: action.payload };
case actionTypes.SET_SELECTED_PRODUCTS:
return { ...state, selectedProducts: action.payload };
case actionTypes.SET_UPDATE_TYPE:
return { ...state, updateType: action.payload };
case actionTypes.SET_DIALOG_TEXT:
@@ -105,6 +110,8 @@ export const reducer = (state, action) => {
return { ...state, isStatusPickerOpen: action.payload };
case actionTypes.SET_IS_TEAM_PICKER_OPEN:
return { ...state, isTeamPickerOpen: action.payload };
case actionTypes.SET_IS_PRODUCT_PICKER_OPEN:
return { ...state, isProductPickerOpen: action.payload };
case actionTypes.SET_INCIDENT_NAME:
return { ...state, incidentName: action.payload };
case actionTypes.SET_ERROR_MSG:
@@ -120,6 +127,8 @@ export const reducer = (state, action) => {
return { ...state, isIncidentResolved: action.payload };
case actionTypes.SET_REASON:
return { ...state, reason: action.payload };
case actionTypes.SET_RESPONDERS:
return { ...state, responderList: action.payload };
default:
return state;
}
@@ -138,16 +147,19 @@ export const initialState = {
openDialog: false,
openConfirmationDialog: false,
selectedOption: undefined,
selectedProducts: [],
updateType: undefined,
dialogText: '',
dialogBodyText: '',
isSeverityPickerOpen: false,
isStatusPickerOpen: false,
isTeamPickerOpen: false,
isProductPickerOpen: false,
incidentName: '',
openDuplicateDialog: false,
errorMsg: '',
isIncidentResolved: false,
responderList: [],
reason: '',
};
@@ -172,3 +184,4 @@ export const DUPLICATE_STATUS = '5';
export const SeverityType = 0;
export const StatusType = 1;
export const TeamType = 2;
export const ProductType = 3;

View File

@@ -7,6 +7,7 @@ import ActivityLog from './ActivityLog';
import UpdateIncidentBox from './UpdateIncidentBox';
import Headers from './Header';
import useIncidentApis from './useIncidentApis';
import useIncidentFormApi from '@src/Pages/Dashboard/useDashboardApi';
import styles from './Incidents.module.scss';
const Incident: FC = () => {
@@ -17,10 +18,12 @@ const Incident: FC = () => {
const incidentId = match?.params?.incidentId || '';
const { startIncidentSearch, fetchHeaderDetails } = useIncidentApis();
const { fetchProductList } = useIncidentFormApi();
useEffect(() => {
startIncidentSearch(incidentId);
fetchHeaderDetails();
fetchProductList();
}, [incidentId]);
return (

View File

@@ -1,4 +1,4 @@
import { SeverityType, StatusType, TeamType } from './constants';
import { ProductType, SeverityType, StatusType, TeamType } from './constants';
export const getUpdateTypeText = (updateType: number): string => {
switch (updateType) {
case SeverityType:
@@ -7,8 +7,10 @@ export const getUpdateTypeText = (updateType: number): string => {
return 'status';
case TeamType:
return 'team';
case ProductType:
return 'product';
default:
return 'severity';
return '';
}
};
@@ -26,12 +28,14 @@ interface Maps {
severityMap: { [key: number]: string };
statusMap: { [key: number]: string };
teamsMap: { [key: number]: string };
productMap: { [key: number]: string };
}
interface InitialValues {
initialSeverity?: { value: number | null };
initialStatus?: { value: number | null };
initialTeam?: { value: number | null };
initialProducts?: { label: string; value: number }[] | null;
}
export const generateOptions = (data: DataItem[]): DataItemModified[] => {
@@ -60,7 +64,7 @@ export const linkSanitization = (link: string): string => {
};
export const getCurrentData = (
data: { [key: string]: any },
data: { [key: string]: any } | null,
dataMap: { [key: string]: string },
key: string,
): string => {
@@ -102,11 +106,17 @@ export const getUpdateValueText = ({
? maps.teamsMap[initialValues.initialTeam.value]
: '-'
} `;
default:
case ProductType:
return ` ${
maps.severityMap && initialValues.initialSeverity?.value
? maps.severityMap[initialValues.initialSeverity.value]
initialValues.initialProducts?.length
? initialValues.initialProducts
.map(
(product: { value: number }) => maps.productMap[product.value],
)
.join(', ')
: '-'
} `;
default:
return '';
}
};

View File

@@ -42,6 +42,8 @@ const initialState: IncidentLogPageState = {
createdAt: null,
updatedAt: null,
rcaLink: '',
assignerTeam: null,
products: null,
},
headerData: {
severities: [],

View File

@@ -81,8 +81,8 @@ export interface IncidentDatatype {
createdAt: Date | null;
updatedAt: Date | null;
rcaLink: string;
assignerTeam: Team;
products: Team[];
assignerTeam: Team | null;
products: Team[] | null;
}
interface Severity {
@@ -179,4 +179,6 @@ export interface UpdateIncidentType {
teamId?: string;
status?: string;
justification?: string;
productIds?: number[];
teamId?: string;
}