-
Notifications
You must be signed in to change notification settings - Fork 321
Mariano/stuff #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mariano/stuff #74
Changes from all commits
f65024d
7bb25e2
b401cf6
adcf0be
766ee6a
4ec298c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "use server"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { db, type Policy, type User } from "@bubba/db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { db, RequirementType, type Policy, type User } from "@bubba/db"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { authActionClient } from "../safe-action"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { z } from "zod"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { ActionData } from "../types"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -30,25 +30,28 @@ export const selectFrameworksAction = authActionClient | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // First create categories | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create categories | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await createOrganizationCategories(user as User, frameworkIds); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Then create frameworks and controls | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create frameworks and controls | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const organizationFrameworks = await Promise.all( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| frameworkIds.map((frameworkId) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createOrganizationFramework(user as User, frameworkId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Finally create policies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create policies | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await createOrganizationPolicy(user as User, frameworkIds); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Finally create control requirements | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create control requirements | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await createOrganizationControlRequirements( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user as User, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| organizationFrameworks.map((framework) => framework.id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create organization evidence | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await createOrganizationEvidence(user as User); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -244,3 +247,26 @@ const createOrganizationControlRequirements = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return controlRequirements; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const createOrganizationEvidence = async (user: User) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!user.organizationId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error("Not authorized - no organization found"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const evidence = await db.controlRequirement.findMany({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| where: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: RequirementType.evidence, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const organizationEvidence = await db.organizationEvidence.createMany({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data: evidence.map((evidence) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| organizationId: user.organizationId!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| evidenceId: evidence.id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: evidence.name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: evidence.description, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return organizationEvidence; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+251
to
+272
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Optimize database operations in createOrganizationEvidence. The function could be optimized to:
const createOrganizationEvidence = async (user: User) => {
if (!user.organizationId) {
throw new Error("Not authorized - no organization found");
}
+ const BATCH_SIZE = 1000;
+
+ try {
+ return await db.$transaction(async (tx) => {
const evidence = await tx.controlRequirement.findMany({
where: {
type: RequirementType.evidence,
},
});
+
+ const chunks = [];
+ for (let i = 0; i < evidence.length; i += BATCH_SIZE) {
+ chunks.push(evidence.slice(i, i + BATCH_SIZE));
+ }
+
+ const results = await Promise.all(
+ chunks.map((chunk) =>
+ tx.organizationEvidence.createMany({
+ data: chunk.map((evidence) => ({
+ organizationId: user.organizationId!,
+ evidenceId: evidence.id,
+ name: evidence.name,
+ description: evidence.description,
+ })),
+ })
+ )
+ );
+
+ return results.reduce(
+ (acc, result) => ({
+ count: acc.count + result.count,
+ }),
+ { count: 0 }
+ );
+ });
+ } catch (error) {
+ console.error("Error creating organization evidence:", error);
+ throw new Error("Failed to create organization evidence");
+ }
};📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| "use client"; | ||
|
|
||
| import type { ColumnDef } from "@tanstack/react-table"; | ||
| import { CheckCircle2, XCircle } from "lucide-react"; | ||
|
|
||
| export interface RequirementType { | ||
| id: string; | ||
| type: string; | ||
| description: string | null; | ||
| organizationPolicy?: { | ||
| policy?: { | ||
| id: string; | ||
| name: string; | ||
| }; | ||
| status?: string; | ||
| } | null; | ||
| } | ||
|
|
||
| export const columns: ColumnDef<RequirementType>[] = [ | ||
| { | ||
| id: "type", | ||
| accessorKey: "type", | ||
| header: "Type", | ||
| cell: ({ row }) => row.original.type, | ||
| }, | ||
| { | ||
| id: "description", | ||
| accessorKey: "description", | ||
| header: "Description", | ||
| cell: ({ row }) => ( | ||
| <div className="truncate">{row.original.description}</div> | ||
| ), | ||
| }, | ||
| { | ||
| id: "status", | ||
| accessorKey: "organizationPolicy.status", | ||
| header: "Status", | ||
| cell: ({ row }) => { | ||
| const requirement = row.original; | ||
| const isCompleted = | ||
| requirement.type === "policy" | ||
| ? requirement.organizationPolicy?.status === "published" | ||
| : false; | ||
|
|
||
| return ( | ||
| <div className="flex items-center justify-center"> | ||
| {isCompleted ? ( | ||
| <CheckCircle2 size={16} className="text-green-500" /> | ||
| ) : ( | ||
| <XCircle size={16} className="text-red-500" /> | ||
| )} | ||
| </div> | ||
| ); | ||
| }, | ||
| }, | ||
| ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| "use client"; | ||
|
|
||
| import { TableHead, TableHeader, TableRow } from "@bubba/ui/table"; | ||
|
|
||
| type Props = { | ||
| table?: { | ||
| getIsAllPageRowsSelected: () => boolean; | ||
| getIsSomePageRowsSelected: () => boolean; | ||
| getAllLeafColumns: () => { | ||
| id: string; | ||
| getIsVisible: () => boolean; | ||
| }[]; | ||
| toggleAllPageRowsSelected: (value: boolean) => void; | ||
| }; | ||
| loading?: boolean; | ||
| }; | ||
|
|
||
| export function DataTableHeader({ table, loading }: Props) { | ||
| const isVisible = (id: string) => | ||
| loading || | ||
| table | ||
| ?.getAllLeafColumns() | ||
| .find((col) => col.id === id) | ||
| ?.getIsVisible(); | ||
|
|
||
| return ( | ||
| <TableHeader> | ||
| <TableRow className="hover:bg-transparent"> | ||
| {isVisible("type") && ( | ||
| <TableHead className="h-11 px-4 text-left align-middle font-medium"> | ||
| Type | ||
| </TableHead> | ||
| )} | ||
| {isVisible("description") && ( | ||
| <TableHead className="h-11 px-4 text-left align-middle font-medium"> | ||
| Description | ||
| </TableHead> | ||
| )} | ||
| {isVisible("status") && ( | ||
| <TableHead className="h-11 px-4 text-left align-middle font-medium"> | ||
| Status | ||
| </TableHead> | ||
| )} | ||
| </TableRow> | ||
| </TableHeader> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| "use client"; | ||
|
|
||
| import { | ||
| flexRender, | ||
| getCoreRowModel, | ||
| useReactTable, | ||
| } from "@tanstack/react-table"; | ||
|
|
||
| import { Table, TableBody, TableCell, TableRow } from "@bubba/ui/table"; | ||
| import { type RequirementType, columns } from "./columns"; | ||
| import { DataTableHeader } from "./data-table-header"; | ||
| import { useRouter } from "next/navigation"; | ||
|
|
||
| interface DataTableProps { | ||
| data: RequirementType[]; | ||
| } | ||
|
|
||
| export function DataTable({ data }: DataTableProps) { | ||
| const router = useRouter(); | ||
|
|
||
| const table = useReactTable({ | ||
| data, | ||
| columns, | ||
| getCoreRowModel: getCoreRowModel(), | ||
| }); | ||
|
|
||
| const onRowClick = (requirement: RequirementType) => { | ||
| if ( | ||
| requirement.type === "policy" && | ||
| requirement.organizationPolicy?.policy?.id | ||
| ) { | ||
| router.push(`/policies/${requirement.organizationPolicy.policy.id}`); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="relative w-full"> | ||
| <div className="overflow-auto rounded-md border"> | ||
| <Table> | ||
| <DataTableHeader table={table} /> | ||
| <TableBody> | ||
| {table.getRowModel().rows?.length ? ( | ||
| table.getRowModel().rows.map((row) => ( | ||
| <TableRow | ||
| key={row.id} | ||
| data-state={row.getIsSelected() && "selected"} | ||
| className="hover:bg-muted/50 cursor-pointer" | ||
| onClick={() => onRowClick(row.original)} | ||
| > | ||
| {row.getVisibleCells().map((cell) => ( | ||
| <TableCell key={cell.id} className="p-4"> | ||
| {flexRender( | ||
| cell.column.columnDef.cell, | ||
| cell.getContext() | ||
| )} | ||
| </TableCell> | ||
| ))} | ||
| </TableRow> | ||
| )) | ||
| ) : ( | ||
| <TableRow> | ||
| <TableCell | ||
| colSpan={columns.length} | ||
| className="h-24 text-center" | ||
| > | ||
| No requirements found. | ||
| </TableCell> | ||
| </TableRow> | ||
| )} | ||
| </TableBody> | ||
| </Table> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider handling partial failures in framework selection.
The evidence creation step could fail independently of other steps. Consider implementing a rollback mechanism or handling partial failures.
🏁 Script executed:
Length of output: 3199
Action Required: Enhance Failure Handling for Evidence Creation
createOrganizationEvidence(user as User)without protecting the operation within a transactional block or explicit error handling.db.$transactionto ensure rollback on failures. Consider adopting a similar approach here or implementing dedicated error handling to manage potential partial failures during framework selection.