Skip to content

[Community][Admin] Member Management Page#198

Open
rohit-r-kumar wants to merge 3 commits intomainfrom
rohit-r-kumar/issue94
Open

[Community][Admin] Member Management Page#198
rohit-r-kumar wants to merge 3 commits intomainfrom
rohit-r-kumar/issue94

Conversation

@rohit-r-kumar
Copy link
Copy Markdown

@rohit-r-kumar rohit-r-kumar commented Apr 6, 2026

Fixes #94

Summary by Sourcery

Add end-to-end support for community member management, including querying, adding, removing, and updating member roles from the admin interface.

New Features:

  • Expose GraphQL query and mutations for listing community members and performing member add, remove, and role update operations with structured mutation results.
  • Introduce an admin UI members page with table, search, add-member modal, and removal actions wired to the new GraphQL operations.
  • Emit member added and removed domain events and support deleting members via the Member aggregate with appropriate permission checks.

Enhancements:

  • Extend member application services to support querying by community, creating members, deleting members, and updating member roles.
  • Add Storybook stories for the new member list and add-member modal components to document and exercise the new UI.

@rohit-r-kumar rohit-r-kumar requested a review from a team April 6, 2026 16:10
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 6, 2026

Reviewer's Guide

Implements a full member management feature for community admins across domain, application services, GraphQL schema/resolvers, and UI, including listing members by community, adding/removing members, updating roles, and enforcing authorization and domain permissions with test coverage and Storybook stories.

Sequence diagram for admin adding a member via Members page

sequenceDiagram
    actor Admin
    participant MembersPage as MembersPage
    participant MemberAddModal as MemberAddModalContainer
    participant Apollo as ApolloClient
    participant GQL as GraphQLServer
    participant MemberResolvers as memberResolvers
    participant AppService as MemberApplicationService
    participant DS as DataSources
    participant DomainMember as MemberAggregate

    Admin->>MembersPage: Open Members admin page
    MembersPage->>Apollo: query AdminMemberListContainerMembersByCommunityId(communityId)
    Apollo->>GQL: membersByCommunityId(communityId)
    GQL->>MemberResolvers: Query.membersByCommunityId(args, context)
    MemberResolvers->>AppService: Member.queryByCommunityId({ communityId })
    AppService->>DS: MemberReadRepo.getByCommunityId(communityId)
    DS-->>AppService: MemberEntityReference[]
    AppService-->>MemberResolvers: MemberEntityReference[]
    MemberResolvers-->>GQL: Member[]
    GQL-->>Apollo: Member[]
    Apollo-->>MembersPage: Member[]

    Admin->>MembersPage: Click Add Member
    MembersPage->>MemberAddModal: open = true

    Admin->>MemberAddModal: Submit memberAdd form values
    MemberAddModal->>Apollo: mutate AdminMemberAddContainerMemberAdd(input)
    Apollo->>GQL: memberAdd(input)
    GQL->>MemberResolvers: Mutation.memberAdd(args, context)
    MemberResolvers->>AppService: Member.addMember(MemberAddCommand)

    AppService->>DS: EndUserReadRepo.getByExternalId(userExternalId)
    DS-->>AppService: EndUser(user)
    AppService->>DS: EndUserReadRepo.getByExternalId(createdByExternalId)
    DS-->>AppService: EndUser(createdBy)
    AppService->>DS: CommunityReadRepo.getById(communityId)
    DS-->>AppService: Community

    AppService->>DS: MemberUnitOfWork.withScopedTransaction(callback)
    DS->>DomainMember: getNewInstance(memberName, community)
    DomainMember->>DomainMember: requestNewAccount()
    DomainMember->>DomainMember: set account fields (createdBy, firstName, lastName, statusCode, user)
    DomainMember->>DS: save(newMember)
    DS-->>AppService: MemberEntityReference

    AppService-->>MemberResolvers: MemberEntityReference
    MemberResolvers-->>GQL: MemberMutationResult{ status.success = true, member }
    GQL-->>Apollo: payload
    Apollo-->>MemberAddModal: payload

    MemberAddModal->>Apollo: refetch AdminMemberListContainerMembersByCommunityId
    Apollo->>GQL: membersByCommunityId(communityId)
    GQL-->>Apollo: Member[]
    Apollo-->>MembersPage: update list
    MemberAddModal-->>Admin: Show success message and close
Loading

Sequence diagram for admin removing a member and domain deletion

sequenceDiagram
    actor Admin
    participant MembersPage as MembersPage
    participant Apollo as ApolloClient
    participant GQL as GraphQLServer
    participant MemberResolvers as memberResolvers
    participant AppService as MemberApplicationService
    participant DS as DataSources
    participant DomainMember as MemberAggregate

    Admin->>MembersPage: Click Remove on member
    MembersPage->>Apollo: mutate AdminMemberListContainerMemberRemove({ memberId })
    Apollo->>GQL: memberRemove(input)
    GQL->>MemberResolvers: Mutation.memberRemove(args, context)
    MemberResolvers->>AppService: Member.removeMember(MemberRemoveCommand)

    AppService->>DS: MemberUnitOfWork.withScopedTransaction(callback)
    DS->>DomainMember: getById(memberId)
    DomainMember->>DomainMember: requestDelete()
    DomainMember->>DomainMember: check visa.canManageMembers or visa.isSystemAccount
    alt authorized
        DomainMember->>DomainMember: super.isDeleted = true
        DomainMember->>DomainMember: addIntegrationEvent(MemberRemovedEvent)
    else unauthorized
        DomainMember-->>AppService: throw PermissionError
    end

    DomainMember->>DS: save(member)
    DS-->>AppService: MemberEntityReference
    AppService-->>MemberResolvers: MemberEntityReference

    alt success
        MemberResolvers-->>GQL: MemberMutationResult{ status.success = true }
    else error
        MemberResolvers-->>GQL: MemberMutationResult{ status.success = false, errorMessage }
    end

    GQL-->>Apollo: payload
    Apollo-->>MembersPage: payload
    MembersPage->>Apollo: refetch AdminMemberListContainerMembersByCommunityId
    Apollo-->>MembersPage: updated members
    MembersPage-->>Admin: Show success or error message
Loading

Updated class diagram for Member aggregate, events, and member application services

classDiagram
    class MemberProps {
        <<interface>>
        string id
        string memberName
        string communityId
        Date createdAt
        Date updatedAt
    }

    class Passport {
        <<value object>>
        bool canManageMembers
        bool isSystemAccount
        bool determineIf(fn)
    }

    class Member {
        +Member(props MemberProps, visa Passport)
        +requestDelete() void
        +loadCommunity() Promise~CommunityEntityReference~
        +isDeleted bool
        +communityId string
        +role EndUserRoleEntityReference
    }

    class MemberRemovedEvent {
        +props MemberRemovedProps
    }

    class MemberRemovedProps {
        <<interface>>
        string memberId
        string communityId
    }

    class MemberAddedEvent {
        +props MemberAddedProps
    }

    class MemberAddedProps {
        <<interface>>
        string memberId
        string communityId
        string memberName
    }

    class MemberApplicationService {
        <<interface>>
        +determineIfAdmin(command MemberDetermineIfAdminCommand) Promise~bool~
        +queryByEndUserExternalId(command MemberQueryByEndUserExternalIdCommand) Promise~MemberEntityReference[]~
        +queryByCommunityId(command MemberQueryByCommunityIdCommand) Promise~MemberEntityReference[]~
        +addMember(command MemberAddCommand) Promise~MemberEntityReference~
        +removeMember(command MemberRemoveCommand) Promise~MemberEntityReference~
        +updateMemberRole(command MemberRoleUpdateCommand) Promise~MemberEntityReference~
    }

    class MemberAddCommand {
        <<interface>>
        string communityId
        string memberName
        string firstName
        string lastName
        string userExternalId
        string createdByExternalId
    }

    class MemberRemoveCommand {
        <<interface>>
        string memberId
    }

    class MemberRoleUpdateCommand {
        <<interface>>
        string memberId
        string roleId
    }

    class MemberQueryByCommunityIdCommand {
        <<interface>>
        string communityId
    }

    class MemberMutationResult {
        <<GraphQL type>>
        MutationStatus status
        Member member
    }

    class MutationStatus {
        bool success
        string errorMessage
    }

    class MemberMutationResolverHelper {
        +MemberMutationResolver(getMember Promise~MemberEntityReference~) Promise~MemberMutationResult~
    }

    MemberProps <|-- Member
    Passport --> Member : visa
    Member --> MemberRemovedEvent : emits
    Member --> MemberAddedEvent : emits

    MemberRemovedEvent --> MemberRemovedProps
    MemberAddedEvent --> MemberAddedProps

    MemberApplicationService --> MemberAddCommand
    MemberApplicationService --> MemberRemoveCommand
    MemberApplicationService --> MemberRoleUpdateCommand
    MemberApplicationService --> MemberQueryByCommunityIdCommand

    MemberMutationResult --> MutationStatus
    MemberMutationResult --> Member

    MemberMutationResolverHelper --> MemberMutationResult
    MemberMutationResolverHelper --> MemberApplicationService
Loading

File-Level Changes

Change Details Files
Expose members-by-community and member admin mutations in GraphQL with consistent result handling and auth checks.
  • Add membersByCommunityId query to GraphQL schema and resolvers requiring a verified JWT.
  • Introduce MemberMutationResult GraphQL type and shared MemberMutationResolver helper to standardize success/error wrapping for memberAdd, memberRemove, and memberRoleUpdate.
  • Wire resolvers to application services for adding, removing, and updating member roles, including propagating createdByExternalId and handling unauthorized calls by returning failure statuses.
packages/ocom/graphql/src/schema/types/member.graphql
packages/ocom/graphql/src/schema/types/member.resolvers.ts
Extend member application service layer with commands for querying by community, adding members, removing members, and updating member roles.
  • Define MemberQueryByCommunityIdCommand, MemberAddCommand, MemberRemoveCommand, and MemberRoleUpdateCommand and associated functions using existing data sources and unit-of-work patterns.
  • Implement addMember to validate end user, admin, and community existence and create a new member and primary account with initial status.
  • Implement removeMember to load a member, call requestDelete, and persist; implement updateMemberRole to load role and member and set member.role.
  • Expose new operations from Member application service factory.
packages/ocom/application-services/src/contexts/community/member/index.ts
packages/ocom/application-services/src/contexts/community/member/query-by-community-id.ts
packages/ocom/application-services/src/contexts/community/member/add-member.ts
packages/ocom/application-services/src/contexts/community/member/remove-member.ts
packages/ocom/application-services/src/contexts/community/member/update-member-role.ts
Enhance the Member aggregate and domain events to support member deletion and emit integration events.
  • Add MemberAddedEvent and MemberRemovedEvent domain event types and export them from the events index.
  • Extend Member aggregate with requestDelete, enforcing canManageMembers or isSystemAccount via visa, marking the aggregate as deleted, and emitting MemberRemovedEvent.
  • Add domain and feature tests for requestDelete covering allowed and forbidden deletion paths.
packages/ocom/domain/src/domain/contexts/community/member/member.ts
packages/ocom/domain/src/domain/contexts/community/member/member.test.ts
packages/ocom/domain/src/domain/contexts/community/member/features/member.feature
packages/ocom/domain/src/domain/events/types/index.ts
packages/ocom/domain/src/domain/events/types/member-added.ts
packages/ocom/domain/src/domain/events/types/member-removed.ts
Add an Admin Members page in the community UI with list, search, add, and remove capabilities backed by the new GraphQL operations.
  • Introduce Members admin subpage route and page component rendering a MemberListContainer under the existing Admin layout.
  • Create MemberList presentational component showing members in a searchable table with status, role, joined date, and optional remove actions, plus Storybook stories for various states.
  • Add MemberListContainer that loads membersByCommunityId, handles remove mutations with notifications, and hosts MemberAddModalContainer.
  • Implement MemberAddModal (form modal) and container wiring it to memberAdd mutation, refetching list and surfacing success/failure via Ant Design message; add Storybook stories for the modal.
  • Define GraphQL queries/mutations/fragments for listing members and adding/removing members for the admin UI containers.
apps/ui-community/src/components/layouts/admin/index.tsx
apps/ui-community/src/components/layouts/admin/pages/members.tsx
apps/ui-community/src/components/layouts/admin/components/member-list.tsx
apps/ui-community/src/components/layouts/admin/components/member-list.stories.tsx
apps/ui-community/src/components/layouts/admin/components/member-list.container.tsx
apps/ui-community/src/components/layouts/admin/components/member-list.container.graphql
apps/ui-community/src/components/layouts/admin/components/member-add-modal.tsx
apps/ui-community/src/components/layouts/admin/components/member-add-modal.container.tsx
apps/ui-community/src/components/layouts/admin/components/member-add-modal.container.graphql
apps/ui-community/src/components/layouts/admin/components/member-add-modal.stories.tsx
Expand GraphQL member resolver and feature tests to cover new queries and mutations and their auth behavior.
  • Augment test GraphContext mocks to include new Community.Member methods (queryByCommunityId, addMember, removeMember, updateMemberRole).
  • Add BDD-style scenarios and expectations for membersByCommunityId (with and without auth), memberAdd/memberRemove/memberRoleUpdate success and failure paths, including unauthorized add behavior.
  • Mirror these scenarios in the .feature file for consistency with test implementation.
packages/ocom/graphql/src/schema/types/member.resolvers.test.ts
packages/ocom/graphql/src/schema/types/features/member.resolvers.feature

Assessment against linked issues

Issue Objective Addressed Explanation
#94 Extend the member domain and application layers to support full admin member management (including invitation value objects, MemberInvited/MemberActivated/MemberRemoved events, member search specs, and a MemberManagementService with invite/activate/deactivate/remove and bulk operations). The PR adds domain support for deleting members via Member.requestDelete and emits a MemberRemovedEvent, and adds MemberAddedEvent plus application services for addMember, removeMember, updateMemberRole and queryByCommunityId. However, it does not introduce MemberInvitation value objects, MemberInvited or MemberActivated events, member search specifications, or a dedicated MemberManagementService. Bulk operations (invite/activate/deactivate/remove) are also not implemented.
#94 Expose a complete GraphQL and admin UI member management page that allows admins to view, search/filter, invite, manage roles, remove members, handle invitations, and perform bulk actions, including the specified queries, mutations, and subscriptions. On the GraphQL side, the PR adds membersByCommunityId plus the memberAdd, memberRemove, and memberRoleUpdate mutations and wires them to application services. On the UI side, it introduces a Members admin route, a member list page with search/filter, status indicators, an Add Member modal, and remove actions. However, it does not implement inviteMember/bulkInviteMembers/getMembers/getMemberInvitations/memberUpdated subscription, nor any UI for invitations, member detail view, or bulk actions (select, bulk invite/remove). The implemented page covers listing/add/remove/role display but not the full set of required management and invitation features.
#94 Add comprehensive automated tests for member management, including unit tests for member operations, BDD features for the invitation workflow, integration tests for member queries/mutations, and E2E tests for member management flows. The PR extends existing tests: it adds BDD scenarios and unit tests for Member.requestDelete permission behavior, and BDD-style tests for new member GraphQL resolvers (membersByCommunityId, memberAdd, memberRemove, memberRoleUpdate) including auth failure cases. However, there are no tests around invitation workflows, no explicit integration tests beyond resolver tests, and no E2E tests for the member management flows. Thus the testing requirements are only partially covered.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 4 issues, and left some high level feedback:

  • The new member.resolvers.test.ts block appears to duplicate several existing scenarios (including two test.for(feature, ...) suites and repeated Querying members by community ID cases); consider consolidating into a single feature suite to avoid redundant tests and future drift.
  • In update-member-role.ts, roleRepo.getById and memberRepo.getById are assumed to succeed and any failure results in a generic Member not found error; it would be safer and clearer to explicitly handle missing roles/members and surface distinct, accurate error messages.
  • MemberAddModal accepts a communityId prop but never uses it, and all context-specific work is done in MemberAddModalContainer; you can remove this unused prop (and related plumbing) to keep the presentational component’s API minimal.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `member.resolvers.test.ts` block appears to duplicate several existing scenarios (including two `test.for(feature, ...)` suites and repeated `Querying members by community ID` cases); consider consolidating into a single feature suite to avoid redundant tests and future drift.
- In `update-member-role.ts`, `roleRepo.getById` and `memberRepo.getById` are assumed to succeed and any failure results in a generic `Member not found` error; it would be safer and clearer to explicitly handle missing roles/members and surface distinct, accurate error messages.
- `MemberAddModal` accepts a `communityId` prop but never uses it, and all context-specific work is done in `MemberAddModalContainer`; you can remove this unused prop (and related plumbing) to keep the presentational component’s API minimal.

## Individual Comments

### Comment 1
<location path="packages/ocom/application-services/src/contexts/community/member/update-member-role.ts" line_range="9-12" />
<code_context>
+	roleId: string;
+}
+
+export const updateMemberRole = (dataSources: DataSources) => {
+	return async (command: MemberRoleUpdateCommand): Promise<Domain.Contexts.Community.Member.MemberEntityReference> => {
+		let memberToReturn: Domain.Contexts.Community.Member.MemberEntityReference | undefined;
+		await dataSources.domainDataSource.Community.Role.EndUserRole.EndUserRoleUnitOfWork.withScopedTransaction(async (roleRepo) => {
+			const role = await roleRepo.getById(command.roleId);
+			await dataSources.domainDataSource.Community.Member.MemberUnitOfWork.withScopedTransaction(async (memberRepo) => {
</code_context>
<issue_to_address>
**issue (bug_risk):** Handle the case where the role cannot be found before assigning it to the member.

If `roleRepo.getById(command.roleId)` returns `undefined` or throws, you may assign an invalid role or surface an unhelpful error. Please explicitly handle the "role not found" case (e.g., throw a clear domain error) before opening the member unit of work so callers can distinguish it from other failures.
</issue_to_address>

### Comment 2
<location path="packages/ocom/application-services/src/contexts/community/member/remove-member.ts" line_range="11-14" />
<code_context>
+		}
+
+		let memberToReturn: Domain.Contexts.Community.Member.MemberEntityReference | undefined;
+		await dataSources.domainDataSource.Community.Member.MemberUnitOfWork.withScopedTransaction(async (repo) => {
+			const newMember = await repo.getNewInstance(command.memberName, community as Domain.Contexts.Community.Community.CommunityEntityReference);
+			const newAccount = newMember.requestNewAccount();
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Clarify and tighten handling of a missing member in the remove-member flow.

Within the unit of work, `repo.getById(command.memberId)` is used before checking for a missing member. If `getById` can return `null`/`undefined`, `member.requestDelete()` will throw before the explicit `Member not found` check runs. Please either guard immediately after `getById` and throw a clear error, or guarantee that `getById` throws and remove the final `if (!memberToReturn)` as unreachable/redundant code.
</issue_to_address>

### Comment 3
<location path="apps/ui-community/src/components/layouts/admin/components/member-list.container.graphql" line_range="1" />
<code_context>
+query AdminMemberListContainerMembersByCommunityId($communityId: ObjectID!) {
+	membersByCommunityId(communityId: $communityId) {
+		...AdminMemberListContainerMemberFields
</code_context>
<issue_to_address>
**issue (review_instructions):** This container GraphQL file is under `apps/ui-community/...`, which doesn’t match the specified `ui-<PortalName>/src/...` path pattern.

Per the instructions, container GraphQL files should live under a path like `ui-<PortalName>/src/components/layouts/<AreaName>/components/<componentName>.container.graphql`.

This file is currently located at `apps/ui-community/src/components/layouts/admin/components/member-list.container.graphql`, which introduces an extra `apps/` segment and doesn’t strictly match the required pattern.

If the convention is still accurate, this file should be moved/renamed so its path matches the `ui-<PortalName>/src/...` pattern (for example, `ui-community/src/components/layouts/admin/components/member-list.container.graphql`).

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.container.graphql`

**Instructions:**
container graphql files should be found in the following path pattern: ui-<PortalName>/src/components/layouts/<AreaName>/components/<componentName>.container.graphql

</details>
</issue_to_address>

### Comment 4
<location path="apps/ui-community/src/components/layouts/admin/components/member-add-modal.container.graphql" line_range="1" />
<code_context>
+mutation AdminMemberAddContainerMemberAdd($input: MemberAddInput!) {
+	memberAdd(input: $input) {
+		status {
</code_context>
<issue_to_address>
**issue (review_instructions):** This container GraphQL file’s path includes an `apps/` prefix, so it doesn’t strictly follow the specified `ui-<PortalName>/src/...` path pattern.

The convention states that container GraphQL files should be at:

`ui-<PortalName>/src/components/layouts/<AreaName>/components/<componentName>.container.graphql`.

This file is at `apps/ui-community/src/components/layouts/admin/components/member-add-modal.container.graphql`, which doesn’t strictly adhere to that pattern because of the `apps/` prefix. If the documented convention is still current, consider relocating/renaming so the path conforms to the expected structure.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.container.graphql`

**Instructions:**
container graphql files should be found in the following path pattern: ui-<PortalName>/src/components/layouts/<AreaName>/components/<componentName>.container.graphql

</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +9 to +12
export const updateMemberRole = (dataSources: DataSources) => {
return async (command: MemberRoleUpdateCommand): Promise<Domain.Contexts.Community.Member.MemberEntityReference> => {
let memberToReturn: Domain.Contexts.Community.Member.MemberEntityReference | undefined;
await dataSources.domainDataSource.Community.Role.EndUserRole.EndUserRoleUnitOfWork.withScopedTransaction(async (roleRepo) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): Handle the case where the role cannot be found before assigning it to the member.

If roleRepo.getById(command.roleId) returns undefined or throws, you may assign an invalid role or surface an unhelpful error. Please explicitly handle the "role not found" case (e.g., throw a clear domain error) before opening the member unit of work so callers can distinguish it from other failures.

Comment on lines +11 to +14
await dataSources.domainDataSource.Community.Member.MemberUnitOfWork.withScopedTransaction(async (repo) => {
const member = await repo.getById(command.memberId);
member.requestDelete();
memberToReturn = await repo.save(member);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): Clarify and tighten handling of a missing member in the remove-member flow.

Within the unit of work, repo.getById(command.memberId) is used before checking for a missing member. If getById can return null/undefined, member.requestDelete() will throw before the explicit Member not found check runs. Please either guard immediately after getById and throw a clear error, or guarantee that getById throws and remove the final if (!memberToReturn) as unreachable/redundant code.

@@ -0,0 +1,37 @@
query AdminMemberListContainerMembersByCommunityId($communityId: ObjectID!) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

issue (review_instructions): This container GraphQL file is under apps/ui-community/..., which doesn’t match the specified ui-<PortalName>/src/... path pattern.

Per the instructions, container GraphQL files should live under a path like ui-<PortalName>/src/components/layouts/<AreaName>/components/<componentName>.container.graphql.

This file is currently located at apps/ui-community/src/components/layouts/admin/components/member-list.container.graphql, which introduces an extra apps/ segment and doesn’t strictly match the required pattern.

If the convention is still accurate, this file should be moved/renamed so its path matches the ui-<PortalName>/src/... pattern (for example, ui-community/src/components/layouts/admin/components/member-list.container.graphql).

Review instructions:

Path patterns: **/*.container.graphql

Instructions:
container graphql files should be found in the following path pattern: ui-/src/components/layouts//components/.container.graphql

@@ -0,0 +1,23 @@
mutation AdminMemberAddContainerMemberAdd($input: MemberAddInput!) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

issue (review_instructions): This container GraphQL file’s path includes an apps/ prefix, so it doesn’t strictly follow the specified ui-<PortalName>/src/... path pattern.

The convention states that container GraphQL files should be at:

ui-<PortalName>/src/components/layouts/<AreaName>/components/<componentName>.container.graphql.

This file is at apps/ui-community/src/components/layouts/admin/components/member-add-modal.container.graphql, which doesn’t strictly adhere to that pattern because of the apps/ prefix. If the documented convention is still current, consider relocating/renaming so the path conforms to the expected structure.

Review instructions:

Path patterns: **/*.container.graphql

Instructions:
container graphql files should be found in the following path pattern: ui-/src/components/layouts//components/.container.graphql

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Community][Admin] Member Management Page

1 participant