Skip to content

Feat/invite user confirmation#397

Merged
ThaminduDilshan merged 4 commits intoasgardeo:mainfrom
RandithaK:feat/invite-user-confirmation
Mar 12, 2026
Merged

Feat/invite user confirmation#397
ThaminduDilshan merged 4 commits intoasgardeo:mainfrom
RandithaK:feat/invite-user-confirmation

Conversation

@RandithaK
Copy link
Contributor

@RandithaK RandithaK commented Mar 12, 2026

Purpose

Added Support for email invitation, retaining capability of invite link direct sharing as a fall back.

Related Issues

  • N/A

Related PRs

  • N/A

Checklist

  • Followed the CONTRIBUTING guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Unit tests provided. (Add links if there are any)

Security checks

Executor ready, No SMTP Configured

part0.mp4

Executor ready,SMTP Configured

part1.mp4

Executor Removed, SMTP Configured

part2.mp4

Copilot AI review requested due to automatic review settings March 12, 2026 12:32
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

Adds UI/state support in the React InviteUser v2 flow to detect when an invitation email was sent and show a dedicated confirmation state, while keeping the invite-link sharing flow as a fallback.

Changes:

  • Add isEmailSent to BaseInviteUser render props and track emailSent state from additionalData.emailSent.
  • Render a new success card when an invite email is detected as successfully sent.
  • Add a changeset to publish the update as a patch for @asgardeo/react.

Reviewed changes

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

File Description
packages/react/src/components/presentation/auth/InviteUser/v2/BaseInviteUser.tsx Tracks emailSent from flow responses and adds an email-sent success UI branch.
.changeset/rude-zebras-dress.md Declares a patch release note for the new invite-via-email capability.
Comments suppressed due to low confidence (1)

packages/react/src/components/presentation/auth/InviteUser/v2/BaseInviteUser.tsx:454

  • In handleSubmit, inviteLink/emailSent state is updated before checking response.flowStatus === 'ERROR'. If the backend returns additionalData.inviteLink or emailSent alongside an error (or a stale value), the component can end up rendering a success state even though an error was reported. Consider checking flowStatus and handling errors before mutating success-related state, or explicitly clearing inviteLink/emailSent when an error response is received.
        // Check if invite link is in the response
        if (response.data?.additionalData?.['inviteLink']) {
          const inviteLinkValue: any = response.data.additionalData['inviteLink'];
          setInviteLink(inviteLinkValue);
          onInviteLinkGenerated?.(inviteLinkValue, response.flowId);
        }

        // Check if email was sent successfully
        if (response.data?.additionalData?.['emailSent'] === 'true') {
          setEmailSent(true);
        }

        // Check for error status
        if (response.flowStatus === 'ERROR') {
          handleError(response);
          return;

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

Comment on lines +712 to +736
// Invite email sent successfully - show email sent confirmation
if (isInviteGenerated && isEmailSent) {
return (
<CardPrimitive className={cx(className, styles.card)} variant={variant}>
<CardPrimitive.Header className={styles.header}>
<CardPrimitive.Title level={2} className={styles.title}>
Invite Email Sent!
</CardPrimitive.Title>
</CardPrimitive.Header>
<CardPrimitive.Content>
<AlertPrimitive variant="success">
<AlertPrimitive.Description>
An invitation email has been sent successfully. The user can complete their registration using the link in
the email.
</AlertPrimitive.Description>
</AlertPrimitive>
<div style={{display: 'flex', gap: '0.5rem', marginTop: '1.5rem'}}>
<Button variant="outline" onClick={resetFlow}>
Invite Another User
</Button>
</div>
</CardPrimitive.Content>
</CardPrimitive>
);
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The email-sent confirmation UI is currently gated by isInviteGenerated && isEmailSent, but isInviteGenerated is derived from inviteLink. If the platform successfully sends an email invitation without returning an inviteLink in additionalData, the component will never show the email confirmation state (even though emailSent is true). Consider keying this branch primarily off isEmailSent (and only using inviteLink for the fallback copy-link path).

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@ThaminduDilshan
Copy link
Contributor

@RandithaK can you fix lint issues reported in [PR Builder / ⬣ ESLint (STATIC ANALYSIS) (lts/*, latest)?
Other two failing jobs, you can ignore for now

@RandithaK
Copy link
Contributor Author

@RandithaK can you fix lint issues reported in [PR Builder / ⬣ ESLint (STATIC ANALYSIS) (lts/*, latest)? Other two failing jobs, you can ignore for now

@RandithaK can you fix lint issues reported in [PR Builder / ⬣ ESLint (STATIC ANALYSIS) (lts/*, latest)? Other two failing jobs, you can ignore for now

Fixed

@asgardeo-github-bot
Copy link

🦋 Changeset detected

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

@ThaminduDilshan
Copy link
Contributor

We'll need to do some improvements later. But merging current changes due to urgency

@ThaminduDilshan ThaminduDilshan merged commit 8c7f686 into asgardeo:main Mar 12, 2026
6 of 8 checks passed
<CardPrimitive className={cx(className, styles.card)} variant={variant}>
<CardPrimitive.Header className={styles.header}>
<CardPrimitive.Title level={2} className={styles.title}>
Invite Email Sent!
Copy link
Contributor

Choose a reason for hiding this comment

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

All user-facing strings should go through t() hook to support i18n and translations.

The existing "Invite Link Generated!" block also hardcodes strings. That's a pre-existing bug, let's fix it with this effort as well.


// Check if email was sent successfully
if (response.data?.additionalData?.['emailSent'] === 'true') {
setEmailSent(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

If the server returns BOTH emailSent: 'true' AND flowStatus: 'ERROR', you'll set emailSent = true and then also trigger error handling. The UI will show the email-sent success card because isInviteGenerated && isEmailSent is checked first in the render. The user will see a success message for a failed flow which is incorrect.

Move the emailSent check to AFTER the error check, or guard it with response.flowStatus !== 'ERROR'.

const {title, subtitle} = extractHeadings(components);
const componentsWithoutHeadings: any = filterHeadings(components);
const isInviteGenerated: any = !!inviteLink;
const isEmailSent: boolean = emailSent;
Copy link
Contributor

Choose a reason for hiding this comment

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

emailSent is already a boolean from useState(false). Here you are creating a new variable with the same type and same value.

Better to rename the state itself to isEmailSent as it follows convention and use it.

the email.
</AlertPrimitive.Description>
</AlertPrimitive>
<div style={{display: 'flex', gap: '0.5rem', marginTop: '1.5rem'}}>
Copy link
Contributor

Choose a reason for hiding this comment

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

This file has a dedicated BaseInviteUser.styles.ts that uses @emotion/css with theme tokens. Your 0.5rem and 1.5rem should use theme.vars.spacing.unit like the rest of the styles file does. Hardcoded pixel/rem values break when someone changes the spacing scale and will hinder if we want to override these styles from branding etc.

Comment on lines +715 to +718
<CardPrimitive className={cx(className, styles.card)} variant={variant}>
<CardPrimitive.Header className={styles.header}>
<CardPrimitive.Title level={2} className={styles.title}>
Invite Email Sent!
Copy link
Contributor

Choose a reason for hiding this comment

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

Your new email-sent block is nearly identical to the existing invite-link block.

This is copy-paste with different text. Extract a shared SuccessCard component or at minimum a helper that takes title, description, and optional extra content. The invite-link block could pass the copy-link section as children.

@@ -624,6 +636,7 @@ const BaseInviteUser: FC<BaseInviteUserProps> = ({
const {title, subtitle} = extractHeadings(components);
const componentsWithoutHeadings: any = filterHeadings(components);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not related to your changes, but when you fix the above-mentioned issues, better to fix these any typed variables to have a proper types.

const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({});
const [inviteLink, setInviteLink] = useState<string | undefined>();
const [inviteLinkCopied, setInviteLinkCopied] = useState(false);
const [emailSent, setEmailSent] = useState(false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Use types

Suggested change
const [emailSent, setEmailSent] = useState(false);
const [emailSent, setEmailSent] = useState<boolean>(false);

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.

6 participants