Skip to content

Commit ca71fa8

Browse files
github-actions[bot]Lewis Carhartclaude
authored
fix(people): address review feedback on devices and export button (#2587)
- Guard host.mdm access in fleet-hosts route to avoid runtime TypeError - Show loading/error states in DevicesTabContent so the compliance chart no longer flashes an empty-state while fetching - Render a skeleton in the MemberRow device column while device data loads instead of defaulting to 'Not Installed' - Replace hand-rolled button styles on PopoverTrigger with base-ui render pattern using Button Co-authored-by: Lewis Carhart <lewis@Lewiss-MacBook-Air.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4e12c5d commit ca71fa8

File tree

5 files changed

+50
-9
lines changed

5 files changed

+50
-9
lines changed

apps/app/src/app/(app)/[orgId]/auditor/(overview)/components/ExportEvidenceButton.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ export function ExportEvidenceButton({ organizationName }: ExportEvidenceButtonP
4040

4141
return (
4242
<Popover open={isOpen} onOpenChange={setIsOpen}>
43-
<PopoverTrigger className="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-7 px-2 cursor-pointer">
44-
Export All Evidence
45-
</PopoverTrigger>
43+
<PopoverTrigger render={<Button variant="outline">Export All Evidence</Button>} />
4644
<PopoverContent align="end" side="bottom" sideOffset={8}>
4745
<PopoverHeader>
4846
<PopoverTitle>Export Options</PopoverTitle>

apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
Badge,
2929
HStack,
3030
Label,
31+
Skeleton,
3132
TableCell,
3233
TableRow,
3334
Text,
@@ -52,6 +53,7 @@ interface MemberRowProps {
5253
customRoles?: CustomRoleOption[];
5354
taskCompletion?: TaskCompletion;
5455
deviceStatus?: 'compliant' | 'non-compliant' | 'not-installed';
56+
isDeviceStatusLoading?: boolean;
5557
}
5658

5759
function getInitials(name?: string | null, email?: string | null): string {
@@ -96,6 +98,7 @@ export function MemberRow({
9698
customRoles = [],
9799
taskCompletion,
98100
deviceStatus,
101+
isDeviceStatusLoading = false,
99102
}: MemberRowProps) {
100103
const { orgId } = useParams<{ orgId: string }>();
101104

@@ -233,7 +236,15 @@ export function MemberRow({
233236

234237
{/* DEVICE */}
235238
<TableCell>
236-
{isPlatformAdmin || isDeactivated || !deviceStatus ? (
239+
{isPlatformAdmin || isDeactivated ? (
240+
<Text size="sm" variant="muted">
241+
242+
</Text>
243+
) : isDeviceStatusLoading ? (
244+
<div className="h-4 w-24">
245+
<Skeleton style={{ height: '100%', width: '100%' }} />
246+
</div>
247+
) : !deviceStatus ? (
237248
<Text size="sm" variant="muted">
238249
239250
</Text>

apps/app/src/app/(app)/[orgId]/people/all/components/TeamMembersClient.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ export function TeamMembersClient({
6868
taskCompletionMap,
6969
complianceMemberIds,
7070
}: TeamMembersClientProps) {
71-
const { agentDevices } = useAgentDevices();
72-
const { fleetHosts } = useFleetHosts();
71+
const { agentDevices, isLoading: isAgentDevicesLoading } = useAgentDevices();
72+
const { fleetHosts, isLoading: isFleetHostsLoading } = useFleetHosts();
73+
const isDeviceStatusLoading = isAgentDevicesLoading || isFleetHostsLoading;
7374

7475
const deviceStatusMap = useMemo(() => {
7576
const map: Record<string, 'compliant' | 'non-compliant' | 'not-installed'> =
@@ -504,6 +505,7 @@ export function TeamMembersClient({
504505
customRoles={customRoles}
505506
taskCompletion={taskCompletionMap[(item as MemberWithUser).id]}
506507
deviceStatus={deviceStatusMap[(item as MemberWithUser).id]}
508+
isDeviceStatusLoading={isDeviceStatusLoading}
507509
/>
508510
) : (
509511
<PendingInvitationRow

apps/app/src/app/(app)/[orgId]/people/devices/components/DevicesTabContent.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { Skeleton } from '@trycompai/design-system';
34
import { useMemo } from 'react';
45
import { useAgentDevices } from '../hooks/useAgentDevices';
56
import { useFleetHosts } from '../hooks/useFleetHosts';
@@ -12,8 +13,16 @@ interface DevicesTabContentProps {
1213
}
1314

1415
export function DevicesTabContent({ isCurrentUserOwner }: DevicesTabContentProps) {
15-
const { agentDevices } = useAgentDevices();
16-
const { fleetHosts } = useFleetHosts();
16+
const {
17+
agentDevices,
18+
isLoading: isAgentLoading,
19+
error: agentError,
20+
} = useAgentDevices();
21+
const {
22+
fleetHosts,
23+
isLoading: isFleetLoading,
24+
error: fleetError,
25+
} = useFleetHosts();
1726

1827
// Filter out Fleet hosts for members who already have device-agent devices.
1928
// Device agent takes priority over Fleet.
@@ -26,6 +35,27 @@ export function DevicesTabContent({ isCurrentUserOwner }: DevicesTabContentProps
2635
);
2736
}, [agentDevices, fleetHosts]);
2837

38+
const isLoading = isAgentLoading || isFleetLoading;
39+
const error = agentError ?? fleetError;
40+
41+
if (isLoading) {
42+
return (
43+
<div className="space-y-6">
44+
<div className="my-6 h-[360px] w-full">
45+
<Skeleton style={{ height: '100%', width: '100%' }} />
46+
</div>
47+
</div>
48+
);
49+
}
50+
51+
if (error) {
52+
return (
53+
<div className="my-6 rounded-md border border-destructive/40 bg-destructive/5 p-4 text-sm text-destructive">
54+
Failed to load device data. Please try again.
55+
</div>
56+
);
57+
}
58+
2959
return (
3060
<div className="space-y-6">
3161
<DeviceComplianceChart

apps/app/src/app/api/people/fleet-hosts/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export async function GET() {
9393
{
9494
id: MDM_POLICY_ID,
9595
name: 'MDM Enabled',
96-
response: host.mdm.connected_to_fleet ? 'pass' : 'fail',
96+
response: host.mdm?.connected_to_fleet ? 'pass' : 'fail',
9797
},
9898
]
9999
: []),

0 commit comments

Comments
 (0)