@uxbertlabs/reportly 1.0.16 → 1.0.18
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 +52 -0
- package/dist/features/n8n-integration.d.ts.map +1 -0
- package/dist/features/screenshot.d.ts.map +1 -1
- package/dist/reportly.cjs.js +372 -5
- package/dist/reportly.cjs.js.map +1 -1
- package/dist/reportly.esm.js +372 -5
- package/dist/reportly.esm.js.map +1 -1
- package/dist/reportly.js +372 -5
- 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 +2 -0
- package/dist/ui/modal.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/core/init.d.ts
CHANGED
@@ -21,6 +21,7 @@ declare class Reportly {
|
|
21
21
|
private finishAnnotation;
|
22
22
|
private retakeScreenshot;
|
23
23
|
private handleIssueSubmit;
|
24
|
+
private handleN8nSubmit;
|
24
25
|
private handleModalClose;
|
25
26
|
open(): void;
|
26
27
|
close(): void;
|
@@ -28,6 +29,12 @@ declare class Reportly {
|
|
28
29
|
getSavedIssues(): SavedIssue[];
|
29
30
|
clearSavedIssues(): void;
|
30
31
|
exportAllIssues(): void;
|
32
|
+
configureN8n(webhookUrl: string, enabled?: boolean, options?: {
|
33
|
+
headers?: Record<string, string>;
|
34
|
+
timeout?: number;
|
35
|
+
}): void;
|
36
|
+
enableN8n(enabled: boolean): void;
|
37
|
+
testN8nConnection(): Promise<any>;
|
31
38
|
on(event: string, callback: EventCallback): void;
|
32
39
|
destroy(): void;
|
33
40
|
}
|
package/dist/core/init.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"AAUA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAA4B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEpG,cAAM,QAAQ;IACZ,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAAU;;IAe/B,IAAI,CAAC,UAAU,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,IAAI;
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"AAUA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAA4B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEpG,cAAM,QAAQ;IACZ,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAAU;;IAe/B,IAAI,CAAC,UAAU,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,IAAI;IAiEpD,OAAO,CAAC,sBAAsB;YAUhB,iBAAiB;YAUjB,eAAe;IAyB7B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,cAAc;YASR,gBAAgB;YA2BhB,gBAAgB;IAwB9B,OAAO,CAAC,iBAAiB;YA4BX,eAAe;IAsD7B,OAAO,CAAC,gBAAgB;IAQxB,IAAI,IAAI,IAAI;IAIZ,KAAK,IAAI,IAAI;IAKb,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAMtD,cAAc,IAAI,UAAU,EAAE;IAI9B,gBAAgB,IAAI,IAAI;IAIxB,eAAe,IAAI,IAAI;IAKvB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,OAAc,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYjI,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKjC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC;IAIjC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAIhD,OAAO,IAAI,IAAI;CAOhB;AAGD,QAAA,MAAM,QAAQ,UAAiB,CAAC;AAGhC,eAAe,QAAQ,CAAC"}
|
@@ -1,7 +1,9 @@
|
|
1
1
|
import type { CompleteIssue, SavedIssue } from '../types';
|
2
|
+
import { type N8nConfig, type N8nResponse } from './n8n-integration';
|
2
3
|
declare class Export {
|
3
4
|
private savedIssues;
|
4
|
-
|
5
|
+
private n8nIntegration;
|
6
|
+
constructor(n8nConfig?: N8nConfig);
|
5
7
|
exportToJSON(issueData: CompleteIssue): string;
|
6
8
|
private saveIssue;
|
7
9
|
private loadSavedIssues;
|
@@ -9,6 +11,34 @@ declare class Export {
|
|
9
11
|
deleteSavedIssue(issueId: number): void;
|
10
12
|
clearSavedIssues(): void;
|
11
13
|
exportAllIssues(): void;
|
14
|
+
/**
|
15
|
+
* Send issue to n8n webhook
|
16
|
+
*/
|
17
|
+
sendToN8n(issueData: CompleteIssue): Promise<N8nResponse>;
|
18
|
+
/**
|
19
|
+
* Configure n8n integration
|
20
|
+
*/
|
21
|
+
configureN8n(config: N8nConfig): void;
|
22
|
+
/**
|
23
|
+
* Check if n8n is enabled
|
24
|
+
*/
|
25
|
+
isN8nEnabled(): boolean;
|
26
|
+
/**
|
27
|
+
* Test n8n connection
|
28
|
+
*/
|
29
|
+
testN8nConnection(): Promise<N8nResponse>;
|
30
|
+
/**
|
31
|
+
* Get n8n configuration
|
32
|
+
*/
|
33
|
+
getN8nConfig(): N8nConfig | null;
|
34
|
+
/**
|
35
|
+
* Enable/disable n8n integration
|
36
|
+
*/
|
37
|
+
setN8nEnabled(enabled: boolean): void;
|
38
|
+
/**
|
39
|
+
* Set n8n webhook URL
|
40
|
+
*/
|
41
|
+
setN8nWebhookUrl(url: string): void;
|
12
42
|
}
|
13
43
|
export default Export;
|
14
44
|
//# sourceMappingURL=export.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/features/export.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/features/export.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAuB,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErF,cAAM,MAAM;IACV,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,SAAS,CAAC,EAAE,SAAS;IAKjC,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,MAAM;IAsB9C,OAAO,CAAC,SAAS;IAmBjB,OAAO,CAAC,eAAe;IAUvB,cAAc,IAAI,UAAU,EAAE;IAI9B,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKvC,gBAAgB,IAAI,IAAI;IAKxB,eAAe,IAAI,IAAI;IAiBvB;;OAEG;IACG,SAAS,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAW/D;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAIrC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC;IAI/C;;OAEG;IACH,YAAY,IAAI,SAAS,GAAG,IAAI;IAIhC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIrC;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGpC;AAED,eAAe,MAAM,CAAC"}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import type { CompleteIssue } from '../types';
|
2
|
+
export interface N8nConfig {
|
3
|
+
webhookUrl: string;
|
4
|
+
enabled: boolean;
|
5
|
+
headers?: Record<string, string>;
|
6
|
+
timeout?: number;
|
7
|
+
}
|
8
|
+
export interface N8nResponse {
|
9
|
+
success: boolean;
|
10
|
+
message: string;
|
11
|
+
workflowId?: string;
|
12
|
+
error?: string;
|
13
|
+
}
|
14
|
+
declare class N8nIntegration {
|
15
|
+
private config;
|
16
|
+
constructor(config?: N8nConfig);
|
17
|
+
/**
|
18
|
+
* Configure n8n integration
|
19
|
+
*/
|
20
|
+
configure(config: N8nConfig): void;
|
21
|
+
/**
|
22
|
+
* Check if n8n integration is configured and enabled
|
23
|
+
*/
|
24
|
+
isEnabled(): boolean;
|
25
|
+
/**
|
26
|
+
* Send issue data to n8n webhook
|
27
|
+
*/
|
28
|
+
sendToN8n(issueData: CompleteIssue): Promise<N8nResponse>;
|
29
|
+
/**
|
30
|
+
* Prepare payload for n8n webhook
|
31
|
+
* This formats the data in a structure that's easy to work with in n8n
|
32
|
+
*/
|
33
|
+
private preparePayload;
|
34
|
+
/**
|
35
|
+
* Test connection to n8n webhook
|
36
|
+
*/
|
37
|
+
testConnection(): Promise<N8nResponse>;
|
38
|
+
/**
|
39
|
+
* Get current configuration
|
40
|
+
*/
|
41
|
+
getConfig(): N8nConfig | null;
|
42
|
+
/**
|
43
|
+
* Update webhook URL
|
44
|
+
*/
|
45
|
+
setWebhookUrl(url: string): void;
|
46
|
+
/**
|
47
|
+
* Enable/disable n8n integration
|
48
|
+
*/
|
49
|
+
setEnabled(enabled: boolean): void;
|
50
|
+
}
|
51
|
+
export default N8nIntegration;
|
52
|
+
//# sourceMappingURL=n8n-integration.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"n8n-integration.d.ts","sourceRoot":"","sources":["../../src/features/n8n-integration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,cAAM,cAAc;IAClB,OAAO,CAAC,MAAM,CAAmB;gBAErB,MAAM,CAAC,EAAE,SAAS;IAI9B;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAIlC;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACG,SAAS,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IA4F/D;;;OAGG;IACH,OAAO,CAAC,cAAc;IAyCtB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAiC5C;;OAEG;IACH,SAAS,IAAI,SAAS,GAAG,IAAI;IAI7B;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAWhC;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAKnC;AAED,eAAe,cAAc,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/features/screenshot.ts"],"names":[],"mappings":"AAGA,cAAM,UAAU;IACd,OAAO,CAAC,iBAAiB,CAAgB;;IAKzC,OAAO,CAAC,IAAI;IAGN,OAAO,CAAC,IAAI,GAAE,UAAU,GAAG,UAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/features/screenshot.ts"],"names":[],"mappings":"AAGA,cAAM,UAAU;IACd,OAAO,CAAC,iBAAiB,CAAgB;;IAKzC,OAAO,CAAC,IAAI;IAGN,OAAO,CAAC,IAAI,GAAE,UAAU,GAAG,UAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;IA8H1E,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,iBAAiB;IA6DzB,OAAO,CAAC,iBAAiB;IAOzB,aAAa,IAAI,MAAM,GAAG,IAAI;IAI9B,KAAK,IAAI,IAAI;CAGd;AAED,eAAe,UAAU,CAAC"}
|
package/dist/reportly.cjs.js
CHANGED
@@ -263,6 +263,9 @@ class Modal {
|
|
263
263
|
<button type="button" class="uxbert-btn uxbert-btn-secondary" id="uxbert-cancel-btn">
|
264
264
|
Cancel
|
265
265
|
</button>
|
266
|
+
<button type="button" class="uxbert-btn uxbert-btn-success" id="uxbert-n8n-btn" style="display: none;">
|
267
|
+
🚀 Send to n8n
|
268
|
+
</button>
|
266
269
|
<button type="submit" class="uxbert-btn uxbert-btn-primary" id="uxbert-submit-btn">
|
267
270
|
📥 Download JSON
|
268
271
|
</button>
|
@@ -317,6 +320,33 @@ class Modal {
|
|
317
320
|
this.callbacks.onRetake();
|
318
321
|
}
|
319
322
|
});
|
323
|
+
// n8n button
|
324
|
+
const n8nBtn = this.modal.querySelector('#uxbert-n8n-btn');
|
325
|
+
n8nBtn.addEventListener('click', () => {
|
326
|
+
this.handleN8nSubmit();
|
327
|
+
});
|
328
|
+
}
|
329
|
+
handleN8nSubmit() {
|
330
|
+
if (!this.modal)
|
331
|
+
return;
|
332
|
+
const titleInput = this.modal.querySelector('#uxbert-title');
|
333
|
+
const descriptionInput = this.modal.querySelector('#uxbert-description');
|
334
|
+
const prioritySelect = this.modal.querySelector('#uxbert-priority');
|
335
|
+
const title = titleInput.value;
|
336
|
+
const description = descriptionInput.value;
|
337
|
+
const priority = prioritySelect.value;
|
338
|
+
if (!title.trim()) {
|
339
|
+
alert('Please enter an issue title');
|
340
|
+
return;
|
341
|
+
}
|
342
|
+
const issueData = {
|
343
|
+
title: title.trim(),
|
344
|
+
description: description.trim(),
|
345
|
+
priority
|
346
|
+
};
|
347
|
+
if (this.callbacks.onSendToN8n) {
|
348
|
+
this.callbacks.onSendToN8n(issueData);
|
349
|
+
}
|
320
350
|
}
|
321
351
|
handleSubmit() {
|
322
352
|
if (!this.modal)
|
@@ -375,6 +405,14 @@ class Modal {
|
|
375
405
|
const viewportRadio = this.modal.querySelector('#uxbert-capture-viewport');
|
376
406
|
return viewportRadio.checked ? 'viewport' : 'fullpage';
|
377
407
|
}
|
408
|
+
setN8nButtonVisible(visible) {
|
409
|
+
if (!this.modal)
|
410
|
+
return;
|
411
|
+
const n8nBtn = this.modal.querySelector('#uxbert-n8n-btn');
|
412
|
+
if (n8nBtn) {
|
413
|
+
n8nBtn.style.display = visible ? 'inline-block' : 'none';
|
414
|
+
}
|
415
|
+
}
|
378
416
|
reset() {
|
379
417
|
if (!this.modal)
|
380
418
|
return;
|
@@ -9454,8 +9492,6 @@ class Screenshot {
|
|
9454
9492
|
}
|
9455
9493
|
async capture(mode = "fullpage") {
|
9456
9494
|
try {
|
9457
|
-
// Show loading screen
|
9458
|
-
this.showLoadingScreen();
|
9459
9495
|
// Hide UXbert UI elements before capturing
|
9460
9496
|
this.hideUXbertElements();
|
9461
9497
|
const originalScrollY = window.scrollY;
|
@@ -9474,6 +9510,8 @@ class Screenshot {
|
|
9474
9510
|
x: window.scrollX,
|
9475
9511
|
y: window.scrollY,
|
9476
9512
|
onclone: async () => {
|
9513
|
+
// Show loading screen after clone (won't appear in screenshot)
|
9514
|
+
this.showLoadingScreen();
|
9477
9515
|
// Wait 1 second after cloning to let animations complete
|
9478
9516
|
await this.wait(1000);
|
9479
9517
|
},
|
@@ -9514,6 +9552,10 @@ class Screenshot {
|
|
9514
9552
|
logging: false,
|
9515
9553
|
width: fullPageWidth,
|
9516
9554
|
height: fullPageHeight,
|
9555
|
+
onclone: async () => {
|
9556
|
+
// Show loading screen after clone (won't appear in screenshot)
|
9557
|
+
this.showLoadingScreen();
|
9558
|
+
},
|
9517
9559
|
ignoreElements: (element) => {
|
9518
9560
|
// Skip cross-origin images that might cause issues
|
9519
9561
|
if (element.tagName === "IMG") {
|
@@ -10157,9 +10199,213 @@ class DeviceInfo {
|
|
10157
10199
|
}
|
10158
10200
|
}
|
10159
10201
|
|
10202
|
+
class N8nIntegration {
|
10203
|
+
constructor(config) {
|
10204
|
+
this.config = config || null;
|
10205
|
+
}
|
10206
|
+
/**
|
10207
|
+
* Configure n8n integration
|
10208
|
+
*/
|
10209
|
+
configure(config) {
|
10210
|
+
this.config = config;
|
10211
|
+
}
|
10212
|
+
/**
|
10213
|
+
* Check if n8n integration is configured and enabled
|
10214
|
+
*/
|
10215
|
+
isEnabled() {
|
10216
|
+
return !!(this.config && this.config.enabled && this.config.webhookUrl);
|
10217
|
+
}
|
10218
|
+
/**
|
10219
|
+
* Send issue data to n8n webhook
|
10220
|
+
*/
|
10221
|
+
async sendToN8n(issueData) {
|
10222
|
+
if (!this.config || !this.config.webhookUrl) {
|
10223
|
+
return {
|
10224
|
+
success: false,
|
10225
|
+
message: 'n8n webhook URL is not configured',
|
10226
|
+
error: 'MISSING_CONFIG'
|
10227
|
+
};
|
10228
|
+
}
|
10229
|
+
if (!this.config.enabled) {
|
10230
|
+
return {
|
10231
|
+
success: false,
|
10232
|
+
message: 'n8n integration is disabled',
|
10233
|
+
error: 'DISABLED'
|
10234
|
+
};
|
10235
|
+
}
|
10236
|
+
try {
|
10237
|
+
// Prepare payload
|
10238
|
+
const payload = this.preparePayload(issueData);
|
10239
|
+
// Setup request headers
|
10240
|
+
const headers = {
|
10241
|
+
'Content-Type': 'application/json',
|
10242
|
+
...this.config.headers
|
10243
|
+
};
|
10244
|
+
// Setup timeout
|
10245
|
+
const timeout = this.config.timeout || 30000; // 30 seconds default
|
10246
|
+
const controller = new AbortController();
|
10247
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
10248
|
+
// Send request
|
10249
|
+
const response = await fetch(this.config.webhookUrl, {
|
10250
|
+
method: 'POST',
|
10251
|
+
headers,
|
10252
|
+
body: JSON.stringify(payload),
|
10253
|
+
signal: controller.signal
|
10254
|
+
});
|
10255
|
+
clearTimeout(timeoutId);
|
10256
|
+
// Check response
|
10257
|
+
if (!response.ok) {
|
10258
|
+
const errorText = await response.text().catch(() => 'Unknown error');
|
10259
|
+
return {
|
10260
|
+
success: false,
|
10261
|
+
message: `n8n webhook request failed: ${response.status} ${response.statusText}`,
|
10262
|
+
error: errorText
|
10263
|
+
};
|
10264
|
+
}
|
10265
|
+
// Parse response
|
10266
|
+
let responseData;
|
10267
|
+
try {
|
10268
|
+
responseData = await response.json();
|
10269
|
+
}
|
10270
|
+
catch (e) {
|
10271
|
+
// Some webhooks don't return JSON
|
10272
|
+
responseData = { message: 'Success' };
|
10273
|
+
}
|
10274
|
+
return {
|
10275
|
+
success: true,
|
10276
|
+
message: 'Issue sent to n8n successfully',
|
10277
|
+
workflowId: responseData.workflowId || responseData.executionId
|
10278
|
+
};
|
10279
|
+
}
|
10280
|
+
catch (error) {
|
10281
|
+
if (error instanceof Error) {
|
10282
|
+
if (error.name === 'AbortError') {
|
10283
|
+
return {
|
10284
|
+
success: false,
|
10285
|
+
message: 'Request to n8n webhook timed out',
|
10286
|
+
error: 'TIMEOUT'
|
10287
|
+
};
|
10288
|
+
}
|
10289
|
+
return {
|
10290
|
+
success: false,
|
10291
|
+
message: `Failed to send issue to n8n: ${error.message}`,
|
10292
|
+
error: error.message
|
10293
|
+
};
|
10294
|
+
}
|
10295
|
+
return {
|
10296
|
+
success: false,
|
10297
|
+
message: 'Unknown error occurred while sending to n8n',
|
10298
|
+
error: 'UNKNOWN'
|
10299
|
+
};
|
10300
|
+
}
|
10301
|
+
}
|
10302
|
+
/**
|
10303
|
+
* Prepare payload for n8n webhook
|
10304
|
+
* This formats the data in a structure that's easy to work with in n8n
|
10305
|
+
*/
|
10306
|
+
preparePayload(issueData) {
|
10307
|
+
return {
|
10308
|
+
// Main issue data
|
10309
|
+
issue: {
|
10310
|
+
title: issueData.title,
|
10311
|
+
description: issueData.description,
|
10312
|
+
priority: issueData.priority,
|
10313
|
+
createdAt: issueData.createdAt
|
10314
|
+
},
|
10315
|
+
// Screenshot data (base64)
|
10316
|
+
screenshot: {
|
10317
|
+
data: issueData.screenshot,
|
10318
|
+
format: 'base64',
|
10319
|
+
mimeType: 'image/png'
|
10320
|
+
},
|
10321
|
+
// Device and browser information
|
10322
|
+
context: {
|
10323
|
+
browser: issueData.deviceInfo.browser,
|
10324
|
+
os: issueData.deviceInfo.os,
|
10325
|
+
screenResolution: issueData.deviceInfo.screenResolution,
|
10326
|
+
viewport: issueData.deviceInfo.viewport,
|
10327
|
+
url: issueData.deviceInfo.url,
|
10328
|
+
userAgent: issueData.deviceInfo.userAgent,
|
10329
|
+
language: issueData.deviceInfo.language,
|
10330
|
+
platform: issueData.deviceInfo.platform,
|
10331
|
+
cookiesEnabled: issueData.deviceInfo.cookiesEnabled,
|
10332
|
+
onLine: issueData.deviceInfo.onLine,
|
10333
|
+
timestamp: issueData.deviceInfo.timestamp
|
10334
|
+
},
|
10335
|
+
// Metadata for tracking
|
10336
|
+
metadata: {
|
10337
|
+
source: 'uxbert-reportly',
|
10338
|
+
version: '1.0.0',
|
10339
|
+
timestamp: new Date().toISOString()
|
10340
|
+
}
|
10341
|
+
};
|
10342
|
+
}
|
10343
|
+
/**
|
10344
|
+
* Test connection to n8n webhook
|
10345
|
+
*/
|
10346
|
+
async testConnection() {
|
10347
|
+
if (!this.config || !this.config.webhookUrl) {
|
10348
|
+
return {
|
10349
|
+
success: false,
|
10350
|
+
message: 'n8n webhook URL is not configured',
|
10351
|
+
error: 'MISSING_CONFIG'
|
10352
|
+
};
|
10353
|
+
}
|
10354
|
+
try {
|
10355
|
+
const controller = new AbortController();
|
10356
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout for test
|
10357
|
+
await fetch(this.config.webhookUrl, {
|
10358
|
+
method: 'HEAD',
|
10359
|
+
signal: controller.signal
|
10360
|
+
});
|
10361
|
+
clearTimeout(timeoutId);
|
10362
|
+
return {
|
10363
|
+
success: true,
|
10364
|
+
message: 'n8n webhook is reachable'
|
10365
|
+
};
|
10366
|
+
}
|
10367
|
+
catch (error) {
|
10368
|
+
return {
|
10369
|
+
success: false,
|
10370
|
+
message: 'Failed to reach n8n webhook',
|
10371
|
+
error: error instanceof Error ? error.message : 'UNKNOWN'
|
10372
|
+
};
|
10373
|
+
}
|
10374
|
+
}
|
10375
|
+
/**
|
10376
|
+
* Get current configuration
|
10377
|
+
*/
|
10378
|
+
getConfig() {
|
10379
|
+
return this.config;
|
10380
|
+
}
|
10381
|
+
/**
|
10382
|
+
* Update webhook URL
|
10383
|
+
*/
|
10384
|
+
setWebhookUrl(url) {
|
10385
|
+
if (!this.config) {
|
10386
|
+
this.config = {
|
10387
|
+
webhookUrl: url,
|
10388
|
+
enabled: true
|
10389
|
+
};
|
10390
|
+
}
|
10391
|
+
else {
|
10392
|
+
this.config.webhookUrl = url;
|
10393
|
+
}
|
10394
|
+
}
|
10395
|
+
/**
|
10396
|
+
* Enable/disable n8n integration
|
10397
|
+
*/
|
10398
|
+
setEnabled(enabled) {
|
10399
|
+
if (this.config) {
|
10400
|
+
this.config.enabled = enabled;
|
10401
|
+
}
|
10402
|
+
}
|
10403
|
+
}
|
10404
|
+
|
10160
10405
|
class Export {
|
10161
|
-
constructor() {
|
10406
|
+
constructor(n8nConfig) {
|
10162
10407
|
this.savedIssues = this.loadSavedIssues();
|
10408
|
+
this.n8nIntegration = new N8nIntegration(n8nConfig);
|
10163
10409
|
}
|
10164
10410
|
exportToJSON(issueData) {
|
10165
10411
|
const json = JSON.stringify(issueData, null, 2);
|
@@ -10228,6 +10474,54 @@ class Export {
|
|
10228
10474
|
document.body.removeChild(link);
|
10229
10475
|
URL.revokeObjectURL(url);
|
10230
10476
|
}
|
10477
|
+
// n8n Integration Methods
|
10478
|
+
/**
|
10479
|
+
* Send issue to n8n webhook
|
10480
|
+
*/
|
10481
|
+
async sendToN8n(issueData) {
|
10482
|
+
const response = await this.n8nIntegration.sendToN8n(issueData);
|
10483
|
+
// Save to localStorage if n8n send was successful
|
10484
|
+
if (response.success) {
|
10485
|
+
this.saveIssue(issueData);
|
10486
|
+
}
|
10487
|
+
return response;
|
10488
|
+
}
|
10489
|
+
/**
|
10490
|
+
* Configure n8n integration
|
10491
|
+
*/
|
10492
|
+
configureN8n(config) {
|
10493
|
+
this.n8nIntegration.configure(config);
|
10494
|
+
}
|
10495
|
+
/**
|
10496
|
+
* Check if n8n is enabled
|
10497
|
+
*/
|
10498
|
+
isN8nEnabled() {
|
10499
|
+
return this.n8nIntegration.isEnabled();
|
10500
|
+
}
|
10501
|
+
/**
|
10502
|
+
* Test n8n connection
|
10503
|
+
*/
|
10504
|
+
async testN8nConnection() {
|
10505
|
+
return this.n8nIntegration.testConnection();
|
10506
|
+
}
|
10507
|
+
/**
|
10508
|
+
* Get n8n configuration
|
10509
|
+
*/
|
10510
|
+
getN8nConfig() {
|
10511
|
+
return this.n8nIntegration.getConfig();
|
10512
|
+
}
|
10513
|
+
/**
|
10514
|
+
* Enable/disable n8n integration
|
10515
|
+
*/
|
10516
|
+
setN8nEnabled(enabled) {
|
10517
|
+
this.n8nIntegration.setEnabled(enabled);
|
10518
|
+
}
|
10519
|
+
/**
|
10520
|
+
* Set n8n webhook URL
|
10521
|
+
*/
|
10522
|
+
setN8nWebhookUrl(url) {
|
10523
|
+
this.n8nIntegration.setWebhookUrl(url);
|
10524
|
+
}
|
10231
10525
|
}
|
10232
10526
|
|
10233
10527
|
function styleInject(css, ref) {
|
@@ -10257,7 +10551,7 @@ function styleInject(css, ref) {
|
|
10257
10551
|
}
|
10258
10552
|
}
|
10259
10553
|
|
10260
|
-
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}}";
|
10554
|
+
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-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}}";
|
10261
10555
|
styleInject(css_248z);
|
10262
10556
|
|
10263
10557
|
// Main initialization file
|
@@ -10289,7 +10583,9 @@ class Reportly {
|
|
10289
10583
|
this.state = new State();
|
10290
10584
|
this.deviceInfo = new DeviceInfo();
|
10291
10585
|
this.screenshot = new Screenshot();
|
10292
|
-
|
10586
|
+
// Initialize export with n8n config if provided
|
10587
|
+
const n8nConfig = userConfig.integrations?.n8n;
|
10588
|
+
this.export = new Export(n8nConfig);
|
10293
10589
|
// Initialize UI components
|
10294
10590
|
this.button = new Button(this.config, {
|
10295
10591
|
onClick: () => this.handleButtonClick(),
|
@@ -10300,6 +10596,7 @@ class Reportly {
|
|
10300
10596
|
onAnnotate: () => this.startAnnotation(),
|
10301
10597
|
onRetake: () => this.retakeScreenshot(),
|
10302
10598
|
onCapture: () => this.captureWithMode(),
|
10599
|
+
onSendToN8n: (issueData) => this.handleN8nSubmit(issueData),
|
10303
10600
|
});
|
10304
10601
|
this.toolbar = new Toolbar({
|
10305
10602
|
onToolChange: (tool) => this.annotation?.setTool(tool),
|
@@ -10315,6 +10612,10 @@ class Reportly {
|
|
10315
10612
|
this.modal.create();
|
10316
10613
|
this.toolbar.create();
|
10317
10614
|
this.annotation.createCanvas();
|
10615
|
+
// Show/hide n8n button based on configuration
|
10616
|
+
if (this.export.isN8nEnabled()) {
|
10617
|
+
this.modal.setN8nButtonVisible(true);
|
10618
|
+
}
|
10318
10619
|
// Setup keyboard shortcuts
|
10319
10620
|
this.setupKeyboardShortcuts();
|
10320
10621
|
this.isInitialized = true;
|
@@ -10442,6 +10743,54 @@ class Reportly {
|
|
10442
10743
|
alert("Failed to export issue. Please try again.");
|
10443
10744
|
}
|
10444
10745
|
}
|
10746
|
+
async handleN8nSubmit(issueData) {
|
10747
|
+
try {
|
10748
|
+
// Create complete issue package
|
10749
|
+
const completeIssue = {
|
10750
|
+
...issueData,
|
10751
|
+
screenshot: this.state?.getScreenshot() || "",
|
10752
|
+
deviceInfo: this.deviceInfo.get(),
|
10753
|
+
createdAt: new Date().toISOString(),
|
10754
|
+
};
|
10755
|
+
// Show loading state
|
10756
|
+
const n8nBtn = document.querySelector('#uxbert-n8n-btn');
|
10757
|
+
if (n8nBtn) {
|
10758
|
+
n8nBtn.disabled = true;
|
10759
|
+
n8nBtn.textContent = '⏳ Sending...';
|
10760
|
+
}
|
10761
|
+
// Send to n8n
|
10762
|
+
const response = await this.export?.sendToN8n(completeIssue);
|
10763
|
+
if (response?.success) {
|
10764
|
+
// Emit event
|
10765
|
+
this.state?.emit("issue:sent-to-n8n", completeIssue);
|
10766
|
+
// Reset state
|
10767
|
+
this.state?.reset();
|
10768
|
+
this.annotation?.clear();
|
10769
|
+
this.modal?.close();
|
10770
|
+
alert("Issue sent to n8n successfully!");
|
10771
|
+
console.log("Issue sent to n8n successfully");
|
10772
|
+
}
|
10773
|
+
else {
|
10774
|
+
alert(`Failed to send to n8n: ${response?.message || 'Unknown error'}`);
|
10775
|
+
console.error("Failed to send to n8n:", response?.error);
|
10776
|
+
}
|
10777
|
+
// Reset button state
|
10778
|
+
if (n8nBtn) {
|
10779
|
+
n8nBtn.disabled = false;
|
10780
|
+
n8nBtn.textContent = '🚀 Send to n8n';
|
10781
|
+
}
|
10782
|
+
}
|
10783
|
+
catch (error) {
|
10784
|
+
console.error("Failed to send to n8n:", error);
|
10785
|
+
alert("Failed to send to n8n. Please try again.");
|
10786
|
+
// Reset button state
|
10787
|
+
const n8nBtn = document.querySelector('#uxbert-n8n-btn');
|
10788
|
+
if (n8nBtn) {
|
10789
|
+
n8nBtn.disabled = false;
|
10790
|
+
n8nBtn.textContent = '🚀 Send to n8n';
|
10791
|
+
}
|
10792
|
+
}
|
10793
|
+
}
|
10445
10794
|
handleModalClose() {
|
10446
10795
|
this.annotation?.hide();
|
10447
10796
|
this.toolbar?.hide();
|
@@ -10470,6 +10819,24 @@ class Reportly {
|
|
10470
10819
|
exportAllIssues() {
|
10471
10820
|
this.export?.exportAllIssues();
|
10472
10821
|
}
|
10822
|
+
// n8n Integration API methods
|
10823
|
+
configureN8n(webhookUrl, enabled = true, options) {
|
10824
|
+
this.export?.configureN8n({
|
10825
|
+
webhookUrl,
|
10826
|
+
enabled,
|
10827
|
+
headers: options?.headers,
|
10828
|
+
timeout: options?.timeout
|
10829
|
+
});
|
10830
|
+
// Update button visibility
|
10831
|
+
this.modal?.setN8nButtonVisible(enabled);
|
10832
|
+
}
|
10833
|
+
enableN8n(enabled) {
|
10834
|
+
this.export?.setN8nEnabled(enabled);
|
10835
|
+
this.modal?.setN8nButtonVisible(enabled);
|
10836
|
+
}
|
10837
|
+
testN8nConnection() {
|
10838
|
+
return this.export?.testN8nConnection() || Promise.resolve({ success: false, message: 'Not initialized' });
|
10839
|
+
}
|
10473
10840
|
on(event, callback) {
|
10474
10841
|
this.state?.on(event, callback);
|
10475
10842
|
}
|