@absreim/react-bootstrap-data-grid 0.1.4 → 1.1.0
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.
- package/ColHeaderCell.d.ts +1 -0
- package/ColHeaderCell.jsx +22 -5
- package/FilterOptionsTable/DateFilterRow.d.ts +10 -0
- package/FilterOptionsTable/DateFilterRow.jsx +63 -0
- package/FilterOptionsTable/FilterOptionsTable.d.ts +8 -0
- package/FilterOptionsTable/FilterOptionsTable.jsx +118 -0
- package/FilterOptionsTable/NumberFilterRow.d.ts +9 -0
- package/FilterOptionsTable/NumberFilterRow.jsx +47 -0
- package/FilterOptionsTable/StringFilterRow.d.ts +9 -0
- package/FilterOptionsTable/StringFilterRow.jsx +47 -0
- package/FilterOptionsTable/types.d.ts +13 -0
- package/FilterOptionsTable/types.js +1 -0
- package/FilterOptionsTable/useFormStateFromTableFilterState.d.ts +4 -0
- package/FilterOptionsTable/useFormStateFromTableFilterState.js +72 -0
- package/Grid.d.ts +2 -1
- package/Grid.jsx +31 -11
- package/ToggleButton.d.ts +8 -0
- package/ToggleButton.jsx +13 -0
- package/hooks/useEditableFromFilterState.d.ts +3 -0
- package/hooks/useEditableFromFilterState.js +14 -0
- package/hooks/useFilter.d.ts +3 -0
- package/hooks/useFilter.js +82 -0
- package/hooks/useFilterStateFromEditable.d.ts +3 -0
- package/hooks/useFilterStateFromEditable.js +18 -0
- package/models/descriptions.d.ts +2 -0
- package/models/descriptions.js +6 -0
- package/package.json +5 -4
- package/types.d.ts +51 -0
- package/types.js +30 -1
- package/util/datetime.d.ts +3 -0
- package/util/datetime.js +9 -0
package/ColHeaderCell.d.ts
CHANGED
package/ColHeaderCell.jsx
CHANGED
|
@@ -10,10 +10,25 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
10
10
|
};
|
|
11
11
|
import { useState } from "react";
|
|
12
12
|
import classNames from "classnames";
|
|
13
|
-
var getUpArrow = function (
|
|
13
|
+
var getUpArrow = function (grayed) { return (<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className={classNames(__spreadArray([
|
|
14
|
+
"bi",
|
|
15
|
+
"bi-arrow-up"
|
|
16
|
+
], (grayed ? ["text-body-secondary"] : []), true))} viewBox="0 0 16 16">
|
|
17
|
+
{!grayed && (<>
|
|
18
|
+
<title>(sorted ascending)</title>
|
|
19
|
+
<desc>
|
|
20
|
+
Up arrow indicating that the column is being sorted in an ascending
|
|
21
|
+
manner
|
|
22
|
+
</desc>
|
|
23
|
+
</>)}
|
|
14
24
|
<path fillRule="evenodd" d="M8 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L7.5 2.707V14.5a.5.5 0 0 0 .5.5"/>
|
|
15
25
|
</svg>); };
|
|
16
26
|
var downArrow = (<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-down" viewBox="0 0 16 16">
|
|
27
|
+
<title>(sorted descending)</title>
|
|
28
|
+
<desc>
|
|
29
|
+
Down arrow indicating that the column is being sorted in an descending
|
|
30
|
+
manner
|
|
31
|
+
</desc>
|
|
17
32
|
<path fillRule="evenodd" d="M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1"/>
|
|
18
33
|
</svg>);
|
|
19
34
|
// Temporary solution to prevent column widths from changing when hovering over
|
|
@@ -22,7 +37,7 @@ var downArrow = (<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
|
|
|
22
37
|
// values.
|
|
23
38
|
var placeholder = (<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-down" viewBox="0 0 16 16"></svg>);
|
|
24
39
|
var ColHeaderCell = function (_a) {
|
|
25
|
-
var label = _a.label, sortModel = _a.sortModel;
|
|
40
|
+
var label = _a.label, sortModel = _a.sortModel, ariaColIndex = _a.ariaColIndex;
|
|
26
41
|
var _b = useState(false), isHovering = _b[0], setIsHovering = _b[1];
|
|
27
42
|
var handleMouseOver = function () {
|
|
28
43
|
return setIsHovering(true);
|
|
@@ -55,19 +70,21 @@ var ColHeaderCell = function (_a) {
|
|
|
55
70
|
switch (sortModel.sortOrder) {
|
|
56
71
|
case null: {
|
|
57
72
|
if (isHovering) {
|
|
58
|
-
return getUpArrow(
|
|
73
|
+
return getUpArrow(true);
|
|
59
74
|
}
|
|
60
75
|
return placeholder;
|
|
61
76
|
}
|
|
62
77
|
case "asc": {
|
|
63
|
-
return getUpArrow();
|
|
78
|
+
return getUpArrow(false);
|
|
64
79
|
}
|
|
65
80
|
case "desc": {
|
|
66
81
|
return downArrow;
|
|
67
82
|
}
|
|
68
83
|
}
|
|
69
84
|
};
|
|
70
|
-
return (<th onClick={sortModel && handleClick} onMouseOver={handleMouseOver} onMouseOut={handleMouseOut} aria-description=
|
|
85
|
+
return (<th onClick={sortModel && handleClick} onMouseOver={handleMouseOver} onMouseOut={handleMouseOut} aria-description={sortModel
|
|
86
|
+
? "Column header"
|
|
87
|
+
: "Column header that can be clicked to change the sorting mode"} style={{ cursor: sortModel ? "pointer" : "default" }} aria-colindex={ariaColIndex}>
|
|
71
88
|
{label}
|
|
72
89
|
{getSortSymbol()}
|
|
73
90
|
</th>);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { DateFormFilterState } from "./types";
|
|
3
|
+
interface DateFilterRowProps {
|
|
4
|
+
includeTime: boolean;
|
|
5
|
+
columnLabel: string;
|
|
6
|
+
filterState: DateFormFilterState;
|
|
7
|
+
setFilterState: (filterState: DateFormFilterState) => void;
|
|
8
|
+
}
|
|
9
|
+
declare const DateFilterRow: FC<DateFilterRowProps>;
|
|
10
|
+
export default DateFilterRow;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { useMemo } from "react";
|
|
13
|
+
import { dateFilterSchemeNames, dateFilterSchemes, } from "../types";
|
|
14
|
+
import { nanoid } from "nanoid/non-secure";
|
|
15
|
+
var DateFilterRow = function (_a) {
|
|
16
|
+
var includeTime = _a.includeTime, columnLabel = _a.columnLabel, filterState = _a.filterState, setFilterState = _a.setFilterState;
|
|
17
|
+
var handleOpChange = function (_a) {
|
|
18
|
+
var target = _a.target;
|
|
19
|
+
setFilterState(__assign(__assign({}, filterState), { scheme: target.value }));
|
|
20
|
+
};
|
|
21
|
+
var handleEnabledChange = function (_a) {
|
|
22
|
+
var target = _a.target;
|
|
23
|
+
setFilterState(__assign(__assign({}, filterState), { enabled: target.checked }));
|
|
24
|
+
};
|
|
25
|
+
var handleStartValueChange = function (_a) {
|
|
26
|
+
var target = _a.target;
|
|
27
|
+
setFilterState(__assign(__assign({}, filterState), { startDate: target.value }));
|
|
28
|
+
};
|
|
29
|
+
var handleEndValueChange = function (_a) {
|
|
30
|
+
var target = _a.target;
|
|
31
|
+
setFilterState(__assign(__assign({}, filterState), { endDate: target.value }));
|
|
32
|
+
};
|
|
33
|
+
var enabled = filterState.enabled, scheme = filterState.scheme, startDate = filterState.startDate, endDate = filterState.endDate;
|
|
34
|
+
var inputType = includeTime ? "datetime-local" : "date";
|
|
35
|
+
var inputId = useMemo(function () { return nanoid(); }, []);
|
|
36
|
+
var startDateInputId = "$startDate-".concat(inputId);
|
|
37
|
+
var endDateInputId = "$endDate-".concat(inputId);
|
|
38
|
+
return (<tr>
|
|
39
|
+
<td>
|
|
40
|
+
<input type="checkbox" checked={enabled} name="enabled" onChange={handleEnabledChange}/>
|
|
41
|
+
</td>
|
|
42
|
+
<td>{columnLabel}</td>
|
|
43
|
+
<td>{filterState.type === "date" ? "Date" : "Datetime"}</td>
|
|
44
|
+
<td>
|
|
45
|
+
<select disabled={!enabled} className="form-select" value={scheme} onChange={handleOpChange}>
|
|
46
|
+
{dateFilterSchemes.map(function (scheme) { return (<option key={scheme} value={scheme}>
|
|
47
|
+
{dateFilterSchemeNames[scheme]}
|
|
48
|
+
</option>); })}
|
|
49
|
+
</select>
|
|
50
|
+
</td>
|
|
51
|
+
<td>
|
|
52
|
+
{scheme !== "endAt" && (<>
|
|
53
|
+
{scheme === "between" && (<label htmlFor={startDateInputId}>Start Date</label>)}
|
|
54
|
+
<input id={startDateInputId} className="form-control" type={inputType} required={enabled} disabled={!enabled} value={startDate} onChange={handleStartValueChange} aria-label="Start Date"/>
|
|
55
|
+
</>)}
|
|
56
|
+
{scheme !== "startFrom" && (<>
|
|
57
|
+
{scheme === "between" && (<label htmlFor={endDateInputId}>End Date</label>)}
|
|
58
|
+
<input className="form-control" type={inputType} required={enabled} disabled={!enabled} value={endDate} onChange={handleEndValueChange} aria-label="End Date"/>
|
|
59
|
+
</>)}
|
|
60
|
+
</td>
|
|
61
|
+
</tr>);
|
|
62
|
+
};
|
|
63
|
+
export default DateFilterRow;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { EditableTableFilterState, TableFilterState } from "../types";
|
|
3
|
+
interface FilterOptionsTableProps {
|
|
4
|
+
filterState: TableFilterState;
|
|
5
|
+
setFilterState: (filterState: EditableTableFilterState) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const FilterOptionsTable: FC<FilterOptionsTableProps>;
|
|
8
|
+
export default FilterOptionsTable;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import StringFilterRow from "./StringFilterRow";
|
|
14
|
+
import { datetimeInputStrToUtc } from "../util/datetime";
|
|
15
|
+
import NumberFilterRow from "./NumberFilterRow";
|
|
16
|
+
import useFormStateFromTableFilterState from "./useFormStateFromTableFilterState";
|
|
17
|
+
import DateFilterRow from "./DateFilterRow";
|
|
18
|
+
var convertFilterFormStateToEditableState = function (filterFormState) {
|
|
19
|
+
return Object.keys(filterFormState).reduce(function (editableState, colName) {
|
|
20
|
+
var rowFilterFormState = filterFormState[colName];
|
|
21
|
+
switch (rowFilterFormState.type) {
|
|
22
|
+
case "string": {
|
|
23
|
+
editableState[colName] = __assign({}, rowFilterFormState);
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
case "number": {
|
|
27
|
+
editableState[colName] = {
|
|
28
|
+
type: rowFilterFormState.type,
|
|
29
|
+
enabled: rowFilterFormState.enabled,
|
|
30
|
+
scheme: rowFilterFormState.scheme,
|
|
31
|
+
numValue: rowFilterFormState.inputValue === ""
|
|
32
|
+
? null
|
|
33
|
+
: Number(rowFilterFormState.inputValue),
|
|
34
|
+
};
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
default: {
|
|
38
|
+
// date or datetime
|
|
39
|
+
var partialFilterState = {
|
|
40
|
+
type: rowFilterFormState.type,
|
|
41
|
+
enabled: rowFilterFormState.enabled,
|
|
42
|
+
};
|
|
43
|
+
var strModifierFn_1 = rowFilterFormState.type === "date"
|
|
44
|
+
? function (str) { return str; }
|
|
45
|
+
: datetimeInputStrToUtc;
|
|
46
|
+
var inputStrToDate = function (str) {
|
|
47
|
+
return str === "" ? null : new Date(strModifierFn_1(str));
|
|
48
|
+
};
|
|
49
|
+
switch (rowFilterFormState.scheme) {
|
|
50
|
+
case "startFrom": {
|
|
51
|
+
editableState[colName] = __assign(__assign({}, partialFilterState), { scheme: rowFilterFormState.scheme, startDate: inputStrToDate(rowFilterFormState.startDate) });
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case "endAt": {
|
|
55
|
+
editableState[colName] = __assign(__assign({}, partialFilterState), { scheme: rowFilterFormState.scheme, endDate: inputStrToDate(rowFilterFormState.endDate) });
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
default: {
|
|
59
|
+
editableState[colName] = __assign(__assign({}, partialFilterState), { scheme: rowFilterFormState.scheme, startDate: inputStrToDate(rowFilterFormState.startDate), endDate: inputStrToDate(rowFilterFormState.endDate) });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return editableState;
|
|
65
|
+
}, {});
|
|
66
|
+
};
|
|
67
|
+
var FilterOptionsTable = function (_a) {
|
|
68
|
+
var filterState = _a.filterState, setFilterState = _a.setFilterState;
|
|
69
|
+
var formFilterState = useFormStateFromTableFilterState(filterState);
|
|
70
|
+
var _b = useState(formFilterState), formState = _b[0], setFormState = _b[1];
|
|
71
|
+
var getRows = function () {
|
|
72
|
+
return Object.keys(formState).map(function (colName) {
|
|
73
|
+
function getColStateSetter(colName) {
|
|
74
|
+
return function (rowState) {
|
|
75
|
+
var _a;
|
|
76
|
+
return setFormState(__assign(__assign({}, formState), (_a = {}, _a[colName] = rowState, _a)));
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
var colLabel = filterState[colName].label;
|
|
80
|
+
var colFilterState = formState[colName];
|
|
81
|
+
switch (colFilterState.type) {
|
|
82
|
+
case "string": {
|
|
83
|
+
return (<StringFilterRow key={colName} columnLabel={colLabel} filterState={colFilterState} setFilterState={getColStateSetter(colName)}/>);
|
|
84
|
+
}
|
|
85
|
+
case "number": {
|
|
86
|
+
return (<NumberFilterRow key={colName} columnLabel={colLabel} filterState={colFilterState} setFilterState={getColStateSetter(colName)}/>);
|
|
87
|
+
}
|
|
88
|
+
default: {
|
|
89
|
+
// date or datetime
|
|
90
|
+
return (<DateFilterRow key={colName} includeTime={colFilterState.type === "datetime"} columnLabel={colLabel} filterState={colFilterState} setFilterState={getColStateSetter(colName)}/>);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
var onSubmit = function (event) {
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
var editableTableFilterState = convertFilterFormStateToEditableState(formState);
|
|
98
|
+
setFilterState(editableTableFilterState);
|
|
99
|
+
};
|
|
100
|
+
return (<form onSubmit={onSubmit}>
|
|
101
|
+
<table className="table">
|
|
102
|
+
<thead>
|
|
103
|
+
<tr>
|
|
104
|
+
<th>Enabled</th>
|
|
105
|
+
<th>Column</th>
|
|
106
|
+
<th>Type</th>
|
|
107
|
+
<th>Operator</th>
|
|
108
|
+
<th>Value</th>
|
|
109
|
+
</tr>
|
|
110
|
+
</thead>
|
|
111
|
+
<tbody>{getRows()}</tbody>
|
|
112
|
+
</table>
|
|
113
|
+
<button className="btn btn-secondary" type="submit">
|
|
114
|
+
Submit
|
|
115
|
+
</button>
|
|
116
|
+
</form>);
|
|
117
|
+
};
|
|
118
|
+
export default FilterOptionsTable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { NumberFormFilterState } from "./types";
|
|
3
|
+
interface NumberFilterRowProps {
|
|
4
|
+
columnLabel: string;
|
|
5
|
+
filterState: NumberFormFilterState;
|
|
6
|
+
setFilterState: (filterState: NumberFormFilterState) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const NumberFilterRow: FC<NumberFilterRowProps>;
|
|
9
|
+
export default NumberFilterRow;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { numberFilterSchemeNames, numberFilterSchemes, } from "../types";
|
|
13
|
+
var NumberFilterRow = function (_a) {
|
|
14
|
+
var columnLabel = _a.columnLabel, filterState = _a.filterState, setFilterState = _a.setFilterState;
|
|
15
|
+
var handleOpChange = function (_a) {
|
|
16
|
+
var target = _a.target;
|
|
17
|
+
setFilterState(__assign(__assign({}, filterState), { scheme: target.value }));
|
|
18
|
+
};
|
|
19
|
+
var handleEnabledChange = function (_a) {
|
|
20
|
+
var target = _a.target;
|
|
21
|
+
setFilterState(__assign(__assign({}, filterState), { enabled: target.checked }));
|
|
22
|
+
};
|
|
23
|
+
var handleNumInputValueChange = function (_a) {
|
|
24
|
+
var target = _a.target;
|
|
25
|
+
setFilterState(__assign(__assign({}, filterState), { inputValue: target.value }));
|
|
26
|
+
};
|
|
27
|
+
var enabled = filterState.enabled, scheme = filterState.scheme, inputValue = filterState.inputValue;
|
|
28
|
+
// TODO: Input labelling for accessibility
|
|
29
|
+
return (<tr>
|
|
30
|
+
<td>
|
|
31
|
+
<input type="checkbox" checked={enabled} name="enabled" onChange={handleEnabledChange}/>
|
|
32
|
+
</td>
|
|
33
|
+
<td>{columnLabel}</td>
|
|
34
|
+
<td>Number</td>
|
|
35
|
+
<td>
|
|
36
|
+
<select disabled={!enabled} className="form-select" value={scheme} onChange={handleOpChange}>
|
|
37
|
+
{numberFilterSchemes.map(function (scheme) { return (<option key={scheme} value={scheme}>
|
|
38
|
+
{numberFilterSchemeNames[scheme]}
|
|
39
|
+
</option>); })}
|
|
40
|
+
</select>
|
|
41
|
+
</td>
|
|
42
|
+
<td>
|
|
43
|
+
<input className="form-control" type="number" required={enabled} disabled={!enabled} value={inputValue} onChange={handleNumInputValueChange}/>
|
|
44
|
+
</td>
|
|
45
|
+
</tr>);
|
|
46
|
+
};
|
|
47
|
+
export default NumberFilterRow;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { StringFilterState } from "../types";
|
|
3
|
+
interface StringFilterRowProps {
|
|
4
|
+
columnLabel: string;
|
|
5
|
+
filterState: StringFilterState;
|
|
6
|
+
setFilterState: (filterState: StringFilterState) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const StringFilterRow: FC<StringFilterRowProps>;
|
|
9
|
+
export default StringFilterRow;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { stringFilterSchemeNames, stringFilterSchemes, } from "../types";
|
|
13
|
+
var StringFilterRow = function (_a) {
|
|
14
|
+
var columnLabel = _a.columnLabel, filterState = _a.filterState, setFilterState = _a.setFilterState;
|
|
15
|
+
var handleOpChange = function (_a) {
|
|
16
|
+
var target = _a.target;
|
|
17
|
+
setFilterState(__assign(__assign({}, filterState), { scheme: target.value }));
|
|
18
|
+
};
|
|
19
|
+
var handleEnabledChange = function (_a) {
|
|
20
|
+
var target = _a.target;
|
|
21
|
+
setFilterState(__assign(__assign({}, filterState), { enabled: target.checked }));
|
|
22
|
+
};
|
|
23
|
+
var handleSearchStringChange = function (_a) {
|
|
24
|
+
var target = _a.target;
|
|
25
|
+
setFilterState(__assign(__assign({}, filterState), { searchString: target.value }));
|
|
26
|
+
};
|
|
27
|
+
var enabled = filterState.enabled, scheme = filterState.scheme, searchString = filterState.searchString;
|
|
28
|
+
// TODO: Input labelling for accessibility
|
|
29
|
+
return (<tr>
|
|
30
|
+
<td>
|
|
31
|
+
<input type="checkbox" checked={enabled} name="enabled" onChange={handleEnabledChange}/>
|
|
32
|
+
</td>
|
|
33
|
+
<td>{columnLabel}</td>
|
|
34
|
+
<td>String</td>
|
|
35
|
+
<td>
|
|
36
|
+
<select disabled={!enabled} className="form-select" value={scheme} onChange={handleOpChange}>
|
|
37
|
+
{stringFilterSchemes.map(function (scheme) { return (<option key={scheme} value={scheme}>
|
|
38
|
+
{stringFilterSchemeNames[scheme]}
|
|
39
|
+
</option>); })}
|
|
40
|
+
</select>
|
|
41
|
+
</td>
|
|
42
|
+
<td>
|
|
43
|
+
<input className="form-control" required={enabled} disabled={!enabled} value={searchString} onChange={handleSearchStringChange}/>
|
|
44
|
+
</td>
|
|
45
|
+
</tr>);
|
|
46
|
+
};
|
|
47
|
+
export default StringFilterRow;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AbstractDateFilterState, AbstractFilterState, DateFilterScheme, NumberFilterScheme, StringFilterState } from "../types";
|
|
2
|
+
export interface NumberFormFilterState extends AbstractFilterState {
|
|
3
|
+
type: "number";
|
|
4
|
+
scheme: NumberFilterScheme;
|
|
5
|
+
inputValue: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DateFormFilterState extends AbstractDateFilterState {
|
|
8
|
+
scheme: DateFilterScheme;
|
|
9
|
+
startDate: string;
|
|
10
|
+
endDate: string;
|
|
11
|
+
}
|
|
12
|
+
export type FilterFormRowState = StringFilterState | NumberFormFilterState | DateFormFilterState;
|
|
13
|
+
export type FilterFormState = Record<string, FilterFormRowState>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { useMemo } from "react";
|
|
13
|
+
import { dateToDatetimeInputStr, dateToInputStr } from "../util/datetime";
|
|
14
|
+
var useFormStateFromTableFilterState = function (tableFilterState) {
|
|
15
|
+
return useMemo(function () {
|
|
16
|
+
return Object.keys(tableFilterState).reduce(function (filterFormState, colName) {
|
|
17
|
+
var editableState = tableFilterState[colName].editableState;
|
|
18
|
+
switch (editableState.type) {
|
|
19
|
+
case "string": {
|
|
20
|
+
filterFormState[colName] = __assign({}, editableState);
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
case "number": {
|
|
24
|
+
filterFormState[colName] = {
|
|
25
|
+
type: "number",
|
|
26
|
+
scheme: editableState.scheme,
|
|
27
|
+
enabled: editableState.enabled,
|
|
28
|
+
inputValue: editableState.numValue === null
|
|
29
|
+
? ""
|
|
30
|
+
: String(editableState.numValue),
|
|
31
|
+
};
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
default: {
|
|
35
|
+
// date or datetime
|
|
36
|
+
var partialFormState = {
|
|
37
|
+
type: editableState.type,
|
|
38
|
+
enabled: editableState.enabled,
|
|
39
|
+
};
|
|
40
|
+
var dateToStrConverter = editableState.type === "date"
|
|
41
|
+
? dateToInputStr
|
|
42
|
+
: dateToDatetimeInputStr;
|
|
43
|
+
switch (editableState.scheme) {
|
|
44
|
+
case "startFrom": {
|
|
45
|
+
filterFormState[colName] = __assign(__assign({}, partialFormState), { scheme: "startFrom", startDate: editableState.startDate === null
|
|
46
|
+
? ""
|
|
47
|
+
: dateToStrConverter(editableState.startDate), endDate: "" });
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "endAt": {
|
|
51
|
+
filterFormState[colName] = __assign(__assign({}, partialFormState), { scheme: "endAt", startDate: "", endDate: editableState.endDate === null
|
|
52
|
+
? ""
|
|
53
|
+
: dateToStrConverter(editableState.endDate) });
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
default: {
|
|
57
|
+
// between
|
|
58
|
+
filterFormState[colName] = __assign(__assign({}, partialFormState), { scheme: "between", startDate: editableState.startDate === null
|
|
59
|
+
? ""
|
|
60
|
+
: dateToStrConverter(editableState.startDate), endDate: editableState.endDate === null
|
|
61
|
+
? ""
|
|
62
|
+
: dateToStrConverter(editableState.endDate) });
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return filterFormState;
|
|
69
|
+
}, {});
|
|
70
|
+
}, [tableFilterState]);
|
|
71
|
+
};
|
|
72
|
+
export default useFormStateFromTableFilterState;
|
package/Grid.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
|
-
import { ColDef, RowDef, Size, TableSortModel } from "./types";
|
|
2
|
+
import { ColDef, FilterModel, RowDef, Size, TableSortModel } from "./types";
|
|
3
3
|
export interface GridPaginationState {
|
|
4
4
|
pageSizeOptions: number[];
|
|
5
5
|
pageSizeIndex: number;
|
|
@@ -14,6 +14,7 @@ export interface GridProps {
|
|
|
14
14
|
cols: ColDef[];
|
|
15
15
|
pagination?: GridPaginationState;
|
|
16
16
|
sortModel?: TableSortModel;
|
|
17
|
+
filterModel?: FilterModel;
|
|
17
18
|
}
|
|
18
19
|
declare const Grid: FC<GridProps>;
|
|
19
20
|
export default Grid;
|
package/Grid.jsx
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useMemo } from "react";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
3
|
import Pagination from "./Pagination";
|
|
4
4
|
import classNames from "classnames";
|
|
5
5
|
import ColHeaderCell from "./ColHeaderCell";
|
|
6
|
+
import useFilter from "./hooks/useFilter";
|
|
7
|
+
import ToggleButton from "./ToggleButton";
|
|
8
|
+
import FilterOptionsTable from "./FilterOptionsTable/FilterOptionsTable";
|
|
9
|
+
import useFilterStateFromEditable from "./hooks/useFilterStateFromEditable";
|
|
6
10
|
var getTypeComparator = function (typeStr) {
|
|
7
11
|
if (typeStr === "date" || typeStr === "datetime") {
|
|
8
12
|
return function (a, b) { return a.valueOf() - b.valueOf(); };
|
|
@@ -24,10 +28,13 @@ var getRowComparator = function (comparator, fieldName) {
|
|
|
24
28
|
return function (rowA, rowB) { return comparator(rowA[fieldName], rowB[fieldName]); };
|
|
25
29
|
};
|
|
26
30
|
var Grid = function (_a) {
|
|
27
|
-
var rows = _a.rows, cols = _a.cols, pagination = _a.pagination, sortModel = _a.sortModel;
|
|
31
|
+
var rows = _a.rows, cols = _a.cols, pagination = _a.pagination, sortModel = _a.sortModel, filterModel = _a.filterModel;
|
|
32
|
+
var editableFilterState = (filterModel === null || filterModel === void 0 ? void 0 : filterModel.tableFilterState) || null;
|
|
33
|
+
var filterState = useFilterStateFromEditable(cols, editableFilterState);
|
|
34
|
+
var filteredRows = useFilter(rows, editableFilterState);
|
|
28
35
|
var sortedRows = useMemo(function () {
|
|
29
36
|
if (!sortModel || !sortModel.sortColDef) {
|
|
30
|
-
return
|
|
37
|
+
return filteredRows;
|
|
31
38
|
}
|
|
32
39
|
var sortFieldName = sortModel.sortColDef.name;
|
|
33
40
|
var sortOrder = sortModel.sortColDef.order;
|
|
@@ -47,8 +54,8 @@ var Grid = function (_a) {
|
|
|
47
54
|
};
|
|
48
55
|
rowComparator = getRowComparator(descComparator, sortFieldName);
|
|
49
56
|
}
|
|
50
|
-
return
|
|
51
|
-
}, [
|
|
57
|
+
return filteredRows.slice().sort(rowComparator);
|
|
58
|
+
}, [filteredRows, cols, sortModel]);
|
|
52
59
|
var currentPageRows = useMemo(function () {
|
|
53
60
|
if (pagination === undefined) {
|
|
54
61
|
return sortedRows;
|
|
@@ -79,7 +86,8 @@ var Grid = function (_a) {
|
|
|
79
86
|
var displayRow = [];
|
|
80
87
|
Object.keys(row).forEach(function (name) {
|
|
81
88
|
if (!nameToIndex.has(name)) {
|
|
82
|
-
|
|
89
|
+
console.error("Warning: row data contains a property named \"".concat(name, "\", but it was not found among the column definitions."));
|
|
90
|
+
return;
|
|
83
91
|
}
|
|
84
92
|
var index = nameToIndex.get(name);
|
|
85
93
|
var formatter = cols[index].formatter;
|
|
@@ -106,6 +114,7 @@ var Grid = function (_a) {
|
|
|
106
114
|
return displayRow;
|
|
107
115
|
});
|
|
108
116
|
}, [currentPageRows, cols]);
|
|
117
|
+
var _b = useState(false), filterOptionsVisible = _b[0], setFilterOptionsVisible = _b[1];
|
|
109
118
|
var handleSetPageNum = function (pageNum) {
|
|
110
119
|
if (pagination === undefined) {
|
|
111
120
|
return;
|
|
@@ -118,15 +127,24 @@ var Grid = function (_a) {
|
|
|
118
127
|
}
|
|
119
128
|
pagination.setPageSizeIndex(Number(event.target.value));
|
|
120
129
|
};
|
|
130
|
+
var handleToggleFilterOptions = function () {
|
|
131
|
+
setFilterOptionsVisible(!filterOptionsVisible);
|
|
132
|
+
};
|
|
121
133
|
// Once this component implements selection state, and if such interactivity is enabled, (conditionally) change the
|
|
122
134
|
// aria role to "grid".
|
|
123
135
|
// Array index is okay for the key for rows until some type of feature involving changing the index of rows, such as
|
|
124
136
|
// sorting or pagination, is implemented.
|
|
137
|
+
// TODO: implement the above described features: conditionally changing aria role to grid and a key field other than
|
|
138
|
+
// index
|
|
125
139
|
return (<div>
|
|
140
|
+
{filterState && filterModel && (<div>
|
|
141
|
+
<ToggleButton isActive={filterOptionsVisible} label={"".concat(filterOptionsVisible ? "Hide" : "Show ", " Filter Options")} onClick={handleToggleFilterOptions}/>
|
|
142
|
+
{filterOptionsVisible && (<FilterOptionsTable filterState={filterState} setFilterState={filterModel.setTableFilterState}/>)}
|
|
143
|
+
</div>)}
|
|
126
144
|
<table className="table">
|
|
127
145
|
<thead>
|
|
128
|
-
<tr>
|
|
129
|
-
{cols.map(function (_a) {
|
|
146
|
+
<tr aria-rowindex={1}>
|
|
147
|
+
{cols.map(function (_a, index) {
|
|
130
148
|
var _b;
|
|
131
149
|
var name = _a.name, label = _a.label, sortable = _a.sortable;
|
|
132
150
|
var colSortModel = sortModel && sortable
|
|
@@ -139,13 +157,15 @@ var Grid = function (_a) {
|
|
|
139
157
|
},
|
|
140
158
|
}
|
|
141
159
|
: undefined;
|
|
142
|
-
return (<ColHeaderCell key={name} label={label} sortModel={colSortModel}/>);
|
|
160
|
+
return (<ColHeaderCell key={name} label={label} sortModel={colSortModel} ariaColIndex={index + 1}/>);
|
|
143
161
|
})}
|
|
144
162
|
</tr>
|
|
145
163
|
</thead>
|
|
146
164
|
<tbody>
|
|
147
|
-
{displayRows.map(function (row, index) { return (<tr key={index}>
|
|
148
|
-
{row.map(function (value, index) { return (<td key={index}
|
|
165
|
+
{displayRows.map(function (row, index) { return (<tr key={index} aria-rowindex={index + 2}>
|
|
166
|
+
{row.map(function (value, index) { return (<td key={index} aria-colindex={index + 1}>
|
|
167
|
+
{value}
|
|
168
|
+
</td>); })}
|
|
149
169
|
</tr>); })}
|
|
150
170
|
</tbody>
|
|
151
171
|
</table>
|
package/ToggleButton.jsx
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
var ToggleButton = function (_a) {
|
|
4
|
+
var isActive = _a.isActive, label = _a.label, onClick = _a.onClick;
|
|
5
|
+
var baseClasses = ["btn", "btn-primary"];
|
|
6
|
+
var variableClasses = {
|
|
7
|
+
active: isActive,
|
|
8
|
+
};
|
|
9
|
+
return (<button type="button" className={classNames(baseClasses, variableClasses)} aria-pressed={isActive} onClick={onClick}>
|
|
10
|
+
{label}
|
|
11
|
+
</button>);
|
|
12
|
+
};
|
|
13
|
+
export default ToggleButton;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
var useEditableFromFilterState = function (filterState) {
|
|
3
|
+
return useMemo(function () {
|
|
4
|
+
if (filterState === null) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
var editableState = {};
|
|
8
|
+
Object.keys(filterState).forEach(function (columnName) {
|
|
9
|
+
editableState[columnName] = filterState[columnName].editableState;
|
|
10
|
+
});
|
|
11
|
+
return editableState;
|
|
12
|
+
}, [filterState]);
|
|
13
|
+
};
|
|
14
|
+
export default useEditableFromFilterState;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
var useFilter = function (rows, filterState) {
|
|
3
|
+
return useMemo(function () {
|
|
4
|
+
if (filterState === null) {
|
|
5
|
+
return rows;
|
|
6
|
+
}
|
|
7
|
+
return rows.filter(function (row) {
|
|
8
|
+
function checkIfPassesStringFilter(value, state) {
|
|
9
|
+
switch (state.scheme) {
|
|
10
|
+
case "contains": {
|
|
11
|
+
return value.includes(state.searchString);
|
|
12
|
+
}
|
|
13
|
+
case "startsWith": {
|
|
14
|
+
return value.startsWith(state.searchString);
|
|
15
|
+
}
|
|
16
|
+
default: {
|
|
17
|
+
return value.endsWith(state.searchString);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function checkIfPassesNumberFilter(value, state) {
|
|
22
|
+
var numValue = Number(state.numValue); // Note that a blank string becomes 0
|
|
23
|
+
switch (state.scheme) {
|
|
24
|
+
case "equals":
|
|
25
|
+
return value === numValue;
|
|
26
|
+
case "greaterThan":
|
|
27
|
+
return value > numValue;
|
|
28
|
+
case "lessThan":
|
|
29
|
+
return value < numValue;
|
|
30
|
+
case "greaterOrEqual":
|
|
31
|
+
return value >= numValue;
|
|
32
|
+
default:
|
|
33
|
+
return value <= numValue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function checkIfPassesDateFilter(value, state) {
|
|
37
|
+
switch (state.scheme) {
|
|
38
|
+
case "startFrom":
|
|
39
|
+
return state.startDate === null || value >= state.startDate;
|
|
40
|
+
case "endAt":
|
|
41
|
+
return state.endDate === null || value <= state.endDate;
|
|
42
|
+
case "between":
|
|
43
|
+
return (state.startDate === null ||
|
|
44
|
+
state.endDate === null ||
|
|
45
|
+
(value >= state.startDate && value <= state.endDate));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
var columnNames = Object.keys(row);
|
|
49
|
+
for (var _i = 0, columnNames_1 = columnNames; _i < columnNames_1.length; _i++) {
|
|
50
|
+
var columnName = columnNames_1[_i];
|
|
51
|
+
if (!(columnName in filterState)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (!filterState[columnName].enabled) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
var columnFilterState = filterState[columnName];
|
|
58
|
+
switch (columnFilterState.type) {
|
|
59
|
+
case "string": {
|
|
60
|
+
if (!checkIfPassesStringFilter(row[columnName], columnFilterState)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case "number": {
|
|
66
|
+
if (!checkIfPassesNumberFilter(row[columnName], columnFilterState)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
default: {
|
|
72
|
+
if (!checkIfPassesDateFilter(row[columnName], columnFilterState)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
}, [rows, filterState]);
|
|
81
|
+
};
|
|
82
|
+
export default useFilter;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
var useFilterStateFromEditable = function (colDefs, editableFilterState) {
|
|
3
|
+
return useMemo(function () {
|
|
4
|
+
if (editableFilterState === null) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
var filterState = {};
|
|
8
|
+
colDefs.forEach(function (_a) {
|
|
9
|
+
var name = _a.name, label = _a.label;
|
|
10
|
+
filterState[name] = {
|
|
11
|
+
editableState: editableFilterState[name],
|
|
12
|
+
label: label,
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
return filterState;
|
|
16
|
+
}, [colDefs, editableFilterState]);
|
|
17
|
+
};
|
|
18
|
+
export default useFilterStateFromEditable;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absreim/react-bootstrap-data-grid",
|
|
3
3
|
"description": "Data grid UI component for use with web apps using React and Bootstrap",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Brook Li",
|
|
7
7
|
"homepage": "https://react-bootstrap-data-grid.vercel.app/",
|
|
@@ -14,11 +14,12 @@
|
|
|
14
14
|
"grid"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"classnames": "^2.5.1"
|
|
17
|
+
"classnames": "^2.5.1",
|
|
18
|
+
"dayjs": "^1.11.13"
|
|
18
19
|
},
|
|
19
20
|
"peerDependencies": {
|
|
20
|
-
"react": "^
|
|
21
|
-
"react-dom": "^
|
|
21
|
+
"react": "^19",
|
|
22
|
+
"react-dom": "^19"
|
|
22
23
|
},
|
|
23
24
|
"main": "./index.js",
|
|
24
25
|
"module": "./index.js",
|
package/types.d.ts
CHANGED
|
@@ -23,3 +23,54 @@ export interface TableSortModel {
|
|
|
23
23
|
sortColDef: SortColDef | null;
|
|
24
24
|
setSortColDef: (sortColDef: SortColDef | null) => void;
|
|
25
25
|
}
|
|
26
|
+
export type TableFilterState = Record<string, ColFilterState>;
|
|
27
|
+
export type EditableTableFilterState = Record<string, FilterState>;
|
|
28
|
+
export interface ColFilterState {
|
|
29
|
+
editableState: FilterState;
|
|
30
|
+
label: string;
|
|
31
|
+
}
|
|
32
|
+
export interface AbstractFilterState {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare const stringFilterSchemes: readonly ["contains", "startsWith", "endsWith"];
|
|
36
|
+
export type StringFilterScheme = (typeof stringFilterSchemes)[number];
|
|
37
|
+
export declare const stringFilterSchemeNames: Record<StringFilterScheme, string>;
|
|
38
|
+
export interface StringFilterState extends AbstractFilterState {
|
|
39
|
+
type: "string";
|
|
40
|
+
scheme: StringFilterScheme;
|
|
41
|
+
searchString: string;
|
|
42
|
+
}
|
|
43
|
+
export declare const numberFilterSchemes: readonly ["equals", "greaterThan", "lessThan", "greaterOrEqual", "lessOrEqual"];
|
|
44
|
+
export type NumberFilterScheme = (typeof numberFilterSchemes)[number];
|
|
45
|
+
export declare const numberFilterSchemeNames: Record<NumberFilterScheme, string>;
|
|
46
|
+
export interface NumberFilterState extends AbstractFilterState {
|
|
47
|
+
type: "number";
|
|
48
|
+
scheme: NumberFilterScheme;
|
|
49
|
+
numValue: number | null;
|
|
50
|
+
}
|
|
51
|
+
export declare const dateFilterSchemes: readonly ["startFrom", "endAt", "between"];
|
|
52
|
+
export type DateFilterScheme = (typeof dateFilterSchemes)[number];
|
|
53
|
+
export declare const dateFilterSchemeNames: Record<DateFilterScheme, string>;
|
|
54
|
+
export interface AbstractDateFilterState extends AbstractFilterState {
|
|
55
|
+
type: "date" | "datetime";
|
|
56
|
+
scheme: DateFilterScheme;
|
|
57
|
+
}
|
|
58
|
+
export interface StartDateFilterState extends AbstractDateFilterState {
|
|
59
|
+
scheme: "startFrom";
|
|
60
|
+
startDate: Date | null;
|
|
61
|
+
}
|
|
62
|
+
export interface EndDateFilterState extends AbstractDateFilterState {
|
|
63
|
+
scheme: "endAt";
|
|
64
|
+
endDate: Date | null;
|
|
65
|
+
}
|
|
66
|
+
export interface BetweenDatesFilterState extends AbstractDateFilterState {
|
|
67
|
+
scheme: "between";
|
|
68
|
+
startDate: Date | null;
|
|
69
|
+
endDate: Date | null;
|
|
70
|
+
}
|
|
71
|
+
export type DateFilterState = StartDateFilterState | EndDateFilterState | BetweenDatesFilterState;
|
|
72
|
+
export type FilterState = StringFilterState | NumberFilterState | DateFilterState;
|
|
73
|
+
export interface FilterModel {
|
|
74
|
+
tableFilterState: EditableTableFilterState;
|
|
75
|
+
setTableFilterState: (state: EditableTableFilterState) => void;
|
|
76
|
+
}
|
package/types.js
CHANGED
|
@@ -1 +1,30 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var stringFilterSchemes = [
|
|
2
|
+
"contains",
|
|
3
|
+
"startsWith",
|
|
4
|
+
"endsWith",
|
|
5
|
+
];
|
|
6
|
+
export var stringFilterSchemeNames = {
|
|
7
|
+
contains: "Contains",
|
|
8
|
+
startsWith: "Starts With",
|
|
9
|
+
endsWith: "Ends With",
|
|
10
|
+
};
|
|
11
|
+
export var numberFilterSchemes = [
|
|
12
|
+
"equals",
|
|
13
|
+
"greaterThan",
|
|
14
|
+
"lessThan",
|
|
15
|
+
"greaterOrEqual",
|
|
16
|
+
"lessOrEqual",
|
|
17
|
+
];
|
|
18
|
+
export var numberFilterSchemeNames = {
|
|
19
|
+
equals: "=",
|
|
20
|
+
greaterThan: ">",
|
|
21
|
+
lessThan: "<",
|
|
22
|
+
greaterOrEqual: ">=",
|
|
23
|
+
lessOrEqual: "<=",
|
|
24
|
+
};
|
|
25
|
+
export var dateFilterSchemes = ["startFrom", "endAt", "between"];
|
|
26
|
+
export var dateFilterSchemeNames = {
|
|
27
|
+
startFrom: "Start Form",
|
|
28
|
+
endAt: "End At",
|
|
29
|
+
between: "Between",
|
|
30
|
+
};
|
package/util/datetime.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
export var dateToInputStr = function (date) { return dayjs(date).format("YYYY-MM-DD"); };
|
|
3
|
+
export var dateToDatetimeInputStr = function (date) {
|
|
4
|
+
return dayjs(date).format("YYYY-MM-DDTHH:mm");
|
|
5
|
+
};
|
|
6
|
+
// All dates and datetimes that the grid displays are in UTC. The datetime
|
|
7
|
+
// string in the value attribute of an input element of type datetime-local
|
|
8
|
+
// is based on the local timezone of the client.
|
|
9
|
+
export var datetimeInputStrToUtc = function (datetimeStr) { return datetimeStr + "Z"; };
|