aboutsummaryrefslogtreecommitdiff
path: root/pw_web/log-viewer
diff options
context:
space:
mode:
Diffstat (limited to 'pw_web/log-viewer')
-rw-r--r--pw_web/log-viewer/src/components/log-list/log-list.styles.ts21
-rw-r--r--pw_web/log-viewer/src/components/log-list/log-list.ts77
-rw-r--r--pw_web/log-viewer/src/components/log-view-controls/log-view-controls.styles.ts4
-rw-r--r--pw_web/log-viewer/src/components/log-view-controls/log-view-controls.ts5
-rw-r--r--pw_web/log-viewer/src/components/log-view/log-view.ts62
-rw-r--r--pw_web/log-viewer/src/components/log-viewer.styles.ts4
-rw-r--r--pw_web/log-viewer/src/components/log-viewer.ts7
-rw-r--r--pw_web/log-viewer/src/index.css8
8 files changed, 103 insertions, 85 deletions
diff --git a/pw_web/log-viewer/src/components/log-list/log-list.styles.ts b/pw_web/log-viewer/src/components/log-list/log-list.styles.ts
index 6dabfb4a0..a10b36360 100644
--- a/pw_web/log-viewer/src/components/log-list/log-list.styles.ts
+++ b/pw_web/log-viewer/src/components/log-list/log-list.styles.ts
@@ -88,9 +88,9 @@ export const styles = css`
--icon-color: var(--sys-log-viewer-color-debug);
}
- .log-row--warning .cell-content--icon,
- .log-row--error .cell-content--icon,
- .log-row--critical .cell-content--icon {
+ .log-row--warning .cell-icon,
+ .log-row--error .cell-icon,
+ .log-row--critical .cell-icon {
color: var(--icon-color);
}
@@ -138,7 +138,7 @@ export const styles = css`
display: block;
grid-row: 1;
overflow: hidden;
- padding: 0.5rem 1rem;
+ padding: var(--sys-log-viewer-table-cell-padding);
text-align: left;
text-overflow: ellipsis;
}
@@ -212,10 +212,6 @@ export const styles = css`
width: 1rem;
}
- .cell-content--icon {
- padding-top: 0.125rem;
- }
-
.cell-icon {
display: block;
font-variation-settings:
@@ -223,8 +219,11 @@ export const styles = css`
'wght' 400,
'GRAD' 200,
'opsz' 58;
- font-size: 1.25rem;
+ font-size: var(--sys-log-viewer-table-cell-icon-size);
user-select: none;
+ display: grid;
+ place-content: center;
+ place-items: center;
}
.overflow-indicator {
@@ -268,8 +267,8 @@ export const styles = css`
mark {
background-color: var(--sys-log-viewer-color-table-mark);
- border-radius: 2px;
- color: var(--sys-log-viewer-color-table-mark);
+ border-radius: 4px;
+ color: var(--sys-log-viewer-color-table-mark-text);
outline: 1px solid var(--sys-log-viewer-color-table-mark);
}
diff --git a/pw_web/log-viewer/src/components/log-list/log-list.ts b/pw_web/log-viewer/src/components/log-list/log-list.ts
index ca450fc94..58d635ce7 100644
--- a/pw_web/log-viewer/src/components/log-list/log-list.ts
+++ b/pw_web/log-viewer/src/components/log-list/log-list.ts
@@ -59,14 +59,6 @@ export class LogList extends LitElement {
@state()
private _isOverflowingToRight = false;
- /** A number representing the scroll percentage in the horizontal direction. */
- @state()
- private _scrollPercentageLeft = 0;
-
- /** Indicates whether to enable autosizing of incoming log entries. */
- @state()
- private _autosizeLocked = false;
-
/**
* Indicates whether to automatically scroll the table container to the bottom
* when new log entries are added.
@@ -74,31 +66,42 @@ export class LogList extends LitElement {
@state()
private _autoscrollIsEnabled = true;
+ /** A number representing the scroll percentage in the horizontal direction. */
+ @state()
+ private _scrollPercentageLeft = 0;
+
@query('.table-container') private _tableContainer!: HTMLDivElement;
@query('table') private _table!: HTMLTableElement;
@query('tbody') private _tableBody!: HTMLTableSectionElement;
@queryAll('tr') private _tableRows!: HTMLTableRowElement[];
- /**
- * Data used for column resizing including the column index, the starting
- * mouse position (X-coordinate), and the initial width of the column.
- */
- private columnResizeData: {
- columnIndex: number;
- startX: number;
- startWidth: number;
- } | null = null;
+ /** Indicates whether to enable autosizing of incoming log entries. */
+ private _autosizeLocked = false;
/** The number of times the `logs` array has been updated. */
private logUpdateCount: number = 0;
+
+ /** The last known vertical scroll position of the table container. */
+ private lastScrollTop: number = 0;
+
/** The maximum number of log entries to render in the list. */
private readonly MAX_ENTRIES = 100_000;
+
/** The maximum number of log updates until autosize is disabled. */
private readonly AUTOSIZE_LIMIT: number = 8;
+
/** The minimum width (in px) for table columns. */
private readonly MIN_COL_WIDTH: number = 52;
- /** The last known vertical scroll position of the table container. */
- private lastScrollTop: number = 0;
+
+ /**
+ * Data used for column resizing including the column index, the starting
+ * mouse position (X-coordinate), and the initial width of the column.
+ */
+ private columnResizeData: {
+ columnIndex: number;
+ startX: number;
+ startWidth: number;
+ } | null = null;
firstUpdated() {
setInterval(() => this.updateHorizontalOverflowState(), 1000);
@@ -148,9 +151,6 @@ export class LogList extends LitElement {
if (this.logUpdateCount >= this.AUTOSIZE_LIMIT) {
this._autosizeLocked = true;
}
- if (!this._autosizeLocked) {
- this.autosizeColumns();
- }
};
/** Called when the Lit virtualizer updates its range of entries. */
@@ -170,6 +170,11 @@ export class LogList extends LitElement {
}, 0); // Complete any rendering tasks before scrolling
}
+ private onJumpToBottomButtonClick() {
+ this._autoscrollIsEnabled = true;
+ this.scrollTableToBottom();
+ }
+
/**
* Calculates the maximum column widths for the table and updates the table
* rows.
@@ -223,7 +228,7 @@ export class LogList extends LitElement {
columnValue = `${col.manualWidth}px`;
} else {
if (i === 0) {
- columnValue = '3.25rem';
+ columnValue = '3rem';
} else {
const chWidth = col.characterLength;
const padding = 34;
@@ -249,11 +254,11 @@ export class LogList extends LitElement {
* @param {string} text - The table cell text to be processed.
*/
private highlightMatchedText(text: string): TemplateResult[] {
- const searchPhrase = this.searchText?.replace(/(^"|')|("|'$)/g, '');
- if (!searchPhrase) {
+ if (!this.searchText) {
return [html`${text}`];
}
+ const searchPhrase = this.searchText?.replace(/(^"|')|("|'$)/g, '');
const escapedsearchText = searchPhrase.replace(
/[.*+?^${}()|[\]\\]/g,
'\\$&',
@@ -285,34 +290,36 @@ export class LogList extends LitElement {
const scrollY =
container.scrollHeight - currentScrollTop - container.clientHeight;
const maxScrollLeft = container.scrollWidth - containerWidth;
- const rowHeight = this._tableRows[0].offsetHeight;
// Determine scroll direction and update the last known scroll position
const isScrollingVertically = currentScrollTop !== this.lastScrollTop;
const isScrollingUp = currentScrollTop < this.lastScrollTop;
this.lastScrollTop = currentScrollTop;
- // Only run autoscroll logic if the user is scrolling vertically
+ const logsAreCleared = this.logs.length == 0;
+
+ if (logsAreCleared) {
+ this._autoscrollIsEnabled = true;
+ return;
+ }
+
+ // Run autoscroll logic if scrolling vertically
if (!isScrollingVertically) {
this._scrollPercentageLeft = scrollLeft / maxScrollLeft || 0;
return;
}
- // User is scrolling up, disable autoscroll
+ // Scroll direction up, disable autoscroll
if (isScrollingUp) {
this._autoscrollIsEnabled = false;
return;
}
- // User is scrolling down, enable autoscroll if they're near the bottom
+ // Scroll direction down, enable autoscroll if near the bottom
if (Math.abs(scrollY) <= 1) {
this._autoscrollIsEnabled = true;
return;
}
-
- if (Math.round(scrollY - rowHeight) >= 1) {
- this._autoscrollIsEnabled = false;
- }
};
/**
@@ -523,7 +530,7 @@ export class LogList extends LitElement {
return html`
<td ?hidden=${!isVisible}>
- <div class="cell-content cell-content--icon">
+ <div class="cell-content">
<md-icon
class="cell-icon"
title="${toTitleCase(field.value.toString())}"
@@ -570,7 +577,7 @@ export class LogList extends LitElement {
<md-filled-button
class="jump-to-bottom-btn"
title="Jump to Bottom"
- @click="${this.scrollTableToBottom}"
+ @click="${this.onJumpToBottomButtonClick}"
leading-icon
data-visible="${this._autoscrollIsEnabled ? 'false' : 'true'}"
>
diff --git a/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.styles.ts b/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.styles.ts
index 0f17bc9f1..0277857eb 100644
--- a/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.styles.ts
+++ b/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.styles.ts
@@ -83,10 +83,10 @@ export const styles = css`
font-size: 1rem;
height: 0.75rem;
line-height: 0.75;
- max-width: 100%;
+ max-width: 30rem;
overflow: hidden;
padding: 0.5rem 1rem;
- width: 25rem;
+ width: 100%;
}
input[type='text'] {
diff --git a/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.ts b/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.ts
index f31f8e129..8c0226f7b 100644
--- a/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.ts
+++ b/pw_web/log-viewer/src/components/log-view-controls/log-view-controls.ts
@@ -50,9 +50,6 @@ export class LogViewControls extends LitElement {
_stateStore: StateStore = new LocalStorageState();
@state()
- _state: State;
-
- @state()
_viewTitle = 'Log View';
@state()
@@ -66,6 +63,8 @@ export class LogViewControls extends LitElement {
@queryAll('.item-checkboxes') _itemCheckboxes!: HTMLCollection[];
+ private _state: State;
+
/** The timer identifier for debouncing search input. */
private _inputDebounceTimer: number | null = null;
diff --git a/pw_web/log-viewer/src/components/log-view/log-view.ts b/pw_web/log-viewer/src/components/log-view/log-view.ts
index e975c044f..900637e5c 100644
--- a/pw_web/log-viewer/src/components/log-view/log-view.ts
+++ b/pw_web/log-viewer/src/components/log-view/log-view.ts
@@ -55,47 +55,44 @@ export class LogView extends LitElement {
@state()
_lineWrap = false;
+ /** The field keys (column values) for the incoming log entries. */
+ @state()
+ private _columnData: TableColumn[] = [];
+
+ /** A string representing the value contained in the search field. */
+ @state()
+ public searchText = '';
+
+ /** A StateStore object that stores state of views */
+ @state()
+ _stateStore: StateStore = new LocalStorageState();
+
+ @query('log-list') _logList!: LogList;
+
/**
* An array containing the logs that remain after the current filter has been
* applied.
*/
- @state()
private _filteredLogs: LogEntry[] = [];
- /** The field keys (column values) for the incoming log entries. */
- @state()
- private _columnData: TableColumn[] = [];
-
/** A function used for filtering rows that contain a certain substring. */
- @state()
private _stringFilter: FilterFunction = () => true;
/**
* A function used for filtering rows that contain a timestamp within a
* certain window.
*/
- @state()
private _timeFilter: FilterFunction = () => true;
- /** A string representing the value contained in the search field. */
- @state()
- public searchText = '';
-
- /** A StateStore object that stores state of views */
- @state()
- _stateStore: StateStore = new LocalStorageState();
-
- @state()
- _state: State;
-
- @query('log-list') _logList!: LogList;
+ private _state: State;
private _debounceTimeout: NodeJS.Timeout | null = null;
+ /** The number of elements in the `logs` array since last updated. */
+ private _lastKnownLogLength: number = 0;
+
/** The amount of time, in ms, before the filter expression is executed. */
private readonly FILTER_DELAY = 100;
- /** The number of elements in the `logs` array since last updated. */
- private lastKnownLogLength: number = 0;
constructor() {
super();
@@ -117,10 +114,13 @@ export class LogView extends LitElement {
super.updated(changedProperties);
if (changedProperties.has('logs')) {
- const newLogs = this.logs.slice(this.lastKnownLogLength);
- this.lastKnownLogLength = this.logs.length;
+ const newLogs = this.logs.slice(this._lastKnownLogLength);
+ this._lastKnownLogLength = this.logs.length;
this.updateFieldsFromNewLogs(newLogs);
+ }
+
+ if (changedProperties.has('logs') || changedProperties.has('searchText')) {
this.filterLogs();
}
@@ -263,16 +263,20 @@ export class LogView extends LitElement {
}
/**
- * Combines constituent filter expressions and filters the logs. The filtered
- * logs are stored in the `_filteredLogs` state property.
+ * Combines filter expressions and filters the logs. The filtered
+ * logs are stored in the `_filteredLogs` property.
*/
private filterLogs() {
const combinedFilter = (logEntry: LogEntry) =>
this._timeFilter(logEntry) && this._stringFilter(logEntry);
- this._filteredLogs = JSON.parse(
- JSON.stringify(this.logs.filter(combinedFilter)),
- );
+ const newFilteredLogs = this.logs.filter(combinedFilter);
+
+ if (
+ JSON.stringify(newFilteredLogs) !== JSON.stringify(this._filteredLogs)
+ ) {
+ this._filteredLogs = newFilteredLogs;
+ }
}
private updateColumnData(event: CustomEvent) {
@@ -322,7 +326,7 @@ export class LogView extends LitElement {
render() {
return html` <log-view-controls
- .columnData=${[...this._columnData]}
+ .columnData=${this._columnData}
.viewId=${this.id}
.hideCloseButton=${!this.isOneOfMany}
.stateStore=${this._stateStore}
diff --git a/pw_web/log-viewer/src/components/log-viewer.styles.ts b/pw_web/log-viewer/src/components/log-viewer.styles.ts
index bc155b383..0bf3a88e6 100644
--- a/pw_web/log-viewer/src/components/log-viewer.styles.ts
+++ b/pw_web/log-viewer/src/components/log-viewer.styles.ts
@@ -43,6 +43,10 @@ export const styles = css`
--sys-log-viewer-height: 100%;
--sys-log-viewer-view-outline-width: 1px;
--sys-log-viewer-view-corner-radius: 0.5rem;
+
+ /* Log List */
+ --sys-log-viewer-table-cell-padding: 0.375rem 0.75rem;
+ --sys-log-viewer-table-cell-icon-size: 1.125rem;
}
.grid-container {
diff --git a/pw_web/log-viewer/src/components/log-viewer.ts b/pw_web/log-viewer/src/components/log-viewer.ts
index 91dba1e76..06c695309 100644
--- a/pw_web/log-viewer/src/components/log-viewer.ts
+++ b/pw_web/log-viewer/src/components/log-viewer.ts
@@ -51,12 +51,11 @@ export class LogViewer extends LitElement {
@state()
_logViews: LogView[] = [];
- /** A StateStore object that stores state of views */
+ /** An object that stores the state of log views */
@state()
_stateStore: StateStore;
- @state()
- _state: State;
+ private _state: State;
constructor(state: StateStore) {
super();
@@ -175,7 +174,7 @@ export class LogViewer extends LitElement {
(view) => html`
<log-view
id=${view.id}
- .logs=${[...this.logs]}
+ .logs=${this.logs}
.isOneOfMany=${this._logViews.length > 1}
.stateStore=${this._stateStore}
@add-view="${this.addLogView}"
diff --git a/pw_web/log-viewer/src/index.css b/pw_web/log-viewer/src/index.css
index f16bd1612..04a79a2c2 100644
--- a/pw_web/log-viewer/src/index.css
+++ b/pw_web/log-viewer/src/index.css
@@ -44,10 +44,16 @@ button {
main {
height: 100vh;
- padding: 2rem;
+ padding: 16px;
width: 100vw;
}
+@media (min-width: 840px) {
+ main {
+ padding: 24px;
+ }
+}
+
a {
color: var(--md-sys-color-primary);
font-weight: 500;