Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js

Issue 2851213005: DevTools: brush up audits 2 launcher UI, allow multiple audit runs, introduce landing page. (Closed)
Patch Set: for landing Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @unrestricted 6 * @unrestricted
7 */ 7 */
8 Audits2.Audits2Panel = class extends UI.Panel { 8 Audits2.Audits2Panel = class extends UI.PanelWithSidebar {
9 constructor() { 9 constructor() {
10 super('audits2'); 10 super('audits2');
11 this.setHideOnDetach(); 11 this.setHideOnDetach();
12 this.registerRequiredCSS('audits2/audits2Panel.css'); 12 this.registerRequiredCSS('audits2/audits2Panel.css');
13 this.registerRequiredCSS('audits2/lighthouse/report-styles.css'); 13 this.registerRequiredCSS('audits2/lighthouse/report-styles.css');
14 14
15 this._protocolService = new Audits2.ProtocolService(); 15 this._protocolService = new Audits2.ProtocolService();
16 this._protocolService.registerStatusCallback(msg => this._updateStatus(Commo n.UIString(msg))); 16 this._protocolService.registerStatusCallback(msg => this._updateStatus(Commo n.UIString(msg)));
17 17
18 this._settings = Audits2.Audits2Panel.Presets.map(preset => { 18 var toolbar = new UI.Toolbar('', this.panelSidebarElement());
19 const setting = Common.settings.createSetting(preset.id, true);
20 setting.setTitle(Common.UIString(preset.description));
21 return setting;
22 });
23 19
24 var auditsViewElement = this.contentElement.createChild('div', 'hbox audits2 -view'); 20 var newButton = new UI.ToolbarButton(Common.UIString('New audit\u2026'), 'la rgeicon-add');
25 this._resultsView = this.contentElement.createChild('div', 'vbox results-vie w'); 21 toolbar.appendToolbarItem(newButton);
26 this._createLauncherUI(auditsViewElement); 22 newButton.addEventListener(UI.ToolbarButton.Events.Click, this._showLauncher UI.bind(this));
23
24 var deleteButton = new UI.ToolbarButton(Common.UIString('Delete audit'), 'la rgeicon-delete');
25 toolbar.appendToolbarItem(deleteButton);
26 deleteButton.addEventListener(UI.ToolbarButton.Events.Click, this._deleteSel ected.bind(this));
27
28 toolbar.appendSeparator();
29
30 var clearButton = new UI.ToolbarButton(Common.UIString('Clear all'), 'largei con-clear');
31 toolbar.appendToolbarItem(clearButton);
32 clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._clearAll.b ind(this));
33
34 this._treeOutline = new UI.TreeOutlineInShadow();
35 this._treeOutline.registerRequiredCSS('audits2/lighthouse/report-styles.css' );
36 this._treeOutline.registerRequiredCSS('audits2/audits2Tree.css');
37 this.panelSidebarElement().appendChild(this._treeOutline.element);
38
39 this._dropTarget = new UI.DropTarget(
40 this.contentElement, [UI.DropTarget.Types.Files],
41 Common.UIString('Drop audit file here'), this._handleDrop.bind(this));
42
43 this._showLandingPage();
27 } 44 }
28 45
29 _reset() { 46 _clearAll() {
30 this.contentElement.classList.remove('show-results'); 47 this._treeOutline.removeChildren();
31 this._resultsView.removeChildren(); 48 if (!this._treeOutline.rootElement().childCount())
49 this._showLandingPage();
32 } 50 }
33 51
34 /** 52 _deleteSelected() {
35 * @param {!Element} auditsViewElement 53 var selection = this._treeOutline.selectedTreeElement;
36 */ 54 if (selection)
37 _createLauncherUI(auditsViewElement) { 55 this._treeOutline.removeChild(selection);
38 auditsViewElement.createChild('div', 'audits2-logo'); 56 if (!this._treeOutline.rootElement().childCount())
57 this._showLandingPage();
58 }
59
60 _showLandingPage() {
61 this.mainElement().removeChildren();
62 var landingPage = this.mainElement().createChild('div', 'vbox audits2-landin g-page');
63 var landingCenter = landingPage.createChild('div', 'vbox audits2-landing-cen ter');
64 landingCenter.createChild('div', 'audits2-logo');
65 var text = landingCenter.createChild('div', 'audits2-landing-text');
66 text.createChild('span', 'audits2-landing-bold-text').textContent = Common.U IString('Audits');
67 text.createChild('span').textContent = Common.UIString(' help you identify a nd fix common problems that affect' +
68 ' your site\'s performance, accessibility, and user experience. ');
69 var link = text.createChild('span', 'link');
70 link.textContent = Common.UIString('Learn more');
71 link.addEventListener(
72 'click', () => InspectorFrontendHost.openInNewTab('https://developers.go ogle.com/web/tools/lighthouse/'));
73
74 var newButton = UI.createTextButton(
75 Common.UIString('Perform an audit\u2026'), this._showLauncherUI.bind(thi s), 'material-button default');
76 landingCenter.appendChild(newButton);
77 }
78
79 _showLauncherUI() {
80 this._dialog = new UI.Dialog();
81 this._dialog.setOutsideClickCallback(event => event.consume(true));
82 var root = UI.createShadowRootWithCoreStyles(this._dialog.contentElement, 'a udits2/audits2Dialog.css');
83 var auditsViewElement = root.createChild('div', 'audits2-view');
39 var uiElement = auditsViewElement.createChild('div'); 84 var uiElement = auditsViewElement.createChild('div');
40 var headerElement = uiElement.createChild('header'); 85 var headerElement = uiElement.createChild('header');
41 headerElement.createChild('p').textContent = Common.UIString( 86 headerElement.createChild('p').textContent = Common.UIString('Audits to perf orm');
42 'Audits will analyze the page against modern development best practices and collect useful performance metrics and diagnostics. Select audits to collect :');
43 uiElement.appendChild(headerElement); 87 uiElement.appendChild(headerElement);
44 88
45 var auditSelectorForm = uiElement.createChild('form', 'audits2-form'); 89 var auditSelectorForm = uiElement.createChild('form', 'audits2-form');
46 90
47 this._settings 91 for (var preset of Audits2.Audits2Panel.Presets) {
48 .map(setting => new UI.ToolbarSettingCheckbox(setting)) 92 preset.setting.setTitle(preset.title);
49 .forEach(checkbox => auditSelectorForm.appendChild(checkbox.element)); 93 var checkbox = new UI.ToolbarSettingCheckbox(preset.setting);
94 var row = auditSelectorForm.createChild('div', 'vbox audits2-launcher-row' );
95 row.appendChild(checkbox.element);
96 row.createChild('span', 'audits2-launcher-description dimmed').textContent = preset.description;
97 }
50 98
51 this._startButton = UI.createTextButton( 99 this._startButton =
52 Common.UIString('Audit this page'), this._startButtonClicked.bind(this), 'run-audit audit-btn'); 100 UI.createTextButton(Common.UIString('Run audit'), this._start.bind(this) , 'material-button default');
53 auditSelectorForm.appendChild(this._startButton); 101 auditSelectorForm.appendChild(this._startButton);
102 this._cancelButton = UI.createTextButton(Common.UIString('Cancel'), this._ca ncel.bind(this), 'material-button');
103 auditSelectorForm.appendChild(this._cancelButton);
54 104
55 this._statusView = this._createStatusView(uiElement); 105 this._statusView = this._createStatusView(uiElement);
106
107 this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeigh t);
108 this._dialog.setMaxContentSize(new UI.Size(600, 400));
109 this._dialog.show(this.mainElement());
110 auditsViewElement.tabIndex = 0;
111 auditsViewElement.focus();
56 } 112 }
57 113
58 /** 114 /**
59 * @param {!Element} launcherUIElement 115 * @param {!Element} launcherUIElement
60 * @return {!Element} 116 * @return {!Element}
61 */ 117 */
62 _createStatusView(launcherUIElement) { 118 _createStatusView(launcherUIElement) {
63 var statusView = launcherUIElement.createChild('div', 'audits2-status hbox h idden'); 119 var statusView = launcherUIElement.createChild('div', 'audits2-status hbox h idden');
64 this._statusIcon = statusView.createChild('span', 'icon'); 120 this._statusIcon = statusView.createChild('span', 'icon');
65 this._statusElement = statusView.createChild('p'); 121 this._statusElement = statusView.createChild('p');
66 this._updateStatus(Common.UIString('Loading...')); 122 this._updateStatus(Common.UIString('Loading...'));
67 return statusView; 123 return statusView;
68 } 124 }
69 125
70 _start() { 126 _start() {
127 this._dialog.setCloseOnEscape(false);
71 this._inspectedURL = SDK.targetManager.mainTarget().inspectedURL(); 128 this._inspectedURL = SDK.targetManager.mainTarget().inspectedURL();
72 129
73 const categoryIDs = this._settings.map(setting => { 130 var categoryIDs = [];
74 const preset = Audits2.Audits2Panel.Presets.find(preset => preset.id === s etting.name); 131 for (var preset of Audits2.Audits2Panel.Presets) {
75 return {configID: preset.configID, value: setting.get()}; 132 if (preset.setting.get())
76 }).filter(agg => !!agg.value).map(agg => agg.configID); 133 categoryIDs.push(preset.configID);
134 }
77 135
78 return Promise.resolve() 136 return Promise.resolve()
79 .then(_ => this._protocolService.attach()) 137 .then(_ => this._protocolService.attach())
80 .then(_ => { 138 .then(_ => {
81 this._auditRunning = true; 139 this._auditRunning = true;
82 this._updateButton(); 140 this._updateButton();
83 this._updateStatus(Common.UIString('Loading...')); 141 this._updateStatus(Common.UIString('Loading\u2026'));
84 }) 142 })
85 .then(_ => this._protocolService.startLighthouse(this._inspectedURL, cat egoryIDs)) 143 .then(_ => this._protocolService.startLighthouse(this._inspectedURL, cat egoryIDs))
86 .then(lighthouseResult => { 144 .then(lighthouseResult => {
87 this._finish(lighthouseResult); 145 this._finish(lighthouseResult);
88 return this._stop(); 146 return this._stop();
89 }).catch(err => { 147 })
90 if (err instanceof Error) this._renderBugReport(err); 148 .catch(err => {
149 if (err instanceof Error)
150 this._renderBugReport(err);
91 }); 151 });
92 } 152 }
93 153
94 /** 154 _hideDialog() {
95 * @param {!Event} event 155 if (!this._dialog)
96 */ 156 return;
97 _startButtonClicked(event) { 157 this._dialog.hide();
158 delete this._dialog;
159 delete this._statusView;
160 delete this._statusIcon;
161 delete this._statusElement;
162 delete this._startButton;
163 delete this._cancelButton;
164 }
165
166 _cancel() {
98 if (this._auditRunning) { 167 if (this._auditRunning) {
99 this._updateStatus(Common.UIString('Cancelling...')); 168 this._updateStatus(Common.UIString('Cancelling\u2026'));
100 this._stop(); 169 this._stop();
101 return; 170 } else {
171 this._hideDialog();
102 } 172 }
103 this._start();
104 } 173 }
105 174
106 _updateButton() { 175 _updateButton() {
107 this._startButton.textContent = 176 if (!this._dialog)
108 this._auditRunning ? Common.UIString('Cancel audit') : Common.UIString(' Audit this page'); 177 return;
109 this._startButton.classList.toggle('started', this._auditRunning); 178 this._startButton.classList.toggle('default', !this._auditRunning);
179 this._startButton.disabled = this._auditRunning;
110 this._statusView.classList.toggle('hidden', !this._auditRunning); 180 this._statusView.classList.toggle('hidden', !this._auditRunning);
111 } 181 }
112 182
113 /** 183 /**
114 * @param {string} statusMessage 184 * @param {string} statusMessage
115 */ 185 */
116 _updateStatus(statusMessage) { 186 _updateStatus(statusMessage) {
187 if (!this._dialog)
188 return;
117 this._statusElement.textContent = statusMessage; 189 this._statusElement.textContent = statusMessage;
118 } 190 }
119 191
120 /** 192 /**
121 * @return {!Promise<undefined>} 193 * @return {!Promise<undefined>}
122 */ 194 */
123 _stop() { 195 _stop() {
124 return this._protocolService.detach().then(_ => { 196 return this._protocolService.detach().then(_ => {
125 this._auditRunning = false; 197 this._auditRunning = false;
126 this._updateButton(); 198 this._updateButton();
127 var resourceTreeModel = SDK.targetManager.mainTarget().model(SDK.ResourceT reeModel); 199 var resourceTreeModel = SDK.targetManager.mainTarget().model(SDK.ResourceT reeModel);
128 if (resourceTreeModel && this._inspectedURL !== SDK.targetManager.mainTarg et().inspectedURL()) 200 if (resourceTreeModel && this._inspectedURL !== SDK.targetManager.mainTarg et().inspectedURL())
129 resourceTreeModel.navigate(this._inspectedURL); 201 resourceTreeModel.navigate(this._inspectedURL).then(() => this._hideDial og());
130 202 else
203 this._hideDialog();
131 }); 204 });
132 } 205 }
133 206
134 /** 207 /**
135 * @param {!ReportRenderer.ReportJSON} lighthouseResult 208 * @param {!ReportRenderer.ReportJSON} lighthouseResult
136 */ 209 */
137 _finish(lighthouseResult) { 210 _finish(lighthouseResult) {
138 if (lighthouseResult === null) { 211 if (lighthouseResult === null) {
139 this._updateStatus(Common.UIString('Auditing failed.')); 212 this._updateStatus(Common.UIString('Auditing failed.'));
140 return; 213 return;
141 } 214 }
142 this._resultsView.removeChildren(); 215 var treeElement = new Audits2.Audits2Panel.TreeElement(lighthouseResult, thi s.mainElement());
143 216 this._treeOutline.appendChild(treeElement);
144 var url = lighthouseResult.url; 217 treeElement._populate();
145 var timestamp = lighthouseResult.generatedTime; 218 treeElement.select();
146 this._createResultsBar(this._resultsView, url, timestamp); 219 this._hideDialog();
147 this._renderReport(this._resultsView, lighthouseResult);
148 this.contentElement.classList.add('show-results');
149 } 220 }
150 221
151 /** 222 /**
152 * @param {!Error} err 223 * @param {!Error} err
153 */ 224 */
154 _renderBugReport(err) { 225 _renderBugReport(err) {
155 console.error(err); 226 console.error(err);
156 this._statusElement.textContent = ''; 227 this._statusElement.textContent = '';
157 this._statusIcon.classList.add('error'); 228 this._statusIcon.classList.add('error');
158 this._statusElement.createTextChild(Common.UIString('We ran into an error. ' )); 229 this._statusElement.createTextChild(Common.UIString('We ran into an error. ' ));
(...skipping 13 matching lines...) Expand all
172 qsBody += '**Stack Trace**:\n ```' + err.stack + '```'; 243 qsBody += '**Stack Trace**:\n ```' + err.stack + '```';
173 var body = '&body=' + encodeURI(qsBody); 244 var body = '&body=' + encodeURI(qsBody);
174 245
175 var reportErrorEl = parentElem.createChild('a', 'audits2-link audits2-report -error'); 246 var reportErrorEl = parentElem.createChild('a', 'audits2-link audits2-report -error');
176 reportErrorEl.href = baseURI + title + body; 247 reportErrorEl.href = baseURI + title + body;
177 reportErrorEl.textContent = Common.UIString('Report this bug'); 248 reportErrorEl.textContent = Common.UIString('Report this bug');
178 reportErrorEl.target = '_blank'; 249 reportErrorEl.target = '_blank';
179 } 250 }
180 251
181 /** 252 /**
182 * @param {!Element} resultsView 253 * @param {!DataTransfer} dataTransfer
183 * @param {!ReportRenderer.ReportJSON} lighthouseResult
184 * @suppressGlobalPropertiesCheck
185 */ 254 */
186 _renderReport(resultsView, lighthouseResult) { 255 _handleDrop(dataTransfer) {
187 var reportContainer = resultsView.createChild('div', 'report-container lh-ro ot'); 256 var items = dataTransfer.items;
188 257 if (!items.length)
189 var dom = new DOM(document);
190 var detailsRenderer = new DetailsRenderer(dom);
191 var categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
192 var renderer = new Audits2.ReportRenderer(dom, categoryRenderer);
193
194 var templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.ht ml'];
195 var templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html ');
196 if (!templatesDOM)
197 return; 258 return;
198 259 var item = items[0];
199 renderer.setTemplateContext(templatesDOM); 260 if (item.kind === 'file') {
200 renderer.renderReport(lighthouseResult, reportContainer); 261 var entry = items[0].webkitGetAsEntry();
262 if (!entry.isFile)
263 return;
264 entry.file(file => {
265 var reader = new FileReader();
266 reader.onload = () => this._loadedFromFile(/** @type {string} */ (reader .result));
267 reader.readAsText(file);
268 });
269 }
201 } 270 }
202 271
203 /** 272 /**
204 * @param {!Element} resultsView 273 * @param {string} profile
205 * @param {string} url
206 * @param {string} timestamp
207 */ 274 */
208 _createResultsBar(resultsView, url, timestamp) { 275 _loadedFromFile(profile) {
209 var elem = resultsView.createChild('div', 'results-bar hbox'); 276 var data = JSON.parse(profile);
210 elem.createChild('div', 'audits2-logo audits2-logo-small'); 277 if (!data['lighthouseVersion'])
211 278 return;
212 var summaryElem = elem.createChild('div', 'audits2-summary'); 279 this._finish(/** @type {!ReportRenderer.ReportJSON} */(data));
213 var reportFor = summaryElem.createChild('span');
214 reportFor.createTextChild('Report for ');
215 var urlElem = reportFor.createChild('b');
216 urlElem.textContent = url;
217 var timeElem = summaryElem.createChild('span');
218 timeElem.textContent =
219 `Generated at ${new Date(timestamp).toLocaleDateString()} ${new Date(tim estamp).toLocaleTimeString()}`;
220
221 var newAuditButton =
222 UI.createTextButton(Common.UIString('New Audit'), this._reset.bind(this) , 'new-audit audit-btn');
223 elem.appendChild(newAuditButton);
224 } 280 }
225 }; 281 };
226 282
227 /** 283 /**
228 * @override 284 * @override
229 */ 285 */
230 Audits2.ReportRenderer = class extends ReportRenderer { 286 Audits2.Audits2Panel.ReportRenderer = class extends ReportRenderer {
231 /** 287 /**
232 * Provides empty element for left nav 288 * Provides empty element for left nav
233 * @override 289 * @override
234 * @returns {!DocumentFragment} 290 * @returns {!DocumentFragment}
235 */ 291 */
236 _renderReportNav() { 292 _renderReportNav() {
237 return createDocumentFragment(); 293 return createDocumentFragment();
238 } 294 }
295
296 /**
297 * @param {!ReportRenderer.ReportJSON} report
298 * @override
299 * @return {!DocumentFragment}
300 */
301 _renderReportHeader(report) {
302 return createDocumentFragment();
303 }
239 }; 304 };
240 305
241
242 class ReportUIFeatures { 306 class ReportUIFeatures {
243 /** 307 /**
244 * @param {!ReportRenderer.ReportJSON} report 308 * @param {!ReportRenderer.ReportJSON} report
245 */ 309 */
246 initFeatures(report) {} 310 initFeatures(report) {
311 }
247 } 312 }
248 313
249 /** @typedef {{id: string, configID: string, description: string}} */ 314 /** @typedef {{setting: !Common.Setting, configID: string, title: string, descri ption: string}} */
250 Audits2.Audits2Panel.Preset; 315 Audits2.Audits2Panel.Preset;
251 316
252 /** @type {!Array.<!Audits2.Audits2Panel.Preset>} */ 317 /** @type {!Array.<!Audits2.Audits2Panel.Preset>} */
253 Audits2.Audits2Panel.Presets = [ 318 Audits2.Audits2Panel.Presets = [
254 // configID maps to Lighthouse's Object.keys(config.categories)[0] value 319 // configID maps to Lighthouse's Object.keys(config.categories)[0] value
255 {id: 'audits2_cat_pwa', configID: 'pwa', description: 'Progressive Web App'}, 320 {
256 {id: 'audits2_cat_perf', configID: 'performance', description: 'Performance me trics and diagnostics'}, 321 setting: Common.settings.createSetting('audits2.cat_pwa', true),
257 {id: 'audits2_cat_a11y', configID: 'accessibility', description: 'Accessibilit y'}, 322 configID: 'pwa',
258 {id: 'audits2_cat_best_practices', configID: 'best-practices', description: 'M odern best practices'}, 323 title: 'Progressive Web App',
324 description: 'Does this page meet the standard of a Progressive Web App'
325 },
326 {
327 setting: Common.settings.createSetting('audits2.cat_perf', true),
328 configID: 'performance',
329 title: 'Performance',
330 description: 'How long does this app take to show content and become usable'
331 },
332 {
333 setting: Common.settings.createSetting('audits2.cat_best_practices', true),
334 configID: 'best-practices',
335 title: 'Best practices',
336 description: 'Does this page follow best practices for modern web developmen t'
337 },
338 {
339 setting: Common.settings.createSetting('audits2.cat_a11y', true),
340 configID: 'accessibility',
341 title: 'Accessibility',
342 description: 'Is this page usable by people with disabilities or impairments '
343 },
259 ]; 344 ];
260 345
261 Audits2.ProtocolService = class extends Common.Object { 346 Audits2.ProtocolService = class extends Common.Object {
262 constructor() { 347 constructor() {
263 super(); 348 super();
264 /** @type {?Protocol.InspectorBackend.Connection} */ 349 /** @type {?Protocol.InspectorBackend.Connection} */
265 this._rawConnection = null; 350 this._rawConnection = null;
266 /** @type {?Services.ServiceManager.Service} */ 351 /** @type {?Services.ServiceManager.Service} */
267 this._backend = null; 352 this._backend = null;
268 /** @type {?Promise} */ 353 /** @type {?Promise} */
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 * @param {!Object=} params 415 * @param {!Object=} params
331 * @return {!Promise<!ReportRenderer.ReportJSON>} 416 * @return {!Promise<!ReportRenderer.ReportJSON>}
332 */ 417 */
333 _send(method, params) { 418 _send(method, params) {
334 if (!this._backendPromise) 419 if (!this._backendPromise)
335 this._initWorker(); 420 this._initWorker();
336 421
337 return this._backendPromise.then(_ => this._backend.send(method, params)); 422 return this._backendPromise.then(_ => this._backend.send(method, params));
338 } 423 }
339 }; 424 };
425
426 Audits2.Audits2Panel.TreeElement = class extends UI.TreeElement {
427 /**
428 * @param {!ReportRenderer.ReportJSON} lighthouseResult
429 * @param {!Element} resultsView
430 */
431 constructor(lighthouseResult, resultsView) {
432 super('', false);
433 this._lighthouseResult = lighthouseResult;
434 this._resultsView = resultsView;
435 /** @type {?Element} */
436 this._reportContainer = null;
437
438 var url = new Common.ParsedURL(lighthouseResult.url);
439 var timestamp = lighthouseResult.generatedTime;
440 var titleElement = this.titleElement();
441 titleElement.classList.add('audits2-report-tree-item');
442 titleElement.createChild('div').textContent = url.domain();
443 titleElement.createChild('span', 'dimmed').textContent = new Date(timestamp) .toLocaleString();
444 this.listItemElement.addEventListener('contextmenu', this._handleContextMenu Event.bind(this), false);
445 }
446
447 _populate() {
448 for (var category of this._lighthouseResult.reportCategories) {
449 var treeElement = new Audits2.Audits2Panel.TreeSubElement(category.id, cat egory.name, category.score);
450 this.appendChild(treeElement);
451 }
452 }
453
454 /**
455 * @override
456 * @param {boolean=} selectedByUser
457 * @return {boolean}
458 */
459 onselect(selectedByUser) {
460 this._renderReport();
461 return true;
462 }
463
464 /**
465 * @param {!Event} event
466 */
467 _handleContextMenuEvent(event) {
468 var contextMenu = new UI.ContextMenu(event);
469 contextMenu.appendItem(Common.UIString('Save as\u2026'), () => {
470 var url = new Common.ParsedURL(this._lighthouseResult.url).domain();
471 var timestamp = this._lighthouseResult.generatedTime;
472 var fileName = `${url}-${new Date(timestamp).toISO8601Compact()}.json`;
473 Workspace.fileManager.save(fileName, JSON.stringify(this._lighthouseResult ), true);
474 });
475 contextMenu.show();
476 }
477
478 /**
479 * @override
480 */
481 onunbind() {
482 if (this._reportContainer && this._reportContainer.parentElement)
483 this._reportContainer.remove();
484 }
485
486 _renderReport() {
487 this._resultsView.removeChildren();
488 if (this._reportContainer) {
489 this._resultsView.appendChild(this._reportContainer);
490 return;
491 }
492
493 this._reportContainer = this._resultsView.createChild('div', 'report-contain er lh-root');
494
495 var dom = new DOM(/** @type {!Document} */(this._resultsView.ownerDocument)) ;
496 var detailsRenderer = new DetailsRenderer(dom);
497 var categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
498 var renderer = new Audits2.Audits2Panel.ReportRenderer(dom, categoryRenderer );
499
500 var templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.ht ml'];
501 var templatesDOM = new DOMParser().parseFromString(templatesHTML, 'text/html ');
502 if (!templatesDOM)
503 return;
504
505 renderer.setTemplateContext(templatesDOM);
506 renderer.renderReport(this._lighthouseResult, this._reportContainer);
507 }
508 };
509
510 Audits2.Audits2Panel.TreeSubElement = class extends UI.TreeElement {
511 /**
512 * @param {string} id
513 * @param {string} name
514 * @param {number} score
515 */
516 constructor(id, name, score) {
517 super('');
518 this._id = id;
519 this.listItemElement.textContent = name;
520 var label = Util.calculateRating(score);
521 var subtitleElement = this.listItemElement.createChild('span', 'lh-root audi ts2-tree-subtitle-' + label);
522 subtitleElement.textContent = String(Math.round(score));
523 }
524
525 /**
526 * @override
527 * @return {boolean}
528 */
529 onselect() {
530 this.parent._renderReport();
531 var node = this.parent._resultsView.querySelector('.lh-category[id=' + this. _id + ']');
532 if (node) {
533 node.scrollIntoView(true);
534 return true;
535 }
536 return false;
537 }
538 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698