blob: 7ca0f38f866f246b1feb9668a8f975623e9f9ad1 [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 {
avm9996337601bc2022-02-21 10:36:45 +010027 constructor(existingChartSection, profile, locale, isCommunityConsole) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010028 this.locale = locale;
avm9996337601bc2022-02-21 10:36:45 +010029 this.isCommunityConsole = isCommunityConsole;
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010030 this.parseAndSetData(profile);
31 this.buildDOM(existingChartSection);
32 if (this.data.length) this.injectChart(this.data[0]?.id);
33 }
34
35 parseAndSetData(profile) {
36 const forumUserInfos = profile?.[1]?.[7] ?? [];
37 const forumTitles = profile?.[1]?.[8] ?? [];
38
39 const forumUserInfoIDs = forumUserInfos.map(ui => ui[1]);
40 const forumTitleIDs = forumTitles.map(t => t[1]);
41 const intersectionForumIDs =
42 forumUserInfoIDs.filter(id => forumTitleIDs.includes(id));
43
44 this.data = [];
45 for (const id of intersectionForumIDs) {
avm9996337601bc2022-02-21 10:36:45 +010046 const fui = forumUserInfos.find(ui => ui?.[1] === id)?.[2];
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010047 const numMessages = kDataKeys.reduce((prevVal, key) => {
48 if (!fui?.[key[0]]) return prevVal;
49 return prevVal + fui[key[0]].reduce((prevVal, userActivity) => {
50 return prevVal + (userActivity?.[3] ?? 0);
51 }, /* initialValue = */ 0);
52 }, /* initialValue = */ 0);
53 this.data.push({
54 id,
avm9996337601bc2022-02-21 10:36:45 +010055 forumTitle: forumTitles.find(t => t?.[1] === id)?.[2],
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +010056 forumUserInfo: fui,
57 numMessages,
58 });
59 }
60 this.data.sort((a, b) => {
61 // First sort by number of messages
62 if (b.numMessages > a.numMessages) return 1;
63 if (b.numMessages < a.numMessages) return -1;
64 // Then sort by name
65 return a.forumTitle.localeCompare(
66 b.forumTitle, 'en', {sensitivity: 'base'});
67 });
68 }
69
70 buildDOM(existingChartSection) {
71 let section = document.createElement('div');
72 section.classList.add('scTailwindUser_profileUserprofilesection');
73
74 let root = document.createElement('div');
75 root.classList.add(
76 'scTailwindSharedActivitychartroot',
77 'TWPT-scTailwindSharedActivitychartroot');
78
79 let title = document.createElement('h2');
80 title.classList.add('scTailwindSharedActivitycharttitle');
Adrià Vilanova Martínez4768e812022-02-01 13:41:28 +010081
avm9996337601bc2022-02-21 10:36:45 +010082 let badge, badgeTooltip;
83 if (this.isCommunityConsole) {
84 [badge, badgeTooltip] = createExtBadge();
85 } else {
86 badge = document.createElement('span');
87 badge.classList.add('TWPT-badge');
88
89 var badgeImg = document.createElement('img');
90 badgeImg.src =
91 'https://fonts.gstatic.com/s/i/materialicons/repeat/v6/24px.svg';
92
93 badge.appendChild(badgeImg);
94 }
95
Adrià Vilanova Martínez4768e812022-02-01 13:41:28 +010096 let titleText = document.createElement('span');
avm9996337601bc2022-02-21 10:36:45 +010097 titleText.textContent =
98 chrome.i18n.getMessage('inject_perforumstats_heading');
Adrià Vilanova Martínez4768e812022-02-01 13:41:28 +010099
100 title.append(badge, titleText);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100101
102 let selector = this.createForumSelector();
103
104 let chartEl = document.createElement('div');
105 chartEl.classList.add('scTailwindSharedActivitychartchart');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100106 chartEl.setAttribute('data-twpt-per-forum-chart', '');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100107
108 root.append(title, selector, chartEl);
109 section.append(root);
110 existingChartSection.after(section);
avm9996337601bc2022-02-21 10:36:45 +0100111 if (this.isCommunityConsole) new MDCTooltip(badgeTooltip);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100112 }
113
114 getAplosData(forumId) {
115 let aplosData = [];
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100116 for (const [key, name, color] of kDataKeys) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100117 let rawData = this.data.find(f => f.id === forumId)?.forumUserInfo?.[key];
118 let data;
avm9996337601bc2022-02-21 10:36:45 +0100119 if (!rawData) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100120 data = [];
avm9996337601bc2022-02-21 10:36:45 +0100121 } else {
122 // We're filtering empty strings since in the public forum there a lose
123 // conversion takes place and the first element of the array is always
124 // null, which breaks the Aplos graph rendering.
125 data =
126 rawData.map(m => JSON.stringify(Object.values(m))).filter(m => !!m);
127 }
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100128 aplosData.push({
129 color,
130 data,
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100131 label: chrome.i18n.getMessage('inject_perforumstats_chart_' + name),
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100132 name,
133 });
134 }
135 return aplosData;
136 }
137
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100138 getMessagesString(num) {
139 if (num == 1) {
140 return chrome.i18n.getMessage(
141 'inject_perforumstats_nummessages_singular');
142 }
143 return chrome.i18n.getMessage(
144 'inject_perforumstats_nummessages_plural', [num]);
145 }
146
147 getForumOptionString(forumTitle, labels) {
148 if (labels.length == 0) return forumTitle;
149 if (labels.length == 1)
150 return chrome.i18n.getMessage(
151 'inject_perforumstats_forumoption_1helper', [forumTitle, ...labels]);
152 if (labels.length == 2)
153 return chrome.i18n.getMessage(
154 'inject_perforumstats_forumoption_2helpers', [forumTitle, ...labels]);
155
156 // If labels.length > 3, this is unexpected. Here's a sensible fallback:
157 return forumTitle + ' (' + labels.join(', ') + ')';
158 }
159
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100160 createForumSelector() {
161 let div = document.createElement('div');
162 div.classList.add('TWPT-select-container');
163
164 let select = document.createElement('select');
165 let noPostsGroup;
166 let noPostsGroupFlag = false;
167 for (const forumData of this.data) {
168 const hasPosted = forumData.numMessages > 0;
169
170 if (!hasPosted && !noPostsGroupFlag) {
171 noPostsGroup = document.createElement('optgroup');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100172 noPostsGroup.label =
173 chrome.i18n.getMessage('inject_perforumstats_optgroup_notposted');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100174 noPostsGroupFlag = true;
175 }
176
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100177 let additionalLabels = [];
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100178 if (hasPosted)
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100179 additionalLabels.push(this.getMessagesString(forumData.numMessages));
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100180 let role = forumData.forumUserInfo?.[1]?.[3] ?? 0;
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100181 if (role)
182 additionalLabels.push(chrome.i18n.getMessage(
183 'inject_perforumstats_role_' + kRoles[role]));
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100184
185 let option = document.createElement('option');
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100186 option.textContent =
187 this.getForumOptionString(forumData.forumTitle, additionalLabels);
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100188 option.value = forumData.id;
189 if (hasPosted)
190 select.append(option);
191 else
192 noPostsGroup.append(option);
193 }
194 if (noPostsGroupFlag) select.append(noPostsGroup);
195 select.addEventListener('change', e => {
196 let forumId = e.target.value;
197 this.injectChart(forumId);
198 });
199
200 div.append(select);
201 return div;
202 }
203
204 injectChart(forumId) {
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100205 let data = this.getAplosData(forumId);
206 let metadata = {
207 activities: [],
208 finalMonth: undefined,
209 locale: this.locale,
210 shouldDisableTransitions: true,
211 };
Adrià Vilanova Martínez69c30502022-01-28 20:47:08 +0100212 let chartTitle = chrome.i18n.getMessage('inject_perforumstats_chart_label');
213 const message = {
214 action: 'renderProfileActivityChart',
215 prefix: 'TWPT-extrainfo',
216 data,
217 metadata,
218 chartTitle,
219 };
220 window.postMessage(message, '*');
Adrià Vilanova Martínez4f56d562022-01-26 00:23:27 +0100221 }
222}