Skip to content

refactor(core): replace Gravatar with reusable UserAvatar component#3927

Merged
PierreBrisorgueil merged 4 commits intomasterfrom
refactor/user-avatar-decomission-gravatar
Apr 9, 2026
Merged

refactor(core): replace Gravatar with reusable UserAvatar component#3927
PierreBrisorgueil merged 4 commits intomasterfrom
refactor/user-avatar-decomission-gravatar

Conversation

@PierreBrisorgueil
Copy link
Copy Markdown
Collaborator

@PierreBrisorgueil PierreBrisorgueil commented Apr 9, 2026

Summary

  • What changed: Removed Gravatar plugin and rewrote UserAvatar component to use Vuetify v-avatar with initials fallback instead of Gravatar API. Simplified the component API from 8 props to 2 (user + size). Updated all consumers (datatable, profile, team member, org members).
  • Why: Gravatar is an unnecessary external dependency that leaks user emails via hashed URLs, adds latency, and provides a poor fallback (generic silhouette). Initials with consistent email-based colors are a better default.
  • Related issues: Closes refactor: decomission Gravatar plugin — use initials avatar #3921, Closes feat(core): expose reusable UserAvatar component #3923

Scope

  • Modules impacted: core (avatar component), lib/plugins (gravatar removal), users, organizations, home
  • Cross-module impact: yes — all consumers of userAvatarComponent updated to new simplified API
  • Risk level: medium — breaking API change for avatar component props, but all internal consumers updated

Validation

  • npm run lint
  • npm run test:unit
  • npm run build
  • Manual checks done (if applicable)

Guardrails check

  • No secrets or credentials introduced (.env*, secrets/**, keys, tokens)
  • No risky rename/move of core stack paths
  • Changes remain merge-friendly for downstream projects
  • Tests added or updated when behavior changed

Before vs After (key changes only)

Area Before After Notes
Avatar fallback Gravatar API (external HTTP) Colored initials (local) No network dependency
Component API 8 props (width, height, radius, border, color, size, disabled, user) 2 props (user, size) Breaking change for consumers
Gravatar plugin Registered globally via .use() Removed Deleted plugin + tests
Avatar shape Manual CSS border-radius Vuetify v-avatar (always circular) Consistent with design system

Notes for reviewers

  • Security considerations: Removes email hash leaking to Gravatar CDN
  • Mergeability considerations: Downstream projects using userAvatarComponent with old props will need to update to size prop
  • Follow-up tasks: Downstream projects need prop migration (width/heightsize)

Summary by CodeRabbit

  • Breaking Changes

    • UserAvatarComponent simplified: removed width, height, radius, border, color, and disabled props. Now uses size prop exclusively. user prop is optional with default size of 32.
    • Avatar rendering now displays uploaded images with colored initials fallback.
    • Removed Gravatar plugin integration.
  • Tests

    • Added UserAvatarComponent unit tests; updated e2e test locators.

Remove Gravatar plugin dependency and replace with initials-based avatar
fallback. The new UserAvatar component shows uploaded avatar images or
colored initials derived from email hash, with a simplified API (user + size).

Closes #3921, Closes #3923
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Warning

Rate limit exceeded

@PierreBrisorgueil has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 11 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 15 minutes and 11 seconds.

⌛ 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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6c78bffb-18b8-49f9-b691-119e8a80654e

📥 Commits

Reviewing files that changed from the base of the PR and between 5966fa8 and 46be246.

📒 Files selected for processing (3)
  • MIGRATIONS.md
  • src/modules/core/components/user.avatar.component.vue
  • src/modules/core/tests/user.avatar.component.unit.tests.js

Walkthrough

Removed Gravatar plugin and refactored UserAvatarComponent to display uploaded images with colored initials fallback. Updated component API from multi-prop styling inputs to single size prop, removed Gravatar dependency, and updated all downstream usages and tests accordingly.

Changes

Cohort / File(s) Summary
Gravatar Plugin Removal
src/lib/plugins/gravatar.js, src/lib/plugins/index.js, src/lib/plugins/tests/gravatar.unit.tests.js
Removed entire Gravatar plugin module, its export from the plugins registry, and corresponding unit test suite (85 + 159 lines of plugin code/tests deleted).
UserAvatarComponent Refactor
src/modules/core/components/user.avatar.component.vue
Replaced Gravatar-based rendering with uploaded image + initials fallback. Props changed from user, size, width, height, radius, border, color, disabled to user (optional, default null) and size (default 32). Added computed properties for initials, full name, avatar color, and contrast-aware text styling.
Avatar Component Integration Updates
src/modules/core/components/core.datatable.component.vue, src/modules/home/components/team.member.component.vue, src/modules/organizations/components/organizations.members.component.vue, src/modules/users/components/user.profile.component.vue
Updated UserAvatarComponent usages by removing explicit styling props (width, height, radius, border, color) and replacing with single :size prop across four component instances.
Plugin Initialization & Test Updates
src/main.js, src/lib/plugins/tests/index.unit.tests.js, src/modules/core/tests/user.avatar.component.unit.tests.js
Removed Gravatar plugin registration from app startup, updated plugin index tests to exclude Gravatar, and added comprehensive new unit test suite for UserAvatarComponent with 175 lines covering props, computed properties, initials generation, color assignment, and conditional rendering.
E2E Test Selector Refinements
src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js, src/modules/organizations/tests/organizations.lifecycle.e2e.tests.js
Improved test assertions by scoping element selectors to role-based queries (getByRole, getByText within main region) for better specificity and maintainability.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Feat, Tests

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: replacing Gravatar plugin with a reusable UserAvatar component based on the initials approach.
Description check ✅ Passed The pull request description provides a comprehensive overview matching the template, with clear summaries, scope, validation details, guardrails checks, and key before/after comparisons for the changes made.
Linked Issues check ✅ Passed All coding requirements from #3921 and #3923 are met: Gravatar plugin and tests removed, component updated to use initials with email-derived colors, all consumers updated, migration docs provided, and tests added/updated.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objectives. E2E test locator updates are necessary adjustments for the component refactoring and do not introduce unrelated functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/user-avatar-decomission-gravatar

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.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.45%. Comparing base (f1223e6) to head (46be246).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3927      +/-   ##
==========================================
+ Coverage   99.26%   99.45%   +0.19%     
==========================================
  Files          30       29       -1     
  Lines         946      922      -24     
  Branches      246      243       -3     
==========================================
- Hits          939      917      -22     
+ Misses          7        5       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@PierreBrisorgueil PierreBrisorgueil marked this pull request as ready for review April 9, 2026 09:36
Copilot AI review requested due to automatic review settings April 9, 2026 09:36
Copy link
Copy Markdown

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

Refactors the core user avatar rendering to remove the Gravatar dependency (privacy + latency) and replace it with a reusable UserAvatarComponent that renders either an uploaded avatar image or a colored initials fallback, then updates call sites accordingly.

Changes:

  • Removed the gravatar plugin (and its unit tests) and unregistered it from the app/plugin index.
  • Rewrote UserAvatarComponent to use Vuetify v-avatar + initials fallback with deterministic email-based colors.
  • Updated avatar consumers (profile, datatable, org members, home team member) to the new user + size API.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/modules/core/components/user.avatar.component.vue Replaces Gravatar-based rendering with v-avatar + initials + tooltip and simplifies props.
src/modules/core/tests/user.avatar.component.unit.tests.js Adds unit coverage for the new avatar component behavior.
src/modules/core/components/core.datatable.component.vue Updates datatable avatar cell to use the new size prop API.
src/modules/users/components/user.profile.component.vue Updates profile avatar to use the new size prop API.
src/modules/organizations/components/organizations.members.component.vue Updates members list avatar slot to use the new size prop API.
src/modules/home/components/team.member.component.vue Updates team member card avatar usage to the new size prop API.
src/main.js Removes .use(plugins.gravatar) registration.
src/lib/plugins/index.js Removes gravatar plugin export.
src/lib/plugins/tests/index.unit.tests.js Updates expected plugin list after gravatar removal.
src/lib/plugins/gravatar.js Deletes the gravatar plugin implementation.
src/lib/plugins/tests/gravatar.unit.tests.js Deletes gravatar plugin unit tests.

Comment thread src/modules/core/components/user.avatar.component.vue Outdated
Comment thread src/modules/core/components/user.avatar.component.vue
Comment thread src/modules/core/components/user.avatar.component.vue Outdated
Comment thread src/modules/core/components/user.avatar.component.vue
Comment thread src/modules/core/tests/user.avatar.component.unit.tests.js
The OrgAvatar tooltip renders the org name in the DOM, causing
Playwright strict mode violations when getByText/locator('text=...')
matches both the original element and tooltip overlays.
- Remove conflicting activator="parent" on v-tooltip (use slot only)
- Make user prop optional (default null) to match null-handling in computed
- Add luminance-based text color contrast (text-black on light backgrounds)
- Add MIGRATIONS.md entry for breaking API change
- Strengthen size test to assert actual width/height on v-avatar
- Add textColorClass computed property tests
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@MIGRATIONS.md`:
- Around line 21-29: Add blank lines before and after the fenced code block in
the "Replace old avatar usage" section of MIGRATIONS.md so the Markdown is valid
(MD031); specifically, ensure there is an empty line immediately above the
```vue fence that contains the "Before/After" userAvatarComponent example and an
empty line immediately after the closing ``` fence so the subsequent line "3.
Remove any `disabled` prop usage — the component no longer wraps in an `<a>`
tag" is not adjacent to the fence.

In `@src/modules/core/components/user.avatar.component.vue`:
- Around line 34-65: The JSDoc blocks are misplaced: the doc for stringToColor
appears above isLightColor while stringToColor lacks its header; update the file
so each function has its JSDoc immediately above it — add or move a JSDoc block
with `@param` {string} hex and `@returns` {boolean} above isLightColor, and add/move
a JSDoc block with `@param` {string} str and `@returns` {string} above stringToColor
(keep descriptions consistent with current comments).

In `@src/modules/core/tests/user.avatar.component.unit.tests.js`:
- Around line 106-125: Add a unit test that covers the avatarColor computed when
the user.email is missing: use the existing createWrapper helper to mount the
component with a user object lacking an email (e.g., { firstName: 'John' }) and
assert wrapper.vm.avatarColor still returns a valid 6-digit hex color; reference
the avatarColor computed and the fallback behavior that uses
stringToColor((this.user && this.user.email) || '') so the test ensures the
empty-string fallback produces a hex color.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f90870c8-a7c2-4490-9dc7-6c54a6f5ec1b

📥 Commits

Reviewing files that changed from the base of the PR and between f1223e6 and 5966fa8.

📒 Files selected for processing (14)
  • MIGRATIONS.md
  • src/lib/plugins/gravatar.js
  • src/lib/plugins/index.js
  • src/lib/plugins/tests/gravatar.unit.tests.js
  • src/lib/plugins/tests/index.unit.tests.js
  • src/main.js
  • src/modules/core/components/core.datatable.component.vue
  • src/modules/core/components/user.avatar.component.vue
  • src/modules/core/tests/user.avatar.component.unit.tests.js
  • src/modules/home/components/team.member.component.vue
  • src/modules/organizations/components/organizations.members.component.vue
  • src/modules/organizations/tests/organizations.domainJoin.e2e.tests.js
  • src/modules/organizations/tests/organizations.lifecycle.e2e.tests.js
  • src/modules/users/components/user.profile.component.vue
💤 Files with no reviewable changes (4)
  • src/lib/plugins/index.js
  • src/main.js
  • src/lib/plugins/gravatar.js
  • src/lib/plugins/tests/gravatar.unit.tests.js

Comment thread MIGRATIONS.md
Comment thread src/modules/core/components/user.avatar.component.vue Outdated
Comment thread src/modules/core/tests/user.avatar.component.unit.tests.js
- Reorder JSDoc blocks so each is directly above its function
- Add blank lines around fenced code block in MIGRATIONS.md (MD031)
- Add missing email edge case test for avatarColor computed
@PierreBrisorgueil PierreBrisorgueil merged commit a5f4e9a into master Apr 9, 2026
6 checks passed
PierreBrisorgueil added a commit that referenced this pull request Apr 13, 2026
setImages was unconditionally concatenating `:${api.port}`, producing
malformed URLs like `https://host:/api/...` on HTTPS deployments where
port is empty (standard prod on port 443). This broke user avatars
everywhere UserAvatarComponent is used after the Gravatar refactor
(a5f4e9a, #3927), since avatars now go through setImages.

Adds conditional port handling matching the pattern already used in
screenshotUrl.js. Adds unit tests for empty and undefined port cases.
Existing tests with port '3000' still pass unchanged.

Fixes #3963
PierreBrisorgueil added a commit that referenced this pull request Apr 13, 2026
* fix(images): omit port when api.port is empty or undefined

setImages was unconditionally concatenating `:${api.port}`, producing
malformed URLs like `https://host:/api/...` on HTTPS deployments where
port is empty (standard prod on port 443). This broke user avatars
everywhere UserAvatarComponent is used after the Gravatar refactor
(a5f4e9a, #3927), since avatars now go through setImages.

Adds conditional port handling matching the pattern already used in
screenshotUrl.js. Adds unit tests for empty and undefined port cases.
Existing tests with port '3000' still pass unchanged.

Fixes #3963

* docs(images): add JSDoc for install and setImages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(core): expose reusable UserAvatar component refactor: decomission Gravatar plugin — use initials avatar

2 participants