diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/ArtifactsTable.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/ArtifactsTable.tsx index 6b0498456e..df5c868e28 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/ArtifactsTable.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/ArtifactsTable.tsx @@ -8,11 +8,14 @@ import { useI18n } from "@/locales/client"; import { Input } from "@comp/ui/input"; import { ColumnDef } from "@tanstack/react-table"; import { useMemo, useState } from "react"; -import type { RelatedArtifact } from "../data/getRelatedArtifacts"; import { Card, CardTitle, CardHeader, CardContent } from "@comp/ui/card"; +import { Artifact, Evidence, Policy } from "@comp/db/types"; interface ArtifactsTableProps { - artifacts: RelatedArtifact[]; + artifacts: (Artifact & { + evidence: Evidence | null; + policy: Policy | null; + })[]; orgId: string; controlId: string; } @@ -26,7 +29,14 @@ export function ArtifactsTable({ const [searchTerm, setSearchTerm] = useState(""); // Define columns for artifacts table - const columns = useMemo[]>( + const columns = useMemo< + ColumnDef< + Artifact & { + evidence: Evidence | null; + policy: Policy | null; + } + >[] + >( () => [ { accessorKey: "name", @@ -36,10 +46,24 @@ export function ArtifactsTable({ title={t("frameworks.artifacts.table.name")} /> ), - cell: ({ row }) => {row.original.name}, + cell: ({ row }) => { + const name = + row.original.type === "evidence" + ? row.original.evidence?.name + : row.original.policy?.name; + return {name}; + }, enableSorting: true, sortingFn: (rowA, rowB, columnId) => { - return rowA.original.name.localeCompare(rowB.original.name); + const nameA = + rowA.original.type === "evidence" + ? rowA.original.evidence?.name || "" + : rowA.original.policy?.name || ""; + const nameB = + rowB.original.type === "evidence" + ? rowB.original.evidence?.name || "" + : rowB.original.policy?.name || ""; + return nameA.localeCompare(nameB); }, }, { @@ -88,7 +112,11 @@ export function ArtifactsTable({ return artifacts.filter( (artifact) => artifact.id.toLowerCase().includes(searchLower) || - artifact.name.toLowerCase().includes(searchLower) || + (artifact.type === "evidence" + ? artifact.evidence?.name?.toLowerCase().includes(searchLower) || + false + : artifact.policy?.name?.toLowerCase().includes(searchLower) || + false) || artifact.type.toLowerCase().includes(searchLower), ); }, [artifacts, searchTerm]); @@ -127,8 +155,18 @@ export function ArtifactsTable({ row.id} + rowClickBasePath={`/${orgId}/`} + getRowId={(row) => { + if (row.type === "policy") { + return `/policies/${row.policyId}`; + } + + if (row.type === "evidence") { + return `/evidence/${row.evidenceId}`; + } + + return `/artifacts/${row.id}`; + }} tableId={"a"} /> diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/RequirementsTable.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/RequirementsTable.tsx index 661c5f1853..87a90c4ba9 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/RequirementsTable.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/RequirementsTable.tsx @@ -5,16 +5,20 @@ import { DataTableColumnHeader } from "@/components/data-table/data-table-column import { DataTableSortList } from "@/components/data-table/data-table-sort-list"; import { useDataTable } from "@/hooks/use-data-table"; import { useI18n } from "@/locales/client"; -import type { FrameworkId, RequirementMap } from "@comp/db/types"; +import type { + FrameworkId, + FrameworkInstance, + RequirementMap, +} from "@comp/db/types"; +import { Card, CardContent, CardHeader, CardTitle } from "@comp/ui/card"; import { Input } from "@comp/ui/input"; import { ColumnDef } from "@tanstack/react-table"; import { useMemo, useState } from "react"; +import { getFrameworkDetails } from "../../../frameworks/lib/getFrameworkDetails"; import { getRequirementDetails } from "../../../frameworks/lib/getRequirementDetails"; -import { Card, CardTitle, CardHeader } from "@comp/ui/card"; -import { CardContent } from "@comp/ui/card"; interface RequirementsTableProps { - requirements: RequirementMap[]; + requirements: (RequirementMap & { frameworkInstance: FrameworkInstance })[]; orgId: string; } @@ -26,29 +30,12 @@ export function RequirementsTable({ const [searchTerm, setSearchTerm] = useState(""); // Define columns for requirements table - const columns = useMemo[]>( + const columns = useMemo< + ColumnDef[] + >( () => [ { - accessorKey: "requirementId", - header: ({ column }) => ( - - ), - cell: ({ row }) => { - const requirementId = row.original.requirementId.split("_").pop(); - return {requirementId}; - }, - enableSorting: true, - sortingFn: (rowA, rowB, columnId) => { - const a = rowA.original.requirementId.split("_").pop() || ""; - const b = rowB.original.requirementId.split("_").pop() || ""; - return a.localeCompare(b); - }, - }, - { - accessorKey: "name", + accessorKey: "id", header: ({ column }) => ( {details?.name}; + + const frameworkDetails = getFrameworkDetails( + row.original.frameworkInstance.frameworkId, + ); + return ( + + {frameworkDetails?.name} - {details?.name} + + ); }, enableSorting: true, sortingFn: (rowA, rowB, columnId) => { @@ -147,6 +142,7 @@ export function RequirementsTable({ // Search in ID, name, and description return ( + frameworkId.toLowerCase().includes(searchLower) || requirementId.toLowerCase().includes(searchLower) || details?.name?.toLowerCase().includes(searchLower) || false || @@ -164,7 +160,7 @@ export function RequirementsTable({ shallow: false, getRowId: (row) => row.id, initialState: { - sorting: [{ id: "requirementId", desc: false }], + sorting: [{ id: "id", desc: false }], }, tableId: "r", }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/SingleControl.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/SingleControl.tsx index 4e728d5867..17c0f3a1c4 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/SingleControl.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/components/SingleControl.tsx @@ -1,24 +1,34 @@ "use client"; import { DisplayFrameworkStatus } from "@/components/frameworks/framework-status"; -import type { Control } from "@comp/db/types"; +import { useI18n } from "@/locales/client"; +import type { + Artifact, + Control, + Evidence, + FrameworkInstance, + Policy, + RequirementMap, +} from "@comp/db/types"; import { Card, CardContent, CardHeader, CardTitle } from "@comp/ui/card"; +import { useParams } from "next/navigation"; import { useMemo } from "react"; import type { ControlProgressResponse } from "../data/getOrganizationControlProgress"; -import { SingleControlSkeleton } from "./SingleControlSkeleton"; -import { useI18n } from "@/locales/client"; -import { useParams } from "next/navigation"; -import { RequirementsTable } from "./RequirementsTable"; import { ArtifactsTable } from "./ArtifactsTable"; -import type { RelatedArtifact } from "../data/getRelatedArtifacts"; -import { Separator } from "@comp/ui/separator"; +import { RequirementsTable } from "./RequirementsTable"; +import { SingleControlSkeleton } from "./SingleControlSkeleton"; interface SingleControlProps { control: Control & { - requirementsMapped: any[]; + requirementsMapped: (RequirementMap & { + frameworkInstance: FrameworkInstance; + })[]; }; controlProgress: ControlProgressResponse; - relatedArtifacts: RelatedArtifact[]; + relatedArtifacts: (Artifact & { + evidence: Evidence | null; + policy: Policy | null; + })[]; } export const SingleControl = ({ @@ -63,13 +73,10 @@ export const SingleControl = ({

{control.description}

- - - { id, }, include: { - requirementsMapped: true, + requirementsMapped: { + include: { + frameworkInstance: true, + }, + }, }, }); diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/data/getRelatedArtifacts.ts b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/data/getRelatedArtifacts.ts index e8221985ba..fff3414b48 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/data/getRelatedArtifacts.ts +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/data/getRelatedArtifacts.ts @@ -2,16 +2,10 @@ import { auth } from "@comp/auth"; import { db } from "@comp/db"; +import { Artifact, Evidence, Policy } from "@comp/db/types"; import { headers } from "next/headers"; import { cache } from "react"; -export interface RelatedArtifact { - id: string; - name: string; - type: string; - createdAt: string; -} - interface GetRelatedArtifactsParams { organizationId: string; controlId: string; @@ -21,7 +15,12 @@ export const getRelatedArtifacts = cache( async ({ organizationId, controlId, - }: GetRelatedArtifactsParams): Promise => { + }: GetRelatedArtifactsParams): Promise< + (Artifact & { + evidence: Evidence | null; + policy: Policy | null; + })[] + > => { try { const session = await auth.api.getSession({ headers: await headers(), @@ -52,27 +51,9 @@ export const getRelatedArtifacts = cache( } // Transform the artifacts into the format expected by the UI - return control.artifacts.map((artifact) => { - let name = "Unknown"; - let displayType = artifact.type; - - if (artifact.policy) { - name = artifact.policy.name; - displayType = "policy"; - } else if (artifact.evidence) { - name = artifact.evidence.name; - displayType = "evidence"; - } - - return { - id: artifact.id, - name, - type: displayType, - createdAt: artifact.createdAt.toISOString(), - }; - }); + return control.artifacts; } catch (error) { - console.error("Error fetching related artifacts:", error); + console.error("Error fetching Linked Artifacts:", error); return []; } }, diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/page.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/page.tsx index 044cc750ff..76b8694424 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/page.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/page.tsx @@ -6,7 +6,7 @@ import { getOrganizationControlProgress } from "./data/getOrganizationControlPro import type { ControlProgressResponse } from "./data/getOrganizationControlProgress"; import { headers } from "next/headers"; import PageWithBreadcrumb from "@/components/pages/PageWithBreadcrumb"; -import { getRelatedArtifacts } from "./data/getRelatedArtifacts"; +import { getRelatedArtifacts } from "@/app/[locale]/(app)/(dashboard)/[orgId]/controls/[controlId]/data/getRelatedArtifacts"; interface ControlPageProps { params: { diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/components/controls-table-columns.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/components/controls-table-columns.tsx index 12eff489ba..cba15d9871 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/components/controls-table-columns.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/controls/components/controls-table-columns.tsx @@ -69,7 +69,7 @@ export function getControlColumns(): ColumnDef< id: "mappedRequirements", accessorKey: "mappedRequirements", header: ({ column }) => ( - + ), cell: ({ row }) => { const control = row.original; @@ -94,8 +94,8 @@ export function getControlColumns(): ColumnDef< ); }, meta: { - label: "Mapped Requirements", - placeholder: "Search mapped requirements...", + label: "Linked Requirements", + placeholder: "Search Linked Requirements...", variant: "text", }, }, diff --git a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/[evidenceId]/components/EvidenceDetails.tsx b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/[evidenceId]/components/EvidenceDetails.tsx index 09fc3f9426..639253827d 100644 --- a/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/[evidenceId]/components/EvidenceDetails.tsx +++ b/apps/app/src/app/[locale]/(app)/(dashboard)/[orgId]/evidence/[evidenceId]/components/EvidenceDetails.tsx @@ -16,13 +16,6 @@ export function EvidenceDetails({ assignees, evidence }: EvidenceDetailsProps) { in compliance reports. )} - - - {evidence.name} Evidence - - {evidence.description || "No description provided."} - -
-

Evidence Overview

+

{evidence.name}

- Manage review frequency, department assignment, and track upcoming - review dates + {evidence.description}

diff --git a/apps/app/src/components/data-table/data-table-sort-list.tsx b/apps/app/src/components/data-table/data-table-sort-list.tsx index 40f517f05a..d3d0b2b267 100644 --- a/apps/app/src/components/data-table/data-table-sort-list.tsx +++ b/apps/app/src/components/data-table/data-table-sort-list.tsx @@ -152,12 +152,6 @@ export function DataTableSortList({ for (const column of table.getAllColumns()) { if (!column.getCanSort()) continue; - // Debug column definitions - console.log(`Column ID: ${column.id}`, { - meta: column.columnDef.meta, - def: column.columnDef, - }); - // Use a safe way to get the label let label = column.columnDef.meta?.label; if (!label) { @@ -171,11 +165,6 @@ export function DataTableSortList({ } } - // Debug all labels and available columns - console.log("Column Labels:", Object.fromEntries(labels)); - console.log("Available Columns:", availableColumns); - console.log("Current Sorting:", sorting); - return { columnLabels: labels, columns: availableColumns, diff --git a/apps/app/src/locales/features/controls.ts b/apps/app/src/locales/features/controls.ts index f58e4791a6..71183ec873 100644 --- a/apps/app/src/locales/features/controls.ts +++ b/apps/app/src/locales/features/controls.ts @@ -14,6 +14,6 @@ export const controls = { no_requirements_mapped: "No requirements mapped to this control.", }, artifacts: { - no_artifacts: "No related artifacts found", + no_artifacts: "No Linked Artifacts found", }, } as const; diff --git a/apps/app/src/locales/features/frameworks.ts b/apps/app/src/locales/features/frameworks.ts index 19e7cfc779..02a66fe0d1 100644 --- a/apps/app/src/locales/features/frameworks.ts +++ b/apps/app/src/locales/features/frameworks.ts @@ -39,7 +39,7 @@ export const frameworks = { control: "Control", artifacts: "Artifacts", actions: "Actions", - requirements: "Mapped Requirements", + requirements: "Linked Requirements", }, statuses: { completed: "Completed", @@ -49,12 +49,14 @@ export const frameworks = { }, requirements: { requirement: "Requirement", - title: "Requirements", + title: "Linked Requirements", description: "Review and manage compliance requirements", table: { id: "ID", name: "Name", description: "Description", + frameworkId: "Framework", + requirementId: "Requirement ID", }, search: { id_placeholder: "Search by ID...", @@ -64,7 +66,7 @@ export const frameworks = { }, }, artifacts: { - title: "Related Artifacts", + title: "Linked Artifacts", table: { id: "ID", name: "Name", @@ -77,6 +79,6 @@ export const frameworks = { type_placeholder: "Filter by type...", universal_placeholder: "Search artifacts...", }, - no_artifacts: "No related artifacts found", + no_artifacts: "No Linked Artifacts found", }, } as const;