+41
-68
posting_stats_page.js
+41
-68
posting_stats_page.js
···
18
this.submitButton = $(this.pageElement.querySelector('input[type="submit"]'), HTMLInputElement);
19
this.progressBar = $(this.pageElement.querySelector('input[type=submit] + progress'), HTMLProgressElement);
20
this.table = $(this.pageElement.querySelector('table.scan-result'));
21
22
this.setupEvents();
23
···
26
}
27
28
setupEvents() {
29
-
$(this.pageElement.querySelector('form')).addEventListener('submit', (e) => {
30
e.preventDefault();
31
32
if (!this.scanStartTime) {
···
38
39
this.rangeInput.addEventListener('input', (e) => {
40
let days = parseInt(this.rangeInput.value, 10);
41
-
this.configurePostingStats({ days });
42
});
43
44
-
this.pageElement.querySelectorAll('input[type="radio"]').forEach(r => {
45
r.addEventListener('click', (e) => {
46
let value = $(r, HTMLInputElement).value;
47
···
67
/** @returns {Promise<void>} */
68
69
async fetchLists() {
70
-
let select = $(this.pageElement.querySelector('.list-choice select'));
71
let lists = await accountAPI.loadUserLists();
72
73
let sorted = lists.sort((a, b) => {
···
78
});
79
80
for (let list of lists) {
81
-
let opt = $tag('option', { value: list.uri, text: list.name + ' ' });
82
-
select.append(opt);
83
-
}
84
-
}
85
-
86
-
/** @param {{ days: number }} args */
87
-
88
-
configurePostingStats(args) {
89
-
if (args.days) {
90
-
let label = $(this.pageElement.querySelector('input[type=range] + label'));
91
-
label.innerText = (args.days == 1) ? '1 day' : `${args.days} days`;
92
}
93
}
94
95
/** @returns {Promise<void>} */
96
97
async scanPostingStats() {
98
-
this.submitButton.value = 'Cancel';
99
-
100
let requestedDays = this.selectedDaysRange();
101
-
102
-
this.progressBar.max = requestedDays;
103
-
this.progressBar.value = 0;
104
-
this.progressBar.style.display = 'inline';
105
-
106
-
this.table.style.display = 'none';
107
108
-
let tbody = $(this.table.querySelector('tbody'));
109
-
tbody.innerHTML = '';
110
-
111
-
let thead = $(this.table.querySelector('thead'));
112
-
thead.innerHTML = '';
113
-
114
-
let startTime = new Date().getTime();
115
-
this.scanStartTime = startTime;
116
-
117
-
let scanInfo = $(this.pageElement.querySelector('.scan-info'));
118
-
scanInfo.style.display = 'none';
119
120
/** @type {FetchAllOnPageLoad} */
121
let onPageLoad = (data) => {
···
126
this.updateProgress(data, startTime);
127
};
128
129
-
let scanType = this.form.elements['scan_type'].value;
130
-
131
if (scanType == 'home') {
132
let items = await accountAPI.loadHomeTimeline(requestedDays, {
133
onPageLoad: onPageLoad,
134
keepLastPage: true
135
});
136
-
137
-
if (this.scanStartTime != startTime) {
138
-
return;
139
-
}
140
141
this.updateResultsTable(items, startTime, requestedDays);
142
} else if (scanType == 'list') {
143
-
let select = $(this.pageElement.querySelector('.list-choice select'), HTMLSelectElement);
144
-
let list = select.value;
145
let items = await accountAPI.loadListTimeline(list, requestedDays, {
146
onPageLoad: onPageLoad,
147
keepLastPage: true
148
});
149
-
150
-
if (this.scanStartTime != startTime) {
151
-
return;
152
-
}
153
154
this.updateResultsTable(items, startTime, requestedDays, { showReposts: false });
155
} else if (scanType == 'users') {
···
172
}));
173
174
let datasets = await Promise.all(requests);
175
-
176
-
if (this.scanStartTime != startTime) {
177
-
return;
178
-
}
179
-
180
let items = datasets.flat();
181
182
this.updateResultsTable(items, startTime, requestedDays, {
···
189
keepLastPage: true
190
});
191
192
-
if (this.scanStartTime != startTime) {
193
-
return;
194
-
}
195
-
196
this.updateResultsTable(items, startTime, requestedDays, { showTotal: false, showPercentages: false });
197
}
198
}
···
209
210
this.progressBar.value = daysBack;
211
}
212
-
213
214
/** @param {string[]} dids */
215
···
265
*/
266
267
updateResultsTable(items, startTime, requestedDays, options = {}) {
268
let users = {};
269
let total = 0;
270
let allReposts = 0;
···
284
let fetchedDays = (startTime - lastDate) / 86400 / 1000;
285
286
if (Math.ceil(fetchedDays) < requestedDays) {
287
-
let scanInfo = $(this.pageElement.querySelector('.scan-info'));
288
-
scanInfo.innerText = `🕓 Showing data from ${Math.round(fetchedDays)} days (the timeline only goes that far):`;
289
-
scanInfo.style.display = 'block';
290
}
291
292
daysBack = Math.min(requestedDays, fetchedDays);
···
314
}
315
}
316
317
-
let thead = $(this.table.querySelector('thead'));
318
let headRow = $tag('tr');
319
320
if (options.showReposts !== false) {
···
337
headRow.append($tag('th', { text: '% of all' }));
338
}
339
340
-
thead.append(headRow);
341
-
342
-
let tbody = $(this.table.querySelector('tbody'));
343
344
if (options.showTotal !== false) {
345
let tr = $tag('tr.total');
···
361
tr.append($tag('td.percent', { text: '' }));
362
}
363
364
-
tbody.append(tr);
365
}
366
367
let sorted = Object.values(users).sort(this.sortUserRows);
···
390
tr.append($tag('td.percent', { text: ((user.own + user.reposts) * 100 / total).toFixed(1) + '%' }));
391
}
392
393
-
tbody.append(tr);
394
}
395
396
this.table.style.display = 'table';
397
-
this.submitButton.value = 'Start scan';
398
-
this.progressBar.style.display = 'none';
399
-
this.scanStartTime = undefined;
400
}
401
402
stopScan() {
···
18
this.submitButton = $(this.pageElement.querySelector('input[type="submit"]'), HTMLInputElement);
19
this.progressBar = $(this.pageElement.querySelector('input[type=submit] + progress'), HTMLProgressElement);
20
this.table = $(this.pageElement.querySelector('table.scan-result'));
21
+
this.tableHead = $(this.table.querySelector('thead'));
22
+
this.tableBody = $(this.table.querySelector('tbody'));
23
+
this.listSelect = $(this.pageElement.querySelector('.list-choice select'), HTMLSelectElement);
24
+
this.scanInfo = $(this.pageElement.querySelector('.scan-info'));
25
+
this.scanType = this.form.elements['scan_type'];
26
27
this.setupEvents();
28
···
31
}
32
33
setupEvents() {
34
+
this.form.addEventListener('submit', (e) => {
35
e.preventDefault();
36
37
if (!this.scanStartTime) {
···
43
44
this.rangeInput.addEventListener('input', (e) => {
45
let days = parseInt(this.rangeInput.value, 10);
46
+
let label = $(this.pageElement.querySelector('input[type=range] + label'));
47
+
label.innerText = (days == 1) ? '1 day' : `${days} days`;
48
});
49
50
+
this.scanType.forEach(r => {
51
r.addEventListener('click', (e) => {
52
let value = $(r, HTMLInputElement).value;
53
···
73
/** @returns {Promise<void>} */
74
75
async fetchLists() {
76
let lists = await accountAPI.loadUserLists();
77
78
let sorted = lists.sort((a, b) => {
···
83
});
84
85
for (let list of lists) {
86
+
this.listSelect.append(
87
+
$tag('option', { value: list.uri, text: list.name + ' ' })
88
+
);
89
}
90
}
91
92
/** @returns {Promise<void>} */
93
94
async scanPostingStats() {
95
+
let startTime = new Date().getTime();
96
let requestedDays = this.selectedDaysRange();
97
+
let scanType = this.scanType.value;
98
99
+
this.startScan(startTime, requestedDays);
100
101
/** @type {FetchAllOnPageLoad} */
102
let onPageLoad = (data) => {
···
107
this.updateProgress(data, startTime);
108
};
109
110
if (scanType == 'home') {
111
let items = await accountAPI.loadHomeTimeline(requestedDays, {
112
onPageLoad: onPageLoad,
113
keepLastPage: true
114
});
115
116
this.updateResultsTable(items, startTime, requestedDays);
117
} else if (scanType == 'list') {
118
+
let list = this.listSelect.value;
119
let items = await accountAPI.loadListTimeline(list, requestedDays, {
120
onPageLoad: onPageLoad,
121
keepLastPage: true
122
});
123
124
this.updateResultsTable(items, startTime, requestedDays, { showReposts: false });
125
} else if (scanType == 'users') {
···
142
}));
143
144
let datasets = await Promise.all(requests);
145
let items = datasets.flat();
146
147
this.updateResultsTable(items, startTime, requestedDays, {
···
154
keepLastPage: true
155
});
156
157
this.updateResultsTable(items, startTime, requestedDays, { showTotal: false, showPercentages: false });
158
}
159
}
···
170
171
this.progressBar.value = daysBack;
172
}
173
174
/** @param {string[]} dids */
175
···
225
*/
226
227
updateResultsTable(items, startTime, requestedDays, options = {}) {
228
+
if (this.scanStartTime != startTime) {
229
+
return;
230
+
}
231
+
232
let users = {};
233
let total = 0;
234
let allReposts = 0;
···
248
let fetchedDays = (startTime - lastDate) / 86400 / 1000;
249
250
if (Math.ceil(fetchedDays) < requestedDays) {
251
+
this.scanInfo.innerText = `🕓 Showing data from ${Math.round(fetchedDays)} days (the timeline only goes that far):`;
252
+
this.scanInfo.style.display = 'block';
253
}
254
255
daysBack = Math.min(requestedDays, fetchedDays);
···
277
}
278
}
279
280
let headRow = $tag('tr');
281
282
if (options.showReposts !== false) {
···
299
headRow.append($tag('th', { text: '% of all' }));
300
}
301
302
+
this.tableHead.append(headRow);
303
304
if (options.showTotal !== false) {
305
let tr = $tag('tr.total');
···
321
tr.append($tag('td.percent', { text: '' }));
322
}
323
324
+
this.tableBody.append(tr);
325
}
326
327
let sorted = Object.values(users).sort(this.sortUserRows);
···
350
tr.append($tag('td.percent', { text: ((user.own + user.reposts) * 100 / total).toFixed(1) + '%' }));
351
}
352
353
+
this.tableBody.append(tr);
354
}
355
356
this.table.style.display = 'table';
357
+
this.stopScan();
358
+
}
359
+
360
+
startScan(startTime, requestedDays) {
361
+
this.submitButton.value = 'Cancel';
362
+
363
+
this.progressBar.max = requestedDays;
364
+
this.progressBar.value = 0;
365
+
this.progressBar.style.display = 'inline';
366
+
367
+
this.table.style.display = 'none';
368
+
this.tableHead.innerHTML = '';
369
+
this.tableBody.innerHTML = '';
370
+
371
+
this.scanStartTime = startTime;
372
+
this.scanInfo.style.display = 'none';
373
}
374
375
stopScan() {