blob: cb2f47c9b2e16e0af7b862e97ec14ae91d49f991 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as constant from '../src/constants';
import { LogHeader } from './log_header';
import { LogRow } from './log_row';
import { FfxLogData } from '../src/log_data';
import { LogField } from '../src/fields';
import { FilterExpression } from '../src/filter';
import { State } from '../src/state';
export const WRAP_LOG_TEXT_ATTR = 'wrap-log-text';
export class LogList {
private logList: HTMLDivElement;
private logHeader: LogHeader;
private hasPreviousLog: boolean = false;
private maxWidths: Array<number>;
constructor(private state: State) {
this.maxWidths = new Array(Object.keys(state.currentFields).length).fill(0);
this.logHeader = new LogHeader(state);
this.logList = this.initLogList();
this.logWrapping = state.shouldWrapLogs;
state.addEventListener('filterChange', (e) => {
const event = e as CustomEvent;
const filter: FilterExpression = event.detail.filter;
const logRows = Array.from(this.logList.children).slice(1);
if (filter.isEmpty()) {
for (const element of logRows) {
element.removeAttribute('hidden');
}
} else {
for (const element of logRows) {
if (filter.accepts(element.children[0])) {
element.removeAttribute('hidden');
} else {
element.setAttribute('hidden', '');
}
}
}
});
}
/**
* Returns the core element.
*/
get element() {
return this.logList;
}
/**
* Appends a log to the current list of logs
*/
public addLog(log: FfxLogData) {
this.addLogElement(log);
this.hasPreviousLog = true;
}
/**
* Resets the state and contents of the webview to contain nothing.
* The persistent state is maintained as that represents user selections.
*/
public reset() {
this.logList.innerHTML = '';
this.logList.appendChild(this.logHeader.element);
this.hasPreviousLog = false;
}
/**
* Defines whether or not to wrap the log text.
*
* @param logWrapActive if true the log text will be wrapped
*/
public set logWrapping(logWrapActive: boolean) {
if (logWrapActive) {
this.logList.setAttribute(WRAP_LOG_TEXT_ATTR, 'true');
} else {
this.logList.removeAttribute(WRAP_LOG_TEXT_ATTR);
}
}
/**
* Initializes the element that contains the list of logs.
*
* @return the log list element.
*/
private initLogList(): HTMLDivElement {
let logList = document.createElement('div');
logList.appendChild(this.logHeader.element);
logList.id = 'log-list';
return logList;
}
private addLogElement(log: FfxLogData) {
const logsToDrop = this.logList.children.length - constant.MAX_LOGS;
for (let i = 0; i < logsToDrop; i++) {
this.popLogElement();
}
this.appendLogElement(log);
if (!this.logList.parentElement?.matches(':hover')) {
this.logList.parentElement?.scrollTo(-1, this.logList.scrollHeight);
};
}
private appendLogElement(log: FfxLogData) {
const element = new LogRow(log, this.hasPreviousLog);
if (!this.filtersAllow(element)) {
element.setAttribute('hidden', '');
}
this.logList.appendChild(element);
this.setMaxCellWidth(element);
}
private setMaxCellWidth(row: Element) {
for (const cell in Array.from(row.children)) {
let id = row.children[cell].id as LogField;
let width = this.maxWidths[cell];
if (width < row.children[cell].scrollWidth) {
this.maxWidths[cell] = row.children[cell].scrollWidth;
this.logHeader.setMaxCellWidth(id, this.maxWidths[cell]);
}
}
}
private popLogElement() {
this.logList.removeChild(this.logList.children[-1]);
}
private filtersAllow(el: Element) {
return this.state.currentFilter.accepts(el);
}
}