myio-js-library 0.1.498 → 0.1.499
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/dist/index.cjs +131 -22
- package/dist/index.d.cts +38 -2
- package/dist/index.js +131 -22
- package/dist/myio-js-library.umd.js +131 -22
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1162,7 +1162,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
1162
1162
|
// package.json
|
|
1163
1163
|
var package_default = {
|
|
1164
1164
|
name: "myio-js-library",
|
|
1165
|
-
version: "0.1.
|
|
1165
|
+
version: "0.1.499",
|
|
1166
1166
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
1167
1167
|
license: "MIT",
|
|
1168
1168
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -5548,7 +5548,7 @@ var MyIOSelectionStoreClass = class _MyIOSelectionStoreClass {
|
|
|
5548
5548
|
if (_MyIOSelectionStoreClass.GlobalDebug) {
|
|
5549
5549
|
console.trace("[SelectionStore] Constructor called from:");
|
|
5550
5550
|
}
|
|
5551
|
-
this.MAX_SELECTION =
|
|
5551
|
+
this.MAX_SELECTION = 20;
|
|
5552
5552
|
this.state = { selectedDevice: null };
|
|
5553
5553
|
this.selectedIds = /* @__PURE__ */ new Set();
|
|
5554
5554
|
this.entities = /* @__PURE__ */ new Map();
|
|
@@ -5633,6 +5633,45 @@ var MyIOSelectionStoreClass = class _MyIOSelectionStoreClass {
|
|
|
5633
5633
|
this._emitSelectionChange("clear");
|
|
5634
5634
|
this._trackEvent("footer_dock.clear_all", { count: 0 });
|
|
5635
5635
|
}
|
|
5636
|
+
/**
|
|
5637
|
+
* Updates the maximum number of concurrent selections at runtime.
|
|
5638
|
+
* Typically called once from MAIN_VIEW onInit with the value from widget
|
|
5639
|
+
* settings so operators can configure it per-customer without code changes.
|
|
5640
|
+
*
|
|
5641
|
+
* If the current selection already exceeds the new limit, keeps the first N
|
|
5642
|
+
* in insertion order, drops the rest, and emits `selection:change` plus
|
|
5643
|
+
* `selection:limit-reached` so any UI reflects the truncation.
|
|
5644
|
+
*
|
|
5645
|
+
* @param {number} n - new maximum (integer ≥ 1)
|
|
5646
|
+
*/
|
|
5647
|
+
setMaxSelection(n) {
|
|
5648
|
+
const v = Math.floor(Number(n));
|
|
5649
|
+
if (!Number.isFinite(v) || v < 1) {
|
|
5650
|
+
this._log("warn", `[MyIOSelectionStoreClass] Invalid maxSelection, ignoring:`, n);
|
|
5651
|
+
return;
|
|
5652
|
+
}
|
|
5653
|
+
if (v === this.MAX_SELECTION) return;
|
|
5654
|
+
const prev = this.MAX_SELECTION;
|
|
5655
|
+
this.MAX_SELECTION = v;
|
|
5656
|
+
this._log("log", `[MyIOSelectionStoreClass] MAX_SELECTION ${prev} \u2192 ${v}`);
|
|
5657
|
+
if (this.selectedIds.size > v) {
|
|
5658
|
+
const kept = Array.from(this.selectedIds).slice(0, v);
|
|
5659
|
+
this.selectedIds = new Set(kept);
|
|
5660
|
+
this._emitSelectionChange("truncate");
|
|
5661
|
+
this._emit("selection:limit-reached", {
|
|
5662
|
+
maxAllowed: v,
|
|
5663
|
+
currentCount: this.selectedIds.size,
|
|
5664
|
+
truncated: true
|
|
5665
|
+
});
|
|
5666
|
+
}
|
|
5667
|
+
}
|
|
5668
|
+
/**
|
|
5669
|
+
* Returns the currently active selection limit.
|
|
5670
|
+
* @returns {number}
|
|
5671
|
+
*/
|
|
5672
|
+
getMaxSelection() {
|
|
5673
|
+
return this.MAX_SELECTION;
|
|
5674
|
+
}
|
|
5636
5675
|
syncFromCheckbox(id, checked) {
|
|
5637
5676
|
if (typeof id !== "string" || typeof checked !== "boolean") return;
|
|
5638
5677
|
if (checked && !this.isSelected(id)) {
|
|
@@ -30587,27 +30626,36 @@ var EnergyModalView = class {
|
|
|
30587
30626
|
}
|
|
30588
30627
|
/**
|
|
30589
30628
|
* (Re)builds the DateRangePicker. Time picker only shown when granularity = '1h'.
|
|
30590
|
-
*
|
|
30629
|
+
*
|
|
30630
|
+
* Preserves only the DATE portion of the previous range — times are always
|
|
30631
|
+
* reset to 00:00:00 (start) / 23:59:59 (end) on every rebuild, so toggling
|
|
30632
|
+
* the granularity tab reliably brings back the full-day default. In 1h
|
|
30633
|
+
* mode the user can then adjust hours/minutes freely; switching back to
|
|
30634
|
+
* 1d wipes any custom time and restores the full-day boundaries.
|
|
30591
30635
|
*/
|
|
30592
30636
|
async rebuildDateRangePicker(input) {
|
|
30593
|
-
|
|
30594
|
-
|
|
30637
|
+
const toYmd = (v) => {
|
|
30638
|
+
if (!v) return void 0;
|
|
30639
|
+
if (v instanceof Date) return v.toISOString().split("T")[0];
|
|
30640
|
+
if (typeof v === "string") return v.split("T")[0];
|
|
30641
|
+
return void 0;
|
|
30642
|
+
};
|
|
30643
|
+
let startYmd;
|
|
30644
|
+
let endYmd;
|
|
30595
30645
|
if (this.dateRangePicker) {
|
|
30596
30646
|
try {
|
|
30597
30647
|
const current = this.dateRangePicker.getDates();
|
|
30598
|
-
|
|
30599
|
-
|
|
30648
|
+
startYmd = toYmd(current.startISO);
|
|
30649
|
+
endYmd = toYmd(current.endISO);
|
|
30600
30650
|
} catch {
|
|
30601
30651
|
}
|
|
30602
30652
|
this.dateRangePicker.destroy();
|
|
30603
30653
|
this.dateRangePicker = null;
|
|
30604
30654
|
}
|
|
30605
|
-
if (!
|
|
30606
|
-
|
|
30607
|
-
}
|
|
30608
|
-
|
|
30609
|
-
presetEnd = this.config.params.endDate instanceof Date ? this.config.params.endDate.toISOString().split("T")[0] : this.config.params.endDate;
|
|
30610
|
-
}
|
|
30655
|
+
if (!startYmd) startYmd = toYmd(this.config.params.startDate);
|
|
30656
|
+
if (!endYmd) endYmd = toYmd(this.config.params.endDate);
|
|
30657
|
+
const presetStart = startYmd ? `${startYmd}T00:00:00-03:00` : void 0;
|
|
30658
|
+
const presetEnd = endYmd ? `${endYmd}T23:59:59-03:00` : void 0;
|
|
30611
30659
|
try {
|
|
30612
30660
|
this.dateRangePicker = await attach(input, {
|
|
30613
30661
|
presetStart,
|
|
@@ -31631,20 +31679,28 @@ var DeviceReportModal = class {
|
|
|
31631
31679
|
* Preserves the currently selected range when rebuilding after a granularity change.
|
|
31632
31680
|
*/
|
|
31633
31681
|
async rebuildDateRangePicker(input) {
|
|
31634
|
-
|
|
31635
|
-
|
|
31682
|
+
const toYmd = (v) => {
|
|
31683
|
+
if (!v) return void 0;
|
|
31684
|
+
if (v instanceof Date) return v.toISOString().split("T")[0];
|
|
31685
|
+
if (typeof v === "string") return v.split("T")[0];
|
|
31686
|
+
return void 0;
|
|
31687
|
+
};
|
|
31688
|
+
let startYmd;
|
|
31689
|
+
let endYmd;
|
|
31636
31690
|
if (this.dateRangePicker) {
|
|
31637
31691
|
try {
|
|
31638
31692
|
const current = this.dateRangePicker.getDates();
|
|
31639
|
-
|
|
31640
|
-
|
|
31693
|
+
startYmd = toYmd(current.startISO);
|
|
31694
|
+
endYmd = toYmd(current.endISO);
|
|
31641
31695
|
} catch {
|
|
31642
31696
|
}
|
|
31643
31697
|
this.dateRangePicker.destroy();
|
|
31644
31698
|
this.dateRangePicker = null;
|
|
31645
31699
|
}
|
|
31646
|
-
if (!
|
|
31647
|
-
if (!
|
|
31700
|
+
if (!startYmd) startYmd = toYmd(this.getDefaultStartDate());
|
|
31701
|
+
if (!endYmd) endYmd = toYmd(this.getDefaultEndDate());
|
|
31702
|
+
const presetStart = startYmd ? `${startYmd}T00:00:00-03:00` : void 0;
|
|
31703
|
+
const presetEnd = endYmd ? `${endYmd}T23:59:59-03:00` : void 0;
|
|
31648
31704
|
try {
|
|
31649
31705
|
this.dateRangePicker = await attach(input, {
|
|
31650
31706
|
presetStart,
|
|
@@ -41746,7 +41802,7 @@ var DEFAULT_CONFIG_TEMPLATE2 = {
|
|
|
41746
41802
|
emptyMessage: "Selecione dispositivos para comparar",
|
|
41747
41803
|
compareButtonLabel: "Comparar",
|
|
41748
41804
|
clearButtonLabel: "Limpar",
|
|
41749
|
-
maxSelections:
|
|
41805
|
+
maxSelections: 20,
|
|
41750
41806
|
darkMode: DEFAULT_DARK_THEME2,
|
|
41751
41807
|
lightMode: DEFAULT_LIGHT_THEME2
|
|
41752
41808
|
};
|
|
@@ -43962,9 +44018,28 @@ var InternalSelectionStore = class {
|
|
|
43962
44018
|
entities = /* @__PURE__ */ new Map();
|
|
43963
44019
|
listeners = /* @__PURE__ */ new Map();
|
|
43964
44020
|
maxSelections;
|
|
43965
|
-
constructor(maxSelections =
|
|
44021
|
+
constructor(maxSelections = DEFAULT_CONFIG_TEMPLATE2.maxSelections ?? 20) {
|
|
43966
44022
|
this.maxSelections = maxSelections;
|
|
43967
44023
|
}
|
|
44024
|
+
/**
|
|
44025
|
+
* Updates the maximum selection limit at runtime.
|
|
44026
|
+
* If the current selection exceeds the new limit, trims the oldest
|
|
44027
|
+
* entries (insertion order) and emits `selection:change`.
|
|
44028
|
+
*/
|
|
44029
|
+
setMaxSelections(n) {
|
|
44030
|
+
const v = Math.floor(Number(n));
|
|
44031
|
+
if (!Number.isFinite(v) || v < 1) return;
|
|
44032
|
+
this.maxSelections = v;
|
|
44033
|
+
if (this.entities.size > v) {
|
|
44034
|
+
const kept = Array.from(this.entities.entries()).slice(0, v);
|
|
44035
|
+
this.entities = new Map(kept);
|
|
44036
|
+
this.emit("selection:change", this.getSelectedEntities());
|
|
44037
|
+
this.emit("selection:limit-reached", v);
|
|
44038
|
+
}
|
|
44039
|
+
}
|
|
44040
|
+
getMaxSelections() {
|
|
44041
|
+
return this.maxSelections;
|
|
44042
|
+
}
|
|
43968
44043
|
on(event, handler) {
|
|
43969
44044
|
if (!this.listeners.has(event)) {
|
|
43970
44045
|
this.listeners.set(event, []);
|
|
@@ -44017,7 +44092,7 @@ var FooterController = class {
|
|
|
44017
44092
|
constructor(params, view) {
|
|
44018
44093
|
this.params = params;
|
|
44019
44094
|
this.view = view;
|
|
44020
|
-
this.maxSelections = params.maxSelections ??
|
|
44095
|
+
this.maxSelections = params.maxSelections ?? params.configTemplate?.maxSelections ?? DEFAULT_CONFIG_TEMPLATE2.maxSelections ?? 20;
|
|
44021
44096
|
this.log = createLogger2(params.debug ?? false);
|
|
44022
44097
|
if (params.colors) {
|
|
44023
44098
|
setAlertColors(params.colors);
|
|
@@ -44361,6 +44436,38 @@ var FooterController = class {
|
|
|
44361
44436
|
hideAlert() {
|
|
44362
44437
|
hideAlert();
|
|
44363
44438
|
}
|
|
44439
|
+
/**
|
|
44440
|
+
* Updates the maximum selection limit at runtime. If the footer is using
|
|
44441
|
+
* an InternalSelectionStore, the store's limit is updated too; external
|
|
44442
|
+
* stores are left untouched (they own their own limit).
|
|
44443
|
+
*
|
|
44444
|
+
* If the current selection exceeds the new limit, the underlying store
|
|
44445
|
+
* will emit `selection:limit-reached` (and may truncate), and the view
|
|
44446
|
+
* re-renders via the existing selection:change handler.
|
|
44447
|
+
*/
|
|
44448
|
+
setMaxSelections(n) {
|
|
44449
|
+
const v = Math.floor(Number(n));
|
|
44450
|
+
if (!Number.isFinite(v) || v < 1) {
|
|
44451
|
+
this.log.warn("setMaxSelections: invalid value, ignoring:", n);
|
|
44452
|
+
return;
|
|
44453
|
+
}
|
|
44454
|
+
this.maxSelections = v;
|
|
44455
|
+
if (this.store instanceof InternalSelectionStore) {
|
|
44456
|
+
this.store.setMaxSelections(v);
|
|
44457
|
+
} else {
|
|
44458
|
+
this.log.log(
|
|
44459
|
+
"setMaxSelections: external store detected \u2014 controller limit updated to",
|
|
44460
|
+
v,
|
|
44461
|
+
"but external store limit is not managed here. Call its own setter if supported."
|
|
44462
|
+
);
|
|
44463
|
+
}
|
|
44464
|
+
}
|
|
44465
|
+
/**
|
|
44466
|
+
* Returns the maximum selection limit currently enforced by the controller.
|
|
44467
|
+
*/
|
|
44468
|
+
getMaxSelections() {
|
|
44469
|
+
return this.maxSelections;
|
|
44470
|
+
}
|
|
44364
44471
|
/**
|
|
44365
44472
|
* Cleanup resources
|
|
44366
44473
|
*/
|
|
@@ -44396,6 +44503,8 @@ function createFooterComponent(params) {
|
|
|
44396
44503
|
clearSelection: () => controller.clearSelection(),
|
|
44397
44504
|
getSelectedEntities: () => controller.getSelectedEntities(),
|
|
44398
44505
|
getSelectionCount: () => controller.getSelectionCount(),
|
|
44506
|
+
setMaxSelections: (n) => controller.setMaxSelections(n),
|
|
44507
|
+
getMaxSelections: () => controller.getMaxSelections(),
|
|
44399
44508
|
// State methods
|
|
44400
44509
|
getCurrentUnitType: () => controller.getCurrentUnitType(),
|
|
44401
44510
|
setDateRange: (start, end) => controller.setDateRange(start, end),
|
package/dist/index.d.cts
CHANGED
|
@@ -3090,6 +3090,23 @@ declare class MyIOSelectionStoreClass {
|
|
|
3090
3090
|
remove(id: any): void;
|
|
3091
3091
|
toggle(id: any): void;
|
|
3092
3092
|
clear(): void;
|
|
3093
|
+
/**
|
|
3094
|
+
* Updates the maximum number of concurrent selections at runtime.
|
|
3095
|
+
* Typically called once from MAIN_VIEW onInit with the value from widget
|
|
3096
|
+
* settings so operators can configure it per-customer without code changes.
|
|
3097
|
+
*
|
|
3098
|
+
* If the current selection already exceeds the new limit, keeps the first N
|
|
3099
|
+
* in insertion order, drops the rest, and emits `selection:change` plus
|
|
3100
|
+
* `selection:limit-reached` so any UI reflects the truncation.
|
|
3101
|
+
*
|
|
3102
|
+
* @param {number} n - new maximum (integer ≥ 1)
|
|
3103
|
+
*/
|
|
3104
|
+
setMaxSelection(n: number): void;
|
|
3105
|
+
/**
|
|
3106
|
+
* Returns the currently active selection limit.
|
|
3107
|
+
* @returns {number}
|
|
3108
|
+
*/
|
|
3109
|
+
getMaxSelection(): number;
|
|
3093
3110
|
syncFromCheckbox(id: any, checked: any): void;
|
|
3094
3111
|
registerEntity(entity: any): void;
|
|
3095
3112
|
unregisterEntity(id: any): void;
|
|
@@ -5499,6 +5516,10 @@ interface SelectionStore {
|
|
|
5499
5516
|
clear: () => void;
|
|
5500
5517
|
getSelectedEntities: () => SelectedEntity[];
|
|
5501
5518
|
getSelectionCount: () => number;
|
|
5519
|
+
/** Optional runtime setter — present on InternalSelectionStore and on
|
|
5520
|
+
* MyIOSelectionStore (when exposed). Callers should feature-detect. */
|
|
5521
|
+
setMaxSelections?: (n: number) => void;
|
|
5522
|
+
getMaxSelections?: () => number;
|
|
5502
5523
|
}
|
|
5503
5524
|
/**
|
|
5504
5525
|
* Date range for comparison modals
|
|
@@ -5523,7 +5544,8 @@ interface FooterComponentParams {
|
|
|
5523
5544
|
configTemplate?: FooterConfigTemplate;
|
|
5524
5545
|
/** Selection store instance (default: window.MyIOSelectionStore) */
|
|
5525
5546
|
selectionStore?: SelectionStore;
|
|
5526
|
-
/** Maximum number of selections allowed
|
|
5547
|
+
/** Maximum number of selections allowed.
|
|
5548
|
+
* Resolution order: this param > configTemplate.maxSelections > DEFAULT_CONFIG_TEMPLATE.maxSelections (20). */
|
|
5527
5549
|
maxSelections?: number;
|
|
5528
5550
|
/** Message shown when dock is empty */
|
|
5529
5551
|
emptyMessage?: string;
|
|
@@ -5585,6 +5607,20 @@ interface FooterComponentInstance {
|
|
|
5585
5607
|
* Get the count of selected entities
|
|
5586
5608
|
*/
|
|
5587
5609
|
getSelectionCount: () => number;
|
|
5610
|
+
/**
|
|
5611
|
+
* Update the maximum number of selections at runtime.
|
|
5612
|
+
* If the current selection exceeds the new limit, it will be truncated
|
|
5613
|
+
* (insertion order) and `selection:limit-reached` will be emitted.
|
|
5614
|
+
*
|
|
5615
|
+
* Note: when the footer is wired to an external store that does not
|
|
5616
|
+
* implement `setMaxSelections`, the controller's internal limit is
|
|
5617
|
+
* updated but the external store's own limit is left untouched.
|
|
5618
|
+
*/
|
|
5619
|
+
setMaxSelections: (n: number) => void;
|
|
5620
|
+
/**
|
|
5621
|
+
* Get the maximum number of selections currently enforced.
|
|
5622
|
+
*/
|
|
5623
|
+
getMaxSelections: () => number;
|
|
5588
5624
|
/**
|
|
5589
5625
|
* Get the current unit type (energy, water, tank, temperature, or null)
|
|
5590
5626
|
*/
|
|
@@ -5640,7 +5676,7 @@ interface FooterComponentInstance {
|
|
|
5640
5676
|
* const footer = createFooterComponent({
|
|
5641
5677
|
* container: document.getElementById('footer-container'),
|
|
5642
5678
|
* theme: 'dark',
|
|
5643
|
-
* maxSelections:
|
|
5679
|
+
* maxSelections: 20,
|
|
5644
5680
|
* onCompareClick: (entities, unitType) => {
|
|
5645
5681
|
* console.log('Compare clicked:', entities.length, unitType);
|
|
5646
5682
|
* },
|
package/dist/index.js
CHANGED
|
@@ -546,7 +546,7 @@ var init_template_card = __esm({
|
|
|
546
546
|
// package.json
|
|
547
547
|
var package_default = {
|
|
548
548
|
name: "myio-js-library",
|
|
549
|
-
version: "0.1.
|
|
549
|
+
version: "0.1.499",
|
|
550
550
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
551
551
|
license: "MIT",
|
|
552
552
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -4932,7 +4932,7 @@ var MyIOSelectionStoreClass = class _MyIOSelectionStoreClass {
|
|
|
4932
4932
|
if (_MyIOSelectionStoreClass.GlobalDebug) {
|
|
4933
4933
|
console.trace("[SelectionStore] Constructor called from:");
|
|
4934
4934
|
}
|
|
4935
|
-
this.MAX_SELECTION =
|
|
4935
|
+
this.MAX_SELECTION = 20;
|
|
4936
4936
|
this.state = { selectedDevice: null };
|
|
4937
4937
|
this.selectedIds = /* @__PURE__ */ new Set();
|
|
4938
4938
|
this.entities = /* @__PURE__ */ new Map();
|
|
@@ -5017,6 +5017,45 @@ var MyIOSelectionStoreClass = class _MyIOSelectionStoreClass {
|
|
|
5017
5017
|
this._emitSelectionChange("clear");
|
|
5018
5018
|
this._trackEvent("footer_dock.clear_all", { count: 0 });
|
|
5019
5019
|
}
|
|
5020
|
+
/**
|
|
5021
|
+
* Updates the maximum number of concurrent selections at runtime.
|
|
5022
|
+
* Typically called once from MAIN_VIEW onInit with the value from widget
|
|
5023
|
+
* settings so operators can configure it per-customer without code changes.
|
|
5024
|
+
*
|
|
5025
|
+
* If the current selection already exceeds the new limit, keeps the first N
|
|
5026
|
+
* in insertion order, drops the rest, and emits `selection:change` plus
|
|
5027
|
+
* `selection:limit-reached` so any UI reflects the truncation.
|
|
5028
|
+
*
|
|
5029
|
+
* @param {number} n - new maximum (integer ≥ 1)
|
|
5030
|
+
*/
|
|
5031
|
+
setMaxSelection(n) {
|
|
5032
|
+
const v = Math.floor(Number(n));
|
|
5033
|
+
if (!Number.isFinite(v) || v < 1) {
|
|
5034
|
+
this._log("warn", `[MyIOSelectionStoreClass] Invalid maxSelection, ignoring:`, n);
|
|
5035
|
+
return;
|
|
5036
|
+
}
|
|
5037
|
+
if (v === this.MAX_SELECTION) return;
|
|
5038
|
+
const prev = this.MAX_SELECTION;
|
|
5039
|
+
this.MAX_SELECTION = v;
|
|
5040
|
+
this._log("log", `[MyIOSelectionStoreClass] MAX_SELECTION ${prev} \u2192 ${v}`);
|
|
5041
|
+
if (this.selectedIds.size > v) {
|
|
5042
|
+
const kept = Array.from(this.selectedIds).slice(0, v);
|
|
5043
|
+
this.selectedIds = new Set(kept);
|
|
5044
|
+
this._emitSelectionChange("truncate");
|
|
5045
|
+
this._emit("selection:limit-reached", {
|
|
5046
|
+
maxAllowed: v,
|
|
5047
|
+
currentCount: this.selectedIds.size,
|
|
5048
|
+
truncated: true
|
|
5049
|
+
});
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5052
|
+
/**
|
|
5053
|
+
* Returns the currently active selection limit.
|
|
5054
|
+
* @returns {number}
|
|
5055
|
+
*/
|
|
5056
|
+
getMaxSelection() {
|
|
5057
|
+
return this.MAX_SELECTION;
|
|
5058
|
+
}
|
|
5020
5059
|
syncFromCheckbox(id, checked) {
|
|
5021
5060
|
if (typeof id !== "string" || typeof checked !== "boolean") return;
|
|
5022
5061
|
if (checked && !this.isSelected(id)) {
|
|
@@ -29971,27 +30010,36 @@ var EnergyModalView = class {
|
|
|
29971
30010
|
}
|
|
29972
30011
|
/**
|
|
29973
30012
|
* (Re)builds the DateRangePicker. Time picker only shown when granularity = '1h'.
|
|
29974
|
-
*
|
|
30013
|
+
*
|
|
30014
|
+
* Preserves only the DATE portion of the previous range — times are always
|
|
30015
|
+
* reset to 00:00:00 (start) / 23:59:59 (end) on every rebuild, so toggling
|
|
30016
|
+
* the granularity tab reliably brings back the full-day default. In 1h
|
|
30017
|
+
* mode the user can then adjust hours/minutes freely; switching back to
|
|
30018
|
+
* 1d wipes any custom time and restores the full-day boundaries.
|
|
29975
30019
|
*/
|
|
29976
30020
|
async rebuildDateRangePicker(input) {
|
|
29977
|
-
|
|
29978
|
-
|
|
30021
|
+
const toYmd = (v) => {
|
|
30022
|
+
if (!v) return void 0;
|
|
30023
|
+
if (v instanceof Date) return v.toISOString().split("T")[0];
|
|
30024
|
+
if (typeof v === "string") return v.split("T")[0];
|
|
30025
|
+
return void 0;
|
|
30026
|
+
};
|
|
30027
|
+
let startYmd;
|
|
30028
|
+
let endYmd;
|
|
29979
30029
|
if (this.dateRangePicker) {
|
|
29980
30030
|
try {
|
|
29981
30031
|
const current = this.dateRangePicker.getDates();
|
|
29982
|
-
|
|
29983
|
-
|
|
30032
|
+
startYmd = toYmd(current.startISO);
|
|
30033
|
+
endYmd = toYmd(current.endISO);
|
|
29984
30034
|
} catch {
|
|
29985
30035
|
}
|
|
29986
30036
|
this.dateRangePicker.destroy();
|
|
29987
30037
|
this.dateRangePicker = null;
|
|
29988
30038
|
}
|
|
29989
|
-
if (!
|
|
29990
|
-
|
|
29991
|
-
}
|
|
29992
|
-
|
|
29993
|
-
presetEnd = this.config.params.endDate instanceof Date ? this.config.params.endDate.toISOString().split("T")[0] : this.config.params.endDate;
|
|
29994
|
-
}
|
|
30039
|
+
if (!startYmd) startYmd = toYmd(this.config.params.startDate);
|
|
30040
|
+
if (!endYmd) endYmd = toYmd(this.config.params.endDate);
|
|
30041
|
+
const presetStart = startYmd ? `${startYmd}T00:00:00-03:00` : void 0;
|
|
30042
|
+
const presetEnd = endYmd ? `${endYmd}T23:59:59-03:00` : void 0;
|
|
29995
30043
|
try {
|
|
29996
30044
|
this.dateRangePicker = await attach(input, {
|
|
29997
30045
|
presetStart,
|
|
@@ -31015,20 +31063,28 @@ var DeviceReportModal = class {
|
|
|
31015
31063
|
* Preserves the currently selected range when rebuilding after a granularity change.
|
|
31016
31064
|
*/
|
|
31017
31065
|
async rebuildDateRangePicker(input) {
|
|
31018
|
-
|
|
31019
|
-
|
|
31066
|
+
const toYmd = (v) => {
|
|
31067
|
+
if (!v) return void 0;
|
|
31068
|
+
if (v instanceof Date) return v.toISOString().split("T")[0];
|
|
31069
|
+
if (typeof v === "string") return v.split("T")[0];
|
|
31070
|
+
return void 0;
|
|
31071
|
+
};
|
|
31072
|
+
let startYmd;
|
|
31073
|
+
let endYmd;
|
|
31020
31074
|
if (this.dateRangePicker) {
|
|
31021
31075
|
try {
|
|
31022
31076
|
const current = this.dateRangePicker.getDates();
|
|
31023
|
-
|
|
31024
|
-
|
|
31077
|
+
startYmd = toYmd(current.startISO);
|
|
31078
|
+
endYmd = toYmd(current.endISO);
|
|
31025
31079
|
} catch {
|
|
31026
31080
|
}
|
|
31027
31081
|
this.dateRangePicker.destroy();
|
|
31028
31082
|
this.dateRangePicker = null;
|
|
31029
31083
|
}
|
|
31030
|
-
if (!
|
|
31031
|
-
if (!
|
|
31084
|
+
if (!startYmd) startYmd = toYmd(this.getDefaultStartDate());
|
|
31085
|
+
if (!endYmd) endYmd = toYmd(this.getDefaultEndDate());
|
|
31086
|
+
const presetStart = startYmd ? `${startYmd}T00:00:00-03:00` : void 0;
|
|
31087
|
+
const presetEnd = endYmd ? `${endYmd}T23:59:59-03:00` : void 0;
|
|
31032
31088
|
try {
|
|
31033
31089
|
this.dateRangePicker = await attach(input, {
|
|
31034
31090
|
presetStart,
|
|
@@ -41130,7 +41186,7 @@ var DEFAULT_CONFIG_TEMPLATE2 = {
|
|
|
41130
41186
|
emptyMessage: "Selecione dispositivos para comparar",
|
|
41131
41187
|
compareButtonLabel: "Comparar",
|
|
41132
41188
|
clearButtonLabel: "Limpar",
|
|
41133
|
-
maxSelections:
|
|
41189
|
+
maxSelections: 20,
|
|
41134
41190
|
darkMode: DEFAULT_DARK_THEME2,
|
|
41135
41191
|
lightMode: DEFAULT_LIGHT_THEME2
|
|
41136
41192
|
};
|
|
@@ -43346,9 +43402,28 @@ var InternalSelectionStore = class {
|
|
|
43346
43402
|
entities = /* @__PURE__ */ new Map();
|
|
43347
43403
|
listeners = /* @__PURE__ */ new Map();
|
|
43348
43404
|
maxSelections;
|
|
43349
|
-
constructor(maxSelections =
|
|
43405
|
+
constructor(maxSelections = DEFAULT_CONFIG_TEMPLATE2.maxSelections ?? 20) {
|
|
43350
43406
|
this.maxSelections = maxSelections;
|
|
43351
43407
|
}
|
|
43408
|
+
/**
|
|
43409
|
+
* Updates the maximum selection limit at runtime.
|
|
43410
|
+
* If the current selection exceeds the new limit, trims the oldest
|
|
43411
|
+
* entries (insertion order) and emits `selection:change`.
|
|
43412
|
+
*/
|
|
43413
|
+
setMaxSelections(n) {
|
|
43414
|
+
const v = Math.floor(Number(n));
|
|
43415
|
+
if (!Number.isFinite(v) || v < 1) return;
|
|
43416
|
+
this.maxSelections = v;
|
|
43417
|
+
if (this.entities.size > v) {
|
|
43418
|
+
const kept = Array.from(this.entities.entries()).slice(0, v);
|
|
43419
|
+
this.entities = new Map(kept);
|
|
43420
|
+
this.emit("selection:change", this.getSelectedEntities());
|
|
43421
|
+
this.emit("selection:limit-reached", v);
|
|
43422
|
+
}
|
|
43423
|
+
}
|
|
43424
|
+
getMaxSelections() {
|
|
43425
|
+
return this.maxSelections;
|
|
43426
|
+
}
|
|
43352
43427
|
on(event, handler) {
|
|
43353
43428
|
if (!this.listeners.has(event)) {
|
|
43354
43429
|
this.listeners.set(event, []);
|
|
@@ -43401,7 +43476,7 @@ var FooterController = class {
|
|
|
43401
43476
|
constructor(params, view) {
|
|
43402
43477
|
this.params = params;
|
|
43403
43478
|
this.view = view;
|
|
43404
|
-
this.maxSelections = params.maxSelections ??
|
|
43479
|
+
this.maxSelections = params.maxSelections ?? params.configTemplate?.maxSelections ?? DEFAULT_CONFIG_TEMPLATE2.maxSelections ?? 20;
|
|
43405
43480
|
this.log = createLogger2(params.debug ?? false);
|
|
43406
43481
|
if (params.colors) {
|
|
43407
43482
|
setAlertColors(params.colors);
|
|
@@ -43745,6 +43820,38 @@ var FooterController = class {
|
|
|
43745
43820
|
hideAlert() {
|
|
43746
43821
|
hideAlert();
|
|
43747
43822
|
}
|
|
43823
|
+
/**
|
|
43824
|
+
* Updates the maximum selection limit at runtime. If the footer is using
|
|
43825
|
+
* an InternalSelectionStore, the store's limit is updated too; external
|
|
43826
|
+
* stores are left untouched (they own their own limit).
|
|
43827
|
+
*
|
|
43828
|
+
* If the current selection exceeds the new limit, the underlying store
|
|
43829
|
+
* will emit `selection:limit-reached` (and may truncate), and the view
|
|
43830
|
+
* re-renders via the existing selection:change handler.
|
|
43831
|
+
*/
|
|
43832
|
+
setMaxSelections(n) {
|
|
43833
|
+
const v = Math.floor(Number(n));
|
|
43834
|
+
if (!Number.isFinite(v) || v < 1) {
|
|
43835
|
+
this.log.warn("setMaxSelections: invalid value, ignoring:", n);
|
|
43836
|
+
return;
|
|
43837
|
+
}
|
|
43838
|
+
this.maxSelections = v;
|
|
43839
|
+
if (this.store instanceof InternalSelectionStore) {
|
|
43840
|
+
this.store.setMaxSelections(v);
|
|
43841
|
+
} else {
|
|
43842
|
+
this.log.log(
|
|
43843
|
+
"setMaxSelections: external store detected \u2014 controller limit updated to",
|
|
43844
|
+
v,
|
|
43845
|
+
"but external store limit is not managed here. Call its own setter if supported."
|
|
43846
|
+
);
|
|
43847
|
+
}
|
|
43848
|
+
}
|
|
43849
|
+
/**
|
|
43850
|
+
* Returns the maximum selection limit currently enforced by the controller.
|
|
43851
|
+
*/
|
|
43852
|
+
getMaxSelections() {
|
|
43853
|
+
return this.maxSelections;
|
|
43854
|
+
}
|
|
43748
43855
|
/**
|
|
43749
43856
|
* Cleanup resources
|
|
43750
43857
|
*/
|
|
@@ -43780,6 +43887,8 @@ function createFooterComponent(params) {
|
|
|
43780
43887
|
clearSelection: () => controller.clearSelection(),
|
|
43781
43888
|
getSelectedEntities: () => controller.getSelectedEntities(),
|
|
43782
43889
|
getSelectionCount: () => controller.getSelectionCount(),
|
|
43890
|
+
setMaxSelections: (n) => controller.setMaxSelections(n),
|
|
43891
|
+
getMaxSelections: () => controller.getMaxSelections(),
|
|
43783
43892
|
// State methods
|
|
43784
43893
|
getCurrentUnitType: () => controller.getCurrentUnitType(),
|
|
43785
43894
|
setDateRange: (start, end) => controller.setDateRange(start, end),
|