Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { graphql } from 'react-relay'

export const UserItemFragment = graphql`
fragment UserItemFragment on User {
id
email
isActive
fullName
}
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { graphql } from 'react-relay'

export const UsersListFragment = graphql`
fragment UsersListFragment on Query
@refetchable(queryName: "usersListPaginationRefetchable")
@argumentDefinitions(
count: { type: "Int", defaultValue: 10 }
cursor: { type: "String" }
orderBy: { type: "String" }
q: { type: "String" }
) {
users(q: $q, first: $count, after: $cursor, orderBy: $orderBy)
@connection(key: "UsersList_users") {
totalCount
edges {
cursor
node {
id
...UserItemFragment @relay(mask: false)
profile {
id
...ProfileItemFragment
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useNotification } from '@baseapp-frontend/utils'

import { UseMutationConfig, graphql, useMutation } from 'react-relay'

import { ProfileUserRoleCreateMutation } from '../../../../../__generated__/ProfileUserRoleCreateMutation.graphql'

export const ProfileUserRoleCreateMutationQuery = graphql`
mutation ProfileUserRoleCreateMutation($input: ProfileUserRoleCreateInput!) {
profileUserRoleCreate(input: $input) {
profileUserRoles {
id
role
}
}
}
`

export const useProfileUserRoleCreateMutation = (): [
(config: UseMutationConfig<ProfileUserRoleCreateMutation>) => void,
boolean,
] => {
const [commitMutation, isMutationInFlight] = useMutation<ProfileUserRoleCreateMutation>(
ProfileUserRoleCreateMutationQuery,
)

const { sendToast } = useNotification()
const commit = (config: UseMutationConfig<ProfileUserRoleCreateMutation>) => {
commitMutation({
...config,
onCompleted: (response, errors) => {
errors?.forEach((error) => {
sendToast(error.message, { type: 'error' })
})
config?.onCompleted?.(response, errors)
},
onError: (error) => {
if (error.message.includes('duplicate key value violates unique constraint')) {
sendToast('You have already invited this user to this profile.', { type: 'error' })
} else {
sendToast(error.message, { type: 'error' })
}
config?.onError?.(error)
},
})
}

return [commit, isMutationInFlight]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ import { useNotification } from '@baseapp-frontend/utils'

import { Disposable, UseMutationConfig, graphql, useMutation } from 'react-relay'

import { RemoveMemberMutation } from '../../../../../__generated__/RemoveMemberMutation.graphql'
import { ProfileUserRoleDeleteMutation } from '../../../../../__generated__/ProfileUserRoleDeleteMutation.graphql'

export const ProfileRemoveMemberMutationQuery = graphql`
mutation RemoveMemberMutation($input: ProfileRemoveMemberInput!) {
profileRemoveMember(input: $input) {
export const ProfileUserRoleDeleteMutationQuery = graphql`
mutation ProfileUserRoleDeleteMutation($input: ProfileUserRoleDeleteInput!) {
profileUserRoleDelete(input: $input) {
deletedId @deleteRecord
}
}
`

export const useRemoveMemberMutation = (): [
(config: UseMutationConfig<RemoveMemberMutation>) => Disposable,
(config: UseMutationConfig<ProfileUserRoleDeleteMutation>) => Disposable,
boolean,
] => {
const { sendToast } = useNotification()
const [commitMutation, isMutationInFlight] = useMutation<RemoveMemberMutation>(
ProfileRemoveMemberMutationQuery,
const [commitMutation, isMutationInFlight] = useMutation<ProfileUserRoleDeleteMutation>(
ProfileUserRoleDeleteMutationQuery,
)

const commit = (config: UseMutationConfig<RemoveMemberMutation>) =>
const commit = (config: UseMutationConfig<ProfileUserRoleDeleteMutation>) =>
commitMutation({
...config,
onCompleted: (response, errors) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { useNotification } from '@baseapp-frontend/utils'

import { Disposable, UseMutationConfig, graphql, useMutation } from 'react-relay'

import { ChangeUserRoleMutation } from '../../../../../__generated__/ChangeUserRoleMutation.graphql'
import { ProfileUserRoleUpdateMutation } from '../../../../../__generated__/ProfileUserRoleUpdateMutation.graphql'

export const ChangeUserRoleMutationQuery = graphql`
mutation ChangeUserRoleMutation($input: RoleUpdateInput!) {
profileRoleUpdate(input: $input) {
export const ProfileUserRoleUpdateMutationQuery = graphql`
mutation ProfileUserRoleUpdateMutation($input: ProfileUserRoleUpdateInput!) {
profileUserRoleUpdate(input: $input) {
profileUserRole {
id
role
Expand All @@ -19,16 +19,16 @@ export const ChangeUserRoleMutationQuery = graphql`
}
`

export const useChangeUserRoleMutation = (): [
(config: UseMutationConfig<ChangeUserRoleMutation>) => Disposable,
export const useProfileUserRoleUpdateMutation = (): [
(config: UseMutationConfig<ProfileUserRoleUpdateMutation>) => Disposable,
boolean,
] => {
const { sendToast } = useNotification()
const [commitMutation, isMutationInFlight] = useMutation<ChangeUserRoleMutation>(
ChangeUserRoleMutationQuery,
const [commitMutation, isMutationInFlight] = useMutation<ProfileUserRoleUpdateMutation>(
ProfileUserRoleUpdateMutationQuery,
)

const commit = (config: UseMutationConfig<ChangeUserRoleMutation>) =>
const commit = (config: UseMutationConfig<ProfileUserRoleUpdateMutation>) =>
commitMutation({
...config,
onCompleted: (response, errors) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { graphql } from 'react-relay'

export const UsersListPaginationQuery = graphql`
query UsersListPaginationQuery($count: Int = 10, $cursor: String, $orderBy: String, $q: String) {
...UsersListFragment @arguments(count: $count, cursor: $cursor, orderBy: $orderBy, q: $q)
}
`
9 changes: 8 additions & 1 deletion packages/components/modules/profiles/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,25 @@ export * from './graphql/fragments/MemberItem'
export * from './graphql/fragments/ProfileComponent'
export * from './graphql/fragments/ProfileItem'
export * from './graphql/fragments/ProfilesList'
export * from './graphql/fragments/UserItem'
export * from './graphql/fragments/UserMembersList'
export * from './graphql/fragments/UsersList'

export * from './graphql/mutations/BlockToggle'
export * from './graphql/mutations/ChangeUserRole'
export * from './graphql/mutations/FollowToggle'
export * from './graphql/mutations/OrganizationCreate'
export * from './graphql/mutations/ProfileUpdate'
export * from './graphql/mutations/ProfileUserRoleUpdate'
export * from './graphql/mutations/ProfileUserRoleCreate'
export * from './graphql/mutations/ProfileUserRoleDelete'
export * from './graphql/mutations/ReportCreate'

export * from './graphql/queries/AddProfilePopover'
export * from './graphql/queries/ProfileSettingsRelayTest'
export * from './graphql/queries/ProfilesList'
export * from './graphql/queries/UserMembersList'
export * from './graphql/queries/UserProfile'
export * from './graphql/queries/UsersList'

export * from './constants'
export type * from './types'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { FC, useState } from 'react'

import { useCurrentProfile } from '@baseapp-frontend/authentication'
import { AvatarWithPlaceholder } from '@baseapp-frontend/design-system/components/web/avatars'
import { ConfirmDialog } from '@baseapp-frontend/design-system/components/web/dialogs'

import { Box, Button, MenuItem, SelectChangeEvent, Typography, useTheme } from '@mui/material'
import { useFragment } from 'react-relay'

import { ProfileRoles } from '../../../../../__generated__/ChangeUserRoleMutation.graphql'
import { ProfileItemFragment$key } from '../../../../../__generated__/ProfileItemFragment.graphql'
import { ProfileItemFragment, useChangeUserRoleMutation } from '../../../common'
import { useRemoveMemberMutation } from '../../../common/graphql/mutations/RemoveMember'
import { ProfileRoles } from '../../../../../__generated__/ProfileUserRoleUpdateMutation.graphql'
import { ProfileItemFragment, useProfileUserRoleUpdateMutation } from '../../../common'
import { useRemoveMemberMutation } from '../../../common/graphql/mutations/ProfileUserRoleDelete'
import MemberPersonalInfo from '../MemberPersonalInfo'
import { MEMBER_ACTIONS, MEMBER_ROLES, MEMBER_STATUSES, roleOptions } from '../constants'
import { capitalizeFirstLetter } from '../utils'
import { MemberItemContainer, MemberPersonalInformation, Select } from './styled'
import { MemberItemContainer, Select } from './styled'
import { MemberItemProps } from './types'

const MemberItem: FC<MemberItemProps> = ({
Expand All @@ -33,7 +33,7 @@ const MemberItem: FC<MemberItemProps> = ({

const { currentProfile } = useCurrentProfile()

const [changeUserRole, isChangingUserRole] = useChangeUserRoleMutation()
const [changeUserRole, isChangingUserRole] = useProfileUserRoleUpdateMutation()
const [removeMember, isRemovingMember] = useRemoveMemberMutation()
const [openConfirmChangeMember, setOpenConfirmChangeMember] = useState(false)
const [openConfirmRemoveMember, setOpenConfirmRemoveMember] = useState(false)
Expand Down Expand Up @@ -183,20 +183,13 @@ const MemberItem: FC<MemberItemProps> = ({
</Button>
}
/>
<MemberPersonalInformation isActive={status === MEMBER_STATUSES.active || false}>
<AvatarWithPlaceholder
width={avatarWidth}
height={avatarHeight}
src={memberProfile?.image?.url ?? ''}
alt="Profile avatar"
color="secondary"
{...avatarProps}
/>
<Box>
<Typography variant="subtitle2">{memberProfile.name}</Typography>
<Typography variant="caption">{memberProfile?.urlPath?.path}</Typography>
</Box>
</MemberPersonalInformation>
<MemberPersonalInfo
avatarProps={avatarProps}
avatarWidth={avatarWidth}
avatarHeight={avatarHeight}
member={member}
status={status}
/>
{renderRoleButton()}
</MemberItemContainer>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Box, Select as MUISelect, alpha, styled } from '@mui/material'

import { MemberPersonalInformationProps } from './types'

export const MemberItemContainer = styled(Box)(({ theme }) => ({
display: 'flex',
gap: theme.spacing(1.5),
Expand All @@ -10,16 +8,6 @@ export const MemberItemContainer = styled(Box)(({ theme }) => ({
padding: theme.spacing(1.5, 0),
}))

export const MemberPersonalInformation = styled(Box, {
shouldForwardProp: (prop) => prop !== 'isActive',
})<MemberPersonalInformationProps>(({ isActive, theme }) => ({
opacity: isActive ? 1 : 0.6,
display: 'flex',
gap: theme.spacing(1.5),
alignItems: 'center',
justifyContent: 'space-between',
}))

export const Select = styled(MUISelect)(({ theme }) => ({
backgroundColor: alpha(theme.palette.grey[500], 0.08),
borderRadius: 8,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface MemberPersonalInformationProps extends BoxProps {
}

export interface MemberItemProps {
member: ProfileItemFragment$key | null | undefined
member: ProfileItemFragment$key | undefined
memberRole: MemberItemFragment$data['role'] | 'owner'
status: MemberItemFragment$data['status']
avatarProps?: AvatarProps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const MemberListItem: FC<MemberListItemProps> = ({
{...memberItemComponentProps}
/>
<MemberItemComponent
member={memberFragment?.user?.profile}
member={memberFragment?.user?.profile || undefined}
memberRole={memberFragment?.role}
status={memberFragment?.status}
userId={memberFragment?.user?.id}
Expand All @@ -57,7 +57,7 @@ const MemberListItem: FC<MemberListItemProps> = ({
return (
<>
<MemberItemComponent
member={memberFragment?.user?.profile}
member={memberFragment?.user?.profile || undefined}
memberRole={memberFragment?.role}
status={memberFragment?.status}
userId={memberFragment?.user?.id}
Expand All @@ -78,7 +78,7 @@ const MemberListItem: FC<MemberListItemProps> = ({

return (
<MemberItemComponent
member={memberFragment?.user?.profile}
member={memberFragment?.user?.profile || undefined}
memberRole={memberFragment?.role}
status={memberFragment?.status}
userId={memberFragment?.user?.id}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { FC } from 'react'

import { AvatarWithPlaceholder } from '@baseapp-frontend/design-system/components/web/avatars'

import { Box, Typography } from '@mui/material'
import { useFragment } from 'react-relay'

import { ProfileItemFragment$key } from '../../../../../__generated__/ProfileItemFragment.graphql'
import { ProfileItemFragment } from '../../../common'
import { MEMBER_STATUSES } from '../constants'
import { MemberPersonalInformation } from '../styled'
import { MemberPersonalInfoProps } from '../types'

const MemberPersonalInfo: FC<MemberPersonalInfoProps> = ({
avatarProps = {},
avatarWidth = 40,
avatarHeight = 40,
member,
status,
children,
}) => {
const memberProfile = useFragment<ProfileItemFragment$key>(ProfileItemFragment, member)
return (
<MemberPersonalInformation isActive={status === MEMBER_STATUSES.active || false}>
<AvatarWithPlaceholder
width={avatarWidth}
height={avatarHeight}
src={memberProfile?.image?.url ?? ''}
alt="Profile avatar"
color="secondary"
{...avatarProps}
>
{memberProfile?.image?.url ? '' : memberProfile?.name?.slice(0, 2)?.toUpperCase()}
</AvatarWithPlaceholder>
<Box>
<Typography variant="subtitle2">{memberProfile?.name}</Typography>
<Typography variant="caption">{memberProfile?.urlPath?.path}</Typography>
</Box>
{children}
</MemberPersonalInformation>
)
}

export default MemberPersonalInfo
Loading
Loading