@@ -5,5 +5,6 @@ sed -i "s~<AUTH_CLIENT_ID>~${AUTH_CLIENT_ID}~g" /usr/share/nginx/html/config.js
|
||||
sed -i "s~<ENVIRONMENT>~${ENVIRONMENT}~g" /usr/share/nginx/html/config.js
|
||||
sed -i "s~<BASE_API_URL>~${BASE_API_URL}~g" /usr/share/nginx/html/config.js
|
||||
sed -i "s~CSP_HEADER~${CSP_HEADER}~g" /etc/nginx/conf.d/nginx.conf
|
||||
sed -i "s~DISABLE_UNIVERSAL_AUTH~${DISABLE_UNIVERSAL_AUTH}~g" /etc/nginx/conf.d/nginx.conf
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -26,7 +26,7 @@ const Dashboard: FC = () => {
|
||||
);
|
||||
const searchParamRef = useRef('');
|
||||
|
||||
const startSessionSearch = (param = pageNumberRef.current): void => {
|
||||
const startIncidentSearch = (param = pageNumberRef.current): void => {
|
||||
const endPoint = FETCH_INCIDENTS_DATA(param);
|
||||
setIsLoading(true);
|
||||
ApiService.get(endPoint)
|
||||
@@ -49,7 +49,7 @@ const Dashboard: FC = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
startSessionSearch();
|
||||
startIncidentSearch();
|
||||
}, []);
|
||||
|
||||
const handlePageNumber = (pageNumber: number): void => {
|
||||
@@ -57,21 +57,21 @@ const Dashboard: FC = () => {
|
||||
pageNumber - 1
|
||||
}&page_size=${currentPageSize}`;
|
||||
setPageNumber(pageNumber - 1);
|
||||
startSessionSearch(`${searchParamRef.current}${finalParams}`);
|
||||
startIncidentSearch(`${searchParamRef.current}${finalParams}`);
|
||||
};
|
||||
|
||||
const handlePageSize = (pageSize: number): void => {
|
||||
const finalParams = `page_number=${currentPageNumber}&page_size=${pageSize}`;
|
||||
setPageSize(pageSize);
|
||||
startSessionSearch(`${searchParamRef.current}${finalParams}`);
|
||||
startIncidentSearch(`${searchParamRef.current}${finalParams}`);
|
||||
};
|
||||
|
||||
const fetchSessionData = (props: any): void => {
|
||||
const fetchIncidentData = (props: any): void => {
|
||||
const { filterQuery = '' } = props;
|
||||
const finalParams = filterQuery ? `${filterQuery}&` : '';
|
||||
setPageNumber(0);
|
||||
searchParamRef.current = finalParams;
|
||||
startSessionSearch(`${finalParams}${pageNumberRef.current}`);
|
||||
startIncidentSearch(`${finalParams}${pageNumberRef.current}`);
|
||||
};
|
||||
|
||||
const returnTable = (): JSX.Element => {
|
||||
@@ -93,7 +93,7 @@ const Dashboard: FC = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DashboardHeader fetchSessionData={fetchSessionData} />
|
||||
<DashboardHeader fetchIncidentData={fetchIncidentData} />
|
||||
{returnTable()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,13 +2,6 @@
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.search-reset-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
|
||||
.header-filter-results-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -45,9 +38,10 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-wrapper {
|
||||
.search-wrapper {
|
||||
margin: 4px 0;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@@ -72,6 +66,46 @@
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&_search-title {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
&_on-error {
|
||||
margin-top: -20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.input-container {
|
||||
border-top-right-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
min-width: 360px;
|
||||
|
||||
&_disabled {
|
||||
div {
|
||||
cursor: not-allowed;
|
||||
input {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-wrapper {
|
||||
border-top-left-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
height: 40px;
|
||||
padding: 0 12px !important;
|
||||
|
||||
&_on-error {
|
||||
margin-top: -20px;
|
||||
}
|
||||
}
|
||||
|
||||
:export {
|
||||
filterSelectedIndicated: var(--navi-color-blue-base);
|
||||
}
|
||||
|
||||
@@ -4,26 +4,34 @@ import { Typography } from '@navi/web-ui/lib/primitives';
|
||||
import FilterWrapper from './FilterWrapper';
|
||||
import { DashboardHeaderConstants } from '../constants';
|
||||
import styles from './DashboardHeader.module.scss';
|
||||
import SmartSearch from './SmartSearch';
|
||||
|
||||
interface DashboardHeaderProps {
|
||||
fetchSessionData: (payload: any) => void;
|
||||
fetchIncidentData: (payload: any) => void;
|
||||
}
|
||||
|
||||
const DashboardHeader: FC<DashboardHeaderProps> = ({ fetchSessionData }) => {
|
||||
const DashboardHeader: FC<DashboardHeaderProps> = ({ fetchIncidentData }) => {
|
||||
const { title } = DashboardHeaderConstants;
|
||||
|
||||
const handleFilterQuery = (query): void => {
|
||||
fetchSessionData({
|
||||
fetchIncidentData({
|
||||
filterQuery: query,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSearchUpdate = (searchValue: string): void => {
|
||||
fetchIncidentData({
|
||||
filterQuery: `incident_name=${searchValue}`,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles['header-wrapper']}>
|
||||
<div>
|
||||
<div className={styles['more-info-wrapper']}>
|
||||
<Typography variant="h1">{title}</Typography>
|
||||
</div>
|
||||
<div className={styles['search-reset-wrapper']}>
|
||||
<div className={styles['search-wrapper']}>
|
||||
<SmartSearch updateSearchResults={handleSearchUpdate} />
|
||||
<FilterWrapper fetchSessionsWithFilters={handleFilterQuery} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
46
src/Pages/Dashboard/partials/SmartSearch.tsx
Normal file
46
src/Pages/Dashboard/partials/SmartSearch.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import React, { FC, useState, useEffect } from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
import { Button, BorderedInput } from '@navi/web-ui/lib/primitives';
|
||||
import SearchIcon from '@navi/web-ui/lib/icons/SearchIcon/SearchIcon';
|
||||
|
||||
import styles from './DashboardHeader.module.scss';
|
||||
|
||||
interface SmartSearchProps {
|
||||
updateSearchResults: (data: any) => void;
|
||||
}
|
||||
|
||||
const SmartSearch: FC<SmartSearchProps> = ({ updateSearchResults }) => {
|
||||
const [searchValue, setSearchValue] = useState<string>('');
|
||||
|
||||
const handleSearchInput = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchValue(e.target.value);
|
||||
};
|
||||
|
||||
const handleButtonClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
updateSearchResults(searchValue);
|
||||
};
|
||||
|
||||
const placeHolder = 'Enter the incident name here';
|
||||
|
||||
return (
|
||||
<div className={styles['input-wrapper']}>
|
||||
<BorderedInput
|
||||
fullWidth
|
||||
value={searchValue}
|
||||
onChange={handleSearchInput}
|
||||
placeholder={placeHolder}
|
||||
containerClassName={cx(styles['input-container'])}
|
||||
/>
|
||||
<Button
|
||||
className={styles['button-wrapper']}
|
||||
disabled={!searchValue}
|
||||
onClick={handleButtonClick}
|
||||
>
|
||||
<SearchIcon color="white" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SmartSearch;
|
||||
@@ -121,9 +121,9 @@ const DrawerMode: FC<DrawerModeProps> = ({ incidentId, slackChannel }) => {
|
||||
const endPoint = UPDATE_INCIDENT;
|
||||
ApiService.post(endPoint, {
|
||||
id: incidentId,
|
||||
teamId: team?.value,
|
||||
status: status?.value,
|
||||
severityId: severity?.value,
|
||||
teamId: `${team?.value}`,
|
||||
status: `${status?.value}`,
|
||||
severityId: `${severity?.value}`,
|
||||
})
|
||||
.then(response => {
|
||||
toast.success('Incident Updated Successfully');
|
||||
|
||||
@@ -36,15 +36,13 @@
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.severity-details-wrapper {
|
||||
.accordion-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 12px;
|
||||
}
|
||||
width: 100%;
|
||||
|
||||
.participant-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
.title {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ import { useEffect, useState } from 'react';
|
||||
import BorderedInput from '@navi/web-ui/lib/primitives/BorderedInput';
|
||||
import Button from '@navi/web-ui/lib/primitives/Button';
|
||||
import { toast } from '@navi/web-ui/lib/primitives/Toast';
|
||||
import { Avatar, Typography } from '@navi/web-ui/lib/primitives';
|
||||
import { Typography } from '@navi/web-ui/lib/primitives';
|
||||
import { LoadingIcon } from '@navi/web-ui/lib/icons';
|
||||
|
||||
import { ApiService } from '@src/services/api';
|
||||
import MembersDetails from '@src/components/MembersDetails';
|
||||
import {
|
||||
FETCH_SINGLE_SEVERITY_DATA,
|
||||
SeverityFormProps,
|
||||
@@ -49,14 +50,11 @@ const SeverityForm = (props: SeverityFormProps) => {
|
||||
|
||||
const submitHandler = () => {
|
||||
const endPoint = UPDATE_SEVERITY_DATA;
|
||||
const slackIds = severities?.participants?.length
|
||||
? severities?.participants?.map(participant => participant?.id)
|
||||
: [];
|
||||
const updatedSlackUsers = slackUsers?.includes(',')
|
||||
? slackUsers.split(',')
|
||||
? slackUsers?.split(',')?.map(item => item.trim())
|
||||
: [slackUsers];
|
||||
if (severities?.slackUserIds) {
|
||||
severities.slackUserIds = [...updatedSlackUsers].concat(slackIds);
|
||||
if (!severities?.workEmailIds) {
|
||||
severities.workEmailIds = [...updatedSlackUsers];
|
||||
const payload = [{ ...severities }];
|
||||
ApiService.post(endPoint, { severities: payload })
|
||||
.then(response => {
|
||||
@@ -103,26 +101,7 @@ const SeverityForm = (props: SeverityFormProps) => {
|
||||
<Typography variant="h4" color="#585757">
|
||||
Members
|
||||
</Typography>
|
||||
{severities?.participants?.length ? (
|
||||
severities?.participants?.map(participant => (
|
||||
<div
|
||||
key={participant?.id}
|
||||
className={styles['severity-details-wrapper']}
|
||||
>
|
||||
<div className={styles['participant-detail']}>
|
||||
<Avatar size={20} isImage src={participant?.image} />{' '}
|
||||
<Typography variant="p3">{participant?.name}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Typography
|
||||
variant="p3"
|
||||
className={styles['severity-details-wrapper']}
|
||||
>
|
||||
-
|
||||
</Typography>
|
||||
)}
|
||||
<MembersDetails data={severities} />
|
||||
</div>
|
||||
</div>
|
||||
<hr className={styles['vertical-line']} />
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ApiService } from '@src/services/api';
|
||||
import { FETCH_SEVERITY_DATA } from './constants';
|
||||
import FallbackComponent from '@src/components/Fallback';
|
||||
import SeverityForm from './SeverityForm';
|
||||
import { returnFormattedDate } from '@src/services/globalUtils';
|
||||
|
||||
import styles from './Severity.module.scss';
|
||||
|
||||
@@ -55,9 +56,16 @@ const SeverityResults = () => {
|
||||
if (isExpanded) setSeverityId(severity?.id);
|
||||
}}
|
||||
header={
|
||||
<Typography variant="h4" style={{ padding: '12px' }}>
|
||||
{severity?.name}
|
||||
</Typography>
|
||||
<div className={styles['accordion-header']}>
|
||||
<Typography variant="h4" className={styles['title']}>
|
||||
{severity?.name}
|
||||
</Typography>
|
||||
{severity?.lastUpdatedAt && (
|
||||
<Typography variant="h4" className={styles['title']}>
|
||||
{returnFormattedDate(severity?.lastUpdatedAt)}
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<SeverityForm
|
||||
|
||||
@@ -49,19 +49,6 @@
|
||||
padding: 0 12px 12px;
|
||||
}
|
||||
|
||||
.participant-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.team-details-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.vertical-line {
|
||||
transform: rotateX(180deg);
|
||||
border: 1px solid #e8e8e8;
|
||||
@@ -73,3 +60,14 @@
|
||||
justify-content: center;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.accordion-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
.title {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface TeamsData {
|
||||
id: string;
|
||||
name: string;
|
||||
slackUserIds: Array<string>;
|
||||
lastUpdatedAt: string;
|
||||
}
|
||||
|
||||
export interface TeamFormProps {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
|
||||
import LoadingIcon from '@navi/web-ui/lib/icons/LoadingIcon';
|
||||
import Button from '@navi/web-ui/lib/primitives/Button';
|
||||
import { toast } from '@navi/web-ui/lib/primitives/Toast';
|
||||
import { BorderedInput, Typography } from '@navi/web-ui/lib/primitives';
|
||||
|
||||
import {
|
||||
FETCH_SINGLE_TEAM_DATA,
|
||||
@@ -10,9 +11,9 @@ import {
|
||||
UPDATE_TEAM_DATA,
|
||||
} from '../constants';
|
||||
import { ApiService } from '@src/services/api';
|
||||
import MembersDetails from '@src/components/MembersDetails';
|
||||
|
||||
import styles from '../Team.module.scss';
|
||||
import { Avatar, BorderedInput, Typography } from '@navi/web-ui/lib/primitives';
|
||||
|
||||
const TeamForm = (props: TeamFormProps) => {
|
||||
const { teamId, isExpanded, setTeamId } = props;
|
||||
@@ -86,26 +87,7 @@ const TeamForm = (props: TeamFormProps) => {
|
||||
<Typography variant="p3" color="#585757">
|
||||
Members
|
||||
</Typography>
|
||||
{data?.participants?.length ? (
|
||||
data?.participants?.map(participant => (
|
||||
<div
|
||||
key={participant?.id}
|
||||
className={styles['team-details-wrapper']}
|
||||
>
|
||||
<div className={styles['participant-detail']}>
|
||||
<Avatar size={20} isImage src={participant?.image} />{' '}
|
||||
<Typography variant="p3">{participant?.name}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Typography
|
||||
variant="p3"
|
||||
className={styles['team-details-wrapper']}
|
||||
>
|
||||
-
|
||||
</Typography>
|
||||
)}
|
||||
<MembersDetails data={data} />
|
||||
</div>
|
||||
</div>
|
||||
<hr className={styles['vertical-line']} />
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import Typography from '@navi/web-ui/lib/primitives/Typography';
|
||||
import { Accordion, AccordionGroup } from '@navi/web-ui/lib/primitives';
|
||||
|
||||
import { TeamResultsTableProps } from '@src/Pages/Incidents/constants';
|
||||
import TeamForm from './TeamForm';
|
||||
import { TeamsData } from '../constants';
|
||||
import { returnFormattedDate } from '@src/services/globalUtils';
|
||||
|
||||
import { Accordion, AccordionGroup } from '@navi/web-ui/lib/primitives';
|
||||
import styles from '../Team.module.scss';
|
||||
|
||||
const TeamResultsTable = (props: TeamResultsTableProps) => {
|
||||
const { teamsData } = props;
|
||||
@@ -23,9 +25,16 @@ const TeamResultsTable = (props: TeamResultsTableProps) => {
|
||||
if (isExpanded) setTeamId(team?.id);
|
||||
}}
|
||||
header={
|
||||
<Typography variant="h4" style={{ padding: '12px' }}>
|
||||
{team?.name}
|
||||
</Typography>
|
||||
<div className={styles['accordion-header']}>
|
||||
<Typography variant="h4" className={styles['title']}>
|
||||
{team?.name}
|
||||
</Typography>
|
||||
{team?.lastUpdatedAt && (
|
||||
<Typography variant="h4" className={styles['title']}>
|
||||
{returnFormattedDate(team?.lastUpdatedAt)}
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<TeamForm
|
||||
|
||||
13
src/components/MembersDetails/Members.module.scss
Normal file
13
src/components/MembersDetails/Members.module.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
.member-details-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.participant-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
54
src/components/MembersDetails/index.tsx
Normal file
54
src/components/MembersDetails/index.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { Avatar, Typography } from '@navi/web-ui/lib/primitives';
|
||||
|
||||
import styles from './Members.module.scss';
|
||||
|
||||
const MembersDetails = (props: any) => {
|
||||
const { data } = props;
|
||||
const totalMembers = data?.participants?.length;
|
||||
const [showTotalMembers, setShowTotalMembers] = useState(10);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{totalMembers ? (
|
||||
<>
|
||||
{data?.participants
|
||||
?.slice(0, showTotalMembers)
|
||||
?.map((participant, index) => (
|
||||
<div
|
||||
key={participant?.id}
|
||||
className={styles['member-details-wrapper']}
|
||||
>
|
||||
<div className={styles['participant-detail']}>
|
||||
<Avatar size={20} isImage src={participant?.image} />{' '}
|
||||
<Typography variant="p3">{participant?.name}</Typography>
|
||||
{totalMembers > 10 && index === showTotalMembers - 1 ? (
|
||||
totalMembers !== showTotalMembers ? (
|
||||
<div onClick={() => setShowTotalMembers(totalMembers)}>
|
||||
<Typography variant="h5">
|
||||
+{totalMembers - showTotalMembers} More
|
||||
</Typography>
|
||||
</div>
|
||||
) : (
|
||||
<div onClick={() => setShowTotalMembers(10)}>
|
||||
<Typography variant="h5">View less</Typography>
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<Typography variant="p3" className={styles['member-details-wrapper']}>
|
||||
-
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MembersDetails;
|
||||
Reference in New Issue
Block a user