Skip to content

Commit

Permalink
Graph filters redesign (#767)
Browse files Browse the repository at this point in the history
* Start on graph filters redesign

* Hook up filters

* Fix code style issues with ESLint

* Lint fixes

* Test fixes

* Remaining tests

* Fix code style issues with ESLint

* Add tests

* Fix code style issues with ESLint

* Add filter chips

* Add inlineFilters chips

* npm update

* App test update

---------

Co-authored-by: Lint Action <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
edlouth and github-actions[bot] authored Nov 6, 2023
1 parent e3d507b commit 63cc196
Show file tree
Hide file tree
Showing 70 changed files with 5,214 additions and 4,591 deletions.
4,755 changes: 3,827 additions & 928 deletions grai-frontend/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion grai-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"chartjs-chart-matrix": "^2.0.1",
"dayjs": "^1.11.6",
"elkjs": "^0.8.2",
"eslint": "^8.52.0",
"eslint": "^8.53.0",
"eslint-plugin-import": "^2.27.5",
"graphql": "^16.8.1",
"jest-websocket-mock": "^2.5.0",
Expand Down
4 changes: 0 additions & 4 deletions grai-frontend/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import App from "./App"
test("renders", async () => {
render(<App />)

await waitFor(() => {
expect(screen.queryByRole("progressbar")).not.toBeInTheDocument()
})

await waitFor(() => {
expect(screen.getByText(/Welcome back!/i)).toBeInTheDocument()
})
Expand Down
6 changes: 3 additions & 3 deletions grai-frontend/src/components/chat/ChatWindow.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react"
import userEvent from "@testing-library/user-event"
import { render, screen, waitFor } from "testing"
import { act, render, screen, waitFor } from "testing"
import ChatWindow from "./ChatWindow"

const handleInput = jest.fn()
Expand All @@ -18,11 +18,11 @@ test("type", async () => {

expect(screen.getByRole("textbox")).toBeInTheDocument()

user.type(screen.getByRole("textbox"), "Hello")
await act(async () => user.type(screen.getByRole("textbox"), "Hello"))

await waitFor(() => expect(screen.getByRole("textbox")).toHaveValue("Hello"))

user.type(screen.getByRole("textbox"), "{enter}")
await act(async () => await user.type(screen.getByRole("textbox"), "{enter}"))

await waitFor(() => expect(screen.getByRole("textbox")).toHaveValue(""))

Expand Down
12 changes: 4 additions & 8 deletions grai-frontend/src/components/edges/EdgeLineage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { gql, useQuery } from "@apollo/client"
import { Alert, Box } from "@mui/material"
import useWorkspace from "helpers/useWorkspace"
import GraphComponent from "components/graph/GraphComponent"
import useFilters from "components/graph/useFilters"
import useInlineFilters from "components/graph/useInlineFilters"
import useCombinedFilters from "components/graph/useCombinedFilters"
import GraphError from "components/utils/GraphError"
import {
GetTablesAndEdgesEdgeLineage,
Expand Down Expand Up @@ -65,8 +64,8 @@ type EdgeLineageProps = {
const EdgeLineage: React.FC<EdgeLineageProps> = ({ edge }) => {
const [value, setValue] = useState(1)
const { organisationName, workspaceName } = useWorkspace()
const { filters, setFilters } = useFilters(`edge-${edge.id}-graph-filters`)
const { inlineFilters, setInlineFilters } = useInlineFilters(
const { combinedFilters } = useCombinedFilters(
`edge-${edge.id}-graph-filters`,
`edge-${edge.id}-graph-inline-filters`,
)

Expand Down Expand Up @@ -106,10 +105,7 @@ const EdgeLineage: React.FC<EdgeLineageProps> = ({ edge }) => {
setValue,
},
}}
filters={filters ?? []}
setFilters={setFilters}
inlineFilters={inlineFilters ?? []}
setInlineFilters={setInlineFilters}
combinedFilters={combinedFilters}
/>
</Box>
)
Expand Down
23 changes: 19 additions & 4 deletions grai-frontend/src/components/filters/FilterField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,30 @@ interface FilterFieldProps<T extends Field>
extends Omit<
AutocompleteProps<T, false, false, false, "div">,
"renderInput"
> {}
> {
placeholder?: string
compact?: boolean
}

const FilterField = <T extends Field>(props: FilterFieldProps<T>) => (
const FilterField = <T extends Field>({
compact,
placeholder,
...rest
}: FilterFieldProps<T>) => (
<Autocomplete
{...props}
{...rest}
openOnFocus
autoSelect
renderInput={params => <TextField {...params} />}
renderInput={params => (
<TextField
{...params}
sx={{ backgroundColor: "white" }}
size={compact ? "small" : undefined}
placeholder={placeholder}
/>
)}
getOptionDisabled={option => option.disabled ?? false}
disablePortal={compact}
/>
)

Expand Down
104 changes: 60 additions & 44 deletions grai-frontend/src/components/filters/FilterRow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react"
import { Close } from "@mui/icons-material"
import { Grid, IconButton } from "@mui/material"
import { Box, Grid, IconButton } from "@mui/material"
import FilterField from "./FilterField"
import FilterRowValue from "./FilterRowValue"
import {
Expand All @@ -19,6 +19,7 @@ type FilterRowProps = {
namespaces: string[]
tags: string[]
sources: Source[]
compact?: boolean
}

const FilterRow: React.FC<FilterRowProps> = ({
Expand All @@ -28,6 +29,7 @@ const FilterRow: React.FC<FilterRowProps> = ({
namespaces,
tags,
sources,
compact,
}) => {
const properties = getProperties(namespaces, tags, sources)

Expand All @@ -53,50 +55,64 @@ const FilterRow: React.FC<FilterRowProps> = ({
}

return (
<Grid container spacing={1} sx={{ mt: 0.5 }}>
<Grid item md={3}>
<FilterField<Property>
options={properties}
value={property}
onChange={(event, newValue) =>
onChange({ ...filter, type: newValue?.value ?? null })
}
data-testid="autocomplete-property"
/>
<Box
sx={{
backgroundColor: compact ? "#F7F7F7" : undefined,
p: 1,
borderRadius: "12px",
mt: 1,
display: "flex",
}}
>
<Grid container>
<Grid item md={3} sx={{ pr: "6px" }}>
<FilterField<Property>
options={properties}
value={property}
onChange={(event, newValue) =>
onChange({ ...filter, type: newValue?.value ?? null })
}
compact={compact}
data-testid="autocomplete-property"
/>
</Grid>
<Grid item md={3} sx={{ pr: "6px" }}>
<FilterField<Field>
placeholder="Field"
disabled={!property}
options={property?.fields ?? []}
value={field}
onChange={handleFieldChange}
compact={compact}
data-testid="autocomplete-field"
/>
</Grid>
<Grid item md={3} sx={{ pr: "6px" }}>
<FilterField<Operator>
placeholder="Operator"
disabled={!field}
options={field?.operators ?? []}
value={operator}
onChange={(event, newValue) =>
onChange({ ...filter, operator: newValue?.value ?? null })
}
compact={compact}
data-testid="autocomplete-operator"
/>
</Grid>
<Grid item md={3}>
<FilterRowValue
operator={operator}
filter={filter}
onChange={onChange}
compact={compact}
/>
</Grid>
</Grid>
<Grid item md={3}>
<FilterField<Field>
disabled={!property}
options={property?.fields ?? []}
value={field}
onChange={handleFieldChange}
data-testid="autocomplete-field"
/>
</Grid>
<Grid item md={3}>
<FilterField<Operator>
disabled={!field}
options={field?.operators ?? []}
value={operator}
onChange={(event, newValue) =>
onChange({ ...filter, operator: newValue?.value ?? null })
}
data-testid="autocomplete-operator"
/>
</Grid>
<Grid item md={2}>
<FilterRowValue
operator={operator}
filter={filter}
onChange={onChange}
/>
</Grid>
<Grid item md={1}>
<IconButton onClick={onRemove} data-testid="filter-row-remove">
<Close />
</IconButton>
</Grid>
</Grid>
<IconButton onClick={onRemove} data-testid="filter-row-remove">
<Close />
</IconButton>
</Box>
)
}

Expand Down
25 changes: 23 additions & 2 deletions grai-frontend/src/components/filters/FilterRowValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ type FilterRowValueProps = {
operator: Operator | null
filter: Filter
onChange: (filter: Filter) => void
compact?: boolean
}

const FilterRowValue: React.FC<FilterRowValueProps> = ({
operator,
filter,
onChange,
compact,
}) => {
const handleValueChange = (
event: React.SyntheticEvent<Element, Event>,
Expand Down Expand Up @@ -55,6 +57,9 @@ const FilterRowValue: React.FC<FilterRowValueProps> = ({
inputProps={{
"data-testid": "value",
}}
size={compact ? "small" : undefined}
placeholder={compact ? "Value" : undefined}
sx={{ backgroundColor: "white" }}
/>
)

Expand All @@ -72,7 +77,13 @@ const FilterRowValue: React.FC<FilterRowValueProps> = ({
),
)}
onChange={handleValueChange}
renderInput={params => <TextField {...params} />}
renderInput={params => (
<TextField
{...params}
sx={{ backgroundColor: "white" }}
placeholder={compact ? "Value" : undefined}
/>
)}
renderOption={(props, option, { selected }) => (
<li {...props}>
<Checkbox
Expand All @@ -84,6 +95,8 @@ const FilterRowValue: React.FC<FilterRowValueProps> = ({
{typeof option === "string" ? option : option?.label}
</li>
)}
size={compact ? "small" : undefined}
disablePortal={compact}
data-testid="autocomplete-value"
/>
)
Expand All @@ -96,7 +109,15 @@ const FilterRowValue: React.FC<FilterRowValueProps> = ({
options={operator.options}
value={arrayFirst(filter.value)}
onChange={handleValueChange}
renderInput={params => <TextField {...params} />}
renderInput={params => (
<TextField
{...params}
sx={{ backgroundColor: "white" }}
placeholder={compact ? "Value" : undefined}
/>
)}
size={compact ? "small" : undefined}
disablePortal={compact}
data-testid="autocomplete-value"
/>
)
Expand Down
30 changes: 18 additions & 12 deletions grai-frontend/src/components/filters/FilterRows.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react"
import { Box } from "@mui/material"
import FilterRowHeader from "components/filters/FilterRowHeader"
import FilterRow from "./FilterRow"
import { Filter, Source } from "./filters"
Expand All @@ -9,6 +10,7 @@ type FilterRowsProps = {
namespaces: string[]
tags: string[]
sources: Source[]
compact?: boolean
}

const FilterRows: React.FC<FilterRowsProps> = ({
Expand All @@ -17,6 +19,7 @@ const FilterRows: React.FC<FilterRowsProps> = ({
namespaces,
tags,
sources,
compact,
}) => {
const handleChangeFilters = (index: number) => (filter: Filter) => {
const newFilters = [...filters]
Expand All @@ -32,18 +35,21 @@ const FilterRows: React.FC<FilterRowsProps> = ({

return (
<>
<FilterRowHeader />
{filters.map((filter, index) => (
<FilterRow
key={index}
filter={filter}
onChange={handleChangeFilters(index)}
onRemove={handleRemoveFilter(index)}
namespaces={namespaces}
tags={tags}
sources={sources}
/>
))}
{compact !== true && <FilterRowHeader />}
<Box sx={{ mt: -1 }}>
{filters.map((filter, index) => (
<FilterRow
key={index}
filter={filter}
onChange={handleChangeFilters(index)}
onRemove={handleRemoveFilter(index)}
namespaces={namespaces}
tags={tags}
sources={sources}
compact={compact}
/>
))}
</Box>
</>
)
}
Expand Down
Loading

0 comments on commit 63cc196

Please sign in to comment.