0
Fork 0
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:
Charles Zhao 2024-03-28 11:27:39 +08:00 committed by GitHub
parent ba966fdefe
commit afda22efa2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 83 additions and 0 deletions

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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