Skip to content

Conversation

@anmolsinghbhatia
Copy link
Collaborator

@anmolsinghbhatia anmolsinghbhatia commented Jan 2, 2026

Problem

When selecting an Unsplash image (or any external URL) as a project cover image, the URL wasn't being saved to the backend. The handleCoverImageChange function was returning null for external URLs, causing the update payload to exclude the cover image.

Root Cause

The handleCoverImageChange function only returned a payload for:

  1. Image removal (returns null values)
  2. Local static images that need upload (for user assets only)

External URLs like Unsplash images are classified as "uploaded_asset" type and don't require upload, so the function fell through to return null, preventing the URL from being included in the update payload.

Solution

  • Updated handleCoverImageChange to return the cover image URL in the payload for external/uploaded assets
  • Replaced cover_image_url with cover_image fields

Testing

  • Verify Unsplash images are saved when selected in project form
  • Verify local static images still upload correctly
  • Verify image removal still works correctly
  • Verify no regressions in existing cover image functionality

Summary by CodeRabbit

  • Bug Fixes
    • Improved cover image handling for uploaded and external assets to ensure consistent processing across all asset types.

✏️ Tip: You can customize this high-level summary in your review settings.

@anmolsinghbhatia anmolsinghbhatia self-assigned this Jan 2, 2026
Copilot AI review requested due to automatic review settings January 2, 2026 08:19
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

The handleCoverImageChange function's return behavior is modified. For user-uploaded assets, the field name changes from cover_image_url to cover_image. For external/uploaded assets, the function now returns { cover_image: newImage } instead of null, eliminating the previous unconditional null path.

Changes

Cohort / File(s) Summary
Cover Image Helper Logic
apps/web/helpers/cover-image.helper.ts
Modified handleCoverImageChange return values: renamed cover_image_url to cover_image for user-uploaded assets; changed external/uploaded asset handling to return { cover_image: newImage } instead of null.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Hoppy changes bring delight,
Cover images now return just right,
No more null paths to confuse,
Field names aligned—no mixed-up clues,
The helper hops forward with cheer!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing the persistence of external cover image URLs (specifically Unsplash images) in project updates.
Description check ✅ Passed The description is comprehensive and follows the template structure with Problem, Root Cause, Solution, and Testing sections clearly documented.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d5e427 and cbe009e.

📒 Files selected for processing (1)
  • apps/web/helpers/cover-image.helper.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • apps/web/helpers/cover-image.helper.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Enable TypeScript strict mode and ensure all files are fully typed

Files:

  • apps/web/helpers/cover-image.helper.ts
**/*.{js,jsx,ts,tsx,json,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with Tailwind plugin for code formatting, run pnpm fix:format

Files:

  • apps/web/helpers/cover-image.helper.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Use ESLint with shared config across packages, adhering to max warnings limits per package
Use camelCase for variable and function names, PascalCase for components and types
Use try-catch with proper error types and log errors appropriately

Files:

  • apps/web/helpers/cover-image.helper.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Agent
  • GitHub Check: Build packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/web/helpers/cover-image.helper.ts (2)

268-273: No backend compatibility issue found — the backend API properly supports the cover_image field.

The backend models and serializers both include the cover_image field as a writable input field. The cover_image_url is a computed read-only property that derives its value from either the cover_image field or the cover_image_asset reference. The change in the helper from returning cover_image_url to cover_image aligns correctly with the backend's expected input field.


276-280: Backend verification confirms the cover_image field is fully supported.

The Project model includes the cover_image field (TextField), and the ProjectSerializer uses fields = "__all__", which means it will accept and persist the cover_image value in PATCH/PUT requests. The field has been stable across multiple migrations, and the model's cover_image_url property correctly returns the stored value. The fix is compatible with the backend API.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@makeplane
Copy link

makeplane bot commented Jan 2, 2026

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug where external cover image URLs (like Unsplash images) were not being persisted to the backend when selected for projects. The root cause was that the handleCoverImageChange helper function was returning null for external URLs instead of returning the URL in the update payload.

Key Changes

  • Modified handleCoverImageChange to return external/uploaded asset URLs in the payload instead of null
  • Changed the field name from cover_image_url to cover_image for uploaded assets, aligning with the backend API contract where cover_image is used for uploads and cover_image_url is a readonly field for rendering

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

3 participants