Merge branch 'master' into TP-51166

This commit is contained in:
Pooja Jaiswal
2024-01-22 18:07:28 +05:30
committed by GitHub
15 changed files with 225 additions and 157 deletions

View File

@@ -16,3 +16,4 @@
- [ ] Peer review
- [ ] Font-family / Basic css shouldnt be overridden
- [ ] File changes shouldnt be more than 20-30, if its more than 25 please create a draft PR and share it so it can reviewed properly.
- [ ] add required clickstrean events if neccesary

View File

@@ -1,9 +1,10 @@
import React from 'react';
import { Provider } from 'react-redux';
import { DarkKnightInstance } from '@navi/dark-knight';
import AppRouter from './AppRouter';
import { store } from './store/index';
import FallbackComponent from './components/Fallback';
import React from 'react';
import './variables.scss';
interface AppProps {
auth: DarkKnightInstance;

View File

@@ -54,6 +54,17 @@
width: 458px !important;
}
:export {
sessionId: rgb(88, 87, 87);
.tooltip {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 110px;
}
.tooltipWrapper {
display: flex;
align-items: center;
position: fixed;
z-index: var(--title-z-index);
line-height: 1;
}

View File

@@ -33,13 +33,9 @@
.drawer {
width: 550px !important;
}
.header {
padding: 16px !important;
> span {
@include flex-center;
> div {
padding: 10px 0px 10px 0px !important;
}
}
@@ -58,26 +54,46 @@
margin: 20px 0 0 40px;
}
.create,
.cancel {
@mixin button-styles {
cursor: pointer;
height: 36px;
}
.button-wrapper {
@include button-styles;
width: 231px;
bottom: 0;
position: fixed;
display: flex;
margin-bottom: 24px;
gap: 24px;
border-top: 1px solid var(--navi-drawer-divider-color);
padding-top: 20px;
width: 100%;
}
.create {
width: 242px;
height: 36px;
}
.cancel {
width: 242px;
height: 36px;
margin-left: 20px;
}
.footer-wrapper {
@include flex-center;
margin-top: 380px;
position: relative;
width: 100%;
box-sizing: border-box;
}
.incident-wrapper,
.Description-wrapper,
.severity-picker,
.Team-wrapper {
@include wrapper-styles;
}
.form-wrapper {
margin: 10px 10px 0px 10px;
}
.severity-wrapper {
width: calc(100% - 156px);
width: calc(100% - 163px);
display: flex;
justify-content: flex-start;
align-items: center;
@@ -119,7 +135,7 @@
.select-picker-item {
min-width: 352px;
margin-top: 2px;
margin-left: 14px;
margin-left: 24px;
}
.arrow-down {

View File

@@ -176,106 +176,112 @@ const CreateIncidentForm: React.FC<CreateIncidentFormProps> = ({
return (
<div>
<div className={styles['incident-wrapper']}>
<div className={styles['incident-name']}>Incident title</div>
<TextArea
name="title"
placeholder="Enter incident title"
containerClassName={styles.textarea}
rows={3}
onChange={handleTitleChange as any}
value={state.title}
fullWidth
error={
!state.isTitleValid
? `Title should be less than ${LIMITS.title.max} characters`
: ''
}
size="large"
/>
</div>
<div className={styles['severity-picker']}>
<div className={styles['name-wrapper']}>Choose severity</div>
<div className={styles['severity-wrapper']}>
{state.severity.map((severityOption: SelectPickerOptionProps) => (
<Chip
key={severityOption.value}
label={severityOption.label}
size="medium"
onChipClick={() => handleSeverityChange(severityOption as any)}
selected={severityOption === state.selectedSeverity}
/>
))}
<div className={styles['form-wrapper']}>
<div className={styles['incident-wrapper']}>
<div className={styles['incident-name']}>Incident title</div>
<TextArea
name="title"
placeholder="Enter incident title"
containerClassName={styles.textarea}
rows={3}
onChange={handleTitleChange as any}
value={state.title}
fullWidth
error={
!state.isTitleValid
? `Title should be less than ${LIMITS.title.max} characters`
: ''
}
size="large"
/>
</div>
</div>
<div className={styles['Team-wrapper']}>
<div className={styles['name-wrapper']}>Choose team</div>
<div className={styles['team-div']} onClick={handleDivClick}>
<div className={styles['select-team']}>
<Typography
variant="p3"
color={
state.selectedTeam.length === 0
? 'var(--navi-color-gray-c2)'
: 'var(--navi-color-gray-c1)'
}
>
{state.selectedTeam.length === 0
? 'Select team'
: ` ${state.selectedTeam.label}`}
</Typography>
<ArrowDownSolidIcon
color="var(--navi-color-gray-c3)"
className={styles['arrow-down']}
/>
<div className={styles['severity-picker']}>
<div className={styles['name-wrapper']}>Choose severity</div>
<div className={styles['severity-wrapper']}>
{state.severity.map((severityOption: SelectPickerOptionProps) => (
<Chip
key={severityOption.value}
label={severityOption.label}
size="medium"
onChipClick={() => handleSeverityChange(severityOption as any)}
selected={severityOption === state.selectedSeverity}
/>
))}
</div>
</div>
<div className={styles['select-picker-style']}>
{state.openSelect && (
<div className={styles['select-picker']} ref={ref}>
<SelectPicker
options={getTeams(state.teams)}
placeholder="Select team"
onSelectionChange={handleTeamChange}
multiSelect={false}
showSearchBar
wrapperClasses={styles['select-picker-item']}
<div className={styles['Team-wrapper']}>
<div className={styles['name-wrapper']}>Choose team</div>
<div className={styles['team-div']} onClick={handleDivClick}>
<div className={styles['select-team']}>
<Typography
variant="p3"
color={
state.selectedTeam.length === 0
? 'var(--navi-color-gray-c2)'
: 'var(--navi-color-gray-c1)'
}
>
{state.selectedTeam.length === 0
? 'Select team'
: ` ${state.selectedTeam.label}`}
</Typography>
<ArrowDownSolidIcon
color="var(--navi-color-gray-c3)"
className={styles['arrow-down']}
/>
</div>
)}
</div>
<div className={styles['select-picker-style']} ref={ref}>
{state.openSelect && (
<div className={styles['select-picker']}>
<SelectPicker
options={getTeams(state.teams)}
placeholder="Select team"
onSelectionChange={handleTeamChange}
multiSelect={false}
showSearchBar
wrapperClasses={styles['select-picker-item']}
/>
</div>
)}
</div>
</div>
<div className={styles['Description-wrapper']}>
<div className={styles['Desc-name']}>Description</div>
<TextArea
name="title"
placeholder="Enter incident description"
containerClassName={styles.textarea}
rows={7}
value={state.description}
onChange={handleDescriptionChange as any}
error={
!state.isDescriptionValid
? `Description should be less than ${LIMITS.description.max} characters`
: ''
}
fullWidth
size="large"
/>
</div>
</div>
<div className={styles['Description-wrapper']}>
<div className={styles['Desc-name']}>Description</div>
<TextArea
name="title"
placeholder="Enter incident description"
containerClassName={styles.textarea}
rows={7}
value={state.description}
onChange={handleDescriptionChange as any}
error={
!state.isDescriptionValid
? `Description should be less than ${LIMITS.description.max} characters`
: ''
}
fullWidth
size="large"
/>
</div>
<div className={styles['footer-wrapper']}>
<div className={styles['cancel']}>
<Button variant="secondary" fullWidth onClick={clearDrawer}>
<div className={styles['button-wrapper']}>
<Button
variant="secondary"
className={styles['cancel']}
fullWidth
onClick={clearDrawer}
>
Cancel
</Button>
</div>
<div className={styles['create']}>
<Button
variant="primary"
fullWidth
onClick={() => createIncidentHandler()}
className={styles['create']}
onClick={createIncidentHandler}
disabled={isDisabled()}
>
Create incident

View File

@@ -20,6 +20,7 @@
justify-content: space-between;
align-items: center;
border: 1px solid var(--navi-color-gray-border);
background-color: var(--navi-color-gray-bg-primary);
}
.filter-wrapper {

View File

@@ -3,12 +3,16 @@ import { useState, useEffect, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);
import styles from './DashboardHeader.module.scss';
import { Button } from '@navi/web-ui/lib/primitives';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import { formatDate } from '@src/services/globalUtils';
import { DATE_FORMAT } from '@src/services/constants';
export interface DateProps {
clearSearchValue: () => void;
updateURLAndFetchData: (payload: string) => void;
@@ -61,16 +65,34 @@ const Date: React.FC<DateProps> = ({
updateURLAndFetchData(updatedQuery);
};
const formatDates = (start_date, end_date) => {
const fromDate = dayjs(start_date).startOf('day');
const toDate = dayjs(end_date).endOf('day');
const formattedFromDate = fromDate.format(DATE_FORMAT);
const formattedToDate = toDate.format(DATE_FORMAT);
const startDateUTC = dayjs(formattedFromDate).utc().format('');
const endDateUTC = dayjs(formattedToDate).utc().format('');
return {
formattedFromDate: startDateUTC,
formattedToDate: endDateUTC,
};
};
const handleApplyClick = () => {
fireEvent(EVENT_NAME.Houston_Check_DateFilter, {
screen_name: SCREEN_NAME.DASHBOARD_PAGE,
});
if (date.length === 2) {
const [start_date, end_date] = date;
const formattedStartDate = formatDate(start_date);
const formattedEndDate = formatDate(end_date);
searchParams.set('from', formattedStartDate);
searchParams.set('to', formattedEndDate);
if (date?.length === 2) {
let [start_date, end_date] = date;
start_date = formatDate(start_date);
end_date = formatDate(end_date);
const { formattedFromDate, formattedToDate } = formatDates(
start_date,
end_date,
);
searchParams.set('from', formattedFromDate);
searchParams.set('to', formattedToDate);
searchParams.delete('incident_name');
searchParams.set('page_number', '0');
searchParams.set('page_size', '10');
@@ -80,12 +102,6 @@ const Date: React.FC<DateProps> = ({
}
setOpen(false);
};
const formatDate = (date: string) => {
const [day, month, year] = date.split('/');
return `${year}-${month}-${day}`;
};
return (
<div className={styles['date-wrapper']}>
<ConfigProvider

View File

@@ -1,15 +1,13 @@
import { FC, useState, useRef } from 'react';
import { FC } from 'react';
import { useNavigate } from 'react-router-dom';
import { AgTable, Pagination } from '@navi/web-ui/lib/components';
import { Tag, Drawer } from '@navi/web-ui/lib/primitives';
import { Tag, Tooltip } from '@navi/web-ui/lib/primitives';
import { returnFormattedDate } from '@src/services/globalUtils';
import DrawerMode from '@src/Pages/Incidents/DrawerMode/index';
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';
interface SearchResultTableProps {
currentPageData: any;
pageDetails: any;
@@ -34,8 +32,6 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
fetchIncidentData,
}) => {
const { pageNumber, totalElements } = pageDetails;
const [drawerState, setDrawerState] = useState<boolean>(false);
const incidentData = useRef<any>({});
const navigate = useNavigate();
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
@@ -45,7 +41,6 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
'white-space': 'nowrap',
overflow: 'hidden',
};
const rowData = currentPageData?.map((item: any, ind: number) => {
let index = 1;
@@ -81,6 +76,19 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
headerName: 'Title',
suppressMovable: true,
cellStyle: cellStyle,
cellRenderer: params => {
if (params.value?.length > 15) {
return (
<div className={styles.tooltipWrapper}>
<Tooltip text={params?.value} withPointer position="right">
<div className={styles.tooltip}>{params?.value}</div>
</Tooltip>
</div>
);
}
return params?.value;
},
},
{
field: 'statusName',
@@ -91,6 +99,9 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
field: 'severityName',
headerName: 'Severity',
suppressMovable: true,
cellStyle: {
zIndex: -1,
},
width: 120,
cellRenderer: params => (
<Tag
@@ -135,30 +146,18 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
if (params?.api?.sizeColumnsToFit) params.api.sizeColumnsToFit();
};
const handleRowClick = (event: any) => {
const handleRowClick = event => {
fireEvent(EVENT_NAME.Houston_Check_Incident, {
screen_name: SCREEN_NAME.DASHBOARD_PAGE,
});
if (event?.data) {
navigate(`/incident/${event.data?.id}`);
if (event && event.event && event.data?.id) {
const { ctrlKey = false, metaKey = false } = event.event;
const incidentId = event.data.id;
const url = `/incident/${incidentId}`;
ctrlKey || metaKey ? window.open(url) : navigate(url);
}
};
const handleCloseDrawer = () => {
incidentData.current = {};
const query = sessionStorage.getItem('filter');
fetchIncidentData({ filterQuery: query, isDrawer: true });
setDrawerState(false);
};
const handleOpenDrawer = rowData => {
incidentData.current = {
incidentId: rowData?.data?.id,
slackChannel: rowData?.data?.slackChannel,
};
setDrawerState(true);
};
return (
<div
className={cx(
@@ -193,18 +192,6 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
rowHeight={54}
detailRowAutoHeight={true}
/>
<Drawer
open={drawerState}
onClose={handleCloseDrawer}
className={styles['drawer-wrapper']}
headerText="Incident Rundown"
showHeaderDivider
>
<DrawerMode
incidentId={incidentData?.current?.incidentId}
slackChannel={incidentData?.current?.slackChannel}
/>
</Drawer>
</div>
);
};

View File

@@ -16,7 +16,7 @@ interface HeaderProps {
const Header: FC<HeaderProps> = ({ incidentName, title }) => {
const navigate = useNavigate();
const handleBacktoDashboard = (): void => {
navigate(-1);
navigate('/');
};
return (
<div>

View File

@@ -11,6 +11,8 @@ import {
setCurrentPageSize,
} from '@src/slices/jiraDashboardSlice';
import { ApiService } from '@src/services/api';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import { JiraDashboardData, JiraDashboardState } from '@src/types';
import { FetchJiraDataProps } from './types';
import { FETCH_JIRA_DATA } from './constants';
@@ -31,6 +33,8 @@ const JiraDashboard: FC = () => {
const dispatch = useDispatch();
const [searchParams, setSearchParams] = useSearchParams();
const navigate = useNavigate();
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const startJiraSearch = (param: string): void => {
const endPoint = FETCH_JIRA_DATA(param);
@@ -53,6 +57,12 @@ const JiraDashboard: FC = () => {
});
};
useEffect(() => {
fireEvent(EVENT_NAME.Houston_Jira_Dashboard_Land, {
screen_name: SCREEN_NAME.JIRA_DASHBOARD_PAGE,
});
}, []);
useEffect(() => {
const pageNumberParam = searchParams.get('page_number');
const pageSizeParam = searchParams.get('page_size');

View File

@@ -1,5 +1,7 @@
import React, { FC } from 'react';
import { useNavigate } from 'react-router-dom';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import GoToLinkIcon from '@src/assets/GoToLinkIcon';
import styles from '../Dashboard.module.scss';
@@ -12,8 +14,14 @@ const HyperlinkCellRenderer: FC<HyperlinkCellRendererProps> = ({
value,
id,
}) => {
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const navigate = useNavigate();
const handleClick = (): void => {
fireEvent(EVENT_NAME.Houston_Jira_Incident_Click, {
screen_name: SCREEN_NAME.JIRA_DASHBOARD_PAGE,
});
navigate(`/incident/${id}`);
};

View File

@@ -6,6 +6,8 @@ const EVENT_NAME = {
Houston_Team_Land: 'Houston_Team_Land',
Houston_dashboard_Land: 'Houston_dashboard_Land',
Houston_Metric_Land: 'Houston_Metric_Land',
Houston_Jira_Dashboard_Land: 'Houston_Jira_Dashboard_Land',
Houston_Jira_Incident_Click: 'Houston_Jira_Incident_Click',
Houston_Add_Member: 'Houston_Add_Member',
Houston_Check_DateFilter: 'Houston_Check_DateFilter',
Houston_Check_Incident: 'Houston_Check_Incident',
@@ -27,6 +29,7 @@ const SCREEN_NAME = {
DASHBOARD_PAGE: 'dashboard_page',
METRIC_PAGE: 'metric_page',
INCIDENT_PAGE: 'incident_page',
JIRA_DASHBOARD_PAGE: 'jira_dashboard_page',
};
export const CLICK_STREAM_EVENT_FACTORY = {

View File

@@ -1 +1,2 @@
export const JANUS_API = `/events`;
export const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss';

View File

@@ -57,3 +57,7 @@ export const handleCopyClick = (textToCopy: string): void => {
export const createURL = (endpoint: string): string => {
return `${window?.config?.BASE_API_URL}${endpoint}`;
};
export const formatDate = (date: string) => {
const [day, month, year] = date.split('/');
return `${year}-${month}-${day}`;
};

3
src/variables.scss Normal file
View File

@@ -0,0 +1,3 @@
:root {
--title-z-index: 1;
}