Skip to content

Commit

Permalink
Use Combobox in datagrid dropdown (#5010)
Browse files Browse the repository at this point in the history
* Combobox allow empty option

* Use new combobox component in datagrid dropdown cell

* Update dropdown

* Fix remove value from dropdown

* Add changeset

* Fix types

* Fix  ts strict

* Extract messages

* Update changeset
  • Loading branch information
poulch authored and Cloud11PL committed Jul 8, 2024
1 parent c0c2d7b commit 3c714ae
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 67 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-lemons-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

The selected value is no longer filtering the options when using any select list in product variant table
4 changes: 4 additions & 0 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -7740,6 +7740,10 @@
"context": "search label",
"string": "Search Countries"
},
"pGfO2i": {
"context": "empty option",
"string": "None"
},
"pGwvpX": {
"context": "status",
"string": "Deactivated"
Expand Down
13 changes: 12 additions & 1 deletion src/components/Combobox/components/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React, { ReactNode, useEffect, useRef, useState } from "react";
import { useIntl } from "react-intl";

import { useCombbobxCustomOption } from "../hooks/useCombbobxCustomOption";
import { useComboboxEmptyOption } from "../hooks/useComboboxEmptyOption";
import { useComboboxHandlers } from "../hooks/useComboboxHandlers";

type HandleOnChangeValue = Option | null;
Expand All @@ -22,6 +23,7 @@ type ComboboxProps = Omit<
fetchOptions: (data: string) => void;
allowCustomValues?: boolean;
alwaysFetchOnFocus?: boolean;
allowEmptyValue?: boolean;
fetchMore?: FetchMoreProps;
value: Option | null;
onChange: (event: ChangeEvent) => void;
Expand All @@ -34,6 +36,7 @@ const ComboboxRoot = ({
options,
alwaysFetchOnFocus = false,
allowCustomValues = false,
allowEmptyValue = false,
fetchMore,
loading,
children,
Expand Down Expand Up @@ -64,6 +67,8 @@ const ComboboxRoot = ({
selectedValue,
});

const { emptyOption } = useComboboxEmptyOption();

const handleOnChange = (value: HandleOnChangeValue) => {
onChange({
target: { value: value?.value ?? null, name: rest.name ?? "" },
Expand All @@ -73,7 +78,13 @@ const ComboboxRoot = ({
return (
<DynamicCombobox
value={selectedValue}
options={[...customValueOption, ...options] as Option[]}
options={
[
...(allowEmptyValue ? [emptyOption] : []),
...customValueOption,
...options,
] as Option[]
}
onChange={handleOnChange}
onScrollEnd={handleFetchMore}
onInputValueChange={value => {
Expand Down
19 changes: 19 additions & 0 deletions src/components/Combobox/hooks/useComboboxEmptyOption.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Option } from "@saleor/macaw-ui-next";
import { useIntl } from "react-intl";

export const useComboboxEmptyOption = () => {
const intl = useIntl();

const emptyOption: Option = {
label: intl.formatMessage({
id: "pGfO2i",
defaultMessage: "None",
description: "empty option",
}),
value: "",
};

return {
emptyOption,
};
};
95 changes: 40 additions & 55 deletions src/components/Datagrid/customCells/DropdownCell.tsx
Original file line number Diff line number Diff line change
@@ -1,96 +1,81 @@
// @ts-strict-ignore
import { Combobox } from "@dashboard/components/Combobox";
import {
CustomCell,
CustomRenderer,
getMiddleCenterBias,
GridCellKind,
ProvideEditorCallback,
} from "@glideapps/glide-data-grid";
import { makeStyles } from "@saleor/macaw-ui";
import { Option } from "@saleor/macaw-ui-next";
import pick from "lodash/pick";
import React from "react";

import SingleAutocompleteSelectField, {
SingleAutocompleteSelectFieldProps,
} from "../../SingleAutocompleteSelectField";
import { Choice } from "../../SingleSelectField";

export type DropdownChoice = Choice<string, string>;
export type DropdownCellContentProps = Pick<
SingleAutocompleteSelectFieldProps,
"allowCustomValues" | "emptyOption"
>;

export type DropdownCellGetSuggestionsFn = (
text: string,
) => Promise<DropdownChoice[]>;
interface DropdownCellProps extends DropdownCellContentProps {
readonly choices?: DropdownChoice[];
export type DropdownCellGetSuggestionsFn = (text: string) => Promise<Option[]>;
export interface DropdownCellProps {
readonly choices?: Option[];
readonly update?: DropdownCellGetSuggestionsFn;
readonly kind: "dropdown-cell";
readonly value: DropdownChoice | null;
readonly value: Option | null;
readonly allowCustomValues?: boolean;
readonly emptyOption?: boolean;
}

export type DropdownCell = CustomCell<DropdownCellProps>;

export const emptyDropdownCellValue: DropdownChoice = {
export const emptyDropdownCellValue: Option = {
label: "",
value: null,
value: "",
};

const useStyles = makeStyles(
{
root: {
"& > div": {
padding: 0,
},
"& input": {
height: "unset",
},
},
},
{ name: "DropdownCell" },
);

const DropdownCellEdit: ReturnType<ProvideEditorCallback<DropdownCell>> = ({
value: cell,
onFinishedEditing,
}) => {
const [data, setData] = React.useState<DropdownChoice[]>([]);
const [data, setData] = React.useState<Option[]>([]);

const getChoices = React.useCallback(
async (text: string) => {
setData(await cell.data.update(text));
setData((await cell.data?.update?.(text)) ?? []);
},
[cell.data],
);
const classes = useStyles();

const userProps = pick(cell.data, ["allowCustomValues", "emptyOption"]);
const props = cell.data.update
? { fetchOnFocus: true, fetchChoices: getChoices, choices: data }
: { choices: cell.data.choices };
: {
fetchOnFocus: false,
fetchChoices: () => Promise.resolve([]),
choices: cell.data.choices,
};

return (
<SingleAutocompleteSelectField
{...userProps}
{...props}
className={classes.root}
nakedInput
onChange={event =>
onFinishedEditing({
<Combobox
allowCustomValues={userProps.allowCustomValues}
alwaysFetchOnFocus={props.fetchOnFocus}
allowEmptyValue={userProps.emptyOption}
fetchMore={{
hasMore: false,
loading: false,
onFetchMore: () => undefined,
}}
options={props.choices ?? []}
value={cell.data.value}
fetchOptions={props.fetchChoices}
loading={false}
name=""
onChange={event => {
return onFinishedEditing({
...cell,
data: {
...cell.data,
value: props.choices.find(c => c.value === event.target.value) ?? {
label: event.target.value,
value: event.target.value,
value: props.choices?.find(c => c.value === event.target.value) ?? {
label: event.target.value ?? "",
value: event.target.value ?? "",
},
},
})
}
name=""
displayValue={cell.data.value.label}
value={cell.data.value.value}
});
}}
/>
);
};
Expand All @@ -104,7 +89,7 @@ export const dropdownCellRenderer: CustomRenderer<DropdownCell> = {

ctx.fillStyle = theme.textDark;
ctx.fillText(
value.label,
value?.label ?? "",
rect.x + 8,
rect.y + rect.height / 2 + getMiddleCenterBias(ctx, theme),
);
Expand Down
16 changes: 5 additions & 11 deletions src/components/Datagrid/customCells/cells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ import {
GridCellKind,
TextCell,
} from "@glideapps/glide-data-grid";
import { Option } from "@saleor/macaw-ui-next";

import {
DropdownCell,
DropdownCellContentProps,
DropdownChoice,
} from "./DropdownCell";
import { DropdownCell, DropdownCellProps } from "./DropdownCell";
import { MoneyCell, MoneyDiscuntedCell } from "./Money";
import {
hueToPillColorLight,
Expand Down Expand Up @@ -186,12 +183,9 @@ export function moneyDiscountedCell(
}

export function dropdownCell(
value: DropdownChoice,
dataOpts: DropdownCellContentProps &
(
| { choices: DropdownChoice[] }
| { update: (text: string) => Promise<DropdownChoice[]> }
),
value: Option,
dataOpts: Pick<DropdownCellProps, "allowCustomValues" | "emptyOption"> &
({ choices: Option[] } | { update: (text: string) => Promise<Option[]> }),
opts?: Partial<GridCell>,
): DropdownCell {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ jest.mock("@saleor/macaw-ui", () => ({
jest.mock("@saleor/macaw-ui-next", () => ({
useTheme: jest.fn(() => () => ({})),
Divider: jest.fn(() => <></>),
DynamicCombobox: jest.fn(() => <></>),
DynamicMultiselect: jest.fn(() => <></>),
vars: {
colors: {
border: {
Expand Down

0 comments on commit 3c714ae

Please sign in to comment.