Skip to content

Commit b046f39

Browse files
committed
Add a top exceptions table.
1 parent 20f1cb5 commit b046f39

File tree

6 files changed

+282
-129
lines changed

6 files changed

+282
-129
lines changed

src/app.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
import { LitElement, html, css } from "lit";
66
import { customElement, state } from "lit/decorators.js";
77
import { ExceptionListEntry, BugMetaMap } from "./types";
8-
import "./exceptions-table";
8+
import "./exceptions-table/exceptions-table";
9+
import "./exceptions-table/top-exceptions-table";
910
import "./github-corner";
1011

1112
const GITHUB_URL = "https://github.com/Trikolon/url-classifier-exceptions-ui";
@@ -139,16 +140,6 @@ export class App extends LitElement {
139140
padding: 1rem 0;
140141
}
141142
142-
/* First h2 gets z-index 10 */
143-
h2:nth-of-type(1) {
144-
z-index: 10;
145-
}
146-
147-
/* Second h2 gets z-index 30 */
148-
h2:nth-of-type(2) {
149-
z-index: 30;
150-
}
151-
152143
h3 {
153144
position: sticky;
154145
top: 3rem;
@@ -157,18 +148,6 @@ export class App extends LitElement {
157148
padding: 0.5rem 0;
158149
}
159150
160-
/* First two h3s get z-index 20 */
161-
h3:nth-of-type(1),
162-
h3:nth-of-type(2) {
163-
z-index: 20;
164-
}
165-
166-
/* Last two h3s get z-index 40 */
167-
h3:nth-of-type(3),
168-
h3:nth-of-type(4) {
169-
z-index: 40;
170-
}
171-
172151
.error {
173152
color: red;
174153
}
@@ -265,9 +244,9 @@ export class App extends LitElement {
265244
exceptions resolve a lot of untracked site breakage, i.e. breakage we don't have a bug for.
266245
</p>
267246
268-
<h2>Global Exceptions</h2>
247+
<h2 style="z-index: 10;">Global Exceptions</h2>
269248
270-
<h3>Baseline</h3>
249+
<h3 style="z-index: 20;">Baseline</h3>
271250
<exceptions-table
272251
id="global-baseline"
273252
.entries=${this.records}
@@ -276,7 +255,7 @@ export class App extends LitElement {
276255
!entry.topLevelUrlPattern?.length && entry.category === "baseline"}
277256
></exceptions-table>
278257
279-
<h3>Convenience</h3>
258+
<h3 style="z-index: 30;">Convenience</h3>
280259
<exceptions-table
281260
id="global-convenience"
282261
.entries=${this.records}
@@ -285,8 +264,8 @@ export class App extends LitElement {
285264
!entry.topLevelUrlPattern?.length && entry.category === "convenience"}
286265
></exceptions-table>
287266
288-
<h2>Per-Site Exceptions</h2>
289-
<h3>Baseline</h3>
267+
<h2 style="z-index: 40;">Per-Site Exceptions</h2>
268+
<h3 style="z-index: 50;">Baseline</h3>
290269
<exceptions-table
291270
id="per-site-baseline"
292271
.entries=${this.records}
@@ -295,14 +274,25 @@ export class App extends LitElement {
295274
!!entry.topLevelUrlPattern?.length && entry.category === "baseline"}
296275
></exceptions-table>
297276
298-
<h3>Convenience</h3>
277+
<h3 style="z-index: 60;">Convenience</h3>
299278
<exceptions-table
300279
id="per-site-convenience"
301280
.entries=${this.records}
302281
.bugMeta=${this.bugMeta}
303282
.filter=${(entry: ExceptionListEntry) =>
304283
!!entry.topLevelUrlPattern?.length && entry.category === "convenience"}
305284
></exceptions-table>
285+
286+
<h3 style="z-index: 70;">Top Resources</h3>
287+
<p>
288+
This table shows the top resources that are allow-listed via site-specific exception list
289+
entries. If a resource is allow-listed under many top level sites, it can be an indicator
290+
that it should be added to the global exceptions list.
291+
</p>
292+
<top-exceptions-table
293+
.entries=${this.records}
294+
.bugMeta=${this.bugMeta}
295+
></top-exceptions-table>
306296
`;
307297
}
308298

src/exception-dialog.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import { ExceptionListEntry } from "./types";
1111
*/
1212
@customElement("exception-dialog")
1313
export class ExceptionDialog extends LitElement {
14+
// Callers can either pass a single entry or an array of entries.
1415
@property({ type: Object })
1516
entry?: ExceptionListEntry;
1617

18+
@property({ type: Array })
19+
entries?: ExceptionListEntry[];
20+
1721
static styles = css`
1822
dialog {
1923
padding: 1.5rem;
@@ -109,7 +113,9 @@ export class ExceptionDialog extends LitElement {
109113
}
110114

111115
render() {
112-
const formattedJson = JSON.stringify(this.entry, null, 2);
116+
let json = this.entry ?? this.entries;
117+
118+
const formattedJson = JSON.stringify(json, null, 2);
113119

114120
return html`
115121
<dialog @close=${this.enablePageScroll} @click=${this.onCloseButtonClick}>

src/exceptions-table.ts renamed to src/exceptions-table/exceptions-table.ts

Lines changed: 11 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
import { LitElement, html, css } from "lit";
66
import { customElement, property } from "lit/decorators.js";
7-
import { BugMetaMap, ExceptionListEntry } from "./types";
8-
import "./badge";
9-
import "./bug-label";
10-
import "./exception-dialog";
11-
import { ExceptionDialog } from "./exception-dialog";
7+
import { BugMetaMap, ExceptionListEntry } from "../types";
8+
import "../badge";
9+
import "../bug-label";
10+
import "../exception-dialog";
11+
import { ExceptionDialog } from "../exception-dialog";
12+
import tableStyles from "./table-styles.css.ts";
13+
import { capitalizeFirstChar, renderUrlPattern } from "./utils.ts";
1214

1315
/**
1416
* A table component for displaying exception list entries.
@@ -44,62 +46,9 @@ export class ExceptionsTable extends LitElement {
4446
}
4547

4648
static styles = css`
47-
.table-container {
48-
overflow-x: auto;
49-
margin: 1rem 0;
50-
border-radius: 8px;
51-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
52-
background: var(--bg-color, #fff);
53-
}
54-
table {
55-
width: 100%;
56-
border-collapse: separate;
57-
border-spacing: 0;
58-
min-width: 800px;
59-
background: inherit;
60-
}
61-
th,
62-
td {
63-
padding: 0.6em 1em;
64-
text-align: left;
65-
border-bottom: 1px solid var(--border-color, #eee);
66-
vertical-align: middle;
67-
font-size: 0.97em;
68-
}
69-
th {
70-
background: var(--bg-color, #fafbfc);
71-
color: var(--heading-color, #222);
72-
font-weight: 600;
73-
position: sticky;
74-
top: 0;
75-
z-index: 1;
76-
}
77-
tr:nth-child(even) {
78-
background: rgba(0, 0, 0, 0.02);
79-
}
80-
tr:hover {
81-
background: rgba(0, 102, 204, 0.07);
82-
transition: background 0.2s;
83-
}
84-
.hidden-col {
85-
display: none;
86-
}
87-
.badges {
88-
display: flex;
89-
flex-wrap: wrap;
90-
gap: 0.3em;
91-
}
49+
${tableStyles}
9250
`;
9351

94-
/**
95-
* Capitalizes the first character of a string.
96-
* @param str The string to capitalize.
97-
* @returns The capitalized string.
98-
*/
99-
private capitalizeFirstChar(str: string): string {
100-
return str.charAt(0).toUpperCase() + str.slice(1);
101-
}
102-
10352
/**
10453
* Renders a list of ETP badges.
10554
* @param categories The categories to render.
@@ -114,7 +63,7 @@ export class ExceptionsTable extends LitElement {
11463
return html`
11564
<span class="badges">
11665
${categories.map(
117-
(cat) => html` <ui-badge type="etp">ETP-${this.capitalizeFirstChar(cat)}</ui-badge> `,
66+
(cat) => html` <ui-badge type="etp">ETP-${capitalizeFirstChar(cat)}</ui-badge> `,
11867
)}
11968
</span>
12069
`;
@@ -166,43 +115,6 @@ export class ExceptionsTable extends LitElement {
166115
}
167116
}
168117

169-
/**
170-
* Get the host from a URL pattern using regex.
171-
* @param urlPattern The URL pattern to get the host from.
172-
* @returns The host from the URL pattern.
173-
*/
174-
private getHostFromUrlPattern(urlPattern: string): string | null {
175-
const match = urlPattern.match(/:\/\/(?:\*\.)?([^/*]+)/);
176-
177-
if (match?.length && match.length >= 2) {
178-
return match[1];
179-
}
180-
181-
console.warn("Failed to parse host from URL pattern", urlPattern);
182-
return null;
183-
}
184-
185-
/**
186-
* Renders the URL pattern for an entry.
187-
* For simplicity we show only the host part.
188-
* The full pattern is shown on hover.
189-
* @param urlPattern The URL pattern to render.
190-
* @returns The rendered URL pattern.
191-
*/
192-
private renderUrlPattern(urlPattern?: string) {
193-
if (!urlPattern) {
194-
return html`-`;
195-
}
196-
let host = this.getHostFromUrlPattern(urlPattern);
197-
198-
// If we can't parse the host, return the original URL pattern.
199-
if (host == null) {
200-
return urlPattern;
201-
}
202-
203-
return html`<span title=${urlPattern}>${host}</span>`;
204-
}
205-
206118
/**
207119
* Renders a list of bug labels for an entry.
208120
* @param entry The entry to render the bug labels for.
@@ -241,9 +153,9 @@ export class ExceptionsTable extends LitElement {
241153
<span class="badges"> ${this.renderBugLabels(entry)} </span>
242154
</td>
243155
<td class="${this.hasGlobalRules ? "" : "hidden-col"}">
244-
${this.renderUrlPattern(entry.topLevelUrlPattern)}
156+
${renderUrlPattern(entry.topLevelUrlPattern)}
245157
</td>
246-
<td>${this.renderUrlPattern(entry.urlPattern)}</td>
158+
<td>${renderUrlPattern(entry.urlPattern)}</td>
247159
<td>
248160
<span class="badges">
249161
${Array.isArray(entry.classifierFeatures)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import { css } from "lit";
6+
7+
// Common styles for all tables.
8+
export default css`
9+
.table-container {
10+
overflow-x: auto;
11+
margin: 1rem 0;
12+
border-radius: 8px;
13+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
14+
background: var(--bg-color, #fff);
15+
}
16+
table {
17+
width: 100%;
18+
border-collapse: separate;
19+
border-spacing: 0;
20+
min-width: 800px;
21+
background: inherit;
22+
}
23+
th,
24+
td {
25+
padding: 0.6em 1em;
26+
text-align: left;
27+
border-bottom: 1px solid var(--border-color, #eee);
28+
vertical-align: middle;
29+
font-size: 0.97em;
30+
}
31+
th {
32+
background: var(--bg-color, #fafbfc);
33+
color: var(--heading-color, #222);
34+
font-weight: 600;
35+
position: sticky;
36+
top: 0;
37+
z-index: 1;
38+
}
39+
tr:nth-child(even) {
40+
background: rgba(0, 0, 0, 0.02);
41+
}
42+
tr:hover {
43+
background: rgba(0, 102, 204, 0.07);
44+
transition: background 0.2s;
45+
}
46+
.hidden-col {
47+
display: none;
48+
}
49+
.badges {
50+
display: flex;
51+
flex-wrap: wrap;
52+
gap: 0.3em;
53+
}
54+
`;

0 commit comments

Comments
 (0)