From fa781d08f5ce41b9802f6b92923da5558725a210 Mon Sep 17 00:00:00 2001 From: kenilkb Date: Thu, 16 Jul 2026 12:30:11 +0530 Subject: [PATCH] Feat: Auto-check all assets by default, show unified asset count in table, display read-only inherited assets in modal --- .../src/controllers/auth.controller.ts | 2 +- Channel-Backend/src/services/auth.service.ts | 2 +- .../src/pages/admin/DirectoryPage.tsx | 120 +++++++++++++----- 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/Channel-Backend/src/controllers/auth.controller.ts b/Channel-Backend/src/controllers/auth.controller.ts index 5becd37..21eb797 100644 --- a/Channel-Backend/src/controllers/auth.controller.ts +++ b/Channel-Backend/src/controllers/auth.controller.ts @@ -59,7 +59,7 @@ export class AuthController { }).parse(req.body); const result = await this.authService.updatePartner(partnerId, { - partnerGroup: partnerGroup === null ? undefined : partnerGroup, + partnerGroup: (partnerGroup === null || partnerGroup === '') ? null : partnerGroup, assignedNdaId: assignedNdaId === null ? undefined : assignedNdaId, assignedMsaId: assignedMsaId === null ? undefined : assignedMsaId, sharedAssetIds, diff --git a/Channel-Backend/src/services/auth.service.ts b/Channel-Backend/src/services/auth.service.ts index 4c0f201..898ed71 100644 --- a/Channel-Backend/src/services/auth.service.ts +++ b/Channel-Backend/src/services/auth.service.ts @@ -137,7 +137,7 @@ export class AuthService { return { inviteToken, emailSent, emailError }; } - public async updatePartner(partnerId: string, options: { partnerGroup?: string, assignedNdaId?: string, assignedMsaId?: string, sharedAssetIds?: string[], mfaEnabled?: boolean }) { + public async updatePartner(partnerId: string, options: { partnerGroup?: string | null, assignedNdaId?: string | null, assignedMsaId?: string | null, sharedAssetIds?: string[], mfaEnabled?: boolean }) { const user = await prisma.user.findUnique({ where: { id: partnerId } }); diff --git a/Channel-Frontend/src/pages/admin/DirectoryPage.tsx b/Channel-Frontend/src/pages/admin/DirectoryPage.tsx index 577f661..5359234 100644 --- a/Channel-Frontend/src/pages/admin/DirectoryPage.tsx +++ b/Channel-Frontend/src/pages/admin/DirectoryPage.tsx @@ -15,6 +15,7 @@ import { Copy, Trash2, Plus, + Lock, } from "lucide-react"; import { motion } from "framer-motion"; import { Link } from "react-router-dom"; @@ -154,7 +155,10 @@ export const DirectoryPage: React.FC = () => { const [partnerAssetToRemove, setPartnerAssetToRemove] = useState<{ id: string, title: string } | null>(null); useEffect(() => { - getAssets().then(setAllAssets).catch(console.error); + getAssets().then((assets) => { + setAllAssets(assets); + setSelectedAssetIds(assets.map(a => a.id)); + }).catch(console.error); getLegalDocuments().then(setAllDocs).catch(console.error); getAssetGroups().then(setAssetGroups).catch(console.error); }, []); @@ -560,6 +564,12 @@ export const DirectoryPage: React.FC = () => { onClick={() => { setInviteResult(null); setEmail(""); + setPartnerGroup(""); + setAssignedNdaId(""); + setAssignedMsaId(""); + setMfaRequired(true); + setSelectedAssetIds(allAssets.map(a => a.id)); + setInviteAssetSearch(""); setIsInviteOpen(true); }} variant="primary" @@ -740,6 +750,7 @@ export const DirectoryPage: React.FC = () => { ) : ( paginatedPartners.map((partner) => { const sc = getStatusConfig(partner.onboardingStatus); + const pGroup = partner.partnerGroup; return ( { setSelectedPartnerForAssets(partner); setIsPartnerAssetsOpen(true); }} - className="text-xs font-bold text-ink-700 hover:text-ink-950 hover:underline cursor-pointer focus:outline-none" + className="text-xs font-bold text-ink-700 hover:text-ink-950 hover:underline cursor-pointer focus:outline-none flex flex-col items-start gap-0.5" > - {partner.sharedAssets?.length || 0} assets + + {((partner.sharedAssets?.length || 0) + (pGroup ? (assetGroups.find(g => g.name.trim().toLowerCase() === pGroup.trim().toLowerCase())?.assets?.length || 0) : 0))} assets + + {pGroup && assetGroups.some(g => g.name.trim().toLowerCase() === pGroup.trim().toLowerCase()) && ( + + Includes {pGroup} Group + + )} @@ -971,19 +989,30 @@ export const DirectoryPage: React.FC = () => { ) : ( /* Current Shared Assets List */ - (!selectedPartnerForAssets?.sharedAssets || selectedPartnerForAssets.sharedAssets.length === 0) ? ( -
- -

No assets shared

-

There are no assets currently assigned to this partner.

-
- ) : ( -
- {selectedPartnerForAssets.sharedAssets.map((item: any) => { - const asset = item.asset; - if (!asset) return null; - return ( -
+ /* Current Shared Assets List */ + (() => { + const matchedGroup = selectedPartnerForAssets?.partnerGroup + ? assetGroups.find(g => g.name.trim().toLowerCase() === selectedPartnerForAssets.partnerGroup.trim().toLowerCase()) + : null; + const inheritedAssets = matchedGroup ? matchedGroup.assets : []; + const directAssets = selectedPartnerForAssets?.sharedAssets || []; + const totalCount = directAssets.length + inheritedAssets.length; + + if (totalCount === 0) { + return ( +
+ +

No assets shared

+

There are no assets currently assigned to this partner.

+
+ ); + } + + return ( +
+ {/* Group Inherited Assets */} + {inheritedAssets.map((asset: any) => ( +
{getFileIcon(asset.type || '', asset.title)}
@@ -992,26 +1021,53 @@ export const DirectoryPage: React.FC = () => { {asset.categoryId || 'General'} - {asset.subcategory && ( - - {asset.subcategory} - - )} + + Inherited ({selectedPartnerForAssets?.partnerGroup}) +
- +
+ +
- ); - })} -
- ) + ))} + + {/* Direct Shared Assets */} + {directAssets.map((item: any) => { + const asset = item.asset; + if (!asset) return null; + return ( +
+
+ {getFileIcon(asset.type || '', asset.title)} +
+

{asset.title}

+
+ + {asset.categoryId || 'General'} + + {asset.subcategory && ( + + {asset.subcategory} + + )} +
+
+
+ +
+ ); + })} +
+ ); + })() )}