mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
Fix type errors after successfully adding a new member via email to the org
This commit is contained in:
1 parent
1dabce94a1
commit
f418ff877c
3 files changed
+67
-45
No files matched your search
@@ -8,8 +8,7 @@ import { Modal } from '@supabase/ui'
|
||||
import { API_URL } from 'lib/constants'
|
||||
import { useOrganizationDetail, useStore } from 'hooks'
|
||||
import { toJS } from 'mobx'
|
||||
|
||||
|
||||
import { Member } from 'types'
|
||||
|
||||
/**
|
||||
* Endpoints (delete when finished)
|
||||
@@ -28,7 +27,6 @@ import { toJS } from 'mobx'
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Modal to invite member to Organization
|
||||
*
|
||||
@@ -40,16 +38,17 @@ import { toJS } from 'mobx'
|
||||
const PageContext = createContext(null)
|
||||
|
||||
function InviteMemberModal({ organization, members = [], user }: any) {
|
||||
|
||||
const PageState = useLocalObservable(() => ({
|
||||
members: [],
|
||||
members: [],
|
||||
addMemberLoading: false,
|
||||
emailAddress: '',
|
||||
emailIsValid() {
|
||||
return String(this.emailAddress)
|
||||
.toLowerCase()
|
||||
.match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
|
||||
}
|
||||
.match(
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
)
|
||||
},
|
||||
}))
|
||||
const { ui } = useStore()
|
||||
const { mutateOrgMembers } = useOrganizationDetail(ui.selectedOrganization?.slug || '')
|
||||
@@ -74,7 +73,7 @@ function InviteMemberModal({ organization, members = [], user }: any) {
|
||||
|
||||
const response = await post(`${API_URL}/organizations/${orgSlug}/members/invite`, {
|
||||
invited_email: PageState.emailAddress,
|
||||
owner_id: toJS(user.id)
|
||||
owner_id: toJS(user.id),
|
||||
})
|
||||
if (isNil(response)) {
|
||||
ui.setNotification({ category: 'error', message: 'Failed to add member' })
|
||||
@@ -85,14 +84,25 @@ function InviteMemberModal({ organization, members = [], user }: any) {
|
||||
})
|
||||
PageState.addMemberLoading = false
|
||||
} else {
|
||||
const newMember = response
|
||||
const newMember: Member = {
|
||||
// [Joshen] Setting a random id for now to fit the Member interface
|
||||
id: 0,
|
||||
invited_at: response.invited_at,
|
||||
is_owner: false,
|
||||
profile: {
|
||||
id: 0,
|
||||
primary_email: response.invited_email,
|
||||
username: response.invited_email[0],
|
||||
},
|
||||
}
|
||||
mutateOrgMembers([...PageState.members, newMember])
|
||||
|
||||
ui.setNotification({ category: 'success', message: 'Successfully added new member.' })
|
||||
toggle()
|
||||
}
|
||||
}
|
||||
|
||||
function onEmailInputChange(e) {
|
||||
function onEmailInputChange(e: any) {
|
||||
PageState.emailAddress = e.target.value
|
||||
}
|
||||
|
||||
@@ -110,7 +120,7 @@ function InviteMemberModal({ organization, members = [], user }: any) {
|
||||
layout="vertical"
|
||||
hideFooter
|
||||
>
|
||||
<div className="w-full py-4 space-y-4">
|
||||
<div className="w-full space-y-4 py-4">
|
||||
<Modal.Content>
|
||||
<div className="text-center">
|
||||
<Input
|
||||
@@ -121,7 +131,7 @@ function InviteMemberModal({ organization, members = [], user }: any) {
|
||||
onChange={onEmailInputChange}
|
||||
value={PageState.emailAddress}
|
||||
className="w-full"
|
||||
/>
|
||||
/>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
<Modal.Seperator />
|
||||
@@ -142,4 +152,4 @@ function InviteMemberModal({ organization, members = [], user }: any) {
|
||||
</PageContext.Provider>
|
||||
)
|
||||
}
|
||||
export default observer(InviteMemberModal)
|
||||
export default observer(InviteMemberModal)
|
||||
@@ -42,11 +42,11 @@ const PageContext = createContext(null)
|
||||
|
||||
// Invite is expired if older than 24hrs
|
||||
function inviteExpired(timestamp: Date) {
|
||||
const inviteDate = new Date(timestamp);
|
||||
const now = new Date();
|
||||
const inviteDate = new Date(timestamp)
|
||||
const now = new Date()
|
||||
var timeBetween = now.valueOf() - inviteDate.valueOf()
|
||||
if(timeBetween / 1000 / 60 / 60 < 24) {
|
||||
return true;
|
||||
if (timeBetween / 1000 / 60 / 60 < 24) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,11 @@ const OrgSettingsLayout = withAuth(
|
||||
get filteredMembers() {
|
||||
const temp = this.members.filter((x: any) => {
|
||||
let profile = x.profile
|
||||
if(profile) {
|
||||
if (profile) {
|
||||
return (
|
||||
profile.username.includes(this.membersFilterString) ||
|
||||
profile.primary_email.includes(this.membersFilterString)
|
||||
)
|
||||
)
|
||||
}
|
||||
if (x.invited_email) {
|
||||
return x.invited_email.includes(this.membersFilterString)
|
||||
@@ -237,7 +237,7 @@ const GeneralSettings = observer(() => {
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="container max-w-4xl my-4 space-y-8">
|
||||
<article className="container my-4 max-w-4xl space-y-8">
|
||||
<SchemaFormPanel
|
||||
title="General"
|
||||
schema={pluckJsonSchemaFields(organizations, BASIC_FIELDS)}
|
||||
@@ -321,8 +321,8 @@ const OrgDeleteModal = observer(() => {
|
||||
onCancel={toggle}
|
||||
header={
|
||||
<div className="flex items-baseline gap-2">
|
||||
<h5 className="text-sm text-scale-1200">Delete organisation</h5>
|
||||
<span className="text-xs text-scale-900">Are you sure?</span>
|
||||
<h5 className="text-scale-1200 text-sm">Delete organisation</h5>
|
||||
<span className="text-scale-900 text-xs">Are you sure?</span>
|
||||
</div>
|
||||
}
|
||||
size="small"
|
||||
@@ -361,9 +361,9 @@ const OrgDeleteModal = observer(() => {
|
||||
}}
|
||||
>
|
||||
{({ isSubmitting }: { isSubmitting: boolean }) => (
|
||||
<div className="py-3 space-y-4">
|
||||
<div className="space-y-4 py-3">
|
||||
<Modal.Content>
|
||||
<p className="text-sm text-scale-900">
|
||||
<p className="text-scale-900 text-sm">
|
||||
This action <span className="text-scale-1200">cannot</span> be undone. This will
|
||||
permanently delete the <span className="text-scale-1200">{orgName}</span>{' '}
|
||||
organization and remove all of its projects.
|
||||
@@ -436,7 +436,7 @@ const TeamSettings = observer(() => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container max-w-4xl my-4 space-y-8">
|
||||
<div className="container my-4 max-w-4xl space-y-8">
|
||||
<div className="flex justify-between">
|
||||
<MembersFilterInput />
|
||||
{PageState.isOrgOwner ? (
|
||||
@@ -456,7 +456,7 @@ const TeamSettings = observer(() => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="container max-w-4xl my-4 space-y-8">
|
||||
<div className="container my-4 max-w-4xl space-y-8">
|
||||
<MembersView />
|
||||
</div>
|
||||
</>
|
||||
@@ -502,24 +502,28 @@ const MembersView = observer(() => {
|
||||
<Table.td>
|
||||
<div className="flex items-center space-x-4">
|
||||
<div>
|
||||
{x.invited_id ?
|
||||
( <span className='flex p-2 border-2 rounded-full border-border-secondary-light dark:border-border-secondary-dark'><IconUser size={18} strokeWidth={2} /></span> )
|
||||
: ( <img
|
||||
src={`https://github.com/${x.profile?.username}.png?size=80`}
|
||||
width="40"
|
||||
className="border rounded-full border-border-secondary-light dark:border-border-secondary-dark"
|
||||
/>
|
||||
)}
|
||||
|
||||
{x.invited_id ? (
|
||||
<span className="border-border-secondary-light dark:border-border-secondary-dark flex rounded-full border-2 p-2">
|
||||
<IconUser size={18} strokeWidth={2} />
|
||||
</span>
|
||||
) : (
|
||||
<img
|
||||
src={`https://github.com/${x.profile?.username}.png?size=80`}
|
||||
width="40"
|
||||
className="border-border-secondary-light dark:border-border-secondary-dark rounded-full border"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
{x.profile?.username && !x.invited_id && (
|
||||
<>
|
||||
<Typography.Text>{x.profile?.username}</Typography.Text>
|
||||
<br />
|
||||
</>
|
||||
) }
|
||||
<Typography.Text type="secondary">{x.profile ? x.profile.primary_email : ''}</Typography.Text>
|
||||
{x.profile?.username && !x.invited_id && (
|
||||
<>
|
||||
<Typography.Text>{x.profile?.username}</Typography.Text>
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
<Typography.Text type="secondary">
|
||||
{x.profile ? x.profile.primary_email : ''}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
</Table.td>
|
||||
@@ -527,7 +531,7 @@ const MembersView = observer(() => {
|
||||
<Table.td>
|
||||
{x.invited_id && (
|
||||
<Badge color={inviteExpired(x.invited_at) ? 'yellow' : 'red'}>
|
||||
{inviteExpired(x.invited_at) ? 'Invited' : 'Expired'}
|
||||
{inviteExpired(x.invited_at) ? 'Invited' : 'Expired'}
|
||||
</Badge>
|
||||
)}
|
||||
</Table.td>
|
||||
@@ -635,7 +639,10 @@ const OwnerDropdown = observer(({ members, member }: any) => {
|
||||
async function handleResendInvite(id: number) {
|
||||
setLoading(true)
|
||||
|
||||
const response = await post(`${API_URL}/organizations/${orgSlug}/members/invite?invited_id=${id}`, {})
|
||||
const response = await post(
|
||||
`${API_URL}/organizations/${orgSlug}/members/invite?invited_id=${id}`,
|
||||
{}
|
||||
)
|
||||
|
||||
if (response.error) {
|
||||
ui.setNotification({
|
||||
@@ -653,7 +660,10 @@ const OwnerDropdown = observer(({ members, member }: any) => {
|
||||
async function handleRevokeInvitation(id: number) {
|
||||
setLoading(true)
|
||||
|
||||
const response = await delete_(`${API_URL}/organizations/${orgSlug}/members/invite?invited_id=${id}`, {})
|
||||
const response = await delete_(
|
||||
`${API_URL}/organizations/${orgSlug}/members/invite?invited_id=${id}`,
|
||||
{}
|
||||
)
|
||||
|
||||
if (response.error) {
|
||||
ui.setNotification({
|
||||
|
||||
@@ -55,6 +55,8 @@ export interface Member {
|
||||
primary_email: string
|
||||
username: string
|
||||
}
|
||||
invited_id?: number
|
||||
invited_at?: string
|
||||
}
|
||||
|
||||
export interface ResponseError {
|
||||
|
||||
Reference in new issue
Block a user