@openreplay/tracker 11.0.0-beta.1 → 11.0.1

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/cjs/app/index.d.ts +4 -0
  3. package/cjs/app/index.js +28 -4
  4. package/cjs/index.d.ts +1 -0
  5. package/cjs/index.js +7 -1
  6. package/cjs/modules/userTesting/SignalManager.d.ts +29 -0
  7. package/cjs/modules/userTesting/SignalManager.js +83 -0
  8. package/cjs/modules/userTesting/index.d.ts +7 -7
  9. package/cjs/modules/userTesting/index.js +169 -195
  10. package/cjs/modules/userTesting/styles.d.ts +28 -11
  11. package/cjs/modules/userTesting/styles.js +51 -29
  12. package/cjs/modules/userTesting/utils.d.ts +9 -0
  13. package/cjs/modules/userTesting/utils.js +87 -0
  14. package/coverage/clover.xml +851 -351
  15. package/coverage/coverage-final.json +10 -4
  16. package/coverage/lcov-report/index.html +38 -23
  17. package/coverage/lcov-report/main/app/canvas.ts.html +1 -1
  18. package/coverage/lcov-report/main/app/guards.ts.html +42 -42
  19. package/coverage/lcov-report/main/app/index.html +24 -24
  20. package/coverage/lcov-report/main/app/index.ts.html +196 -28
  21. package/coverage/lcov-report/main/app/logger.ts.html +1 -1
  22. package/coverage/lcov-report/main/app/messages.gen.ts.html +1 -1
  23. package/coverage/lcov-report/main/app/nodes.ts.html +1 -1
  24. package/coverage/lcov-report/main/app/observer/iframe_observer.ts.html +1 -1
  25. package/coverage/lcov-report/main/app/observer/iframe_offsets.ts.html +1 -1
  26. package/coverage/lcov-report/main/app/observer/index.html +1 -1
  27. package/coverage/lcov-report/main/app/observer/shadow_root_observer.ts.html +1 -1
  28. package/coverage/lcov-report/main/app/observer/top_observer.ts.html +1 -1
  29. package/coverage/lcov-report/main/app/sanitizer.ts.html +1 -1
  30. package/coverage/lcov-report/main/app/session.ts.html +1 -1
  31. package/coverage/lcov-report/main/app/ticker.ts.html +1 -1
  32. package/coverage/lcov-report/main/index.html +11 -11
  33. package/coverage/lcov-report/main/index.ts.html +33 -6
  34. package/coverage/lcov-report/main/modules/Network/beaconProxy.ts.html +1 -1
  35. package/coverage/lcov-report/main/modules/Network/fetchProxy.ts.html +1 -1
  36. package/coverage/lcov-report/main/modules/Network/index.html +1 -1
  37. package/coverage/lcov-report/main/modules/Network/index.ts.html +1 -1
  38. package/coverage/lcov-report/main/modules/Network/networkMessage.ts.html +1 -1
  39. package/coverage/lcov-report/main/modules/Network/utils.ts.html +1 -1
  40. package/coverage/lcov-report/main/modules/Network/xhrProxy.ts.html +1 -1
  41. package/coverage/lcov-report/main/modules/attributeSender.ts.html +1 -1
  42. package/coverage/lcov-report/main/modules/axiosSpy.ts.html +1 -1
  43. package/coverage/lcov-report/main/modules/connection.ts.html +1 -1
  44. package/coverage/lcov-report/main/modules/console.ts.html +1 -1
  45. package/coverage/lcov-report/main/modules/constructedStyleSheets.ts.html +1 -1
  46. package/coverage/lcov-report/main/modules/cssrules.ts.html +1 -1
  47. package/coverage/lcov-report/main/modules/exception.ts.html +1 -1
  48. package/coverage/lcov-report/main/modules/featureFlags.ts.html +1 -1
  49. package/coverage/lcov-report/main/modules/focus.ts.html +1 -1
  50. package/coverage/lcov-report/main/modules/fonts.ts.html +1 -1
  51. package/coverage/lcov-report/main/modules/img.ts.html +1 -1
  52. package/coverage/lcov-report/main/modules/index.html +1 -1
  53. package/coverage/lcov-report/main/modules/input.ts.html +1 -1
  54. package/coverage/lcov-report/main/modules/mouse.ts.html +1 -1
  55. package/coverage/lcov-report/main/modules/network.ts.html +1 -1
  56. package/coverage/lcov-report/main/modules/performance.ts.html +1 -1
  57. package/coverage/lcov-report/main/modules/scroll.ts.html +1 -1
  58. package/coverage/lcov-report/main/modules/selection.ts.html +1 -1
  59. package/coverage/lcov-report/main/modules/tabs.ts.html +1 -1
  60. package/coverage/lcov-report/main/modules/timing.ts.html +1 -1
  61. package/coverage/lcov-report/main/modules/userTesting/SignalManager.ts.html +361 -0
  62. package/coverage/lcov-report/main/modules/userTesting/dnd.ts.html +10 -22
  63. package/coverage/lcov-report/main/modules/userTesting/index.html +61 -31
  64. package/coverage/lcov-report/main/modules/userTesting/index.ts.html +809 -113
  65. package/coverage/lcov-report/main/modules/userTesting/recorder.ts.html +136 -67
  66. package/coverage/lcov-report/main/modules/userTesting/styles.ts.html +159 -87
  67. package/coverage/lcov-report/main/modules/userTesting/utils.ts.html +361 -0
  68. package/coverage/lcov-report/main/modules/viewport.ts.html +1 -1
  69. package/coverage/lcov-report/main/utils.ts.html +48 -6
  70. package/coverage/lcov-report/webworker/BatchWriter.ts.html +1 -1
  71. package/coverage/lcov-report/webworker/MessageEncoder.gen.ts.html +1 -1
  72. package/coverage/lcov-report/webworker/PrimitiveEncoder.ts.html +1 -1
  73. package/coverage/lcov-report/webworker/QueueSender.ts.html +1 -1
  74. package/coverage/lcov-report/webworker/index.html +1 -1
  75. package/coverage/lcov-report/webworker/index.ts.html +1 -1
  76. package/coverage/lcov.info +1535 -653
  77. package/lib/app/index.d.ts +4 -0
  78. package/lib/app/index.js +28 -4
  79. package/lib/index.d.ts +1 -0
  80. package/lib/index.js +7 -1
  81. package/lib/modules/userTesting/SignalManager.d.ts +29 -0
  82. package/lib/modules/userTesting/SignalManager.js +80 -0
  83. package/lib/modules/userTesting/index.d.ts +7 -7
  84. package/lib/modules/userTesting/index.js +141 -167
  85. package/lib/modules/userTesting/styles.d.ts +28 -11
  86. package/lib/modules/userTesting/styles.js +50 -28
  87. package/lib/modules/userTesting/utils.d.ts +9 -0
  88. package/lib/modules/userTesting/utils.js +79 -0
  89. package/package.json +2 -2
@@ -1,18 +1,8 @@
1
1
  import * as styles from './styles.js';
2
2
  import Recorder, { Quality } from './recorder.js';
3
3
  import attachDND from './dnd.js';
4
- function createElement(tag, className, styles, textContent, id) {
5
- const element = document.createElement(tag);
6
- element.className = className;
7
- Object.assign(element.style, styles);
8
- if (textContent) {
9
- element.textContent = textContent;
10
- }
11
- if (id) {
12
- element.id = id;
13
- }
14
- return element;
15
- }
4
+ import { generateGrid, generateChevron, createSpinner, createElement, TEST_START, TASK_IND, SESSION_ID, TEST_ID, } from './utils.js';
5
+ import SignalManager from './SignalManager.js';
16
6
  export default class UserTestManager {
17
7
  constructor(app, storageKey) {
18
8
  this.app = app;
@@ -22,80 +12,28 @@ export default class UserTestManager {
22
12
  this.widgetGuidelinesVisible = true;
23
13
  this.widgetTasksVisible = false;
24
14
  this.widgetVisible = true;
15
+ this.isActive = false;
25
16
  this.descriptionSection = null;
26
17
  this.taskSection = null;
27
18
  this.endSection = null;
28
19
  this.stopButton = null;
20
+ this.stopButtonContainer = null;
29
21
  this.test = null;
30
22
  this.testId = null;
31
- this.token = null;
32
- this.durations = {
33
- testStart: 0,
34
- tasks: [],
35
- };
36
- this.signalTask = (taskId, status, answer) => {
37
- if (!taskId)
38
- return console.error('OR: no task id');
39
- const taskStart = this.durations.tasks.find((t) => t.taskId === taskId);
40
- const timestamp = this.app.timestamp();
41
- const duration = taskStart ? timestamp - taskStart.started : 0;
42
- const ingest = this.app.options.ingestPoint;
43
- return fetch(`${ingest}/v1/web/uxt/signals/task`, {
44
- method: 'POST',
45
- headers: {
46
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
47
- Authorization: `Bearer ${this.token}`,
48
- },
49
- body: JSON.stringify({
50
- testId: this.testId,
51
- taskId,
52
- status,
53
- duration,
54
- timestamp,
55
- answer,
56
- }),
57
- });
58
- };
59
- this.signalTest = (status) => {
60
- const timestamp = this.app.timestamp();
61
- if (status === 'begin' && this.testId) {
62
- this.app.localStorage.setItem(this.storageKey, this.testId.toString());
63
- this.app.localStorage.setItem('or_uxt_test_start', timestamp.toString());
64
- }
65
- else {
66
- this.app.localStorage.removeItem(this.storageKey);
67
- this.app.localStorage.removeItem('or_uxt_task_index');
68
- this.app.localStorage.removeItem('or_uxt_test_start');
69
- }
70
- const ingest = this.app.options.ingestPoint;
71
- const start = this.durations.testStart || timestamp;
72
- const duration = timestamp - start;
73
- return fetch(`${ingest}/v1/web/uxt/signals/test`, {
74
- method: 'POST',
75
- headers: {
76
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
77
- Authorization: `Bearer ${this.token}`,
78
- },
79
- body: JSON.stringify({
80
- testId: this.testId,
81
- status,
82
- duration,
83
- timestamp,
84
- }),
85
- });
86
- };
23
+ this.signalManager = null;
87
24
  this.getTest = (id, token, inProgress) => {
88
25
  this.testId = id;
89
- this.token = token;
90
26
  const ingest = this.app.options.ingestPoint;
91
- fetch(`${ingest}/v1/web/uxt/test/${id}`, {
27
+ return fetch(`${ingest}/v1/web/uxt/test/${id}`, {
92
28
  headers: {
93
29
  Authorization: `Bearer ${token}`,
94
30
  },
95
31
  })
96
32
  .then((res) => res.json())
97
33
  .then(({ test }) => {
34
+ this.isActive = true;
98
35
  this.test = test;
36
+ this.signalManager = new SignalManager(this.app.options.ingestPoint, () => this.app.timestamp(), token, id, this.storageKey, (k, v) => this.app.localStorage.setItem(k, v), (k) => this.app.localStorage.removeItem(k), (k) => this.app.localStorage.getItem(k), () => this.app.getSessionID());
99
37
  this.createGreeting(test.title, test.reqMic, test.reqCamera);
100
38
  if (inProgress) {
101
39
  if (test.reqMic || test.reqCamera) {
@@ -105,6 +43,7 @@ export default class UserTestManager {
105
43
  this.showTaskSection();
106
44
  }
107
45
  })
46
+ .then(() => id)
108
47
  .catch((err) => {
109
48
  console.log('OR: Error fetching test', err);
110
49
  });
@@ -118,48 +57,56 @@ export default class UserTestManager {
118
57
  this.currentTaskIndex = 0;
119
58
  this.userRecorder = new Recorder(app);
120
59
  const sessionId = this.app.getSessionID();
121
- const savedSessionId = this.app.localStorage.getItem('or_uxt_session_id');
60
+ const savedSessionId = this.app.localStorage.getItem(SESSION_ID);
122
61
  if (sessionId !== savedSessionId) {
123
62
  this.app.localStorage.removeItem(this.storageKey);
124
- this.app.localStorage.removeItem('or_uxt_session_id');
125
- this.app.localStorage.removeItem('or_uxt_test_id');
126
- this.app.localStorage.removeItem('or_uxt_task_index');
127
- this.app.localStorage.removeItem('or_uxt_test_start');
63
+ this.app.localStorage.removeItem(SESSION_ID);
64
+ this.app.localStorage.removeItem(TEST_ID);
65
+ this.app.localStorage.removeItem(TASK_IND);
66
+ this.app.localStorage.removeItem(TEST_START);
128
67
  }
129
- const taskIndex = this.app.localStorage.getItem('or_uxt_task_index');
68
+ const taskIndex = this.app.localStorage.getItem(TASK_IND);
130
69
  if (taskIndex) {
131
70
  this.currentTaskIndex = parseInt(taskIndex, 10);
132
- this.durations.testStart = parseInt(this.app.localStorage.getItem('or_uxt_test_start'), 10);
133
71
  }
134
72
  }
73
+ getTestId() {
74
+ return this.testId;
75
+ }
135
76
  createGreeting(title, micRequired, cameraRequired) {
136
77
  const titleElement = createElement('div', 'title', styles.titleStyle, title);
137
- const descriptionElement = createElement('div', 'description', styles.descriptionStyle, 'Welcome, this session will be recorded. You have complete control, and can stop the session at any time.');
138
- const noticeElement = createElement('div', 'notice', styles.noticeStyle, `Please note that your ${micRequired ? 'audio,' : ''} ${cameraRequired ? 'video,' : ''} ${micRequired || cameraRequired ? 'and' : ''} screen will be recorded for research purposes during this test.`);
78
+ const descriptionElement = createElement('div', 'description', styles.descriptionStyle, `Welcome, you're here to help us improve, not to be judged. Your insights matter!\n
79
+ 📹 We're recording this browser tab to learn from your experience.
80
+ 🎤 Please enable mic and camera if asked, to give us a complete picture.`);
139
81
  const buttonElement = createElement('div', 'button', styles.buttonStyle, 'Read guidelines to begin');
140
82
  this.removeGreeting = () => {
141
- this.container.innerHTML = '';
83
+ // this.container.innerHTML = ''
142
84
  if (micRequired || cameraRequired) {
143
85
  void this.userRecorder.startRecording(30, Quality.Standard, micRequired, cameraRequired);
144
86
  }
145
87
  this.container.removeChild(buttonElement);
146
- this.container.removeChild(noticeElement);
147
88
  this.container.removeChild(descriptionElement);
148
89
  this.container.removeChild(titleElement);
149
90
  return false;
150
91
  };
151
92
  buttonElement.onclick = () => {
152
- var _a, _b;
93
+ var _a, _b, _c, _d;
153
94
  this.removeGreeting();
154
- this.durations.testStart = this.app.timestamp();
155
- void this.signalTest('begin');
156
- this.showWidget(((_a = this.test) === null || _a === void 0 ? void 0 : _a.description) || '', ((_b = this.test) === null || _b === void 0 ? void 0 : _b.tasks) || []);
95
+ const durations = (_a = this.signalManager) === null || _a === void 0 ? void 0 : _a.getDurations();
96
+ if (durations && this.signalManager) {
97
+ durations.testStart = this.app.timestamp();
98
+ this.signalManager.setDurations(durations);
99
+ }
100
+ void ((_b = this.signalManager) === null || _b === void 0 ? void 0 : _b.signalTest('begin'));
101
+ this.container.style.fontFamily = `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"`;
102
+ Object.assign(this.container.style, styles.containerWidgetStyle);
103
+ this.showWidget(((_c = this.test) === null || _c === void 0 ? void 0 : _c.guidelines) || '', ((_d = this.test) === null || _d === void 0 ? void 0 : _d.tasks) || []);
157
104
  };
158
- this.container.append(titleElement, descriptionElement, noticeElement, buttonElement);
105
+ this.container.append(titleElement, descriptionElement, buttonElement);
159
106
  this.bg.appendChild(this.container);
160
107
  document.body.appendChild(this.bg);
161
108
  }
162
- showWidget(description, tasks, inProgress) {
109
+ showWidget(guidelines, tasks, inProgress) {
163
110
  this.container.innerHTML = '';
164
111
  Object.assign(this.bg.style, {
165
112
  position: 'fixed',
@@ -176,18 +123,25 @@ export default class UserTestManager {
176
123
  });
177
124
  // Create title section
178
125
  const titleSection = this.createTitleSection();
126
+ this.container.style.fontFamily = `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"`;
179
127
  Object.assign(this.container.style, styles.containerWidgetStyle);
180
- const descriptionSection = this.createDescriptionSection(description);
128
+ const descriptionSection = this.createDescriptionSection(guidelines);
181
129
  const tasksSection = this.createTasksSection(tasks);
182
130
  const stopButton = createElement('div', 'stop_bn_or', styles.stopWidgetStyle, 'Abort Session');
183
- this.container.append(titleSection, descriptionSection, tasksSection, stopButton);
131
+ const stopContainer = createElement('div', 'stop_ct_or', { fontSize: '13px!important' });
132
+ stopContainer.style.fontSize = '13px';
133
+ stopContainer.append(stopButton);
134
+ this.container.append(titleSection, descriptionSection, tasksSection, stopContainer);
184
135
  this.taskSection = tasksSection;
185
136
  this.descriptionSection = descriptionSection;
186
137
  this.stopButton = stopButton;
138
+ this.stopButtonContainer = stopContainer;
187
139
  stopButton.onclick = () => {
140
+ var _a;
188
141
  this.userRecorder.discard();
189
- void this.signalTest('skipped');
142
+ void ((_a = this.signalManager) === null || _a === void 0 ? void 0 : _a.signalTest('skipped'));
190
143
  document.body.removeChild(this.bg);
144
+ window.close();
191
145
  };
192
146
  if (!inProgress) {
193
147
  this.hideTaskSection();
@@ -200,11 +154,20 @@ export default class UserTestManager {
200
154
  var _a;
201
155
  const title = createElement('div', 'title', styles.titleWidgetStyle);
202
156
  const leftIcon = generateGrid();
203
- const titleText = createElement('div', 'title_text', {}, (_a = this.test) === null || _a === void 0 ? void 0 : _a.title);
157
+ const titleText = createElement('div', 'title_text', {
158
+ maxWidth: '19rem',
159
+ overflow: 'hidden',
160
+ textOverflow: 'ellipsis',
161
+ width: '100%',
162
+ fontSize: 16,
163
+ lineHeight: 'auto',
164
+ cursor: 'pointer',
165
+ }, (_a = this.test) === null || _a === void 0 ? void 0 : _a.title);
204
166
  const rightIcon = generateChevron();
205
167
  title.append(leftIcon, titleText, rightIcon);
206
168
  const toggleWidget = (isVisible) => {
207
169
  this.widgetVisible = isVisible;
170
+ this.container.style.fontFamily = `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"`;
208
171
  Object.assign(this.container.style, this.widgetVisible
209
172
  ? styles.containerWidgetStyle
210
173
  : { border: 'none', background: 'none', padding: 0 });
@@ -222,27 +185,37 @@ export default class UserTestManager {
222
185
  }
223
186
  return isVisible;
224
187
  };
225
- rightIcon.onclick = () => {
188
+ const collapseWidget = () => {
226
189
  Object.assign(rightIcon.style, {
227
190
  transform: this.widgetVisible ? 'rotate(0deg)' : 'rotate(180deg)',
228
191
  });
229
192
  toggleWidget(!this.widgetVisible);
230
193
  };
194
+ titleText.onclick = collapseWidget;
195
+ rightIcon.onclick = collapseWidget;
231
196
  attachDND(this.bg, leftIcon);
232
197
  this.collapseWidget = () => toggleWidget(false);
233
198
  return title;
234
199
  }
235
- createDescriptionSection(description) {
200
+ createDescriptionSection(guidelines) {
236
201
  const section = createElement('div', 'description_section_or', styles.descriptionWidgetStyle);
237
202
  const titleContainer = createElement('div', 'description_s_title_or', styles.sectionTitleStyle);
238
- const title = createElement('div', 'title', {}, 'Introduction & Guidelines');
203
+ const title = createElement('div', 'title', {
204
+ fontSize: 13,
205
+ fontWeight: 500,
206
+ lineHeight: 'auto',
207
+ }, 'Introduction & Guidelines');
239
208
  const icon = createElement('div', 'icon', styles.symbolIcon, '-');
240
209
  const content = createElement('div', 'content', styles.contentStyle);
241
210
  const descriptionC = createElement('div', 'text_description', {
242
211
  maxHeight: '250px',
243
- overflow: 'scroll',
212
+ overflowY: 'auto',
213
+ whiteSpace: 'pre-wrap',
214
+ fontSize: 13,
215
+ color: '#454545',
216
+ lineHeight: 'auto',
244
217
  });
245
- descriptionC.innerHTML = description;
218
+ descriptionC.innerHTML = guidelines;
246
219
  const button = createElement('div', 'button_begin_or', styles.buttonWidgetStyle, 'Begin Test');
247
220
  titleContainer.append(title, icon);
248
221
  content.append(descriptionC, button);
@@ -260,15 +233,21 @@ export default class UserTestManager {
260
233
  content.removeChild(button);
261
234
  };
262
235
  button.onclick = () => {
236
+ var _a, _b, _c;
263
237
  toggleDescriptionVisibility();
264
238
  if (this.test) {
265
- if (this.durations.tasks.findIndex((t) => this.test && t.taskId === this.test.tasks[0].task_id) === -1) {
266
- this.durations.tasks.push({
239
+ const durations = (_a = this.signalManager) === null || _a === void 0 ? void 0 : _a.getDurations();
240
+ const taskDurationInd = durations
241
+ ? durations.tasks.findIndex((t) => this.test && t.taskId === this.test.tasks[0].task_id)
242
+ : null;
243
+ if (durations && taskDurationInd === -1) {
244
+ durations.tasks.push({
267
245
  taskId: this.test.tasks[0].task_id,
268
246
  started: this.app.timestamp(),
269
247
  });
248
+ (_b = this.signalManager) === null || _b === void 0 ? void 0 : _b.setDurations(durations);
270
249
  }
271
- void this.signalTask(this.test.tasks[0].task_id, 'begin');
250
+ void ((_c = this.signalManager) === null || _c === void 0 ? void 0 : _c.signalTask(this.test.tasks[0].task_id, 'begin'));
272
251
  }
273
252
  this.showTaskSection();
274
253
  content.removeChild(button);
@@ -276,14 +255,20 @@ export default class UserTestManager {
276
255
  return section;
277
256
  }
278
257
  createTasksSection(tasks) {
258
+ this.container.style.fontFamily = `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"`;
259
+ Object.assign(this.container.style, styles.containerWidgetStyle);
279
260
  const section = createElement('div', 'task_section_or', styles.descriptionWidgetStyle);
280
261
  const titleContainer = createElement('div', 'description_t_title_or', styles.sectionTitleStyle);
281
- const title = createElement('div', 'title', {}, 'Tasks');
262
+ const title = createElement('div', 'title', {
263
+ fontSize: '13px',
264
+ fontWeight: '500',
265
+ lineHeight: 'auto',
266
+ }, 'Tasks');
282
267
  const icon = createElement('div', 'icon', styles.symbolIcon, '-');
283
268
  const content = createElement('div', 'content', styles.contentStyle);
284
269
  const pagination = createElement('div', 'pagination', styles.paginationStyle);
285
- const leftArrow = createElement('span', 'leftArrow', {}, '<');
286
- const rightArrow = createElement('span', 'rightArrow', {}, '>');
270
+ // const leftArrow = createElement('span', 'leftArrow', {}, '<')
271
+ // const rightArrow = createElement('span', 'rightArrow', {}, '>')
287
272
  const taskCard = createElement('div', 'taskCard', styles.taskDescriptionCard);
288
273
  const taskText = createElement('div', 'taskText', styles.taskTextStyle);
289
274
  const taskDescription = createElement('div', 'taskDescription', styles.taskDescriptionStyle);
@@ -295,8 +280,8 @@ export default class UserTestManager {
295
280
  });
296
281
  const inputContainer = createElement('div', 'inputArea', styles.taskDescriptionCard);
297
282
  inputContainer.append(inputTitle, inputArea);
298
- const closePanelButton = createElement('div', 'closePanelButton', styles.taskButtonStyle, 'Collapse panel');
299
- const nextButton = createElement('div', 'nextButton', styles.taskButtonBorderedStyle, 'Done, next');
283
+ const closePanelButton = createElement('div', 'closePanelButton', styles.taskButtonStyle, 'Collapse Panel');
284
+ const nextButton = createElement('div', 'nextButton', styles.taskButtonBorderedStyle, 'Done, Next');
300
285
  titleContainer.append(title, icon);
301
286
  taskCard.append(taskText, taskDescription);
302
287
  taskButtons.append(closePanelButton, nextButton);
@@ -313,13 +298,23 @@ export default class UserTestManager {
313
298
  inputContainer.style.display = 'none';
314
299
  }
315
300
  };
316
- pagination.appendChild(leftArrow);
301
+ // pagination.appendChild(leftArrow)
317
302
  tasks.forEach((_, index) => {
318
- const pageNumber = createElement('span', `or_task_${index}`, {}, (index + 1).toString());
303
+ const pageNumber = createElement('span', `or_task_${index}`, {
304
+ outline: '1px solid #efefef',
305
+ fontSize: '13px',
306
+ height: '24px',
307
+ width: '24px',
308
+ display: 'flex',
309
+ flexDirection: 'column',
310
+ alignItems: 'center',
311
+ justifyContent: 'center',
312
+ borderRadius: '6.25em',
313
+ }, (index + 1).toString());
319
314
  pageNumber.id = `or_task_${index}`;
320
315
  pagination.append(pageNumber);
321
316
  });
322
- pagination.appendChild(rightArrow);
317
+ // pagination.appendChild(rightArrow)
323
318
  const toggleTasksVisibility = () => {
324
319
  this.widgetTasksVisible = !this.widgetTasksVisible;
325
320
  icon.textContent = this.widgetTasksVisible ? '-' : '+';
@@ -354,19 +349,23 @@ export default class UserTestManager {
354
349
  titleContainer.onclick = toggleTasksVisibility;
355
350
  closePanelButton.onclick = this.collapseWidget;
356
351
  nextButton.onclick = () => {
352
+ var _a, _b, _c, _d;
357
353
  const textAnswer = tasks[this.currentTaskIndex].allow_typing ? inputArea.value : undefined;
358
354
  inputArea.value = '';
359
- void this.signalTask(tasks[this.currentTaskIndex].task_id, 'done', textAnswer);
355
+ void ((_a = this.signalManager) === null || _a === void 0 ? void 0 : _a.signalTask(tasks[this.currentTaskIndex].task_id, 'done', textAnswer));
360
356
  if (this.currentTaskIndex < tasks.length - 1) {
361
357
  this.currentTaskIndex++;
362
358
  updateTaskContent();
363
- if (this.durations.tasks.findIndex((t) => t.taskId === tasks[this.currentTaskIndex].task_id) === -1) {
364
- this.durations.tasks.push({
359
+ const durations = (_b = this.signalManager) === null || _b === void 0 ? void 0 : _b.getDurations();
360
+ if (durations &&
361
+ durations.tasks.findIndex((t) => t.taskId === tasks[this.currentTaskIndex].task_id) === -1) {
362
+ durations.tasks.push({
365
363
  taskId: tasks[this.currentTaskIndex].task_id,
366
364
  started: this.app.timestamp(),
367
365
  });
366
+ (_c = this.signalManager) === null || _c === void 0 ? void 0 : _c.setDurations(durations);
368
367
  }
369
- void this.signalTask(tasks[this.currentTaskIndex].task_id, 'begin');
368
+ void ((_d = this.signalManager) === null || _d === void 0 ? void 0 : _d.signalTask(tasks[this.currentTaskIndex].task_id, 'begin'));
370
369
  highlightActive();
371
370
  }
372
371
  else {
@@ -385,32 +384,53 @@ export default class UserTestManager {
385
384
  return section;
386
385
  }
387
386
  showEndSection() {
388
- var _a, _b, _c, _d, _e, _f;
389
- void this.signalTest('done');
387
+ var _a, _b, _c, _d, _e;
388
+ let isLoading = true;
389
+ void ((_a = this.signalManager) === null || _a === void 0 ? void 0 : _a.signalTest('done'));
390
390
  const section = createElement('div', 'end_section_or', styles.endSectionStyle);
391
391
  const title = createElement('div', 'end_title_or', {
392
392
  fontSize: '1.25rem',
393
393
  fontWeight: '500',
394
- }, ((_a = this.test) === null || _a === void 0 ? void 0 : _a.reqMic) || ((_b = this.test) === null || _b === void 0 ? void 0 : _b.reqCamera) ? 'Uploading test recording...' : 'Thank you! 👍');
395
- const description = createElement('div', 'end_description_or', {}, (_d = (_c = this.test) === null || _c === void 0 ? void 0 : _c.conclusion) !== null && _d !== void 0 ? _d : 'Thank you for participating in our user test. Your feedback has been captured and will be used to enhance our website. \n' +
394
+ }, 'Thank you! 👍');
395
+ const description = createElement('div', 'end_description_or', {}, (_c = (_b = this.test) === null || _b === void 0 ? void 0 : _b.conclusion) !== null && _c !== void 0 ? _c : 'Thank you for participating in our usability test. Your feedback has been captured and will be used to enhance our website. \n' +
396
396
  '\n' +
397
397
  'We appreciate your time and valuable input.');
398
- if (((_e = this.test) === null || _e === void 0 ? void 0 : _e.reqMic) || ((_f = this.test) === null || _f === void 0 ? void 0 : _f.reqCamera)) {
399
- this.userRecorder.sendToAPI().then(() => {
400
- title.textContent = 'Thank you! 👍';
398
+ const button = createElement('div', 'end_button_or', styles.buttonWidgetStyle, 'Submitting Feedback');
399
+ const spinner = createSpinner();
400
+ button.appendChild(spinner);
401
+ if (((_d = this.test) === null || _d === void 0 ? void 0 : _d.reqMic) || ((_e = this.test) === null || _e === void 0 ? void 0 : _e.reqCamera)) {
402
+ void this.userRecorder
403
+ .sendToAPI()
404
+ .then(() => {
405
+ button.removeChild(spinner);
406
+ button.textContent = 'End Session';
407
+ isLoading = false;
408
+ })
409
+ .catch((err) => {
410
+ console.error(err);
411
+ button.removeChild(spinner);
412
+ button.textContent = 'End Session';
413
+ isLoading = false;
401
414
  });
402
415
  }
403
- const button = createElement('div', 'end_button_or', styles.buttonWidgetStyle, 'End Session');
416
+ else {
417
+ button.removeChild(spinner);
418
+ button.textContent = 'End Session';
419
+ isLoading = false;
420
+ }
404
421
  if (this.taskSection) {
405
422
  this.container.removeChild(this.taskSection);
406
423
  }
407
424
  if (this.descriptionSection) {
408
425
  this.container.removeChild(this.descriptionSection);
409
426
  }
410
- if (this.stopButton) {
411
- this.container.removeChild(this.stopButton);
427
+ if (this.stopButton && this.stopButtonContainer) {
428
+ this.container.removeChild(this.stopButtonContainer);
412
429
  }
413
430
  button.onclick = () => {
431
+ if (isLoading)
432
+ return;
433
+ window.close();
414
434
  document.body.removeChild(this.bg);
415
435
  };
416
436
  section.append(title, description, button);
@@ -418,49 +438,3 @@ export default class UserTestManager {
418
438
  this.container.append(section);
419
439
  }
420
440
  }
421
- function generateGrid() {
422
- const grid = document.createElement('div');
423
- grid.className = 'grid';
424
- for (let i = 0; i < 16; i++) {
425
- const cell = document.createElement('div');
426
- Object.assign(cell.style, {
427
- width: '2px',
428
- height: '2px',
429
- borderRadius: '10px',
430
- background: 'white',
431
- });
432
- cell.className = 'cell';
433
- grid.appendChild(cell);
434
- }
435
- Object.assign(grid.style, {
436
- display: 'grid',
437
- gridTemplateColumns: 'repeat(4, 1fr)',
438
- gridTemplateRows: 'repeat(4, 1fr)',
439
- gap: '2px',
440
- cursor: 'grab',
441
- });
442
- return grid;
443
- }
444
- function generateChevron() {
445
- const triangle = document.createElement('div');
446
- Object.assign(triangle.style, {
447
- width: '0',
448
- height: '0',
449
- borderLeft: '7px solid transparent',
450
- borderRight: '7px solid transparent',
451
- borderBottom: '7px solid white',
452
- });
453
- const container = document.createElement('div');
454
- container.appendChild(triangle);
455
- Object.assign(container.style, {
456
- display: 'flex',
457
- alignItems: 'center',
458
- justifyContent: 'center',
459
- width: '16px',
460
- height: '16px',
461
- cursor: 'pointer',
462
- marginLeft: 'auto',
463
- transform: 'rotate(180deg)',
464
- });
465
- return container;
466
- }
@@ -9,6 +9,7 @@ export declare const bgStyle: {
9
9
  alignItems: string;
10
10
  justifyContent: string;
11
11
  zIndex: number;
12
+ fontFamily: string;
12
13
  };
13
14
  export declare const containerStyle: {
14
15
  display: string;
@@ -27,6 +28,7 @@ export declare const containerWidgetStyle: {
27
28
  gap: string;
28
29
  'align-items': string;
29
30
  padding: string;
31
+ fontFamily: string;
30
32
  'border-radius': string;
31
33
  border: string;
32
34
  background: string;
@@ -50,6 +52,7 @@ export declare const descriptionStyle: {
50
52
  fontStyle: string;
51
53
  fontWeight: string;
52
54
  lineHeight: string;
55
+ whiteSpace: string;
53
56
  };
54
57
  export declare const noticeStyle: {
55
58
  color: string;
@@ -93,6 +96,8 @@ export declare const contentStyle: {
93
96
  flexDirection: string;
94
97
  alignItems: string;
95
98
  gap: string;
99
+ fontSize: string;
100
+ lineHeight: string;
96
101
  };
97
102
  export declare const titleWidgetStyle: {
98
103
  padding: string;
@@ -114,17 +119,14 @@ export declare const descriptionWidgetStyle: {
114
119
  boxSizing: string;
115
120
  display: string;
116
121
  width: string;
117
- borderRadius: string;
118
- border: string;
122
+ borderBottom: string;
119
123
  background: string;
120
124
  padding: string;
121
125
  alignSelf: string;
122
126
  color: string;
123
127
  fontFamily: string;
124
- fontSize: string;
125
128
  fontStyle: string;
126
129
  fontWeight: string;
127
- lineHeight: string;
128
130
  };
129
131
  export declare const endSectionStyle: {
130
132
  display: string;
@@ -133,17 +135,14 @@ export declare const endSectionStyle: {
133
135
  gap: string;
134
136
  boxSizing: string;
135
137
  width: string;
136
- borderRadius: string;
137
- border: string;
138
+ borderBottom: string;
138
139
  background: string;
139
140
  padding: string;
140
141
  alignSelf: string;
141
142
  color: string;
142
143
  fontFamily: string;
143
- fontSize: string;
144
144
  fontStyle: string;
145
145
  fontWeight: string;
146
- lineHeight: string;
147
146
  };
148
147
  export declare const symbolIcon: {
149
148
  fontSize: string;
@@ -174,9 +173,12 @@ export declare const buttonWidgetStyle: {
174
173
  };
175
174
  export declare const stopWidgetStyle: {
176
175
  marginTop: string;
176
+ marginBottom: string;
177
177
  cursor: string;
178
178
  display: string;
179
179
  fontWeight: string;
180
+ fontSize: string;
181
+ lineHeight: string;
180
182
  };
181
183
  export declare const paginationStyle: {
182
184
  display: string;
@@ -189,21 +191,27 @@ export declare const paginationStyle: {
189
191
  };
190
192
  export declare const taskNumberActive: {
191
193
  display: string;
192
- padding: string;
193
194
  flexDirection: string;
194
195
  alignItems: string;
196
+ justifyContent: string;
195
197
  borderRadius: string;
196
198
  outline: string;
199
+ fontSize: string;
200
+ height: string;
201
+ width: string;
197
202
  };
198
203
  export declare const taskNumberDone: {
199
204
  display: string;
200
- padding: string;
201
205
  flexDirection: string;
202
206
  alignItems: string;
207
+ justifyContent: string;
203
208
  borderRadius: string;
204
209
  outline: string;
205
210
  boxShadow: string;
206
211
  background: string;
212
+ fontSize: string;
213
+ height: string;
214
+ width: string;
207
215
  };
208
216
  export declare const taskDescriptionCard: {
209
217
  borderRadius: string;
@@ -220,7 +228,8 @@ export declare const taskTextStyle: {
220
228
  fontWeight: string;
221
229
  };
222
230
  export declare const taskDescriptionStyle: {
223
- color: string;
231
+ fontSize: string;
232
+ lineHeight: string;
224
233
  };
225
234
  export declare const taskButtonStyle: {
226
235
  marginRight: string;
@@ -258,3 +267,11 @@ export declare const taskButtonsRow: {
258
267
  width: string;
259
268
  boxSizing: string;
260
269
  };
270
+ export declare const spinnerStyles: {
271
+ border: string;
272
+ width: string;
273
+ height: string;
274
+ borderRadius: string;
275
+ borderLeftColor: string;
276
+ animation: string;
277
+ };