This commit is contained in:
Stefan Pejcic
2024-11-07 19:03:37 +01:00
parent c6df945ed5
commit 09f9f9502d
2472 changed files with 620417 additions and 0 deletions

View File

@@ -0,0 +1,440 @@
import type { GridFilterModel, GridSortModel } from "@mui/x-data-grid";
import { GridLogicOperator } from "@mui/x-data-grid";
import type { CrudFilters, CrudSorting } from "@refinedev/core";
import {
transformCrudFiltersToFilterModel,
transformCrudOperatorToMuiOperator,
transformCrudSortingToSortModel,
transformFilterModelToCrudFilters,
transformMuiOperatorToCrudOperator,
transformSortModelToCrudSorting,
} from ".";
describe("transformSortModelToCrudSorting", () => {
it("Map grid sort model to crud sorting", () => {
const gridSorter: GridSortModel = [
{ field: "title", sort: "asc" },
{ field: "view", sort: "desc" },
];
const crudSorter: CrudSorting = [
{ field: "title", order: "asc" },
{ field: "view", order: "desc" },
];
expect(transformSortModelToCrudSorting(gridSorter)).toEqual(crudSorter);
});
it("if sort direction is 'undefined', then use 'asc'", () => {
const gridSorter: GridSortModel = [{ field: "title", sort: undefined }];
const crudSorter: CrudSorting = [{ field: "title", order: "asc" }];
expect(transformSortModelToCrudSorting(gridSorter)).toEqual(crudSorter);
});
it("if sort direction is 'null', then use 'asc'", () => {
const gridSorter: GridSortModel = [{ field: "title", sort: null }];
const crudSorter: CrudSorting = [{ field: "title", order: "asc" }];
expect(transformSortModelToCrudSorting(gridSorter)).toEqual(crudSorter);
});
});
describe("transformCrudSortingToSortModel", () => {
it("Map crud sorting to grid sort model", () => {
const crudSorter: CrudSorting = [
{ field: "title", order: "asc" },
{ field: "view", order: "desc" },
];
const gridSorter: GridSortModel = [
{ field: "title", sort: "asc" },
{ field: "view", sort: "desc" },
];
expect(transformCrudSortingToSortModel(crudSorter)).toEqual(gridSorter);
});
});
describe("transformFilterModelToCrudFilters", () => {
it("Map filter model to crud filters with 'or' operator", () => {
const filterModel: GridFilterModel = {
items: [
{
id: 1,
field: "rating",
operator: ">",
value: 4,
},
{
id: 2,
field: "isAdmin",
operator: "is",
value: true,
},
],
logicOperator: GridLogicOperator.Or,
};
const crudFilters: CrudFilters = [
{
operator: "or",
value: [
{
field: "rating",
operator: "gt",
value: 4,
},
{
field: "isAdmin",
operator: "eq",
value: true,
},
],
},
];
expect(transformFilterModelToCrudFilters(filterModel)).toEqual(crudFilters);
});
it("Map filter model to crud filters with 'and' operator", () => {
const filterModel: GridFilterModel = {
items: [
{
id: 1,
field: "rating",
operator: ">",
value: 4,
},
{
id: 2,
field: "isAdmin",
operator: "is",
value: true,
},
],
logicOperator: GridLogicOperator.And,
};
const crudFilters: CrudFilters = [
{
field: "rating",
operator: "gt",
value: 4,
},
{
field: "isAdmin",
operator: "eq",
value: true,
},
];
expect(transformFilterModelToCrudFilters(filterModel)).toEqual(crudFilters);
});
it("Map filter model to crud filters with undefined operator", () => {
const filterModel: GridFilterModel = {
items: [
{
id: 1,
field: "rating",
operator: ">",
value: 4,
},
{
id: 2,
field: "isAdmin",
operator: "is",
value: true,
},
],
};
const crudFilters: CrudFilters = [
{
field: "rating",
operator: "gt",
value: 4,
},
{
field: "isAdmin",
operator: "eq",
value: true,
},
];
expect(transformFilterModelToCrudFilters(filterModel)).toEqual(crudFilters);
});
});
describe("transformMuiOperatorToCrudOperators", () => {
it("transform mui operator to crud operator", () => {
expect(transformMuiOperatorToCrudOperator("equals")).toEqual("eq");
expect(transformMuiOperatorToCrudOperator("is")).toEqual("eq");
expect(transformMuiOperatorToCrudOperator("=")).toEqual("eq");
expect(transformMuiOperatorToCrudOperator("!=")).toEqual("ne");
expect(transformMuiOperatorToCrudOperator("not")).toEqual("ne");
expect(transformMuiOperatorToCrudOperator("isAnyOf")).toEqual("in");
expect(transformMuiOperatorToCrudOperator("<")).toEqual("lt");
expect(transformMuiOperatorToCrudOperator("before")).toEqual("lt");
expect(transformMuiOperatorToCrudOperator("<=")).toEqual("lte");
expect(transformMuiOperatorToCrudOperator("onOrBefore")).toEqual("lte");
expect(transformMuiOperatorToCrudOperator(">")).toEqual("gt");
expect(transformMuiOperatorToCrudOperator("after")).toEqual("gt");
expect(transformMuiOperatorToCrudOperator(">=")).toEqual("gte");
expect(transformMuiOperatorToCrudOperator("onOrAfter")).toEqual("gte");
expect(transformMuiOperatorToCrudOperator("startsWith")).toEqual(
"startswith",
);
expect(transformMuiOperatorToCrudOperator("endsWith")).toEqual("endswith");
expect(transformMuiOperatorToCrudOperator("isEmpty")).toEqual("null");
expect(transformMuiOperatorToCrudOperator("isNotEmpty")).toEqual("nnull");
expect(transformMuiOperatorToCrudOperator("contains")).toEqual("contains");
expect(transformMuiOperatorToCrudOperator("something")).toEqual(
"something",
);
});
});
describe("transformCrudOperatorToMuiOperator", () => {
it("transform crud operator to mui operator with 'number' value", () => {
expect(transformCrudOperatorToMuiOperator("eq", "number")).toEqual("=");
expect(transformCrudOperatorToMuiOperator("ne", "number")).toEqual("!=");
expect(transformCrudOperatorToMuiOperator("gt", "number")).toEqual(">");
expect(transformCrudOperatorToMuiOperator("gte", "number")).toEqual(">=");
expect(transformCrudOperatorToMuiOperator("lt", "number")).toEqual("<");
expect(transformCrudOperatorToMuiOperator("lte", "number")).toEqual("<=");
expect(transformCrudOperatorToMuiOperator("null", "number")).toEqual(
"isEmpty",
);
expect(transformCrudOperatorToMuiOperator("nnull", "number")).toEqual(
"isNotEmpty",
);
expect(transformCrudOperatorToMuiOperator("in", "number")).toEqual(
"isAnyOf",
);
});
it("transform crud operator to mui operator with 'boolean' value", () => {
expect(transformCrudOperatorToMuiOperator("eq", "boolean")).toEqual("is");
expect(transformCrudOperatorToMuiOperator("eq", "boolean")).toEqual("is");
});
it("transform crud operator to mui operator with 'string' value", () => {
expect(transformCrudOperatorToMuiOperator("contains", "string")).toEqual(
"contains",
);
expect(transformCrudOperatorToMuiOperator("eq", "string")).toEqual(
"equals",
);
expect(transformCrudOperatorToMuiOperator("null", "string")).toEqual(
"isEmpty",
);
expect(transformCrudOperatorToMuiOperator("nnull", "string")).toEqual(
"isNotEmpty",
);
expect(transformCrudOperatorToMuiOperator("startswith", "string")).toEqual(
"startsWith",
);
expect(transformCrudOperatorToMuiOperator("endswith", "string")).toEqual(
"endsWith",
);
expect(transformCrudOperatorToMuiOperator("in", "string")).toEqual(
"isAnyOf",
);
});
it("transform crud operator to mui operator with 'date' and 'dateTime' value", () => {
expect(transformCrudOperatorToMuiOperator("eq", "date")).toEqual("is");
expect(transformCrudOperatorToMuiOperator("ne", "date")).toEqual("not");
expect(transformCrudOperatorToMuiOperator("gt", "date")).toEqual("after");
expect(transformCrudOperatorToMuiOperator("gte", "dateTime")).toEqual(
"onOrAfter",
);
expect(transformCrudOperatorToMuiOperator("lt", "dateTime")).toEqual(
"before",
);
expect(transformCrudOperatorToMuiOperator("lte", "dateTime")).toEqual(
"onOrBefore",
);
});
it("transform crud operator to mui operator with undefined value", () => {
expect(transformCrudOperatorToMuiOperator("null", undefined)).toEqual(
"isEmpty",
);
expect(transformCrudOperatorToMuiOperator("nnull", undefined)).toEqual(
"isNotEmpty",
);
});
});
describe("transformCrudFiltersToFilterModel", () => {
it("Map crud filters to filter model with 'or' operator", () => {
const crudFilters: CrudFilters = [
{
operator: "or",
value: [
{
field: "rating",
operator: "gt",
value: 4,
},
{
field: "isAdmin",
operator: "eq",
value: true,
},
],
},
];
const columnsLookup = {
rating: "number",
isAdmin: "boolean",
};
const filterModel: GridFilterModel = {
items: [
{
field: "rating",
operator: ">",
value: 4,
id: "ratinggt",
},
{
field: "isAdmin",
operator: "is",
value: true,
id: "isAdmineq",
},
],
logicOperator: GridLogicOperator.Or,
};
expect(
transformCrudFiltersToFilterModel(crudFilters, columnsLookup),
).toEqual(filterModel);
});
it("Map crud filters to filter model with 'and' operator", () => {
const crudFilters: CrudFilters = [
{
field: "rating",
operator: "gt",
value: 4,
},
{
field: "isAdmin",
operator: "eq",
value: true,
},
];
const columnsLookup = {
rating: "number",
isAdmin: "boolean",
};
const filterModel: GridFilterModel = {
items: [
{
field: "rating",
operator: ">",
value: 4,
id: "ratinggt",
},
{
field: "isAdmin",
operator: "is",
value: true,
id: "isAdmineq",
},
],
logicOperator: GridLogicOperator.And,
};
expect(
transformCrudFiltersToFilterModel(crudFilters, columnsLookup),
).toEqual(filterModel);
});
it("Map crud filters to filter model with 'or' and 'and' operator, should prioritize to 'or' filter", () => {
const crudFilters: CrudFilters = [
{
field: "createdAt",
operator: "gt",
value: "2022-04-06T14:29",
},
{
operator: "or",
value: [
{
field: "rating",
operator: "gt",
value: 4,
},
{
field: "isAdmin",
operator: "eq",
value: true,
},
],
},
{
field: "status",
operator: "eq",
value: "draft",
},
];
const columnsLookup = {
rating: "number",
isAdmin: "boolean",
};
const filterModel: GridFilterModel = {
items: [
{
field: "rating",
operator: ">",
value: 4,
id: "ratinggt",
},
{
field: "isAdmin",
operator: "is",
value: true,
id: "isAdmineq",
},
],
logicOperator: GridLogicOperator.Or,
};
expect(
transformCrudFiltersToFilterModel(crudFilters, columnsLookup),
).toEqual(filterModel);
});
it("Map crud filters to filter model with no filters, should return default mui filter mui", () => {
const crudFilters: CrudFilters = [];
const columnsLookup = {};
expect(
transformCrudFiltersToFilterModel(crudFilters, columnsLookup),
).toEqual({
items: [],
logicOperator: "and",
});
});
});

View File

@@ -0,0 +1,229 @@
import type {
GridFilterItem,
GridFilterModel,
GridSortModel,
} from "@mui/x-data-grid";
import { GridLogicOperator } from "@mui/x-data-grid";
import type {
CrudFilters,
CrudOperators,
CrudSorting,
LogicalFilter,
} from "@refinedev/core";
export const transformSortModelToCrudSorting = (
sortModel: GridSortModel,
): CrudSorting => {
const sorter = sortModel.map(({ field, sort }) => ({
field,
order: sort || "asc",
}));
return sorter;
};
export const transformCrudSortingToSortModel = (
crudSorting: CrudSorting,
): GridSortModel => {
const sortModel = crudSorting.map(({ field, order }) => ({
field,
sort: order,
}));
return sortModel;
};
export const transformMuiOperatorToCrudOperator = (
operatorValue?: string,
): Exclude<CrudOperators, "or" | "and"> => {
if (!operatorValue) {
return "eq";
}
switch (operatorValue) {
case "equals":
case "is":
case "=":
return "eq";
case "!=":
case "not":
return "ne";
case "contains":
return "contains";
case "isAnyOf":
return "in";
case ">":
case "after":
return "gt";
case ">=":
case "onOrAfter":
return "gte";
case "<":
case "before":
return "lt";
case "<=":
case "onOrBefore":
return "lte";
case "startsWith":
return "startswith";
case "endsWith":
return "endswith";
case "isEmpty":
return "null";
case "isNotEmpty":
return "nnull";
default:
return operatorValue as Exclude<CrudOperators, "or" | "and">;
}
};
export const transformFilterModelToCrudFilters = ({
items,
logicOperator,
}: GridFilterModel): CrudFilters => {
const filters = items.map(({ field, value, operator }) => {
const filter: LogicalFilter = {
field: field,
value: ["isEmpty", "isNotEmpty"].includes(operator) ? true : value ?? "",
operator: transformMuiOperatorToCrudOperator(operator),
};
return filter;
});
if (logicOperator === GridLogicOperator.Or) {
return [{ operator: "or", value: filters }];
}
return filters;
};
export const transformCrudOperatorToMuiOperator = (
operator: CrudOperators,
columnType?: string,
): string => {
switch (columnType) {
case "number":
switch (operator) {
case "eq":
return "=";
case "ne":
return "!=";
case "gt":
return ">";
case "gte":
return ">=";
case "lt":
return "<";
case "lte":
return "<=";
case "null":
return "isEmpty";
case "nnull":
return "isNotEmpty";
case "in":
return "isAnyOf";
default:
return operator;
}
case "singleSelect":
case "boolean":
switch (operator) {
case "eq":
return "is";
default:
return operator;
}
case undefined:
case "string":
switch (operator) {
case "eq":
return "equals";
case "contains":
return "contains";
case "null":
return "isEmpty";
case "nnull":
return "isNotEmpty";
case "startswith":
return "startsWith";
case "endswith":
return "endsWith";
case "in":
return "isAnyOf";
default:
return operator;
}
case "date":
case "dateTime":
switch (operator) {
case "eq":
return "is";
case "ne":
return "not";
case "gt":
return "after";
case "gte":
return "onOrAfter";
case "lt":
return "before";
case "lte":
return "onOrBefore";
case "null":
return "isEmpty";
case "nnull":
return "isNotEmpty";
default:
return operator;
}
default:
return operator;
}
};
export const transformCrudFiltersToFilterModel = (
crudFilters: CrudFilters,
columnsType?: Record<string, string>,
): GridFilterModel | undefined => {
const gridFilterItems: GridFilterItem[] = [];
const isExistOrFilter = crudFilters.some(
(filter) => filter.operator === "or",
);
if (columnsType) {
if (isExistOrFilter) {
const orLogicalFilters = crudFilters.find(
(filter) => filter.operator === "or",
)?.value as LogicalFilter[];
orLogicalFilters.map(({ field, value, operator }) => {
const columnType = columnsType[field];
gridFilterItems.push({
field: field,
operator: transformCrudOperatorToMuiOperator(operator, columnType),
value: value === "" ? undefined : value,
id: field + operator,
});
});
} else {
(crudFilters as LogicalFilter[]).map(({ field, value, operator }) => {
const columnType = columnsType[field];
gridFilterItems.push({
field: field,
operator: transformCrudOperatorToMuiOperator(operator, columnType),
value: value === "" ? undefined : value,
id: field + operator,
});
});
}
}
return {
items: gridFilterItems,
// If there is "or" filter, default link operator is "or"
logicOperator: isExistOrFilter
? GridLogicOperator.Or
: GridLogicOperator.And,
};
};

View File

@@ -0,0 +1 @@
export * from "./dataGrid";