-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(console): Groups and group user management (#2461)
* feat(console): Groups and group user management * Added group details page * Updated group member model * Updated routing & context * Promisified * Added invitations in DO * Mermelated list & list item * Added group listing page * Added group page skeleton * Added pending invites * Added invite member modal * Added nice dropdown * Added migration * Replaced null with undefined for provider icons * Added false divving instead of comments * Removed explicit undefined cast * Added IdentityNode helper
- Loading branch information
1 parent
e3a24a7
commit 5bd9f8d
Showing
29 changed files
with
1,456 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace' | ||
import { AccountURN } from '@proofzero/urns/account' | ||
import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' | ||
import { LoaderFunction, json } from '@remix-run/cloudflare' | ||
import { parseJwt, requireJWT } from '~/utilities/session.server' | ||
import createAccountClient from '@proofzero/platform-clients/account' | ||
import createAddressClient from '@proofzero/platform-clients/address' | ||
import { getAuthzHeaderConditionallyFromToken } from '@proofzero/utils' | ||
import { PlatformAddressURNHeader } from '@proofzero/types/headers' | ||
import { NO_OP_ADDRESS_PLACEHOLDER } from '@proofzero/platform/address/src/constants' | ||
import { AddressURN } from '@proofzero/urns/address' | ||
import { Outlet, useLoaderData } from '@remix-run/react' | ||
|
||
type GroupMemberModel = { | ||
URN: AddressURN | ||
iconURL: string | ||
title: string | ||
address: string | ||
joinTimestamp: number | ||
} | ||
|
||
type GroupModel = { | ||
URN: string | ||
name: string | ||
members: GroupMemberModel[] | ||
} | ||
|
||
type GroupRootLoaderData = { | ||
groups: GroupModel[] | ||
} | ||
|
||
export type GroupRootContextData = GroupRootLoaderData | ||
|
||
export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( | ||
async ({ request, context }) => { | ||
const jwt = await requireJWT(request) | ||
const parsedJwt = parseJwt(jwt!) | ||
const accountURN = parsedJwt.sub as AccountURN | ||
|
||
const traceHeader = generateTraceContextHeaders(context.traceSpan) | ||
|
||
const accountClient = createAccountClient(Account, { | ||
...getAuthzHeaderConditionallyFromToken(jwt), | ||
...traceHeader, | ||
}) | ||
|
||
const addressClient = createAddressClient(Address, { | ||
[PlatformAddressURNHeader]: NO_OP_ADDRESS_PLACEHOLDER, | ||
...getAuthzHeaderConditionallyFromToken(jwt), | ||
...traceHeader, | ||
}) | ||
|
||
const groups = await accountClient.listIdentityGroups.query({ | ||
accountURN, | ||
}) | ||
|
||
const mappedGroups = await Promise.all( | ||
groups.map(async (group) => { | ||
const memberMap = group.members | ||
.filter((m) => m.joinTimestamp != null) | ||
.reduce( | ||
(acc, curr) => ({ ...acc, [curr.URN]: curr }), | ||
{} as Record<AddressURN, { URN: AddressURN; joinTimestamp: number }> | ||
) | ||
|
||
const memberProfiles = await addressClient.getAddressProfileBatch.query( | ||
group.members.map((m) => m.URN) | ||
) | ||
|
||
const memberModels: GroupMemberModel[] = memberProfiles.map( | ||
(profile) => ({ | ||
URN: profile.id, | ||
iconURL: profile.icon!, | ||
title: profile.title, | ||
address: profile.address, | ||
joinTimestamp: memberMap[profile.id].joinTimestamp, | ||
}) | ||
) | ||
|
||
return { | ||
URN: group.URN, | ||
name: group.name, | ||
members: memberModels, | ||
} | ||
}) | ||
) | ||
|
||
return json<GroupRootLoaderData>({ | ||
groups: mappedGroups, | ||
}) | ||
} | ||
) | ||
|
||
export default () => { | ||
const data = useLoaderData<GroupRootLoaderData>() | ||
|
||
return <Outlet context={data} /> | ||
} |
Oops, something went wrong.