-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpopup.js
299 lines (271 loc) · 13.5 KB
/
popup.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
document.addEventListener('DOMContentLoaded', function () {
// review screen elements
var quitButton = document.getElementById('quit');
var nextButton = document.getElementById('next');
// var instructionsDiv = document.getElementById('instructions');
var subjectDiv = document.getElementById('subject');
var fromDiv = document.getElementById('from');
var bodyDiv = document.getElementById('body');
var reviewCountDiv = document.getElementById('reviewCount');
var msgDiv = document.getElementById('msg');
var skipButton = document.getElementById('skip');
// question and answer elements
var questionDiv = document.getElementById('question');
var noButton = document.getElementById('noBtn');
var yesButton = document.getElementById('yesBtn');
var applyCurrentLabelButton = document.getElementById('applyLabelBtn');
var applyLabelAndFinishButton = document.getElementById('applyLabelsAndFinishBtn');
var redoButton = document.getElementById('redoBtn');
// setup screen elements
var setupSection = document.getElementById('setupSection');
var reviewSection = document.getElementById('reviewSection');
var fiveButton = document.getElementById('five');
var tenButton = document.getElementById('ten');
var twentyButton = document.getElementById('twenty');
var fiftyButton = document.getElementById('fifty');
var setupMsg = document.getElementById('setupMsg'); // this can be used for displaying response errors
var skipToggle = document.getElementById('skipping');
var clearButton = document.getElementById('clearAllLabels');
var resetButton = document.getElementById('reset');
// hide reset button by default
resetButton.classList.add('dn');
resetButton.classList.remove('dib');
var spinner = document.getElementById('spinner');
function getToggleState() {
return skipToggle.checked;
}
function showSpinner() {
spinner.classList.add('dib');
spinner.classList.remove('dn');
}
/**
* Updates the user interface with the provided email details, review count, and maximum reviews.
*
* @param {object} emailDetails - The details of the email.
* @param {string} emailDetails.subject - The subject of the email.
* @param {string} emailDetails.from - The sender of the email.
* @param {string} emailDetails.body - The body of the email.
* @param {number} reviewCount - The current review count.
* @param {number} maxReviews - The maximum number of reviews.
* @returns {void}
*/
function updateUI(emailDetails, reviewCount, maxReviews) {
// instructionsDiv.textContent = ''; // Clear the instructions
subjectDiv.textContent = 'Subject: ' + (emailDetails.subject || 'No subject');
fromDiv.textContent = 'From: ' + (emailDetails.from || 'No from');
bodyDiv.textContent = 'Body: ' + (emailDetails.body || 'Message body parsing unsuccessful');
reviewCountDiv.textContent = `Review count: ${reviewCount + 1} of ${maxReviews}`;
msgDiv.textContent = ''; // Clear any previous messages
setupMsg.textContent = ''; // Clear any previous messages
// If on the last review, change the 'next' button text to 'Finish'
// Also, toggle display of 'applyLabelAndNext' and 'applyLabelsAndFinish' buttons
if (reviewCount + 1 === maxReviews) {
nextButton.textContent = 'Finish';
nextButton.title = 'Apply \'reviewed\' label, finish review session, & return to setup';
applyCurrentLabelButton.classList.add('dn');
applyCurrentLabelButton.classList.remove('dib');
applyLabelAndFinishButton.classList.add('dib');
applyLabelAndFinishButton.classList.remove('dn');
// hide skip button
skipButton.classList.add('dn');
skipButton.classList.remove('dib');
} else {
nextButton.textContent = 'Next';
nextButton.title = 'Apply \'reviewed\' label & go to next thread';
applyCurrentLabelButton.classList.add('dib');
applyCurrentLabelButton.classList.remove('dn');
applyLabelAndFinishButton.classList.add('dn');
applyLabelAndFinishButton.classList.remove('dib');
// show skip button
skipButton.classList.add('dib');
skipButton.classList.remove('dn');
}
}
// // Function to request and display the current state
function loadState() {
chrome.runtime.sendMessage({ action: 'loadFromState' }, responseFromBackgroundCallback);
}
function toggleYesNoBtns(isLeafNode) {
if(isLeafNode) {
yesButton.classList.add('dn');
yesButton.classList.remove('dib');
noButton.classList.add('dn');
noButton.classList.remove('dib');
redoButton.classList.add('dib');
redoButton.classList.remove('dn');
labelBtnsDiv.classList.add('dib');
labelBtnsDiv.classList.remove('dn');
} else {
yesButton.classList.add('dib');
yesButton.classList.remove('dn');
noButton.classList.add('dib');
noButton.classList.remove('dn');
redoButton.classList.add('dn');
redoButton.classList.remove('dib');
labelBtnsDiv.classList.add('dn');
labelBtnsDiv.classList.remove('dib');
}
}
/**
* Updates the titles of the yes and no buttons based on the review state and whether the node is a leaf node.
*
* @param {boolean} isLeafNode - Indicates whether the node is a leaf node.
* @param {Object} reviewState - The review state object containing the titles for the yes and no buttons.
*/
function updateYesNoTitles(isLeafNode, reviewState) {
if(!isLeafNode) {
yesButton.title = reviewState.yesBtnTitle;
noButton.title = reviewState.noBtnTitle;
}
}
/**
* Handles the response received from the background script.
* @param {Object} response - The response object from the background script.
*/
function responseFromBackgroundCallback(response) {
// hide the spinner, now that a response has come back
spinner.classList.add('dn');
spinner.classList.remove('dib');
if (response.error) {
console.log('Displaying error: ', response.error);
setupMsg.textContent = 'Error: ' + response.error;
} else {
console.log("Displaying notification:", response.message);
// displaying notifications
if(response.type === 'notification') {
msgDiv.textContent = response.message;
setupMsg.textContent = response.message;
}
// leaving review state
else if (response.type === 'returnToSetup' ||
response.type === 'finishReview' ||
response.type === 'applyLabelsAndFinish') {
console.log("Returning to setup section");
// Toggle the display of the sections
setupSection.classList.remove('dn');
reviewSection.classList.add('dn');
reviewSection.classList.remove('flex');
reviewSection.classList.remove('flex-column');
reviewSection.classList.remove('justify-between');
// Change the 'next' button text back to 'Next'
nextButton.textContent = 'Next';
}
// in reviewing state
else {
let state = response.data.state;
// update skipping input checkbox w/ state.skipping value
skipToggle.checked = state.skipping;
if (!(state && state.currentEmailDetails && state.currentIndex !== -1 && state.maxReviews !== -1)) {
console.log("Review data not valid, showing setup section");
// If the review data is not valid, show the setup section
setupSection.classList.remove('dn');
reviewSection.classList.add('dn');
reviewSection.classList.remove('flex');
reviewSection.classList.remove('flex-column');
reviewSection.classList.remove('justify-between');
// Change the 'next' button text back to 'Next'
nextButton.textContent = 'Next';
return; // return early when review data is not valid
}
// If the response is to load the state or to go to the next email, update the UI
if(response.type === 'loadFromState' || response.type === 'nextEmail' ||
response.type === 'startReviewSession' || response.type === "nextQuestionNo" ||
response.type === "nextQuestionYes") {
// Toggle the display of the sections
// console.log("showing review section");
setupSection.classList.add('dn');
reviewSection.classList.remove('dn');
reviewSection.classList.add('flex');
reviewSection.classList.add('flex-column');
reviewSection.classList.add('justify-between');
console.log("response", response);
questionDiv.textContent = response.data.reviewState.questionText;
questionDiv.title = response.data.reviewState.questionExplanation || '';
// if we are on a leaf node, we will conditionally display the 'apply label' button
// and 'redo decision tree' button instead of the 'yes' and 'no' buttons
toggleYesNoBtns(response.data.reviewState.isLeafNode);
updateYesNoTitles(response.data.reviewState.isLeafNode, response.data.reviewState);
}
nextButton.disabled = false;
console.log("refreshing email data, not returning to setup");
msgDiv.textContent = ''; // Clear any previous messages
setupMsg.textContent = ''; // Clear any previous messages
// Update the UI with the email details and review count
updateUI(state.currentEmailDetails, state.reviewCount, state.maxReviews);
}
}
}
/**
* Handles an action by sending a message to the background script.
* @param {string} action - The action to be performed.
*/
function handleActionWithBackground(action) {
chrome.runtime.sendMessage({ action: action },
responseFromBackgroundCallback);
}
/**
* Sends a message to background.js to start a new review session and initialize maxReviews
*
* @param {number} maxReviews - The maximum number of reviews to be performed.
* @param {boolean} skipping - Indicates whether skipping is allowed during the review session.
*/
function startReviewSession(maxReviews, skipping) {
chrome.runtime.sendMessage({ action: 'startReviewSession', maxReviews, skipping },
responseFromBackgroundCallback);
}
// Event listeners for review buttons
quitButton.addEventListener('click', () => handleActionWithBackground('returnToSetup'));
nextButton.addEventListener('click', () => {
this.disabled = true;
if (nextButton.textContent === 'Next') {
handleActionWithBackground('nextEmail');
} else if (nextButton.textContent === 'Finish') {
handleActionWithBackground('finishReview');
} else {
console.error('Invalid button text');
}
});
skipButton.addEventListener('click', () => handleActionWithBackground('skipEmail'));
// Event listeners for question buttons
noButton.addEventListener('click', () => handleActionWithBackground('nextQuestionNo'));
yesButton.addEventListener('click', () => handleActionWithBackground('nextQuestionYes'));
applyCurrentLabelButton.addEventListener('click', () => handleActionWithBackground('applyLabelAndGotoNextEmail'));
applyLabelAndFinishButton.addEventListener('click', () => {
showSpinner();
handleActionWithBackground('applyLabelsAndFinish');
});
redoButton.addEventListener('click', () => handleActionWithBackground('loadFromState')); // redoDecisionTree
// Event listener for clear button
clearButton.addEventListener('click', () => {
showSpinner();
handleActionWithBackground('clearAllLabels');
});
// Event listeners for setup buttons
fiveButton.addEventListener('click', () => {
startReviewSession(5, getToggleState());
showSpinner();
});
tenButton.addEventListener('click', () => {
startReviewSession(10, getToggleState());
showSpinner();
});
twentyButton.addEventListener('click', () => {
startReviewSession(20, getToggleState());
showSpinner();
});
fiftyButton.addEventListener('click', () => {
startReviewSession(50, getToggleState());
showSpinner();
});
resetButton.addEventListener('click', () => {
showSpinner();
handleActionWithBackground('resetState');
});
// Event listener for skipping toggle, which saves skipping value into state
skipToggle.addEventListener('change', () => {
chrome.runtime.sendMessage({ action: 'updateSkipping', skipping: getToggleState() }, function(response) {
console.log("response", response);
});
});
loadState();
});