@uxbertlabs/reportly 1.0.17 → 1.0.19
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/core/init.d.ts +7 -0
- package/dist/core/init.d.ts.map +1 -1
- package/dist/features/export.d.ts +31 -1
- package/dist/features/export.d.ts.map +1 -1
- package/dist/features/n8n-integration.d.ts +56 -0
- package/dist/features/n8n-integration.d.ts.map +1 -0
- package/dist/reportly.cjs.js +427 -47
- package/dist/reportly.cjs.js.map +1 -1
- package/dist/reportly.esm.js +427 -47
- package/dist/reportly.esm.js.map +1 -1
- package/dist/reportly.js +427 -47
- package/dist/reportly.js.map +1 -1
- package/dist/reportly.min.js +2 -2
- package/dist/reportly.min.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/modal.d.ts +5 -3
- package/dist/ui/modal.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/reportly.esm.js
CHANGED
@@ -182,11 +182,11 @@ class Modal {
|
|
182
182
|
}
|
183
183
|
create() {
|
184
184
|
// Create overlay
|
185
|
-
this.overlay = document.createElement(
|
186
|
-
this.overlay.className =
|
185
|
+
this.overlay = document.createElement("div");
|
186
|
+
this.overlay.className = "uxbert-overlay";
|
187
187
|
// Create modal
|
188
|
-
this.modal = document.createElement(
|
189
|
-
this.modal.className =
|
188
|
+
this.modal = document.createElement("div");
|
189
|
+
this.modal.className = "uxbert-modal";
|
190
190
|
// Modal HTML
|
191
191
|
this.modal.innerHTML = `
|
192
192
|
<div class="uxbert-modal-header">
|
@@ -231,12 +231,13 @@ class Modal {
|
|
231
231
|
|
232
232
|
<div class="uxbert-form-group">
|
233
233
|
<label class="uxbert-form-label" for="uxbert-priority">Priority</label>
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
</
|
234
|
+
<select id="uxbert-priority" class="uxbert-form-select">
|
235
|
+
<option value="5" selected>Lowest</option>
|
236
|
+
<option value="4">Low</option>
|
237
|
+
<option value="3" selected>Medium</option>
|
238
|
+
<option value="2">High</option>
|
239
|
+
<option value="1">Highest</option>
|
240
|
+
</select>
|
240
241
|
</div>
|
241
242
|
|
242
243
|
<div class="uxbert-capture-action" id="uxbert-capture-action">
|
@@ -261,6 +262,9 @@ class Modal {
|
|
261
262
|
<button type="button" class="uxbert-btn uxbert-btn-secondary" id="uxbert-cancel-btn">
|
262
263
|
Cancel
|
263
264
|
</button>
|
265
|
+
<button type="button" class="uxbert-btn uxbert-btn-success" id="uxbert-n8n-btn" style="display: none;">
|
266
|
+
🚀 Send to n8n
|
267
|
+
</button>
|
264
268
|
<button type="submit" class="uxbert-btn uxbert-btn-primary" id="uxbert-submit-btn">
|
265
269
|
📥 Download JSON
|
266
270
|
</button>
|
@@ -277,72 +281,103 @@ class Modal {
|
|
277
281
|
if (!this.modal)
|
278
282
|
return;
|
279
283
|
// Close button
|
280
|
-
const closeBtn = this.modal.querySelector(
|
281
|
-
closeBtn.addEventListener(
|
284
|
+
const closeBtn = this.modal.querySelector(".uxbert-modal-close");
|
285
|
+
closeBtn.addEventListener("click", () => this.close());
|
282
286
|
// Cancel button
|
283
|
-
const cancelBtn = this.modal.querySelector(
|
284
|
-
cancelBtn.addEventListener(
|
287
|
+
const cancelBtn = this.modal.querySelector("#uxbert-cancel-btn");
|
288
|
+
cancelBtn.addEventListener("click", () => this.close());
|
285
289
|
// Overlay click to close
|
286
|
-
this.overlay?.addEventListener(
|
290
|
+
this.overlay?.addEventListener("click", (e) => {
|
287
291
|
if (e.target === this.overlay) {
|
288
292
|
this.close();
|
289
293
|
}
|
290
294
|
});
|
291
295
|
// Form submit
|
292
|
-
const form = this.modal.querySelector(
|
293
|
-
form.addEventListener(
|
296
|
+
const form = this.modal.querySelector("#uxbert-issue-form");
|
297
|
+
form.addEventListener("submit", (e) => {
|
294
298
|
e.preventDefault();
|
295
299
|
this.handleSubmit();
|
296
300
|
});
|
297
301
|
// Capture button
|
298
|
-
const captureBtn = this.modal.querySelector(
|
299
|
-
captureBtn.addEventListener(
|
302
|
+
const captureBtn = this.modal.querySelector("#uxbert-capture-btn");
|
303
|
+
captureBtn.addEventListener("click", () => {
|
300
304
|
if (this.callbacks.onCapture) {
|
301
305
|
this.callbacks.onCapture();
|
302
306
|
}
|
303
307
|
});
|
304
308
|
// Annotate button
|
305
|
-
const annotateBtn = this.modal.querySelector(
|
306
|
-
annotateBtn.addEventListener(
|
309
|
+
const annotateBtn = this.modal.querySelector("#uxbert-annotate-btn");
|
310
|
+
annotateBtn.addEventListener("click", () => {
|
307
311
|
if (this.callbacks.onAnnotate) {
|
308
312
|
this.callbacks.onAnnotate();
|
309
313
|
}
|
310
314
|
});
|
311
315
|
// Retake button
|
312
|
-
const retakeBtn = this.modal.querySelector(
|
313
|
-
retakeBtn.addEventListener(
|
316
|
+
const retakeBtn = this.modal.querySelector("#uxbert-retake-btn");
|
317
|
+
retakeBtn.addEventListener("click", () => {
|
314
318
|
if (this.callbacks.onRetake) {
|
315
319
|
this.callbacks.onRetake();
|
316
320
|
}
|
317
321
|
});
|
322
|
+
// n8n button
|
323
|
+
const n8nBtn = this.modal.querySelector("#uxbert-n8n-btn");
|
324
|
+
n8nBtn.addEventListener("click", () => {
|
325
|
+
this.handleN8nSubmit();
|
326
|
+
});
|
327
|
+
}
|
328
|
+
handleN8nSubmit() {
|
329
|
+
if (!this.modal)
|
330
|
+
return;
|
331
|
+
const titleInput = this.modal.querySelector("#uxbert-title");
|
332
|
+
const descriptionInput = this.modal.querySelector("#uxbert-description");
|
333
|
+
const prioritySelect = this.modal.querySelector("#uxbert-priority");
|
334
|
+
const title = titleInput.value;
|
335
|
+
const description = descriptionInput.value;
|
336
|
+
const priority = prioritySelect.value;
|
337
|
+
if (!title.trim()) {
|
338
|
+
alert("Please enter an issue title");
|
339
|
+
return;
|
340
|
+
}
|
341
|
+
const issueData = {
|
342
|
+
title: title.trim(),
|
343
|
+
description: description.trim(),
|
344
|
+
priority,
|
345
|
+
};
|
346
|
+
if (this.callbacks.onSendToN8n) {
|
347
|
+
this.callbacks.onSendToN8n(issueData);
|
348
|
+
}
|
318
349
|
}
|
319
350
|
handleSubmit() {
|
320
351
|
if (!this.modal)
|
321
352
|
return;
|
322
|
-
const titleInput = this.modal.querySelector(
|
323
|
-
const descriptionInput = this.modal.querySelector(
|
324
|
-
const prioritySelect = this.modal.querySelector(
|
353
|
+
const titleInput = this.modal.querySelector("#uxbert-title");
|
354
|
+
const descriptionInput = this.modal.querySelector("#uxbert-description");
|
355
|
+
const prioritySelect = this.modal.querySelector("#uxbert-priority");
|
325
356
|
const title = titleInput.value;
|
326
357
|
const description = descriptionInput.value;
|
327
358
|
const priority = prioritySelect.value;
|
328
359
|
if (!title.trim()) {
|
329
|
-
alert(
|
360
|
+
alert("Please enter an issue title");
|
330
361
|
return;
|
331
362
|
}
|
332
363
|
const issueData = {
|
333
364
|
title: title.trim(),
|
334
365
|
description: description.trim(),
|
335
|
-
priority
|
366
|
+
priority,
|
336
367
|
};
|
337
368
|
if (this.callbacks.onSubmit) {
|
338
369
|
this.callbacks.onSubmit(issueData);
|
339
370
|
}
|
340
371
|
}
|
341
372
|
open() {
|
342
|
-
this.overlay?.classList.add(
|
373
|
+
this.overlay?.classList.add("active");
|
374
|
+
// Prevent body scroll when modal is open
|
375
|
+
document.body.style.overflow = "hidden";
|
343
376
|
}
|
344
377
|
close() {
|
345
|
-
this.overlay?.classList.remove(
|
378
|
+
this.overlay?.classList.remove("active");
|
379
|
+
// Restore body scroll when modal is closed
|
380
|
+
document.body.style.overflow = "";
|
346
381
|
this.reset();
|
347
382
|
if (this.callbacks.onClose) {
|
348
383
|
this.callbacks.onClose();
|
@@ -351,39 +386,49 @@ class Modal {
|
|
351
386
|
setScreenshot(screenshot) {
|
352
387
|
if (!this.modal)
|
353
388
|
return;
|
354
|
-
const container = this.modal.querySelector(
|
355
|
-
const img = this.modal.querySelector(
|
356
|
-
const captureAction = this.modal.querySelector(
|
357
|
-
const submitBtn = this.modal.querySelector(
|
389
|
+
const container = this.modal.querySelector("#uxbert-screenshot-container");
|
390
|
+
const img = this.modal.querySelector("#uxbert-screenshot-img");
|
391
|
+
const captureAction = this.modal.querySelector("#uxbert-capture-action");
|
392
|
+
const submitBtn = this.modal.querySelector("#uxbert-submit-btn");
|
358
393
|
if (screenshot) {
|
359
394
|
img.src = screenshot;
|
360
|
-
container.style.display =
|
361
|
-
captureAction.style.display =
|
395
|
+
container.style.display = "block";
|
396
|
+
captureAction.style.display = "none";
|
362
397
|
submitBtn.disabled = false;
|
363
398
|
}
|
364
399
|
else {
|
365
|
-
container.style.display =
|
366
|
-
captureAction.style.display =
|
400
|
+
container.style.display = "none";
|
401
|
+
captureAction.style.display = "block";
|
367
402
|
submitBtn.disabled = true;
|
368
403
|
}
|
369
404
|
}
|
370
405
|
getCaptureMode() {
|
371
406
|
if (!this.modal)
|
372
|
-
return
|
373
|
-
const viewportRadio = this.modal.querySelector(
|
374
|
-
return viewportRadio.checked ?
|
407
|
+
return "viewport";
|
408
|
+
const viewportRadio = this.modal.querySelector("#uxbert-capture-viewport");
|
409
|
+
return viewportRadio.checked ? "viewport" : "fullpage";
|
410
|
+
}
|
411
|
+
setN8nButtonVisible(visible) {
|
412
|
+
if (!this.modal)
|
413
|
+
return;
|
414
|
+
const n8nBtn = this.modal.querySelector("#uxbert-n8n-btn");
|
415
|
+
if (n8nBtn) {
|
416
|
+
n8nBtn.style.display = visible ? "inline-block" : "none";
|
417
|
+
}
|
375
418
|
}
|
376
419
|
reset() {
|
377
420
|
if (!this.modal)
|
378
421
|
return;
|
379
|
-
this.modal.querySelector(
|
380
|
-
this.modal.querySelector(
|
381
|
-
this.modal.querySelector(
|
422
|
+
this.modal.querySelector("#uxbert-title").value = "";
|
423
|
+
this.modal.querySelector("#uxbert-description").value = "";
|
424
|
+
this.modal.querySelector("#uxbert-priority").value = "Medium";
|
382
425
|
this.setScreenshot(null);
|
383
426
|
}
|
384
427
|
destroy() {
|
385
428
|
if (this.overlay && this.overlay.parentNode) {
|
386
429
|
this.overlay.parentNode.removeChild(this.overlay);
|
430
|
+
// Restore body scroll when destroying modal
|
431
|
+
document.body.style.overflow = "";
|
387
432
|
this.overlay = null;
|
388
433
|
this.modal = null;
|
389
434
|
}
|
@@ -10159,9 +10204,223 @@ class DeviceInfo {
|
|
10159
10204
|
}
|
10160
10205
|
}
|
10161
10206
|
|
10207
|
+
class N8nIntegration {
|
10208
|
+
constructor(config) {
|
10209
|
+
this.config = config || null;
|
10210
|
+
}
|
10211
|
+
/**
|
10212
|
+
* Configure n8n integration
|
10213
|
+
*/
|
10214
|
+
configure(config) {
|
10215
|
+
this.config = config;
|
10216
|
+
}
|
10217
|
+
/**
|
10218
|
+
* Check if n8n integration is configured and enabled
|
10219
|
+
*/
|
10220
|
+
isEnabled() {
|
10221
|
+
return !!(this.config && this.config.enabled && this.config.webhookUrl);
|
10222
|
+
}
|
10223
|
+
/**
|
10224
|
+
* Send issue data to n8n webhook
|
10225
|
+
*/
|
10226
|
+
async sendToN8n(issueData) {
|
10227
|
+
if (!this.config || !this.config.webhookUrl) {
|
10228
|
+
return {
|
10229
|
+
success: false,
|
10230
|
+
message: "n8n webhook URL is not configured",
|
10231
|
+
error: "MISSING_CONFIG",
|
10232
|
+
};
|
10233
|
+
}
|
10234
|
+
if (!this.config.enabled) {
|
10235
|
+
return {
|
10236
|
+
success: false,
|
10237
|
+
message: "n8n integration is disabled",
|
10238
|
+
error: "DISABLED",
|
10239
|
+
};
|
10240
|
+
}
|
10241
|
+
try {
|
10242
|
+
// Prepare FormData with binary screenshot
|
10243
|
+
const formData = await this.prepareFormData(issueData);
|
10244
|
+
// Setup request headers (don't set Content-Type - browser will set it with boundary for FormData)
|
10245
|
+
const headers = {
|
10246
|
+
...this.config.headers,
|
10247
|
+
};
|
10248
|
+
// Setup timeout
|
10249
|
+
const timeout = this.config.timeout || 30000; // 30 seconds default
|
10250
|
+
const controller = new AbortController();
|
10251
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
10252
|
+
// Send request
|
10253
|
+
const response = await fetch(this.config.webhookUrl, {
|
10254
|
+
method: "POST",
|
10255
|
+
headers,
|
10256
|
+
body: formData,
|
10257
|
+
signal: controller.signal,
|
10258
|
+
});
|
10259
|
+
clearTimeout(timeoutId);
|
10260
|
+
// Check response
|
10261
|
+
if (!response.ok) {
|
10262
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
10263
|
+
return {
|
10264
|
+
success: false,
|
10265
|
+
message: `n8n webhook request failed: ${response.status} ${response.statusText}`,
|
10266
|
+
error: errorText,
|
10267
|
+
};
|
10268
|
+
}
|
10269
|
+
// Parse response
|
10270
|
+
let responseData;
|
10271
|
+
try {
|
10272
|
+
responseData = await response.json();
|
10273
|
+
}
|
10274
|
+
catch (e) {
|
10275
|
+
// Some webhooks don't return JSON
|
10276
|
+
responseData = { message: "Success" };
|
10277
|
+
}
|
10278
|
+
return {
|
10279
|
+
success: true,
|
10280
|
+
message: "Issue sent to n8n successfully",
|
10281
|
+
workflowId: responseData.workflowId || responseData.executionId,
|
10282
|
+
};
|
10283
|
+
}
|
10284
|
+
catch (error) {
|
10285
|
+
if (error instanceof Error) {
|
10286
|
+
if (error.name === "AbortError") {
|
10287
|
+
return {
|
10288
|
+
success: false,
|
10289
|
+
message: "Request to n8n webhook timed out",
|
10290
|
+
error: "TIMEOUT",
|
10291
|
+
};
|
10292
|
+
}
|
10293
|
+
return {
|
10294
|
+
success: false,
|
10295
|
+
message: `Failed to send issue to n8n: ${error.message}`,
|
10296
|
+
error: error.message,
|
10297
|
+
};
|
10298
|
+
}
|
10299
|
+
return {
|
10300
|
+
success: false,
|
10301
|
+
message: "Unknown error occurred while sending to n8n",
|
10302
|
+
error: "UNKNOWN",
|
10303
|
+
};
|
10304
|
+
}
|
10305
|
+
}
|
10306
|
+
/**
|
10307
|
+
* Convert base64 data URL to Blob
|
10308
|
+
*/
|
10309
|
+
base64ToBlob(base64Data) {
|
10310
|
+
// Extract the base64 string and mime type
|
10311
|
+
const matches = base64Data.match(/^data:([^;]+);base64,(.+)$/);
|
10312
|
+
if (!matches) {
|
10313
|
+
throw new Error("Invalid base64 data URL");
|
10314
|
+
}
|
10315
|
+
const mimeType = matches[1];
|
10316
|
+
const base64String = matches[2];
|
10317
|
+
// Decode base64
|
10318
|
+
const byteCharacters = atob(base64String);
|
10319
|
+
const byteNumbers = new Array(byteCharacters.length);
|
10320
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
10321
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
10322
|
+
}
|
10323
|
+
const byteArray = new Uint8Array(byteNumbers);
|
10324
|
+
return new Blob([byteArray], { type: mimeType });
|
10325
|
+
}
|
10326
|
+
/**
|
10327
|
+
* Prepare FormData payload for n8n webhook
|
10328
|
+
* This sends the screenshot as a binary file instead of base64 JSON
|
10329
|
+
*/
|
10330
|
+
async prepareFormData(issueData) {
|
10331
|
+
const formData = new FormData();
|
10332
|
+
// Add issue data as JSON string
|
10333
|
+
formData.append("title", issueData.title);
|
10334
|
+
formData.append("description", issueData.description);
|
10335
|
+
formData.append("priority", issueData.priority);
|
10336
|
+
formData.append("createdAt", issueData.createdAt);
|
10337
|
+
// Convert base64 screenshot to binary Blob and add as file
|
10338
|
+
const screenshotBlob = this.base64ToBlob(issueData.screenshot);
|
10339
|
+
const filename = `screenshot-${Date.now()}.png`;
|
10340
|
+
formData.append("screenshot", screenshotBlob, filename);
|
10341
|
+
// Add device info as individual fields
|
10342
|
+
formData.append("browser", issueData.deviceInfo.browser);
|
10343
|
+
formData.append("os", issueData.deviceInfo.os);
|
10344
|
+
formData.append("screenResolution", issueData.deviceInfo.screenResolution);
|
10345
|
+
formData.append("viewport", issueData.deviceInfo.viewport);
|
10346
|
+
formData.append("url", issueData.deviceInfo.url);
|
10347
|
+
formData.append("userAgent", issueData.deviceInfo.userAgent);
|
10348
|
+
formData.append("language", issueData.deviceInfo.language || "");
|
10349
|
+
formData.append("platform", issueData.deviceInfo.platform);
|
10350
|
+
formData.append("cookiesEnabled", String(issueData.deviceInfo.cookiesEnabled));
|
10351
|
+
formData.append("onLine", String(issueData.deviceInfo.onLine));
|
10352
|
+
formData.append("timestamp", issueData.deviceInfo.timestamp);
|
10353
|
+
// Add metadata
|
10354
|
+
formData.append("source", "uxbert-reportly");
|
10355
|
+
formData.append("version", "1.0.0");
|
10356
|
+
return formData;
|
10357
|
+
}
|
10358
|
+
/**
|
10359
|
+
* Test connection to n8n webhook
|
10360
|
+
*/
|
10361
|
+
async testConnection() {
|
10362
|
+
if (!this.config || !this.config.webhookUrl) {
|
10363
|
+
return {
|
10364
|
+
success: false,
|
10365
|
+
message: "n8n webhook URL is not configured",
|
10366
|
+
error: "MISSING_CONFIG",
|
10367
|
+
};
|
10368
|
+
}
|
10369
|
+
try {
|
10370
|
+
const controller = new AbortController();
|
10371
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout for test
|
10372
|
+
await fetch(this.config.webhookUrl, {
|
10373
|
+
method: "HEAD",
|
10374
|
+
signal: controller.signal,
|
10375
|
+
});
|
10376
|
+
clearTimeout(timeoutId);
|
10377
|
+
return {
|
10378
|
+
success: true,
|
10379
|
+
message: "n8n webhook is reachable",
|
10380
|
+
};
|
10381
|
+
}
|
10382
|
+
catch (error) {
|
10383
|
+
return {
|
10384
|
+
success: false,
|
10385
|
+
message: "Failed to reach n8n webhook",
|
10386
|
+
error: error instanceof Error ? error.message : "UNKNOWN",
|
10387
|
+
};
|
10388
|
+
}
|
10389
|
+
}
|
10390
|
+
/**
|
10391
|
+
* Get current configuration
|
10392
|
+
*/
|
10393
|
+
getConfig() {
|
10394
|
+
return this.config;
|
10395
|
+
}
|
10396
|
+
/**
|
10397
|
+
* Update webhook URL
|
10398
|
+
*/
|
10399
|
+
setWebhookUrl(url) {
|
10400
|
+
if (!this.config) {
|
10401
|
+
this.config = {
|
10402
|
+
webhookUrl: url,
|
10403
|
+
enabled: true,
|
10404
|
+
};
|
10405
|
+
}
|
10406
|
+
else {
|
10407
|
+
this.config.webhookUrl = url;
|
10408
|
+
}
|
10409
|
+
}
|
10410
|
+
/**
|
10411
|
+
* Enable/disable n8n integration
|
10412
|
+
*/
|
10413
|
+
setEnabled(enabled) {
|
10414
|
+
if (this.config) {
|
10415
|
+
this.config.enabled = enabled;
|
10416
|
+
}
|
10417
|
+
}
|
10418
|
+
}
|
10419
|
+
|
10162
10420
|
class Export {
|
10163
|
-
constructor() {
|
10421
|
+
constructor(n8nConfig) {
|
10164
10422
|
this.savedIssues = this.loadSavedIssues();
|
10423
|
+
this.n8nIntegration = new N8nIntegration(n8nConfig);
|
10165
10424
|
}
|
10166
10425
|
exportToJSON(issueData) {
|
10167
10426
|
const json = JSON.stringify(issueData, null, 2);
|
@@ -10230,6 +10489,54 @@ class Export {
|
|
10230
10489
|
document.body.removeChild(link);
|
10231
10490
|
URL.revokeObjectURL(url);
|
10232
10491
|
}
|
10492
|
+
// n8n Integration Methods
|
10493
|
+
/**
|
10494
|
+
* Send issue to n8n webhook
|
10495
|
+
*/
|
10496
|
+
async sendToN8n(issueData) {
|
10497
|
+
const response = await this.n8nIntegration.sendToN8n(issueData);
|
10498
|
+
// Save to localStorage if n8n send was successful
|
10499
|
+
if (response.success) {
|
10500
|
+
this.saveIssue(issueData);
|
10501
|
+
}
|
10502
|
+
return response;
|
10503
|
+
}
|
10504
|
+
/**
|
10505
|
+
* Configure n8n integration
|
10506
|
+
*/
|
10507
|
+
configureN8n(config) {
|
10508
|
+
this.n8nIntegration.configure(config);
|
10509
|
+
}
|
10510
|
+
/**
|
10511
|
+
* Check if n8n is enabled
|
10512
|
+
*/
|
10513
|
+
isN8nEnabled() {
|
10514
|
+
return this.n8nIntegration.isEnabled();
|
10515
|
+
}
|
10516
|
+
/**
|
10517
|
+
* Test n8n connection
|
10518
|
+
*/
|
10519
|
+
async testN8nConnection() {
|
10520
|
+
return this.n8nIntegration.testConnection();
|
10521
|
+
}
|
10522
|
+
/**
|
10523
|
+
* Get n8n configuration
|
10524
|
+
*/
|
10525
|
+
getN8nConfig() {
|
10526
|
+
return this.n8nIntegration.getConfig();
|
10527
|
+
}
|
10528
|
+
/**
|
10529
|
+
* Enable/disable n8n integration
|
10530
|
+
*/
|
10531
|
+
setN8nEnabled(enabled) {
|
10532
|
+
this.n8nIntegration.setEnabled(enabled);
|
10533
|
+
}
|
10534
|
+
/**
|
10535
|
+
* Set n8n webhook URL
|
10536
|
+
*/
|
10537
|
+
setN8nWebhookUrl(url) {
|
10538
|
+
this.n8nIntegration.setWebhookUrl(url);
|
10539
|
+
}
|
10233
10540
|
}
|
10234
10541
|
|
10235
10542
|
function styleInject(css, ref) {
|
@@ -10259,7 +10566,7 @@ function styleInject(css, ref) {
|
|
10259
10566
|
}
|
10260
10567
|
}
|
10261
10568
|
|
10262
|
-
var css_248z = ":root{--uxbert-primary:#4f46e5;--uxbert-primary-hover:#4338ca;--uxbert-danger:#ef4444;--uxbert-success:#10b981;--uxbert-bg:#fff;--uxbert-text:#1f2937;--uxbert-border:#e5e7eb;--uxbert-shadow:0 10px 25px rgba(0,0,0,.1);--uxbert-z-button:999999;--uxbert-z-modal:1000000;--uxbert-z-canvas:1000001;--uxbert-z-toolbar:1000002}[data-theme=dark]{--uxbert-bg:#1f2937;--uxbert-text:#f9fafb;--uxbert-border:#374151}.uxbert-fab{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:flex;font-size:24px;height:56px;justify-content:center;position:fixed;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-button)}.uxbert-fab:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-fab.bottom-right{bottom:24px;right:24px}.uxbert-fab.bottom-left{bottom:24px;left:24px}.uxbert-fab.top-right{right:24px;top:24px}.uxbert-fab.top-left{left:24px;top:24px}.uxbert-overlay{align-items:center;animation:fadeIn .3s ease;background:rgba(0,0,0,.5);display:none;height:100%;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:var(--uxbert-z-modal)}.uxbert-overlay.active{display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.uxbert-modal{animation:slideUp .3s ease;background:var(--uxbert-bg);border-radius:12px;box-shadow:var(--uxbert-shadow);color:var(--uxbert-text);max-height:90vh;max-width:600px;overflow-y:auto;padding:24px;width:90%}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.uxbert-modal-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.uxbert-modal-title{font-size:20px;font-weight:600;margin:0}.uxbert-modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:24px;height:32px;justify-content:center;padding:0;width:32px}.uxbert-modal-close:hover{background:var(--uxbert-border)}.uxbert-form-group{margin-bottom:16px}.uxbert-form-label{display:block;font-size:14px;font-weight:500;margin-bottom:8px}.uxbert-capture-mode{display:flex;flex-wrap:wrap;gap:12px}.uxbert-radio-label{align-items:center;border:2px solid var(--uxbert-border);border-radius:8px;cursor:pointer;display:flex;flex:1;gap:8px;min-width:140px;padding:10px 16px;transition:all .2s ease}.uxbert-radio-label:hover{background:rgba(79,70,229,.05);border-color:var(--uxbert-primary)}.uxbert-radio-label input[type=radio]{cursor:pointer;height:18px;margin:0;width:18px}.uxbert-radio-label input[type=radio]:checked{accent-color:var(--uxbert-primary)}.uxbert-radio-label:has(input[type=radio]:checked){background:rgba(79,70,229,.1);border-color:var(--uxbert-primary)}.uxbert-radio-label span{flex:1;font-size:14px;font-weight:500}.uxbert-form-input,.uxbert-form-select,.uxbert-form-textarea{background:var(--uxbert-bg);border:1px solid var(--uxbert-border);border-radius:6px;box-sizing:border-box;color:var(--uxbert-text);font-family:inherit;font-size:14px;padding:10px;width:100%}.uxbert-form-textarea{min-height:100px;resize:vertical}.uxbert-form-input:focus,.uxbert-form-select:focus,.uxbert-form-textarea:focus{border-color:var(--uxbert-primary);outline:none}.uxbert-capture-action{margin:16px 0;text-align:center}.uxbert-capture-action .uxbert-btn{min-width:200px}.uxbert-screenshot-preview{border:1px solid var(--uxbert-border);border-radius:8px;margin:16px 0;overflow:hidden}.uxbert-screenshot-preview img{display:block;width:100%}.uxbert-screenshot-actions{background:var(--uxbert-border);display:flex;gap:8px;padding:12px}.uxbert-btn{align-items:center;border:none;border-radius:6px;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:8px;padding:10px 20px;transition:all .2s ease}.uxbert-btn-primary{background:var(--uxbert-primary);color:#fff}.uxbert-btn-primary:hover{background:var(--uxbert-primary-hover)}.uxbert-btn-secondary{background:var(--uxbert-border);color:var(--uxbert-text)}.uxbert-btn-secondary:hover{background:#d1d5db}.uxbert-btn-danger{background:var(--uxbert-danger);color:#fff}.uxbert-btn-danger:hover{background:#dc2626}.uxbert-modal-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:20px}.uxbert-toolbar-toggle{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;bottom:24px;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:none;font-size:24px;height:56px;justify-content:center;position:fixed;right:24px;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar-toggle.active{display:flex}.uxbert-toolbar-toggle.hidden{opacity:0;pointer-events:none;transform:scale(.8)}.uxbert-toolbar-toggle:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-toolbar{background:var(--uxbert-bg);border-radius:12px;bottom:24px;box-shadow:var(--uxbert-shadow);display:none;flex-direction:column;gap:8px;max-height:80vh;opacity:0;overflow-y:auto;padding:16px;pointer-events:none;position:fixed;right:24px;transform:translateY(20px);transition:all .3s ease;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar.active{display:flex}.uxbert-toolbar.expanded{opacity:1;pointer-events:all;transform:translateY(0)}.uxbert-toolbar-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:8px}.uxbert-toolbar-title{flex:1;font-size:14px;font-weight:600}.uxbert-toolbar-exit,.uxbert-toolbar-minimize{align-items:center;background:var(--uxbert-border);border:none;border-radius:6px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:20px;font-weight:700;height:32px;justify-content:center;transition:all .2s ease;width:32px}.uxbert-toolbar-exit{background:var(--uxbert-danger);color:#fff}.uxbert-toolbar-minimize:hover{background:#d1d5db;transform:scale(1.1)}.uxbert-toolbar-exit:hover{background:#dc2626;transform:scale(1.1)}.uxbert-toolbar-tools{display:flex;flex-wrap:wrap;gap:8px}.uxbert-tool-btn{align-items:center;background:var(--uxbert-bg);border:2px solid var(--uxbert-border);border-radius:6px;cursor:pointer;display:flex;font-family:Arial,sans-serif;font-size:18px;font-weight:700;height:40px;justify-content:center;transition:all .2s ease;width:40px}.uxbert-tool-btn.active,.uxbert-tool-btn:hover{background:var(--uxbert-primary);border-color:var(--uxbert-primary);color:#fff}.uxbert-color-picker{display:flex;gap:6px;margin:8px 0}.uxbert-color-option{border:2px solid var(--uxbert-border);border-radius:50%;cursor:pointer;height:32px;transition:transform .2s ease;width:32px}.uxbert-color-option:hover{transform:scale(1.1)}.uxbert-color-option.active{border:3px solid var(--uxbert-text)}.uxbert-canvas-overlay{cursor:crosshair;display:none;left:0;position:absolute;top:0;z-index:var(--uxbert-z-canvas)}.uxbert-canvas-overlay.active{display:block}.uxbert-canvas-overlay.viewport-mode{left:0;position:fixed;top:0}.uxbert-text-input{background:hsla(0,0%,100%,.95);border:2px solid var(--uxbert-primary);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--uxbert-text);font-family:Arial,sans-serif;font-size:16px;font-weight:700;min-width:200px;outline:none;padding:8px 12px;z-index:var(--uxbert-z-toolbar)}.uxbert-text-input:focus{border-color:var(--uxbert-primary-hover);box-shadow:0 4px 16px rgba(79,70,229,.3)}.uxbert-text-input::placeholder{color:#9ca3af;font-weight:400}@media (max-width:768px){.uxbert-modal{max-height:95vh;padding:16px;width:95%}.uxbert-toolbar{bottom:90px;left:16px;max-height:60vh;right:16px;width:auto}.uxbert-toolbar-toggle{bottom:16px;height:56px;right:16px;width:56px}.uxbert-fab{font-size:20px;height:48px;width:48px}.uxbert-color-picker,.uxbert-toolbar-tools{justify-content:center}}";
|
10569
|
+
var css_248z = ":root{--uxbert-primary:#4f46e5;--uxbert-primary-hover:#4338ca;--uxbert-danger:#ef4444;--uxbert-success:#10b981;--uxbert-bg:#fff;--uxbert-text:#1f2937;--uxbert-border:#e5e7eb;--uxbert-shadow:0 10px 25px rgba(0,0,0,.1);--uxbert-z-button:999999;--uxbert-z-modal:1000000;--uxbert-z-canvas:1000001;--uxbert-z-toolbar:1000002}[data-theme=dark]{--uxbert-bg:#1f2937;--uxbert-text:#f9fafb;--uxbert-border:#374151}.uxbert-fab{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:flex;font-size:24px;height:56px;justify-content:center;position:fixed;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-button)}.uxbert-fab:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-fab.bottom-right{bottom:24px;right:24px}.uxbert-fab.bottom-left{bottom:24px;left:24px}.uxbert-fab.top-right{right:24px;top:24px}.uxbert-fab.top-left{left:24px;top:24px}.uxbert-overlay{align-items:center;animation:fadeIn .3s ease;background:rgba(0,0,0,.5);display:none;height:100%;justify-content:center;left:0;overflow:hidden;position:fixed;top:0;width:100%;z-index:var(--uxbert-z-modal)}.uxbert-overlay.active{display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.uxbert-modal{animation:slideUp .3s ease;background:var(--uxbert-bg);border-radius:12px;box-shadow:var(--uxbert-shadow);color:var(--uxbert-text);max-height:90vh;max-width:600px;overflow-y:auto;padding:24px;width:90%}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.uxbert-modal-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.uxbert-modal-title{font-size:20px;font-weight:600;margin:0}.uxbert-modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:24px;height:32px;justify-content:center;padding:0;width:32px}.uxbert-modal-close:hover{background:var(--uxbert-border)}.uxbert-form-group{margin-bottom:16px}.uxbert-form-label{display:block;font-size:14px;font-weight:500;margin-bottom:8px}.uxbert-capture-mode{display:flex;flex-wrap:wrap;gap:12px}.uxbert-radio-label{align-items:center;border:2px solid var(--uxbert-border);border-radius:8px;cursor:pointer;display:flex;flex:1;gap:8px;min-width:140px;padding:10px 16px;transition:all .2s ease}.uxbert-radio-label:hover{background:rgba(79,70,229,.05);border-color:var(--uxbert-primary)}.uxbert-radio-label input[type=radio]{cursor:pointer;height:18px;margin:0;width:18px}.uxbert-radio-label input[type=radio]:checked{accent-color:var(--uxbert-primary)}.uxbert-radio-label:has(input[type=radio]:checked){background:rgba(79,70,229,.1);border-color:var(--uxbert-primary)}.uxbert-radio-label span{flex:1;font-size:14px;font-weight:500}.uxbert-form-input,.uxbert-form-select,.uxbert-form-textarea{background:var(--uxbert-bg);border:1px solid var(--uxbert-border);border-radius:6px;box-sizing:border-box;color:var(--uxbert-text);font-family:inherit;font-size:14px;padding:10px;width:100%}.uxbert-form-textarea{min-height:100px;resize:vertical}.uxbert-form-input:focus,.uxbert-form-select:focus,.uxbert-form-textarea:focus{border-color:var(--uxbert-primary);outline:none}.uxbert-capture-action{margin:16px 0;text-align:center}.uxbert-capture-action .uxbert-btn{min-width:200px}.uxbert-screenshot-preview{border:1px solid var(--uxbert-border);border-radius:8px;margin:16px 0;overflow:hidden}.uxbert-screenshot-preview img{display:block;width:100%}.uxbert-screenshot-actions{background:var(--uxbert-border);display:flex;gap:8px;padding:12px}.uxbert-btn{align-items:center;border:none;border-radius:6px;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:8px;padding:10px 20px;transition:all .2s ease}.uxbert-btn-primary{background:var(--uxbert-primary);color:#fff}.uxbert-btn-primary:hover{background:var(--uxbert-primary-hover)}.uxbert-btn-secondary{background:var(--uxbert-border);color:var(--uxbert-text)}.uxbert-btn-secondary:hover{background:#d1d5db}.uxbert-btn-success{background:var(--uxbert-success);color:#fff}.uxbert-btn-success:hover{background:#059669}.uxbert-btn-danger{background:var(--uxbert-danger);color:#fff}.uxbert-btn-danger:hover{background:#dc2626}.uxbert-modal-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:20px}.uxbert-toolbar-toggle{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;bottom:24px;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:none;font-size:24px;height:56px;justify-content:center;position:fixed;right:24px;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar-toggle.active{display:flex}.uxbert-toolbar-toggle.hidden{opacity:0;pointer-events:none;transform:scale(.8)}.uxbert-toolbar-toggle:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-toolbar{background:var(--uxbert-bg);border-radius:12px;bottom:24px;box-shadow:var(--uxbert-shadow);display:none;flex-direction:column;gap:8px;max-height:80vh;opacity:0;overflow-y:auto;padding:16px;pointer-events:none;position:fixed;right:24px;transform:translateY(20px);transition:all .3s ease;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar.active{display:flex}.uxbert-toolbar.expanded{opacity:1;pointer-events:all;transform:translateY(0)}.uxbert-toolbar-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:8px}.uxbert-toolbar-title{flex:1;font-size:14px;font-weight:600}.uxbert-toolbar-exit,.uxbert-toolbar-minimize{align-items:center;background:var(--uxbert-border);border:none;border-radius:6px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:20px;font-weight:700;height:32px;justify-content:center;transition:all .2s ease;width:32px}.uxbert-toolbar-exit{background:var(--uxbert-danger);color:#fff}.uxbert-toolbar-minimize:hover{background:#d1d5db;transform:scale(1.1)}.uxbert-toolbar-exit:hover{background:#dc2626;transform:scale(1.1)}.uxbert-toolbar-tools{display:flex;flex-wrap:wrap;gap:8px}.uxbert-tool-btn{align-items:center;background:var(--uxbert-bg);border:2px solid var(--uxbert-border);border-radius:6px;cursor:pointer;display:flex;font-family:Arial,sans-serif;font-size:18px;font-weight:700;height:40px;justify-content:center;transition:all .2s ease;width:40px}.uxbert-tool-btn.active,.uxbert-tool-btn:hover{background:var(--uxbert-primary);border-color:var(--uxbert-primary);color:#fff}.uxbert-color-picker{display:flex;gap:6px;margin:8px 0}.uxbert-color-option{border:2px solid var(--uxbert-border);border-radius:50%;cursor:pointer;height:32px;transition:transform .2s ease;width:32px}.uxbert-color-option:hover{transform:scale(1.1)}.uxbert-color-option.active{border:3px solid var(--uxbert-text)}.uxbert-canvas-overlay{cursor:crosshair;display:none;left:0;position:absolute;top:0;z-index:var(--uxbert-z-canvas)}.uxbert-canvas-overlay.active{display:block}.uxbert-canvas-overlay.viewport-mode{left:0;position:fixed;top:0}.uxbert-text-input{background:hsla(0,0%,100%,.95);border:2px solid var(--uxbert-primary);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--uxbert-text);font-family:Arial,sans-serif;font-size:16px;font-weight:700;min-width:200px;outline:none;padding:8px 12px;z-index:var(--uxbert-z-toolbar)}.uxbert-text-input:focus{border-color:var(--uxbert-primary-hover);box-shadow:0 4px 16px rgba(79,70,229,.3)}.uxbert-text-input::placeholder{color:#9ca3af;font-weight:400}@media (max-width:768px){.uxbert-modal{max-height:95vh;padding:16px;width:95%}.uxbert-toolbar{bottom:90px;left:16px;max-height:60vh;right:16px;width:auto}.uxbert-toolbar-toggle{bottom:16px;height:56px;right:16px;width:56px}.uxbert-fab{font-size:20px;height:48px;width:48px}.uxbert-color-picker,.uxbert-toolbar-tools{justify-content:center}}";
|
10263
10570
|
styleInject(css_248z);
|
10264
10571
|
|
10265
10572
|
// Main initialization file
|
@@ -10291,7 +10598,9 @@ class Reportly {
|
|
10291
10598
|
this.state = new State();
|
10292
10599
|
this.deviceInfo = new DeviceInfo();
|
10293
10600
|
this.screenshot = new Screenshot();
|
10294
|
-
|
10601
|
+
// Initialize export with n8n config if provided
|
10602
|
+
const n8nConfig = userConfig.integrations?.n8n;
|
10603
|
+
this.export = new Export(n8nConfig);
|
10295
10604
|
// Initialize UI components
|
10296
10605
|
this.button = new Button(this.config, {
|
10297
10606
|
onClick: () => this.handleButtonClick(),
|
@@ -10302,6 +10611,7 @@ class Reportly {
|
|
10302
10611
|
onAnnotate: () => this.startAnnotation(),
|
10303
10612
|
onRetake: () => this.retakeScreenshot(),
|
10304
10613
|
onCapture: () => this.captureWithMode(),
|
10614
|
+
onSendToN8n: (issueData) => this.handleN8nSubmit(issueData),
|
10305
10615
|
});
|
10306
10616
|
this.toolbar = new Toolbar({
|
10307
10617
|
onToolChange: (tool) => this.annotation?.setTool(tool),
|
@@ -10317,6 +10627,10 @@ class Reportly {
|
|
10317
10627
|
this.modal.create();
|
10318
10628
|
this.toolbar.create();
|
10319
10629
|
this.annotation.createCanvas();
|
10630
|
+
// Show/hide n8n button based on configuration
|
10631
|
+
if (this.export.isN8nEnabled()) {
|
10632
|
+
this.modal.setN8nButtonVisible(true);
|
10633
|
+
}
|
10320
10634
|
// Setup keyboard shortcuts
|
10321
10635
|
this.setupKeyboardShortcuts();
|
10322
10636
|
this.isInitialized = true;
|
@@ -10444,6 +10758,54 @@ class Reportly {
|
|
10444
10758
|
alert("Failed to export issue. Please try again.");
|
10445
10759
|
}
|
10446
10760
|
}
|
10761
|
+
async handleN8nSubmit(issueData) {
|
10762
|
+
try {
|
10763
|
+
// Create complete issue package
|
10764
|
+
const completeIssue = {
|
10765
|
+
...issueData,
|
10766
|
+
screenshot: this.state?.getScreenshot() || "",
|
10767
|
+
deviceInfo: this.deviceInfo.get(),
|
10768
|
+
createdAt: new Date().toISOString(),
|
10769
|
+
};
|
10770
|
+
// Show loading state
|
10771
|
+
const n8nBtn = document.querySelector('#uxbert-n8n-btn');
|
10772
|
+
if (n8nBtn) {
|
10773
|
+
n8nBtn.disabled = true;
|
10774
|
+
n8nBtn.textContent = '⏳ Sending...';
|
10775
|
+
}
|
10776
|
+
// Send to n8n
|
10777
|
+
const response = await this.export?.sendToN8n(completeIssue);
|
10778
|
+
if (response?.success) {
|
10779
|
+
// Emit event
|
10780
|
+
this.state?.emit("issue:sent-to-n8n", completeIssue);
|
10781
|
+
// Reset state
|
10782
|
+
this.state?.reset();
|
10783
|
+
this.annotation?.clear();
|
10784
|
+
this.modal?.close();
|
10785
|
+
alert("Issue sent to n8n successfully!");
|
10786
|
+
console.log("Issue sent to n8n successfully");
|
10787
|
+
}
|
10788
|
+
else {
|
10789
|
+
alert(`Failed to send to n8n: ${response?.message || 'Unknown error'}`);
|
10790
|
+
console.error("Failed to send to n8n:", response?.error);
|
10791
|
+
}
|
10792
|
+
// Reset button state
|
10793
|
+
if (n8nBtn) {
|
10794
|
+
n8nBtn.disabled = false;
|
10795
|
+
n8nBtn.textContent = '🚀 Send to n8n';
|
10796
|
+
}
|
10797
|
+
}
|
10798
|
+
catch (error) {
|
10799
|
+
console.error("Failed to send to n8n:", error);
|
10800
|
+
alert("Failed to send to n8n. Please try again.");
|
10801
|
+
// Reset button state
|
10802
|
+
const n8nBtn = document.querySelector('#uxbert-n8n-btn');
|
10803
|
+
if (n8nBtn) {
|
10804
|
+
n8nBtn.disabled = false;
|
10805
|
+
n8nBtn.textContent = '🚀 Send to n8n';
|
10806
|
+
}
|
10807
|
+
}
|
10808
|
+
}
|
10447
10809
|
handleModalClose() {
|
10448
10810
|
this.annotation?.hide();
|
10449
10811
|
this.toolbar?.hide();
|
@@ -10472,6 +10834,24 @@ class Reportly {
|
|
10472
10834
|
exportAllIssues() {
|
10473
10835
|
this.export?.exportAllIssues();
|
10474
10836
|
}
|
10837
|
+
// n8n Integration API methods
|
10838
|
+
configureN8n(webhookUrl, enabled = true, options) {
|
10839
|
+
this.export?.configureN8n({
|
10840
|
+
webhookUrl,
|
10841
|
+
enabled,
|
10842
|
+
headers: options?.headers,
|
10843
|
+
timeout: options?.timeout
|
10844
|
+
});
|
10845
|
+
// Update button visibility
|
10846
|
+
this.modal?.setN8nButtonVisible(enabled);
|
10847
|
+
}
|
10848
|
+
enableN8n(enabled) {
|
10849
|
+
this.export?.setN8nEnabled(enabled);
|
10850
|
+
this.modal?.setN8nButtonVisible(enabled);
|
10851
|
+
}
|
10852
|
+
testN8nConnection() {
|
10853
|
+
return this.export?.testN8nConnection() || Promise.resolve({ success: false, message: 'Not initialized' });
|
10854
|
+
}
|
10475
10855
|
on(event, callback) {
|
10476
10856
|
this.state?.on(event, callback);
|
10477
10857
|
}
|