refactor(): Fix incidents feedback on QA (#13044)

Co-authored-by: Aseem Bansal <asmbansal2@gmail.com>
Co-authored-by: John Joyce <john@Mac-307.lan>
This commit is contained in:
John Joyce 2025-04-01 17:22:41 -07:00 committed by GitHub
parent 18aa1f076d
commit 87af4b9d53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 51 additions and 42 deletions

View File

@ -31,7 +31,8 @@ export const IncidentDetailDrawer = ({
}: IncidentDetailDrawerProps) => {
const [isEditView, setIsEditView] = useState<boolean>(false);
const showEditor = isEditView || mode === IncidentAction.CREATE;
const modalClosePopup = () => {
const onCloseModal = () => {
if (showEditor) {
Modal.confirm({
title: 'Exit Editor',
@ -48,15 +49,21 @@ export const IncidentDetailDrawer = ({
onCancel?.();
}
};
const handleSubmit = (i?: Incident) => {
setIsEditView(false);
onSubmit?.(i);
};
return (
<ClickOutside onClickOutside={modalClosePopup} wrapperClassName="incident-monitor-builder-modal">
<ClickOutside onClickOutside={onCloseModal} wrapperClassName="incident-monitor-builder-modal">
<Drawer
width={600}
placement="right"
closable={false}
visible
bodyStyle={modalBodyStyle}
onClose={modalClosePopup}
onClose={onCloseModal}
>
<IncidentDrawerHeader
mode={mode}
@ -73,8 +80,8 @@ export const IncidentDetailDrawer = ({
data={incident}
mode={mode}
incidentUrn={incident?.urn}
onSubmit={onSubmit}
entity={entity}
onSubmit={handleSubmit}
/>
) : (
<IncidentView incident={incident as IncidentTableRow} />

View File

@ -34,7 +34,6 @@ export const IncidentEditor = ({
incidentUrn,
onSubmit,
data,
onClose,
mode = IncidentAction.CREATE,
entity,
}: IncidentEditorProps) => {
@ -60,7 +59,6 @@ export const IncidentEditor = ({
incidentUrn,
mode,
onSubmit,
onClose,
user,
assignees: cachedAssignees,
linkedAssets: cachedLinkedAssets,

View File

@ -70,7 +70,7 @@ export const getCacheIncident = ({
return newIncident;
};
export const useIncidentHandler = ({ mode, onSubmit, incidentUrn, onClose, user, assignees, linkedAssets, entity }) => {
export const useIncidentHandler = ({ mode, onSubmit, incidentUrn, user, assignees, linkedAssets, entity }) => {
const [raiseIncidentMutation] = useRaiseIncidentMutation();
const [updateIncidentMutation] = useUpdateIncidentMutation();
const [form] = Form.useForm();
@ -118,7 +118,6 @@ export const useIncidentHandler = ({ mode, onSubmit, incidentUrn, onClose, user,
const finalizeSubmission = () => {
onSubmit?.();
onClose?.();
};
const handleSubmissionError = (error: any) => {

View File

@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import { Empty } from 'antd';
import { useGetEntityIncidentsQuery } from '../../../../../graphql/incident.generated';
import { useEntityData } from '../../../../entity/shared/EntityContext';
import { useEntityData, useRefetch } from '../../../../entity/shared/EntityContext';
import { PAGE_SIZE } from './incidentUtils';
import { EntityPrivileges, Incident } from '../../../../../types.generated';
import { combineEntityDataWithSiblings } from '../../../../entity/shared/siblingUtils';
@ -19,6 +19,7 @@ import { getQueryParams } from '../Dataset/Validations/assertionUtils';
export const IncidentList = () => {
const { urn } = useEntityData();
const refetchEntity = useRefetch();
const [showIncidentBuilder, setShowIncidentBuilder] = useState(false);
const [entity, setEntity] = useState<EntityStagedForIncident>();
const [visibleIncidents, setVisibleIncidents] = useState<IncidentTable>({
@ -36,7 +37,11 @@ export const IncidentList = () => {
const [selectedFilters, setSelectedFilters] = useState<IncidentListFilter>(incidentDefaultFilters);
// Fetch filtered incidents.
const { loading, data, refetch } = useGetEntityIncidentsQuery({
const {
loading,
data,
refetch: refetchIncidents,
} = useGetEntityIncidentsQuery({
variables: {
urn,
start: 0,
@ -76,6 +81,11 @@ export const IncidentList = () => {
const privileges = (data?.entity as any)?.privileges as EntityPrivileges;
const refetch = () => {
refetchEntity();
refetchIncidents();
};
const renderListTable = () => {
if (loading) {
return <IncidentListLoading />;
@ -94,6 +104,7 @@ export const IncidentList = () => {
}
return <Empty description="No incidents yet" image={Empty.PRESENTED_IMAGE_SIMPLE} />;
};
return (
<>
<IncidentTitleContainer
@ -115,10 +126,10 @@ export const IncidentList = () => {
urn={urn}
mode={IncidentAction.CREATE}
onSubmit={() => {
setShowIncidentBuilder(false);
setTimeout(() => {
refetch();
}, 2000);
setShowIncidentBuilder(false);
}, 3000);
}}
onCancel={() => setShowIncidentBuilder(false)}
entity={entity}

View File

@ -4,7 +4,7 @@ import { Table } from '@src/alchemy-components';
import { SortingState } from '@src/alchemy-components/components/Table/types';
import { EntityPrivileges } from '@src/types.generated';
import { IncidentDetailDrawer } from './AcrylComponents/IncidentDetailDrawer';
import { IncidentListFilter, IncidentTable, IncidentTableRow } from './types';
import { IncidentListFilter, IncidentTable } from './types';
import { useIncidentsTableColumns, useOpenIncidentDetailModal } from './hooks';
import { getSiblingWithUrn } from '../Dataset/Validations/acrylUtils';
import { StyledTableContainer } from './styledComponents';
@ -31,40 +31,28 @@ export const IncidentListTable = ({ incidentData, filter, refetch, privileges }:
);
// get columns data from the custom hooks
const incidentsTableCols = useIncidentsTableColumns(privileges);
const incidentsTableCols = useIncidentsTableColumns(refetch, privileges);
const [sortedOptions, setSortedOptions] = useState<{ sortColumn: string; sortOrder: SortingState }>({
sortColumn: '',
sortOrder: SortingState.ORIGINAL,
});
const [focusIncidentUrn, setFocusIncidentUrn] = useState<string | null>(null);
const [focusIncidentData, setFocusIncidentData] = useState<IncidentTableRow>();
const focusedIncident = incidentData.incidents.find((incident) => incident.urn === focusIncidentUrn);
const focusedEntityUrn = focusedIncident ? entityData?.urn : undefined;
const focusedIncidentEntity =
focusedEntityUrn && entityData ? getSiblingWithUrn(entityData, focusedEntityUrn) : undefined;
const getGroupData = () => {
return (incidentData?.groupBy && incidentData?.groupBy[groupBy]) || [];
};
const updateIncidentData = (selectedURN: string) => {
const data = groupBy ? getGroupData() : incidentData.incidents || [];
const urnExists = data
.map((item) => item.incidents)
.flat()
.filter((incident) => selectedURN.includes(incident.urn));
setFocusIncidentData(urnExists[0]);
};
useOpenIncidentDetailModal(setFocusIncidentUrn, updateIncidentData);
const focusedIncidentEntity =
focusedEntityUrn && entityData ? getSiblingWithUrn(entityData, focusedEntityUrn) : undefined;
useOpenIncidentDetailModal(setFocusIncidentUrn);
useEffect(() => {
if (focusIncidentUrn && !focusedIncident) {
setFocusIncidentUrn(null);
setFocusIncidentData(undefined);
}
}, [focusIncidentUrn, focusedIncident]);
@ -84,7 +72,6 @@ export const IncidentListTable = ({ incidentData, filter, refetch, privileges }:
};
const onRowClick = (record) => {
setFocusIncidentData(record);
setFocusIncidentUrn(record.urn);
};
@ -139,14 +126,13 @@ export const IncidentListTable = ({ incidentData, filter, refetch, privileges }:
<IncidentDetailDrawer
urn={focusIncidentUrn}
mode={IncidentAction.EDIT}
incident={focusIncidentData}
incident={focusedIncident}
privileges={privileges}
onCancel={() => setFocusIncidentUrn(null)}
onSubmit={() => {
setTimeout(() => {
refetch();
}, 2000);
setFocusIncidentUrn(null);
}, 3000);
}}
/>
)}

View File

@ -19,6 +19,7 @@ import { PAGE_SIZE, updateActiveIncidentInCache } from './incidentUtils';
type IncidentResolutionPopupProps = {
incident: IncidentTableRow;
refetch: () => void;
handleClose: () => void;
};
@ -32,7 +33,7 @@ const ModalTitle = () => (
</ModalTitleContainer>
);
export const IncidentResolutionPopup = ({ incident, handleClose }: IncidentResolutionPopupProps) => {
export const IncidentResolutionPopup = ({ incident, refetch, handleClose }: IncidentResolutionPopupProps) => {
const client = useApolloClient();
const { user } = useUserContext();
const { urn, entityType } = useEntityData();
@ -79,10 +80,10 @@ export const IncidentResolutionPopup = ({ incident, handleClose }: IncidentResol
incidentUrn: incident.urn,
user,
});
updateActiveIncidentInCache(client, urn, updatedIncident, PAGE_SIZE);
message.success({ content: 'Incident updated!', duration: 2 });
handleClose?.();
setTimeout(() => refetch(), 3000);
})
.catch((error) => {
handleGraphQLError({

View File

@ -30,13 +30,14 @@ const ResolveButton = styled(Button)`
export const IncidentResolveButton = ({
incident,
refetch,
privileges,
}: {
incident: IncidentTableRow;
refetch: () => void;
privileges?: EntityPrivileges;
}) => {
const canEditIncidents = privileges?.canEditIncidents || false;
const me = useUserContext();
const [showResolvePopup, setShowResolvePopup] = useState(false);
const [incidentResolver, setIncidentResolver] = useState<CorpUser | any>(null);
@ -45,6 +46,7 @@ export const IncidentResolveButton = ({
me?.urn === incidentResolver?.urn
? ME
: incidentResolver?.properties?.displayName || incidentResolver?.username;
useEffect(() => {
if (incident?.lastUpdated?.actor) {
getAssigneeEntities({
@ -132,7 +134,9 @@ export const IncidentResolveButton = ({
showPopoverWithResolver
)}
{showResolvePopup && <IncidentResolutionPopup incident={incident} handleClose={handleShowPopup} />}
{showResolvePopup && (
<IncidentResolutionPopup incident={incident} refetch={refetch} handleClose={handleShowPopup} />
)}
</Container>
);
};

View File

@ -15,7 +15,7 @@ import { IncidentResolveButton } from './IncidentResolveButton';
import { IncidentAssigneeAvatarStack } from './IncidentAssigneeAvatarStack';
import { CategoryType } from './styledComponents';
export const useIncidentsTableColumns = (privileges?: EntityPrivileges) => {
export const useIncidentsTableColumns = (refetch: () => void, privileges?: EntityPrivileges) => {
return useMemo(() => {
const columns = [
{
@ -107,13 +107,17 @@ export const useIncidentsTableColumns = (privileges?: EntityPrivileges) => {
key: 'actions',
width: '15%',
render: (record) => {
return !record.groupName && <IncidentResolveButton incident={record} privileges={privileges} />;
return (
!record.groupName && (
<IncidentResolveButton incident={record} privileges={privileges} refetch={refetch} />
)
);
},
alignment: 'right' as AlignmentOptions,
},
];
return columns;
}, [privileges]);
}, [privileges, refetch]);
};
export const useIncidentURNCopyLink = (Urn: string) => {
@ -172,7 +176,7 @@ export const getOnOpenAssertionLink = (Urn: string) => {
* @param {Function} setFocusAssertionUrn - Function to set details of the viewing assertion and open detail Modal.
* @returns {Object} Object containing the 'assertionUrnParam' from the URL.
*/
export const useOpenIncidentDetailModal = (setFocusIncidentUrn, updateIncidentData) => {
export const useOpenIncidentDetailModal = (setFocusIncidentUrn) => {
const location = useLocation();
const history = useHistory();
const incidentUrnParam = getQueryParams('incident_urn', location);
@ -182,7 +186,6 @@ export const useOpenIncidentDetailModal = (setFocusIncidentUrn, updateIncidentDa
const decodedIncidentUrn = decodeURIComponent(incidentUrnParam);
setFocusIncidentUrn(decodedIncidentUrn);
updateIncidentData(decodedIncidentUrn);
// Remove the query parameter from the URL
const newUrlParams = new URLSearchParams(location.search);