Skip to content

Commit

Permalink
Add filter button to job table cells (#4105)
Browse files Browse the repository at this point in the history
In a similar way to the copy button, this adds an icon button which appears when the user hovers over the cell. It applies a filter to the cell's column for the cell's value. It appears only for cells for whose columns can be filtered by.
  • Loading branch information
mauriceyap authored Dec 19, 2024
1 parent 9967a86 commit 6b15e67
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 50 deletions.
76 changes: 76 additions & 0 deletions internal/lookout/ui/src/components/ActionableValueOnHover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ReactNode, useState } from "react"

import { IconButton, IconButtonProps, styled } from "@mui/material"

import { CopyIconButton } from "./CopyIconButton"
import { AddFilter } from "./icons"

const OuterContainer = styled("div")({
display: "flex",
flexDirection: "row",
gap: "0.5ch",
})

const StyledIconButton = styled(IconButton)<IconButtonProps & { hidden: boolean }>(({ hidden }) => ({
padding: 0,
visibility: hidden ? "hidden" : "unset",
}))

export interface CopyActionProps {
copyContent: string
}

export interface FilterActionProps {
onFilter: () => void
}

export interface ActionableValueOnHoverProps {
children: ReactNode
copyAction?: CopyActionProps
filterAction?: FilterActionProps
stopPropogationOnActionClick?: boolean
}

export const ActionableValueOnHover = ({
children,
copyAction,
filterAction,
stopPropogationOnActionClick = false,
}: ActionableValueOnHoverProps) => {
const [hovering, setHovering] = useState(false)
return (
<OuterContainer onMouseEnter={() => setHovering(true)} onMouseLeave={() => setHovering(false)}>
<div>{children}</div>
{copyAction && (
<div>
<CopyIconButton
content={copyAction.copyContent}
size="small"
onClick={(e) => {
if (stopPropogationOnActionClick) {
e.stopPropagation()
}
}}
hidden={!hovering}
/>
</div>
)}
{filterAction && (
<div>
<StyledIconButton
size="small"
hidden={!hovering}
onClick={(e) => {
if (stopPropogationOnActionClick) {
e.stopPropagation()
}
filterAction.onFilter()
}}
>
<AddFilter fontSize="inherit" />
</StyledIconButton>
</div>
)}
</OuterContainer>
)
}
32 changes: 0 additions & 32 deletions internal/lookout/ui/src/components/CopyableValueOnHover.tsx

This file was deleted.

11 changes: 11 additions & 0 deletions internal/lookout/ui/src/components/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Add, FilterAlt } from "@mui/icons-material"
import { SvgIcon, SvgIconProps } from "@mui/material"

export const AddFilter: typeof SvgIcon = (props: SvgIconProps) => (
<SvgIcon {...props}>
<Add {...props} viewBox="-20 -20 44 44" />
<FilterAlt {...props} viewBox="0 0 28 28" />
</SvgIcon>
)

AddFilter.muiName = "AddFilter"
33 changes: 23 additions & 10 deletions internal/lookout/ui/src/components/lookoutV2/JobsTableCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import styles from "./JobsTableCell.module.css"
import { JobsTableFilter } from "./JobsTableFilter"
import { JobRow, JobTableRow } from "../../models/jobsTableModels"
import { Match } from "../../models/lookoutV2Models"
import { getColumnMetadata, toColId } from "../../utils/jobsTableColumns"
import { FilterType, getColumnMetadata, toColId } from "../../utils/jobsTableColumns"
import { matchForColumn } from "../../utils/jobsTableUtils"
import { CopyableValueOnHover } from "../CopyableValueOnHover"
import { ActionableValueOnHover } from "../ActionableValueOnHover"

const sharedCellStyle = {
padding: 0,
Expand Down Expand Up @@ -255,18 +255,31 @@ export const BodyCell = ({ cell, rowIsGroup, rowIsExpanded, onExpandedChange, on
...cell.getContext(),
onClickRowCheckbox,
})
) : !rowIsGroup && Boolean(cell.getValue()) && columnMetadata.allowCopy ? (
<CopyableValueOnHover copyContent={String(cell.getValue())} onCopyButtonClick={(e) => e.stopPropagation()}>
) : (
<ActionableValueOnHover
stopPropogationOnActionClick
copyAction={
!rowIsGroup && Boolean(cell.getValue()) && columnMetadata.allowCopy
? { copyContent: String(cell.getValue()) }
: undefined
}
filterAction={
columnMetadata.filterType === undefined
? undefined
: {
onFilter: () => {
cell.column.setFilterValue(
columnMetadata.filterType === FilterType.Enum ? [cell.getValue()] : cell.getValue(),
)
},
}
}
>
{flexRender(cell.column.columnDef.cell, {
...cell.getContext(),
onClickRowCheckbox,
})}
</CopyableValueOnHover>
) : (
flexRender(cell.column.columnDef.cell, {
...cell.getContext(),
onClickRowCheckbox,
})
</ActionableValueOnHover>
)}
</TableCell>
)
Expand Down
13 changes: 11 additions & 2 deletions internal/lookout/ui/src/components/lookoutV2/JobsTableFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,23 @@ const TextFilter = ({
useEffect(() => {
onSetTextFieldRef(ref)
}, [ref])
const [textFieldValue, setTextFieldValue] = useState(defaultValue)
useEffect(() => {
setTextFieldValue(defaultValue)
}, [defaultValue])

const debouncedOnChange = useDebouncedCallback(onChange, 300)
useEffect(() => {
debouncedOnChange(textFieldValue)
}, [textFieldValue, debouncedOnChange])

return (
<TextField
onChange={(e) => debouncedOnChange(e.currentTarget.value)}
onChange={(e) => setTextFieldValue(e.currentTarget.value)}
value={textFieldValue}
inputRef={ref}
type={"text"}
size={"small"}
defaultValue={defaultValue}
error={parseError !== undefined}
placeholder={label}
sx={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Table, TableBody, TableCell, TableRow, Link } from "@mui/material"
import validator from "validator"

import styles from "./KeyValuePairTable.module.css"
import { CopyableValueOnHover } from "../../CopyableValueOnHover"
import { ActionableValueOnHover } from "../../ActionableValueOnHover"

export interface KeyValuePairTable {
data: {
Expand Down Expand Up @@ -37,11 +37,9 @@ export const KeyValuePairTable = ({ data }: KeyValuePairTable) => {
<TableRow key={key}>
<TableCell className={styles.cell}>{key}</TableCell>
<TableCell className={styles.cell}>
{allowCopy ? (
<CopyableValueOnHover copyContent={value}>{nodeToDisplay}</CopyableValueOnHover>
) : (
nodeToDisplay
)}
<ActionableValueOnHover copyAction={allowCopy ? { copyContent: value } : undefined}>
{nodeToDisplay}
</ActionableValueOnHover>
</TableCell>
</TableRow>
)
Expand Down

0 comments on commit 6b15e67

Please sign in to comment.