Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,591 changes: 184 additions & 2,407 deletions vuu-ui/package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,23 @@ export const getDataItemEditControl = ({
if (dataDescriptor.editable === false) {
return (
<VuuInput
data-edit-control="data-edit-control"
variant="secondary"
{...InputProps}
onCommit={onCommit}
readOnly
data-edit-control
/>
);
} else if (isTimeDataValue(dataDescriptor)) {
if (InputProps?.inputProps) {
const { value, onChange } = InputProps.inputProps;
return (
<VuuTimePicker
data-edit-control="data-edit-control"
className={className}
value={asTimeString(value, true)}
onChange={onChange}
onCommit={onCommit}
data-edit-control
/>
);
}
Expand All @@ -78,7 +78,7 @@ export const getDataItemEditControl = ({
<VuuDatePicker
className={className}
onCommit={handleCommitNumber}
data-edit-control="data-edit-control"
data-edit-control
/>
);
} else if (dataDescriptor.serverDataType === "string" && table) {
Expand All @@ -90,7 +90,7 @@ export const getDataItemEditControl = ({
column={dataDescriptor.name}
onCommit={onCommit}
table={table}
data-edit-control="data-edit-control"
data-edit-control
/>
);
}
Expand All @@ -102,7 +102,7 @@ export const getDataItemEditControl = ({
commitWhenCleared={commitWhenCleared}
onCommit={onCommit}
errorMessage={errorMessage}
data-edit-control="data-edit-control"
data-edit-control
/>
);
};
19 changes: 18 additions & 1 deletion vuu-ui/packages/vuu-filter-types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,21 @@ export declare type FilterState = {

export declare type FilterChangeHandler = (filter: Filter | undefined) => void;

export declare type FilterValue = string | number | readonly string[];
export declare type ColumnFilterValue =
| string
| number
| [string, string];

export declare type ColumnFilterOp = FilterClauseOp | "between";

export declare type ColumnFilterDescriptor = {
column: ColumnDescriptor;
op: ColumnFilterOp;
filterValue: ColumnFilterValue;
};

export declare type ColumnFilterChangeHandler = (
value: ColumnFilterValue,
column: ColumnDescriptor,
op: ColumnFilterOp,
) => void;
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ describe("ColumnFilter", () => {
cy.get("@inputs").eq(1).should("have.value", "200");
});

it("should trigger onFilterChange with correct parameters when input changes", () => {
const onFilterChange = cy.stub().as("onFilterChange");
it("should trigger handleColumnFilterChange with correct parameters when input changes", () => {
const handleColumnFilterChange = cy.stub().as("handleColumnFilterChange");
cy.mount(
<LocalDataSourceProvider>
<NumericColumnFilterValueWithBetweenOp
onFilterChange={onFilterChange}
onColumnFilterChange={handleColumnFilterChange}
/>
</LocalDataSourceProvider>,
);
Expand All @@ -82,7 +82,7 @@ describe("ColumnFilter", () => {
cy.get("@inputs").eq(0).clear().type("123");
cy.get("@inputs").eq(1).clear().type("456");

cy.get("@onFilterChange").should(
cy.get("@handleColumnFilterChange").should(
"have.been.calledWith",
["35", "45.3"],
{ name: "price", serverDataType: "double" },
Expand All @@ -91,13 +91,13 @@ describe("ColumnFilter", () => {
});
});

describe("WHEN onFilterChange event for range edit controls are triggerd", () => {
it("should trigger onFilterChange with correct parameters when numeric range input changes", () => {
const onFilterChange = cy.stub().as("onFilterChange");
describe("WHEN handleColumnFilterChange event for range edit controls are triggerd", () => {
it("should trigger handleColumnFilterChange with correct parameters when numeric range input changes", () => {
const handleColumnFilterChange = cy.stub().as("handleColumnFilterChange");
cy.mount(
<LocalDataSourceProvider>
<NumericColumnFilterValueWithBetweenOp
onFilterChange={onFilterChange}
onColumnFilterChange={handleColumnFilterChange}
/>
</LocalDataSourceProvider>,
);
Expand All @@ -106,17 +106,21 @@ describe("ColumnFilter", () => {
cy.get("@inputs").eq(0).clear().type("123");
cy.get("@inputs").eq(1).clear().type("456");

cy.get("@onFilterChange").should(
cy.get("@handleColumnFilterChange").should(
"have.been.calledWith",
["35", "45.3"],
{ name: "price", serverDataType: "double" },
"between",
);
});

it("should trigger onFilterChange with correct parameters when time range input changes", () => {
const onFilterChange = cy.stub().as("onFilterChange");
cy.mount(<TimeColumnRangeFilter onFilterChange={onFilterChange} />);
it("should trigger handleColumnFilterChange with correct parameters when time range input changes", () => {
const handleColumnFilterChange = cy.stub().as("handleColumnFilterChange");
cy.mount(
<TimeColumnRangeFilter
onColumnFilterChange={handleColumnFilterChange}
/>,
);

cy.findByTestId("columnfilter").find("input").as("inputs");

Expand All @@ -129,7 +133,7 @@ describe("ColumnFilter", () => {
.realPress("Tab")
.realPress("ArrowUp");

cy.get("@onFilterChange").should(
cy.get("@handleColumnFilterChange").should(
"have.been.calledWith",
["01:00:00", "00:01:02"],
{ name: "lastUpdate", serverDataType: "long", type: "time" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface ColumnFilterProps
extends SegmentedButtonGroupProps,
Pick<
ColumnFilterHookProps,
"column" | "operator" | "value" | "onFilterChange"
"column" | "operator" | "value" | "onColumnFilterChange"
> {
/**
* Display operator picker.
Expand All @@ -48,7 +48,7 @@ export const ColumnFilter = forwardRef(function ColumnFilter(
showOperatorPicker = false,
table,
value,
onFilterChange,
onColumnFilterChange,
...buttonGroupProps
}: ColumnFilterProps,
forwardRef: ForwardedRef<HTMLDivElement>,
Expand All @@ -73,7 +73,7 @@ export const ColumnFilter = forwardRef(function ColumnFilter(
operator,
column,
value,
onFilterChange,
onColumnFilterChange,
});

useMemo(
Expand Down
69 changes: 36 additions & 33 deletions vuu-ui/packages/vuu-filters/src/column-filter/useColumnFilter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { FilterClauseOp, FilterValue } from "@vuu-ui/vuu-filter-types";
import {
ColumnFilterChangeHandler,
ColumnFilterOp,
ColumnFilterValue,
FilterClauseOp,
} from "@vuu-ui/vuu-filter-types";
import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
import {
ChangeEventHandler,
Expand All @@ -11,14 +16,15 @@ import { CommitHandler, queryClosest } from "@vuu-ui/vuu-utils";
import { VuuTypeaheadInputProps } from "@vuu-ui/vuu-ui-controls";
import { getOperators } from "../filter-clause/operator-utils";

export type Operator = FilterClauseOp | "between";

export const assertValidOperator = (
allowedOperators: FilterClauseOp[],
column: ColumnDescriptor,
op: Operator,
op: ColumnFilterOp,
) => {
if (!allowedOperators.find((filterClauseOp) => filterClauseOp === op)) {
if (
!allowedOperators.find((filterClauseOp) => filterClauseOp === op) &&
!(op === "between")
) {
console.warn(
`[useColumnFilter] '${op} not supported for column ${column.name}'`,
);
Expand All @@ -27,8 +33,8 @@ export const assertValidOperator = (

export const assertValidValue = (
{ serverDataType: _ }: ColumnDescriptor,
operator: Operator,
value?: FilterValue,
operator: ColumnFilterOp,
value?: ColumnFilterValue,
) => {
if (value !== undefined) {
if (operator === "between") {
Expand All @@ -52,29 +58,26 @@ export const assertValidValue = (

export type ColumnFilterHookProps = {
column: ColumnDescriptor;
operator?: Operator;
operator?: ColumnFilterOp;
/**
* Filter value. Pair of values expected when operator is
* 'between'
*/
value?: FilterValue;
value?: ColumnFilterValue;
/**
* Filter change events.
*/
onFilterChange?: (
value: FilterValue,
column: ColumnDescriptor,
op: Operator,
) => void;
onColumnFilterChange?: ColumnFilterChangeHandler;
};

export const useColumnFilter = ({
operator = "=",
value,
column,
onFilterChange,
onColumnFilterChange,
}: ColumnFilterHookProps) => {
const getDefaultValue = (op: Operator) => (op === "between" ? ["", ""] : "");
const getDefaultValue = (op: ColumnFilterOp): ColumnFilterValue =>
op === "between" ? ["", ""] : "";
const filterValue = useRef(value ?? getDefaultValue(operator));
const [op, setOp] = useState(operator);
const allowedOperators = useMemo(() => getOperators(column), [column]);
Expand All @@ -83,20 +86,20 @@ export const useColumnFilter = ({
if (value && value !== filterValue.current) {
filterValue.current = value;
setTimeout(() => {
onFilterChange?.(value, column, op);
onColumnFilterChange?.(value, column, op);
}, 100);
}
}, [value, column, op, onFilterChange]);
}, [value, column, op, onColumnFilterChange]);

const handleOperatorChange = useCallback((changedOp: Operator) => {
const handleOperatorChange = useCallback((changedOp: ColumnFilterOp) => {
setOp(changedOp);
}, []);

const handleCommit = useCallback<CommitHandler<HTMLElement>>(
(e, newValue) => {
console.log(`[useColumnFilter] handleCommit ${newValue}`);
if (Array.isArray(filterValue.current)) {
filterValue.current = [newValue as FilterValue, filterValue.current[1]];
filterValue.current = [newValue.toString(), filterValue.current[1]];
if (
filterValue.current &&
(filterValue.current[0] === undefined ||
Expand All @@ -107,17 +110,17 @@ export const useColumnFilter = ({
);
}
} else {
filterValue.current = newValue as FilterValue;
filterValue.current = newValue as ColumnFilterValue;
}
onFilterChange?.(filterValue.current, column, op);
onColumnFilterChange?.(filterValue.current, column, op);
},
[op, column, onFilterChange],
[op, column, onColumnFilterChange],
);

const handleRangeCommit = useCallback<CommitHandler<HTMLElement>>(
(e, newValue) => {
if (Array.isArray(filterValue.current)) {
filterValue.current = [filterValue.current[0], newValue as FilterValue];
filterValue.current = [filterValue.current[0], newValue.toString()];
if (
filterValue.current &&
(filterValue.current[0] === undefined ||
Expand All @@ -128,33 +131,33 @@ export const useColumnFilter = ({
);
}
} else {
filterValue.current = newValue as FilterValue;
filterValue.current = newValue as ColumnFilterValue;
}
onFilterChange?.(filterValue.current, column, op);
onColumnFilterChange?.(filterValue.current, column, op);
},
[op, column, onFilterChange],
[op, column, onColumnFilterChange],
);

const handleInputChange = useCallback<ChangeEventHandler<HTMLInputElement>>(
(e) => {
if (Array.isArray(filterValue.current)) {
const editControl = queryClosest(e.target, "[data-edit-control]", true);
const updated: FilterValue = [
!editControl?.className?.includes("rangeHigh")
const updated: ColumnFilterValue = [
!editControl.className?.includes("rangeHigh")
? e.target.value
: filterValue.current[0],
editControl?.className?.includes("rangeHigh")
editControl.className?.includes("rangeHigh")
? e.target.value
: filterValue.current[1],
];
filterValue.current = updated;
onFilterChange?.(updated, column, op);
onColumnFilterChange?.(updated, column, op);
} else {
filterValue.current = e.target.value;
onFilterChange?.(e.target.value, column, op);
onColumnFilterChange?.(e.target.value, column, op);
}
},
[op, column, onFilterChange],
[op, column, onColumnFilterChange],
);

const inputProps = useMemo<VuuTypeaheadInputProps["inputProps"]>(
Expand Down
6 changes: 5 additions & 1 deletion vuu-ui/packages/vuu-utils/src/column-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,12 @@ export const isTextColumn = ({ serverDataType }: ColumnDescriptor) =>
? false
: serverDataType === "char" || serverDataType === "string";

export const toColumnDescriptor = (name: string): ColumnDescriptor => ({
export const toColumnDescriptor = (
name: string,
serverDataType?: ColumnDescriptor["serverDataType"],
): ColumnDescriptor => ({
name,
serverDataType,
});

/**
Expand Down
Loading
Loading