solid_apm 0.11.0 → 0.11.2
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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5ae3dca7dc8bedd15f5e89ee1c533d5f7e95707c4afa8b550f679a799a3bed0e
|
|
4
|
+
data.tar.gz: 4b45583cb978b1b7515e4b3482f1bbc0fc9e67963228a5deaf74163abceeb333
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01cebd760d13efbfac07743552fc34a91b9230d60bee26ba061ee7aca5e2db536f3f57580b35442bbb7996ae991d6c9b824f40a5efd134f7e8f15ea0ced30f10
|
|
7
|
+
data.tar.gz: a48210bbf993f9da2c4a8200a3cbc01c2c661147bd5b6451ad5486029859fe0c6c29f1aa84f146c40943d535176d4ad8e388fb9cfc3d741e605099255e294e62
|
|
@@ -101,4 +101,223 @@
|
|
|
101
101
|
</div>
|
|
102
102
|
<% end %>
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
<script>
|
|
105
|
+
class TimeRangeForm {
|
|
106
|
+
constructor() {
|
|
107
|
+
this.form = document.getElementById('time-range-form');
|
|
108
|
+
this.relativeTab = document.getElementById('relative-tab');
|
|
109
|
+
this.absoluteTab = document.getElementById('absolute-tab');
|
|
110
|
+
this.relativePanel = document.getElementById('relative-panel');
|
|
111
|
+
this.absolutePanel = document.getElementById('absolute-panel');
|
|
112
|
+
this.customFromControl = document.getElementById('custom-from-control');
|
|
113
|
+
this.customToControl = document.getElementById('custom-to-control');
|
|
114
|
+
|
|
115
|
+
// Timezone handling
|
|
116
|
+
this.browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
117
|
+
this.timezoneOffset = new Date().getTimezoneOffset();
|
|
118
|
+
|
|
119
|
+
this.init();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
init() {
|
|
123
|
+
this.setupEventListeners();
|
|
124
|
+
this.initializeFormState();
|
|
125
|
+
this.addTimezoneToForm();
|
|
126
|
+
this.adjustAbsoluteTimes();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
setupEventListeners() {
|
|
130
|
+
if (this.form) {
|
|
131
|
+
this.form.addEventListener('submit', (e) => this.handleFormSubmit(e));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
switchToRelative(event) {
|
|
136
|
+
event.preventDefault();
|
|
137
|
+
|
|
138
|
+
this.relativeTab.classList.add('is-primary');
|
|
139
|
+
this.absoluteTab.classList.remove('is-primary');
|
|
140
|
+
this.relativePanel.classList.remove('is-hidden');
|
|
141
|
+
this.absolutePanel.classList.add('is-hidden');
|
|
142
|
+
|
|
143
|
+
this.removeFields(['from_timestamp', 'to_timestamp']);
|
|
144
|
+
this.cleanupUrlParams(['from_timestamp', 'to_timestamp', 'from_datetime', 'to_datetime']);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
switchToAbsolute(event) {
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
|
|
150
|
+
this.absoluteTab.classList.add('is-primary');
|
|
151
|
+
this.relativeTab.classList.remove('is-primary');
|
|
152
|
+
this.absolutePanel.classList.remove('is-hidden');
|
|
153
|
+
this.relativePanel.classList.add('is-hidden');
|
|
154
|
+
|
|
155
|
+
this.cleanupUrlParams(['quick_range', 'from_value', 'from_unit', 'to_value', 'to_unit', 'quick_range_apply']);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
handleQuickRangeChange(select) {
|
|
159
|
+
const isCustom = select.value === 'custom';
|
|
160
|
+
|
|
161
|
+
this.toggleVisibility(this.customFromControl, isCustom);
|
|
162
|
+
this.toggleVisibility(this.customToControl, isCustom);
|
|
163
|
+
|
|
164
|
+
if (!isCustom) {
|
|
165
|
+
this.applyQuickRange();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
applyQuickRange() {
|
|
170
|
+
const quickRangeSelect = this.form.querySelector('[name="quick_range"]');
|
|
171
|
+
if (!quickRangeSelect || quickRangeSelect.value === 'custom') return;
|
|
172
|
+
|
|
173
|
+
this.removeFields(['from_datetime', 'to_datetime', 'from_timestamp', 'to_timestamp']);
|
|
174
|
+
this.addHiddenField('quick_range_apply', quickRangeSelect.value);
|
|
175
|
+
this.form.submit();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
handleFormSubmit(event) {
|
|
179
|
+
const isAbsoluteMode = !this.absolutePanel.classList.contains('is-hidden');
|
|
180
|
+
|
|
181
|
+
if (isAbsoluteMode) {
|
|
182
|
+
this.handleAbsoluteModeSubmit();
|
|
183
|
+
} else {
|
|
184
|
+
this.handleRelativeModeSubmit();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
handleAbsoluteModeSubmit() {
|
|
189
|
+
const fromDatetime = this.form.querySelector('[name="from_datetime"]');
|
|
190
|
+
const toDatetime = this.form.querySelector('[name="to_datetime"]');
|
|
191
|
+
|
|
192
|
+
if (fromDatetime?.value && toDatetime?.value) {
|
|
193
|
+
const fromTimestamp = Math.floor(new Date(fromDatetime.value).getTime() / 1000);
|
|
194
|
+
const toTimestamp = Math.floor(new Date(toDatetime.value).getTime() / 1000);
|
|
195
|
+
|
|
196
|
+
fromDatetime.disabled = true;
|
|
197
|
+
toDatetime.disabled = true;
|
|
198
|
+
|
|
199
|
+
this.addHiddenField('from_timestamp', fromTimestamp);
|
|
200
|
+
this.addHiddenField('to_timestamp', toTimestamp);
|
|
201
|
+
this.addHiddenField('browser_timezone', this.browserTimezone);
|
|
202
|
+
this.removeFields(['quick_range', 'from_value', 'from_unit', 'to_value', 'to_unit', 'quick_range_apply']);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
handleRelativeModeSubmit() {
|
|
207
|
+
const quickRangeSelect = this.form.querySelector('[name="quick_range"]');
|
|
208
|
+
const quickRangeValue = quickRangeSelect?.value;
|
|
209
|
+
|
|
210
|
+
if (quickRangeValue && quickRangeValue !== 'custom') {
|
|
211
|
+
this.removeFields(['from_value', 'from_unit', 'to_value', 'to_unit', 'quick_range_apply']);
|
|
212
|
+
} else if (quickRangeValue === 'custom') {
|
|
213
|
+
this.removeFields(['quick_range_apply']);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.removeFields(['from_datetime', 'to_datetime', 'from_timestamp', 'to_timestamp']);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
initializeFormState() {
|
|
220
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
221
|
+
const hasCustomParams = urlParams.has('from_value') && urlParams.has('from_unit');
|
|
222
|
+
const hasQuickRange = urlParams.has('quick_range') && urlParams.get('quick_range') !== 'custom';
|
|
223
|
+
const quickRangeSelect = this.form.querySelector('[name="quick_range"]');
|
|
224
|
+
|
|
225
|
+
if (hasQuickRange) {
|
|
226
|
+
this.toggleVisibility(this.customFromControl, false);
|
|
227
|
+
this.toggleVisibility(this.customToControl, false);
|
|
228
|
+
} else if (hasCustomParams || urlParams.get('quick_range') === 'custom') {
|
|
229
|
+
if (quickRangeSelect) quickRangeSelect.value = 'custom';
|
|
230
|
+
this.toggleVisibility(this.customFromControl, true);
|
|
231
|
+
this.toggleVisibility(this.customToControl, true);
|
|
232
|
+
} else {
|
|
233
|
+
// Default state - show quick range only
|
|
234
|
+
this.toggleVisibility(this.customFromControl, false);
|
|
235
|
+
this.toggleVisibility(this.customToControl, false);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Utility methods
|
|
240
|
+
removeFields(fieldNames) {
|
|
241
|
+
fieldNames.forEach(name => {
|
|
242
|
+
this.form.querySelectorAll(`[name="${name}"]`).forEach(field => field.remove());
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
addHiddenField(name, value) {
|
|
247
|
+
const input = document.createElement('input');
|
|
248
|
+
input.type = 'hidden';
|
|
249
|
+
input.name = name;
|
|
250
|
+
input.value = value;
|
|
251
|
+
this.form.appendChild(input);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
toggleVisibility(element, show) {
|
|
255
|
+
if (!element) return;
|
|
256
|
+
element.classList.toggle('is-hidden', !show);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
cleanupUrlParams(params) {
|
|
260
|
+
const url = new URL(window.location);
|
|
261
|
+
params.forEach(param => url.searchParams.delete(param));
|
|
262
|
+
window.history.replaceState({}, '', url);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Timezone-related methods
|
|
266
|
+
addTimezoneToForm() {
|
|
267
|
+
// Add timezone information to form for server processing
|
|
268
|
+
this.addHiddenField('browser_timezone', this.browserTimezone);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
adjustAbsoluteTimes() {
|
|
272
|
+
// Convert timestamps from URL to browser timezone for datetime-local inputs
|
|
273
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
274
|
+
const fromTimestamp = urlParams.get('from_timestamp');
|
|
275
|
+
const toTimestamp = urlParams.get('to_timestamp');
|
|
276
|
+
|
|
277
|
+
if (fromTimestamp && toTimestamp) {
|
|
278
|
+
const fromDatetime = this.form.querySelector('[name="from_datetime"]');
|
|
279
|
+
const toDatetime = this.form.querySelector('[name="to_datetime"]');
|
|
280
|
+
|
|
281
|
+
if (fromDatetime && toDatetime) {
|
|
282
|
+
// Convert UTC timestamps to local datetime strings
|
|
283
|
+
const fromDate = new Date(parseInt(fromTimestamp) * 1000);
|
|
284
|
+
const toDate = new Date(parseInt(toTimestamp) * 1000);
|
|
285
|
+
|
|
286
|
+
fromDatetime.value = this.formatDatetimeLocal(fromDate);
|
|
287
|
+
toDatetime.value = this.formatDatetimeLocal(toDate);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
formatDatetimeLocal(date) {
|
|
293
|
+
// Format date for datetime-local input (YYYY-MM-DDTHH:MM)
|
|
294
|
+
const year = date.getFullYear();
|
|
295
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
296
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
297
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
298
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
299
|
+
|
|
300
|
+
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Global functions for onclick handlers (maintaining backward compatibility)
|
|
305
|
+
let timeRangeFormInstance;
|
|
306
|
+
|
|
307
|
+
function switchToRelative(event) {
|
|
308
|
+
timeRangeFormInstance?.switchToRelative(event);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function switchToAbsolute(event) {
|
|
312
|
+
timeRangeFormInstance?.switchToAbsolute(event);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function handleQuickRangeChange(select) {
|
|
316
|
+
timeRangeFormInstance?.handleQuickRangeChange(select);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Initialize when DOM is ready
|
|
320
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
321
|
+
timeRangeFormInstance = new TimeRangeForm();
|
|
322
|
+
});
|
|
323
|
+
</script>
|
data/lib/solid_apm/engine.rb
CHANGED
|
@@ -6,32 +6,44 @@ module SolidApm
|
|
|
6
6
|
|
|
7
7
|
config.app_middleware.use Middleware
|
|
8
8
|
|
|
9
|
-
initializer
|
|
10
|
-
|
|
9
|
+
initializer 'solid_apm.assets' do |app|
|
|
10
|
+
# Add engine's assets to the load path for both Propshaft and Sprockets
|
|
11
|
+
if app.config.respond_to?(:assets)
|
|
12
|
+
app.config.assets.paths << root.join('app/assets/stylesheets')
|
|
13
|
+
app.config.assets.paths << root.join('app/assets/javascripts')
|
|
14
|
+
|
|
15
|
+
# For Sprockets
|
|
16
|
+
unless defined?(Propshaft)
|
|
17
|
+
app.config.assets.precompile += %w[
|
|
18
|
+
solid_apm/application.css
|
|
19
|
+
solid_apm/application.js
|
|
20
|
+
]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
11
23
|
end
|
|
12
24
|
|
|
13
25
|
begin
|
|
14
26
|
# Mount the MCP server only if the main app added the fast_mcp in is Gemfile.
|
|
15
27
|
require 'fast_mcp'
|
|
16
|
-
initializer
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
initializer 'solid_apm.mount_mcp_server' do |app|
|
|
29
|
+
mcp_server_config = SolidApm.mcp_server_config.reverse_merge(
|
|
30
|
+
name: 'solid-apm-mcp',
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
path: '/solid_apm/mcp'
|
|
33
|
+
)
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
FastMcp.mount_in_rails(
|
|
36
|
+
app,
|
|
37
|
+
**mcp_server_config
|
|
38
|
+
) do |server|
|
|
39
|
+
app.config.after_initialize do
|
|
40
|
+
require_relative 'mcp/spans_for_transaction_tool'
|
|
41
|
+
require_relative 'mcp/impactful_transactions_resource'
|
|
42
|
+
server.register_resources(SolidApm::Mcp::ImpactfulTransactionsResource)
|
|
43
|
+
server.register_tools(SolidApm::Mcp::SpansForTransactionTool)
|
|
44
|
+
end
|
|
32
45
|
end
|
|
33
46
|
end
|
|
34
|
-
end
|
|
35
47
|
rescue LoadError
|
|
36
48
|
# Ignored
|
|
37
49
|
end
|
data/lib/solid_apm/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solid_apm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.11.
|
|
4
|
+
version: 0.11.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jean-Francis Bastien
|
|
@@ -119,7 +119,6 @@ files:
|
|
|
119
119
|
- Rakefile
|
|
120
120
|
- app/assets/config/solid_apm_manifest.js
|
|
121
121
|
- app/assets/javascripts/solid_apm/application.js
|
|
122
|
-
- app/assets/javascripts/solid_apm/time_range_form.js
|
|
123
122
|
- app/assets/stylesheets/solid_apm/application.css
|
|
124
123
|
- app/controllers/solid_apm/application_controller.rb
|
|
125
124
|
- app/controllers/solid_apm/spans_controller.rb
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
class TimeRangeForm {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.form = document.getElementById('time-range-form');
|
|
4
|
-
this.relativeTab = document.getElementById('relative-tab');
|
|
5
|
-
this.absoluteTab = document.getElementById('absolute-tab');
|
|
6
|
-
this.relativePanel = document.getElementById('relative-panel');
|
|
7
|
-
this.absolutePanel = document.getElementById('absolute-panel');
|
|
8
|
-
this.customFromControl = document.getElementById('custom-from-control');
|
|
9
|
-
this.customToControl = document.getElementById('custom-to-control');
|
|
10
|
-
|
|
11
|
-
// Timezone handling
|
|
12
|
-
this.browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
13
|
-
this.timezoneOffset = new Date().getTimezoneOffset();
|
|
14
|
-
|
|
15
|
-
this.init();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
init() {
|
|
19
|
-
this.setupEventListeners();
|
|
20
|
-
this.initializeFormState();
|
|
21
|
-
this.addTimezoneToForm();
|
|
22
|
-
this.adjustAbsoluteTimes();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
setupEventListeners() {
|
|
26
|
-
if (this.form) {
|
|
27
|
-
this.form.addEventListener('submit', (e) => this.handleFormSubmit(e));
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
switchToRelative(event) {
|
|
32
|
-
event.preventDefault();
|
|
33
|
-
|
|
34
|
-
this.relativeTab.classList.add('is-primary');
|
|
35
|
-
this.absoluteTab.classList.remove('is-primary');
|
|
36
|
-
this.relativePanel.classList.remove('is-hidden');
|
|
37
|
-
this.absolutePanel.classList.add('is-hidden');
|
|
38
|
-
|
|
39
|
-
this.removeFields(['from_timestamp', 'to_timestamp']);
|
|
40
|
-
this.cleanupUrlParams(['from_timestamp', 'to_timestamp', 'from_datetime', 'to_datetime']);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
switchToAbsolute(event) {
|
|
44
|
-
event.preventDefault();
|
|
45
|
-
|
|
46
|
-
this.absoluteTab.classList.add('is-primary');
|
|
47
|
-
this.relativeTab.classList.remove('is-primary');
|
|
48
|
-
this.absolutePanel.classList.remove('is-hidden');
|
|
49
|
-
this.relativePanel.classList.add('is-hidden');
|
|
50
|
-
|
|
51
|
-
this.cleanupUrlParams(['quick_range', 'from_value', 'from_unit', 'to_value', 'to_unit', 'quick_range_apply']);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
handleQuickRangeChange(select) {
|
|
55
|
-
const isCustom = select.value === 'custom';
|
|
56
|
-
|
|
57
|
-
this.toggleVisibility(this.customFromControl, isCustom);
|
|
58
|
-
this.toggleVisibility(this.customToControl, isCustom);
|
|
59
|
-
|
|
60
|
-
if (!isCustom) {
|
|
61
|
-
this.applyQuickRange();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
applyQuickRange() {
|
|
66
|
-
const quickRangeSelect = this.form.querySelector('[name="quick_range"]');
|
|
67
|
-
if (!quickRangeSelect || quickRangeSelect.value === 'custom') return;
|
|
68
|
-
|
|
69
|
-
this.removeFields(['from_datetime', 'to_datetime', 'from_timestamp', 'to_timestamp']);
|
|
70
|
-
this.addHiddenField('quick_range_apply', quickRangeSelect.value);
|
|
71
|
-
this.form.submit();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
handleFormSubmit(event) {
|
|
75
|
-
const isAbsoluteMode = !this.absolutePanel.classList.contains('is-hidden');
|
|
76
|
-
|
|
77
|
-
if (isAbsoluteMode) {
|
|
78
|
-
this.handleAbsoluteModeSubmit();
|
|
79
|
-
} else {
|
|
80
|
-
this.handleRelativeModeSubmit();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
handleAbsoluteModeSubmit() {
|
|
85
|
-
const fromDatetime = this.form.querySelector('[name="from_datetime"]');
|
|
86
|
-
const toDatetime = this.form.querySelector('[name="to_datetime"]');
|
|
87
|
-
|
|
88
|
-
if (fromDatetime?.value && toDatetime?.value) {
|
|
89
|
-
const fromTimestamp = Math.floor(new Date(fromDatetime.value).getTime() / 1000);
|
|
90
|
-
const toTimestamp = Math.floor(new Date(toDatetime.value).getTime() / 1000);
|
|
91
|
-
|
|
92
|
-
fromDatetime.disabled = true;
|
|
93
|
-
toDatetime.disabled = true;
|
|
94
|
-
|
|
95
|
-
this.addHiddenField('from_timestamp', fromTimestamp);
|
|
96
|
-
this.addHiddenField('to_timestamp', toTimestamp);
|
|
97
|
-
this.addHiddenField('browser_timezone', this.browserTimezone);
|
|
98
|
-
this.removeFields(['quick_range', 'from_value', 'from_unit', 'to_value', 'to_unit', 'quick_range_apply']);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
handleRelativeModeSubmit() {
|
|
103
|
-
const quickRangeSelect = this.form.querySelector('[name="quick_range"]');
|
|
104
|
-
const quickRangeValue = quickRangeSelect?.value;
|
|
105
|
-
|
|
106
|
-
if (quickRangeValue && quickRangeValue !== 'custom') {
|
|
107
|
-
this.removeFields(['from_value', 'from_unit', 'to_value', 'to_unit', 'quick_range_apply']);
|
|
108
|
-
} else if (quickRangeValue === 'custom') {
|
|
109
|
-
this.removeFields(['quick_range_apply']);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
this.removeFields(['from_datetime', 'to_datetime', 'from_timestamp', 'to_timestamp']);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
initializeFormState() {
|
|
116
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
117
|
-
const hasCustomParams = urlParams.has('from_value') && urlParams.has('from_unit');
|
|
118
|
-
const hasQuickRange = urlParams.has('quick_range') && urlParams.get('quick_range') !== 'custom';
|
|
119
|
-
const quickRangeSelect = this.form.querySelector('[name="quick_range"]');
|
|
120
|
-
|
|
121
|
-
if (hasQuickRange) {
|
|
122
|
-
this.toggleVisibility(this.customFromControl, false);
|
|
123
|
-
this.toggleVisibility(this.customToControl, false);
|
|
124
|
-
} else if (hasCustomParams || urlParams.get('quick_range') === 'custom') {
|
|
125
|
-
if (quickRangeSelect) quickRangeSelect.value = 'custom';
|
|
126
|
-
this.toggleVisibility(this.customFromControl, true);
|
|
127
|
-
this.toggleVisibility(this.customToControl, true);
|
|
128
|
-
} else {
|
|
129
|
-
// Default state - show quick range only
|
|
130
|
-
this.toggleVisibility(this.customFromControl, false);
|
|
131
|
-
this.toggleVisibility(this.customToControl, false);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Utility methods
|
|
136
|
-
removeFields(fieldNames) {
|
|
137
|
-
fieldNames.forEach(name => {
|
|
138
|
-
this.form.querySelectorAll(`[name="${name}"]`).forEach(field => field.remove());
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
addHiddenField(name, value) {
|
|
143
|
-
const input = document.createElement('input');
|
|
144
|
-
input.type = 'hidden';
|
|
145
|
-
input.name = name;
|
|
146
|
-
input.value = value;
|
|
147
|
-
this.form.appendChild(input);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
toggleVisibility(element, show) {
|
|
151
|
-
if (!element) return;
|
|
152
|
-
element.classList.toggle('is-hidden', !show);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
cleanupUrlParams(params) {
|
|
156
|
-
const url = new URL(window.location);
|
|
157
|
-
params.forEach(param => url.searchParams.delete(param));
|
|
158
|
-
window.history.replaceState({}, '', url);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Timezone-related methods
|
|
162
|
-
addTimezoneToForm() {
|
|
163
|
-
// Add timezone information to form for server processing
|
|
164
|
-
this.addHiddenField('browser_timezone', this.browserTimezone);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
adjustAbsoluteTimes() {
|
|
168
|
-
// Convert timestamps from URL to browser timezone for datetime-local inputs
|
|
169
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
170
|
-
const fromTimestamp = urlParams.get('from_timestamp');
|
|
171
|
-
const toTimestamp = urlParams.get('to_timestamp');
|
|
172
|
-
|
|
173
|
-
if (fromTimestamp && toTimestamp) {
|
|
174
|
-
const fromDatetime = this.form.querySelector('[name="from_datetime"]');
|
|
175
|
-
const toDatetime = this.form.querySelector('[name="to_datetime"]');
|
|
176
|
-
|
|
177
|
-
if (fromDatetime && toDatetime) {
|
|
178
|
-
// Convert UTC timestamps to local datetime strings
|
|
179
|
-
const fromDate = new Date(parseInt(fromTimestamp) * 1000);
|
|
180
|
-
const toDate = new Date(parseInt(toTimestamp) * 1000);
|
|
181
|
-
|
|
182
|
-
fromDatetime.value = this.formatDatetimeLocal(fromDate);
|
|
183
|
-
toDatetime.value = this.formatDatetimeLocal(toDate);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
formatDatetimeLocal(date) {
|
|
189
|
-
// Format date for datetime-local input (YYYY-MM-DDTHH:MM)
|
|
190
|
-
const year = date.getFullYear();
|
|
191
|
-
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
192
|
-
const day = String(date.getDate()).padStart(2, '0');
|
|
193
|
-
const hours = String(date.getHours()).padStart(2, '0');
|
|
194
|
-
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
195
|
-
|
|
196
|
-
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Global functions for onclick handlers (maintaining backward compatibility)
|
|
202
|
-
let timeRangeFormInstance;
|
|
203
|
-
|
|
204
|
-
function switchToRelative(event) {
|
|
205
|
-
timeRangeFormInstance?.switchToRelative(event);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function switchToAbsolute(event) {
|
|
209
|
-
timeRangeFormInstance?.switchToAbsolute(event);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function handleQuickRangeChange(select) {
|
|
213
|
-
timeRangeFormInstance?.handleQuickRangeChange(select);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Initialize when DOM is ready
|
|
217
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
218
|
-
timeRangeFormInstance = new TimeRangeForm();
|
|
219
|
-
});
|