PreviewBranchActions() — supabase Function Reference
Architecture documentation for the PreviewBranchActions() function in Overview.tsx from the supabase codebase.
Entity Profile
Relationship Graph
Source Code
apps/studio/components/interfaces/BranchManagement/Overview.tsx lines 229–526
const PreviewBranchActions = ({
branch,
onSelectDeleteBranch,
generateCreatePullRequestURL,
}: {
branch: Branch
repo: string
onSelectDeleteBranch: () => void
generateCreatePullRequestURL: (branchName?: string) => string
}) => {
const gitlessBranching = useIsBranching2Enabled()
const queryClient = useQueryClient()
const { project_ref: branchRef, parent_project_ref: projectRef } = branch
const { can: canDeleteBranches } = useAsyncCheckPermissions(
PermissionAction.DELETE,
'preview_branches'
)
const { can: canUpdateBranches } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'preview_branches'
)
// If user can update branches, they can restore branches
const canRestoreBranches = canUpdateBranches
const { data } = useBranchQuery({ projectRef, branchRef })
const isBranchActiveHealthy = data?.status === 'ACTIVE_HEALTHY'
const isPersistentBranch = branch.persistent
const { hasAccess: hasAccessToPersistentBranching } = useCheckEntitlements('branching_persistent')
const [showConfirmResetModal, setShowConfirmResetModal] = useState(false)
const [showBranchModeSwitch, setShowBranchModeSwitch] = useState(false)
const [
showPersistentBranchDeleteConfirmationModal,
setShowPersistentBranchDeleteConfirmationModal,
] = useState(false)
const [showEditBranchModal, setShowEditBranchModal] = useState(false)
const { mutate: resetBranch, isPending: isResetting } = useBranchResetMutation({
onSuccess() {
toast.success('Success! Please allow a few seconds for the branch to reset.')
setShowConfirmResetModal(false)
},
})
const { mutate: updateBranch, isPending: isUpdatingBranch } = useBranchUpdateMutation({
onSuccess() {
toast.success('Successfully updated branch')
setShowBranchModeSwitch(false)
if (projectRef) {
queryClient.invalidateQueries({ queryKey: branchKeys.list(projectRef) })
}
},
})
const { mutate: restoreBranch } = useBranchRestoreMutation({
onSuccess() {
toast.success('Success! Please allow a few minutes for the branch to restore.')
setShowBranchModeSwitch(false)
},
})
const onRestoreBranch = () => {
restoreBranch({ branchRef, projectRef })
}
const onConfirmReset = () => {
resetBranch({ branchRef, projectRef })
}
const onTogglePersistent = () => {
updateBranch({ branchRef, projectRef, persistent: !branch.persistent })
}
const onDeleteBranch = (e: Event | React.MouseEvent<HTMLDivElement>) => {
if (isPersistentBranch) {
setShowPersistentBranchDeleteConfirmationModal(true)
} else {
e.stopPropagation()
onSelectDeleteBranch()
}
}
return (
<>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
type="text"
icon={<MoreVertical />}
className="px-1"
onClick={(e) => e.stopPropagation()}
/>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" side="bottom" align="end">
{/* Edit Branch (gitless) */}
{gitlessBranching && (
<DropdownMenuItemTooltip
className="gap-x-2"
disabled={!canUpdateBranches || !isBranchActiveHealthy || isUpdatingBranch}
onSelect={(e) => {
e.stopPropagation()
setShowEditBranchModal(true)
}}
onClick={(e) => {
e.stopPropagation()
setShowEditBranchModal(true)
}}
tooltip={{
content: {
side: 'left',
text: !canUpdateBranches
? 'You need additional permissions to edit branches'
: !isBranchActiveHealthy
? 'Branch is still initializing. Please wait for it to become healthy before editing.'
: undefined,
},
}}
>
<Pencil size={14} /> Edit branch
</DropdownMenuItemTooltip>
)}
{!branch.deletion_scheduled_at && (
<DropdownMenuItemTooltip
className="gap-x-2"
disabled={isResetting || !isBranchActiveHealthy}
onSelect={(e) => {
e.stopPropagation()
setShowConfirmResetModal(true)
}}
onClick={(e) => {
e.stopPropagation()
setShowConfirmResetModal(true)
}}
tooltip={{
content: {
side: 'left',
text: !isBranchActiveHealthy
? 'Branch is still initializing. Please wait for it to become healthy before resetting.'
: undefined,
},
}}
>
<RefreshCw size={14} /> Reset branch
</DropdownMenuItemTooltip>
)}
{!branch.deletion_scheduled_at && (
<DropdownMenuItemTooltip
className="gap-x-2"
disabled={
!isBranchActiveHealthy || (!branch.persistent && !hasAccessToPersistentBranching)
}
onSelect={(e) => {
e.stopPropagation()
setShowBranchModeSwitch(true)
}}
onClick={(e) => {
e.stopPropagation()
setShowBranchModeSwitch(true)
}}
tooltip={{
content: {
side: 'left',
text: !isBranchActiveHealthy
? 'Branch is still initializing. Please wait for it to become healthy before switching.'
: !branch.persistent && !hasAccessToPersistentBranching
? 'Upgrade your plan to access persistent branches'
: undefined,
},
}}
>
{branch.persistent ? (
<>
<Clock size={14} /> Switch to preview
</>
) : (
<>
<Infinity size={14} className="scale-110" /> Switch to persistent
</>
)}
</DropdownMenuItemTooltip>
)}
{/* Create PR if applicable */}
{branch.git_branch && branch.pr_number === undefined && (
<DropdownMenuItem asChild className="gap-x-2">
<a
target="_blank"
rel="noreferrer"
href={generateCreatePullRequestURL(branch.git_branch)}
onClick={(e) => e.stopPropagation()}
>
<ExternalLink size={14} /> Create pull request
</a>
</DropdownMenuItem>
)}
{branch.deletion_scheduled_at && (
<DropdownMenuItemTooltip
className="gap-x-2"
disabled={!canRestoreBranches || branch.preview_project_status !== 'INACTIVE'}
onSelect={(e) => {
e.stopPropagation()
onRestoreBranch()
}}
onClick={(e) => {
e.stopPropagation()
onRestoreBranch()
}}
tooltip={{
content: {
side: 'left',
text: !canRestoreBranches
? 'You need additional permissions to restore branches'
: branch.preview_project_status !== 'INACTIVE'
? 'Preview project is not fully paused or already coming up. Please wait for it to become fully paused before restoring.'
: undefined,
},
}}
>
<Clock size={14} /> Restore branch
</DropdownMenuItemTooltip>
)}
<DropdownMenuSeparator />
<DropdownMenuItemTooltip
className="gap-x-2"
disabled={!canDeleteBranches}
onSelect={onDeleteBranch}
onClick={onDeleteBranch}
tooltip={{
content: {
side: 'left',
text: !canDeleteBranches
? 'You need additional permissions to delete branches'
: undefined,
},
}}
>
<Trash2 size={14} /> Delete branch
</DropdownMenuItemTooltip>
</DropdownMenuContent>
</DropdownMenu>
<TextConfirmModal
variant="warning"
visible={showConfirmResetModal}
onCancel={() => setShowConfirmResetModal(false)}
onConfirm={onConfirmReset}
loading={isResetting}
title="Reset branch"
confirmLabel="Reset branch"
confirmPlaceholder="Type in name of branch"
confirmString={branch?.name ?? ''}
alert={{
title: `Are you sure you want to reset the "${branch.name}" branch? All data will be deleted.`,
}}
/>
<ConfirmationModal
variant="default"
visible={showBranchModeSwitch}
confirmLabel={branch.persistent ? 'Switch to preview' : 'Switch to persistent'}
title="Confirm branch mode switch"
loading={isUpdatingBranch}
onCancel={() => setShowBranchModeSwitch(false)}
onConfirm={onTogglePersistent}
>
<p className="text-sm text-foreground-light">
Are you sure you want to switch the branch "{branch.name}" to{' '}
{branch.persistent ? 'preview' : 'persistent'}?
</p>
</ConfirmationModal>
<ConfirmationModal
variant="warning"
visible={showPersistentBranchDeleteConfirmationModal}
confirmLabel={'Switch to preview'}
title="Branch must be switched to preview before deletion"
loading={isUpdatingBranch}
onCancel={() => setShowPersistentBranchDeleteConfirmationModal(false)}
onConfirm={onTogglePersistent}
>
<p className="text-sm text-foreground-light">
You must switch the branch "{branch.name}" to preview before deleting it.
</p>
</ConfirmationModal>
<EditBranchModal
branch={branch}
visible={showEditBranchModal}
onClose={() => setShowEditBranchModal(false)}
/>
</>
)
}
Domain
Subdomains
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free