@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.
- package/CHANGELOG.md +4 -0
- package/cjs/app/index.d.ts +4 -0
- package/cjs/app/index.js +28 -4
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +7 -1
- package/cjs/modules/userTesting/SignalManager.d.ts +29 -0
- package/cjs/modules/userTesting/SignalManager.js +83 -0
- package/cjs/modules/userTesting/index.d.ts +7 -7
- package/cjs/modules/userTesting/index.js +169 -195
- package/cjs/modules/userTesting/styles.d.ts +28 -11
- package/cjs/modules/userTesting/styles.js +51 -29
- package/cjs/modules/userTesting/utils.d.ts +9 -0
- package/cjs/modules/userTesting/utils.js +87 -0
- package/coverage/clover.xml +851 -351
- package/coverage/coverage-final.json +10 -4
- package/coverage/lcov-report/index.html +38 -23
- package/coverage/lcov-report/main/app/canvas.ts.html +1 -1
- package/coverage/lcov-report/main/app/guards.ts.html +42 -42
- package/coverage/lcov-report/main/app/index.html +24 -24
- package/coverage/lcov-report/main/app/index.ts.html +196 -28
- package/coverage/lcov-report/main/app/logger.ts.html +1 -1
- package/coverage/lcov-report/main/app/messages.gen.ts.html +1 -1
- package/coverage/lcov-report/main/app/nodes.ts.html +1 -1
- package/coverage/lcov-report/main/app/observer/iframe_observer.ts.html +1 -1
- package/coverage/lcov-report/main/app/observer/iframe_offsets.ts.html +1 -1
- package/coverage/lcov-report/main/app/observer/index.html +1 -1
- package/coverage/lcov-report/main/app/observer/shadow_root_observer.ts.html +1 -1
- package/coverage/lcov-report/main/app/observer/top_observer.ts.html +1 -1
- package/coverage/lcov-report/main/app/sanitizer.ts.html +1 -1
- package/coverage/lcov-report/main/app/session.ts.html +1 -1
- package/coverage/lcov-report/main/app/ticker.ts.html +1 -1
- package/coverage/lcov-report/main/index.html +11 -11
- package/coverage/lcov-report/main/index.ts.html +33 -6
- package/coverage/lcov-report/main/modules/Network/beaconProxy.ts.html +1 -1
- package/coverage/lcov-report/main/modules/Network/fetchProxy.ts.html +1 -1
- package/coverage/lcov-report/main/modules/Network/index.html +1 -1
- package/coverage/lcov-report/main/modules/Network/index.ts.html +1 -1
- package/coverage/lcov-report/main/modules/Network/networkMessage.ts.html +1 -1
- package/coverage/lcov-report/main/modules/Network/utils.ts.html +1 -1
- package/coverage/lcov-report/main/modules/Network/xhrProxy.ts.html +1 -1
- package/coverage/lcov-report/main/modules/attributeSender.ts.html +1 -1
- package/coverage/lcov-report/main/modules/axiosSpy.ts.html +1 -1
- package/coverage/lcov-report/main/modules/connection.ts.html +1 -1
- package/coverage/lcov-report/main/modules/console.ts.html +1 -1
- package/coverage/lcov-report/main/modules/constructedStyleSheets.ts.html +1 -1
- package/coverage/lcov-report/main/modules/cssrules.ts.html +1 -1
- package/coverage/lcov-report/main/modules/exception.ts.html +1 -1
- package/coverage/lcov-report/main/modules/featureFlags.ts.html +1 -1
- package/coverage/lcov-report/main/modules/focus.ts.html +1 -1
- package/coverage/lcov-report/main/modules/fonts.ts.html +1 -1
- package/coverage/lcov-report/main/modules/img.ts.html +1 -1
- package/coverage/lcov-report/main/modules/index.html +1 -1
- package/coverage/lcov-report/main/modules/input.ts.html +1 -1
- package/coverage/lcov-report/main/modules/mouse.ts.html +1 -1
- package/coverage/lcov-report/main/modules/network.ts.html +1 -1
- package/coverage/lcov-report/main/modules/performance.ts.html +1 -1
- package/coverage/lcov-report/main/modules/scroll.ts.html +1 -1
- package/coverage/lcov-report/main/modules/selection.ts.html +1 -1
- package/coverage/lcov-report/main/modules/tabs.ts.html +1 -1
- package/coverage/lcov-report/main/modules/timing.ts.html +1 -1
- package/coverage/lcov-report/main/modules/userTesting/SignalManager.ts.html +361 -0
- package/coverage/lcov-report/main/modules/userTesting/dnd.ts.html +10 -22
- package/coverage/lcov-report/main/modules/userTesting/index.html +61 -31
- package/coverage/lcov-report/main/modules/userTesting/index.ts.html +809 -113
- package/coverage/lcov-report/main/modules/userTesting/recorder.ts.html +136 -67
- package/coverage/lcov-report/main/modules/userTesting/styles.ts.html +159 -87
- package/coverage/lcov-report/main/modules/userTesting/utils.ts.html +361 -0
- package/coverage/lcov-report/main/modules/viewport.ts.html +1 -1
- package/coverage/lcov-report/main/utils.ts.html +48 -6
- package/coverage/lcov-report/webworker/BatchWriter.ts.html +1 -1
- package/coverage/lcov-report/webworker/MessageEncoder.gen.ts.html +1 -1
- package/coverage/lcov-report/webworker/PrimitiveEncoder.ts.html +1 -1
- package/coverage/lcov-report/webworker/QueueSender.ts.html +1 -1
- package/coverage/lcov-report/webworker/index.html +1 -1
- package/coverage/lcov-report/webworker/index.ts.html +1 -1
- package/coverage/lcov.info +1535 -653
- package/lib/app/index.d.ts +4 -0
- package/lib/app/index.js +28 -4
- package/lib/index.d.ts +1 -0
- package/lib/index.js +7 -1
- package/lib/modules/userTesting/SignalManager.d.ts +29 -0
- package/lib/modules/userTesting/SignalManager.js +80 -0
- package/lib/modules/userTesting/index.d.ts +7 -7
- package/lib/modules/userTesting/index.js +141 -167
- package/lib/modules/userTesting/styles.d.ts +28 -11
- package/lib/modules/userTesting/styles.js +50 -28
- package/lib/modules/userTesting/utils.d.ts +9 -0
- package/lib/modules/userTesting/utils.js +79 -0
- 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
|
-
|
|
5
|
-
|
|
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.
|
|
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(
|
|
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(
|
|
125
|
-
this.app.localStorage.removeItem(
|
|
126
|
-
this.app.localStorage.removeItem(
|
|
127
|
-
this.app.localStorage.removeItem(
|
|
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(
|
|
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,
|
|
138
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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', {
|
|
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
|
-
|
|
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(
|
|
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', {
|
|
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
|
-
|
|
212
|
+
overflowY: 'auto',
|
|
213
|
+
whiteSpace: 'pre-wrap',
|
|
214
|
+
fontSize: 13,
|
|
215
|
+
color: '#454545',
|
|
216
|
+
lineHeight: 'auto',
|
|
244
217
|
});
|
|
245
|
-
descriptionC.innerHTML =
|
|
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
|
-
|
|
266
|
-
|
|
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', {
|
|
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
|
|
299
|
-
const nextButton = createElement('div', 'nextButton', styles.taskButtonBorderedStyle, 'Done,
|
|
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}`, {
|
|
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
|
-
|
|
364
|
-
|
|
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
|
|
389
|
-
|
|
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
|
-
},
|
|
395
|
-
const description = createElement('div', 'end_description_or', {}, (
|
|
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
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
};
|