mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
feat(console): add quick join options in tenant selector dropdown (#5568)
* feat(console): implement interim landing page for new users to join invited tenants * feat(console): add quick join options in tenant selector dropdown
This commit is contained in:
parent
ba966fdefe
commit
afda22efa2
3 changed files with 83 additions and 0 deletions
|
@ -0,0 +1,26 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: _.unit(2.5) _.unit(4);
|
||||
margin: _.unit(1);
|
||||
border-radius: 6px;
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
justify-content: space-between;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-hover);
|
||||
}
|
||||
|
||||
.meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: _.unit(2);
|
||||
|
||||
.name {
|
||||
font: var(--font-body-2);
|
||||
@include _.text-ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import { OrganizationInvitationStatus, type TenantTag } from '@logto/schemas';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { useCloudApi } from '@/cloud/hooks/use-cloud-api';
|
||||
import TenantEnvTag from '@/components/TenantEnvTag';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
import Button from '@/ds-components/Button';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
data: {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
tenantName: string;
|
||||
tenantTag: TenantTag;
|
||||
};
|
||||
};
|
||||
|
||||
function TenantInvitationDropdownItem({ data }: Props) {
|
||||
const cloudApi = useCloudApi();
|
||||
const { navigateTenant, resetTenants } = useContext(TenantsContext);
|
||||
const { id, organizationId, tenantName, tenantTag } = data;
|
||||
|
||||
return (
|
||||
<div className={styles.item}>
|
||||
<div className={styles.meta}>
|
||||
<div className={styles.name}>{tenantName}</div>
|
||||
<TenantEnvTag tag={tenantTag} />
|
||||
</div>
|
||||
<Button
|
||||
size="small"
|
||||
type="outline"
|
||||
title="general.join"
|
||||
onClick={async () => {
|
||||
await cloudApi.patch(`/api/invitations/:invitationId/status`, {
|
||||
params: { invitationId: id },
|
||||
body: { status: OrganizationInvitationStatus.Accepted },
|
||||
});
|
||||
// TODO: @charles, need to fetch only the target tenant instance instead of all.
|
||||
const data = await cloudApi.get('/api/tenants');
|
||||
resetTenants(data);
|
||||
navigateTenant(organizationId.slice(2));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TenantInvitationDropdownItem;
|
|
@ -1,3 +1,4 @@
|
|||
import { OrganizationInvitationStatus } from '@logto/schemas';
|
||||
import { useContext, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
@ -11,9 +12,11 @@ import Divider from '@/ds-components/Divider';
|
|||
import Dropdown from '@/ds-components/Dropdown';
|
||||
import OverlayScrollbar from '@/ds-components/OverlayScrollbar';
|
||||
import useUserDefaultTenantId from '@/hooks/use-user-default-tenant-id';
|
||||
import useUserInvitations from '@/hooks/use-user-invitations';
|
||||
import { onKeyDownHandler } from '@/utils/a11y';
|
||||
|
||||
import TenantDropdownItem from './TenantDropdownItem';
|
||||
import TenantInvitationDropdownItem from './TenantInvitationDropdownItem';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
export default function TenantSelector() {
|
||||
|
@ -25,6 +28,7 @@ export default function TenantSelector() {
|
|||
currentTenantId,
|
||||
navigateTenant,
|
||||
} = useContext(TenantsContext);
|
||||
const { data: pendingInvitations } = useUserInvitations(OrganizationInvitationStatus.Pending);
|
||||
|
||||
const anchorRef = useRef<HTMLDivElement>(null);
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
|
@ -76,6 +80,9 @@ export default function TenantSelector() {
|
|||
}}
|
||||
/>
|
||||
))}
|
||||
{pendingInvitations?.map((invitation) => (
|
||||
<TenantInvitationDropdownItem key={invitation.id} data={invitation} />
|
||||
))}
|
||||
</OverlayScrollbar>
|
||||
<Divider />
|
||||
<button
|
||||
|
|
Loading…
Reference in a new issue