import clsx from 'clsx'; import { cloneElement, forwardRef, Fragment, ReactElement, useEffect, useState, } from 'react'; import {ButtonBase} from '../ui/buttons/button-base'; import {PersonalWorkspace, useUserWorkspaces} from './user-workspaces'; import {UnfoldMoreIcon} from '../icons/material/UnfoldMore'; import {AddIcon} from '../icons/material/Add'; import {NewWorkspaceDialog} from './new-workspace-dialog'; import {WorkspaceMembersDialog} from './workspace-members-dialog'; import { useActiveWorkspace, useActiveWorkspaceId, } from './active-workspace-id-context'; import {DialogTrigger} from '../ui/overlays/dialog/dialog-trigger'; import {Workspace} from './types/workspace'; import {Dialog} from '../ui/overlays/dialog/dialog'; import {DialogBody} from '../ui/overlays/dialog/dialog-body'; import {Button, ButtonProps} from '../ui/buttons/button'; import {CheckIcon} from '../icons/material/Check'; import {Menu, MenuItem, MenuTrigger} from '../ui/navigation/menu/menu-trigger'; import {KeyboardArrowDownIcon} from '../icons/material/KeyboardArrowDown'; import {PersonAddIcon} from '../icons/material/PersonAdd'; import {DeleteIcon} from '../icons/material/Delete'; import {ExitToAppIcon} from '../icons/material/ExitToApp'; import {EditIcon} from '../icons/material/Edit'; import {RenameWorkspaceDialog} from './rename-workspace-dialog'; import {ConfirmationDialog} from '../ui/overlays/dialog/confirmation-dialog'; import {useDeleteWorkspace} from './requests/delete-workspace'; import {useRemoveMember} from './requests/remove-member'; import {useAuth} from '../auth/use-auth'; import {Trans} from '../i18n/trans'; import {LeaveWorkspaceConfirmation} from './leave-workspace-confirmation'; import {openDialog} from '@common/ui/overlays/store/dialog-store'; import {useDialogContext} from '@common/ui/overlays/dialog/dialog-context'; import {PolicyFailMessage} from '@common/billing/upgrade/policy-fail-message'; interface WorkspaceSelectorProps { className?: string; onChange?: (id: number) => void; trigger?: ReactElement; placement?: 'top' | 'bottom'; } export function WorkspaceSelector({ onChange, className, trigger, placement = 'top', }: WorkspaceSelectorProps) { const {data: workspaces, isFetched, isFetching} = useUserWorkspaces(); const {setWorkspaceId} = useActiveWorkspaceId(); const activeWorkspace = useActiveWorkspace(); const [selectorIsOpen, setSelectorIsOpen] = useState(false); const {hasPermission} = useAuth(); // if user no longer has access to previously selected workspace, select personal one useEffect(() => { // make sure we don't unset active workspace while user workspaces are being re-fetched if (isFetched && !isFetching && !activeWorkspace) { setWorkspaceId(PersonalWorkspace.id); } }, [activeWorkspace, workspaces, setWorkspaceId, isFetched, isFetching]); if ( // if we have a custom trigger, leave rendering up to the customer trigger !trigger && (!activeWorkspace || (!hasPermission('workspaces.create') && workspaces?.length === 1)) ) { return null; } return ( { setSelectorIsOpen(false); }} > {trigger ? ( cloneElement(trigger, { onClick: () => setSelectorIsOpen(!selectorIsOpen), }) ) : ( setSelectorIsOpen(!selectorIsOpen)} workspace={activeWorkspace!} className={className} /> )}
{workspaces?.map(workspace => ( ))}
setSelectorIsOpen(false)} onCreated={id => onChange?.(id)} workspaceCount={workspaces ? workspaces.length - 1 : 0} />
); } interface CreateWorkspaceButtonProps { onClick: () => void; onCreated?: (id: number) => void; workspaceCount: number; } function CreateWorkspaceButton({ onClick, onCreated, workspaceCount, }: CreateWorkspaceButtonProps) { const {setWorkspaceId} = useActiveWorkspaceId(); const {checkOverQuotaOrNoPermission} = useAuth(); const {overQuotaOrNoPermission} = checkOverQuotaOrNoPermission( 'workspaces.create', 'count', workspaceCount, ); return ( {overQuotaOrNoPermission && ( } /> )} ); } interface DefaultTriggerProps { onClick: () => void; workspace: Workspace; className?: string; } const DefaultTrigger = forwardRef( ({workspace, className, onClick, ...other}, ref) => { return ( {workspace.default ? ( ) : ( workspace.name )} {workspace.default ? ( ) : ( )} ); }, ); interface WorkspaceItemProps { workspace: Workspace; onChange: WorkspaceSelectorProps['onChange']; setSelectorIsOpen: (value: boolean) => void; } function WorkspaceItem({ workspace, onChange, setSelectorIsOpen, }: WorkspaceItemProps) { const {workspaceId, setWorkspaceId} = useActiveWorkspaceId(); const isActive = workspaceId === workspace.id; return (
{ setWorkspaceId(workspace.id); onChange?.(workspace.id); setSelectorIsOpen(false); }} className={clsx( 'mb-4 flex cursor-pointer items-center gap-12 rounded-lg p-10 text-left', isActive && 'bg-primary/5', !isActive && 'hover:bg-hover', )} >
{workspace.name}
{workspace.default ? ( ) : ( )}
{workspace.id !== 0 && ( )}
); } interface LeaveWorkspaceDialogProps { workspace: Workspace; onChange?: (id: number) => void; } function LeaveWorkspaceDialog({ workspace, onChange, }: LeaveWorkspaceDialogProps) { const removeMember = useRemoveMember(); const {user} = useAuth(); const {close} = useDialogContext(); return ( { removeMember.mutate( { workspaceId: workspace.id, memberId: user!.id, memberType: 'member', }, { onSuccess: () => { close(); onChange?.(PersonalWorkspace.id); }, }, ); }} /> ); } interface DeleteWorkspaceConfirmationProps { workspace: Workspace; onChange?: (id: number) => void; } function DeleteWorkspaceConfirmation({ workspace, onChange, }: DeleteWorkspaceConfirmationProps) { const deleteWorkspace = useDeleteWorkspace(); const {close} = useDialogContext(); return ( } body={ } confirm={} isLoading={deleteWorkspace.isPending} onConfirm={() => { deleteWorkspace.mutate( {id: workspace.id}, { onSuccess: () => { close(); onChange?.(PersonalWorkspace.id); }, }, ); }} /> ); } interface ManageButtonProps { setSelectorIsOpen: (value: boolean) => void; workspace: Workspace; onChange?: (id: number) => void; } function ManageButton({ setSelectorIsOpen, workspace, onChange, }: ManageButtonProps) { const {user} = useAuth(); return ( setSelectorIsOpen(false)}> { e.stopPropagation(); openDialog(WorkspaceMembersDialog, {workspace}); }} value="workspaceMembers" startIcon={} > {workspace.owner_id === user?.id && ( { e.stopPropagation(); openDialog(RenameWorkspaceDialog, {workspace}); }} value="updateWorkspace" startIcon={} > )} {workspace.owner_id !== user?.id && ( { e.stopPropagation(); openDialog(LeaveWorkspaceDialog, {workspace, onChange}); }} value="leaveWorkspace" startIcon={} > )} {workspace.owner_id === user?.id && ( { e.stopPropagation(); openDialog(DeleteWorkspaceConfirmation, {workspace, onChange}); }} value="deleteWorkspace" startIcon={} > )} ); }