HM-58. Добавлен новый тип логов client-logs (#21)

This commit is contained in:
Nikolay
2020-07-20 00:29:06 +03:00
committed by GitHub
parent 47fe69bc65
commit 05b43cac78
8 changed files with 232 additions and 67 deletions

View File

@ -26,7 +26,9 @@ class Component extends EmitService {
throw new Error(message);
}
this.mainNode = content.firstElementChild.cloneNode(true);
parentNode.appendChild(this.mainNode);
if (parentNode) {
parentNode.appendChild(this.mainNode);
}
this._listeners = [];
this._events = {};
}

View File

@ -1,24 +1,93 @@
import Component from '../component/index';
import routeService from '../../services/RouteService';
import {createElement} from '../../utils/elementUtils';
import {LOG_TYPE, LOG_LABELS} from '../../consts';
class LogsFilters extends Component {
constructor (parentNode) {
super('#logs-filters', parentNode);
this.initFilter();
this.messageInput = this.mainNode.querySelector('#logs-filter-message');
this.addEventListener(this.mainNode, 'submit', this.submit);
this.addEventListener(this.typeInput, 'change', this.changeType);
}
const {message = ''} = routeService.getUrlData().query;
changeType = () => {
const tableType = this.typeInput.value;
routeService.pushQuery({tableType}, true);
const [showInputs, hideInputs] = (() => {
if (tableType === LOG_TYPE.SERVER) {
return [this.serverInputs, this.clientInputs];
}
return [this.clientInputs, this.serverInputs];
})();
hideInputs.forEach(({input, parentNode}) => {
input.value = '';
parentNode.style.display = 'none';
});
showInputs.forEach(({input, parentNode}) => {
input.value = '';
parentNode.style.display = 'block';
});
}
this.messageInput.value = message;
submit = (event) => {
event.preventDefault();
const {query} = routeService.getUrlData();
this.addEventListener(this.mainNode, 'submit', (event) => {
event.preventDefault();
const inputs = query.tableType === LOG_TYPE.SERVER
? this.serverInputs
: this.clientInputs;
routeService.pushQuery({
message: this.messageInput.value,
routeService.pushQuery(inputs.reduce((memo, {name, input}) => ({
...memo,
[name]: input.value,
}), {}));
}
initInput = ({name, id}) => {
const input = this.mainNode.querySelector(`#${id}`);
return {
name,
input,
parentNode: input.parentNode,
};
}
initFilter = () => {
this.initTypeSelect();
this.serverInputs = [
{name: 'type', id: 'logs-filter-log-type'},
{name: 'message', id: 'logs-filter-message'},
{name: 'trace', id: 'logs-filter-trace'},
].map(this.initInput);
this.clientInputs = [
{name: 'type', id: 'logs-filter-request-type'},
].map(this.initInput);
this.changeType();
}
initTypeSelect = () => {
const {tableType = LOG_TYPE.SERVER} = routeService.getUrlData().query;
this.typeInput = this.mainNode.querySelector('#logs-filter-type');
LOG_LABELS.forEach(({id, label}) => {
createElement({
tagName: 'option',
parentNode: this.typeInput,
options: {
textContent: label,
},
args: {
value: id,
},
});
});
const {query} = routeService.getUrlData();
if (!query.type) {
routeService.pushQuery({tableType: LOG_TYPE.SERVER});
}
this.typeInput.value = tableType;
}
}

View File

@ -5,14 +5,8 @@ import Pagination from '../pagination';
import LogsFilters from '../logs-filters';
import routeService from '../../services/RouteService';
import {prepareToNumber} from '../../utils/urlUtils';
const COLS = [
{id: '_id', label: 'id', width: '240px'},
{id: 'date', label: 'Дата', width: '150px'},
{id: 'type', label: 'Тип', width: '70px'},
{id: 'message', label: 'Сообщение', width: '200px'},
{id: 'trace', label: 'Стек', width: '200px'},
];
import {LOG_TYPE, LOG_COLS} from '../../consts';
import {createElement, markText} from '../../utils/elementUtils';
const ELEMENTS_ON_PAGE = 15;
@ -20,63 +14,84 @@ class LogsPage extends Component {
constructor (mainNodeSelector, parentNode) {
super(mainNodeSelector, parentNode);
this.filters = new LogsFilters(this.mainNode);
this.header = createElement({
tagName: 'div',
parentNode: this.mainNode,
});
this.body = createElement({
tagName: 'div',
parentNode: this.mainNode,
});
this.footer = createElement({
tagName: 'div',
parentNode: this.mainNode,
});
this.table = new Table(this.mainNode, COLS);
this.filters = new LogsFilters(this.header);
this.pagination = new Pagination(this.mainNode);
this.tables = {
[LOG_TYPE.SERVER]: new Table(null, LOG_COLS[LOG_TYPE.SERVER]),
[LOG_TYPE.CLIENT]: new Table(null, LOG_COLS[LOG_TYPE.CLIENT]),
};
this.pagination = new Pagination(this.footer);
routeService.onChange(this.renderTable);
this.pagination.onPageChange((pageNumber) => {
const start = (pageNumber - 1) * ELEMENTS_ON_PAGE;
const end = start + ELEMENTS_ON_PAGE;
const rows = this.logList.slice(start, end + 1);
this.table.render(rows);
});
this.loadLogList();
this.initPage();
}
loadLogList = async () => {
this.logList = await storageLogsApi.request();
initPage = async () => {
this.logList = {
[LOG_TYPE.SERVER]: await storageLogsApi.requestServerLogs(),
[LOG_TYPE.CLIENT]: await storageLogsApi.requestClientLogs(),
};
this.renderTable();
}
filterRows = (queryMessage) => {
return this.logList.reduce((memo, row) => {
const message = row.message.toLowerCase();
const searchMessage = (queryMessage || '').toLowerCase();
if (searchMessage === '') {
memo.push(row);
return memo;
}
if (message.includes(searchMessage)) {
const replaceMessage = new RegExp(searchMessage, 'g');
const newText = message.replace(replaceMessage, `<span class="text-warning bg-dark">${searchMessage}</span>`);
memo.push({
...row,
message: newText,
});
}
return memo;
}, []);
filterRows = (rows, query) => {
const filteredRows = rows.filter((row) => {
return Object.entries(query).every(([key, value]) => {
const rowValue = row[key];
if (!rowValue) {
return true;
}
return rowValue.toLowerCase().includes(value.toLowerCase());
});
});
return filteredRows.map((row) => {
return Object.entries(query).reduce((memo, [key, searchMessage]) => {
const rowValue = memo[key];
if (!rowValue) {
return memo;
}
return {
...memo,
[key]: markText(searchMessage, rowValue),
};
}, row);
});
}
cutPagginationPage = (filteredRows, queryPageNumber) => {
const countPages = Math.ceil(filteredRows.length / ELEMENTS_ON_PAGE);
const pageNumber = prepareToNumber(queryPageNumber, countPages);
this.pagination.changeCountPages(countPages);
const start = (pageNumber - 1) * ELEMENTS_ON_PAGE;
const end = start + ELEMENTS_ON_PAGE;
return filteredRows.slice(start, end + 1);
}
renderTable = () => {
const {query} = routeService.getUrlData();
const filterRows = this.filterRows(query.message);
const countPages = Math.ceil(filterRows.length / ELEMENTS_ON_PAGE);
const pageNumber = prepareToNumber(query.pageNumber, countPages);
this.pagination.changeCountPages(countPages);
const start = (pageNumber - 1) * ELEMENTS_ON_PAGE;
const end = start + ELEMENTS_ON_PAGE;
const rows = filterRows.slice(start, end + 1);
const {tableType, ...omitQuery} = query;
this.table?.mainNode?.remove();
this.table = this.tables[tableType];
this.body.appendChild(this.table.mainNode);
const filteredRows = this.filterRows(this.logList[tableType], omitQuery);
const rows = this.cutPagginationPage(filteredRows, query.pageNumber);
this.table.render(rows);
}
}