diff --git a/src/Pages/Incidents/Incidents.module.scss b/src/Pages/Incidents/Incidents.module.scss index 62fbb55..08b93d8 100644 --- a/src/Pages/Incidents/Incidents.module.scss +++ b/src/Pages/Incidents/Incidents.module.scss @@ -15,7 +15,20 @@ .audit-log { padding-right: 20px; } - +.info-icon { + height: 20px; + width: 20px; + margin-left: 4px; + display: flex; + align-items: center; + :hover { + cursor: pointer; + } +} +.alert-icon { + margin-top: 4px; + padding-bottom: 1px; +} .tab-content-wrapper { margin-top: 13px; margin-left: 24px; @@ -24,6 +37,7 @@ .log-update-text { margin-top: 16px; + display: flex; } .log-update-dropdown { @@ -63,6 +77,21 @@ border: 1px solid var(--navi-color-gray-bg-secondary); } +.dropdown-disabled { + margin-top: 8px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; + padding: 4px 8px; + background-color: var(--navi-color-gray-bg-primary); + border-radius: 4px; + border: 1px solid var(--navi-color-gray-bg-secondary); +} +.open-box-disabled { + border: 1px solid var(--navi-color-gray-bg-secondary); + background: #fff; +} .open-box { border: 1px solid var(--navi-color-blue-base); background: var(--navi-color-gray-bg-primary); diff --git a/src/Pages/Incidents/constants.ts b/src/Pages/Incidents/constants.ts index e949af5..4b564f7 100644 --- a/src/Pages/Incidents/constants.ts +++ b/src/Pages/Incidents/constants.ts @@ -30,6 +30,7 @@ export const LINK_JIRA_INCIDENT = `${window?.config?.BASE_API_URL}/houston/link- export const UNLINK_JIRA_INCIDENT = `${window?.config?.BASE_API_URL}/houston/unlink-jira-from-incident`; +export const SLACK_BASE_URL = 'https://go-navi.slack.com/'; export const FETCH_AUDIT_LOG = (incidentId: string): string => { return `${window?.config?.BASE_API_URL}/houston/logs/incident/${incidentId}`; }; diff --git a/src/Pages/Incidents/index.tsx b/src/Pages/Incidents/index.tsx index d56cf52..e0765b6 100644 --- a/src/Pages/Incidents/index.tsx +++ b/src/Pages/Incidents/index.tsx @@ -1,11 +1,12 @@ import { FC, useEffect, useState, useReducer, MutableRefObject } from 'react'; import { useMatch } from 'react-router-dom'; +import classnames from 'classnames'; import { toast } from '@navi/web-ui/lib/primitives/Toast'; -import { ArrowDownIcon } from '@navi/web-ui/lib/icons'; +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, Typography } from '@navi/web-ui/lib/primitives'; +import { ModalDialog, Tooltip, Typography } 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'; @@ -30,6 +31,7 @@ import { SeverityType, StatusType, TeamType, + SLACK_BASE_URL, } from './constants'; import styles from './Incidents.module.scss'; @@ -39,7 +41,9 @@ const Incident: FC = () => { const updatedSeverities = generateOptions(state.headerData?.severities); const updatedStatuses = generateOptions(state.headerData?.incidentStatuses); const updatedTeams = generateOptions(state.headerData?.teams); - + const [open, setOpen] = useState(false); + const userData = JSON.parse(localStorage.getItem('user-data') || '{}'); + const userEmail = userData?.emailId || []; const IncidentMatch = useMatch({ end: true, path: '/incident/:incidentId', @@ -61,7 +65,6 @@ const Incident: FC = () => { map[Incidentteam.value] = Incidentteam.label; return map; }, {}); - const handleSevClickOutside = () => { dispatch({ type: actionTypes.SET_IS_SEVERITY_PICKER_OPEN, @@ -82,7 +85,6 @@ const Incident: FC = () => { payload: false, }); }; - const refStatus = useOutsideClick({ callback: handleStatusClickOutside, }) as MutableRefObject; @@ -231,6 +233,15 @@ const Incident: FC = () => { }); }; + const participants = state.incidentParticipants?.participants; + const others = state.incidentParticipants?.others; + + const participantsList = (participants || []).concat(others || []); + // check if user email id lies in participantsList array + const isUserParticipantList = participantsList?.some( + (participant: any) => participant.email === userEmail, + ); + const updateIncident = (payload: any): void => { const endPoint = UPDATE_INCIDENT; ApiService.post(endPoint, payload) @@ -269,7 +280,59 @@ const Incident: FC = () => { payload: !state.isTeamPickerOpen, }); }; + const combinedSevClassNames = classnames( + styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'], + { + [styles['open-box']]: state.isSeverityPickerOpen, + [styles['open-box-disabled']]: + state.isSeverityPickerOpen && !isUserParticipantList, + }, + ); + const combinedStatusClassNames = classnames( + styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'], + { + [styles['open-box']]: state.isStatusPickerOpen, + [styles['open-box-disabled']]: + state.isStatusPickerOpen && !isUserParticipantList, + }, + ); + const combinedTeamClassNames = classnames( + styles[isUserParticipantList ? 'dropdown-box' : 'dropdown-disabled'], + { + [styles['open-box']]: state.isTeamPickerOpen, + [styles['open-box-disabled']]: + state.isTeamPickerOpen && !isUserParticipantList, + }, + ); + const handleDisabledDropdownClick = (): void => { + setOpen(true); + }; + const closeModal = (): void => { + setOpen(false); + }; + + const handleSevClick = () => { + if (isUserParticipantList) { + handleSeverityDropdownClick(); + } else { + handleDisabledDropdownClick(); + } + }; + const handleStatusClick = () => { + if (isUserParticipantList) { + handleStatusDropdownClick(); + } else { + handleDisabledDropdownClick(); + } + }; + const handleTeamClick = () => { + if (isUserParticipantList) { + handleTeamDropdownClick(); + } else { + handleDisabledDropdownClick(); + } + }; const handleSeveritySelectionChange = ( selectedOption: SelectPickerOptionProps | SelectPickerOptionProps[], ): void => { @@ -400,8 +463,7 @@ const Incident: FC = () => { }; const handleGoToSlackChannel = () => { - console.log('hello'); - const slackChannelURL = `https://go-navi.slack.com/archives/${state.incidentData?.slackChannel}`; + const slackChannelURL = `${SLACK_BASE_URL}/archives/${state.incidentData?.slackChannel}`; window.open(slackChannelURL, '_blank'); dispatch({ type: actionTypes.SET_OPEN_DIALOG, @@ -462,6 +524,19 @@ const Incident: FC = () => { > UPDATE INCIDENT + {!isUserParticipantList && ( +
+ +
+ +
+
+
+ )}
@@ -476,17 +551,17 @@ const Incident: FC = () => {
{severityMap && state.severity?.value ? severityMap[state.severity.value] @@ -531,15 +606,17 @@ const Incident: FC = () => {
{incidentStatusMap && state.status?.value ? incidentStatusMap[state.status.value] @@ -581,15 +658,17 @@ const Incident: FC = () => {
{teamsMap && state.team?.value ? teamsMap[state.team.value] @@ -603,6 +682,7 @@ const Incident: FC = () => { />
+
{state.isTeamPickerOpen && (
{ /> }
+ {
-
+ {open && ( + , + onClick: handleGoToSlackChannel, + }, + ]} + header="You are not authorised to update this incident" + onClose={closeModal} + > + + You must be a participant of this incident to update it. Please + join the Slack channel to be added a participant + + + )} + {state.openDialog ? ( { { label: 'Go to slack channel', onClick: handleGoToSlackChannel, - startAdornment: , + startAdornment: , }, ]} header={`${state.dialogText}`} @@ -674,62 +778,64 @@ const Incident: FC = () => { mark this incident as {`${state.dialogBodyText}`} on Slack. -
+ ) : null}
- { - dispatch({ - type: actionTypes.SET_OPEN_CONFIRMATION_DIALOG, - payload: false, - }); + {state.openConfirmationDialog ? ( + { + dispatch({ + type: actionTypes.SET_OPEN_CONFIRMATION_DIALOG, + payload: false, + }); + }, }, - }, - { - label: 'Update incident', - onClick: () => { - dispatch({ - type: actionTypes.SET_OPEN_CONFIRMATION_DIALOG, - payload: false, - }); - handleCloseConfirmationDialog(); + { + label: 'Update incident', + onClick: () => { + dispatch({ + type: actionTypes.SET_OPEN_CONFIRMATION_DIALOG, + payload: false, + }); + handleCloseConfirmationDialog(); + }, }, - }, - ]} - header={`Are you sure you want to update the incident?`} - onClose={() => - dispatch({ - type: actionTypes.SET_OPEN_CONFIRMATION_DIALOG, - payload: false, - }) - } - > -
- - You are updating this incident‘s - {getUpdateTypeText(state.updateType)} - from - - {getUpdateValueText()} + ]} + header={`Are you sure you want to update the incident?`} + onClose={() => + dispatch({ + type: actionTypes.SET_OPEN_CONFIRMATION_DIALOG, + payload: false, + }) + } + > +
+ + You are updating this incident‘s + {getUpdateTypeText(state.updateType)} + from + + {getUpdateValueText()} + + to  + + {state.selectedOption?.label || '..'} + - to  - - {state.selectedOption?.label || '..'} - - -
- +
+
+ ) : null}
diff --git a/src/assets/GoToLinkIcon.tsx b/src/assets/GoToLinkIcon.tsx index c0efdd4..9d3dbae 100644 --- a/src/assets/GoToLinkIcon.tsx +++ b/src/assets/GoToLinkIcon.tsx @@ -5,6 +5,7 @@ import { IconProps } from './types'; const GoToLinkIcon: FC = ({ width = '16', height = '16', + color = '#fff', ...restProps }) => { return ( @@ -12,8 +13,9 @@ const GoToLinkIcon: FC = ({ width="20" height="20" viewBox="0 0 20 20" - fill="none" + fill={color} xmlns="http://www.w3.org/2000/svg" + {...restProps} > = ({ width="20" height="20" > - +