Story 2458: Webpage Integration: Edit User Profile - Bio and tagline#2502
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adds biography, tagline, and profile-links fields to the User model with related migrations, serializer validation, and admin/form/view wiring. It introduces a WYSIWYG editor "bio" preset with disabled-button styling and character-limit enforcement, and reworks the profile edit page into an Alpine-driven async save flow. A testimonial asset path is also corrected. ChangesProfile editing
Estimated code review effort: 4 (Complex) | ~60 minutes Mock data cleanup
Sequence Diagram(s)sequenceDiagram
participant User
participant ProfileEditPage as templates/v3/user_profile_edit.html
participant ProfileForm as window.profileForm
participant WysiwygEditor as frontend/wysiwyg-editor.js
participant UsersApi as /api/v1/users/me/
User->>ProfileEditPage: edit tagline, biography, links
WysiwygEditor->>ProfileEditPage: wysiwyg-update (markdownCharacters)
User->>ProfileForm: click "Save Changes"
ProfileForm->>WysiwygEditor: currentBiography()
ProfileForm->>ProfileForm: validate links and biography length
ProfileForm->>UsersApi: PATCH tagline, biography, profile_links
UsersApi-->>ProfileForm: success/error response
ProfileForm-->>ProfileEditPage: update saveStatus/saveError
Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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 |
jlchilders11
left a comment
There was a problem hiding this comment.
In addition to a few nits that I'd like updated, I notice that the submit functionality doesn't seem to have a non javascript version?
Got it! Made changes in accordance with your comments, which I think they were all correct. With respect to the submit functionality not having a non-JS version, however, I consider this could be handled separately because it requires a page-wide change. We don't currently have any What do you think? Sorry if I missed this part. I didn't get it from the ticket's descripton. |
90693e0 to
8cc21df
Compare
So the form elements were not added to the UI, since it was assumed the integrator would put those elements where they believed they would work best. I do believe there may be a larger discussion about how we want to handle the full page submission, since it seems the integration tickets don't handle that case/non js version. |
|
Per discussion with Teo, the JS-less submit will be spun off into its own ticket, to be completed once all other sections are complete: #2509 |
julhoang
left a comment
There was a problem hiding this comment.
Hi @javiercoronadonarvaez , I've added a couple of request below. Additionally, would you mind adding a top margin/padding above the "This tagline is displayed next..." help text to better match Figma? Thanks a lot!
| /* | ||
| Biography toolbar icons, normalized to `currentColor` so they inherit the | ||
| toolbar button colour and active/hover states. Used only by the "bio" toolbar | ||
| preset so the icons on other editors (news, examples) are unchanged. | ||
| */ | ||
| export const BIO_ICONS = { | ||
| bold: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M12.7096 9.83464C13.1177 9.58617 13.462 9.24582 13.7152 8.84071C13.9684 8.4356 14.1234 7.97694 14.168 7.5013C14.1757 7.07121 14.0986 6.6438 13.9411 6.2435C13.7837 5.84319 13.5489 5.47783 13.2501 5.16829C12.9514 4.85875 12.5947 4.61109 12.2002 4.43945C11.8058 4.26781 11.3814 4.17556 10.9513 4.16797H5.54297V15.8346H11.3763C11.7856 15.8303 12.19 15.7453 12.5665 15.5847C12.943 15.424 13.2841 15.1908 13.5704 14.8983C13.8567 14.6058 14.0826 14.2597 14.2352 13.8799C14.3878 13.5001 14.464 13.0939 14.4596 12.6846V12.5846C14.4599 12.0072 14.2954 11.4417 13.9854 10.9546C13.6754 10.4675 13.2328 10.0789 12.7096 9.83464ZM7.20964 5.83464H10.7096C11.0648 5.82364 11.4148 5.92154 11.7127 6.11518C12.0106 6.30882 12.2422 6.58895 12.3763 6.91797C12.512 7.35779 12.4681 7.83346 12.2542 8.24101C12.0403 8.64857 11.6737 8.95487 11.2346 9.09297C11.0641 9.14294 10.8873 9.1682 10.7096 9.16797H7.20964V5.83464ZM11.043 14.168H7.20964V10.8346H11.043C11.3981 10.8236 11.7481 10.9215 12.046 11.1152C12.3439 11.3088 12.5755 11.5889 12.7096 11.918C12.8454 12.3578 12.8015 12.8335 12.5875 13.241C12.3736 13.6486 12.0071 13.9549 11.568 14.093C11.3975 14.1429 11.2207 14.1682 11.043 14.168Z"/></svg>', | ||
| italic: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M9.79818 7.5013H11.4648L9.63151 15.8346H7.96484L9.79818 7.5013ZM11.1982 4.16797C11.0334 4.16797 10.8722 4.21684 10.7352 4.30841C10.5982 4.39998 10.4914 4.53013 10.4283 4.6824C10.3652 4.83467 10.3487 5.00223 10.3809 5.16388C10.413 5.32553 10.4924 5.47401 10.6089 5.59056C10.7255 5.7071 10.874 5.78647 11.0356 5.81862C11.1973 5.85078 11.3648 5.83427 11.5171 5.7712C11.6694 5.70813 11.7995 5.60132 11.8911 5.46428C11.9826 5.32724 12.0315 5.16612 12.0315 5.0013C12.0315 4.78029 11.9437 4.56833 11.7874 4.41205C11.6312 4.25577 11.4192 4.16797 11.1982 4.16797Z"/></svg>', | ||
| underline: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M15.8346 16.668V18.3346H4.16797V16.668H15.8346ZM13.3346 11.0138C13.3072 11.5638 13.1439 12.0984 12.8594 12.5699C12.5749 13.0414 12.178 13.435 11.7042 13.7157C11.2304 13.9963 10.6945 14.1552 10.1443 14.1781C9.59412 14.2011 9.04681 14.0874 8.5513 13.8471C7.98017 13.6001 7.49581 13.1881 7.16028 12.664C6.82474 12.1399 6.65332 11.5276 6.66797 10.9055V4.17214H5.0013V11.0138C5.0295 11.7983 5.24201 12.5652 5.62165 13.2523C6.00129 13.9394 6.53738 14.5274 7.18653 14.9689C7.83568 15.4103 8.57964 15.6927 9.3582 15.7931C10.1368 15.8936 10.928 15.8093 11.668 15.5471C12.6522 15.2191 13.5062 14.5856 14.1057 13.7388C14.7051 12.8921 15.0189 11.8761 15.0013 10.8388V4.17214H13.3346V11.0138Z"/></svg>', | ||
| orderedList: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M2.08203 13.3346H3.7487V13.7513H2.91536V14.5846H3.7487V15.0013H2.08203V15.8346H4.58203V12.5013H2.08203V13.3346ZM2.91536 7.5013H3.7487V4.16797H2.08203V5.0013H2.91536V7.5013ZM2.08203 9.16797H3.58203L2.08203 10.918V11.668H4.58203V10.8346H3.08203L4.58203 9.08464V8.33464H2.08203V9.16797ZM6.2487 5.0013V6.66797H17.9154V5.0013H6.2487ZM6.2487 15.0013H17.9154V13.3346H6.2487V15.0013ZM6.2487 10.8346H17.9154V9.16797H6.2487V10.8346Z"/></svg>', | ||
| link: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M9.16797 14.1654H5.83464C4.72957 14.1654 3.66976 13.7264 2.88836 12.945C2.10696 12.1636 1.66797 11.1038 1.66797 9.9987C1.66797 8.89363 2.10696 7.83382 2.88836 7.05242C3.66976 6.27102 4.72957 5.83203 5.83464 5.83203H9.16797V7.4987H5.83464C5.17159 7.4987 4.53571 7.76209 4.06687 8.23093C3.59803 8.69977 3.33464 9.33566 3.33464 9.9987C3.33464 10.6617 3.59803 11.2976 4.06687 11.7665C4.53571 12.2353 5.17159 12.4987 5.83464 12.4987H9.16797V14.1654ZM14.168 5.83203H10.8346V7.4987H14.168C14.831 7.4987 15.4669 7.76209 15.9357 8.23093C16.4046 8.69977 16.668 9.33566 16.668 9.9987C16.668 10.6617 16.4046 11.2976 15.9357 11.7665C15.4669 12.2353 14.831 12.4987 14.168 12.4987H10.8346V14.1654H14.168C15.273 14.1654 16.3328 13.7264 17.1142 12.945C17.8956 12.1636 18.3346 11.1038 18.3346 9.9987C18.3346 8.89363 17.8956 7.83382 17.1142 7.05242C16.3328 6.27102 15.273 5.83203 14.168 5.83203ZM13.3346 9.16536H6.66797V10.832H13.3346V9.16536Z"/></svg>', | ||
| markdown: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M18.125 3.75H1.875C1.54348 3.75 1.22554 3.8817 0.991117 4.11612C0.756696 4.35054 0.625 4.66848 0.625 5V15C0.625 15.3315 0.756696 15.6495 0.991117 15.8839C1.22554 16.1183 1.54348 16.25 1.875 16.25H18.125C18.4565 16.25 18.7745 16.1183 19.0089 15.8839C19.2433 15.6495 19.375 15.3315 19.375 15V5C19.375 4.66848 19.2433 4.35054 19.0089 4.11612C18.7745 3.8817 18.4565 3.75 18.125 3.75ZM18.125 15H1.875V5H18.125V15ZM10 8.125V11.875C10 12.0408 9.93415 12.1997 9.81694 12.3169C9.69973 12.4342 9.54076 12.5 9.375 12.5C9.20924 12.5 9.05027 12.4342 8.93306 12.3169C8.81585 12.1997 8.75 12.0408 8.75 11.875V9.63359L7.31719 11.0672C7.25914 11.1253 7.19021 11.1714 7.11434 11.2029C7.03846 11.2343 6.95713 11.2505 6.875 11.2505C6.79287 11.2505 6.71154 11.2343 6.63566 11.2029C6.55979 11.1714 6.49086 11.1253 6.43281 11.0672L5 9.63359V11.875C5 12.0408 4.93415 12.1997 4.81694 12.3169C4.69973 12.4342 4.54076 12.5 4.375 12.5C4.20924 12.5 4.05027 12.4342 3.93306 12.3169C3.81585 12.1997 3.75 12.0408 3.75 11.875V8.125C3.7499 8.00132 3.78651 7.88038 3.85517 7.77751C3.92384 7.67464 4.02149 7.59446 4.13576 7.54711C4.25002 7.49977 4.37576 7.48739 4.49707 7.51154C4.61837 7.5357 4.72978 7.59531 4.81719 7.68281L6.875 9.74141L8.93281 7.68281C9.02022 7.59531 9.13163 7.5357 9.25293 7.51154C9.37424 7.48739 9.49998 7.49977 9.61424 7.54711C9.72851 7.59446 9.82616 7.67464 9.89483 7.77751C9.96349 7.88038 10.0001 8.00132 10 8.125ZM16.0672 9.55781C16.1253 9.61586 16.1714 9.68479 16.2029 9.76066C16.2343 9.83654 16.2505 9.91787 16.2505 10C16.2505 10.0821 16.2343 10.1635 16.2029 10.2393C16.1714 10.3152 16.1253 10.3841 16.0672 10.4422L14.1922 12.3172C14.1341 12.3753 14.0652 12.4214 13.9893 12.4529C13.9135 12.4843 13.8321 12.5005 13.75 12.5005C13.6679 12.5005 13.5865 12.4843 13.5107 12.4529C13.4348 12.4214 13.3659 12.3753 13.3078 12.3172L11.4328 10.4422C11.3155 10.3249 11.2497 10.1659 11.2497 10C11.2497 9.83415 11.3155 9.67509 11.4328 9.55781C11.5501 9.44054 11.7091 9.37465 11.875 9.37465C12.0409 9.37465 12.1999 9.44054 12.3172 9.55781L13.125 10.3664V8.125C13.125 7.95924 13.1908 7.80027 13.3081 7.68306C13.4253 7.56585 13.5842 7.5 13.75 7.5C13.9158 7.5 14.0747 7.56585 14.1919 7.68306C14.3092 7.80027 14.375 7.95924 14.375 8.125V10.3664L15.1828 9.55781C15.2409 9.4997 15.3098 9.4536 15.3857 9.42215C15.4615 9.3907 15.5429 9.37451 15.625 9.37451C15.7071 9.37451 15.7885 9.3907 15.8643 9.42215C15.9402 9.4536 16.0091 9.4997 16.0672 9.55781Z"/></svg>', | ||
| undo: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M8.66667 7.83203C7.25 8.08203 6 8.58203 4.83333 9.4987L2.5 7.08203V12.9154H8.33333L6.08333 10.6654C9.16667 8.4987 13.4167 9.16536 15.6667 12.2487C15.8333 12.4987 16 12.6654 16.0833 12.9154L17.5833 12.1654C15.75 8.9987 12.25 7.2487 8.66667 7.83203Z"/></svg>', | ||
| redo: | ||
| '<svg width="18" height="18" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path d="M11.3333 7.83203C12.75 8.08203 14 8.58203 15.1667 9.4987L17.5 7.08203V12.9154H11.6667L13.9167 10.6654C10.8333 8.41536 6.58333 9.16536 4.41667 12.2487C4.25 12.4987 4.08333 12.6654 4 12.9154L2.5 12.1654C4.25 8.9987 7.75 7.2487 11.3333 7.83203Z"/></svg>', | ||
| }; | ||
|
|
There was a problem hiding this comment.
Would you mind helping me understand why we're adding icons for just this Bio section? I thought the const ICONS above should already have these as well 🤔
There was a problem hiding this comment.
Hey Julia, using BIO_ICONS is intentional rather than a duplicate. The main reason is that bio design employs a different icon style than the existing ICONS set. In that sense, the news/examples editors read from ICONS, so if I folded the bio glyphs into ICONS, I'd silently change the toolbar appearance of other wysiwyg instance in the app.
Please note that wysiwyg for bio is different than how it's render in other places, like that for posts, for example. You could say that the bio wysiwyg is a more bare bones version. You only have a few of the total number of options to edit the text.
There was a problem hiding this comment.
Very well-spotted and thanks for flagging this! I've flagged this to Glauber and we can handle consolidating the icon set in a follow-up ticket.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
users/views.py (1)
368-371: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAmbiguous unicode apostrophe in fallback string.
Static analysis flags the
’(right single quotation mark, U+2019) in this fallback copy vs. a plain ASCII apostrophe. Cosmetic only, but worth normalizing for consistency with other fallback strings in this file.🤖 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 `@users/views.py` around lines 368 - 371, The fallback bio copy in the user context setup uses a non-ASCII apostrophe, which should be normalized for consistency with the other strings in this file. Update the fallback string in the logic that assigns ctx["bio"] within the user view to use a plain ASCII apostrophe instead of the curly apostrophe, keeping the message otherwise unchanged.Source: Linters/SAST tools
🤖 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 `@templates/v3/includes/_field_text.html`:
- Around line 100-101: The Alpine state for the text field is still initializing
value to an empty string, so prefilled server-rendered text is not preserved and
the counter starts incorrectly. Update the x-data initialization in the field
text template so the value state is seeded from the rendered input value when
max_chars/x-model="value" is used, and make sure the character counter derives
from that initial value in the same component.
---
Nitpick comments:
In `@users/views.py`:
- Around line 368-371: The fallback bio copy in the user context setup uses a
non-ASCII apostrophe, which should be normalized for consistency with the other
strings in this file. Update the fallback string in the logic that assigns
ctx["bio"] within the user view to use a plain ASCII apostrophe instead of the
curly apostrophe, keeping the message otherwise unchanged.
🪄 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 Plus
Run ID: bb4ef39e-1e82-4281-9aad-9111ef1ff4ea
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (15)
core/mock_data.pyfrontend/wysiwyg-editor.jspackage.jsonstatic/css/v3/wysiwyg-editor.cssstatic/js/v3/wysiwyg-editor.jstemplates/v3/includes/_button.htmltemplates/v3/includes/_field_text.htmltemplates/v3/includes/_wysiwyg_editor.htmltemplates/v3/includes/header/_header_avatar.htmltemplates/v3/user_profile_edit.htmlusers/admin.pyusers/migrations/0022_user_biography_user_tagline.pyusers/models.pyusers/serializers.pyusers/views.py
✅ Files skipped from review due to trivial changes (1)
- core/mock_data.py
🚧 Files skipped from review as they are similar to previous changes (9)
- templates/v3/includes/_button.html
- users/admin.py
- templates/v3/includes/header/_header_avatar.html
- users/serializers.py
- static/css/v3/wysiwyg-editor.css
- users/models.py
- package.json
- templates/v3/user_profile_edit.html
- frontend/wysiwyg-editor.js
There was a problem hiding this comment.
Hi @herzog0 ! I have 2 more suggestions for this PR and would love to hear your thoughts!
- Right now, saving changes to the tagline + bio doesn't wipe the
localStoragedata, so returning to the User Profile page always renders fromlocalStorageinstead of the actual DB state. This makes it a bit confusing to tell whether the data we see is temporary or has actually been saved. Can we clear out thelocalStoragekeys upon saving the fields?
Edit: Oh actually, I forgot user can see the saved data at: http://localhost:8000/users/me/, so maybe this localStorage persistence is beneficial to save drafts 🤔. We can probably just disregard my comment above! - Right now, the tagline has a check that prevents users from typing past the character limit, but biography allows over-typing. I'm wondering if we can pick one behaviour and make it consistent across both fields?
- Nit UI: The help text of the tagline field is missing a margin top (
--space-default)
There was a problem hiding this comment.
Since this biography field is added in this PR, can we fold this change into the 0022 migration?
9c0902d to
0ad7fca
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
users/forms.py (1)
189-196: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider moving
SLACK_TEAM_IDto Django settings.
SLACK_TEAM_IDis hardcoded as a module-level constant. If this value varies per environment (e.g., staging vs. production Slack workspaces), it would require a code change rather than a configuration change. Moving it tosettings.pywould improve deployability.🤖 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 `@users/forms.py` around lines 189 - 196, Move the hardcoded SLACK_TEAM_ID in users/forms.py into Django settings and read it from there when building SLACK_APP_REDIRECT_URL_PREFIX. Update the Slack link construction in the module so it uses the configured settings value instead of a module-level constant, and ensure any related usage in user_profile_edit.html stays aligned with the same setting.
🤖 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.
Nitpick comments:
In `@users/forms.py`:
- Around line 189-196: Move the hardcoded SLACK_TEAM_ID in users/forms.py into
Django settings and read it from there when building
SLACK_APP_REDIRECT_URL_PREFIX. Update the Slack link construction in the module
so it uses the configured settings value instead of a module-level constant, and
ensure any related usage in user_profile_edit.html stays aligned with the same
setting.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 242428b9-eec2-4346-a977-a83b908f2830
📒 Files selected for processing (22)
core/context_processors.pycore/mock_data.pyfrontend/wysiwyg-editor.jspackage.jsonstatic/css/v3/wysiwyg-editor.cssstatic/js/v3/wysiwyg-editor.jstemplates/v3/includes/_button.htmltemplates/v3/includes/_field_text.htmltemplates/v3/includes/_wysiwyg_editor.htmltemplates/v3/includes/header/_header_avatar.htmltemplates/v3/user_profile_edit.htmlusers/admin.pyusers/forms.pyusers/migrations/0022_user_profile_links.pyusers/migrations/0023_user_biography_user_tagline.pyusers/migrations/0024_add_biography_max_length.pyusers/migrations/0025_alter_user_biography_alter_user_profile_links.pyusers/models.pyusers/serializers.pyusers/tests/test_forms.pyusers/tests/test_serializers.pyusers/views.py
✅ Files skipped from review due to trivial changes (1)
- package.json
🚧 Files skipped from review as they are similar to previous changes (8)
- templates/v3/includes/_button.html
- users/admin.py
- core/mock_data.py
- templates/v3/includes/_field_text.html
- templates/v3/includes/header/_header_avatar.html
- static/css/v3/wysiwyg-editor.css
- frontend/wysiwyg-editor.js
- templates/v3/user_profile_edit.html
f0506af to
d3d9aec
Compare
- Fix mock_data bug when fetching "img/v3/demo-page/avatar.png"
… section if already saved
7cd04d6 to
4409696
Compare
julhoang
left a comment
There was a problem hiding this comment.
Hi @herzog0 ! Thanks for all of your updates. I just have a few super nit UI/UX suggestions that I'll mention below, none are blockers though – approving now! 🙌
--
1/ I've just happened to come across this UI issue where if I keep typing a ridiculous long word, the page layout will break since the textarea width keep expanding 😅 I think adding a simple word-break will resolve this issue.
2/ I noticed that the Biography still allow going over the character limit if you paste in the text, while the Tagline truncate the pasted-text. It'd be great if the UX can be a bit more consistent here.
3/ Upon saving the data and refresh the page, the Biography field still "Saved to draft" while Tagline correctly doesn't have it. I think the Biography's "Saved to draft" shouldn't be there.
Issue: #2458
Summary & Context
Adds editable tagline (plain text, 70-char limit and counter, saved on "Save Changes") and biography (rich-text editor with local auto-save, and 20,000 character limit and counter) to the user profile, persists both to the
Userrecord, and renders the saved biography on the public profile.Changes
tagline(CharField, max 70) andbiography(TextField) to theUsermodel via migration0022.PATCH /api/v1/users/me/(reused the existingCurrentUserAPIView; added both fields toCurrentUserSerializer)./users/me/?edit=True.alpine_clickto the shared_button.htmlinclude.Please list any potential risks or areas that need extra attention during review/testing
Kept
PATCH /api/v1/users/me/instead of the ticket'sPOST /api/user/profileendpoints.PATCHis the correct verb for updating a few fields on the current user. It's a partial, idempotent update;POSTfor an update is weaker and non-idempotent.CurrentUserAPIView). I only added two serializer fields, so no need for new view, URL, or save logic./api/v1/versioning convention (the ticket's path was unversioned).Biography is stored as markdown, not HTML. The existing WYSIWYG editor serializes to markdown and the bio card renders markdown → HTML, so I kept that pipeline. (The ticket's "HTML" backend note doesn't match the existing infrastructure.)
Meet Boost Core homepage tagline display is intentionally deferred (out of scope for this PR).
_user_profile.html(used by many other cards), so changing it there has wide repercussions.Screenshots
Local Storage Persistence and correct endpoint redirection
ProfileLocalStoragePersistance.mov
On Save Persistence Functionality
Funcionality.mov
Character Limiting
CharacterLimitEnforced.mov
Self-review Checklist
Frontend
Summary by CodeRabbit
New Features
Bug Fixes