mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
add loading state for org members and roles
This commit is contained in:
1 parent
c8bea30f69
commit
dc741f388d
2 files changed
+44
-38
No files matched your search
@@ -2,27 +2,21 @@ import Image from 'next/image'
|
||||
import * as Tooltip from '@radix-ui/react-tooltip'
|
||||
import { useState, Fragment } from 'react'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Loading,
|
||||
Listbox,
|
||||
IconUser,
|
||||
Modal,
|
||||
IconAlertCircle,
|
||||
IconHelpCircle,
|
||||
} from 'ui'
|
||||
import { Badge, Button, Loading, Listbox, IconUser, Modal, IconAlertCircle, IconLoader } from 'ui'
|
||||
|
||||
import { Member, Role } from 'types'
|
||||
import { Member } from 'types'
|
||||
import { useStore, useParams } from 'hooks'
|
||||
import { isInviteExpired, getUserDisplayName } from '../Organization.utils'
|
||||
|
||||
import { useProfileQuery } from 'data/profile/profile-query'
|
||||
import { useOrganizationMemberUpdateMutation } from 'data/organizations/organization-member-update-mutation'
|
||||
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
|
||||
import Table from 'components/to-be-cleaned/Table'
|
||||
import MemberActions from './MemberActions'
|
||||
import RolesHelperModal from './RolesHelperModal/RolesHelperModal'
|
||||
import { getRolesManagementPermissions } from './TeamSettings.utils'
|
||||
import { isInviteExpired, getUserDisplayName } from '../Organization.utils'
|
||||
import { useProfileQuery } from 'data/profile/profile-query'
|
||||
import { useOrganizationRolesQuery } from 'data/organizations/organization-roles-query'
|
||||
import { useOrganizationDetailQuery } from 'data/organizations/organization-detail-query'
|
||||
import { useOrganizationMemberUpdateMutation } from 'data/organizations/organization-member-update-mutation'
|
||||
|
||||
interface SelectedMember extends Member {
|
||||
oldRoleId: number
|
||||
@@ -30,24 +24,38 @@ interface SelectedMember extends Member {
|
||||
}
|
||||
|
||||
export interface MembersViewProps {
|
||||
roles: Role[]
|
||||
members: Member[]
|
||||
searchString: string
|
||||
}
|
||||
|
||||
const MembersView = ({ searchString, roles, members }: MembersViewProps) => {
|
||||
const MembersView = ({ searchString }: MembersViewProps) => {
|
||||
const { ui } = useStore()
|
||||
const { slug } = useParams()
|
||||
|
||||
const { data: profile } = useProfileQuery()
|
||||
const { data: detailData, isLoading: isLoadingOrgDetails } = useOrganizationDetailQuery({ slug })
|
||||
const { data: rolesData, isLoading: isLoadingRoles } = useOrganizationRolesQuery({ slug })
|
||||
const { mutate: updateOrganizationMember, isLoading } = useOrganizationMemberUpdateMutation({
|
||||
onSuccess() {
|
||||
ui.setNotification({
|
||||
category: 'success',
|
||||
message: `Successfully updated role for ${getUserDisplayName(selectedMember)}`,
|
||||
})
|
||||
},
|
||||
onError() {
|
||||
ui.setNotification({
|
||||
category: 'error',
|
||||
message: `Failed to update role for ${getUserDisplayName(selectedMember)}`,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const roles = rolesData?.roles ?? []
|
||||
const members = detailData?.members ?? []
|
||||
const { rolesAddable, rolesRemovable } = getRolesManagementPermissions(roles)
|
||||
|
||||
const [selectedMember, setSelectedMember] = useState<SelectedMember>()
|
||||
const [userRoleChangeModalVisible, setUserRoleChangeModalVisible] = useState(false)
|
||||
|
||||
if (!members) return <div />
|
||||
|
||||
const filteredMembers = (
|
||||
!searchString
|
||||
? members
|
||||
@@ -68,21 +76,6 @@ const MembersView = ({ searchString, roles, members }: MembersViewProps) => {
|
||||
return roles.find((x: any) => x.id === id)?.name
|
||||
}
|
||||
|
||||
const { isLoading, mutate } = useOrganizationMemberUpdateMutation({
|
||||
onSuccess() {
|
||||
ui.setNotification({
|
||||
category: 'success',
|
||||
message: `Successfully updated role for ${getUserDisplayName(selectedMember)}`,
|
||||
})
|
||||
},
|
||||
onError() {
|
||||
ui.setNotification({
|
||||
category: 'error',
|
||||
message: `Failed to update role for ${getUserDisplayName(selectedMember)}`,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const handleRoleChange = async () => {
|
||||
if (!selectedMember) return
|
||||
|
||||
@@ -95,11 +88,20 @@ const MembersView = ({ searchString, roles, members }: MembersViewProps) => {
|
||||
throw new Error('gotrue_id is required')
|
||||
}
|
||||
|
||||
mutate({ slug, gotrueId: gotrue_id, roleId: newRoleId })
|
||||
|
||||
updateOrganizationMember({ slug, gotrueId: gotrue_id, roleId: newRoleId })
|
||||
setUserRoleChangeModalVisible(false)
|
||||
}
|
||||
|
||||
if (isLoadingOrgDetails) {
|
||||
return (
|
||||
<div className="py-4 space-y-2">
|
||||
<ShimmeringLoader />
|
||||
<ShimmeringLoader className="w-3/4" />
|
||||
<ShimmeringLoader className="w-1/2" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="rounded">
|
||||
@@ -185,7 +187,11 @@ const MembersView = ({ searchString, roles, members }: MembersViewProps) => {
|
||||
</Table.td>
|
||||
|
||||
<Table.td>
|
||||
{role !== undefined ? (
|
||||
{isLoadingRoles ? (
|
||||
<div className="w-[140px]">
|
||||
<IconLoader className="animate-spin" size={16} strokeWidth={1.5} />
|
||||
</div>
|
||||
) : role !== undefined ? (
|
||||
<Tooltip.Root delayDuration={0}>
|
||||
<Tooltip.Trigger className="w-[140px]">
|
||||
<Listbox
|
||||
|
||||
@@ -117,7 +117,7 @@ const TeamSettings = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="container my-4 max-w-4xl space-y-8">
|
||||
<MembersView searchString={searchString} roles={roles} members={members} />
|
||||
<MembersView searchString={searchString} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user