blob: 552dece4a0d566f7734035cb7a78fc7fa05adc1d [file] [log] [blame]
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +01001// Each entry includes the following information in order:
2// - ID
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +01003// - Codename
4// - Color (for the label in the legend)
5const kDataKeys = [
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +01006 [4, 'recommended', '#34A853'],
7 [6, 'replies', '#DADCE0'],
8 [5, 'questions', '#77909D'],
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +01009];
10const kRoles = {
11 1: 'bronze',
12 2: 'silver',
13 3: 'gold',
14 4: 'platinum',
15 5: 'diamond',
16 10: 'community_manager',
17 20: 'community_specialist',
18 100: 'google_employee',
19 30: 'alumnus',
20};
21
22export default class PerForumStatsSection {
23 constructor(existingChartSection, profile, locale) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010024 this.locale = locale;
25 this.parseAndSetData(profile);
26 this.buildDOM(existingChartSection);
27 if (this.data.length) this.injectChart(this.data[0]?.id);
28 }
29
30 parseAndSetData(profile) {
31 const forumUserInfos = profile?.[1]?.[7] ?? [];
32 const forumTitles = profile?.[1]?.[8] ?? [];
33
34 const forumUserInfoIDs = forumUserInfos.map(ui => ui[1]);
35 const forumTitleIDs = forumTitles.map(t => t[1]);
36 const intersectionForumIDs =
37 forumUserInfoIDs.filter(id => forumTitleIDs.includes(id));
38
39 this.data = [];
40 for (const id of intersectionForumIDs) {
41 const fui = forumUserInfos.find(ui => ui[1] === id)?.[2];
42 const numMessages = kDataKeys.reduce((prevVal, key) => {
43 if (!fui?.[key[0]]) return prevVal;
44 return prevVal + fui[key[0]].reduce((prevVal, userActivity) => {
45 return prevVal + (userActivity?.[3] ?? 0);
46 }, /* initialValue = */ 0);
47 }, /* initialValue = */ 0);
48 this.data.push({
49 id,
50 forumTitle: forumTitles.find(t => t[1] === id)?.[2],
51 forumUserInfo: fui,
52 numMessages,
53 });
54 }
55 this.data.sort((a, b) => {
56 // First sort by number of messages
57 if (b.numMessages > a.numMessages) return 1;
58 if (b.numMessages < a.numMessages) return -1;
59 // Then sort by name
60 return a.forumTitle.localeCompare(
61 b.forumTitle, 'en', {sensitivity: 'base'});
62 });
63 }
64
65 buildDOM(existingChartSection) {
66 let section = document.createElement('div');
67 section.classList.add('scTailwindUser_profileUserprofilesection');
68
69 let root = document.createElement('div');
70 root.classList.add(
71 'scTailwindSharedActivitychartroot',
72 'TWPT-scTailwindSharedActivitychartroot');
73
74 let title = document.createElement('h2');
75 title.classList.add('scTailwindSharedActivitycharttitle');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +010076 title.textContent = chrome.i18n.getMessage('inject_perforumstats_heading');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010077
78 let selector = this.createForumSelector();
79
80 let chartEl = document.createElement('div');
81 chartEl.classList.add('scTailwindSharedActivitychartchart');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +010082 chartEl.setAttribute('data-twpt-per-forum-chart', '');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010083
84 root.append(title, selector, chartEl);
85 section.append(root);
86 existingChartSection.after(section);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010087 }
88
89 getAplosData(forumId) {
90 let aplosData = [];
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +010091 for (const [key, name, color] of kDataKeys) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010092 let rawData = this.data.find(f => f.id === forumId)?.forumUserInfo?.[key];
93 let data;
94 if (!rawData)
95 data = [];
96 else
97 data = rawData.map(m => JSON.stringify(Object.values(m)));
98 aplosData.push({
99 color,
100 data,
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100101 label: chrome.i18n.getMessage('inject_perforumstats_chart_' + name),
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100102 name,
103 });
104 }
105 return aplosData;
106 }
107
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100108 getMessagesString(num) {
109 if (num == 1) {
110 return chrome.i18n.getMessage(
111 'inject_perforumstats_nummessages_singular');
112 }
113 return chrome.i18n.getMessage(
114 'inject_perforumstats_nummessages_plural', [num]);
115 }
116
117 getForumOptionString(forumTitle, labels) {
118 if (labels.length == 0) return forumTitle;
119 if (labels.length == 1)
120 return chrome.i18n.getMessage(
121 'inject_perforumstats_forumoption_1helper', [forumTitle, ...labels]);
122 if (labels.length == 2)
123 return chrome.i18n.getMessage(
124 'inject_perforumstats_forumoption_2helpers', [forumTitle, ...labels]);
125
126 // If labels.length > 3, this is unexpected. Here's a sensible fallback:
127 return forumTitle + ' (' + labels.join(', ') + ')';
128 }
129
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100130 createForumSelector() {
131 let div = document.createElement('div');
132 div.classList.add('TWPT-select-container');
133
134 let select = document.createElement('select');
135 let noPostsGroup;
136 let noPostsGroupFlag = false;
137 for (const forumData of this.data) {
138 const hasPosted = forumData.numMessages > 0;
139
140 if (!hasPosted && !noPostsGroupFlag) {
141 noPostsGroup = document.createElement('optgroup');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100142 noPostsGroup.label =
143 chrome.i18n.getMessage('inject_perforumstats_optgroup_notposted');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100144 noPostsGroupFlag = true;
145 }
146
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100147 let additionalLabels = [];
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100148 if (hasPosted)
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100149 additionalLabels.push(this.getMessagesString(forumData.numMessages));
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100150 let role = forumData.forumUserInfo?.[1]?.[3] ?? 0;
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100151 if (role)
152 additionalLabels.push(chrome.i18n.getMessage(
153 'inject_perforumstats_role_' + kRoles[role]));
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100154
155 let option = document.createElement('option');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100156 option.textContent =
157 this.getForumOptionString(forumData.forumTitle, additionalLabels);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100158 option.value = forumData.id;
159 if (hasPosted)
160 select.append(option);
161 else
162 noPostsGroup.append(option);
163 }
164 if (noPostsGroupFlag) select.append(noPostsGroup);
165 select.addEventListener('change', e => {
166 let forumId = e.target.value;
167 this.injectChart(forumId);
168 });
169
170 div.append(select);
171 return div;
172 }
173
174 injectChart(forumId) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100175 let data = this.getAplosData(forumId);
176 let metadata = {
177 activities: [],
178 finalMonth: undefined,
179 locale: this.locale,
180 shouldDisableTransitions: true,
181 };
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100182 let chartTitle = chrome.i18n.getMessage('inject_perforumstats_chart_label');
183 const message = {
184 action: 'renderProfileActivityChart',
185 prefix: 'TWPT-extrainfo',
186 data,
187 metadata,
188 chartTitle,
189 };
190 window.postMessage(message, '*');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100191 }
192}