diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/TestCaseStatus/InlineTestCaseIncidentStatus.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/TestCaseStatus/InlineTestCaseIncidentStatus.component.tsx index c5a234a3533..a7521ceb0ac 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/TestCaseStatus/InlineTestCaseIncidentStatus.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/TestCaseStatus/InlineTestCaseIncidentStatus.component.tsx @@ -19,15 +19,13 @@ import { Close as CloseIcon, } from '@mui/icons-material'; import { - Avatar, Box, Chip, + Divider, IconButton, List, ListItem, - ListItemAvatar, ListItemButton, - ListItemText, Menu, MenuItem, Popover, @@ -38,6 +36,7 @@ import { AxiosError } from 'axios'; import { debounce, isEmpty, startCase } from 'lodash'; import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { PAGE_SIZE_BASE } from '../../../../constants/constants'; import { EntityType } from '../../../../enums/entity.enum'; import { CreateTestCaseResolutionStatus } from '../../../../generated/api/tests/createTestCaseResolutionStatus'; import { @@ -54,6 +53,8 @@ import { getEntityReferenceFromEntity, } from '../../../../utils/EntityUtils'; import { showErrorToast } from '../../../../utils/ToastUtils'; +import Loader from '../../../common/Loader/Loader'; +import { UserTag } from '../../../common/UserTag/UserTag.component'; import { TestCaseStatusIncidentManagerProps } from './TestCaseIncidentManagerStatus.interface'; interface InlineTestCaseIncidentStatusProps { @@ -72,6 +73,40 @@ const STATUS_COLORS: Record< Resolved: { bg: '#E8F5E9', color: '#4CAF50', border: '#81C784' }, }; +const ACTION_BUTTON_STYLES = { + cancel: { + width: 24, + height: 24, + padding: 0, + borderRadius: '4px', + backgroundColor: 'grey.200', + color: 'grey.600', + '&:hover': { + backgroundColor: 'grey.300', + }, + }, + submit: { + width: 24, + height: 24, + padding: 0, + borderRadius: '4px', + backgroundColor: 'primary.main', + color: 'common.white', + '&:hover': { + backgroundColor: 'primary.dark', + }, + '&:disabled': { + backgroundColor: 'grey.200', + color: 'grey.400', + }, + }, + icon: { + fontSize: 14, + width: 14, + height: 14, + }, +}; + const InlineTestCaseIncidentStatus = ({ data, hasEditPermission, @@ -85,6 +120,7 @@ const InlineTestCaseIncidentStatus = ({ const [showAssigneePopover, setShowAssigneePopover] = useState(false); const [showResolvedPopover, setShowResolvedPopover] = useState(false); const [isLoading, setIsLoading] = useState(false); + const [isLoadingUsers, setIsLoadingUsers] = useState(false); const [userOptions, setUserOptions] = useState([]); const [selectedAssignee, setSelectedAssignee] = useState( @@ -115,8 +151,9 @@ const InlineTestCaseIncidentStatus = ({ const searchUsers = useCallback( async (query: string) => { + setIsLoadingUsers(true); try { - const res = await getUserAndTeamSearch(query, true); + const res = await getUserAndTeamSearch(query, true, PAGE_SIZE_BASE); const hits = res.data.hits.hits; const suggestOptions: Option[] = hits.map((hit) => ({ label: getEntityName(hit._source), @@ -146,6 +183,8 @@ const InlineTestCaseIncidentStatus = ({ } } catch (err) { showErrorToast(err as AxiosError); + } finally { + setIsLoadingUsers(false); } }, [initialOptions] @@ -322,15 +361,6 @@ const InlineTestCaseIncidentStatus = ({ } }; - const getInitials = (name: string) => { - return name - .split(' ') - .map((n) => n[0]) - .join('') - .toUpperCase() - .slice(0, 2); - }; - const statusColor = STATUS_COLORS[statusType] || STATUS_COLORS.New; return ( @@ -382,6 +412,11 @@ const InlineTestCaseIncidentStatus = ({ horizontal: 'left', }} open={showStatusMenu} + sx={{ + '.MuiPaper-root': { + width: 'max-content', + }, + }} transformOrigin={{ vertical: 'top', horizontal: 'left', @@ -392,8 +427,15 @@ const InlineTestCaseIncidentStatus = ({ key={status} selected={status === statusType} sx={{ - minWidth: 150, + minWidth: 100, fontWeight: status === statusType ? 600 : 400, + '&.Mui-selected': { + backgroundColor: 'primary.main', + color: 'primary.contrastText', + '&:hover': { + backgroundColor: 'primary.dark', + }, + }, }} onClick={() => handleStatusChange(status)}> {status} @@ -401,48 +443,55 @@ const InlineTestCaseIncidentStatus = ({ ))} + {/* Assigned status popover */} - - - - - - - {t('label.assigned')} - - - - - - - - - + + + + + + {t('label.assigned')} + + + + + + + + + + + handleSearchUsers(e.target.value)} /> - - {userOptions.map((option) => { - const user: EntityReference = { - id: option.value, - name: option.name, - displayName: option.displayName, - type: option.type || EntityType.USER, - }; + + {isLoadingUsers ? ( + + + + ) : userOptions.length === 0 ? ( + + + {t('message.no-users-found')} + + + ) : ( + userOptions.map((option) => { + const user: EntityReference = { + id: option.value, + name: option.name, + displayName: option.displayName, + type: option.type || EntityType.USER, + }; - return ( - - handleAssigneeSelect(user)}> - - - {getInitials(option.displayName || option.name || 'U')} - - - - - - ); - })} + return ( + + handleAssigneeSelect(user)}> + + + + ); + }) + )} + {/* Resolved status popover */} - - - - - - - {t('label.resolved')} - - - - - - - - - + + + + + + {t('label.resolved')} + + + + + + + + + + + {t('label.reason')} - + {Object.values(TestCaseFailureReasonType).map((reason) => ( + ) : undefined + } key={reason} label={startCase(reason)} - sx={{ cursor: 'pointer' }} - variant={selectedReason === reason ? 'filled' : 'outlined'} + sx={{ + cursor: 'pointer', + borderRadius: '6px', + fontSize: '12px', + fontWeight: 500, + height: 'auto', + '& .MuiChip-label': { + px: selectedReason === reason ? 0.5 : 1.5, + py: 0.5, + }, + ...(selectedReason === reason + ? { + backgroundColor: 'primary.main', + color: 'common.white', + border: 'none', + '&:hover': { + backgroundColor: 'primary.dark', + }, + '& .MuiChip-icon': { + color: 'common.white', + // marginLeft: '8px', + }, + } + : { + backgroundColor: 'grey.50', + color: 'grey.900', + border: '1px solid', + borderColor: 'grey.200', + '&:hover': { + backgroundColor: 'grey.100', + }, + }), + }} onClick={() => setSelectedReason(reason)} /> ))} @@ -557,9 +651,10 @@ const InlineTestCaseIncidentStatus = ({ {t('label.comment')}