fix(FR-2979): display sender on shared folder invitations in summary page#7607
Merged
Merged
Conversation
Contributor
Author
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has required the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Contributor
Coverage Report for react-coverage (./react)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||
fa7cde6 to
26a8be8
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes the Summary page invitation card showing an empty sender by applying the existing invitation-inviter-email capability check (already used in FolderInvitationResponseModal) so inviter_user_email is read on manager ≥25.6.0 while falling back to inviter on older managers.
Changes:
- Add
baiClient.supports('invitation-inviter-email')check inSummaryItemInvitation. - Render
inviter_user_emailwhen supported, fall back toinviterotherwise. - Add
'use memo'directive to the component.
26a8be8 to
147f8b1
Compare
3 tasks
147f8b1 to
25baf00
Compare
25baf00 to
f849b3a
Compare
nowgnuesLee
requested changes
May 28, 2026
f849b3a to
005aaf8
Compare
8515841 to
868c4a8
Compare
Merge activity
|
…page (#7607) Linked Jira: [FR-2979](https://lablup.atlassian.net/browse/FR-2979) Backend counterpart: [BA-6193](https://lablup.atlassian.net/browse/BA-6193) (merged, SSO empty-email) Backend follow-up: [BA-6228](https://lablup.atlassian.net/browse/BA-6228) (expose `inviter_user_email` as a separate DTO field) <!-- `Resolves #N (FR-2979)` will be added once the Jira→GitHub clone webhook fires. --> ## TL;DR FR-2979 ("Summary page invitation card shows empty `From:`") has **two independent root causes**. This PR fixes the frontend one. The other one is server-side and lives in BA-6193. Both need to land for FR-2979 to be fully resolved end-to-end. | # | Root cause | Where it lives | Status | | --- | --- | --- | --- | | 1 | Both the Summary card and `FolderInvitationResponseModal` read `invitation.inviter` blindly. The legacy backend used to put the inviter email there, but manager v25.6.0 plans to expose it under a separate `inviter_user_email` field. This PR gates the read with the existing `invitation-inviter-email` capability flag and falls back to the legacy `inviter` field for older managers. | Frontend (this PR) | Fixed here | | 2 | Backend persists `User.email = ""` for SSO-created accounts and mirrors it straight into the invitation response, so the sender renders blank regardless of the field name; the accept handler's `if not inviter_email` check also raises on the empty string. | Backend ([BA-6193](https://lablup.atlassian.net/browse/BA-6193)) | Tracked separately | After **this PR alone**: users invited by a manually-created sender on a manager that exposes `inviter_user_email` see the sender's email again. Users whose inviter is an SSO-created account still see blank — unblocked only by BA-6193. ## What this PR does Use the same capability-check pattern that `FolderInvitationResponseModal.tsx` originally followed (added in FR-1101): read `baiClient.supports('invitation-inviter-email')` and choose the field accordingly. Both call sites also fall back to `'-'` to avoid rendering `From: undefined` when neither field has a value. - `react/src/components/FolderInvitationResponseModal.tsx` — add `useSuspendedBackendaiClient` + `hasInviterEmail`, render `(hasInviterEmail ? item.inviter_user_email : item.inviter) || '-'` in the "From" descriptions item. - `react/src/components/SummaryPageItems/SummaryItemInvitation.tsx` — same gating in the card title. ## Known limitation (and the backend follow-up that unblocks it) The current `VFolderInvitationDTO` (`src/ai/backend/common/dto/manager/vfolder/response.py` in `lablup/backend.ai`) only declares the single `inviter` field: ```python class VFolderInvitationDTO(BackendAISchema): inviter: str = Field(description="Inviter email, or username if email is empty") ... ``` The handler collapses both possibilities into that field (`inviter=info.inviter_user_email or info.inviter_username or ""`). So on managers where the capability flag is *true* but the DTO has not yet been expanded with `inviter_user_email`, this PR will render `From: -` for every invitation. Older managers (capability = false) continue to read the legacy `inviter` field and work as before. The backend side needs to add `inviter_user_email` as a separate DTO field for the capability-gated branch to actually show the email. Tracked separately in [BA-6228](https://lablup.atlassian.net/browse/BA-6228) — until that lands, manager ≥ 25.6.0 will render `From: -` for every invitation. Older managers (capability = false) continue to read the legacy `inviter` field and work as before. ## What this PR explicitly does NOT fix — and why the frontend can't The SSO-side problem above is **not** addressable from the client: - The invitation payload contains the empty email itself; there is no other identifying field to fall back to. - The payload has no `is_sso` / `external_id` flag, so the frontend cannot even differentiate SSO rows to apply a special UI. - A cosmetic "Unknown sender" fallback would only mask the symptom while leaving the accept-flow exception in BA-6193 untouched. So the fix has to land where the empty email originates — the backend. See [BA-6193](https://lablup.atlassian.net/browse/BA-6193). ## Verification - `bash scripts/verify.sh` — Relay, Lint, Format PASS. TypeScript surfaces only pre-existing failures in unrelated files; no new errors in the touched files. - Manual: invite a manually-created user from another manually-created user on a manager that exposes `inviter_user_email`; the Summary card and the invitation modal both show the inviter's email. On a manager that only returns `inviter` (current main), both fall back to the legacy field and render correctly. SSO-related rows remain blank, expected until BA-6193 lands. ## Checklist - [x] Documentation — n/a (capability-check pattern already documented by FR-1101's PR) - [x] Minimum required manager version — no change (the existing capability flag covers both old and new managers) - [x] Minimum requirements to check during review — log in as the invitee and confirm the Summary invitation card title and the `FolderInvitationResponseModal` "From:" field both show the inviter's email (or `-` if not available on the current manager) - [ ] Test case(s) — covered by the e2e in #7610 (FR-2982) [FR-2979]: https://lablup.atlassian.net/browse/FR-2979?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [BA-6193]: https://lablup.atlassian.net/browse/BA-6193?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [BA-6228]: https://lablup.atlassian.net/browse/BA-6228?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
868c4a8 to
17c6056
Compare
graphite-app Bot
pushed a commit
that referenced
this pull request
Jun 9, 2026
#7610) Resolves #7608 (FR-2982) > Stacked on #7607 — merge that one first. ## Summary - Extend `acceptAllInvitationAndVerifySpecificFolder` (in `e2e/utils/test-util.ts`) with an optional `inviterEmail` parameter. - When the parameter is provided, assert that the open `FolderInvitationResponseModal` contains that email before the Accept loop. This catches regressions in the modal's "From" field — i.e. broken `item.inviter_user_email` plumbing or a broken `invitation-inviter-email` capability check. - Pass `userInfo.user.email` (the inviter set up by `loginAsUser` in `beforeEach`) at the single existing call site in `e2e/vfolder/vfolder-crud.spec.ts` ("User can share vFolder"), so the assertion runs in CI. - No production source changes; e2e-only. ## Why - The "From" field is the only place an invitee sees who shared a folder with them. Today no e2e / unit / Storybook test asserts that field is non-empty or correct. - Existing test already exercises the modal, so the new check is a low-cost extension rather than a new scenario. ## Test plan - [ ] CI: existing `vfolder/vfolder-crud.spec.ts` "User can share vFolder" run passes with the new assertion enabled. - [ ] On a backend with `invitation-inviter-email` capability, the assertion confirms `user@lablup.com` is rendered inside the modal. - [ ] On a backend without that capability, the assertion would fail (the modal falls back to `item.inviter`, a non-email value); intentional — this is the regression we want to surface.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Linked Jira: FR-2979
Backend counterpart: BA-6193 (merged, SSO empty-email)
Backend follow-up: BA-6228 (expose
inviter_user_emailas a separate DTO field)TL;DR
FR-2979 ("Summary page invitation card shows empty
From:") has two independent root causes. This PR fixes the frontend one. The other one is server-side and lives in BA-6193. Both need to land for FR-2979 to be fully resolved end-to-end.FolderInvitationResponseModalreadinvitation.inviterblindly. The legacy backend used to put the inviter email there, but manager v25.6.0 plans to expose it under a separateinviter_user_emailfield. This PR gates the read with the existinginvitation-inviter-emailcapability flag and falls back to the legacyinviterfield for older managers.User.email = ""for SSO-created accounts and mirrors it straight into the invitation response, so the sender renders blank regardless of the field name; the accept handler'sif not inviter_emailcheck also raises on the empty string.After this PR alone: users invited by a manually-created sender on a manager that exposes
inviter_user_emailsee the sender's email again. Users whose inviter is an SSO-created account still see blank — unblocked only by BA-6193.What this PR does
Use the same capability-check pattern that
FolderInvitationResponseModal.tsxoriginally followed (added in FR-1101): readbaiClient.supports('invitation-inviter-email')and choose the field accordingly. Both call sites also fall back to'-'to avoid renderingFrom: undefinedwhen neither field has a value.react/src/components/FolderInvitationResponseModal.tsx— adduseSuspendedBackendaiClient+hasInviterEmail, render(hasInviterEmail ? item.inviter_user_email : item.inviter) || '-'in the "From" descriptions item.react/src/components/SummaryPageItems/SummaryItemInvitation.tsx— same gating in the card title.Known limitation (and the backend follow-up that unblocks it)
The current
VFolderInvitationDTO(src/ai/backend/common/dto/manager/vfolder/response.pyinlablup/backend.ai) only declares the singleinviterfield:The handler collapses both possibilities into that field (
inviter=info.inviter_user_email or info.inviter_username or ""). So on managers where the capability flag is true but the DTO has not yet been expanded withinviter_user_email, this PR will renderFrom: -for every invitation. Older managers (capability = false) continue to read the legacyinviterfield and work as before.The backend side needs to add
inviter_user_emailas a separate DTO field for the capability-gated branch to actually show the email. Tracked separately in BA-6228 — until that lands, manager ≥ 25.6.0 will renderFrom: -for every invitation. Older managers (capability = false) continue to read the legacyinviterfield and work as before.What this PR explicitly does NOT fix — and why the frontend can't
The SSO-side problem above is not addressable from the client:
is_sso/external_idflag, so the frontend cannot even differentiate SSO rows to apply a special UI.So the fix has to land where the empty email originates — the backend. See BA-6193.
Verification
bash scripts/verify.sh— Relay, Lint, Format PASS. TypeScript surfaces only pre-existing failures in unrelated files; no new errors in the touched files.inviter_user_email; the Summary card and the invitation modal both show the inviter's email. On a manager that only returnsinviter(current main), both fall back to the legacy field and render correctly. SSO-related rows remain blank, expected until BA-6193 lands.Checklist
FolderInvitationResponseModal"From:" field both show the inviter's email (or-if not available on the current manager)