Skip to content

Commit

Permalink
web: keyboard shortcuts for navigating the overview table (#5576)
Browse files Browse the repository at this point in the history
* web: keyboard shortcuts for navigating the overview table

* response to comments

* more response to comments
  • Loading branch information
nicks authored Mar 22, 2022
1 parent f8939b2 commit e7d690a
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 62 deletions.
1 change: 0 additions & 1 deletion web/src/GlobalNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ export function GlobalNav(props: GlobalNavProps) {
open={helpDialogOpen}
anchorEl={helpDialogAnchor}
onClose={() => toggleHelpDialog(AnalyticsAction.Close)}
isOverview={true}
/>
<UpdateDialog
open={updateDialogOpen}
Expand Down
15 changes: 1 addition & 14 deletions web/src/HelpDialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,5 @@ export default {
}

export const DialogOverview = () => (
<HelpDialog
open={true}
onClose={onRequestClose}
anchorEl={document.body}
isOverview={true}
/>
)
export const DialogLegacy = () => (
<HelpDialog
open={true}
onClose={onRequestClose}
anchorEl={document.body}
isOverview={false}
/>
<HelpDialog open={true} onClose={onRequestClose} anchorEl={document.body} />
)
10 changes: 1 addition & 9 deletions web/src/HelpDialog.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { mount } from "enzyme"
import React from "react"
import { MemoryRouter } from "react-router-dom"
import { DialogLegacy, DialogOverview } from "./HelpDialog.stories"
import { DialogOverview } from "./HelpDialog.stories"

it("renders overview dialog", () => {
mount(
Expand All @@ -10,11 +10,3 @@ it("renders overview dialog", () => {
</MemoryRouter>
)
})

it("renders legacy dialog", () => {
mount(
<MemoryRouter initialEntries={["/"]}>
<DialogLegacy />
</MemoryRouter>
)
})
14 changes: 3 additions & 11 deletions web/src/HelpDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ type props = {
open: boolean
onClose: () => void
anchorEl: Element | null
isOverview: boolean
}

let ShortcutRow = styled.div`
Expand Down Expand Up @@ -126,16 +125,9 @@ export default function HelpDialog(props: props) {
<ShortcutBox>Shift</ShortcutBox> + <ShortcutBox>1</ShortcutBox>,{" "}
<ShortcutBox>2</ShortcutBox>
</Shortcut>
{props.isOverview ? null : (
<React.Fragment>
<Shortcut label="View Logs">
<ShortcutBox>1</ShortcutBox>
</Shortcut>
<Shortcut label="View Alerts">
<ShortcutBox>2</ShortcutBox>
</Shortcut>
</React.Fragment>
)}
<Shortcut label="Select Resource Row">
<ShortcutBox>x</ShortcutBox>
</Shortcut>
<Shortcut label="Clear Logs">{cmdOrCtrlShortcut("Backspace")}</Shortcut>
<Shortcut label="Make Snapshot">
<ShortcutBox>s</ShortcutBox>
Expand Down
132 changes: 109 additions & 23 deletions web/src/OverviewTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import {
AccordionDetails,
AccordionSummary,
} from "@material-ui/core"
import React, { ChangeEvent, MouseEvent, useMemo, useState } from "react"
import React, {
ChangeEvent,
MouseEvent,
MutableRefObject,
useEffect,
useMemo,
useRef,
useState,
} from "react"
import {
HeaderGroup,
Row,
Expand Down Expand Up @@ -40,6 +48,7 @@ import {
rowIsDisabled,
RowValues,
} from "./OverviewTableColumns"
import { OverviewTableKeyboardShortcuts } from "./OverviewTableKeyboardShortcuts"
import {
AccordionDetailsStyleResetMixin,
AccordionStyleResetMixin,
Expand All @@ -63,6 +72,7 @@ import { Color, Font, FontSize, SizeUnit } from "./style-helpers"
import { isZeroTime, timeDiff } from "./time"
import {
ResourceName,
ResourceStatus,
TargetType,
TriggerMode,
UIButton,
Expand All @@ -82,10 +92,12 @@ type TableWrapperProps = {
type TableGroupProps = {
label: string
setGlobalSortBy: (id: string) => void
focused: string
} & TableOptions<RowValues>

type TableProps = {
setGlobalSortBy?: (id: string) => void
focused: string
} & TableOptions<RowValues>

type ResourceTableHeadRowProps = {
Expand Down Expand Up @@ -142,7 +154,7 @@ const ResourceTable = styled.table`
}
td:first-child {
padding-left: ${SizeUnit(0.75)};
padding-left: 24px;
}
td:last-child {
Expand All @@ -163,8 +175,16 @@ export const ResourceTableRow = styled.tr`
color: ${Color.gray60};
padding-top: 6px;
padding-bottom: 6px;
padding-left: 4px;
&.isDisabled {
&.isFocused,
&:focus {
border-left: 4px solid ${Color.blue};
outline: none;
td:first-child {
padding-left: 22px;
}
}
&.isSelected {
Expand Down Expand Up @@ -454,6 +474,22 @@ function sortByDisableStatus(resources: UIResource[] = []) {
return sorted
}

function onlyEnabledRows(rows: RowValues[]): RowValues[] {
return rows.filter(
(row) => row.statusLine.runtimeStatus !== ResourceStatus.Disabled
)
}
function onlyDisabledRows(rows: RowValues[]): RowValues[] {
return rows.filter(
(row) => row.statusLine.runtimeStatus === ResourceStatus.Disabled
)
}
function enabledRowsFirst(rows: RowValues[]): RowValues[] {
let result = onlyEnabledRows(rows)
result.push(...onlyDisabledRows(rows))
return result
}

export function labeledResourcesToTableCells(
resources: UIResource[] | undefined,
buttons: UIButton[] | undefined,
Expand Down Expand Up @@ -592,6 +628,42 @@ function ShowMoreResourcesRow({
)
}

function TableRow(props: { row: Row<RowValues>; focused: string }) {
let { row, focused } = props
const { isSelected } = useResourceSelection()
let isFocused = row.original.name == focused
let rowClasses =
(rowIsDisabled(row) ? "isDisabled " : "") +
(isSelected(row.original.name) ? "isSelected " : "") +
(isFocused ? "isFocused " : "")
let ref: MutableRefObject<HTMLTableRowElement | null> = useRef(null)

useEffect(() => {
if (isFocused && ref.current) {
ref.current.focus()
}
}, [isFocused, ref])

return (
<ResourceTableRow
tabIndex={-1}
ref={ref}
{...row.getRowProps({
className: rowClasses,
})}
>
{row.cells.map((cell) => (
<ResourceTableData
{...cell.getCellProps()}
className={cell.column.isSorted ? "isSorted" : ""}
>
{cell.render("Cell")}
</ResourceTableData>
))}
</ResourceTableRow>
)
}

export function Table(props: TableProps) {
if (props.data.length === 0) {
return null
Expand Down Expand Up @@ -619,7 +691,6 @@ export function Table(props: TableProps) {
)

const showMoreOnClick = () => setPageSize(pageSize * RESOURCE_LIST_MULTIPLIER)
const { isSelected } = useResourceSelection()

// TODO (lizz): Consider adding `aria-sort` markup to table headings
return (
Expand All @@ -636,25 +707,12 @@ export function Table(props: TableProps) {
<tbody {...getTableBodyProps()}>
{page.map((row: Row<RowValues>) => {
prepareRow(row)

let rowClasses =
(rowIsDisabled(row) ? "isDisabled " : "") +
(isSelected(row.original.name) ? "isSelected " : "")
return (
<ResourceTableRow
{...row.getRowProps({
className: rowClasses,
})}
>
{row.cells.map((cell) => (
<ResourceTableData
{...cell.getCellProps()}
className={cell.column.isSorted ? "isSorted" : ""}
>
{cell.render("Cell")}
</ResourceTableData>
))}
</ResourceTableRow>
<TableRow
key={row.original.name}
row={row}
focused={props.focused}
/>
)
})}
<ShowMoreResourcesRow
Expand Down Expand Up @@ -710,6 +768,18 @@ export function TableGroupedByLabels({
() => labeledResourcesToTableCells(resources, buttons, logAlertIndex),
[resources, buttons]
)

const totalOrder = useMemo(() => {
let totalOrder = []
data.labels.forEach((label) =>
totalOrder.push(...enabledRowsFirst(data.labelsToResources[label]))
)
totalOrder.push(...enabledRowsFirst(data.unlabeled))
totalOrder.push(...enabledRowsFirst(data.tiltfile))
return totalOrder
}, [data])
let [focused, setFocused] = useState("")

const columns = getTableColumns(features)

// Global table settings are currently used to sort multiple
Expand Down Expand Up @@ -738,6 +808,7 @@ export function TableGroupedByLabels({
columns={columns}
useControlledState={useControlledState}
setGlobalSortBy={setGlobalSortBy}
focused={focused}
/>
))}
<TableGroup
Expand All @@ -746,13 +817,20 @@ export function TableGroupedByLabels({
columns={columns}
useControlledState={useControlledState}
setGlobalSortBy={setGlobalSortBy}
focused={focused}
/>
<TableGroup
label={TILTFILE_LABEL}
data={data.tiltfile}
columns={columns}
useControlledState={useControlledState}
setGlobalSortBy={setGlobalSortBy}
focused={focused}
/>
<OverviewTableKeyboardShortcuts
focused={focused}
setFocused={setFocused}
rows={totalOrder}
/>
</>
)
Expand All @@ -768,13 +846,21 @@ export function TableWithoutGroups({ resources, buttons }: TableWrapperProps) {
}, [resources, buttons])
const columns = getTableColumns(features)

let totalOrder = useMemo(() => enabledRowsFirst(data), [data])
let [focused, setFocused] = useState("")

if (resources?.length === 0) {
return null
}

return (
<TableWithoutGroupsRoot>
<Table columns={columns} data={data} />
<Table columns={columns} data={data} focused={focused} />
<OverviewTableKeyboardShortcuts
focused={focused}
setFocused={setFocused}
rows={totalOrder}
/>
</TableWithoutGroupsRoot>
)
}
Expand Down
Loading

0 comments on commit e7d690a

Please sign in to comment.