@openreplay/tracker 11.0.0 → 11.0.2

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