feat: add cover image support for work itemsCover image attachment#9240
feat: add cover image support for work itemsCover image attachment#9240jribnik wants to merge 4 commits into
Conversation
Let users designate any image attachment on a work item as its cover, shown on kanban cards and the detail/peek views. The cover is set and cleared from the attachment's context menu and persisted via a new cover_image_attachment foreign key on the issue. - API: add Issue.cover_image_attachment FK (migration 0122), expose and validate cover_image_attachment_id in the issue serializer, and include it in the issue list/detail/sub-issue/grouper projections. - Web: resolve the cover URL deterministically from the attachment id, render it on kanban cards and the detail/peek views, and add a set/remove cover action to the attachment menu. - i18n: add the cover toast/menu strings to all locales. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Deleting the attachment that backed a cover image left a dangling cover_image_attachment_id: the v2 attachment endpoint soft-deletes the FileAsset, so the cover FK's on_delete=SET_NULL never fired, and the frontend store never cleared the reference either. - API: clear cover_image_attachment on any issue referencing the asset during the soft delete, so API clients stay consistent too. - Web: when removeAttachment deletes the current cover, also persist cover_image_attachment_id: null on the work item. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous cover-clear ran an extra updateIssue PATCH after the delete had already succeeded; when that second request rejected, the caller's try/catch surfaced a spurious "Attachment not removed" error even though the delete went through. The backend already nulls the cover FK during the soft delete, so mirror it in the local store instead of issuing a redundant network request. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds end-to-end cover image support for issues: a new nullable ChangesIssue Cover Image Feature
Sequence Diagram(s)sequenceDiagram
participant User
participant AttachmentListItem as IssueAttachmentsListItem
participant AttachmentList as IssueAttachmentItemList
participant API as BackendAPI
participant Store as IssueStore
participant Display as CoverImageComponent
rect rgba(59, 130, 246, 0.5)
note over User,AttachmentList: Setting a cover image
User->>AttachmentListItem: Click "Make cover image"
AttachmentListItem->>AttachmentList: onToggleCoverImage(attachmentId)
AttachmentList->>API: PATCH issue {cover_image_attachment_id: attachmentId}
API-->>AttachmentList: {cover_image_attachment_id, ...}
AttachmentList->>Store: updateIssue(cover_image_attachment_id)
AttachmentList->>API: fetchActivities
AttachmentList-->>User: setPromiseToast(success)
end
rect rgba(16, 185, 129, 0.5)
note over Store,Display: Rendering cover image
Display->>Store: read cover_image_attachment_id
Display->>Display: useIssueCoverImage(workspace, project, issue, attachment)
Display->>Display: fetch image from asset URL
Display-->>User: render img with object-cover
end
rect rgba(239, 68, 68, 0.5)
note over User,Store: Removing cover image via attachment delete
User->>API: DELETE attachment
API->>API: Issue.filter(cover_image_attachment=attachment).update(None)
API-->>AttachmentList: {deleted}
AttachmentList->>Store: updateIssue({cover_image_attachment_id: null})
Store-->>User: cover image cleared
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
🧹 Nitpick comments (1)
apps/web/core/components/issues/attachment/attachment-item-list.tsx (1)
71-98: ⚡ Quick winAdd explicit typed error handling and logging around cover toggle updates.
This new async path relies on promise chaining without a typed
try/catchlog path in the handler, which makes failures harder to diagnose.♻️ Suggested update
const handleToggleCoverImage = useCallback( async (attachmentId: string) => { const isCurrentCover = getIssueById(issueId)?.cover_image_attachment_id === attachmentId; const nextCoverId = isCurrentCover ? null : attachmentId; - const coverPromise = updateIssue(workspaceSlug, projectId, issueId, { - cover_image_attachment_id: nextCoverId, - }).then(() => { - handleFetchPropertyActivities(); - return; - }); - - setPromiseToast(coverPromise, { - loading: isCurrentCover ? t("attachment.remove_cover_loading") : t("attachment.set_cover_loading"), - success: { - title: isCurrentCover ? t("attachment.remove_cover_success_title") : t("attachment.set_cover_success_title"), - message: () => - isCurrentCover ? t("attachment.remove_cover_success_message") : t("attachment.set_cover_success_message"), - }, - error: { - title: isCurrentCover ? t("attachment.remove_cover_error_title") : t("attachment.set_cover_error_title"), - message: () => - isCurrentCover ? t("attachment.remove_cover_error_message") : t("attachment.set_cover_error_message"), - }, - }); - - return coverPromise; + try { + const coverPromise = updateIssue(workspaceSlug, projectId, issueId, { + cover_image_attachment_id: nextCoverId, + }).then(() => { + handleFetchPropertyActivities(); + }); + + setPromiseToast(coverPromise, { + loading: isCurrentCover ? t("attachment.remove_cover_loading") : t("attachment.set_cover_loading"), + success: { + title: isCurrentCover ? t("attachment.remove_cover_success_title") : t("attachment.set_cover_success_title"), + message: () => + isCurrentCover ? t("attachment.remove_cover_success_message") : t("attachment.set_cover_success_message"), + }, + error: { + title: isCurrentCover ? t("attachment.remove_cover_error_title") : t("attachment.set_cover_error_title"), + message: () => + isCurrentCover ? t("attachment.remove_cover_error_message") : t("attachment.set_cover_error_message"), + }, + }); + + await coverPromise; + } catch (error: unknown) { + console.error("Failed to toggle cover image", error); + throw error; + } },As per coding guidelines:
**/*.{ts,tsx,js,jsx}: Use try-catch with proper error types and log errors appropriately for error handling.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/core/components/issues/attachment/attachment-item-list.tsx` around lines 71 - 98, The handleToggleCoverImage function uses promise chaining without explicit typed error handling and logging, making failures difficult to diagnose. Add a try-catch block around the updateIssue call to explicitly catch and log errors with proper error type handling. Inside the catch block, log the error with appropriate context to aid debugging, then re-throw or handle the error appropriately so setPromiseToast can still handle the error state. This ensures all async failures in the cover image toggle operation are properly captured and logged.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/api/plane/app/serializers/issue.py`:
- Around line 203-214: The cover image attachment validation in the serializer
is missing a check for creation requests. Currently, the condition on line 206
only enforces issue ownership during updates (when self.instance is not None),
which allows a create request to reference an image attachment from a different
issue in the same project. Modify the validation logic to either disallow
setting a cover_image_attachment during creation entirely (by raising a
ValidationError if self.instance is None and cover_image_attachment is
provided), or add explicit validation to ensure the cover image doesn't already
belong to another issue, preventing cross-issue cover image references at both
create and update time.
In `@apps/web/core/components/issues/issue-detail/cover-image.tsx`:
- Around line 7-31: The imageLoadError state in the IssueDetailCoverImage
component remains true after an image fails to load, causing the component to
return null even when a new valid cover image URL is provided. Add a useEffect
hook that depends on the coverImageUrl dependency and resets imageLoadError to
false whenever the coverImageUrl changes, ensuring the component attempts to
render new cover images instead of maintaining the previous failure state.
In `@apps/web/core/components/issues/issue-layouts/kanban/cover-image.tsx`:
- Around line 21-27: The imageLoadError state is set to true when image loading
fails but is never reset when a new coverImageAttachmentId arrives and
coverImageUrl updates. Add a useEffect hook that depends on coverImageUrl and
resets imageLoadError to false whenever coverImageUrl changes. This ensures that
when the useIssueCoverImage hook updates coverImageUrl with a new valid URL, the
stale error state from the previous failed image load is cleared and the
component can render the new image instead of continuing to return null.
In `@packages/i18n/src/locales/cs/common.json`:
- Around line 766-777: The newly added cover-image related strings in the Czech
locale file are currently in English, causing mixed-language UI for Czech users.
Translate all twelve strings (make_cover_image, remove_cover_image,
set_cover_loading, set_cover_success_title, set_cover_success_message,
set_cover_error_title, set_cover_error_message, remove_cover_loading,
remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message) from English to Czech
to ensure consistent localization throughout the cover image workflow.
In `@packages/i18n/src/locales/de/common.json`:
- Around line 766-777: The cover image feature strings in the German locale file
(packages/i18n/src/locales/de/common.json) are currently in English, causing
mixed-language UI for German users. Translate all twelve newly added strings
(make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) to their proper German equivalents to maintain
language consistency throughout the cover image workflow.
In `@packages/i18n/src/locales/es/common.json`:
- Around line 766-777: The newly added cover-image related strings in
packages/i18n/src/locales/es/common.json are in English, causing mixed-language
display for Spanish users. Translate all the English values for the keys from
make_cover_image through remove_cover_error_message into proper Spanish
translations. This includes the action labels, loading states, success messages,
and error messages for the cover image feature. Ensure each key maintains its
corresponding Spanish translation value rather than the English text currently
present.
In `@packages/i18n/src/locales/fr/common.json`:
- Around line 766-777: The newly added cover image strings in the French locale
file are still in English, causing French users to see mixed-language content in
the same workflow. Translate all twelve string values for the keys
"make_cover_image", "remove_cover_image", "set_cover_loading",
"set_cover_success_title", "set_cover_success_message", "set_cover_error_title",
"set_cover_error_message", "remove_cover_loading", "remove_cover_success_title",
"remove_cover_success_message", "remove_cover_error_title", and
"remove_cover_error_message" from their current English values to appropriate
French translations in the common.json file.
In `@packages/i18n/src/locales/id/common.json`:
- Around line 766-777: The newly added cover-image related strings in the
Indonesian locale file (id/common.json) are currently in English, causing
mixed-language display for Indonesian users. Translate all twelve cover-image
string values to Indonesian: make_cover_image, remove_cover_image,
set_cover_loading, set_cover_success_title, set_cover_success_message,
set_cover_error_title, set_cover_error_message, remove_cover_loading,
remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message. Keep the keys
unchanged; only replace the English text values with proper Indonesian
translations.
In `@packages/i18n/src/locales/it/common.json`:
- Around line 766-777: Translate all the newly added cover-image related strings
from English to Italian in the common.json file for the Italian locale. The
strings that need translation are: make_cover_image, remove_cover_image,
set_cover_loading, set_cover_success_title, set_cover_success_message,
set_cover_error_title, set_cover_error_message, remove_cover_loading,
remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message. Replace each English
value with its appropriate Italian translation to ensure consistent language
presentation for Italian users throughout the cover image flow.
In `@packages/i18n/src/locales/ja/common.json`:
- Around line 766-777: The cover-image related keys (make_cover_image,
remove_cover_image, set_cover_loading, set_cover_success_title,
set_cover_success_message, set_cover_error_title, set_cover_error_message,
remove_cover_loading, remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, remove_cover_error_message) were added in English but
not translated into other locales, causing mixed-language UI. Replace all these
key values with appropriate translations in each locale file: at
packages/i18n/src/locales/ja/common.json lines 766-777 with Japanese
translations, at packages/i18n/src/locales/ko/common.json lines 766-777 with
Korean translations, at packages/i18n/src/locales/pl/common.json lines 766-777
with Polish translations, at packages/i18n/src/locales/pt-BR/common.json lines
766-777 with Portuguese (Brazil) translations, at
packages/i18n/src/locales/ro/common.json lines 766-777 with Romanian
translations, and at packages/i18n/src/locales/ru/common.json lines 766-777 with
Russian translations.
In `@packages/i18n/src/locales/sk/common.json`:
- Around line 766-777: Translate all the English cover image strings in the
Slovak locale file to Slovak. The strings with keys make_cover_image,
remove_cover_image, set_cover_loading, set_cover_success_title,
set_cover_success_message, set_cover_error_title, set_cover_error_message,
remove_cover_loading, remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message currently contain
English text. Replace each English value with its appropriate Slovak translation
to ensure consistent localization and avoid mixed-language UI in the Slovak
locale.
In `@packages/i18n/src/locales/tr-TR/common.json`:
- Around line 766-777: The cover-image related strings in the Turkish locale
file (packages/i18n/src/locales/tr-TR/common.json) are currently in English and
need to be translated to Turkish. Replace the English values for all twelve keys
(make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) with their appropriate Turkish translations to
ensure Turkish users see localized content in the UI for cover image actions and
toast messages.
In `@packages/i18n/src/locales/ua/common.json`:
- Around line 766-777: The cover image related strings in the Ukrainian locale
file (make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message keys) are currently in English rather than Ukrainian,
breaking localization consistency. Translate each of these string values from
English to their corresponding Ukrainian equivalents while keeping the key names
unchanged.
In `@packages/i18n/src/locales/vi-VN/common.json`:
- Around line 766-777: The cover-image related strings in the Vietnamese locale
file are currently in English and need to be translated to Vietnamese. Translate
all twelve keys (make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) from their English values to their appropriate
Vietnamese equivalents to ensure the cover image workflow is fully localized for
Vietnamese users.
In `@packages/i18n/src/locales/zh-CN/common.json`:
- Around line 766-777: The cover-image related strings in the Simplified Chinese
locale file are currently in English instead of being translated to Chinese. In
packages/i18n/src/locales/zh-CN/common.json, translate the values for the
following keys from English to Simplified Chinese: make_cover_image,
remove_cover_image, set_cover_loading, set_cover_success_title,
set_cover_success_message, set_cover_error_title, set_cover_error_message,
remove_cover_loading, remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message. Ensure each
translation is contextually appropriate and consistent with the existing tone
and style of the zh-CN locale file.
In `@packages/i18n/src/locales/zh-TW/common.json`:
- Around line 766-777: The cover image feature strings in the zh-TW locale file
(make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) are currently in English instead of Traditional
Chinese. Translate each of these twelve string values from English to
Traditional Chinese to ensure consistent localization for zh-TW users.
---
Nitpick comments:
In `@apps/web/core/components/issues/attachment/attachment-item-list.tsx`:
- Around line 71-98: The handleToggleCoverImage function uses promise chaining
without explicit typed error handling and logging, making failures difficult to
diagnose. Add a try-catch block around the updateIssue call to explicitly catch
and log errors with proper error type handling. Inside the catch block, log the
error with appropriate context to aid debugging, then re-throw or handle the
error appropriately so setPromiseToast can still handle the error state. This
ensures all async failures in the cover image toggle operation are properly
captured and logged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a3f955f0-6deb-483b-ab06-c2d43150909e
📒 Files selected for processing (37)
apps/api/plane/app/serializers/issue.pyapps/api/plane/app/views/issue/attachment.pyapps/api/plane/app/views/issue/base.pyapps/api/plane/app/views/issue/sub_issue.pyapps/api/plane/db/migrations/0122_issue_cover_image_attachment.pyapps/api/plane/db/models/issue.pyapps/api/plane/utils/grouper.pyapps/web/core/components/issues/attachment/attachment-item-list.tsxapps/web/core/components/issues/attachment/attachment-list-item.tsxapps/web/core/components/issues/issue-detail/cover-image.tsxapps/web/core/components/issues/issue-detail/main-content.tsxapps/web/core/components/issues/issue-layouts/kanban/block.tsxapps/web/core/components/issues/issue-layouts/kanban/cover-image.tsxapps/web/core/components/issues/peek-overview/issue-detail.tsxapps/web/core/hooks/use-issue-cover-image.tsapps/web/core/store/issue/issue-details/attachment.store.tsapps/web/core/store/issue/issue-details/issue.store.tspackages/i18n/src/locales/cs/common.jsonpackages/i18n/src/locales/de/common.jsonpackages/i18n/src/locales/en/common.jsonpackages/i18n/src/locales/es/common.jsonpackages/i18n/src/locales/fr/common.jsonpackages/i18n/src/locales/id/common.jsonpackages/i18n/src/locales/it/common.jsonpackages/i18n/src/locales/ja/common.jsonpackages/i18n/src/locales/ko/common.jsonpackages/i18n/src/locales/pl/common.jsonpackages/i18n/src/locales/pt-BR/common.jsonpackages/i18n/src/locales/ro/common.jsonpackages/i18n/src/locales/ru/common.jsonpackages/i18n/src/locales/sk/common.jsonpackages/i18n/src/locales/tr-TR/common.jsonpackages/i18n/src/locales/ua/common.jsonpackages/i18n/src/locales/vi-VN/common.jsonpackages/i18n/src/locales/zh-CN/common.jsonpackages/i18n/src/locales/zh-TW/common.jsonpackages/types/src/issues/issue.ts
| "make_cover_image": "Make cover image", | ||
| "remove_cover_image": "Remove cover image", | ||
| "set_cover_loading": "Setting cover image...", | ||
| "set_cover_success_title": "Cover image set", | ||
| "set_cover_success_message": "This image is now the cover image", | ||
| "set_cover_error_title": "Couldn't set cover image", | ||
| "set_cover_error_message": "Could not set this image as the cover", | ||
| "remove_cover_loading": "Removing cover image...", | ||
| "remove_cover_success_title": "Cover image removed", | ||
| "remove_cover_success_message": "This work item no longer has a cover image", | ||
| "remove_cover_error_title": "Couldn't remove cover image", | ||
| "remove_cover_error_message": "Could not remove the cover image" |
There was a problem hiding this comment.
Localize the new cover-image strings for this locale.
The newly added values are in English, so German users will see mixed-language labels/toasts in the same flow.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/i18n/src/locales/de/common.json` around lines 766 - 777, The cover
image feature strings in the German locale file
(packages/i18n/src/locales/de/common.json) are currently in English, causing
mixed-language UI for German users. Translate all twelve newly added strings
(make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) to their proper German equivalents to maintain
language consistency throughout the cover image workflow.
| "make_cover_image": "Make cover image", | ||
| "remove_cover_image": "Remove cover image", | ||
| "set_cover_loading": "Setting cover image...", | ||
| "set_cover_success_title": "Cover image set", | ||
| "set_cover_success_message": "This image is now the cover image", | ||
| "set_cover_error_title": "Couldn't set cover image", | ||
| "set_cover_error_message": "Could not set this image as the cover", | ||
| "remove_cover_loading": "Removing cover image...", | ||
| "remove_cover_success_title": "Cover image removed", | ||
| "remove_cover_success_message": "This work item no longer has a cover image", | ||
| "remove_cover_error_title": "Couldn't remove cover image", | ||
| "remove_cover_error_message": "Could not remove the cover image" |
There was a problem hiding this comment.
Localize new cover-image strings for Turkish.
The newly added cover-image keys are English strings, so Turkish users will see untranslated content in attachment actions/toasts.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/i18n/src/locales/tr-TR/common.json` around lines 766 - 777, The
cover-image related strings in the Turkish locale file
(packages/i18n/src/locales/tr-TR/common.json) are currently in English and need
to be translated to Turkish. Replace the English values for all twelve keys
(make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) with their appropriate Turkish translations to
ensure Turkish users see localized content in the UI for cover image actions and
toast messages.
| "make_cover_image": "Make cover image", | ||
| "remove_cover_image": "Remove cover image", | ||
| "set_cover_loading": "Setting cover image...", | ||
| "set_cover_success_title": "Cover image set", | ||
| "set_cover_success_message": "This image is now the cover image", | ||
| "set_cover_error_title": "Couldn't set cover image", | ||
| "set_cover_error_message": "Could not set this image as the cover", | ||
| "remove_cover_loading": "Removing cover image...", | ||
| "remove_cover_success_title": "Cover image removed", | ||
| "remove_cover_success_message": "This work item no longer has a cover image", | ||
| "remove_cover_error_title": "Couldn't remove cover image", | ||
| "remove_cover_error_message": "Could not remove the cover image" |
There was a problem hiding this comment.
Localize new cover-image strings for Ukrainian.
attachment.make_cover_image and related set/remove cover toast strings are English here, which breaks localization consistency for ua.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/i18n/src/locales/ua/common.json` around lines 766 - 777, The cover
image related strings in the Ukrainian locale file (make_cover_image,
remove_cover_image, set_cover_loading, set_cover_success_title,
set_cover_success_message, set_cover_error_title, set_cover_error_message,
remove_cover_loading, remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message keys) are currently in
English rather than Ukrainian, breaking localization consistency. Translate each
of these string values from English to their corresponding Ukrainian equivalents
while keeping the key names unchanged.
| "make_cover_image": "Make cover image", | ||
| "remove_cover_image": "Remove cover image", | ||
| "set_cover_loading": "Setting cover image...", | ||
| "set_cover_success_title": "Cover image set", | ||
| "set_cover_success_message": "This image is now the cover image", | ||
| "set_cover_error_title": "Couldn't set cover image", | ||
| "set_cover_error_message": "Could not set this image as the cover", | ||
| "remove_cover_loading": "Removing cover image...", | ||
| "remove_cover_success_title": "Cover image removed", | ||
| "remove_cover_success_message": "This work item no longer has a cover image", | ||
| "remove_cover_error_title": "Couldn't remove cover image", | ||
| "remove_cover_error_message": "Could not remove the cover image" |
There was a problem hiding this comment.
Localize new cover-image strings for Vietnamese.
The new cover-image labels/messages are English in the vi-VN locale, so this flow won’t be fully localized for Vietnamese users.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/i18n/src/locales/vi-VN/common.json` around lines 766 - 777, The
cover-image related strings in the Vietnamese locale file are currently in
English and need to be translated to Vietnamese. Translate all twelve keys
(make_cover_image, remove_cover_image, set_cover_loading,
set_cover_success_title, set_cover_success_message, set_cover_error_title,
set_cover_error_message, remove_cover_loading, remove_cover_success_title,
remove_cover_success_message, remove_cover_error_title, and
remove_cover_error_message) from their English values to their appropriate
Vietnamese equivalents to ensure the cover image workflow is fully localized for
Vietnamese users.
| "make_cover_image": "Make cover image", | ||
| "remove_cover_image": "Remove cover image", | ||
| "set_cover_loading": "Setting cover image...", | ||
| "set_cover_success_title": "Cover image set", | ||
| "set_cover_success_message": "This image is now the cover image", | ||
| "set_cover_error_title": "Couldn't set cover image", | ||
| "set_cover_error_message": "Could not set this image as the cover", | ||
| "remove_cover_loading": "Removing cover image...", | ||
| "remove_cover_success_title": "Cover image removed", | ||
| "remove_cover_success_message": "This work item no longer has a cover image", | ||
| "remove_cover_error_title": "Couldn't remove cover image", | ||
| "remove_cover_error_message": "Could not remove the cover image" |
There was a problem hiding this comment.
Localize new cover-image strings for Simplified Chinese.
The added cover-image action/toast strings are still English, which introduces inconsistent language in zh-CN.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/i18n/src/locales/zh-CN/common.json` around lines 766 - 777, The
cover-image related strings in the Simplified Chinese locale file are currently
in English instead of being translated to Chinese. In
packages/i18n/src/locales/zh-CN/common.json, translate the values for the
following keys from English to Simplified Chinese: make_cover_image,
remove_cover_image, set_cover_loading, set_cover_success_title,
set_cover_success_message, set_cover_error_title, set_cover_error_message,
remove_cover_loading, remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message. Ensure each
translation is contextually appropriate and consistent with the existing tone
and style of the zh-CN locale file.
| "make_cover_image": "Make cover image", | ||
| "remove_cover_image": "Remove cover image", | ||
| "set_cover_loading": "Setting cover image...", | ||
| "set_cover_success_title": "Cover image set", | ||
| "set_cover_success_message": "This image is now the cover image", | ||
| "set_cover_error_title": "Couldn't set cover image", | ||
| "set_cover_error_message": "Could not set this image as the cover", | ||
| "remove_cover_loading": "Removing cover image...", | ||
| "remove_cover_success_title": "Cover image removed", | ||
| "remove_cover_success_message": "This work item no longer has a cover image", | ||
| "remove_cover_error_title": "Couldn't remove cover image", | ||
| "remove_cover_error_message": "Could not remove the cover image" |
There was a problem hiding this comment.
Translate new attachment cover-image strings in zh-TW locale.
Lines 766-777 are still English, which causes mixed-language UI for Traditional Chinese users.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/i18n/src/locales/zh-TW/common.json` around lines 766 - 777, The
cover image feature strings in the zh-TW locale file (make_cover_image,
remove_cover_image, set_cover_loading, set_cover_success_title,
set_cover_success_message, set_cover_error_title, set_cover_error_message,
remove_cover_loading, remove_cover_success_title, remove_cover_success_message,
remove_cover_error_title, and remove_cover_error_message) are currently in
English instead of Traditional Chinese. Translate each of these twelve string
values from English to Traditional Chinese to ensure consistent localization for
zh-TW users.
- Reset the image load-error flag when the cover URL changes, so a new valid cover renders after a previous one failed to load (kanban + detail). - Reject a cover_image_attachment on issue create: a new issue has no attachments of its own yet, so the ownership check now requires an existing instance instead of being skipped on create. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Description
Closes #3921.
Lets users designate any image attachment on a work item as its cover image, displayed on Kanban cards and the
detail/peek views — giving design-oriented teams a quick visual preview as the issue requests.
The cover is set/cleared from the attachment's context menu ("Make cover image" / "Remove cover image") and
persisted via a new
cover_image_attachmentforeign key on the issue.Design note: #3921 floats two ways to choose a cover — upload one, or auto-use the first image in the
description. This PR implements the explicit approach (the user picks which attachment is the cover) rather than
auto-detecting, so the cover is deterministic and user-controlled rather than changing implicitly as description
content changes.
Issue.cover_image_attachmentFK →FileAsset(migration0122), exposes and validatescover_image_attachment_idin the issue serializer (must be an image attachment belonging to the work item), andincludes it in the issue list/detail/sub-issue/grouper projections.
cards and the detail/peek views, and adds the set/remove action to the attachment menu.
Type of Change
Screenshots and Media (if applicable)
Screen.Recording.2026-06-15.at.3.48.18.PM.mov
Test Scenarios
views.
cover_image_attachment_idthat isn't an image attachment belonging to the work item.pnpm --filter @plane/i18n run sync:checkpasses (all locales in sync).References
Closes #3921
Summary by CodeRabbit
Release Notes