@monolith-forensics/monolith-ui 1.2.61 → 1.2.63

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.
@@ -7,6 +7,7 @@ import { DefaultOperators } from "./DefaultOperators";
7
7
  import Input from "../Input";
8
8
  import DateInput from "../DateInput";
9
9
  import { useDebouncedCallback } from "use-debounce";
10
+ import moment from "moment";
10
11
  const StyledContainer = styled.div `
11
12
  display: flex;
12
13
  flex-direction: row;
@@ -34,6 +35,10 @@ const RuleContainer = styled(StyledContainer) `
34
35
  const FilterContainer = styled(StyledContainer) `
35
36
  gap: 10px;
36
37
  flex-wrap: wrap;
38
+
39
+ button.mfui-DropDownMenu:hover {
40
+ border-color: ${({ theme }) => theme.palette.primary.main};
41
+ }
37
42
  `;
38
43
  const StyledButton = styled(Button) `
39
44
  border-radius: 0;
@@ -104,6 +109,26 @@ const StyledDateInput = styled(DateInput) `
104
109
  border-color: ${({ theme }) => theme.palette.primary.main};
105
110
  }
106
111
  `;
112
+ const dateFormatResolver = (resolution) => {
113
+ switch (resolution) {
114
+ case "day":
115
+ return "YYYY-MM-DD";
116
+ // case "month":
117
+ // return "YYYY-MM";
118
+ // case "year":
119
+ // return "YYYY";
120
+ // case "hour":
121
+ // return "YYYY-MM-DD HH";
122
+ // case "minute":
123
+ // return "YYYY-MM-DD HH:mm";
124
+ case "second":
125
+ return "YYYY-MM-DD HH:mm:ss";
126
+ case "millisecond":
127
+ return "YYYY-MM-DD HH:mm:ss.SSS";
128
+ default:
129
+ return "YYYY-MM-DD HH:mm:ss";
130
+ }
131
+ };
107
132
  const ValueEditor = ({ rule, inputType, filterDef, onChange }) => {
108
133
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
109
134
  const theme = useTheme();
@@ -115,7 +140,24 @@ const ValueEditor = ({ rule, inputType, filterDef, onChange }) => {
115
140
  onChange === null || onChange === void 0 ? void 0 : onChange(Object.assign(Object.assign({}, rule), { value: selected.map((s) => s.value) }));
116
141
  }, 100);
117
142
  const handleTimestampChange = useDebouncedCallback((timestamp) => {
118
- onChange === null || onChange === void 0 ? void 0 : onChange(Object.assign(Object.assign({}, rule), { value: timestamp ? [timestamp] : undefined }));
143
+ let formattedValue = timestamp;
144
+ if (formattedValue && filterDef.resolution) {
145
+ const date = moment(formattedValue);
146
+ switch (filterDef.resolution) {
147
+ case "day":
148
+ date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
149
+ break;
150
+ case "second":
151
+ date.set({ millisecond: 0 });
152
+ break;
153
+ case "millisecond":
154
+ break;
155
+ default:
156
+ break;
157
+ }
158
+ formattedValue = date.format(dateFormatResolver(filterDef.resolution));
159
+ }
160
+ onChange === null || onChange === void 0 ? void 0 : onChange(Object.assign(Object.assign({}, rule), { value: formattedValue ? [formattedValue] : undefined }));
119
161
  }, 100);
120
162
  switch (inputType) {
121
163
  case "text":
@@ -125,7 +167,7 @@ const ValueEditor = ({ rule, inputType, filterDef, onChange }) => {
125
167
  case "date":
126
168
  return (_jsx(StyledDateInput, { arrow: false, enableCalendar: true, format: "YYYY-MM-DD", defaultValue: ((_c = rule.value) === null || _c === void 0 ? void 0 : _c[0]) === "" ? undefined : (_d = rule.value) === null || _d === void 0 ? void 0 : _d[0], onChange: handleTimestampChange }));
127
169
  case "datetime":
128
- return (_jsx(StyledDateInput, { arrow: false, enableCalendar: true, format: "YYYY-MM-DD HH:mm:ss", defaultValue: ((_e = rule.value) === null || _e === void 0 ? void 0 : _e[0]) === "" ? undefined : (_f = rule.value) === null || _f === void 0 ? void 0 : _f[0], onChange: handleTimestampChange }));
170
+ return (_jsx(StyledDateInput, { arrow: false, enableCalendar: true, format: dateFormatResolver(filterDef === null || filterDef === void 0 ? void 0 : filterDef.resolution), defaultValue: ((_e = rule.value) === null || _e === void 0 ? void 0 : _e[0]) === "" ? undefined : (_f = rule.value) === null || _f === void 0 ? void 0 : _f[0], onChange: handleTimestampChange }));
129
171
  case "multiselect":
130
172
  let display = Array.isArray(rule.value) && rule.value.length > 0
131
173
  ? ((_h = (_g = filterDef === null || filterDef === void 0 ? void 0 : filterDef.selectOptions) === null || _g === void 0 ? void 0 : _g.filter((o) => rule.value.includes(o.value))) === null || _h === void 0 ? void 0 : _h.map((o) => o.label).join(", ")) || "Select Value"
@@ -178,7 +220,7 @@ const ValueSelector = ({ rule, inputType, filterDef, onChange }) => {
178
220
  var _a, _b;
179
221
  onChange === null || onChange === void 0 ? void 0 : onChange(Object.assign(Object.assign({}, rule), { value: [((_a = rule === null || rule === void 0 ? void 0 : rule.value) === null || _a === void 0 ? void 0 : _a[0]) || "", ((_b = e.value) === null || _b === void 0 ? void 0 : _b[0]) || ""] }));
180
222
  };
181
- return (_jsxs(_Fragment, { children: [_jsx(ValueEditor, { rule: rule, inputType: inputType, filterDef: filterDef, onChange: handleValueChange }), isBetween && (_jsxs(_Fragment, { children: [_jsx(FieldLabel, { children: "and" }), _jsx(ValueEditor, { rule: Object.assign(Object.assign({}, rule), { value: [((_a = rule === null || rule === void 0 ? void 0 : rule.value) === null || _a === void 0 ? void 0 : _a[1]) || ""] }), inputType: inputType, onChange: handleSecondaryValueChange })] }))] }));
223
+ return (_jsxs(_Fragment, { children: [_jsx(ValueEditor, { rule: rule, inputType: inputType, filterDef: filterDef, onChange: handleValueChange }), isBetween && (_jsxs(_Fragment, { children: [_jsx(FieldLabel, { children: "and" }), _jsx(ValueEditor, { rule: Object.assign(Object.assign({}, rule), { value: [((_a = rule === null || rule === void 0 ? void 0 : rule.value) === null || _a === void 0 ? void 0 : _a[1]) || ""] }), inputType: inputType, filterDef: filterDef, onChange: handleSecondaryValueChange })] }))] }));
182
224
  };
183
225
  const CloseLabel = styled(StyledButton) `
184
226
  padding: 2px;
@@ -189,12 +231,34 @@ const CloseLabel = styled(StyledButton) `
189
231
  border-color: ${({ theme }) => theme.palette.primary.main};
190
232
  }
191
233
  `;
192
- const Rules = ({ rules = [], combinator, showCombinator, filterDefinitions, onDelete, onUpdate, }) => {
234
+ const Rules = ({ rules = [], combinator, showCombinator, filterDefinitions, onDelete, onUpdate, onUpdateRootCombinator, }) => {
235
+ const handleCombinatorChange = (e) => {
236
+ onUpdateRootCombinator(e);
237
+ };
193
238
  const handleOperatorChange = (rule, operator) => {
194
239
  onUpdate(Object.assign(Object.assign({}, rule), { operator }));
195
240
  };
196
- return (_jsxs(_Fragment, { children: [showCombinator === true && (_jsx(FieldLabel, { children: combinator.toUpperCase() })), rules.map((rule, index) => {
241
+ return (_jsxs(_Fragment, { children: [showCombinator === true && (_jsx(DropDownMenu, { variant: "outlined", data: [
242
+ { label: "AND", value: "and" },
243
+ { label: "OR", value: "or" },
244
+ ],
245
+ // arrow={true}
246
+ size: "sm", buttonProps: {
247
+ title: "Chain these query filters together using AND | OR logic",
248
+ variant: "contained",
249
+ style: {
250
+ fontWeight: "normal",
251
+ fontSize: 12,
252
+ padding: "3px 5px",
253
+ height: 20,
254
+ borderRadius: 4,
255
+ },
256
+ }, onItemSelect: (e) => handleCombinatorChange(e.value), dropDownProps: {
257
+ style: { width: 175, maxWidth: 400 },
258
+ }, children: combinator.toUpperCase() })), rules.map((rule) => {
197
259
  const filterDef = filterDefinitions.find((f) => f.dataField === rule.dataField);
260
+ if (!filterDef)
261
+ throw new Error(`Filter Definition not found for dataField: ${rule.dataField}`);
198
262
  const operatorOptions = (filterDef === null || filterDef === void 0 ? void 0 : filterDef.operators) || DefaultOperators;
199
263
  const inputType = (filterDef === null || filterDef === void 0 ? void 0 : filterDef.inputType) || "text";
200
264
  return (_jsxs(RuleContainer, { "data-rule-id": rule.id, children: [_jsx(FieldLabel, { children: rule.label }), _jsx(DropDownMenu, { variant: "outlined", data: operatorOptions,
@@ -219,5 +283,5 @@ export const QueryFilter = ({ queryFilter, }) => {
219
283
  const { filter, filterDefinitions, showCombinator } = queryFilter;
220
284
  if (((_a = filter === null || filter === void 0 ? void 0 : filter.rules) === null || _a === void 0 ? void 0 : _a.length) == 0)
221
285
  return null;
222
- return (_jsx(FilterContainer, { className: "mfui-QueryFilter", children: _jsx(Rules, { rules: filter.rules, combinator: filter.combinator, showCombinator: showCombinator, filterDefinitions: filterDefinitions, onDelete: (rule) => queryFilter.removeRule(rule.id), onUpdate: (rule) => queryFilter.updateRule(rule) }) }));
286
+ return (_jsx(FilterContainer, { className: "mfui-QueryFilter", children: _jsx(Rules, { rules: filter.rules, combinator: filter.combinator, showCombinator: showCombinator, filterDefinitions: filterDefinitions, onDelete: (rule) => queryFilter.removeRule(rule.id), onUpdate: (rule) => queryFilter.updateRule(rule), onUpdateRootCombinator: (e) => queryFilter.updateRootCombinator(e) }) }));
223
287
  };
@@ -12,6 +12,7 @@ export type QueryFilterType = {
12
12
  addRule: (rule: Rule) => void;
13
13
  removeRule: (id: string) => void;
14
14
  updateRule: (rule: Rule) => void;
15
+ updateRootCombinator: (combinator: Combinator) => void;
15
16
  };
16
17
  export type UseQueryFilter = (args: UseQueryFilterProps) => QueryFilterType;
17
18
  export type Combinator = "and" | "or";
@@ -26,6 +27,7 @@ export interface FilterDefinition {
26
27
  pluralLabel?: string;
27
28
  operators?: Operator[];
28
29
  inputType?: HTMLInputElement["type"];
30
+ resolution?: "day" | "second" | "millisecond";
29
31
  placeholder?: string;
30
32
  selectOptions?: DropDownItem[];
31
33
  editorType?: EditorType;
@@ -20,6 +20,9 @@ export const useQueryFilter = (args) => {
20
20
  const rules = filter.rules.map((r) => (r.id === rule.id ? rule : r));
21
21
  setFilter(Object.assign(Object.assign({}, filter), { rules }));
22
22
  };
23
+ const updateRootCombinator = (combinator) => {
24
+ setFilter(Object.assign(Object.assign({}, filter), { combinator }));
25
+ };
23
26
  useEffect(() => {
24
27
  var _a;
25
28
  (_a = args === null || args === void 0 ? void 0 : args.onFilterChange) === null || _a === void 0 ? void 0 : _a.call(args, filter);
@@ -28,6 +31,7 @@ export const useQueryFilter = (args) => {
28
31
  filter,
29
32
  filterDefinitions: args.filterDefinitions,
30
33
  showCombinator: args.showCombinator,
34
+ updateRootCombinator,
31
35
  addRule,
32
36
  removeRule,
33
37
  updateRule,
@@ -35,6 +35,7 @@ const TableMenu = () => {
35
35
  const queryFilter = useQueryFilter({
36
36
  defaultFilter: filterState,
37
37
  filterDefinitions: (filterOptions === null || filterOptions === void 0 ? void 0 : filterOptions.filterDefinitions) || [],
38
+ showCombinator: true,
38
39
  onFilterChange: (q) => {
39
40
  var _a;
40
41
  handleFilterChange(q);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "1.2.61",
3
+ "version": "1.2.63",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",