Skip to content

Commit d006340

Browse files
ktranDevtools-frontend LUCI CQ
authored andcommitted
[GM3Restyling] Update EmptyWidget headlines for the Application panel
Previously, selected tabs in the application panel had a static headline. Since we are now differentiating between e.g. having cookies and no cookies, we need to allow for switching the headline. Screenshot: https://imgur.com/a/0hXKQy1 Bug:325443331 Change-Id: Ib3f909477d42e997b5ae01184e33d2da2f991432 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6170725 Commit-Queue: Kim-Anh Tran <[email protected]> Reviewed-by: Kateryna Prokopenko <[email protected]>
1 parent db5324b commit d006340

File tree

7 files changed

+104
-30
lines changed

7 files changed

+104
-30
lines changed

front_end/panels/application/ApplicationPanelSidebar.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ const UIStrings = {
9898
*@description Text in Application Panel Sidebar of the Application panel
9999
*/
100100
storage: 'Storage',
101+
/**
102+
*@description Text in Application Panelthat shows if no local storage
103+
* can be shown.
104+
*/
105+
noLocalStorage: 'No local storage detected',
101106
/**
102107
*@description Text in Application Panel Sidebar of the Application panel
103108
*/
@@ -106,10 +111,18 @@ const UIStrings = {
106111
*@description Text in Application Panel Sidebar of the Application panel
107112
*/
108113
sessionStorage: 'Session storage',
114+
/**
115+
*@description Text in Application Panel if no session storage can be shown.
116+
*/
117+
noSessionStorage: 'No session storage detected',
109118
/**
110119
*@description Text in Application Panel Sidebar of the Application panel
111120
*/
112121
extensionStorage: 'Extension storage',
122+
/**
123+
*@description Text in Application Panel if no extension storage can be shown
124+
*/
125+
noExtensionStorage: 'No extension storage detected',
113126
/**
114127
*@description Text for extension session storage in Application panel
115128
*/
@@ -130,6 +143,10 @@ const UIStrings = {
130143
*@description Text for web cookies
131144
*/
132145
cookies: 'Cookies',
146+
/**
147+
*@description Text in Application Panel Sidebar if no cookies are set
148+
*/
149+
noCookies: 'No cookies set',
133150
/**
134151
*@description Text in Application Panel Sidebar of the Application panel
135152
*/
@@ -154,6 +171,10 @@ const UIStrings = {
154171
*@description Text in Application Panel Sidebar of the Application panel
155172
*/
156173
indexeddb: 'IndexedDB',
174+
/**
175+
*@description Text in Application Panel if no indexedDB is detected
176+
*/
177+
noIndexeddb: 'No indexedDB detected',
157178
/**
158179
*@description A context menu item in the Application Panel Sidebar of the Application panel
159180
*/
@@ -344,17 +365,17 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
344365

345366
const storageSectionTitle = i18nString(UIStrings.storage);
346367
const storageTreeElement = this.addSidebarSection(storageSectionTitle, 'storage');
347-
this.localStorageListTreeElement =
348-
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.localStorage), 'local-storage');
368+
this.localStorageListTreeElement = new ExpandableApplicationPanelTreeElement(
369+
panel, i18nString(UIStrings.localStorage), i18nString(UIStrings.noLocalStorage), '', 'local-storage');
349370
this.localStorageListTreeElement.setLink(
350371
'https://developer.chrome.com/docs/devtools/storage/localstorage/?utm_source=devtools' as
351372
Platform.DevToolsPath.UrlString);
352373
const localStorageIcon = IconButton.Icon.create('table');
353374
this.localStorageListTreeElement.setLeadingIcons([localStorageIcon]);
354375

355376
storageTreeElement.appendChild(this.localStorageListTreeElement);
356-
this.sessionStorageListTreeElement =
357-
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.sessionStorage), 'session-storage');
377+
this.sessionStorageListTreeElement = new ExpandableApplicationPanelTreeElement(
378+
panel, i18nString(UIStrings.sessionStorage), i18nString(UIStrings.noSessionStorage), '', 'session-storage');
358379
this.sessionStorageListTreeElement.setLink(
359380
'https://developer.chrome.com/docs/devtools/storage/sessionstorage/?utm_source=devtools' as
360381
Platform.DevToolsPath.UrlString);
@@ -363,8 +384,9 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
363384

364385
storageTreeElement.appendChild(this.sessionStorageListTreeElement);
365386

366-
this.extensionStorageListTreeElement =
367-
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.extensionStorage), 'extension-storage');
387+
this.extensionStorageListTreeElement = new ExpandableApplicationPanelTreeElement(
388+
panel, i18nString(UIStrings.extensionStorage), i18nString(UIStrings.noExtensionStorage), '',
389+
'extension-storage');
368390
this.extensionStorageListTreeElement.setLink(
369391
'https://developer.chrome.com/docs/extensions/reference/api/storage/?utm_source=devtools' as
370392
Platform.DevToolsPath.UrlString);
@@ -379,8 +401,8 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.Targe
379401
Platform.DevToolsPath.UrlString);
380402
storageTreeElement.appendChild(this.indexedDBListTreeElement);
381403

382-
this.cookieListTreeElement =
383-
new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.cookies), 'cookies');
404+
this.cookieListTreeElement = new ExpandableApplicationPanelTreeElement(
405+
panel, i18nString(UIStrings.cookies), i18nString(UIStrings.noCookies), '', 'cookies');
384406
this.cookieListTreeElement.setLink(
385407
'https://developer.chrome.com/docs/devtools/storage/cookies/?utm_source=devtools' as
386408
Platform.DevToolsPath.UrlString);
@@ -1235,7 +1257,7 @@ export class IndexedDBTreeElement extends ExpandableApplicationPanelTreeElement
12351257
private idbDatabaseTreeElements: IDBDatabaseTreeElement[];
12361258
private storageBucket?: Protocol.Storage.StorageBucket;
12371259
constructor(storagePanel: ResourcesPanel, storageBucket?: Protocol.Storage.StorageBucket) {
1238-
super(storagePanel, i18nString(UIStrings.indexeddb), 'indexed-db');
1260+
super(storagePanel, i18nString(UIStrings.indexeddb), i18nString(UIStrings.noIndexeddb), '', 'indexed-db');
12391261
const icon = IconButton.Icon.create('database');
12401262
this.setLeadingIcons([icon]);
12411263
this.idbDatabaseTreeElements = [];
@@ -1861,7 +1883,11 @@ export class StorageCategoryView extends UI.Widget.VBox {
18611883
this.emptyWidget.show(this.element);
18621884
}
18631885

1864-
setHeader(header: string): void {
1886+
setText(text: string): void {
1887+
this.emptyWidget.text = text;
1888+
}
1889+
1890+
setHeadline(header: string): void {
18651891
this.emptyWidget.header = header;
18661892
}
18671893

@@ -2236,7 +2262,8 @@ export class FrameTreeElement extends ApplicationPanelTreeElement {
22362262
resourceType === Common.ResourceType.resourceTypes.Document ? this : this.categoryElements.get(categoryName);
22372263
if (!categoryElement) {
22382264
categoryElement = new ExpandableApplicationPanelTreeElement(
2239-
this.section.panel, resource.resourceType().category().title(), categoryName, categoryName === 'Frames');
2265+
this.section.panel, resource.resourceType().category().title(), '', '', categoryName,
2266+
categoryName === 'Frames');
22402267
this.categoryElements.set(resourceType.name(), categoryElement);
22412268
this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);
22422269
}
@@ -2250,7 +2277,7 @@ export class FrameTreeElement extends ApplicationPanelTreeElement {
22502277
let categoryElement = this.categoryElements.get(categoryKey);
22512278
if (!categoryElement) {
22522279
categoryElement = new ExpandableApplicationPanelTreeElement(
2253-
this.section.panel, i18nString(UIStrings.openedWindows), categoryKey);
2280+
this.section.panel, i18nString(UIStrings.openedWindows), '', '', categoryKey);
22542281
this.categoryElements.set(categoryKey, categoryElement);
22552282
this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);
22562283
}
@@ -2267,7 +2294,8 @@ export class FrameTreeElement extends ApplicationPanelTreeElement {
22672294
i18nString(UIStrings.webWorkers);
22682295
let categoryElement = this.categoryElements.get(categoryKey);
22692296
if (!categoryElement) {
2270-
categoryElement = new ExpandableApplicationPanelTreeElement(this.section.panel, categoryName, categoryKey);
2297+
categoryElement =
2298+
new ExpandableApplicationPanelTreeElement(this.section.panel, categoryName, '', '', categoryKey);
22712299
this.categoryElements.set(categoryKey, categoryElement);
22722300
this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);
22732301
}
@@ -2364,7 +2392,6 @@ export class FrameResourceTreeElement extends ApplicationPanelTreeElement {
23642392
if (view) {
23652393
return view;
23662394
}
2367-
23682395
return new UI.EmptyWidget.EmptyWidget('', this.resource.url);
23692396
});
23702397
return this.previewPromise;
@@ -2373,7 +2400,7 @@ export class FrameResourceTreeElement extends ApplicationPanelTreeElement {
23732400
override onselect(selectedByUser?: boolean): boolean {
23742401
super.onselect(selectedByUser);
23752402
if (this.resource.isGenerated) {
2376-
this.panel.showCategoryView(i18nString(UIStrings.theContentOfThisDocumentHasBeen), null);
2403+
this.panel.showCategoryView(i18nString(UIStrings.theContentOfThisDocumentHasBeen), '', '', null);
23772404
} else {
23782405
void this.panel.scheduleShowView(this.preparePreview());
23792406
}

front_end/panels/application/ApplicationPanelTreeElement.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,21 @@ export class ExpandableApplicationPanelTreeElement extends ApplicationPanelTreeE
5555
protected readonly categoryName: string;
5656
protected categoryLink: Platform.DevToolsPath.UrlString|null;
5757

58-
constructor(resourcesPanel: ResourcesPanel, categoryName: string, settingsKey: string, settingsDefault = false) {
58+
// These strings are used for the empty state in each top most tree element
59+
// in the Application Panel.
60+
protected emptyCategoryHeadline: string;
61+
protected categoryDescription: string;
62+
63+
constructor(
64+
resourcesPanel: ResourcesPanel, categoryName: string, emptyCategoryHeadline: string, categoryDescription: string,
65+
settingsKey: string, settingsDefault = false) {
5966
super(resourcesPanel, categoryName, false, settingsKey);
6067
this.expandedSetting =
6168
Common.Settings.Settings.instance().createSetting('resources-' + settingsKey + '-expanded', settingsDefault);
6269
this.categoryName = categoryName;
6370
this.categoryLink = null;
71+
this.emptyCategoryHeadline = emptyCategoryHeadline;
72+
this.categoryDescription = categoryDescription;
6473
}
6574

6675
override get itemURL(): Platform.DevToolsPath.UrlString {
@@ -73,10 +82,33 @@ export class ExpandableApplicationPanelTreeElement extends ApplicationPanelTreeE
7382

7483
override onselect(selectedByUser: boolean|undefined): boolean {
7584
super.onselect(selectedByUser);
76-
this.resourcesPanel.showCategoryView(this.categoryName, this.categoryLink);
85+
this.updateCategoryView();
7786
return false;
7887
}
7988

89+
private updateCategoryView(): void {
90+
const headline = this.childCount() === 0 ? this.emptyCategoryHeadline : this.categoryName;
91+
this.resourcesPanel.showCategoryView(this.categoryName, headline, this.categoryDescription, this.categoryLink);
92+
}
93+
94+
override appendChild(
95+
child: UI.TreeOutline.TreeElement,
96+
comparator?: ((arg0: UI.TreeOutline.TreeElement, arg1: UI.TreeOutline.TreeElement) => number)|undefined): void {
97+
super.appendChild(child, comparator);
98+
// Only update if relevant (changing from 0 to 1 child).
99+
if (this.selected && this.childCount() === 1) {
100+
this.updateCategoryView();
101+
}
102+
}
103+
104+
override removeChild(child: UI.TreeOutline.TreeElement): void {
105+
super.removeChild(child);
106+
// Only update if relevant (changing to 0 children).
107+
if (this.selected && this.childCount() === 0) {
108+
this.updateCategoryView();
109+
}
110+
}
111+
80112
override onattach(): void {
81113
super.onattach();
82114
if (this.expandedSetting.get()) {

front_end/panels/application/PreloadingTreeElement.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export class PreloadingSummaryTreeElement extends ExpandableApplicationPanelTree
9292
#attempt: PreloadingAttemptTreeElement|null = null;
9393

9494
constructor(panel: ResourcesPanel) {
95-
super(panel, i18nString(UIStrings.speculativeLoads), 'preloading');
95+
super(panel, i18nString(UIStrings.speculativeLoads), '', '', 'preloading');
9696

9797
const icon = IconButton.Icon.create('arrow-up-down');
9898
this.setLeadingIcons([icon]);
@@ -103,7 +103,7 @@ export class PreloadingSummaryTreeElement extends ExpandableApplicationPanelTree
103103

104104
// Note that
105105
//
106-
// - TreeElement.ensureSelection assumes TreeElement.treeOutline initalized.
106+
// - TreeElement.ensureSelection assumes TreeElement.treeOutline initialized.
107107
// - TreeElement.treeOutline is propagated in TreeElement.appendChild.
108108
//
109109
// So, `this.constructChildren` should be called just after `parent.appendChild(this)`

front_end/panels/application/ResourcesPanel.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
3333
private domStorageView: DOMStorageItemsView|null;
3434
private extensionStorageView: ExtensionStorageItemsView|null;
3535
private cookieView: CookieItemsView|null;
36-
private readonly emptyWidget: UI.EmptyWidget.EmptyWidget|null;
3736
private readonly sidebar: ApplicationPanelSidebar;
3837

3938
private constructor() {
@@ -59,8 +58,6 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
5958

6059
this.cookieView = null;
6160

62-
this.emptyWidget = null;
63-
6461
this.sidebar = new ApplicationPanelSidebar(this);
6562
this.sidebar.show(this.panelSidebarElement());
6663
}
@@ -144,13 +141,16 @@ export class ResourcesPanel extends UI.Panel.PanelWithSidebar {
144141
return view;
145142
}
146143

147-
showCategoryView(categoryName: string, categoryLink: Platform.DevToolsPath.UrlString|null): void {
144+
showCategoryView(
145+
categoryName: string, categoryHeadline: string, categoryDescription: string,
146+
categoryLink: Platform.DevToolsPath.UrlString|null): void {
148147
if (!this.categoryView) {
149148
this.categoryView = new StorageCategoryView();
150149
}
151150
this.categoryView.element.setAttribute(
152151
'jslog', `${VisualLogging.pane().context(Platform.StringUtilities.toKebabCase(categoryName))}`);
153-
this.categoryView.setHeader(categoryName);
152+
this.categoryView.setHeadline(categoryHeadline);
153+
this.categoryView.setText(categoryDescription);
154154
this.categoryView.setLink(categoryLink);
155155
this.showView(this.categoryView);
156156
}

front_end/panels/application/ServiceWorkerCacheTreeElement.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ const UIStrings = {
2020
*@description Text in Application Panel Sidebar of the Application panel
2121
*/
2222
cacheStorage: 'Cache storage',
23+
/**
24+
*@description Text in Application Panel if no cache storage was detected.
25+
*/
26+
noCacheStorage: 'No cache storage detected',
2327
/**
2428
*@description A context menu item in the Application Panel Sidebar of the Application panel
2529
*/
@@ -37,7 +41,8 @@ export class ServiceWorkerCacheTreeElement extends ExpandableApplicationPanelTre
3741
private storageBucket?: Protocol.Storage.StorageBucket;
3842

3943
constructor(resourcesPanel: ResourcesPanel, storageBucket?: Protocol.Storage.StorageBucket) {
40-
super(resourcesPanel, i18nString(UIStrings.cacheStorage), 'cache-storage');
44+
super(
45+
resourcesPanel, i18nString(UIStrings.cacheStorage), i18nString(UIStrings.noCacheStorage), '', 'cache-storage');
4146
const icon = IconButton.Icon.create('database');
4247
this.setLink(
4348
'https://developer.chrome.com/docs/devtools/storage/cache/?utm_source=devtools' as

front_end/panels/application/StorageBucketsTreeElement.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,17 @@ import {ServiceWorkerCacheTreeElement} from './ServiceWorkerCacheTreeElement.js'
2020
const UIStrings = {
2121
/**
2222
*@description Label for an item in the Application Panel Sidebar of the Application panel
23-
* Storage Buckets allow developers to seperate site data into buckets so that they can be
23+
* Storage Buckets allow developers to separate site data into buckets so that they can be
2424
* deleted independently.
2525
*/
2626
storageBuckets: 'Storage buckets',
27+
/**
28+
*@description Text for an item in the Application Panel
29+
* if no storage buckets are available to show. Storage Buckets allow developers to separate
30+
* site data into buckets so that they can be
31+
* deleted independently. https://developer.chrome.com/docs/web-platform/storage-buckets.
32+
*/
33+
noStorageBuckets: 'No storage buckets detected',
2734
};
2835
const str_ = i18n.i18n.registerUIStrings('panels/application/StorageBucketsTreeElement.ts', UIStrings);
2936
export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -32,7 +39,9 @@ export class StorageBucketsTreeParentElement extends ExpandableApplicationPanelT
3239
private bucketTreeElements: Set<StorageBucketsTreeElement> = new Set();
3340

3441
constructor(storagePanel: ResourcesPanel) {
35-
super(storagePanel, i18nString(UIStrings.storageBuckets), 'storage-buckets');
42+
super(
43+
storagePanel, i18nString(UIStrings.storageBuckets), i18nString(UIStrings.noStorageBuckets), '',
44+
'storage-buckets');
3645
const icon = IconButton.Icon.create('database');
3746
this.setLeadingIcons([icon]);
3847
this.setLink(
@@ -134,7 +143,7 @@ export class StorageBucketsTreeElement extends ExpandableApplicationPanelTreeEle
134143
bucketInfo: Protocol.Storage.StorageBucketInfo) {
135144
const {bucket} = bucketInfo;
136145
const {origin} = SDK.StorageKeyManager.parseStorageKey(bucketInfo.bucket.storageKey);
137-
super(resourcesPanel, `${bucket.name} - ${origin}`, 'storage-bucket');
146+
super(resourcesPanel, `${bucket.name} - ${origin}`, '', '', 'storage-bucket');
138147
this.bucketModel = model;
139148
this.storageBucketInfo = bucketInfo;
140149
const icon = IconButton.Icon.create('database');

front_end/ui/legacy/EmptyWidget.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,14 @@ export class EmptyWidget extends VBox {
5757
this.contentElement.setAttribute('jslog', `${VisualLogging.section('empty-view')}`);
5858
this.#headerElement = this.contentElement.createChild('div', 'header');
5959
this.#headerElement.textContent = header;
60-
this.#textElement = this.contentElement.createChild('div', 'description');
60+
this.#textElement = this.contentElement.createChild('div', 'description').createChild('span');
6161
this.#textElement.textContent = text;
6262
}
6363

6464
appendLink(link: Platform.DevToolsPath.UrlString): HTMLElement {
6565
const learnMoreLink = XLink.create(link, i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more');
66-
return this.#textElement.appendChild(learnMoreLink) as HTMLElement;
66+
this.#textElement.insertAdjacentElement('afterend', learnMoreLink);
67+
return learnMoreLink;
6768
}
6869

6970
set text(text: string) {

0 commit comments

Comments
 (0)