TP-48516 | Mark incident as duplicate from Houston UI (#105)
* TP-48516 | design implemented * TP-48516 | updated Goto incident and css changes * TP-48516 | Api integrated * TP-48516 | added input validations , api integration * TP-48516 | Disabled duplicate button * TP-48516 | resolving PR commits * TP-48516 | resolved error message color bug * TP-48516 | added return type * TP-48516 | resolving PR comments * TP-48516 | padding for GoTo CTA increased
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@navi/dark-knight": "^1.0.13",
|
||||
"@navi/web-ui": "^1.58.13",
|
||||
"@navi/web-ui": "^1.59.2",
|
||||
"@reduxjs/toolkit": "^1.9.7",
|
||||
"@stoddabr/react-tableau-embed-live": "^0.3.26",
|
||||
"antd": "^5.9.4",
|
||||
|
||||
@@ -183,3 +183,25 @@
|
||||
.popup-style {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
margin-top: 24px;
|
||||
font-size: 12px;
|
||||
color: var(--navi-color-blue-base);
|
||||
border: none;
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.incident-input {
|
||||
margin-top: 20px;
|
||||
input {
|
||||
color: var(--navi-color-gray-c2);
|
||||
}
|
||||
}
|
||||
|
||||
.incident-label {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export const IncidentConstants = {
|
||||
incidentId: 'Incident Id',
|
||||
};
|
||||
|
||||
const URL_PREFIX = createURL('/houston');
|
||||
export const URL_PREFIX = createURL('/houston');
|
||||
|
||||
export const FETCH_INCIDENT_DATA = (payload: any): string => {
|
||||
return `${URL_PREFIX}/incidents/${payload}`;
|
||||
@@ -38,6 +38,7 @@ export const FETCH_AUDIT_LOG = (incidentId: string): string => {
|
||||
return `${URL_PREFIX}/logs/incident/${incidentId}`;
|
||||
};
|
||||
|
||||
export const incidentRegrex = /^_houston-0*[1-9][0-9]*$/;
|
||||
export interface ContentProps {
|
||||
incidentData: any;
|
||||
}
|
||||
@@ -64,7 +65,10 @@ export interface CreatedInfoProps {
|
||||
updatedAt: string;
|
||||
isLastItem: boolean;
|
||||
}
|
||||
|
||||
export interface ResponseType {
|
||||
data: '';
|
||||
status: number;
|
||||
}
|
||||
export const actionTypes = {
|
||||
SET_INCIDENT_DATA: 'SET_INCIDENT_DATA',
|
||||
SET_HEADER_DATA: 'SET_HEADER_DATA',
|
||||
@@ -84,6 +88,10 @@ export const actionTypes = {
|
||||
SET_IS_SEVERITY_PICKER_OPEN: 'SET_IS_SEVERITY_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',
|
||||
SET_INCIDENT_NAME: 'SET_INCIDENT_NAME',
|
||||
SET_ERROR_MSG: 'SET_ERROR_MSG',
|
||||
RESET_DUPLICATE_DIALOG: 'RESET_DUPLICATE_DIALOG',
|
||||
};
|
||||
|
||||
export const reducer = (state, action) => {
|
||||
@@ -108,6 +116,8 @@ export const reducer = (state, action) => {
|
||||
return { ...state, totalLog: action.payload };
|
||||
case actionTypes.SET_OPEN_DIALOG:
|
||||
return { ...state, openDialog: action.payload };
|
||||
case actionTypes.SET_DUPLICATE_DIALOG:
|
||||
return { ...state, openDuplicateDialog: action.payload };
|
||||
case actionTypes.SET_OPEN_CONFIRMATION_DIALOG:
|
||||
return { ...state, openConfirmationDialog: action.payload };
|
||||
case actionTypes.SET_SELECTED_OPTION:
|
||||
@@ -124,6 +134,17 @@ 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_INCIDENT_NAME:
|
||||
return { ...state, incidentName: action.payload };
|
||||
case actionTypes.SET_ERROR_MSG:
|
||||
return { ...state, errorMsg: action.payload };
|
||||
case actionTypes.RESET_DUPLICATE_DIALOG:
|
||||
return {
|
||||
...state,
|
||||
openDuplicateDialog: false,
|
||||
incidentName: '',
|
||||
errorMsg: '',
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -148,6 +169,9 @@ export const initialState = {
|
||||
isSeverityPickerOpen: false,
|
||||
isStatusPickerOpen: false,
|
||||
isTeamPickerOpen: false,
|
||||
incidentName: '',
|
||||
openDuplicateDialog: false,
|
||||
errorMsg: '',
|
||||
};
|
||||
|
||||
export const RESOLVE_STATUS = '4';
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { FC, useEffect, useState, useReducer, MutableRefObject } from 'react';
|
||||
import { useMatch } from 'react-router-dom';
|
||||
import classnames from 'classnames';
|
||||
import { Tabs } from 'antd';
|
||||
import { toast } from '@navi/web-ui/lib/primitives/Toast';
|
||||
import { AlertOutlineIcon, ArrowDownIcon } from '@navi/web-ui/lib/icons';
|
||||
import TabItem from '@navi/web-ui/lib-esm/components/Tabs/TabItem';
|
||||
import Tabs from '@navi/web-ui/lib-esm/components/Tabs/Tabs';
|
||||
import { SelectPicker } from '@navi/web-ui/lib/components';
|
||||
import { ModalDialog, Tooltip, Typography } from '@navi/web-ui/lib/primitives';
|
||||
import {
|
||||
BorderedInput,
|
||||
ModalDialog,
|
||||
Tooltip,
|
||||
Typography,
|
||||
Button,
|
||||
} from '@navi/web-ui/lib/primitives';
|
||||
|
||||
import { SelectPickerOptionProps } from '@navi/web-ui/lib/components/SelectPicker/types';
|
||||
import GoToLinkIcon from '@src/assets/GoToLinkIcon';
|
||||
import { ApiService } from '@src/services/api';
|
||||
@@ -34,15 +40,15 @@ import {
|
||||
StatusType,
|
||||
TeamType,
|
||||
SLACK_BASE_URL,
|
||||
incidentRegrex,
|
||||
ResponseType,
|
||||
} from './constants';
|
||||
import styles from './Incidents.module.scss';
|
||||
|
||||
const Incident: FC = () => {
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
|
||||
const { fireEvent } = useClickStream();
|
||||
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
|
||||
|
||||
const updatedSeverities = generateOptions(state.headerData?.severities);
|
||||
const updatedStatuses = generateOptions(state.headerData?.incidentStatuses);
|
||||
const updatedTeams = generateOptions(state.headerData?.teams);
|
||||
@@ -54,6 +60,8 @@ const Incident: FC = () => {
|
||||
path: '/incident/:incidentId',
|
||||
});
|
||||
const incidentId = IncidentMatch?.params?.incidentId || '';
|
||||
const currentIncidentId = parseInt(incidentId, 10);
|
||||
const incidentName = state.incidentName;
|
||||
|
||||
const severityMap = state.headerData?.severities?.reduce((map, severity) => {
|
||||
map[severity.value] = severity.label;
|
||||
@@ -70,6 +78,7 @@ const Incident: FC = () => {
|
||||
map[Incidentteam.value] = Incidentteam.label;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
const handleSevClickOutside = () => {
|
||||
dispatch({
|
||||
type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN,
|
||||
@@ -376,16 +385,6 @@ const Incident: FC = () => {
|
||||
payload: 'resolved',
|
||||
});
|
||||
dispatch({ type: actionTypes.SET_OPEN_DIALOG, payload: true });
|
||||
} else if (value === DUPLICATE_STATUS) {
|
||||
dispatch({
|
||||
type: actionTypes.SET_DIALOG_TEXT,
|
||||
payload: 'Duplicate incident',
|
||||
});
|
||||
dispatch({
|
||||
type: actionTypes.SET_DIALOG_BODY_TEXT,
|
||||
payload: 'duplicate',
|
||||
});
|
||||
dispatch({ type: actionTypes.SET_OPEN_DIALOG, payload: true });
|
||||
} else {
|
||||
toast('Updating ticket. Please wait a moment.', {
|
||||
icon: <LoadingIcon />,
|
||||
@@ -436,11 +435,16 @@ const Incident: FC = () => {
|
||||
payload: false,
|
||||
});
|
||||
dispatch({ type: actionTypes.SET_IS_TEAM_PICKER_OPEN, payload: false });
|
||||
if (
|
||||
updateType === StatusType &&
|
||||
(selectedvalue === RESOLVE_STATUS || selectedvalue === DUPLICATE_STATUS)
|
||||
) {
|
||||
if (updateType === StatusType && selectedvalue === RESOLVE_STATUS) {
|
||||
handleStatusSelectionChange(selectedOption);
|
||||
} else if (
|
||||
updateType === StatusType &&
|
||||
selectedvalue === DUPLICATE_STATUS
|
||||
) {
|
||||
dispatch({
|
||||
type: actionTypes.SET_DUPLICATE_DIALOG,
|
||||
payload: true,
|
||||
});
|
||||
} else {
|
||||
dispatch({ type: actionTypes.SET_UPDATE_TYPE, payload: updateType });
|
||||
dispatch({
|
||||
@@ -508,6 +512,81 @@ const Incident: FC = () => {
|
||||
} `;
|
||||
}
|
||||
};
|
||||
const handleIncidentChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement>,
|
||||
): void => {
|
||||
const inputValue = e.target.value;
|
||||
validateIncidentID(inputValue);
|
||||
dispatch({
|
||||
type: actionTypes.SET_INCIDENT_NAME,
|
||||
payload: inputValue,
|
||||
});
|
||||
};
|
||||
const handleResetDialog = (): void => {
|
||||
dispatch({
|
||||
type: actionTypes.RESET_DUPLICATE_DIALOG,
|
||||
});
|
||||
};
|
||||
const validateIncidentID = (value: string): void => {
|
||||
dispatch({
|
||||
type: actionTypes.SET_ERROR_MSG,
|
||||
payload: !incidentRegrex.test(value)
|
||||
? 'Please enter a valid incident I.D.'
|
||||
: '',
|
||||
});
|
||||
};
|
||||
|
||||
const extractIncidentId = (incidentName: string): number | null => {
|
||||
return (match => (match ? parseInt(match[1], 10) : null))(
|
||||
incidentName.match(/_houston-(\d+)/),
|
||||
);
|
||||
};
|
||||
const duplicateOfId = extractIncidentId(incidentName);
|
||||
const disable = (): boolean => {
|
||||
return !incidentName || !validate(incidentName);
|
||||
};
|
||||
const goToIncident = (): void => {
|
||||
if (state.incidentName) {
|
||||
const incidentId = extractIncidentId(state.incidentName);
|
||||
window.open(`/incident/${incidentId}`, '_blank');
|
||||
}
|
||||
};
|
||||
const validate = (value: string): boolean => incidentRegrex.test(value);
|
||||
const isDisabled = (): boolean => {
|
||||
const incidentId = extractIncidentId(state.incidentName);
|
||||
return !incidentId;
|
||||
};
|
||||
|
||||
const markDuplicateIncident = (): void => {
|
||||
const endPoint = UPDATE_INCIDENT;
|
||||
toast('Updating ticket. Please wait a moment.', {
|
||||
icon: <LoadingIcon />,
|
||||
});
|
||||
ApiService.post(endPoint, {
|
||||
id: currentIncidentId,
|
||||
status: DUPLICATE_STATUS,
|
||||
duplicateOfId: duplicateOfId,
|
||||
})
|
||||
.then((response: ResponseType) => {
|
||||
if (response?.status === 200) {
|
||||
const toastMessage = `This incident is marked as duplicate of _houston-${duplicateOfId}`;
|
||||
toast.success(toastMessage);
|
||||
startIncidentSearch();
|
||||
fetchIncidentLog();
|
||||
handleResetDialog();
|
||||
fetchParticipants();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
const toastMessage = `${
|
||||
error?.response?.data?.error?.message
|
||||
? `${error?.response?.data?.error?.message}`
|
||||
: 'Something went wrong. Please try again.'
|
||||
}`;
|
||||
toast.error(toastMessage);
|
||||
startIncidentSearch();
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
@@ -521,222 +600,232 @@ const Incident: FC = () => {
|
||||
|
||||
<div className={styles['tab-content-wrapper']}>
|
||||
<Tabs
|
||||
onTabChange={function noRefCheck() {}}
|
||||
defaultSelectedKey={'detail-key'}
|
||||
>
|
||||
<TabItem label="Details" key="detail-key">
|
||||
<div className={styles['horizontal-line']}>
|
||||
<div className={styles['content-wrapper']}>
|
||||
<div className={styles['audit-log']}>
|
||||
<div className={styles['log-update-text']}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="var(--navi-color-gray-c3)"
|
||||
>
|
||||
UPDATE INCIDENT
|
||||
</Typography>
|
||||
{!isUserParticipantList && (
|
||||
<div className={styles['info-icon']}>
|
||||
<Tooltip
|
||||
text="Only Slack channel participants can update this incident."
|
||||
withPointer
|
||||
position={'right'}
|
||||
>
|
||||
<div className={styles['alert-icon']}>
|
||||
<AlertOutlineIcon />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles['log-update-dropdown']}>
|
||||
<div className={styles['dropdown-severity']}>
|
||||
<div>
|
||||
defaultActiveKey="1"
|
||||
items={[
|
||||
{
|
||||
key: '1',
|
||||
label: 'Details',
|
||||
children: (
|
||||
<div>
|
||||
<div className={styles['content-wrapper']}>
|
||||
<div className={styles['audit-log']}>
|
||||
<div className={styles['log-update-text']}>
|
||||
<Typography
|
||||
variant="p5"
|
||||
color="var(--navi-color-gray-c2"
|
||||
variant="h6"
|
||||
color="var(--navi-color-gray-c3)"
|
||||
>
|
||||
Severity
|
||||
UPDATE INCIDENT
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refSeverity}>
|
||||
<div
|
||||
className={combinedSevClassNames}
|
||||
onClick={handleSevClick}
|
||||
>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p4"
|
||||
color={
|
||||
isUserParticipantList
|
||||
? 'var(--navi-color-gray-c1)'
|
||||
: 'var(--navi-color-gray-c3)'
|
||||
}
|
||||
{!isUserParticipantList && (
|
||||
<div className={styles['info-icon']}>
|
||||
<Tooltip
|
||||
text="Only Slack channel participants can update this incident."
|
||||
withPointer
|
||||
position={'right'}
|
||||
>
|
||||
{severityMap && state.severity?.value
|
||||
? severityMap[state.severity.value]
|
||||
: '-'}
|
||||
</Typography>
|
||||
<div className={styles['alert-icon']}>
|
||||
<AlertOutlineIcon />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className={styles['arrowdown-style']}>
|
||||
<ArrowDownIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['severity-selectpicker']}>
|
||||
{state.isSeverityPickerOpen && (
|
||||
<div
|
||||
className={
|
||||
styles['severity-selectpicker-style']
|
||||
}
|
||||
>
|
||||
<SelectPicker
|
||||
multiSelect={false}
|
||||
onSelectionChange={selectedOption =>
|
||||
handleOpenConfirmationDailog(
|
||||
selectedOption,
|
||||
SeverityType,
|
||||
)
|
||||
}
|
||||
options={updatedSeverities}
|
||||
selectedValue={state.severity?.value.toString()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['dropdown-status']}>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p5"
|
||||
color="var(--navi-color-gray-c2)"
|
||||
>
|
||||
Status
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refStatus}>
|
||||
<div
|
||||
className={combinedStatusClassNames}
|
||||
onClick={handleStatusClick}
|
||||
>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p4"
|
||||
color={
|
||||
isUserParticipantList
|
||||
? 'var(--navi-color-gray-c1)'
|
||||
: 'var(--navi-color-gray-c3)'
|
||||
}
|
||||
>
|
||||
{incidentStatusMap && state.status?.value
|
||||
? incidentStatusMap[state.status.value]
|
||||
: '-'}
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<ArrowDownIcon
|
||||
className={styles['arrowdown-style']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['status-selectpicker']}>
|
||||
{state.isStatusPickerOpen && (
|
||||
<div
|
||||
className={styles['status-selectpicker-style']}
|
||||
>
|
||||
<SelectPicker
|
||||
multiSelect={false}
|
||||
onSelectionChange={selectedOption =>
|
||||
handleOpenConfirmationDailog(
|
||||
selectedOption,
|
||||
StatusType,
|
||||
)
|
||||
}
|
||||
options={updatedStatuses}
|
||||
selectedValue={state.status?.value.toString()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['dropdown-team']}>
|
||||
<div>
|
||||
<Typography variant="p5" color="#585757">
|
||||
Team
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refTeam}>
|
||||
<div
|
||||
className={combinedTeamClassNames}
|
||||
onClick={handleTeamClick}
|
||||
>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p4"
|
||||
color={
|
||||
isUserParticipantList
|
||||
? 'var(--navi-color-gray-c1)'
|
||||
: 'var(--navi-color-gray-c3)'
|
||||
}
|
||||
>
|
||||
{teamsMap && state.team?.value
|
||||
? teamsMap[state.team.value]
|
||||
: '-'}
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<div className={styles['log-update-dropdown']}>
|
||||
<div className={styles['dropdown-severity']}>
|
||||
<div>
|
||||
<ArrowDownIcon
|
||||
className={styles['arrowdown-style']}
|
||||
/>
|
||||
<Typography
|
||||
variant="p5"
|
||||
color="var(--navi-color-gray-c2"
|
||||
>
|
||||
Severity
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refSeverity}>
|
||||
<div
|
||||
className={combinedSevClassNames}
|
||||
onClick={handleSevClick}
|
||||
>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p4"
|
||||
color={
|
||||
isUserParticipantList
|
||||
? 'var(--navi-color-gray-c1)'
|
||||
: 'var(--navi-color-gray-c3)'
|
||||
}
|
||||
>
|
||||
{severityMap && state.severity?.value
|
||||
? severityMap[state.severity.value]
|
||||
: '-'}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={styles['arrowdown-style']}>
|
||||
<ArrowDownIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['severity-selectpicker']}>
|
||||
{state.isSeverityPickerOpen && (
|
||||
<div
|
||||
className={
|
||||
styles['severity-selectpicker-style']
|
||||
}
|
||||
>
|
||||
<SelectPicker
|
||||
multiSelect={false}
|
||||
onSelectionChange={selectedOption =>
|
||||
handleOpenConfirmationDailog(
|
||||
selectedOption,
|
||||
SeverityType,
|
||||
)
|
||||
}
|
||||
options={updatedSeverities}
|
||||
selectedValue={state.severity?.value.toString()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles['team-selectpicker']}>
|
||||
{state.isTeamPickerOpen && (
|
||||
<div
|
||||
className={styles['team-selectpicker-style']}
|
||||
<div className={styles['dropdown-status']}>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p5"
|
||||
color="var(--navi-color-gray-c2)"
|
||||
>
|
||||
<SelectPicker
|
||||
multiSelect={false}
|
||||
onSelectionChange={selectedOption =>
|
||||
handleOpenConfirmationDailog(
|
||||
selectedOption,
|
||||
TeamType,
|
||||
)
|
||||
}
|
||||
options={updatedTeams}
|
||||
selectedValue={state.team?.value.toString()}
|
||||
/>
|
||||
Status
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refStatus}>
|
||||
<div
|
||||
className={combinedStatusClassNames}
|
||||
onClick={handleStatusClick}
|
||||
>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p4"
|
||||
color={
|
||||
isUserParticipantList
|
||||
? 'var(--navi-color-gray-c1)'
|
||||
: 'var(--navi-color-gray-c3)'
|
||||
}
|
||||
>
|
||||
{incidentStatusMap && state.status?.value
|
||||
? incidentStatusMap[state.status.value]
|
||||
: '-'}
|
||||
</Typography>
|
||||
</div>
|
||||
<div>
|
||||
<ArrowDownIcon
|
||||
className={styles['arrowdown-style']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles['status-selectpicker']}>
|
||||
{state.isStatusPickerOpen && (
|
||||
<div
|
||||
className={
|
||||
styles['status-selectpicker-style']
|
||||
}
|
||||
>
|
||||
<SelectPicker
|
||||
multiSelect={false}
|
||||
onSelectionChange={selectedOption =>
|
||||
handleOpenConfirmationDailog(
|
||||
selectedOption,
|
||||
StatusType,
|
||||
)
|
||||
}
|
||||
options={updatedStatuses}
|
||||
selectedValue={state.status?.value.toString()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['dropdown-team']}>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p5"
|
||||
color="var(--navi-color-gray-c2)"
|
||||
>
|
||||
Team
|
||||
</Typography>
|
||||
</div>
|
||||
<div ref={refTeam}>
|
||||
<div
|
||||
className={combinedTeamClassNames}
|
||||
onClick={handleTeamClick}
|
||||
>
|
||||
<div>
|
||||
<Typography
|
||||
variant="p4"
|
||||
color={
|
||||
isUserParticipantList
|
||||
? 'var(--navi-color-gray-c1)'
|
||||
: 'var(--navi-color-gray-c3)'
|
||||
}
|
||||
>
|
||||
{teamsMap && state.team?.value
|
||||
? teamsMap[state.team.value]
|
||||
: '-'}
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ArrowDownIcon
|
||||
className={styles['arrowdown-style']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles['team-selectpicker']}>
|
||||
{state.isTeamPickerOpen && (
|
||||
<div
|
||||
className={
|
||||
styles['team-selectpicker-style']
|
||||
}
|
||||
>
|
||||
<SelectPicker
|
||||
multiSelect={false}
|
||||
onSelectionChange={selectedOption =>
|
||||
handleOpenConfirmationDailog(
|
||||
selectedOption,
|
||||
TeamType,
|
||||
)
|
||||
}
|
||||
options={updatedTeams}
|
||||
selectedValue={state.team?.value.toString()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ActivityLog
|
||||
incidentLog={state.incidentLog}
|
||||
totalLog={state.totalLog}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
<ActivityLog
|
||||
incidentLog={state.incidentLog}
|
||||
totalLog={state.totalLog}
|
||||
|
||||
<DescriptionContent
|
||||
id={state.incidentData?.id}
|
||||
incidentName={state.incidentData?.incidentName}
|
||||
description={state.incidentData?.description}
|
||||
slackChannel={state.incidentData?.slackChannel}
|
||||
incidentParticipants={state.incidentParticipants}
|
||||
jiraIds={state.incidentData?.jiraLinks}
|
||||
rcaLink={state.incidentData?.rcaLink}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DescriptionContent
|
||||
id={state.incidentData?.id}
|
||||
incidentName={state.incidentData?.incidentName}
|
||||
description={state.incidentData?.description}
|
||||
slackChannel={state.incidentData?.slackChannel}
|
||||
incidentParticipants={state.incidentParticipants}
|
||||
jiraIds={state.incidentData?.jiraLinks}
|
||||
rcaLink={state.incidentData?.rcaLink}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
{open && (
|
||||
<ModalDialog
|
||||
@@ -748,7 +837,9 @@ const Incident: FC = () => {
|
||||
},
|
||||
{
|
||||
label: 'Open Channel',
|
||||
startAdornment: <GoToLinkIcon color="#fff" />,
|
||||
startAdornment: (
|
||||
<GoToLinkIcon color="var(--navi-color-gray-bg-primary)" />
|
||||
),
|
||||
onClick: handleGoToSlackChannel,
|
||||
},
|
||||
]}
|
||||
@@ -761,6 +852,54 @@ const Incident: FC = () => {
|
||||
</Typography>
|
||||
</ModalDialog>
|
||||
)}
|
||||
{state.openDuplicateDialog ? (
|
||||
<ModalDialog
|
||||
open={state.openDuplicateDialog}
|
||||
footerButtons={[
|
||||
{
|
||||
label: 'Cancel',
|
||||
onClick: handleResetDialog,
|
||||
},
|
||||
{
|
||||
label: 'Mark as duplicate',
|
||||
disabled: disable(),
|
||||
onClick: () => {
|
||||
markDuplicateIncident();
|
||||
},
|
||||
},
|
||||
]}
|
||||
header={`Duplicate incident`}
|
||||
onClose={handleResetDialog}
|
||||
>
|
||||
<Typography variant="p3" color="var(--navi-color-gray-c1)">
|
||||
Once marked as duplicate, this incident will be archived after 24
|
||||
hours.
|
||||
</Typography>
|
||||
<div className={styles['incident-input']}>
|
||||
<BorderedInput
|
||||
inputLabel="Attach incident to"
|
||||
labelClassName={styles['incident-label']}
|
||||
fullWidth
|
||||
value={state.incidentName ? state.incidentName : '_houston-'}
|
||||
onChange={handleIncidentChange}
|
||||
error={state.errorMsg}
|
||||
Icon={<AlertOutlineIcon color="var(--navi-color-red-base)" />}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className={styles['hint-text']}
|
||||
variant="text"
|
||||
startAdornment={
|
||||
<GoToLinkIcon color="var(--navi-color-blue-base)" />
|
||||
}
|
||||
disabled={isDisabled()}
|
||||
onClick={goToIncident}
|
||||
>
|
||||
Go to incident
|
||||
</Button>
|
||||
</ModalDialog>
|
||||
) : null}
|
||||
{state.openDialog ? (
|
||||
<ModalDialog
|
||||
open={state.openDialog}
|
||||
@@ -777,7 +916,9 @@ const Incident: FC = () => {
|
||||
{
|
||||
label: 'Go to slack channel',
|
||||
onClick: handleGoToSlackChannel,
|
||||
startAdornment: <GoToLinkIcon color="#fff" />,
|
||||
startAdornment: (
|
||||
<GoToLinkIcon color="var(--navi-color-gray-bg-primary)" />
|
||||
),
|
||||
},
|
||||
]}
|
||||
header={`${state.dialogText}`}
|
||||
|
||||
Reference in New Issue
Block a user