blob: 3e6bf665d024b5509cd0938267194954ac9e04a0 [file] [log] [blame]
Patrick Hulcea087f622018-05-18 00:37:531// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tim van der Lippe76961572021-04-06 10:48:075import * as Common from '../../core/common/common.js';
Tim van der Lippebb352e62021-04-01 17:57:286import * as i18n from '../../core/i18n/i18n.js';
Tim van der Lippeaa61faf2021-04-07 15:32:077import * as UI from '../../ui/legacy/legacy.js';
Paul Lewisdaac1062020-03-05 14:37:108
Tim van der Lippe5f62c6f2021-02-25 16:39:269import type * as ReportRenderer from './LighthouseReporterTypes.js';
Tim van der Lippe1e10f852020-10-30 14:35:0110
Simon Zünd6f95e842021-03-01 07:41:5511const UIStrings = {
vidorteg06840022020-11-21 05:18:0312 /**
Jack Franklinfd72c072022-12-21 11:45:0113 *@description Title of combo box in audits report selector
14 */
vidorteg06840022020-11-21 05:18:0315 reports: 'Reports',
16 /**
Jack Franklinfd72c072022-12-21 11:45:0117 *@description New report item label in Lighthouse Report Selector
18 */
vidorteg06840022020-11-21 05:18:0319 newReport: '(new report)',
Ergun Erdogmus5efc7e92025-02-21 11:36:5020} as const;
Tim van der Lippe7a077eb2021-03-23 18:02:1121const str_ = i18n.i18n.registerUIStrings('panels/lighthouse/LighthouseReportSelector.ts', UIStrings);
vidorteg06840022020-11-21 05:18:0322const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
Paul Lewis51474192020-01-09 16:02:2223export class ReportSelector {
Jan Scheffler9d4136d2021-08-10 10:55:0424 private readonly renderNewLighthouseView: () => void;
25 private newLighthouseItem: HTMLOptionElement;
26 private readonly comboBoxInternal: UI.Toolbar.ToolbarComboBox;
27 private readonly itemByOptionElement: Map<Element, Item>;
Jan Schefflerc5a400f2021-01-22 16:41:4728
29 constructor(renderNewLighthouseView: () => void) {
Jan Scheffler9d4136d2021-08-10 10:55:0430 this.renderNewLighthouseView = renderNewLighthouseView;
31 this.newLighthouseItem = document.createElement('option');
32 this.comboBoxInternal = new UI.Toolbar.ToolbarComboBox(
33 this.handleChange.bind(this), i18nString(UIStrings.reports), 'lighthouse-report');
34 this.comboBoxInternal.setMaxWidth(180);
35 this.comboBoxInternal.setMinWidth(140);
36 this.itemByOptionElement = new Map();
37 this.setEmptyState();
Patrick Hulcea087f622018-05-18 00:37:5338 }
39
Jan Scheffler9d4136d2021-08-10 10:55:0440 private setEmptyState(): void {
Benedikt Meurer56e8db42025-01-17 13:27:5441 this.comboBoxInternal.removeOptions();
Patrick Hulcea087f622018-05-18 00:37:5342
Jan Scheffler9d4136d2021-08-10 10:55:0443 this.comboBoxInternal.setEnabled(false);
44 this.newLighthouseItem = document.createElement('option');
45 this.newLighthouseItem.label = i18nString(UIStrings.newReport);
Benedikt Meurer56e8db42025-01-17 13:27:5446 this.comboBoxInternal.addOption(this.newLighthouseItem);
Jan Scheffler9d4136d2021-08-10 10:55:0447 this.comboBoxInternal.select(this.newLighthouseItem);
Patrick Hulcea087f622018-05-18 00:37:5348 }
49
Jan Scheffler9d4136d2021-08-10 10:55:0450 private handleChange(_event: Event): void {
51 const item = this.selectedItem();
Tim van der Lippe1d6e57a2019-09-30 11:55:3452 if (item) {
Patrick Hulcea087f622018-05-18 00:37:5353 item.select();
Tim van der Lippe1d6e57a2019-09-30 11:55:3454 } else {
Jan Scheffler9d4136d2021-08-10 10:55:0455 this.renderNewLighthouseView();
Tim van der Lippe1d6e57a2019-09-30 11:55:3456 }
Patrick Hulcea087f622018-05-18 00:37:5357 }
58
Jan Scheffler9d4136d2021-08-10 10:55:0459 private selectedItem(): Item {
60 const option = this.comboBoxInternal.selectedOption();
61 return this.itemByOptionElement.get(option as Element) as Item;
Patrick Hulcea087f622018-05-18 00:37:5362 }
63
Jan Schefflerc5a400f2021-01-22 16:41:4764 hasItems(): boolean {
Jan Scheffler9d4136d2021-08-10 10:55:0465 return this.itemByOptionElement.size > 0;
Patrick Hulcea087f622018-05-18 00:37:5366 }
67
Jan Schefflerc5a400f2021-01-22 16:41:4768 comboBox(): UI.Toolbar.ToolbarComboBox {
Jan Scheffler9d4136d2021-08-10 10:55:0469 return this.comboBoxInternal;
Patrick Hulcea087f622018-05-18 00:37:5370 }
71
Jan Schefflerc5a400f2021-01-22 16:41:4772 prepend(item: Item): void {
Patrick Hulcea087f622018-05-18 00:37:5373 const optionEl = item.optionElement();
Benedikt Meurer56e8db42025-01-17 13:27:5474 const selectEl = this.comboBoxInternal.element;
Patrick Hulcea087f622018-05-18 00:37:5375
Jan Scheffler9d4136d2021-08-10 10:55:0476 this.itemByOptionElement.set(optionEl, item);
Patrick Hulcea087f622018-05-18 00:37:5377 selectEl.insertBefore(optionEl, selectEl.firstElementChild);
Jan Scheffler9d4136d2021-08-10 10:55:0478 this.comboBoxInternal.setEnabled(true);
79 this.comboBoxInternal.select(optionEl);
Patrick Hulcea087f622018-05-18 00:37:5380 item.select();
81 }
82
Jan Schefflerc5a400f2021-01-22 16:41:4783 clearAll(): void {
Jan Scheffler9d4136d2021-08-10 10:55:0484 for (const elem of this.comboBoxInternal.options()) {
85 if (elem === this.newLighthouseItem) {
Patrick Hulcea087f622018-05-18 00:37:5386 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:3487 }
Patrick Hulcea087f622018-05-18 00:37:5388
Jan Scheffler9d4136d2021-08-10 10:55:0489 this.itemByOptionElement.get(elem)?.delete();
90 this.itemByOptionElement.delete(elem);
Patrick Hulcea087f622018-05-18 00:37:5391 }
92
Jan Scheffler9d4136d2021-08-10 10:55:0493 this.setEmptyState();
Patrick Hulcea087f622018-05-18 00:37:5394 }
95
Jan Schefflerc5a400f2021-01-22 16:41:4796 selectNewReport(): void {
Jan Scheffler9d4136d2021-08-10 10:55:0497 this.comboBoxInternal.select(this.newLighthouseItem);
Patrick Hulcea087f622018-05-18 00:37:5398 }
Paul Lewiscf2ef222019-11-22 14:55:3599}
Patrick Hulcea087f622018-05-18 00:37:53100
Paul Lewiscf2ef222019-11-22 14:55:35101export class Item {
Jan Scheffler9d4136d2021-08-10 10:55:04102 private readonly renderReport: () => void;
103 private readonly showLandingCallback: () => void;
104 private readonly element: HTMLOptionElement;
Jan Schefflerc5a400f2021-01-22 16:41:47105
106 constructor(lighthouseResult: ReportRenderer.ReportJSON, renderReport: () => void, showLandingCallback: () => void) {
Jan Scheffler9d4136d2021-08-10 10:55:04107 this.renderReport = renderReport;
108 this.showLandingCallback = showLandingCallback;
Patrick Hulcea087f622018-05-18 00:37:53109
Adam Raine393209c2022-09-21 23:38:50110 // In Lighthouse 10.0, `finalUrl` is not provided on snapshot or timespan reports.
111 // `finalDisplayedUrl` is the new preferred URL to use for cosmetic identification.
112 // TODO: Remove the `finalUrl` backport once Lighthouse 10.0 is rolled into DevTools.
113 const finalDisplayedUrl = lighthouseResult.finalDisplayedUrl || lighthouseResult.finalUrl || '';
114
115 const url = new Common.ParsedURL.ParsedURL(finalDisplayedUrl);
Paul Irish8f1e33d2018-05-31 02:29:50116 const timestamp = lighthouseResult.fetchTime;
Jan Scheffler9d4136d2021-08-10 10:55:04117 this.element = document.createElement('option');
118 this.element.label = `${new Date(timestamp).toLocaleTimeString()} - ${url.domain()}`;
Patrick Hulcea087f622018-05-18 00:37:53119 }
120
Jan Schefflerc5a400f2021-01-22 16:41:47121 select(): void {
Jan Scheffler9d4136d2021-08-10 10:55:04122 this.renderReport();
Patrick Hulcea087f622018-05-18 00:37:53123 }
124
Jan Schefflerc5a400f2021-01-22 16:41:47125 optionElement(): Element {
Jan Scheffler9d4136d2021-08-10 10:55:04126 return this.element;
Patrick Hulcea087f622018-05-18 00:37:53127 }
128
Jan Schefflerc5a400f2021-01-22 16:41:47129 delete(): void {
Jan Scheffler9d4136d2021-08-10 10:55:04130 if (this.element) {
131 this.element.remove();
Tim van der Lippe1d6e57a2019-09-30 11:55:34132 }
Jan Scheffler9d4136d2021-08-10 10:55:04133 this.showLandingCallback();
Patrick Hulcea087f622018-05-18 00:37:53134 }
Paul Lewiscf2ef222019-11-22 14:55:35135}