myio-js-library 0.1.21 → 0.1.22
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/README.md +235 -0
- package/dist/index.cjs +321 -10
- package/dist/index.d.cts +97 -5
- package/dist/index.js +320 -10
- package/dist/myio-js-library.umd.js +320 -10
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -945,6 +945,241 @@ The component includes premium MyIO styling with:
|
|
|
945
945
|
- Responsive design for mobile and desktop
|
|
946
946
|
- Portuguese month names and day abbreviations
|
|
947
947
|
|
|
948
|
+
### Premium Date Range Input Component
|
|
949
|
+
|
|
950
|
+
#### `createInputDateRangePickerInsideDIV(params: CreateInputDateRangePickerInsideDIVParams): Promise<DateRangeInputController>`
|
|
951
|
+
|
|
952
|
+
Creates a complete, beautifully styled date range input inside a target DIV container, combining the functionality of `createDateRangePicker` with premium MyIO styling. This component automatically creates the HTML structure, injects styling, and provides a clean API for ThingsBoard widgets and other applications.
|
|
953
|
+
|
|
954
|
+
**Parameters:**
|
|
955
|
+
- `params: CreateInputDateRangePickerInsideDIVParams` - Configuration object:
|
|
956
|
+
- `containerId: string` - The DIV id where the input will be created (required)
|
|
957
|
+
- `inputId: string` - The id to set on the created input (required)
|
|
958
|
+
- `label?: string` - Optional label text (default: "Período de Datas")
|
|
959
|
+
- `placeholder?: string` - Input placeholder (default: "Clique para selecionar período")
|
|
960
|
+
- `pickerOptions?: CreateDateRangePickerOptions` - Pass-through options for createDateRangePicker
|
|
961
|
+
- `classNames?: object` - Custom CSS classes for wrapper, label, input, and helper
|
|
962
|
+
- `injectStyles?: boolean` - Inject premium MyIO styling (default: true)
|
|
963
|
+
- `showHelper?: boolean` - Show helper text with format info (default: true)
|
|
964
|
+
|
|
965
|
+
**Returns:** Promise resolving to `DateRangeInputController` object with:
|
|
966
|
+
- `input: HTMLInputElement` - The created input element
|
|
967
|
+
- `container: HTMLElement` - The target container element
|
|
968
|
+
- `wrapper: HTMLElement` - The wrapper element created by this component
|
|
969
|
+
- `picker: DateRangeControl` - The date range picker instance
|
|
970
|
+
- `getDisplayValue(): string` - Get current display value from input
|
|
971
|
+
- `getDates(): DateRangeResult` - Get current date range data
|
|
972
|
+
- `setDates(startISO: string, endISO: string): void` - Set date range programmatically
|
|
973
|
+
- `setHelperText(text: string, type?: 'default' | 'success' | 'error'): void` - Update helper text
|
|
974
|
+
- `destroy(): void` - Clean up and remove all created elements
|
|
975
|
+
|
|
976
|
+
**Key Features:**
|
|
977
|
+
- **Automatic HTML Creation**: Creates complete styled input structure inside target DIV
|
|
978
|
+
- **Premium MyIO Styling**: Beautiful styling matching demos/energy.html with purple brand colors
|
|
979
|
+
- **Container-Based**: Works with any DIV container, perfect for ThingsBoard widgets
|
|
980
|
+
- **Accessibility Built-in**: ARIA labels, keyboard navigation, screen reader support
|
|
981
|
+
- **Responsive Design**: Mobile-friendly with proper touch targets
|
|
982
|
+
- **Error Handling**: Robust validation and graceful error recovery
|
|
983
|
+
- **Memory Management**: Proper cleanup with destroy() method
|
|
984
|
+
|
|
985
|
+
**Usage Example:**
|
|
986
|
+
```javascript
|
|
987
|
+
import { createInputDateRangePickerInsideDIV } from 'myio-js-library';
|
|
988
|
+
|
|
989
|
+
const controller = await createInputDateRangePickerInsideDIV({
|
|
990
|
+
containerId: 'date-picker-container',
|
|
991
|
+
inputId: 'energy-date-range',
|
|
992
|
+
label: 'Período de Análise',
|
|
993
|
+
pickerOptions: {
|
|
994
|
+
presetStart: '2025-09-01',
|
|
995
|
+
presetEnd: '2025-09-25',
|
|
996
|
+
onApply: (result) => {
|
|
997
|
+
console.log('Date range selected:', result);
|
|
998
|
+
// result.startISO: "2025-09-01T00:00:00-03:00"
|
|
999
|
+
// result.endISO: "2025-09-25T23:59:59-03:00"
|
|
1000
|
+
loadEnergyData(result.startISO, result.endISO);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
// Get current selection
|
|
1006
|
+
const dates = controller.getDates();
|
|
1007
|
+
console.log('Current range:', dates.startISO, 'to', dates.endISO);
|
|
1008
|
+
|
|
1009
|
+
// Update helper text
|
|
1010
|
+
controller.setHelperText('Período válido selecionado', 'success');
|
|
1011
|
+
|
|
1012
|
+
// Clean up when done
|
|
1013
|
+
controller.destroy();
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
**ThingsBoard Widget Integration:**
|
|
1017
|
+
```html
|
|
1018
|
+
<script src="https://unpkg.com/myio-js-library@latest/dist/myio-js-library.umd.min.js"></script>
|
|
1019
|
+
<script>
|
|
1020
|
+
const { createInputDateRangePickerInsideDIV } = MyIOLibrary;
|
|
1021
|
+
|
|
1022
|
+
// In your widget's onInit function
|
|
1023
|
+
self.onInit = async function() {
|
|
1024
|
+
try {
|
|
1025
|
+
// Create date range picker in existing container
|
|
1026
|
+
self.dateRangePicker = await createInputDateRangePickerInsideDIV({
|
|
1027
|
+
containerId: 'widget-date-container',
|
|
1028
|
+
inputId: 'energy-widget-dates',
|
|
1029
|
+
label: 'Período de Datas',
|
|
1030
|
+
placeholder: 'Selecione o período de análise',
|
|
1031
|
+
pickerOptions: {
|
|
1032
|
+
maxRangeDays: 31,
|
|
1033
|
+
onApply: (result) => {
|
|
1034
|
+
// Update widget state and reload data
|
|
1035
|
+
updateWidgetData(result.startISO, result.endISO);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
console.log('[ENERGY] Date range picker initialized successfully');
|
|
1041
|
+
} catch (error) {
|
|
1042
|
+
console.error('[ENERGY] Failed to initialize date picker:', error);
|
|
1043
|
+
// Fallback to legacy implementation
|
|
1044
|
+
initLegacyDatePicker();
|
|
1045
|
+
}
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
// Clean up on widget destroy
|
|
1049
|
+
self.onDestroy = function() {
|
|
1050
|
+
if (self.dateRangePicker) {
|
|
1051
|
+
self.dateRangePicker.destroy();
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
</script>
|
|
1055
|
+
```
|
|
1056
|
+
|
|
1057
|
+
**Premium Styling Features:**
|
|
1058
|
+
- **MyIO Brand Colors**: Purple theme (#4A148C) with hover effects
|
|
1059
|
+
- **Responsive Layout**: Adapts to mobile and desktop with proper spacing
|
|
1060
|
+
- **Accessibility**: High contrast mode support, reduced motion support
|
|
1061
|
+
- **Visual Feedback**: Hover states, focus indicators, success/error states
|
|
1062
|
+
- **Typography**: Roboto font family with proper line heights
|
|
1063
|
+
- **Shadow Effects**: Subtle shadows and smooth transitions
|
|
1064
|
+
|
|
1065
|
+
**Migration from Basic Implementation:**
|
|
1066
|
+
```javascript
|
|
1067
|
+
// OLD: Manual HTML + basic styling
|
|
1068
|
+
var $inputStart = $('input[name="startDatetimes"]');
|
|
1069
|
+
MyIOLibrary.createDateRangePicker($inputStart[0], options);
|
|
1070
|
+
|
|
1071
|
+
// NEW: Automatic creation + premium styling
|
|
1072
|
+
const controller = await MyIOLibrary.createInputDateRangePickerInsideDIV({
|
|
1073
|
+
containerId: 'date-container',
|
|
1074
|
+
inputId: 'startDatetimes',
|
|
1075
|
+
label: 'Período de Datas',
|
|
1076
|
+
pickerOptions: options
|
|
1077
|
+
});
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
### Premium Modal Components
|
|
1081
|
+
|
|
1082
|
+
The library includes four premium modal components for ThingsBoard dashboards that provide comprehensive device analytics and reporting capabilities.
|
|
1083
|
+
|
|
1084
|
+
#### `openDashboardPopupReport(params: OpenDeviceReportParams): ModalHandle`
|
|
1085
|
+
|
|
1086
|
+
Opens a device-specific daily consumption report modal with built-in date range picker, sortable table, and CSV export functionality.
|
|
1087
|
+
|
|
1088
|
+
**Parameters:**
|
|
1089
|
+
- `ingestionId: string` - Data ingestion identifier (required)
|
|
1090
|
+
- `deviceId?: string` - Optional device ID for additional metadata
|
|
1091
|
+
- `identifier?: string` - Device identifier/code (e.g., "ENTRADA-001", "CHILLER-A")
|
|
1092
|
+
- `label?: string` - Human-readable label/name (e.g., "Outback", "Shopping Center Norte")
|
|
1093
|
+
- `ui?: object` - UI configuration (theme, width)
|
|
1094
|
+
- `api: object` - API configuration:
|
|
1095
|
+
- `clientId?: string` - Client ID for data API
|
|
1096
|
+
- `clientSecret?: string` - Client secret for data API
|
|
1097
|
+
- `dataApiBaseUrl?: string` - Data API base URL
|
|
1098
|
+
- `ingestionToken?: string` - Token for data ingestion access
|
|
1099
|
+
|
|
1100
|
+
**Returns:** `ModalHandle` object with:
|
|
1101
|
+
- `close(): void` - Close the modal
|
|
1102
|
+
- `on(event: 'close'|'loaded'|'error', handler: Function): void` - Event listeners
|
|
1103
|
+
|
|
1104
|
+
**Key Features:**
|
|
1105
|
+
- **Built-in Date Range Picker**: No need to specify dates in parameters
|
|
1106
|
+
- **Automatic Data Loading**: Fetches daily consumption data for selected period
|
|
1107
|
+
- **Sortable Table**: Click column headers to sort by date or consumption
|
|
1108
|
+
- **CSV Export**: Download report data with proper Brazilian formatting
|
|
1109
|
+
- **Responsive Design**: Works on desktop and mobile devices
|
|
1110
|
+
- **Error Handling**: Graceful error display and recovery
|
|
1111
|
+
|
|
1112
|
+
**Usage Example:**
|
|
1113
|
+
```javascript
|
|
1114
|
+
import { openDashboardPopupReport } from 'myio-js-library';
|
|
1115
|
+
|
|
1116
|
+
const modal = openDashboardPopupReport({
|
|
1117
|
+
ingestionId: 'abc123-ingestion-id',
|
|
1118
|
+
deviceId: 'device-uuid',
|
|
1119
|
+
identifier: 'ENTRADA-001',
|
|
1120
|
+
label: 'Outback Shopping',
|
|
1121
|
+
api: {
|
|
1122
|
+
clientId: 'your-client-id',
|
|
1123
|
+
clientSecret: 'your-client-secret',
|
|
1124
|
+
dataApiBaseUrl: 'https://api.data.apps.myio-bas.com',
|
|
1125
|
+
ingestionToken: 'your-ingestion-token'
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
modal.on('loaded', (data) => {
|
|
1130
|
+
console.log('Report loaded:', data.count, 'days');
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
modal.on('close', () => {
|
|
1134
|
+
console.log('Modal closed');
|
|
1135
|
+
});
|
|
1136
|
+
```
|
|
1137
|
+
|
|
1138
|
+
**UMD Usage (ThingsBoard widgets):**
|
|
1139
|
+
```html
|
|
1140
|
+
<script src="https://unpkg.com/myio-js-library@latest/dist/myio-js-library.umd.min.js"></script>
|
|
1141
|
+
<script>
|
|
1142
|
+
const { openDashboardPopupReport } = MyIOLibrary;
|
|
1143
|
+
|
|
1144
|
+
const modal = openDashboardPopupReport({
|
|
1145
|
+
ingestionId: 'demo-ingestion-123',
|
|
1146
|
+
deviceId: 'demo-device-123',
|
|
1147
|
+
identifier: 'ENTRADA-001',
|
|
1148
|
+
label: 'Outback',
|
|
1149
|
+
api: {
|
|
1150
|
+
clientId: 'demo-client',
|
|
1151
|
+
clientSecret: 'demo-secret',
|
|
1152
|
+
dataApiBaseUrl: 'https://api.data.apps.myio-bas.com',
|
|
1153
|
+
ingestionToken: 'demo-ingestion-token'
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
|
|
1157
|
+
modal.on('loaded', (data) => {
|
|
1158
|
+
console.log('Device report loaded with', data.count, 'days of data');
|
|
1159
|
+
});
|
|
1160
|
+
</script>
|
|
1161
|
+
```
|
|
1162
|
+
|
|
1163
|
+
**Migration from Legacy API:**
|
|
1164
|
+
```javascript
|
|
1165
|
+
// OLD API (deprecated)
|
|
1166
|
+
MyIOLibrary.openDashboardPopupReport({
|
|
1167
|
+
ingestionId: 'demo-ingestion-123',
|
|
1168
|
+
deviceLabel: 'Entrada Subestação', // ❌ Deprecated
|
|
1169
|
+
storeLabel: 'Outback', // ❌ Deprecated
|
|
1170
|
+
date: { start: '2025-09-01', end: '2025-09-25' }, // ❌ Deprecated
|
|
1171
|
+
api: { tbJwtToken: 'jwt-token' } // ❌ Deprecated
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
// NEW API (recommended)
|
|
1175
|
+
MyIOLibrary.openDashboardPopupReport({
|
|
1176
|
+
ingestionId: 'demo-ingestion-123',
|
|
1177
|
+
identifier: 'ENTRADA-001', // ✅ Clear device identifier
|
|
1178
|
+
label: 'Outback', // ✅ Clear human-readable name
|
|
1179
|
+
api: { ingestionToken: 'ingestion-token' } // ✅ Clear token purpose
|
|
1180
|
+
});
|
|
1181
|
+
```
|
|
1182
|
+
|
|
948
1183
|
### MYIO Components - Drag-to-Footer Dock Implementation
|
|
949
1184
|
|
|
950
1185
|
The library includes three main interactive components for building comparative selection interfaces:
|
package/dist/index.cjs
CHANGED
|
@@ -582,6 +582,7 @@ __export(index_exports, {
|
|
|
582
582
|
classifyWaterLabel: () => classifyWaterLabel,
|
|
583
583
|
classifyWaterLabels: () => classifyWaterLabels,
|
|
584
584
|
createDateRangePicker: () => createDateRangePicker2,
|
|
585
|
+
createInputDateRangePickerInsideDIV: () => createInputDateRangePickerInsideDIV,
|
|
585
586
|
decodePayload: () => decodePayload,
|
|
586
587
|
decodePayloadBase64Xor: () => decodePayloadBase64Xor,
|
|
587
588
|
detectDeviceType: () => detectDeviceType,
|
|
@@ -5414,7 +5415,6 @@ function createDateRangePicker($2, input, opts) {
|
|
|
5414
5415
|
helpText.className = "myio-text-muted";
|
|
5415
5416
|
helpText.style.fontSize = "12px";
|
|
5416
5417
|
helpText.style.marginTop = "4px";
|
|
5417
|
-
helpText.textContent = "Formato: DD/MM/YY HH:mm at\xE9 DD/MM/YY HH:mm";
|
|
5418
5418
|
input.parentNode?.appendChild(helpText);
|
|
5419
5419
|
const moment = window.moment;
|
|
5420
5420
|
const startDate = opts.presetStart ? moment(opts.presetStart).startOf("day") : moment().startOf("month");
|
|
@@ -5493,6 +5493,25 @@ var DateRangePickerJQ = {
|
|
|
5493
5493
|
};
|
|
5494
5494
|
|
|
5495
5495
|
// src/components/premium-modals/report-device/DeviceReportModal.ts
|
|
5496
|
+
var createDefaultEnergyFetcher = (params) => {
|
|
5497
|
+
return async ({ baseUrl, ingestionId, startISO, endISO }) => {
|
|
5498
|
+
const url = `${baseUrl}/api/v1/telemetry/devices/${ingestionId}/energy?startTime=${encodeURIComponent(startISO)}&endTime=${encodeURIComponent(endISO)}&granularity=1d&page=1&pageSize=1000&deep=0`;
|
|
5499
|
+
const token = params.api.ingestionToken;
|
|
5500
|
+
if (!token) {
|
|
5501
|
+
throw new Error("ingestionToken is required for Data/Ingestion API calls");
|
|
5502
|
+
}
|
|
5503
|
+
const response = await fetch(url, {
|
|
5504
|
+
headers: {
|
|
5505
|
+
"Authorization": `Bearer ${token}`,
|
|
5506
|
+
"Content-Type": "application/json"
|
|
5507
|
+
}
|
|
5508
|
+
});
|
|
5509
|
+
if (!response.ok) {
|
|
5510
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
5511
|
+
}
|
|
5512
|
+
return response.json();
|
|
5513
|
+
};
|
|
5514
|
+
};
|
|
5496
5515
|
var DeviceReportModal = class {
|
|
5497
5516
|
constructor(params) {
|
|
5498
5517
|
this.params = params;
|
|
@@ -5501,16 +5520,18 @@ var DeviceReportModal = class {
|
|
|
5501
5520
|
clientSecret: params.api.clientSecret,
|
|
5502
5521
|
base: params.api.dataApiBaseUrl
|
|
5503
5522
|
});
|
|
5523
|
+
this.energyFetcher = params.fetcher || createDefaultEnergyFetcher(params);
|
|
5504
5524
|
}
|
|
5505
5525
|
modal;
|
|
5506
5526
|
authClient;
|
|
5527
|
+
energyFetcher;
|
|
5507
5528
|
data = [];
|
|
5508
5529
|
isLoading = false;
|
|
5509
5530
|
eventHandlers = {};
|
|
5510
5531
|
dateRangePicker = null;
|
|
5511
5532
|
show() {
|
|
5512
5533
|
this.modal = createModal({
|
|
5513
|
-
title: `Relat\xF3rio - ${this.params.
|
|
5534
|
+
title: `Relat\xF3rio - ${this.params.identifier || "SEM IDENTIFICADOR"} - ${this.params.label || "SEM ETIQUETA"}`,
|
|
5514
5535
|
width: "80vw",
|
|
5515
5536
|
height: "90vh",
|
|
5516
5537
|
theme: this.params.ui?.theme || "light"
|
|
@@ -5570,8 +5591,8 @@ var DeviceReportModal = class {
|
|
|
5570
5591
|
exportBtn?.addEventListener("click", () => this.exportCSV());
|
|
5571
5592
|
try {
|
|
5572
5593
|
this.dateRangePicker = await attach(dateRangeInput, {
|
|
5573
|
-
presetStart: this.
|
|
5574
|
-
presetEnd: this.
|
|
5594
|
+
presetStart: this.getDefaultStartDate(),
|
|
5595
|
+
presetEnd: this.getDefaultEndDate(),
|
|
5575
5596
|
maxRangeDays: 31,
|
|
5576
5597
|
parentEl: this.modal.element,
|
|
5577
5598
|
onApply: ({ startISO, endISO }) => {
|
|
@@ -5605,8 +5626,13 @@ var DeviceReportModal = class {
|
|
|
5605
5626
|
const startDate = startISO.split("T")[0];
|
|
5606
5627
|
const endDate = endISO.split("T")[0];
|
|
5607
5628
|
const dateRange = rangeDaysInclusive(startDate, endDate);
|
|
5608
|
-
const
|
|
5609
|
-
|
|
5629
|
+
const apiResponse = await this.energyFetcher({
|
|
5630
|
+
baseUrl: this.params.api.dataApiBaseUrl || "https://api.data.apps.myio-bas.com",
|
|
5631
|
+
ingestionId: this.params.ingestionId,
|
|
5632
|
+
startISO,
|
|
5633
|
+
endISO
|
|
5634
|
+
});
|
|
5635
|
+
this.data = this.processApiResponse(apiResponse, dateRange);
|
|
5610
5636
|
this.renderTable();
|
|
5611
5637
|
exportBtn.disabled = false;
|
|
5612
5638
|
this.emit("loaded", {
|
|
@@ -5624,6 +5650,28 @@ var DeviceReportModal = class {
|
|
|
5624
5650
|
spinner.style.display = "none";
|
|
5625
5651
|
}
|
|
5626
5652
|
}
|
|
5653
|
+
processApiResponse(apiResponse, dateRange) {
|
|
5654
|
+
const dataArray = Array.isArray(apiResponse) ? apiResponse : apiResponse.data || [];
|
|
5655
|
+
if (!Array.isArray(dataArray) || dataArray.length === 0) {
|
|
5656
|
+
console.warn("[DeviceReportModal] API returned empty or invalid response, zero-filling date range");
|
|
5657
|
+
return dateRange.map((date) => ({ date, consumption: 0 }));
|
|
5658
|
+
}
|
|
5659
|
+
const deviceData = dataArray[0];
|
|
5660
|
+
const consumption = deviceData.consumption || [];
|
|
5661
|
+
const dailyMap = {};
|
|
5662
|
+
consumption.forEach((item) => {
|
|
5663
|
+
if (item.timestamp && item.value != null) {
|
|
5664
|
+
const date = item.timestamp.slice(0, 10);
|
|
5665
|
+
const value = Number(item.value);
|
|
5666
|
+
if (!dailyMap[date]) dailyMap[date] = 0;
|
|
5667
|
+
dailyMap[date] += value;
|
|
5668
|
+
}
|
|
5669
|
+
});
|
|
5670
|
+
return dateRange.map((date) => ({
|
|
5671
|
+
date,
|
|
5672
|
+
consumption: dailyMap[date] || 0
|
|
5673
|
+
}));
|
|
5674
|
+
}
|
|
5627
5675
|
generateMockData(dateRange) {
|
|
5628
5676
|
return dateRange.map((date) => ({
|
|
5629
5677
|
date,
|
|
@@ -5698,14 +5746,14 @@ var DeviceReportModal = class {
|
|
|
5698
5746
|
const now = /* @__PURE__ */ new Date();
|
|
5699
5747
|
const timestamp = now.toLocaleDateString("pt-BR") + " - " + now.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
|
|
5700
5748
|
const csvData = [
|
|
5701
|
-
["Dispositivo/Loja", this.params.
|
|
5749
|
+
["Dispositivo/Loja", this.params.identifier || "N/A", this.params.label || ""],
|
|
5702
5750
|
["DATA EMISS\xC3O", timestamp, ""],
|
|
5703
5751
|
["Total", fmtPt(total), ""],
|
|
5704
5752
|
["Data", "Consumo", ""],
|
|
5705
5753
|
...this.data.map((row) => [this.formatDate(row.date), fmtPt(row.consumption)])
|
|
5706
5754
|
];
|
|
5707
5755
|
const csvContent = toCsv(csvData);
|
|
5708
|
-
this.downloadCSV(csvContent, `relatorio-${this.params.
|
|
5756
|
+
this.downloadCSV(csvContent, `relatorio-${this.params.identifier || "dispositivo"}-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
|
|
5709
5757
|
}
|
|
5710
5758
|
downloadCSV(content, filename) {
|
|
5711
5759
|
const blob = new Blob([content], { type: "text/csv;charset=utf-8;" });
|
|
@@ -6667,8 +6715,8 @@ var AllReportModal = class {
|
|
|
6667
6715
|
});
|
|
6668
6716
|
try {
|
|
6669
6717
|
this.dateRangePicker = await attach(dateRangeInput, {
|
|
6670
|
-
presetStart: this.
|
|
6671
|
-
presetEnd: this.
|
|
6718
|
+
presetStart: this.getDefaultStartDate(),
|
|
6719
|
+
presetEnd: this.getDefaultEndDate(),
|
|
6672
6720
|
maxRangeDays: 31,
|
|
6673
6721
|
parentEl: this.modal.element,
|
|
6674
6722
|
onApply: ({ startISO, endISO }) => {
|
|
@@ -7123,6 +7171,268 @@ async function createDateRangePicker2(input, options = {}) {
|
|
|
7123
7171
|
};
|
|
7124
7172
|
return await DateRangePickerJQ.attach(input, defaultOptions);
|
|
7125
7173
|
}
|
|
7174
|
+
|
|
7175
|
+
// src/components/createInputDateRangePickerInsideDIV.ts
|
|
7176
|
+
var PREMIUM_STYLES = `
|
|
7177
|
+
.myio-daterange-wrapper {
|
|
7178
|
+
font-family: 'Roboto', Arial, sans-serif;
|
|
7179
|
+
background: #f9f9f9;
|
|
7180
|
+
padding: 20px;
|
|
7181
|
+
border-radius: 8px;
|
|
7182
|
+
margin-bottom: 20px;
|
|
7183
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
|
7184
|
+
transition: all 0.2s ease;
|
|
7185
|
+
}
|
|
7186
|
+
|
|
7187
|
+
.myio-daterange-wrapper:hover {
|
|
7188
|
+
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
|
7189
|
+
}
|
|
7190
|
+
|
|
7191
|
+
.myio-daterange-label {
|
|
7192
|
+
display: block;
|
|
7193
|
+
margin-bottom: 8px;
|
|
7194
|
+
font-weight: 500;
|
|
7195
|
+
color: #333;
|
|
7196
|
+
font-size: 14px;
|
|
7197
|
+
line-height: 1.4;
|
|
7198
|
+
}
|
|
7199
|
+
|
|
7200
|
+
.myio-daterange-input {
|
|
7201
|
+
width: 100%;
|
|
7202
|
+
max-width: 300px;
|
|
7203
|
+
padding: 8px 12px;
|
|
7204
|
+
border: 1px solid #ddd;
|
|
7205
|
+
border-radius: 4px;
|
|
7206
|
+
background: white;
|
|
7207
|
+
font-size: 14px;
|
|
7208
|
+
color: #333;
|
|
7209
|
+
cursor: pointer;
|
|
7210
|
+
transition: all 0.2s ease;
|
|
7211
|
+
font-family: inherit;
|
|
7212
|
+
line-height: 1.4;
|
|
7213
|
+
}
|
|
7214
|
+
|
|
7215
|
+
.myio-daterange-input:hover {
|
|
7216
|
+
border-color: #4A148C;
|
|
7217
|
+
box-shadow: 0 0 0 2px rgba(74, 20, 140, 0.1);
|
|
7218
|
+
}
|
|
7219
|
+
|
|
7220
|
+
.myio-daterange-input:focus {
|
|
7221
|
+
outline: none;
|
|
7222
|
+
border-color: #4A148C;
|
|
7223
|
+
box-shadow: 0 0 0 3px rgba(74, 20, 140, 0.2);
|
|
7224
|
+
}
|
|
7225
|
+
|
|
7226
|
+
.myio-daterange-input::placeholder {
|
|
7227
|
+
color: #999;
|
|
7228
|
+
opacity: 1;
|
|
7229
|
+
}
|
|
7230
|
+
|
|
7231
|
+
.myio-daterange-helper {
|
|
7232
|
+
font-size: 12px;
|
|
7233
|
+
color: #666;
|
|
7234
|
+
margin-top: 4px;
|
|
7235
|
+
line-height: 1.3;
|
|
7236
|
+
transition: color 0.2s ease;
|
|
7237
|
+
}
|
|
7238
|
+
|
|
7239
|
+
.myio-daterange-helper.success {
|
|
7240
|
+
color: #28a745;
|
|
7241
|
+
font-weight: 500;
|
|
7242
|
+
}
|
|
7243
|
+
|
|
7244
|
+
.myio-daterange-helper.error {
|
|
7245
|
+
color: #dc3545;
|
|
7246
|
+
font-weight: 500;
|
|
7247
|
+
}
|
|
7248
|
+
|
|
7249
|
+
/* Responsive design */
|
|
7250
|
+
@media (max-width: 768px) {
|
|
7251
|
+
.myio-daterange-wrapper {
|
|
7252
|
+
padding: 16px;
|
|
7253
|
+
margin-bottom: 16px;
|
|
7254
|
+
}
|
|
7255
|
+
|
|
7256
|
+
.myio-daterange-input {
|
|
7257
|
+
max-width: 100%;
|
|
7258
|
+
font-size: 16px; /* Prevents zoom on iOS */
|
|
7259
|
+
}
|
|
7260
|
+
}
|
|
7261
|
+
|
|
7262
|
+
/* High contrast mode support */
|
|
7263
|
+
@media (prefers-contrast: high) {
|
|
7264
|
+
.myio-daterange-wrapper {
|
|
7265
|
+
border: 2px solid #000;
|
|
7266
|
+
}
|
|
7267
|
+
|
|
7268
|
+
.myio-daterange-input {
|
|
7269
|
+
border: 2px solid #000;
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
|
|
7273
|
+
/* Reduced motion support */
|
|
7274
|
+
@media (prefers-reduced-motion: reduce) {
|
|
7275
|
+
.myio-daterange-wrapper,
|
|
7276
|
+
.myio-daterange-input,
|
|
7277
|
+
.myio-daterange-helper {
|
|
7278
|
+
transition: none;
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
`;
|
|
7282
|
+
function injectPremiumStyles() {
|
|
7283
|
+
const styleId = "myio-daterange-premium-styles";
|
|
7284
|
+
if (document.getElementById(styleId)) {
|
|
7285
|
+
return;
|
|
7286
|
+
}
|
|
7287
|
+
const styleEl = document.createElement("style");
|
|
7288
|
+
styleEl.id = styleId;
|
|
7289
|
+
styleEl.textContent = PREMIUM_STYLES;
|
|
7290
|
+
document.head.appendChild(styleEl);
|
|
7291
|
+
console.log("[MyIO] Premium date range styles injected");
|
|
7292
|
+
}
|
|
7293
|
+
function validateId(id, context) {
|
|
7294
|
+
if (!id || typeof id !== "string") {
|
|
7295
|
+
throw new Error(`[createInputDateRangePickerInsideDIV] ${context} must be a non-empty string`);
|
|
7296
|
+
}
|
|
7297
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id)) {
|
|
7298
|
+
throw new Error(`[createInputDateRangePickerInsideDIV] ${context} '${id}' is not a valid HTML ID`);
|
|
7299
|
+
}
|
|
7300
|
+
}
|
|
7301
|
+
async function createInputDateRangePickerInsideDIV(params) {
|
|
7302
|
+
const {
|
|
7303
|
+
containerId,
|
|
7304
|
+
inputId,
|
|
7305
|
+
label = "Per\xEDodo de Datas",
|
|
7306
|
+
placeholder = "Clique para selecionar per\xEDodo",
|
|
7307
|
+
pickerOptions = {},
|
|
7308
|
+
classNames = {},
|
|
7309
|
+
injectStyles = true,
|
|
7310
|
+
showHelper = true
|
|
7311
|
+
} = params;
|
|
7312
|
+
validateId(containerId, "containerId");
|
|
7313
|
+
validateId(inputId, "inputId");
|
|
7314
|
+
const container = document.getElementById(containerId);
|
|
7315
|
+
if (!container) {
|
|
7316
|
+
throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
|
|
7317
|
+
}
|
|
7318
|
+
if (injectStyles) {
|
|
7319
|
+
injectPremiumStyles();
|
|
7320
|
+
}
|
|
7321
|
+
let inputEl = document.getElementById(inputId);
|
|
7322
|
+
if (inputEl && inputEl.tagName.toLowerCase() !== "input") {
|
|
7323
|
+
throw new Error(`[createInputDateRangePickerInsideDIV] Element '#${inputId}' exists but is not an input element`);
|
|
7324
|
+
}
|
|
7325
|
+
const wrapper = document.createElement("div");
|
|
7326
|
+
wrapper.className = classNames.wrapper || "myio-daterange-wrapper";
|
|
7327
|
+
wrapper.setAttribute("data-myio-component", "daterange-input");
|
|
7328
|
+
wrapper.setAttribute("data-version", "1.0.0");
|
|
7329
|
+
let labelEl = null;
|
|
7330
|
+
if (label) {
|
|
7331
|
+
labelEl = document.createElement("label");
|
|
7332
|
+
labelEl.className = classNames.label || "myio-daterange-label";
|
|
7333
|
+
labelEl.textContent = label;
|
|
7334
|
+
labelEl.setAttribute("for", inputId);
|
|
7335
|
+
wrapper.appendChild(labelEl);
|
|
7336
|
+
}
|
|
7337
|
+
if (!inputEl) {
|
|
7338
|
+
inputEl = document.createElement("input");
|
|
7339
|
+
inputEl.type = "text";
|
|
7340
|
+
inputEl.id = inputId;
|
|
7341
|
+
inputEl.name = inputId;
|
|
7342
|
+
}
|
|
7343
|
+
inputEl.className = classNames.input || "myio-daterange-input";
|
|
7344
|
+
inputEl.readOnly = true;
|
|
7345
|
+
inputEl.placeholder = placeholder;
|
|
7346
|
+
inputEl.autocomplete = "off";
|
|
7347
|
+
inputEl.setAttribute("aria-label", label || "Date range selector");
|
|
7348
|
+
if (showHelper) {
|
|
7349
|
+
inputEl.setAttribute("aria-describedby", `${inputId}-helper`);
|
|
7350
|
+
}
|
|
7351
|
+
let helperEl = null;
|
|
7352
|
+
if (showHelper) {
|
|
7353
|
+
helperEl = document.createElement("div");
|
|
7354
|
+
helperEl.id = `${inputId}-helper`;
|
|
7355
|
+
helperEl.className = classNames.helper || "myio-daterange-helper";
|
|
7356
|
+
helperEl.setAttribute("aria-live", "polite");
|
|
7357
|
+
}
|
|
7358
|
+
wrapper.appendChild(inputEl);
|
|
7359
|
+
if (helperEl) {
|
|
7360
|
+
wrapper.appendChild(helperEl);
|
|
7361
|
+
}
|
|
7362
|
+
const existingWrapper = container.querySelector('[data-myio-component="daterange-input"]');
|
|
7363
|
+
if (existingWrapper) {
|
|
7364
|
+
console.warn(`[createInputDateRangePickerInsideDIV] Replacing existing daterange input in container '#${containerId}'`);
|
|
7365
|
+
existingWrapper.remove();
|
|
7366
|
+
}
|
|
7367
|
+
container.appendChild(wrapper);
|
|
7368
|
+
const enhancedOptions = {
|
|
7369
|
+
maxRangeDays: 31,
|
|
7370
|
+
onApply: (result) => {
|
|
7371
|
+
if (helperEl) {
|
|
7372
|
+
const startDate = new Date(result.startISO);
|
|
7373
|
+
const endDate = new Date(result.endISO);
|
|
7374
|
+
const days = Math.ceil((endDate.getTime() - startDate.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
|
|
7375
|
+
helperEl.textContent = `Per\xEDodo selecionado: ${days} dia${days !== 1 ? "s" : ""}`;
|
|
7376
|
+
helperEl.className = (classNames.helper || "myio-daterange-helper") + " success";
|
|
7377
|
+
setTimeout(() => {
|
|
7378
|
+
if (helperEl) {
|
|
7379
|
+
helperEl.className = classNames.helper || "myio-daterange-helper";
|
|
7380
|
+
}
|
|
7381
|
+
}, 3e3);
|
|
7382
|
+
}
|
|
7383
|
+
if (pickerOptions.onApply) {
|
|
7384
|
+
pickerOptions.onApply(result);
|
|
7385
|
+
}
|
|
7386
|
+
},
|
|
7387
|
+
...pickerOptions
|
|
7388
|
+
};
|
|
7389
|
+
let picker;
|
|
7390
|
+
try {
|
|
7391
|
+
picker = await createDateRangePicker2(inputEl, enhancedOptions);
|
|
7392
|
+
console.log(`[createInputDateRangePickerInsideDIV] Successfully initialized for input '#${inputId}'`);
|
|
7393
|
+
} catch (error) {
|
|
7394
|
+
wrapper.remove();
|
|
7395
|
+
throw new Error(`[createInputDateRangePickerInsideDIV] Failed to initialize date picker: ${error.message}`);
|
|
7396
|
+
}
|
|
7397
|
+
const controller = {
|
|
7398
|
+
input: inputEl,
|
|
7399
|
+
container,
|
|
7400
|
+
wrapper,
|
|
7401
|
+
picker,
|
|
7402
|
+
getDisplayValue: () => inputEl.value,
|
|
7403
|
+
getDates: () => picker.getDates(),
|
|
7404
|
+
setDates: (startISO, endISO) => {
|
|
7405
|
+
try {
|
|
7406
|
+
picker.setDates(startISO, endISO);
|
|
7407
|
+
} catch (error) {
|
|
7408
|
+
console.error(`[createInputDateRangePickerInsideDIV] Error setting dates:`, error);
|
|
7409
|
+
throw error;
|
|
7410
|
+
}
|
|
7411
|
+
},
|
|
7412
|
+
setHelperText: (text, type = "default") => {
|
|
7413
|
+
if (helperEl) {
|
|
7414
|
+
helperEl.textContent = text;
|
|
7415
|
+
const baseClass = classNames.helper || "myio-daterange-helper";
|
|
7416
|
+
helperEl.className = type === "default" ? baseClass : `${baseClass} ${type}`;
|
|
7417
|
+
}
|
|
7418
|
+
},
|
|
7419
|
+
destroy: () => {
|
|
7420
|
+
try {
|
|
7421
|
+
picker.destroy();
|
|
7422
|
+
console.log(`[createInputDateRangePickerInsideDIV] Date picker destroyed for input '#${inputId}'`);
|
|
7423
|
+
} catch (error) {
|
|
7424
|
+
console.warn(`[createInputDateRangePickerInsideDIV] Error destroying picker:`, error);
|
|
7425
|
+
}
|
|
7426
|
+
try {
|
|
7427
|
+
wrapper.remove();
|
|
7428
|
+
console.log(`[createInputDateRangePickerInsideDIV] Wrapper removed for input '#${inputId}'`);
|
|
7429
|
+
} catch (error) {
|
|
7430
|
+
console.warn(`[createInputDateRangePickerInsideDIV] Error removing wrapper:`, error);
|
|
7431
|
+
}
|
|
7432
|
+
}
|
|
7433
|
+
};
|
|
7434
|
+
return controller;
|
|
7435
|
+
}
|
|
7126
7436
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7127
7437
|
0 && (module.exports = {
|
|
7128
7438
|
MyIOChartModal,
|
|
@@ -7139,6 +7449,7 @@ async function createDateRangePicker2(input, options = {}) {
|
|
|
7139
7449
|
classifyWaterLabel,
|
|
7140
7450
|
classifyWaterLabels,
|
|
7141
7451
|
createDateRangePicker,
|
|
7452
|
+
createInputDateRangePickerInsideDIV,
|
|
7142
7453
|
decodePayload,
|
|
7143
7454
|
decodePayloadBase64Xor,
|
|
7144
7455
|
detectDeviceType,
|