731 lines
27 KiB
JavaScript
731 lines
27 KiB
JavaScript
// Copyright 1999-2025. WebPros International GmbH. All rights reserved.
|
|
|
|
Jsw.onReady(function () {
|
|
const appState = PanelMigrator.initAppState();
|
|
|
|
const severityLevel = {
|
|
INFO: 1,
|
|
ERROR: 2,
|
|
WARNING: 3,
|
|
DEBUG: 4,
|
|
EXCEPTION: 5,
|
|
MIGRATOR_EXECUTION: 6,
|
|
};
|
|
|
|
const severityProperties = {};
|
|
severityProperties[severityLevel.INFO] = {
|
|
title: 'Info',
|
|
rowCssClass: 'plesk-migrator-log-row-severity-info',
|
|
severityCellCssClass: 'plesk-migrator-log-cell-severity-info',
|
|
};
|
|
severityProperties[severityLevel.ERROR] = {
|
|
title: 'Error',
|
|
rowCssClass: 'plesk-migrator-log-row-severity-error',
|
|
severityCellCssClass: 'plesk-migrator-log-cell-severity-error',
|
|
};
|
|
severityProperties[severityLevel.WARNING] = {
|
|
title: 'Warning',
|
|
rowCssClass: 'plesk-migrator-log-row-severity-warning',
|
|
severityCellCssClass: 'plesk-migrator-log-cell-severity-warning',
|
|
};
|
|
severityProperties[severityLevel.DEBUG] = {
|
|
title: 'Debug',
|
|
rowCssClass: 'plesk-migrator-log-row-severity-debug',
|
|
severityCellCssClass: 'plesk-migrator-log-cell-severity-debug',
|
|
};
|
|
severityProperties[severityLevel.EXCEPTION] = {
|
|
title: 'Exception',
|
|
rowCssClass: 'plesk-migrator-log-row-severity-debug',
|
|
severityCellCssClass: 'plesk-migrator-log-cell-severity-debug',
|
|
};
|
|
severityProperties[severityLevel.MIGRATOR_EXECUTION] = {
|
|
title: 'Migrator execution',
|
|
rowCssClass: 'plesk-migrator-log-row-severity-migrator-execution',
|
|
severityCellCssClass: 'plesk-migrator-log-cell-severity-migrator-execution',
|
|
};
|
|
|
|
|
|
const LogRecords = Class.create({
|
|
initialize() {
|
|
this._records = {}; // recordId => LogRecord
|
|
this._expandedRecords = {};
|
|
this._rootRecords = [];
|
|
this._inProgressRecords = {};
|
|
this._htmlLogTable = $('migration-log-table');
|
|
this._htmlLogTableBody = this._htmlLogTable.select('tbody').first();
|
|
|
|
this._showDebug = false;
|
|
this._highlightText = null;
|
|
this._filterText = null;
|
|
},
|
|
appendRecords(recordsData) {
|
|
for (let i = 0; i < recordsData.length; i++) {
|
|
const recordData = recordsData[i];
|
|
this.appendRecord(recordData);
|
|
}
|
|
},
|
|
appendRecord(recordData) {
|
|
if (this._records[recordData.recordId]) {
|
|
const existingRecord = this._records[recordData.recordId];
|
|
this.updateRecordExpandability(existingRecord);
|
|
if (recordData.finished) {
|
|
existingRecord.finishRecord();
|
|
delete this._inProgressRecords[existingRecord.getRecordId()];
|
|
}
|
|
existingRecord.updateRecordChildErrorMark(recordData.hasChildErrors, recordData.hasChildWarnings);
|
|
return;
|
|
}
|
|
|
|
let parentRecord = null;
|
|
const rootParentRecordId = 2147483647;
|
|
if (recordData.parentRecordId != rootParentRecordId) {
|
|
parentRecord = this._records[recordData.parentRecordId];
|
|
}
|
|
|
|
const record = new LogRecord(this, recordData, parentRecord);
|
|
this._records[record.getRecordId()] = record;
|
|
|
|
if (!record.isFinished()) {
|
|
this._inProgressRecords[record.getRecordId()] = record;
|
|
}
|
|
|
|
if (parentRecord) {
|
|
parentRecord.appendChildRecord(record);
|
|
parentRecord.getHtmlEndRow().insert({ before: record.getHtmlRow() });
|
|
parentRecord.getHtmlEndRow().insert({ before: record.getHtmlEndRow() });
|
|
this.updateRecordExpandability(parentRecord);
|
|
} else {
|
|
this._htmlLogTableBody.insert(record.getHtmlRow());
|
|
this._htmlLogTableBody.insert(record.getHtmlEndRow());
|
|
this._rootRecords.push(record);
|
|
}
|
|
|
|
record.setCollapsed();
|
|
this.updateRecordExpandability(record);
|
|
|
|
record.highlightText(this._highlightText);
|
|
this.updateRecordVisibility(record);
|
|
},
|
|
expandRecord(record) {
|
|
this.expandRecordsByIds([record.getRecordId()]);
|
|
},
|
|
expandRecordsByIds(recordIds) {
|
|
const self = this;
|
|
|
|
const collapsedRecordIds = [];
|
|
for (let i = 0; i < recordIds.length; i++) {
|
|
const recordId = recordIds[i];
|
|
if (self._expandedRecords[recordId] != 1) {
|
|
collapsedRecordIds.push(recordId);
|
|
}
|
|
}
|
|
|
|
if (collapsedRecordIds.length == 0) {
|
|
return;
|
|
}
|
|
|
|
const requestFunctions = [];
|
|
|
|
// divide list of records into parts, to handle long lists of expanded records:
|
|
// when there are too many records in a single AJAX request, backend could
|
|
// fail to respond (because of memory limit on response, or max execution time of PHP or CGI).
|
|
const maxPartSize = 50;
|
|
const collapsedRecordIdsParts = divideIntoParts(collapsedRecordIds, maxPartSize);
|
|
|
|
collapsedRecordIdsParts.forEach(function (collapsedRecordIdsPart) {
|
|
requestFunctions.push(function (onSuccess) {
|
|
new Ajax.Request(URL_GET_LOG_RECORDS, {
|
|
// perform POST request as list of parent IDs could be long and exceed URL length limit
|
|
// (the problem is more actual for IIS which has more strict limits)
|
|
method: 'post',
|
|
parameters: {
|
|
'parent-ids': collapsedRecordIdsPart.join(),
|
|
},
|
|
onSuccess(response) {
|
|
const recordsData = response.responseText.evalJSON();
|
|
|
|
self.appendRecords(recordsData);
|
|
|
|
for (let i = 0; i < collapsedRecordIdsPart.length; i++) {
|
|
const recordId = collapsedRecordIdsPart[i];
|
|
self._records[recordId].setExpanded();
|
|
self._expandedRecords[recordId] = 1;
|
|
for (let j = 0; j < self._records[recordId].getChildRecords().length; j++) {
|
|
const childRecord = self._records[recordId].getChildRecords()[j];
|
|
self.updateRecordVisibility(childRecord);
|
|
}
|
|
}
|
|
},
|
|
onComplete() {
|
|
onSuccess();
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
callAsyncFunctionsChain(requestFunctions);
|
|
},
|
|
expandRecordsByIdsRaw(recordIds) {
|
|
const self = this;
|
|
|
|
for (let i = 0; i < recordIds.length; i++) {
|
|
const recordId = recordIds[i];
|
|
if (self._expandedRecords[recordId] == 1) {
|
|
continue;
|
|
}
|
|
if (!self._records[recordId].isExpandable()) {
|
|
continue;
|
|
}
|
|
|
|
self._records[recordId].setExpanded();
|
|
self._expandedRecords[recordId] = 1;
|
|
for (let j = 0; j < self._records[recordId].getChildRecords().length; j++) {
|
|
const childRecord = self._records[recordId].getChildRecords()[j];
|
|
self.updateRecordVisibility(childRecord);
|
|
}
|
|
}
|
|
},
|
|
collapseRecord(record) {
|
|
for (let i = 0; i < record.getChildRecords().length; i++) {
|
|
const childRecord = record.getChildRecords()[i];
|
|
|
|
for (let j = 0; j < childRecord.getChildRecords().length; j++) {
|
|
const childChildRecord = childRecord.getChildRecords()[j];
|
|
this._removeRecord(childChildRecord);
|
|
}
|
|
childRecord.removeAllChildRecords();
|
|
childRecord.hide();
|
|
childRecord.setCollapsed();
|
|
delete this._expandedRecords[childRecord.getRecordId()];
|
|
}
|
|
record.setCollapsed();
|
|
|
|
delete this._expandedRecords[record.getRecordId()];
|
|
},
|
|
_removeRecord(record) {
|
|
for (let i = 0; i < record.getChildRecords().length; i++) {
|
|
const childRecord = record.getChildRecords()[i];
|
|
this._removeRecord(childRecord);
|
|
}
|
|
|
|
delete this._records[record.getRecordId()];
|
|
record.getHtmlRow().remove();
|
|
record.getHtmlEndRow().remove();
|
|
},
|
|
toggleDebug() {
|
|
const self = this;
|
|
this._showDebug = !this._showDebug;
|
|
this._foreachRecord(function (record) {
|
|
self.updateRecordVisibility(record);
|
|
});
|
|
this._foreachRecord(function (record) {
|
|
self.updateRecordExpandability(record);
|
|
});
|
|
},
|
|
getExpandedRecordIds() {
|
|
return Object.keys(this._expandedRecords);
|
|
},
|
|
getInProgressRecords() {
|
|
return this._inProgressRecords;
|
|
},
|
|
getRootRecords() {
|
|
return this._rootRecords;
|
|
},
|
|
setHighlightText(searchText) {
|
|
const self = this;
|
|
this._highlightText = searchText;
|
|
this._foreachRecord(function (record) {
|
|
record.highlightText(searchText);
|
|
});
|
|
this._foreachRecord(function (record) {
|
|
self.updateRecordExpandability(record);
|
|
});
|
|
},
|
|
setFilterText(searchText) {
|
|
const self = this;
|
|
this._filterText = searchText;
|
|
this._foreachRecord(function (record) {
|
|
self.updateRecordVisibility(record);
|
|
});
|
|
this._foreachRecord(function (record) {
|
|
self.updateRecordExpandability(record);
|
|
});
|
|
},
|
|
updateRecordVisibility(record) {
|
|
if (this._isFiltered(record)) {
|
|
record.hide();
|
|
return;
|
|
}
|
|
if (record.getParentRecord() && !record.getParentRecord().isExpanded()) {
|
|
record.hide();
|
|
return;
|
|
}
|
|
record.show();
|
|
},
|
|
updateRecordExpandability(record) {
|
|
for (let i = 0; i < record.getChildRecords().length; i++) {
|
|
const childRecord = record.getChildRecords()[i];
|
|
if (!this._isFiltered(childRecord)) {
|
|
record.setExpandable(true);
|
|
return;
|
|
}
|
|
}
|
|
record.setExpandable(false);
|
|
},
|
|
_foreachRecord(callback) {
|
|
const self = this;
|
|
Object.keys(this._records).forEach(function (key, index) {
|
|
const record = self._records[key];
|
|
callback(record);
|
|
});
|
|
},
|
|
_isFiltered(record) {
|
|
return (
|
|
(record.isDebug() && !this._showDebug) ||
|
|
(
|
|
this._filterText &&
|
|
!(record.getMessage().toLowerCase()
|
|
.indexOf(this._filterText.toLowerCase()) > -1)
|
|
)
|
|
);
|
|
},
|
|
});
|
|
|
|
var LogRecord = Class.create({
|
|
initialize(logRecords, logRecordData, parentRecord) {
|
|
this._logRecords = logRecords;
|
|
|
|
this._childRecords = [];
|
|
|
|
this._recordId = logRecordData.recordId;
|
|
this._severity = logRecordData.severity;
|
|
this._time = logRecordData.time;
|
|
this._message = logRecordData.message;
|
|
this._finished = logRecordData.finished;
|
|
|
|
this._parentRecord = parentRecord;
|
|
|
|
this._isExpandable = false;
|
|
|
|
this._initializeHtml();
|
|
this.updateRecordChildErrorMark(logRecordData.hasChildErrors, logRecordData.hasChildWarnings);
|
|
},
|
|
_initializeHtml() {
|
|
const messageCellProperties = {
|
|
style: `white-space: pre-wrap; word-wrap: break-word; padding-left: ${this.getLevel() * 50}px`,
|
|
class: 'messageText',
|
|
};
|
|
|
|
const severityDescriptor = severityProperties[this._severity];
|
|
|
|
const rowProperties = { class: `${severityDescriptor.rowCssClass} logItemRow`, style: 'display: none' };
|
|
const severityCellProperties = {
|
|
class: severityDescriptor.severityCellCssClass,
|
|
style: 'white-space: nowrap',
|
|
};
|
|
|
|
this._htmlRow = new Element('tr', rowProperties);
|
|
|
|
this._htmlTimeCol = new Element('td', { class: 'logRecordDate' }).update(this._time.escapeHTML());
|
|
this._htmlErrorIcon = new Element(
|
|
'img', {
|
|
src: migratorImage('log/error.png'),
|
|
style: 'width: 16px; height: 16px; margin-left: 8px; display: none;',
|
|
},
|
|
);
|
|
this._htmlWarningIcon = new Element(
|
|
'img', {
|
|
src: migratorImage('log/warning.png'),
|
|
style: 'width: 16px; height: 16px; margin-left: 8px; display: none;',
|
|
},
|
|
);
|
|
this._htmlSeverityCol = new Element('td', severityCellProperties).update(
|
|
severityDescriptor.title.escapeHTML(),
|
|
)
|
|
.insert(this._htmlErrorIcon)
|
|
.insert(this._htmlWarningIcon);
|
|
|
|
this._htmlMessageCol = new Element('td', messageCellProperties);
|
|
|
|
const htmlMessageColContainer = new Element('div', { class: 'plesk-migrator-log-container-message-column' });
|
|
this._htmlWorkingContainer = new Element('div', { class: 'plesk-migrator-log-working-container' });
|
|
this._htmlExpandContainer = new Element('div', { class: 'plesk-migrator-log-expand-container' });
|
|
this._htmlMessageContainer = new Element('div', { class: 'plesk-migrator-log-message-container' });
|
|
this._htmlMessageContainer.update(this._message.escapeHTML());
|
|
htmlMessageColContainer.insert(this._htmlWorkingContainer);
|
|
htmlMessageColContainer.insert(this._htmlExpandContainer);
|
|
htmlMessageColContainer.insert(this._htmlMessageContainer);
|
|
this._htmlMessageCol.insert(htmlMessageColContainer);
|
|
|
|
this._htmlExpandIcon = new Element('img', {
|
|
src: migratorImage('log-expand-icon.gif'),
|
|
class: 'plesk-migrator-expand-image',
|
|
tabindex: 0,
|
|
alt: 'Expand',
|
|
role: 'button',
|
|
'aria-expanded': this._expanded ? 'true' : 'false',
|
|
style: 'display: none',
|
|
});
|
|
|
|
this._htmlCollapseIcon = new Element('img', {
|
|
src: migratorImage('log-collapse-icon.gif'),
|
|
class: 'plesk-migrator-expand-image',
|
|
tabindex: 0,
|
|
alt: 'Collapse',
|
|
style: 'display: none',
|
|
role: 'button',
|
|
'aria-expanded': this._expanded ? 'true' : 'false',
|
|
});
|
|
|
|
if (!this._finished) {
|
|
this._htmlWorkingIcon = new Element(
|
|
'img', {
|
|
src: migratorImage('log-record-working.gif'),
|
|
style: 'width: 16px; height: 16px;',
|
|
},
|
|
);
|
|
this._htmlWorkingContainer.insert(this._htmlWorkingIcon);
|
|
} else {
|
|
this._htmlWorkingIcon = null;
|
|
}
|
|
|
|
this._htmlExpandContainer.insert(this._htmlExpandIcon);
|
|
this._htmlExpandContainer.insert(this._htmlCollapseIcon);
|
|
|
|
[this._htmlExpandIcon, this._htmlCollapseIcon].forEach(icon => {
|
|
icon.addEventListener('keydown', event => {
|
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
event.preventDefault();
|
|
icon.click();
|
|
}
|
|
});
|
|
});
|
|
|
|
this._htmlRow.insert(this._htmlTimeCol);
|
|
this._htmlRow.insert(this._htmlSeverityCol);
|
|
this._htmlRow.insert(this._htmlMessageCol);
|
|
|
|
this._expanded = false;
|
|
|
|
this._endHtmlRow = new Element('tr', { style: 'display: none' });
|
|
},
|
|
appendChildRecord(record) {
|
|
this._childRecords.push(record);
|
|
},
|
|
getChildRecords() {
|
|
return this._childRecords;
|
|
},
|
|
removeAllChildRecords() {
|
|
this._childRecords = [];
|
|
},
|
|
getHtmlRow() {
|
|
return this._htmlRow;
|
|
},
|
|
// Get fake hidden HTML row, which marks place right after the last child record.
|
|
// So, DOM tree will look like:
|
|
// <tr>This log record</tr>
|
|
// <tr>Child record #1</tr>
|
|
// <tr>Child record #2</tr>
|
|
// ...
|
|
// <tr>Child record #N (last child record)</tr>
|
|
// <tr>End record (hidden)</tr>
|
|
getHtmlEndRow() {
|
|
return this._endHtmlRow;
|
|
},
|
|
getRecordId() {
|
|
return this._recordId;
|
|
},
|
|
getMessage() {
|
|
return this._message;
|
|
},
|
|
getParentRecord() {
|
|
return this._parentRecord;
|
|
},
|
|
getLevel() {
|
|
let i = 0;
|
|
let parent = this.getParentRecord();
|
|
while (parent) {
|
|
i++;
|
|
parent = parent.getParentRecord();
|
|
}
|
|
return i;
|
|
},
|
|
hide() {
|
|
this.getHtmlRow().hide();
|
|
},
|
|
show() {
|
|
this.getHtmlRow().show();
|
|
},
|
|
setExpandable(isExpandable) {
|
|
this._isExpandable = isExpandable;
|
|
if (isExpandable) {
|
|
if (this._expanded) {
|
|
this._htmlCollapseIcon.show();
|
|
this._htmlExpandIcon.hide();
|
|
} else {
|
|
this._htmlCollapseIcon.hide();
|
|
this._htmlExpandIcon.show();
|
|
}
|
|
} else {
|
|
this._htmlCollapseIcon.hide();
|
|
this._htmlExpandIcon.hide();
|
|
}
|
|
},
|
|
isExpandable() {
|
|
return this._isExpandable;
|
|
},
|
|
setExpanded() {
|
|
const record = this;
|
|
this._htmlCollapseIcon.show();
|
|
this._htmlExpandIcon.hide();
|
|
this._htmlExpandContainer.stopObserving('click');
|
|
this._htmlExpandContainer.observe(
|
|
'click', function () {
|
|
record._logRecords.collapseRecord(record);
|
|
},
|
|
);
|
|
this._expanded = true;
|
|
},
|
|
setCollapsed() {
|
|
const record = this;
|
|
this._htmlCollapseIcon.hide();
|
|
this._htmlExpandIcon.show();
|
|
this._htmlExpandContainer.stopObserving('click');
|
|
this._htmlExpandContainer.observe(
|
|
'click', function () {
|
|
record._logRecords.expandRecord(record);
|
|
},
|
|
);
|
|
this._expanded = false;
|
|
},
|
|
finishRecord() {
|
|
this._finished = true;
|
|
if (this._htmlWorkingIcon) {
|
|
this._htmlWorkingIcon.remove();
|
|
this._htmlWorkingIcon = null;
|
|
}
|
|
},
|
|
updateRecordChildErrorMark(hasChildErrors, hasChildWarnings) {
|
|
if (hasChildErrors) {
|
|
this._htmlWarningIcon.hide();
|
|
this._htmlErrorIcon.show();
|
|
} else if (hasChildWarnings) {
|
|
this._htmlWarningIcon.show();
|
|
}
|
|
},
|
|
isFinished() {
|
|
return this._finished;
|
|
},
|
|
isExpanded() {
|
|
return this._expanded;
|
|
},
|
|
isDebug() {
|
|
return this._severity == severityLevel.DEBUG || this._severity == severityLevel.EXCEPTION;
|
|
},
|
|
highlightText(searchText) {
|
|
this._htmlMessageContainer.update(highlight(this._message, searchText));
|
|
},
|
|
});
|
|
|
|
function divideIntoParts(list, maxPartSize) {
|
|
const parts = [];
|
|
for (let i = 0; i < list.length; i += maxPartSize) {
|
|
parts.push(list.slice(i, i + maxPartSize));
|
|
}
|
|
return parts;
|
|
}
|
|
|
|
// Call chain of asynchronous functions, one-by-one: the first function is called, when it completes its
|
|
// async execution, the second function is called, when it completes its async execution, the third function
|
|
// is called, and so on.
|
|
// "functions" argument is a list, each item is a function, which accepts single argument - callback,
|
|
// which must be called by the function once it completes its async execution.
|
|
function callAsyncFunctionsChain(functions) {
|
|
if (functions.length == 0) {
|
|
return;
|
|
}
|
|
|
|
let functionId = 0;
|
|
|
|
function callNextRequestFunction() {
|
|
if (functionId >= functions.length) {
|
|
return;
|
|
}
|
|
|
|
functions[functionId](function () {
|
|
functionId++;
|
|
setTimeout(function () {
|
|
callNextRequestFunction();
|
|
}, 0);
|
|
});
|
|
}
|
|
|
|
callNextRequestFunction();
|
|
}
|
|
|
|
// Update log periodically with AJAX
|
|
function periodicUpdateLog() {
|
|
if (!appState.mounted) {
|
|
return;
|
|
}
|
|
|
|
const rootParentRecordId = 2147483647;
|
|
|
|
let lastRootRecordId = rootParentRecordId;
|
|
const rootRecords = logRecords.getRootRecords();
|
|
if (rootRecords.length > 0) {
|
|
lastRootRecordId = rootRecords[rootRecords.length - 1].getRecordId();
|
|
}
|
|
|
|
const recordIdPairs = [
|
|
`${rootParentRecordId}.${lastRootRecordId}`,
|
|
];
|
|
|
|
const inProgressRecs = logRecords.getInProgressRecords();
|
|
for (const recId in inProgressRecs) {
|
|
if (inProgressRecs.hasOwnProperty(recId)) {
|
|
const inProgressRecord = inProgressRecs[recId];
|
|
const childRecords = inProgressRecord.getChildRecords();
|
|
let lastChildRecordId = rootParentRecordId;
|
|
if (childRecords.length > 0) {
|
|
lastChildRecordId = childRecords[childRecords.length - 1].getRecordId();
|
|
}
|
|
|
|
recordIdPairs.push(`${inProgressRecord.getRecordId()}.${lastChildRecordId}`);
|
|
}
|
|
}
|
|
|
|
let url = URL_GET_LOG_UPDATES;
|
|
if ($('automaticExpandBottom').checked) {
|
|
url += '/get-all-new-records/true';
|
|
}
|
|
|
|
new Ajax.Request(url, {
|
|
// perform POST request as list of parent IDs could be long and exceed URL length limit
|
|
// (the problem is more actual for IIS which has more strict limits)
|
|
method: 'post',
|
|
parameters: {
|
|
'in-progress-record-ids': recordIdPairs.join(','),
|
|
},
|
|
onSuccess(response) {
|
|
if (!appState.mounted) {
|
|
return;
|
|
}
|
|
|
|
const recordsData = response.responseText.evalJSON();
|
|
if (recordsData.length > 0) {
|
|
logRecords.appendRecords(recordsData);
|
|
|
|
if ($('automaticExpandBottom').checked) {
|
|
const recordIds = [];
|
|
recordsData.forEach(function (recordData) {
|
|
recordIds.push(recordData.recordId);
|
|
});
|
|
logRecords.expandRecordsByIdsRaw(recordIds);
|
|
}
|
|
|
|
if ($('automaticScrollBottom').checked) {
|
|
scrollToBottom();
|
|
}
|
|
}
|
|
},
|
|
onComplete() {
|
|
setTimeout(function () {
|
|
periodicUpdateLog();
|
|
}, 2000);
|
|
},
|
|
});
|
|
}
|
|
|
|
function scrollToBottom() {
|
|
window.scrollTo(0, document.body.scrollHeight);
|
|
}
|
|
|
|
function synchronizeScrollCheckboxes() {
|
|
$('automaticScrollTop').observe('change', function (e) {
|
|
$('automaticScrollBottom').checked = $('automaticScrollTop').checked;
|
|
});
|
|
$('automaticScrollBottom').observe('change', function (e) {
|
|
$('automaticScrollTop').checked = $('automaticScrollBottom').checked;
|
|
});
|
|
}
|
|
|
|
function observeDebugCheckboxes() {
|
|
$('showDebugTop').observe('change', function (e) {
|
|
$('showDebugBottom').checked = $('showDebugTop').checked;
|
|
logRecords.toggleDebug();
|
|
});
|
|
$('showDebugBottom').observe('change', function (e) {
|
|
$('showDebugTop').checked = $('showDebugBottom').checked;
|
|
logRecords.toggleDebug();
|
|
});
|
|
}
|
|
|
|
function synchronizeAutomaticExpandCheckboxes() {
|
|
$('automaticExpandTop').observe('change', function (e) {
|
|
$('automaticExpandBottom').checked = $('automaticExpandTop').checked;
|
|
});
|
|
$('automaticExpandBottom').observe('change', function (e) {
|
|
$('automaticExpandTop').checked = $('automaticExpandBottom').checked;
|
|
});
|
|
}
|
|
|
|
function observeSearch() {
|
|
function startSearch(searchText) {
|
|
if (!searchText) {
|
|
return;
|
|
}
|
|
|
|
new Ajax.Request(URL_SEARCH_LOG_RECORDS, {
|
|
parameters: {
|
|
'search-text': searchText,
|
|
},
|
|
onSuccess(response) {
|
|
const parentRecordIds = response.responseText.evalJSON();
|
|
logRecords.expandRecordsByIds(parentRecordIds);
|
|
},
|
|
});
|
|
}
|
|
|
|
$('buttonSearch').observe('click', function () {
|
|
const searchText = $('searchText').value;
|
|
logRecords.setHighlightText(searchText);
|
|
logRecords.setFilterText('');
|
|
startSearch(searchText);
|
|
});
|
|
$('buttonFilter').observe('click', function () {
|
|
const searchText = $('searchText').value;
|
|
logRecords.setHighlightText(searchText);
|
|
logRecords.setFilterText(searchText);
|
|
startSearch(searchText);
|
|
});
|
|
}
|
|
|
|
function highlight(text, search) {
|
|
if (!search) {
|
|
return text.escapeHTML();
|
|
}
|
|
|
|
const startIndex = text.toLowerCase().indexOf(search.toLowerCase());
|
|
if (startIndex === -1) {
|
|
return text.escapeHTML();
|
|
}
|
|
return (
|
|
`${text.substr(0, startIndex).escapeHTML()
|
|
}<span class="plesk-migrator-log-search-highlight">${
|
|
text.substr(startIndex, search.length).escapeHTML()
|
|
}</span>${
|
|
highlight(text.substr(startIndex + search.length), search)}`
|
|
);
|
|
}
|
|
|
|
var logRecords = new LogRecords();
|
|
logRecords.appendRecords(INITIAL_LOG_RECORDS);
|
|
|
|
synchronizeScrollCheckboxes();
|
|
observeDebugCheckboxes();
|
|
synchronizeAutomaticExpandCheckboxes();
|
|
observeSearch();
|
|
periodicUpdateLog();
|
|
});
|