Skip to content

feat: Create Policies#138

Merged
carhartlewis merged 2 commits into
mainfrom
lewis/policy-editor
Mar 16, 2025
Merged

feat: Create Policies#138
carhartlewis merged 2 commits into
mainfrom
lewis/policy-editor

Conversation

@carhartlewis

@carhartlewis carhartlewis commented Mar 16, 2025

Copy link
Copy Markdown
Contributor

Added the ability to create custom policies

Summary by CodeRabbit

  • New Features

    • Introduced a streamlined workflow for creating policies using an interactive form and responsive modal that adapts for both desktop and mobile.
    • Enabled direct policy creation from the toolbar with updated buttons and real-time notifications for success or error.
    • Enhanced user guidance through updated localized messages across multiple languages.
  • Style

    • Made subtle visual adjustments to components for a more consistent look and feel.

carhartlewis and others added 2 commits March 16, 2025 15:15
@vercel

vercel Bot commented Mar 16, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 16, 2025 7:21pm
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
comp-portal ⬜️ Skipped (Inspect) Mar 16, 2025 7:21pm

@coderabbitai

coderabbitai Bot commented Mar 16, 2025

Copy link
Copy Markdown

Walkthrough

This pull request introduces a suite of features centered on policy creation. A new action (createPolicyAction) and its corresponding schema (createPolicySchema) are added to handle policy creation in the backend with authentication and validation. On the frontend, new components for creating policies—a form (CreateNewPolicyForm) and a responsive modal (CreatePolicySheet)—are introduced, along with updates to the toolbar to trigger this modal rather than navigating away. Additionally, minor stylistic adjustments are applied and localized text updates enhance international messaging.

Changes

File(s) Change Summary
apps/app/src/actions/policies/create-new-policy.ts Introduces createPolicyAction that validates user authentication, creates a new policy in the database, establishes an organization relationship, and handles errors and revalidation.
apps/app/src/actions/schema.ts Updates code indentation (from spaces to tabs) and adds the new createPolicySchema for policy creation input validation.
apps/app/src/app/.../SingleControlSkeleton.tsx Adjusts JSX structure by removing the rounded-md class and refining indentation for consistent styling.
apps/app/src/components/forms/policies/create-new-policy.tsx Adds the new CreateNewPolicyForm component utilizing Bubba UI and react-hook-form to capture policy details and trigger the creation action with appropriate notifications.
apps/app/src/components/sheets/create-policy-sheet.tsx Introduces the CreatePolicySheet component, which renders a modal (Sheet on desktop and Drawer on mobile) for policy creation, with responsive state management and internationalization.
apps/app/src/components/tables/policies/filter-toolbar.tsx Modifies the toolbar to replace a navigation link with a Button that opens the CreatePolicySheet, integrating new imports and state from navigation hooks.
apps/app/src/locales/{en,es,fr,no,pt}.ts Adds a new "new" section to the policies object in multiple localization files with keys for success, error, details, title, and description messages for policy creation.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant T as FilterToolbar
    participant S as CreatePolicySheet
    participant F as CreateNewPolicyForm
    participant A as createPolicyAction
    participant DB as Database
    participant UI as NotificationSystem

    U->>T: Click "Create Policy" button
    T->>S: Set open state to true
    S->>F: Render policy creation form
    U->>F: Fill and submit form data
    F->>A: Call createPolicyAction with form data
    A->>DB: Insert new policy record
    DB-->>A: Return success or error response
    A-->>F: Pass result (success/error)
    F->>UI: Display toast notification (success/error)
Loading

Possibly related PRs

Poem

I'm a little rabbit, so thrilled and light,
Hopping through code changes from morning to night.
Policies now spring to life with a graceful leap,
Forms and modals where our new features sleep.
With each streamlined line, I twirl and cheer—
CodeRabbit dances as changes appear!
🐰 Happy hops and code, oh so dear!

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@carhartlewis

Copy link
Copy Markdown
Contributor Author

Shipped from 39,000 feet

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
apps/app/src/actions/schema.ts (1)

271-276: Add validation constraints to the createPolicySchema.

While the schema structure is appropriate, it lacks validation constraints that are present in other schemas in this file.

Consider adding validation constraints for improved data integrity and consistent user feedback:

export const createPolicySchema = z.object({
-	title: z.string(),
-	description: z.string(),
+	title: z.string({
+		required_error: "Policy title is required",
+	}).min(1, {
+		message: "Policy title should be at least 1 character",
+	}).max(100, {
+		message: "Policy title should be at most 100 characters",
+	}),
+	description: z.string({
+		required_error: "Policy description is required",
+	}).min(1, {
+		message: "Policy description should be at least 1 character",
+	}).max(255, {
+		message: "Policy description should be at most 255 characters",
+	}),
	frameworkIds: z.array(z.string()),
	controlIds: z.array(z.string()),
});
apps/app/src/components/sheets/create-policy-sheet.tsx (1)

23-45: Fix potentially invalid Tailwind class in desktop view.

The component handles desktop view appropriately with a Sheet component, but there's a potential issue with the Tailwind classes used.

The size-auto class in line 32 might not be a standard Tailwind class. Consider replacing it with more standard sizing classes:

<Button
  size="icon"
  variant="ghost"
- className="p-0 m-0 size-auto hover:bg-transparent"
+ className="p-0 m-0 h-auto w-auto hover:bg-transparent"
  onClick={() => setOpen(null)}
>
apps/app/src/actions/policies/create-new-policy.ts (3)

21-26: Ensure uniqueness for title used as a slug.

Currently, the slug field is directly set to the title, which may lead to potential collisions if different policies share the same title. Consider implementing a slug-generation strategy (e.g., appending random suffixes, or using a library like slugify) to ensure uniqueness and avoid conflicts.


47-55: Consider customizing default department and frequency.

Hard-coding Departments.none and Frequency.monthly might not always be suitable. If these defaults can vary by organization or context, it might be more flexible to either accept them from user input (with safe defaults) or store them in a configuration file.


65-71: Enhance error handling details.

For debugging or user feedback, consider including the exact error message (e.g., error.message) rather than returning a generic "Failed to create policy" message. This will simplify troubleshooting issues in both development and production.

 console.error(error);
 return {
-  success: false,
-  error: "Failed to create policy",
+  success: false,
+  error: error instanceof Error ? error.message : "Failed to create policy",
 };
apps/app/src/components/tables/policies/filter-toolbar.tsx (2)

128-132: Unify button label for consistent UX.

The label is set to t("common.actions.addNew"). If you want consistent terminology, consider standardizing across both the mobile and desktop button to either “Create New Policy” or “Add Policy” in alignment with t("policies.create_new").

<Button onClick={() => setOpen("true")} variant="action">
  <Plus className="h-4 w-4" />
- {t("common.actions.addNew")}
+ {t("policies.create_new")}
</Button>

184-187: Avoid dual button usage for the same action.

Users see two separate buttons for creating a policy—one for mobile (lines 128-132) and one for desktop (lines 184-187). Although it’s intentional for responsive design, ensure messaging remains consistent across devices, potentially reusing the same text or style. This duplication might be simplified by conditionally rendering one component or by reusing the same label for uniformity.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b53245b and 732a96b.

⛔ Files ignored due to path filters (1)
  • apps/app/languine.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • apps/app/src/actions/policies/create-new-policy.ts (1 hunks)
  • apps/app/src/actions/schema.ts (1 hunks)
  • apps/app/src/app/[locale]/(app)/(dashboard)/(home)/overview/frameworks/controls/[id]/components/SingleControlSkeleton.tsx (1 hunks)
  • apps/app/src/components/forms/policies/create-new-policy.tsx (1 hunks)
  • apps/app/src/components/sheets/create-policy-sheet.tsx (1 hunks)
  • apps/app/src/components/tables/policies/filter-toolbar.tsx (3 hunks)
  • apps/app/src/locales/en.ts (1 hunks)
  • apps/app/src/locales/es.ts (1 hunks)
  • apps/app/src/locales/fr.ts (1 hunks)
  • apps/app/src/locales/no.ts (1 hunks)
  • apps/app/src/locales/pt.ts (1 hunks)
🔇 Additional comments (12)
apps/app/src/app/[locale]/(app)/(dashboard)/(home)/overview/frameworks/controls/[id]/components/SingleControlSkeleton.tsx (1)

29-29: Minor styling update to remove rounded corners

The rounded-md class has been removed from this skeleton loader div. This appears to be an intentional UI consistency change for the loading state.

apps/app/src/locales/pt.ts (1)

361-367: Successfully added Portuguese translations for policy creation

The new translations for the policy creation feature are appropriately structured and follow the same pattern as other localization entries. These strings will provide proper user feedback during policy creation in Portuguese.

apps/app/src/locales/es.ts (1)

361-367: Successfully added Spanish translations for policy creation

The added translations for the policy creation feature are well-structured and consistent with both the existing Spanish localization patterns and the corresponding translations in other language files.

apps/app/src/locales/no.ts (1)

361-367: Successfully added Norwegian translations for policy creation

The Norwegian translations for the policy creation feature have been properly implemented, maintaining consistent structure with both the existing localization patterns and the equivalent translations in other language files.

apps/app/src/locales/fr.ts (1)

361-367: New translations for policy creation added correctly.

The French translations for the policy creation feature have been added appropriately, with clear and concise messages for:

  • Success notification
  • Error notification
  • Section titles and form field labels

These translations align well with the policy creation functionality being implemented.

apps/app/src/locales/en.ts (1)

362-368: Clear and consistent English translations for policy creation.

The English translation strings for the policy creation feature are concise and user-friendly. They properly match the structure seen in the French translations, maintaining consistency across languages.

apps/app/src/components/sheets/create-policy-sheet.tsx (2)

1-12: Appropriate imports and setup for the component.

The component imports necessary UI components from the Bubba UI library and uses appropriate hooks for internationalization, responsive design, and state management.


13-22: Well-structured component with responsive behavior.

The component correctly uses the useMediaQuery hook to determine viewport size and useQueryState to manage the open/closed state through URL parameters, which is a good practice for maintaining state across page refreshes and navigation.

apps/app/src/actions/policies/create-new-policy.ts (1)

28-45:

Details

❓ Verification inconclusive

Validate user input for collisions or improper references.

While you create references for frameworks (policyFrameworks) and controls (PolicyControl) using IDs from the request, there’s no check for whether they actually exist in the database. If the IDs are invalid or belong to a resource outside of the user’s organization, your code may create inconsistent records. Consider adding a quick validation step or referencing constraints to ensure the IDs correspond to valid frameworks and controls within the same organization (if applicable).


🏁 Script executed:

#!/bin/bash
# This script demonstrates how you might discover non-existent references to frameworks or controls.
# We search for the policy creation logic to verify if there's an existing validation.
rg -A 10 "map((id) => ({ frameworkId: id }))"

Length of output: 170


Below is a revised review comment that asks you to take a closer look at input validation. Since our initial regex search failed (likely due to regex parsing issues) and a fixed-string search for built-in validations hasn’t produced evidence that incoming IDs are verified, please manually verify that any reference IDs (both for frameworks and controls) undergo validation before being used. Consider adding a check that confirms the referenced records exist (and belong to the user’s organization, if applicable) before creating the policy.

Action Required: Validate Policy Reference IDs
• In file apps/app/src/actions/policies/create-new-policy.ts (lines 28–45), ensure that the IDs provided in frameworkIds and controlIds are verified—i.e. confirm that each provided ID corresponds to an existing record (and to a record from the correct organization).
• If relying solely on the database’s foreign key constraints isn’t enough (for example, if collision handling or more expressive error messages are desired), add an explicit validation step before the policy is created.

apps/app/src/components/forms/policies/create-new-policy.tsx (2)

60-127: Form UX improvements.

  1. Prevent double submissions: The submit button is disabled while createPolicy.status === "executing", which is good. However, consider also disabling form inputs or providing a loading indicator to enhance clarity.
  2. Validation errors: You are using Zod with react-hook-form; this is solid. Ensure that you show relevant field-level error messages if a user fails validation. The FormMessage components are present, so you may want to confirm they display all validation messages effectively (e.g., if title is required but omitted).
  3. Handling additional fields: If you plan to incorporate more advanced policy fields in the future (like departments, frequency, etc.), it’s straightforward to expand the Zod schema, so this is well-prepared for extension.

36-44:

Details

❓ Verification inconclusive

Add handling for edge cases or empty arrays.

When frameworkIds or controlIds arrays are empty, it might be a valid scenario or an oversight. If your system requires at least one framework or control, prompt the user or handle that logic gracefully. Otherwise, clarify that empty arrays are acceptable inputs.


🏁 Script executed:

#!/bin/bash
# Checking where createPolicyForm is used to confirm that empty arrays are valid scenario
rg -A 5 'CreateNewPolicyForm'

Length of output: 1998


I'll now run a shell script to search for mentions of frameworkIds and controlIds in the create-new-policy.tsx file to verify if there's any handling for empty arrays within this file.


🏁 Script executed:

#!/bin/bash
# Search for frameworkIds in the file
rg -n "frameworkIds" apps/app/src/components/forms/policies/create-new-policy.tsx

# Search for controlIds in the file
rg -n "controlIds" apps/app/src/components/forms/policies/create-new-policy.tsx

Length of output: 213


Action Required: Clarify Handling of Empty Arrays in CreateNewPolicyForm

The current implementation in apps/app/src/components/forms/policies/create-new-policy.tsx initializes both frameworkIds and controlIds as empty arrays (see lines 51-52). Please confirm whether empty arrays are valid inputs:

  • If a policy should always include at least one framework or control, add validation and prompt the user appropriately.
  • If empty arrays are acceptable, please add a clarifying comment or documentation to make this behavior explicit.
apps/app/src/components/tables/policies/filter-toolbar.tsx (1)

190-190: Confirmation of dynamic route state.

<CreatePolicySheet /> relies on useQueryState("create-policy-sheet"). If users navigate away from the page, ensure that the state is reset or remains valid on revisit to avoid confusion (e.g., returning to the page with the "create-policy-sheet" query param set might unexpectedly open the sheet). You can choose to reset or ignore stale query params if that’s undesirable.

Comment on lines +47 to +54
return (
<Drawer open={isOpen} onOpenChange={handleOpenChange}>
<DrawerTitle hidden>{t("policies.create_new")}</DrawerTitle>
<DrawerContent className="p-6">
<CreateNewPolicyForm />
</DrawerContent>
</Drawer>
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure accessibility of drawer title for screen readers.

The mobile view uses a Drawer component with a hidden title, which might affect accessibility.

The hidden prop on DrawerTitle may hide the title from screen readers. Consider alternative approaches to visually hide while keeping it accessible:

- <DrawerTitle hidden>{t("policies.create_new")}</DrawerTitle>
+ <DrawerTitle className="sr-only">{t("policies.create_new")}</DrawerTitle>

Or if the Bubba UI library's DrawerTitle handles this accessibility concern internally, you may validate that with:


🏁 Script executed:

#!/bin/bash
# Search for DrawerTitle component implementation to verify accessibility handling
fd --type f --extension tsx --extension jsx --exec grep -l "DrawerTitle" {} \; | xargs cat

Length of output: 28519


Action Required: Update Drawer Title for Accessibility

Please replace the use of the hidden prop on <DrawerTitle> with a visually hidden class (e.g. sr-only) so that the title remains available to screen readers. The current implementation forwards the hidden prop to the underlying element, which results in the title being hidden from all users—including those using assistive technologies.

For example, in the file apps/app/src/components/sheets/create-policy-sheet.tsx at lines 47–54, change:

- <DrawerTitle hidden>{t("policies.create_new")}</DrawerTitle>
+ <DrawerTitle className="sr-only">{t("policies.create_new")}</DrawerTitle>

This approach visually hides the title while ensuring it remains accessible. Please also verify that this change is consistent with the intended behavior of the Bubba UI library and does not conflict with any internal accessibility handling.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<Drawer open={isOpen} onOpenChange={handleOpenChange}>
<DrawerTitle hidden>{t("policies.create_new")}</DrawerTitle>
<DrawerContent className="p-6">
<CreateNewPolicyForm />
</DrawerContent>
</Drawer>
)
return (
<Drawer open={isOpen} onOpenChange={handleOpenChange}>
<DrawerTitle className="sr-only">{t("policies.create_new")}</DrawerTitle>
<DrawerContent className="p-6">
<CreateNewPolicyForm />
</DrawerContent>
</Drawer>
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants