Skip to content
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

release: v4.3.1 #2140

Merged
merged 6 commits into from
Jan 11, 2025
Merged

release: v4.3.1 #2140

merged 6 commits into from
Jan 11, 2025

Conversation

AmruthPillai
Copy link
Owner

@AmruthPillai AmruthPillai commented Jan 11, 2025

Summary by CodeRabbit

Release Notes v4.3.1

  • New Features

    • Added support for Ollama integration alongside OpenAI.
    • Enhanced accessibility with visually hidden descriptions.
  • Improvements

    • Refined form validation for language and skill levels.
    • Updated context menus to dropdown menus for better user interaction.
    • Improved synchronization between editor content and form states.
    • Enhanced user guidance with additional information in custom sections.
    • Updated placeholder text in profile sections to reflect a shift in focus from LinkedIn to GitHub.
  • Bug Fixes

    • Fixed icon and placeholder text inconsistencies in profile sections.
    • Enhanced error logging and debugging capabilities.
  • Chores

    • Updated package version.
    • Added new accessibility dependency.
    • Stricter console logging rules for TypeScript files.
    • Streamlined workflow configuration for linting, testing, and building.

Copy link

coderabbitai bot commented Jan 11, 2025

Warning

Rate limit exceeded

@AmruthPillai has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 9b20c46 and 3b73dcf.

📒 Files selected for processing (2)
  • apps/client/src/libs/lingui.ts (1 hunks)
  • apps/server/src/printer/printer.service.ts (1 hunks)
📝 Walkthrough

Walkthrough

The pull request encompasses multiple files across different sections of the application, focusing on enhancing form interactions, improving accessibility, and refining UI components. Key changes include updating form state synchronization in various dialogs, transitioning from context menus to dropdown menus, adding ref forwarding, and introducing coercion for number inputs in schemas.

Changes

File Path Change Summary
apps/client/src/pages/builder/sidebars/left/dialogs/* Updated RichInput and AiActions to synchronize editor content and form state
apps/client/src/pages/builder/sidebars/left/sections/shared/* Refactored context menus to dropdown menus, added new section management functions
libs/schema/src/sections/language.ts and skill.ts Modified level property to use z.coerce.number() for type conversion
apps/client/src/pages/dashboard/* Updated card components with ref forwarding and dropdown menu implementation
package.json Version bump to 4.3.1 and added @radix-ui/react-visually-hidden dependency
.eslintrc.json Added stricter console logging rules for TypeScript files

Assessment against linked issues

Objective Addressed Explanation
Fix Skill Level Type Conversion [#2139]
Support Ollama Integration [#1872] OpenAI settings updated to mention Ollama
Resume Preview Image [#2005] No direct changes related to preview image

Poem

🐰 Code hops and changes, swift and light,
Menus dance, forms sync just right
Schemas coerce with gentle might
Refs forward, accessibility bright
A rabbit's code review takes flight! 🚀


🪧 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. (Beta)
  • @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.

Copy link

nx-cloud bot commented Jan 11, 2025

View your CI Pipeline Execution ↗ for commit 3b73dcf.

Command Status Duration Result
nx run-many -t build ✅ Succeeded 1m 19s View ↗
nx run-many -t lint ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2025-01-11 17:01:55 UTC

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (15)
apps/client/src/pages/builder/sidebars/left/dialogs/volunteer.tsx (1)

118-118: Consider documenting the true parameter in setContent.

The second parameter true in editor.commands.setContent(value, true) is important for preserving the editor's history stack. Consider adding a brief comment explaining its purpose for maintainability.

-                        editor.commands.setContent(value, true);
+                        // Preserve editor history stack for undo/redo functionality
+                        editor.commands.setContent(value, true);
apps/client/src/pages/builder/sidebars/left/sections/summary.tsx (1)

35-41: Consider memoizing the onChange handler.

The current implementation creates a new function on every render. Consider memoizing the handler using useCallback to optimize performance:

+ import { useCallback } from 'react';

  export const SummarySection = () => {
    const setValue = useResumeStore((state) => state.setValue);
+   const handleAiChange = useCallback((editor) => (value) => {
+     editor.commands.setContent(value, true);
+     setValue("sections.summary.content", value);
+   }, [setValue]);

    return (
      // ...
      <RichInput
        footer={(editor) => (
          <AiActions
            value={editor.getText()}
-           onChange={(value) => {
-             editor.commands.setContent(value, true);
-             setValue("sections.summary.content", value);
-           }}
+           onChange={handleAiChange(editor)}
          />
        )}
      />
    );
  };
apps/client/src/pages/builder/sidebars/left/sections/shared/section-list-item.tsx (1)

Line range hint 77-77: Update cursor style to match new interaction model.

The class cursor-context-menu suggests right-click interaction, which doesn't align with the new dropdown menu behavior.

-"flex-1 cursor-context-menu p-4 hover:bg-secondary-accent",
+"flex-1 cursor-pointer p-4 hover:bg-secondary-accent",
apps/client/src/pages/builder/sidebars/left/sections/shared/section-base.tsx (1)

Line range hint 134-146: Consider memoizing event handler callbacks.

The event handlers in the map callback are recreated on each render. Consider optimizing performance by memoizing these callbacks or moving them outside the map function.

Here's how you could optimize it:

 {section.items.map((item, index) => {
+  const handleUpdate = () => onUpdate(item as T);
+  const handleDelete = () => onDelete(item as T);
+  const handleDuplicate = () => onDuplicate(item as T);
+  const handleToggleVisibility = () => onToggleVisibility(index);
+
   return (
     <SectionListItem
       key={item.id}
       id={item.id}
       visible={item.visible}
       title={title(item as T)}
       description={description?.(item as T)}
-      onUpdate={() => {
-        onUpdate(item as T);
-      }}
-      onDelete={() => {
-        onDelete(item as T);
-      }}
-      onDuplicate={() => {
-        onDuplicate(item as T);
-      }}
-      onToggleVisibility={() => {
-        onToggleVisibility(index);
-      }}
+      onUpdate={handleUpdate}
+      onDelete={handleDelete}
+      onDuplicate={handleDuplicate}
+      onToggleVisibility={handleToggleVisibility}
     />
   );
 })}

For even better performance, you could use useCallback if these handlers are passed to memoized child components:

const handleUpdate = useCallback((item: T) => onUpdate(item), [onUpdate]);
const handleDelete = useCallback((item: T) => onDelete(item), [onDelete]);
const handleDuplicate = useCallback((item: T) => onDuplicate(item), [onDuplicate]);
apps/client/src/pages/builder/sidebars/left/dialogs/languages.tsx (1)

77-80: LGTM! Consider adding aria-label for better screen reader support.

The conditional rendering logic is clear and consistent. The level is now properly displayed when greater than 0, and "Hidden" is shown when the level is 0.

Consider adding an aria-label to improve screen reader experience:

-                  {field.value > 0 ? (
-                    <span className="text-base font-bold">{field.value}</span>
-                  ) : (
-                    <span className="text-base font-bold">{t`Hidden`}</span>
-                  )}
+                  {field.value > 0 ? (
+                    <span className="text-base font-bold" aria-label={t`Language proficiency level: ${field.value}`}>{field.value}</span>
+                  ) : (
+                    <span className="text-base font-bold" aria-label={t`Language proficiency level: Hidden`}>{t`Hidden`}</span>
+                  )}
apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx (1)

91-94: LGTM! Consider accessibility and performance improvements.

The conditional rendering logic matches the languages dialog, maintaining consistency across the application.

Consider these improvements:

  1. Add aria-label for better screen reader support:
-                  {field.value > 0 ? (
-                    <span className="text-base font-bold">{field.value}</span>
-                  ) : (
-                    <span className="text-base font-bold">{t`Hidden`}</span>
-                  )}
+                  {field.value > 0 ? (
+                    <span className="text-base font-bold" aria-label={t`Skill level: ${field.value}`}>{field.value}</span>
+                  ) : (
+                    <span className="text-base font-bold" aria-label={t`Skill level: Hidden`}>{t`Hidden`}</span>
+                  )}
  1. Consider memoizing the AnimatePresence children to optimize performance when there are many keywords:
const AnimatedBadge = memo(({ item, index, onRemove }) => (
  <motion.div
    key={item}
    layout
    initial={{ opacity: 0, y: -50 }}
    animate={{ opacity: 1, y: 0, transition: { delay: index * 0.1 } }}
    exit={{ opacity: 0, x: -50 }}
  >
    <Badge
      className="cursor-pointer"
      onClick={() => onRemove(item)}
    >
      <span className="mr-1">{item}</span>
      <X size={12} weight="bold" />
    </Badge>
  </motion.div>
));
apps/client/src/pages/dashboard/settings/_sections/openai.tsx (3)

42-43: Consider adding Ollama API key validation.

The simplified isEnabled logic correctly depends only on apiKey. However, since we now support both OpenAI and Ollama, consider updating the API key validation to accommodate Ollama's format.

 const formSchema = z.object({
   apiKey: z
     .string()
-    .regex(/^sk-.+$/, "That doesn't look like a valid OpenAI API key.")
+    .regex(/^(sk-.+|sk-\d{16})$/, "That doesn't look like a valid OpenAI/Ollama API key.")
     .default(""),
   // ... rest of the schema
 });

104-107: Enhance Ollama setup instructions.

Consider improving the Ollama setup instructions by:

  1. Making the example API key less likely to be copied directly
  2. Adding a link to Ollama's documentation
-            You can also integrate with Ollama simply by setting the API key to
-            `sk-1234567890abcdef` and the Base URL to your Ollama URL, i.e.
-            `http://localhost:11434/v1`. You can also pick and choose models and set the max tokens
-            as per your preference.
+            You can also integrate with <a href="https://ollama.ai/download" target="_blank" rel="noopener noreferrer">Ollama</a> by:
+            1. Setting the API key to any 16-digit value prefixed with `sk-` (e.g., `sk-0000000000000000`)
+            2. Setting the Base URL to your Ollama endpoint (default: `http://localhost:11434/v1`)
+            3. Choosing from available <a href="https://ollama.ai/library" target="_blank" rel="noopener noreferrer">Ollama models</a>

Line range hint 173-216: Update disclaimer to include Ollama.

The disclaimer section only mentions OpenAI's terms and privacy policy. Consider adding a similar disclaimer for Ollama or making it generic for both services.

           <Trans>
             <span className="font-medium">Note: </span>
-            By utilizing the OpenAI API, you acknowledge and accept the{" "}
+            By utilizing the OpenAI or Ollama APIs, you acknowledge and accept their respective terms of use
+            and privacy policies ({" "}
             <a
               href="https://openai.com/policies/terms-of-use"
               rel="noopener noreferrer nofollow"
               target="_blank"
             >
-              terms of use
+              OpenAI Terms
             </a>{" "}
-            and{" "}
+            |{" "}
             <a
               href="https://openai.com/policies/privacy-policy"
               rel="noopener noreferrer nofollow"
               target="_blank"
             >
-              privacy policy
+              Privacy
             </a>{" "}
+            |{" "}
+            <a
+              href="https://github.com/ollama/ollama/blob/main/LICENSE"
+              rel="noopener noreferrer nofollow"
+              target="_blank"
+            >
+              Ollama License
+            </a>
             ). Please note that Reactive Resume bears no responsibility for any
             improper or unauthorized utilization of the service, and any resulting repercussions or
             liabilities solely rest on the user.
           </Trans>
apps/client/src/pages/builder/sidebars/left/dialogs/references.tsx (1)

87-93: LGTM! Consider documenting the setContent parameter

The implementation correctly synchronizes the editor content with the form state. However, consider adding a comment explaining the purpose of the true parameter in setContent(value, true).

 onChange={(value) => {
+  // The second parameter (true) prevents the editor from creating a new history entry
   editor.commands.setContent(value, true);
   field.onChange(value);
 }}
apps/client/src/pages/builder/sidebars/left/dialogs/certifications.tsx (1)

101-107: Consider extracting the common AiActions pattern

While the implementation is correct, this pattern is duplicated across multiple dialog components. Consider extracting it into a reusable hook or component.

Example implementation:

// hooks/useAiActionsHandler.ts
export const useAiActionsHandler = (editor: Editor, field: ControllerRenderProps) => {
  return useCallback(
    (value: string) => {
      editor.commands.setContent(value, true);
      field.onChange(value);
    },
    [editor, field]
  );
};

// Usage in dialog components:
const handleAiChange = useAiActionsHandler(editor, field);
<AiActions value={editor.getText()} onChange={handleAiChange} />
apps/client/src/pages/builder/sidebars/left/dialogs/profiles.tsx (1)

54-54: Consider using more inclusive placeholder examples.

While GitHub is commonly used, consider using more generic examples or multiple examples to better indicate that users can add any social network profile. This would make the form more intuitive for users who want to add other platforms like LinkedIn, Twitter, etc.

-<Input {...field} placeholder="GitHub" />
+<Input {...field} placeholder="GitHub, LinkedIn, Twitter, etc." />

-<URLInput {...field} placeholder="https://github.com/johndoe" />
+<URLInput {...field} placeholder="https://github.com/johndoe or https://linkedin.com/in/johndoe" />

-placeholder="github"
+placeholder="github, linkedin, twitter"

Also applies to: 82-82, 103-103

apps/client/src/pages/builder/sidebars/left/dialogs/education.tsx (1)

144-150: Consider extracting the common RichInput pattern.

The same RichInput configuration with AI actions appears in multiple dialog components. Consider extracting this into a reusable component to reduce duplication and maintain consistency.

Example implementation:

// components/RichInputWithAI.tsx
interface RichInputWithAIProps extends RichInputProps {
  field: ControllerRenderProps;
}

export const RichInputWithAI: React.FC<RichInputWithAIProps> = ({ field, ...props }) => (
  <RichInput
    {...field}
    {...props}
    content={field.value}
    footer={(editor) => (
      <AiActions
        value={editor.getText()}
        onChange={(value) => {
          editor.commands.setContent(value, true);
          field.onChange(value);
        }}
      />
    )}
    onChange={(value) => {
      field.onChange(value);
    }}
  />
);
apps/client/src/pages/builder/sidebars/left/dialogs/projects.tsx (1)

114-120: LGTM! Proper form state synchronization implemented.

The implementation correctly synchronizes the form state with AI-generated content by calling both editor.commands.setContent and field.onChange. This ensures data consistency when using AI actions.

Consider extracting this pattern into a custom hook (e.g., useRichInputSync) since it's being reused across multiple dialog components, as evident from the AI summary.

apps/client/src/pages/builder/sidebars/left/sections/custom/section.tsx (1)

56-58: Add error handling for icon loading

Consider adding error handling for cases where the icon fails to load or doesn't exist:

-                {field.icon ? <i className={cn(`ph ph-${field.icon}`)} /> : <Envelope />}
+                {field.icon ? (
+                  <i className={cn(`ph ph-${field.icon}`)} onError={() => handleChange("icon", "")} />
+                ) : (
+                  <Envelope />
+                )}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 54bace4 and 58ef309.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (24)
  • apps/client/src/pages/builder/sidebars/left/dialogs/awards.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/certifications.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/custom-section.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/education.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/experience.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/languages.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/profiles.tsx (3 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/projects.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/publications.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/references.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/skills.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/dialogs/volunteer.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/sections/custom/section.tsx (5 hunks)
  • apps/client/src/pages/builder/sidebars/left/sections/shared/section-base.tsx (1 hunks)
  • apps/client/src/pages/builder/sidebars/left/sections/shared/section-dialog.tsx (3 hunks)
  • apps/client/src/pages/builder/sidebars/left/sections/shared/section-list-item.tsx (3 hunks)
  • apps/client/src/pages/builder/sidebars/left/sections/summary.tsx (1 hunks)
  • apps/client/src/pages/dashboard/resumes/_layouts/grid/_components/base-card.tsx (2 hunks)
  • apps/client/src/pages/dashboard/resumes/_layouts/grid/_components/resume-card.tsx (4 hunks)
  • apps/client/src/pages/dashboard/settings/_sections/openai.tsx (6 hunks)
  • apps/server/src/mail/mail.service.ts (1 hunks)
  • libs/schema/src/sections/language.ts (1 hunks)
  • libs/schema/src/sections/skill.ts (1 hunks)
  • package.json (2 hunks)
🔇 Additional comments (21)
apps/client/src/pages/builder/sidebars/left/dialogs/volunteer.tsx (1)

115-121: LGTM! Proper synchronization between editor and form state.

The implementation correctly handles both the editor content update and form state management, ensuring consistency when AI actions are triggered.

apps/client/src/pages/builder/sidebars/left/sections/summary.tsx (1)

35-41: LGTM! Good state synchronization approach.

The implementation ensures proper synchronization between the editor's content and form state, maintaining consistency with similar changes across dialog components.

libs/schema/src/sections/language.ts (1)

9-9: LGTM! Good fix for the slider validation issue.

Adding coercion to the level field is a good solution that will automatically handle string-to-number conversion while maintaining the validation constraints. This should resolve the slider component validation errors mentioned in issue #2139.

libs/schema/src/sections/skill.ts (1)

9-9: LGTM! Consistent with language schema changes.

Good to see the same coercion approach being applied consistently across similar schemas. This maintains a uniform behavior for level fields throughout the application.

apps/client/src/pages/builder/sidebars/left/sections/shared/section-list-item.tsx (2)

6-11: LGTM! Import changes align with accessibility improvements.

The replacement of ContextMenu imports with DropdownMenu components aligns with the PR objective to enhance accessibility.


Line range hint 72-103: LGTM! Excellent accessibility improvements.

The conversion from ContextMenu to DropdownMenu enhances accessibility by:

  • Supporting keyboard navigation
  • Removing the requirement for right-click interactions
  • Maintaining all existing functionality in a more accessible way
apps/client/src/pages/builder/sidebars/left/sections/shared/section-base.tsx (1)

73-84: LGTM! Well-structured event handlers.

The new event handlers are well-implemented with consistent patterns and proper type safety.

apps/client/src/pages/builder/sidebars/left/sections/shared/section-dialog.tsx (1)

4-4: LGTM! Good accessibility improvement.

The addition of VisuallyHidden and DialogDescription components from Radix UI demonstrates a commitment to improving accessibility.

Also applies to: 18-18

package.json (1)

4-4: LGTM! Version bump and dependency addition look good.

The version bump to 4.3.1 and addition of @radix-ui/react-visually-hidden dependency are properly implemented.

Also applies to: 169-169

apps/client/src/pages/dashboard/settings/_sections/openai.tsx (1)

31-31: LGTM! Schema change allows flexibility for both OpenAI and Ollama.

The addition of .or(z.literal("")) correctly allows empty baseURL for OpenAI while maintaining validation for Ollama URLs.

apps/client/src/pages/builder/sidebars/left/dialogs/publications.tsx (1)

101-107: LGTM! Consistent implementation across dialogs

The implementation maintains consistency with other dialog components, which is excellent for code maintainability.

apps/client/src/pages/builder/sidebars/left/dialogs/awards.tsx (1)

107-113: LGTM! Well-implemented form state synchronization.

The implementation correctly ensures that both the editor's content and form state are updated when AI-generated content is applied, maintaining consistency in the application state.

apps/client/src/pages/builder/sidebars/left/dialogs/experience.tsx (1)

120-126: LGTM! Consistent implementation across components.

The changes maintain consistency with other dialog components, following the same pattern of synchronizing editor content with form state.

apps/client/src/pages/builder/sidebars/left/dialogs/education.tsx (1)

144-150: LGTM! Consistent implementation.

The changes maintain consistency with other dialog components in handling AI-generated content.

apps/client/src/pages/builder/sidebars/left/dialogs/custom-section.tsx (1)

134-140: LGTM! Consistent implementation across dialog components.

The implementation follows the same pattern as other dialog components, ensuring proper synchronization between the editor's content and form state when using AI actions.

This implementation mirrors the pattern seen in projects.tsx and other dialog components. The earlier suggestion about extracting this pattern into a custom hook applies here as well.

apps/client/src/pages/dashboard/resumes/_layouts/grid/_components/base-card.tsx (1)

3-3: LGTM! Well-structured implementation of ref forwarding.

The implementation correctly uses forwardRef to pass refs to the underlying Card component, which is essential for the DropdownMenu integration. The type safety is maintained with proper TypeScript annotations.

Also applies to: 14-28

apps/client/src/pages/dashboard/resumes/_layouts/grid/_components/resume-card.tsx (2)

12-16: LGTM! Clean import declarations.

The imports are properly organized and specifically import only the required DropdownMenu components.


Line range hint 60-124: LGTM! Improved accessibility with DropdownMenu.

The transition from ContextMenu to DropdownMenu enhances accessibility by:

  1. Making the menu accessible via both click and keyboard navigation
  2. Maintaining all existing functionality while improving usability
  3. Using appropriate cursor styling with cursor-context-menu
apps/client/src/pages/builder/sidebars/left/sections/custom/section.tsx (3)

43-43: Improved button accessibility with ghost variant

The change from variant="link" to variant="ghost" for icon buttons provides better visual feedback and hover states, improving accessibility.

Also applies to: 55-55, 106-106


60-82: Enhanced user guidance with icon selection help

Good addition of the help text and link to Phosphor Icons. This improves the user experience by providing clear guidance on available icons.


130-130: Consider adding icon validation

While setting "envelope" as the default icon is a good UX improvement, consider adding validation to ensure the icon exists in the Phosphor Icons set.

Run this script to verify the icon's existence:

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
.eslintrc.json (1)

12-12: Consider environment-specific ESLint configuration.

While removing console statements is good for production, having them error during development might hinder debugging. Consider using environment variables or separate ESLint configurations:

-        "no-console": "error",
+        "no-console": ["error", {
+          "allow": process.env.NODE_ENV === "development" ? ["warn", "error"] : []
+        }],

This would:

  • Allow console.warn and console.error during development
  • Maintain strict enforcement in production
  • Provide a better developer experience while ensuring clean production code
apps/server/src/printer/printer.service.ts (1)

Line range hint 91-209: Consider breaking down generateResume into smaller functions

The generateResume function is handling multiple concerns and is quite long (200+ lines). This makes it harder to maintain and test.

Consider breaking it down into smaller, focused functions:

  1. setupBrowserPage: Handle browser setup and configuration
  2. generatePdfPages: Handle PDF generation for each page
  3. embedFonts: Handle font loading and embedding
  4. mergePdfPages: Handle merging of PDF pages
  5. saveAndUpload: Handle storage operations

Example structure:

private async setupBrowserPage(resume: ResumeDto) {
  const browser = await this.getBrowser();
  const page = await browser.newPage();
  // ... setup code ...
  return { browser, page };
}

private async generatePdfPages(page: Page, numberPages: number) {
  const pagesBuffer: Buffer[] = [];
  // ... PDF generation code ...
  return pagesBuffer;
}

private async embedFonts(pdf: PDFDocument, fontData: FontData) {
  // ... font embedding code ...
}

private async mergePdfPages(pdf: PDFDocument, pagesBuffer: Buffer[]) {
  // ... PDF merging code ...
  return pdf;
}

private async saveAndUpload(buffer: Buffer, resume: ResumeDto) {
  // ... storage code ...
  return resumeUrl;
}

async generateResume(resume: ResumeDto) {
  try {
    const { browser, page } = await this.setupBrowserPage(resume);
    const pagesBuffer = await this.generatePdfPages(page, resume.data.metadata.layout.length);
    
    const pdf = await PDFDocument.create();
    pdf.registerFontkit(fontkit);
    
    await this.embedFonts(pdf, resume.data.metadata.typography.font);
    await this.mergePdfPages(pdf, pagesBuffer);
    
    const buffer = Buffer.from(await pdf.save());
    const resumeUrl = await this.saveAndUpload(buffer, resume);
    
    await page.close();
    await browser.disconnect();
    
    return resumeUrl;
  } catch (error) {
    this.logger.error('Failed to generate resume', {
      userId: resume.userId,
      resumeId: resume.id,
      error: error instanceof Error ? error.message : String(error),
    });
    throw new InternalServerErrorException(
      ErrorMessage.ResumeGenerationFailed,
      error instanceof Error ? error.message : String(error),
    );
  }
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 58ef309 and 198c269.

📒 Files selected for processing (3)
  • .eslintrc.json (1 hunks)
  • apps/client/src/libs/lingui.ts (1 hunks)
  • apps/server/src/printer/printer.service.ts (1 hunks)
🔇 Additional comments (1)
.eslintrc.json (1)

12-12: Verify existing console usage before enforcing error level.

The stricter "no-console": "error" rule will break builds if there are any existing console statements in TypeScript files. Let's verify the impact:

apps/client/src/libs/lingui.ts Outdated Show resolved Hide resolved
apps/server/src/printer/printer.service.ts Outdated Show resolved Hide resolved
@AmruthPillai AmruthPillai merged commit 62046c4 into main Jan 11, 2025
4 of 5 checks passed
@AmruthPillai AmruthPillai deleted the release/v4.3.1 branch January 11, 2025 15:15
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.

[Bug] Issue with choosing Skill level [Bug] No preview image [Feature] Use Ollama
1 participant