feat(workspace): added option to leave workspace (#2854)

This commit is contained in:
Waleed
2026-01-16 12:38:11 -08:00
committed by GitHub
parent fa63af9222
commit c863125c6b
3 changed files with 71 additions and 2 deletions

View File

@@ -161,6 +161,20 @@ interface ContextMenuProps {
* Set to true when creation is in progress or user lacks permissions
*/
disableCreateFolder?: boolean
/**
* Callback when leave is clicked (for workspaces)
*/
onLeave?: () => void
/**
* Whether to show the leave option (default: false)
* Set to true for workspaces the user can leave
*/
showLeave?: boolean
/**
* Whether the leave option is disabled (default: false)
* Set to true when user cannot leave (e.g., last admin)
*/
disableLeave?: boolean
}
/**
@@ -198,6 +212,9 @@ export function ContextMenu({
disableDelete = false,
disableCreate = false,
disableCreateFolder = false,
onLeave,
showLeave = false,
disableLeave = false,
}: ContextMenuProps) {
const [hexInput, setHexInput] = useState(currentColor || '#ffffff')
@@ -412,8 +429,20 @@ export function ContextMenu({
</PopoverItem>
)}
{/* Destructive action */}
{/* Destructive actions */}
{(hasNavigationSection || hasEditSection || hasCopySection) && <PopoverDivider rootOnly />}
{showLeave && onLeave && (
<PopoverItem
rootOnly
disabled={disableLeave}
onClick={() => {
onLeave()
onClose()
}}
>
Leave
</PopoverItem>
)}
<PopoverItem
rootOnly
disabled={disableDelete}

View File

@@ -103,6 +103,14 @@ interface WorkspaceHeaderProps {
* Whether to show the collapse button
*/
showCollapseButton?: boolean
/**
* Callback to leave the workspace
*/
onLeaveWorkspace?: (workspaceId: string) => Promise<void>
/**
* Current user's session ID for owner check
*/
sessionUserId?: string
}
/**
@@ -128,6 +136,8 @@ export function WorkspaceHeader({
onImportWorkspace,
isImportingWorkspace,
showCollapseButton = true,
onLeaveWorkspace,
sessionUserId,
}: WorkspaceHeaderProps) {
const [isInviteModalOpen, setIsInviteModalOpen] = useState(false)
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
@@ -267,6 +277,16 @@ export function WorkspaceHeader({
}
}
/**
* Handles leave action from context menu
*/
const handleLeaveAction = async () => {
if (!capturedWorkspaceRef.current || !onLeaveWorkspace) return
await onLeaveWorkspace(capturedWorkspaceRef.current.id)
setIsWorkspaceMenuOpen(false)
}
/**
* Handle delete workspace
*/
@@ -512,6 +532,8 @@ export function WorkspaceHeader({
const capturedPermissions = capturedWorkspaceRef.current?.permissions
const contextCanEdit = capturedPermissions === 'admin' || capturedPermissions === 'write'
const contextCanAdmin = capturedPermissions === 'admin'
const capturedWorkspace = workspaces.find((w) => w.id === capturedWorkspaceRef.current?.id)
const isOwner = capturedWorkspace && sessionUserId === capturedWorkspace.ownerId
return (
<ContextMenu
@@ -523,10 +545,12 @@ export function WorkspaceHeader({
onDuplicate={handleDuplicateAction}
onExport={handleExportAction}
onDelete={handleDeleteAction}
onLeave={handleLeaveAction}
showRename={true}
showDuplicate={true}
showExport={true}
disableRename={!contextCanEdit}
showLeave={!isOwner && !!onLeaveWorkspace}
disableRename={!contextCanAdmin}
disableDuplicate={!contextCanEdit}
disableExport={!contextCanAdmin}
disableDelete={!contextCanAdmin}

View File

@@ -157,6 +157,7 @@ export function Sidebar() {
isCreatingWorkspace,
updateWorkspaceName,
confirmDeleteWorkspace,
handleLeaveWorkspace,
} = useWorkspaceManagement({
workspaceId,
sessionUserId: sessionData?.user?.id,
@@ -378,6 +379,17 @@ export function Sidebar() {
[workspaces, confirmDeleteWorkspace]
)
/** Leaves a workspace */
const handleLeaveWorkspaceWrapper = useCallback(
async (workspaceIdToLeave: string) => {
const workspaceToLeave = workspaces.find((w) => w.id === workspaceIdToLeave)
if (workspaceToLeave) {
await handleLeaveWorkspace(workspaceToLeave)
}
},
[workspaces, handleLeaveWorkspace]
)
/** Duplicates a workspace */
const handleDuplicateWorkspace = useCallback(
async (_workspaceIdToDuplicate: string, workspaceName: string) => {
@@ -509,6 +521,8 @@ export function Sidebar() {
onImportWorkspace={handleImportWorkspace}
isImportingWorkspace={isImportingWorkspace}
showCollapseButton={isOnWorkflowPage}
onLeaveWorkspace={handleLeaveWorkspaceWrapper}
sessionUserId={sessionData?.user?.id}
/>
</div>
) : (
@@ -542,6 +556,8 @@ export function Sidebar() {
onImportWorkspace={handleImportWorkspace}
isImportingWorkspace={isImportingWorkspace}
showCollapseButton={isOnWorkflowPage}
onLeaveWorkspace={handleLeaveWorkspaceWrapper}
sessionUserId={sessionData?.user?.id}
/>
</div>