// Copyright 1999-2024. WebPros International GmbH. All rights reserved. Jsw.onReady(function() { const appState = PanelMigrator.initAppState(); var severityLevel = { INFO: 1, ERROR: 2, WARNING: 3, DEBUG: 4, EXCEPTION: 5, MIGRATOR_EXECUTION: 6 }; var 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' }; var LogRecords = Class.create({ initialize: function() { 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: function(recordsData) { for (var i = 0; i < recordsData.length; i++) { var recordData = recordsData[i]; this.appendRecord(recordData); } }, appendRecord: function(recordData) { if (this._records[recordData.recordId]) { var 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; } var parentRecord = null; var rootParentRecordId = 2147483647; if (recordData.parentRecordId != rootParentRecordId) { parentRecord = this._records[recordData.parentRecordId]; } var 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: function(record) { this.expandRecordsByIds([record.getRecordId()]); }, expandRecordsByIds: function(recordIds) { var self = this; var collapsedRecordIds = []; for (var i = 0; i < recordIds.length; i++) { var recordId = recordIds[i]; if (self._expandedRecords[recordId] != 1) { collapsedRecordIds.push(recordId); } } if (collapsedRecordIds.length == 0) { return } var 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). var maxPartSize = 50; var 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: function (response) { var recordsData = response.responseText.evalJSON(); self.appendRecords(recordsData); for (var i = 0; i < collapsedRecordIdsPart.length; i++) { var recordId = collapsedRecordIdsPart[i]; self._records[recordId].setExpanded(); self._expandedRecords[recordId] = 1; for (var j = 0; j < self._records[recordId].getChildRecords().length; j++) { var childRecord = self._records[recordId].getChildRecords()[j]; self.updateRecordVisibility(childRecord); } } }, onComplete: function() { onSuccess(); } }); }); }); callAsyncFunctionsChain(requestFunctions); }, expandRecordsByIdsRaw: function(recordIds) { var self = this; for (var i = 0; i < recordIds.length; i++) { var recordId = recordIds[i]; if (self._expandedRecords[recordId] == 1) { continue; } if (!self._records[recordId].isExpandable()) { continue; } self._records[recordId].setExpanded(); self._expandedRecords[recordId] = 1; for (var j = 0; j < self._records[recordId].getChildRecords().length; j++) { var childRecord = self._records[recordId].getChildRecords()[j]; self.updateRecordVisibility(childRecord); } } }, collapseRecord: function(record) { for (var i = 0; i < record.getChildRecords().length; i++) { var childRecord = record.getChildRecords()[i]; for (var j = 0; j < childRecord.getChildRecords().length; j++) { var 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: function(record) { for (var i = 0; i < record.getChildRecords().length; i++) { var childRecord = record.getChildRecords()[i]; this._removeRecord(childRecord); } delete this._records[record.getRecordId()]; record.getHtmlRow().remove(); record.getHtmlEndRow().remove(); }, toggleDebug: function() { var self = this; this._showDebug = !this._showDebug; this._foreachRecord(function(record) { self.updateRecordVisibility(record); }); this._foreachRecord(function(record) { self.updateRecordExpandability(record); }); }, getExpandedRecordIds: function() { return Object.keys(this._expandedRecords); }, getInProgressRecords: function () { return this._inProgressRecords; }, getRootRecords: function() { return this._rootRecords; }, setHighlightText: function(searchText) { var self = this; this._highlightText = searchText; this._foreachRecord(function(record) { record.highlightText(searchText) }); this._foreachRecord(function(record) { self.updateRecordExpandability(record); }); }, setFilterText: function(searchText) { var self = this; this._filterText = searchText; this._foreachRecord(function(record) { self.updateRecordVisibility(record); }); this._foreachRecord(function(record) { self.updateRecordExpandability(record); }); }, updateRecordVisibility: function(record) { if (this._isFiltered(record)) { record.hide(); return; } if (record.getParentRecord() &&!record.getParentRecord().isExpanded()) { record.hide(); return; } record.show(); }, updateRecordExpandability: function(record) { for (var i = 0; i < record.getChildRecords().length; i++) { var childRecord = record.getChildRecords()[i]; if (!this._isFiltered(childRecord)) { record.setExpandable(true); return; } } record.setExpandable(false); }, _foreachRecord: function(callback) { var self = this; Object.keys(this._records).forEach(function(key, index) { var record = self._records[key]; callback(record); }); }, _isFiltered: function(record) { return ( (record.isDebug() && !this._showDebug) || ( this._filterText && !(record.getMessage().toLowerCase().indexOf(this._filterText.toLowerCase()) > -1) ) ); } }); var LogRecord = Class.create({ initialize: function(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: function() { var messageCellProperties = { 'style': 'white-space: pre-wrap; word-wrap: break-word; padding-left: ' + (this.getLevel() * 50) + 'px', 'class': 'messageText' }; var severityDescriptor = severityProperties[this._severity]; var rowProperties = {'class': severityDescriptor.rowCssClass + ' logItemRow', 'style': 'display: none'}; var 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); var 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', 'style': 'display: none' } ); this._htmlCollapseIcon = new Element( 'img', { 'src': migratorImage('log-collapse-icon.gif'), 'class': 'plesk-migrator-expand-image', 'style': 'display: none' } ); 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._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: function(record) { this._childRecords.push(record); }, getChildRecords: function() { return this._childRecords; }, removeAllChildRecords: function() { this._childRecords = []; }, getHtmlRow: function() { return this._htmlRow; }, // Get fake hidden HTML row, which marks place right after the last child record. // So, DOM tree will look like: //