Merge branch 'master' into INFRA-2836
This commit is contained in:
@@ -3,20 +3,23 @@ import { useSelector, useDispatch } from 'react-redux';
|
||||
import classnames from 'classnames';
|
||||
import { 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 { SelectPicker } from '@navi/web-ui/lib/components';
|
||||
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
|
||||
import useOutsideClick from '@src/services/hooks/useOustideClick';
|
||||
import { Participant } from '@src/types';
|
||||
import {
|
||||
setOpenDialogDuplicate,
|
||||
setOpenDialogResolve,
|
||||
setOpenDialogUpdate,
|
||||
setOpenDialognotParticipants,
|
||||
setUpdateDetails,
|
||||
setSelectedOptions,
|
||||
} from '@src/slices/IncidentSlice';
|
||||
import { IncidentPageState } from '@src/types';
|
||||
import useClickStream from '@src/services/clickStream';
|
||||
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
|
||||
import AllDailogBox from './AllDailogBox';
|
||||
import ResolveForm from '../ResolveForm';
|
||||
import {
|
||||
generateOptions,
|
||||
getCurrentData,
|
||||
@@ -38,10 +41,13 @@ import styles from '../Incidents.module.scss';
|
||||
|
||||
const Dropdowns: FC = () => {
|
||||
const reduxDispatch = useDispatch();
|
||||
|
||||
const { fireEvent } = useClickStream();
|
||||
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
|
||||
const incidentData = useSelector(
|
||||
(state: IncidentPageState) => state.incidentLog.incidentData,
|
||||
);
|
||||
const currentIncidentId = incidentData?.id;
|
||||
const slackChannel = incidentData?.slackChannel;
|
||||
const incidentParticipants = useSelector(
|
||||
(state: IncidentPageState) => state.incidentLog.participantsData,
|
||||
);
|
||||
@@ -182,8 +188,18 @@ const Dropdowns: FC = () => {
|
||||
? selectedOption[0].value
|
||||
: selectedOption.value;
|
||||
if (currentState !== selectedvalue) {
|
||||
fireEvent(EVENT_NAME.Houston_Resolve_Incident_initiate, {
|
||||
screen_name: SCREEN_NAME.INCIDENT_PAGE,
|
||||
});
|
||||
if (updateType === StatusType && selectedvalue === RESOLVE_STATUS) {
|
||||
reduxDispatch(setOpenDialogResolve(true));
|
||||
dispatch({
|
||||
type: actionTypes.SET_IS_INCIDENT_RESOLVED,
|
||||
payload: true,
|
||||
});
|
||||
dispatch({
|
||||
type: actionTypes.SET_IS_STATUS_PICKER_OPEN,
|
||||
payload: !state.isStatusPickerOpen,
|
||||
});
|
||||
} else if (
|
||||
updateType === StatusType &&
|
||||
selectedvalue === DUPLICATE_STATUS
|
||||
@@ -198,7 +214,12 @@ const Dropdowns: FC = () => {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleDrawerClose = () => {
|
||||
dispatch({
|
||||
type: actionTypes.SET_IS_INCIDENT_RESOLVED,
|
||||
payload: false,
|
||||
});
|
||||
};
|
||||
const handleSevClickOutside = (): void => {
|
||||
dispatch({
|
||||
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
|
||||
@@ -364,6 +385,28 @@ const Dropdowns: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
<AllDailogBox />
|
||||
{state.isIncidentResolved && (
|
||||
<div className={styles['incident-resolved']}>
|
||||
<Drawer
|
||||
open={state.isIncidentResolved}
|
||||
headerText="Resolve incident"
|
||||
headerContainerClasses={styles.header}
|
||||
className={styles.drawer}
|
||||
onClose={() => {
|
||||
dispatch({
|
||||
type: actionTypes.SET_IS_INCIDENT_RESOLVED,
|
||||
payload: false,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ResolveForm
|
||||
handleDrawerClose={handleDrawerClose}
|
||||
incidentId={currentIncidentId}
|
||||
slackChannel={slackChannel}
|
||||
/>
|
||||
</Drawer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -208,3 +208,26 @@
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.incident-label {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.drawer {
|
||||
width: 444px !important;
|
||||
height: 100% !important;
|
||||
> div {
|
||||
padding: 16px 16px 16px 0px !important;
|
||||
}
|
||||
}
|
||||
.header {
|
||||
padding: 16px !important;
|
||||
border-bottom: 1px solid var(--navi-drawer-divider-color);
|
||||
> span {
|
||||
@include flex-center;
|
||||
}
|
||||
}
|
||||
|
||||
116
src/Pages/Incidents/ResolveForm/ResolveForm.module.scss
Normal file
116
src/Pages/Incidents/ResolveForm/ResolveForm.module.scss
Normal file
@@ -0,0 +1,116 @@
|
||||
@import 'mixins';
|
||||
|
||||
.Factor-wrapper,
|
||||
.jira-wrapper,
|
||||
.Team-wrapper,
|
||||
.Tag-wrapper,
|
||||
.RCA-wrapper {
|
||||
@include wrapper-styles;
|
||||
}
|
||||
.button-wrapper {
|
||||
@include button-styles;
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
margin-bottom: 24px;
|
||||
border-top: 1px solid var(--navi-drawer-divider-color);
|
||||
padding-top: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
.resolve {
|
||||
width: 184px;
|
||||
height: 36px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
.cancel {
|
||||
width: 184px;
|
||||
height: 36px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
.textarea {
|
||||
min-width: 404px !important;
|
||||
color: var(--navi-color-gray-c2);
|
||||
|
||||
> div > textarea {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.footer-wrapper {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select-div {
|
||||
position: relative;
|
||||
width: 404px;
|
||||
height: 36px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--navi-color-gray-border);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.select-team {
|
||||
position: relative;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select-picker {
|
||||
border-radius: 4px;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.select-picker-style {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
.select-picker-item {
|
||||
min-width: 404px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.arrow-down {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
display: flex;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.arrow-dropdown {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
display: flex;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.autocomplete {
|
||||
height: 36px;
|
||||
width: 384px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0px 10px;
|
||||
> div {
|
||||
> div {
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-wrapper {
|
||||
margin: 16px 4px 0px 20px;
|
||||
}
|
||||
.factor-label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.jira {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.add-jira-link {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
79
src/Pages/Incidents/ResolveForm/constants.ts
Normal file
79
src/Pages/Incidents/ResolveForm/constants.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { URL_PREFIX } from '../constants';
|
||||
|
||||
export const FETCH_RESOLVE_CONFIG = `${URL_PREFIX}/tags/resolve`;
|
||||
export const RESOLVE_INCIDENTS = `${URL_PREFIX}/incidents/resolve`;
|
||||
|
||||
export interface Team {
|
||||
tag_value_id: number;
|
||||
tag_value_name: string;
|
||||
}
|
||||
export interface ResolveFormProps {
|
||||
handleDrawerClose: () => void;
|
||||
incidentId: number | null;
|
||||
slackChannel: string;
|
||||
}
|
||||
export const initialState = {
|
||||
team: [],
|
||||
factors: [],
|
||||
tags: [],
|
||||
openFactorPicker: false,
|
||||
selectedTeam: [],
|
||||
selectedFactor: [],
|
||||
selectedTag: [],
|
||||
rca: '',
|
||||
jiraLinks: [],
|
||||
};
|
||||
|
||||
export const actionTypes = {
|
||||
SET_TEAM: 'SET_TEAM',
|
||||
SET_FACTORS: 'SET_FACTORS',
|
||||
SET_TAGS: 'SET_TAGS',
|
||||
SET_OPEN_FACTOR_PICKER: 'SET_OPEN_FACTOR_PICKER',
|
||||
SET_SELECTED_TEAM: 'SET_SELECTED_TEAM',
|
||||
SET_SELECTED_FACTOR: 'SET_SELECTED_FACTOR',
|
||||
SET_SELECTED_TAG: 'SET_SELECTED_TAG',
|
||||
SET_RCA: 'SET_RCA',
|
||||
RESET_STATE: 'RESET_STATE',
|
||||
ADD_JIRA_LINK: 'ADD_JIRA_LINK',
|
||||
UPDATE_JIRA_LINK: 'UPDATE_JIRA_LINK',
|
||||
};
|
||||
export const reducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case actionTypes.SET_TEAM:
|
||||
return { ...state, team: action.payload };
|
||||
case actionTypes.SET_FACTORS:
|
||||
return { ...state, factors: action.payload };
|
||||
case actionTypes.SET_TAGS:
|
||||
return { ...state, tags: action.payload };
|
||||
case actionTypes.SET_OPEN_FACTOR_PICKER:
|
||||
return { ...state, openFactorPicker: action.payload };
|
||||
case actionTypes.SET_SELECTED_TEAM:
|
||||
return { ...state, selectedTeam: action.payload };
|
||||
case actionTypes.SET_SELECTED_FACTOR:
|
||||
return { ...state, selectedFactor: action.payload };
|
||||
case actionTypes.SET_SELECTED_TAG:
|
||||
return { ...state, selectedTag: action.payload };
|
||||
case actionTypes.SET_RCA:
|
||||
return { ...state, rca: action.payload };
|
||||
case actionTypes.RESET_STATE:
|
||||
return {
|
||||
...state,
|
||||
selectedTeam: [],
|
||||
selectedFactor: [],
|
||||
selectedTag: [],
|
||||
rca: '',
|
||||
jiraLinks: [''],
|
||||
openFactorPicker: false,
|
||||
};
|
||||
case actionTypes.ADD_JIRA_LINK:
|
||||
return { ...state, jiraLinks: [...state.jiraLinks, ''] };
|
||||
case actionTypes.UPDATE_JIRA_LINK: {
|
||||
const { index, value } = action.payload;
|
||||
const updatedLinks = [...state.jiraLinks];
|
||||
updatedLinks[index] = value;
|
||||
return { ...state, jiraLinks: updatedLinks };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
325
src/Pages/Incidents/ResolveForm/index.tsx
Normal file
325
src/Pages/Incidents/ResolveForm/index.tsx
Normal file
@@ -0,0 +1,325 @@
|
||||
import React, { useEffect, MutableRefObject } from 'react';
|
||||
import {
|
||||
BorderedInput,
|
||||
Button,
|
||||
TextArea,
|
||||
Typography,
|
||||
} from '@navi/web-ui/lib/primitives';
|
||||
import { toast } from '@navi/web-ui/lib/primitives/Toast';
|
||||
import { AddIcon, ArrowDownSolidIcon } from '@navi/web-ui/lib/icons';
|
||||
import { AutoComplete, SelectPicker } from '@navi/web-ui/lib/components';
|
||||
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
|
||||
import ErrorBoundary from '@src/components/ErrorBoundary/ErrorBoundary';
|
||||
import useOutsideClick from '@src/hooks/useOutsideClick';
|
||||
import useClickStream from '@src/services/clickStream';
|
||||
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
|
||||
import { ApiService } from '@src/services/api';
|
||||
import LoadingIcon from '@src/assets/LoadingIcon';
|
||||
import { ResolveFormProps } from './constants';
|
||||
import {
|
||||
reducer,
|
||||
actionTypes,
|
||||
initialState,
|
||||
FETCH_RESOLVE_CONFIG,
|
||||
RESOLVE_INCIDENTS,
|
||||
} from './constants';
|
||||
import styles from './ResolveForm.module.scss';
|
||||
import useIncidentApis from '../useIncidentApis';
|
||||
|
||||
const ResolveForm: React.FC<ResolveFormProps> = ({
|
||||
handleDrawerClose,
|
||||
incidentId,
|
||||
}) => {
|
||||
const [state, dispatch] = React.useReducer(reducer, initialState);
|
||||
const { startIncidentSearch } = useIncidentApis();
|
||||
const { fireEvent } = useClickStream();
|
||||
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
|
||||
const getData = () => {
|
||||
ApiService.get(FETCH_RESOLVE_CONFIG)
|
||||
.then(response => {
|
||||
const apiResponse = response?.data?.data;
|
||||
if (!apiResponse) {
|
||||
toast.error('Something went wrong. Please try again later');
|
||||
return;
|
||||
}
|
||||
dispatch({
|
||||
type: actionTypes.SET_TEAM,
|
||||
payload: apiResponse.tags[0].tag_values,
|
||||
});
|
||||
dispatch({
|
||||
type: actionTypes.SET_FACTORS,
|
||||
payload: apiResponse.tags[1].tag_values,
|
||||
});
|
||||
dispatch({
|
||||
type: actionTypes.SET_TAGS,
|
||||
payload: apiResponse.tags[2].tag_values,
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
const toastMessage = error?.response?.data?.error?.message
|
||||
? `${error?.response?.data?.error?.message},`
|
||||
: '';
|
||||
toast.error(toastMessage);
|
||||
});
|
||||
};
|
||||
const business_options = state.team.map(team => ({
|
||||
label: team.tag_value_name,
|
||||
value: team.tag_value_id,
|
||||
}));
|
||||
const factor_options = state.factors.map(factor => ({
|
||||
label: factor.tag_value_name,
|
||||
value: factor.tag_value_id,
|
||||
}));
|
||||
const tag_options = state.tags.map(tag => ({
|
||||
label: tag.tag_value_name,
|
||||
value: tag.tag_value_id,
|
||||
}));
|
||||
const factor_ref = useOutsideClick({
|
||||
callback: () => {
|
||||
dispatch({ type: actionTypes.SET_OPEN_FACTOR_PICKER, payload: false });
|
||||
},
|
||||
}) as MutableRefObject<HTMLDivElement>;
|
||||
|
||||
const handleAddJiraLink = (): void => {
|
||||
dispatch({ type: actionTypes.ADD_JIRA_LINK });
|
||||
};
|
||||
|
||||
const handleJiraLinkChange = (index, value): void => {
|
||||
dispatch({ type: actionTypes.UPDATE_JIRA_LINK, payload: { index, value } });
|
||||
};
|
||||
|
||||
const handleFactorClick = (): void => {
|
||||
dispatch({
|
||||
type: actionTypes.SET_OPEN_FACTOR_PICKER,
|
||||
payload: !state.openFactorPicker,
|
||||
});
|
||||
};
|
||||
const handleTeamChange = (
|
||||
val: SelectPickerOptionProps | SelectPickerOptionProps[],
|
||||
): void => {
|
||||
dispatch({ type: actionTypes.SET_SELECTED_TEAM, payload: val });
|
||||
};
|
||||
|
||||
const handleFactorChange = (
|
||||
val: SelectPickerOptionProps | SelectPickerOptionProps[],
|
||||
): void => {
|
||||
dispatch({ type: actionTypes.SET_SELECTED_FACTOR, payload: val });
|
||||
dispatch({ type: actionTypes.SET_OPEN_FACTOR_PICKER, payload: false });
|
||||
};
|
||||
const handleTagsChange = (
|
||||
val: SelectPickerOptionProps | SelectPickerOptionProps[],
|
||||
): void => {
|
||||
dispatch({ type: actionTypes.SET_SELECTED_TAG, payload: val });
|
||||
};
|
||||
const handleRCAchange = (e: React.ChangeEvent<HTMLTextAreaElement>): void => {
|
||||
dispatch({ type: actionTypes.SET_RCA, payload: e.target.value });
|
||||
};
|
||||
const clearTags = (): void => {
|
||||
dispatch({ type: actionTypes.SET_SELECTED_TAG, payload: [] });
|
||||
};
|
||||
const clearTeam = (): void => {
|
||||
dispatch({ type: actionTypes.SET_SELECTED_TEAM, payload: [] });
|
||||
};
|
||||
|
||||
const isDisabled = () => {
|
||||
return (
|
||||
state.selectedTeam.length === 0 ||
|
||||
state.selectedFactor.length === 0 ||
|
||||
!(state.rca && state.rca.trim())
|
||||
);
|
||||
};
|
||||
|
||||
const buildRequestPayload = () => {
|
||||
const { selectedTeam, selectedFactor, selectedTag, rca, jiraLinks } = state;
|
||||
const validJiraLinks = jiraLinks
|
||||
.map(link => link.trim())
|
||||
.filter(link => link !== '');
|
||||
|
||||
return {
|
||||
incident_id: incidentId,
|
||||
business_affected: selectedTeam?.map(item => item?.value) || [],
|
||||
contributing_factors: selectedFactor?.value,
|
||||
additional_tags: selectedTag?.map(item => item?.value) || [],
|
||||
rca_summary: rca.trim() || '',
|
||||
jira_links: validJiraLinks || [],
|
||||
};
|
||||
};
|
||||
|
||||
const handleResolveIncident = () => {
|
||||
fireEvent(EVENT_NAME.Houston_Resolve_Incident_submit, {
|
||||
screen_name: SCREEN_NAME.INCIDENT_PAGE,
|
||||
});
|
||||
const endPoint = RESOLVE_INCIDENTS;
|
||||
const requestPayload = buildRequestPayload();
|
||||
toast('Updating ticket. Please wait a moment.', {
|
||||
icon: <LoadingIcon />,
|
||||
});
|
||||
ApiService.post(endPoint, requestPayload)
|
||||
.then(response => {
|
||||
if (response?.status === 200) {
|
||||
const toastMessage = response?.data?.message
|
||||
? `${response?.data?.message}`
|
||||
: 'Incident resolved successfully';
|
||||
toast.success(toastMessage);
|
||||
handleDrawerClose();
|
||||
startIncidentSearch(incidentId?.toString() || '');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
const toastMessage = `${
|
||||
error?.response?.data?.error?.message
|
||||
? `${error?.response?.data?.error?.message}`
|
||||
: 'Something went wrong. Please try again.'
|
||||
}`;
|
||||
toast.error(toastMessage);
|
||||
startIncidentSearch(incidentId?.toString() || '');
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, []);
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<div>
|
||||
<div className={styles['form-wrapper']}>
|
||||
<div className={styles['Team-wrapper']}>
|
||||
<Typography variant="p3">Business affected</Typography>
|
||||
<div>
|
||||
<AutoComplete
|
||||
limitChipThreshold={2}
|
||||
options={business_options}
|
||||
updateSelectedOptions={handleTeamChange}
|
||||
selectedOptions={state.selectedTeam?.map(item => item?.value)}
|
||||
updateOnChipRemoval={handleTeamChange}
|
||||
updateClearAllCallback={clearTeam}
|
||||
variant="bordered"
|
||||
placeholder=""
|
||||
persistMenuOnSelect
|
||||
containerClassName={styles['autocomplete']}
|
||||
dropdownIconContainerClass={styles['arrow-dropdown']}
|
||||
enableSelectedOptionSorting
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['Factor-wrapper']} ref={factor_ref}>
|
||||
<Typography variant="p3" className={styles['factor-label']}>
|
||||
Contributing factor
|
||||
</Typography>
|
||||
<div className={styles['select-div']} onClick={handleFactorClick}>
|
||||
<div className={styles['select-team']}>
|
||||
<Typography
|
||||
variant="p3"
|
||||
color={
|
||||
state.selectedFactor.length === 0
|
||||
? 'var(--navi-color-gray-c2)'
|
||||
: 'var(--navi-color-gray-c1)'
|
||||
}
|
||||
>
|
||||
{state.selectedFactor.length === 0
|
||||
? ''
|
||||
: ` ${state.selectedFactor.label}`}
|
||||
</Typography>
|
||||
<ArrowDownSolidIcon
|
||||
color="var(--navi-color-gray-c3)"
|
||||
className={styles['arrow-down']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['select-picker-style']}>
|
||||
{state.openFactorPicker && (
|
||||
<div className={styles['select-picker']}>
|
||||
<SelectPicker
|
||||
options={factor_options}
|
||||
onSelectionChange={handleFactorChange}
|
||||
multiSelect={false}
|
||||
showSearchBar={false}
|
||||
wrapperClasses={styles['select-picker-item']}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['Tag-wrapper']}>
|
||||
<Typography variant="p3"> Additional tags (optional)</Typography>
|
||||
<div>
|
||||
<AutoComplete
|
||||
limitChipThreshold={1}
|
||||
options={tag_options}
|
||||
updateClearAllCallback={clearTags}
|
||||
updateSelectedOptions={handleTagsChange}
|
||||
selectedOptions={state.selectedTag?.map(item => item?.value)}
|
||||
updateOnChipRemoval={handleTagsChange}
|
||||
variant="bordered"
|
||||
persistMenuOnSelect
|
||||
containerClassName={styles['autocomplete']}
|
||||
dropdownIconContainerClass={styles['arrow-dropdown']}
|
||||
autoCompletePickerWrapper={styles['autocomplete-picker']}
|
||||
enableSelectedOptionSorting
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles['RCA-wrapper']}>
|
||||
<Typography variant="p3">RCA </Typography>
|
||||
<TextArea
|
||||
name="title"
|
||||
placeholder="Enter RCA"
|
||||
containerClassName={styles.textarea}
|
||||
rows={3}
|
||||
onChange={handleRCAchange}
|
||||
value={state.rca}
|
||||
size="medium"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles['jira-wrapper']}>
|
||||
<Typography variant="p3" className={styles['jira']}>
|
||||
Jira tickets (optional)
|
||||
</Typography>
|
||||
{state.jiraLinks?.map((link, index) => (
|
||||
<BorderedInput
|
||||
key={index}
|
||||
placeholder="Enter Jira ticket"
|
||||
value={link}
|
||||
containerClassName={styles.textarea}
|
||||
onChange={e => handleJiraLinkChange(index, e.target.value)}
|
||||
hintMsg="Please enter jira link"
|
||||
/>
|
||||
))}
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={handleAddJiraLink}
|
||||
startAdornment={<AddIcon color="var(--navi-color-blue-base)" />}
|
||||
className={styles['add-jira-link']}
|
||||
>
|
||||
Add Jira link
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['footer-wrapper']}>
|
||||
<div className={styles['button-wrapper']}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
className={styles['cancel']}
|
||||
fullWidth
|
||||
onClick={handleDrawerClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="primary"
|
||||
fullWidth
|
||||
className={styles['resolve']}
|
||||
onClick={handleResolveIncident}
|
||||
disabled={isDisabled()}
|
||||
>
|
||||
Resolve incident
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
export default ResolveForm;
|
||||
8
src/Pages/Incidents/ResolveForm/mixins.scss
Normal file
8
src/Pages/Incidents/ResolveForm/mixins.scss
Normal file
@@ -0,0 +1,8 @@
|
||||
@mixin wrapper-styles {
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
@mixin button-styles {
|
||||
cursor: pointer;
|
||||
height: 36px;
|
||||
}
|
||||
@@ -61,6 +61,7 @@ export const actionTypes = {
|
||||
SET_INCIDENT_NAME: 'SET_INCIDENT_NAME',
|
||||
SET_ERROR_MSG: 'SET_ERROR_MSG',
|
||||
RESET_DUPLICATE_DIALOG: 'RESET_DUPLICATE_DIALOG',
|
||||
SET_IS_INCIDENT_RESOLVED: 'SET_IS_INCIDENT_RESOLVED',
|
||||
};
|
||||
|
||||
export const reducer = (state, action) => {
|
||||
@@ -114,6 +115,8 @@ export const reducer = (state, action) => {
|
||||
incidentName: '',
|
||||
errorMsg: '',
|
||||
};
|
||||
case actionTypes.SET_IS_INCIDENT_RESOLVED:
|
||||
return { ...state, isIncidentResolved: action.payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -141,6 +144,7 @@ export const initialState = {
|
||||
incidentName: '',
|
||||
openDuplicateDialog: false,
|
||||
errorMsg: '',
|
||||
isIncidentResolved: false,
|
||||
};
|
||||
|
||||
export const RESOLVE_STATUS = '4';
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
|
||||
const useIncidentApis = (): useIncidentApiProps => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleApiError = error => {
|
||||
const toastMessage = `${
|
||||
error?.response?.data?.error?.message
|
||||
@@ -102,6 +101,7 @@ const useIncidentApis = (): useIncidentApiProps => {
|
||||
if (response?.status === 200) {
|
||||
const toastMessage = `This incident is marked as duplicate of _houston-${duplicateOfId}`;
|
||||
toast.success(toastMessage);
|
||||
dispatch(setOpenDialogDuplicate(false));
|
||||
startIncidentSearch(incidentId);
|
||||
dispatch(setOpenDialogDuplicate(false));
|
||||
}
|
||||
|
||||
@@ -149,6 +149,7 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
|
||||
onPageChange={handlePageNumberChange}
|
||||
onPageSizeChange={handlePageSizeChange}
|
||||
containerClasses={styles['search-list-table-pagination']}
|
||||
pageSizeOptions={[10, 20, 50]}
|
||||
/>
|
||||
}
|
||||
columnDefs={columnData}
|
||||
|
||||
@@ -22,6 +22,8 @@ const EVENT_NAME = {
|
||||
Houston_Create_Team_Initiate: 'Houston_Create_Team_Initiate',
|
||||
Houston_Create_Incident_initiate: 'Houston_Create_Incident_initiate',
|
||||
Houston_Create_Incident_submit: 'Houston_Create_Incident_submit',
|
||||
Houston_Resolve_Incident_initiate: 'Houston_Resolve_Incident_initiate',
|
||||
Houston_Resolve_Incident_submit: 'Houston_Resolve_Incident_submit',
|
||||
};
|
||||
|
||||
const SCREEN_NAME = {
|
||||
|
||||
Reference in New Issue
Block a user