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  }