Skip to content

Commit f79a401

Browse files
authored
Merge pull request #580 from trycompai/main
[comp] Production Deploy
2 parents 1044494 + c85c50c commit f79a401

File tree

9 files changed

+73
-10
lines changed

9 files changed

+73
-10
lines changed

apps/framework-editor/app/(pages)/frameworks/[frameworkId]/FrameworkRequirementsClientPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function FrameworkRequirementsClientPage({
5757
setIsEditRequirementDialogOpen(true);
5858
};
5959

60-
const handleRequirementUpdated = (updatedRequirement: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description'>) => {
60+
const handleRequirementUpdated = (updatedRequirement: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description' | 'identifier'>) => {
6161
setRequirementsList(prevList =>
6262
prevList.map(req =>
6363
req.id === updatedRequirement.id ? { ...req, ...updatedRequirement } : req

apps/framework-editor/app/(pages)/frameworks/[frameworkId]/actions/add-requirement-action.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { FrameworkEditorRequirement } from '@prisma/client';
99
const AddRequirementSchema = z.object({
1010
name: z.string().min(3, { message: 'Requirement name must be at least 3 characters long' }),
1111
description: z.string().optional(), // Description can be optional
12+
identifier: z.string().optional(), // Identifier can be optional
1213
frameworkId: z.string().min(1, { message: 'Framework ID is required' }),
1314
});
1415

@@ -27,6 +28,7 @@ export async function addRequirementAction(
2728
const rawInput = {
2829
name: formData.get('name'),
2930
description: formData.get('description'),
31+
identifier: formData.get('identifier'),
3032
frameworkId: formData.get('frameworkId'),
3133
};
3234

@@ -40,13 +42,14 @@ export async function addRequirementAction(
4042
};
4143
}
4244

43-
const { name, description, frameworkId } = validationResult.data;
45+
const { name, description, identifier, frameworkId } = validationResult.data;
4446

4547
try {
4648
const newRequirement = await db.frameworkEditorRequirement.create({
4749
data: {
4850
name,
4951
description: description || '', // Ensure description is at least an empty string if optional and not provided
52+
identifier: identifier || '', // Ensure identifier is at least an empty string if optional and not provided
5053
framework: {
5154
connect: { id: frameworkId },
5255
},

apps/framework-editor/app/(pages)/frameworks/[frameworkId]/components/AddRequirementDialog.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export function AddRequirementDialog({ isOpen, onOpenChange, frameworkId, onRequ
4040
const [formState, formAction, isPending] = useActionState(addRequirementAction, initialFormState);
4141
const [name, setName] = useState('');
4242
const [description, setDescription] = useState('');
43+
const [identifier, setIdentifier] = useState('');
4344

4445
useEffect(() => {
4546
if (formState.success && formState.data) {
@@ -50,6 +51,7 @@ export function AddRequirementDialog({ isOpen, onOpenChange, frameworkId, onRequ
5051
onRequirementAdded(); // Close dialog and refresh list
5152
setName(''); // Reset local state
5253
setDescription('');
54+
setIdentifier('');
5355
// The form itself will reset due to the key change on next open if desired, or if onOpenChange triggers a reset
5456
} else if (!formState.success && (formState.error || formState.issues)) {
5557
const issueMessages = formState.issues?.map(i => `${i.path.join('.')} : ${i.message}`).join('; ') || '';
@@ -66,6 +68,7 @@ export function AddRequirementDialog({ isOpen, onOpenChange, frameworkId, onRequ
6668
// Reset form fields and formState when dialog is opened
6769
setName('');
6870
setDescription('');
71+
setIdentifier('');
6972
setFormKey(Date.now()); // Reset form state by changing key, ensuring useFormState re-initializes
7073
} else {
7174
// If dialog is closed ensure parent knows
@@ -111,6 +114,25 @@ export function AddRequirementDialog({ isOpen, onOpenChange, frameworkId, onRequ
111114
</p>
112115
)}
113116
</div>
117+
<div className="grid grid-cols-4 items-center gap-4">
118+
<Label htmlFor={`identifier-${frameworkId}`} className="text-right">
119+
Identifier
120+
</Label>
121+
<Input
122+
id={`identifier-${frameworkId}`}
123+
name="identifier"
124+
value={identifier}
125+
onChange={(e) => setIdentifier(e.target.value)}
126+
className="col-span-3"
127+
placeholder="e.g., cc1-1"
128+
disabled={isPending}
129+
/>
130+
{formState.issues?.find(issue => issue.path.includes('identifier')) && (
131+
<p className="col-span-4 text-sm text-destructive text-right">
132+
{formState.issues.find(issue => issue.path.includes('identifier'))?.message}
133+
</p>
134+
)}
135+
</div>
114136
<div className="grid grid-cols-4 items-center gap-4">
115137
<Label htmlFor={`description-${frameworkId}`} className="text-right">
116138
Description

apps/framework-editor/app/(pages)/frameworks/[frameworkId]/components/EditRequirementDialog.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import { RequirementBaseSchema } from '../../schemas'
2121
interface EditRequirementDialogProps {
2222
isOpen: boolean
2323
onOpenChange: (isOpen: boolean) => void
24-
requirement: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description'> & { frameworkId: string }
25-
onRequirementUpdated?: (updatedData: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description'>) => void
24+
requirement: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description' | 'identifier'> & { frameworkId: string }
25+
onRequirementUpdated?: (updatedData: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description' | 'identifier'>) => void
2626
}
2727

2828
const requirementFormSchema = RequirementBaseSchema;
@@ -40,6 +40,7 @@ export function EditRequirementDialog({
4040
defaultValues: {
4141
name: requirement.name,
4242
description: requirement.description ?? '',
43+
identifier: requirement.identifier ?? '',
4344
},
4445
mode: 'onChange',
4546
})
@@ -48,6 +49,7 @@ export function EditRequirementDialog({
4849
form.reset({
4950
name: requirement.name,
5051
description: requirement.description ?? '',
52+
identifier: requirement.identifier ?? '',
5153
})
5254
}, [requirement, form])
5355

@@ -59,6 +61,9 @@ export function EditRequirementDialog({
5961
if (values.description) {
6062
formData.append('description', values.description);
6163
}
64+
if (values.identifier) {
65+
formData.append('identifier', values.identifier);
66+
}
6267

6368
const result = await updateRequirementAction(null, formData);
6469

@@ -91,6 +96,7 @@ export function EditRequirementDialog({
9196
form.reset({
9297
name: requirement.name,
9398
description: requirement.description ?? '',
99+
identifier: requirement.identifier ?? '',
94100
});
95101
}
96102
onOpenChange(open);
@@ -119,6 +125,21 @@ export function EditRequirementDialog({
119125
</FormItem>
120126
)}
121127
/>
128+
<FormField
129+
control={form.control}
130+
name="identifier"
131+
render={({ field }) => (
132+
<FormItem className="grid grid-cols-4 items-center gap-2">
133+
<FormLabel className="text-right">Identifier</FormLabel>
134+
<FormControl className="col-span-3">
135+
<Input placeholder="e.g., cc1-1" {...field} />
136+
</FormControl>
137+
<div className="col-start-2 col-span-3">
138+
<FormMessage />
139+
</div>
140+
</FormItem>
141+
)}
142+
/>
122143
<FormField
123144
control={form.control}
124145
name="description"

apps/framework-editor/app/(pages)/frameworks/[frameworkId]/components/columns.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,18 @@ export function getColumns(
2121
onDelete: (requirement: FrameworkEditorRequirement) => void
2222
): ColumnDef<FrameworkEditorRequirement>[] {
2323
return [
24+
{
25+
accessorKey: "identifier",
26+
header: "Identifier",
27+
size: 150,
28+
cell: ({ row }) => {
29+
const identifier = row.getValue("identifier") as string;
30+
return identifier || "-";
31+
},
32+
},
2433
{
2534
accessorKey: "name",
26-
header: "Requirement ID / Name",
35+
header: "Name",
2736
size: 250,
2837
cell: ({ row }) => row.getValue("name"),
2938
},

apps/framework-editor/app/(pages)/frameworks/actions/update-requirement-action.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const UpdateRequirementSchema = RequirementBaseSchema.extend({
1313

1414
export interface UpdateRequirementActionState {
1515
success: boolean
16-
data?: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description'>
16+
data?: Pick<FrameworkEditorRequirement, 'id' | 'name' | 'description' | 'identifier'>
1717
error?: string
1818
issues?: z.ZodIssue[]
1919
}
@@ -26,6 +26,7 @@ export async function updateRequirementAction(
2626
id: formData.get('id'),
2727
name: formData.get('name'),
2828
description: formData.get('description'),
29+
identifier: formData.get('identifier'),
2930
frameworkId: formData.get('frameworkId')
3031
}
3132

@@ -39,7 +40,7 @@ export async function updateRequirementAction(
3940
}
4041
}
4142

42-
const { id, name, description, frameworkId } = validationResult.data
43+
const { id, name, description, identifier, frameworkId } = validationResult.data
4344

4445
try {
4546
const existingRequirement = await db.frameworkEditorRequirement.findUnique({
@@ -55,11 +56,13 @@ export async function updateRequirementAction(
5556
data: {
5657
name,
5758
description: description,
59+
identifier: identifier || '',
5860
},
5961
select: {
6062
id: true,
6163
name: true,
6264
description: true,
65+
identifier: true,
6366
}
6467
});
6568

apps/framework-editor/app/(pages)/frameworks/schemas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export const FrameworkBaseSchema = z.object({
99
export const RequirementBaseSchema = z.object({
1010
name: z.string().min(1, { message: "Requirement name is required." }),
1111
description: z.string().optional(), // Assuming description can be optional
12+
identifier: z.string().optional(), // Identifier is optional
1213
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- DropIndex
2+
DROP INDEX "FrameworkEditorRequirement_frameworkId_name_key";
3+
4+
-- AlterTable
5+
ALTER TABLE "FrameworkEditorRequirement" ADD COLUMN "identifier" TEXT NOT NULL DEFAULT '';

packages/db/prisma/schema/framework-editor.prisma

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,11 @@ model FrameworkEditorRequirement {
2121
frameworkId String
2222
framework FrameworkEditorFramework @relation(fields: [frameworkId], references: [id])
2323
24-
name String // Original requirement ID within that framework, e.g., "CC1.1"
24+
name String // Original requirement ID within that framework, e.g., "Privacy"
25+
identifier String @default("") // Unique identifier for the requirement, e.g., "cc1-1"
2526
description String
2627
2728
controlTemplates FrameworkEditorControlTemplate[]
28-
29-
@@unique([frameworkId, name])
3029
}
3130

3231
model FrameworkEditorPolicyTemplate {

0 commit comments

Comments
 (0)