blob: 153cfb13983d18b7e5164f4246d4021bd5abde96 [file] [log] [blame]
Adrià Vilanova Martínez4768e812022-02-01 13:41:28 +01001import {MDCTooltip} from '@material/tooltip';
2
3import {createExtBadge} from './common.js';
4
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +01005// Each entry includes the following information in order:
6// - ID
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +01007// - Codename
8// - Color (for the label in the legend)
9const kDataKeys = [
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +010010 [4, 'recommended', '#34A853'],
11 [6, 'replies', '#DADCE0'],
12 [5, 'questions', '#77909D'],
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010013];
14const kRoles = {
15 1: 'bronze',
16 2: 'silver',
17 3: 'gold',
18 4: 'platinum',
19 5: 'diamond',
20 10: 'community_manager',
21 20: 'community_specialist',
22 100: 'google_employee',
23 30: 'alumnus',
24};
25
26export default class PerForumStatsSection {
27 constructor(existingChartSection, profile, locale) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010028 this.locale = locale;
29 this.parseAndSetData(profile);
30 this.buildDOM(existingChartSection);
31 if (this.data.length) this.injectChart(this.data[0]?.id);
32 }
33
34 parseAndSetData(profile) {
35 const forumUserInfos = profile?.[1]?.[7] ?? [];
36 const forumTitles = profile?.[1]?.[8] ?? [];
37
38 const forumUserInfoIDs = forumUserInfos.map(ui => ui[1]);
39 const forumTitleIDs = forumTitles.map(t => t[1]);
40 const intersectionForumIDs =
41 forumUserInfoIDs.filter(id => forumTitleIDs.includes(id));
42
43 this.data = [];
44 for (const id of intersectionForumIDs) {
45 const fui = forumUserInfos.find(ui => ui[1] === id)?.[2];
46 const numMessages = kDataKeys.reduce((prevVal, key) => {
47 if (!fui?.[key[0]]) return prevVal;
48 return prevVal + fui[key[0]].reduce((prevVal, userActivity) => {
49 return prevVal + (userActivity?.[3] ?? 0);
50 }, /* initialValue = */ 0);
51 }, /* initialValue = */ 0);
52 this.data.push({
53 id,
54 forumTitle: forumTitles.find(t => t[1] === id)?.[2],
55 forumUserInfo: fui,
56 numMessages,
57 });
58 }
59 this.data.sort((a, b) => {
60 // First sort by number of messages
61 if (b.numMessages > a.numMessages) return 1;
62 if (b.numMessages < a.numMessages) return -1;
63 // Then sort by name
64 return a.forumTitle.localeCompare(
65 b.forumTitle, 'en', {sensitivity: 'base'});
66 });
67 }
68
69 buildDOM(existingChartSection) {
70 let section = document.createElement('div');
71 section.classList.add('scTailwindUser_profileUserprofilesection');
72
73 let root = document.createElement('div');
74 root.classList.add(
75 'scTailwindSharedActivitychartroot',
76 'TWPT-scTailwindSharedActivitychartroot');
77
78 let title = document.createElement('h2');
79 title.classList.add('scTailwindSharedActivitycharttitle');
Adrià Vilanova Martínez4768e812022-02-01 13:41:28 +010080
81 const [badge, badgeTooltip] = createExtBadge();
82 let titleText = document.createElement('span');
83 titleText.textContent = chrome.i18n.getMessage('inject_perforumstats_heading');
84
85 title.append(badge, titleText);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010086
87 let selector = this.createForumSelector();
88
89 let chartEl = document.createElement('div');
90 chartEl.classList.add('scTailwindSharedActivitychartchart');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +010091 chartEl.setAttribute('data-twpt-per-forum-chart', '');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010092
93 root.append(title, selector, chartEl);
94 section.append(root);
95 existingChartSection.after(section);
Adrià Vilanova Martínez4768e812022-02-01 13:41:28 +010096 new MDCTooltip(badgeTooltip);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010097 }
98
99 getAplosData(forumId) {
100 let aplosData = [];
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100101 for (const [key, name, color] of kDataKeys) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100102 let rawData = this.data.find(f => f.id === forumId)?.forumUserInfo?.[key];
103 let data;
104 if (!rawData)
105 data = [];
106 else
107 data = rawData.map(m => JSON.stringify(Object.values(m)));
108 aplosData.push({
109 color,
110 data,
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100111 label: chrome.i18n.getMessage('inject_perforumstats_chart_' + name),
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100112 name,
113 });
114 }
115 return aplosData;
116 }
117
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100118 getMessagesString(num) {
119 if (num == 1) {
120 return chrome.i18n.getMessage(
121 'inject_perforumstats_nummessages_singular');
122 }
123 return chrome.i18n.getMessage(
124 'inject_perforumstats_nummessages_plural', [num]);
125 }
126
127 getForumOptionString(forumTitle, labels) {
128 if (labels.length == 0) return forumTitle;
129 if (labels.length == 1)
130 return chrome.i18n.getMessage(
131 'inject_perforumstats_forumoption_1helper', [forumTitle, ...labels]);
132 if (labels.length == 2)
133 return chrome.i18n.getMessage(
134 'inject_perforumstats_forumoption_2helpers', [forumTitle, ...labels]);
135
136 // If labels.length > 3, this is unexpected. Here's a sensible fallback:
137 return forumTitle + ' (' + labels.join(', ') + ')';
138 }
139
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100140 createForumSelector() {
141 let div = document.createElement('div');
142 div.classList.add('TWPT-select-container');
143
144 let select = document.createElement('select');
145 let noPostsGroup;
146 let noPostsGroupFlag = false;
147 for (const forumData of this.data) {
148 const hasPosted = forumData.numMessages > 0;
149
150 if (!hasPosted && !noPostsGroupFlag) {
151 noPostsGroup = document.createElement('optgroup');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100152 noPostsGroup.label =
153 chrome.i18n.getMessage('inject_perforumstats_optgroup_notposted');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100154 noPostsGroupFlag = true;
155 }
156
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100157 let additionalLabels = [];
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100158 if (hasPosted)
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100159 additionalLabels.push(this.getMessagesString(forumData.numMessages));
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100160 let role = forumData.forumUserInfo?.[1]?.[3] ?? 0;
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100161 if (role)
162 additionalLabels.push(chrome.i18n.getMessage(
163 'inject_perforumstats_role_' + kRoles[role]));
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100164
165 let option = document.createElement('option');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100166 option.textContent =
167 this.getForumOptionString(forumData.forumTitle, additionalLabels);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100168 option.value = forumData.id;
169 if (hasPosted)
170 select.append(option);
171 else
172 noPostsGroup.append(option);
173 }
174 if (noPostsGroupFlag) select.append(noPostsGroup);
175 select.addEventListener('change', e => {
176 let forumId = e.target.value;
177 this.injectChart(forumId);
178 });
179
180 div.append(select);
181 return div;
182 }
183
184 injectChart(forumId) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100185 let data = this.getAplosData(forumId);
186 let metadata = {
187 activities: [],
188 finalMonth: undefined,
189 locale: this.locale,
190 shouldDisableTransitions: true,
191 };
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100192 let chartTitle = chrome.i18n.getMessage('inject_perforumstats_chart_label');
193 const message = {
194 action: 'renderProfileActivityChart',
195 prefix: 'TWPT-extrainfo',
196 data,
197 metadata,
198 chartTitle,
199 };
200 window.postMessage(message, '*');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100201 }
202}