@schukai/monster 3.54.0 → 3.55.1
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +25 -0
- package/package.json +1 -1
- package/source/components/datatable/datasource/rest.mjs +93 -57
- package/source/components/datatable/datatable/header.mjs +8 -0
- package/source/components/datatable/datatable.mjs +88 -44
- package/source/components/datatable/embedded-pagination.mjs +24 -43
- package/source/components/datatable/filter/util.mjs +138 -0
- package/source/components/datatable/filter.mjs +418 -174
- package/source/components/datatable/pagination.mjs +26 -2
- package/source/components/datatable/status.mjs +226 -0
- package/source/components/datatable/style/datatable.pcss +1 -0
- package/source/components/datatable/style/embedded-pagination.pcss +59 -2
- package/source/components/datatable/style/filter.pcss +4 -0
- package/source/components/datatable/style/pagination.pcss +28 -4
- package/source/components/datatable/style/status.pcss +42 -0
- package/source/components/datatable/stylesheet/column-bar.mjs +15 -9
- package/source/components/datatable/stylesheet/dataset.mjs +14 -8
- package/source/components/datatable/stylesheet/datasource.mjs +14 -8
- package/source/components/datatable/stylesheet/datatable.mjs +15 -9
- package/source/components/datatable/stylesheet/embedded-pagination.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-button.mjs +15 -9
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-date-range.mjs +14 -8
- package/source/components/datatable/stylesheet/filter-range.mjs +14 -8
- package/source/components/datatable/stylesheet/filter.mjs +15 -9
- package/source/components/datatable/stylesheet/pagination.mjs +15 -9
- package/source/components/datatable/stylesheet/select-filter.mjs +14 -8
- package/source/components/datatable/stylesheet/status.mjs +33 -0
- package/source/components/form/action-button.mjs +3 -1
- package/source/components/form/api-button.mjs +1 -1
- package/source/components/form/button-bar.mjs +1 -1
- package/source/components/form/button.mjs +1 -1
- package/source/components/form/confirm-button.mjs +3 -1
- package/source/components/form/context-error.mjs +272 -0
- package/source/components/form/context-help.mjs +7 -5
- package/source/components/form/form.mjs +4 -2
- package/source/components/form/message-state-button.mjs +4 -2
- package/source/components/form/popper-button.mjs +9 -4
- package/source/components/form/popper.mjs +11 -3
- package/source/components/form/reload.mjs +1 -1
- package/source/components/form/select.mjs +3 -3
- package/source/components/form/shadow-reload.mjs +1 -1
- package/source/components/form/state-button.mjs +4 -1
- package/source/components/form/style/context-error.pcss +32 -0
- package/source/components/form/style/context-help.pcss +22 -5
- package/source/components/form/stylesheet/action-button.mjs +14 -8
- package/source/components/form/stylesheet/api-button.mjs +14 -8
- package/source/components/form/stylesheet/button-bar.mjs +14 -8
- package/source/components/form/stylesheet/button.mjs +14 -8
- package/source/components/form/stylesheet/confirm-button.mjs +14 -8
- package/source/components/form/stylesheet/context-error.mjs +33 -0
- package/source/components/form/stylesheet/context-help.mjs +15 -9
- package/source/components/form/stylesheet/form.mjs +14 -8
- package/source/components/form/stylesheet/message-state-button.mjs +14 -8
- package/source/components/form/stylesheet/popper-button.mjs +14 -8
- package/source/components/form/stylesheet/popper.mjs +14 -8
- package/source/components/form/stylesheet/select.mjs +15 -9
- package/source/components/form/stylesheet/state-button.mjs +14 -8
- package/source/components/form/stylesheet/tabs.mjs +15 -9
- package/source/components/form/stylesheet/tree-select.mjs +14 -8
- package/source/components/form/tabs.mjs +53 -7
- package/source/components/form/template.mjs +1 -1
- package/source/components/form/tree-select.mjs +1 -1
- package/source/components/host/collapse.mjs +20 -5
- package/source/components/host/config-manager.mjs +41 -2
- package/source/components/host/host.mjs +14 -0
- package/source/components/host/stylesheet/call-button.mjs +15 -9
- package/source/components/host/stylesheet/collapse.mjs +14 -8
- package/source/components/host/stylesheet/config-manager.mjs +14 -8
- package/source/components/host/stylesheet/details.mjs +14 -8
- package/source/components/host/stylesheet/host.mjs +14 -8
- package/source/components/host/stylesheet/overlay.mjs +15 -9
- package/source/components/host/stylesheet/toggle-button.mjs +15 -9
- package/source/components/host/stylesheet/viewer.mjs +14 -8
- package/source/components/host/util.mjs +6 -1
- package/source/components/notify/stylesheet/message.mjs +15 -9
- package/source/components/notify/stylesheet/notify.mjs +14 -8
- package/source/components/state/stylesheet/log.mjs +14 -8
- package/source/components/state/stylesheet/state.mjs +14 -8
- package/source/components/stylesheet/badge.mjs +14 -8
- package/source/components/stylesheet/border.mjs +14 -8
- package/source/components/stylesheet/button.mjs +14 -8
- package/source/components/stylesheet/card.mjs +14 -8
- package/source/components/stylesheet/color.mjs +14 -8
- package/source/components/stylesheet/common.mjs +14 -8
- package/source/components/stylesheet/control.mjs +14 -8
- package/source/components/stylesheet/data-grid.mjs +14 -8
- package/source/components/stylesheet/display.mjs +14 -8
- package/source/components/stylesheet/floating-ui.mjs +14 -8
- package/source/components/stylesheet/form.mjs +14 -8
- package/source/components/stylesheet/host.mjs +14 -8
- package/source/components/stylesheet/icons.mjs +15 -9
- package/source/components/stylesheet/link.mjs +14 -8
- package/source/components/stylesheet/normalize.mjs +14 -8
- package/source/components/stylesheet/popper.mjs +14 -8
- package/source/components/stylesheet/property.mjs +14 -8
- package/source/components/stylesheet/ripple.mjs +14 -8
- package/source/components/stylesheet/skeleton.mjs +14 -8
- package/source/components/stylesheet/space.mjs +14 -8
- package/source/components/stylesheet/spinner.mjs +14 -8
- package/source/components/stylesheet/table.mjs +14 -8
- package/source/components/stylesheet/theme.mjs +14 -8
- package/source/components/stylesheet/typography.mjs +14 -8
- package/source/components/tree-menu/stylesheet/tree-menu.mjs +14 -8
- package/source/data/transformer.mjs +38 -43
- package/source/dom/attributes.mjs +5 -5
- package/source/dom/customelement.mjs +1 -1
- package/source/dom/updater.mjs +14 -5
- package/source/dom/util.mjs +42 -0
- package/source/i18n/providers/embed.mjs +3 -3
- package/source/monster.mjs +5 -0
- package/source/text/formatter.mjs +2 -2
- package/source/types/noderecursiveiterator.mjs +9 -7
- package/source/types/observer.mjs +1 -1
- package/source/types/version.mjs +1 -1
- package/source/util/sleep.mjs +17 -0
- package/test/cases/components/form/button.mjs +2 -1
- package/test/cases/components/form/select.mjs +1 -1
- package/test/cases/components/form/tree-select.mjs +1 -1
- package/test/cases/data/transformer.mjs +2 -2
- package/test/cases/dom/updater.mjs +67 -46
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +18 -13
@@ -4,7 +4,11 @@
|
|
4
4
|
*/
|
5
5
|
|
6
6
|
import { instanceSymbol } from "../../constants.mjs";
|
7
|
-
import {
|
7
|
+
import { findTargetElementFromEvent } from "../../dom/events.mjs";
|
8
|
+
import {
|
9
|
+
findElementWithIdUpwards,
|
10
|
+
findElementWithSelectorUpwards,
|
11
|
+
} from "../../dom/util.mjs";
|
8
12
|
import {
|
9
13
|
assembleMethodSymbol,
|
10
14
|
CustomElement,
|
@@ -23,11 +27,20 @@ import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
|
|
23
27
|
import "../form/message-state-button.mjs";
|
24
28
|
import { Formatter } from "../../text/formatter.mjs";
|
25
29
|
import { generateRangeComparisonExpression } from "../../text/util.mjs";
|
26
|
-
|
30
|
+
|
27
31
|
import {
|
28
32
|
parseBracketedKeyValueHash,
|
29
33
|
createBracketedKeyValueHash,
|
30
34
|
} from "../../text/bracketed-key-value-hash.mjs";
|
35
|
+
import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
|
36
|
+
import { SpaceStyleSheet } from "../stylesheet/space.mjs";
|
37
|
+
import { FormStyleSheet } from "../stylesheet/form.mjs";
|
38
|
+
|
39
|
+
import {
|
40
|
+
getStoredFilterConfigKey,
|
41
|
+
getFilterConfigKey,
|
42
|
+
parseDateInput,
|
43
|
+
} from "./filter/util.mjs";
|
31
44
|
|
32
45
|
import "./filter/select.mjs";
|
33
46
|
|
@@ -51,12 +64,32 @@ const searchButtonElementSymbol = Symbol("searchButtonElement");
|
|
51
64
|
*/
|
52
65
|
const resetButtonElementSymbol = Symbol("resetButtonElement");
|
53
66
|
|
67
|
+
/**
|
68
|
+
* @private
|
69
|
+
* @type {symbol}
|
70
|
+
*/
|
71
|
+
const saveButtonElementSymbol = Symbol("saveButtonElement");
|
72
|
+
|
54
73
|
/**
|
55
74
|
* @private
|
56
75
|
* @type {symbol}
|
57
76
|
*/
|
58
77
|
const filterControlElementSymbol = Symbol("filterControlElement");
|
59
78
|
|
79
|
+
/**
|
80
|
+
* @private
|
81
|
+
* @type {symbol}
|
82
|
+
*/
|
83
|
+
const filterSaveActionButtonElementSymbol = Symbol(
|
84
|
+
"filterSaveActionButtonElement",
|
85
|
+
);
|
86
|
+
|
87
|
+
/**
|
88
|
+
* @private
|
89
|
+
* @type {symbol}
|
90
|
+
*/
|
91
|
+
const filterTabElementSymbol = Symbol("filterTabElement");
|
92
|
+
|
60
93
|
/**
|
61
94
|
* @private
|
62
95
|
* @type {symbol}
|
@@ -132,10 +165,13 @@ class Filter extends CustomElement {
|
|
132
165
|
* @returns {Monster.Components.Datatable.Filter}
|
133
166
|
*/
|
134
167
|
showFailureMessage(message) {
|
135
|
-
this[searchButtonElementSymbol].setState(
|
168
|
+
this[searchButtonElementSymbol].setState(
|
169
|
+
"failed",
|
170
|
+
this.getOption("timeouts.message", 4000),
|
171
|
+
);
|
136
172
|
this[searchButtonElementSymbol]
|
137
|
-
.setMessage(
|
138
|
-
.showMessage(
|
173
|
+
.setMessage(message.toString())
|
174
|
+
.showMessage(this.getOption("timeouts.message", 4000));
|
139
175
|
return this;
|
140
176
|
}
|
141
177
|
|
@@ -154,7 +190,10 @@ class Filter extends CustomElement {
|
|
154
190
|
* @returns {Monster.Components.Datatable.Filter}
|
155
191
|
*/
|
156
192
|
showSuccess() {
|
157
|
-
this[searchButtonElementSymbol].setState(
|
193
|
+
this[searchButtonElementSymbol].setState(
|
194
|
+
"successful",
|
195
|
+
this.getOption("timeouts.message", 4000),
|
196
|
+
);
|
158
197
|
return this;
|
159
198
|
}
|
160
199
|
|
@@ -175,17 +214,34 @@ class Filter extends CustomElement {
|
|
175
214
|
* @property {string} defaultQuery Default query
|
176
215
|
*/
|
177
216
|
get defaults() {
|
178
|
-
|
217
|
+
return Object.assign({}, super.defaults, {
|
179
218
|
templates: {
|
180
219
|
main: getTemplate(),
|
181
220
|
},
|
221
|
+
|
182
222
|
labels: {
|
183
223
|
search: "Search",
|
184
224
|
reset: "Reset",
|
225
|
+
save: "Save",
|
226
|
+
"filter-name": "Filter name",
|
185
227
|
"empty-query-and-no-default": "Please select a filter",
|
186
228
|
"query-not-changed": "The query has not changed",
|
187
229
|
},
|
188
230
|
|
231
|
+
templateMapping: {
|
232
|
+
"filter-save-label": null,
|
233
|
+
"filter-name-label": name,
|
234
|
+
},
|
235
|
+
|
236
|
+
storedConfig: {
|
237
|
+
enabled: true,
|
238
|
+
selector: "",
|
239
|
+
},
|
240
|
+
|
241
|
+
timeouts: {
|
242
|
+
message: 4000,
|
243
|
+
},
|
244
|
+
|
189
245
|
queries: {
|
190
246
|
wrap: (value, definition) => {
|
191
247
|
return value;
|
@@ -201,8 +257,6 @@ class Filter extends CustomElement {
|
|
201
257
|
query: "",
|
202
258
|
defaultQuery: "",
|
203
259
|
});
|
204
|
-
|
205
|
-
return obj;
|
206
260
|
}
|
207
261
|
|
208
262
|
/**
|
@@ -217,6 +271,15 @@ class Filter extends CustomElement {
|
|
217
271
|
* @return {FilterButton}
|
218
272
|
*/
|
219
273
|
[assembleMethodSymbol]() {
|
274
|
+
this.setOption(
|
275
|
+
"templateMapping.filter-save-label",
|
276
|
+
this.getOption("labels.save"),
|
277
|
+
);
|
278
|
+
this.setOption(
|
279
|
+
"templateMapping.filter-name-label",
|
280
|
+
this.getOption("labels.filter-name"),
|
281
|
+
);
|
282
|
+
|
220
283
|
super[assembleMethodSymbol]();
|
221
284
|
|
222
285
|
initControlReferences.call(this);
|
@@ -226,9 +289,10 @@ class Filter extends CustomElement {
|
|
226
289
|
.call(this)
|
227
290
|
.then(() => {
|
228
291
|
initFilter.call(this);
|
292
|
+
updateFilterTabs.call(this);
|
229
293
|
})
|
230
294
|
.catch((error) => {
|
231
|
-
|
295
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message);
|
232
296
|
});
|
233
297
|
}
|
234
298
|
|
@@ -260,7 +324,7 @@ class Filter extends CustomElement {
|
|
260
324
|
* @return {Array<CSSStyleSheet>}
|
261
325
|
*/
|
262
326
|
static getCSSStyleSheet() {
|
263
|
-
return [FilterStyleSheet];
|
327
|
+
return [FilterStyleSheet, FormStyleSheet, ThemeStyleSheet, SpaceStyleSheet];
|
264
328
|
}
|
265
329
|
}
|
266
330
|
|
@@ -285,6 +349,20 @@ function initControlReferences() {
|
|
285
349
|
this[resetButtonElementSymbol] = this.shadowRoot.querySelector(
|
286
350
|
"[data-monster-role=reset-button]",
|
287
351
|
);
|
352
|
+
|
353
|
+
this[saveButtonElementSymbol] = this.shadowRoot.querySelector(
|
354
|
+
"[data-monster-role=save-button]",
|
355
|
+
);
|
356
|
+
|
357
|
+
this[filterSaveActionButtonElementSymbol] = this.shadowRoot.querySelector(
|
358
|
+
"[data-monster-role=save-action-button]",
|
359
|
+
);
|
360
|
+
|
361
|
+
this[filterTabElementSymbol] = findElementWithSelectorUpwards(
|
362
|
+
this,
|
363
|
+
this.getOption("storedConfig.selector", ""),
|
364
|
+
);
|
365
|
+
|
288
366
|
return this;
|
289
367
|
}
|
290
368
|
|
@@ -329,7 +407,8 @@ function initFilter() {
|
|
329
407
|
const v = escapeAttributeValue(valuesFromHash[element.id]);
|
330
408
|
const searchInput = element.firstElementChild;
|
331
409
|
try {
|
332
|
-
searchInput.value = valuesFromHash[element.id];
|
410
|
+
// searchInput.value = valuesFromHash[element.id];
|
411
|
+
searchInput.value = v; //valuesFromHash[element.id];
|
333
412
|
} catch (error) {}
|
334
413
|
}
|
335
414
|
|
@@ -349,6 +428,7 @@ function initFilter() {
|
|
349
428
|
"options",
|
350
429
|
this[settingsSymbol].getOptions(),
|
351
430
|
);
|
431
|
+
|
352
432
|
setTimeout(() => {
|
353
433
|
this[filterSelectElementSymbol].value = this[settingsSymbol].getSelected();
|
354
434
|
}, 10);
|
@@ -360,6 +440,11 @@ function initFilter() {
|
|
360
440
|
* @returns {*}
|
361
441
|
*/
|
362
442
|
function escapeAttributeValue(input) {
|
443
|
+
if (input === undefined || input === null) {
|
444
|
+
debugger;
|
445
|
+
return input;
|
446
|
+
}
|
447
|
+
|
363
448
|
return input
|
364
449
|
.replace(/&/g, "&")
|
365
450
|
.replace(/"/g, """)
|
@@ -374,10 +459,9 @@ function escapeAttributeValue(input) {
|
|
374
459
|
* @returns {boolean}
|
375
460
|
*/
|
376
461
|
function getVisibilityFromSlotAttribute(element) {
|
377
|
-
return
|
378
|
-
element.getAttribute("slot") === "hidden"
|
379
|
-
|
380
|
-
: true;
|
462
|
+
return !(
|
463
|
+
element.hasAttribute("slot") && element.getAttribute("slot") === "hidden"
|
464
|
+
);
|
381
465
|
}
|
382
466
|
|
383
467
|
/**
|
@@ -405,7 +489,7 @@ function initEventHandler() {
|
|
405
489
|
if (self[filterSelectElementSymbol]) {
|
406
490
|
self[filterSelectElementSymbol].addEventListener(
|
407
491
|
"monster-selection-cleared",
|
408
|
-
function (
|
492
|
+
function () {
|
409
493
|
const settings = self[settingsSymbol].getOptions();
|
410
494
|
|
411
495
|
for (const setting of settings) {
|
@@ -443,8 +527,109 @@ function initEventHandler() {
|
|
443
527
|
);
|
444
528
|
}
|
445
529
|
|
530
|
+
if (self[filterSaveActionButtonElementSymbol]) {
|
531
|
+
self[filterSaveActionButtonElementSymbol].setOption(
|
532
|
+
"actions.click",
|
533
|
+
function (event) {
|
534
|
+
const button = findTargetElementFromEvent(
|
535
|
+
event,
|
536
|
+
"data-monster-role",
|
537
|
+
"save-action-button",
|
538
|
+
);
|
539
|
+
const form = button.closest("[data-monster-role=form]");
|
540
|
+
|
541
|
+
if (!form) {
|
542
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
543
|
+
return;
|
544
|
+
}
|
545
|
+
|
546
|
+
const input = form.querySelector("input[name=filter-name]");
|
547
|
+
if (!input) {
|
548
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
549
|
+
return;
|
550
|
+
}
|
551
|
+
|
552
|
+
const name = input.value;
|
553
|
+
if (!name) {
|
554
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
555
|
+
button.setMessage("Please enter a name").showMessage();
|
556
|
+
return;
|
557
|
+
}
|
558
|
+
|
559
|
+
doSearch
|
560
|
+
.call(self, { showEffect: false })
|
561
|
+
.then(() => {
|
562
|
+
const configKey = getStoredFilterConfigKey.call(self);
|
563
|
+
const host = getDocument().querySelector("monster-host");
|
564
|
+
if (!host) {
|
565
|
+
return;
|
566
|
+
}
|
567
|
+
|
568
|
+
const query = self.getOption("query");
|
569
|
+
if (!query) {
|
570
|
+
button.setState(
|
571
|
+
"failed",
|
572
|
+
self.getOption(
|
573
|
+
"timeouts.message",
|
574
|
+
self.getOption("timeouts.message", 4000),
|
575
|
+
),
|
576
|
+
);
|
577
|
+
button
|
578
|
+
.setMessage("No query found")
|
579
|
+
.showMessage(self.getOption("timeouts.message", 4000));
|
580
|
+
return;
|
581
|
+
}
|
582
|
+
|
583
|
+
host
|
584
|
+
.hasConfig(configKey)
|
585
|
+
.then((hasConfig) => {
|
586
|
+
return new Promise((resolve, reject) => {
|
587
|
+
if (hasConfig) {
|
588
|
+
host.getConfig(configKey).then(resolve).catch(reject);
|
589
|
+
return;
|
590
|
+
}
|
591
|
+
return resolve({});
|
592
|
+
});
|
593
|
+
})
|
594
|
+
.then((config) => {
|
595
|
+
config[name] = query;
|
596
|
+
return host.setConfig(configKey, {
|
597
|
+
...config,
|
598
|
+
});
|
599
|
+
})
|
600
|
+
.then(() => {
|
601
|
+
button.setState(
|
602
|
+
"successful",
|
603
|
+
self.getOption("timeouts.message", 4000),
|
604
|
+
);
|
605
|
+
updateFilterTabs.call(self);
|
606
|
+
})
|
607
|
+
.catch((error) => {
|
608
|
+
button.setState(
|
609
|
+
"failed",
|
610
|
+
self.getOption("timeouts.message", 4000),
|
611
|
+
);
|
612
|
+
button
|
613
|
+
.setMessage(error.message)
|
614
|
+
.showMessage(self.getOption("timeouts.message", 4000));
|
615
|
+
});
|
616
|
+
})
|
617
|
+
.catch((error) => {
|
618
|
+
button.setState("failed", self.getOption("timeouts.message", 4000));
|
619
|
+
const msg = error.message || error;
|
620
|
+
button
|
621
|
+
.setMessage(msg)
|
622
|
+
.showMessage(self.getOption("timeouts.message", 4000));
|
623
|
+
});
|
624
|
+
},
|
625
|
+
);
|
626
|
+
}
|
627
|
+
|
446
628
|
self[searchButtonElementSymbol].setOption("actions.click", () => {
|
447
|
-
doSearch
|
629
|
+
doSearch
|
630
|
+
.call(self)
|
631
|
+
.then(() => {})
|
632
|
+
.catch((error) => {});
|
448
633
|
});
|
449
634
|
|
450
635
|
// the reset button should reset the filter and the search query
|
@@ -492,46 +677,192 @@ function initEventHandler() {
|
|
492
677
|
doSearch.call(self, { showEffect: false });
|
493
678
|
}
|
494
679
|
});
|
680
|
+
|
681
|
+
// tabs
|
682
|
+
const element = this[filterTabElementSymbol];
|
683
|
+
if (element) {
|
684
|
+
initTabEvents.call(this);
|
685
|
+
}
|
686
|
+
}
|
687
|
+
|
688
|
+
function initTabEvents() {
|
689
|
+
this[filterTabElementSymbol].addEventListener(
|
690
|
+
"monster-tab-changed",
|
691
|
+
(event) => {
|
692
|
+
const query = event?.detail?.data?.["data-monster-query"];
|
693
|
+
this.setOption("query", query);
|
694
|
+
},
|
695
|
+
);
|
696
|
+
|
697
|
+
this[filterTabElementSymbol].addEventListener(
|
698
|
+
"monster-tab-remove",
|
699
|
+
(event) => {
|
700
|
+
const labels = [];
|
701
|
+
const buttons = this[filterTabElementSymbol].getOption("buttons");
|
702
|
+
|
703
|
+
const keys = ["popper", "standard"];
|
704
|
+
for (let i = 0; i < keys.length; i++) {
|
705
|
+
const key = keys[i];
|
706
|
+
|
707
|
+
for (const button of buttons[key]) {
|
708
|
+
if (button.label !== event.detail.label) {
|
709
|
+
labels.push(button.label);
|
710
|
+
}
|
711
|
+
}
|
712
|
+
}
|
713
|
+
|
714
|
+
const document = getDocument();
|
715
|
+
const host = document.querySelector("monster-host");
|
716
|
+
if (!(host && this.id)) {
|
717
|
+
return;
|
718
|
+
}
|
719
|
+
|
720
|
+
const configKey = getStoredFilterConfigKey.call(this);
|
721
|
+
host
|
722
|
+
.hasConfig(configKey)
|
723
|
+
.then((hasConfig) => {
|
724
|
+
if (!hasConfig) {
|
725
|
+
return;
|
726
|
+
}
|
727
|
+
|
728
|
+
return host.getConfig(configKey);
|
729
|
+
})
|
730
|
+
.then((config) => {
|
731
|
+
for (const [name, query] of Object.entries(config)) {
|
732
|
+
if (labels.includes(name)) {
|
733
|
+
continue;
|
734
|
+
}
|
735
|
+
|
736
|
+
delete config[name];
|
737
|
+
}
|
738
|
+
|
739
|
+
return host.setConfig(configKey, {
|
740
|
+
...config,
|
741
|
+
});
|
742
|
+
});
|
743
|
+
},
|
744
|
+
);
|
495
745
|
}
|
496
746
|
|
497
747
|
/**
|
498
748
|
* @private
|
499
749
|
*/
|
500
|
-
function
|
750
|
+
function updateFilterTabs() {
|
751
|
+
const element = this[filterTabElementSymbol];
|
752
|
+
if (!element) {
|
753
|
+
return;
|
754
|
+
}
|
755
|
+
|
756
|
+
const document = getDocument();
|
757
|
+
const host = document.querySelector("monster-host");
|
758
|
+
if (!(host && this.id)) {
|
759
|
+
return;
|
760
|
+
}
|
761
|
+
|
762
|
+
const configKey = getStoredFilterConfigKey.call(this);
|
763
|
+
host
|
764
|
+
.hasConfig(configKey)
|
765
|
+
.then((hasConfig) => {
|
766
|
+
if (!hasConfig) {
|
767
|
+
return;
|
768
|
+
}
|
769
|
+
|
770
|
+
return host.getConfig(configKey);
|
771
|
+
})
|
772
|
+
.then((config) => {
|
773
|
+
for (const [name, query] of Object.entries(config)) {
|
774
|
+
const found = element.querySelector(
|
775
|
+
`[data-monster-button-label="${name}"]`,
|
776
|
+
);
|
777
|
+
if (found) {
|
778
|
+
continue;
|
779
|
+
}
|
780
|
+
|
781
|
+
if (query === undefined || query === null) {
|
782
|
+
continue;
|
783
|
+
}
|
784
|
+
|
785
|
+
const escapedQuery = escapeAttributeValue(query);
|
786
|
+
|
787
|
+
element.insertAdjacentHTML(
|
788
|
+
"beforeend",
|
789
|
+
`
|
790
|
+
<div data-monster-button-label="${name}"
|
791
|
+
data-monster-removable="true"
|
792
|
+
data-monster-query="${escapedQuery}" data-monster-role="filter-tab" >
|
793
|
+
</div>`,
|
794
|
+
);
|
795
|
+
}
|
796
|
+
})
|
797
|
+
.catch((error) => {
|
798
|
+
if (error instanceof Error) {
|
799
|
+
addAttributeToken(
|
800
|
+
this,
|
801
|
+
ATTRIBUTE_ERRORMESSAGE,
|
802
|
+
error.message + " " + error.stack,
|
803
|
+
);
|
804
|
+
} else {
|
805
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error + "");
|
806
|
+
}
|
807
|
+
});
|
808
|
+
}
|
809
|
+
|
810
|
+
/**
|
811
|
+
* @private
|
812
|
+
* @param showEffect
|
813
|
+
* @returns {Promise<*>}
|
814
|
+
*/
|
815
|
+
function doSearch({ showEffect } = { showEffect: true }) {;
|
816
|
+
|
501
817
|
this.resetFailureMessage();
|
502
818
|
|
503
819
|
if (showEffect) {
|
504
|
-
this[searchButtonElementSymbol].setState(
|
820
|
+
this[searchButtonElementSymbol].setState(
|
821
|
+
"activity",
|
822
|
+
this.getOption("timeouts.message", 4000),
|
823
|
+
);
|
505
824
|
}
|
506
825
|
|
507
|
-
collectSearchQueries
|
826
|
+
return collectSearchQueries
|
508
827
|
.call(this)
|
509
828
|
.then((query) => {
|
510
829
|
const buildQuery = buildSearchQuery.call(this, query);
|
511
830
|
if (buildQuery === "" && !this.getOption("defaultQuery")) {
|
512
|
-
this
|
513
|
-
|
514
|
-
|
515
|
-
.
|
516
|
-
|
831
|
+
const msg = this.getOption("labels.empty-query-and-no-default");
|
832
|
+
|
833
|
+
if (showEffect) {
|
834
|
+
this[searchButtonElementSymbol].removeState();
|
835
|
+
this[searchButtonElementSymbol]
|
836
|
+
.setMessage(msg)
|
837
|
+
.showMessage(this.getOption("timeouts.message", 4000));
|
838
|
+
}
|
839
|
+
|
840
|
+
throw new Error(msg);
|
517
841
|
}
|
518
842
|
|
519
843
|
if (buildQuery === this.getOption("query")) {
|
520
|
-
this
|
521
|
-
|
522
|
-
|
523
|
-
.
|
524
|
-
|
844
|
+
const msg = this.getOption("labels.query-not-changed");
|
845
|
+
|
846
|
+
if (showEffect) {
|
847
|
+
this[searchButtonElementSymbol].removeState();
|
848
|
+
this[searchButtonElementSymbol]
|
849
|
+
.setMessage(msg)
|
850
|
+
.showMessage(this.getOption("timeouts.message", 4000));
|
851
|
+
}
|
852
|
+
|
853
|
+
throw new Error(msg);
|
525
854
|
}
|
526
855
|
|
527
856
|
if (showEffect) {
|
528
|
-
this[searchButtonElementSymbol].setState(
|
857
|
+
this[searchButtonElementSymbol].setState(
|
858
|
+
"activity",
|
859
|
+
this.getOption("timeouts.message", 4000),
|
860
|
+
);
|
529
861
|
}
|
530
862
|
|
531
863
|
this.setOption("query", buildSearchQuery.call(this, query));
|
532
864
|
})
|
533
865
|
.catch((error) => {
|
534
|
-
console.error(error);
|
535
866
|
if (error instanceof Error) {
|
536
867
|
addAttributeToken(
|
537
868
|
this,
|
@@ -542,15 +873,22 @@ function doSearch({ showEffect } = { showEffect: true }) {
|
|
542
873
|
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
|
543
874
|
}
|
544
875
|
|
545
|
-
|
546
|
-
|
876
|
+
if (showEffect) {
|
877
|
+
this[searchButtonElementSymbol].setState(
|
878
|
+
"failed",
|
879
|
+
this.getOption("timeouts.message", 4000),
|
880
|
+
);
|
881
|
+
this[searchButtonElementSymbol].setMessage(error.message).showMessage();
|
882
|
+
}
|
883
|
+
|
884
|
+
return Promise.reject(error);
|
547
885
|
});
|
548
886
|
}
|
549
887
|
|
550
888
|
/**
|
551
889
|
* @private
|
552
890
|
* @param queries
|
553
|
-
* @returns {string
|
891
|
+
* @returns {*|string}
|
554
892
|
*/
|
555
893
|
function buildSearchQuery(queries) {
|
556
894
|
if (!isArray(queries) || queries.length === 0) {
|
@@ -581,6 +919,8 @@ function collectSearchQueries() {
|
|
581
919
|
const query = [];
|
582
920
|
const wrapCallback = this.getOption("queries.wrap");
|
583
921
|
|
922
|
+
let hasNoIdError = false;
|
923
|
+
|
584
924
|
getSlottedElements
|
585
925
|
.call(this, "label[data-monster-label]")
|
586
926
|
.forEach((element) => {
|
@@ -591,7 +931,7 @@ function collectSearchQueries() {
|
|
591
931
|
|
592
932
|
const id = element.id;
|
593
933
|
if (!id) {
|
594
|
-
|
934
|
+
hasNoIdError = true;
|
595
935
|
return;
|
596
936
|
}
|
597
937
|
|
@@ -659,132 +999,16 @@ function collectSearchQueries() {
|
|
659
999
|
}
|
660
1000
|
});
|
661
1001
|
|
1002
|
+
if (hasNoIdError) {
|
1003
|
+
reject(new Error("some or all filter elements have no id"));
|
1004
|
+
return;
|
1005
|
+
}
|
1006
|
+
|
662
1007
|
getGlobal().location.hash = createBracketedKeyValueHash(currentHash);
|
663
1008
|
resolve(query);
|
664
1009
|
});
|
665
1010
|
}
|
666
1011
|
|
667
|
-
/**
|
668
|
-
* @private
|
669
|
-
* @param {String} str
|
670
|
-
* @param {String} field
|
671
|
-
* @returns {String}
|
672
|
-
* @throws {Error} if no field is defined
|
673
|
-
*/
|
674
|
-
function parseDateInput(str, field) {
|
675
|
-
if (!str) {
|
676
|
-
return "";
|
677
|
-
}
|
678
|
-
|
679
|
-
if (!field) {
|
680
|
-
throw new Error("no field is defined");
|
681
|
-
}
|
682
|
-
|
683
|
-
// Define the supported formats
|
684
|
-
//let formats = ['DD-MM-YYYY', 'MM-DD-YYYY', 'YYYY-MM-DD', 'YYYY/MM/DD', 'DD.MM.YYYY'];
|
685
|
-
const formats = ["YYYY-MM-DD"];
|
686
|
-
// Determine the current date format of the localization
|
687
|
-
const currentDateFormat = new Intl.DateTimeFormat()
|
688
|
-
.format(new Date())
|
689
|
-
.replace(/\d/g, "D");
|
690
|
-
// formats.push(currentDateFormat);
|
691
|
-
|
692
|
-
// Run through the supported formats and try to parse the date
|
693
|
-
for (let i = 0; i < formats.length; i++) {
|
694
|
-
const format = formats[i];
|
695
|
-
// Replace the corresponding placeholders in the format string with regular expressions
|
696
|
-
|
697
|
-
try {
|
698
|
-
const pattern = format
|
699
|
-
.replace("DD", "\\d{2}")
|
700
|
-
.replace("MM", "\\d{2}")
|
701
|
-
.replace("YYYY", "\\d{4}");
|
702
|
-
const rangePattern =
|
703
|
-
"(?<from>" + pattern + ")\\s*-\\s*(?<to>" + pattern + ")";
|
704
|
-
|
705
|
-
const rangeRegex = new RegExp("^" + rangePattern + "$", "g");
|
706
|
-
|
707
|
-
if (rangeRegex.test(str)) {
|
708
|
-
rangeRegex.lastIndex = 0;
|
709
|
-
|
710
|
-
const rangeResult = rangeRegex.exec(str);
|
711
|
-
|
712
|
-
if (!rangeResult) {
|
713
|
-
continue;
|
714
|
-
}
|
715
|
-
|
716
|
-
const from = rangeResult?.groups?.from;
|
717
|
-
const to = rangeResult?.groups?.to;
|
718
|
-
|
719
|
-
if (from && to) {
|
720
|
-
return (
|
721
|
-
"(" +
|
722
|
-
field +
|
723
|
-
">='" +
|
724
|
-
from +
|
725
|
-
" 00:00:00' AND " +
|
726
|
-
field +
|
727
|
-
"<='" +
|
728
|
-
to +
|
729
|
-
" 23:59:59')"
|
730
|
-
);
|
731
|
-
}
|
732
|
-
|
733
|
-
if (from) {
|
734
|
-
return "(" + field + ">='" + from + " 00:00:00')";
|
735
|
-
} else if (to) {
|
736
|
-
return "(" + field + "<='" + to + "' 23:59:59')";
|
737
|
-
}
|
738
|
-
|
739
|
-
return "false";
|
740
|
-
}
|
741
|
-
|
742
|
-
const prefix = str.substring(0, 1) === "-";
|
743
|
-
const suffix = str.substring(str.length - 1, str.length) === "-";
|
744
|
-
|
745
|
-
if (prefix) {
|
746
|
-
str = str.substring(1, str.length);
|
747
|
-
} else if (suffix) {
|
748
|
-
str = str.substring(0, str.length - 1);
|
749
|
-
}
|
750
|
-
|
751
|
-
const regex = new RegExp("^(?<date>" + pattern + ")$", "g");
|
752
|
-
if (regex.test(str)) {
|
753
|
-
regex.lastIndex = 0;
|
754
|
-
const result = regex.exec(str);
|
755
|
-
|
756
|
-
if (!result) {
|
757
|
-
continue;
|
758
|
-
}
|
759
|
-
|
760
|
-
const date = result?.groups?.date;
|
761
|
-
if (date) {
|
762
|
-
if (prefix) {
|
763
|
-
return "(" + field + "<='" + date + " 23:59:59')";
|
764
|
-
} else if (suffix) {
|
765
|
-
return "(" + field + ">='" + date + "' 00:00:00')";
|
766
|
-
}
|
767
|
-
return (
|
768
|
-
"(" +
|
769
|
-
field +
|
770
|
-
">='" +
|
771
|
-
date +
|
772
|
-
" 00:00:00' AND " +
|
773
|
-
field +
|
774
|
-
"<='" +
|
775
|
-
date +
|
776
|
-
" 23:59:59')"
|
777
|
-
);
|
778
|
-
} else {
|
779
|
-
return "false";
|
780
|
-
}
|
781
|
-
}
|
782
|
-
} catch (e) {}
|
783
|
-
}
|
784
|
-
|
785
|
-
return "false";
|
786
|
-
}
|
787
|
-
|
788
1012
|
/**
|
789
1013
|
* @private
|
790
1014
|
* @param label
|
@@ -796,7 +1020,9 @@ function getControlValuesFromLabel(label) {
|
|
796
1020
|
if (foundControl) {
|
797
1021
|
if (foundControl.tagName === "INPUT") {
|
798
1022
|
if (foundControl.type === "checkbox") {
|
799
|
-
const checkedControls = label.querySelectorAll(
|
1023
|
+
const checkedControls = label.querySelectorAll(
|
1024
|
+
`${foundControl}:checked`,
|
1025
|
+
);
|
800
1026
|
const values = [];
|
801
1027
|
|
802
1028
|
checkedControls.forEach((checkedControl) => {
|
@@ -805,7 +1031,7 @@ function getControlValuesFromLabel(label) {
|
|
805
1031
|
|
806
1032
|
return values;
|
807
1033
|
} else if (foundControl.type === "radio") {
|
808
|
-
const checkedControl = label.querySelector(`${
|
1034
|
+
const checkedControl = label.querySelector(`${foundControl}:checked`);
|
809
1035
|
|
810
1036
|
if (checkedControl) {
|
811
1037
|
return checkedControl.value;
|
@@ -823,14 +1049,6 @@ function getControlValuesFromLabel(label) {
|
|
823
1049
|
return null;
|
824
1050
|
}
|
825
1051
|
|
826
|
-
/**
|
827
|
-
* @private
|
828
|
-
* @returns {string}
|
829
|
-
*/
|
830
|
-
function getFilterConfigKey() {
|
831
|
-
return generateUniqueConfigKey("datatable", this?.id, "filter");
|
832
|
-
}
|
833
|
-
|
834
1052
|
/**
|
835
1053
|
* @private
|
836
1054
|
* @returns {Promise<unknown>}
|
@@ -849,7 +1067,7 @@ function initFromConfig() {
|
|
849
1067
|
host
|
850
1068
|
.getConfig(configKey)
|
851
1069
|
.then((config) => {
|
852
|
-
if (config) {
|
1070
|
+
if (config && isObject(config)) {
|
853
1071
|
this[settingsSymbol].setOptions(config);
|
854
1072
|
}
|
855
1073
|
resolve();
|
@@ -860,7 +1078,17 @@ function initFromConfig() {
|
|
860
1078
|
return;
|
861
1079
|
}
|
862
1080
|
|
863
|
-
|
1081
|
+
// config not written
|
1082
|
+
if (error?.message?.match(/is not defined/)) {
|
1083
|
+
resolve();
|
1084
|
+
return;
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
addAttributeToken(
|
1088
|
+
this,
|
1089
|
+
ATTRIBUTE_ERRORMESSAGE,
|
1090
|
+
error?.message || error,
|
1091
|
+
);
|
864
1092
|
reject(error);
|
865
1093
|
});
|
866
1094
|
});
|
@@ -880,7 +1108,7 @@ function updateConfig() {
|
|
880
1108
|
try {
|
881
1109
|
host.setConfig(configKey, this[settingsSymbol].getOptions());
|
882
1110
|
} catch (error) {
|
883
|
-
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE,
|
1111
|
+
addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, error?.message || error);
|
884
1112
|
}
|
885
1113
|
}
|
886
1114
|
|
@@ -898,15 +1126,31 @@ function getTemplate() {
|
|
898
1126
|
<slot name="hidden"></slot>
|
899
1127
|
</div>
|
900
1128
|
<div data-monster-role="select-and-search">
|
1129
|
+
<monster-message-state-button data-monster-role="search-button" class="stretched-control"
|
1130
|
+
data-monster-replace="path:labels.search">
|
1131
|
+
</monster-message-state-button>
|
901
1132
|
<monster-select class="stretched-control"
|
902
1133
|
data-monster-selected-template="summary"
|
903
1134
|
data-monster-option-type="checkbox"
|
904
1135
|
data-monster-option-filter-mode="options"
|
905
1136
|
data-monster-option-filter-position="popper"
|
906
1137
|
data-monster-role="filter-select"></monster-select>
|
907
|
-
<monster-
|
908
|
-
|
909
|
-
|
1138
|
+
<monster-popper-button data-monster-role="save-button" class="stretched-control"
|
1139
|
+
data-monster-attributes="data-monster-visible path:storedConfig.enabled">
|
1140
|
+
<div slot="button">\${filter-save-label}</div>
|
1141
|
+
<div class="monster-form" data-monster-role="form">
|
1142
|
+
|
1143
|
+
<label for="filter-name">\${filter-name-label}
|
1144
|
+
<input name="filter-name"
|
1145
|
+
type="search"
|
1146
|
+
class="monster-margin-bottom-5"></label>
|
1147
|
+
<monster-message-state-button
|
1148
|
+
data-monster-role="save-action-button"
|
1149
|
+
data-monster-option-labels-button="\${filter-save-label}">
|
1150
|
+
</monster-message-state-button>
|
1151
|
+
|
1152
|
+
</div>
|
1153
|
+
</monster-popper-button>
|
910
1154
|
<monster-button data-monster-role="reset-button" class="stretched-control"
|
911
1155
|
data-monster-replace="path:labels.reset">
|
912
1156
|
</monster-button>
|