github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/OverviewTableBulkActions.tsx (about) 1 import React, { useMemo } from "react" 2 import styled from "styled-components" 3 import { 4 ApiButtonToggleState, 5 buttonsByComponent, 6 ButtonSet, 7 } from "./ApiButton" 8 import { BulkApiButton } from "./BulkApiButton" 9 import { useFeatures } from "./feature" 10 import { useResourceSelection } from "./ResourceSelectionContext" 11 import SrOnly from "./SrOnly" 12 import { Color, FontSize, SizeUnit } from "./style-helpers" 13 import { UIButton } from "./types" 14 15 // Types 16 type OverviewTableBulkActionsProps = { 17 uiButtons?: UIButton[] 18 } 19 20 type ActionButtons = { [key in BulkAction]: UIButton[] } 21 22 export enum BulkAction { 23 Disable = "disable", // Enable / disable are states of the same toggle, so use a single name 24 } 25 26 // Styles 27 const BulkActionMenu = styled.div` 28 align-items: center; 29 display: flex; 30 flex-direction: row; 31 margin-left: ${SizeUnit(2)}; 32 white-space: nowrap; 33 ` 34 35 const SelectedCount = styled.p` 36 margin: ${SizeUnit(0.25)}; 37 font-size: ${FontSize.small}; 38 color: ${Color.gray70}; 39 ` 40 41 // Helpers 42 export function buttonsByAction( 43 resourceButtons: Map<string, ButtonSet>, 44 selectedResources: Set<string> 45 ) { 46 const actionButtons: ActionButtons = { 47 [BulkAction.Disable]: [], 48 } 49 50 selectedResources.forEach((resource) => { 51 const buttonSet = resourceButtons.get(resource) 52 if (buttonSet && buttonSet.toggleDisable) { 53 actionButtons[BulkAction.Disable].push(buttonSet.toggleDisable) 54 } 55 }) 56 57 return actionButtons 58 } 59 60 // Components 61 function BulkSelectedCount({ count }: { count: number }) { 62 if (!count) { 63 return null 64 } 65 66 return ( 67 <SelectedCount> 68 {count} <SrOnly>resources</SrOnly> selected 69 </SelectedCount> 70 ) 71 } 72 73 export function OverviewTableBulkActions({ 74 uiButtons, 75 }: OverviewTableBulkActionsProps) { 76 const features = useFeatures() 77 const { selected, clearSelections } = useResourceSelection() 78 79 const resourceButtons = useMemo( 80 () => buttonsByComponent(uiButtons), 81 [uiButtons] 82 ) 83 84 const actionButtons = useMemo( 85 () => buttonsByAction(resourceButtons, selected), 86 [selected, uiButtons] 87 ) 88 89 // Don't render if there are no selections 90 if (selected.size === 0) { 91 return null 92 } 93 94 const onClickCallback = clearSelections 95 96 return ( 97 <BulkActionMenu aria-label="Bulk resource actions"> 98 <BulkApiButton 99 bulkAction={BulkAction.Disable} 100 buttonText="Enable" 101 requiresConfirmation={false} 102 uiButtons={actionButtons[BulkAction.Disable]} 103 targetToggleState={ApiButtonToggleState.On} 104 onClickCallback={onClickCallback} 105 /> 106 <BulkApiButton 107 bulkAction={BulkAction.Disable} 108 buttonText="Disable" 109 requiresConfirmation={true} 110 uiButtons={actionButtons[BulkAction.Disable]} 111 targetToggleState={ApiButtonToggleState.Off} 112 onClickCallback={onClickCallback} 113 /> 114 <BulkSelectedCount count={selected.size} /> 115 </BulkActionMenu> 116 ) 117 }