mig-schema-table 3.0.63 → 3.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { oas31 } from "openapi3-ts";
2
2
  import React, { CSSProperties, Dispatch, SetStateAction } from "react";
3
3
  import { IColumnConfig } from "../../types";
4
- import { ISchemaColumnFilterPopoverConfig } from "../SchemaColumnFilterPopover";
4
+ import { ISchemaTableThMenuConfig } from "../SchemaTableThMenu";
5
5
  export declare enum EColumnFilterStatus {
6
6
  UNAVAILABLE = "UNAVAILABLE",
7
7
  AVAILABLE = "AVAILABLE",
@@ -9,7 +9,6 @@ export declare enum EColumnFilterStatus {
9
9
  }
10
10
  interface IThProps {
11
11
  columnFilterStatus: EColumnFilterStatus;
12
- disableColumnFilter: (propName: string) => void;
13
12
  isAllChecked?: boolean;
14
13
  isSortable: boolean;
15
14
  numberOfSelectedRows?: number;
@@ -18,11 +17,11 @@ interface IThProps {
18
17
  propIsRequired: boolean;
19
18
  propName: string;
20
19
  schema?: oas31.SchemaObject;
21
- setPopoverConfig?: Dispatch<SetStateAction<ISchemaColumnFilterPopoverConfig | undefined>>;
20
+ setMenuConfig: Dispatch<SetStateAction<ISchemaTableThMenuConfig | undefined>>;
22
21
  setSortAsc: Dispatch<SetStateAction<boolean>>;
23
22
  setSortColumn: Dispatch<SetStateAction<string>>;
24
23
  sortAsc?: boolean;
25
24
  style: CSSProperties;
26
25
  }
27
- declare const _default: ({ columnFilterStatus, disableColumnFilter, isAllChecked, isSortable, numberOfSelectedRows, onSelectAllIndexesHandler, propConfig, propIsRequired, propName, schema, setPopoverConfig, setSortAsc, setSortColumn, sortAsc, style, }: IThProps) => import("react/jsx-runtime").JSX.Element;
26
+ declare const _default: ({ columnFilterStatus, isAllChecked, isSortable, numberOfSelectedRows, onSelectAllIndexesHandler, propConfig, propIsRequired, propName, schema, setMenuConfig, setSortAsc, setSortColumn, sortAsc, style, }: IThProps) => import("react/jsx-runtime").JSX.Element;
28
27
  export default _default;
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import { t, uncamel } from "../../inc/string";
4
+ import { SELECT_ALL_COLUMN_NAME } from "../constants";
5
+ import { timeZone } from "../../inc/date";
6
+ export var EColumnFilterStatus;
7
+ (function (EColumnFilterStatus) {
8
+ EColumnFilterStatus["UNAVAILABLE"] = "UNAVAILABLE";
9
+ EColumnFilterStatus["AVAILABLE"] = "AVAILABLE";
10
+ EColumnFilterStatus["ACTIVE"] = "ACTIVE";
11
+ })(EColumnFilterStatus || (EColumnFilterStatus = {}));
12
+ const SchemaTableTh = ({ columnFilterStatus, isAllChecked, isSortable, numberOfSelectedRows, onSelectAllIndexesHandler, propConfig, propIsRequired, propName, schema, setMenuConfig, setSortAsc, setSortColumn, sortAsc, style, }) => {
13
+ const classNames = [
14
+ `schema-table-th`,
15
+ `schema-table-th--filter-${columnFilterStatus}`,
16
+ ];
17
+ classNames.push(isSortable ? "schema-table-th--sortable" : "schema-table-th--unsortable");
18
+ if (sortAsc !== undefined) {
19
+ classNames.push("schema-table-th--sorted");
20
+ }
21
+ const onLabelClick = React.useCallback(() => {
22
+ if (sortAsc === undefined) {
23
+ setSortColumn(propName);
24
+ setSortAsc(!(propConfig === null || propConfig === void 0 ? void 0 : propConfig.defaultSortDesc));
25
+ return;
26
+ }
27
+ setSortAsc((sortAsc) => !sortAsc);
28
+ }, [
29
+ propConfig === null || propConfig === void 0 ? void 0 : propConfig.defaultSortDesc,
30
+ propName,
31
+ setSortAsc,
32
+ setSortColumn,
33
+ sortAsc,
34
+ ]);
35
+ const onTriggerClick = React.useCallback((e) => {
36
+ const referenceElement = e.currentTarget;
37
+ setMenuConfig((menuConfig) => {
38
+ if ((menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.propName) === propName) {
39
+ return undefined;
40
+ }
41
+ return {
42
+ propConfig,
43
+ propIsRequired,
44
+ propName,
45
+ referenceElement,
46
+ };
47
+ });
48
+ }, [propConfig, propIsRequired, propName, setMenuConfig]);
49
+ const labelBody = React.useMemo(() => {
50
+ if ((propConfig === null || propConfig === void 0 ? void 0 : propConfig.title) !== undefined) {
51
+ return propConfig.title;
52
+ }
53
+ if ((schema === null || schema === void 0 ? void 0 : schema.format) &&
54
+ schema.format.startsWith("date") &&
55
+ (propConfig === null || propConfig === void 0 ? void 0 : propConfig.showTimezones) !== false) {
56
+ return `${uncamel(propName)} (${t(timeZone)})`;
57
+ }
58
+ return uncamel(propName);
59
+ }, [propConfig, propName, schema === null || schema === void 0 ? void 0 : schema.format]);
60
+ if (propName === SELECT_ALL_COLUMN_NAME) {
61
+ return (_jsx("div", Object.assign({ style: style, className: classNames.join(" ") }, { children: _jsx("div", Object.assign({ style: {
62
+ width: "100%",
63
+ textAlign: "center",
64
+ }, title: `${numberOfSelectedRows || 0} selected` }, { children: _jsx("input", { type: "checkbox", checked: isAllChecked, onChange: onSelectAllIndexesHandler }) })) })));
65
+ }
66
+ if (!schema && !(propConfig === null || propConfig === void 0 ? void 0 : propConfig.renderData) && !(propConfig === null || propConfig === void 0 ? void 0 : propConfig.renderCell)) {
67
+ return _jsx("div", { style: style, className: classNames.join(" ") });
68
+ }
69
+ switch (schema === null || schema === void 0 ? void 0 : schema.type) {
70
+ case "boolean":
71
+ classNames.push(`text-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "center"}`, `justify-content-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "center"}`);
72
+ break;
73
+ case "integer":
74
+ case "number":
75
+ classNames.push(`text-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "end"}`, `justify-content-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "end"}`);
76
+ break;
77
+ default:
78
+ if (propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) {
79
+ classNames.push(`text-${propConfig.align}`);
80
+ }
81
+ }
82
+ return (_jsxs("div", Object.assign({ style: style, className: classNames.join(" ") }, { children: [_jsxs("div", Object.assign({ className: "schema-table-th__label-body", style: { lineHeight: "44px" }, onClick: onLabelClick }, { children: [_jsx("span", Object.assign({ className: "schema-table-th__label-body-text" }, { children: labelBody })), sortAsc === undefined ? null : (_jsx("span", Object.assign({ className: "schema-table-th__sort-icon" }, { children: sortAsc ? "↓" : "↑" })))] })), _jsx("button", Object.assign({ className: "schema-table-th__trigger-el", onClick: onTriggerClick }, { children: "\u2304" }))] })));
83
+ };
84
+ export default React.memo(SchemaTableTh);
@@ -2,14 +2,14 @@ import React from "react";
2
2
  import { oas31 } from "openapi3-ts";
3
3
  import { TColumnFilterValue } from "../../index";
4
4
  import { IColumnConfig } from "../../../types";
5
- export interface IFilterFormComponentProps {
5
+ export interface IFilterMenuComponentProps {
6
6
  columnFilterValue: TColumnFilterValue;
7
- onChange: (newValue?: TColumnFilterValue) => void;
7
+ onChange: (newValue: TColumnFilterValue | undefined, persistState: boolean) => void;
8
8
  onInputKeyDown: (e: React.KeyboardEvent) => void;
9
9
  propConfig?: IColumnConfig<any>;
10
10
  propIsRequired: boolean;
11
11
  propName: string;
12
12
  propSchema?: oas31.SchemaObject;
13
13
  }
14
- declare const _default: React.MemoExoticComponent<({ columnFilterValue, onChange, onInputKeyDown, propConfig, propIsRequired, propName, propSchema, }: IFilterFormComponentProps) => import("react/jsx-runtime").JSX.Element>;
14
+ declare const _default: React.MemoExoticComponent<({ columnFilterValue, onChange, onInputKeyDown, propConfig, propIsRequired, propName, propSchema, }: IFilterMenuComponentProps) => import("react/jsx-runtime").JSX.Element>;
15
15
  export default _default;
@@ -0,0 +1,107 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import React from "react";
14
+ import { t } from "../../../inc/string";
15
+ import { DEFAULT_DATE_FORMAT, DEFAULT_DATE_TIME_FORMAT, } from "../../../inc/constant";
16
+ import DatePicker from "react-datepicker";
17
+ import nl from "date-fns/locale/nl";
18
+ import { endOfDay } from "date-fns";
19
+ const FilterMenuComponent = ({ columnFilterValue, onChange, onInputKeyDown, propConfig, propIsRequired, propName, propSchema, }) => {
20
+ const { type, format, minimum, maximum } = propSchema || {};
21
+ const value = columnFilterValue;
22
+ switch (type) {
23
+ case "integer":
24
+ return (_jsx("ol", Object.assign({ className: "schema-table-menu schema-table-th-menu__filter-menu-component" }, { children: _jsx("li", { children: _jsx("input", { autoFocus: true, className: "form-control", type: "number", value: (value || ""), "data-prop-name": propName, onChange: (e) => {
25
+ onChange(e.currentTarget.value === ""
26
+ ? undefined
27
+ : parseInt(e.currentTarget.value), false);
28
+ }, onBlur: (e) => {
29
+ onChange(e.currentTarget.value === ""
30
+ ? undefined
31
+ : parseInt(e.currentTarget.value), true);
32
+ }, onKeyDown: onInputKeyDown, placeholder: `Search ${propName}`, min: minimum, max: maximum }) }) })));
33
+ case "boolean":
34
+ let selectValue = value ? "✓" : "✕";
35
+ if (value === undefined) {
36
+ selectValue = "";
37
+ }
38
+ return (_jsx("ol", Object.assign({ className: "schema-table-menu schema-table-th-menu__filter-menu-component" }, { children: _jsx("li", { children: _jsxs("select", Object.assign({ autoFocus: true, className: "form-select", value: selectValue, "data-prop-name": propName, onChange: (e) => {
39
+ switch (e.currentTarget.value) {
40
+ case "✓":
41
+ onChange(true, true);
42
+ break;
43
+ case "✕":
44
+ onChange(false, true);
45
+ break;
46
+ default:
47
+ onChange(undefined, true);
48
+ }
49
+ } }, { children: [_jsx("option", Object.assign({ value: "" }, { children: "All" }), "all"), ["✓", "✕"].map((optionValue) => (_jsx("option", Object.assign({ value: optionValue }, { children: optionValue }), `column-filter-select-${optionValue}`)))] })) }) })));
50
+ // @ts-ignore
51
+ case "string":
52
+ if (propSchema === null || propSchema === void 0 ? void 0 : propSchema.enum) {
53
+ return (_jsx("ol", Object.assign({ className: "schema-table-menu schema-table-th-menu__filter-menu-component" }, { children: _jsx("li", { children: _jsxs("select", Object.assign({ autoFocus: true, className: "form-select", value: value, "data-prop-name": propName, onChange: (e) => {
54
+ onChange(e.currentTarget.value || undefined, true);
55
+ } }, { children: [_jsx("option", Object.assign({ value: "" }, { children: "All" }), "all"), propSchema.enum.map((name) => {
56
+ const rowName = !(propConfig === null || propConfig === void 0 ? void 0 : propConfig.translation)
57
+ ? name
58
+ : t(name, propConfig.translation);
59
+ return (_jsx("option", Object.assign({ value: rowName }, { children: rowName }), `column-filter-select-${rowName}`));
60
+ })] })) }) })));
61
+ }
62
+ if (format === "date-time" || format === "date") {
63
+ const dateFormat = format === "date" ? DEFAULT_DATE_FORMAT : DEFAULT_DATE_TIME_FORMAT;
64
+ const dateRangeValue = (columnFilterValue || {
65
+ from: undefined,
66
+ to: undefined,
67
+ filterEmpty: undefined,
68
+ });
69
+ return (_jsxs("ol", Object.assign({ className: "schema-table-menu schema-table-th-menu__filter-menu-component" }, { children: [propIsRequired ? null : (_jsxs("li", Object.assign({ style: { padding: 8 } }, { children: [_jsxs("label", Object.assign({ className: "d-flex" }, { children: [_jsx("input", { type: "checkbox", className: "m-0 me-1", checked: !!dateRangeValue.filterEmpty, onChange: () => {
70
+ const { filterEmpty } = dateRangeValue, newDateRangeValue = __rest(dateRangeValue, ["filterEmpty"]);
71
+ if (!filterEmpty) {
72
+ newDateRangeValue.filterEmpty = true;
73
+ }
74
+ onChange(Object.keys(newDateRangeValue).length
75
+ ? newDateRangeValue
76
+ : undefined, true);
77
+ } }), "Hide empty values"] })), _jsx("hr", {})] }))), _jsxs("li", Object.assign({ style: { padding: 8 } }, { children: [_jsx("label", Object.assign({ style: { width: 120, paddingLeft: 4 } }, { children: "Start date-time" })), _jsx(DatePicker, { dateFormat: dateFormat, "data-prop-name": propName, locale: nl, selected: dateRangeValue.from, onChange: (date) => {
78
+ if (!date && !dateRangeValue.to) {
79
+ onChange(undefined, true);
80
+ return;
81
+ }
82
+ if (dateRangeValue.to && date && date > dateRangeValue.to) {
83
+ return;
84
+ }
85
+ onChange(Object.assign(Object.assign({}, columnFilterValue), { from: date || undefined }), true);
86
+ }, placeholderText: dateFormat, isClearable: true, selectsStart: true, showTimeSelect: format === "date-time", timeIntervals: 15, shouldCloseOnSelect: format === "date" })] })), _jsxs("li", Object.assign({ style: { padding: 8 } }, { children: [_jsx("label", Object.assign({ style: { width: 120, paddingLeft: 4 } }, { children: "End date-time" })), _jsx(DatePicker, { id: "filter-date", dateFormat: dateFormat, "data-prop-name": propName, locale: nl, selectsEnd: true, selected: dateRangeValue.to, onChange: (date) => {
87
+ if (!date && !dateRangeValue.from) {
88
+ onChange(undefined, true);
89
+ return;
90
+ }
91
+ const to = date ? endOfDay(date) : undefined;
92
+ if (dateRangeValue.from && to && to < dateRangeValue.from) {
93
+ return;
94
+ }
95
+ onChange(Object.assign(Object.assign({}, columnFilterValue), { to }), true);
96
+ }, placeholderText: dateFormat, isClearable: true, startDate: dateRangeValue.from, endDate: dateRangeValue.to, showTimeSelect: format === "date-time", timeIntervals: 15, shouldCloseOnSelect: format === "date" })] }))] })));
97
+ }
98
+ // falls through
99
+ default:
100
+ return (_jsx("ol", Object.assign({ className: "schema-table-menu schema-table-th-menu__filter-menu-component" }, { children: _jsx("li", { children: _jsx("input", { autoFocus: true, type: "text", className: "form-control", placeholder: `Search ${propName}`, "aria-label": `Search ${propName}`, value: (value || ""), "data-prop-name": propName, onChange: (e) => {
101
+ onChange(e.currentTarget.value || undefined, false);
102
+ }, onKeyDown: onInputKeyDown, onBlur: (e) => {
103
+ onChange(e.currentTarget.value || undefined, true);
104
+ } }) }) })));
105
+ }
106
+ };
107
+ export default React.memo(FilterMenuComponent);
@@ -0,0 +1,22 @@
1
+ import React, { Dispatch, SetStateAction } from "react";
2
+ import { oas31 } from "openapi3-ts";
3
+ import { TColumnFilterValue } from "../index";
4
+ import { IColumnConfig } from "../../types";
5
+ export interface ISchemaTableThMenuConfig {
6
+ referenceElement: HTMLElement;
7
+ propName: string;
8
+ propConfig?: IColumnConfig<any>;
9
+ propIsRequired: boolean;
10
+ }
11
+ type TSchemaTableThMenuProps = ISchemaTableThMenuConfig & {
12
+ onChange: (newValue: TColumnFilterValue | undefined, persistState: boolean) => void;
13
+ onInputKeyDown: (e: React.KeyboardEvent) => void;
14
+ propIsRequired: boolean;
15
+ propSchema: oas31.SchemaObject;
16
+ setSortColumn: Dispatch<SetStateAction<string>>;
17
+ setSortAsc: Dispatch<SetStateAction<boolean>>;
18
+ value: TColumnFilterValue;
19
+ onClose: (e: MouseEvent | React.MouseEvent) => void;
20
+ };
21
+ declare const _default: React.MemoExoticComponent<({ onChange, onClose, onInputKeyDown, propConfig, propIsRequired, propName, propSchema, referenceElement, setSortAsc, setSortColumn, value, }: TSchemaTableThMenuProps) => import("react/jsx-runtime").JSX.Element>;
22
+ export default _default;
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import FilterMenuComponent from "./FilterMenuComponent";
4
+ import { usePopper } from "react-popper";
5
+ const SchemaTableThMenu = ({ onChange, onClose, onInputKeyDown, propConfig, propIsRequired, propName, propSchema, referenceElement, setSortAsc, setSortColumn, value, }) => {
6
+ const [menu, setMenu] = React.useState(null);
7
+ const [subMenu, setSubMenu] = React.useState(null);
8
+ const [subMenuReferenceElement, setSubMenuReferenceElement] = React.useState(null);
9
+ const menuPopper = usePopper(referenceElement, menu, {
10
+ placement: "bottom-end",
11
+ });
12
+ const subMenuPopper = usePopper(subMenuReferenceElement, subMenu, {
13
+ placement: "right-start",
14
+ });
15
+ React.useEffect(() => {
16
+ const onWindowClick = (e) => {
17
+ if (!menu) {
18
+ return;
19
+ }
20
+ let parent = e.target;
21
+ while (parent && menu) {
22
+ if (parent === menu || parent === subMenu) {
23
+ return;
24
+ }
25
+ parent =
26
+ parent.parentNode === window.document ? null : parent.parentNode;
27
+ }
28
+ onClose(e);
29
+ };
30
+ window.addEventListener("click", onWindowClick, { capture: true });
31
+ return () => {
32
+ window.removeEventListener("click", onWindowClick, { capture: true });
33
+ };
34
+ }, [onClose, menu, subMenu]);
35
+ const FilterMenu = (propConfig === null || propConfig === void 0 ? void 0 : propConfig.FilterMenu) || FilterMenuComponent;
36
+ const onSortAscendingClick = React.useCallback((e) => {
37
+ setSortColumn(propName);
38
+ setSortAsc(true);
39
+ onClose(e);
40
+ }, [onClose, propName, setSortAsc, setSortColumn]);
41
+ const onSortDescendingClick = React.useCallback((e) => {
42
+ setSortColumn(propName);
43
+ setSortAsc(false);
44
+ onClose(e);
45
+ }, [onClose, propName, setSortAsc, setSortColumn]);
46
+ const onFilterCheckboxChange = React.useCallback(() => {
47
+ onChange(undefined, true);
48
+ }, [onChange]);
49
+ return (_jsxs(_Fragment, { children: [_jsx("div", Object.assign({ className: "schema-table-th-menu", ref: setMenu, style: menuPopper.styles.popper }, menuPopper.attributes.popper, { children: _jsxs("ol", Object.assign({ className: "schema-table-menu" }, { children: [_jsxs("li", Object.assign({ onClick: onSortAscendingClick, style: { padding: 8 } }, { children: [_jsx("span", Object.assign({ className: "schema-table-th-menu__icon" }, { children: "\u2193" })), " Sort ascending"] })), _jsxs("li", Object.assign({ onClick: onSortDescendingClick, style: { padding: 8 } }, { children: [_jsx("span", Object.assign({ className: "schema-table-th-menu__icon" }, { children: "\u2191" })), " Sort descending"] })), _jsxs("li", Object.assign({ style: { padding: 8 }, onMouseOver: (e) => {
50
+ setSubMenuReferenceElement(e.currentTarget);
51
+ } }, { children: [_jsx("span", Object.assign({ className: "schema-table-th-menu__icon" }, { children: _jsx("input", { type: "checkbox", id: "schema-table-th-menu__filters", checked: value !== undefined, disabled: value === undefined, onChange: onFilterCheckboxChange }) })), _jsx("label", Object.assign({ htmlFor: "schema-table-th-menu__filters" }, { children: "Filters" })), _jsx("div", Object.assign({ className: "schema-table-th-menu__sub-menu-indicator" }, { children: ">" }))] }))] })) })), subMenuReferenceElement ? (_jsx("div", Object.assign({ className: "schema-table-th-menu__sub-menu", ref: setSubMenu, style: subMenuPopper.styles.popper }, subMenuPopper.attributes.popper, { children: _jsx(FilterMenu, { columnFilterValue: value, onChange: onChange, onInputKeyDown: onInputKeyDown, propConfig: propConfig, propIsRequired: propIsRequired, propName: propName, propSchema: propSchema }) }))) : null] }));
52
+ };
53
+ export default React.memo(SchemaTableThMenu);
@@ -44,7 +44,7 @@ export interface ISchemaTableProps<T> {
44
44
  export interface IDateColumnFilterValue {
45
45
  from?: Date;
46
46
  to?: Date;
47
- filterEmpty?: boolean;
47
+ filterEmpty?: true;
48
48
  }
49
49
  export type TColumnFilterValue = string | number | boolean | IDateColumnFilterValue;
50
50
  declare function SchemaTable<T>({ Heading, checkedIndexes, config, customElement, data, defaultColumnFilters, defaultSortAsc, defaultSortColumn, disabledCheckedIndexes, enableAutoFocus, getRowClassName, getRowSelected, isColumnFilterable, isSearchable, isSortable, maxHeight, onCheckedIndexesChange, onRowClick, onRowDoubleClick, rowHeight, schema, searchPlaceholder, style, useFilterStateHash, width, }: ISchemaTableProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -3,12 +3,12 @@ import React from "react";
3
3
  import { VariableSizeGrid, VariableSizeList } from "react-window";
4
4
  import { localeFormat } from "../inc/date";
5
5
  import { t, uncamel } from "../inc/string";
6
- import Th, { EColumnFilterStatus } from "./Th";
7
6
  import { SELECT_ALL_COLUMN_NAME, SELECT_ALL_COLUMN_WIDTH } from "./constants";
8
7
  import Td from "./Td";
9
8
  import { DEFAULT_DATE_FORMAT, DEFAULT_DATE_TIME_FORMAT } from "../inc/constant";
10
- import SchemaColumnFilterPopover from "./SchemaColumnFilterPopover";
11
9
  import { parseLocationHash, serializeLocationHash } from "../inc/data";
10
+ import SchemaTableTh, { EColumnFilterStatus } from "./SchemaTableTh";
11
+ import SchemaTableThMenu from "./SchemaTableThMenu";
12
12
  const startOfTheWorldDate = new Date("1000-01-01 00:00:00Z");
13
13
  function getSortByValue(propSchema, propConfig) {
14
14
  var _a;
@@ -27,7 +27,7 @@ function getSortByValue(propSchema, propConfig) {
27
27
  function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, customElement, data, defaultColumnFilters = {}, defaultSortAsc = false, defaultSortColumn, disabledCheckedIndexes, enableAutoFocus, getRowClassName, getRowSelected, isColumnFilterable, isSearchable, isSortable, maxHeight, onCheckedIndexesChange, onRowClick, onRowDoubleClick, rowHeight = 36, schema, searchPlaceholder, style, useFilterStateHash, width, }) {
28
28
  const [sortColumn, setSortColumn] = React.useState(defaultSortColumn);
29
29
  const [sortAsc, setSortAsc] = React.useState(defaultSortAsc);
30
- const [popoverConfig, setPopoverConfig] = React.useState();
30
+ const [schemaTableThMenuConfig, setSchemaTableThMenuConfig] = React.useState();
31
31
  const isDataFunction = data instanceof Function;
32
32
  const [sourceData, setSourceData] = React.useState(isDataFunction ? undefined : data);
33
33
  const [locationHash, setLocationHash] = React.useState(parseLocationHash(window.location.hash));
@@ -367,27 +367,29 @@ function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, custo
367
367
  }
368
368
  setSortAsc(x);
369
369
  }, [isDataFunction]);
370
- const SchemaTableTh = React.useCallback(({ style, index }) => {
370
+ const ConfiguredSchemaTableTh = React.useCallback(({ style, index }) => {
371
371
  const propName = columnNames[index];
372
372
  const propSchema = (propName === SELECT_ALL_COLUMN_NAME
373
373
  ? { type: "boolean" }
374
374
  : properties[propName]);
375
375
  const propConfig = config ? config[propName] : undefined;
376
376
  let columnFilterStatus = isColumnFilterable &&
377
- (propSchema || (propConfig === null || propConfig === void 0 ? void 0 : propConfig.FilterForm)) &&
377
+ (propSchema || (propConfig === null || propConfig === void 0 ? void 0 : propConfig.FilterMenu)) &&
378
378
  (propConfig === null || propConfig === void 0 ? void 0 : propConfig.isFilterable) !== false
379
379
  ? EColumnFilterStatus.AVAILABLE
380
380
  : EColumnFilterStatus.UNAVAILABLE;
381
381
  if (columnFilterMap[propName] !== undefined) {
382
382
  columnFilterStatus = EColumnFilterStatus.ACTIVE;
383
383
  }
384
- return (_jsx(Th, { isAllChecked: isAllRowsChecked, columnFilterStatus: columnFilterStatus, disableColumnFilter: disableColumnFilter, isSortable: !!isSortable, numberOfSelectedRows: checkedIndexes === null || checkedIndexes === void 0 ? void 0 : checkedIndexes.length, onSelectAllIndexesHandler: onSelectAllIndexesHandler, propConfig: propConfig, propIsRequired: required.includes(propName), propName: propName, schema: propSchema, setPopoverConfig: setPopoverConfig, setSortAsc: onSetSortAsc, setSortColumn: onSetSortColumn, sortAsc: sortColumn === propName ? sortAsc : undefined, style: style }));
384
+ return (_jsx(SchemaTableTh, { columnFilterStatus: columnFilterStatus,
385
+ // disableColumnFilter={disableColumnFilter}
386
+ isAllChecked: isAllRowsChecked, isSortable: !!isSortable, numberOfSelectedRows: checkedIndexes === null || checkedIndexes === void 0 ? void 0 : checkedIndexes.length, onSelectAllIndexesHandler: onSelectAllIndexesHandler, propConfig: propConfig, propIsRequired: required.includes(propName), propName: propName, schema: propSchema, setMenuConfig: setSchemaTableThMenuConfig, setSortAsc: onSetSortAsc, setSortColumn: onSetSortColumn, sortAsc: sortColumn === propName ? sortAsc : undefined, style: style }));
385
387
  }, [
386
388
  checkedIndexes === null || checkedIndexes === void 0 ? void 0 : checkedIndexes.length,
387
389
  columnFilterMap,
388
390
  columnNames,
389
391
  config,
390
- disableColumnFilter,
392
+ // disableColumnFilter,
391
393
  isAllRowsChecked,
392
394
  isColumnFilterable,
393
395
  isSortable,
@@ -424,19 +426,15 @@ function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, custo
424
426
  if (isDataFunction) {
425
427
  setIsDirty(true);
426
428
  }
427
- if (useFilterStateHash) {
428
- window.location.hash = serializeLocationHash(Object.assign(Object.assign({}, locationHash), { searchQuery: e.currentTarget.value }));
429
- return;
430
- }
431
429
  setSearchQuery(e.currentTarget.value);
432
- }, [isDataFunction, locationHash, useFilterStateHash]);
430
+ }, [isDataFunction]);
433
431
  const refreshData = React.useCallback(() => {
434
432
  setIsDirty(false);
435
433
  setSourceData(undefined);
436
434
  }, []);
437
435
  const onInputKeyDown = React.useCallback((e) => {
438
436
  if (e.key === "Enter") {
439
- setPopoverConfig(undefined);
437
+ setSchemaTableThMenuConfig(undefined);
440
438
  if (isDirty) {
441
439
  refreshData();
442
440
  }
@@ -452,8 +450,10 @@ function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, custo
452
450
  ? rowsMaxHeight
453
451
  : rowsHeight;
454
452
  }, [maxHeight, isSearchable, rowCount, rowHeight]);
455
- const onPopoverClose = React.useCallback(() => {
456
- setPopoverConfig(undefined);
453
+ const onPopoverClose = React.useCallback((e) => {
454
+ setSchemaTableThMenuConfig(undefined);
455
+ e.preventDefault();
456
+ e.stopPropagation();
457
457
  }, []);
458
458
  React.useEffect(() => {
459
459
  if (!useFilterStateHash) {
@@ -471,35 +471,31 @@ function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, custo
471
471
  if (!useFilterStateHash) {
472
472
  return;
473
473
  }
474
- if (locationHash.columnFilterMap) {
475
- setColumnFilterMap(locationHash.columnFilterMap);
476
- }
477
- if (locationHash.searchQuery !== undefined) {
478
- setSearchQuery(locationHash.searchQuery);
479
- }
474
+ setColumnFilterMap(locationHash.columnFilterMap || {});
475
+ setSearchQuery(locationHash.searchQuery || "");
480
476
  }, [locationHash, useFilterStateHash]);
481
- const onSchemaColumnFilterChange = React.useCallback((newColumnFilterValue) => {
482
- if (!popoverConfig) {
477
+ const onSchemaColumnFilterChange = React.useCallback((newColumnFilterValue, persistState) => {
478
+ if (!schemaTableThMenuConfig) {
483
479
  return;
484
480
  }
485
481
  if (isDataFunction) {
486
482
  setIsDirty(true);
487
483
  }
488
- if (newColumnFilterValue === undefined) {
489
- disableColumnFilter(popoverConfig.propName);
484
+ if (useFilterStateHash && persistState) {
485
+ window.location.hash = serializeLocationHash(Object.assign(Object.assign({}, locationHash), { columnFilterMap: Object.assign(Object.assign({}, columnFilterMap), { [schemaTableThMenuConfig.propName]: newColumnFilterValue }) }));
490
486
  return;
491
487
  }
492
- if (useFilterStateHash) {
493
- window.location.hash = serializeLocationHash(Object.assign(Object.assign({}, locationHash), { columnFilterMap: Object.assign(Object.assign({}, columnFilterMap), { [popoverConfig.propName]: newColumnFilterValue }) }));
488
+ if (newColumnFilterValue === undefined) {
489
+ disableColumnFilter(schemaTableThMenuConfig.propName);
494
490
  return;
495
491
  }
496
- setColumnFilterMap((columnFilterMap) => (Object.assign(Object.assign({}, columnFilterMap), { [popoverConfig.propName]: newColumnFilterValue })));
492
+ setColumnFilterMap((columnFilterMap) => (Object.assign(Object.assign({}, columnFilterMap), { [schemaTableThMenuConfig.propName]: newColumnFilterValue })));
497
493
  }, [
498
494
  columnFilterMap,
499
495
  disableColumnFilter,
500
496
  isDataFunction,
501
497
  locationHash,
502
- popoverConfig,
498
+ schemaTableThMenuConfig,
503
499
  useFilterStateHash,
504
500
  ]);
505
501
  const searchInputAutoFocus = React.useMemo(() => {
@@ -508,7 +504,20 @@ function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, custo
508
504
  }
509
505
  return enableAutoFocus;
510
506
  }, [enableAutoFocus]);
511
- return (_jsxs("div", Object.assign({ className: `schema-table${onRowClick ? " schema-table--clickable-rows" : ""}`, style: Object.assign(Object.assign({}, style), { width: rowWidth }), role: "table" }, { children: [_jsxs("div", Object.assign({ className: "schema-table__action-container" }, { children: [_jsx("div", Object.assign({ style: { flex: 1 } }, { children: isSearchable ? (_jsx("input", { type: "text", placeholder: searchPlaceholder || "Search...", value: searchQuery, onChange: onSearchChange, onKeyDown: onInputKeyDown, autoFocus: searchInputAutoFocus })) : null })), customElement] })), _jsx(Heading, Object.assign({ height: 50, itemCount: columnCount, itemSize: getColumnWidth, layout: "horizontal", width: rowWidth, sortAsc: sortAsc, setSortAsc: onSetSortAsc, setSortColumn: onSetSortColumn, sortColumn: sortColumn, sortedRenderData: sortedRenderData, className: "schema-table__th-row" }, { children: SchemaTableTh }), `thead_${rowWidth}_${sortColumn}_${sortAsc}_${searchQuery}`), sourceData && !isDirty ? (_jsx(VariableSizeGrid, Object.assign({ className: "schema-table__tbody", height: tableBodyHeight, width: rowWidth, columnWidth: getColumnWidth, rowHeight: getRowHeight, columnCount: columnCount, rowCount: rowCount }, { children: SchemaTableTd }), `tbody_${tableBodyHeight}_${rowWidth}_${sortColumn}_${sortAsc}_${searchQuery}_${columnCount}`)) : (_jsx("div", Object.assign({ style: {
507
+ const onClearFiltersButtonClick = React.useCallback(() => {
508
+ if (useFilterStateHash) {
509
+ window.location.hash = "";
510
+ return;
511
+ }
512
+ setColumnFilterMap({});
513
+ setSearchQuery("");
514
+ }, [useFilterStateHash]);
515
+ const onSearchBlur = React.useCallback(() => {
516
+ if (useFilterStateHash && searchQuery !== locationHash.searchQuery) {
517
+ window.location.hash = serializeLocationHash(Object.assign(Object.assign({}, locationHash), { searchQuery }));
518
+ }
519
+ }, [locationHash, searchQuery, useFilterStateHash]);
520
+ return (_jsxs("div", Object.assign({ className: `schema-table${onRowClick ? " schema-table--clickable-rows" : ""}`, style: Object.assign(Object.assign({}, style), { width: rowWidth }), role: "table" }, { children: [_jsxs("div", Object.assign({ className: "schema-table__action-container" }, { children: [_jsx("div", Object.assign({ style: { flex: 1 } }, { children: isSearchable ? (_jsx("input", { type: "text", placeholder: searchPlaceholder || "Search...", value: searchQuery, onChange: onSearchChange, onKeyDown: onInputKeyDown, autoFocus: searchInputAutoFocus, onBlur: onSearchBlur })) : null })), customElement, _jsx("button", Object.assign({ onClick: onClearFiltersButtonClick, disabled: Object.keys(columnFilterMap).length + searchQuery.length === 0 }, { children: "Clear filters" }))] })), _jsx(Heading, Object.assign({ height: 50, itemCount: columnCount, itemSize: getColumnWidth, layout: "horizontal", width: rowWidth, sortAsc: sortAsc, setSortAsc: onSetSortAsc, setSortColumn: onSetSortColumn, sortColumn: sortColumn, sortedRenderData: sortedRenderData, className: "schema-table__th-row" }, { children: ConfiguredSchemaTableTh }), `thead_${rowWidth}_${sortColumn}_${sortAsc}_${searchQuery}`), sourceData && !isDirty ? (_jsx(VariableSizeGrid, Object.assign({ className: "schema-table__tbody", height: tableBodyHeight, width: rowWidth, columnWidth: getColumnWidth, rowHeight: getRowHeight, columnCount: columnCount, rowCount: rowCount }, { children: SchemaTableTd }), `tbody_${tableBodyHeight}_${rowWidth}_${sortColumn}_${sortAsc}_${searchQuery}_${columnCount}`)) : (_jsx("div", Object.assign({ style: {
512
521
  width: rowWidth,
513
522
  height: Math.max(50, tableBodyHeight),
514
523
  border: "1px solid #BBB",
@@ -517,6 +526,6 @@ function SchemaTable({ Heading = VariableSizeList, checkedIndexes, config, custo
517
526
  backgroundColor: "#CCC",
518
527
  alignItems: "center",
519
528
  justifyContent: "center",
520
- } }, { children: isDirty ? (_jsx("button", Object.assign({ onClick: refreshData, className: "btn border" }, { children: "Refresh data" }))) : (_jsx("div", { children: "\u231B Loading..." })) }))), popoverConfig ? (_jsx(SchemaColumnFilterPopover, { referenceElement: popoverConfig.referenceElement, onClose: onPopoverClose, onChange: onSchemaColumnFilterChange, onInputKeyDown: onInputKeyDown, propIsRequired: popoverConfig.propIsRequired, propName: popoverConfig.propName, propSchema: schema.properties[popoverConfig.propName], value: columnFilterMap[popoverConfig.propName], propConfig: popoverConfig.propConfig })) : null] })));
529
+ } }, { children: isDirty ? (_jsx("button", Object.assign({ onClick: refreshData, className: "btn border" }, { children: "Refresh data" }))) : (_jsx("div", { children: "\u231B Loading..." })) }))), schemaTableThMenuConfig ? (_jsx(SchemaTableThMenu, { onChange: onSchemaColumnFilterChange, onClose: onPopoverClose, onInputKeyDown: onInputKeyDown, propConfig: schemaTableThMenuConfig.propConfig, propIsRequired: schemaTableThMenuConfig.propIsRequired, propName: schemaTableThMenuConfig.propName, propSchema: schema.properties[schemaTableThMenuConfig.propName], referenceElement: schemaTableThMenuConfig.referenceElement, setSortAsc: setSortAsc, setSortColumn: setSortColumn, value: columnFilterMap[schemaTableThMenuConfig.propName] })) : null] })));
521
530
  }
522
531
  export default React.memo(SchemaTable);
package/dist/inc/data.js CHANGED
@@ -1,3 +1,15 @@
1
+ const unserializeDates = (serializedObject) => {
2
+ if (serializedObject instanceof Object) {
3
+ if (serializedObject.$Date) {
4
+ return new Date(serializedObject.$Date);
5
+ }
6
+ return Object.entries(serializedObject).reduce((prev, [prop, value]) => {
7
+ prev[prop] = unserializeDates(value);
8
+ return prev;
9
+ }, {});
10
+ }
11
+ return serializedObject;
12
+ };
1
13
  export const parseLocationHash = (search) => {
2
14
  if (!search.length) {
3
15
  return {};
@@ -15,10 +27,24 @@ export const parseLocationHash = (search) => {
15
27
  return;
16
28
  }
17
29
  // @ts-ignore
18
- result[decodeURIComponent(splitPair[0])] = JSON.parse(decodeURIComponent(splitPair[1]));
30
+ result[decodeURIComponent(splitPair[0])] = unserializeDates(JSON.parse(decodeURIComponent(splitPair[1])));
19
31
  });
20
32
  return result;
21
33
  };
34
+ const serializeDates = (object) => {
35
+ if (!(object instanceof Object)) {
36
+ return object;
37
+ }
38
+ if (object instanceof Date) {
39
+ return {
40
+ $Date: object.toISOString(),
41
+ };
42
+ }
43
+ return Object.entries(object).reduce((prev, [prop, value]) => {
44
+ prev[prop] = serializeDates(value);
45
+ return prev;
46
+ }, {});
47
+ };
22
48
  export const serializeLocationHash = (params) => `${Object.entries(params)
23
- .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(value))}`)
49
+ .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(serializeDates(value)))}`)
24
50
  .join("&")}`;
package/dist/index.css CHANGED
@@ -1,58 +1,36 @@
1
- .schema-table .popover {
2
- --bs-popover-max-width: 1024px;
1
+ .schema-table,
2
+ .schema-table * {
3
+ box-sizing: border-box;
3
4
  }
4
- .schema-table__tbody {
5
- overflow-x: hidden !important;
6
- border-collapse: collapse;
7
- width: 100%;
8
- }
9
- .schema-table__th-row {
10
- overflow: hidden !important;
11
- }
12
- .schema-table .schema-column-filter-popover {
13
- background-color: #eee;
5
+ .schema-table button {
6
+ border: 1px solid #e4e4e4;
7
+ padding: 8px;
14
8
  }
15
- .schema-table .schema-column-filter-popover input,
16
- .schema-table .schema-column-filter-popover select {
17
- width: 100%;
18
- padding: 3px;
19
- margin-top: 3px;
20
- border-radius: 5px;
9
+ .schema-table button:enabled {
10
+ background-color: #f6f6f6;
11
+ color: #404040;
21
12
  }
22
- .schema-table .schema-column-filter-popover input[type=checkbox] {
23
- width: fit-content;
24
- margin-top: 10px;
25
- margin-left: 30px;
13
+ .schema-table button:enabled:hover {
14
+ border-color: #dbdbdb;
15
+ background-color: #ececec;
26
16
  }
27
- .schema-table .schema-column-filter-popover input[type=number],
28
- .schema-table .schema-column-filter-popover input[type=text],
29
- .schema-table .schema-column-filter-popover select {
30
- min-width: 150px;
17
+ .schema-table input {
18
+ padding: 8px;
19
+ border: 1px solid #888;
31
20
  }
32
- .schema-table .schema-column-filter-popover .react-datepicker {
33
- display: flex;
21
+ .schema-table input:hover {
22
+ border-color: lightblue;
34
23
  }
35
- .schema-table__th {
36
- background-color: #eee;
37
- align-items: center;
38
- padding-left: 8px;
39
- padding-right: 8px;
24
+ .schema-table select {
25
+ height: 33px;
40
26
  }
41
- .schema-table__th div {
42
- overflow: hidden;
43
- white-space: nowrap;
44
- text-overflow: ellipsis;
45
- }
46
- .schema-table__th,
47
- .schema-table__th button {
48
- font-weight: bold;
49
- display: flex;
50
- }
51
- .schema-table__th--column-filter-status-ACTIVE button {
52
- font-style: italic;
27
+ .schema-table__tbody {
28
+ overflow-x: hidden !important;
29
+ border-collapse: collapse;
30
+ width: 100%;
53
31
  }
54
- .schema-table__th--column-filter-status-ACTIVE svg {
55
- color: var(--bs-red, red);
32
+ .schema-table__th-row {
33
+ overflow: hidden !important;
56
34
  }
57
35
  .schema-table__td {
58
36
  overflow: hidden;
@@ -81,16 +59,103 @@
81
59
  .schema-table--clickable-rows .schema-table__td {
82
60
  cursor: pointer;
83
61
  }
84
- .schema-table button {
85
- border: 1px solid transparent;
86
- }
87
62
  .schema-table__action-container {
88
63
  display: flex;
89
64
  flex-direction: row;
90
65
  padding-bottom: 1rem;
91
66
  }
92
- .schema-table__action-container input {
93
- width: 30%;
94
- border-radius: 8px;
95
- padding: 4px 10px;
67
+
68
+ .schema-table-th {
69
+ border-right: 1px solid #ddd;
70
+ border-top: 1px solid #ddd;
71
+ border-bottom: 1px solid #ddd;
72
+ color: #666;
73
+ display: flex;
74
+ align-items: center;
75
+ padding-left: 8px;
76
+ padding-right: 8px;
77
+ user-select: none;
78
+ }
79
+ .schema-table-th div {
80
+ overflow: hidden;
81
+ white-space: nowrap;
82
+ text-overflow: ellipsis;
83
+ }
84
+ .schema-table-th--sorted {
85
+ background-color: #eff6fb;
86
+ }
87
+ .schema-table-th--filter-ACTIVE .schema-table-th__label-body-text {
88
+ text-decoration: underline;
89
+ font-style: italic;
90
+ }
91
+ .schema-table-th__label-body {
92
+ display: flex;
93
+ flex: 1;
94
+ font-size: 14px;
95
+ align-items: center;
96
+ }
97
+ .schema-table-th__trigger-el {
98
+ display: none;
99
+ position: absolute;
100
+ border: 1px solid #ddd;
101
+ top: 0;
102
+ right: 0;
103
+ bottom: 0;
104
+ width: 24px;
105
+ cursor: pointer;
106
+ background-color: #eff6fb;
107
+ color: #666;
108
+ font-size: 28px;
109
+ text-align: center;
110
+ padding: 0 0 5px !important;
111
+ }
112
+ .schema-table-th__sort-icon {
113
+ font-size: 24px;
114
+ width: 32px;
115
+ display: block;
116
+ text-align: center;
117
+ }
118
+ .schema-table-th:hover {
119
+ background-color: #eff6fb;
120
+ }
121
+ .schema-table-th:hover .schema-table-th__trigger-el {
122
+ display: block !important;
123
+ }
124
+
125
+ .schema-table-th-menu {
126
+ background-color: white;
127
+ }
128
+ .schema-table-th-menu label {
129
+ flex: 1;
130
+ }
131
+ .schema-table-th-menu .schema-table-th-menu__sub-menu-indicator {
132
+ padding-left: 8px;
133
+ margin-left: 8px;
134
+ }
135
+ .schema-table-th-menu__icon {
136
+ display: block;
137
+ width: 24px;
138
+ overflow: hidden;
139
+ text-align: center;
140
+ }
141
+
142
+ .schema-table-th-menu__sub-menu {
143
+ background-color: white;
144
+ border: 1px solid #ddd;
145
+ }
146
+
147
+ .schema-table-menu {
148
+ font-size: 14px;
149
+ list-style: none outside;
150
+ padding: 0;
151
+ margin: 0;
152
+ }
153
+ .schema-table-menu li {
154
+ display: flex;
155
+ border: 1px solid #ddd;
156
+ align-items: center;
157
+ cursor: pointer;
158
+ }
159
+ .schema-table-menu li:hover {
160
+ background-color: #eff6fb;
96
161
  }
package/dist/types.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import React from "react";
2
- import { IFilterFormComponentProps } from "./SchemaTable/SchemaColumnFilterPopover/FilterFormComponent";
3
2
  import { TColumnFilterValue } from "./SchemaTable";
3
+ import { IFilterMenuComponentProps } from "./SchemaTable/SchemaTableThMenu/FilterMenuComponent";
4
4
  export interface IColumnConfig<T> {
5
- FilterForm?: (props: IFilterFormComponentProps) => React.ReactElement | null;
5
+ FilterMenu?: (props: IFilterMenuComponentProps) => React.ReactElement | null;
6
6
  align?: "start" | "center" | "end";
7
7
  dateFormat?: string;
8
8
  defaultSortDesc?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mig-schema-table",
3
- "version": "3.0.63",
3
+ "version": "3.0.66",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist/"
@@ -1,84 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { t } from "../../../inc/string";
4
- import { DEFAULT_DATE_FORMAT, DEFAULT_DATE_TIME_FORMAT, } from "../../../inc/constant";
5
- import DatePicker from "react-datepicker";
6
- import nl from "date-fns/locale/nl";
7
- import { endOfDay } from "date-fns";
8
- const FilterFormComponent = ({ columnFilterValue, onChange, onInputKeyDown, propConfig, propIsRequired, propName, propSchema, }) => {
9
- const { type, format, minimum, maximum } = propSchema || {};
10
- const value = columnFilterValue;
11
- switch (type) {
12
- case "integer":
13
- return (_jsx("div", Object.assign({ className: "input-group" }, { children: _jsx("input", { autoFocus: true, className: "form-control", type: "number", value: (value || ""), "data-prop-name": propName, onChange: (e) => {
14
- onChange(e.currentTarget.value === ""
15
- ? undefined
16
- : parseInt(e.currentTarget.value));
17
- }, onKeyDown: onInputKeyDown, placeholder: `Search ${propName}`, min: minimum, max: maximum }) })));
18
- case "boolean":
19
- let selectValue = value ? "✓" : "✕";
20
- if (value === undefined) {
21
- selectValue = "";
22
- }
23
- return (_jsxs("select", Object.assign({ autoFocus: true, className: "form-select", value: selectValue, "data-prop-name": propName, onChange: (e) => {
24
- switch (e.currentTarget.value) {
25
- case "✓":
26
- onChange(true);
27
- break;
28
- case "✕":
29
- onChange(false);
30
- break;
31
- default:
32
- onChange(undefined);
33
- }
34
- } }, { children: [_jsx("option", Object.assign({ value: "" }, { children: "All" }), "all"), ["✓", "✕"].map((optionValue) => (_jsx("option", Object.assign({ value: optionValue }, { children: optionValue }), `column-filter-select-${optionValue}`)))] })));
35
- // @ts-ignore
36
- case "string":
37
- if (propSchema === null || propSchema === void 0 ? void 0 : propSchema.enum) {
38
- return (_jsxs("select", Object.assign({ autoFocus: true, className: "form-select", value: value, "data-prop-name": propName, onChange: (e) => {
39
- onChange(e.currentTarget.value || undefined);
40
- } }, { children: [_jsx("option", Object.assign({ value: "" }, { children: "All" }), "all"), propSchema.enum.map((name) => {
41
- const rowName = !(propConfig === null || propConfig === void 0 ? void 0 : propConfig.translation)
42
- ? name
43
- : t(name, propConfig.translation);
44
- return (_jsx("option", Object.assign({ value: rowName }, { children: rowName }), `column-filter-select-${rowName}`));
45
- })] })));
46
- }
47
- if (format === "date-time" || format === "date") {
48
- const dateFormat = format === "date" ? DEFAULT_DATE_FORMAT : DEFAULT_DATE_TIME_FORMAT;
49
- const dateRangeValue = (columnFilterValue || {
50
- from: undefined,
51
- to: undefined,
52
- filterEmpty: undefined,
53
- });
54
- return (_jsxs("div", { children: [propIsRequired ? null : (_jsxs("div", { children: [_jsxs("label", Object.assign({ className: "d-flex" }, { children: [_jsx("input", { type: "checkbox", className: "m-0 me-1", checked: !!dateRangeValue.filterEmpty, onChange: () => {
55
- onChange(Object.assign(Object.assign({}, dateRangeValue), { filterEmpty: !dateRangeValue.filterEmpty }));
56
- } }), "Hide empty values"] })), _jsx("hr", {})] })), _jsxs("div", Object.assign({ className: "input-group d-flex" }, { children: [_jsxs("div", Object.assign({ className: "d-flex flex-column m-1" }, { children: [_jsx("label", { children: "Start date-time" }), _jsx(DatePicker, { autoFocus: true, dateFormat: dateFormat, "data-prop-name": propName, locale: nl, selected: dateRangeValue.from, onChange: (date) => {
57
- if (!date && !dateRangeValue.to) {
58
- onChange(undefined);
59
- return;
60
- }
61
- if (dateRangeValue.to && date && date > dateRangeValue.to) {
62
- return;
63
- }
64
- onChange(Object.assign(Object.assign({}, columnFilterValue), { from: date || undefined }));
65
- }, placeholderText: dateFormat, isClearable: true, selectsStart: true, showTimeSelect: format === "date-time", timeIntervals: 15, shouldCloseOnSelect: format === "date" })] })), _jsxs("div", Object.assign({ className: "d-flex flex-column m-1" }, { children: [_jsx("label", { children: "End date-time" }), _jsx(DatePicker, { id: "filter-date", dateFormat: dateFormat, "data-prop-name": propName, locale: nl, selectsEnd: true, selected: dateRangeValue.to, onChange: (date) => {
66
- if (!date && !dateRangeValue.from) {
67
- onChange(undefined);
68
- return;
69
- }
70
- const to = date ? endOfDay(date) : undefined;
71
- if (dateRangeValue.from && to && to < dateRangeValue.from) {
72
- return;
73
- }
74
- onChange(Object.assign(Object.assign({}, columnFilterValue), { to }));
75
- }, placeholderText: dateFormat, isClearable: true, startDate: dateRangeValue.from, endDate: dateRangeValue.to, showTimeSelect: format === "date-time", timeIntervals: 15, shouldCloseOnSelect: format === "date" })] }))] }))] }));
76
- }
77
- // falls through
78
- default:
79
- return (_jsx("div", Object.assign({ className: "input-group" }, { children: _jsx("input", { autoFocus: true, type: "text", className: "form-control", placeholder: `Search ${propName}`, "aria-label": `Search ${propName}`, value: (value || ""), "data-prop-name": propName, onChange: (e) => {
80
- onChange(e.currentTarget.value || undefined);
81
- }, onKeyDown: onInputKeyDown }) })));
82
- }
83
- };
84
- export default React.memo(FilterFormComponent);
@@ -1,20 +0,0 @@
1
- import React from "react";
2
- import { oas31 } from "openapi3-ts";
3
- import { TColumnFilterValue } from "../index";
4
- import { IColumnConfig } from "../../types";
5
- export interface ISchemaColumnFilterPopoverConfig {
6
- referenceElement: HTMLElement;
7
- propName: string;
8
- propConfig?: IColumnConfig<any>;
9
- propIsRequired: boolean;
10
- }
11
- type TSchemaColumnFilterPopoverProps = ISchemaColumnFilterPopoverConfig & {
12
- onChange: (newValue?: TColumnFilterValue) => void;
13
- onInputKeyDown: (e: React.KeyboardEvent) => void;
14
- propIsRequired: boolean;
15
- propSchema: oas31.SchemaObject;
16
- value: TColumnFilterValue;
17
- onClose: () => void;
18
- };
19
- declare const _default: React.MemoExoticComponent<({ onChange, onClose, onInputKeyDown, propIsRequired, propName, propSchema, referenceElement, value, propConfig, }: TSchemaColumnFilterPopoverProps) => import("react/jsx-runtime").JSX.Element>;
20
- export default _default;
@@ -1,38 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import FilterFormComponent from "./FilterFormComponent";
4
- import { usePopper } from "react-popper";
5
- const SchemaColumnFilterPopover = ({ onChange, onClose, onInputKeyDown, propIsRequired, propName, propSchema, referenceElement, value, propConfig, }) => {
6
- const [popperElement, setPopperElement] = React.useState(null);
7
- const [arrowElement, setArrowElement] = React.useState(null);
8
- const { styles, attributes } = usePopper(referenceElement, popperElement, {
9
- modifiers: [{ name: "arrow", options: { element: arrowElement } }],
10
- });
11
- React.useEffect(() => {
12
- const onWindowClick = (e) => {
13
- if (!popperElement) {
14
- return;
15
- }
16
- let parent = e.target;
17
- while (parent && popperElement) {
18
- if (parent === popperElement) {
19
- return;
20
- }
21
- parent =
22
- parent.parentNode === window.document ? null : parent.parentNode;
23
- }
24
- onClose();
25
- };
26
- window.addEventListener("click", onWindowClick, { capture: true });
27
- return () => {
28
- window.removeEventListener("click", onWindowClick, { capture: true });
29
- };
30
- }, [onClose, popperElement]);
31
- const classNames = ["popover", "schema-column-filter-popover"];
32
- if (attributes.popper) {
33
- classNames.push(`bs-popover-${attributes.popper["data-popper-placement"]}`);
34
- }
35
- const FilterForm = (propConfig === null || propConfig === void 0 ? void 0 : propConfig.FilterForm) || FilterFormComponent;
36
- return (_jsxs("div", Object.assign({ className: classNames.join(" "), role: "tooltip", ref: setPopperElement, style: styles.popper }, attributes.popper, { children: [_jsx("div", { className: "popover-arrow", ref: setArrowElement, style: styles.arrow }), _jsx("div", Object.assign({ className: "popover-body" }, { children: _jsx(FilterForm, { columnFilterValue: value, onChange: onChange, onInputKeyDown: onInputKeyDown, propConfig: propConfig, propIsRequired: propIsRequired, propName: propName, propSchema: propSchema }) }))] })));
37
- };
38
- export default React.memo(SchemaColumnFilterPopover);
@@ -1,95 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from "react";
3
- import { t, uncamel } from "../../inc/string";
4
- import { SELECT_ALL_COLUMN_NAME } from "../constants";
5
- import { timeZone } from "../../inc/date";
6
- export var EColumnFilterStatus;
7
- (function (EColumnFilterStatus) {
8
- EColumnFilterStatus["UNAVAILABLE"] = "UNAVAILABLE";
9
- EColumnFilterStatus["AVAILABLE"] = "AVAILABLE";
10
- EColumnFilterStatus["ACTIVE"] = "ACTIVE";
11
- })(EColumnFilterStatus || (EColumnFilterStatus = {}));
12
- const Th = ({ columnFilterStatus, disableColumnFilter, isAllChecked, isSortable, numberOfSelectedRows, onSelectAllIndexesHandler, propConfig, propIsRequired, propName, schema, setPopoverConfig, setSortAsc, setSortColumn, sortAsc, style, }) => {
13
- const thDivProps = {
14
- style,
15
- className: `schema-table__th schema-table__th--column-filter-status-${columnFilterStatus} ${isSortable ? "schema-table__th--sortable" : "schema-table__th--unsortable"}`,
16
- };
17
- const onSortButtonClick = React.useCallback(() => {
18
- if (sortAsc === undefined) {
19
- setSortColumn(propName);
20
- setSortAsc(!(propConfig === null || propConfig === void 0 ? void 0 : propConfig.defaultSortDesc));
21
- return;
22
- }
23
- setSortAsc((sortAsc) => !sortAsc);
24
- }, [
25
- propConfig === null || propConfig === void 0 ? void 0 : propConfig.defaultSortDesc,
26
- propName,
27
- setSortAsc,
28
- setSortColumn,
29
- sortAsc,
30
- ]);
31
- const onFilterButtonClick = React.useCallback((e) => {
32
- if (columnFilterStatus === EColumnFilterStatus.ACTIVE &&
33
- disableColumnFilter) {
34
- disableColumnFilter(propName);
35
- return;
36
- }
37
- if (!setPopoverConfig) {
38
- return;
39
- }
40
- const referenceElement = e.currentTarget;
41
- setPopoverConfig((popoverConfig) => {
42
- if (popoverConfig) {
43
- return undefined;
44
- }
45
- return {
46
- propConfig,
47
- propIsRequired,
48
- propName,
49
- referenceElement,
50
- };
51
- });
52
- }, [
53
- columnFilterStatus,
54
- disableColumnFilter,
55
- propConfig,
56
- propIsRequired,
57
- propName,
58
- setPopoverConfig,
59
- ]);
60
- const labelBody = React.useMemo(() => {
61
- if ((propConfig === null || propConfig === void 0 ? void 0 : propConfig.title) !== undefined) {
62
- return propConfig.title;
63
- }
64
- if ((schema === null || schema === void 0 ? void 0 : schema.format) &&
65
- schema.format.startsWith("date") &&
66
- (propConfig === null || propConfig === void 0 ? void 0 : propConfig.showTimezones) !== false) {
67
- return `${uncamel(propName)} (${t(timeZone)})`;
68
- }
69
- return uncamel(propName);
70
- }, [propConfig, propName, schema === null || schema === void 0 ? void 0 : schema.format]);
71
- if (propName === SELECT_ALL_COLUMN_NAME) {
72
- return (_jsx("div", Object.assign({}, thDivProps, { children: _jsx("div", Object.assign({ style: {
73
- width: "100%",
74
- textAlign: "center",
75
- }, title: `${numberOfSelectedRows || 0} selected` }, { children: _jsx("input", { type: "checkbox", checked: isAllChecked, onChange: onSelectAllIndexesHandler }) })) })));
76
- }
77
- if (!schema && !(propConfig === null || propConfig === void 0 ? void 0 : propConfig.renderData) && !(propConfig === null || propConfig === void 0 ? void 0 : propConfig.renderCell)) {
78
- return _jsx("div", Object.assign({}, thDivProps));
79
- }
80
- switch (schema === null || schema === void 0 ? void 0 : schema.type) {
81
- case "boolean":
82
- thDivProps.className += ` text-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "center"} justify-content-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "center"}`;
83
- break;
84
- case "integer":
85
- case "number":
86
- thDivProps.className += ` text-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "end"} justify-content-${(propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) || "end"}`;
87
- break;
88
- default:
89
- if (propConfig === null || propConfig === void 0 ? void 0 : propConfig.align) {
90
- thDivProps.className += ` text-${propConfig.align}`;
91
- }
92
- }
93
- return (_jsxs("div", Object.assign({}, thDivProps, { children: [isSortable ? (_jsxs("button", Object.assign({ className: "px-0", disabled: (propConfig === null || propConfig === void 0 ? void 0 : propConfig.sortable) === false, onClick: onSortButtonClick }, { children: [labelBody, sortAsc === undefined ? null : sortAsc ? "▲" : "▼"] }))) : (_jsx("div", Object.assign({ style: { lineHeight: "44px" } }, { children: labelBody }))), columnFilterStatus !== EColumnFilterStatus.UNAVAILABLE ? (_jsx("button", Object.assign({ onClick: onFilterButtonClick, "data-bs-toggle": "dropdown" }, { children: _jsx("svg", Object.assign({ viewBox: "0 0 36 36", xmlns: "http://www.w3.org/2000/svg", height: 16, width: 16, style: { display: "block" }, fill: "currentColor" }, { children: _jsx("polygon", { points: "14,30 22,25 22,17 35.999,0 17.988,0 0,0 14,17 " }) })) }))) : null] })));
94
- };
95
- export default React.memo(Th);