From f543326ebefea441ca614057e53c14479994ad99 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Sun, 29 Mar 2026 23:11:39 +0530 Subject: [PATCH 001/125] feat(react): add ui primitives and data table updates --- .../auth0/shared/data-pagination.tsx | 106 ++-- .../components/auth0/shared/data-table.tsx | 48 +- packages/react/src/components/ui/chip.tsx | 113 +++++ .../react/src/components/ui/color-picker.tsx | 3 +- packages/react/src/components/ui/combobox.tsx | 452 ++++++++++++++++++ .../src/components/ui/text-field-group.tsx | 391 +++++++++++++++ 6 files changed, 1036 insertions(+), 77 deletions(-) create mode 100644 packages/react/src/components/ui/chip.tsx create mode 100644 packages/react/src/components/ui/combobox.tsx create mode 100644 packages/react/src/components/ui/text-field-group.tsx diff --git a/packages/react/src/components/auth0/shared/data-pagination.tsx b/packages/react/src/components/auth0/shared/data-pagination.tsx index d41e5e8fb..7fd945117 100644 --- a/packages/react/src/components/auth0/shared/data-pagination.tsx +++ b/packages/react/src/components/auth0/shared/data-pagination.tsx @@ -10,10 +10,8 @@ import { Pagination, PaginationContent, PaginationItem, - PaginationLink, PaginationPrevious, PaginationNext, - PaginationEllipsis, } from '@/components/auth0/shared/pagination'; import { Select, @@ -44,12 +42,12 @@ export const defaultLabels: DataPaginationLabels = { showing: 'Showing', to: 'to', of: 'of', - results: 'results', + results: '', totalResults: 'total results', - show: 'Show', + show: '', perPage: 'per page', - previous: 'Previous', - next: 'Next', + previous: '', + next: '', goToPage: 'Go to page {page}', goToPrevious: 'Go to previous page', goToNext: 'Go to next page', @@ -66,6 +64,7 @@ export interface RegularPaginationState { export interface CheckpointPaginationState { pageSize: number; + currentPage?: number; totalItems?: number; hasNextPage: boolean; hasPreviousPage: boolean; @@ -96,32 +95,6 @@ const formatNumber = (num: number | undefined | null, locale?: string): string = return num.toLocaleString(resolvedLocale); }; -const interpolate = (str: string, values: Record): string => - str.replace(/\{(\w+)\}/g, (_, key) => String(values[key] ?? '')); - -const generatePageNumbers = ( - currentPage: number, - totalPages: number, - maxVisible: number = 5, -): (number | 'ellipsis')[] => { - if (totalPages <= maxVisible) return Array.from({ length: totalPages }, (_, i) => i + 1); - - const pages: (number | 'ellipsis')[] = [1]; - const range = Math.floor((maxVisible - 3) / 2); - let start = Math.max(2, currentPage - range); - let end = Math.min(totalPages - 1, currentPage + range); - - if (currentPage <= range + 2) end = maxVisible - 2; - if (currentPage >= totalPages - range - 1) start = totalPages - (maxVisible - 2); - - if (start > 2) pages.push('ellipsis'); - for (let i = start; i <= end; i++) pages.push(i); - if (end < totalPages - 1) pages.push('ellipsis'); - pages.push(totalPages); - - return pages; -}; - /** * * @param props - Component props. @@ -170,18 +143,6 @@ export function DataPagination({ return Array.from(uniqueOptions).sort((a, b) => a - b); }, [shouldShowPageSizeSelector, pageSizeOptions, currentPageSize]); - const pageNumbers = useMemo( - () => - isRegular && regularState - ? generatePageNumbers( - regularState.currentPage, - regularState.totalPages, - regularState.maxVisiblePages, - ) - : [], - [isRegular, regularState], - ); - useEffect(() => { if (ariaLiveRegionRef.current) { if (isRegular && regularState) { @@ -196,7 +157,6 @@ export function DataPagination({ return null; } - const shouldShowPageNumbers = isRegular; const safeCurrentPageSize = currentPageSize as number; return ( @@ -223,9 +183,7 @@ export function DataPagination({ : (regularState.currentPage - 1) * regularState.pageSize + 1, locale, )} - {' '} - {labels.to}{' '} - + - {formatNumber( Math.min( regularState.currentPage * regularState.pageSize, @@ -237,8 +195,34 @@ export function DataPagination({ {labels.of}{' '} {formatNumber(regularState.totalItems, locale)} + + {labels.results && <> {labels.results}} + + ) : checkpointState?.totalItems !== undefined && + checkpointState?.currentPage !== undefined ? ( + <> + {labels.showing}{' '} + + {formatNumber( + checkpointState.totalItems === 0 + ? 0 + : (checkpointState.currentPage - 1) * checkpointState.pageSize + 1, + locale, + )} + - + {formatNumber( + Math.min( + checkpointState.currentPage * checkpointState.pageSize, + checkpointState.totalItems, + ), + locale, + )} {' '} - {labels.results} + {labels.of}{' '} + + {formatNumber(checkpointState.totalItems, locale)} + + {labels.results && <> {labels.results}} ) : checkpointState?.totalItems !== undefined ? ( <> @@ -254,7 +238,7 @@ export function DataPagination({
{shouldShowPageSizeSelector && allPageSizeOptions.length > 0 && (
- {labels.show} + {labels.show && {labels.show}} +
+ {endAdornment && ( +
+ {endAdornment} +
+ )} +
+ + ); + } + + return ( + +
+ {startAdornment && ( +
+ {startAdornment} +
+ )} + {hasChips && (showAllChips || visibleChips.length > 0) && ( +
+ {visibleChips.map((chip, index) => ( +
{ + chipRefs.current[index] = el; + }} + tabIndex={-1} + onKeyDown={(e) => handleChipKeyDown(e, index)} + onFocus={() => setFocusedChipIndex(index)} + className={cn( + 'focus:ring-ring rounded-lg focus:ring-3 focus:outline-none', + focusedChipIndex === index && 'ring-ring ring-3', + )} + > + handleChipRemove(chip.value)} + className="max-w-xs" + > + {chip.label} + +
+ ))} + {!showAllChips && hiddenChipCount > 0 && ( + + +{hiddenChipCount} more + + )} +
+ )} + + {endAdornment && ( +
+ {endAdornment} +
+ )} +
+
+ ); +} + +const TextFieldGroupWithRef = React.forwardRef(TextFieldGroup); + +export { TextFieldGroupWithRef as TextFieldGroup, textFieldGroupVariants }; From 038ed92ef74ab30839aac160747032a8b9275e13 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Sun, 29 Mar 2026 23:13:13 +0530 Subject: [PATCH 002/125] feat(core, react): add types, schemas, and i18n for invitations --- .../core/src/i18n/translations/en-US.json | 119 +++++++++ packages/core/src/i18n/translations/ja.json | 119 +++++++++ .../core/src/schemas/my-organization/index.ts | 4 + .../invitation-create-schema.test.ts | 226 ++++++++++++++++++ .../invitation-create-schema-types.ts | 24 ++ .../invitation-create-schema.ts | 77 ++++++ .../member-management/invitation-schema.ts | 59 +++++ .../member-management/member-schema.ts | 42 ++++ .../member-management-utils.ts | 25 ++ packages/react/src/types/index.ts | 2 + .../my-organization/config/config-types.ts | 8 + .../organization-invitation-table-types.ts | 213 +++++++++++++++++ .../organization-member-management-types.ts | 112 +++++++++ 13 files changed, 1030 insertions(+) create mode 100644 packages/core/src/schemas/my-organization/member-management/__tests__/invitation-create-schema.test.ts create mode 100644 packages/core/src/schemas/my-organization/member-management/invitation-create-schema-types.ts create mode 100644 packages/core/src/schemas/my-organization/member-management/invitation-create-schema.ts create mode 100644 packages/core/src/schemas/my-organization/member-management/invitation-schema.ts create mode 100644 packages/core/src/schemas/my-organization/member-management/member-schema.ts create mode 100644 packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts create mode 100644 packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts create mode 100644 packages/react/src/types/my-organization/member-management/organization-member-management-types.ts diff --git a/packages/core/src/i18n/translations/en-US.json b/packages/core/src/i18n/translations/en-US.json index 473839493..821bc29c4 100644 --- a/packages/core/src/i18n/translations/en-US.json +++ b/packages/core/src/i18n/translations/en-US.json @@ -1065,5 +1065,124 @@ "install_guardian_description": "In order to continue, install the Auth0 Guardian app via the app store from your mobile device" } } + }, + "member_management": { + "header": { + "title": "Members", + "description": "Manage the members of your organization." + }, + "invite_button": "Invite Member", + "tabs": { + "members": "Members", + "invitations": "Invitations" + }, + "member": { + "table": { + "columns": { + "name": "Name", + "email": "Email", + "roles": "Roles" + }, + "empty_message": "No members found." + }, + "remove": { + "title": "Remove Member", + "description": "Are you sure you want to remove ${name} from this organization?", + "confirm_button": "Remove", + "cancel_button": "Cancel", + "success": "${name} has been removed from the organization." + }, + "error": { + "fetch_failed": "Failed to load members. Please try again.", + "remove_failed": "Failed to remove member. Please try again." + } + }, + "invitation": { + "table": { + "columns": { + "email": "Email", + "status": "Status", + "inviter": "Invited By", + "created_at": "Created At", + "expires_at": "Expires At", + "roles": "Roles" + }, + "empty_message": "No pending invitations.", + "search_placeholder": "Search by email...", + "filter_by_role": "Filter By Role", + "all_roles": "All", + "reset_filter": "Reset", + "showing_results": "Showing ${start}-${end} of ${total}", + "status_pending": "Pending", + "status_expired": "Expired" + }, + "actions": { + "menu_label": "Actions", + "view_details": "View Details", + "copy_url": "Copy Invitation URL", + "revoke_and_resend": "Revoke and Resend", + "revoke": "Revoke Invitation" + }, + "create": { + "title": "Invite Member", + "description": "Send an invitation to join this organization.", + "email_label": "Email Address", + "email_placeholder": "Enter email address and press Enter", + "email_helper": "Add up to 10 members in a comma-separated list.", + "email_limit_error": "You can add up to 10 email addresses.", + "email_invalid_error": "Please enter a valid email address.", + "email_duplicate_error": "This email has already been added.", + "email_required_error": "Please enter at least one email address.", + "roles_label": "Roles", + "roles_placeholder": "Select roles (optional)", + "provider_label": "Provider", + "provider_placeholder": "Select provider (optional)", + "provider_helper": "If none is selected, the member can log in with any provider.", + "submit_button": "Send Invite", + "creating": "Creating...", + "cancel_button": "Cancel", + "success": "Invitation sent to ${email}." + }, + "details": { + "title": "Invitation Details", + "email_label": "Email", + "status_label": "Status", + "roles_label": "Roles", + "provider_label": "Identity Provider", + "created_at_label": "Created", + "expires_at_label": "Expires", + "invited_by_label": "Invited By", + "invitation_url_label": "Invitation URL", + "copy_url_button": "Copy", + "close_button": "Close", + "revoke_button": "Revoke Invitation", + "resend_button": "Revoke and Resend" + }, + "revoke": { + "title": "Revoke Invitation", + "description": "Are you sure you want to revoke the invitation to ${email}?", + "confirm_button": "Revoke", + "cancel_button": "Cancel", + "success": "Invitation for ${email} has been revoked." + }, + "revoke_resend": { + "title": "Revoke and Resend Invitation", + "description": "Are you sure you want to revoke the current invitation and send a new one to ${email}?", + "confirm_button": "Proceed", + "cancel_button": "Cancel" + }, + "success": { + "url_copied": "Invitation URL copied to clipboard.", + "invitation_resent": "Invitation resent to ${email}." + }, + "error": { + "fetch_failed": "Failed to load invitations. Please try again.", + "create_failed": "Failed to send invitation. Please try again.", + "revoke_failed": "Failed to revoke invitation. Please try again.", + "resend_failed": "Failed to resend invitation. Please try again.", + "revoke_resend_failed": "Failed to revoke and resend invitation. Please try again.", + "copy_url_failed": "Failed to copy invitation URL. Please try again." + } + } } } diff --git a/packages/core/src/i18n/translations/ja.json b/packages/core/src/i18n/translations/ja.json index 2786bb395..e83a9ad5d 100644 --- a/packages/core/src/i18n/translations/ja.json +++ b/packages/core/src/i18n/translations/ja.json @@ -1067,5 +1067,124 @@ "install_guardian_description": "続行するには、お使いのモバイルデバイスからアプリストア経由でAuth0 Guardianアプリをインストールしてください。" } } + }, + "member_management": { + "header": { + "title": "メンバー", + "description": "組織のメンバーを管理します。" + }, + "invite_button": "メンバーを招待", + "tabs": { + "members": "メンバー", + "invitations": "招待" + }, + "member": { + "table": { + "columns": { + "name": "名前", + "email": "メール", + "roles": "ロール" + }, + "empty_message": "メンバーが見つかりません。" + }, + "remove": { + "title": "メンバーを削除", + "description": "この組織から${name}を削除してもよろしいですか?", + "confirm_button": "削除", + "cancel_button": "キャンセル", + "success": "${name}が組織から削除されました。" + }, + "error": { + "fetch_failed": "メンバーの読み込みに失敗しました。もう一度お試しください。", + "remove_failed": "メンバーの削除に失敗しました。もう一度お試しください。" + } + }, + "invitation": { + "table": { + "columns": { + "email": "メール", + "status": "ステータス", + "inviter": "招待者", + "created_at": "作成日", + "expires_at": "有効期限", + "roles": "ロール" + }, + "empty_message": "保留中の招待はありません。", + "search_placeholder": "メールで検索...", + "filter_by_role": "ロールで絞り込み", + "all_roles": "すべて", + "reset_filter": "リセット", + "showing_results": "${start}〜${end} / ${total}件", + "status_pending": "保留中", + "status_expired": "期限切れ" + }, + "actions": { + "menu_label": "アクション", + "view_details": "詳細を表示", + "copy_url": "招待URLをコピー", + "revoke_and_resend": "取り消して再送信", + "revoke": "招待を取り消す" + }, + "create": { + "title": "メンバーを招待", + "description": "この組織に参加するための招待を送信します。", + "email_label": "メールアドレス", + "email_placeholder": "メールアドレスを入力してEnterを押してください", + "email_helper": "カンマ区切りで最大10名まで追加できます。", + "email_limit_error": "メールアドレスは最大10件まで追加できます。", + "email_invalid_error": "有効なメールアドレスを入力してください。", + "email_duplicate_error": "このメールアドレスは既に追加されています。", + "email_required_error": "メールアドレスを1つ以上入力してください。", + "roles_label": "ロール", + "roles_placeholder": "ロールを選択(任意)", + "provider_label": "プロバイダー", + "provider_placeholder": "プロバイダーを選択(任意)", + "provider_helper": "選択しない場合、メンバーは任意のプロバイダーでログインできます。", + "submit_button": "招待を送信", + "creating": "作成中...", + "cancel_button": "キャンセル", + "success": "${email}に招待を送信しました。" + }, + "details": { + "title": "招待の詳細", + "email_label": "メール", + "status_label": "ステータス", + "roles_label": "ロール", + "provider_label": "IDプロバイダー", + "created_at_label": "作成日", + "expires_at_label": "有効期限", + "invited_by_label": "招待者", + "invitation_url_label": "招待URL", + "copy_url_button": "コピー", + "close_button": "閉じる", + "revoke_button": "招待を取り消す", + "resend_button": "取り消して再送信" + }, + "revoke": { + "title": "招待を取り消す", + "description": "${email}への招待を取り消してもよろしいですか?", + "confirm_button": "取り消す", + "cancel_button": "キャンセル", + "success": "${email}への招待が取り消されました。" + }, + "revoke_resend": { + "title": "招待を取り消して再送信", + "description": "現在の招待を取り消し、${email}に新しい招待を送信してもよろしいですか?", + "confirm_button": "続行", + "cancel_button": "キャンセル" + }, + "success": { + "url_copied": "招待URLをクリップボードにコピーしました。", + "invitation_resent": "${email}に招待を再送信しました。" + }, + "error": { + "fetch_failed": "招待の読み込みに失敗しました。もう一度お試しください。", + "create_failed": "招待の送信に失敗しました。もう一度お試しください。", + "revoke_failed": "招待の取り消しに失敗しました。もう一度お試しください。", + "resend_failed": "招待の再送信に失敗しました。もう一度お試しください。", + "revoke_resend_failed": "招待の取り消しと再送信に失敗しました。もう一度お試しください。", + "copy_url_failed": "招待URLのコピーに失敗しました。もう一度お試しください。" + } + } } } diff --git a/packages/core/src/schemas/my-organization/index.ts b/packages/core/src/schemas/my-organization/index.ts index 28b4269df..e426faa35 100644 --- a/packages/core/src/schemas/my-organization/index.ts +++ b/packages/core/src/schemas/my-organization/index.ts @@ -7,3 +7,7 @@ export * from './organization-management'; export * from './idp-management'; export * from './domain-management'; +export * from './member-management/member-schema'; +export * from './member-management/invitation-schema'; +export * from './member-management/invitation-create-schema'; +export * from './member-management/invitation-create-schema-types'; diff --git a/packages/core/src/schemas/my-organization/member-management/__tests__/invitation-create-schema.test.ts b/packages/core/src/schemas/my-organization/member-management/__tests__/invitation-create-schema.test.ts new file mode 100644 index 000000000..e24e90ec0 --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/__tests__/invitation-create-schema.test.ts @@ -0,0 +1,226 @@ +import { describe, it, expect } from 'vitest'; + +import { + createInvitationCreateSchema, + invitationCreateSchemaDefaults, +} from '../invitation-create-schema'; + +describe('Invitation Create Schema', () => { + describe('default schema', () => { + describe.each([ + { input: 'user@example.com', shouldPass: true, description: 'simple email' }, + { input: 'test.user@domain.com', shouldPass: true, description: 'email with dots' }, + { input: 'user+tag@example.com', shouldPass: true, description: 'email with plus tag' }, + { input: 'user@sub.domain.com', shouldPass: true, description: 'email with subdomain' }, + { input: 'a@b.co', shouldPass: true, description: 'minimal valid email' }, + { + input: 'user-name@example.org', + shouldPass: true, + description: 'email with hyphen in local', + }, + { + input: 'user_name@example.org', + shouldPass: true, + description: 'email with underscore in local', + }, + ])('when email is "$input" ($description)', ({ input, shouldPass }) => { + it(`should ${shouldPass ? 'accept' : 'reject'}`, () => { + const result = invitationCreateSchemaDefaults.emailSchema.safeParse(input); + expect(result.success).toBe(shouldPass); + }); + }); + + describe.each([ + { input: '', shouldPass: false, description: 'empty string' }, + { input: ' ', shouldPass: false, description: 'whitespace only' }, + { input: 'notanemail', shouldPass: false, description: 'missing @ and domain' }, + { input: '@example.com', shouldPass: false, description: 'missing local part' }, + { input: 'user@', shouldPass: false, description: 'missing domain' }, + { input: 'user@.com', shouldPass: false, description: 'missing domain name' }, + { input: 'user @example.com', shouldPass: false, description: 'space in local part' }, + ])('when email is "$input" ($description)', ({ input, shouldPass }) => { + it(`should ${shouldPass ? 'accept' : 'reject'}`, () => { + const result = invitationCreateSchemaDefaults.emailSchema.safeParse(input); + expect(result.success).toBe(shouldPass); + }); + }); + + it('should return the default error message on validation failure', () => { + const result = invitationCreateSchemaDefaults.emailSchema.safeParse(''); + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].message).toBe('Please enter a valid email address'); + } + }); + + it('should have default maxEmails of 10', () => { + expect(invitationCreateSchemaDefaults.maxEmails).toBe(10); + }); + + it('should have default emailRegex', () => { + expect(invitationCreateSchemaDefaults.emailRegex).toBeInstanceOf(RegExp); + expect(invitationCreateSchemaDefaults.emailRegex.test('user@example.com')).toBe(true); + }); + }); + + describe('createInvitationCreateSchema factory', () => { + describe('with custom error message', () => { + it('should use custom default error message', () => { + const customMessage = 'Custom email validation error'; + const schema = createInvitationCreateSchema({}, customMessage); + const result = schema.emailSchema.safeParse(''); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].message).toBe(customMessage); + } + }); + + it('should use field-level error message over default', () => { + const fieldError = 'Field-level error'; + const defaultError = 'Default error'; + const schema = createInvitationCreateSchema( + { email: { errorMessage: fieldError } }, + defaultError, + ); + const result = schema.emailSchema.safeParse('invalid'); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].message).toBe(fieldError); + } + }); + }); + + describe('with custom regex', () => { + it('should accept emails matching the custom regex', () => { + const customRegex = /^[\w.+-]+@auth0\.com$/; + const schema = createInvitationCreateSchema({ + email: { + regex: customRegex, + errorMessage: 'Only @auth0.com emails allowed', + }, + }); + + expect(schema.emailSchema.safeParse('user@auth0.com').success).toBe(true); + expect(schema.emailSchema.safeParse('test.user@auth0.com').success).toBe(true); + }); + + it('should reject emails not matching the custom regex', () => { + const customRegex = /^[\w.+-]+@auth0\.com$/; + const schema = createInvitationCreateSchema({ + email: { + regex: customRegex, + errorMessage: 'Only @auth0.com emails allowed', + }, + }); + + expect(schema.emailSchema.safeParse('user@example.com').success).toBe(false); + expect(schema.emailSchema.safeParse('user@gmail.com').success).toBe(false); + }); + + it('should use custom error message with custom regex validation failure', () => { + const customRegex = /^[\w.+-]+@auth0\.com$/; + const customErrorMessage = 'Only @auth0.com emails allowed'; + const schema = createInvitationCreateSchema({ + email: { + regex: customRegex, + errorMessage: customErrorMessage, + }, + }); + const result = schema.emailSchema.safeParse('user@example.com'); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].message).toBe(customErrorMessage); + } + }); + }); + + describe('with custom maxEmails', () => { + it('should override the default maxEmails', () => { + const schema = createInvitationCreateSchema({ maxEmails: 5 }); + expect(schema.maxEmails).toBe(5); + }); + + it('should allow maxEmails of 1', () => { + const schema = createInvitationCreateSchema({ maxEmails: 1 }); + expect(schema.maxEmails).toBe(1); + }); + + it('should default to 10 when maxEmails is not provided', () => { + const schema = createInvitationCreateSchema({}); + expect(schema.maxEmails).toBe(10); + }); + }); + + describe('with empty options', () => { + it('should behave like the default schema', () => { + const schema = createInvitationCreateSchema({}); + + expect(schema.emailSchema.safeParse('user@example.com').success).toBe(true); + expect(schema.emailSchema.safeParse('').success).toBe(false); + expect(schema.maxEmails).toBe(10); + }); + }); + + describe('with undefined options', () => { + it('should behave like the default schema', () => { + const schema = createInvitationCreateSchema(undefined); + + expect(schema.emailSchema.safeParse('user@example.com').success).toBe(true); + expect(schema.emailSchema.safeParse('').success).toBe(false); + expect(schema.maxEmails).toBe(10); + }); + }); + + describe('with no arguments', () => { + it('should return defaults', () => { + const schema = createInvitationCreateSchema(); + + expect(schema.emailSchema.safeParse('user@example.com').success).toBe(true); + expect(schema.emailSchema.safeParse('').success).toBe(false); + expect(schema.maxEmails).toBe(10); + expect(schema.emailErrorMessage).toBe('Please enter a valid email address'); + }); + }); + }); + + describe('return value structure', () => { + it('should return emailSchema, emailRegex, emailErrorMessage, and maxEmails', () => { + const result = createInvitationCreateSchema(); + + expect(result).toHaveProperty('emailSchema'); + expect(result).toHaveProperty('emailRegex'); + expect(result).toHaveProperty('emailErrorMessage'); + expect(result).toHaveProperty('maxEmails'); + }); + + it('should return a Zod schema for emailSchema', () => { + const result = createInvitationCreateSchema(); + expect(result.emailSchema.safeParse).toBeDefined(); + expect(typeof result.emailSchema.safeParse).toBe('function'); + }); + }); + + describe('edge cases', () => { + it('should handle email field config with only regex (no errorMessage)', () => { + const schema = createInvitationCreateSchema({ + email: { regex: /^[\w.+-]+@company\.com$/ }, + }); + + // Should use the default error message since none was provided + expect(schema.emailErrorMessage).toBe('Please enter a valid email address'); + }); + + it('should handle email field config with only errorMessage (no regex)', () => { + const schema = createInvitationCreateSchema({ + email: { errorMessage: 'Custom error' }, + }); + + // Should still use the default regex + expect(schema.emailSchema.safeParse('user@example.com').success).toBe(true); + expect(schema.emailErrorMessage).toBe('Custom error'); + }); + }); +}); diff --git a/packages/core/src/schemas/my-organization/member-management/invitation-create-schema-types.ts b/packages/core/src/schemas/my-organization/member-management/invitation-create-schema-types.ts new file mode 100644 index 000000000..b115aa96d --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/invitation-create-schema-types.ts @@ -0,0 +1,24 @@ +/** + * Invitation creation schema type definitions. + * @module invitation-create-schema-types + * @internal + */ + +/** + * Schema configuration for a single email field. + * @internal + */ +export interface EmailFieldConfig { + regex?: RegExp; + errorMessage?: string; +} + +/** + * Schema configuration for invitation creation form. + * Consumers can override validation rules for each field. + * @internal + */ +export interface InvitationCreateSchemas { + email?: EmailFieldConfig; + maxEmails?: number; +} diff --git a/packages/core/src/schemas/my-organization/member-management/invitation-create-schema.ts b/packages/core/src/schemas/my-organization/member-management/invitation-create-schema.ts new file mode 100644 index 000000000..557818a4e --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/invitation-create-schema.ts @@ -0,0 +1,77 @@ +/** + * Invitation creation schema for form validation. + * @module invitation-create-schema + * @internal + */ + +import { z } from 'zod'; + +import { type InvitationCreateSchemas } from './invitation-create-schema-types'; + +/** Default email regex pattern. */ +const DEFAULT_EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + +/** Default maximum number of email addresses allowed. */ +const DEFAULT_MAX_EMAILS = 10; + +/** + * Helper to merge schema field config with defaults. + * @param schema - Schema configuration + * @param field - Form field name + * @param defaultError - Default error message + * @returns The merged field configuration + * @internal + */ +const mergeFieldConfig = ( + schema: InvitationCreateSchemas | undefined, + field: 'email', + defaultError: string, +) => { + const fieldConfig = schema?.[field]; + return fieldConfig + ? { + ...fieldConfig, + errorMessage: fieldConfig.errorMessage || defaultError, + } + : { + errorMessage: defaultError, + }; +}; + +/** + * Creates a schema for invitation create form validation. + * @param options - Schema configuration options (consumers can override) + * @param defaultEmailError - Default error message for invalid email + * @returns Object containing Zod email schema, email regex, and maxEmails + */ +export const createInvitationCreateSchema = ( + options: InvitationCreateSchemas = {}, + defaultEmailError = 'Please enter a valid email address', +) => { + const emailConfig = mergeFieldConfig(options, 'email', defaultEmailError); + + const emailRegex = emailConfig.regex ?? DEFAULT_EMAIL_REGEX; + const emailErrorMessage = emailConfig.errorMessage ?? defaultEmailError; + const maxEmails = options.maxEmails ?? DEFAULT_MAX_EMAILS; + + const emailSchema = z.string().min(1, emailErrorMessage).regex(emailRegex, emailErrorMessage); + + return { + emailSchema, + emailRegex, + emailErrorMessage, + maxEmails, + }; +}; + +/** + * Default invitation create schema configuration. + */ +export const invitationCreateSchemaDefaults = createInvitationCreateSchema(); + +/** + * Type for a validated email value. + */ +export type InternalInvitationEmailValue = z.infer< + typeof invitationCreateSchemaDefaults.emailSchema +>; diff --git a/packages/core/src/schemas/my-organization/member-management/invitation-schema.ts b/packages/core/src/schemas/my-organization/member-management/invitation-schema.ts new file mode 100644 index 000000000..82651afcd --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/invitation-schema.ts @@ -0,0 +1,59 @@ +/** + * Invitation validation schemas. + * @module invitation-schema + * @internal + */ + +import { z } from 'zod'; + +/** + * Schema for organization invitation data. + * @internal + */ +export const invitationSchema = z.object({ + id: z.string(), + invitee: z.object({ + email: z.string().email(), + }), + inviter: z.object({ + name: z.string().optional(), + }), + roles: z.array(z.string()).optional(), + created_at: z.string().optional(), + expires_at: z.string().optional(), +}); + +/** + * Schema for invitation list response. + * @internal + */ +export const invitationListResponseSchema = z.object({ + invitations: z.array(invitationSchema), + total: z.number().optional(), + start: z.number().optional(), + limit: z.number().optional(), +}); + +/** + * Schema for creating an invitation. + * @internal + */ +export const createInvitationSchema = z.object({ + invitee: z.object({ + email: z.string().email(), + }), + roles: z.array(z.string()).optional(), +}); + +/** + * Schema for revoking an invitation. + * @internal + */ +export const revokeInvitationSchema = z.object({ + invitation_id: z.string(), +}); + +export type Invitation = z.infer; +export type InvitationListResponse = z.infer; +export type CreateInvitationInput = z.infer; +export type RevokeInvitationInput = z.infer; diff --git a/packages/core/src/schemas/my-organization/member-management/member-schema.ts b/packages/core/src/schemas/my-organization/member-management/member-schema.ts new file mode 100644 index 000000000..a3499147a --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/member-schema.ts @@ -0,0 +1,42 @@ +/** + * Member validation schemas. + * @module member-schema + * @internal + */ + +import { z } from 'zod'; + +/** + * Schema for organization member data. + * @internal + */ +export const memberSchema = z.object({ + user_id: z.string(), + email: z.string().email().optional(), + name: z.string().optional(), + picture: z.string().url().optional(), + roles: z.array(z.string()).optional(), +}); + +/** + * Schema for member list response. + * @internal + */ +export const memberListResponseSchema = z.object({ + members: z.array(memberSchema), + total: z.number().optional(), + start: z.number().optional(), + limit: z.number().optional(), +}); + +/** + * Schema for removing a member. + * @internal + */ +export const removeMemberSchema = z.object({ + user_id: z.string(), +}); + +export type Member = z.infer; +export type MemberListResponse = z.infer; +export type RemoveMemberInput = z.infer; diff --git a/packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts b/packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts new file mode 100644 index 000000000..9f6c24379 --- /dev/null +++ b/packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts @@ -0,0 +1,25 @@ +/** + * Member management utility functions. + * @module member-management-utils + * @internal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; + +import type { InvitationStatus } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * Determines the status of an invitation based on `expires_at`. + * @param invitation - The invitation to check. + * @returns The invitation status. + */ +export function getInvitationStatus(invitation: MemberInvitation): InvitationStatus { + if (invitation.expires_at) { + const expiresAt = new Date(invitation.expires_at); + if (expiresAt < new Date()) { + return 'expired'; + } + } + + return 'pending'; +} diff --git a/packages/react/src/types/index.ts b/packages/react/src/types/index.ts index e88c10c02..844caff99 100644 --- a/packages/react/src/types/index.ts +++ b/packages/react/src/types/index.ts @@ -25,3 +25,5 @@ export * from './my-organization/idp-management/sso-provisioning/provisioning-to export * from './my-organization/idp-management/sso-provisioning/sso-provisioning-tab-types'; export * from './my-organization/organization-management/organization-details-edit-types'; export * from './my-organization/organization-management/organization-details-types'; +export * from './my-organization/member-management/organization-invitation-table-types'; +export * from './my-organization/member-management/organization-member-management-types'; diff --git a/packages/react/src/types/my-organization/config/config-types.ts b/packages/react/src/types/my-organization/config/config-types.ts index b305c8cd9..3b7a27cba 100644 --- a/packages/react/src/types/my-organization/config/config-types.ts +++ b/packages/react/src/types/my-organization/config/config-types.ts @@ -8,6 +8,13 @@ import type { IdpStrategy, } from '@auth0/universal-components-core'; +/** Role returned from organization configuration. */ +export interface ConfigRole { + id: string; + name: string; + description?: string; +} + /** useConfig hook result. */ export interface UseConfigResult { config: GetConfigurationResponseContent | null; @@ -16,4 +23,5 @@ export interface UseConfigResult { filteredStrategies: IdpStrategy[]; shouldAllowDeletion: boolean; isConfigValid: boolean; + allowedRoles: ConfigRole[]; } diff --git a/packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts b/packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts new file mode 100644 index 000000000..eb03e9850 --- /dev/null +++ b/packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts @@ -0,0 +1,213 @@ +/** + * Organization invitation table types. + * @module organization-invitation-table-types + */ + +import type { + SharedComponentProps, + ComponentAction, + MemberInvitation, +} from '@auth0/universal-components-core'; + +/** Invitation status. */ +export type InvitationStatus = 'pending' | 'expired'; + +/** Role option for invitation. */ +export interface RoleOption { + id: string; + name: string; + description?: string; +} + +/** Identity provider option for invitation. */ +export interface IdentityProviderOption { + id: string; + name: string; + type?: string; +} + +/** Input for creating an invitation. */ +export interface CreateInvitationInput { + invitee: { + email: string; + }; + inviter?: { + name?: string; + }; + roles?: string[]; + identity_provider_id?: string; + /** Time to live in seconds */ + ttl_sec?: number; +} + +/** Pagination state for invitation table (checkpoint-based). */ +export interface InvitationPaginationState { + pageSize: number; + currentPage: number; + totalItems?: number; + hasNextPage: boolean; + hasPreviousPage: boolean; +} + +/** Sort configuration for invitation table. */ +export interface InvitationSortConfig { + key: string | null; + direction: 'asc' | 'desc'; +} + +/** Filter state for invitation table. */ +export interface InvitationFilterState { + searchQuery?: string; + roleId?: string; +} + +/** CSS classes for OrganizationInvitationTab. */ +export interface OrganizationInvitationTabClasses { + 'OrganizationInvitationTab-root'?: string; + 'OrganizationInvitationTab-table'?: string; + 'OrganizationInvitationTab-createModal'?: string; + 'OrganizationInvitationTab-detailsModal'?: string; + 'OrganizationInvitationTab-revokeModal'?: string; + 'OrganizationInvitationTab-revokeResendModal'?: string; + 'OrganizationInvitationTab-searchInput'?: string; + 'OrganizationInvitationTab-filterDropdown'?: string; + 'OrganizationInvitationTab-pagination'?: string; +} + +/** OrganizationInvitationTab translation messages. */ +export interface OrganizationInvitationTabMessages { + table?: { + columns?: { + email?: string; + status?: string; + inviter?: string; + created_at?: string; + expires_at?: string; + roles?: string; + }; + empty_message?: string; + search_placeholder?: string; + filter_by_role?: string; + all_roles?: string; + reset_filter?: string; + showing_results?: string; + status_pending?: string; + status_expired?: string; + }; + actions?: { + menu_label?: string; + view_details?: string; + copy_url?: string; + revoke_and_resend?: string; + revoke?: string; + }; + create?: { + title?: string; + description?: string; + email_label?: string; + email_placeholder?: string; + email_helper?: string; + email_limit_error?: string; + email_invalid_error?: string; + email_duplicate_error?: string; + email_required_error?: string; + roles_label?: string; + roles_placeholder?: string; + provider_label?: string; + provider_placeholder?: string; + submit_button?: string; + creating?: string; + cancel_button?: string; + }; + details?: { + title?: string; + email_label?: string; + status_label?: string; + roles_label?: string; + provider_label?: string; + created_at_label?: string; + expires_at_label?: string; + invited_by_label?: string; + invitation_url_label?: string; + copy_url_button?: string; + close_button?: string; + revoke_button?: string; + resend_button?: string; + }; + revoke?: { + title?: string; + description?: string; + confirm_button?: string; + cancel_button?: string; + }; + revoke_resend?: { + title?: string; + description?: string; + confirm_button?: string; + cancel_button?: string; + }; + success?: { + url_copied?: string; + invitation_resent?: string; + }; + error?: { + fetch_failed?: string; + create_failed?: string; + revoke_failed?: string; + resend_failed?: string; + revoke_resend_failed?: string; + copy_url_failed?: string; + }; +} + +/** Props for OrganizationInvitationTab component. */ +export interface OrganizationInvitationTabProps + extends SharedComponentProps< + OrganizationInvitationTabMessages, + OrganizationInvitationTabClasses + > { + createAction?: ComponentAction; + revokeAction?: ComponentAction; +} + +/** Props for OrganizationInvitationTableActionsColumn component. */ +export interface OrganizationInvitationTableActionsColumnProps { + invitation: MemberInvitation; + customMessages?: Partial; + readOnly?: boolean; + onViewDetails?: (invitation: MemberInvitation) => void; + onCopyUrl?: (invitation: MemberInvitation) => void; + onRevokeAndResend?: (invitation: MemberInvitation) => void; + onRevoke?: (invitation: MemberInvitation) => void; +} + +/** Props for OrganizationInvitationTable component. */ +export interface OrganizationInvitationTableProps { + invitations: MemberInvitation[]; + loading?: boolean; + customMessages?: Partial; + pagination: InvitationPaginationState; + filters?: InvitationFilterState; + sortConfig?: InvitationSortConfig; + availableRoles?: RoleOption[]; + readOnly?: boolean; + onView?: (invitation: MemberInvitation) => void; + onCopyUrl?: (invitation: MemberInvitation) => void; + onRevokeAndResend?: (invitation: MemberInvitation) => void; + onRevoke?: (invitation: MemberInvitation) => void; + onNextPage?: () => void; + onPreviousPage?: () => void; + onPageSizeChange?: (pageSize: number) => void; + onSortChange?: (sortConfig: InvitationSortConfig) => void; + onRoleFilterChange?: (roleId: string | undefined) => void; + className?: string; +} + +/** Props for InvitationSearchFilter component. */ +export interface InvitationSearchFilterProps { + filters?: InvitationFilterState; + availableRoles?: RoleOption[]; + customMessages?: Partial; + className?: string; + onRoleFilterChange?: (roleId: string | undefined) => void; +} diff --git a/packages/react/src/types/my-organization/member-management/organization-member-management-types.ts b/packages/react/src/types/my-organization/member-management/organization-member-management-types.ts new file mode 100644 index 000000000..5225612ad --- /dev/null +++ b/packages/react/src/types/my-organization/member-management/organization-member-management-types.ts @@ -0,0 +1,112 @@ +/** + * Organization member management types. + * @module organization-member-management-types + */ + +import type { + ComponentAction, + SharedComponentProps, + MemberInvitation, +} from '@auth0/universal-components-core'; + +import type { + CreateInvitationInput, + IdentityProviderOption, + InvitationFilterState, + InvitationPaginationState, + InvitationSortConfig, + OrganizationInvitationTabClasses, + OrganizationInvitationTabMessages, + RoleOption, +} from './organization-invitation-table-types'; + +export type ActiveTab = 'members' | 'invitations'; + +export interface UseOrganizationMemberManagementOptions { + customMessages?: OrganizationMemberManagementMessages; + readOnly?: boolean; + /** Action hooks for invitation creation (onBefore/onAfter) */ + createInvitationAction?: ComponentAction; + /** Action hooks for invitation revocation (onBefore/onAfter) */ + revokeInvitationAction?: ComponentAction; + /** Action hooks for invitation revoke-and-resend (onBefore/onAfter) */ + resendInvitationAction?: ComponentAction; +} + +export interface MemberManagementState { + activeTab: ActiveTab; + isLoading: boolean; + availableRoles: RoleOption[]; + availableProviders: IdentityProviderOption[]; + + invitations: MemberInvitation[]; + isFetchingInvitations: boolean; + isCreatingInvitation: boolean; + isRevokingInvitation: boolean; + isResendingInvitation: boolean; + invitationPagination: InvitationPaginationState; + invitationFilters: InvitationFilterState; + invitationSortConfig: InvitationSortConfig; + showCreateModal: boolean; + showDetailsModal: boolean; + showRevokeModal: boolean; + showRevokeResendModal: boolean; + selectedInvitation: MemberInvitation | null; +} + +export interface MemberManagementHandlers { + setActiveTab: (tab: ActiveTab) => void; + + handleCreateClick: () => void; + handleCreateSubmit: (data: CreateInvitationInput) => void; + handleCreateCancel: () => void; + handleDetailsClick: (invitation: MemberInvitation) => void; + handleDetailsClose: () => void; + handleRevokeClick: (invitation: MemberInvitation) => void; + handleRevokeConfirm: () => void; + handleRevokeCancel: () => void; + handleRevokeResendClick: (invitation: MemberInvitation) => void; + handleRevokeResendConfirm: () => void; + handleRevokeResendCancel: () => void; + handleCopyUrl: (invitation: MemberInvitation) => Promise; + handleNextPage: () => void; + handlePreviousPage: () => void; + handlePageSizeChange: (pageSize: number) => void; + handleSortChange: (sortConfig: InvitationSortConfig) => void; + handleRoleFilterChange: (roleId: string | undefined) => void; +} + +/** CSS classes for OrganizationMemberManagement. */ +export interface OrganizationMemberManagementClasses extends OrganizationInvitationTabClasses { + 'OrganizationMemberManagement-root'?: string; + 'OrganizationMemberManagement-header'?: string; + 'OrganizationMemberManagement-tabs'?: string; +} + +/** OrganizationMemberManagement translation messages. */ +export interface OrganizationMemberManagementMessages { + header?: { + title?: string; + description?: string; + }; + tabs?: { + members?: string; + invitations?: string; + }; + invitation?: OrganizationInvitationTabMessages; +} + +/** Props for OrganizationMemberManagement component. */ +export interface OrganizationMemberManagementProps + extends SharedComponentProps< + OrganizationMemberManagementMessages, + OrganizationMemberManagementClasses + > { + hideHeader?: boolean; + /** Action hooks for invitation creation (onBefore/onAfter) */ + createInvitationAction?: ComponentAction; + /** Action hooks for invitation revocation (onBefore/onAfter) */ + revokeInvitationAction?: ComponentAction; + /** Action hooks for invitation revoke-and-resend (onBefore/onAfter) */ + resendInvitationAction?: ComponentAction; +} From e29c38839d2ef32d7414a61cde88d28a8c9ff53b Mon Sep 17 00:00:00 2001 From: rax7389 Date: Sun, 29 Mar 2026 23:14:16 +0530 Subject: [PATCH 003/125] feat(core, react): add service types and invitation components --- packages/core/package.json | 4 +- .../sso-provider/sso-provider-types.ts | 1 - .../src/services/my-organization/index.ts | 1 + .../member-management-types.ts | 111 +++++++ .../organization-invitation-details-modal.tsx | 250 +++++++++++++++ .../organization-invitation-revoke-modal.tsx | 92 ++++++ ...zation-invitation-table-actions-column.tsx | 114 +++++++ .../organization-invitation-table.tsx | 188 +++++++++++ .../organization-invitation-create-modal.tsx | 302 ++++++++++++++++++ .../shared/search-filter/search-filter.tsx | 83 +++++ pnpm-lock.yaml | 11 +- 11 files changed, 1149 insertions(+), 8 deletions(-) create mode 100644 packages/core/src/services/my-organization/member-management/member-management-types.ts create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx diff --git a/packages/core/package.json b/packages/core/package.json index 8affd2ed0..a10bad66f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -51,8 +51,8 @@ "@vitest/coverage-v8": "^3.2.4" }, "dependencies": { - "@auth0/myaccount-js": "1.0.0-beta.0", - "@auth0/myorganization-js": "1.0.0-beta.3", + "@auth0/myaccount-js": "^1.0.0-beta.0", + "@auth0/myorganization-js": "file:../../auth0-myorganization-js-1.0.0-beta.4.tgz", "zod": "^3.22.4" } } diff --git a/packages/core/src/services/my-organization/idp-management/sso-provider/sso-provider-types.ts b/packages/core/src/services/my-organization/idp-management/sso-provider/sso-provider-types.ts index 6bd555911..e73ac5de0 100644 --- a/packages/core/src/services/my-organization/idp-management/sso-provider/sso-provider-types.ts +++ b/packages/core/src/services/my-organization/idp-management/sso-provider/sso-provider-types.ts @@ -13,7 +13,6 @@ import type { export type ListIdentityProvidersResponseContent = MyOrganization.ListIdentityProvidersResponseContent; export type IdentityProvider = MyOrganization.IdpKnownResponse; -export type DetachIdpProviderResponseContent = MyOrganization.DetachIdpProviderResponseContent; export type CreateIdentityProviderRequestContent = MyOrganization.CreateIdentityProviderRequestContent; export type CreateIdentityProviderResponseContent = diff --git a/packages/core/src/services/my-organization/index.ts b/packages/core/src/services/my-organization/index.ts index deb30e8e6..5e1816d52 100644 --- a/packages/core/src/services/my-organization/index.ts +++ b/packages/core/src/services/my-organization/index.ts @@ -7,4 +7,5 @@ export * from './organization-management'; export * from './idp-management'; export * from './domain-management'; +export * from './member-management/member-management-types'; export * from './config'; diff --git a/packages/core/src/services/my-organization/member-management/member-management-types.ts b/packages/core/src/services/my-organization/member-management/member-management-types.ts new file mode 100644 index 000000000..7c7561743 --- /dev/null +++ b/packages/core/src/services/my-organization/member-management/member-management-types.ts @@ -0,0 +1,111 @@ +/** + * Member management type definitions for organization member and invitation operations. + * @module member-management-types + * @internal + */ +import type { MyOrganization } from '@auth0/myorganization-js'; + +/** + * Organization member ID type. + */ +export type OrgMemberId = MyOrganization.OrgMemberId; + +/** + * Organization member entity. + */ +export type OrgMember = MyOrganization.OrgMember; + +/** + * Organization member role. + */ +export type OrgMemberRole = MyOrganization.OrgMemberRole; + +/** + * Organization member role ID. + */ +export type OrgMemberRoleId = MyOrganization.OrgMemberRoleId; + +/** + * Response content for listing organization members. + */ +export type ListOrganizationMembersResponseContent = + MyOrganization.ListOrganizationMembersResponseContent; + +/** + * Response content for getting a single organization member. + */ +export type GetOrganizationMemberResponseContent = + MyOrganization.GetOrganizationMemberResponseContent; + +/** + * Request parameters for listing organization members. + */ +export type ListOrganizationMembersRequestParameters = + MyOrganization.ListOrganizationMembersRequestParameters; + +/** + * Response content for getting organization member roles. + */ +export type GetOrganizationMemberRolesResponseContent = + MyOrganization.GetOrganizationMemberRolesResponseContent; + +/** + * Request content for assigning a role to an organization member. + */ +export type AssignOrganizationMemberRoleRequestContent = + MyOrganization.AssignOrganizationMemberRoleRequestContent; + +/** + * Response content for assigning a role to an organization member. + */ +export type AssignOrganizationMemberRoleResponseContent = + MyOrganization.AssignOrganizationMemberRoleResponseContent; + +/** + * Invitation ID type. + */ +export type InvitationId = MyOrganization.InvitationId; + +/** + * Member invitation entity. + */ +export type MemberInvitation = MyOrganization.MemberInvitation; + +/** + * Member invitation invitee details. + */ +export type MemberInvitationInvitee = MyOrganization.MemberInvitationInvitee; + +/** + * Member invitation inviter details. + */ +export type MemberInvitationInviter = MyOrganization.MemberInvitationInviter; + +/** + * Response content for listing member invitations. + */ +export type ListMembersInvitationsResponseContent = + MyOrganization.ListMembersInvitationsResponseContent; + +/** + * Request parameters for listing member invitations. + */ +export type ListMemberInvitationsRequestParameters = + MyOrganization.ListMemberInvitationsRequestParameters; + +/** + * Request content for creating a member invitation. + */ +export type CreateMemberInvitationRequestContent = + MyOrganization.CreateMemberInvitationRequestContent; + +/** + * Response content for creating a member invitation. + */ +export type CreateMemberInvitationResponseContent = + MyOrganization.CreateMemberInvitationResponseContent; + +/** + * Response content for getting a member invitation. + */ +export type GetMemberInvitationResponseContent = MyOrganization.GetMemberInvitationResponseContent; diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx new file mode 100644 index 000000000..71897a038 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx @@ -0,0 +1,250 @@ +/** + * Organization invitation details modal component. + * @module organization-invitation-details-modal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; +import { Link } from 'lucide-react'; +import * as React from 'react'; + +import { CopyableTextField } from '@/components/auth0/shared/copyable-text-field'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Label } from '@/components/ui/label'; +import { TextField } from '@/components/ui/text-field'; +import { TextFieldGroup } from '@/components/ui/text-field-group'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { getInvitationStatus } from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { + InvitationStatus, + RoleOption, + IdentityProviderOption, + OrganizationInvitationTabMessages, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export interface OrganizationInvitationDetailsModalProps { + invitation: MemberInvitation | null; + isOpen: boolean; + isRevoking?: boolean; + isResending?: boolean; + customMessages?: Partial; + availableRoles?: RoleOption[]; + availableProviders?: IdentityProviderOption[]; + readOnly?: boolean; + onClose: () => void; + onCopyUrl?: (invitation: MemberInvitation) => void; + onRevoke?: (invitation?: MemberInvitation) => void; + onResend?: (invitation?: MemberInvitation) => void; + className?: string; +} + +/** + * Returns the badge variant for a given invitation status. + * @param status - The invitation status. + * @returns The badge variant string. + */ +function getStatusBadgeVariant(status: InvitationStatus): 'warning' | 'destructive' { + return status === 'pending' ? 'warning' : 'destructive'; +} + +/** + * Modal for viewing invitation details with revoke and resend actions. + * @param props - The component props. + * @param props.invitation - The invitation to display. + * @param props.isOpen - Whether the modal is open. + * @param props.isRevoking - Whether a revoke action is in progress. + * @param props.isResending - Whether a resend action is in progress. + * @param props.customMessages - Custom translation messages. + * @param props.availableRoles - Available roles for display. + * @param props.availableProviders - Available providers for display. + * @param props.readOnly - Whether in read-only mode. + * @param props.onClose - Callback when modal is closed. + * @param props.onCopyUrl - Callback when copy URL is clicked. + * @param props.onRevoke - Callback when revoke is clicked. + * @param props.onResend - Callback when revoke and resend is clicked. + * @param props.className - Optional CSS class name. + * @returns The modal component. + */ +export function OrganizationInvitationDetailsModal({ + invitation, + isOpen, + isRevoking = false, + isResending = false, + customMessages = {}, + availableRoles = [], + availableProviders = [], + readOnly = false, + onClose, + onCopyUrl, + onRevoke, + onResend, + className, +}: OrganizationInvitationDetailsModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const status = invitation ? getInvitationStatus(invitation) : 'pending'; + const isPending = status === 'pending'; + const isActionInProgress = isRevoking || isResending; + + const roleNames = React.useMemo(() => { + if (!invitation?.roles || invitation.roles.length === 0) return []; + return invitation.roles + .map((roleId) => { + const role = availableRoles.find((r) => r.id === roleId); + return role?.name ?? roleId; + }) + .filter(Boolean); + }, [invitation?.roles, availableRoles]); + + const providerName = React.useMemo(() => { + if (!invitation?.identity_provider_id) return null; + const provider = availableProviders.find((p) => p.id === invitation.identity_provider_id); + return provider?.name ?? invitation.identity_provider_id; + }, [invitation?.identity_provider_id, availableProviders]); + + const handleCopyUrl = React.useCallback(() => { + if (invitation) { + onCopyUrl?.(invitation); + } + }, [invitation, onCopyUrl]); + + const handleRevoke = React.useCallback(() => { + if (invitation) { + onRevoke?.(invitation); + } + }, [invitation, onRevoke]); + + const handleResend = React.useCallback(() => { + if (invitation) { + onResend?.(invitation); + } + }, [invitation, onResend]); + + return ( + + + +
+ {t('invitation.details.title')} + + {isPending + ? t('invitation.table.status_pending') + : t('invitation.table.status_expired')} + +
+ {t('invitation.details.title')} +
+ +
+ {/* Email */} +
+ + +
+ + {/* Created At */} +
+ + +
+ + {/* Expires At */} +
+ + +
+ + {/* Roles */} +
+ + {roleNames.length > 0 ? ( + ({ label: name, value: name }))} + summarizeChips={false} + disabled + readOnly + /> + ) : ( + + )} +
+ + {/* Invitation URL */} + {invitation?.invitation_url && ( +
+ + } + /> +
+ )} + + {/* Revoke / Resend Actions (inline, below invitation URL) */} + {!readOnly && ( +
+ + +
+ )} + + {/* Invited By */} +
+ + +
+ + {/* Identity Provider */} + {providerName && ( +
+ + +
+ )} +
+ + + + +
+
+ ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx new file mode 100644 index 000000000..43132ae07 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx @@ -0,0 +1,92 @@ +/** + * Organization invitation revoke modal component. + * @module organization-invitation-revoke-modal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationInvitationTabMessages } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export interface OrganizationInvitationRevokeModalProps { + invitation: MemberInvitation | null; + isOpen: boolean; + isLoading?: boolean; + isRevokeAndResend?: boolean; + customMessages?: Partial; + onClose: () => void; + onConfirm: (invitation: MemberInvitation) => void; + className?: string; +} + +/** + * Modal for confirming invitation revocation or revoke and resend. + * @param props - The component props. + * @param props.invitation - The invitation to revoke. + * @param props.isOpen - Whether the modal is open. + * @param props.isLoading - Whether the action is in progress. + * @param props.isRevokeAndResend - Whether this is a revoke and resend action. + * @param props.customMessages - Custom translation messages. + * @param props.onClose - Callback when modal is closed. + * @param props.onConfirm - Callback when action is confirmed. + * @param props.className - Optional CSS class name. + * @returns The modal component. + */ +export function OrganizationInvitationRevokeModal({ + invitation, + isOpen, + isLoading = false, + isRevokeAndResend = false, + customMessages = {}, + onClose, + onConfirm, + className, +}: OrganizationInvitationRevokeModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const namespace = isRevokeAndResend ? 'invitation.revoke_resend' : 'invitation.revoke'; + + const handleConfirm = React.useCallback(() => { + if (invitation) { + onConfirm(invitation); + } + }, [invitation, onConfirm]); + + return ( + + + + {t(`${namespace}.title`)} + + + <> + {t.trans(`${namespace}.description`, { + components: { + bold: (children: string) => {children}, + }, + vars: { email: invitation?.invitee?.email ?? '' }, + })} + + + + + + + + + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx new file mode 100644 index 000000000..2757176db --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx @@ -0,0 +1,114 @@ +/** + * Organization invitation table row actions dropdown. + * @module organization-invitation-table-actions-column + * @internal + */ + +import { MoreHorizontal, Eye, Copy, RefreshCcw, Trash2 } from 'lucide-react'; +import * as React from 'react'; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + DropdownMenuPortal, + DropdownMenuSeparator, +} from '@/components/ui/dropdown-menu'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { getInvitationStatus } from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { OrganizationInvitationTableActionsColumnProps } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * OrganizationInvitationTableActionsColumn Component + * Handles the actions column for Invitation table with dropdown menu. + * @param props - Component props. + * @param props.invitation - The invitation to show actions for. + * @param props.customMessages - Custom translation messages to override defaults. + * @param props.readOnly - Whether the component is in read-only mode. + * @param props.onViewDetails - Callback fired when view details action is triggered. + * @param props.onCopyUrl - Callback fired when copy URL action is triggered. + * @param props.onRevokeAndResend - Callback fired when revoke and resend action is triggered. + * @param props.onRevoke - Callback fired when revoke action is triggered. + * @returns JSX element. + */ +export function OrganizationInvitationTableActionsColumn({ + invitation, + customMessages = {}, + readOnly = false, + onViewDetails, + onCopyUrl, + onRevokeAndResend, + onRevoke, +}: OrganizationInvitationTableActionsColumnProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + const status = getInvitationStatus(invitation); + const isPending = status === 'pending'; + + const handleViewDetails = React.useCallback(() => { + onViewDetails?.(invitation); + }, [invitation, onViewDetails]); + + const handleCopyUrl = React.useCallback(() => { + onCopyUrl?.(invitation); + }, [invitation, onCopyUrl]); + + const handleRevokeAndResend = React.useCallback(() => { + onRevokeAndResend?.(invitation); + }, [invitation, onRevokeAndResend]); + + const handleRevoke = React.useCallback(() => { + onRevoke?.(invitation); + }, [invitation, onRevoke]); + + return ( +
+ + + + {t('invitation.actions.menu_label')} + + + + {/* View Details - always available */} + + + {t('invitation.actions.view_details')} + + + {/* Copy URL - only for pending invitations with URL */} + {isPending && invitation.invitation_url && ( + + + {t('invitation.actions.copy_url')} + + )} + + {!readOnly && ( + + + {t('invitation.actions.revoke_and_resend')} + + )} + + {!readOnly && ( + <> + + + + {t('invitation.actions.revoke')} + + + )} + + + +
+ ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx new file mode 100644 index 000000000..96d34da73 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx @@ -0,0 +1,188 @@ +/** + * Organization invitation table component. + * @module organization-invitation-table + * @internal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { OrganizationInvitationTableActionsColumn } from './organization-invitation-table-actions-column'; + +import { InvitationSearchFilter } from '@/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter'; +import { DataPagination } from '@/components/auth0/shared/data-pagination'; +import { DataTable, type Column } from '@/components/auth0/shared/data-table'; +import { Badge } from '@/components/ui/badge'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { cn } from '@/lib/utils'; +import { getInvitationStatus } from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { OrganizationInvitationTableProps } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * Organization invitation table component. + * Displays invitations with search, filtering, and pagination. + * @param props - The component props. + * @param props.invitations - The list of invitations to display. + * @param props.loading - Whether the table is loading. + * @param props.customMessages - Custom translation messages. + * @param props.pagination - Pagination state. + * @param props.filters - Current filter state. + * @param props.availableRoles - Available roles for filtering. + * @param props.readOnly - Whether the component is in read-only mode. + * @param props.onView - Callback when viewing invitation details. + * @param props.onCopyUrl - Callback when copying invitation URL. + * @param props.onRevokeAndResend - Callback when revoking and resending invitation. + * @param props.onRevoke - Callback when revoking invitation. + * @param props.onPageChange - Callback when page changes. + * @param props.onPageSizeChange - Callback when page size changes. + * @param props.onRoleFilterChange - Callback when role filter changes. + * @param props.className - Optional CSS class name. + * @returns The invitation table component. + */ +export function OrganizationInvitationTable({ + invitations, + loading = false, + customMessages = {}, + pagination, + filters, + availableRoles, + readOnly = false, + sortConfig, + onSortChange, + onView, + onCopyUrl, + onRevokeAndResend, + onRevoke, + onNextPage, + onPreviousPage, + onPageSizeChange, + onRoleFilterChange, + className, +}: OrganizationInvitationTableProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const renderDate = (_invitation: MemberInvitation, value: string | number | Date) => ( + + {new Date(value).toLocaleString(undefined, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + })} + + ); + + const columns: Column[] = React.useMemo( + () => [ + { + type: 'text', + accessorKey: 'invitee', + title: t('invitation.table.columns.email'), + enableSorting: false, + render: (invitation) => ( +
{invitation.invitee?.email}
+ ), + }, + { + type: 'text', + accessorKey: 'organization_id', + title: t('invitation.table.columns.status'), + enableSorting: false, + render: (invitation) => { + const status = getInvitationStatus(invitation); + return ( + + {status === 'pending' + ? t('invitation.table.status_pending') + : t('invitation.table.status_expired')} + + ); + }, + }, + { + type: 'date', + accessorKey: 'created_at', + title: t('invitation.table.columns.created_at'), + enableSorting: true, + format: 'medium', + render: renderDate, + }, + { + type: 'date', + accessorKey: 'expires_at', + title: t('invitation.table.columns.expires_at'), + enableSorting: false, + format: 'medium', + render: renderDate, + }, + { + type: 'text', + accessorKey: 'inviter', + title: t('invitation.table.columns.inviter'), + enableSorting: false, + render: (invitation) => ( + {invitation.inviter?.name ?? '-'} + ), + }, + { + type: 'actions', + title: '', + enableSorting: false, + render: (invitation) => ( + + ), + }, + ], + [t, customMessages, readOnly, onView, onCopyUrl, onRevokeAndResend, onRevoke], + ); + + return ( +
+ + + + + {invitations.length > 0 && ( +
+ +
+ )} +
+ ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx new file mode 100644 index 000000000..2ad901088 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx @@ -0,0 +1,302 @@ +/** + * Organization invitation create modal component. + * @module organization-invitation-create-modal + */ + +import { + createInvitationCreateSchema, + type InvitationCreateSchemas, +} from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { Combobox } from '@/components/ui/combobox'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { TextFieldGroup } from '@/components/ui/text-field-group'; +import type { ChipItem } from '@/components/ui/text-field-group'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + CreateInvitationInput, + RoleOption, + IdentityProviderOption, + OrganizationInvitationTabMessages, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export interface OrganizationInvitationCreateModalProps { + isOpen: boolean; + isLoading?: boolean; + customMessages?: Partial; + availableRoles?: RoleOption[]; + availableProviders?: IdentityProviderOption[]; + inviterName?: string; + schema?: InvitationCreateSchemas; + onClose: () => void; + onCreate: (data: CreateInvitationInput) => void; + className?: string; +} + +/** + * Modal for creating a new invitation. + * Supports multiple email addresses, role selection, and provider selection. + * Validation rules can be overridden via the `schema` prop. + * + * @param props - The component props. + * @param props.isOpen - Whether the modal is open. + * @param props.isLoading - Whether the form is loading. + * @param props.customMessages - Custom translation messages. + * @param props.availableRoles - Available roles for selection. + * @param props.availableProviders - Available identity providers. + * @param props.inviterName - Name of the person sending the invitation. + * @param props.schema - Schema overrides for validation (email regex, maxEmails, error messages). + * @param props.onClose - Callback when modal is closed. + * @param props.onCreate - Callback when invitation is created. + * @param props.className - Optional CSS class name. + * @returns The modal component. + */ +export function OrganizationInvitationCreateModal({ + isOpen, + isLoading = false, + customMessages = {}, + availableRoles = [], + availableProviders = [], + inviterName, + schema, + onClose, + onCreate, + className, +}: OrganizationInvitationCreateModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const validationConfig = React.useMemo( + () => createInvitationCreateSchema(schema, t('invitation.create.email_invalid_error')), + [schema, t], + ); + + const [emailInput, setEmailInput] = React.useState(''); + const [emailChips, setEmailChips] = React.useState([]); + const [selectedRoles, setSelectedRoles] = React.useState([]); + const [selectedProvider, setSelectedProvider] = React.useState(); + const [emailError, setEmailError] = React.useState(); + + const handleEmailInputChange = React.useCallback((e: React.ChangeEvent) => { + setEmailInput(e.target.value); + setEmailError(undefined); + }, []); + + const hasInvalidChips = React.useMemo( + () => emailChips.some((chip) => chip.variant === 'destructive'), + [emailChips], + ); + + const handleEmailChipAdd = React.useCallback( + (value: string) => { + const trimmedEmail = value.trim().replace(/,/g, ''); + + if (!trimmedEmail) return; + + if (emailChips.length >= validationConfig.maxEmails) { + setEmailError(t('invitation.create.email_limit_error')); + return; + } + + if (emailChips.some((chip) => chip.value === trimmedEmail)) { + setEmailError(t('invitation.create.email_duplicate_error')); + return; + } + + const result = validationConfig.emailSchema.safeParse(trimmedEmail); + if (!result.success) { + setEmailChips((prev) => [ + ...prev, + { label: trimmedEmail, value: trimmedEmail, variant: 'destructive' }, + ]); + setEmailInput(''); + setEmailError(t('invitation.create.email_invalid_error')); + return; + } + + setEmailChips((prev) => [...prev, { label: trimmedEmail, value: trimmedEmail }]); + setEmailInput(''); + setEmailError(undefined); + }, + [emailChips, validationConfig, t], + ); + + const handleEmailChipRemove = React.useCallback((value: string) => { + setEmailChips((prev) => { + const updated = prev.filter((chip) => chip.value !== value); + if (!updated.some((chip) => chip.variant === 'destructive')) { + setEmailError(undefined); + } + return updated; + }); + }, []); + + const handleRoleChange = React.useCallback((value: string | string[]) => { + setSelectedRoles(Array.isArray(value) ? value : value ? [value] : []); + }, []); + + const handleProviderChange = React.useCallback((value: string) => { + setSelectedProvider(value || undefined); + }, []); + + const handleSubmit = React.useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + + // Add any remaining input to emails + const finalEmails = emailChips.map((chip) => chip.value); + if (emailInput.trim()) { + const trimmedEmail = emailInput.trim(); + const result = validationConfig.emailSchema.safeParse(trimmedEmail); + if (result.success && !finalEmails.includes(trimmedEmail)) { + finalEmails.push(trimmedEmail); + } + } + + if (finalEmails.length === 0) { + setEmailError(t('invitation.create.email_required_error')); + return; + } + + // Create invitations for each email + for (const email of finalEmails) { + const invitationData: CreateInvitationInput = { + invitee: { email }, + roles: selectedRoles.length > 0 ? selectedRoles : undefined, + identity_provider_id: selectedProvider, + }; + + if (inviterName) { + invitationData.inviter = { name: inviterName }; + } + + onCreate(invitationData); + } + }, + [ + emailChips, + emailInput, + validationConfig, + selectedRoles, + selectedProvider, + inviterName, + onCreate, + t, + ], + ); + + const handleClose = React.useCallback(() => { + setEmailInput(''); + setEmailChips([]); + setSelectedRoles([]); + setSelectedProvider(undefined); + setEmailError(undefined); + onClose(); + }, [onClose]); + + const canSubmit = React.useMemo( + () => + !hasInvalidChips && + (emailChips.length > 0 || + (emailInput.trim() !== '' && + validationConfig.emailSchema.safeParse(emailInput.trim()).success)), + [emailChips.length, emailInput, validationConfig, hasInvalidChips], + ); + + const roleOptions = React.useMemo( + () => availableRoles.map((role) => ({ label: role.name, value: role.id })), + [availableRoles], + ); + + return ( + + +
+ + {t('invitation.create.title')} + {t('invitation.create.description')} + + +
+ {/* Email Input */} +
+ + +

{t('invitation.create.email_helper')}

+ {emailError &&

{emailError}

} +
+ + {/* Roles Combobox */} +
+ + +
+ + {/* Provider Dropdown */} +
+ + +

+ {t('invitation.create.provider_helper')} +

+
+
+ + + + + +
+
+
+ ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx new file mode 100644 index 000000000..5ddb328e4 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx @@ -0,0 +1,83 @@ +/** + * Search and filter component for invitations. + * @module search-filter + * @internal + */ + +import { X } from 'lucide-react'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { InvitationSearchFilterProps } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * Filter bar for invitation table. + * Shows a right-aligned role filter dropdown with a reset button. + * @param props - The component props. + * @param props.filters - Current filter state. + * @param props.availableRoles - Available roles for filtering. + * @param props.customMessages - Custom translation messages. + * @param props.className - Optional CSS class name. + * @param props.onRoleFilterChange - Callback fired when role filter changes. + * @returns The filter bar component. + */ +export function InvitationSearchFilter({ + filters, + availableRoles = [], + customMessages = {}, + className, + onRoleFilterChange, +}: InvitationSearchFilterProps): React.JSX.Element | null { + const { t } = useTranslator('member_management', customMessages); + + const handleRoleFilterChange = React.useCallback( + (value: string) => { + onRoleFilterChange?.(value === 'all' ? undefined : value); + }, + [onRoleFilterChange], + ); + + const handleReset = React.useCallback(() => { + onRoleFilterChange?.(undefined); + }, [onRoleFilterChange]); + + const hasActiveFilter = !!filters?.roleId; + + if (availableRoles.length === 0) { + return null; + } + + return ( +
+ + + +
+ ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a18a59fb0..36d3a5f05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -544,8 +544,8 @@ importers: specifier: 1.0.0-beta.0 version: 1.0.0-beta.0 '@auth0/myorganization-js': - specifier: 1.0.0-beta.3 - version: 1.0.0-beta.3 + specifier: file:../../auth0-myorganization-js-1.0.0-beta.4.tgz + version: file:auth0-myorganization-js-1.0.0-beta.4.tgz zod: specifier: ^3.22.4 version: 3.25.76 @@ -729,8 +729,9 @@ packages: resolution: {integrity: sha512-slj0RtNfieNk1BC1ERrCQw65qMUVKU5qacbTc8BFH8R316CUpsOhZ2MIiV9l3VEkaqY1hmCZm03+ZI6ym+3PZg==} engines: {node: '>=18.0.0'} - '@auth0/myorganization-js@1.0.0-beta.3': - resolution: {integrity: sha512-ul7BmJjJinfgu1xAK3LPR4tgcSxEW9BgjCHy5RHHbF2UBbioYTlbx7dVLn+b8m09UnPmtxTvPisoza/KhacG3Q==} + '@auth0/myorganization-js@file:auth0-myorganization-js-1.0.0-beta.4.tgz': + resolution: {integrity: sha512-yTZbJ0K75WsCGsb9bXBGTs32WLXEXqyTuM9lgmYST8uSag2ILfJdYZPQZkvyKM5v+7Sk5B9vz0mg3tNfv8SFNg==, tarball: file:auth0-myorganization-js-1.0.0-beta.4.tgz} + version: 1.0.0-beta.4 engines: {node: '>=18.0.0'} '@auth0/nextjs-auth0@4.16.0': @@ -7303,7 +7304,7 @@ snapshots: '@auth0/myaccount-js@1.0.0-beta.0': {} - '@auth0/myorganization-js@1.0.0-beta.3': + '@auth0/myorganization-js@file:auth0-myorganization-js-1.0.0-beta.4.tgz': dependencies: '@auth0/auth0-auth-js': 1.5.0 From 1333dcbc76e14314534ec2beb228cee1946c90b1 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Sun, 29 Mar 2026 23:21:56 +0530 Subject: [PATCH 004/125] chore: add myorganization-js beta 4 tarball --- auth0-myorganization-js-1.0.0-beta.4.tgz | Bin 0 -> 179690 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 auth0-myorganization-js-1.0.0-beta.4.tgz diff --git a/auth0-myorganization-js-1.0.0-beta.4.tgz b/auth0-myorganization-js-1.0.0-beta.4.tgz new file mode 100644 index 0000000000000000000000000000000000000000..b6675e14dc53667955b082e2dcbbd041093ed61d GIT binary patch literal 179690 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�ML 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 literal 0 HcmV?d00001 From 17553938c847615ed868747928b5504692ec6ca3 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Sun, 29 Mar 2026 23:22:39 +0530 Subject: [PATCH 005/125] feat(react, examples): add invitation hook, container, and example apps --- .../src/app/member-management/page.tsx | 21 + .../src/components/navigation/side-bar.tsx | 11 +- .../next-rwa/src/providers/i18n-provider.tsx | 1 + examples/react-spa-npm/src/App.tsx | 9 + .../react-spa-npm/src/components/side-bar.tsx | 11 +- .../src/views/member-management-page.tsx | 21 + examples/react-spa-shadcn/src/App.tsx | 9 + .../src/components/side-bar.tsx | 11 +- .../src/pages/MemberManagement.tsx | 23 + examples/scripts/utils/env-writer.mjs | 2 + examples/scripts/utils/resource-servers.mjs | 2 + .../organization-member-management.tsx | 213 +++++++++ packages/react/src/components/index.ts | 1 + packages/react/src/hooks/index.ts | 3 + .../src/hooks/my-organization/use-config.ts | 6 + .../use-organization-member-management.ts | 420 ++++++++++++++++++ 16 files changed, 761 insertions(+), 3 deletions(-) create mode 100644 examples/next-rwa/src/app/member-management/page.tsx create mode 100644 examples/react-spa-npm/src/views/member-management-page.tsx create mode 100644 examples/react-spa-shadcn/src/pages/MemberManagement.tsx create mode 100644 packages/react/src/components/auth0/my-organization/organization-member-management.tsx create mode 100644 packages/react/src/hooks/my-organization/use-organization-member-management.ts diff --git a/examples/next-rwa/src/app/member-management/page.tsx b/examples/next-rwa/src/app/member-management/page.tsx new file mode 100644 index 000000000..7dcc22ec3 --- /dev/null +++ b/examples/next-rwa/src/app/member-management/page.tsx @@ -0,0 +1,21 @@ +'use client'; + +// import { OrganizationMemberManagement } from '@auth0/universal-components-react/rwa'; + +export default function MemberManagementPage() { + return ( + + ); +} diff --git a/examples/next-rwa/src/components/navigation/side-bar.tsx b/examples/next-rwa/src/components/navigation/side-bar.tsx index e9a45a6f1..0eb2407d3 100644 --- a/examples/next-rwa/src/components/navigation/side-bar.tsx +++ b/examples/next-rwa/src/components/navigation/side-bar.tsx @@ -1,7 +1,7 @@ 'use client'; import { useUser } from '@auth0/nextjs-auth0'; -import { Building, Settings, Shield, User } from 'lucide-react'; +import { Building, Settings, Shield, User, Users } from 'lucide-react'; import Link from 'next/link'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -74,6 +74,15 @@ export const Sidebar: React.FC = () => { {t('sidebar.identity-providers')} +
  • + + + {t('sidebar.members')} + +
  • diff --git a/examples/next-rwa/src/providers/i18n-provider.tsx b/examples/next-rwa/src/providers/i18n-provider.tsx index 793c0e42d..5312cc407 100644 --- a/examples/next-rwa/src/providers/i18n-provider.tsx +++ b/examples/next-rwa/src/providers/i18n-provider.tsx @@ -26,6 +26,7 @@ i18n.use(initReactI18next).init({ 'sidebar.organization-settings': 'Organization Settings', 'sidebar.domains': 'Domains', 'sidebar.identity-providers': 'Identity Providers', + 'sidebar.members': 'Members', }, }, }, diff --git a/examples/react-spa-npm/src/App.tsx b/examples/react-spa-npm/src/App.tsx index 08ec086e1..9b443b784 100644 --- a/examples/react-spa-npm/src/App.tsx +++ b/examples/react-spa-npm/src/App.tsx @@ -8,6 +8,7 @@ import { Navbar } from './components/nav-bar'; import { Sidebar } from './components/side-bar'; import DomainManagementPage from './views/domain-management-page'; import HomePage from './views/home-page'; +import MemberManagementPage from './views/member-management-page'; import MFAPage from './views/mfa-page'; import OrganizationManagementPage from './views/organization-management-page'; import ProfilePage from './views/profile-page'; @@ -101,6 +102,14 @@ function AppContent() { } /> + + + + } + /> diff --git a/examples/react-spa-npm/src/components/side-bar.tsx b/examples/react-spa-npm/src/components/side-bar.tsx index 402398c19..58ab2150e 100644 --- a/examples/react-spa-npm/src/components/side-bar.tsx +++ b/examples/react-spa-npm/src/components/side-bar.tsx @@ -1,4 +1,4 @@ -import { User, Building, Settings, Shield } from 'lucide-react'; +import { User, Building, Settings, Shield, Users } from 'lucide-react'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; @@ -70,6 +70,15 @@ export const Sidebar: React.FC = () => { {t('sidebar.domain-management')} +
  • + + + {t('sidebar.member-management')} + +
  • diff --git a/examples/react-spa-npm/src/views/member-management-page.tsx b/examples/react-spa-npm/src/views/member-management-page.tsx new file mode 100644 index 000000000..e9667f79d --- /dev/null +++ b/examples/react-spa-npm/src/views/member-management-page.tsx @@ -0,0 +1,21 @@ +// import { OrganizationMemberManagement } from '@auth0/universal-components-react/spa'; + +const MemberManagementPage = () => { + return ( +
    +

    + Follow{' '} + + Quickstart guidance + {' '} + on how to add Member Management component. +

    + {/* */} +
    + ); +}; + +export default MemberManagementPage; diff --git a/examples/react-spa-shadcn/src/App.tsx b/examples/react-spa-shadcn/src/App.tsx index c39fdede8..f8f142aa2 100644 --- a/examples/react-spa-shadcn/src/App.tsx +++ b/examples/react-spa-shadcn/src/App.tsx @@ -10,6 +10,7 @@ import { Sidebar } from './components/side-bar'; import { config } from './config/env'; // import { useDarkMode } from './hooks/use-dark-mode'; import DomainManagement from './pages/DomainManagement'; +import MemberManagement from './pages/MemberManagement'; import IdentityProviderManagement from './pages/IdentityProviderManagement'; import IdentityProviderManagementCreate from './pages/IdentityProviderManagementCreate'; import IdentityProviderManagementEdit from './pages/IdentityProviderManagementEdit'; @@ -136,6 +137,14 @@ const App = () => { } /> + + + + } + /> {/* */} diff --git a/examples/react-spa-shadcn/src/components/side-bar.tsx b/examples/react-spa-shadcn/src/components/side-bar.tsx index e0bc08a9b..591c48d73 100644 --- a/examples/react-spa-shadcn/src/components/side-bar.tsx +++ b/examples/react-spa-shadcn/src/components/side-bar.tsx @@ -1,4 +1,4 @@ -import { User, Building, Shield, Settings } from 'lucide-react'; +import { User, Building, Shield, Settings, Users } from 'lucide-react'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; @@ -70,6 +70,15 @@ export const Sidebar: React.FC = () => { {t('sidebar.domain-management')} +
  • + + + {t('sidebar.member-management')} + +
  • diff --git a/examples/react-spa-shadcn/src/pages/MemberManagement.tsx b/examples/react-spa-shadcn/src/pages/MemberManagement.tsx new file mode 100644 index 000000000..bd89bdcc3 --- /dev/null +++ b/examples/react-spa-shadcn/src/pages/MemberManagement.tsx @@ -0,0 +1,23 @@ +// import { OrganizationMemberManagement } from '@auth0/universal-components-react/spa'; + +const MemberManagement = () => { + return ( +
    +

    + Follow{' '} + + Quickstart guidance + {' '} + on how to add Member Management component. +

    +
    + {/* */} +
    +
    + ); +}; + +export default MemberManagement; diff --git a/examples/scripts/utils/env-writer.mjs b/examples/scripts/utils/env-writer.mjs index 9b4d573fd..52eee8c88 100644 --- a/examples/scripts/utils/env-writer.mjs +++ b/examples/scripts/utils/env-writer.mjs @@ -72,6 +72,8 @@ const MYORG_SCOPES = [ "delete:my_org:domains", "create:my_org:domains", "update:my_org:domains", + "read:my_org:member_invitations", + "delete:my_org:member_invitations" ] // My Account API scopes diff --git a/examples/scripts/utils/resource-servers.mjs b/examples/scripts/utils/resource-servers.mjs index d7eeb6b91..95fe0c88d 100644 --- a/examples/scripts/utils/resource-servers.mjs +++ b/examples/scripts/utils/resource-servers.mjs @@ -26,6 +26,8 @@ export const MYORG_API_SCOPES = [ "read:my_org:identity_providers_provisioning", "delete:my_org:identity_providers_provisioning", "read:my_org:configuration", +"read:my_org:member_invitations", +"delete:my_org:member_invitations" ] // My Account API Scopes - desired scopes for MFA management diff --git a/packages/react/src/components/auth0/my-organization/organization-member-management.tsx b/packages/react/src/components/auth0/my-organization/organization-member-management.tsx new file mode 100644 index 000000000..88a7fd98e --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/organization-member-management.tsx @@ -0,0 +1,213 @@ +/** + * Organization member management component. + * @module organization-member-management + */ + +import { getComponentStyles } from '@auth0/universal-components-core'; +import { Plus } from 'lucide-react'; +import * as React from 'react'; + +import { GateKeeper } from '../shared/gate-keeper/gate-keeper'; + +import { OrganizationInvitationDetailsModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal'; +import { OrganizationInvitationRevokeModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal'; +import { OrganizationInvitationTable } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table'; +import { OrganizationInvitationCreateModal } from '@/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal'; +import { Header } from '@/components/auth0/shared/header'; +import { StyledScope } from '@/components/auth0/shared/styled-scope'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { useOrganizationMemberManagement } from '@/hooks/my-organization/use-organization-member-management'; +import { useTheme } from '@/hooks/shared/use-theme'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + MemberManagementState, + MemberManagementHandlers, + OrganizationMemberManagementProps, +} from '@/types/my-organization/member-management/organization-member-management-types'; + +/** + * Props for the OrganizationMemberManagementView component. + */ +export interface OrganizationMemberManagementViewProps { + state: MemberManagementState & { + styling: OrganizationMemberManagementProps['styling']; + customMessages: OrganizationMemberManagementProps['customMessages']; + hideHeader: boolean; + readOnly: boolean; + }; + handlers: MemberManagementHandlers; +} + +/** + * View component for organization member management. + * @param props - The component props. + * @returns The component. + */ +export function OrganizationMemberManagementView({ + state, + handlers, +}: OrganizationMemberManagementViewProps) { + const { isDarkMode } = useTheme(); + const { t } = useTranslator('member_management', state.customMessages as Record); + + const currentStyles = React.useMemo( + () => getComponentStyles(state.styling, isDarkMode), + [state.styling, isDarkMode], + ); + + return ( + +
    + {!state.hideHeader && ( +
    +
    +
    + )} + + + handlers.setActiveTab(value as 'members' | 'invitations') + } + className={currentStyles.classes?.['OrganizationMemberManagement-tabs']} + > + + {t('tabs.members')} + {t('tabs.invitations')} + + + + {/* */} + + + + + + + + + + invitation && handlers.handleRevokeClick(invitation)} + onResend={(invitation) => invitation && handlers.handleRevokeResendClick(invitation)} + className={currentStyles.classes?.['OrganizationInvitationTab-detailsModal']} + /> + + handlers.handleRevokeConfirm()} + className={currentStyles.classes?.['OrganizationInvitationTab-revokeModal']} + /> + + handlers.handleRevokeResendConfirm()} + className={currentStyles.classes?.['OrganizationInvitationTab-revokeResendModal']} + /> +
    +
    + ); +} + +/** + * Container component for organization member management. + * @param props - The component props. + * @returns The component. + */ +export function OrganizationMemberManagement(props: OrganizationMemberManagementProps) { + const { + hideHeader = false, + customMessages = {}, + styling = { variables: { common: {}, light: {}, dark: {} }, classes: {} }, + readOnly = false, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + } = props; + + const { state, handlers } = useOrganizationMemberManagement({ + customMessages, + readOnly, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + }); + + const extendedState = { + ...state, + styling, + customMessages, + hideHeader, + readOnly, + }; + + return ( + + + + ); +} diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index 9b0ccceee..e57cc966d 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -12,6 +12,7 @@ export { } from './auth0/my-organization/sso-provider-create'; export { SsoProviderTable, SsoProviderTableView } from './auth0/my-organization/sso-provider-table'; export { DomainTable, DomainTableView } from './auth0/my-organization/domain-table'; +export { OrganizationMemberManagement } from './auth0/my-organization/organization-member-management'; export { OrganizationDetailsEdit, OrganizationDetailsEditView, diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index 646b4e008..f32bcfe11 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -28,3 +28,6 @@ export { useSsoDomainTab } from './my-organization/use-sso-domain-tab'; export { useSsoProviderCreate } from './my-organization/use-sso-provider-create'; export { useSsoProviderEdit } from './my-organization/use-sso-provider-edit'; export { useSsoProviderTable } from './my-organization/use-sso-provider-table'; + +// Member Management hooks +export { useOrganizationMemberManagement } from './my-organization/use-organization-member-management'; diff --git a/packages/react/src/hooks/my-organization/use-config.ts b/packages/react/src/hooks/my-organization/use-config.ts index f3db4455f..bf0488256 100644 --- a/packages/react/src/hooks/my-organization/use-config.ts +++ b/packages/react/src/hooks/my-organization/use-config.ts @@ -51,6 +51,11 @@ export function useConfig(): UseConfigResult { const isConfigValid = !!allowedStrategies?.length; + const allowedRoles = + ((config as Record)?.allowed_roles as + | Array<{ id: string; name: string; description?: string }> + | undefined) ?? []; + return { config: config ?? null, isLoadingConfig: configQuery.isLoading, @@ -58,5 +63,6 @@ export function useConfig(): UseConfigResult { filteredStrategies, shouldAllowDeletion, isConfigValid, + allowedRoles, }; } diff --git a/packages/react/src/hooks/my-organization/use-organization-member-management.ts b/packages/react/src/hooks/my-organization/use-organization-member-management.ts new file mode 100644 index 000000000..cc846b7c4 --- /dev/null +++ b/packages/react/src/hooks/my-organization/use-organization-member-management.ts @@ -0,0 +1,420 @@ +/** + * Organization member management hook. + * @module use-organization-member-management + */ + +import { + type MemberInvitation, + type ListIdentityProvidersResponseContent, +} from '@auth0/universal-components-core'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import * as React from 'react'; + +import { showToast } from '@/components/auth0/shared/toast'; +import { useConfig } from '@/hooks/my-organization/use-config'; +import { useCoreClient } from '@/hooks/shared/use-core-client'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + CreateInvitationInput, + InvitationSortConfig, + InvitationFilterState, + RoleOption, + IdentityProviderOption, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; +import type { + ActiveTab, + MemberManagementState, + MemberManagementHandlers, + UseOrganizationMemberManagementOptions, +} from '@/types/my-organization/member-management/organization-member-management-types'; + +const DEFAULT_PAGE_SIZE = 10; + +export const memberManagementQueryKeys = { + all: ['member-management'] as const, + invitations: () => [...memberManagementQueryKeys.all, 'invitations'] as const, +}; + +/** + * Maps invitation table column accessor keys to the API's sort field names. + */ +const INVITATION_SORT_FIELD_MAP: Record = { + created_at: 'created_at', +}; + +/** + * Hook for organization member management. + * @param options - Hook configuration options. + * @returns State and handler functions. + */ +export function useOrganizationMemberManagement(options: UseOrganizationMemberManagementOptions): { + state: MemberManagementState; + handlers: MemberManagementHandlers; +} { + const { + customMessages = {}, + readOnly = false, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + } = options; + const { coreClient } = useCoreClient(); + const { t } = useTranslator('member_management', customMessages as Record); + const queryClient = useQueryClient(); + + const [activeTab, setActiveTab] = React.useState('members'); + + const { allowedRoles } = useConfig(); + const availableRoles: RoleOption[] = allowedRoles; + + const providersQuery = useQuery({ + queryKey: [...memberManagementQueryKeys.all, 'identity-providers'], + queryFn: async () => { + const response: ListIdentityProvidersResponseContent = await coreClient! + .getMyOrganizationApiClient() + .organization.identityProviders.list(); + const providers = response.identity_providers ?? []; + return providers.map((p) => ({ + id: p.id!, + name: p.display_name ?? p.name ?? '', + type: p.strategy, + })); + }, + enabled: !!coreClient && activeTab === 'invitations', + }); + + const availableProviders: IdentityProviderOption[] = providersQuery.data ?? []; + + const [invitationPageSize, setInvitationPageSize] = React.useState(DEFAULT_PAGE_SIZE); + const [currentFromToken, setCurrentFromToken] = React.useState(undefined); + const [previousTokens, setPreviousTokens] = React.useState>([]); + const [invitationCurrentPage, setInvitationCurrentPage] = React.useState(1); + const [invitationFilters, setInvitationFilters] = React.useState({}); + const [invitationSortConfig, setInvitationSortConfig] = React.useState({ + key: null, + direction: 'asc', + }); + const [showCreateModal, setShowCreateModal] = React.useState(false); + const [showDetailsModal, setShowDetailsModal] = React.useState(false); + const [selectedInvitation, setSelectedInvitation] = React.useState(null); + const detailsRequestIdRef = React.useRef(0); + + const invitationsQuery = useQuery({ + queryKey: [ + ...memberManagementQueryKeys.invitations(), + invitationPageSize, + currentFromToken, + invitationFilters, + invitationSortConfig, + ], + queryFn: async () => { + const apiSortField = invitationSortConfig.key + ? INVITATION_SORT_FIELD_MAP[invitationSortConfig.key] + : undefined; + const sortBy = apiSortField + ? `${apiSortField}:${invitationSortConfig.direction === 'asc' ? '1' : '-1'}` + : undefined; + + const page = await coreClient!.getMyOrganizationApiClient().organization.invitations.list({ + take: invitationPageSize, + from: currentFromToken, + sort: sortBy, + }); + + const invitations: MemberInvitation[] = page.data; + const next = page.response.next ?? null; + const total = (page.response as Record).total as number | undefined; + + return { + invitations, + next, + total, + }; + }, + enabled: !!coreClient && activeTab === 'invitations', + }); + + const currentInvitations = invitationsQuery.data?.invitations ?? []; + const nextToken = invitationsQuery.data?.next ?? null; + const invitationsTotalItems = invitationsQuery.data?.total; + + const createInvitationMutation = useMutation({ + mutationFn: async (data: CreateInvitationInput) => { + if (createInvitationAction?.onBefore && !createInvitationAction.onBefore(data)) { + throw new Error('Create action cancelled by onBefore'); + } + const response = await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.create({ + invitees: [{ email: data.invitee.email, roles: data.roles }], + inviter: data.inviter, + ttl_sec: data.ttl_sec, + }); + return Array.isArray(response) ? response[0] : response; + }, + onSuccess: (result, data) => { + createInvitationAction?.onAfter?.(data, result); + showToast({ type: 'success', message: t('invitation.create.success') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + onError: () => { + showToast({ type: 'error', message: t('invitation.error.create_failed') }); + }, + }); + + const revokeInvitationMutation = useMutation({ + mutationFn: async (invitation: MemberInvitation) => { + if (revokeInvitationAction?.onBefore && !revokeInvitationAction.onBefore(invitation)) { + throw new Error('Revoke action cancelled by onBefore'); + } + await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.delete(invitation.id!); + return invitation; + }, + onSuccess: (invitation) => { + revokeInvitationAction?.onAfter?.(invitation); + showToast({ type: 'success', message: t('invitation.revoke.success') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + onError: () => { + showToast({ type: 'error', message: t('invitation.error.revoke_failed') }); + }, + }); + + const resendInvitationMutation = useMutation({ + mutationFn: async (invitation: MemberInvitation) => { + if (resendInvitationAction?.onBefore && !resendInvitationAction.onBefore(invitation)) { + throw new Error('Resend action cancelled by onBefore'); + } + const freshInvitation = await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.get(invitation.id!); + await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.delete(freshInvitation.id ?? invitation.id!); + const email = freshInvitation.invitee?.email ?? invitation.invitee?.email ?? ''; + const roles = freshInvitation.roles ?? invitation.roles; + const response = await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.create({ + invitees: [{ email, roles }], + }); + return Array.isArray(response) ? response[0] : response; + }, + onSuccess: (result, invitation) => { + resendInvitationAction?.onAfter?.(invitation, result); + showToast({ type: 'success', message: t('invitation.success.invitation_resent') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + onError: () => { + showToast({ type: 'error', message: t('invitation.error.resend_failed') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + }); + + const handleCreateClick = React.useCallback(() => { + if (readOnly) return; + setShowCreateModal(true); + }, [readOnly]); + + const handleCreateSubmit = React.useCallback( + (data: CreateInvitationInput) => { + if (!coreClient) return; + createInvitationMutation.mutate(data, { + onSuccess: () => setShowCreateModal(false), + }); + }, + [coreClient], + ); + + const handleCreateCancel = React.useCallback(() => { + setShowCreateModal(false); + }, []); + + const handleDetailsClick = React.useCallback( + async (invitation: MemberInvitation) => { + setSelectedInvitation(invitation); + setShowDetailsModal(true); + if (!coreClient) return; + const requestId = ++detailsRequestIdRef.current; + try { + const response = await coreClient + .getMyOrganizationApiClient() + .organization.invitations.get(invitation.id!); + if (detailsRequestIdRef.current === requestId) { + setSelectedInvitation(response); + } + } catch { + if (detailsRequestIdRef.current === requestId) { + showToast({ type: 'error', message: t('invitation.error.fetch_failed') }); + } + } + }, + [coreClient, t], + ); + + const handleDetailsClose = React.useCallback(() => { + setShowDetailsModal(false); + setSelectedInvitation(null); + }, []); + + const [showRevokeModal, setShowRevokeModal] = React.useState(false); + const [showRevokeResendModal, setShowRevokeResendModal] = React.useState(false); + + const handleRevokeClick = React.useCallback( + (invitation: MemberInvitation) => { + if (readOnly) return; + if (showDetailsModal) { + setShowDetailsModal(false); + } + setSelectedInvitation(invitation); + setShowRevokeModal(true); + }, + [readOnly, showDetailsModal], + ); + + const handleRevokeConfirm = React.useCallback(() => { + if (!selectedInvitation || !coreClient) return; + revokeInvitationMutation.mutate(selectedInvitation, { + onSuccess: () => { + setShowRevokeModal(false); + setSelectedInvitation(null); + }, + }); + }, [selectedInvitation, coreClient]); + + const handleRevokeCancel = React.useCallback(() => { + setShowRevokeModal(false); + }, []); + + const handleRevokeResendClick = React.useCallback( + (invitation: MemberInvitation) => { + if (readOnly) return; + if (showDetailsModal) { + setShowDetailsModal(false); + } + setSelectedInvitation(invitation); + setShowRevokeResendModal(true); + }, + [readOnly, showDetailsModal], + ); + + const handleRevokeResendConfirm = React.useCallback(() => { + if (!selectedInvitation || !coreClient) return; + resendInvitationMutation.mutate(selectedInvitation, { + onSuccess: () => { + setShowRevokeResendModal(false); + setSelectedInvitation(null); + }, + }); + }, [selectedInvitation, coreClient]); + + const handleRevokeResendCancel = React.useCallback(() => { + setShowRevokeResendModal(false); + }, []); + + const handleCopyUrl = React.useCallback( + async (invitation: MemberInvitation) => { + if (!invitation.invitation_url) return; + try { + await navigator.clipboard.writeText(invitation.invitation_url); + showToast({ type: 'success', message: t('invitation.success.url_copied') }); + } catch { + showToast({ type: 'error', message: t('invitation.error.copy_url_failed') }); + } + }, + [t], + ); + + const handleNextPage = React.useCallback(() => { + if (nextToken) { + setPreviousTokens((prev) => [...prev, currentFromToken]); + setCurrentFromToken(nextToken); + setInvitationCurrentPage((prev) => prev + 1); + } + }, [nextToken, currentFromToken]); + + const handlePreviousPage = React.useCallback(() => { + const previousToken = previousTokens[previousTokens.length - 1]; + setPreviousTokens((prev) => prev.slice(0, -1)); + setCurrentFromToken(previousToken); + setInvitationCurrentPage((prev) => Math.max(1, prev - 1)); + }, [previousTokens]); + + const handlePageSizeChange = React.useCallback((pageSize: number) => { + setInvitationPageSize(pageSize); + setCurrentFromToken(undefined); + setPreviousTokens([]); + setInvitationCurrentPage(1); + }, []); + + const handleRoleFilterChange = React.useCallback((roleId: string | undefined) => { + setInvitationFilters((prev) => ({ ...prev, roleId })); + setCurrentFromToken(undefined); + setPreviousTokens([]); + setInvitationCurrentPage(1); + }, []); + + const handleSortChange = React.useCallback((sortConfig: InvitationSortConfig) => { + setInvitationSortConfig(sortConfig); + setCurrentFromToken(undefined); + setPreviousTokens([]); + setInvitationCurrentPage(1); + }, []); + + const state: MemberManagementState = { + activeTab, + isLoading: invitationsQuery.isLoading || invitationsQuery.isFetching, + availableRoles, + availableProviders, + + invitations: currentInvitations, + isFetchingInvitations: invitationsQuery.isLoading || invitationsQuery.isFetching, + isCreatingInvitation: createInvitationMutation.isPending, + isRevokingInvitation: revokeInvitationMutation.isPending, + isResendingInvitation: resendInvitationMutation.isPending, + invitationPagination: { + pageSize: invitationPageSize, + currentPage: invitationCurrentPage, + totalItems: invitationsTotalItems, + hasNextPage: !!nextToken, + hasPreviousPage: previousTokens.length > 0, + }, + invitationFilters, + invitationSortConfig, + showCreateModal, + showDetailsModal, + showRevokeModal, + showRevokeResendModal, + selectedInvitation, + }; + + const handlers: MemberManagementHandlers = { + setActiveTab, + + handleCreateClick, + handleCreateSubmit, + handleCreateCancel, + handleDetailsClick, + handleDetailsClose, + handleRevokeClick, + handleRevokeConfirm, + handleRevokeCancel, + handleRevokeResendClick, + handleRevokeResendConfirm, + handleRevokeResendCancel, + handleCopyUrl, + handleNextPage, + handlePreviousPage, + handlePageSizeChange, + handleSortChange, + handleRoleFilterChange, + }; + + return { state, handlers }; +} + +export type UseOrganizationMemberManagementResult = ReturnType< + typeof useOrganizationMemberManagement +>; From 3a5757fe8e9984c53b1ba5d4c2b478d676d1039e Mon Sep 17 00:00:00 2001 From: rax7389 Date: Sun, 29 Mar 2026 23:23:16 +0530 Subject: [PATCH 006/125] test(react): add tests and mocks for invitation components --- .../__tests__/sso-provider-tab.test.tsx | 1 + .../sso-provider-table-action.test.tsx | 1 + ...nization-invitation-details-modal.test.tsx | 386 ++++++++++++++++++ ...anization-invitation-revoke-modal.test.tsx | 246 +++++++++++ ...n-invitation-table-actions-column.test.tsx | 321 +++++++++++++++ ...anization-invitation-create-modal.test.tsx | 218 ++++++++++ .../__tests__/search-filter.test.tsx | 107 +++++ .../__tests__/use-sso-provider-create.test.ts | 1 + .../__tests__/use-sso-provider-edit.test.ts | 1 + .../__tests__/use-sso-provider-table.test.ts | 1 + .../my-organization/config/config.mocks.ts | 1 + .../my-organization/config/config.mocks.ts | 1 + .../member-management/invitation.mocks.ts | 108 +++++ 13 files changed, 1393 insertions(+) create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx create mode 100644 packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts diff --git a/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-edit/__tests__/sso-provider-tab.test.tsx b/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-edit/__tests__/sso-provider-tab.test.tsx index 44d237165..1c70a2cf0 100644 --- a/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-edit/__tests__/sso-provider-tab.test.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-edit/__tests__/sso-provider-tab.test.tsx @@ -31,6 +31,7 @@ describe('SsoProviderTab', () => { display_name: 'Test Provider Display', options: {}, strategy: 'oidc', // Use a valid strategy property + attributes: [], // Required by IdpOidcResponse }, onDelete: vi.fn(), onRemove: vi.fn(), diff --git a/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-table/__tests__/sso-provider-table-action.test.tsx b/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-table/__tests__/sso-provider-table-action.test.tsx index ff7eaaaef..bded3583b 100644 --- a/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-table/__tests__/sso-provider-table-action.test.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/idp-management/sso-provider-table/__tests__/sso-provider-table-action.test.tsx @@ -22,6 +22,7 @@ function createMockProvider(overrides = {}) { strategy: 'oidc' as const, is_enabled: true, options: {}, + attributes: [], ...overrides, }; } diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx new file mode 100644 index 000000000..266f128cc --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx @@ -0,0 +1,386 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { OrganizationInvitationDetailsModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockDetailsModalProps, + createMockInvitation, + createMockPendingInvitation, + createMockExpiredInvitation, + createMockRoles, + createMockProviders, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationDetailsModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + describe('when is true', () => { + it('should render the modal', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: 'invitation.details.title' }), + ).toBeInTheDocument(); + }); + }); + + describe('when is false', () => { + it('should not render the modal content', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + }); + + describe('invitation', () => { + describe('when invitation is provided', () => { + it('should display the invitee email', () => { + const invitation = createMockInvitation({ invitee: { email: 'user@example.com' } }); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('user@example.com')).toBeInTheDocument(); + }); + + it('should display the inviter name', () => { + const invitation = createMockInvitation({ inviter: { name: 'John Doe' } }); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('John Doe')).toBeInTheDocument(); + }); + + it('should display created_at date', () => { + const invitation = createMockInvitation({ + created_at: '2024-06-15T10:00:00.000Z', + }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.created_at_label')).toBeInTheDocument(); + }); + + it('should display expires_at date', () => { + const invitation = createMockInvitation({ + expires_at: '2025-06-15T10:00:00.000Z', + }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.expires_at_label')).toBeInTheDocument(); + }); + }); + + describe('when invitation is null', () => { + it('should handle null invitation gracefully', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + }); + + describe('status badge', () => { + it('should display pending status for pending invitations', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.table.status_pending')).toBeInTheDocument(); + }); + + it('should display expired status for expired invitations', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.table.status_expired')).toBeInTheDocument(); + }); + }); + + describe('roles', () => { + it('should resolve role IDs to names when availableRoles provided', () => { + const invitation = createMockInvitation({ roles: ['role_admin', 'role_member'] }); + const availableRoles = createMockRoles(); + + renderWithProviders( + , + ); + + expect(screen.getByText('Admin')).toBeInTheDocument(); + expect(screen.getByText('Member')).toBeInTheDocument(); + }); + + it('should show role ID as fallback when role not found in availableRoles', () => { + const invitation = createMockInvitation({ roles: ['role_unknown'] }); + + renderWithProviders( + , + ); + + expect(screen.getByText('role_unknown')).toBeInTheDocument(); + }); + + it('should show dash when no roles assigned', () => { + const invitation = createMockInvitation({ roles: [] }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.roles_label')).toBeInTheDocument(); + }); + }); + + describe('invitation URL', () => { + it('should display invitation URL when available', () => { + const invitation = createMockInvitation({ + invitation_url: 'https://example.auth0.com/invite?ticket=abc', + }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.invitation_url_label')).toBeInTheDocument(); + }); + + it('should not display invitation URL section when no URL', () => { + const invitation = createMockInvitation({ invitation_url: undefined }); + + renderWithProviders( + , + ); + + expect(screen.queryByText('invitation.details.invitation_url_label')).not.toBeInTheDocument(); + }); + }); + + describe('identity provider', () => { + it('should display provider name when resolved', () => { + const invitation = createMockInvitation({ identity_provider_id: 'con_provider1' }); + const availableProviders = createMockProviders(); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('Google')).toBeInTheDocument(); + }); + + it('should show provider ID as fallback when provider not found', () => { + const invitation = createMockInvitation({ identity_provider_id: 'con_unknown' }); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('con_unknown')).toBeInTheDocument(); + }); + + it('should not display provider section when no provider assigned', () => { + const invitation = createMockInvitation({ identity_provider_id: undefined }); + + renderWithProviders( + , + ); + + expect(screen.queryByText('invitation.details.provider_label')).not.toBeInTheDocument(); + }); + }); + + describe('readOnly', () => { + describe('when readOnly is false', () => { + it('should show Revoke and Resend buttons', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'invitation.details.revoke_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'invitation.details.resend_button' }), + ).toBeInTheDocument(); + }); + }); + + describe('when readOnly is true', () => { + it('should not show Revoke and Resend buttons', () => { + renderWithProviders( + , + ); + + expect( + screen.queryByRole('button', { name: 'invitation.details.revoke_button' }), + ).not.toBeInTheDocument(); + expect( + screen.queryByRole('button', { name: 'invitation.details.resend_button' }), + ).not.toBeInTheDocument(); + }); + }); + }); + + describe('action callbacks', () => { + it('should call onRevoke when Revoke button is clicked', async () => { + const user = userEvent.setup(); + const onRevoke = vi.fn(); + const invitation = createMockPendingInvitation(); + + renderWithProviders( + , + ); + + const revokeButton = screen.getByRole('button', { + name: 'invitation.details.revoke_button', + }); + await user.click(revokeButton); + + expect(onRevoke).toHaveBeenCalledTimes(1); + expect(onRevoke).toHaveBeenCalledWith(invitation); + }); + + it('should call onResend when Resend button is clicked', async () => { + const user = userEvent.setup(); + const onResend = vi.fn(); + const invitation = createMockPendingInvitation(); + + renderWithProviders( + , + ); + + const resendButton = screen.getByRole('button', { + name: 'invitation.details.resend_button', + }); + await user.click(resendButton); + + expect(onResend).toHaveBeenCalledTimes(1); + expect(onResend).toHaveBeenCalledWith(invitation); + }); + + it('should call onClose when Close button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + const closeButton = screen.getByRole('button', { + name: 'invitation.details.close_button', + }); + await user.click(closeButton); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); + + describe('action in progress', () => { + it('should disable Revoke button when isRevoking is true', () => { + renderWithProviders( + , + ); + + const revokeButton = screen.getByRole('button', { + name: 'invitation.details.revoke_button', + }); + expect(revokeButton).toBeDisabled(); + }); + + it('should disable Resend button when isResending is true', () => { + renderWithProviders( + , + ); + + const resendButton = screen.getByRole('button', { + name: 'invitation.details.resend_button', + }); + expect(resendButton).toBeDisabled(); + }); + + it('should disable both buttons when either action is in progress', () => { + renderWithProviders( + , + ); + + const revokeButton = screen.getByRole('button', { + name: 'invitation.details.revoke_button', + }); + const resendButton = screen.getByRole('button', { + name: 'invitation.details.resend_button', + }); + expect(revokeButton).toBeDisabled(); + expect(resendButton).toBeDisabled(); + }); + }); + + describe('className', () => { + it('should apply custom class to modal', () => { + const customClass = 'custom-details-class'; + + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass(customClass); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx new file mode 100644 index 000000000..595076fa3 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx @@ -0,0 +1,246 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { OrganizationInvitationRevokeModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockRevokeModalProps, + createMockPendingInvitation, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationRevokeModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + describe('when is true', () => { + it('should render the modal', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + + describe('when is false', () => { + it('should not render the modal content', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + }); + + describe('revoke mode', () => { + describe('when isRevokeAndResend is false', () => { + it('should render revoke-specific title', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke.title')).toBeInTheDocument(); + }); + + it('should render revoke-specific description', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke.description')).toBeInTheDocument(); + }); + + it('should render revoke-specific button text', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'invitation.revoke.confirm_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'invitation.revoke.cancel_button' }), + ).toBeInTheDocument(); + }); + }); + + describe('when isRevokeAndResend is true', () => { + it('should render revoke-and-resend title', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke_resend.title')).toBeInTheDocument(); + }); + + it('should render revoke-and-resend description', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke_resend.description')).toBeInTheDocument(); + }); + + it('should render revoke-and-resend button text', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'invitation.revoke_resend.confirm_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'invitation.revoke_resend.cancel_button' }), + ).toBeInTheDocument(); + }); + }); + }); + + describe('isLoading', () => { + describe('when is true', () => { + it('should disable confirm button', () => { + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + expect(confirmButton).toBeDisabled(); + }); + + it('should disable cancel button', () => { + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.revoke.cancel_button', + }); + expect(cancelButton).toBeDisabled(); + }); + }); + + describe('when is false', () => { + it('should enable confirm button', () => { + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + expect(confirmButton).toBeEnabled(); + }); + }); + }); + + describe('onConfirm', () => { + it('should call onConfirm with invitation when confirm button is clicked', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + const invitation = createMockPendingInvitation(); + + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + await user.click(confirmButton); + + expect(onConfirm).toHaveBeenCalledTimes(1); + expect(onConfirm).toHaveBeenCalledWith(invitation); + }); + + it('should not call onConfirm when invitation is null', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + await user.click(confirmButton); + + expect(onConfirm).not.toHaveBeenCalled(); + }); + }); + + describe('onClose', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.revoke.cancel_button', + }); + await user.click(cancelButton); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); + + describe('className', () => { + it('should apply custom class to modal', () => { + const customClass = 'custom-revoke-class'; + + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass(customClass); + }); + }); + + describe('invitation', () => { + describe('when invitation is null', () => { + it('should handle null invitation gracefully', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx new file mode 100644 index 000000000..ee819768e --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx @@ -0,0 +1,321 @@ +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { OrganizationInvitationTableActionsColumn } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockActionsColumnProps, + createMockPendingInvitation, + createMockExpiredInvitation, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationTableActionsColumn', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe('Rendering and Basic Structure', () => { + it('should render dropdown trigger button', () => { + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + expect(trigger).toBeInTheDocument(); + expect(trigger).toHaveClass('h-8', 'w-8'); + }); + + it('should have proper accessibility attributes', () => { + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + expect(trigger).toHaveAttribute('type', 'button'); + }); + }); + + describe('Dropdown Menu Interactions', () => { + it('should open dropdown menu when trigger button is clicked', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + + it('should close dropdown menu when user presses Escape key', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + + await user.keyboard('{Escape}'); + + await waitFor(() => { + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).not.toBeInTheDocument(); + }); + }); + }); + + describe('Invitation Status: Pending', () => { + it('should show View Details action', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockPendingInvitation(), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + + it('should show Copy URL action when invitation has URL', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockPendingInvitation({ + invitation_url: 'https://example.com/invite?ticket=abc', + }), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.copy_url' }), + ).toBeInTheDocument(); + }); + + it('should not show Copy URL action when invitation has no URL', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockPendingInvitation({ invitation_url: undefined }), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.copy_url' }), + ).not.toBeInTheDocument(); + }); + + it('should show Revoke & Resend action when not readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: false }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.revoke_and_resend' }), + ).toBeInTheDocument(); + }); + + it('should show Revoke action when not readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: false }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.revoke' }), + ).toBeInTheDocument(); + }); + }); + + describe('Invitation Status: Expired', () => { + it('should show View Details action', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockExpiredInvitation(), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + + it('should not show Copy URL action for expired invitations', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockExpiredInvitation(), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.copy_url' }), + ).not.toBeInTheDocument(); + }); + }); + + describe('Read-Only Mode', () => { + it('should not show Revoke & Resend action when readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: true }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.revoke_and_resend' }), + ).not.toBeInTheDocument(); + }); + + it('should not show Revoke action when readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: true }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.revoke' }), + ).not.toBeInTheDocument(); + }); + + it('should still show View Details when readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: true }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + }); + + describe('Callback Invocations', () => { + it('should call onViewDetails when View Details is clicked', async () => { + const user = userEvent.setup(); + const onViewDetails = vi.fn(); + const invitation = createMockPendingInvitation(); + const props = createMockActionsColumnProps({ invitation, onViewDetails }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.view_details', + }); + await user.click(menuItem); + + expect(onViewDetails).toHaveBeenCalledTimes(1); + expect(onViewDetails).toHaveBeenCalledWith(invitation); + }); + + it('should call onCopyUrl when Copy URL is clicked', async () => { + const user = userEvent.setup(); + const onCopyUrl = vi.fn(); + const invitation = createMockPendingInvitation({ + invitation_url: 'https://example.com/invite', + }); + const props = createMockActionsColumnProps({ invitation, onCopyUrl }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.copy_url', + }); + await user.click(menuItem); + + expect(onCopyUrl).toHaveBeenCalledTimes(1); + expect(onCopyUrl).toHaveBeenCalledWith(invitation); + }); + + it('should call onRevokeAndResend when Revoke & Resend is clicked', async () => { + const user = userEvent.setup(); + const onRevokeAndResend = vi.fn(); + const invitation = createMockPendingInvitation(); + const props = createMockActionsColumnProps({ invitation, onRevokeAndResend }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.revoke_and_resend', + }); + await user.click(menuItem); + + expect(onRevokeAndResend).toHaveBeenCalledTimes(1); + expect(onRevokeAndResend).toHaveBeenCalledWith(invitation); + }); + + it('should call onRevoke when Revoke is clicked', async () => { + const user = userEvent.setup(); + const onRevoke = vi.fn(); + const invitation = createMockPendingInvitation(); + const props = createMockActionsColumnProps({ invitation, onRevoke }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.revoke', + }); + await user.click(menuItem); + + expect(onRevoke).toHaveBeenCalledTimes(1); + expect(onRevoke).toHaveBeenCalledWith(invitation); + }); + }); + + describe('Custom Messages', () => { + it('should accept custom messages prop without error', async () => { + const user = userEvent.setup(); + const customMessages = { + actions: { + view_details: 'Custom View Details', + }, + }; + const props = createMockActionsColumnProps({ customMessages }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + // The mock translator returns keys, so verify the menu item renders + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx new file mode 100644 index 000000000..d35fcca86 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx @@ -0,0 +1,218 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { OrganizationInvitationCreateModal } from '@/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockCreateModalProps, + createMockRoles, + createMockProviders, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationCreateModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + describe('when is true', () => { + it('should render the modal', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect(screen.getByText('invitation.create.title')).toBeInTheDocument(); + }); + }); + + describe('when is false', () => { + it('should not render the modal content', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + }); + + describe('isLoading', () => { + describe('when is true', () => { + it('should disable form inputs', () => { + renderWithProviders( + , + ); + + const emailInput = screen.getByPlaceholderText('invitation.create.email_placeholder'); + expect(emailInput).toBeDisabled(); + }); + + it('should disable cancel and submit buttons', () => { + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.create.cancel_button', + }); + expect(cancelButton).toBeDisabled(); + }); + }); + + describe('when is false', () => { + it('should enable form inputs', () => { + renderWithProviders( + , + ); + + const emailInput = screen.getByPlaceholderText('invitation.create.email_placeholder'); + expect(emailInput).toBeEnabled(); + }); + }); + }); + + describe('className', () => { + describe('when className is provided', () => { + it('should apply custom class to modal', () => { + const customClass = 'custom-modal-class'; + + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass(customClass); + }); + }); + }); + + describe('onClose', () => { + describe('when modal is closed', () => { + it('should call onClose callback via cancel button', async () => { + const user = userEvent.setup(); + const mockOnClose = vi.fn(); + + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.create.cancel_button', + }); + await user.click(cancelButton); + + expect(mockOnClose).toHaveBeenCalledTimes(1); + }); + }); + }); + + describe('email input', () => { + it('should render email input field', () => { + renderWithProviders(); + + expect( + screen.getByPlaceholderText('invitation.create.email_placeholder'), + ).toBeInTheDocument(); + expect(screen.getByText(/invitation\.create\.email_label/)).toBeInTheDocument(); + }); + + it('should show helper text by default', () => { + renderWithProviders(); + + expect(screen.getByText('invitation.create.email_helper')).toBeInTheDocument(); + }); + }); + + describe('submit', () => { + it('should disable submit button when no emails are added', () => { + renderWithProviders(); + + const submitButton = screen.getByRole('button', { + name: 'invitation.create.submit_button', + }); + expect(submitButton).toBeDisabled(); + }); + + it('should show creating text when isLoading is true', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.creating')).toBeInTheDocument(); + }); + }); + + describe('availableRoles', () => { + describe('when roles are provided', () => { + it('should render roles combobox', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.roles_label')).toBeInTheDocument(); + }); + }); + + describe('when no roles are provided', () => { + it('should still render roles section', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.roles_label')).toBeInTheDocument(); + }); + }); + }); + + describe('availableProviders', () => { + describe('when providers are provided', () => { + it('should render provider dropdown', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.provider_label')).toBeInTheDocument(); + }); + }); + + describe('when no providers are provided', () => { + it('should still render provider section', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.provider_label')).toBeInTheDocument(); + }); + }); + }); + + describe('description', () => { + it('should render description text', () => { + renderWithProviders(); + + expect(screen.getByText('invitation.create.description')).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx new file mode 100644 index 000000000..ab63f1a42 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx @@ -0,0 +1,107 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { InvitationSearchFilter } from '@/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter'; +import { renderWithProviders } from '@/tests/utils'; +import { createMockSearchFilterProps } from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('InvitationSearchFilter', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('rendering', () => { + it('should render the filter when roles are provided', () => { + renderWithProviders(); + + expect(screen.getByText(/invitation\.table\.filter_by_role/)).toBeInTheDocument(); + }); + + it('should return null when no roles are provided', () => { + const { container } = renderWithProviders( + , + ); + + expect(container.innerHTML).toBe(''); + }); + + it('should render reset button', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { name: 'invitation.table.reset_filter' }), + ).toBeInTheDocument(); + }); + }); + + describe('reset button', () => { + it('should be disabled when no active filter', () => { + renderWithProviders( + , + ); + + const resetButton = screen.getByRole('button', { + name: 'invitation.table.reset_filter', + }); + expect(resetButton).toBeDisabled(); + }); + + it('should be enabled when there is an active filter', () => { + renderWithProviders( + , + ); + + const resetButton = screen.getByRole('button', { + name: 'invitation.table.reset_filter', + }); + expect(resetButton).toBeEnabled(); + }); + + it('should call onRoleFilterChange with undefined when reset is clicked', async () => { + const user = userEvent.setup(); + const onRoleFilterChange = vi.fn(); + + renderWithProviders( + , + ); + + const resetButton = screen.getByRole('button', { + name: 'invitation.table.reset_filter', + }); + await user.click(resetButton); + + expect(onRoleFilterChange).toHaveBeenCalledTimes(1); + expect(onRoleFilterChange).toHaveBeenCalledWith(undefined); + }); + }); + + describe('className', () => { + it('should apply custom class when provided', () => { + const customClass = 'custom-filter-class'; + + const { container } = renderWithProviders( + , + ); + + const filterDiv = container.firstChild as HTMLElement; + expect(filterDiv).toHaveClass(customClass); + }); + + it('should apply default class when no custom class provided', () => { + const { container } = renderWithProviders( + , + ); + + const filterDiv = container.firstChild as HTMLElement; + expect(filterDiv).toHaveClass('mb-4'); + }); + }); +}); diff --git a/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-create.test.ts b/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-create.test.ts index f85fcf5e4..5444dd821 100644 --- a/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-create.test.ts +++ b/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-create.test.ts @@ -27,6 +27,7 @@ describe('useSsoProviderCreate', () => { strategy: 'samlp', display_name: 'Test Provider', options: {}, + attributes: [], }; const mockT = vi.fn((key: string, params?: Record) => { diff --git a/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-edit.test.ts b/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-edit.test.ts index 580468cc8..974d7771c 100644 --- a/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-edit.test.ts +++ b/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-edit.test.ts @@ -88,6 +88,7 @@ describe('useSsoProviderEdit', () => { strategy: 'samlp', display_name: 'Test Provider', options: {}, + attributes: [], }; const mockOrganization: OrganizationPrivate = { diff --git a/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-table.test.ts b/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-table.test.ts index 54fc0fe89..9fc5bc810 100644 --- a/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-table.test.ts +++ b/packages/react/src/hooks/my-organization/__tests__/use-sso-provider-table.test.ts @@ -31,6 +31,7 @@ const mockIdentityProviders: IdentityProvider[] = [ strategy: 'okta', is_enabled: true, options: {}, + attributes: [], }, { id: 'idp-2', diff --git a/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts b/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts index dd682ce97..2b0f13b39 100644 --- a/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts +++ b/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts @@ -20,5 +20,6 @@ export const createMockUseConfig = (overrides?: Partial): MockUse }, fetchConfig: vi.fn(async () => undefined), filteredStrategies: [], + allowedRoles: [], ...overrides, }); diff --git a/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts b/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts index 102991ff4..9a78bfa91 100644 --- a/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts +++ b/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts @@ -14,5 +14,6 @@ export const createMockUseConfig = (overrides?: Partial): MockUse }, fetchConfig: vi.fn(async () => undefined), filteredStrategies: [], + allowedRoles: [], ...overrides, }); diff --git a/packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts b/packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts new file mode 100644 index 000000000..d3fcbc0f3 --- /dev/null +++ b/packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts @@ -0,0 +1,108 @@ +import type { MemberInvitation } from '@auth0/universal-components-core'; +import { vi } from 'vitest'; + +import type { OrganizationInvitationDetailsModalProps } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal'; +import type { OrganizationInvitationRevokeModalProps } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal'; +import type { OrganizationInvitationCreateModalProps } from '@/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal'; +import type { + RoleOption, + IdentityProviderOption, + OrganizationInvitationTableActionsColumnProps, + InvitationSearchFilterProps, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export const createMockInvitation = (overrides?: Partial): MemberInvitation => ({ + id: 'inv_abc123xyz456', + invitee: { email: 'test@example.com' }, + inviter: { name: 'Admin User' }, + roles: ['role_admin'], + created_at: '2024-01-01T00:00:00.000Z', + expires_at: '2099-12-31T23:59:59.000Z', + invitation_url: 'https://example.auth0.com/invitation?ticket=abc123', + ...overrides, +}); + +export const createMockPendingInvitation = ( + overrides?: Partial, +): MemberInvitation => + createMockInvitation({ + invitation_url: 'https://example.auth0.com/invitation?ticket=pending123', + ...overrides, + }); + +export const createMockExpiredInvitation = ( + overrides?: Partial, +): MemberInvitation => + createMockInvitation({ + expires_at: '2020-01-01T00:00:00.000Z', + invitation_url: undefined, + ...overrides, + }); + +export const createMockRoles = (): RoleOption[] => [ + { id: 'role_admin', name: 'Admin', description: 'Administrator role' }, + { id: 'role_member', name: 'Member', description: 'Member role' }, + { id: 'role_viewer', name: 'Viewer', description: 'Viewer role' }, +]; + +export const createMockProviders = (): IdentityProviderOption[] => [ + { id: 'con_provider1', name: 'Google', type: 'social' }, + { id: 'con_provider2', name: 'Okta', type: 'enterprise' }, +]; + +export const createMockCreateModalProps = ( + overrides: Partial = {}, +): OrganizationInvitationCreateModalProps => ({ + isOpen: true, + isLoading: false, + onClose: vi.fn(), + onCreate: vi.fn(), + ...overrides, +}); + +export const createMockActionsColumnProps = ( + overrides: Partial = {}, +): OrganizationInvitationTableActionsColumnProps => ({ + invitation: createMockPendingInvitation(), + readOnly: false, + onViewDetails: vi.fn(), + onCopyUrl: vi.fn(), + onRevokeAndResend: vi.fn(), + onRevoke: vi.fn(), + ...overrides, +}); + +export const createMockDetailsModalProps = ( + overrides: Partial = {}, +): OrganizationInvitationDetailsModalProps => ({ + invitation: createMockPendingInvitation(), + isOpen: true, + isRevoking: false, + isResending: false, + onClose: vi.fn(), + onCopyUrl: vi.fn(), + onRevoke: vi.fn(), + onResend: vi.fn(), + ...overrides, +}); + +export const createMockRevokeModalProps = ( + overrides: Partial = {}, +): OrganizationInvitationRevokeModalProps => ({ + invitation: createMockPendingInvitation(), + isOpen: true, + isLoading: false, + isRevokeAndResend: false, + onClose: vi.fn(), + onConfirm: vi.fn(), + ...overrides, +}); + +export const createMockSearchFilterProps = ( + overrides: Partial = {}, +): InvitationSearchFilterProps => ({ + filters: {}, + availableRoles: createMockRoles(), + onRoleFilterChange: vi.fn(), + ...overrides, +}); From ed0b7a669134144dd91109747bada8001f42bba0 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Mon, 30 Mar 2026 16:52:08 +0530 Subject: [PATCH 007/125] chore(core): update myorganization-js package to beta 5 --- auth0-myorganization-js-1.0.0-beta.4.tgz | Bin 179690 -> 0 bytes auth0-myorganization-js-1.0.0-beta.5.tgz | Bin 0 -> 179720 bytes packages/core/package.json | 2 +- .../member-management-types.ts | 12 ------------ pnpm-lock.yaml | 11 ++++++----- 5 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 auth0-myorganization-js-1.0.0-beta.4.tgz create mode 100644 auth0-myorganization-js-1.0.0-beta.5.tgz diff --git a/auth0-myorganization-js-1.0.0-beta.4.tgz b/auth0-myorganization-js-1.0.0-beta.4.tgz deleted file mode 100644 index b6675e14dc53667955b082e2dcbbd041093ed61d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 179690 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�ML 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 diff --git a/auth0-myorganization-js-1.0.0-beta.5.tgz b/auth0-myorganization-js-1.0.0-beta.5.tgz new file mode 100644 index 0000000000000000000000000000000000000000..75ecbc4e8350abc3c27ed75e69f6e3a154975d2d GIT binary patch literal 179720 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 z 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.0.0'} - '@auth0/myorganization-js@1.0.0-beta.5': - resolution: {integrity: sha512-2KocBHkgrhIyZQ0YLfk1j5o9X2a/i/NpTjc5QLtv45T9qsnq9ybTPuCRPWkeJc8a8z670IT9aRyGR6SWGftZ0A==} + '@auth0/myorganization-js@file:auth0-myorganization-js-1.0.0-beta.5.tgz': + resolution: {integrity: sha512-7KODXVGUP0OTU7l8SUHfhmjtpXgrwETJnysD111i2WxPTb31Ssx4iGMLlkA7wnJwuM+mEjzAdDXVOtaoLAMxbg==, tarball: file:auth0-myorganization-js-1.0.0-beta.5.tgz} + version: 1.0.0-beta.5 engines: {node: '>=18.0.0'} '@auth0/nextjs-auth0@4.16.0': @@ -7304,7 +7305,7 @@ snapshots: '@auth0/myaccount-js@1.0.0-beta.0': {} - '@auth0/myorganization-js@1.0.0-beta.5': + '@auth0/myorganization-js@file:auth0-myorganization-js-1.0.0-beta.5.tgz': dependencies: '@auth0/auth0-auth-js': 1.5.0 From 18d978ef112d96f253e04bc9e35746e1f565af99 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Wed, 1 Apr 2026 18:07:52 +0530 Subject: [PATCH 008/125] feat(core): add member detail translations --- .../core/src/i18n/translations/en-US.json | 70 ++++++++++++++++++ packages/core/src/i18n/translations/fr.json | 74 +++++++++++++++++++ packages/core/src/i18n/translations/ja.json | 71 +++++++++++++++++- 3 files changed, 214 insertions(+), 1 deletion(-) diff --git a/packages/core/src/i18n/translations/en-US.json b/packages/core/src/i18n/translations/en-US.json index 821bc29c4..bdd2b389d 100644 --- a/packages/core/src/i18n/translations/en-US.json +++ b/packages/core/src/i18n/translations/en-US.json @@ -1095,6 +1095,76 @@ "error": { "fetch_failed": "Failed to load members. Please try again.", "remove_failed": "Failed to remove member. Please try again." + }, + "detail": { + "back_button": "Back to Members", + "tabs": { + "details": "Details", + "roles": "Roles" + }, + "user_details": { + "title": "User Details", + "name": "Name", + "email": "Email", + "phone_number": "Phone Number", + "provider": "Provider", + "created_at": "Created At", + "last_login": "Last Login" + }, + "danger_zone": { + "remove_from_org": { + "title": "Remove member from ${organization}", + "description": "Once confirmed, this operation cannot be undone.", + "button": "Delete", + "confirm_title": "Remove Member", + "confirm_description": "Are you sure you want to remove ${email} from ${organization}? This action will not delete their account but it will revoke their access and prevent them from signing in.", + "confirm_button": "Remove", + "cancel_button": "Cancel", + "success": "${email} has been removed from ${organization}." + }, + "delete_member": { + "title": "Delete this member", + "description": "Once confirmed, this operation cannot be undone.", + "button": "Delete", + "confirm_title": "Delete Member", + "confirm_description": "Are you sure you want to remove ${email} from ${organization}? This action will not delete their account but it will revoke their access and prevent them from signing in.", + "confirm_button": "Delete", + "cancel_button": "Cancel", + "success": "${email} has been deleted from ${organization}." + } + }, + "roles": { + "title": "Roles", + "description": "Manage user roles and permissions when accessing ${appName}.", + "assign_button": "Assign Roles", + "table": { + "name": "Name", + "description": "Description", + "empty_message": "No roles assigned." + }, + "assign_modal": { + "title": "Assign Roles", + "roles_label": "Roles", + "roles_placeholder": "Select role(s)", + "submit_button": "Assign Role(s)", + "cancel_button": "Cancel", + "no_roles_available": "All available roles are already assigned." + }, + "remove_confirm": { + "title": "Remove Role", + "description": "Are you sure you want to remove the role ${roleName} from this member?", + "confirm_button": "Remove", + "cancel_button": "Cancel" + } + }, + "error": { + "fetch_failed": "Failed to load member details. Please try again.", + "fetch_roles_failed": "Failed to load member roles. Please try again.", + "remove_from_org_failed": "Failed to remove member from organization. Please try again.", + "delete_failed": "Failed to delete member. Please try again.", + "assign_role_failed": "Failed to assign role. Please try again.", + "remove_role_failed": "Failed to remove role. Please try again." + } } }, "invitation": { diff --git a/packages/core/src/i18n/translations/fr.json b/packages/core/src/i18n/translations/fr.json index 7c67af69f..fb793f5aa 100644 --- a/packages/core/src/i18n/translations/fr.json +++ b/packages/core/src/i18n/translations/fr.json @@ -1016,5 +1016,79 @@ "install_guardian_description": "Pour continuer, installez l'application Auth0 Guardian via l'app store depuis votre appareil mobile" } } + }, + "member_management": { + "member": { + "detail": { + "back_button": "Back to Members", + "tabs": { + "details": "Details", + "roles": "Roles" + }, + "user_details": { + "title": "User Details", + "name": "Name", + "email": "Email", + "phone_number": "Phone Number", + "provider": "Provider", + "created_at": "Created At", + "last_login": "Last Login" + }, + "danger_zone": { + "remove_from_org": { + "title": "Remove member from organization", + "description": "Once confirmed, this operation cannot be undone.", + "button": "Delete", + "confirm_title": "Remove Member", + "confirm_description": "Are you sure you want to remove this member from the organization?", + "confirm_button": "Remove", + "cancel_button": "Cancel", + "success": "Member has been removed from the organization." + }, + "delete_member": { + "title": "Delete this member", + "description": "Once confirmed, this operation cannot be undone.", + "button": "Delete", + "confirm_title": "Delete Member", + "confirm_description": "Are you sure you want to permanently delete this member? This action cannot be undone.", + "confirm_button": "Delete", + "cancel_button": "Cancel", + "success": "Member has been deleted." + } + }, + "roles": { + "title": "Roles", + "description": "Manage user roles and permissions when accessing ${appName}.", + "assign_button": "Assign Roles", + "table": { + "name": "Name", + "description": "Description", + "empty_message": "No roles assigned." + }, + "assign_modal": { + "title": "Assign Roles", + "roles_label": "Roles", + "roles_placeholder": "Select roles", + "submit_button": "Assign", + "cancel_button": "Cancel", + "no_roles_available": "All available roles are already assigned." + }, + "remove_confirm": { + "title": "Remove Role", + "description": "Are you sure you want to remove the role ${roleName} from this member?", + "confirm_button": "Remove", + "cancel_button": "Cancel" + } + }, + "error": { + "fetch_failed": "Failed to load member details. Please try again.", + "fetch_roles_failed": "Failed to load member roles. Please try again.", + "remove_from_org_failed": "Failed to remove member from organization. Please try again.", + "delete_failed": "Failed to delete member. Please try again.", + "assign_role_failed": "Failed to assign role. Please try again.", + "remove_role_failed": "Failed to remove role. Please try again." + } + } + } } } diff --git a/packages/core/src/i18n/translations/ja.json b/packages/core/src/i18n/translations/ja.json index e83a9ad5d..00af699e9 100644 --- a/packages/core/src/i18n/translations/ja.json +++ b/packages/core/src/i18n/translations/ja.json @@ -879,7 +879,6 @@ "modal": { "title": "${organizationName}から${providerName}を削除", "description": "この操作により、この組織のすべてのユーザーの${providerName}へのアクセスが取り消されます。ユーザーは削除されませんが、このプロバイダーを使用してサインインできなくなります", - "content": { "description": "確認のためプロバイダー名を入力してください。", "field": { @@ -1097,6 +1096,76 @@ "error": { "fetch_failed": "メンバーの読み込みに失敗しました。もう一度お試しください。", "remove_failed": "メンバーの削除に失敗しました。もう一度お試しください。" + }, + "detail": { + "back_button": "Back to Members", + "tabs": { + "details": "Details", + "roles": "Roles" + }, + "user_details": { + "title": "User Details", + "name": "Name", + "email": "Email", + "phone_number": "Phone Number", + "provider": "Provider", + "created_at": "Created At", + "last_login": "Last Login" + }, + "danger_zone": { + "remove_from_org": { + "title": "Remove member from organization", + "description": "Once confirmed, this operation cannot be undone.", + "button": "Delete", + "confirm_title": "Remove Member", + "confirm_description": "Are you sure you want to remove this member from the organization?", + "confirm_button": "Remove", + "cancel_button": "Cancel", + "success": "Member has been removed from the organization." + }, + "delete_member": { + "title": "Delete this member", + "description": "Once confirmed, this operation cannot be undone.", + "button": "Delete", + "confirm_title": "Delete Member", + "confirm_description": "Are you sure you want to permanently delete this member? This action cannot be undone.", + "confirm_button": "Delete", + "cancel_button": "Cancel", + "success": "Member has been deleted." + } + }, + "roles": { + "title": "Roles", + "description": "Manage user roles and permissions when accessing ${appName}.", + "assign_button": "Assign Roles", + "table": { + "name": "Name", + "description": "Description", + "empty_message": "No roles assigned." + }, + "assign_modal": { + "title": "Assign Roles", + "roles_label": "Roles", + "roles_placeholder": "Select roles", + "submit_button": "Assign", + "cancel_button": "Cancel", + "no_roles_available": "All available roles are already assigned." + }, + "remove_confirm": { + "title": "Remove Role", + "description": "Are you sure you want to remove the role ${roleName} from this member?", + "confirm_button": "Remove", + "cancel_button": "Cancel" + } + }, + "error": { + "fetch_failed": "Failed to load member details. Please try again.", + "fetch_roles_failed": "Failed to load member roles. Please try again.", + "remove_from_org_failed": "Failed to remove member from organization. Please try again.", + "delete_failed": "Failed to delete member. Please try again.", + "assign_role_failed": "Failed to assign role. Please try again.", + "remove_role_failed": "Failed to remove role. Please try again." + } } }, "invitation": { From fa4126d19510aaff857d9247b0f259e46ff03a61 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Wed, 1 Apr 2026 18:43:16 +0530 Subject: [PATCH 009/125] feat(core): add member detail service types and update mock client --- .../member-management-types.ts | 18 ++ .../my-organization/my-organization-client.ts | 171 ++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/packages/core/src/services/my-organization/member-management/member-management-types.ts b/packages/core/src/services/my-organization/member-management/member-management-types.ts index 1c19b950a..3f99864ec 100644 --- a/packages/core/src/services/my-organization/member-management/member-management-types.ts +++ b/packages/core/src/services/my-organization/member-management/member-management-types.ts @@ -97,3 +97,21 @@ export type CreateMemberInvitationResponseContent = * Response content for getting a member invitation. */ export type GetMemberInvitationResponseContent = MyOrganization.GetMemberInvitationResponseContent; + +/** + * Request content for deleting organization members. + */ +export type DeleteOrganizationMembersRequestContent = + MyOrganization.DeleteOrganizationMembersRequestContent; + +/** + * Request content for changing roles of an organization member. + */ +export type OrganizationMemberRolesChangeRequestContent = + MyOrganization.OrganizationMemberRolesChangeRequestContent; + +/** + * Response content for changing roles of an organization member. + */ +export type OrganizationMemberRolesChangeResponseContent = + MyOrganization.OrganizationMemberRolesChangeResponseContent; diff --git a/packages/core/src/services/my-organization/my-organization-client.ts b/packages/core/src/services/my-organization/my-organization-client.ts index 8156c3d7e..245941e32 100644 --- a/packages/core/src/services/my-organization/my-organization-client.ts +++ b/packages/core/src/services/my-organization/my-organization-client.ts @@ -34,3 +34,174 @@ export function createMyOrganizationClient(config: ClientAuthConfig) { fetcher: createSpaFetcher(config, MY_ORGANIZATION_DPOP_NONCE_ID), }); } + +/** + * Creates a mock MyOrganizationClient with hardcoded data for development and testing. + * @param _config - Auth configuration (unused in mock) + * @returns Mock MyOrganizationClient instance + * @internal + */ +export function createMockMyOrganizationClient(_config: ClientAuthConfig) { + return { + organization: { + configuration: { + get: () => + Promise.resolve({ + allowed_strategies: ['samlp', 'oidc', 'adfs', 'waad', 'google-apps', 'okta'], + connection_deletion_behavior: 'allow', + allowed_roles: [ + { id: 'role_id_1', name: 'Admin', description: 'Full access' }, + { id: 'role_id_2', name: 'Member', description: 'They are not an admin' }, + { id: 'role_id_3', name: 'Editor', description: 'They can edit things' }, + ], + }), + }, + domains: { + list: () => + Promise.resolve({ + data: [ + { + id: 'ord_1ctwYRk98Yk6TBUMX9J3cc', + org_id: 'org_HdiNOwdtHO4fuiTU', + domain: 'acme.com', + status: 'verified', + verification_txt: 'e7d1460097a29cf98c1808fb70f7b155', + verification_host: '_ss-verification.org_HdiNOwdtHO4fuiTU.acme.com', + }, + { + id: 'ord_1ctCAedWhdwC2jxwqJ6XNU', + org_id: 'org_HdiNOwdtHO4fuiTU', + domain: 'new-domain.com', + status: 'pending', + verification_txt: '4ea9a74799fb2f4f080e17b97a2d54ec', + verification_host: '_ss-verification.org_HdiNOwdtHO4fuiTU.new-domain.com', + }, + ], + }), + }, + invitations: { + list: () => + Promise.resolve({ + data: [ + { + id: 'oui_12asdf12', + organization_id: 'org_123234', + inviter: { name: 'Allison the Admin' }, + invitee: { email: 'user@example.com' }, + identity_provider_id: 'con_abc123', + created_at: '2025-05-01T12:00:00.000Z', + expires_at: '2025-05-03T12:00:00.000Z', + roles: ['role_id_1', 'role_id_2'], + invitation_url: + 'https://login.example.com/authorize?invitation=oui_12asdf12&organization=org_123234', + ticket_id: '1asdfasd23usjdef', + }, + { + id: 'oui_34ghij34', + organization_id: 'org_123234', + inviter: { name: 'Allison the Admin' }, + invitee: { email: 'jane.smith@example.com' }, + created_at: '2025-05-02T09:30:00.000Z', + expires_at: '2025-05-04T09:30:00.000Z', + roles: ['role_id_1'], + invitation_url: + 'https://login.example.com/authorize?invitation=oui_34ghij34&organization=org_123234', + ticket_id: '2bsdfbsd34vtjefg', + }, + ], + response: { next: null, total: 2 }, + }), + get: (id: string) => + Promise.resolve({ + id, + organization_id: 'org_123234', + inviter: { name: 'Allison the Admin' }, + invitee: { email: 'user@example.com' }, + identity_provider_id: 'con_abc123', + created_at: '2025-05-01T12:00:00.000Z', + expires_at: '2025-05-03T12:00:00.000Z', + roles: ['role_id_1', 'role_id_2'], + invitation_url: + 'https://login.example.com/authorize?invitation=' + id + '&organization=org_123234', + ticket_id: '1asdfasd23usjdef', + }), + create: () => + Promise.resolve([ + { + id: 'oui_new_abc123', + organization_id: 'org_123234', + inviter: { name: 'Allison the Admin' }, + invitee: { email: 'new.user@example.com' }, + created_at: new Date().toISOString(), + expires_at: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString(), + roles: ['role_id_1'], + invitation_url: + 'https://login.example.com/authorize?invitation=oui_new_abc123&organization=org_123234', + ticket_id: 'new_ticket_123', + }, + ]), + delete: () => Promise.resolve(undefined), + }, + members: { + list: () => + Promise.resolve({ + data: [ + { + user_id: 'auth0|123234235', + name: 'Millard Lauren', + email: 'millard.lauren@acme.com', + created_at: '2025-09-01T23:59:00.000Z', + last_login: '2025-09-01T23:59:00.000Z', + }, + { + user_id: 'auth0|987654321', + name: 'Jane Smith', + email: 'jane.smith@acme.com', + created_at: '2025-08-15T10:00:00.000Z', + last_login: '2025-09-01T08:30:00.000Z', + }, + { + user_id: 'auth0|555666777', + name: 'Bob Wilson', + email: 'bob.wilson@acme.com', + created_at: '2025-07-20T14:30:00.000Z', + last_login: '2025-08-28T16:45:00.000Z', + }, + ], + response: { next: null, total: 3 }, + }), + get: (userId: string) => + Promise.resolve({ + user_id: userId, + name: 'Millard Lauren', + email: 'millard.lauren@acme.com', + phone_number: '+1 (123) 456-7891', + created_at: '2025-09-01T23:59:00.000Z', + last_login: '2025-09-01T23:59:00.000Z', + roles: [ + { id: 'role_id_2', name: 'Member', description: 'They are not an admin' }, + { id: 'role_id_3', name: 'Editor', description: 'They can edit things' }, + ], + }), + deleteMembers: () => Promise.resolve(undefined), + roles: { + list: () => + Promise.resolve({ + roles: [ + { id: 'role_id_2', name: 'Member', description: 'They are not an admin' }, + { id: 'role_id_3', name: 'Editor', description: 'They can edit things' }, + ], + }), + assign: () => Promise.resolve({}), + unassign: () => Promise.resolve({}), + }, + }, + memberships: { + deleteMemberships: () => Promise.resolve(undefined), + }, + identityProviders: { + list: () => Promise.resolve({ identity_providers: [] }), + }, + }, + } as unknown as MyOrganizationClient; +} From bd9553d095ba8b6185706e1ff054b03905f932b7 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Wed, 1 Apr 2026 19:35:54 +0530 Subject: [PATCH 010/125] feat(react): add member detail presentational components and tests Add pure presentational sub-components for OrganizationMemberDetail, organized into feature subfolders following the invitations/ pattern: - member-user-details: user info card - member-danger-zone: danger actions + remove-from-org and delete modals - member-roles: roles tab + assign and remove-role modals --- .../__tests__/member-delete-modal.test.tsx | 120 ++++++++++++ .../member-detail-danger-zone.test.tsx | 117 ++++++++++++ .../member-remove-from-org-modal.test.tsx | 128 +++++++++++++ .../member-delete-modal.tsx | 62 ++++++ .../member-detail-danger-zone.tsx | 97 ++++++++++ .../member-remove-from-org-modal.tsx | 63 ++++++ .../member-assign-roles-modal.test.tsx | 140 ++++++++++++++ .../member-detail-roles-tab.test.tsx | 180 ++++++++++++++++++ .../member-remove-role-modal.test.tsx | 139 ++++++++++++++ .../member-assign-roles-modal.tsx | 124 ++++++++++++ .../member-roles/member-detail-roles-tab.tsx | 105 ++++++++++ .../member-roles/member-remove-role-modal.tsx | 71 +++++++ .../member-detail-user-details.test.tsx | 134 +++++++++++++ .../member-detail-user-details.tsx | 103 ++++++++++ .../member-management/member.mocks.ts | 122 ++++++++++++ .../organization-member-detail-types.ts | 160 ++++++++++++++++ 16 files changed, 1865 insertions(+) create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-delete-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-detail-danger-zone.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-remove-from-org-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-assign-roles-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-detail-roles-tab.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-remove-role-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/__tests__/member-detail-user-details.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details.tsx create mode 100644 packages/react/src/tests/utils/__mocks__/my-organization/member-management/member.mocks.ts create mode 100644 packages/react/src/types/my-organization/member-management/organization-member-detail-types.ts diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-delete-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-delete-modal.test.tsx new file mode 100644 index 000000000..514d9d614 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-delete-modal.test.tsx @@ -0,0 +1,120 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberDeleteModal } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { createMockDeleteModalProps } from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberDeleteModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + it('should render the modal when isOpen is true', () => { + renderWithProviders(); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should not render the modal when isOpen is false', () => { + renderWithProviders(); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + describe('content', () => { + it('should display the confirm title', () => { + renderWithProviders(); + + expect( + screen.getByText('member.detail.danger_zone.delete_member.confirm_title'), + ).toBeInTheDocument(); + }); + + it('should display the confirm description', () => { + renderWithProviders(); + + expect( + screen.getByText('member.detail.danger_zone.delete_member.confirm_description'), + ).toBeInTheDocument(); + }); + + it('should render confirm and cancel buttons', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.delete_member.confirm_button', + }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.delete_member.cancel_button', + }), + ).toBeInTheDocument(); + }); + }); + + describe('isLoading', () => { + it('should disable cancel button when isLoading is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.delete_member.cancel_button', + }), + ).toBeDisabled(); + }); + + it('should enable buttons when isLoading is false', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.delete_member.cancel_button', + }), + ).toBeEnabled(); + }); + }); + + describe('onConfirm', () => { + it('should call onConfirm when confirm button is clicked', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + + renderWithProviders(); + + await user.click( + screen.getByRole('button', { + name: 'member.detail.danger_zone.delete_member.confirm_button', + }), + ); + + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + }); + + describe('onClose', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders(); + + await user.click( + screen.getByRole('button', { + name: 'member.detail.danger_zone.delete_member.cancel_button', + }), + ); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-detail-danger-zone.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-detail-danger-zone.test.tsx new file mode 100644 index 000000000..6fec89dca --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-detail-danger-zone.test.tsx @@ -0,0 +1,117 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberDetailDangerZone } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone'; +import { renderWithProviders } from '@/tests/utils'; +import { createMockDangerZoneProps } from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberDetailDangerZone', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('rendering', () => { + it('should render both danger cards', () => { + renderWithProviders(); + + expect( + screen.getByText('member.detail.danger_zone.remove_from_org.title'), + ).toBeInTheDocument(); + expect(screen.getByText('member.detail.danger_zone.delete_member.title')).toBeInTheDocument(); + }); + + it('should render both action buttons', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.remove_from_org.button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.delete_member.button' }), + ).toBeInTheDocument(); + }); + }); + + describe('readOnly', () => { + it('should disable both buttons when readOnly is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.remove_from_org.button' }), + ).toBeDisabled(); + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.delete_member.button' }), + ).toBeDisabled(); + }); + + it('should enable buttons when readOnly is false', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.remove_from_org.button' }), + ).toBeEnabled(); + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.delete_member.button' }), + ).toBeEnabled(); + }); + }); + + describe('loading states', () => { + it('should disable remove button when isRemovingFromOrg is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.remove_from_org.button' }), + ).toBeDisabled(); + }); + + it('should disable delete button when isDeletingMember is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.detail.danger_zone.delete_member.button' }), + ).toBeDisabled(); + }); + }); + + describe('callbacks', () => { + it('should call onRemoveFromOrgClick when remove button is clicked', async () => { + const user = userEvent.setup(); + const onRemoveFromOrgClick = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.detail.danger_zone.remove_from_org.button' }), + ); + + expect(onRemoveFromOrgClick).toHaveBeenCalledTimes(1); + }); + + it('should call onDeleteMemberClick when delete button is clicked', async () => { + const user = userEvent.setup(); + const onDeleteMemberClick = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.detail.danger_zone.delete_member.button' }), + ); + + expect(onDeleteMemberClick).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-remove-from-org-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-remove-from-org-modal.test.tsx new file mode 100644 index 000000000..42185dac3 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/__tests__/member-remove-from-org-modal.test.tsx @@ -0,0 +1,128 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberRemoveFromOrgModal } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { createMockRemoveFromOrgModalProps } from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberRemoveFromOrgModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + it('should render the modal when isOpen is true', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should not render the modal when isOpen is false', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + describe('content', () => { + it('should display the confirm title', () => { + renderWithProviders(); + + expect( + screen.getByText('member.detail.danger_zone.remove_from_org.confirm_title'), + ).toBeInTheDocument(); + }); + + it('should display the confirm description', () => { + renderWithProviders(); + + expect( + screen.getByText('member.detail.danger_zone.remove_from_org.confirm_description'), + ).toBeInTheDocument(); + }); + + it('should render confirm and cancel buttons', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.remove_from_org.confirm_button', + }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.remove_from_org.cancel_button', + }), + ).toBeInTheDocument(); + }); + }); + + describe('isLoading', () => { + it('should disable both buttons when isLoading is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.remove_from_org.cancel_button', + }), + ).toBeDisabled(); + }); + + it('should enable buttons when isLoading is false', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { + name: 'member.detail.danger_zone.remove_from_org.cancel_button', + }), + ).toBeEnabled(); + }); + }); + + describe('onConfirm', () => { + it('should call onConfirm when confirm button is clicked', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { + name: 'member.detail.danger_zone.remove_from_org.confirm_button', + }), + ); + + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + }); + + describe('onClose', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { + name: 'member.detail.danger_zone.remove_from_org.cancel_button', + }), + ); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal.tsx new file mode 100644 index 000000000..d024ff04f --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal.tsx @@ -0,0 +1,62 @@ +/** + * Confirmation modal for deleting a member (deletes the underlying user). + * @module member-delete-modal + */ + +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberDeleteModalProps { + isOpen: boolean; + isLoading?: boolean; + customMessages?: OrganizationMemberDetailMessages; + onClose: () => void; + onConfirm: () => void; +} + +/** + * Renders the delete member confirmation dialog. + * @param root0 - Component props + * @returns The rendered confirmation dialog element + */ +export function MemberDeleteModal({ + isOpen, + isLoading = false, + customMessages, + onClose, + onConfirm, +}: MemberDeleteModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + + return ( + !open && onClose()}> + + + {t('member.detail.danger_zone.delete_member.confirm_title')} + + {t('member.detail.danger_zone.delete_member.confirm_description')} + + + + + + + + + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone.tsx new file mode 100644 index 000000000..a50292c48 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone.tsx @@ -0,0 +1,97 @@ +/** + * Member detail danger zone component — remove from org and delete member actions. + * @module member-detail-danger-zone + * @internal + */ + +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { Card } from '@/components/ui/card'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberDetailDangerZoneProps { + readOnly?: boolean; + isRemovingFromOrg?: boolean; + isDeletingMember?: boolean; + customMessages?: OrganizationMemberDetailMessages; + onRemoveFromOrgClick: () => void; + onDeleteMemberClick: () => void; +} + +/** + * Renders a single danger zone action card with a title, description, and destructive button. + * @param root0 - Component props + * @returns The rendered danger zone card element + */ +function DangerCard({ + title, + description, + buttonLabel, + isLoading, + disabled, + onClick, +}: { + title: string; + description: string; + buttonLabel: string; + isLoading?: boolean; + disabled?: boolean; + onClick: () => void; +}): React.JSX.Element { + return ( + +
    + {title} + {description} +
    + +
    + ); +} + +/** + * Renders the danger zone section with remove from org and delete member actions. + * @param root0 - Component props + * @returns The rendered danger zone section element + */ +export function MemberDetailDangerZone({ + readOnly = false, + isRemovingFromOrg = false, + isDeletingMember = false, + customMessages, + onRemoveFromOrgClick, + onDeleteMemberClick, +}: MemberDetailDangerZoneProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + + return ( +
    + + +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal.tsx new file mode 100644 index 000000000..3f3552323 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal.tsx @@ -0,0 +1,63 @@ +/** + * Confirmation modal for removing a member from the organization. + * @module member-remove-from-org-modal + * @internal + */ + +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberRemoveFromOrgModalProps { + isOpen: boolean; + isLoading?: boolean; + customMessages?: OrganizationMemberDetailMessages; + onClose: () => void; + onConfirm: () => void; +} + +/** + * Renders the remove from organization confirmation dialog. + * @param root0 - Component props + * @returns The rendered confirmation dialog element + */ +export function MemberRemoveFromOrgModal({ + isOpen, + isLoading = false, + customMessages, + onClose, + onConfirm, +}: MemberRemoveFromOrgModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + + return ( + !open && onClose()}> + + + {t('member.detail.danger_zone.remove_from_org.confirm_title')} + + {t('member.detail.danger_zone.remove_from_org.confirm_description')} + + + + + + + + + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-assign-roles-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-assign-roles-modal.test.tsx new file mode 100644 index 000000000..af0dd8a19 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-assign-roles-modal.test.tsx @@ -0,0 +1,140 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberAssignRolesModal } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockAssignRolesModalProps, + createMockMemberRole, + createMockAvailableRoles, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberAssignRolesModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + it('should render the modal when isOpen is true', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should not render the modal when isOpen is false', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + describe('content', () => { + it('should display the modal title', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.roles.assign_modal.title')).toBeInTheDocument(); + }); + + it('should render submit and cancel buttons', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { name: 'member.detail.roles.assign_modal.submit_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.detail.roles.assign_modal.cancel_button' }), + ).toBeInTheDocument(); + }); + }); + + describe('no roles available', () => { + it('should show no roles message when all roles are already assigned', () => { + const availableRoles = createMockAvailableRoles(); + const assignedRoles = availableRoles.map((r) => + createMockMemberRole({ id: r.id, name: r.name }), + ); + + renderWithProviders( + , + ); + + expect( + screen.getByText('member.detail.roles.assign_modal.no_roles_available'), + ).toBeInTheDocument(); + }); + + it('should not show no roles message when there are unassigned roles', () => { + renderWithProviders( + , + ); + + expect( + screen.queryByText('member.detail.roles.assign_modal.no_roles_available'), + ).not.toBeInTheDocument(); + }); + }); + + describe('roles label', () => { + it('should show roles label when there are unassigned roles', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('member.detail.roles.assign_modal.roles_label')).toBeInTheDocument(); + }); + }); + + describe('submit button', () => { + it('should disable submit button when no roles are selected', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { name: 'member.detail.roles.assign_modal.submit_button' }), + ).toBeDisabled(); + }); + + it('should disable submit button when isLoading is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.detail.roles.assign_modal.submit_button' }), + ).toBeDisabled(); + }); + }); + + describe('onClose', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.detail.roles.assign_modal.cancel_button' }), + ); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-detail-roles-tab.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-detail-roles-tab.test.tsx new file mode 100644 index 000000000..2af596de5 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-detail-roles-tab.test.tsx @@ -0,0 +1,180 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberDetailRolesTab } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockRolesTabProps, + createMockMemberRole, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberDetailRolesTab', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('rendering', () => { + it('should render the roles section title', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.roles.title')).toBeInTheDocument(); + }); + + it('should render the roles description', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.roles.description')).toBeInTheDocument(); + }); + + it('should render column headers', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.roles.table.name')).toBeInTheDocument(); + expect(screen.getByText('member.detail.roles.table.description')).toBeInTheDocument(); + }); + }); + + describe('roles data', () => { + it('should render role names in the table', () => { + const memberRoles = [ + createMockMemberRole({ id: 'rol_1', name: 'Admin', description: 'Admin role' }), + createMockMemberRole({ id: 'rol_2', name: 'Viewer', description: 'Viewer role' }), + ]; + + renderWithProviders(); + + expect(screen.getByText('Admin')).toBeInTheDocument(); + expect(screen.getByText('Viewer')).toBeInTheDocument(); + }); + + it('should render role descriptions in the table', () => { + const memberRoles = [ + createMockMemberRole({ id: 'rol_1', name: 'Admin', description: 'Administrator role' }), + ]; + + renderWithProviders(); + + expect(screen.getByText('Administrator role')).toBeInTheDocument(); + }); + + it('should not display description text when description is absent', () => { + const memberRoles = [ + createMockMemberRole({ id: 'rol_1', name: 'Admin', description: undefined }), + ]; + + renderWithProviders(); + + // The role name should still render + expect(screen.getByText('Admin')).toBeInTheDocument(); + // The specific description text from the mock default is not present + expect(screen.queryByText('Administrator role')).not.toBeInTheDocument(); + }); + + it('should show empty state message when there are no roles', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('member.detail.roles.table.empty_message')).toBeInTheDocument(); + }); + }); + + describe('assign roles button', () => { + it('should show assign button when readOnly is false', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: /member\.detail\.roles\.assign_button/i }), + ).toBeInTheDocument(); + }); + + it('should hide assign button when readOnly is true', () => { + renderWithProviders( + , + ); + + expect( + screen.queryByRole('button', { name: /member\.detail\.roles\.assign_button/i }), + ).not.toBeInTheDocument(); + }); + + it('should call onAssignRolesClick when assign button is clicked', async () => { + const user = userEvent.setup(); + const onAssignRolesClick = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: /member\.detail\.roles\.assign_button/i }), + ); + + expect(onAssignRolesClick).toHaveBeenCalledTimes(1); + }); + }); + + describe('remove role button', () => { + it('should render trash icon button for each role when not readOnly', () => { + const memberRoles = [ + createMockMemberRole({ id: 'rol_1', name: 'Admin' }), + createMockMemberRole({ id: 'rol_2', name: 'Viewer' }), + ]; + + renderWithProviders( + , + ); + + expect(screen.getByLabelText('Remove role Admin')).toBeInTheDocument(); + expect(screen.getByLabelText('Remove role Viewer')).toBeInTheDocument(); + }); + + it('should not render trash icon when readOnly is true', () => { + const memberRoles = [createMockMemberRole({ id: 'rol_1', name: 'Admin' })]; + + renderWithProviders( + , + ); + + expect(screen.queryByLabelText('Remove role Admin')).not.toBeInTheDocument(); + }); + + it('should call onRemoveRole with the role when trash button is clicked', async () => { + const user = userEvent.setup(); + const onRemoveRole = vi.fn(); + const role = createMockMemberRole({ id: 'rol_1', name: 'Admin' }); + + renderWithProviders( + , + ); + + await user.click(screen.getByLabelText('Remove role Admin')); + + expect(onRemoveRole).toHaveBeenCalledTimes(1); + expect(onRemoveRole).toHaveBeenCalledWith(role); + }); + + it('should disable trash button for role being removed', () => { + const role = createMockMemberRole({ id: 'rol_1', name: 'Admin' }); + + renderWithProviders( + , + ); + + expect(screen.getByLabelText('Remove role Admin')).toBeDisabled(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-remove-role-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-remove-role-modal.test.tsx new file mode 100644 index 000000000..75c9a8282 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/__tests__/member-remove-role-modal.test.tsx @@ -0,0 +1,139 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberRemoveRoleModal } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockRemoveRoleModalProps, + createMockMemberRole, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberRemoveRoleModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + it('should render the modal when isOpen is true', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should not render the modal when isOpen is false', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + describe('content', () => { + it('should display the confirm title', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.roles.remove_confirm.title')).toBeInTheDocument(); + }); + + it('should render confirm and cancel buttons', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { + name: 'member.detail.roles.remove_confirm.confirm_button', + }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { + name: 'member.detail.roles.remove_confirm.cancel_button', + }), + ).toBeInTheDocument(); + }); + }); + + describe('role', () => { + it('should handle null role gracefully', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should render with a specific role', () => { + const role = createMockMemberRole({ id: 'rol_1', name: 'Manager' }); + + renderWithProviders(); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + + describe('isLoading', () => { + it('should disable cancel button when isLoading is true', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { + name: 'member.detail.roles.remove_confirm.cancel_button', + }), + ).toBeDisabled(); + }); + + it('should enable buttons when isLoading is false', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { + name: 'member.detail.roles.remove_confirm.cancel_button', + }), + ).toBeEnabled(); + }); + }); + + describe('onConfirm', () => { + it('should call onConfirm when confirm button is clicked', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { + name: 'member.detail.roles.remove_confirm.confirm_button', + }), + ); + + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + }); + + describe('onClose', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { + name: 'member.detail.roles.remove_confirm.cancel_button', + }), + ); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal.tsx new file mode 100644 index 000000000..791dca03d --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal.tsx @@ -0,0 +1,124 @@ +/** + * Modal for assigning roles to a member. + * @module member-assign-roles-modal + * @internal + */ + +import type { OrgMemberRole } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { Combobox } from '@/components/ui/combobox'; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Label } from '@/components/ui/label'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { RoleOption } from '@/types/my-organization/member-management/organization-invitation-table-types'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberAssignRolesModalProps { + isOpen: boolean; + isLoading?: boolean; + availableRoles: RoleOption[]; + assignedRoles: OrgMemberRole[]; + customMessages?: OrganizationMemberDetailMessages; + onClose: () => void; + onAssign: (roleIds: string[]) => void; +} + +/** + * Renders the assign roles dialog for selecting and assigning roles to a member. + * @param root0 - Component props + * @returns The rendered assign roles dialog element + */ +export function MemberAssignRolesModal({ + isOpen, + isLoading = false, + availableRoles, + assignedRoles, + customMessages, + onClose, + onAssign, +}: MemberAssignRolesModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + const [selectedRoles, setSelectedRoles] = React.useState([]); + + const assignedRoleIds = React.useMemo( + () => new Set(assignedRoles.map((r) => r.id)), + [assignedRoles], + ); + + const unassignedRoles = React.useMemo( + () => availableRoles.filter((r) => !assignedRoleIds.has(r.id)), + [availableRoles, assignedRoleIds], + ); + + const handleOpenChange = React.useCallback( + (open: boolean) => { + if (!open) { + setSelectedRoles([]); + onClose(); + } + }, + [onClose], + ); + + const handleSubmit = React.useCallback(() => { + if (selectedRoles.length > 0) { + onAssign(selectedRoles); + } + }, [selectedRoles, onAssign]); + + React.useEffect(() => { + if (!isOpen) { + setSelectedRoles([]); + } + }, [isOpen]); + + return ( + + + + {t('member.detail.roles.assign_modal.title')} + + +
    + {unassignedRoles.length === 0 ? ( +

    + {t('member.detail.roles.assign_modal.no_roles_available')} +

    + ) : ( + <> + + ({ value: r.id, label: r.name }))} + value={selectedRoles} + onChange={(val) => setSelectedRoles(Array.isArray(val) ? val : [val])} + placeholder={t('member.detail.roles.assign_modal.roles_placeholder')} + disabled={isLoading} + /> + + )} +
    + + + + + +
    +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab.tsx new file mode 100644 index 000000000..ed7ddeaab --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab.tsx @@ -0,0 +1,105 @@ +/** + * Member detail roles tab component. + * @module member-detail-roles-tab + * @internal + */ + +import type { OrgMemberRole } from '@auth0/universal-components-core'; +import { Plus, Trash2 } from 'lucide-react'; +import * as React from 'react'; + +import { DataTable, type Column } from '@/components/auth0/shared/data-table'; +import { Button } from '@/components/ui/button'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { RoleOption } from '@/types/my-organization/member-management/organization-invitation-table-types'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberDetailRolesTabProps { + memberRoles: OrgMemberRole[]; + availableRoles: RoleOption[]; + isLoading?: boolean; + removingRoleId?: string | null; + readOnly?: boolean; + customMessages?: OrganizationMemberDetailMessages; + onAssignRolesClick: () => void; + onRemoveRole: (role: OrgMemberRole) => void; +} + +/** + * Renders the roles tab for a member detail view with a table and assign/remove actions. + * @param root0 - Component props + * @returns The rendered roles tab element + */ +export function MemberDetailRolesTab({ + memberRoles, + isLoading = false, + removingRoleId = null, + readOnly = false, + customMessages, + onAssignRolesClick, + onRemoveRole, +}: MemberDetailRolesTabProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + + const columns: Column[] = React.useMemo( + () => [ + { + type: 'text', + accessorKey: 'name', + title: t('member.detail.roles.table.name'), + enableSorting: false, + render: (role) => {role.name}, + }, + { + type: 'text', + accessorKey: 'description', + title: t('member.detail.roles.table.description'), + enableSorting: false, + render: (role) => {role.description ?? '—'}, + }, + { + type: 'actions', + title: '', + enableSorting: false, + render: (role) => + readOnly ? null : ( + + ), + }, + ], + [t, readOnly, removingRoleId, onRemoveRole], + ); + + return ( +
    +
    +
    +

    {t('member.detail.roles.title')}

    +

    {t('member.detail.roles.description')}

    +
    + {!readOnly && ( + + )} +
    + + +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal.tsx new file mode 100644 index 000000000..252d460d0 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal.tsx @@ -0,0 +1,71 @@ +/** + * Confirmation modal for removing a role from a member. + * @module member-remove-role-modal + * @internal + */ + +import type { OrgMemberRole } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberRemoveRoleModalProps { + isOpen: boolean; + isLoading?: boolean; + role: OrgMemberRole | null; + customMessages?: OrganizationMemberDetailMessages; + onClose: () => void; + onConfirm: () => void; +} + +/** + * Renders the remove role confirmation dialog. + * @param root0 - Component props + * @returns The rendered confirmation dialog element + */ +export function MemberRemoveRoleModal({ + isOpen, + isLoading = false, + role, + customMessages, + onClose, + onConfirm, +}: MemberRemoveRoleModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + + return ( + !open && onClose()}> + + + {t('member.detail.roles.remove_confirm.title')} + + + <> + {t.trans('member.detail.roles.remove_confirm.description', { + vars: { roleName: role?.name ?? '' }, + components: { bold: (children: string) => {children} }, + })} + + + + + + + + + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/__tests__/member-detail-user-details.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/__tests__/member-detail-user-details.test.tsx new file mode 100644 index 000000000..880da49de --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/__tests__/member-detail-user-details.test.tsx @@ -0,0 +1,134 @@ +import { screen } from '@testing-library/react'; +import { describe, it, expect, afterEach, vi } from 'vitest'; + +import { MemberDetailUserDetails } from '@/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockUserDetailsProps, + createMockMember, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('MemberDetailUserDetails', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('rendering', () => { + it('should render the user details card', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.user_details.title')).toBeInTheDocument(); + }); + + it('should render all field labels', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.user_details.name')).toBeInTheDocument(); + expect(screen.getByText('member.detail.user_details.email')).toBeInTheDocument(); + expect(screen.getByText('member.detail.user_details.phone_number')).toBeInTheDocument(); + expect(screen.getByText('member.detail.user_details.provider')).toBeInTheDocument(); + expect(screen.getByText('member.detail.user_details.created_at')).toBeInTheDocument(); + expect(screen.getByText('member.detail.user_details.last_login')).toBeInTheDocument(); + }); + }); + + describe('member name', () => { + it('should display the member name', () => { + const member = createMockMember({ name: 'Jane Doe' }); + + renderWithProviders(); + + expect(screen.getByText('Jane Doe')).toBeInTheDocument(); + }); + + it('should display "—" when name is missing', () => { + const member = createMockMember({ name: undefined }); + + renderWithProviders(); + + expect(screen.getAllByText('—').length).toBeGreaterThanOrEqual(1); + }); + }); + + describe('email field', () => { + it('should display the email as a copyable field when present', () => { + const member = createMockMember({ email: 'user@example.com' }); + + renderWithProviders(); + + expect(screen.getByDisplayValue('user@example.com')).toBeInTheDocument(); + }); + + it('should display "—" when email is missing', () => { + const member = createMockMember({ email: undefined }); + + renderWithProviders(); + + expect(screen.getAllByText('—').length).toBeGreaterThanOrEqual(1); + }); + }); + + describe('phone number field', () => { + it('should display phone number as copyable when present', () => { + const member = { + ...createMockMember(), + phone_number: '+1234567890', + } as Parameters[0]['member']; + + renderWithProviders(); + + expect(screen.getByDisplayValue('+1234567890')).toBeInTheDocument(); + }); + + it('should display "—" when phone number is absent', () => { + const member = createMockMember(); + + renderWithProviders(); + + expect(screen.getAllByText('—').length).toBeGreaterThanOrEqual(1); + }); + }); + + describe('provider field', () => { + it('should display provider when present', () => { + const member = { + ...createMockMember(), + connection: 'google-oauth2', + } as Parameters[0]['member']; + + renderWithProviders(); + + expect(screen.getByText('google-oauth2')).toBeInTheDocument(); + }); + + it('should display "—" when provider is absent', () => { + const member = createMockMember(); + + renderWithProviders(); + + expect(screen.getAllByText('—').length).toBeGreaterThanOrEqual(1); + }); + }); + + describe('date fields', () => { + it('should render created_at label', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.user_details.created_at')).toBeInTheDocument(); + }); + + it('should render last_login label', () => { + renderWithProviders(); + + expect(screen.getByText('member.detail.user_details.last_login')).toBeInTheDocument(); + }); + + it('should display "—" when created_at is missing', () => { + const member = createMockMember({ created_at: undefined }); + + renderWithProviders(); + + expect(screen.getAllByText('—').length).toBeGreaterThanOrEqual(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details.tsx new file mode 100644 index 000000000..748c6b55f --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details.tsx @@ -0,0 +1,103 @@ +/** + * Member detail user details card component. + * @module member-detail-user-details + * @internal + */ + +import type { OrgMember } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { CopyableTextField } from '@/components/auth0/shared/copyable-text-field'; +import { Card } from '@/components/ui/card'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberDetailMessages } from '@/types/my-organization/member-management/organization-member-detail-types'; + +export interface MemberDetailUserDetailsProps { + member: OrgMember; + customMessages?: OrganizationMemberDetailMessages; +} + +/** + * Formats an ISO date string into a human-readable locale string. + * @param dateStr - The ISO date string to format + * @returns A formatted date/time string, or '—' if the input is empty + */ +function formatDate(dateStr?: string): string { + if (!dateStr) return '—'; + return new Date(dateStr).toLocaleString(undefined, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + }); +} + +/** + * Renders the user details card for a member showing name, email, phone, and login timestamps. + * @param root0 - Component props + * @returns The rendered user details card element + */ +export function MemberDetailUserDetails({ + member, + customMessages, +}: MemberDetailUserDetailsProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages as Record); + + const memberRecord = member as Record; + const phoneNumber = (memberRecord.phone_number as string | undefined) ?? ''; + const provider = (memberRecord.connection as string | undefined) ?? ''; + + const fields = [ + { + label: t('member.detail.user_details.name'), + value: member.name ?? '—', + copyable: false, + }, + { + label: t('member.detail.user_details.email'), + value: member.email ?? '—', + copyable: true, + }, + { + label: t('member.detail.user_details.phone_number'), + value: phoneNumber || '—', + copyable: !!phoneNumber, + }, + { + label: t('member.detail.user_details.provider'), + value: provider || '—', + copyable: false, + }, + { + label: t('member.detail.user_details.created_at'), + value: formatDate(member.created_at), + copyable: false, + }, + { + label: t('member.detail.user_details.last_login'), + value: formatDate(member.last_login), + copyable: false, + }, + ]; + + return ( + +

    + {t('member.detail.user_details.title')} +

    +
    + {fields.map((field) => ( +
    + {field.label} + {field.copyable && field.value !== '—' ? ( + + ) : ( + {field.value} + )} +
    + ))} +
    +
    + ); +} diff --git a/packages/react/src/tests/utils/__mocks__/my-organization/member-management/member.mocks.ts b/packages/react/src/tests/utils/__mocks__/my-organization/member-management/member.mocks.ts new file mode 100644 index 000000000..5a9d96e17 --- /dev/null +++ b/packages/react/src/tests/utils/__mocks__/my-organization/member-management/member.mocks.ts @@ -0,0 +1,122 @@ +import type { OrgMember, OrgMemberRole } from '@auth0/universal-components-core'; +import { vi } from 'vitest'; + +import type { MemberDeleteModalProps } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal'; +import type { MemberDetailDangerZoneProps } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone'; +import type { MemberRemoveFromOrgModalProps } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal'; +import type { MemberAssignRolesModalProps } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal'; +import type { MemberDetailRolesTabProps } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab'; +import type { MemberRemoveRoleModalProps } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal'; +import type { MemberDetailUserDetailsProps } from '@/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details'; +import type { RoleOption } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export const createMockMember = (overrides?: Partial): OrgMember => + ({ + user_id: 'auth0|testuser123', + name: 'Test User', + email: 'test@example.com', + created_at: '2024-01-01T00:00:00.000Z', + last_login: '2024-06-15T10:00:00.000Z', + ...overrides, + }) as OrgMember; + +export const createMockMemberWithPhone = (overrides?: Partial): OrgMember => + createMockMember({ + ...({ + phone_number: '+1234567890', + connection: 'Username-Password-Authentication', + } as unknown as Partial), + ...overrides, + }); + +export const createMockMemberRole = (overrides?: Partial): OrgMemberRole => ({ + id: 'rol_abc123', + name: 'Admin', + description: 'Administrator role', + ...overrides, +}); + +export const createMockMemberRoles = (): OrgMemberRole[] => [ + createMockMemberRole({ id: 'rol_admin', name: 'Admin', description: 'Administrator role' }), + createMockMemberRole({ id: 'rol_member', name: 'Member', description: 'Member role' }), +]; + +export const createMockAvailableRoles = (): RoleOption[] => [ + { id: 'rol_admin', name: 'Admin', description: 'Administrator role' }, + { id: 'rol_member', name: 'Member', description: 'Member role' }, + { id: 'rol_viewer', name: 'Viewer', description: 'Viewer role' }, +]; + +export const createMockUserDetailsProps = ( + overrides: Partial = {}, +): MemberDetailUserDetailsProps => ({ + member: createMockMember(), + ...overrides, +}); + +export const createMockDangerZoneProps = ( + overrides: Partial = {}, +): MemberDetailDangerZoneProps => ({ + readOnly: false, + isRemovingFromOrg: false, + isDeletingMember: false, + onRemoveFromOrgClick: vi.fn(), + onDeleteMemberClick: vi.fn(), + ...overrides, +}); + +export const createMockRemoveFromOrgModalProps = ( + overrides: Partial = {}, +): MemberRemoveFromOrgModalProps => ({ + isOpen: true, + isLoading: false, + onClose: vi.fn(), + onConfirm: vi.fn(), + ...overrides, +}); + +export const createMockDeleteModalProps = ( + overrides: Partial = {}, +): MemberDeleteModalProps => ({ + isOpen: true, + isLoading: false, + onClose: vi.fn(), + onConfirm: vi.fn(), + ...overrides, +}); + +export const createMockRolesTabProps = ( + overrides: Partial = {}, +): MemberDetailRolesTabProps => ({ + memberRoles: createMockMemberRoles(), + availableRoles: createMockAvailableRoles(), + isLoading: false, + removingRoleId: null, + readOnly: false, + onAssignRolesClick: vi.fn(), + onRemoveRole: vi.fn(), + ...overrides, +}); + +export const createMockAssignRolesModalProps = ( + overrides: Partial = {}, +): MemberAssignRolesModalProps => ({ + isOpen: true, + isLoading: false, + availableRoles: createMockAvailableRoles(), + assignedRoles: [], + onClose: vi.fn(), + onAssign: vi.fn(), + ...overrides, +}); + +export const createMockRemoveRoleModalProps = ( + overrides: Partial = {}, +): MemberRemoveRoleModalProps => ({ + isOpen: true, + isLoading: false, + role: createMockMemberRole(), + onClose: vi.fn(), + onConfirm: vi.fn(), + ...overrides, +}); diff --git a/packages/react/src/types/my-organization/member-management/organization-member-detail-types.ts b/packages/react/src/types/my-organization/member-management/organization-member-detail-types.ts new file mode 100644 index 000000000..20ab65aef --- /dev/null +++ b/packages/react/src/types/my-organization/member-management/organization-member-detail-types.ts @@ -0,0 +1,160 @@ +/** + * Organization member detail types. + * @module organization-member-detail-types + */ + +import type { + ComponentAction, + SharedComponentProps, + OrgMember, + OrgMemberRole, +} from '@auth0/universal-components-core'; + +import type { RoleOption } from './organization-invitation-table-types'; + +export type MemberDetailTab = 'details' | 'roles'; + +export interface UseOrganizationMemberDetailOptions { + userId: string; + onBack?: () => void; + customMessages?: OrganizationMemberDetailMessages; + readOnly?: boolean; + removeFromOrgAction?: ComponentAction; + deleteMemberAction?: ComponentAction; + assignRoleAction?: ComponentAction<{ userId: string; roleId: string }>; + removeRoleAction?: ComponentAction<{ userId: string; roleId: string }>; +} + +export interface MemberDetailState { + activeTab: MemberDetailTab; + member: OrgMember | null; + memberRoles: OrgMemberRole[]; + availableRoles: RoleOption[]; + isFetchingMember: boolean; + isFetchingRoles: boolean; + isLoading: boolean; + isRemovingFromOrg: boolean; + isDeletingMember: boolean; + isAssigningRole: boolean; + removingRoleId: string | null; + showRemoveFromOrgModal: boolean; + showDeleteMemberModal: boolean; + showAssignRolesModal: boolean; + showRemoveRoleModal: boolean; + roleToRemove: OrgMemberRole | null; +} + +export interface MemberDetailHandlers { + setActiveTab: (tab: MemberDetailTab) => void; + handleBack: () => void; + handleRemoveFromOrgClick: () => void; + handleRemoveFromOrgConfirm: () => void; + handleRemoveFromOrgCancel: () => void; + handleDeleteMemberClick: () => void; + handleDeleteMemberConfirm: () => void; + handleDeleteMemberCancel: () => void; + handleAssignRolesClick: () => void; + handleAssignRolesSubmit: (roleIds: string[]) => void; + handleAssignRolesCancel: () => void; + handleRemoveRoleClick: (role: OrgMemberRole) => void; + handleRemoveRoleConfirm: () => void; + handleRemoveRoleCancel: () => void; +} + +/** CSS classes for OrganizationMemberDetail. */ +export interface OrganizationMemberDetailClasses { + 'OrganizationMemberDetail-root'?: string; + 'OrganizationMemberDetail-header'?: string; + 'OrganizationMemberDetail-tabs'?: string; + 'OrganizationMemberDetail-detailsTab'?: string; + 'OrganizationMemberDetail-rolesTab'?: string; +} + +/** OrganizationMemberDetail translation messages. */ +export interface OrganizationMemberDetailMessages { + member?: { + detail?: { + back_button?: string; + tabs?: { + details?: string; + roles?: string; + }; + user_details?: { + title?: string; + name?: string; + email?: string; + phone_number?: string; + provider?: string; + created_at?: string; + last_login?: string; + }; + danger_zone?: { + remove_from_org?: { + title?: string; + description?: string; + button?: string; + confirm_title?: string; + confirm_description?: string; + confirm_button?: string; + cancel_button?: string; + success?: string; + }; + delete_member?: { + title?: string; + description?: string; + button?: string; + confirm_title?: string; + confirm_description?: string; + confirm_button?: string; + cancel_button?: string; + success?: string; + }; + }; + roles?: { + title?: string; + description?: string; + assign_button?: string; + table?: { + name?: string; + description?: string; + empty_message?: string; + }; + assign_modal?: { + title?: string; + description?: string; + roles_label?: string; + roles_placeholder?: string; + submit_button?: string; + cancel_button?: string; + no_roles_available?: string; + }; + remove_confirm?: { + title?: string; + description?: string; + confirm_button?: string; + cancel_button?: string; + }; + }; + error?: { + fetch_failed?: string; + fetch_roles_failed?: string; + remove_from_org_failed?: string; + delete_failed?: string; + assign_role_failed?: string; + remove_role_failed?: string; + }; + }; + }; +} + +/** Props for OrganizationMemberDetail component. */ +export interface OrganizationMemberDetailProps + extends SharedComponentProps { + userId: string; + onBack?: () => void; + hideHeader?: boolean; + removeFromOrgAction?: ComponentAction; + deleteMemberAction?: ComponentAction; + assignRoleAction?: ComponentAction<{ userId: string; roleId: string }>; + removeRoleAction?: ComponentAction<{ userId: string; roleId: string }>; +} From a761becf5870e42cdac5628e8894016293efd353 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Wed, 1 Apr 2026 19:40:52 +0530 Subject: [PATCH 011/125] feat(react): add organizationmemberdetail hook and container component --- .../organization-member-detail.tsx | 261 +++++++++++++++++ packages/react/src/components/index.ts | 4 + packages/react/src/hooks/index.ts | 1 + .../my-organization/use-member-detail.ts | 271 ++++++++++++++++++ .../utils/__mocks__/core/core-client.mocks.ts | 19 ++ 5 files changed, 556 insertions(+) create mode 100644 packages/react/src/components/auth0/my-organization/organization-member-detail.tsx create mode 100644 packages/react/src/hooks/my-organization/use-member-detail.ts diff --git a/packages/react/src/components/auth0/my-organization/organization-member-detail.tsx b/packages/react/src/components/auth0/my-organization/organization-member-detail.tsx new file mode 100644 index 000000000..795b3e108 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/organization-member-detail.tsx @@ -0,0 +1,261 @@ +/** + * Organization member detail component. + * @module organization-member-detail + */ + +import { getComponentStyles } from '@auth0/universal-components-core'; +import { ArrowLeft } from 'lucide-react'; +import * as React from 'react'; + +import { GateKeeper } from '../shared/gate-keeper/gate-keeper'; + +import { MemberDeleteModal } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-delete-modal'; +import { MemberDetailDangerZone } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-detail-danger-zone'; +import { MemberRemoveFromOrgModal } from '@/components/auth0/my-organization/shared/member-management/members/member-danger-zone/member-remove-from-org-modal'; +import { MemberAssignRolesModal } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-assign-roles-modal'; +import { MemberDetailRolesTab } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-detail-roles-tab'; +import { MemberRemoveRoleModal } from '@/components/auth0/my-organization/shared/member-management/members/member-roles/member-remove-role-modal'; +import { MemberDetailUserDetails } from '@/components/auth0/my-organization/shared/member-management/members/member-user-details/member-detail-user-details'; +import { StyledScope } from '@/components/auth0/shared/styled-scope'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { useOrganizationMemberDetail } from '@/hooks/my-organization/use-member-detail'; +import { useTheme } from '@/hooks/shared/use-theme'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + MemberDetailState, + MemberDetailHandlers, + OrganizationMemberDetailProps, +} from '@/types/my-organization/member-management/organization-member-detail-types'; + +/** + * Props for the OrganizationMemberDetailView component. + */ +export interface OrganizationMemberDetailViewProps { + state: MemberDetailState & { + styling: OrganizationMemberDetailProps['styling']; + customMessages: OrganizationMemberDetailProps['customMessages']; + }; + handlers: MemberDetailHandlers; +} + +/** + * Returns the initials (up to 2 chars) from a display name. + * @param name - The display name to extract initials from + * @returns Up to 2 uppercase initials, or '?' if the name is empty + */ +function getInitials(name?: string): string { + if (!name) return '?'; + const parts = name.trim().split(/\s+/); + const first = parts[0] ?? ''; + if (parts.length === 1) return first.charAt(0).toUpperCase(); + const last = parts[parts.length - 1] ?? ''; + return (first.charAt(0) + last.charAt(0)).toUpperCase(); +} + +/** + * Details tab content — user details card + danger zone. + * @param root0 - Component props containing state and handlers + * @returns The rendered details tab element, or null if no member is loaded + */ +function OrganizationMemberEditDetailsTab({ + state, + handlers, +}: OrganizationMemberDetailViewProps): React.JSX.Element | null { + if (!state.member) return null; + + return ( +
    + + +
    + ); +} + +/** + * Roles tab content — roles table with assign/remove. + * @param root0 - Component props containing state and handlers + * @returns The rendered roles tab element + */ +function OrganizationMemberEditRolesTab({ + state, + handlers, +}: OrganizationMemberDetailViewProps): React.JSX.Element { + return ( + + ); +} + +/** + * View component for organization member detail. + * @param root0 - Component props containing state and handlers + * @returns The rendered member detail view element + */ +export function OrganizationMemberDetailView({ + state, + handlers, +}: OrganizationMemberDetailViewProps): React.JSX.Element { + const { isDarkMode } = useTheme(); + const { t } = useTranslator('member_management', state.customMessages as Record); + + const currentStyles = React.useMemo( + () => getComponentStyles(state.styling, isDarkMode), + [state.styling, isDarkMode], + ); + + const memberRecord = state.member as Record | null; + const userId = (memberRecord?.user_id as string | undefined) ?? ''; + const displayName = (memberRecord?.name as string | undefined) ?? userId; + const initials = getInitials(displayName || undefined); + + return ( + +
    + {/* Back button */} +
    + + + {/* Member header */} +
    +
    + {initials} +
    +
    +

    {displayName}

    + {userId && ( + + {userId} + + )} +
    +
    +
    + + {/* Tabs */} + handlers.setActiveTab(value as 'details' | 'roles')} + className={currentStyles.classes?.['OrganizationMemberDetail-tabs']} + > + + {t('member.detail.tabs.details')} + {t('member.detail.tabs.roles')} + + + + + + + + + + + + {/* Modals */} + + + + + + + +
    +
    + ); +} + +/** + * Container component for organization member detail. + * @param props - {@link OrganizationMemberDetailProps} + * @returns The rendered member detail container element + */ +export function OrganizationMemberDetail(props: OrganizationMemberDetailProps) { + const { + userId, + onBack, + customMessages = {}, + styling = { variables: { common: {}, light: {}, dark: {} }, classes: {} }, + removeFromOrgAction, + deleteMemberAction, + assignRoleAction, + removeRoleAction, + } = props; + + const { state, handlers } = useOrganizationMemberDetail({ + userId, + onBack, + customMessages, + removeFromOrgAction, + deleteMemberAction, + assignRoleAction, + removeRoleAction, + }); + + const extendedState = { + ...state, + styling, + customMessages, + }; + + return ( + + + + ); +} diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index e57cc966d..2d49a4fc8 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -13,6 +13,10 @@ export { export { SsoProviderTable, SsoProviderTableView } from './auth0/my-organization/sso-provider-table'; export { DomainTable, DomainTableView } from './auth0/my-organization/domain-table'; export { OrganizationMemberManagement } from './auth0/my-organization/organization-member-management'; +export { + OrganizationMemberDetail, + OrganizationMemberDetailView, +} from './auth0/my-organization/organization-member-detail'; export { OrganizationDetailsEdit, OrganizationDetailsEditView, diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index f32bcfe11..d87fe36fe 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -31,3 +31,4 @@ export { useSsoProviderTable } from './my-organization/use-sso-provider-table'; // Member Management hooks export { useOrganizationMemberManagement } from './my-organization/use-organization-member-management'; +export { useOrganizationMemberDetail } from './my-organization/use-member-detail'; diff --git a/packages/react/src/hooks/my-organization/use-member-detail.ts b/packages/react/src/hooks/my-organization/use-member-detail.ts new file mode 100644 index 000000000..9f2630cc6 --- /dev/null +++ b/packages/react/src/hooks/my-organization/use-member-detail.ts @@ -0,0 +1,271 @@ +/** + * Organization member detail hook. + * @module use-member-detail + */ + +import type { OrgMember, OrgMemberRole } from '@auth0/universal-components-core'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import * as React from 'react'; + +import { showToast } from '@/components/auth0/shared/toast'; +import { useConfig } from '@/hooks/my-organization/use-config'; +import { useCoreClient } from '@/hooks/shared/use-core-client'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { RoleOption } from '@/types/my-organization/member-management/organization-invitation-table-types'; +import type { + MemberDetailTab, + MemberDetailState, + MemberDetailHandlers, + UseOrganizationMemberDetailOptions, +} from '@/types/my-organization/member-management/organization-member-detail-types'; + +export const memberDetailQueryKeys = { + all: ['member-detail'] as const, + member: (id: string) => [...memberDetailQueryKeys.all, 'member', id] as const, +}; + +/** + * Hook for organization member detail page. + * @param options - Hook configuration options. + * @returns State and handler functions. + */ +export function useOrganizationMemberDetail(options: UseOrganizationMemberDetailOptions): { + state: MemberDetailState; + handlers: MemberDetailHandlers; +} { + const { + userId, + onBack, + customMessages = {}, + readOnly = false, + removeFromOrgAction, + deleteMemberAction, + assignRoleAction, + removeRoleAction, + } = options; + + const { coreClient } = useCoreClient(); + const { t } = useTranslator('member_management', customMessages as Record); + const queryClient = useQueryClient(); + const { allowedRoles } = useConfig(); + + const availableRoles: RoleOption[] = allowedRoles; + + const [activeTab, setActiveTab] = React.useState('details'); + const [showRemoveFromOrgModal, setShowRemoveFromOrgModal] = React.useState(false); + const [showDeleteMemberModal, setShowDeleteMemberModal] = React.useState(false); + const [showAssignRolesModal, setShowAssignRolesModal] = React.useState(false); + const [showRemoveRoleModal, setShowRemoveRoleModal] = React.useState(false); + const [roleToRemove, setRoleToRemove] = React.useState(null); + + const memberQuery = useQuery({ + queryKey: memberDetailQueryKeys.member(userId), + queryFn: () => coreClient!.getMyOrganizationApiClient().organization.members.get(userId), + enabled: !!coreClient && !!userId, + }); + + const removeFromOrgMutation = useMutation({ + mutationFn: async () => { + if (removeFromOrgAction?.onBefore && !removeFromOrgAction.onBefore(userId)) { + throw new Error('Remove from org cancelled by onBefore'); + } + await coreClient! + .getMyOrganizationApiClient() + .organization.memberships.deleteMemberships({ members: [userId] }); + }, + onSuccess: () => { + removeFromOrgAction?.onAfter?.(userId); + showToast({ + type: 'success', + message: t('member.detail.danger_zone.remove_from_org.success'), + }); + setShowRemoveFromOrgModal(false); + onBack?.(); + }, + onError: () => { + showToast({ type: 'error', message: t('member.detail.error.remove_from_org_failed') }); + }, + }); + + const deleteMemberMutation = useMutation({ + mutationFn: async () => { + if (deleteMemberAction?.onBefore && !deleteMemberAction.onBefore(userId)) { + throw new Error('Delete member cancelled by onBefore'); + } + await coreClient! + .getMyOrganizationApiClient() + .organization.members.deleteMembers({ members: [userId] }); + }, + onSuccess: () => { + deleteMemberAction?.onAfter?.(userId); + showToast({ type: 'success', message: t('member.detail.danger_zone.delete_member.success') }); + setShowDeleteMemberModal(false); + onBack?.(); + }, + onError: () => { + showToast({ type: 'error', message: t('member.detail.error.delete_failed') }); + }, + }); + + const assignRoleMutation = useMutation({ + mutationFn: async (roleIds: string[]) => { + for (const roleId of roleIds) { + if (assignRoleAction?.onBefore && !assignRoleAction.onBefore({ userId: userId, roleId })) { + throw new Error('Assign role cancelled by onBefore'); + } + } + await coreClient! + .getMyOrganizationApiClient() + .organization.members.roles.assign(userId, { role_ids: roleIds }); + for (const roleId of roleIds) { + assignRoleAction?.onAfter?.({ userId: userId, roleId }); + } + }, + onSuccess: () => { + showToast({ type: 'success', message: t('member.detail.roles.assign_button') }); + setShowAssignRolesModal(false); + queryClient.invalidateQueries({ queryKey: memberDetailQueryKeys.member(userId) }); + }, + onError: () => { + showToast({ type: 'error', message: t('member.detail.error.assign_role_failed') }); + }, + }); + + const removeRoleMutation = useMutation({ + mutationFn: async (role: OrgMemberRole) => { + if ( + removeRoleAction?.onBefore && + !removeRoleAction.onBefore({ userId: userId, roleId: role.id }) + ) { + throw new Error('Remove role cancelled by onBefore'); + } + await coreClient! + .getMyOrganizationApiClient() + .organization.members.roles.unassign(userId, { role_ids: [role.id] }); + removeRoleAction?.onAfter?.({ userId: userId, roleId: role.id }); + }, + onSuccess: () => { + showToast({ + type: 'success', + message: t('member.detail.roles.remove_confirm.confirm_button'), + }); + setShowRemoveRoleModal(false); + setRoleToRemove(null); + queryClient.invalidateQueries({ queryKey: memberDetailQueryKeys.member(userId) }); + }, + onError: () => { + showToast({ type: 'error', message: t('member.detail.error.remove_role_failed') }); + }, + }); + + const handleBack = React.useCallback(() => { + onBack?.(); + }, [onBack]); + + const handleRemoveFromOrgClick = React.useCallback(() => { + if (readOnly) return; + setShowRemoveFromOrgModal(true); + }, [readOnly]); + + const handleRemoveFromOrgConfirm = React.useCallback(() => { + if (!coreClient) return; + removeFromOrgMutation.mutate(); + }, [coreClient]); + + const handleRemoveFromOrgCancel = React.useCallback(() => { + setShowRemoveFromOrgModal(false); + }, []); + + const handleDeleteMemberClick = React.useCallback(() => { + if (readOnly) return; + setShowDeleteMemberModal(true); + }, [readOnly]); + + const handleDeleteMemberConfirm = React.useCallback(() => { + if (!coreClient) return; + deleteMemberMutation.mutate(); + }, [coreClient]); + + const handleDeleteMemberCancel = React.useCallback(() => { + setShowDeleteMemberModal(false); + }, []); + + const handleAssignRolesClick = React.useCallback(() => { + if (readOnly) return; + setShowAssignRolesModal(true); + }, [readOnly]); + + const handleAssignRolesSubmit = React.useCallback( + (roleIds: string[]) => { + if (!coreClient) return; + assignRoleMutation.mutate(roleIds); + }, + [coreClient], + ); + + const handleAssignRolesCancel = React.useCallback(() => { + setShowAssignRolesModal(false); + }, []); + + const handleRemoveRoleClick = React.useCallback( + (role: OrgMemberRole) => { + if (readOnly) return; + setRoleToRemove(role); + setShowRemoveRoleModal(true); + }, + [readOnly], + ); + + const handleRemoveRoleConfirm = React.useCallback(() => { + if (!roleToRemove || !coreClient) return; + removeRoleMutation.mutate(roleToRemove); + }, [roleToRemove, coreClient]); + + const handleRemoveRoleCancel = React.useCallback(() => { + setShowRemoveRoleModal(false); + setRoleToRemove(null); + }, []); + + const member = (memberQuery.data as OrgMember) ?? null; + const memberRoles: OrgMemberRole[] = member?.roles ?? []; + + const state: MemberDetailState = { + activeTab, + member, + memberRoles, + availableRoles, + isFetchingMember: memberQuery.isLoading || memberQuery.isFetching, + isFetchingRoles: memberQuery.isLoading || memberQuery.isFetching, + isLoading: memberQuery.isLoading, + isRemovingFromOrg: removeFromOrgMutation.isPending, + isDeletingMember: deleteMemberMutation.isPending, + isAssigningRole: assignRoleMutation.isPending, + removingRoleId: removeRoleMutation.isPending ? (roleToRemove?.id ?? null) : null, + showRemoveFromOrgModal, + showDeleteMemberModal, + showAssignRolesModal, + showRemoveRoleModal, + roleToRemove, + }; + + const handlers: MemberDetailHandlers = { + setActiveTab, + handleBack, + handleRemoveFromOrgClick, + handleRemoveFromOrgConfirm, + handleRemoveFromOrgCancel, + handleDeleteMemberClick, + handleDeleteMemberConfirm, + handleDeleteMemberCancel, + handleAssignRolesClick, + handleAssignRolesSubmit, + handleAssignRolesCancel, + handleRemoveRoleClick, + handleRemoveRoleConfirm, + handleRemoveRoleCancel, + }; + + return { state, handlers }; +} + +export type UseOrganizationMemberDetailResult = ReturnType; diff --git a/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts b/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts index 2964c44ac..984adb267 100644 --- a/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts +++ b/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts @@ -95,6 +95,25 @@ const createMockMyOrgApiService = (): CoreClientInterface['myOrganizationApiClie }), }, }, + members: { + list: vi.fn().mockResolvedValue({ data: [], response: { next: null, total: 0 } }), + get: vi.fn().mockResolvedValue({ + user_id: 'auth0|123234235', + name: 'Test User', + email: 'test@example.com', + created_at: '2025-01-01T00:00:00.000Z', + last_login: '2025-01-01T00:00:00.000Z', + }), + deleteMembers: vi.fn().mockResolvedValue(undefined), + roles: { + list: vi.fn().mockResolvedValue({ roles: [] }), + assign: vi.fn().mockResolvedValue({}), + unassign: vi.fn().mockResolvedValue({}), + }, + }, + memberships: { + deleteMemberships: vi.fn().mockResolvedValue(undefined), + }, }, } as unknown as NonNullable; return service; From d1821ade95c4c35741380b270f8ba5f8212af824 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Thu, 2 Apr 2026 23:30:37 +0530 Subject: [PATCH 012/125] feat(react): implement member detail page and update member management --- .../app/member-management/[user_id]/page.tsx | 16 ++++++ .../src/app/member-management/page.tsx | 53 ++++++++++++++----- examples/react-spa-npm/src/App.tsx | 9 ++++ .../src/views/member-detail-page.tsx | 15 ++++++ .../src/views/member-management-page.tsx | 53 ++++++++++++++----- 5 files changed, 122 insertions(+), 24 deletions(-) create mode 100644 examples/next-rwa/src/app/member-management/[user_id]/page.tsx create mode 100644 examples/react-spa-npm/src/views/member-detail-page.tsx diff --git a/examples/next-rwa/src/app/member-management/[user_id]/page.tsx b/examples/next-rwa/src/app/member-management/[user_id]/page.tsx new file mode 100644 index 000000000..03553c33d --- /dev/null +++ b/examples/next-rwa/src/app/member-management/[user_id]/page.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { OrganizationMemberDetail } from '@auth0/universal-components-react/rwa'; +import { useRouter, useParams } from 'next/navigation'; + +export default function MemberDetailPage() { + const router = useRouter(); + const params = useParams(); + const user_id = params.user_id as string; + + return ( +
    + router.push('/member-management')} /> +
    + ); +} diff --git a/examples/next-rwa/src/app/member-management/page.tsx b/examples/next-rwa/src/app/member-management/page.tsx index 7dcc22ec3..048a33b4d 100644 --- a/examples/next-rwa/src/app/member-management/page.tsx +++ b/examples/next-rwa/src/app/member-management/page.tsx @@ -1,21 +1,50 @@ 'use client'; -// import { OrganizationMemberManagement } from '@auth0/universal-components-react/rwa'; +import { useRouter } from 'next/navigation'; + +const mockMembers = [ + { user_id: 'auth0|123234235', name: 'Test User', email: 'testuser@example.com' }, + { user_id: 'auth0|987654321', name: 'Jane Smith', email: 'janesmith@example.com' }, + { user_id: 'auth0|567891234', name: 'Alice Johnson', email: 'alicejohnson@example.com' }, +]; export default function MemberManagementPage() { + const router = useRouter(); + return (
    -

    - Follow{' '} - - Quickstart guidance - {' '} - on how to add Member Management component. -

    - {/* */} +

    Members

    +
    + + + + + + + + + + {mockMembers.map((member) => ( + + + + + + + ))} + +
    NameEmailUser ID +
    {member.name}{member.email} + {member.user_id} + + +
    +
    ); } diff --git a/examples/react-spa-npm/src/App.tsx b/examples/react-spa-npm/src/App.tsx index 9b443b784..f34e51e17 100644 --- a/examples/react-spa-npm/src/App.tsx +++ b/examples/react-spa-npm/src/App.tsx @@ -8,6 +8,7 @@ import { Navbar } from './components/nav-bar'; import { Sidebar } from './components/side-bar'; import DomainManagementPage from './views/domain-management-page'; import HomePage from './views/home-page'; +import MemberDetailPage from './views/member-detail-page'; import MemberManagementPage from './views/member-management-page'; import MFAPage from './views/mfa-page'; import OrganizationManagementPage from './views/organization-management-page'; @@ -102,6 +103,14 @@ function AppContent() { } /> + + + + } + /> { + const navigate = useNavigate(); + const { user_id } = useParams<{ user_id: string }>(); + + return ( +
    + navigate('/member-management')} /> +
    + ); +}; + +export default MemberDetailPage; diff --git a/examples/react-spa-npm/src/views/member-management-page.tsx b/examples/react-spa-npm/src/views/member-management-page.tsx index e9667f79d..d45293426 100644 --- a/examples/react-spa-npm/src/views/member-management-page.tsx +++ b/examples/react-spa-npm/src/views/member-management-page.tsx @@ -1,19 +1,48 @@ -// import { OrganizationMemberManagement } from '@auth0/universal-components-react/spa'; +import { useNavigate } from 'react-router-dom'; + +const mockMembers = [ + { user_id: 'auth0|123234235', name: 'Test User', email: 'testuser@example.com' }, + { user_id: 'auth0|987654321', name: 'Jane Smith', email: 'janesmith@example.com' }, + { user_id: 'auth0|567891234', name: 'Alice Johnson', email: 'alicejohnson@example.com' }, +]; const MemberManagementPage = () => { + const navigate = useNavigate(); + return (
    -

    - Follow{' '} - - Quickstart guidance - {' '} - on how to add Member Management component. -

    - {/* */} +

    Members

    +
    + + + + + + + + + + {mockMembers.map((member) => ( + + + + + + + ))} + +
    NameEmailUser ID +
    {member.name}{member.email} + {member.user_id} + + +
    +
    ); }; From ab9e4a8ff9f4ea4a2f15c4ef1c44df3248741bdf Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Tue, 7 Apr 2026 11:21:14 +0530 Subject: [PATCH 013/125] feat(core): update translatiions --- .../core/src/i18n/translations/en-US.json | 45 +++---- packages/core/src/i18n/translations/fr.json | 114 ++++++++++-------- packages/core/src/i18n/translations/ja.json | 111 ++++++++--------- 3 files changed, 146 insertions(+), 124 deletions(-) diff --git a/packages/core/src/i18n/translations/en-US.json b/packages/core/src/i18n/translations/en-US.json index bdd2b389d..c4e87d228 100644 --- a/packages/core/src/i18n/translations/en-US.json +++ b/packages/core/src/i18n/translations/en-US.json @@ -1085,13 +1085,6 @@ }, "empty_message": "No members found." }, - "remove": { - "title": "Remove Member", - "description": "Are you sure you want to remove ${name} from this organization?", - "confirm_button": "Remove", - "cancel_button": "Cancel", - "success": "${name} has been removed from the organization." - }, "error": { "fetch_failed": "Failed to load members. Please try again.", "remove_failed": "Failed to remove member. Please try again." @@ -1114,29 +1107,33 @@ "danger_zone": { "remove_from_org": { "title": "Remove member from ${organization}", - "description": "Once confirmed, this operation cannot be undone.", - "button": "Delete", - "confirm_title": "Remove Member", - "confirm_description": "Are you sure you want to remove ${email} from ${organization}? This action will not delete their account but it will revoke their access and prevent them from signing in.", + "title_plural": "Remove members from ${organization}", + "description": "Are you sure you want to remove ${email} from this organization? This action will not delete their account but it will revoke their access and prevent them from signing in.", + "description_plural": "Are you sure you want to remove ${count} members from this organization? This action will not delete their account but it will revoke their access and prevent them from signing in.", "confirm_button": "Remove", "cancel_button": "Cancel", - "success": "${email} has been removed from ${organization}." + "success": "${email} has been removed from ${organization}.", + "success_plural": "The selected members have been removed from ${organization}." }, "delete_member": { - "title": "Delete this member", - "description": "Once confirmed, this operation cannot be undone.", - "button": "Delete", - "confirm_title": "Delete Member", - "confirm_description": "Are you sure you want to remove ${email} from ${organization}? This action will not delete their account but it will revoke their access and prevent them from signing in.", + "title": "Delete member", + "title_plural": "Delete members", + "description": "Are you sure you want to delete ${email}? This action cannot be undone.", + "description_plural": "Are you sure you want to delete ${count} members? This action cannot be undone.", "confirm_button": "Delete", "cancel_button": "Cancel", - "success": "${email} has been deleted from ${organization}." + "success": "${email} has been deleted.", + "success_plural": "The selected members have been deleted." } }, "roles": { "title": "Roles", "description": "Manage user roles and permissions when accessing ${appName}.", "assign_button": "Assign Roles", + "no_roles_available": "There are no more roles available to assign to this member.", + "max_roles_reached": "You have reached the maximum of ${max} roles for this member.", + "remove_button": "Remove Role", + "remove_button_plural": "Remove Roles", "table": { "name": "Name", "description": "Description", @@ -1148,13 +1145,17 @@ "roles_placeholder": "Select role(s)", "submit_button": "Assign Role(s)", "cancel_button": "Cancel", - "no_roles_available": "All available roles are already assigned." + "no_roles_available": "All available roles are already assigned.", + "success": "The role has been assigned.", + "success_plural": "The roles have been assigned." }, "remove_confirm": { - "title": "Remove Role", - "description": "Are you sure you want to remove the role ${roleName} from this member?", + "title": "Remove Role from Member?", + "title_plural": "Remove Roles from Member?", + "description": "This will remove the ${roleName} role from \"${memberName}\".", "confirm_button": "Remove", - "cancel_button": "Cancel" + "cancel_button": "Cancel", + "success": "\"${roleName}\" role has been removed from member." } }, "error": { diff --git a/packages/core/src/i18n/translations/fr.json b/packages/core/src/i18n/translations/fr.json index fb793f5aa..97c3d650e 100644 --- a/packages/core/src/i18n/translations/fr.json +++ b/packages/core/src/i18n/translations/fr.json @@ -1019,74 +1019,94 @@ }, "member_management": { "member": { + "table": { + "columns": { + "name": "Nom", + "email": "E-mail", + "roles": "Rôles" + }, + "empty_message": "Aucun membre trouvé." + }, + "error": { + "fetch_failed": "Échec du chargement des membres. Veuillez réessayer.", + "remove_failed": "Échec de la suppression du membre. Veuillez réessayer." + }, "detail": { - "back_button": "Back to Members", + "back_button": "Retour aux membres", "tabs": { - "details": "Details", - "roles": "Roles" + "details": "Détails", + "roles": "Rôles" }, "user_details": { - "title": "User Details", - "name": "Name", - "email": "Email", - "phone_number": "Phone Number", - "provider": "Provider", - "created_at": "Created At", - "last_login": "Last Login" + "title": "Détails de l'utilisateur", + "name": "Nom", + "email": "E-mail", + "phone_number": "Numéro de téléphone", + "provider": "Fournisseur", + "created_at": "Créé le", + "last_login": "Dernière connexion" }, "danger_zone": { "remove_from_org": { - "title": "Remove member from organization", - "description": "Once confirmed, this operation cannot be undone.", - "button": "Delete", - "confirm_title": "Remove Member", - "confirm_description": "Are you sure you want to remove this member from the organization?", - "confirm_button": "Remove", - "cancel_button": "Cancel", - "success": "Member has been removed from the organization." + "title": "Retirer le membre de ${organization}", + "title_plural": "Retirer les membres de ${organization}", + "description": "Êtes-vous sûr de vouloir retirer ${email} de cette organisation ? Cette action ne supprimera pas son compte, mais révoquera son accès et l'empêchera de se connecter.", + "description_plural": "Êtes-vous sûr de vouloir retirer ${count} membres de cette organisation ? Cette action ne supprimera pas leur compte, mais révoquera leur accès et les empêchera de se connecter.", + "confirm_button": "Retirer", + "cancel_button": "Annuler", + "success": "${email} a été retiré de ${organization}.", + "success_plural": "Les membres sélectionnés ont été retirés de ${organization}." }, "delete_member": { - "title": "Delete this member", - "description": "Once confirmed, this operation cannot be undone.", - "button": "Delete", - "confirm_title": "Delete Member", - "confirm_description": "Are you sure you want to permanently delete this member? This action cannot be undone.", - "confirm_button": "Delete", - "cancel_button": "Cancel", - "success": "Member has been deleted." + "title": "Supprimer le membre", + "title_plural": "Supprimer les membres", + "description": "Êtes-vous sûr de vouloir supprimer ${email} ? Cette action est irréversible.", + "description_plural": "Êtes-vous sûr de vouloir supprimer ${count} membres ? Cette action est irréversible.", + "confirm_button": "Supprimer", + "cancel_button": "Annuler", + "success": "${email} a été supprimé.", + "success_plural": "Les membres sélectionnés ont été supprimés." } }, "roles": { - "title": "Roles", - "description": "Manage user roles and permissions when accessing ${appName}.", - "assign_button": "Assign Roles", + "title": "Rôles", + "description": "Gérez les rôles et autorisations de l'utilisateur pour l'accès à ${appName}.", + "assign_button": "Attribuer des rôles", + "no_roles_available": "Il n'y a plus de rôles disponibles à attribuer à ce membre.", + "max_roles_reached": "Vous avez atteint le nombre maximum de ${max} rôles pour ce membre.", + "remove_button": "Supprimer le rôle", + "remove_button_plural": "Supprimer les rôles", "table": { - "name": "Name", + "name": "Nom", "description": "Description", - "empty_message": "No roles assigned." + "empty_message": "Aucun rôle attribué." }, "assign_modal": { - "title": "Assign Roles", - "roles_label": "Roles", - "roles_placeholder": "Select roles", - "submit_button": "Assign", - "cancel_button": "Cancel", - "no_roles_available": "All available roles are already assigned." + "title": "Attribuer des rôles", + "roles_label": "Rôles", + "roles_placeholder": "Sélectionner un ou des rôles", + "submit_button": "Attribuer le(s) rôle(s)", + "cancel_button": "Annuler", + "no_roles_available": "Tous les rôles disponibles sont déjà attribués.", + "success": "Le rôle a été attribué.", + "success_plural": "Les rôles ont été attribués." }, "remove_confirm": { - "title": "Remove Role", - "description": "Are you sure you want to remove the role ${roleName} from this member?", - "confirm_button": "Remove", - "cancel_button": "Cancel" + "title": "Retirer le rôle du membre ?", + "title_plural": "Retirer les rôles du membre ?", + "description": "Cela retirera le rôle ${roleName} de \"${memberName}\".", + "confirm_button": "Retirer", + "cancel_button": "Annuler", + "success": "Le rôle \"${roleName}\" a été retiré du membre." } }, "error": { - "fetch_failed": "Failed to load member details. Please try again.", - "fetch_roles_failed": "Failed to load member roles. Please try again.", - "remove_from_org_failed": "Failed to remove member from organization. Please try again.", - "delete_failed": "Failed to delete member. Please try again.", - "assign_role_failed": "Failed to assign role. Please try again.", - "remove_role_failed": "Failed to remove role. Please try again." + "fetch_failed": "Échec du chargement des détails du membre. Veuillez réessayer.", + "fetch_roles_failed": "Échec du chargement des rôles du membre. Veuillez réessayer.", + "remove_from_org_failed": "Échec du retrait du membre de l'organisation. Veuillez réessayer.", + "delete_failed": "Échec de la suppression du membre. Veuillez réessayer.", + "assign_role_failed": "Échec de l'attribution du rôle. Veuillez réessayer.", + "remove_role_failed": "Échec du retrait du rôle. Veuillez réessayer." } } } diff --git a/packages/core/src/i18n/translations/ja.json b/packages/core/src/i18n/translations/ja.json index 00af699e9..57fb6a571 100644 --- a/packages/core/src/i18n/translations/ja.json +++ b/packages/core/src/i18n/translations/ja.json @@ -1086,85 +1086,86 @@ }, "empty_message": "メンバーが見つかりません。" }, - "remove": { - "title": "メンバーを削除", - "description": "この組織から${name}を削除してもよろしいですか?", - "confirm_button": "削除", - "cancel_button": "キャンセル", - "success": "${name}が組織から削除されました。" - }, "error": { "fetch_failed": "メンバーの読み込みに失敗しました。もう一度お試しください。", "remove_failed": "メンバーの削除に失敗しました。もう一度お試しください。" }, "detail": { - "back_button": "Back to Members", + "back_button": "メンバー一覧に戻る", "tabs": { - "details": "Details", - "roles": "Roles" + "details": "詳細", + "roles": "ロール" }, "user_details": { - "title": "User Details", - "name": "Name", - "email": "Email", - "phone_number": "Phone Number", - "provider": "Provider", - "created_at": "Created At", - "last_login": "Last Login" + "title": "ユーザー詳細", + "name": "名前", + "email": "メール", + "phone_number": "電話番号", + "provider": "プロバイダー", + "created_at": "作成日", + "last_login": "最終ログイン" }, "danger_zone": { "remove_from_org": { - "title": "Remove member from organization", - "description": "Once confirmed, this operation cannot be undone.", - "button": "Delete", - "confirm_title": "Remove Member", - "confirm_description": "Are you sure you want to remove this member from the organization?", - "confirm_button": "Remove", - "cancel_button": "Cancel", - "success": "Member has been removed from the organization." + "title": "${organization} からメンバーを削除", + "title_plural": "${organization} からメンバーを削除", + "description": "この組織から ${email} を削除してもよろしいですか?この操作によりアカウントは削除されませんが、アクセス権が取り消され、サインインできなくなります。", + "description_plural": "この組織から ${count} 人のメンバーを削除してもよろしいですか?この操作によりアカウントは削除されませんが、アクセス権が取り消され、サインインできなくなります。", + "confirm_button": "削除", + "cancel_button": "キャンセル", + "success": "${email} が ${organization} から削除されました。", + "success_plural": "選択されたメンバーが ${organization} から削除されました。" }, "delete_member": { - "title": "Delete this member", - "description": "Once confirmed, this operation cannot be undone.", - "button": "Delete", - "confirm_title": "Delete Member", - "confirm_description": "Are you sure you want to permanently delete this member? This action cannot be undone.", - "confirm_button": "Delete", - "cancel_button": "Cancel", - "success": "Member has been deleted." + "title": "メンバーを削除", + "title_plural": "メンバーを削除", + "description": "${email} を削除してもよろしいですか?この操作は取り消せません。", + "description_plural": "${count} 人のメンバーを削除してもよろしいですか?この操作は取り消せません。", + "confirm_button": "削除", + "cancel_button": "キャンセル", + "success": "${email} が削除されました。", + "success_plural": "選択されたメンバーが削除されました。" } }, "roles": { - "title": "Roles", - "description": "Manage user roles and permissions when accessing ${appName}.", - "assign_button": "Assign Roles", + "title": "ロール", + "description": "${appName} にアクセスする際のユーザーのロールと権限を管理します。", + "assign_button": "ロールを割り当てる", + "no_roles_available": "このメンバーに割り当てられるロールはもうありません。", + "max_roles_reached": "このメンバーの最大登録数 ${max} に達しました。", + "remove_button": "ロールを削除", + "remove_button_plural": "ロールを削除", "table": { - "name": "Name", - "description": "Description", - "empty_message": "No roles assigned." + "name": "名前", + "description": "説明", + "empty_message": "割り当てられたロールはありません。" }, "assign_modal": { - "title": "Assign Roles", - "roles_label": "Roles", - "roles_placeholder": "Select roles", - "submit_button": "Assign", - "cancel_button": "Cancel", - "no_roles_available": "All available roles are already assigned." + "title": "ロールを割り当てる", + "roles_label": "ロール", + "roles_placeholder": "ロールを選択", + "submit_button": "割り当て", + "cancel_button": "キャンセル", + "no_roles_available": "利用可能なすべてのロールがすでに割り当てられています。", + "success": "ロールが割り当てられました。", + "success_plural": "ロールが割り当てられました。" }, "remove_confirm": { - "title": "Remove Role", - "description": "Are you sure you want to remove the role ${roleName} from this member?", - "confirm_button": "Remove", - "cancel_button": "Cancel" + "title": "メンバーからロールを削除しますか?", + "title_plural": "メンバーからロールを削除しますか?", + "description": "\"${memberName}\" から ${roleName} ロールを削除します。", + "confirm_button": "削除", + "cancel_button": "キャンセル", + "success": "\"${roleName}\" ロールがメンバーから削除されました。" } }, "error": { - "fetch_failed": "Failed to load member details. Please try again.", - "fetch_roles_failed": "Failed to load member roles. Please try again.", - "remove_from_org_failed": "Failed to remove member from organization. Please try again.", - "delete_failed": "Failed to delete member. Please try again.", - "assign_role_failed": "Failed to assign role. Please try again.", - "remove_role_failed": "Failed to remove role. Please try again." + "fetch_failed": "メンバー詳細の読み込みに失敗しました。もう一度お試しください。", + "fetch_roles_failed": "メンバーのロールの読み込みに失敗しました。もう一度お試しください。", + "remove_from_org_failed": "組織からのメンバーの削除に失敗しました。もう一度お試しください。", + "delete_failed": "メンバーの削除に失敗しました。もう一度お試しください。", + "assign_role_failed": "ロールの割り当てに失敗しました。もう一度お試しください。", + "remove_role_failed": "ロールの削除に失敗しました。もう一度お試しください。" } } }, From 6c8ea1a62a77fe70ba79a76e728284627e536ff2 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Wed, 8 Apr 2026 16:47:22 +0530 Subject: [PATCH 014/125] feat(core, react): add service, react types, and invitation components --- auth0-myorganization-js-1.0.0-beta.4.tgz | Bin 0 -> 179690 bytes .../src/services/my-organization/index.ts | 1 + .../member-management-types.ts | 111 +++++++ .../organization-invitation-details-modal.tsx | 250 +++++++++++++++ .../organization-invitation-revoke-modal.tsx | 92 ++++++ ...zation-invitation-table-actions-column.tsx | 114 +++++++ .../organization-invitation-table.tsx | 188 +++++++++++ .../organization-invitation-create-modal.tsx | 302 ++++++++++++++++++ .../shared/search-filter/search-filter.tsx | 83 +++++ .../member-management-utils.ts | 25 ++ packages/react/src/types/index.ts | 2 + .../organization-invitation-table-types.ts | 213 ++++++++++++ .../organization-member-management-types.ts | 147 +++++++++ pnpm-lock.yaml | 15 +- 14 files changed, 1536 insertions(+), 7 deletions(-) create mode 100644 auth0-myorganization-js-1.0.0-beta.4.tgz create mode 100644 packages/core/src/services/my-organization/member-management/member-management-types.ts create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx create mode 100644 packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts create mode 100644 packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts create mode 100644 packages/react/src/types/my-organization/member-management/organization-member-management-types.ts diff --git a/auth0-myorganization-js-1.0.0-beta.4.tgz b/auth0-myorganization-js-1.0.0-beta.4.tgz new file mode 100644 index 0000000000000000000000000000000000000000..b6675e14dc53667955b082e2dcbbd041093ed61d GIT binary patch literal 179690 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�ML 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 literal 0 HcmV?d00001 diff --git a/packages/core/src/services/my-organization/index.ts b/packages/core/src/services/my-organization/index.ts index deb30e8e6..5e1816d52 100644 --- a/packages/core/src/services/my-organization/index.ts +++ b/packages/core/src/services/my-organization/index.ts @@ -7,4 +7,5 @@ export * from './organization-management'; export * from './idp-management'; export * from './domain-management'; +export * from './member-management/member-management-types'; export * from './config'; diff --git a/packages/core/src/services/my-organization/member-management/member-management-types.ts b/packages/core/src/services/my-organization/member-management/member-management-types.ts new file mode 100644 index 000000000..7c7561743 --- /dev/null +++ b/packages/core/src/services/my-organization/member-management/member-management-types.ts @@ -0,0 +1,111 @@ +/** + * Member management type definitions for organization member and invitation operations. + * @module member-management-types + * @internal + */ +import type { MyOrganization } from '@auth0/myorganization-js'; + +/** + * Organization member ID type. + */ +export type OrgMemberId = MyOrganization.OrgMemberId; + +/** + * Organization member entity. + */ +export type OrgMember = MyOrganization.OrgMember; + +/** + * Organization member role. + */ +export type OrgMemberRole = MyOrganization.OrgMemberRole; + +/** + * Organization member role ID. + */ +export type OrgMemberRoleId = MyOrganization.OrgMemberRoleId; + +/** + * Response content for listing organization members. + */ +export type ListOrganizationMembersResponseContent = + MyOrganization.ListOrganizationMembersResponseContent; + +/** + * Response content for getting a single organization member. + */ +export type GetOrganizationMemberResponseContent = + MyOrganization.GetOrganizationMemberResponseContent; + +/** + * Request parameters for listing organization members. + */ +export type ListOrganizationMembersRequestParameters = + MyOrganization.ListOrganizationMembersRequestParameters; + +/** + * Response content for getting organization member roles. + */ +export type GetOrganizationMemberRolesResponseContent = + MyOrganization.GetOrganizationMemberRolesResponseContent; + +/** + * Request content for assigning a role to an organization member. + */ +export type AssignOrganizationMemberRoleRequestContent = + MyOrganization.AssignOrganizationMemberRoleRequestContent; + +/** + * Response content for assigning a role to an organization member. + */ +export type AssignOrganizationMemberRoleResponseContent = + MyOrganization.AssignOrganizationMemberRoleResponseContent; + +/** + * Invitation ID type. + */ +export type InvitationId = MyOrganization.InvitationId; + +/** + * Member invitation entity. + */ +export type MemberInvitation = MyOrganization.MemberInvitation; + +/** + * Member invitation invitee details. + */ +export type MemberInvitationInvitee = MyOrganization.MemberInvitationInvitee; + +/** + * Member invitation inviter details. + */ +export type MemberInvitationInviter = MyOrganization.MemberInvitationInviter; + +/** + * Response content for listing member invitations. + */ +export type ListMembersInvitationsResponseContent = + MyOrganization.ListMembersInvitationsResponseContent; + +/** + * Request parameters for listing member invitations. + */ +export type ListMemberInvitationsRequestParameters = + MyOrganization.ListMemberInvitationsRequestParameters; + +/** + * Request content for creating a member invitation. + */ +export type CreateMemberInvitationRequestContent = + MyOrganization.CreateMemberInvitationRequestContent; + +/** + * Response content for creating a member invitation. + */ +export type CreateMemberInvitationResponseContent = + MyOrganization.CreateMemberInvitationResponseContent; + +/** + * Response content for getting a member invitation. + */ +export type GetMemberInvitationResponseContent = MyOrganization.GetMemberInvitationResponseContent; diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx new file mode 100644 index 000000000..71897a038 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal.tsx @@ -0,0 +1,250 @@ +/** + * Organization invitation details modal component. + * @module organization-invitation-details-modal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; +import { Link } from 'lucide-react'; +import * as React from 'react'; + +import { CopyableTextField } from '@/components/auth0/shared/copyable-text-field'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Label } from '@/components/ui/label'; +import { TextField } from '@/components/ui/text-field'; +import { TextFieldGroup } from '@/components/ui/text-field-group'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { getInvitationStatus } from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { + InvitationStatus, + RoleOption, + IdentityProviderOption, + OrganizationInvitationTabMessages, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export interface OrganizationInvitationDetailsModalProps { + invitation: MemberInvitation | null; + isOpen: boolean; + isRevoking?: boolean; + isResending?: boolean; + customMessages?: Partial; + availableRoles?: RoleOption[]; + availableProviders?: IdentityProviderOption[]; + readOnly?: boolean; + onClose: () => void; + onCopyUrl?: (invitation: MemberInvitation) => void; + onRevoke?: (invitation?: MemberInvitation) => void; + onResend?: (invitation?: MemberInvitation) => void; + className?: string; +} + +/** + * Returns the badge variant for a given invitation status. + * @param status - The invitation status. + * @returns The badge variant string. + */ +function getStatusBadgeVariant(status: InvitationStatus): 'warning' | 'destructive' { + return status === 'pending' ? 'warning' : 'destructive'; +} + +/** + * Modal for viewing invitation details with revoke and resend actions. + * @param props - The component props. + * @param props.invitation - The invitation to display. + * @param props.isOpen - Whether the modal is open. + * @param props.isRevoking - Whether a revoke action is in progress. + * @param props.isResending - Whether a resend action is in progress. + * @param props.customMessages - Custom translation messages. + * @param props.availableRoles - Available roles for display. + * @param props.availableProviders - Available providers for display. + * @param props.readOnly - Whether in read-only mode. + * @param props.onClose - Callback when modal is closed. + * @param props.onCopyUrl - Callback when copy URL is clicked. + * @param props.onRevoke - Callback when revoke is clicked. + * @param props.onResend - Callback when revoke and resend is clicked. + * @param props.className - Optional CSS class name. + * @returns The modal component. + */ +export function OrganizationInvitationDetailsModal({ + invitation, + isOpen, + isRevoking = false, + isResending = false, + customMessages = {}, + availableRoles = [], + availableProviders = [], + readOnly = false, + onClose, + onCopyUrl, + onRevoke, + onResend, + className, +}: OrganizationInvitationDetailsModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const status = invitation ? getInvitationStatus(invitation) : 'pending'; + const isPending = status === 'pending'; + const isActionInProgress = isRevoking || isResending; + + const roleNames = React.useMemo(() => { + if (!invitation?.roles || invitation.roles.length === 0) return []; + return invitation.roles + .map((roleId) => { + const role = availableRoles.find((r) => r.id === roleId); + return role?.name ?? roleId; + }) + .filter(Boolean); + }, [invitation?.roles, availableRoles]); + + const providerName = React.useMemo(() => { + if (!invitation?.identity_provider_id) return null; + const provider = availableProviders.find((p) => p.id === invitation.identity_provider_id); + return provider?.name ?? invitation.identity_provider_id; + }, [invitation?.identity_provider_id, availableProviders]); + + const handleCopyUrl = React.useCallback(() => { + if (invitation) { + onCopyUrl?.(invitation); + } + }, [invitation, onCopyUrl]); + + const handleRevoke = React.useCallback(() => { + if (invitation) { + onRevoke?.(invitation); + } + }, [invitation, onRevoke]); + + const handleResend = React.useCallback(() => { + if (invitation) { + onResend?.(invitation); + } + }, [invitation, onResend]); + + return ( + + + +
    + {t('invitation.details.title')} + + {isPending + ? t('invitation.table.status_pending') + : t('invitation.table.status_expired')} + +
    + {t('invitation.details.title')} +
    + +
    + {/* Email */} +
    + + +
    + + {/* Created At */} +
    + + +
    + + {/* Expires At */} +
    + + +
    + + {/* Roles */} +
    + + {roleNames.length > 0 ? ( + ({ label: name, value: name }))} + summarizeChips={false} + disabled + readOnly + /> + ) : ( + + )} +
    + + {/* Invitation URL */} + {invitation?.invitation_url && ( +
    + + } + /> +
    + )} + + {/* Revoke / Resend Actions (inline, below invitation URL) */} + {!readOnly && ( +
    + + +
    + )} + + {/* Invited By */} +
    + + +
    + + {/* Identity Provider */} + {providerName && ( +
    + + +
    + )} +
    + + + + +
    +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx new file mode 100644 index 000000000..43132ae07 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal.tsx @@ -0,0 +1,92 @@ +/** + * Organization invitation revoke modal component. + * @module organization-invitation-revoke-modal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationInvitationTabMessages } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export interface OrganizationInvitationRevokeModalProps { + invitation: MemberInvitation | null; + isOpen: boolean; + isLoading?: boolean; + isRevokeAndResend?: boolean; + customMessages?: Partial; + onClose: () => void; + onConfirm: (invitation: MemberInvitation) => void; + className?: string; +} + +/** + * Modal for confirming invitation revocation or revoke and resend. + * @param props - The component props. + * @param props.invitation - The invitation to revoke. + * @param props.isOpen - Whether the modal is open. + * @param props.isLoading - Whether the action is in progress. + * @param props.isRevokeAndResend - Whether this is a revoke and resend action. + * @param props.customMessages - Custom translation messages. + * @param props.onClose - Callback when modal is closed. + * @param props.onConfirm - Callback when action is confirmed. + * @param props.className - Optional CSS class name. + * @returns The modal component. + */ +export function OrganizationInvitationRevokeModal({ + invitation, + isOpen, + isLoading = false, + isRevokeAndResend = false, + customMessages = {}, + onClose, + onConfirm, + className, +}: OrganizationInvitationRevokeModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const namespace = isRevokeAndResend ? 'invitation.revoke_resend' : 'invitation.revoke'; + + const handleConfirm = React.useCallback(() => { + if (invitation) { + onConfirm(invitation); + } + }, [invitation, onConfirm]); + + return ( + + + + {t(`${namespace}.title`)} + + + <> + {t.trans(`${namespace}.description`, { + components: { + bold: (children: string) => {children}, + }, + vars: { email: invitation?.invitee?.email ?? '' }, + })} + + + + + + + + + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx new file mode 100644 index 000000000..2757176db --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column.tsx @@ -0,0 +1,114 @@ +/** + * Organization invitation table row actions dropdown. + * @module organization-invitation-table-actions-column + * @internal + */ + +import { MoreHorizontal, Eye, Copy, RefreshCcw, Trash2 } from 'lucide-react'; +import * as React from 'react'; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + DropdownMenuPortal, + DropdownMenuSeparator, +} from '@/components/ui/dropdown-menu'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { getInvitationStatus } from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { OrganizationInvitationTableActionsColumnProps } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * OrganizationInvitationTableActionsColumn Component + * Handles the actions column for Invitation table with dropdown menu. + * @param props - Component props. + * @param props.invitation - The invitation to show actions for. + * @param props.customMessages - Custom translation messages to override defaults. + * @param props.readOnly - Whether the component is in read-only mode. + * @param props.onViewDetails - Callback fired when view details action is triggered. + * @param props.onCopyUrl - Callback fired when copy URL action is triggered. + * @param props.onRevokeAndResend - Callback fired when revoke and resend action is triggered. + * @param props.onRevoke - Callback fired when revoke action is triggered. + * @returns JSX element. + */ +export function OrganizationInvitationTableActionsColumn({ + invitation, + customMessages = {}, + readOnly = false, + onViewDetails, + onCopyUrl, + onRevokeAndResend, + onRevoke, +}: OrganizationInvitationTableActionsColumnProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + const status = getInvitationStatus(invitation); + const isPending = status === 'pending'; + + const handleViewDetails = React.useCallback(() => { + onViewDetails?.(invitation); + }, [invitation, onViewDetails]); + + const handleCopyUrl = React.useCallback(() => { + onCopyUrl?.(invitation); + }, [invitation, onCopyUrl]); + + const handleRevokeAndResend = React.useCallback(() => { + onRevokeAndResend?.(invitation); + }, [invitation, onRevokeAndResend]); + + const handleRevoke = React.useCallback(() => { + onRevoke?.(invitation); + }, [invitation, onRevoke]); + + return ( +
    + + + + {t('invitation.actions.menu_label')} + + + + {/* View Details - always available */} + + + {t('invitation.actions.view_details')} + + + {/* Copy URL - only for pending invitations with URL */} + {isPending && invitation.invitation_url && ( + + + {t('invitation.actions.copy_url')} + + )} + + {!readOnly && ( + + + {t('invitation.actions.revoke_and_resend')} + + )} + + {!readOnly && ( + <> + + + + {t('invitation.actions.revoke')} + + + )} + + + +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx new file mode 100644 index 000000000..f68ba2ef0 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx @@ -0,0 +1,188 @@ +/** + * Organization invitation table component. + * @module organization-invitation-table + * @internal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { OrganizationInvitationTableActionsColumn } from './organization-invitation-table-actions-column'; + +import { SearchFilter } from '@/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter'; +import { DataPagination } from '@/components/auth0/shared/data-pagination'; +import { DataTable, type Column } from '@/components/auth0/shared/data-table'; +import { Badge } from '@/components/ui/badge'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { cn } from '@/lib/utils'; +import { getInvitationStatus } from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { OrganizationInvitationTableProps } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * Organization invitation table component. + * Displays invitations with search, filtering, and pagination. + * @param props - The component props. + * @param props.invitations - The list of invitations to display. + * @param props.loading - Whether the table is loading. + * @param props.customMessages - Custom translation messages. + * @param props.pagination - Pagination state. + * @param props.filters - Current filter state. + * @param props.availableRoles - Available roles for filtering. + * @param props.readOnly - Whether the component is in read-only mode. + * @param props.onView - Callback when viewing invitation details. + * @param props.onCopyUrl - Callback when copying invitation URL. + * @param props.onRevokeAndResend - Callback when revoking and resending invitation. + * @param props.onRevoke - Callback when revoking invitation. + * @param props.onPageChange - Callback when page changes. + * @param props.onPageSizeChange - Callback when page size changes. + * @param props.onRoleFilterChange - Callback when role filter changes. + * @param props.className - Optional CSS class name. + * @returns The invitation table component. + */ +export function OrganizationInvitationTable({ + invitations, + loading = false, + customMessages = {}, + pagination, + filters, + availableRoles, + readOnly = false, + sortConfig, + onSortChange, + onView, + onCopyUrl, + onRevokeAndResend, + onRevoke, + onNextPage, + onPreviousPage, + onPageSizeChange, + onRoleFilterChange, + className, +}: OrganizationInvitationTableProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const renderDate = (_invitation: MemberInvitation, value: string | number | Date) => ( + + {new Date(value).toLocaleString(undefined, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + })} + + ); + + const columns: Column[] = React.useMemo( + () => [ + { + type: 'text', + accessorKey: 'invitee', + title: t('invitation.table.columns.email'), + enableSorting: false, + render: (invitation) => ( +
    {invitation.invitee?.email}
    + ), + }, + { + type: 'text', + accessorKey: 'organization_id', + title: t('invitation.table.columns.status'), + enableSorting: false, + render: (invitation) => { + const status = getInvitationStatus(invitation); + return ( + + {status === 'pending' + ? t('invitation.table.status_pending') + : t('invitation.table.status_expired')} + + ); + }, + }, + { + type: 'date', + accessorKey: 'created_at', + title: t('invitation.table.columns.created_at'), + enableSorting: true, + format: 'medium', + render: renderDate, + }, + { + type: 'date', + accessorKey: 'expires_at', + title: t('invitation.table.columns.expires_at'), + enableSorting: false, + format: 'medium', + render: renderDate, + }, + { + type: 'text', + accessorKey: 'inviter', + title: t('invitation.table.columns.inviter'), + enableSorting: false, + render: (invitation) => ( + {invitation.inviter?.name ?? '-'} + ), + }, + { + type: 'actions', + title: '', + enableSorting: false, + render: (invitation) => ( + + ), + }, + ], + [t, customMessages, readOnly, onView, onCopyUrl, onRevokeAndResend, onRevoke], + ); + + return ( +
    + + + + + {invitations.length > 0 && ( +
    + +
    + )} +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx new file mode 100644 index 000000000..2ad901088 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx @@ -0,0 +1,302 @@ +/** + * Organization invitation create modal component. + * @module organization-invitation-create-modal + */ + +import { + createInvitationCreateSchema, + type InvitationCreateSchemas, +} from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { Combobox } from '@/components/ui/combobox'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { TextFieldGroup } from '@/components/ui/text-field-group'; +import type { ChipItem } from '@/components/ui/text-field-group'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + CreateInvitationInput, + RoleOption, + IdentityProviderOption, + OrganizationInvitationTabMessages, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export interface OrganizationInvitationCreateModalProps { + isOpen: boolean; + isLoading?: boolean; + customMessages?: Partial; + availableRoles?: RoleOption[]; + availableProviders?: IdentityProviderOption[]; + inviterName?: string; + schema?: InvitationCreateSchemas; + onClose: () => void; + onCreate: (data: CreateInvitationInput) => void; + className?: string; +} + +/** + * Modal for creating a new invitation. + * Supports multiple email addresses, role selection, and provider selection. + * Validation rules can be overridden via the `schema` prop. + * + * @param props - The component props. + * @param props.isOpen - Whether the modal is open. + * @param props.isLoading - Whether the form is loading. + * @param props.customMessages - Custom translation messages. + * @param props.availableRoles - Available roles for selection. + * @param props.availableProviders - Available identity providers. + * @param props.inviterName - Name of the person sending the invitation. + * @param props.schema - Schema overrides for validation (email regex, maxEmails, error messages). + * @param props.onClose - Callback when modal is closed. + * @param props.onCreate - Callback when invitation is created. + * @param props.className - Optional CSS class name. + * @returns The modal component. + */ +export function OrganizationInvitationCreateModal({ + isOpen, + isLoading = false, + customMessages = {}, + availableRoles = [], + availableProviders = [], + inviterName, + schema, + onClose, + onCreate, + className, +}: OrganizationInvitationCreateModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const validationConfig = React.useMemo( + () => createInvitationCreateSchema(schema, t('invitation.create.email_invalid_error')), + [schema, t], + ); + + const [emailInput, setEmailInput] = React.useState(''); + const [emailChips, setEmailChips] = React.useState([]); + const [selectedRoles, setSelectedRoles] = React.useState([]); + const [selectedProvider, setSelectedProvider] = React.useState(); + const [emailError, setEmailError] = React.useState(); + + const handleEmailInputChange = React.useCallback((e: React.ChangeEvent) => { + setEmailInput(e.target.value); + setEmailError(undefined); + }, []); + + const hasInvalidChips = React.useMemo( + () => emailChips.some((chip) => chip.variant === 'destructive'), + [emailChips], + ); + + const handleEmailChipAdd = React.useCallback( + (value: string) => { + const trimmedEmail = value.trim().replace(/,/g, ''); + + if (!trimmedEmail) return; + + if (emailChips.length >= validationConfig.maxEmails) { + setEmailError(t('invitation.create.email_limit_error')); + return; + } + + if (emailChips.some((chip) => chip.value === trimmedEmail)) { + setEmailError(t('invitation.create.email_duplicate_error')); + return; + } + + const result = validationConfig.emailSchema.safeParse(trimmedEmail); + if (!result.success) { + setEmailChips((prev) => [ + ...prev, + { label: trimmedEmail, value: trimmedEmail, variant: 'destructive' }, + ]); + setEmailInput(''); + setEmailError(t('invitation.create.email_invalid_error')); + return; + } + + setEmailChips((prev) => [...prev, { label: trimmedEmail, value: trimmedEmail }]); + setEmailInput(''); + setEmailError(undefined); + }, + [emailChips, validationConfig, t], + ); + + const handleEmailChipRemove = React.useCallback((value: string) => { + setEmailChips((prev) => { + const updated = prev.filter((chip) => chip.value !== value); + if (!updated.some((chip) => chip.variant === 'destructive')) { + setEmailError(undefined); + } + return updated; + }); + }, []); + + const handleRoleChange = React.useCallback((value: string | string[]) => { + setSelectedRoles(Array.isArray(value) ? value : value ? [value] : []); + }, []); + + const handleProviderChange = React.useCallback((value: string) => { + setSelectedProvider(value || undefined); + }, []); + + const handleSubmit = React.useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + + // Add any remaining input to emails + const finalEmails = emailChips.map((chip) => chip.value); + if (emailInput.trim()) { + const trimmedEmail = emailInput.trim(); + const result = validationConfig.emailSchema.safeParse(trimmedEmail); + if (result.success && !finalEmails.includes(trimmedEmail)) { + finalEmails.push(trimmedEmail); + } + } + + if (finalEmails.length === 0) { + setEmailError(t('invitation.create.email_required_error')); + return; + } + + // Create invitations for each email + for (const email of finalEmails) { + const invitationData: CreateInvitationInput = { + invitee: { email }, + roles: selectedRoles.length > 0 ? selectedRoles : undefined, + identity_provider_id: selectedProvider, + }; + + if (inviterName) { + invitationData.inviter = { name: inviterName }; + } + + onCreate(invitationData); + } + }, + [ + emailChips, + emailInput, + validationConfig, + selectedRoles, + selectedProvider, + inviterName, + onCreate, + t, + ], + ); + + const handleClose = React.useCallback(() => { + setEmailInput(''); + setEmailChips([]); + setSelectedRoles([]); + setSelectedProvider(undefined); + setEmailError(undefined); + onClose(); + }, [onClose]); + + const canSubmit = React.useMemo( + () => + !hasInvalidChips && + (emailChips.length > 0 || + (emailInput.trim() !== '' && + validationConfig.emailSchema.safeParse(emailInput.trim()).success)), + [emailChips.length, emailInput, validationConfig, hasInvalidChips], + ); + + const roleOptions = React.useMemo( + () => availableRoles.map((role) => ({ label: role.name, value: role.id })), + [availableRoles], + ); + + return ( + + +
    + + {t('invitation.create.title')} + {t('invitation.create.description')} + + +
    + {/* Email Input */} +
    + + +

    {t('invitation.create.email_helper')}

    + {emailError &&

    {emailError}

    } +
    + + {/* Roles Combobox */} +
    + + +
    + + {/* Provider Dropdown */} +
    + + +

    + {t('invitation.create.provider_helper')} +

    +
    +
    + + + + + +
    +
    +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx new file mode 100644 index 000000000..73612ad9a --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx @@ -0,0 +1,83 @@ +/** + * Search and filter component for invitations. + * @module search-filter + * @internal + */ + +import { X } from 'lucide-react'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { SearchFilterProps } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * Filter bar for invitation table. + * Shows a right-aligned role filter dropdown with a reset button. + * @param props - The component props. + * @param props.filters - Current filter state. + * @param props.availableRoles - Available roles for filtering. + * @param props.customMessages - Custom translation messages. + * @param props.className - Optional CSS class name. + * @param props.onRoleFilterChange - Callback fired when role filter changes. + * @returns The filter bar component. + */ +export function SearchFilter({ + filters, + availableRoles = [], + customMessages = {}, + className, + onRoleFilterChange, +}: SearchFilterProps): React.JSX.Element | null { + const { t } = useTranslator('member_management', customMessages); + + const handleRoleFilterChange = React.useCallback( + (value: string) => { + onRoleFilterChange?.(value === 'all' ? undefined : value); + }, + [onRoleFilterChange], + ); + + const handleReset = React.useCallback(() => { + onRoleFilterChange?.(undefined); + }, [onRoleFilterChange]); + + const hasActiveFilter = !!filters?.roleId; + + if (availableRoles.length === 0) { + return null; + } + + return ( +
    + + + +
    + ); +} diff --git a/packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts b/packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts new file mode 100644 index 000000000..9f6c24379 --- /dev/null +++ b/packages/react/src/lib/utils/my-organization/member-management/member-management-utils.ts @@ -0,0 +1,25 @@ +/** + * Member management utility functions. + * @module member-management-utils + * @internal + */ + +import type { MemberInvitation } from '@auth0/universal-components-core'; + +import type { InvitationStatus } from '@/types/my-organization/member-management/organization-invitation-table-types'; + +/** + * Determines the status of an invitation based on `expires_at`. + * @param invitation - The invitation to check. + * @returns The invitation status. + */ +export function getInvitationStatus(invitation: MemberInvitation): InvitationStatus { + if (invitation.expires_at) { + const expiresAt = new Date(invitation.expires_at); + if (expiresAt < new Date()) { + return 'expired'; + } + } + + return 'pending'; +} diff --git a/packages/react/src/types/index.ts b/packages/react/src/types/index.ts index e88c10c02..844caff99 100644 --- a/packages/react/src/types/index.ts +++ b/packages/react/src/types/index.ts @@ -25,3 +25,5 @@ export * from './my-organization/idp-management/sso-provisioning/provisioning-to export * from './my-organization/idp-management/sso-provisioning/sso-provisioning-tab-types'; export * from './my-organization/organization-management/organization-details-edit-types'; export * from './my-organization/organization-management/organization-details-types'; +export * from './my-organization/member-management/organization-invitation-table-types'; +export * from './my-organization/member-management/organization-member-management-types'; diff --git a/packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts b/packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts new file mode 100644 index 000000000..1496d3c25 --- /dev/null +++ b/packages/react/src/types/my-organization/member-management/organization-invitation-table-types.ts @@ -0,0 +1,213 @@ +/** + * Organization invitation table types. + * @module organization-invitation-table-types + */ + +import type { + SharedComponentProps, + ComponentAction, + MemberInvitation, +} from '@auth0/universal-components-core'; + +/** Invitation status. */ +export type InvitationStatus = 'pending' | 'expired'; + +/** Role option for invitation. */ +export interface RoleOption { + id: string; + name: string; + description?: string; +} + +/** Identity provider option for invitation. */ +export interface IdentityProviderOption { + id: string; + name: string; + type?: string; +} + +/** Input for creating an invitation. */ +export interface CreateInvitationInput { + invitee: { + email: string; + }; + inviter?: { + name?: string; + }; + roles?: string[]; + identity_provider_id?: string; + /** Time to live in seconds */ + ttl_sec?: number; +} + +/** Pagination state for invitation table (checkpoint-based). */ +export interface InvitationPaginationState { + pageSize: number; + currentPage: number; + totalItems?: number; + hasNextPage: boolean; + hasPreviousPage: boolean; +} + +/** Sort configuration for invitation table. */ +export interface InvitationSortConfig { + key: string | null; + direction: 'asc' | 'desc'; +} + +/** Filter state for invitation table. */ +export interface InvitationFilterState { + searchQuery?: string; + roleId?: string; +} + +/** CSS classes for OrganizationInvitationTab. */ +export interface OrganizationInvitationTabClasses { + 'OrganizationInvitationTab-root'?: string; + 'OrganizationInvitationTab-table'?: string; + 'OrganizationInvitationTab-createModal'?: string; + 'OrganizationInvitationTab-detailsModal'?: string; + 'OrganizationInvitationTab-revokeModal'?: string; + 'OrganizationInvitationTab-revokeResendModal'?: string; + 'OrganizationInvitationTab-searchInput'?: string; + 'OrganizationInvitationTab-filterDropdown'?: string; + 'OrganizationInvitationTab-pagination'?: string; +} + +/** OrganizationInvitationTab translation messages. */ +export interface OrganizationInvitationTabMessages { + table?: { + columns?: { + email?: string; + status?: string; + inviter?: string; + created_at?: string; + expires_at?: string; + roles?: string; + }; + empty_message?: string; + search_placeholder?: string; + filter_by_role?: string; + all_roles?: string; + reset_filter?: string; + showing_results?: string; + status_pending?: string; + status_expired?: string; + }; + actions?: { + menu_label?: string; + view_details?: string; + copy_url?: string; + revoke_and_resend?: string; + revoke?: string; + }; + create?: { + title?: string; + description?: string; + email_label?: string; + email_placeholder?: string; + email_helper?: string; + email_limit_error?: string; + email_invalid_error?: string; + email_duplicate_error?: string; + email_required_error?: string; + roles_label?: string; + roles_placeholder?: string; + provider_label?: string; + provider_placeholder?: string; + submit_button?: string; + creating?: string; + cancel_button?: string; + }; + details?: { + title?: string; + email_label?: string; + status_label?: string; + roles_label?: string; + provider_label?: string; + created_at_label?: string; + expires_at_label?: string; + invited_by_label?: string; + invitation_url_label?: string; + copy_url_button?: string; + close_button?: string; + revoke_button?: string; + resend_button?: string; + }; + revoke?: { + title?: string; + description?: string; + confirm_button?: string; + cancel_button?: string; + }; + revoke_resend?: { + title?: string; + description?: string; + confirm_button?: string; + cancel_button?: string; + }; + success?: { + url_copied?: string; + invitation_resent?: string; + }; + error?: { + fetch_failed?: string; + create_failed?: string; + revoke_failed?: string; + resend_failed?: string; + revoke_resend_failed?: string; + copy_url_failed?: string; + }; +} + +/** Props for OrganizationInvitationTab component. */ +export interface OrganizationInvitationTabProps + extends SharedComponentProps< + OrganizationInvitationTabMessages, + OrganizationInvitationTabClasses + > { + createAction?: ComponentAction; + revokeAction?: ComponentAction; +} + +/** Props for OrganizationInvitationTableActionsColumn component. */ +export interface OrganizationInvitationTableActionsColumnProps { + invitation: MemberInvitation; + customMessages?: Partial; + readOnly?: boolean; + onViewDetails?: (invitation: MemberInvitation) => void; + onCopyUrl?: (invitation: MemberInvitation) => void; + onRevokeAndResend?: (invitation: MemberInvitation) => void; + onRevoke?: (invitation: MemberInvitation) => void; +} + +/** Props for OrganizationInvitationTable component. */ +export interface OrganizationInvitationTableProps { + invitations: MemberInvitation[]; + loading?: boolean; + customMessages?: Partial; + pagination: InvitationPaginationState; + filters?: InvitationFilterState; + sortConfig?: InvitationSortConfig; + availableRoles?: RoleOption[]; + readOnly?: boolean; + onView?: (invitation: MemberInvitation) => void; + onCopyUrl?: (invitation: MemberInvitation) => void; + onRevokeAndResend?: (invitation: MemberInvitation) => void; + onRevoke?: (invitation: MemberInvitation) => void; + onNextPage?: () => void; + onPreviousPage?: () => void; + onPageSizeChange?: (pageSize: number) => void; + onSortChange?: (sortConfig: InvitationSortConfig) => void; + onRoleFilterChange?: (roleId: string | undefined) => void; + className?: string; +} + +/** Props for SearchFilter component. */ +export interface SearchFilterProps { + filters?: InvitationFilterState; + availableRoles?: RoleOption[]; + customMessages?: Partial; + className?: string; + onRoleFilterChange?: (roleId: string | undefined) => void; +} diff --git a/packages/react/src/types/my-organization/member-management/organization-member-management-types.ts b/packages/react/src/types/my-organization/member-management/organization-member-management-types.ts new file mode 100644 index 000000000..07a18b42d --- /dev/null +++ b/packages/react/src/types/my-organization/member-management/organization-member-management-types.ts @@ -0,0 +1,147 @@ +/** + * Organization member management types. + * @module organization-member-management-types + */ + +import type { + ComponentAction, + SharedComponentProps, + MemberInvitation, +} from '@auth0/universal-components-core'; +import type { UseMutationResult, UseQueryResult } from '@tanstack/react-query'; + +import type { + CreateInvitationInput, + IdentityProviderOption, + InvitationFilterState, + InvitationPaginationState, + InvitationSortConfig, + OrganizationInvitationTabClasses, + OrganizationInvitationTabMessages, + RoleOption, +} from './organization-invitation-table-types'; + +export type ActiveTab = 'members' | 'invitations'; + +export interface TableQueryParams { + pageSize: number; + fromToken: string | undefined; + sortConfig: TSort; + filters: TFilter; +} + +export interface UseMemberManagementServiceOptions { + customMessages?: OrganizationMemberManagementMessages; + activeTab: ActiveTab; + createInvitationAction?: ComponentAction; + revokeInvitationAction?: ComponentAction; + resendInvitationAction?: ComponentAction; + invitationParams: TableQueryParams; +} + +export interface MemberManagementServiceResult { + providersQuery: UseQueryResult; + invitationsQuery: UseQueryResult<{ + invitations: MemberInvitation[]; + next: string | null; + total: number | undefined; + }>; + createInvitationMutation: UseMutationResult< + MemberInvitation | undefined, + Error, + CreateInvitationInput + >; + revokeInvitationMutation: UseMutationResult; + resendInvitationMutation: UseMutationResult< + MemberInvitation | undefined, + Error, + MemberInvitation + >; + fetchInvitationDetails: (invitationId: string) => Promise; +} + +export interface UseOrganizationMemberManagementOptions { + customMessages?: OrganizationMemberManagementMessages; + readOnly?: boolean; + /** Action hooks for invitation creation (onBefore/onAfter) */ + createInvitationAction?: ComponentAction; + /** Action hooks for invitation revocation (onBefore/onAfter) */ + revokeInvitationAction?: ComponentAction; + /** Action hooks for invitation revoke-and-resend (onBefore/onAfter) */ + resendInvitationAction?: ComponentAction; +} + +export interface UseOrganizationMemberManagementResult { + activeTab: ActiveTab; + isLoading: boolean; + availableRoles: RoleOption[]; + availableProviders: IdentityProviderOption[]; + + invitations: MemberInvitation[]; + isFetchingInvitations: boolean; + isCreatingInvitation: boolean; + isRevokingInvitation: boolean; + isResendingInvitation: boolean; + invitationPagination: InvitationPaginationState; + invitationFilters: InvitationFilterState; + invitationSortConfig: InvitationSortConfig; + showCreateModal: boolean; + showDetailsModal: boolean; + showRevokeModal: boolean; + showRevokeResendModal: boolean; + selectedInvitation: MemberInvitation | null; + + setActiveTab: (tab: ActiveTab) => void; + handleCreateClick: () => void; + handleCreateSubmit: (data: CreateInvitationInput) => void; + handleCreateCancel: () => void; + handleDetailsClick: (invitation: MemberInvitation) => void; + handleDetailsClose: () => void; + handleRevokeClick: (invitation: MemberInvitation) => void; + handleRevokeConfirm: () => void; + handleRevokeCancel: () => void; + handleRevokeResendClick: (invitation: MemberInvitation) => void; + handleRevokeResendConfirm: () => void; + handleRevokeResendCancel: () => void; + handleCopyUrl: (invitation: MemberInvitation) => Promise; + handleNextPage: () => void; + handlePreviousPage: () => void; + handlePageSizeChange: (pageSize: number) => void; + handleSortChange: (sortConfig: InvitationSortConfig) => void; + handleRoleFilterChange: (roleId: string | undefined) => void; +} + +/** CSS classes for OrganizationMemberManagement. */ +export interface OrganizationMemberManagementClasses extends OrganizationInvitationTabClasses { + 'OrganizationMemberManagement-root'?: string; + 'OrganizationMemberManagement-header'?: string; + 'OrganizationMemberManagement-tabs'?: string; +} + +/** OrganizationMemberManagement translation messages. */ +export interface OrganizationMemberManagementMessages { + header?: { + title?: string; + description?: string; + }; + tabs?: { + members?: string; + invitations?: string; + }; + invitation?: OrganizationInvitationTabMessages; +} + +/** Props for OrganizationMemberManagement component. */ +export interface OrganizationMemberManagementProps + extends SharedComponentProps< + OrganizationMemberManagementMessages, + OrganizationMemberManagementClasses + > { + hideHeader?: boolean; + /** Action hooks for invitation creation (onBefore/onAfter) */ + createInvitationAction?: ComponentAction; + /** Action hooks for invitation revocation (onBefore/onAfter) */ + revokeInvitationAction?: ComponentAction; + /** Action hooks for invitation revoke-and-resend (onBefore/onAfter) */ + resendInvitationAction?: ComponentAction; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1dd266d0..8d6842bd3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -548,8 +548,8 @@ importers: specifier: 1.0.0-beta.0 version: 1.0.0-beta.0 '@auth0/myorganization-js': - specifier: 1.0.0-beta.6 - version: 1.0.0-beta.6 + specifier: file:../../auth0-myorganization-js-1.0.0-beta.4.tgz + version: file:auth0-myorganization-js-1.0.0-beta.4.tgz zod: specifier: ^3.22.4 version: 3.25.76 @@ -733,9 +733,10 @@ packages: resolution: {integrity: sha512-slj0RtNfieNk1BC1ERrCQw65qMUVKU5qacbTc8BFH8R316CUpsOhZ2MIiV9l3VEkaqY1hmCZm03+ZI6ym+3PZg==} engines: {node: '>=18.0.0'} - '@auth0/myorganization-js@1.0.0-beta.6': - resolution: {integrity: sha512-pHqZ86E3+l1++Aw3TbPLRzuCkZYHlQnmdIJz/Ydij8FrGXfUhS3wDP9ZZrwHnPVXBw91pOhxQR5kOavAYRmi5w==} - engines: {node: '>=20.0.0'} + '@auth0/myorganization-js@file:auth0-myorganization-js-1.0.0-beta.4.tgz': + resolution: {integrity: sha512-yTZbJ0K75WsCGsb9bXBGTs32WLXEXqyTuM9lgmYST8uSag2ILfJdYZPQZkvyKM5v+7Sk5B9vz0mg3tNfv8SFNg==, tarball: file:auth0-myorganization-js-1.0.0-beta.4.tgz} + version: 1.0.0-beta.4 + engines: {node: '>=18.0.0'} '@auth0/nextjs-auth0@4.16.0': resolution: {integrity: sha512-QTQdK+/YL68J7b1tSdvJTT16+r+Dxwy/m0kwl73CEy/QsYCpHE1sCZYgQ4UaFZb5jHQ7d4R2JUkHN5k2fKQ4zg==} @@ -7363,7 +7364,7 @@ snapshots: '@auth0/myaccount-js@1.0.0-beta.0': {} - '@auth0/myorganization-js@1.0.0-beta.6': + '@auth0/myorganization-js@file:auth0-myorganization-js-1.0.0-beta.4.tgz': dependencies: '@auth0/auth0-auth-js': 1.5.0 @@ -12375,7 +12376,7 @@ snapshots: headers-polyfill: 4.0.3 is-node-process: 1.2.0 outvariant: 1.4.3 - path-to-regexp: 6.3.0 + path-to-regexp: 8.4.2 picocolors: 1.1.1 rettime: 0.7.0 strict-event-emitter: 0.5.1 From 53b1407460be03d013eac197a088bead9e49fc2b Mon Sep 17 00:00:00 2001 From: rax7389 Date: Wed, 8 Apr 2026 16:53:33 +0530 Subject: [PATCH 015/125] chore: update core package.json for myorganization-js --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index 497130fe8..b71882c24 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -52,7 +52,7 @@ }, "dependencies": { "@auth0/myaccount-js": "1.0.0-beta.0", - "@auth0/myorganization-js": "1.0.0-beta.6", + "@auth0/myorganization-js": "file:../../auth0-myorganization-js-1.0.0-beta.4.tgz", "zod": "^3.22.4" } } From 5b79311117f6cfd3dbb1a88c188205e2b0bd6b04 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Wed, 8 Apr 2026 16:54:15 +0530 Subject: [PATCH 016/125] feat(react, examples): add invitation hook, container, and example apps --- .../src/app/member-management/page.tsx | 21 ++ .../src/components/navigation/side-bar.tsx | 11 +- .../next-rwa/src/providers/i18n-provider.tsx | 1 + examples/react-spa-npm/src/App.tsx | 9 + .../react-spa-npm/src/components/side-bar.tsx | 11 +- .../src/views/member-management-page.tsx | 21 ++ examples/react-spa-shadcn/src/App.tsx | 9 + .../src/components/side-bar.tsx | 11 +- .../src/pages/MemberManagement.tsx | 23 ++ examples/scripts/utils/env-writer.mjs | 2 + examples/scripts/utils/resource-servers.mjs | 2 + .../organization-member-management.tsx | 244 +++++++++++++++ packages/react/src/components/index.ts | 1 + packages/react/src/hooks/index.ts | 3 + .../services/use-member-management-service.ts | 201 +++++++++++++ .../src/hooks/my-organization/use-config.ts | 6 + .../use-organization-member-management.ts | 282 ++++++++++++++++++ 17 files changed, 855 insertions(+), 3 deletions(-) create mode 100644 examples/next-rwa/src/app/member-management/page.tsx create mode 100644 examples/react-spa-npm/src/views/member-management-page.tsx create mode 100644 examples/react-spa-shadcn/src/pages/MemberManagement.tsx create mode 100644 packages/react/src/components/auth0/my-organization/organization-member-management.tsx create mode 100644 packages/react/src/hooks/my-organization/shared/services/use-member-management-service.ts create mode 100644 packages/react/src/hooks/my-organization/use-organization-member-management.ts diff --git a/examples/next-rwa/src/app/member-management/page.tsx b/examples/next-rwa/src/app/member-management/page.tsx new file mode 100644 index 000000000..7dcc22ec3 --- /dev/null +++ b/examples/next-rwa/src/app/member-management/page.tsx @@ -0,0 +1,21 @@ +'use client'; + +// import { OrganizationMemberManagement } from '@auth0/universal-components-react/rwa'; + +export default function MemberManagementPage() { + return ( +
    + ); +} diff --git a/examples/next-rwa/src/components/navigation/side-bar.tsx b/examples/next-rwa/src/components/navigation/side-bar.tsx index e9a45a6f1..0eb2407d3 100644 --- a/examples/next-rwa/src/components/navigation/side-bar.tsx +++ b/examples/next-rwa/src/components/navigation/side-bar.tsx @@ -1,7 +1,7 @@ 'use client'; import { useUser } from '@auth0/nextjs-auth0'; -import { Building, Settings, Shield, User } from 'lucide-react'; +import { Building, Settings, Shield, User, Users } from 'lucide-react'; import Link from 'next/link'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -74,6 +74,15 @@ export const Sidebar: React.FC = () => { {t('sidebar.identity-providers')} +
  • + + + {t('sidebar.members')} + +
  • diff --git a/examples/next-rwa/src/providers/i18n-provider.tsx b/examples/next-rwa/src/providers/i18n-provider.tsx index 793c0e42d..5312cc407 100644 --- a/examples/next-rwa/src/providers/i18n-provider.tsx +++ b/examples/next-rwa/src/providers/i18n-provider.tsx @@ -26,6 +26,7 @@ i18n.use(initReactI18next).init({ 'sidebar.organization-settings': 'Organization Settings', 'sidebar.domains': 'Domains', 'sidebar.identity-providers': 'Identity Providers', + 'sidebar.members': 'Members', }, }, }, diff --git a/examples/react-spa-npm/src/App.tsx b/examples/react-spa-npm/src/App.tsx index 08ec086e1..9b443b784 100644 --- a/examples/react-spa-npm/src/App.tsx +++ b/examples/react-spa-npm/src/App.tsx @@ -8,6 +8,7 @@ import { Navbar } from './components/nav-bar'; import { Sidebar } from './components/side-bar'; import DomainManagementPage from './views/domain-management-page'; import HomePage from './views/home-page'; +import MemberManagementPage from './views/member-management-page'; import MFAPage from './views/mfa-page'; import OrganizationManagementPage from './views/organization-management-page'; import ProfilePage from './views/profile-page'; @@ -101,6 +102,14 @@ function AppContent() { } /> + + + + } + /> diff --git a/examples/react-spa-npm/src/components/side-bar.tsx b/examples/react-spa-npm/src/components/side-bar.tsx index 402398c19..58ab2150e 100644 --- a/examples/react-spa-npm/src/components/side-bar.tsx +++ b/examples/react-spa-npm/src/components/side-bar.tsx @@ -1,4 +1,4 @@ -import { User, Building, Settings, Shield } from 'lucide-react'; +import { User, Building, Settings, Shield, Users } from 'lucide-react'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; @@ -70,6 +70,15 @@ export const Sidebar: React.FC = () => { {t('sidebar.domain-management')} +
  • + + + {t('sidebar.member-management')} + +
  • diff --git a/examples/react-spa-npm/src/views/member-management-page.tsx b/examples/react-spa-npm/src/views/member-management-page.tsx new file mode 100644 index 000000000..e9667f79d --- /dev/null +++ b/examples/react-spa-npm/src/views/member-management-page.tsx @@ -0,0 +1,21 @@ +// import { OrganizationMemberManagement } from '@auth0/universal-components-react/spa'; + +const MemberManagementPage = () => { + return ( +
    +

    + Follow{' '} + + Quickstart guidance + {' '} + on how to add Member Management component. +

    + {/* */} +
    + ); +}; + +export default MemberManagementPage; diff --git a/examples/react-spa-shadcn/src/App.tsx b/examples/react-spa-shadcn/src/App.tsx index c39fdede8..f8f142aa2 100644 --- a/examples/react-spa-shadcn/src/App.tsx +++ b/examples/react-spa-shadcn/src/App.tsx @@ -10,6 +10,7 @@ import { Sidebar } from './components/side-bar'; import { config } from './config/env'; // import { useDarkMode } from './hooks/use-dark-mode'; import DomainManagement from './pages/DomainManagement'; +import MemberManagement from './pages/MemberManagement'; import IdentityProviderManagement from './pages/IdentityProviderManagement'; import IdentityProviderManagementCreate from './pages/IdentityProviderManagementCreate'; import IdentityProviderManagementEdit from './pages/IdentityProviderManagementEdit'; @@ -136,6 +137,14 @@ const App = () => { } /> + + + + } + /> {/* */} diff --git a/examples/react-spa-shadcn/src/components/side-bar.tsx b/examples/react-spa-shadcn/src/components/side-bar.tsx index e0bc08a9b..591c48d73 100644 --- a/examples/react-spa-shadcn/src/components/side-bar.tsx +++ b/examples/react-spa-shadcn/src/components/side-bar.tsx @@ -1,4 +1,4 @@ -import { User, Building, Shield, Settings } from 'lucide-react'; +import { User, Building, Shield, Settings, Users } from 'lucide-react'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; @@ -70,6 +70,15 @@ export const Sidebar: React.FC = () => { {t('sidebar.domain-management')} +
  • + + + {t('sidebar.member-management')} + +
  • diff --git a/examples/react-spa-shadcn/src/pages/MemberManagement.tsx b/examples/react-spa-shadcn/src/pages/MemberManagement.tsx new file mode 100644 index 000000000..bd89bdcc3 --- /dev/null +++ b/examples/react-spa-shadcn/src/pages/MemberManagement.tsx @@ -0,0 +1,23 @@ +// import { OrganizationMemberManagement } from '@auth0/universal-components-react/spa'; + +const MemberManagement = () => { + return ( +
    +

    + Follow{' '} + + Quickstart guidance + {' '} + on how to add Member Management component. +

    +
    + {/* */} +
    +
    + ); +}; + +export default MemberManagement; diff --git a/examples/scripts/utils/env-writer.mjs b/examples/scripts/utils/env-writer.mjs index 9b4d573fd..52eee8c88 100644 --- a/examples/scripts/utils/env-writer.mjs +++ b/examples/scripts/utils/env-writer.mjs @@ -72,6 +72,8 @@ const MYORG_SCOPES = [ "delete:my_org:domains", "create:my_org:domains", "update:my_org:domains", + "read:my_org:member_invitations", + "delete:my_org:member_invitations" ] // My Account API scopes diff --git a/examples/scripts/utils/resource-servers.mjs b/examples/scripts/utils/resource-servers.mjs index d7eeb6b91..95fe0c88d 100644 --- a/examples/scripts/utils/resource-servers.mjs +++ b/examples/scripts/utils/resource-servers.mjs @@ -26,6 +26,8 @@ export const MYORG_API_SCOPES = [ "read:my_org:identity_providers_provisioning", "delete:my_org:identity_providers_provisioning", "read:my_org:configuration", +"read:my_org:member_invitations", +"delete:my_org:member_invitations" ] // My Account API Scopes - desired scopes for MFA management diff --git a/packages/react/src/components/auth0/my-organization/organization-member-management.tsx b/packages/react/src/components/auth0/my-organization/organization-member-management.tsx new file mode 100644 index 000000000..b5338b493 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/organization-member-management.tsx @@ -0,0 +1,244 @@ +/** + * Organization member management component. + * @module organization-member-management + */ + +import { getComponentStyles } from '@auth0/universal-components-core'; +import { Plus } from 'lucide-react'; +import * as React from 'react'; + +import { GateKeeper } from '../shared/gate-keeper/gate-keeper'; + +import { OrganizationInvitationDetailsModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal'; +import { OrganizationInvitationRevokeModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal'; +import { OrganizationInvitationTable } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table'; +import { OrganizationInvitationCreateModal } from '@/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal'; +import { Header } from '@/components/auth0/shared/header'; +import { StyledScope } from '@/components/auth0/shared/styled-scope'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { useOrganizationMemberManagement } from '@/hooks/my-organization/use-organization-member-management'; +import { useTheme } from '@/hooks/shared/use-theme'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + OrganizationMemberManagementProps, + UseOrganizationMemberManagementResult, +} from '@/types/my-organization/member-management/organization-member-management-types'; + +/** + * Props for the OrganizationMemberManagementView component. + */ +export interface OrganizationMemberManagementViewProps + extends UseOrganizationMemberManagementResult { + styling: OrganizationMemberManagementProps['styling']; + customMessages: OrganizationMemberManagementProps['customMessages']; + hideHeader: boolean; + readOnly: boolean; +} + +/** + * View component for organization member management. + * @param props - The component props. + * @returns The component. + */ +export function OrganizationMemberManagementView(props: OrganizationMemberManagementViewProps) { + const { + styling, + customMessages, + hideHeader, + readOnly, + activeTab, + invitations, + isFetchingInvitations, + isCreatingInvitation, + isRevokingInvitation, + isResendingInvitation, + invitationPagination, + invitationFilters, + invitationSortConfig, + availableRoles, + availableProviders, + showCreateModal, + showDetailsModal, + showRevokeModal, + showRevokeResendModal, + selectedInvitation, + setActiveTab, + handleCreateClick, + handleCreateSubmit, + handleCreateCancel, + handleDetailsClick, + handleDetailsClose, + handleRevokeClick, + handleRevokeConfirm, + handleRevokeCancel, + handleRevokeResendClick, + handleRevokeResendConfirm, + handleRevokeResendCancel, + handleCopyUrl, + handleSortChange, + handleNextPage, + handlePreviousPage, + handlePageSizeChange, + handleRoleFilterChange, + } = props; + + const { isDarkMode } = useTheme(); + const { t } = useTranslator('member_management', customMessages as Record); + + const currentStyles = React.useMemo( + () => getComponentStyles(styling, isDarkMode), + [styling, isDarkMode], + ); + + return ( + +
    + {!hideHeader && ( +
    +
    +
    + )} + + setActiveTab(value as 'members' | 'invitations')} + className={currentStyles.classes?.['OrganizationMemberManagement-tabs']} + > + + {t('tabs.members')} + {t('tabs.invitations')} + + + + {/* */} + + + + + + + + + + invitation && handleRevokeClick(invitation)} + onResend={(invitation) => invitation && handleRevokeResendClick(invitation)} + className={currentStyles.classes?.['OrganizationInvitationTab-detailsModal']} + /> + + handleRevokeConfirm()} + className={currentStyles.classes?.['OrganizationInvitationTab-revokeModal']} + /> + + handleRevokeResendConfirm()} + className={currentStyles.classes?.['OrganizationInvitationTab-revokeResendModal']} + /> +
    +
    + ); +} + +/** + * Container component for organization member management. + * @param props - The component props. + * @returns The component. + */ +export function OrganizationMemberManagement(props: OrganizationMemberManagementProps) { + const { + hideHeader = false, + customMessages = {}, + styling = { variables: { common: {}, light: {}, dark: {} }, classes: {} }, + readOnly = false, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + } = props; + + const memberManagement = useOrganizationMemberManagement({ + customMessages, + readOnly, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + }); + + return ( + + + + ); +} diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index 9b0ccceee..e57cc966d 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -12,6 +12,7 @@ export { } from './auth0/my-organization/sso-provider-create'; export { SsoProviderTable, SsoProviderTableView } from './auth0/my-organization/sso-provider-table'; export { DomainTable, DomainTableView } from './auth0/my-organization/domain-table'; +export { OrganizationMemberManagement } from './auth0/my-organization/organization-member-management'; export { OrganizationDetailsEdit, OrganizationDetailsEditView, diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index 646b4e008..f32bcfe11 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -28,3 +28,6 @@ export { useSsoDomainTab } from './my-organization/use-sso-domain-tab'; export { useSsoProviderCreate } from './my-organization/use-sso-provider-create'; export { useSsoProviderEdit } from './my-organization/use-sso-provider-edit'; export { useSsoProviderTable } from './my-organization/use-sso-provider-table'; + +// Member Management hooks +export { useOrganizationMemberManagement } from './my-organization/use-organization-member-management'; diff --git a/packages/react/src/hooks/my-organization/shared/services/use-member-management-service.ts b/packages/react/src/hooks/my-organization/shared/services/use-member-management-service.ts new file mode 100644 index 000000000..3adbec2a8 --- /dev/null +++ b/packages/react/src/hooks/my-organization/shared/services/use-member-management-service.ts @@ -0,0 +1,201 @@ +/** + * Member management service hook. + * @module use-member-management-service + * @internal + */ + +import { + type MemberInvitation, + type ListIdentityProvidersResponseContent, +} from '@auth0/universal-components-core'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import * as React from 'react'; + +import { showToast } from '@/components/auth0/shared/toast'; +import { useCoreClient } from '@/hooks/shared/use-core-client'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + CreateInvitationInput, + InvitationSortConfig, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; +import type { + UseMemberManagementServiceOptions, + MemberManagementServiceResult, +} from '@/types/my-organization/member-management/organization-member-management-types'; + +export const memberManagementQueryKeys = { + all: ['member-management'] as const, + invitations: () => [...memberManagementQueryKeys.all, 'invitations'] as const, +}; + +const INVITATION_SORT_FIELD_MAP: Record = { + created_at: 'created_at', +}; + +/** + * Builds a sort parameter string for the API. + * @param sortConfig - The sort configuration. + * @returns The formatted sort string, or undefined if no valid sort key. + */ +function buildSortParam(sortConfig: InvitationSortConfig): string | undefined { + if (!sortConfig.key) return undefined; + const apiField = INVITATION_SORT_FIELD_MAP[sortConfig.key]; + if (!apiField) return undefined; + const direction = sortConfig.direction === 'asc' ? '1' : '-1'; + return `${apiField}:${direction}`; +} + +/** + * Service hook for member management API operations. + * @param options - Service configuration options. + * @returns Query and mutation objects for member management. + */ +export function useMemberManagementService( + options: UseMemberManagementServiceOptions, +): MemberManagementServiceResult { + const { + customMessages = {}, + activeTab, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + invitationParams, + } = options; + + const isInvitationsTabActive = activeTab === 'invitations'; + + const { coreClient } = useCoreClient(); + const { t } = useTranslator('member_management', customMessages as Record); + const queryClient = useQueryClient(); + + const providersQuery = useQuery({ + queryKey: [...memberManagementQueryKeys.all, 'identity-providers'], + queryFn: async () => { + const response: ListIdentityProvidersResponseContent = await coreClient! + .getMyOrganizationApiClient() + .organization.identityProviders.list(); + const providers = response.identity_providers ?? []; + return providers.map((p) => ({ + id: p.id!, + name: p.display_name ?? p.name ?? '', + type: p.strategy, + })); + }, + enabled: !!coreClient && isInvitationsTabActive, + }); + + const invitationsQuery = useQuery({ + queryKey: [ + ...memberManagementQueryKeys.invitations(), + invitationParams.pageSize, + invitationParams.fromToken, + invitationParams.filters, + invitationParams.sortConfig, + ], + queryFn: async () => { + const page = await coreClient!.getMyOrganizationApiClient().organization.invitations.list({ + take: invitationParams.pageSize, + from: invitationParams.fromToken, + sort: buildSortParam(invitationParams.sortConfig), + }); + + const invitations: MemberInvitation[] = page.data; + const next = page.response.next ?? null; + const total = (page.response as Record).total as number | undefined; + + return { invitations, next, total }; + }, + enabled: !!coreClient && isInvitationsTabActive, + }); + + const createInvitationMutation = useMutation({ + mutationFn: async (data: CreateInvitationInput) => { + if (createInvitationAction?.onBefore && !createInvitationAction.onBefore(data)) { + throw new Error('Create action cancelled by onBefore'); + } + const response = await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.create({ + invitees: [{ email: data.invitee.email, roles: data.roles }], + inviter: data.inviter, + ttl_sec: data.ttl_sec, + }); + return Array.isArray(response) ? response[0] : response; + }, + onSuccess: (result, data) => { + createInvitationAction?.onAfter?.(data, result); + showToast({ type: 'success', message: t('invitation.create.success') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + onError: () => { + showToast({ type: 'error', message: t('invitation.error.create_failed') }); + }, + }); + + const revokeInvitationMutation = useMutation({ + mutationFn: async (invitation: MemberInvitation) => { + if (revokeInvitationAction?.onBefore && !revokeInvitationAction.onBefore(invitation)) { + throw new Error('Revoke action cancelled by onBefore'); + } + await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.delete(invitation.id!); + return invitation; + }, + onSuccess: (invitation) => { + revokeInvitationAction?.onAfter?.(invitation); + showToast({ type: 'success', message: t('invitation.revoke.success') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + onError: () => { + showToast({ type: 'error', message: t('invitation.error.revoke_failed') }); + }, + }); + + const resendInvitationMutation = useMutation({ + mutationFn: async (invitation: MemberInvitation) => { + if (resendInvitationAction?.onBefore && !resendInvitationAction.onBefore(invitation)) { + throw new Error('Resend action cancelled by onBefore'); + } + const freshInvitation = await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.get(invitation.id!); + await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.delete(freshInvitation.id ?? invitation.id!); + const email = freshInvitation.invitee?.email ?? invitation.invitee?.email ?? ''; + const roles = freshInvitation.roles ?? invitation.roles; + const response = await coreClient! + .getMyOrganizationApiClient() + .organization.invitations.create({ + invitees: [{ email, roles }], + }); + return Array.isArray(response) ? response[0] : response; + }, + onSuccess: (result, invitation) => { + resendInvitationAction?.onAfter?.(invitation, result); + showToast({ type: 'success', message: t('invitation.success.invitation_resent') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + onError: () => { + showToast({ type: 'error', message: t('invitation.error.resend_failed') }); + queryClient.invalidateQueries({ queryKey: memberManagementQueryKeys.invitations() }); + }, + }); + + const fetchInvitationDetails = React.useCallback( + async (invitationId: string): Promise => { + return coreClient!.getMyOrganizationApiClient().organization.invitations.get(invitationId); + }, + [coreClient], + ); + + return { + providersQuery, + invitationsQuery, + createInvitationMutation, + revokeInvitationMutation, + resendInvitationMutation, + fetchInvitationDetails, + }; +} diff --git a/packages/react/src/hooks/my-organization/use-config.ts b/packages/react/src/hooks/my-organization/use-config.ts index f3db4455f..bf0488256 100644 --- a/packages/react/src/hooks/my-organization/use-config.ts +++ b/packages/react/src/hooks/my-organization/use-config.ts @@ -51,6 +51,11 @@ export function useConfig(): UseConfigResult { const isConfigValid = !!allowedStrategies?.length; + const allowedRoles = + ((config as Record)?.allowed_roles as + | Array<{ id: string; name: string; description?: string }> + | undefined) ?? []; + return { config: config ?? null, isLoadingConfig: configQuery.isLoading, @@ -58,5 +63,6 @@ export function useConfig(): UseConfigResult { filteredStrategies, shouldAllowDeletion, isConfigValid, + allowedRoles, }; } diff --git a/packages/react/src/hooks/my-organization/use-organization-member-management.ts b/packages/react/src/hooks/my-organization/use-organization-member-management.ts new file mode 100644 index 000000000..1af33e6da --- /dev/null +++ b/packages/react/src/hooks/my-organization/use-organization-member-management.ts @@ -0,0 +1,282 @@ +/** + * Organization member management hook. + * @module use-organization-member-management + */ + +import { type MemberInvitation } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { showToast } from '@/components/auth0/shared/toast'; +import { useMemberManagementService } from '@/hooks/my-organization/shared/services/use-member-management-service'; +import { useConfig } from '@/hooks/my-organization/use-config'; +import { useCheckpointPagination } from '@/hooks/shared/use-checkpoint-pagination'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { + CreateInvitationInput, + InvitationFilterState, + InvitationSortConfig, + RoleOption, + IdentityProviderOption, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; +import type { + ActiveTab, + UseOrganizationMemberManagementOptions, + UseOrganizationMemberManagementResult, +} from '@/types/my-organization/member-management/organization-member-management-types'; + +export { memberManagementQueryKeys } from '@/hooks/my-organization/shared/services/use-member-management-service'; + +/** + * Hook for organization member management. + * @param options - Hook configuration options. + * @returns State and handler functions. + */ +export function useOrganizationMemberManagement( + options: UseOrganizationMemberManagementOptions, +): UseOrganizationMemberManagementResult { + const { + customMessages = {}, + readOnly = false, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + } = options; + + const { t } = useTranslator('member_management', customMessages as Record); + + const [activeTab, setActiveTab] = React.useState('members'); + + const { allowedRoles } = useConfig(); + const availableRoles: RoleOption[] = allowedRoles; + + const { + pageSize: invitationPageSize, + currentPage: invitationCurrentPage, + fromToken: invitationFromToken, + hasPreviousPage: invitationHasPreviousPage, + sortConfig: invitationSortConfig, + filters: invitationFilters, + goToNextPage: invitationGoToNextPage, + goToPreviousPage: invitationGoToPreviousPage, + changePageSize: invitationChangePageSize, + changeSortConfig: invitationChangeSortConfig, + changeFilters: invitationChangeFilters, + } = useCheckpointPagination(); + + const [showCreateModal, setShowCreateModal] = React.useState(false); + const [showDetailsModal, setShowDetailsModal] = React.useState(false); + const [showRevokeModal, setShowRevokeModal] = React.useState(false); + const [showRevokeResendModal, setShowRevokeResendModal] = React.useState(false); + const [selectedInvitation, setSelectedInvitation] = React.useState(null); + const detailsRequestIdRef = React.useRef(0); + + const { + providersQuery, + invitationsQuery, + createInvitationMutation, + revokeInvitationMutation, + resendInvitationMutation, + fetchInvitationDetails, + } = useMemberManagementService({ + customMessages, + activeTab, + createInvitationAction, + revokeInvitationAction, + resendInvitationAction, + invitationParams: { + pageSize: invitationPageSize, + fromToken: invitationFromToken, + sortConfig: invitationSortConfig, + filters: invitationFilters, + }, + }); + + const availableProviders: IdentityProviderOption[] = providersQuery.data ?? []; + const currentInvitations = invitationsQuery.data?.invitations ?? []; + const invitationNextToken = invitationsQuery.data?.next ?? null; + const invitationsTotalItems = invitationsQuery.data?.total; + + const handleCreateClick = React.useCallback(() => { + if (readOnly) return; + setShowCreateModal(true); + }, [readOnly]); + + const handleCreateSubmit = React.useCallback( + (data: CreateInvitationInput) => { + createInvitationMutation.mutate(data, { + onSuccess: () => setShowCreateModal(false), + }); + }, + [createInvitationMutation], + ); + + const handleCreateCancel = React.useCallback(() => { + setShowCreateModal(false); + }, []); + + const handleDetailsClick = React.useCallback( + async (invitation: MemberInvitation) => { + setSelectedInvitation(invitation); + setShowDetailsModal(true); + const requestId = ++detailsRequestIdRef.current; + try { + const response = await fetchInvitationDetails(invitation.id!); + if (detailsRequestIdRef.current === requestId) { + setSelectedInvitation(response); + } + } catch { + if (detailsRequestIdRef.current === requestId) { + showToast({ type: 'error', message: t('invitation.error.fetch_failed') }); + } + } + }, + [fetchInvitationDetails, t], + ); + + const handleDetailsClose = React.useCallback(() => { + setShowDetailsModal(false); + setSelectedInvitation(null); + }, []); + + const handleRevokeClick = React.useCallback( + (invitation: MemberInvitation) => { + if (readOnly) return; + if (showDetailsModal) { + setShowDetailsModal(false); + } + setSelectedInvitation(invitation); + setShowRevokeModal(true); + }, + [readOnly, showDetailsModal], + ); + + const handleRevokeConfirm = React.useCallback(() => { + if (!selectedInvitation) return; + revokeInvitationMutation.mutate(selectedInvitation, { + onSuccess: () => { + setShowRevokeModal(false); + setSelectedInvitation(null); + }, + }); + }, [selectedInvitation, revokeInvitationMutation]); + + const handleRevokeCancel = React.useCallback(() => { + setShowRevokeModal(false); + }, []); + + const handleRevokeResendClick = React.useCallback( + (invitation: MemberInvitation) => { + if (readOnly) return; + if (showDetailsModal) { + setShowDetailsModal(false); + } + setSelectedInvitation(invitation); + setShowRevokeResendModal(true); + }, + [readOnly, showDetailsModal], + ); + + const handleRevokeResendConfirm = React.useCallback(() => { + if (!selectedInvitation) return; + resendInvitationMutation.mutate(selectedInvitation, { + onSuccess: () => { + setShowRevokeResendModal(false); + setSelectedInvitation(null); + }, + }); + }, [selectedInvitation, resendInvitationMutation]); + + const handleRevokeResendCancel = React.useCallback(() => { + setShowRevokeResendModal(false); + }, []); + + const handleCopyUrl = React.useCallback( + async (invitation: MemberInvitation) => { + if (!invitation.invitation_url) return; + try { + await navigator.clipboard.writeText(invitation.invitation_url); + showToast({ type: 'success', message: t('invitation.success.url_copied') }); + } catch { + showToast({ type: 'error', message: t('invitation.error.copy_url_failed') }); + } + }, + [t], + ); + + const handleNextPage = React.useCallback(() => { + if (invitationNextToken) { + invitationGoToNextPage(invitationNextToken); + } + }, [invitationNextToken, invitationGoToNextPage]); + + const handlePreviousPage = React.useCallback(() => { + invitationGoToPreviousPage(); + }, [invitationGoToPreviousPage]); + + const handlePageSizeChange = React.useCallback( + (pageSize: number) => { + invitationChangePageSize(pageSize); + }, + [invitationChangePageSize], + ); + + const handleSortChange = React.useCallback( + (sortConfig: InvitationSortConfig) => { + invitationChangeSortConfig(sortConfig); + }, + [invitationChangeSortConfig], + ); + + const handleRoleFilterChange = React.useCallback( + (roleId: string | undefined) => { + invitationChangeFilters((prev) => ({ ...prev, roleId })); + }, + [invitationChangeFilters], + ); + + return { + activeTab, + isLoading: invitationsQuery.isLoading || invitationsQuery.isFetching, + availableRoles, + availableProviders, + + invitations: currentInvitations, + isFetchingInvitations: invitationsQuery.isLoading || invitationsQuery.isFetching, + isCreatingInvitation: createInvitationMutation.isPending, + isRevokingInvitation: revokeInvitationMutation.isPending, + isResendingInvitation: resendInvitationMutation.isPending, + invitationPagination: { + pageSize: invitationPageSize, + currentPage: invitationCurrentPage, + totalItems: invitationsTotalItems, + hasNextPage: !!invitationNextToken, + hasPreviousPage: invitationHasPreviousPage, + }, + invitationFilters, + invitationSortConfig, + showCreateModal, + showDetailsModal, + showRevokeModal, + showRevokeResendModal, + selectedInvitation, + + setActiveTab, + handleCreateClick, + handleCreateSubmit, + handleCreateCancel, + handleDetailsClick, + handleDetailsClose, + handleRevokeClick, + handleRevokeConfirm, + handleRevokeCancel, + handleRevokeResendClick, + handleRevokeResendConfirm, + handleRevokeResendCancel, + handleCopyUrl, + handleNextPage, + handlePreviousPage, + handlePageSizeChange, + handleSortChange, + handleRoleFilterChange, + }; +} From b725dd061c9cf973e658892f73dd4321f6f9de9d Mon Sep 17 00:00:00 2001 From: rax7389 Date: Wed, 8 Apr 2026 16:55:03 +0530 Subject: [PATCH 017/125] test(react): add tests and mocks for invitation components --- ...nization-invitation-details-modal.test.tsx | 386 ++++++++++++++++ ...anization-invitation-revoke-modal.test.tsx | 246 +++++++++++ ...n-invitation-table-actions-column.test.tsx | 321 ++++++++++++++ ...anization-invitation-create-modal.test.tsx | 218 +++++++++ .../__tests__/search-filter.test.tsx | 103 +++++ .../use-member-management-service.test.ts | 414 ++++++++++++++++++ .../my-organization/config/config.mocks.ts | 1 + .../utils/__mocks__/core/core-client.mocks.ts | 10 + .../my-organization/config/config.mocks.ts | 1 + .../member-management/invitation.mocks.ts | 108 +++++ 10 files changed, 1808 insertions(+) create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx create mode 100644 packages/react/src/hooks/my-organization/__tests__/use-member-management-service.test.ts create mode 100644 packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx new file mode 100644 index 000000000..266f128cc --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-details/__tests__/organization-invitation-details-modal.test.tsx @@ -0,0 +1,386 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { OrganizationInvitationDetailsModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockDetailsModalProps, + createMockInvitation, + createMockPendingInvitation, + createMockExpiredInvitation, + createMockRoles, + createMockProviders, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationDetailsModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + describe('when is true', () => { + it('should render the modal', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: 'invitation.details.title' }), + ).toBeInTheDocument(); + }); + }); + + describe('when is false', () => { + it('should not render the modal content', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + }); + + describe('invitation', () => { + describe('when invitation is provided', () => { + it('should display the invitee email', () => { + const invitation = createMockInvitation({ invitee: { email: 'user@example.com' } }); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('user@example.com')).toBeInTheDocument(); + }); + + it('should display the inviter name', () => { + const invitation = createMockInvitation({ inviter: { name: 'John Doe' } }); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('John Doe')).toBeInTheDocument(); + }); + + it('should display created_at date', () => { + const invitation = createMockInvitation({ + created_at: '2024-06-15T10:00:00.000Z', + }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.created_at_label')).toBeInTheDocument(); + }); + + it('should display expires_at date', () => { + const invitation = createMockInvitation({ + expires_at: '2025-06-15T10:00:00.000Z', + }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.expires_at_label')).toBeInTheDocument(); + }); + }); + + describe('when invitation is null', () => { + it('should handle null invitation gracefully', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + }); + + describe('status badge', () => { + it('should display pending status for pending invitations', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.table.status_pending')).toBeInTheDocument(); + }); + + it('should display expired status for expired invitations', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.table.status_expired')).toBeInTheDocument(); + }); + }); + + describe('roles', () => { + it('should resolve role IDs to names when availableRoles provided', () => { + const invitation = createMockInvitation({ roles: ['role_admin', 'role_member'] }); + const availableRoles = createMockRoles(); + + renderWithProviders( + , + ); + + expect(screen.getByText('Admin')).toBeInTheDocument(); + expect(screen.getByText('Member')).toBeInTheDocument(); + }); + + it('should show role ID as fallback when role not found in availableRoles', () => { + const invitation = createMockInvitation({ roles: ['role_unknown'] }); + + renderWithProviders( + , + ); + + expect(screen.getByText('role_unknown')).toBeInTheDocument(); + }); + + it('should show dash when no roles assigned', () => { + const invitation = createMockInvitation({ roles: [] }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.roles_label')).toBeInTheDocument(); + }); + }); + + describe('invitation URL', () => { + it('should display invitation URL when available', () => { + const invitation = createMockInvitation({ + invitation_url: 'https://example.auth0.com/invite?ticket=abc', + }); + + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.details.invitation_url_label')).toBeInTheDocument(); + }); + + it('should not display invitation URL section when no URL', () => { + const invitation = createMockInvitation({ invitation_url: undefined }); + + renderWithProviders( + , + ); + + expect(screen.queryByText('invitation.details.invitation_url_label')).not.toBeInTheDocument(); + }); + }); + + describe('identity provider', () => { + it('should display provider name when resolved', () => { + const invitation = createMockInvitation({ identity_provider_id: 'con_provider1' }); + const availableProviders = createMockProviders(); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('Google')).toBeInTheDocument(); + }); + + it('should show provider ID as fallback when provider not found', () => { + const invitation = createMockInvitation({ identity_provider_id: 'con_unknown' }); + + renderWithProviders( + , + ); + + expect(screen.getByDisplayValue('con_unknown')).toBeInTheDocument(); + }); + + it('should not display provider section when no provider assigned', () => { + const invitation = createMockInvitation({ identity_provider_id: undefined }); + + renderWithProviders( + , + ); + + expect(screen.queryByText('invitation.details.provider_label')).not.toBeInTheDocument(); + }); + }); + + describe('readOnly', () => { + describe('when readOnly is false', () => { + it('should show Revoke and Resend buttons', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'invitation.details.revoke_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'invitation.details.resend_button' }), + ).toBeInTheDocument(); + }); + }); + + describe('when readOnly is true', () => { + it('should not show Revoke and Resend buttons', () => { + renderWithProviders( + , + ); + + expect( + screen.queryByRole('button', { name: 'invitation.details.revoke_button' }), + ).not.toBeInTheDocument(); + expect( + screen.queryByRole('button', { name: 'invitation.details.resend_button' }), + ).not.toBeInTheDocument(); + }); + }); + }); + + describe('action callbacks', () => { + it('should call onRevoke when Revoke button is clicked', async () => { + const user = userEvent.setup(); + const onRevoke = vi.fn(); + const invitation = createMockPendingInvitation(); + + renderWithProviders( + , + ); + + const revokeButton = screen.getByRole('button', { + name: 'invitation.details.revoke_button', + }); + await user.click(revokeButton); + + expect(onRevoke).toHaveBeenCalledTimes(1); + expect(onRevoke).toHaveBeenCalledWith(invitation); + }); + + it('should call onResend when Resend button is clicked', async () => { + const user = userEvent.setup(); + const onResend = vi.fn(); + const invitation = createMockPendingInvitation(); + + renderWithProviders( + , + ); + + const resendButton = screen.getByRole('button', { + name: 'invitation.details.resend_button', + }); + await user.click(resendButton); + + expect(onResend).toHaveBeenCalledTimes(1); + expect(onResend).toHaveBeenCalledWith(invitation); + }); + + it('should call onClose when Close button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + const closeButton = screen.getByRole('button', { + name: 'invitation.details.close_button', + }); + await user.click(closeButton); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); + + describe('action in progress', () => { + it('should disable Revoke button when isRevoking is true', () => { + renderWithProviders( + , + ); + + const revokeButton = screen.getByRole('button', { + name: 'invitation.details.revoke_button', + }); + expect(revokeButton).toBeDisabled(); + }); + + it('should disable Resend button when isResending is true', () => { + renderWithProviders( + , + ); + + const resendButton = screen.getByRole('button', { + name: 'invitation.details.resend_button', + }); + expect(resendButton).toBeDisabled(); + }); + + it('should disable both buttons when either action is in progress', () => { + renderWithProviders( + , + ); + + const revokeButton = screen.getByRole('button', { + name: 'invitation.details.revoke_button', + }); + const resendButton = screen.getByRole('button', { + name: 'invitation.details.resend_button', + }); + expect(revokeButton).toBeDisabled(); + expect(resendButton).toBeDisabled(); + }); + }); + + describe('className', () => { + it('should apply custom class to modal', () => { + const customClass = 'custom-details-class'; + + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass(customClass); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx new file mode 100644 index 000000000..595076fa3 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/__tests__/organization-invitation-revoke-modal.test.tsx @@ -0,0 +1,246 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { OrganizationInvitationRevokeModal } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockRevokeModalProps, + createMockPendingInvitation, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationRevokeModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + describe('when is true', () => { + it('should render the modal', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + + describe('when is false', () => { + it('should not render the modal content', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + }); + + describe('revoke mode', () => { + describe('when isRevokeAndResend is false', () => { + it('should render revoke-specific title', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke.title')).toBeInTheDocument(); + }); + + it('should render revoke-specific description', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke.description')).toBeInTheDocument(); + }); + + it('should render revoke-specific button text', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'invitation.revoke.confirm_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'invitation.revoke.cancel_button' }), + ).toBeInTheDocument(); + }); + }); + + describe('when isRevokeAndResend is true', () => { + it('should render revoke-and-resend title', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke_resend.title')).toBeInTheDocument(); + }); + + it('should render revoke-and-resend description', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.revoke_resend.description')).toBeInTheDocument(); + }); + + it('should render revoke-and-resend button text', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'invitation.revoke_resend.confirm_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'invitation.revoke_resend.cancel_button' }), + ).toBeInTheDocument(); + }); + }); + }); + + describe('isLoading', () => { + describe('when is true', () => { + it('should disable confirm button', () => { + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + expect(confirmButton).toBeDisabled(); + }); + + it('should disable cancel button', () => { + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.revoke.cancel_button', + }); + expect(cancelButton).toBeDisabled(); + }); + }); + + describe('when is false', () => { + it('should enable confirm button', () => { + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + expect(confirmButton).toBeEnabled(); + }); + }); + }); + + describe('onConfirm', () => { + it('should call onConfirm with invitation when confirm button is clicked', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + const invitation = createMockPendingInvitation(); + + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + await user.click(confirmButton); + + expect(onConfirm).toHaveBeenCalledTimes(1); + expect(onConfirm).toHaveBeenCalledWith(invitation); + }); + + it('should not call onConfirm when invitation is null', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + + renderWithProviders( + , + ); + + const confirmButton = screen.getByRole('button', { + name: 'invitation.revoke.confirm_button', + }); + await user.click(confirmButton); + + expect(onConfirm).not.toHaveBeenCalled(); + }); + }); + + describe('onClose', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.revoke.cancel_button', + }); + await user.click(cancelButton); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + }); + + describe('className', () => { + it('should apply custom class to modal', () => { + const customClass = 'custom-revoke-class'; + + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass(customClass); + }); + }); + + describe('invitation', () => { + describe('when invitation is null', () => { + it('should handle null invitation gracefully', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx new file mode 100644 index 000000000..ee819768e --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/__tests__/organization-invitation-table-actions-column.test.tsx @@ -0,0 +1,321 @@ +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { OrganizationInvitationTableActionsColumn } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table-actions-column'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockActionsColumnProps, + createMockPendingInvitation, + createMockExpiredInvitation, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationTableActionsColumn', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe('Rendering and Basic Structure', () => { + it('should render dropdown trigger button', () => { + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + expect(trigger).toBeInTheDocument(); + expect(trigger).toHaveClass('h-8', 'w-8'); + }); + + it('should have proper accessibility attributes', () => { + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + expect(trigger).toHaveAttribute('type', 'button'); + }); + }); + + describe('Dropdown Menu Interactions', () => { + it('should open dropdown menu when trigger button is clicked', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + + it('should close dropdown menu when user presses Escape key', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + + await user.keyboard('{Escape}'); + + await waitFor(() => { + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).not.toBeInTheDocument(); + }); + }); + }); + + describe('Invitation Status: Pending', () => { + it('should show View Details action', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockPendingInvitation(), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + + it('should show Copy URL action when invitation has URL', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockPendingInvitation({ + invitation_url: 'https://example.com/invite?ticket=abc', + }), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.copy_url' }), + ).toBeInTheDocument(); + }); + + it('should not show Copy URL action when invitation has no URL', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockPendingInvitation({ invitation_url: undefined }), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.copy_url' }), + ).not.toBeInTheDocument(); + }); + + it('should show Revoke & Resend action when not readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: false }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.revoke_and_resend' }), + ).toBeInTheDocument(); + }); + + it('should show Revoke action when not readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: false }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.revoke' }), + ).toBeInTheDocument(); + }); + }); + + describe('Invitation Status: Expired', () => { + it('should show View Details action', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockExpiredInvitation(), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + + it('should not show Copy URL action for expired invitations', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ + invitation: createMockExpiredInvitation(), + }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.copy_url' }), + ).not.toBeInTheDocument(); + }); + }); + + describe('Read-Only Mode', () => { + it('should not show Revoke & Resend action when readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: true }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.revoke_and_resend' }), + ).not.toBeInTheDocument(); + }); + + it('should not show Revoke action when readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: true }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.queryByRole('menuitem', { name: 'invitation.actions.revoke' }), + ).not.toBeInTheDocument(); + }); + + it('should still show View Details when readOnly', async () => { + const user = userEvent.setup(); + const props = createMockActionsColumnProps({ readOnly: true }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + }); + + describe('Callback Invocations', () => { + it('should call onViewDetails when View Details is clicked', async () => { + const user = userEvent.setup(); + const onViewDetails = vi.fn(); + const invitation = createMockPendingInvitation(); + const props = createMockActionsColumnProps({ invitation, onViewDetails }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.view_details', + }); + await user.click(menuItem); + + expect(onViewDetails).toHaveBeenCalledTimes(1); + expect(onViewDetails).toHaveBeenCalledWith(invitation); + }); + + it('should call onCopyUrl when Copy URL is clicked', async () => { + const user = userEvent.setup(); + const onCopyUrl = vi.fn(); + const invitation = createMockPendingInvitation({ + invitation_url: 'https://example.com/invite', + }); + const props = createMockActionsColumnProps({ invitation, onCopyUrl }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.copy_url', + }); + await user.click(menuItem); + + expect(onCopyUrl).toHaveBeenCalledTimes(1); + expect(onCopyUrl).toHaveBeenCalledWith(invitation); + }); + + it('should call onRevokeAndResend when Revoke & Resend is clicked', async () => { + const user = userEvent.setup(); + const onRevokeAndResend = vi.fn(); + const invitation = createMockPendingInvitation(); + const props = createMockActionsColumnProps({ invitation, onRevokeAndResend }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.revoke_and_resend', + }); + await user.click(menuItem); + + expect(onRevokeAndResend).toHaveBeenCalledTimes(1); + expect(onRevokeAndResend).toHaveBeenCalledWith(invitation); + }); + + it('should call onRevoke when Revoke is clicked', async () => { + const user = userEvent.setup(); + const onRevoke = vi.fn(); + const invitation = createMockPendingInvitation(); + const props = createMockActionsColumnProps({ invitation, onRevoke }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + const menuItem = screen.getByRole('menuitem', { + name: 'invitation.actions.revoke', + }); + await user.click(menuItem); + + expect(onRevoke).toHaveBeenCalledTimes(1); + expect(onRevoke).toHaveBeenCalledWith(invitation); + }); + }); + + describe('Custom Messages', () => { + it('should accept custom messages prop without error', async () => { + const user = userEvent.setup(); + const customMessages = { + actions: { + view_details: 'Custom View Details', + }, + }; + const props = createMockActionsColumnProps({ customMessages }); + renderWithProviders(); + + const trigger = screen.getByRole('button'); + await user.click(trigger); + + // The mock translator returns keys, so verify the menu item renders + expect( + screen.getByRole('menuitem', { name: 'invitation.actions.view_details' }), + ).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx new file mode 100644 index 000000000..d35fcca86 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/__tests__/organization-invitation-create-modal.test.tsx @@ -0,0 +1,218 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { OrganizationInvitationCreateModal } from '@/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockCreateModalProps, + createMockRoles, + createMockProviders, +} from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('OrganizationInvitationCreateModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + describe('when is true', () => { + it('should render the modal', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect(screen.getByText('invitation.create.title')).toBeInTheDocument(); + }); + }); + + describe('when is false', () => { + it('should not render the modal content', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + }); + + describe('isLoading', () => { + describe('when is true', () => { + it('should disable form inputs', () => { + renderWithProviders( + , + ); + + const emailInput = screen.getByPlaceholderText('invitation.create.email_placeholder'); + expect(emailInput).toBeDisabled(); + }); + + it('should disable cancel and submit buttons', () => { + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.create.cancel_button', + }); + expect(cancelButton).toBeDisabled(); + }); + }); + + describe('when is false', () => { + it('should enable form inputs', () => { + renderWithProviders( + , + ); + + const emailInput = screen.getByPlaceholderText('invitation.create.email_placeholder'); + expect(emailInput).toBeEnabled(); + }); + }); + }); + + describe('className', () => { + describe('when className is provided', () => { + it('should apply custom class to modal', () => { + const customClass = 'custom-modal-class'; + + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass(customClass); + }); + }); + }); + + describe('onClose', () => { + describe('when modal is closed', () => { + it('should call onClose callback via cancel button', async () => { + const user = userEvent.setup(); + const mockOnClose = vi.fn(); + + renderWithProviders( + , + ); + + const cancelButton = screen.getByRole('button', { + name: 'invitation.create.cancel_button', + }); + await user.click(cancelButton); + + expect(mockOnClose).toHaveBeenCalledTimes(1); + }); + }); + }); + + describe('email input', () => { + it('should render email input field', () => { + renderWithProviders(); + + expect( + screen.getByPlaceholderText('invitation.create.email_placeholder'), + ).toBeInTheDocument(); + expect(screen.getByText(/invitation\.create\.email_label/)).toBeInTheDocument(); + }); + + it('should show helper text by default', () => { + renderWithProviders(); + + expect(screen.getByText('invitation.create.email_helper')).toBeInTheDocument(); + }); + }); + + describe('submit', () => { + it('should disable submit button when no emails are added', () => { + renderWithProviders(); + + const submitButton = screen.getByRole('button', { + name: 'invitation.create.submit_button', + }); + expect(submitButton).toBeDisabled(); + }); + + it('should show creating text when isLoading is true', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.creating')).toBeInTheDocument(); + }); + }); + + describe('availableRoles', () => { + describe('when roles are provided', () => { + it('should render roles combobox', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.roles_label')).toBeInTheDocument(); + }); + }); + + describe('when no roles are provided', () => { + it('should still render roles section', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.roles_label')).toBeInTheDocument(); + }); + }); + }); + + describe('availableProviders', () => { + describe('when providers are provided', () => { + it('should render provider dropdown', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.provider_label')).toBeInTheDocument(); + }); + }); + + describe('when no providers are provided', () => { + it('should still render provider section', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('invitation.create.provider_label')).toBeInTheDocument(); + }); + }); + }); + + describe('description', () => { + it('should render description text', () => { + renderWithProviders(); + + expect(screen.getByText('invitation.create.description')).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx new file mode 100644 index 000000000..7b83b6a4d --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx @@ -0,0 +1,103 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { vi, describe, it, expect, afterEach } from 'vitest'; + +import { SearchFilter } from '@/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter'; +import { renderWithProviders } from '@/tests/utils'; +import { createMockSearchFilterProps } from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; + +describe('SearchFilter', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('rendering', () => { + it('should render the filter when roles are provided', () => { + renderWithProviders(); + + expect(screen.getByText(/invitation\.table\.filter_by_role/)).toBeInTheDocument(); + }); + + it('should return null when no roles are provided', () => { + const { container } = renderWithProviders( + , + ); + + expect(container.innerHTML).toBe(''); + }); + + it('should render reset button', () => { + renderWithProviders(); + + expect( + screen.getByRole('button', { name: 'invitation.table.reset_filter' }), + ).toBeInTheDocument(); + }); + }); + + describe('reset button', () => { + it('should be disabled when no active filter', () => { + renderWithProviders(); + + const resetButton = screen.getByRole('button', { + name: 'invitation.table.reset_filter', + }); + expect(resetButton).toBeDisabled(); + }); + + it('should be enabled when there is an active filter', () => { + renderWithProviders( + , + ); + + const resetButton = screen.getByRole('button', { + name: 'invitation.table.reset_filter', + }); + expect(resetButton).toBeEnabled(); + }); + + it('should call onRoleFilterChange with undefined when reset is clicked', async () => { + const user = userEvent.setup(); + const onRoleFilterChange = vi.fn(); + + renderWithProviders( + , + ); + + const resetButton = screen.getByRole('button', { + name: 'invitation.table.reset_filter', + }); + await user.click(resetButton); + + expect(onRoleFilterChange).toHaveBeenCalledTimes(1); + expect(onRoleFilterChange).toHaveBeenCalledWith(undefined); + }); + }); + + describe('className', () => { + it('should apply custom class when provided', () => { + const customClass = 'custom-filter-class'; + + const { container } = renderWithProviders( + , + ); + + const filterDiv = container.firstChild as HTMLElement; + expect(filterDiv).toHaveClass(customClass); + }); + + it('should apply default class when no custom class provided', () => { + const { container } = renderWithProviders( + , + ); + + const filterDiv = container.firstChild as HTMLElement; + expect(filterDiv).toHaveClass('mb-4'); + }); + }); +}); diff --git a/packages/react/src/hooks/my-organization/__tests__/use-member-management-service.test.ts b/packages/react/src/hooks/my-organization/__tests__/use-member-management-service.test.ts new file mode 100644 index 000000000..5fff9f1d7 --- /dev/null +++ b/packages/react/src/hooks/my-organization/__tests__/use-member-management-service.test.ts @@ -0,0 +1,414 @@ +import { renderHook, waitFor, act } from '@testing-library/react'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; + +import { useMemberManagementService } from '@/hooks/my-organization/shared/services/use-member-management-service'; +import { memberManagementQueryKeys } from '@/hooks/my-organization/shared/services/use-member-management-service'; +import * as useCoreClientModule from '@/hooks/shared/use-core-client'; +import * as useTranslatorModule from '@/hooks/shared/use-translator'; +import { mockCore, mockToast, createMockI18nService } from '@/tests/utils'; +import { createMockInvitation } from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; +import { createTestQueryClientWrapper } from '@/tests/utils/test-provider'; +import type { UseMemberManagementServiceOptions } from '@/types/my-organization/member-management/organization-member-management-types'; + +const { mockedShowToast } = mockToast(); +const { initMockCoreClient } = mockCore(); + +const createDefaultOptions = ( + overrides?: Partial, +): UseMemberManagementServiceOptions => ({ + customMessages: {}, + activeTab: 'invitations', + invitationParams: { + pageSize: 10, + fromToken: undefined, + sortConfig: { key: null, direction: 'asc' }, + filters: {}, + }, + ...overrides, +}); + +const renderService = (options: UseMemberManagementServiceOptions) => { + const { wrapper, queryClient } = createTestQueryClientWrapper(); + return { + queryClient, + ...renderHook(() => useMemberManagementService(options), { wrapper }), + }; +}; + +describe('useMemberManagementService', () => { + let mockCoreClient: ReturnType; + + beforeEach(() => { + vi.clearAllMocks(); + + mockCoreClient = initMockCoreClient(); + + vi.spyOn(useCoreClientModule, 'useCoreClient').mockReturnValue({ + coreClient: mockCoreClient, + }); + + vi.spyOn(useTranslatorModule, 'useTranslator').mockReturnValue({ + t: createMockI18nService().translator('member_management'), + changeLanguage: vi.fn(), + currentLanguage: 'en', + fallbackLanguage: 'en', + }); + }); + + describe('memberManagementQueryKeys', () => { + it('should have correct base key', () => { + expect(memberManagementQueryKeys.all).toEqual(['member-management']); + }); + + it('should have correct invitations key', () => { + expect(memberManagementQueryKeys.invitations()).toEqual(['member-management', 'invitations']); + }); + }); + + describe('providersQuery', () => { + it('should fetch identity providers when invitations tab is active', async () => { + const options = createDefaultOptions({ activeTab: 'invitations' }); + const { result } = renderService(options); + + await waitFor(() => { + expect(result.current.providersQuery.isSuccess).toBe(true); + }); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.identityProviders.list, + ).toHaveBeenCalled(); + }); + + it('should not fetch identity providers when members tab is active', () => { + const options = createDefaultOptions({ activeTab: 'members' }); + const { result } = renderService(options); + + expect(result.current.providersQuery.fetchStatus).toBe('idle'); + }); + }); + + describe('invitationsQuery', () => { + it('should fetch invitations when invitations tab is active', async () => { + const options = createDefaultOptions({ activeTab: 'invitations' }); + const { result } = renderService(options); + + await waitFor(() => { + expect(result.current.invitationsQuery.isSuccess).toBe(true); + }); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.list, + ).toHaveBeenCalledWith( + expect.objectContaining({ + take: 10, + from: undefined, + sort: undefined, + }), + ); + }); + + it('should not fetch invitations when members tab is active', () => { + const options = createDefaultOptions({ activeTab: 'members' }); + const { result } = renderService(options); + + expect(result.current.invitationsQuery.fetchStatus).toBe('idle'); + }); + + it('should pass sort parameter when sort config has a valid key', async () => { + const options = createDefaultOptions({ + invitationParams: { + pageSize: 10, + fromToken: undefined, + sortConfig: { key: 'created_at', direction: 'desc' }, + filters: {}, + }, + }); + const { result } = renderService(options); + + await waitFor(() => { + expect(result.current.invitationsQuery.isSuccess).toBe(true); + }); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.list, + ).toHaveBeenCalledWith( + expect.objectContaining({ + sort: 'created_at:-1', + }), + ); + }); + + it('should pass fromToken when provided', async () => { + const options = createDefaultOptions({ + invitationParams: { + pageSize: 10, + fromToken: 'token_abc', + sortConfig: { key: null, direction: 'asc' }, + filters: {}, + }, + }); + const { result } = renderService(options); + + await waitFor(() => { + expect(result.current.invitationsQuery.isSuccess).toBe(true); + }); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.list, + ).toHaveBeenCalledWith( + expect.objectContaining({ + from: 'token_abc', + }), + ); + }); + + it('should return parsed invitations data', async () => { + const mockInvitation = createMockInvitation(); + mockCoreClient.getMyOrganizationApiClient().organization.invitations.list = vi + .fn() + .mockResolvedValue({ + data: [mockInvitation], + response: { next: 'next_token', total: 5 }, + }); + + const options = createDefaultOptions(); + const { result } = renderService(options); + + await waitFor(() => { + expect(result.current.invitationsQuery.isSuccess).toBe(true); + }); + + expect(result.current.invitationsQuery.data).toEqual({ + invitations: [mockInvitation], + next: 'next_token', + total: 5, + }); + }); + }); + + describe('createInvitationMutation', () => { + it('should create an invitation and show success toast', async () => { + const options = createDefaultOptions(); + const { result } = renderService(options); + + await act(async () => { + result.current.createInvitationMutation.mutate({ + invitee: { email: 'new@example.com' }, + roles: ['role_admin'], + }); + }); + + await waitFor(() => { + expect(result.current.createInvitationMutation.isSuccess).toBe(true); + }); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.create, + ).toHaveBeenCalled(); + expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ type: 'success' })); + }); + + it('should call onBefore action and cancel if it returns false', async () => { + const onBefore = vi.fn().mockReturnValue(false); + const options = createDefaultOptions({ + createInvitationAction: { onBefore }, + }); + const { result } = renderService(options); + + await act(async () => { + result.current.createInvitationMutation.mutate({ + invitee: { email: 'new@example.com' }, + }); + }); + + await waitFor(() => { + expect(result.current.createInvitationMutation.isError).toBe(true); + }); + + expect(onBefore).toHaveBeenCalled(); + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.create, + ).not.toHaveBeenCalled(); + }); + + it('should call onAfter action on success', async () => { + const onAfter = vi.fn(); + const options = createDefaultOptions({ + createInvitationAction: { onAfter }, + }); + const { result } = renderService(options); + + await act(async () => { + result.current.createInvitationMutation.mutate({ + invitee: { email: 'new@example.com' }, + }); + }); + + await waitFor(() => { + expect(result.current.createInvitationMutation.isSuccess).toBe(true); + }); + + expect(onAfter).toHaveBeenCalled(); + }); + + it('should show error toast on failure', async () => { + mockCoreClient.getMyOrganizationApiClient().organization.invitations.create = vi + .fn() + .mockRejectedValue(new Error('Create failed')); + + const options = createDefaultOptions(); + const { result } = renderService(options); + + await act(async () => { + result.current.createInvitationMutation.mutate({ + invitee: { email: 'new@example.com' }, + }); + }); + + await waitFor(() => { + expect(result.current.createInvitationMutation.isError).toBe(true); + }); + + expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ type: 'error' })); + }); + }); + + describe('revokeInvitationMutation', () => { + it('should revoke an invitation and show success toast', async () => { + const invitation = createMockInvitation(); + const options = createDefaultOptions(); + const { result } = renderService(options); + + await act(async () => { + result.current.revokeInvitationMutation.mutate(invitation); + }); + + await waitFor(() => { + expect(result.current.revokeInvitationMutation.isSuccess).toBe(true); + }); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.delete, + ).toHaveBeenCalledWith(invitation.id); + expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ type: 'success' })); + }); + + it('should call onBefore action and cancel if it returns false', async () => { + const onBefore = vi.fn().mockReturnValue(false); + const invitation = createMockInvitation(); + const options = createDefaultOptions({ + revokeInvitationAction: { onBefore }, + }); + const { result } = renderService(options); + + await act(async () => { + result.current.revokeInvitationMutation.mutate(invitation); + }); + + await waitFor(() => { + expect(result.current.revokeInvitationMutation.isError).toBe(true); + }); + + expect(onBefore).toHaveBeenCalledWith(invitation); + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.delete, + ).not.toHaveBeenCalled(); + }); + + it('should show error toast on failure', async () => { + mockCoreClient.getMyOrganizationApiClient().organization.invitations.delete = vi + .fn() + .mockRejectedValue(new Error('Revoke failed')); + + const invitation = createMockInvitation(); + const options = createDefaultOptions(); + const { result } = renderService(options); + + await act(async () => { + result.current.revokeInvitationMutation.mutate(invitation); + }); + + await waitFor(() => { + expect(result.current.revokeInvitationMutation.isError).toBe(true); + }); + + expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ type: 'error' })); + }); + }); + + describe('resendInvitationMutation', () => { + it('should revoke and resend an invitation', async () => { + const invitation = createMockInvitation(); + const options = createDefaultOptions(); + const { result } = renderService(options); + + await act(async () => { + result.current.resendInvitationMutation.mutate(invitation); + }); + + await waitFor(() => { + expect(result.current.resendInvitationMutation.isSuccess).toBe(true); + }); + + const orgApi = mockCoreClient.getMyOrganizationApiClient().organization; + expect(orgApi.invitations.get).toHaveBeenCalledWith(invitation.id); + expect(orgApi.invitations.delete).toHaveBeenCalled(); + expect(orgApi.invitations.create).toHaveBeenCalled(); + expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ type: 'success' })); + }); + + it('should call onBefore action and cancel if it returns false', async () => { + const onBefore = vi.fn().mockReturnValue(false); + const invitation = createMockInvitation(); + const options = createDefaultOptions({ + resendInvitationAction: { onBefore }, + }); + const { result } = renderService(options); + + await act(async () => { + result.current.resendInvitationMutation.mutate(invitation); + }); + + await waitFor(() => { + expect(result.current.resendInvitationMutation.isError).toBe(true); + }); + + expect(onBefore).toHaveBeenCalledWith(invitation); + }); + + it('should show error toast on failure', async () => { + mockCoreClient.getMyOrganizationApiClient().organization.invitations.get = vi + .fn() + .mockRejectedValue(new Error('Fetch failed')); + + const invitation = createMockInvitation(); + const options = createDefaultOptions(); + const { result } = renderService(options); + + await act(async () => { + result.current.resendInvitationMutation.mutate(invitation); + }); + + await waitFor(() => { + expect(result.current.resendInvitationMutation.isError).toBe(true); + }); + + expect(mockedShowToast).toHaveBeenCalledWith(expect.objectContaining({ type: 'error' })); + }); + }); + + describe('fetchInvitationDetails', () => { + it('should fetch invitation details by id', async () => { + const mockInvitation = createMockInvitation(); + const options = createDefaultOptions(); + const { result } = renderService(options); + + const details = await result.current.fetchInvitationDetails('inv_abc123xyz456'); + + expect( + mockCoreClient.getMyOrganizationApiClient().organization.invitations.get, + ).toHaveBeenCalledWith('inv_abc123xyz456'); + expect(details).toEqual(mockInvitation); + }); + }); +}); diff --git a/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts b/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts index dd682ce97..2b0f13b39 100644 --- a/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts +++ b/packages/react/src/internals/__mocks__/my-organization/config/config.mocks.ts @@ -20,5 +20,6 @@ export const createMockUseConfig = (overrides?: Partial): MockUse }, fetchConfig: vi.fn(async () => undefined), filteredStrategies: [], + allowedRoles: [], ...overrides, }); diff --git a/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts b/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts index 2964c44ac..02aa5053c 100644 --- a/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts +++ b/packages/react/src/tests/utils/__mocks__/core/core-client.mocks.ts @@ -8,6 +8,7 @@ import { createMockEmptyAuthenticationMethods, } from '@/tests/utils/__mocks__/my-account/mfa/mfa.mocks'; import { createMockIdentityProvider } from '@/tests/utils/__mocks__/my-organization/domain-management/domain.mocks'; +import { createMockInvitation } from '@/tests/utils/__mocks__/my-organization/member-management/invitation.mocks'; import { createMockOrganization } from '@/tests/utils/__mocks__/my-organization/organization-management/organization-details.mocks'; const createMockMyAccountApiService = (): CoreClientInterface['myAccountApiClient'] => { @@ -55,6 +56,15 @@ const createMockMyOrgApiService = (): CoreClientInterface['myOrganizationApiClie delete: vi.fn().mockResolvedValue(undefined), }, }, + invitations: { + list: vi.fn().mockResolvedValue({ + data: [createMockInvitation()], + response: { next: null }, + }), + get: vi.fn().mockResolvedValue(createMockInvitation()), + create: vi.fn().mockResolvedValue([createMockInvitation()]), + delete: vi.fn().mockResolvedValue(undefined), + }, domains: { list: vi.fn().mockResolvedValue([]), create: vi.fn().mockResolvedValue({}), diff --git a/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts b/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts index 102991ff4..9a78bfa91 100644 --- a/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts +++ b/packages/react/src/tests/utils/__mocks__/my-organization/config/config.mocks.ts @@ -14,5 +14,6 @@ export const createMockUseConfig = (overrides?: Partial): MockUse }, fetchConfig: vi.fn(async () => undefined), filteredStrategies: [], + allowedRoles: [], ...overrides, }); diff --git a/packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts b/packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts new file mode 100644 index 000000000..79ec5d15d --- /dev/null +++ b/packages/react/src/tests/utils/__mocks__/my-organization/member-management/invitation.mocks.ts @@ -0,0 +1,108 @@ +import type { MemberInvitation } from '@auth0/universal-components-core'; +import { vi } from 'vitest'; + +import type { OrganizationInvitationDetailsModalProps } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-details/organization-invitation-details-modal'; +import type { OrganizationInvitationRevokeModalProps } from '@/components/auth0/my-organization/shared/member-management/invitations/invitation-revoke/organization-invitation-revoke-modal'; +import type { OrganizationInvitationCreateModalProps } from '@/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal'; +import type { + RoleOption, + IdentityProviderOption, + OrganizationInvitationTableActionsColumnProps, + SearchFilterProps, +} from '@/types/my-organization/member-management/organization-invitation-table-types'; + +export const createMockInvitation = (overrides?: Partial): MemberInvitation => ({ + id: 'inv_abc123xyz456', + invitee: { email: 'test@example.com' }, + inviter: { name: 'Admin User' }, + roles: ['role_admin'], + created_at: '2024-01-01T00:00:00.000Z', + expires_at: '2099-12-31T23:59:59.000Z', + invitation_url: 'https://example.auth0.com/invitation?ticket=abc123', + ...overrides, +}); + +export const createMockPendingInvitation = ( + overrides?: Partial, +): MemberInvitation => + createMockInvitation({ + invitation_url: 'https://example.auth0.com/invitation?ticket=pending123', + ...overrides, + }); + +export const createMockExpiredInvitation = ( + overrides?: Partial, +): MemberInvitation => + createMockInvitation({ + expires_at: '2020-01-01T00:00:00.000Z', + invitation_url: undefined, + ...overrides, + }); + +export const createMockRoles = (): RoleOption[] => [ + { id: 'role_admin', name: 'Admin', description: 'Administrator role' }, + { id: 'role_member', name: 'Member', description: 'Member role' }, + { id: 'role_viewer', name: 'Viewer', description: 'Viewer role' }, +]; + +export const createMockProviders = (): IdentityProviderOption[] => [ + { id: 'con_provider1', name: 'Google', type: 'social' }, + { id: 'con_provider2', name: 'Okta', type: 'enterprise' }, +]; + +export const createMockCreateModalProps = ( + overrides: Partial = {}, +): OrganizationInvitationCreateModalProps => ({ + isOpen: true, + isLoading: false, + onClose: vi.fn(), + onCreate: vi.fn(), + ...overrides, +}); + +export const createMockActionsColumnProps = ( + overrides: Partial = {}, +): OrganizationInvitationTableActionsColumnProps => ({ + invitation: createMockPendingInvitation(), + readOnly: false, + onViewDetails: vi.fn(), + onCopyUrl: vi.fn(), + onRevokeAndResend: vi.fn(), + onRevoke: vi.fn(), + ...overrides, +}); + +export const createMockDetailsModalProps = ( + overrides: Partial = {}, +): OrganizationInvitationDetailsModalProps => ({ + invitation: createMockPendingInvitation(), + isOpen: true, + isRevoking: false, + isResending: false, + onClose: vi.fn(), + onCopyUrl: vi.fn(), + onRevoke: vi.fn(), + onResend: vi.fn(), + ...overrides, +}); + +export const createMockRevokeModalProps = ( + overrides: Partial = {}, +): OrganizationInvitationRevokeModalProps => ({ + invitation: createMockPendingInvitation(), + isOpen: true, + isLoading: false, + isRevokeAndResend: false, + onClose: vi.fn(), + onConfirm: vi.fn(), + ...overrides, +}); + +export const createMockSearchFilterProps = ( + overrides: Partial = {}, +): SearchFilterProps => ({ + filters: {}, + availableRoles: createMockRoles(), + onRoleFilterChange: vi.fn(), + ...overrides, +}); From e44e20aa3b1a735e77f44d79ded1038919be4d81 Mon Sep 17 00:00:00 2001 From: rax7389 Date: Mon, 13 Apr 2026 22:53:36 +0530 Subject: [PATCH 018/125] refactor(react): addressed review comments --- .../organization-invitation-create-modal.tsx | 21 ++++++++-------- .../shared/search-filter/search-filter.tsx | 5 +++- .../member-management-utils.ts | 9 ++----- .../organization-member-management-types.ts | 24 +++++++++---------- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx index 2ad901088..758346dcf 100644 --- a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx @@ -174,20 +174,19 @@ export function OrganizationInvitationCreateModal({ return; } - // Create invitations for each email - for (const email of finalEmails) { - const invitationData: CreateInvitationInput = { - invitee: { email }, + const invitationData: CreateInvitationInput = { + invitees: finalEmails.map((email) => ({ + email, roles: selectedRoles.length > 0 ? selectedRoles : undefined, - identity_provider_id: selectedProvider, - }; + })), + identity_provider_id: selectedProvider, + }; - if (inviterName) { - invitationData.inviter = { name: inviterName }; - } - - onCreate(invitationData); + if (inviterName) { + invitationData.inviter = { name: inviterName }; } + + onCreate(invitationData); }, [ emailChips, diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx index 73612ad9a..62da9a66f 100644 --- a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx @@ -58,7 +58,10 @@ export function SearchFilter({ return (
    - - - - - {availableProviders.map((provider) => ( - - {provider.name} - - ))} - - -

    - {t('invitation.create.provider_helper')} -

    -
    + {/* Provider Dropdown */} +
    + + +

    + {t('invitation.create.provider_helper')} +

    + - - - - - + + + + ); From 7268bd9cd6d17ce3155fce58a61d946827b1238d Mon Sep 17 00:00:00 2001 From: rax7389 Date: Wed, 13 May 2026 23:30:45 +0530 Subject: [PATCH 068/125] fix: zindex fix for dropdowns --- packages/react/src/components/ui/combobox.tsx | 2 +- packages/react/src/components/ui/select.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react/src/components/ui/combobox.tsx b/packages/react/src/components/ui/combobox.tsx index 9296eb42c..d72b06c2d 100644 --- a/packages/react/src/components/ui/combobox.tsx +++ b/packages/react/src/components/ui/combobox.tsx @@ -402,7 +402,7 @@ export function Combobox({ diff --git a/packages/react/src/components/ui/select.tsx b/packages/react/src/components/ui/select.tsx index 3e2e386e5..e5f978d04 100644 --- a/packages/react/src/components/ui/select.tsx +++ b/packages/react/src/components/ui/select.tsx @@ -63,7 +63,7 @@ function SelectContent({ Date: Thu, 14 May 2026 11:29:43 +0530 Subject: [PATCH 069/125] feat(examples): add member scopes to bootstrap --- examples/scripts/utils/env-writer.mjs | 6 +++++- examples/scripts/utils/resource-servers.mjs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/scripts/utils/env-writer.mjs b/examples/scripts/utils/env-writer.mjs index ab8f132c3..cb2adba70 100644 --- a/examples/scripts/utils/env-writer.mjs +++ b/examples/scripts/utils/env-writer.mjs @@ -75,7 +75,11 @@ const MYORG_SCOPES = [ "read:my_org:member_invitations", "delete:my_org:member_invitations", "create:my_org:member_invitations", - "read:my_org:member_roles" + "read:my_org:member_roles", + "delete:my_org:member_roles", + "create:my_org:member_roles", + "read:my_org:members", + "delete:my_org:memberships", ] // My Account API scopes diff --git a/examples/scripts/utils/resource-servers.mjs b/examples/scripts/utils/resource-servers.mjs index 1e93b6028..f0cde7475 100644 --- a/examples/scripts/utils/resource-servers.mjs +++ b/examples/scripts/utils/resource-servers.mjs @@ -29,7 +29,11 @@ export const MYORG_API_SCOPES = [ "read:my_org:member_invitations", "delete:my_org:member_invitations", "create:my_org:member_invitations", -"read:my_org:member_roles" +"read:my_org:member_roles", +"delete:my_org:member_roles", +"create:my_org:member_roles", +"read:my_org:members", +"delete:my_org:memberships", ] // My Account API Scopes - desired scopes for MFA management From cc7d301eb3e9c1235ad7aa7c0fe17dfc4560c94b Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Thu, 14 May 2026 11:43:44 +0530 Subject: [PATCH 070/125] refactor(react): remove unused export --- packages/react/src/hooks/my-organization/use-member-detail.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react/src/hooks/my-organization/use-member-detail.ts b/packages/react/src/hooks/my-organization/use-member-detail.ts index 8b84f5b83..a17b0b186 100644 --- a/packages/react/src/hooks/my-organization/use-member-detail.ts +++ b/packages/react/src/hooks/my-organization/use-member-detail.ts @@ -132,5 +132,3 @@ export function useOrganizationMemberDetail( handleRemoveRolesConfirm, }; } - -export type { UseOrganizationMemberDetailResult }; From 4020ca7832074b918def76df4106646deaac2bc9 Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Thu, 14 May 2026 14:01:20 +0530 Subject: [PATCH 071/125] feat(react): simplify organization member detail tests --- .../organization-member-detail.test.tsx | 153 +++++++++--------- 1 file changed, 79 insertions(+), 74 deletions(-) diff --git a/packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx b/packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx index 4f6deb467..70a70c43c 100644 --- a/packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx +++ b/packages/react/src/components/auth0/my-organization/__tests__/organization-member-detail.test.tsx @@ -240,7 +240,6 @@ describe('OrganizationMemberDetail', () => { await waitForComponentToLoad(); - // Navigate to roles then back to details const rolesTab = screen.getByRole('tab', { name: 'member.detail.tabs.roles' }); await user.click(rolesTab); @@ -278,13 +277,11 @@ describe('OrganizationMemberDetail', () => { await waitForComponentToLoad(); - // Click remove from org button in details tab const removeButton = screen.getByRole('button', { name: /member.detail.actions.remove_from_org.delete_button/i, }); await user.click(removeButton); - // Modal should open — confirm const confirmButton = await screen.findByRole('button', { name: /member.detail.danger_zone.remove_from_org.confirm_button/i, }); @@ -404,7 +401,8 @@ describe('OrganizationMemberDetail', () => { describe('assignRolesAction.onBefore', () => { describe('when returns true', () => { - it('should call members.roles.assign when onBefore returns true', () => { + it('should call members.roles.assign', async () => { + const user = userEvent.setup(); const assignRolesAction: ComponentAction<{ userId: string; roleIds: string[] }> = { disabled: false, onBefore: vi.fn(() => true), @@ -417,38 +415,46 @@ describe('OrganizationMemberDetail', () => { ).mockResolvedValue({}); renderWithProviders( - { - if ( - assignRolesAction.onBefore && - !assignRolesAction.onBefore({ userId: 'auth0|testuser123', roleIds }) - ) - return; - void apiService.organization.members.roles.assign('auth0|testuser123', { - role_ids: roleIds, - }); - assignRolesAction.onAfter?.({ userId: 'auth0|testuser123', roleIds }); - }), - })} + , ); - // Modal is open — verify it renders and submit button is disabled (no roles selected) - expect(screen.getByText('member.detail.roles.assign_modal.title')).toBeInTheDocument(); + await waitForComponentToLoad(); + + const rolesTab = screen.getByRole('tab', { name: 'member.detail.tabs.roles' }); + await user.click(rolesTab); + + const assignButton = await screen.findByRole('button', { + name: /member.detail.roles.assign_button/i, + }); + await user.click(assignButton); + + await screen.findByText('member.detail.roles.assign_modal.title'); + + const comboboxInput = screen.getByPlaceholderText( + 'member.detail.roles.assign_modal.roles_placeholder', + ); + await user.click(comboboxInput); + + await user.click(await screen.findByRole('button', { name: /admin/i })); + + await user.click( + screen.getByRole('button', { + name: /member.detail.roles.assign_modal.submit_button/i, + }), + ); - const submitButton = screen.getByRole('button', { - name: /member.detail.roles.assign_modal.submit_button/i, + await waitFor(() => { + expect(assignRolesAction.onBefore).toHaveBeenCalled(); + expect(apiService.organization.members.roles.assign).toHaveBeenCalled(); }); - expect(submitButton).toBeDisabled(); }); }); describe('when returns false', () => { - it('should not call members.roles.assign when onBefore returns false', async () => { + it('should not call members.roles.assign', async () => { + const user = userEvent.setup(); const assignRolesAction: ComponentAction<{ userId: string; roleIds: string[] }> = { disabled: false, onBefore: vi.fn(() => false), @@ -460,33 +466,41 @@ describe('OrganizationMemberDetail', () => { apiService.organization.members.roles.assign as ReturnType ).mockResolvedValue({}); - const handleAssignRolesSubmit = vi.fn((roleIds: string[]) => { - if ( - assignRolesAction.onBefore && - !assignRolesAction.onBefore({ userId: 'auth0|testuser123', roleIds }) - ) - return; - void apiService.organization.members.roles.assign('auth0|testuser123', { - role_ids: roleIds, - }); - }); - renderWithProviders( - , ); - // Directly invoke the submit handler with role IDs to test the guard - handleAssignRolesSubmit(['rol_admin']); + await waitForComponentToLoad(); + + const rolesTab = screen.getByRole('tab', { name: 'member.detail.tabs.roles' }); + await user.click(rolesTab); - expect(assignRolesAction.onBefore).toHaveBeenCalledWith({ - userId: 'auth0|testuser123', - roleIds: ['rol_admin'], + const assignButton = await screen.findByRole('button', { + name: /member.detail.roles.assign_button/i, }); + await user.click(assignButton); + + await screen.findByText('member.detail.roles.assign_modal.title'); + + const comboboxInput = screen.getByPlaceholderText( + 'member.detail.roles.assign_modal.roles_placeholder', + ); + await user.click(comboboxInput); + + await user.click(await screen.findByRole('button', { name: /admin/i })); + + await user.click( + screen.getByRole('button', { + name: /member.detail.roles.assign_modal.submit_button/i, + }), + ); + + await waitFor(() => { + expect(assignRolesAction.onBefore).toHaveBeenCalled(); + }); + expect(apiService.organization.members.roles.assign).not.toHaveBeenCalled(); }); }); @@ -525,14 +539,12 @@ describe('OrganizationMemberDetail', () => { const rolesTab = screen.getByRole('tab', { name: 'member.detail.tabs.roles' }); await user.click(rolesTab); - // Find remove role button for first role const removeRoleButtons = await screen.findAllByRole('button', { name: /member.detail.roles.remove_confirm.confirm_button|remove/i, }); await user.click(removeRoleButtons[0]!); - // Confirm in modal const confirmButton = await screen.findByRole('button', { name: /member.detail.roles.remove_confirm.confirm_button/i, }); @@ -553,36 +565,31 @@ describe('OrganizationMemberDetail', () => { onAfter: vi.fn(), }; - const role = createMockMemberRole({ id: 'rol_admin', name: 'Admin' }); - const apiService = mockCoreClient.getMyOrganizationApiClient(); + (apiService.organization.members.get as ReturnType).mockResolvedValue( + memberWithRoles, + ); ( apiService.organization.members.roles.unassign as ReturnType ).mockResolvedValue({}); - // Directly render the view with the remove role modal open renderWithProviders( - { - if ( - removeRolesAction.onBefore && - !removeRolesAction.onBefore({ - userId: 'auth0|testuser123', - roleIds: [role.id], - }) - ) - return; - void apiService.organization.members.roles.unassign('auth0|testuser123', { - role_ids: [role.id], - }); - }), - })} + , ); + await waitForComponentToLoad(); + + const rolesTab = screen.getByRole('tab', { name: 'member.detail.tabs.roles' }); + await user.click(rolesTab); + + const removeRoleButtons = await screen.findAllByRole('button', { + name: /member.detail.roles.remove_confirm.confirm_button|remove/i, + }); + + await user.click(removeRoleButtons[0]!); + const confirmButton = await screen.findByRole('button', { name: /member.detail.roles.remove_confirm.confirm_button/i, }); @@ -746,7 +753,6 @@ describe('OrganizationMemberDetailView', () => { />, ); - // Badge should not be in DOM when userId is empty const badges = document.querySelectorAll('.font-mono'); expect(badges.length).toBe(0); }); @@ -779,7 +785,7 @@ describe('OrganizationMemberDetailView', () => { ).not.toBeInTheDocument(); }); - it('when modal cancel is clicked, should call closeModal', async () => { + it('when cancel is clicked, should call closeModal', async () => { const user = userEvent.setup(); const closeModal = vi.fn(); @@ -831,7 +837,6 @@ describe('OrganizationMemberDetailView', () => { />, ); - // Loading state shows Spinner (sr-only text "Loading...") expect(screen.getByRole('button', { name: 'Loading...' })).toBeInTheDocument(); }); }); From 32ee1b34735e8aa555a44bd7e769974dc420873b Mon Sep 17 00:00:00 2001 From: subramanyachakravarthy-okta Date: Thu, 14 May 2026 14:26:42 +0530 Subject: [PATCH 072/125] feat(examples): update import path and decode user_id parameter --- .../next-rwa/src/app/member-management/[user_id]/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/next-rwa/src/app/member-management/[user_id]/page.tsx b/examples/next-rwa/src/app/member-management/[user_id]/page.tsx index 03553c33d..e5cda6897 100644 --- a/examples/next-rwa/src/app/member-management/[user_id]/page.tsx +++ b/examples/next-rwa/src/app/member-management/[user_id]/page.tsx @@ -1,12 +1,12 @@ 'use client'; -import { OrganizationMemberDetail } from '@auth0/universal-components-react/rwa'; +import { OrganizationMemberDetail } from '@auth0/universal-components-react'; import { useRouter, useParams } from 'next/navigation'; export default function MemberDetailPage() { const router = useRouter(); const params = useParams(); - const user_id = params.user_id as string; + const user_id = decodeURIComponent(params.user_id as string); return (
    From ffdc42e6458d5983c0c39ee698746f61853519eb Mon Sep 17 00:00:00 2001 From: rax7389 Date: Thu, 14 May 2026 22:42:55 +0530 Subject: [PATCH 073/125] fix: add truncate for email column --- .../invitation-table/organization-invitation-table.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx index cdb07ddfa..4bbf78ccd 100644 --- a/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/invitations/invitation-table/organization-invitation-table.tsx @@ -79,15 +79,17 @@ export function OrganizationInvitationTable({ type: 'text', accessorKey: 'invitee', title: t('invitation.table.columns.email'), + width: '25%', enableSorting: false, render: (invitation) => ( -
    {invitation.invitee?.email}
    +
    {invitation.invitee?.email}
    ), }, { type: 'text', accessorKey: 'organization_id', title: t('invitation.table.columns.status'), + width: '10%', enableSorting: false, render: (invitation) => { const status = getInvitationStatus(invitation); From dfacb5d191c8dea70108426dc498b839fc68515f Mon Sep 17 00:00:00 2001 From: rax7389 Date: Fri, 15 May 2026 15:17:27 +0530 Subject: [PATCH 074/125] fix: addressed review comments --- .../organization-invitation-create-modal.tsx | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx index 0a98579d9..a4f1b6be9 100644 --- a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/invitation-create/organization-invitation-create-modal.tsx @@ -72,15 +72,19 @@ export function OrganizationInvitationCreateModal({ const [selectedProvider, setSelectedProvider] = React.useState(); const [emailError, setEmailError] = React.useState(); + const resetForm = React.useCallback(() => { + setEmailInput(''); + setEmailChips([]); + setSelectedRoles([]); + setSelectedProvider(undefined); + setEmailError(undefined); + }, []); + React.useEffect(() => { if (!isOpen) { - setEmailInput(''); - setEmailChips([]); - setSelectedRoles([]); - setSelectedProvider(undefined); - setEmailError(undefined); + resetForm(); } - }, [isOpen]); + }, [isOpen, resetForm]); const handleEmailInputChange = React.useCallback((e: React.ChangeEvent) => { setEmailInput(e.target.value); @@ -154,6 +158,9 @@ export function OrganizationInvitationCreateModal({ const result = validationConfig.emailSchema.safeParse(trimmedEmail); if (result.success && !finalEmails.includes(trimmedEmail)) { finalEmails.push(trimmedEmail); + } else if (!result.success) { + setEmailError(t('invitation.create.email_invalid_error')); + return; } } @@ -182,13 +189,9 @@ export function OrganizationInvitationCreateModal({ ]); const handleClose = React.useCallback(() => { - setEmailInput(''); - setEmailChips([]); - setSelectedRoles([]); - setSelectedProvider(undefined); - setEmailError(undefined); + resetForm(); onClose(); - }, [onClose]); + }, [onClose, resetForm]); const canSubmit = React.useMemo( () => @@ -213,7 +216,6 @@ export function OrganizationInvitationCreateModal({
    - {/* Email Input */}
    {emailError}

    }
    - {/* Roles Combobox */}
    - {/* Provider Dropdown */}
    + {currentValue && !disabled && ( + + )} +
    + ); +} + +export { Search, searchVariants }; From bc66c1af7b47d2afb13b5240e17db526345073c8 Mon Sep 17 00:00:00 2001 From: grandmaester Date: Mon, 18 May 2026 03:03:26 +0530 Subject: [PATCH 077/125] feat(core): add schemas, i18n, custom messages and types --- .../custom-messages/my-organization/index.ts | 1 + .../member-management-types.ts | 2 + .../member-management/member-tab-types.ts | 51 +++++ .../core/src/i18n/translations/en-US.json | 31 ++- packages/core/src/i18n/translations/fr.json | 31 ++- packages/core/src/i18n/translations/ja.json | 31 ++- .../core/src/schemas/my-organization/index.ts | 1 + .../members/__tests__/member-schema.test.ts | 201 ++++++++++++++++++ .../members/member-schema.ts | 45 ++++ .../member-management-constants.ts | 1 + 10 files changed, 389 insertions(+), 6 deletions(-) create mode 100644 packages/core/src/i18n/custom-messages/my-organization/member-management/member-tab-types.ts create mode 100644 packages/core/src/schemas/my-organization/member-management/members/__tests__/member-schema.test.ts create mode 100644 packages/core/src/schemas/my-organization/member-management/members/member-schema.ts diff --git a/packages/core/src/i18n/custom-messages/my-organization/index.ts b/packages/core/src/i18n/custom-messages/my-organization/index.ts index 845ecef45..1c6aa7c35 100644 --- a/packages/core/src/i18n/custom-messages/my-organization/index.ts +++ b/packages/core/src/i18n/custom-messages/my-organization/index.ts @@ -9,3 +9,4 @@ export * from './organization-management'; export * from './domain-management'; export * from './member-management/invitation-tab-types'; export * from './member-management/member-management-types'; +export * from './member-management/member-tab-types'; diff --git a/packages/core/src/i18n/custom-messages/my-organization/member-management/member-management-types.ts b/packages/core/src/i18n/custom-messages/my-organization/member-management/member-management-types.ts index 60bfc9796..16144d5f3 100644 --- a/packages/core/src/i18n/custom-messages/my-organization/member-management/member-management-types.ts +++ b/packages/core/src/i18n/custom-messages/my-organization/member-management/member-management-types.ts @@ -5,6 +5,7 @@ */ import type { OrganizationInvitationTabMessages } from './invitation-tab-types'; +import type { OrganizationMemberTabMessages } from './member-tab-types'; export interface OrganizationMemberManagementMessages { header?: { @@ -16,4 +17,5 @@ export interface OrganizationMemberManagementMessages { invitations?: string; }; invitation?: OrganizationInvitationTabMessages; + member?: OrganizationMemberTabMessages; } diff --git a/packages/core/src/i18n/custom-messages/my-organization/member-management/member-tab-types.ts b/packages/core/src/i18n/custom-messages/my-organization/member-management/member-tab-types.ts new file mode 100644 index 000000000..3aca07074 --- /dev/null +++ b/packages/core/src/i18n/custom-messages/my-organization/member-management/member-tab-types.ts @@ -0,0 +1,51 @@ +/** + * Custom message type definitions for member tab. + * @module member-tab-types + * @internal + */ + +export interface OrganizationMemberTabMessages { + table?: { + columns?: { + name?: string; + roles?: string; + last_login?: string; + }; + empty_message?: string; + search_placeholder?: string; + filter_by_role?: string; + all_roles?: string; + reset_filter?: string; + showing_results?: string; + }; + actions?: { + menu_label?: string; + view_details?: string; + assign_roles?: string; + remove_from_org?: string; + }; + assign_roles?: { + title?: string; + description?: string; + roles_label?: string; + roles_placeholder?: string; + submit_button?: string; + cancel_button?: string; + no_roles_available?: string; + }; + remove_from_org?: { + title?: string; + description?: string; + confirm_button?: string; + cancel_button?: string; + }; + success?: { + removed_from_org?: string; + role_assigned?: string; + }; + error?: { + fetch_failed?: string; + assign_roles_failed?: string; + remove_from_org_failed?: string; + }; +} diff --git a/packages/core/src/i18n/translations/en-US.json b/packages/core/src/i18n/translations/en-US.json index e659518a1..e7cebedc7 100644 --- a/packages/core/src/i18n/translations/en-US.json +++ b/packages/core/src/i18n/translations/en-US.json @@ -1085,14 +1085,41 @@ "columns": { "name": "Name", "email": "Email", - "roles": "Roles" + "roles": "Roles", + "last_login": "Last Login" }, - "empty_message": "No members found." + "empty_message": "No members found.", + "search_placeholder": "Search by email...", + "filter_by_role": "Filter By Role", + "all_roles": "All", + "reset_filter": "Reset" + }, + "actions": { + "menu_label": "Actions", + "view_details": "View Details", + "assign_role": "Assign Role", + "remove_from_org": "Remove from Organization" }, "error": { "fetch_failed": "Failed to load members. Please try again.", "remove_failed": "Failed to remove member. Please try again." }, + "remove_from_org_modal": { + "title": "Remove Member from ${organizationName}", + "description": "Are you sure you want to remove ${memberName} from this organization? This action will not delete their account but it will revoke their access and prevent them from signing in.", + "remove_button": "Remove", + "cancel_button": "Cancel" + }, + "assign_role_modal": { + "title": "Assign Roles", + "roles_label": "Roles", + "roles_placeholder": "Select role(s)", + "submit_button": "Assign Role(s)", + "cancel_button": "Cancel", + "no_roles_available": "All available roles are already assigned.", + "success": "The role has been assigned.", + "success_plural": "The roles have been assigned." + }, "detail": { "back_button": "Back to Members", "tabs": { diff --git a/packages/core/src/i18n/translations/fr.json b/packages/core/src/i18n/translations/fr.json index 74c0146a5..0e5d14a12 100644 --- a/packages/core/src/i18n/translations/fr.json +++ b/packages/core/src/i18n/translations/fr.json @@ -1023,14 +1023,41 @@ "columns": { "name": "Nom", "email": "E-mail", - "roles": "Rôles" + "roles": "Rôles", + "last_login": "Dernière connexion" }, - "empty_message": "Aucun membre trouvé." + "empty_message": "Aucun membre trouvé.", + "search_placeholder": "Rechercher par e-mail...", + "filter_by_role": "Filtrer par rôle", + "all_roles": "Tous", + "reset_filter": "Réinitialiser" + }, + "actions": { + "menu_label": "Actions", + "view_details": "Afficher les détails", + "assign_role": "Attribuer un rôle", + "remove_from_org": "Supprimer de l'organisation" }, "error": { "fetch_failed": "Échec du chargement des membres. Veuillez réessayer.", "remove_failed": "Échec de la suppression du membre. Veuillez réessayer." }, + "remove_from_org_modal": { + "title": "Supprimer le membre de ${organizationName}", + "description": "Voulez-vous vraiment supprimer ${memberName} de cette organisation ? Cette action ne supprimera pas son compte, mais elle révoquera son accès et l'empêchera de se connecter.", + "remove_button": "Supprimer", + "cancel_button": "Annuler" + }, + "assign_role_modal": { + "title": "Attribuer des rôles", + "roles_label": "Rôles", + "roles_placeholder": "Sélectionner un ou des rôles", + "submit_button": "Attribuer le(s) rôle(s)", + "cancel_button": "Annuler", + "no_roles_available": "Tous les rôles disponibles sont déjà attribués.", + "success": "Le rôle a été attribué.", + "success_plural": "Les rôles ont été attribués." + }, "detail": { "back_button": "Retour aux membres", "tabs": { diff --git a/packages/core/src/i18n/translations/ja.json b/packages/core/src/i18n/translations/ja.json index c8c83fe63..18eda58b9 100644 --- a/packages/core/src/i18n/translations/ja.json +++ b/packages/core/src/i18n/translations/ja.json @@ -1086,14 +1086,41 @@ "columns": { "name": "名前", "email": "メール", - "roles": "ロール" + "roles": "ロール", + "last_login": "最終ログイン" }, - "empty_message": "メンバーが見つかりません。" + "empty_message": "メンバーが見つかりません。", + "search_placeholder": "メールで検索...", + "filter_by_role": "ロールでフィルター", + "all_roles": "すべて", + "reset_filter": "リセット" + }, + "actions": { + "menu_label": "アクション", + "view_details": "詳細を表示", + "assign_role": "ロールを割り当てる", + "remove_from_org": "組織から削除" }, "error": { "fetch_failed": "メンバーの読み込みに失敗しました。もう一度お試しください。", "remove_failed": "メンバーの削除に失敗しました。もう一度お試しください。" }, + "remove_from_org_modal": { + "title": "${organizationName} からメンバーを削除", + "description": "この組織から ${memberName} を削除してもよろしいですか?この操作でアカウントは削除されませんが、アクセス権が取り消され、サインインできなくなります。", + "remove_button": "削除", + "cancel_button": "キャンセル" + }, + "assign_role_modal": { + "title": "ロールを割り当てる", + "roles_label": "ロール", + "roles_placeholder": "ロールを選択", + "submit_button": "ロールを割り当てる", + "cancel_button": "キャンセル", + "no_roles_available": "利用可能なすべてのロールがすでに割り当てられています。", + "success": "ロールが割り当てられました。", + "success_plural": "ロールが割り当てられました。" + }, "detail": { "back_button": "メンバー一覧に戻る", "tabs": { diff --git a/packages/core/src/schemas/my-organization/index.ts b/packages/core/src/schemas/my-organization/index.ts index c800eec7e..84c779143 100644 --- a/packages/core/src/schemas/my-organization/index.ts +++ b/packages/core/src/schemas/my-organization/index.ts @@ -10,3 +10,4 @@ export * from './domain-management'; export * from './member-management/invitations/invitation-schema'; export * from './member-management/invitations/invitation-create-schema'; export * from './member-management/invitations/invitation-create-schema-types'; +export * from './member-management/members/member-schema'; diff --git a/packages/core/src/schemas/my-organization/member-management/members/__tests__/member-schema.test.ts b/packages/core/src/schemas/my-organization/member-management/members/__tests__/member-schema.test.ts new file mode 100644 index 000000000..afa0fd5de --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/members/__tests__/member-schema.test.ts @@ -0,0 +1,201 @@ +import { describe, expect, it } from 'vitest'; + +import { memberListResponseSchema, memberSchema } from '../member-schema'; + +describe('Member Schema', () => { + describe('memberSchema', () => { + it('should accept a member with only the required user_id field', () => { + const result = memberSchema.safeParse({ user_id: 'auth0|123' }); + + expect(result.success).toBe(true); + }); + + it('should accept a member with all supported fields', () => { + const result = memberSchema.safeParse({ + user_id: 'auth0|123', + roles: [ + { id: 'rol_admin', name: 'Admin' }, + { id: 'rol_viewer', name: 'Viewer' }, + ], + email: 'member@example.com', + name: 'Ada Lovelace', + given_name: 'Ada', + family_name: 'Lovelace', + nickname: 'ada', + updated_at: '2026-05-18T10:00:00.000Z', + created_at: '2026-05-10T10:00:00.000Z', + last_login: '2026-05-17T10:00:00.000Z', + }); + + expect(result.success).toBe(true); + }); + + it('should reject a member when user_id is missing', () => { + const result = memberSchema.safeParse({ + email: 'member@example.com', + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['user_id']); + } + }); + + it('should reject a member when user_id is not a string', () => { + const result = memberSchema.safeParse({ user_id: 12345 }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['user_id']); + } + }); + + describe.each([ + { input: 'member@example.com', shouldPass: true, description: 'valid email' }, + { input: 'user+tag@example.com', shouldPass: true, description: 'email with plus tag' }, + { input: undefined, shouldPass: true, description: 'undefined optional email' }, + { input: '', shouldPass: false, description: 'empty string' }, + { input: 'invalid-email', shouldPass: false, description: 'invalid email format' }, + { input: 'user@', shouldPass: false, description: 'missing domain' }, + ])('when email is $input ($description)', ({ input, shouldPass }) => { + it(`should ${shouldPass ? 'accept' : 'reject'} the member`, () => { + const result = memberSchema.safeParse({ + user_id: 'auth0|123', + email: input, + }); + + expect(result.success).toBe(shouldPass); + }); + }); + + it('should accept a member when roles are omitted', () => { + const result = memberSchema.safeParse({ user_id: 'auth0|123' }); + + expect(result.success).toBe(true); + }); + + it('should accept a member with an empty roles array', () => { + const result = memberSchema.safeParse({ + user_id: 'auth0|123', + roles: [], + }); + + expect(result.success).toBe(true); + }); + + it('should reject a member when a role is missing id', () => { + const result = memberSchema.safeParse({ + user_id: 'auth0|123', + roles: [{ name: 'Admin' }], + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['roles', 0, 'id']); + } + }); + + it('should reject a member when a role is missing name', () => { + const result = memberSchema.safeParse({ + user_id: 'auth0|123', + roles: [{ id: 'rol_admin' }], + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['roles', 0, 'name']); + } + }); + + it('should reject a member when roles is not an array', () => { + const result = memberSchema.safeParse({ + user_id: 'auth0|123', + roles: { id: 'rol_admin', name: 'Admin' }, + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['roles']); + } + }); + }); + + describe('memberListResponseSchema', () => { + it('should accept a valid member list response', () => { + const result = memberListResponseSchema.safeParse({ + members: [ + { + user_id: 'auth0|123', + email: 'member@example.com', + roles: [{ id: 'rol_admin', name: 'Admin' }], + }, + { + user_id: 'auth0|456', + name: 'Grace Hopper', + }, + ], + total: 2, + start: 0, + limit: 10, + }); + + expect(result.success).toBe(true); + }); + + it('should accept a response with only members', () => { + const result = memberListResponseSchema.safeParse({ + members: [{ user_id: 'auth0|123' }], + }); + + expect(result.success).toBe(true); + }); + + it('should reject a response when members is missing', () => { + const result = memberListResponseSchema.safeParse({ + total: 1, + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['members']); + } + }); + + it('should reject a response when members is not an array', () => { + const result = memberListResponseSchema.safeParse({ + members: { user_id: 'auth0|123' }, + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['members']); + } + }); + + it('should reject a response when a member entry is invalid', () => { + const result = memberListResponseSchema.safeParse({ + members: [{ user_id: 'auth0|123' }, { email: 'missing-user-id@example.com' }], + }); + + expect(result.success).toBe(false); + if (!result.success && result.error?.errors[0]) { + expect(result.error.errors[0].path).toEqual(['members', 1, 'user_id']); + } + }); + + describe.each([ + { field: 'total', value: '2' }, + { field: 'start', value: '0' }, + { field: 'limit', value: '10' }, + ])('when $field is not a number', ({ field, value }) => { + it('should reject the response', () => { + const result = memberListResponseSchema.safeParse({ + members: [{ user_id: 'auth0|123' }], + [field]: value, + }); + + expect(result.success).toBe(false); + }); + }); + }); +}); diff --git a/packages/core/src/schemas/my-organization/member-management/members/member-schema.ts b/packages/core/src/schemas/my-organization/member-management/members/member-schema.ts new file mode 100644 index 000000000..9c2276e56 --- /dev/null +++ b/packages/core/src/schemas/my-organization/member-management/members/member-schema.ts @@ -0,0 +1,45 @@ +/** + * Member validation schemas. + * @module member-schema + * @internal + */ + +import { z } from 'zod'; + +/** + * Schema for organization member data. + * @internal + */ +export const memberSchema = z.object({ + user_id: z.string(), + roles: z + .array( + z.object({ + id: z.string(), + name: z.string(), + }), + ) + .optional(), + email: z.string().email().optional(), + name: z.string().optional(), + given_name: z.string().optional(), + family_name: z.string().optional(), + nickname: z.string().optional(), + updated_at: z.string().optional(), + created_at: z.string().optional(), + last_login: z.string().optional(), +}); + +/** + * Schema for member list response. + * @internal + */ +export const memberListResponseSchema = z.object({ + members: z.array(memberSchema), + total: z.number().optional(), + start: z.number().optional(), + limit: z.number().optional(), +}); + +export type Member = z.infer; +export type MemberListResponse = z.infer; diff --git a/packages/core/src/services/my-organization/member-management/member-management-constants.ts b/packages/core/src/services/my-organization/member-management/member-management-constants.ts index 042d29089..2f29e8b9f 100644 --- a/packages/core/src/services/my-organization/member-management/member-management-constants.ts +++ b/packages/core/src/services/my-organization/member-management/member-management-constants.ts @@ -8,4 +8,5 @@ export const memberManagementQueryKeys = { all: ['member-management'] as const, invitations: () => [...memberManagementQueryKeys.all, 'invitations'] as const, roles: () => [...memberManagementQueryKeys.all, 'roles'] as const, + members: () => [...memberManagementQueryKeys.all, 'members'] as const, }; From 07548a890a9ad9726a745bf3a10a03739f7fc2d7 Mon Sep 17 00:00:00 2001 From: grandmaester Date: Mon, 18 May 2026 03:48:53 +0530 Subject: [PATCH 078/125] feat(core, react): add service types and member flow components --- .../member-management-types.ts | 5 + ...nization-member-assign-role-modal.test.tsx | 179 +++++++++++++++++ .../organization-member-assign-role-modal.tsx | 115 +++++++++++ ...tion-member-remove-from-org-modal.test.tsx | 151 +++++++++++++++ ...anization-member-remove-from-org-modal.tsx | 75 ++++++++ ...ation-member-table-actions-column.test.tsx | 116 +++++++++++ .../organization-member-table.test.tsx | 116 +++++++++++ ...ganization-member-table-actions-column.tsx | 84 ++++++++ .../organization-member-table.tsx | 182 ++++++++++++++++++ .../__tests__/search-filter.test.tsx | 68 ++++++- .../shared/search-filter/search-filter.tsx | 31 ++- .../member-management-utils.ts | 120 +++++++++++- .../utils/__mocks__/core/core-client.mocks.ts | 9 + .../member-management/member.mocks.ts | 108 +++++++++++ packages/react/src/types/index.ts | 1 + .../organization-invitation-table-types.ts | 33 ++-- .../organization-member-management-types.ts | 92 +++++++-- .../organization-member-table-types.ts | 61 ++++++ 18 files changed, 1508 insertions(+), 38 deletions(-) create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/__tests__/organization-member-assign-role-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/organization-member-assign-role-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/__tests__/organization-member-remove-from-org-modal.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/organization-member-remove-from-org-modal.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table-actions-column.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table.test.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table-actions-column.tsx create mode 100644 packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table.tsx create mode 100644 packages/react/src/tests/utils/__mocks__/my-organization/member-management/member.mocks.ts create mode 100644 packages/react/src/types/my-organization/member-management/organization-member-table-types.ts diff --git a/packages/core/src/services/my-organization/member-management/member-management-types.ts b/packages/core/src/services/my-organization/member-management/member-management-types.ts index 157bf58c3..5726da4af 100644 --- a/packages/core/src/services/my-organization/member-management/member-management-types.ts +++ b/packages/core/src/services/my-organization/member-management/member-management-types.ts @@ -103,3 +103,8 @@ export type Role = MyOrganization.Role; * Organization role ID. */ export type RoleId = MyOrganization.RoleId; + +/** + * Response content for listing organization roles. + */ +export type ListRolesResponseContent = MyOrganization.ListRolesResponseContent; diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/__tests__/organization-member-assign-role-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/__tests__/organization-member-assign-role-modal.test.tsx new file mode 100644 index 000000000..f1f9c9e37 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/__tests__/organization-member-assign-role-modal.test.tsx @@ -0,0 +1,179 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { afterEach, describe, expect, it, vi } from 'vitest'; + +import { OrganizationMemberAssignRolesModal } from '@/components/auth0/my-organization/shared/member-management/members/members-assign/organization-member-assign-role-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockMember, + createMockMemberAssignRoleModalProps, + createMockRoleOptions, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('OrganizationMemberAssignRolesModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + it('should render the modal when open', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should not render the modal content when closed', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + describe('rendering', () => { + it('should render title, label, and action buttons when roles are available', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('member.assign_role_modal.title')).toBeInTheDocument(); + expect(screen.getByText('member.assign_role_modal.roles_label')).toBeInTheDocument(); + expect( + screen.getByPlaceholderText('member.assign_role_modal.roles_placeholder'), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.assign_role_modal.cancel_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.assign_role_modal.submit_button' }), + ).toBeDisabled(); + }); + + it('should show no roles message when all roles are already assigned', () => { + const availableRoles = createMockRoleOptions(); + + renderWithProviders( + ({ id: role.id })), + })} + />, + ); + + expect(screen.getByText('member.assign_role_modal.no_roles_available')).toBeInTheDocument(); + expect( + screen.queryByPlaceholderText('member.assign_role_modal.roles_placeholder'), + ).not.toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.assign_role_modal.submit_button' }), + ).toBeDisabled(); + }); + }); + + describe('loading state', () => { + it('should disable the combobox and action buttons when loading', () => { + renderWithProviders( + , + ); + + expect( + screen.getByPlaceholderText('member.assign_role_modal.roles_placeholder'), + ).toBeDisabled(); + expect( + screen.getByRole('button', { name: 'member.assign_role_modal.cancel_button' }), + ).toBeDisabled(); + expect( + screen.getByRole('button', { name: 'member.assign_role_modal.submit_button' }), + ).toBeDisabled(); + }); + }); + + describe('callbacks', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.assign_role_modal.cancel_button' }), + ); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('should call onAssign with selected role ids when submit is clicked', async () => { + const user = userEvent.setup(); + const onAssign = vi.fn(); + const member = createMockMember({ user_id: 'usr_assign_1' }); + + renderWithProviders( + , + ); + + await user.click(screen.getByPlaceholderText('member.assign_role_modal.roles_placeholder')); + await user.click(screen.getByRole('button', { name: 'Admin' })); + + const submitButton = screen.getByRole('button', { + name: 'member.assign_role_modal.submit_button', + }); + expect(submitButton).toBeEnabled(); + + await user.click(submitButton); + + expect(onAssign).toHaveBeenCalledTimes(1); + expect(onAssign).toHaveBeenCalledWith('usr_assign_1', ['role_admin']); + }); + + it('should not call onAssign when member is null', async () => { + const user = userEvent.setup(); + const onAssign = vi.fn(); + + renderWithProviders( + , + ); + + await user.click(screen.getByPlaceholderText('member.assign_role_modal.roles_placeholder')); + await user.click(screen.getByRole('button', { name: 'Admin' })); + await user.click( + screen.getByRole('button', { name: 'member.assign_role_modal.submit_button' }), + ); + + expect(onAssign).not.toHaveBeenCalled(); + }); + + it('should filter out already assigned roles from the combobox options', async () => { + const user = userEvent.setup(); + + renderWithProviders( + , + ); + + await user.click(screen.getByPlaceholderText('member.assign_role_modal.roles_placeholder')); + + expect(screen.queryByRole('button', { name: 'Admin' })).not.toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Member' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'Viewer' })).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/organization-member-assign-role-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/organization-member-assign-role-modal.tsx new file mode 100644 index 000000000..65d4e2350 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-assign/organization-member-assign-role-modal.tsx @@ -0,0 +1,115 @@ +/** + * Modal for assigning roles to a member. + * @module member-assign-roles-modal + * @internal + */ + +// import type { OrgMemberRole } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { Combobox } from '@/components/ui/combobox'; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Label } from '@/components/ui/label'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberAssignRoleModalProps } from '@/types/my-organization/member-management/organization-member-management-types'; + +/** + * Renders the assign roles dialog for selecting and assigning roles to a member. + * @param root0 - Component props + * @returns The rendered assign roles dialog element + */ +export function OrganizationMemberAssignRolesModal({ + member, + isOpen, + isLoading = false, + availableRoles, + assignedRoles, + className, + customMessages = {}, + onClose, + onAssign, +}: OrganizationMemberAssignRoleModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + const [selectedRoles, setSelectedRoles] = React.useState([]); + + const assignedRoleIds = React.useMemo( + () => new Set(assignedRoles.map((r) => r.id)), + [assignedRoles], + ); + + const unassignedRoles = React.useMemo( + () => availableRoles.filter((r) => !assignedRoleIds.has(r.id)), + [availableRoles, assignedRoleIds], + ); + + const handleOpenChange = React.useCallback( + (open: boolean) => { + if (!open) { + setSelectedRoles([]); + onClose(); + } + }, + [onClose], + ); + + const handleSubmit = React.useCallback(() => { + if (selectedRoles.length > 0 && member) { + onAssign(member.user_id ?? '', selectedRoles); + } + }, [selectedRoles, onAssign]); + + React.useEffect(() => { + if (!isOpen) { + setSelectedRoles([]); + } + }, [isOpen]); + + return ( + + + + {t('member.assign_role_modal.title')} + + +
    + {unassignedRoles.length === 0 ? ( +

    + {t('member.assign_role_modal.no_roles_available')} +

    + ) : ( + <> + + ({ value: r.id, label: r.name }))} + value={selectedRoles} + onChange={(val) => setSelectedRoles(Array.isArray(val) ? val : [val])} + placeholder={t('member.assign_role_modal.roles_placeholder')} + disabled={isLoading} + /> + + )} +
    + + + + + +
    +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/__tests__/organization-member-remove-from-org-modal.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/__tests__/organization-member-remove-from-org-modal.test.tsx new file mode 100644 index 000000000..244af66ec --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/__tests__/organization-member-remove-from-org-modal.test.tsx @@ -0,0 +1,151 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { afterEach, describe, expect, it, vi } from 'vitest'; + +import { OrganizationMemberRemoveFromOrgModal } from '@/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/organization-member-remove-from-org-modal'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockMember, + createMockMemberRemoveFromOrgModalProps, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('OrganizationMemberRemoveFromOrgModal', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('isOpen', () => { + it('should render the modal when open', () => { + renderWithProviders( + , + ); + + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); + + it('should not render the modal content when closed', () => { + renderWithProviders( + , + ); + + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + }); + + describe('rendering', () => { + it('should render title, description, and action buttons', () => { + renderWithProviders( + , + ); + + expect(screen.getByText('member.remove_from_org_modal.title')).toBeInTheDocument(); + expect(screen.getByText('member.remove_from_org_modal.description')).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.remove_from_org_modal.cancel_button' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'member.remove_from_org_modal.remove_button' }), + ).toBeInTheDocument(); + }); + + it('should apply custom class name to the modal content', () => { + renderWithProviders( + , + ); + + const modalContent = document.querySelector('[data-slot="dialog-content"]'); + expect(modalContent).toHaveClass('custom-remove-modal'); + }); + }); + + describe('loading state', () => { + it('should disable both buttons when loading', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.remove_from_org_modal.cancel_button' }), + ).toBeDisabled(); + expect(screen.getByRole('button', { name: '...' })).toBeDisabled(); + }); + + it('should disable the remove button when member has no user id', () => { + renderWithProviders( + , + ); + + expect( + screen.getByRole('button', { name: 'member.remove_from_org_modal.remove_button' }), + ).toBeDisabled(); + }); + }); + + describe('callbacks', () => { + it('should call onClose when cancel button is clicked', async () => { + const user = userEvent.setup(); + const onClose = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.remove_from_org_modal.cancel_button' }), + ); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('should call onConfirm with member user id when remove button is clicked', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + const member = createMockMember({ user_id: 'usr_remove_1' }); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.remove_from_org_modal.remove_button' }), + ); + + expect(onConfirm).toHaveBeenCalledTimes(1); + expect(onConfirm).toHaveBeenCalledWith('usr_remove_1'); + }); + + it('should not call onConfirm when member has no user id', async () => { + const user = userEvent.setup(); + const onConfirm = vi.fn(); + + renderWithProviders( + , + ); + + await user.click( + screen.getByRole('button', { name: 'member.remove_from_org_modal.remove_button' }), + ); + + expect(onConfirm).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/organization-member-remove-from-org-modal.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/organization-member-remove-from-org-modal.tsx new file mode 100644 index 000000000..736e34ed7 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-remove-from-organization/organization-member-remove-from-org-modal.tsx @@ -0,0 +1,75 @@ +/** + * Confirmation modal for removing a member from the organization. + * @module member-remove-from-org-modal + * @internal + */ + +import * as React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberRemoveFromOrgModalProps } from '@/types/my-organization/member-management/organization-member-management-types'; + +/** + * Renders the confirmation dialog for removing a member from the organization. + * @param root0 - Component props + * @returns The rendered confirmation dialog element + */ +export function OrganizationMemberRemoveFromOrgModal({ + member, + isOpen, + className, + customMessages = {}, + isLoading = false, + onClose, + onConfirm, +}: OrganizationMemberRemoveFromOrgModalProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const handleConfirm = React.useCallback(() => { + if (!member?.user_id) return; + onConfirm(member.user_id); + }, [member?.user_id, onConfirm]); + + return ( + !open && onClose()}> + + + + {t('member.remove_from_org_modal.title', { + vars: { orgName: member?.name ?? '' }, + })} + + + + <> + {t.trans('member.remove_from_org_modal.description', { + vars: { memberName: member?.name ?? '' }, + components: { bold: (children: string) => {children} }, + })} + + + + + + + + + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table-actions-column.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table-actions-column.test.tsx new file mode 100644 index 000000000..b16241597 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table-actions-column.test.tsx @@ -0,0 +1,116 @@ +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { OrganizationMemberTableActionsColumn } from '@/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table-actions-column'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockMember, + createMockMemberActionsColumnProps, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('OrganizationMemberTableActionsColumn', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe('Rendering and Basic Structure', () => { + it('should render dropdown trigger button', () => { + const props = createMockMemberActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button', { name: 'member.actions.menu_label' }); + expect(trigger).toBeInTheDocument(); + expect(trigger).toHaveClass('h-8', 'w-8'); + }); + + it('should have proper accessibility attributes', () => { + const props = createMockMemberActionsColumnProps(); + renderWithProviders(); + + const trigger = screen.getByRole('button', { name: 'member.actions.menu_label' }); + expect(trigger).toHaveAttribute('type', 'button'); + }); + }); + + describe('Dropdown Menu Interactions', () => { + it('should open dropdown menu when trigger button is clicked', async () => { + const user = userEvent.setup(); + const props = createMockMemberActionsColumnProps(); + renderWithProviders(); + + await user.click(screen.getByRole('button', { name: 'member.actions.menu_label' })); + + expect( + screen.getByRole('menuitem', { name: 'member.actions.view_details' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('menuitem', { name: 'member.actions.assign_role' }), + ).toBeInTheDocument(); + expect( + screen.getByRole('menuitem', { name: 'member.actions.remove_from_org' }), + ).toBeInTheDocument(); + }); + + it('should close dropdown menu when user presses Escape key', async () => { + const user = userEvent.setup(); + const props = createMockMemberActionsColumnProps(); + renderWithProviders(); + + await user.click(screen.getByRole('button', { name: 'member.actions.menu_label' })); + expect( + screen.getByRole('menuitem', { name: 'member.actions.assign_role' }), + ).toBeInTheDocument(); + + await user.keyboard('{Escape}'); + + await waitFor(() => { + expect( + screen.queryByRole('menuitem', { name: 'member.actions.assign_role' }), + ).not.toBeInTheDocument(); + }); + }); + }); + + describe('Actions', () => { + it('should link View Details to the member management details route', async () => { + const user = userEvent.setup(); + const member = createMockMember({ user_id: 'usr_abc' }); + const props = createMockMemberActionsColumnProps({ member }); + renderWithProviders(); + + await user.click(screen.getByRole('button', { name: 'member.actions.menu_label' })); + + const viewDetailsLink = screen.getByRole('link', { name: 'member.actions.view_details' }); + expect(viewDetailsLink).toHaveAttribute('href', '/member-management/usr_abc'); + }); + + it('should call onAssignRole when Assign Role is clicked', async () => { + const user = userEvent.setup(); + const onAssignRole = vi.fn(); + const member = createMockMember(); + const props = createMockMemberActionsColumnProps({ member, onAssignRole }); + renderWithProviders(); + + await user.click(screen.getByRole('button', { name: 'member.actions.menu_label' })); + await user.click(screen.getByRole('menuitem', { name: 'member.actions.assign_role' })); + + expect(onAssignRole).toHaveBeenCalledTimes(1); + expect(onAssignRole).toHaveBeenCalledWith(member); + }); + + it('should call onRemoveFromOrg when Remove from Org is clicked', async () => { + const user = userEvent.setup(); + const onRemoveFromOrg = vi.fn(); + const member = createMockMember(); + const props = createMockMemberActionsColumnProps({ member, onRemoveFromOrg }); + renderWithProviders(); + + await user.click(screen.getByRole('button', { name: 'member.actions.menu_label' })); + await user.click(screen.getByRole('menuitem', { name: 'member.actions.remove_from_org' })); + + expect(onRemoveFromOrg).toHaveBeenCalledTimes(1); + expect(onRemoveFromOrg).toHaveBeenCalledWith(member); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table.test.tsx new file mode 100644 index 000000000..1dc6e3303 --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/__tests__/organization-member-table.test.tsx @@ -0,0 +1,116 @@ +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { OrganizationMemberTable } from '@/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table'; +import { renderWithProviders } from '@/tests/utils'; +import { + createMockMember, + createMockMemberTableProps, +} from '@/tests/utils/__mocks__/my-organization/member-management/member.mocks'; + +describe('OrganizationMemberTable', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe('Rendering', () => { + it('should render member details, roles, and relative last login text', () => { + vi.spyOn(Date, 'now').mockReturnValue(new Date('2026-05-15T12:00:00.000Z').getTime()); + + const props = createMockMemberTableProps({ + members: [ + createMockMember({ + user_id: 'usr_1', + given_name: 'Ada', + family_name: 'Lovelace', + email: 'ada@example.com', + last_login: '2026-05-13T12:00:00.000Z', + roles: [ + { id: 'role_admin', name: 'Admin' }, + { id: 'role_member', name: 'Member' }, + { id: 'role_viewer', name: 'Viewer' }, + ], + }), + ], + }); + + renderWithProviders(); + + expect(screen.getByText('Ada Lovelace')).toBeInTheDocument(); + expect(screen.getByText('ada@example.com')).toBeInTheDocument(); + expect(screen.getByText('AL')).toBeInTheDocument(); + expect(screen.getByText('Admin, Member, +1')).toBeInTheDocument(); + expect(screen.getByText('2 days ago')).toBeInTheDocument(); + }); + + it('should render fallback values when member roles and last login are missing', () => { + const props = createMockMemberTableProps({ + members: [ + createMockMember({ + user_id: 'usr_2', + given_name: undefined, + family_name: undefined, + name: '', + email: undefined, + last_login: undefined, + roles: [], + }), + ], + }); + + renderWithProviders(); + + expect(screen.getAllByText('-').length).toBeGreaterThan(0); + }); + + it('should render the empty state when there are no members', () => { + const props = createMockMemberTableProps({ + members: [], + pagination: { + pageSize: 10, + currentPage: 1, + totalItems: 0, + hasNextPage: false, + hasPreviousPage: false, + }, + }); + + renderWithProviders(); + + expect(screen.getByText('member.table.empty_message')).toBeInTheDocument(); + expect(screen.queryByLabelText('Go to next page')).not.toBeInTheDocument(); + }); + }); + + describe('Pagination', () => { + it('should call onNextPage and onPreviousPage when pagination controls are clicked', async () => { + const user = userEvent.setup(); + const onNextPage = vi.fn(); + const onPreviousPage = vi.fn(); + const props = createMockMemberTableProps({ + onNextPage, + onPreviousPage, + pagination: { + pageSize: 10, + currentPage: 2, + totalItems: 25, + hasNextPage: true, + hasPreviousPage: true, + }, + }); + + renderWithProviders(); + + await user.click(screen.getByLabelText('Go to next page')); + await user.click(screen.getByLabelText('Go to previous page')); + + expect(onNextPage).toHaveBeenCalledTimes(1); + expect(onPreviousPage).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table-actions-column.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table-actions-column.tsx new file mode 100644 index 000000000..f75f8eb0c --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table-actions-column.tsx @@ -0,0 +1,84 @@ +/** + * Organization member table row actions dropdown. + * @module organization-member-table-actions-column + * @internal + */ + +import { MoreHorizontal, Eye, UserRoundCheck, Trash2 } from 'lucide-react'; +import * as React from 'react'; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + DropdownMenuPortal, +} from '@/components/ui/dropdown-menu'; +import { Link } from '@/components/ui/link'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import type { OrganizationMemberTableActionsColumnProps } from '@/types/my-organization/member-management/organization-member-table-types'; + +/** + * OrganizationMemberTableActionsColumn Component + * Handles the actions column for Member table with dropdown menu. + * @param props - Component props. + * @param props.member - The member to show actions for. + * @param props.customMessages - Custom translation messages to override defaults. + * @param props.readOnly - Whether the component is in read-only mode. + * @param props.onAssignRole - Callback fired when assign role action is triggered. + * @param props.onRemoveFromOrg - Callback fired when remove from organization action is triggered. + * @returns JSX element. + */ +export function OrganizationMemberTableActionsColumn({ + member, + onAssignRole, + onRemoveFromOrg, +}: OrganizationMemberTableActionsColumnProps): React.JSX.Element { + const { t } = useTranslator('member_management'); + + const handleAssignRole = React.useCallback(() => { + onAssignRole?.(member); + }, [member, onAssignRole]); + + const handleRemoveFromOrg = React.useCallback(() => { + onRemoveFromOrg?.(member); + }, [member, onRemoveFromOrg]); + + return ( +
    + + + + {t('member.actions.menu_label')} + + + + {/* View Details */} + + + + {t('member.actions.view_details')} + + + {/* Assign Role */} + + + {t('member.actions.assign_role')} + + {/* Remove from Org */} + + + {t('member.actions.remove_from_org')} + + + + +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table.tsx new file mode 100644 index 000000000..84822039b --- /dev/null +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/members/members-table/organization-member-table.tsx @@ -0,0 +1,182 @@ +/** + * Organization member table component. + * @module organization-member-table + * @internal + */ + +import type { OrgMember } from '@auth0/universal-components-core'; +import * as React from 'react'; + +import { OrganizationMemberTableActionsColumn } from './organization-member-table-actions-column'; + +import { SearchFilter } from '@/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter'; +import { DataPagination } from '@/components/auth0/shared/data-pagination'; +import { DataTable, type Column } from '@/components/auth0/shared/data-table'; +import { useTranslator } from '@/hooks/shared/use-translator'; +import { cn } from '@/lib/utils'; +import { + getMemberDisplayName, + getRelativeLastLoginLabel, + MemberAvatar, +} from '@/lib/utils/my-organization/member-management/member-management-utils'; +import type { OrganizationMemberTableProps } from '@/types/my-organization/member-management/organization-member-table-types'; + +/** + * Organization member table component. + * Displays members with search, filtering, and pagination. + * @param props - The component props. + * @param props.members - The list of members to display. + * @param props.loading - Whether the table is loading. + * @param props.pagination - Pagination state. + * @param props.filters - Current filter state. + * @param props.availableRoles - Available roles for filtering. + * @param props.onView - Callback when viewing member details. + * @param props.onAssignRole - Callback when assigning a role to a member. + * @param props.onRemoveFromOrg - Callback when removing a member from the organization. + * @param props.onNextPage - Callback when navigating to the next page. + * @param props.onPreviousPage - Callback when navigating to the previous page. + * @param props.onPageSizeChange - Callback when page size changes. + * @param props.onRoleFilterChange - Callback when role filter changes. + * @param props.onSearchTermChange - Callback when search term changes. + * @param props.className - Optional CSS class name. + * @returns The member table component. + */ +export function OrganizationMemberTable({ + members, + loading = false, + pagination, + filters, + customMessages = {}, + availableRoles, + sortConfig, + className, + onSortChange, + onView, + onAssignRole, + onRemoveFromOrg, + onNextPage, + onPreviousPage, + onPageSizeChange, + onRoleFilterChange, + onSearchTermChange, +}: OrganizationMemberTableProps): React.JSX.Element { + const { t } = useTranslator('member_management', customMessages); + + const renderName = React.useCallback( + (member: OrgMember) => ( +
    + +
    +
    {getMemberDisplayName(member)}
    +
    {member.email ?? '-'}
    +
    +
    + ), + [], + ); + + const renderRoles = React.useCallback((member: OrgMember) => { + const roleNames = member.roles?.map((role) => role.name) ?? []; + + if (roleNames.length === 0) { + return -; + } + + const visibleRoles = roleNames.slice(0, 2).join(', '); + const remainingCount = roleNames.length - 2; + + return ( + + {visibleRoles} + {remainingCount > 0 ? `, +${remainingCount}` : ''} + + ); + }, []); + + const renderLastLogin = React.useCallback((member: OrgMember) => { + return {getRelativeLastLoginLabel(member.last_login)}; + }, []); + + const columns: Column[] = React.useMemo( + () => [ + { + type: 'text', + accessorKey: 'name', + title: t('member.table.columns.name'), + enableSorting: false, + render: renderName, + }, + { + type: 'text', + accessorKey: 'roles', + title: t('member.table.columns.roles'), + enableSorting: false, + render: renderRoles, + }, + { + type: 'text', + accessorKey: 'last_login', + title: t('member.table.columns.last_login'), + enableSorting: false, + render: renderLastLogin, + }, + { + type: 'actions', + title: '', + render: (member) => ( + + ), + }, + ], + [t, onView, onAssignRole, onRemoveFromOrg, renderName, renderRoles, renderLastLogin], + ); + + return ( +
    + {false && ( + + )} + + + + {members.length > 0 && ( +
    + +
    + )} +
    + ); +} diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx index 7b83b6a4d..2e01ec90c 100644 --- a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/__tests__/search-filter.test.tsx @@ -33,6 +33,72 @@ describe('SearchFilter', () => { screen.getByRole('button', { name: 'invitation.table.reset_filter' }), ).toBeInTheDocument(); }); + + it('should render member search input on the members tab', () => { + renderWithProviders( + , + ); + + expect( + screen.getByPlaceholderText('Search for a member by name or email'), + ).toBeInTheDocument(); + }); + + it('should not render member search input on the invitations tab', () => { + renderWithProviders( + , + ); + + expect( + screen.queryByPlaceholderText('Search for a member by name or email'), + ).not.toBeInTheDocument(); + }); + }); + + describe('search', () => { + it('should update the search input value as the user types', async () => { + const user = userEvent.setup(); + + renderWithProviders( + , + ); + + const searchInput = screen.getByPlaceholderText('Search for a member by name or email'); + await user.type(searchInput, 'ada@example.com'); + + expect(searchInput).toHaveValue('ada@example.com'); + }); + + it('should call onSearchTermChange with the current search term on keydown', async () => { + const user = userEvent.setup(); + const onSearchTermChange = vi.fn(); + + renderWithProviders( + , + ); + + const searchInput = screen.getByPlaceholderText('Search for a member by name or email'); + await user.type(searchInput, 'ada'); + await user.keyboard('{Enter}'); + + expect(onSearchTermChange).toHaveBeenLastCalledWith('ada'); + }); + + it('should clear the search input when Escape is pressed', async () => { + const user = userEvent.setup(); + + renderWithProviders( + , + ); + + const searchInput = screen.getByPlaceholderText('Search for a member by name or email'); + await user.type(searchInput, 'ada'); + await user.keyboard('{Escape}'); + + expect(searchInput).toHaveValue(''); + }); }); describe('reset button', () => { @@ -97,7 +163,7 @@ describe('SearchFilter', () => { ); const filterDiv = container.firstChild as HTMLElement; - expect(filterDiv).toHaveClass('mb-4'); + expect(filterDiv).toHaveClass('mt-8', 'mb-6'); }); }); }); diff --git a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx index 62da9a66f..eb1bcdd49 100644 --- a/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx +++ b/packages/react/src/components/auth0/my-organization/shared/member-management/shared/search-filter/search-filter.tsx @@ -8,6 +8,7 @@ import { X } from 'lucide-react'; import * as React from 'react'; import { Button } from '@/components/ui/button'; +import { Search } from '@/components/ui/search'; import { Select, SelectContent, @@ -26,17 +27,22 @@ import type { SearchFilterProps } from '@/types/my-organization/member-managemen * @param props.availableRoles - Available roles for filtering. * @param props.customMessages - Custom translation messages. * @param props.className - Optional CSS class name. + * @param props.activeTab - The currently active tab (members or invitations). * @param props.onRoleFilterChange - Callback fired when role filter changes. - * @returns The filter bar component. + * @param props.onSearchTermChange - Callback fired when search term changes. + * @returns The search and filter component. */ export function SearchFilter({ filters, availableRoles = [], customMessages = {}, className, + activeTab, onRoleFilterChange, + onSearchTermChange, }: SearchFilterProps): React.JSX.Element | null { const { t } = useTranslator('member_management', customMessages); + const [searchTerm, setSearchTerm] = React.useState(''); const handleRoleFilterChange = React.useCallback( (value: string) => { @@ -45,6 +51,16 @@ export function SearchFilter({ [onRoleFilterChange], ); + const handleKeyDownSearch = React.useCallback( + (event: React.KeyboardEvent) => { + if (event.key === 'Escape') { + setSearchTerm(''); + } + onSearchTermChange?.(searchTerm); + }, + [searchTerm], + ); + const handleReset = React.useCallback(() => { onRoleFilterChange?.(undefined); }, [onRoleFilterChange]); @@ -56,10 +72,19 @@ export function SearchFilter({ } return ( -
    +
    + {activeTab === 'members' && ( + + )} +
    +

    + Follow{' '} + + Quickstart guidance + {' '} + on how to add Member Management component. +

    + {/* */} +
    +

    + Follow{' '} + + Quickstart guidance + {' '} + on how to add Member Management component. +

    + {/* */} +