first commit
This commit is contained in:
commit
1218dd1517
12716 files changed
+989233
No files matched your search
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
require([
|
||||
'jquery',
|
||||
], function($) {
|
||||
'use strict';
|
||||
|
||||
$(function() {
|
||||
BackendUserConfirmation.addFocusToFormInput();
|
||||
});
|
||||
|
||||
var BackendUserConfirmation = {
|
||||
confirmationPassword: '#confirmationPassword',
|
||||
|
||||
addFocusToFormInput: function () {
|
||||
var $confirmationPassword = $(this.confirmationPassword);
|
||||
if ($confirmationPassword.length) {
|
||||
$confirmationPassword.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
require([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router'
|
||||
], function($, Router) {
|
||||
'use strict';
|
||||
|
||||
$(function() {
|
||||
Router.initialize();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Walk through the installation process of TYPO3
|
||||
*/
|
||||
require([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/PasswordStrength'
|
||||
], function($, InfoBox, Severity, ProgressBar, PasswordStrength) {
|
||||
'use strict';
|
||||
|
||||
$(function() {
|
||||
Installer.initialize();
|
||||
});
|
||||
|
||||
var Installer = {
|
||||
selectorBody: '.t3js-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorMainContent: '.t3js-installer-content',
|
||||
selectorProgressBar: '.t3js-installer-progress',
|
||||
selectorDatabaseConnectOutput: '.t3js-installer-databaseConnect-output',
|
||||
selectorDatabaseSelectOutput: '.t3js-installer-databaseSelect-output',
|
||||
selectorDatabaseDataOutput: '.t3js-installer-databaseData-output',
|
||||
selectorDefaultConfigurationOutput: '.t3js-installer-defaultConfiguration-output',
|
||||
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
|
||||
$(document).on('click', '.t3js-installer-environmentFolders-retry', function(e) {
|
||||
e.preventDefault();
|
||||
self.showEnvironmentAndFolders();
|
||||
});
|
||||
$(document).on('click', '.t3js-installer-environmentFolders-execute', function(e) {
|
||||
e.preventDefault();
|
||||
self.executeEnvironmentAndFolders();
|
||||
});
|
||||
$(document).on('click', '.t3js-installer-databaseConnect-execute', function(e) {
|
||||
e.preventDefault();
|
||||
self.executeDatabaseConnect();
|
||||
});
|
||||
$(document).on('click', '.t3js-installer-databaseSelect-execute', function(e) {
|
||||
e.preventDefault();
|
||||
self.executeDatabaseSelect();
|
||||
});
|
||||
$(document).on('click', '.t3js-installer-databaseData-execute', function(e) {
|
||||
e.preventDefault();
|
||||
self.executeDatabaseData();
|
||||
});
|
||||
$(document).on('click', '.t3js-installer-defaultConfiguration-execute', function(e) {
|
||||
e.preventDefault();
|
||||
self.executeDefaultConfiguration();
|
||||
});
|
||||
|
||||
$(document).on('keyup', '.t3-install-form-password-strength', function() {
|
||||
PasswordStrength.initialize('.t3-install-form-password-strength');
|
||||
});
|
||||
|
||||
// Database connect db driver selection
|
||||
$(document).on('change', '#t3js-connect-database-driver', function() {
|
||||
var driver = $(this).val();
|
||||
$('.t3-install-driver-data').hide();
|
||||
$('.t3-install-driver-data input').attr('disabled', 'disabled');
|
||||
$('#' + driver + ' input').attr('disabled', false);
|
||||
$('#' + driver).show();
|
||||
});
|
||||
|
||||
this.setProgress(0);
|
||||
this.getMainLayout();
|
||||
},
|
||||
|
||||
getUrl: function(action) {
|
||||
var url = location.href;
|
||||
url = url.replace(location.search, '');
|
||||
if (action !== undefined) {
|
||||
url = url + '?install[action]=' + action;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
setProgress: function(done) {
|
||||
var $progressBar = $(this.selectorProgressBar);
|
||||
var percent = 0;
|
||||
if (done !== 0) {
|
||||
percent = (done / 5) * 100;
|
||||
$progressBar.find('.progress-bar').empty().text(done + ' / 5 - ' + percent + '% Complete');
|
||||
}
|
||||
$progressBar
|
||||
.find('.progress-bar')
|
||||
.css('width', percent + '%')
|
||||
.attr('aria-valuenow', percent);
|
||||
},
|
||||
|
||||
getMainLayout: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('mainLayout'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
$(self.selectorBody).empty().append(data.html);
|
||||
self.checkInstallerAvailable();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
checkInstallerAvailable: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('checkInstallerAvailable'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkEnvironmentAndFolders();
|
||||
} else {
|
||||
self.showInstallerNotAvailable();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showInstallerNotAvailable: function() {
|
||||
var $outputContainer = $(this.selectorMainContent);
|
||||
$.ajax({
|
||||
url: this.getUrl('showInstallerNotAvailable'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$outputContainer.empty().append(data.html);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkEnvironmentAndFolders: function() {
|
||||
var self = this;
|
||||
this.setProgress(1);
|
||||
$.ajax({
|
||||
url: this.getUrl('checkEnvironmentAndFolders'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkTrustedHostsPattern();
|
||||
} else {
|
||||
self.showEnvironmentAndFolders();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showEnvironmentAndFolders: function() {
|
||||
var $outputContainer = $(this.selectorMainContent);
|
||||
$.ajax({
|
||||
url: this.getUrl('showEnvironmentAndFolders'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$outputContainer.empty().html(data.html);
|
||||
var $detailContainer = $('.t3js-installer-environment-details');
|
||||
var hasMessage = false;
|
||||
if (Array.isArray(data.environmentStatusErrors)) {
|
||||
data.environmentStatusErrors.forEach(function(element) {
|
||||
hasMessage = true;
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$detailContainer.append(message);
|
||||
});
|
||||
}
|
||||
if (Array.isArray(data.environmentStatusWarnings)) {
|
||||
data.environmentStatusWarnings.forEach(function(element) {
|
||||
hasMessage = true;
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$detailContainer.append(message);
|
||||
});
|
||||
}
|
||||
if (Array.isArray(data.structureErrors)) {
|
||||
data.structureErrors.forEach(function(element) {
|
||||
hasMessage = true;
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$detailContainer.append(message);
|
||||
});
|
||||
}
|
||||
if (hasMessage === true) {
|
||||
$detailContainer.show();
|
||||
$('.t3js-installer-environmentFolders-bad').show();
|
||||
} else {
|
||||
$('.t3js-installer-environmentFolders-good').show();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeEnvironmentAndFolders: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('executeEnvironmentAndFolders'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkTrustedHostsPattern();
|
||||
} else {
|
||||
// @todo message output handling
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkTrustedHostsPattern: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('checkTrustedHostsPattern'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.executeSilentConfigurationUpdate();
|
||||
} else {
|
||||
self.executeAdjustTrustedHostsPattern();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeAdjustTrustedHostsPattern: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('executeAdjustTrustedHostsPattern'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
self.executeSilentConfigurationUpdate();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeSilentConfigurationUpdate: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('executeSilentConfigurationUpdate'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkDatabaseConnect();
|
||||
} else {
|
||||
self.executeSilentConfigurationUpdate();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkDatabaseConnect: function() {
|
||||
this.setProgress(2);
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('checkDatabaseConnect'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkDatabaseSelect();
|
||||
} else {
|
||||
self.showDatabaseConnect();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showDatabaseConnect: function() {
|
||||
var $outputContainer = $(this.selectorMainContent);
|
||||
$.ajax({
|
||||
url: this.getUrl('showDatabaseConnect'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$outputContainer.empty().html(data.html);
|
||||
$('#t3js-connect-database-driver').trigger('change');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeDatabaseConnect: function() {
|
||||
var self = this;
|
||||
var $outputContainer = $(this.selectorDatabaseConnectOutput);
|
||||
var postData = {
|
||||
'install[action]': 'executeDatabaseConnect',
|
||||
'install[token]': $(self.selectorModuleContent).data('installer-database-connect-execute-token')
|
||||
};
|
||||
$($(this.selectorBody + ' form').serializeArray()).each(function() {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
$.ajax({
|
||||
url: this.getUrl(),
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkDatabaseSelect();
|
||||
} else {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.empty().append(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkDatabaseSelect: function() {
|
||||
var self = this;
|
||||
this.setProgress(3);
|
||||
$.ajax({
|
||||
url: this.getUrl('checkDatabaseSelect'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkDatabaseData();
|
||||
} else {
|
||||
self.showDatabaseSelect();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showDatabaseSelect: function() {
|
||||
var $outputContainer = $(this.selectorMainContent);
|
||||
$.ajax({
|
||||
url: this.getUrl('showDatabaseSelect'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$outputContainer.empty().html(data.html);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeDatabaseSelect: function() {
|
||||
var self = this;
|
||||
var $outputContainer = $(this.selectorDatabaseSelectOutput);
|
||||
var postData = {
|
||||
'install[action]': 'executeDatabaseSelect',
|
||||
'install[token]': $(self.selectorModuleContent).data('installer-database-select-execute-token')
|
||||
};
|
||||
$($(this.selectorBody + ' form').serializeArray()).each(function() {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
$.ajax({
|
||||
url: this.getUrl(),
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkDatabaseData();
|
||||
} else {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.empty().append(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkDatabaseData: function() {
|
||||
var self = this;
|
||||
this.setProgress(4);
|
||||
$.ajax({
|
||||
url: this.getUrl('checkDatabaseData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.showDefaultConfiguration();
|
||||
} else {
|
||||
self.showDatabaseData();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showDatabaseData: function() {
|
||||
var $outputContainer = $(this.selectorMainContent);
|
||||
$.ajax({
|
||||
url: this.getUrl('showDatabaseData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$outputContainer.empty().html(data.html);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeDatabaseData: function() {
|
||||
var self = this;
|
||||
var $outputContainer = $(this.selectorDatabaseDataOutput);
|
||||
var postData = {
|
||||
'install[action]': 'executeDatabaseData',
|
||||
'install[token]': $(self.selectorModuleContent).data('installer-database-data-execute-token')
|
||||
};
|
||||
$($(this.selectorBody + ' form').serializeArray()).each(function() {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().html(message);
|
||||
$.ajax({
|
||||
url: this.getUrl(),
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.showDefaultConfiguration();
|
||||
} else {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.empty().append(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showDefaultConfiguration: function() {
|
||||
var $outputContainer = $(this.selectorMainContent);
|
||||
this.setProgress(5);
|
||||
$.ajax({
|
||||
url: this.getUrl('showDefaultConfiguration'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$outputContainer.empty().html(data.html);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
executeDefaultConfiguration: function() {
|
||||
var self = this;
|
||||
var postData = {
|
||||
'install[action]': 'executeDefaultConfiguration',
|
||||
'install[token]': $(self.selectorModuleContent).data('installer-default-configuration-execute-token')
|
||||
};
|
||||
$($(this.selectorBody + ' form').serializeArray()).each(function() {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
$.ajax({
|
||||
url: this.getUrl(),
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
success: function(data) {
|
||||
top.location.href = data.redirect;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/AjaxQueue
|
||||
*/
|
||||
define(['jquery'], function($) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
requests: [],
|
||||
requestCount: 0,
|
||||
threshold: 5,
|
||||
queue: [],
|
||||
|
||||
add: function(payload) {
|
||||
this.queue.push(payload);
|
||||
this.handleNext();
|
||||
},
|
||||
|
||||
flush: function() {
|
||||
this.queue = [];
|
||||
this.requests.map(function(request) {
|
||||
request.abort();
|
||||
});
|
||||
this.requests = [];
|
||||
},
|
||||
|
||||
handleNext: function() {
|
||||
if (this.queue.length > 0 && this.requestCount < this.threshold) {
|
||||
var that = this;
|
||||
this.incrementRequestCount();
|
||||
this.sendRequest(that.queue.shift()).always(function() {
|
||||
that.decrementRequestCount();
|
||||
that.handleNext();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
sendRequest: function(payload) {
|
||||
var that = this;
|
||||
var xhr = $.ajax(payload);
|
||||
this.requests.push(xhr);
|
||||
xhr.always(function() {
|
||||
const idx = that.requests.indexOf(xhr);
|
||||
delete that.requests[idx];
|
||||
});
|
||||
|
||||
return xhr;
|
||||
},
|
||||
|
||||
incrementRequestCount: function() {
|
||||
this.requestCount++;
|
||||
},
|
||||
|
||||
decrementRequestCount: function() {
|
||||
if (this.requestCount > 0) {
|
||||
this.requestCount--;
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/Cache
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Backend/Icons',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, Icons, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
initialize: function($trigger) {
|
||||
$.ajax({
|
||||
url: Router.getUrl('cacheClearAll', 'maintenance'),
|
||||
cache: false,
|
||||
beforeSend: function() {
|
||||
$trigger.addClass('disabled');
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
if (data.status.length > 0) {
|
||||
data.status.forEach((function(element) {
|
||||
Notification.success(element.title, element.message);
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong clearing caches');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
// In case the clear cache action fails (typically 500 from server), do not kill the entire
|
||||
// install tool, instead show a notification that something went wrong.
|
||||
Notification.error(
|
||||
'Clearing caches went wrong on the server side. Check the system for broken extensions or missing database tables and try again'
|
||||
);
|
||||
},
|
||||
complete: function() {
|
||||
$trigger.removeClass('disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/CreateAdmin
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Install/PasswordStrength',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, Severity, PasswordStrength, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorChangeForm: '#t3js-changeInstallToolPassword-form',
|
||||
selectorOutputContainer: '.t3js-changeInstallToolPassword-output',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
|
||||
currentModal.on('submit', this.selectorChangeForm, function(e) {
|
||||
e.preventDefault();
|
||||
self.change();
|
||||
});
|
||||
currentModal.on('click', '.t3-install-form-password-strength', function(e) {
|
||||
PasswordStrength.initialize('.t3-install-form-password-strength');
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('changeInstallToolPasswordGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
change: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('install-tool-token');
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'changeInstallToolPassword',
|
||||
'token': executeToken,
|
||||
'password': self.currentModal.find('.t3js-changeInstallToolPassword-password').val(),
|
||||
'passwordCheck': self.currentModal.find('.t3js-changeInstallToolPassword-password-check').val()
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.showMessage('', element.message, element.severity);
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
},
|
||||
complete: function() {
|
||||
self.currentModal.find('.t3js-changeInstallToolPassword-password,.t3js-changeInstallToolPassword-password-check').val('')
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ClearTable
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorClearTrigger: '.t3js-clearTables-clear',
|
||||
selectorStatsTrigger: '.t3js-clearTables-stats',
|
||||
selectorOutputContainer: '.t3js-clearTables-output',
|
||||
selectorStatContainer: '.t3js-clearTables-stat-container',
|
||||
selectorStatTemplate: '.t3js-clearTables-stat-template',
|
||||
selectorStatDescription: '.t3js-clearTables-stat-description',
|
||||
selectorStatRows: '.t3js-clearTables-stat-rows',
|
||||
selectorStatName: '.t3js-clearTables-stat-name',
|
||||
selectorStatLastRuler: '.t3js-clearTables-stat-lastRuler',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getStats();
|
||||
|
||||
currentModal.on('click', this.selectorStatsTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
$(self.selectorOutputContainer).empty();
|
||||
self.getStats();
|
||||
});
|
||||
|
||||
currentModal.on('click', this.selectorClearTrigger, function(e) {
|
||||
var table = $(e.target).closest(self.selectorClearTrigger).data('table');
|
||||
e.preventDefault();
|
||||
self.clear(table);
|
||||
});
|
||||
},
|
||||
|
||||
getStats: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('clearTablesStats'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
if (Array.isArray(data.stats) && data.stats.length > 0) {
|
||||
data.stats.forEach(function(element) {
|
||||
if (element.rowCount > 0) {
|
||||
var aStat = modalContent.find(self.selectorStatTemplate).clone();
|
||||
aStat.find(self.selectorStatDescription).text(element.description);
|
||||
aStat.find(self.selectorStatName).text(element.name);
|
||||
aStat.find(self.selectorStatRows).text(element.rowCount);
|
||||
aStat.find(self.selectorClearTrigger).attr('data-table', element.name);
|
||||
modalContent.find(self.selectorStatContainer).append(aStat.html());
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clear: function(table) {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('clear-tables-clear-token');
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
context: this,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'clearTablesClear',
|
||||
'token': executeToken,
|
||||
'table': table
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.message);
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
this.getStats();
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ClearTypo3tempFiles
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorDeleteTrigger: '.t3js-clearTypo3temp-delete',
|
||||
selectorOutputContainer: '.t3js-clearTypo3temp-output',
|
||||
selectorStatContainer: '.t3js-clearTypo3temp-stat-container',
|
||||
selectorStatsTrigger: '.t3js-clearTypo3temp-stats',
|
||||
selectorStatTemplate: '.t3js-clearTypo3temp-stat-template',
|
||||
selectorStatDescription: '.t3js-clearTypo3temp-stat-description',
|
||||
selectorStatNumberOfFiles: '.t3js-clearTypo3temp-stat-numberOfFiles',
|
||||
selectorStatDirectory: '.t3js-clearTypo3temp-stat-directory',
|
||||
selectorStatName: '.t3js-clearTypo3temp-stat-name',
|
||||
selectorStatLastRuler: '.t3js-clearTypo3temp-stat-lastRuler',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getStats();
|
||||
|
||||
currentModal.on('click', this.selectorStatsTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
$(self.selectorOutputContainer).empty();
|
||||
self.getStats();
|
||||
});
|
||||
currentModal.on('click', this.selectorDeleteTrigger, function(e) {
|
||||
var folder = $(this).data('folder');
|
||||
var storageUid = $(this).data('storage-uid');
|
||||
e.preventDefault();
|
||||
self.delete(folder, storageUid);
|
||||
});
|
||||
},
|
||||
|
||||
getStats: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('clearTypo3tempFilesStats'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
if (Array.isArray(data.stats) && data.stats.length > 0) {
|
||||
data.stats.forEach(function(element) {
|
||||
if (element.numberOfFiles > 0) {
|
||||
var aStat = modalContent.find(self.selectorStatTemplate).clone();
|
||||
aStat.find(self.selectorStatNumberOfFiles).text(element.numberOfFiles);
|
||||
aStat.find(self.selectorStatDirectory).text(element.directory);
|
||||
aStat.find(self.selectorDeleteTrigger).attr('data-folder', element.directory);
|
||||
aStat.find(self.selectorDeleteTrigger).attr('data-storage-uid', element.storageUid);
|
||||
modalContent.find(self.selectorStatContainer).append(aStat.html());
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
delete: function(folder, storageUid) {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('clear-typo3temp-delete-token');
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: Router.getUrl(),
|
||||
context: this,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'clearTypo3tempFiles',
|
||||
'token': executeToken,
|
||||
'folder': folder,
|
||||
'storageUid': storageUid
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.message);
|
||||
});
|
||||
this.getStats();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/CoreUpdate
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
/**
|
||||
* The action queue defines what actions are called in which order
|
||||
*/
|
||||
actionQueue: {
|
||||
coreUpdateIsUpdateAvailable: {
|
||||
loadingMessage: 'Checking for possible regular or security update',
|
||||
finishMessage: undefined,
|
||||
nextActionName: undefined
|
||||
},
|
||||
coreUpdateCheckPreConditions: {
|
||||
loadingMessage: 'Checking if update is possible',
|
||||
finishMessage: 'System can be updated',
|
||||
nextActionName: 'coreUpdateDownload'
|
||||
},
|
||||
coreUpdateDownload: {
|
||||
loadingMessage: 'Downloading new core',
|
||||
finishMessage: undefined,
|
||||
nextActionName: 'coreUpdateVerifyChecksum'
|
||||
},
|
||||
coreUpdateVerifyChecksum: {
|
||||
loadingMessage: 'Verifying checksum of downloaded core',
|
||||
finishMessage: undefined,
|
||||
nextActionName: 'coreUpdateUnpack'
|
||||
},
|
||||
coreUpdateUnpack: {
|
||||
loadingMessage: 'Unpacking core',
|
||||
finishMessage: undefined,
|
||||
nextActionName: 'coreUpdateMove'
|
||||
},
|
||||
coreUpdateMove: {
|
||||
loadingMessage: 'Moving core',
|
||||
finishMessage: undefined,
|
||||
nextActionName: 'coreUpdateActivate'
|
||||
},
|
||||
coreUpdateActivate: {
|
||||
loadingMessage: 'Activating core',
|
||||
finishMessage: 'Core updated - please reload your browser',
|
||||
nextActionName: undefined
|
||||
}
|
||||
},
|
||||
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorOutput: '.t3js-coreUpdate-output',
|
||||
selectorTemplate: '.t3js-coreUpdate-buttonTemplate',
|
||||
|
||||
/**
|
||||
* Clone of a DOM object acts as button template
|
||||
*/
|
||||
buttonTemplate: null,
|
||||
|
||||
/**
|
||||
* Fetching the templates out of the DOM
|
||||
*/
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData().done(function() {
|
||||
var buttonTemplateSection = currentModal.find(self.selectorTemplate);
|
||||
self.buttonTemplate = buttonTemplateSection.children().clone();
|
||||
});
|
||||
|
||||
currentModal.on('click', '.t3js-coreUpdate-init', function(e) {
|
||||
e.preventDefault();
|
||||
// Don't use jQuery's data() function, as the DOM is re-rendered and any set data attribute gets lost.
|
||||
// See showActionButton()
|
||||
var action = $(e.target).attr('data-action');
|
||||
currentModal.find(self.selectorOutput).empty();
|
||||
self[action]();
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
return $.ajax({
|
||||
url: Router.getUrl('coreUpdateGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Public method checkForUpdate
|
||||
*/
|
||||
checkForUpdate: function() {
|
||||
this.callAction('coreUpdateIsUpdateAvailable');
|
||||
},
|
||||
|
||||
/**
|
||||
* Public method updateDevelopment
|
||||
*/
|
||||
updateDevelopment: function() {
|
||||
this.update('development');
|
||||
},
|
||||
|
||||
updateRegular: function() {
|
||||
this.update('regular');
|
||||
},
|
||||
|
||||
/**
|
||||
* Execute core update.
|
||||
*
|
||||
* @param type Either 'development' or 'regular'
|
||||
*/
|
||||
update: function(type) {
|
||||
if (type !== 'development') {
|
||||
type = 'regular';
|
||||
}
|
||||
this.callAction('coreUpdateCheckPreConditions', type);
|
||||
},
|
||||
|
||||
/**
|
||||
* Generic method to call actions from the queue
|
||||
*
|
||||
* @param actionName Name of the action to be called
|
||||
* @param type Update type (optional)
|
||||
*/
|
||||
callAction: function(actionName, type) {
|
||||
var self = this;
|
||||
var data = {
|
||||
install: {
|
||||
action: actionName
|
||||
}
|
||||
};
|
||||
if (type !== undefined) {
|
||||
data.install["type"] = type;
|
||||
}
|
||||
this.addLoadingMessage(this.actionQueue[actionName].loadingMessage);
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
data: data,
|
||||
cache: false,
|
||||
success: function(result) {
|
||||
var canContinue = self.handleResult(result, self.actionQueue[actionName].finishMessage);
|
||||
if (canContinue === true && (self.actionQueue[actionName].nextActionName !== undefined)) {
|
||||
self.callAction(self.actionQueue[actionName].nextActionName, type);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, self.currentModal.find(self.selectorModalBody));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle ajax result of core update step.
|
||||
*
|
||||
* @param data
|
||||
* @param successMessage Optional success message
|
||||
*/
|
||||
handleResult: function(data, successMessage) {
|
||||
var canContinue = data.success;
|
||||
this.removeLoadingMessage();
|
||||
|
||||
if (data.status && typeof(data.status) === 'object') {
|
||||
this.showStatusMessages(data.status);
|
||||
}
|
||||
if (data.action && typeof(data.action) === 'object') {
|
||||
this.showActionButton(data.action);
|
||||
}
|
||||
if (canContinue && successMessage) {
|
||||
this.addMessage(Severity.ok, successMessage);
|
||||
}
|
||||
return canContinue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a loading message with some text.
|
||||
*
|
||||
* @param messageTitle
|
||||
*/
|
||||
addLoadingMessage: function(messageTitle) {
|
||||
var domMessage = FlashMessage.render(Severity.loading, messageTitle);
|
||||
this.currentModal.find(this.selectorOutput).append(domMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an enabled loading message
|
||||
*/
|
||||
removeLoadingMessage: function() {
|
||||
this.currentModal.find(this.selectorOutput).find('.alert-loading').remove();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a list of status messages
|
||||
*
|
||||
* @param messages
|
||||
*/
|
||||
showStatusMessages: function(messages) {
|
||||
var self = this;
|
||||
$.each(messages, function(index, element) {
|
||||
var title = false;
|
||||
var message = false;
|
||||
var severity = element.severity;
|
||||
if (element.title) {
|
||||
title = element.title;
|
||||
}
|
||||
if (element.message) {
|
||||
message = element.message;
|
||||
}
|
||||
self.addMessage(severity, title, message);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Show an action button
|
||||
*
|
||||
* @param button
|
||||
*/
|
||||
showActionButton: function(button) {
|
||||
var title = false;
|
||||
var action = false;
|
||||
if (button.title) {
|
||||
title = button.title;
|
||||
}
|
||||
if (button.action) {
|
||||
action = button.action;
|
||||
}
|
||||
var domButton = this.buttonTemplate;
|
||||
if (action) {
|
||||
domButton.attr('data-action', action);
|
||||
}
|
||||
if (title) {
|
||||
domButton.text(title);
|
||||
}
|
||||
this.currentModal.find(this.selectorOutput).append(domButton);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a status message
|
||||
*
|
||||
* @param severity
|
||||
* @param title
|
||||
* @param message
|
||||
*/
|
||||
addMessage: function(severity, title, message) {
|
||||
var domMessage = FlashMessage.render(severity, title, message);
|
||||
this.currentModal.find(this.selectorOutput).append(domMessage);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/CreateAdmin
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Install/PasswordStrength',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, PasswordStrength, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorCreateForm: '#t3js-createAdmin-form',
|
||||
selectorOutputContainer: '.t3js-createAdmin-output',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
|
||||
currentModal.on('submit', this.selectorCreateForm, function(e) {
|
||||
e.preventDefault();
|
||||
self.create();
|
||||
});
|
||||
|
||||
currentModal.on('click', '.t3-install-form-password-strength', function(e) {
|
||||
PasswordStrength.initialize('.t3-install-form-password-strength');
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('createAdminGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
create: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('create-admin-token');
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'createAdmin',
|
||||
'token': executeToken,
|
||||
'userName': self.currentModal.find('.t3js-createAdmin-user').val(),
|
||||
'userPassword': self.currentModal.find('.t3js-createAdmin-password').val(),
|
||||
'userPasswordCheck': self.currentModal.find('.t3js-createAdmin-password-check').val(),
|
||||
'userSystemMaintainer': (self.currentModal.find('.t3js-createAdmin-system-maintainer').is(':checked')) ? 1 : 0
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
if (element.severity == 2) {
|
||||
Notification.error(element.message);
|
||||
}
|
||||
else {
|
||||
Notification.success(element.title);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
this.currentModal.find('.t3js-createAdmin-user').val('');
|
||||
this.currentModal.find('.t3js-createAdmin-password').val('');
|
||||
this.currentModal.find('.t3js-createAdmin-password-check').val('');
|
||||
this.currentModal.find('.t3js-createAdmin-system-maintainer').prop('checked', false);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/DatabaseAnalyzer
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorAnalyzeTrigger: '.t3js-databaseAnalyzer-analyze',
|
||||
selectorExecuteTrigger: '.t3js-databaseAnalyzer-execute',
|
||||
selectorOutputContainer: '.t3js-databaseAnalyzer-output',
|
||||
selectorSuggestionBlock: '.t3js-databaseAnalyzer-suggestion-block',
|
||||
selectorSuggestionList: '.t3js-databaseAnalyzer-suggestion-list',
|
||||
selectorSuggestionLine: '.t3js-databaseAnalyzer-suggestion-line',
|
||||
selectorSuggestionLineTemplate: '.t3js-databaseAnalyzer-suggestion-line-template',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
|
||||
// Select / deselect all checkboxes
|
||||
currentModal.on('click', '.t3js-databaseAnalyzer-suggestion-block-checkbox', function(e) {
|
||||
$(this).closest('fieldset').find(':checkbox').prop('checked', this.checked);
|
||||
});
|
||||
currentModal.on('click', this.selectorAnalyzeTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.analyze();
|
||||
});
|
||||
currentModal.on('click', this.selectorExecuteTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.execute();
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('databaseAnalyzer'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
self.analyze();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
analyze: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var outputContainer = modalContent.find(this.selectorOutputContainer);
|
||||
var executeTrigger = modalContent.find(this.selectorExecuteTrigger);
|
||||
var analyzeTrigger = modalContent.find(this.selectorAnalyzeTrigger);
|
||||
|
||||
outputContainer.empty().append(ProgressBar.render(Severity.loading, 'Analyzing current database schema...', ''));
|
||||
|
||||
analyzeTrigger.prop('disabled', true);
|
||||
executeTrigger.prop('disabled', true);
|
||||
|
||||
outputContainer.on('change', 'input[type="checkbox"]', function() {
|
||||
var hasCheckedCheckboxes = outputContainer.find(':checked').length > 0;
|
||||
executeTrigger.prop('disabled', !hasCheckedCheckboxes);
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl('databaseAnalyzerAnalyze'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
outputContainer.find('.alert-loading').remove();
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
outputContainer.append(message);
|
||||
});
|
||||
}
|
||||
if (Array.isArray(data.suggestions)) {
|
||||
data.suggestions.forEach(function(element) {
|
||||
var aBlock = modalContent.find(self.selectorSuggestionBlock).clone();
|
||||
aBlock.removeClass(self.selectorSuggestionBlock.substr(1));
|
||||
var key = element.key;
|
||||
aBlock.find('.t3js-databaseAnalyzer-suggestion-block-legend').text(element.label);
|
||||
aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('id', 't3-install-' + key + '-checkbox');
|
||||
if (element.enabled) {
|
||||
aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('checked', 'checked');
|
||||
}
|
||||
aBlock.find('.t3js-databaseAnalyzer-suggestion-block-label').attr('for', 't3-install-' + key + '-checkbox');
|
||||
element.children.forEach(function(line) {
|
||||
var aLine = modalContent.find(self.selectorSuggestionLineTemplate).children().clone();
|
||||
var hash = line.hash;
|
||||
var $checkbox = aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox');
|
||||
$checkbox.attr('id', 't3-install-db-' + hash).attr('data-hash', hash);
|
||||
if (element.enabled) {
|
||||
$checkbox.attr('checked', 'checked');
|
||||
}
|
||||
aLine.find('.t3js-databaseAnalyzer-suggestion-line-label').attr('for', 't3-install-db-' + hash);
|
||||
aLine.find('.t3js-databaseAnalyzer-suggestion-line-statement').text(line.statement);
|
||||
if (typeof line.current !== 'undefined') {
|
||||
aLine.find('.t3js-databaseAnalyzer-suggestion-line-current-value').text(line.current);
|
||||
aLine.find('.t3js-databaseAnalyzer-suggestion-line-current').show();
|
||||
}
|
||||
if (typeof line.rowCount !== 'undefined') {
|
||||
aLine.find('.t3js-databaseAnalyzer-suggestion-line-count-value').text(line.rowCount);
|
||||
aLine.find('.t3js-databaseAnalyzer-suggestion-line-count').show();
|
||||
}
|
||||
aBlock.find(self.selectorSuggestionList).append(aLine);
|
||||
});
|
||||
outputContainer.append(aBlock.html());
|
||||
});
|
||||
|
||||
var isInitiallyDisabled = outputContainer.find(':checked').length === 0;
|
||||
analyzeTrigger.prop('disabled', false);
|
||||
executeTrigger.prop('disabled', isInitiallyDisabled);
|
||||
}
|
||||
if (data.suggestions.length === 0 && data.status.length === 0) {
|
||||
outputContainer.append(InfoBox.render(Severity.ok, 'Database schema is up to date. Good job!', ''));
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
execute: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('database-analyzer-execute-token');
|
||||
var outputContainer = modalContent.find(this.selectorOutputContainer);
|
||||
var selectedHashes = [];
|
||||
|
||||
outputContainer.find('.t3js-databaseAnalyzer-suggestion-line input:checked').each(function() {
|
||||
selectedHashes.push($(this).data('hash'));
|
||||
});
|
||||
outputContainer.empty().append(ProgressBar.render(Severity.loading, 'Executing database updates...', ''));
|
||||
modalContent.find(this.selectorExecuteTrigger).prop('disabled', true);
|
||||
modalContent.find(this.selectorAnalyzeTrigger).prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'databaseAnalyzerExecute',
|
||||
'token': executeToken,
|
||||
'hashes': selectedHashes
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.showMessage(element.title, element.message, element.severity);
|
||||
});
|
||||
}
|
||||
}
|
||||
self.analyze();
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/DumpAutoload
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorDumpTrigger: '.t3js-dumpAutoload-dump',
|
||||
selectorOutputContainer: '.t3js-dumpAutoload-output',
|
||||
|
||||
initialize: function($trigger) {
|
||||
$.ajax({
|
||||
url: Router.getUrl('dumpAutoload'),
|
||||
cache: false,
|
||||
beforeSend: function() {
|
||||
$trigger.addClass('disabled');
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
if (data.status.length > 0) {
|
||||
data.status.forEach((function(element) {
|
||||
Notification.success(element.message);
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
// In case the dump action fails (typically 500 from server), do not kill the entire
|
||||
// install tool, instead show a notification that something went wrong.
|
||||
Notification.error('Dumping autoload files went wrong on the server side. Check the system for broken extensions and try again')
|
||||
},
|
||||
complete: function() {
|
||||
$trigger.removeClass('disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/EnvironmentCheck
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorGridderBadge: '.t3js-environmentCheck-badge',
|
||||
selectorExecuteTrigger: '.t3js-environmentCheck-execute',
|
||||
selectorOutputContainer: '.t3js-environmentCheck-output',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
|
||||
// Get status on initialize to have the badge and content ready
|
||||
this.runTests();
|
||||
|
||||
currentModal.on('click', this.selectorExecuteTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.runTests();
|
||||
});
|
||||
},
|
||||
|
||||
runTests: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $errorBadge = $(this.selectorGridderBadge);
|
||||
$errorBadge.text('').hide();
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
modalContent.find(this.selectorOutputContainer).empty().append(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl('environmentCheckGetStatus'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
modalContent.empty().append(data.html);
|
||||
var warningCount = 0;
|
||||
var errorCount = 0;
|
||||
if (data.success === true && typeof(data.status) === 'object') {
|
||||
$.each(data.status, function(i, element) {
|
||||
if (Array.isArray(element) && element.length > 0) {
|
||||
element.forEach(function(aStatus) {
|
||||
if (aStatus.severity === 1) {
|
||||
warningCount += 1;
|
||||
}
|
||||
if (aStatus.severity === 2) {
|
||||
errorCount += 1;
|
||||
}
|
||||
var message = InfoBox.render(aStatus.severity, aStatus.title, aStatus.message);
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
});
|
||||
}
|
||||
});
|
||||
if (errorCount > 0) {
|
||||
$errorBadge.removeClass('label-warning').addClass('label-danger').text(errorCount).show();
|
||||
} else if (warningCount > 0) {
|
||||
$errorBadge.removeClass('label-error').addClass('label-warning').text(warningCount).show();
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ExtensionCompatTester
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Install/Cache',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Cache, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorCheckTrigger: '.t3js-extensionCompatTester-check',
|
||||
selectorUninstallTrigger: '.t3js-extensionCompatTester-uninstall',
|
||||
selectorOutputContainer: '.t3js-extensionCompatTester-output',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getLoadedExtensionList();
|
||||
|
||||
currentModal.on('click', this.selectorCheckTrigger, function(e) {
|
||||
currentModal.find(self.selectorUninstallTrigger).hide();
|
||||
currentModal.find(self.selectorOutputContainer).empty();
|
||||
self.getLoadedExtensionList();
|
||||
});
|
||||
currentModal.on('click', this.selectorUninstallTrigger, function(e) {
|
||||
self.uninstallExtension($(e.target).data('extension'));
|
||||
});
|
||||
},
|
||||
|
||||
getLoadedExtensionList: function () {
|
||||
const self = this;
|
||||
this.currentModal.find(this.selectorCheckTrigger).prop('disabled', true);
|
||||
|
||||
this.currentModal.find('.modal-loading').hide();
|
||||
const modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
const $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
const message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.append(message);
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl('extensionCompatTesterLoadedExtensionList'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
modalContent.empty().append(data.html);
|
||||
|
||||
const $outputContainer = self.currentModal.find(self.selectorOutputContainer);
|
||||
const progressBar = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.append(progressBar);
|
||||
|
||||
if (data.success === true) {
|
||||
self.loadExtLocalconf().done(function() {
|
||||
$outputContainer.append(
|
||||
InfoBox.render(Severity.ok, 'ext_localconf.php of all loaded extensions successfully loaded', '')
|
||||
);
|
||||
self.loadExtTables().done(function() {
|
||||
$outputContainer.append(
|
||||
InfoBox.render(Severity.ok, 'ext_tables.php of all loaded extensions successfully loaded', '')
|
||||
);
|
||||
}).fail(function(xhr) {
|
||||
self.renderFailureMessages('ext_tables.php', xhr.responseJSON.brokenExtensions, $outputContainer);
|
||||
}).always(function() {
|
||||
self.unlockModal();
|
||||
})
|
||||
}).fail(function(xhr) {
|
||||
self.renderFailureMessages('ext_localconf.php', xhr.responseJSON.brokenExtensions, $outputContainer);
|
||||
$outputContainer.append(
|
||||
InfoBox.render(Severity.notice, 'Skipped scanning ext_tables.php files due to previous errors', '')
|
||||
);
|
||||
self.unlockModal();
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unlockModal: function() {
|
||||
this.currentModal.find(this.selectorOutputContainer).find('.alert-loading').remove();
|
||||
this.currentModal.find(this.selectorCheckTrigger).prop('disabled', false);
|
||||
},
|
||||
|
||||
renderFailureMessages: function(scope, brokenExtensions, $outputContainer) {
|
||||
for (let i = 0; i < brokenExtensions.length; ++i) {
|
||||
let extension = brokenExtensions[i];
|
||||
|
||||
let uninstallAction;
|
||||
if (!extension.isProtected) {
|
||||
uninstallAction = $('<button />', {'class': 'btn btn-danger t3js-extensionCompatTester-uninstall'})
|
||||
.attr('data-extension', extension.name)
|
||||
.text('Uninstall extension "' + extension.name + '"');
|
||||
}
|
||||
$outputContainer.append(
|
||||
InfoBox.render(
|
||||
Severity.error,
|
||||
'Loading ' + scope + ' of extension "' + extension.name + '" failed',
|
||||
(extension.isProtected ? 'Extension is mandatory and cannot be uninstalled.' : '')
|
||||
),
|
||||
uninstallAction
|
||||
);
|
||||
}
|
||||
|
||||
this.unlockModal();
|
||||
},
|
||||
|
||||
loadExtLocalconf: function() {
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('extension-compat-tester-load-ext_localconf-token');
|
||||
return $.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'extensionCompatTesterLoadExtLocalconf',
|
||||
'token': executeToken
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadExtTables: function() {
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('extension-compat-tester-load-ext_tables-token');
|
||||
return $.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
cache: false,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'extensionCompatTesterLoadExtTables',
|
||||
'token': executeToken
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Send an ajax request to uninstall an extension (or multiple extensions)
|
||||
*
|
||||
* @param extension string of extension(s) - may be comma separated
|
||||
*/
|
||||
uninstallExtension: function(extension) {
|
||||
var self = this;
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('extension-compat-tester-uninstall-extension-token');
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = $(this.selectorOutputContainer);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.append(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'extensionCompatTesterUninstallExtension',
|
||||
'token': executeToken,
|
||||
'extension': extension
|
||||
}
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
modalContent.find(self.selectorOutputContainer).empty().append(message);
|
||||
});
|
||||
}
|
||||
$(self.selectorUninstallTrigger).hide();
|
||||
//Cache.clearAll();
|
||||
self.getLoadedExtensionList();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ExtensionConfiguration
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'TYPO3/CMS/Backend/ModuleMenu',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification, ModuleMenu) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorFormListener: '.t3js-extensionConfiguration-form',
|
||||
selectorOutputContainer: '.t3js-extensionConfiguration-output',
|
||||
selectorSearchInput: '.t3js-extensionConfiguration-search',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getContent();
|
||||
|
||||
// Focus search field on certain user interactions
|
||||
currentModal.on('keydown', function(e) {
|
||||
var $searchInput = currentModal.find(self.selectorSearchInput);
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
// Focus search field on ctrl-f
|
||||
switch (String.fromCharCode(e.which).toLowerCase()) {
|
||||
case 'f':
|
||||
e.preventDefault();
|
||||
$searchInput.focus();
|
||||
break;
|
||||
}
|
||||
} else if (e.keyCode === 27) {
|
||||
// Clear search on ESC key
|
||||
e.preventDefault();
|
||||
$searchInput.val('').focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Perform expand collapse on search matches
|
||||
currentModal.on('keyup', this.selectorSearchInput, function(e) {
|
||||
var typedQuery = $(e.target).val();
|
||||
var $searchInput = currentModal.find(self.selectorSearchInput);
|
||||
currentModal.find('.search-item').each(function() {
|
||||
var $item = $(this);
|
||||
if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
|
||||
$item.removeClass('hidden').addClass('searchhit');
|
||||
} else {
|
||||
$item.removeClass('searchhit').addClass('hidden');
|
||||
}
|
||||
});
|
||||
currentModal.find('.searchhit').collapse('show');
|
||||
// Make search field clearable
|
||||
require(['jquery.clearable'], function() {
|
||||
$searchInput.clearable().focus();
|
||||
});
|
||||
});
|
||||
|
||||
currentModal.on('submit', this.selectorFormListener, function(e) {
|
||||
e.preventDefault();
|
||||
self.write($(this));
|
||||
});
|
||||
},
|
||||
|
||||
getContent: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('extensionConfigurationGetContent'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.title, element.message);
|
||||
});
|
||||
}
|
||||
modalContent.html(data.html);
|
||||
self.initializeWrap();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit the form and show the result message
|
||||
*
|
||||
* @param {jQuery} $form The form of the current extension
|
||||
*/
|
||||
write: function($form) {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('extension-configuration-write-token');
|
||||
var extensionConfiguration = {};
|
||||
$.each($form.serializeArray(), function() {
|
||||
extensionConfiguration[this.name] = this.value;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'token': executeToken,
|
||||
'action': 'extensionConfigurationWrite',
|
||||
'extensionKey': $form.attr('data-extensionKey'),
|
||||
'extensionConfiguration': extensionConfiguration
|
||||
}
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.showMessage(element.title, element.message, element.severity);
|
||||
});
|
||||
if ($('body').data('context') === 'backend') {
|
||||
ModuleMenu.App.refreshMenu();
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
}).always(function() {
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* configuration properties
|
||||
*/
|
||||
initializeWrap: function() {
|
||||
this.currentModal.find('.t3js-emconf-offset').each(function() {
|
||||
var $me = $(this);
|
||||
var $parent = $me.parent();
|
||||
var id = $me.attr('id');
|
||||
var val = $me.attr('value');
|
||||
var valArr = val.split(',');
|
||||
|
||||
$me
|
||||
.attr('data-offsetfield-x', '#' + id + '_offset_x')
|
||||
.attr('data-offsetfield-y', '#' + id + '_offset_y')
|
||||
.wrap('<div class="hidden"></div>');
|
||||
|
||||
var elementX = $('<div>', {'class': 'form-multigroup-item'}).append(
|
||||
$('<div>', {'class': 'input-group'}).append(
|
||||
$('<div>', {'class': 'input-group-addon'}).text('x'),
|
||||
$('<input>', {
|
||||
'id': id + '_offset_x',
|
||||
'class': 'form-control t3js-emconf-offsetfield',
|
||||
'data-target': '#' + id,
|
||||
'value': $.trim(valArr[0])
|
||||
})
|
||||
)
|
||||
);
|
||||
var elementY = $('<div>', {'class': 'form-multigroup-item'}).append(
|
||||
$('<div>', {'class': 'input-group'}).append(
|
||||
$('<div>', {'class': 'input-group-addon'}).text('y'),
|
||||
$('<input>', {
|
||||
'id': id + '_offset_y',
|
||||
'class': 'form-control t3js-emconf-offsetfield',
|
||||
'data-target': '#' + id,
|
||||
'value': $.trim(valArr[1])
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
var offsetGroup = $('<div>', {'class': 'form-multigroup-wrap'}).append(elementX, elementY);
|
||||
$parent.append(offsetGroup);
|
||||
$parent.find('.t3js-emconf-offsetfield').keyup(function() {
|
||||
var $target = $parent.find($(this).data('target'));
|
||||
$target.val($parent.find($target.data('offsetfield-x')).val() + ',' + $parent.find($target.data('offsetfield-y')).val());
|
||||
});
|
||||
});
|
||||
|
||||
this.currentModal.find('.t3js-emconf-wrap').each(function() {
|
||||
var $me = $(this),
|
||||
$parent = $me.parent(),
|
||||
id = $me.attr('id'),
|
||||
val = $me.attr('value'),
|
||||
valArr = val.split('|');
|
||||
|
||||
$me.attr('data-wrapfield-start', '#' + id + '_wrap_start')
|
||||
.attr('data-wrapfield-end', '#' + id + '_wrap_end')
|
||||
.wrap('<div class="hidden"></div>');
|
||||
|
||||
var wrapGroup = $('<div>', {'class': 'form-multigroup-wrap'}).append(
|
||||
$('<div>', {'class': 'form-multigroup-item'}).append(
|
||||
$('<input>', {
|
||||
'id': id + '_wrap_start',
|
||||
'class': 'form-control t3js-emconf-wrapfield',
|
||||
'data-target': '#' + id,
|
||||
'value': $.trim(valArr[0])
|
||||
})
|
||||
),
|
||||
$('<div>', {'class': 'form-multigroup-item'}).append(
|
||||
$('<input>', {
|
||||
'id': id + '_wrap_end',
|
||||
'class': 'form-control t3js-emconf-wrapfield',
|
||||
'data-target': '#' + id,
|
||||
'value': $.trim(valArr[1])
|
||||
})
|
||||
)
|
||||
);
|
||||
$parent.append(wrapGroup);
|
||||
$parent.find('.t3js-emconf-wrapfield').keyup(function() {
|
||||
var $target = $parent.find($(this).data('target'));
|
||||
$target.val($parent.find($target.data('wrapfield-start')).val() + '|' + $parent.find($target.data('wrapfield-end')).val());
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ExtensionScanner
|
||||
*/
|
||||
define(['jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'TYPO3/CMS/Install/AjaxQueue'
|
||||
], function($, Router, Notification, AjaxQueue) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
listOfAffectedRestFileHashes: [],
|
||||
selectorExtensionContainer: '.t3js-extensionScanner-extension',
|
||||
selectorNumberOfFiles: '.t3js-extensionScanner-number-of-files',
|
||||
selectorScanSingleTrigger: '.t3js-extensionScanner-scan-single',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
|
||||
currentModal.on('show.bs.collapse', self.selectorExtensionContainer, function(e) {
|
||||
// Scan a single extension by opening the panel
|
||||
var $me = $(e.currentTarget);
|
||||
if (typeof $me.data('scanned') === 'undefined') {
|
||||
var extension = $me.data('extension');
|
||||
self.scanSingleExtension(extension);
|
||||
$me.data('scanned', true);
|
||||
}
|
||||
}).on('hide.bs.modal', function() {
|
||||
AjaxQueue.flush();
|
||||
}).on('click', self.selectorScanSingleTrigger, function(e) {
|
||||
// Scan a single extension by clicking "Rescan"
|
||||
e.preventDefault();
|
||||
|
||||
var extension = $(e.currentTarget).closest(self.selectorExtensionContainer).data('extension');
|
||||
self.scanSingleExtension(extension);
|
||||
}).on('click', '.t3js-extensionScanner-scan-all', function(e) {
|
||||
// Scan all button
|
||||
e.preventDefault();
|
||||
var $extensions = currentModal.find(self.selectorExtensionContainer);
|
||||
self.scanAll($extensions);
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('extensionScannerGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} extension
|
||||
* @returns {string}
|
||||
*/
|
||||
getExtensionSelector: function(extension) {
|
||||
return this.selectorExtensionContainer + '-' + extension;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {JQuery} $extensions
|
||||
*/
|
||||
scanAll: function($extensions) {
|
||||
var self = this;
|
||||
this.currentModal.find(this.selectorExtensionContainer)
|
||||
.removeClass('panel-danger panel-warning panel-success')
|
||||
.find('.panel-progress-bar')
|
||||
.css('width', 0)
|
||||
.attr('aria-valuenow', 0)
|
||||
.find('span')
|
||||
.text('0%');
|
||||
this.setProgressForAll();
|
||||
$extensions.each(function() {
|
||||
var $me = $(this);
|
||||
var extension = $me.data('extension');
|
||||
self.scanSingleExtension(extension);
|
||||
$me.data('scanned', true);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} extension
|
||||
* @param {number} doneFiles
|
||||
* @param {number} numberOfFiles
|
||||
*/
|
||||
setStatusMessageForScan: function(extension, doneFiles, numberOfFiles) {
|
||||
this.currentModal.find(this.getExtensionSelector(extension))
|
||||
.find(this.selectorNumberOfFiles)
|
||||
.text('Checked ' + doneFiles + ' of ' + numberOfFiles + ' files');
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} extension
|
||||
* @param {number} doneFiles
|
||||
* @param {number} numberOfFiles
|
||||
*/
|
||||
setProgressForScan: function(extension, doneFiles, numberOfFiles) {
|
||||
var percent = (doneFiles / numberOfFiles) * 100;
|
||||
this.currentModal.find(this.getExtensionSelector(extension))
|
||||
.find('.panel-progress-bar')
|
||||
.css('width', percent + '%')
|
||||
.attr('aria-valuenow', percent)
|
||||
.find('span')
|
||||
.text(percent + '%');
|
||||
},
|
||||
|
||||
/**
|
||||
* Update main progress bar
|
||||
*/
|
||||
setProgressForAll: function() {
|
||||
var self = this;
|
||||
// var numberOfExtensions = $(this.selectorExtensionContainer).length;
|
||||
var numberOfExtensions = this.currentModal.find(this.selectorExtensionContainer).length;
|
||||
var numberOfSuccess = this.currentModal.find(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-success').length;
|
||||
var numberOfWarning = this.currentModal.find(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-warning').length;
|
||||
var numberOfError = this.currentModal.find(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-danger').length;
|
||||
var numberOfScannedExtensions = numberOfSuccess + numberOfWarning + numberOfError;
|
||||
var percent = (numberOfScannedExtensions / numberOfExtensions) * 100;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
this.currentModal.find('.t3js-extensionScanner-progress-all-extension .progress-bar')
|
||||
.css('width', percent + '%')
|
||||
.attr('aria-valuenow', percent)
|
||||
.find('span')
|
||||
.text(numberOfScannedExtensions + ' of ' + numberOfExtensions + ' scanned');
|
||||
|
||||
if (numberOfScannedExtensions === numberOfExtensions) {
|
||||
Notification.success('Scan finished', 'All extensions have been scanned');
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'extensionScannerMarkFullyScannedRestFiles',
|
||||
'token': self.currentModal.find(self.selectorModuleContent).data('extension-scanner-mark-fully-scanned-rest-files-token'),
|
||||
'hashes': self.uniqueArray(this.listOfAffectedRestFileHashes)
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
Notification.success('Marked not affected files', 'Marked ' + data.markedAsNotAffected + ' ReST files as not affected.');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method removing duplicate entries from an array
|
||||
*
|
||||
* @param {Array} anArray
|
||||
* @returns {Array}
|
||||
*/
|
||||
uniqueArray: function(anArray) {
|
||||
return anArray.filter(function(value, index, self) {
|
||||
return self.indexOf(value) === index;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle a single extension scan
|
||||
*
|
||||
* @param {string} extension
|
||||
*/
|
||||
scanSingleExtension: function(extension) {
|
||||
var self = this;
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('extension-scanner-files-token');
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $extensionContainer = this.currentModal.find(this.getExtensionSelector(extension));
|
||||
var hitTemplate = '#t3js-extensionScanner-file-hit-template';
|
||||
var restTemplate = '#t3js-extensionScanner-file-hit-rest-template';
|
||||
var hitFound = false;
|
||||
$extensionContainer.removeClass('panel-danger panel-warning panel-success t3js-extensionscan-finished');
|
||||
$extensionContainer.data('hasRun', 'true');
|
||||
$extensionContainer.find('.t3js-extensionScanner-scan-single').text('Scanning...').attr('disabled', 'disabled');
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text('0');
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text('0');
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text('0');
|
||||
this.setProgressForAll();
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'extensionScannerFiles',
|
||||
'token': executeToken,
|
||||
'extension': extension
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.files)) {
|
||||
var numberOfFiles = data.files.length;
|
||||
if (numberOfFiles > 0) {
|
||||
self.setStatusMessageForScan(extension, 0, numberOfFiles);
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body').text('');
|
||||
var doneFiles = 0;
|
||||
data.files.forEach(function(file) {
|
||||
AjaxQueue.add(
|
||||
{
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'extensionScannerScanFile',
|
||||
'token': self.currentModal.find(self.selectorModuleContent).data('extension-scanner-scan-file-token'),
|
||||
'extension': extension,
|
||||
'file': file
|
||||
}
|
||||
},
|
||||
url: Router.getUrl(),
|
||||
cache: false,
|
||||
success: function(fileData) {
|
||||
doneFiles = doneFiles + 1;
|
||||
self.setStatusMessageForScan(extension, doneFiles, numberOfFiles);
|
||||
self.setProgressForScan(extension, doneFiles, numberOfFiles);
|
||||
if (fileData.success && $.isArray(fileData.matches)) {
|
||||
$(fileData.matches).each(function() {
|
||||
hitFound = true;
|
||||
var match = this;
|
||||
var aMatch = modalContent.find(hitTemplate).clone();
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-panel-head').attr('href', '#collapse' + match.uniqueId);
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-panel-body').attr('id', 'collapse' + match.uniqueId);
|
||||
aMatch.find('.t3js-extensionScanner-hit-filename').text(file);
|
||||
aMatch.find('.t3js-extensionScanner-hit-message').text(match.message);
|
||||
if (match.indicator === 'strong') {
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
|
||||
.append('<span class="badge" title="Reliable match, false positive unlikely">strong</span>');
|
||||
} else {
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
|
||||
.append('<span class="badge" title="Probable match, but can be a false positive">weak</span>');
|
||||
}
|
||||
if (match.silenced === true) {
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
|
||||
.append('<span class="badge" title="Match has been annotated by extension author as false positive match">silenced</span>');
|
||||
}
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-lineContent').empty().text(match.lineContent);
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-line').empty().text(match.line + ': ');
|
||||
if ($.isArray(match.restFiles)) {
|
||||
$(match.restFiles).each(function() {
|
||||
var restFile = this;
|
||||
var aRest = modalContent.find(restTemplate).clone();
|
||||
aRest.find('.t3js-extensionScanner-hit-rest-panel-head').attr('href', '#collapse' + restFile.uniqueId);
|
||||
aRest.find('.t3js-extensionScanner-hit-rest-panel-head .badge').empty().text(restFile.version);
|
||||
aRest.find('.t3js-extensionScanner-hit-rest-panel-body').attr('id', 'collapse' + restFile.uniqueId);
|
||||
aRest.find('.t3js-extensionScanner-hit-rest-headline').text(restFile.headline);
|
||||
aRest.find('.t3js-extensionScanner-hit-rest-body').text(restFile.content);
|
||||
aRest.addClass('panel-' + restFile.class);
|
||||
aMatch.find('.t3js-extensionScanner-hit-file-rest-container').append(aRest);
|
||||
self.listOfAffectedRestFileHashes.push(restFile.file_hash);
|
||||
});
|
||||
}
|
||||
var panelClass =
|
||||
aMatch.find('.panel-breaking', '.t3js-extensionScanner-hit-file-rest-container').length > 0
|
||||
? 'panel-danger'
|
||||
: 'panel-warning';
|
||||
aMatch.addClass(panelClass);
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body').removeClass('hide').append(aMatch);
|
||||
if (panelClass === 'panel-danger') {
|
||||
$extensionContainer.removeClass('panel-warning').addClass(panelClass);
|
||||
}
|
||||
if (panelClass === 'panel-warning' && !$extensionContainer.hasClass('panel-danger')) {
|
||||
$extensionContainer.addClass(panelClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (fileData.success) {
|
||||
var currentLinesOfCode = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-loc').text());
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text(currentLinesOfCode + parseInt(fileData.effectiveCodeLines));
|
||||
if (fileData.isFileIgnored) {
|
||||
var currentIgnoredFiles = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').text());
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text(currentIgnoredFiles + 1);
|
||||
}
|
||||
var currentIgnoredLines = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').text());
|
||||
$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text(currentIgnoredLines + parseInt(fileData.ignoredLines));
|
||||
}
|
||||
if (doneFiles === numberOfFiles) {
|
||||
if (!hitFound) {
|
||||
$extensionContainer.addClass('panel-success');
|
||||
}
|
||||
$extensionContainer.addClass('t3js-extensionscan-finished');
|
||||
self.setProgressForAll();
|
||||
$extensionContainer.find('.t3js-extensionScanner-scan-single').text('Rescan').attr('disabled', null);
|
||||
}
|
||||
},
|
||||
error: function(data) {
|
||||
doneFiles = doneFiles + 1;
|
||||
self.setStatusMessageForScan(extension, doneFiles, numberOfFiles);
|
||||
self.setProgressForScan(extension, doneFiles, numberOfFiles);
|
||||
self.setProgressForAll();
|
||||
console.error(data);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
Notification.warning('No files found', 'The extension EXT:' + extension + ' contains no files we can scan');
|
||||
}
|
||||
} else {
|
||||
Notification.error('Oops, an error occurred', 'Please look at the browser console output for details');
|
||||
console.error(data);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/Features
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-features-content',
|
||||
selectorSaveTrigger: '.t3js-features-save',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getContent();
|
||||
|
||||
currentModal.on('click', this.selectorSaveTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.save();
|
||||
});
|
||||
},
|
||||
|
||||
getContent: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('featuresGetContent'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
save: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('features-save-token');
|
||||
var postData = {};
|
||||
$(this.currentModal.find(this.selectorModuleContent + ' form').serializeArray()).each(function() {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
postData['install[action]'] = 'featuresSave';
|
||||
postData['install[token]'] = executeToken;
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.showMessage(element.title, element.message, element.severity);
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/FlashMessage
|
||||
*/
|
||||
define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @type {{template: (*)}}
|
||||
*/
|
||||
var FlashMessage = {
|
||||
template: $('<div class="t3js-message typo3-message alert"><h4></h4><p class="messageText"></p></div>')
|
||||
};
|
||||
|
||||
/**
|
||||
* render a FlashMessage
|
||||
* @param {Number} severity
|
||||
* @param {String} title
|
||||
* @param {String} message
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
FlashMessage.render = function(severity, title, message) {
|
||||
var flashMessage = this.template.clone();
|
||||
flashMessage.addClass('alert-' + Severity.getCssClass(severity));
|
||||
if (title) {
|
||||
flashMessage.find('h4').text(title);
|
||||
}
|
||||
if (message) {
|
||||
flashMessage.find('.messageText').text(message);
|
||||
} else {
|
||||
flashMessage.find('.messageText').remove();
|
||||
}
|
||||
return flashMessage;
|
||||
};
|
||||
|
||||
return FlashMessage;
|
||||
});
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/FolderStructure
|
||||
*/
|
||||
define(['jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorGridderBadge: '.t3js-folderStructure-badge',
|
||||
selectorFixTrigger: '.t3js-folderStructure-errors-fix',
|
||||
selectorOutputContainer: '.t3js-folderStructure-output',
|
||||
selectorErrorContainer: '.t3js-folderStructure-errors',
|
||||
selectorErrorList: '.t3js-folderStructure-errors-list',
|
||||
selectorErrorFixTrigger: '.t3js-folderStructure-errors-fix',
|
||||
selectorOkContainer: '.t3js-folderStructure-ok',
|
||||
selectorOkList: '.t3js-folderStructure-ok-list',
|
||||
selectorPermissionContainer: '.t3js-folderStructure-permissions',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
|
||||
// Get status on initialize to have the badge and content ready
|
||||
this.getStatus();
|
||||
|
||||
currentModal.on('click', this.selectorErrorFixTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.fix();
|
||||
});
|
||||
},
|
||||
|
||||
getStatus: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $errorBadge = $(this.selectorGridderBadge);
|
||||
$errorBadge.text('').hide();
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
modalContent.find(self.selectorOutputContainer).empty().append(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl('folderStructureGetStatus'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
modalContent.empty().append(data.html);
|
||||
if (data.success === true && Array.isArray(data.errorStatus)) {
|
||||
var errorCount = 0;
|
||||
if (data.errorStatus.length > 0) {
|
||||
modalContent.find(self.selectorErrorContainer).show();
|
||||
modalContent.find(self.selectorErrorList).empty();
|
||||
data.errorStatus.forEach((function(element) {
|
||||
errorCount += 1;
|
||||
$errorBadge.text(errorCount).show();
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
modalContent.find(self.selectorErrorList).append(message);
|
||||
}));
|
||||
} else {
|
||||
modalContent.find(self.selectorErrorContainer).hide();
|
||||
}
|
||||
}
|
||||
if (data.success === true && Array.isArray(data.okStatus)) {
|
||||
if (data.okStatus.length > 0) {
|
||||
modalContent.find(self.selectorOkContainer).show();
|
||||
modalContent.find(self.selectorOkList).empty();
|
||||
data.okStatus.forEach((function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
modalContent.find(self.selectorOkList).append(message);
|
||||
}));
|
||||
} else {
|
||||
modalContent.find(self.selectorOkContainer).hide();
|
||||
}
|
||||
}
|
||||
var element = data.folderStructureFilePermissionStatus;
|
||||
message = InfoBox.render(element.severity, element.title, element.message);
|
||||
modalContent.find(self.selectorPermissionContainer).empty().append(message);
|
||||
element = data.folderStructureDirectoryPermissionStatus;
|
||||
message = InfoBox.render(element.severity, element.title, element.message);
|
||||
modalContent.find(self.selectorPermissionContainer).append(message);
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
fix: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().html(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl('folderStructureFix'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
if (data.success === true && Array.isArray(data.fixedStatus)) {
|
||||
if (data.fixedStatus.length > 0) {
|
||||
data.fixedStatus.forEach(function(element) {
|
||||
message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
});
|
||||
} else {
|
||||
message = InfoBox.render(Severity.warning, 'Nothing fixed', '');
|
||||
$outputContainer.append(message);
|
||||
}
|
||||
self.getStatus();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeLoadingMessage: function($container) {
|
||||
$container.find('.alert-loading').remove();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ImageProcessing
|
||||
*/
|
||||
define(['jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorExecuteTrigger: '.t3js-imageProcessing-execute',
|
||||
selectorTestContainer: '.t3js-imageProcessing-twinContainer',
|
||||
selectorTwinImageTemplate: '.t3js-imageProcessing-twinImage-template',
|
||||
selectorCommandContainer: '.t3js-imageProcessing-command',
|
||||
selectorCommandText: '.t3js-imageProcessing-command-text',
|
||||
selectorTwinImages: '.t3js-imageProcessing-images',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
|
||||
currentModal.on('click', this.selectorExecuteTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.runTests();
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('imageProcessingGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
self.runTests();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
runTests: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $twinImageTemplate = this.currentModal.find(this.selectorTwinImageTemplate);
|
||||
modalContent.find(this.selectorTestContainer).each(function() {
|
||||
var $container = $(this);
|
||||
var testType = $container.data('test');
|
||||
var message = InfoBox.render(Severity.loading, 'Loading...', '');
|
||||
$container.empty().html(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl(testType),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$container.empty();
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$container.append(message);
|
||||
});
|
||||
}
|
||||
var $aTwin = $twinImageTemplate.clone();
|
||||
$aTwin.removeClass('t3js-imageProcessing-twinImage-template');
|
||||
if (data.fileExists === true) {
|
||||
$aTwin.find('img.reference').attr('src', data.referenceFile);
|
||||
$aTwin.find('img.result').attr('src', data.outputFile);
|
||||
$aTwin.find(self.selectorTwinImages).show();
|
||||
}
|
||||
if (Array.isArray(data.command) && data.command.length > 0) {
|
||||
$aTwin.find(self.selectorCommandContainer).show();
|
||||
var commandText = [];
|
||||
data.command.forEach(function(element) {
|
||||
commandText.push('<strong>Command:</strong>\n' + element[1]);
|
||||
if (element.length === 3) {
|
||||
commandText.push('<strong>Result:</strong>\n' + element[2]);
|
||||
}
|
||||
});
|
||||
$aTwin.find(self.selectorCommandText).html(commandText.join('\n'));
|
||||
}
|
||||
$container.append($aTwin);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/InfoBox
|
||||
*/
|
||||
define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @type {{template: (*)}}
|
||||
*/
|
||||
var InfoBox = {
|
||||
template: $('<div class="t3js-infobox callout callout-sm"><h4 class="callout-title"></h4><div class="callout-body"></div></div>')
|
||||
};
|
||||
|
||||
/**
|
||||
* render a InfoBox
|
||||
* @param {Number} severity
|
||||
* @param {String} title
|
||||
* @param {String} message
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
InfoBox.render = function(severity, title, message) {
|
||||
var infoBox = this.template.clone();
|
||||
infoBox.addClass('callout-' + Severity.getCssClass(severity));
|
||||
if (title) {
|
||||
infoBox.find('h4').text(title);
|
||||
}
|
||||
if (message) {
|
||||
infoBox.find('.callout-body').text(message);
|
||||
} else {
|
||||
infoBox.find('.callout-body').remove();
|
||||
}
|
||||
return infoBox;
|
||||
};
|
||||
|
||||
return InfoBox;
|
||||
});
|
||||
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/LanguagePacks
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Core/SecurityUtility',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, SecurityUtility) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorOutputContainer: '.t3js-languagePacks-output',
|
||||
selectorContentContainer: '.t3js-languagePacks-mainContent',
|
||||
selectorActivateLanguage: '.t3js-languagePacks-activateLanguage',
|
||||
selectorActivateLanguageIcon: '#t3js-languagePacks-activate-icon',
|
||||
selectorAddLanguageToggle: '.t3js-languagePacks-addLanguage-toggle',
|
||||
selectorLanguageInactive: '.t3js-languagePacks-inactive',
|
||||
selectorDeactivateLanguage: '.t3js-languagePacks-deactivateLanguage',
|
||||
selectorDeactivateLanguageIcon: '#t3js-languagePacks-deactivate-icon',
|
||||
selectorUpdate: '.t3js-languagePacks-update',
|
||||
selectorLanguageUpdateIcon: '#t3js-languagePacks-languageUpdate-icon',
|
||||
selectorNotifications: '.t3js-languagePacks-notifications',
|
||||
|
||||
currentModal: {},
|
||||
|
||||
activeLanguages: [],
|
||||
activeExtensions: [],
|
||||
|
||||
packsUpdateDetails: {
|
||||
toHandle: 0,
|
||||
handled: 0,
|
||||
updated: 0,
|
||||
new: 0,
|
||||
failed: 0
|
||||
},
|
||||
|
||||
notifications: [],
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
|
||||
// Get configuration list on modal open
|
||||
this.getData();
|
||||
|
||||
currentModal.on('click', this.selectorAddLanguageToggle, function(e) {
|
||||
currentModal.find(self.selectorContentContainer + ' ' + self.selectorLanguageInactive).toggle();
|
||||
});
|
||||
|
||||
currentModal.on('click', this.selectorActivateLanguage, function(e) {
|
||||
var iso = $(e.target).closest(self.selectorActivateLanguage).data('iso');
|
||||
e.preventDefault();
|
||||
self.activateLanguage(iso);
|
||||
});
|
||||
|
||||
currentModal.on('click', this.selectorDeactivateLanguage, function(e) {
|
||||
var iso = $(e.target).closest(self.selectorDeactivateLanguage).data('iso');
|
||||
e.preventDefault();
|
||||
self.deactivateLanguage(iso);
|
||||
});
|
||||
|
||||
currentModal.on('click', this.selectorUpdate, function(e) {
|
||||
var iso = $(e.target).closest(self.selectorUpdate).data('iso');
|
||||
var extension = $(e.target).closest(self.selectorUpdate).data('extension');
|
||||
e.preventDefault();
|
||||
self.updatePacks(iso, extension);
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('languagePacksGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.activeLanguages = data.activeLanguages;
|
||||
self.activeExtensions = data.activeExtensions;
|
||||
modalContent.empty().append(data.html);
|
||||
var contentContainer = modalContent.parent().find(self.selectorContentContainer);
|
||||
contentContainer.empty();
|
||||
contentContainer.append(self.languageMatrixHtml(data));
|
||||
contentContainer.append(self.extensionMatrixHtml(data));
|
||||
$('[data-toggle="tooltip"]').tooltip({container: contentContainer});
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.error, 'Something went wrong', '');
|
||||
self.addNotification(message);
|
||||
}
|
||||
|
||||
self.renderNotifications();
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
activateLanguage: function(iso) {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().append(message);
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
context: this,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'languagePacksActivateLanguage',
|
||||
'token': this.currentModal.find(this.selectorModuleContent).data('language-packs-activate-language-token'),
|
||||
'iso': iso
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
beforeSend: function() {
|
||||
self.getNotificationBox().empty();
|
||||
},
|
||||
success: function(data) {
|
||||
$outputContainer.empty();
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
self.addNotification(message);
|
||||
});
|
||||
} else {
|
||||
var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
|
||||
self.addNotification(message);
|
||||
}
|
||||
this.getData();
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
deactivateLanguage: function(iso) {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().append(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
context: this,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'languagePacksDeactivateLanguage',
|
||||
'token': self.currentModal.find(self.selectorModuleContent).data('language-packs-deactivate-language-token'),
|
||||
'iso': iso
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
beforeSend: function() {
|
||||
self.getNotificationBox().empty();
|
||||
},
|
||||
success: function(data) {
|
||||
$outputContainer.empty();
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
self.addNotification(message);
|
||||
});
|
||||
} else {
|
||||
var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
|
||||
self.addNotification(message);
|
||||
}
|
||||
this.getData();
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updatePacks: function(iso, extension) {
|
||||
var self = this;
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
var $contentContainer = this.currentModal.find(this.selectorContentContainer);
|
||||
var updateIsoTimes = true;
|
||||
var isos = iso === undefined ? this.activeLanguages : [ iso ];
|
||||
var extensions = this.activeExtensions;
|
||||
if (extension !== undefined) {
|
||||
extensions = [ extension ];
|
||||
updateIsoTimes = false;
|
||||
}
|
||||
|
||||
this.packsUpdateDetails = {
|
||||
toHandle: isos.length * extensions.length,
|
||||
handled: 0,
|
||||
updated: 0,
|
||||
new: 0,
|
||||
failed: 0
|
||||
};
|
||||
|
||||
$outputContainer.empty().append(
|
||||
$('<div>', {'class': 'progress'}).append(
|
||||
$('<div>', {
|
||||
'class': 'progress-bar progress-bar-info',
|
||||
'role': 'progressbar',
|
||||
'aria-valuenow': 0,
|
||||
'aria-valuemin': 0,
|
||||
'aria-valuemax': 100,
|
||||
'style': 'width: 0;'
|
||||
}).append(
|
||||
$('<span>', {'class': 'text-nowrap'}).text('0 of ' + this.packsUpdateDetails.toHandle + ' language ' +
|
||||
this.pluralize(this.packsUpdateDetails.toHandle) + ' updated')
|
||||
)
|
||||
));
|
||||
$contentContainer.empty();
|
||||
|
||||
isos.forEach(function(iso) {
|
||||
extensions.forEach(function(extension) {
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
context: this,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'languagePacksUpdatePack',
|
||||
'token': self.currentModal.find(self.selectorModuleContent).data('language-packs-update-pack-token'),
|
||||
'iso': iso,
|
||||
'extension': extension
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
beforeSend: function() {
|
||||
self.getNotificationBox().empty();
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.packsUpdateDetails.handled++;
|
||||
if (data.packResult === 'new') {
|
||||
self.packsUpdateDetails.new++;
|
||||
} else if (data.packResult === 'update') {
|
||||
self.packsUpdateDetails.updated++;
|
||||
} else {
|
||||
self.packsUpdateDetails.failed++;
|
||||
}
|
||||
self.packUpdateDone(updateIsoTimes, isos);
|
||||
} else {
|
||||
self.packsUpdateDetails.handled++;
|
||||
self.packsUpdateDetails.failed++;
|
||||
self.packUpdateDone(updateIsoTimes, isos);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.packsUpdateDetails.handled++;
|
||||
self.packsUpdateDetails.failed++;
|
||||
self.packUpdateDone(updateIsoTimes, isos);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
pluralize: function(count, word, suffix, additionalCount) {
|
||||
word = word || 'pack';
|
||||
suffix = suffix || 's';
|
||||
additionalCount = additionalCount || 0;
|
||||
return count !== 1 && additionalCount !== 1 ? word + suffix : word;
|
||||
},
|
||||
|
||||
packUpdateDone: function(updateIsoTimes, isos) {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
if (this.packsUpdateDetails.handled === this.packsUpdateDetails.toHandle) {
|
||||
// All done - create summary, update 'last update' of iso list, render main view
|
||||
var message = InfoBox.render(
|
||||
Severity.ok,
|
||||
'Language packs updated',
|
||||
this.packsUpdateDetails.new + ' new language ' + this.pluralize(this.packsUpdateDetails.new) + ' downloaded, ' +
|
||||
this.packsUpdateDetails.updated + ' language ' + this.pluralize(this.packsUpdateDetails.updated) + ' updated, ' +
|
||||
this.packsUpdateDetails.failed + ' language ' + this.pluralize(this.packsUpdateDetails.failed) + ' not available'
|
||||
);
|
||||
this.addNotification(message);
|
||||
if (updateIsoTimes === true) {
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
context: this,
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'languagePacksUpdateIsoTimes',
|
||||
'token': this.currentModal.find(this.selectorModuleContent).data('language-packs-update-iso-times-token'),
|
||||
'isos': isos
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.getData();
|
||||
} else {
|
||||
var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
|
||||
self.addNotification(message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.getData();
|
||||
}
|
||||
} else {
|
||||
// Update progress bar
|
||||
var percent = (this.packsUpdateDetails.handled / this.packsUpdateDetails.toHandle) * 100;
|
||||
$outputContainer.find('.progress-bar')
|
||||
.css('width', percent + '%')
|
||||
.attr('aria-valuenow', percent)
|
||||
.find('span')
|
||||
.text(this.packsUpdateDetails.handled + ' of ' + this.packsUpdateDetails.toHandle + ' language ' +
|
||||
this.pluralize(this.packsUpdateDetails.handled, 'pack', 's', this.packsUpdateDetails.toHandle) + ' updated');
|
||||
}
|
||||
},
|
||||
|
||||
languageMatrixHtml: function(data) {
|
||||
var activateIcon = this.currentModal.find(this.selectorActivateLanguageIcon).html();
|
||||
var deactivateIcon = this.currentModal.find(this.selectorDeactivateLanguageIcon).html();
|
||||
var updateIcon = this.currentModal.find(this.selectorLanguageUpdateIcon).html();
|
||||
var $markupContainer = $('<div>');
|
||||
|
||||
var $tbody = $('<tbody>');
|
||||
data.languages.forEach(function(language) {
|
||||
var active = language.active;
|
||||
var $tr = $('<tr>');
|
||||
if (active) {
|
||||
$tbody.append(
|
||||
$tr.append(
|
||||
$('<td>').append(
|
||||
$('<a>', {
|
||||
'class': 'btn btn-default t3js-languagePacks-deactivateLanguage',
|
||||
'data-iso': language.iso,
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Deactivate'
|
||||
}).append(deactivateIcon),
|
||||
$('<a>', {
|
||||
'class': 'btn btn-default t3js-languagePacks-update',
|
||||
'data-iso': language.iso,
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Download language packs'
|
||||
}).append(updateIcon)
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$tbody.append(
|
||||
$tr.addClass('t3-languagePacks-inactive t3js-languagePacks-inactive').css({'display': 'none'}).append(
|
||||
$('<td>').append(
|
||||
$('<a>', {
|
||||
'class': 'btn btn-default t3js-languagePacks-activateLanguage',
|
||||
'data-iso': language.iso,
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Activate'
|
||||
}).append(activateIcon)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
$tr.append(
|
||||
$('<td>').text(language.name),
|
||||
$('<td>').text(language.iso),
|
||||
$('<td>').text(language.dependencies.join(', ')),
|
||||
$('<td>').text(language.lastUpdate === null ? '' : language.lastUpdate)
|
||||
);
|
||||
$tbody.append($tr);
|
||||
});
|
||||
$markupContainer.append(
|
||||
$('<h3>').text('Active languages'),
|
||||
$('<table>', {'class': 'table table-striped table-bordered'}).append(
|
||||
$('<thead>').append(
|
||||
$('<tr>').append(
|
||||
$('<th>').append(
|
||||
$('<button>', {'class': 'btn btn-default t3js-languagePacks-addLanguage-toggle', 'type': 'button'}).append(
|
||||
$('<span>').append(activateIcon),
|
||||
' Add language'
|
||||
),
|
||||
$('<button>', {'class': 'btn btn-default disabled update-all t3js-languagePacks-update', 'type': 'button', 'disabled': 'disabled'}).append(
|
||||
$('<span>').append(updateIcon),
|
||||
' Update all'
|
||||
)
|
||||
),
|
||||
$('<th>').text('Language'),
|
||||
$('<th>').text('Locale'),
|
||||
$('<th>').text('Dependencies'),
|
||||
$('<th>').text('Last update')
|
||||
)
|
||||
),
|
||||
$tbody
|
||||
)
|
||||
);
|
||||
|
||||
if (Array.isArray(this.activeLanguages) && this.activeLanguages.length) {
|
||||
$markupContainer.find('.update-all').removeClass('disabled').removeAttr('disabled');
|
||||
}
|
||||
return $markupContainer.html();
|
||||
},
|
||||
|
||||
extensionMatrixHtml: function(data) {
|
||||
var securityUtility = new SecurityUtility();
|
||||
var updateIcon = this.currentModal.find(this.selectorLanguageUpdateIcon).html();
|
||||
var tooltip = '';
|
||||
var extensionTitle = '';
|
||||
var rowCount = 0;
|
||||
var $markupContainer = $('<div>');
|
||||
|
||||
var $headerRow = $('<tr>');
|
||||
$headerRow.append(
|
||||
$('<th>').text('Extension'),
|
||||
$('<th>').text('Key')
|
||||
);
|
||||
data.activeLanguages.forEach(function(language) {
|
||||
$headerRow.append(
|
||||
$('<th>').append(
|
||||
$('<a>', {
|
||||
'class': 'btn btn-default t3js-languagePacks-update',
|
||||
'data-iso': language,
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Download and update all language packs'
|
||||
}).append(
|
||||
$('<span>').append(updateIcon),
|
||||
' ' + language
|
||||
)
|
||||
)
|
||||
)
|
||||
});
|
||||
|
||||
var $tbody = $('<tbody>');
|
||||
data.extensions.forEach(function(extension) {
|
||||
rowCount++;
|
||||
if (typeof extension.icon !== 'undefined') {
|
||||
extensionTitle = $('<span>').append(
|
||||
$('<img>', {
|
||||
'style': 'max-height: 16px; max-width: 16px;',
|
||||
'src': '../' + extension.icon,
|
||||
'alt': extension.title
|
||||
}),
|
||||
$('<span>').text(' ' + extension.title)
|
||||
);
|
||||
} else {
|
||||
extensionTitle = $('<span>').text(extension.title)
|
||||
}
|
||||
var $tr = $('<tr>');
|
||||
$tr.append(
|
||||
$('<td>').html(extensionTitle),
|
||||
$('<td>').text(extension.key)
|
||||
);
|
||||
extension.packs.forEach(function(pack) {
|
||||
var $column = $('<td>');
|
||||
$tr.append($column);
|
||||
if (pack.exists !== true) {
|
||||
if (pack.lastUpdate !== null) {
|
||||
tooltip = 'No language pack available for ' + pack.iso + ' when tried at ' + pack.lastUpdate + '. Click to re-try.';
|
||||
} else {
|
||||
tooltip = 'Language pack not downloaded. Click to download';
|
||||
}
|
||||
} else {
|
||||
if (pack.lastUpdate === null) {
|
||||
tooltip = 'Downloaded. Click to renew';
|
||||
} else {
|
||||
tooltip = 'Language pack downloaded at ' + pack.lastUpdate + '. Click to renew';
|
||||
}
|
||||
}
|
||||
$column.append(
|
||||
$('<a>', {
|
||||
'class': 'btn btn-default t3js-languagePacks-update',
|
||||
'data-extension': extension.key,
|
||||
'data-iso': pack.iso,
|
||||
'data-toggle': 'tooltip',
|
||||
'title': securityUtility.encodeHtml(tooltip),
|
||||
}).append(updateIcon)
|
||||
);
|
||||
});
|
||||
$tbody.append($tr);
|
||||
});
|
||||
|
||||
$markupContainer.append(
|
||||
$('<h3>').text('Translation status'),
|
||||
$('<table>', {'class': 'table table-striped table-bordered'}).append(
|
||||
$('<thead>').append($headerRow),
|
||||
$tbody
|
||||
)
|
||||
);
|
||||
if (rowCount === 0) {
|
||||
return InfoBox.render(Severity.ok, 'Language packs have been found for every installed extension.', 'To download the latest changes, use the refresh button in the list above.');
|
||||
}
|
||||
return $markupContainer.html();
|
||||
},
|
||||
getNotificationBox: function() {
|
||||
return this.currentModal.find(this.selectorNotifications);
|
||||
},
|
||||
addNotification: function(notification) {
|
||||
this.notifications.push(notification);
|
||||
},
|
||||
renderNotifications: function() {
|
||||
var $notificationBox = this.getNotificationBox();
|
||||
for (var i = 0; i < this.notifications.length; ++i) {
|
||||
$notificationBox.append(this.notifications[i]);
|
||||
}
|
||||
this.notifications = [];
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/LocalConfiguration
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorToggleAllTrigger: '.t3js-localConfiguration-toggleAll',
|
||||
selectorWriteTrigger: '.t3js-localConfiguration-write',
|
||||
selectorSearchTrigger: '.t3js-localConfiguration-search',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getContent();
|
||||
|
||||
// Write out new settings
|
||||
currentModal.on('click', this.selectorWriteTrigger, function() {
|
||||
self.write();
|
||||
});
|
||||
|
||||
// Expand / collapse "Toggle all" button
|
||||
currentModal.on('click', this.selectorToggleAllTrigger, function() {
|
||||
var modalContent = self.currentModal.find(self.selectorModalBody);
|
||||
var panels = modalContent.find('.panel-collapse');
|
||||
var action = (panels.eq(0).hasClass('in')) ? 'hide' : 'show';
|
||||
panels.collapse(action);
|
||||
});
|
||||
|
||||
// Make jquerys "contains" work case-insensitive
|
||||
jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) {
|
||||
return function(elem) {
|
||||
return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
|
||||
};
|
||||
});
|
||||
|
||||
// Focus search field on certain user interactions
|
||||
currentModal.on('keydown', function(e) {
|
||||
var $searchInput = currentModal.find(self.selectorSearchTrigger);
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
// Focus search field on ctrl-f
|
||||
switch (String.fromCharCode(e.which).toLowerCase()) {
|
||||
case 'f':
|
||||
e.preventDefault();
|
||||
$searchInput.focus();
|
||||
break;
|
||||
}
|
||||
} else if (e.keyCode === 27) {
|
||||
// Clear search on ESC key
|
||||
e.preventDefault();
|
||||
$searchInput.val('').focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Perform expand collapse on search matches
|
||||
currentModal.on('keyup', this.selectorSearchTrigger, function(e) {
|
||||
var typedQuery = $(e.target).val();
|
||||
var $searchInput = currentModal.find((self.selectorSearchTrigger));
|
||||
currentModal.find('div.item').each(function() {
|
||||
var $item = $(this);
|
||||
if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
|
||||
$item.removeClass('hidden').addClass('searchhit');
|
||||
} else {
|
||||
$item.removeClass('searchhit').addClass('hidden');
|
||||
}
|
||||
});
|
||||
currentModal.find('.searchhit').parent().collapse('show');
|
||||
// Make search field clearable
|
||||
require(['jquery.clearable'], function() {
|
||||
var searchResultShown = ('' !== $searchInput.first().val());
|
||||
$searchInput.clearable().focus();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getContent: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('localConfigurationGetContent'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.title, element.message);
|
||||
});
|
||||
}
|
||||
modalContent.html(data.html);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
write: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('local-configuration-write-token');
|
||||
var configurationValues = {};
|
||||
this.currentModal.find('.t3js-localConfiguration-pathValue').each(function(i, element) {
|
||||
var $element = $(element);
|
||||
if ($element.attr('type') === 'checkbox') {
|
||||
if (element.checked) {
|
||||
configurationValues[$element.data('path')] = '1';
|
||||
} else {
|
||||
configurationValues[$element.data('path')] = '0';
|
||||
}
|
||||
} else {
|
||||
configurationValues[$element.data('path')] = $element.val();
|
||||
}
|
||||
});
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'localConfigurationWrite',
|
||||
'token': executeToken,
|
||||
'configurationValues': configurationValues
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.showMessage(element.title, element.message, element.severity);
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/CreateAdmin
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorForm: '#t3js-mailTest-form',
|
||||
selectorEmail: '.t3js-mailTest-email',
|
||||
selectorOutputContainer: '.t3js-mailTest-output',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
currentModal.on('submit', this.selectorForm, function(e) {
|
||||
e.preventDefault();
|
||||
self.send();
|
||||
});
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('mailTestGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
send: function() {
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('mail-test-token');
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputContainer);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().html(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'mailTest',
|
||||
'token': executeToken,
|
||||
'email': this.currentModal.find('.t3js-mailTest-email').val()
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
$outputContainer.empty();
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.html(message);
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
// 500 can happen here if the mail configuration is broken
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/Cache
|
||||
*/
|
||||
define([
|
||||
'jquery'
|
||||
], function($) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
initialize: function(field) {
|
||||
// Simple password strength indicator
|
||||
$(document).on('keyup', field, function() {
|
||||
var value = $(this).val();
|
||||
var strongRegex = new RegExp('^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$', 'g');
|
||||
var mediumRegex = new RegExp('^(?=.{8,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$', 'g');
|
||||
var enoughRegex = new RegExp('(?=.{8,}).*', 'g');
|
||||
|
||||
if (value.length === 0) {
|
||||
$(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42');
|
||||
} else if (!enoughRegex.test(value)) {
|
||||
$(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42');
|
||||
} else if (strongRegex.test(value)) {
|
||||
$(this).attr('style', 'background-color:#CDEACA; border:1px solid #58B548');
|
||||
} else if (mediumRegex.test(value)) {
|
||||
$(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D');
|
||||
} else {
|
||||
$(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/LanguagePacks
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
currentModal: {},
|
||||
|
||||
|
||||
initialize: function(currentModal) {
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('phpInfoGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/Presets
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-presets-content',
|
||||
selectorActivateTrigger: '.t3js-presets-activate',
|
||||
selectorOutputContainer: '.t3js-presets-output',
|
||||
selectorImageExecutable: '.t3js-presets-image-executable',
|
||||
selectorImageExecutableTrigger: '.t3js-presets-image-executable-trigger',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.getContent();
|
||||
|
||||
// Load content with post data on click 'custom image executable path'
|
||||
currentModal.on('click', this.selectorImageExecutableTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.getCustomImagePathContent();
|
||||
});
|
||||
|
||||
// Write out selected preset
|
||||
currentModal.on('click', this.selectorActivateTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.activate();
|
||||
});
|
||||
|
||||
// Automatically select the custom preset if a value in one of its input fields is changed
|
||||
currentModal.find('.t3js-custom-preset').on('input', '.t3js-custom-preset', function(e) {
|
||||
$('#' + $(this).data('radio')).prop('checked', true);
|
||||
});
|
||||
},
|
||||
|
||||
getContent: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('presetsGetContent'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getCustomImagePathContent: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var presetsContentToken = this.currentModal.find(this.selectorModuleContent).data('presets-content-token');
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'token': presetsContentToken,
|
||||
'action': 'presetsGetContent',
|
||||
'values': {
|
||||
'Image': {
|
||||
'additionalSearchPath': this.currentModal.find(this.selectorImageExecutable).val()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('presets-activate-token');
|
||||
var postData = {};
|
||||
$(this.currentModal.find(this.selectorModuleContent + ' form').serializeArray()).each(function() {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
postData['install[action]'] = 'presetsActivate';
|
||||
postData['install[token]'] = executeToken;
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.showMessage(element.title, element.message, element.severity);
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/ProgressBar
|
||||
*/
|
||||
define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @type {{template: (*)}}
|
||||
*/
|
||||
var ProgressBar = {
|
||||
template: $('<div class="progress"><div class="t3js-progressbar progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <span></span></div></div>')
|
||||
};
|
||||
|
||||
/**
|
||||
* render a ProgressBar
|
||||
* @param {Number} severity
|
||||
* @param {String} title
|
||||
* @param {Number} progress
|
||||
* @returns {jQuery}
|
||||
*/
|
||||
ProgressBar.render = function(severity, title, progress) {
|
||||
var progressBar = this.template.clone();
|
||||
progressBar.addClass('progress-bar-' + Severity.getCssClass(severity));
|
||||
if (progress) {
|
||||
progressBar.css('width', progress + '%');
|
||||
progressBar.attr('aria-valuenow', progresss);
|
||||
}
|
||||
if (title) {
|
||||
progressBar.find('span').text(title);
|
||||
}
|
||||
return progressBar;
|
||||
};
|
||||
|
||||
return ProgressBar;
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/DumpAutoload
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorOutputContainer: '.t3js-resetBackendUserUc-output',
|
||||
|
||||
initialize: function($trigger) {
|
||||
$.ajax({
|
||||
url: Router.getUrl('resetBackendUserUc'),
|
||||
cache: false,
|
||||
beforeSend: function() {
|
||||
$trigger.addClass('disabled');
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
if (data.status.length > 0) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.message);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong ...');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
// If reset fails on server side (typically a 500), do not crash entire install tool
|
||||
// but render an error notification instead.
|
||||
Notification.error('Resetting backend user uc failed. Please check the system for missing database fields and try again.');
|
||||
},
|
||||
complete: function() {
|
||||
$trigger.removeClass('disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/Router
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Backend/Modal',
|
||||
'TYPO3/CMS/Backend/Icons'
|
||||
], function($, InfoBox, Severity, ProgressBar, Modal, Icons) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorBody: '.t3js-body',
|
||||
selectorMainContent: '.t3js-module-body',
|
||||
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
|
||||
this.registerInstallToolRoutes();
|
||||
|
||||
$(document).on('click', '.t3js-login-lockInstallTool', function(e) {
|
||||
e.preventDefault();
|
||||
self.logout();
|
||||
});
|
||||
$(document).on('click', '.t3js-login-login', function(e) {
|
||||
e.preventDefault();
|
||||
self.login();
|
||||
});
|
||||
$(document).on('keydown', '#t3-install-form-password', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
$('.t3js-login-login').click();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.card .btn', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $me = $(e.currentTarget);
|
||||
var requireModule = $me.data('require');
|
||||
var inlineState = $me.data('inline');
|
||||
var isInline = typeof inlineState !== 'undefined' && parseInt(inlineState) === 1;
|
||||
if (isInline) {
|
||||
require([requireModule], function(aModule) {
|
||||
if (typeof aModule.initialize !== 'undefined') {
|
||||
aModule.initialize($me);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var modalTitle = $me.closest('.card').find('.card-title').html();
|
||||
var modalSize = $me.data('modalSize') || Modal.sizes.large;
|
||||
var $modal = Modal.advanced({
|
||||
type: Modal.types.default,
|
||||
title: modalTitle,
|
||||
size: modalSize,
|
||||
content: $('<div class="modal-loading">'),
|
||||
additionalCssClasses: ['install-tool-modal'],
|
||||
callback: function (currentModal) {
|
||||
require([requireModule], function (aModule) {
|
||||
if (typeof aModule.initialize !== 'undefined') {
|
||||
aModule.initialize(currentModal);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
Icons.getIcon('spinner-circle', Icons.sizes.default, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
|
||||
$modal.find('.modal-loading').append(icon);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if ($(this.selectorBody).data('context') === 'backend') {
|
||||
this.executeSilentConfigurationUpdate();
|
||||
} else {
|
||||
this.preAccessCheck();
|
||||
}
|
||||
},
|
||||
|
||||
registerInstallToolRoutes: function() {
|
||||
if (typeof TYPO3.settings === 'undefined') {
|
||||
TYPO3.settings = {
|
||||
ajaxUrls: {
|
||||
icons: '?install[controller]=icon&install[action]=getIcon',
|
||||
icons_cache: '?install[controller]=icon&install[action]=getCacheIdentifier'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getUrl: function(action, controller) {
|
||||
var url = location.href;
|
||||
var context = $(this.selectorBody).data('context');
|
||||
url = url.replace(location.search, '');
|
||||
if (controller === undefined) {
|
||||
controller = $(this.selectorBody).data('controller');
|
||||
}
|
||||
url = url + '?install[controller]=' + controller;
|
||||
if (context !== undefined && context !== '') {
|
||||
url = url + '&install[context]=' + context;
|
||||
}
|
||||
if (action !== undefined) {
|
||||
url = url + '&install[action]=' + action;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
preAccessCheck: function() {
|
||||
this.updateLoadingInfo("Execute pre access check");
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl("preAccessCheck", "layout"),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.installToolLocked) {
|
||||
self.checkEnableInstallToolFile();
|
||||
} else if (!data.isAuthorized) {
|
||||
self.showLogin();
|
||||
} else {
|
||||
self.executeSilentConfigurationUpdate();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
executeSilentConfigurationUpdate: function() {
|
||||
var self = this;
|
||||
this.updateLoadingInfo('Checking session and executing silent configuration update');
|
||||
$.ajax({
|
||||
url: this.getUrl('executeSilentConfigurationUpdate', 'layout'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.executeSilentLegacyExtConfExtensionConfigurationUpdate();
|
||||
} else {
|
||||
self.executeSilentConfigurationUpdate();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Legacy layer to upmerge LocalConfiguration EXT/extConf serialized array keys
|
||||
* to EXTENSIONS array in LocalConfiguration for initial update from v8 to v9.
|
||||
*
|
||||
* @deprecated since TYPO3 v9, will be removed with v10 - re-route executeSilentConfigurationUpdate()
|
||||
* to executeSilentExtensionConfigurationUpdate() on removal of this function.
|
||||
*/
|
||||
executeSilentLegacyExtConfExtensionConfigurationUpdate: function() {
|
||||
var self = this;
|
||||
this.updateLoadingInfo('Executing silent extension configuration update');
|
||||
$.ajax({
|
||||
url: this.getUrl('executeSilentLegacyExtConfExtensionConfigurationUpdate', 'layout'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.executeSilentExtensionConfigurationSynchronization();
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.error, 'Something went wrong', '');
|
||||
$outputContainer.empty().append(message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Extensions which come with new default settings in ext_conf_template.txt extension
|
||||
* configuration files get their new defaults written to LocalConfiguration.
|
||||
*/
|
||||
executeSilentExtensionConfigurationSynchronization: function() {
|
||||
var self = this;
|
||||
this.updateLoadingInfo('Executing silent extension configuration synchronization');
|
||||
$.ajax({
|
||||
url: this.getUrl('executeSilentExtensionConfigurationSynchronization', 'layout'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.loadMainLayout();
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.error, 'Something went wrong', '');
|
||||
$outputContainer.empty().append(message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadMainLayout: function() {
|
||||
var self = this;
|
||||
var $outputContainer = $(this.selectorBody);
|
||||
this.updateLoadingInfo('Loading main layout');
|
||||
$.ajax({
|
||||
url: this.getUrl('mainLayout', 'layout'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
|
||||
$outputContainer.empty().append(data.html);
|
||||
// Mark main module as active in standalone
|
||||
if ($(self.selectorBody).data('context') !== 'backend') {
|
||||
var controller = $outputContainer.data('controller');
|
||||
$outputContainer.find('.t3js-mainmodule[data-controller="' + controller + '"]').addClass('active');
|
||||
}
|
||||
self.loadCards();
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.error, 'Something went wrong', '');
|
||||
$outputContainer.empty().append(message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleAjaxError: function(xhr, $outputContainer) {
|
||||
var message = '';
|
||||
if (xhr.status === 403) {
|
||||
// Install tool session expired - depending on context render error message or login
|
||||
var context = $(this.selectorBody).data('context');
|
||||
if (context === 'backend') {
|
||||
message = InfoBox.render(
|
||||
Severity.error,
|
||||
'The install tool session expired. Please reload the backend and try again.'
|
||||
);
|
||||
$(this.selectorBody).empty().append(message);
|
||||
} else {
|
||||
this.checkEnableInstallToolFile();
|
||||
}
|
||||
} else {
|
||||
// @todo Recovery tests should be started here
|
||||
var url = this.getUrl(undefined, 'upgrade');
|
||||
message =
|
||||
'<div class="t3js-infobox callout callout-sm callout-danger">'
|
||||
+ '<div class="callout-body">'
|
||||
+ '<p>Something went wrong. Please use <b><a href="' + url + '">Check for broken'
|
||||
+ ' extensions</a></b> to see if a loaded extension breaks this part of the install tool'
|
||||
+ ' and unload it.</p>'
|
||||
+ '<p>The box below may additionally reveal further details on what went wrong depending on your debug settings.'
|
||||
+ ' It may help to temporarily switch to debug mode using <b>Settings > Configuration Presets > Debug settings.</b></p>'
|
||||
+ '<p>If this error happens at an early state and no full exception back trace is shown, it may also help'
|
||||
+ ' to manually increase debugging output in <code>typo3conf/LocalConfiguration.php</code>:'
|
||||
+ '<code>[\'BE\'][\'debug\'] => true</code>, <code>[\'SYS\'][\'devIPmask\'] => \'*\'</code>, <code>[\'SYS\'][\'displayErrors\'] => 1</code>,'
|
||||
+ '<code>[\'SYS\'][\'systemLogLevel\'] => 0</code>, <code>[\'SYS\'][\'exceptionalErrors\'] => 12290</code></p>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '<div class="panel-group" role="tablist" aria-multiselectable="true">'
|
||||
+ '<div class="panel panel-default panel-flat searchhit">'
|
||||
+ '<div class="panel-heading" role="tab" id="heading-error">'
|
||||
+ '<h3 class="panel-title">'
|
||||
+ '<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse-error" aria-expanded="true" aria-controls="collapse-error" class="collapsed">'
|
||||
+ '<span class="caret"></span>'
|
||||
+ '<strong>Ajax error</strong>'
|
||||
+ '</a>'
|
||||
+'</h3>'
|
||||
+ '</div>'
|
||||
+ '<div id="collapse-error" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-error">'
|
||||
+ '<div class="panel-body">'
|
||||
+ xhr.responseText
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
+ '</div>';
|
||||
|
||||
if (typeof $outputContainer !== 'undefined') {
|
||||
// Write to given output container. This is typically a modal if given
|
||||
$outputContainer.empty().html(message);
|
||||
} else {
|
||||
// Else write to main frame
|
||||
$(this.selectorBody).empty().html(message);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
checkEnableInstallToolFile: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('checkEnableInstallToolFile'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.checkLogin();
|
||||
} else {
|
||||
self.showEnableInstallTool();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showEnableInstallTool: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('showEnableInstallToolFile'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$(self.selectorBody).empty().append(data.html);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkLogin: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('checkLogin'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.loadMainLayout();
|
||||
} else {
|
||||
self.showLogin();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showLogin: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: this.getUrl('showLogin'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
$(self.selectorBody).empty().append(data.html);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
login: function() {
|
||||
var self = this;
|
||||
var $outputContainer = $('.t3js-login-output');
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().html(message);
|
||||
$.ajax({
|
||||
url: this.getUrl(),
|
||||
cache: false,
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'login',
|
||||
'token': $('[data-login-token]').data('login-token'),
|
||||
'password': $('.t3-install-form-input-text').val()
|
||||
}
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.executeSilentConfigurationUpdate();
|
||||
} else {
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.empty().html(message);
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
logout: function() {
|
||||
var self = this;
|
||||
$.ajax({
|
||||
url: self.getUrl('logout'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
self.showEnableInstallTool();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadCards: function() {
|
||||
var self = this;
|
||||
var outputContainer = $(this.selectorMainContent);
|
||||
$.ajax({
|
||||
url: this.getUrl('cards'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
|
||||
outputContainer.empty().append(data.html);
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.error, 'Something went wrong', '');
|
||||
outputContainer.empty().append(message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
self.handleAjaxError(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateLoadingInfo: function(info) {
|
||||
var $outputContainer = $(this.selectorBody);
|
||||
$outputContainer.find('#t3js-ui-block-detail').text(info);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/Severity
|
||||
*/
|
||||
define([], function() {
|
||||
'use strict';
|
||||
|
||||
var Severity = {
|
||||
loading: -3,
|
||||
notice: -2,
|
||||
info: -1,
|
||||
ok: 0,
|
||||
warning: 1,
|
||||
error: 2
|
||||
};
|
||||
|
||||
Severity.getCssClass = function(severity) {
|
||||
var severityClass;
|
||||
switch (severity) {
|
||||
case Severity.loading:
|
||||
severityClass = 'notice alert-loading';
|
||||
break;
|
||||
case Severity.notice:
|
||||
severityClass = 'notice';
|
||||
break;
|
||||
case Severity.ok:
|
||||
severityClass = 'success';
|
||||
break;
|
||||
case Severity.warning:
|
||||
severityClass = 'warning';
|
||||
break;
|
||||
case Severity.error:
|
||||
severityClass = 'danger';
|
||||
break;
|
||||
case Severity.info:
|
||||
default:
|
||||
severityClass = 'info';
|
||||
}
|
||||
return severityClass;
|
||||
};
|
||||
|
||||
return Severity;
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/LanguagePacks
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
currentModal: {},
|
||||
|
||||
|
||||
initialize: function(currentModal) {
|
||||
this.currentModal = currentModal;
|
||||
this.getData();
|
||||
},
|
||||
|
||||
getData: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('systemInformationGetData'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/SystemMaintainer
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap',
|
||||
'chosen'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorWriteTrigger: '.t3js-systemMaintainer-write',
|
||||
selectorOutputContainer: '.t3js-systemMaintainer-output',
|
||||
selectorChosenContainer: '.t3js-systemMaintainer-chosen',
|
||||
selectorChosenField: '.t3js-systemMaintainer-chosen-select',
|
||||
currentModal: {},
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
var isInIframe = window.location !== window.parent.location;
|
||||
if (isInIframe) {
|
||||
top.require(['TYPO3/CMS/Install/chosen.jquery.min'], function () {
|
||||
self.getList();
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.getList();
|
||||
}
|
||||
|
||||
currentModal.on('click', this.selectorWriteTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.write();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
getList: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
$.ajax({
|
||||
url: Router.getUrl('systemMaintainerGetList'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.title, element.message);
|
||||
});
|
||||
}
|
||||
modalContent.html((data.html));
|
||||
if (Array.isArray(data.users)) {
|
||||
data.users.forEach(function(element) {
|
||||
var name = element.username;
|
||||
if (element.disable) {
|
||||
name = '[DISABLED] ' + name;
|
||||
}
|
||||
var $option = $('<option>', {'value': element.uid}).text(name);
|
||||
if (element.isSystemMaintainer) {
|
||||
$option.attr('selected', 'selected');
|
||||
}
|
||||
modalContent.find(self.selectorChosenField).append($option);
|
||||
});
|
||||
}
|
||||
var config = {
|
||||
'.t3js-systemMaintainer-chosen-select': {width: "100%", placeholder_text_multiple: "users"}
|
||||
};
|
||||
|
||||
for (var selector in config) {
|
||||
modalContent.find(selector).chosen(config[selector]);
|
||||
}
|
||||
modalContent.find(self.selectorChosenContainer).show();
|
||||
modalContent.find(self.selectorChosenField).trigger('chosen:updated');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
|
||||
write: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('system-maintainer-write-token');
|
||||
var selectedUsers = this.currentModal.find(this.selectorChosenField).val();
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: Router.getUrl(),
|
||||
data: {
|
||||
'install': {
|
||||
'users': selectedUsers,
|
||||
'token': executeToken,
|
||||
'action': 'systemMaintainerWrite'
|
||||
}
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function(element) {
|
||||
Notification.success(element.title, element.message);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/TcaExtTablesCheck
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorCheckTrigger: '.t3js-tcaExtTablesCheck-check',
|
||||
selectorOutputContainer: '.t3js-tcaExtTablesCheck-output',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.check();
|
||||
currentModal.on('click', this.selectorCheckTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.check();
|
||||
});
|
||||
},
|
||||
|
||||
check: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = $(this.selectorOutputContainer);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().html(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl('tcaExtTablesCheck'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
modalContent.empty().append(data.html);
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
if (data.status.length > 0) {
|
||||
var message = InfoBox.render(
|
||||
Severity.warning,
|
||||
'Following extensions change TCA in ext_tables.php',
|
||||
'Check ext_tables.php files, look for ExtensionManagementUtility calls and $GLOBALS[\'TCA\'] modifications'
|
||||
);
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
modalContent.append(message);
|
||||
});
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.ok, 'No TCA changes in ext_tables.php files. Good job!', '');
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong', 'Use "Check for broken extensions"');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/TcaIntegrityChecker
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification'
|
||||
], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorCheckTrigger: '.t3js-tcaMigrationsCheck-check',
|
||||
selectorOutputContainer: '.t3js-tcaMigrationsCheck-output',
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
this.check();
|
||||
currentModal.on('click', this.selectorCheckTrigger, function(e) {
|
||||
e.preventDefault();
|
||||
self.check();
|
||||
});
|
||||
},
|
||||
|
||||
check: function() {
|
||||
var self = this;
|
||||
var $outputContainer = $(this.selectorOutputContainer);
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var message = ProgressBar.render(Severity.loading, 'Loading...', '');
|
||||
$outputContainer.empty().html(message);
|
||||
$.ajax({
|
||||
url: Router.getUrl('tcaMigrationsCheck'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
modalContent.empty().append(data.html);
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
if (data.status.length > 0) {
|
||||
var message = InfoBox.render(
|
||||
Severity.warning,
|
||||
'TCA migrations need to be applied',
|
||||
'Check the following list and apply needed changes.'
|
||||
);
|
||||
modalContent.find(self.selectorOutputContainer).empty();
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
data.status.forEach(function(element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
});
|
||||
} else {
|
||||
var message = InfoBox.render(Severity.ok, 'No TCA migrations need to be applied', 'Your TCA looks good.');
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
}
|
||||
} else {
|
||||
var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"');
|
||||
modalContent.find(self.selectorOutputContainer).append(message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/UpgradeDocs
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'bootstrap',
|
||||
'chosen',
|
||||
'jquery.clearable'
|
||||
], function($, Router, ProgressBar, InfoBox, Severity, Notification) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorFulltextSearch: '.t3js-upgradeDocs-fulltext-search',
|
||||
selectorChosenField: '.t3js-upgradeDocs-chosen-select',
|
||||
selectorChangeLogsForVersionContainer: '.t3js-version-changes',
|
||||
selectorChangeLogsForVersion: '.t3js-changelog-list',
|
||||
selectorUpgradeDoc: '.t3js-upgrade-doc',
|
||||
|
||||
chosenField: null,
|
||||
fulltextSearchField: null,
|
||||
|
||||
initialize: function(currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
var isInIframe = (window.location !== window.parent.location);
|
||||
if (isInIframe) {
|
||||
top.require(['TYPO3/CMS/Install/chosen.jquery.min'], function () {
|
||||
self.getContent();
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.getContent();
|
||||
}
|
||||
|
||||
// Mark a file as read
|
||||
currentModal.on('click', '.t3js-upgradeDocs-markRead', function(e) {
|
||||
self.markRead(e.target);
|
||||
});
|
||||
currentModal.on('click', '.t3js-upgradeDocs-unmarkRead', function(e) {
|
||||
self.unmarkRead(e.target);
|
||||
});
|
||||
|
||||
// Make jquerys "contains" work case-insensitive
|
||||
jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) {
|
||||
return function(elem) {
|
||||
return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getContent: function() {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
modalContent.on('show.bs.collapse', this.selectorUpgradeDoc, function (e) {
|
||||
self.renderTags($(e.currentTarget));
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeDocsGetContent'),
|
||||
cache: false,
|
||||
success: function(data) {
|
||||
if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
|
||||
modalContent.empty().append(data.html);
|
||||
|
||||
self.initializeFullTextSearch();
|
||||
self.initializeChosenSelector();
|
||||
self.loadChangelogs();
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadChangelogs: function() {
|
||||
var self = this;
|
||||
var promises = [];
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
this.currentModal.find(this.selectorChangeLogsForVersionContainer).each(function(index, el) {
|
||||
var $request = $.ajax({
|
||||
url: Router.getUrl('upgradeDocsGetChangelogForVersion'),
|
||||
cache: false,
|
||||
data: {
|
||||
install: {
|
||||
version: el.dataset.version
|
||||
}
|
||||
},
|
||||
success: function(data) {
|
||||
if (data.success === true) {
|
||||
var $panelGroup = $(el);
|
||||
var $container = $panelGroup.find(self.selectorChangeLogsForVersion);
|
||||
$container.html(data.html);
|
||||
self.moveNotRelevantDocuments($container);
|
||||
|
||||
// Remove loading spinner form panel
|
||||
$panelGroup.find('.t3js-panel-loading').remove();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
|
||||
promises.push($request);
|
||||
});
|
||||
|
||||
$.when.apply($, promises).done(function () {
|
||||
self.fulltextSearchField.prop('disabled', false);
|
||||
self.appendItemsToChosenSelector();
|
||||
});
|
||||
},
|
||||
|
||||
initializeFullTextSearch: function() {
|
||||
var self = this;
|
||||
this.fulltextSearchField = this.currentModal.find(this.selectorFulltextSearch);
|
||||
this.fulltextSearchField.clearable().focus();
|
||||
this.initializeChosenSelector();
|
||||
this.fulltextSearchField.on('keyup', function() {
|
||||
self.combinedFilterSearch();
|
||||
});
|
||||
},
|
||||
|
||||
initializeChosenSelector: function() {
|
||||
var self = this;
|
||||
this.chosenField = this.currentModal.find(this.selectorModalBody).find(this.selectorChosenField);
|
||||
|
||||
var config = {
|
||||
'.chosen-select': {width: "100%", placeholder_text_multiple: "tags"},
|
||||
'.chosen-select-deselect': {allow_single_deselect: true},
|
||||
'.chosen-select-no-single': {disable_search_threshold: 10},
|
||||
'.chosen-select-no-results': {no_results_text: 'Oops, nothing found!'},
|
||||
'.chosen-select-width': {width: "100%"}
|
||||
};
|
||||
for (var selector in config) {
|
||||
this.currentModal.find(selector).chosen(config[selector]);
|
||||
}
|
||||
this.chosenField.on('change', function() {
|
||||
self.combinedFilterSearch();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Appends tags to the chosen selector
|
||||
*/
|
||||
appendItemsToChosenSelector: function() {
|
||||
var self = this;
|
||||
var tagString = '';
|
||||
$(this.currentModal.find(this.selectorUpgradeDoc)).each(function() {
|
||||
tagString += $(this).data('item-tags') + ',';
|
||||
});
|
||||
var tagArray = this.trimExplodeAndUnique(',', tagString).sort(function(a, b) {
|
||||
// Sort case-insensitive by name
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
});
|
||||
this.chosenField.prop('disabled', false);
|
||||
$.each(tagArray, function(i, tag) {
|
||||
self.chosenField.append($('<option>').text(tag));
|
||||
});
|
||||
this.chosenField.trigger('chosen:updated');
|
||||
},
|
||||
|
||||
combinedFilterSearch: function() {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $items = modalContent.find('div.item');
|
||||
if (this.chosenField.val().length < 1 && this.fulltextSearchField.val().length < 1) {
|
||||
this.currentModal.find('.panel-version .panel-collapse.in').collapse('hide');
|
||||
$items.removeClass('hidden searchhit filterhit');
|
||||
return false;
|
||||
}
|
||||
$items.addClass('hidden').removeClass('searchhit filterhit');
|
||||
|
||||
// apply tags
|
||||
if (this.chosenField.val().length > 0) {
|
||||
$items
|
||||
.addClass('hidden')
|
||||
.removeClass('filterhit');
|
||||
var orTags = [];
|
||||
var andTags = [];
|
||||
$.each(this.chosenField.val(), function(index, item) {
|
||||
var tagFilter = '[data-item-tags*="' + item + '"]';
|
||||
if (item.indexOf(':') > 0) {
|
||||
orTags.push(tagFilter);
|
||||
} else {
|
||||
andTags.push(tagFilter);
|
||||
}
|
||||
});
|
||||
var andString = andTags.join('');
|
||||
var tags = [];
|
||||
if (orTags.length) {
|
||||
for (var i = 0; i < orTags.length; i++) {
|
||||
tags.push(andString + orTags[i]);
|
||||
}
|
||||
} else {
|
||||
tags.push(andString);
|
||||
}
|
||||
var tagSelection = tags.join(',');
|
||||
modalContent.find(tagSelection)
|
||||
.removeClass('hidden')
|
||||
.addClass('searchhit filterhit');
|
||||
} else {
|
||||
$items
|
||||
.addClass('filterhit')
|
||||
.removeClass('hidden');
|
||||
}
|
||||
// apply fulltext search
|
||||
var typedQuery = this.fulltextSearchField.val();
|
||||
modalContent.find('div.item.filterhit').each(function() {
|
||||
var $item = $(this);
|
||||
if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
|
||||
$item.removeClass('hidden').addClass('searchhit');
|
||||
} else {
|
||||
$item.removeClass('searchhit').addClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
modalContent.find('.searchhit').closest('.panel-collapse').collapse('show');
|
||||
|
||||
//check for empty panels
|
||||
modalContent.find('.panel-version').each(function() {
|
||||
if ($(this).find('.searchhit', '.filterhit').length < 1) {
|
||||
$(this).find(' > .panel-collapse').collapse('hide');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
renderTags: function($upgradeDocumentContainer) {
|
||||
var $tagContainer = $upgradeDocumentContainer.find('.t3js-tags');
|
||||
if ($tagContainer.children().length === 0) {
|
||||
var tags = $upgradeDocumentContainer.data('item-tags').split(',');
|
||||
tags.forEach(function (value) {
|
||||
$tagContainer.append($('<span />', {'class': 'label'}).text(value));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves all documents that are either read or not affected
|
||||
*
|
||||
* @param {JQuery} $container
|
||||
*/
|
||||
moveNotRelevantDocuments: function($container) {
|
||||
$container.find('[data-item-state="read"]').appendTo(this.currentModal.find('.panel-body-read'));
|
||||
$container.find('[data-item-state="notAffected"]').appendTo(this.currentModal.find('.panel-body-not-affected'));
|
||||
},
|
||||
|
||||
markRead: function(element) {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('upgrade-docs-mark-read-token');
|
||||
var $button = $(element).closest('a');
|
||||
$button.toggleClass('t3js-upgradeDocs-unmarkRead t3js-upgradeDocs-markRead');
|
||||
$button.find('i').toggleClass('fa-check fa-ban');
|
||||
$button.closest('.panel').appendTo(this.currentModal.find('.panel-body-read'));
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: Router.getUrl(),
|
||||
data: {
|
||||
'install': {
|
||||
'ignoreFile': $button.data('filepath'),
|
||||
'token': executeToken,
|
||||
'action': 'upgradeDocsMarkRead'
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unmarkRead: function(element) {
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('upgrade-docs-unmark-read-token');
|
||||
var $button = $(element).closest('a');
|
||||
var version = $button.closest('.panel').data('item-version');
|
||||
$button.toggleClass('t3js-upgradeDocs-markRead t3js-upgradeDocs-unmarkRead');
|
||||
$button.find('i').toggleClass('fa-check fa-ban');
|
||||
$button.closest('.panel').appendTo(this.currentModal.find('*[data-group-version="' + version + '"] .panel-body'));
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: Router.getUrl(),
|
||||
data: {
|
||||
'install': {
|
||||
'ignoreFile': $button.data('filepath'),
|
||||
'token': executeToken,
|
||||
action: 'upgradeDocsUnmarkRead'
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
Router.handleAjaxError(xhr, modalContent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
trimExplodeAndUnique: function(delimiter, string) {
|
||||
var result = [];
|
||||
var items = string.split(delimiter);
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var item = items[i].trim();
|
||||
if (item.length > 0) {
|
||||
if ($.inArray(item, result) === -1) {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module: TYPO3/CMS/Install/UpgradeWizards
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'TYPO3/CMS/Install/Router',
|
||||
'TYPO3/CMS/Install/FlashMessage',
|
||||
'TYPO3/CMS/Install/ProgressBar',
|
||||
'TYPO3/CMS/Install/InfoBox',
|
||||
'TYPO3/CMS/Install/Severity',
|
||||
'TYPO3/CMS/Backend/Notification',
|
||||
'TYPO3/CMS/Core/SecurityUtility'
|
||||
],
|
||||
function ($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Notification, SecurityUtility) {
|
||||
'use strict';
|
||||
|
||||
var securityUtility = new SecurityUtility();
|
||||
|
||||
return {
|
||||
selectorModalBody: '.t3js-modal-body',
|
||||
selectorModuleContent: '.t3js-module-content',
|
||||
selectorOutputWizardsContainer: '.t3js-upgradeWizards-wizards-output',
|
||||
selectorOutputDoneContainer: '.t3js-upgradeWizards-done-output',
|
||||
selectorWizardsBlockingAddsTemplate: '.t3js-upgradeWizards-blocking-adds-template',
|
||||
selectorWizardsBlockingAddsRows: '.t3js-upgradeWizards-blocking-adds-rows',
|
||||
selectorWizardsBlockingAddsExecute: '.t3js-upgradeWizards-blocking-adds-execute',
|
||||
selectorWizardsBlockingCharsetTemplate: '.t3js-upgradeWizards-blocking-charset-template',
|
||||
selectorWizardsBlockingCharsetFix: '.t3js-upgradeWizards-blocking-charset-fix',
|
||||
selectorWizardsDoneBodyTemplate: '.t3js-upgradeWizards-done-body-template',
|
||||
selectorWizardsDoneRows: '.t3js-upgradeWizards-done-rows',
|
||||
selectorWizardsDoneRowTemplate: '.t3js-upgradeWizards-done-row-template table tr',
|
||||
selectorWizardsDoneRowMarkUndone: '.t3js-upgradeWizards-done-markUndone',
|
||||
selectorWizardsDoneRowTitle: '.t3js-upgradeWizards-done-title',
|
||||
selectorWizardsListTemplate: '.t3js-upgradeWizards-list-template',
|
||||
selectorWizardsListRows: '.t3js-upgradeWizards-list-rows',
|
||||
selectorWizardsListRowTemplate: '.t3js-upgradeWizards-list-row-template',
|
||||
selectorWizardsListRowTitle: '.t3js-upgradeWizards-list-row-title',
|
||||
selectorWizardsListRowExplanation: '.t3js-upgradeWizards-list-row-explanation',
|
||||
selectorWizardsListRowExecute: '.t3js-upgradeWizards-list-row-execute',
|
||||
selectorWizardsInputTemplate: '.t3js-upgradeWizards-input',
|
||||
selectorWizardsInputTitle: '.t3js-upgradeWizards-input-title',
|
||||
selectorWizardsInputHtml: '.t3js-upgradeWizards-input-html',
|
||||
selectorWizardsInputPerform: '.t3js-upgradeWizards-input-perform',
|
||||
|
||||
initialize: function (currentModal) {
|
||||
var self = this;
|
||||
this.currentModal = currentModal;
|
||||
|
||||
this.getData().done(function() {
|
||||
self.doneUpgrades();
|
||||
});
|
||||
|
||||
// Mark a done wizard undone
|
||||
currentModal.on('click', this.selectorWizardsDoneRowMarkUndone, function (e) {
|
||||
self.markUndone(e.target.dataset.identifier);
|
||||
});
|
||||
|
||||
// Execute "fix default mysql connection db charset" blocking wizard
|
||||
currentModal.on('click', this.selectorWizardsBlockingCharsetFix, function (e) {
|
||||
self.blockingUpgradesDatabaseCharsetFix();
|
||||
});
|
||||
|
||||
// Execute "add required fields + tables" blocking wizard
|
||||
currentModal.on('click', this.selectorWizardsBlockingAddsExecute, function (e) {
|
||||
self.blockingUpgradesDatabaseAddsExecute();
|
||||
});
|
||||
|
||||
// Get user input of a single upgrade wizard
|
||||
currentModal.on('click', this.selectorWizardsListRowExecute, function (e) {
|
||||
self.wizardInput(e.target.dataset.identifier, e.target.dataset.title);
|
||||
});
|
||||
|
||||
// Execute one upgrade wizard
|
||||
currentModal.on('click', this.selectorWizardsInputPerform, function (e) {
|
||||
self.wizardExecute(e.target.dataset.identifier, e.target.dataset.title);
|
||||
});
|
||||
},
|
||||
|
||||
renderProgressBar: function (title) {
|
||||
return ProgressBar.render(Severity.loading, title, '')
|
||||
},
|
||||
|
||||
getData: function () {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
return $.ajax({
|
||||
url: Router.getUrl('upgradeWizardsGetData'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
if (data.success === true) {
|
||||
modalContent.empty().append(data.html);
|
||||
self.blockingUpgradesDatabaseCharsetTest();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
blockingUpgradesDatabaseCharsetTest: function () {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputWizardsContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Checking database charset...'));
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetTest'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
if (data.success === true) {
|
||||
if (data.needsUpdate === true) {
|
||||
modalContent.find(self.selectorOutputWizardsContainer).append(modalContent.find(self.selectorWizardsBlockingCharsetTemplate)).clone();
|
||||
} else {
|
||||
self.blockingUpgradesDatabaseAdds();
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
blockingUpgradesDatabaseCharsetFix: function () {
|
||||
var self = this;
|
||||
var $outputContainer = $(this.selectorOutputWizardsContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Setting database charset to UTF-8...'));
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetFix'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status) && data.status.length > 0) {
|
||||
data.status.forEach(function (element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
$outputContainer.append(message);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
blockingUpgradesDatabaseAdds: function () {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputWizardsContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Check for missing mandatory database tables and fields...'));
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeWizardsBlockingDatabaseAdds'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
if (data.success === true) {
|
||||
if (data.needsUpdate === true) {
|
||||
var adds = modalContent.find(self.selectorWizardsBlockingAddsTemplate).clone();
|
||||
if (typeof(data.adds.tables) === 'object') {
|
||||
data.adds.tables.forEach(function (element) {
|
||||
var title = 'Table: ' + securityUtility.encodeHtml(element.table);
|
||||
adds.find(self.selectorWizardsBlockingAddsRows).append(title, '<br>');
|
||||
});
|
||||
}
|
||||
if (typeof(data.adds.columns) === 'object') {
|
||||
data.adds.columns.forEach(function (element) {
|
||||
var title = 'Table: ' + securityUtility.encodeHtml(element.table)
|
||||
+ ', Field: ' + securityUtility.encodeHtml(element.field);
|
||||
adds.find(self.selectorWizardsBlockingAddsRows).append(title, '<br>');
|
||||
});
|
||||
}
|
||||
if (typeof(data.adds.indexes) === 'object') {
|
||||
data.adds.indexes.forEach(function (element) {
|
||||
var title = 'Table: ' + securityUtility.encodeHtml(element.table)
|
||||
+ ', Index: ' + securityUtility.encodeHtml(element.index);
|
||||
adds.find(self.selectorWizardsBlockingAddsRows).append(title, '<br>');
|
||||
});
|
||||
}
|
||||
modalContent.find(self.selectorOutputWizardsContainer).append(adds);
|
||||
} else {
|
||||
self.wizardsList();
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
blockingUpgradesDatabaseAddsExecute: function () {
|
||||
var self = this;
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputWizardsContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Adding database tables and fields...'));
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeWizardsBlockingDatabaseExecute'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status) && data.status.length > 0) {
|
||||
data.status.forEach(function (element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
});
|
||||
self.wizardsList();
|
||||
}
|
||||
} else {
|
||||
var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
$outputContainer.append(message);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wizardsList: function () {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputWizardsContainer);
|
||||
$outputContainer.append(this.renderProgressBar('Loading upgrade wizards...'));
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeWizardsList'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
var list = modalContent.find(self.selectorWizardsListTemplate).clone();
|
||||
list.removeClass('t3js-upgradeWizards-list-template');
|
||||
if (data.success === true) {
|
||||
var numberOfWizardsTodo = 0;
|
||||
var numberOfWizards = 0;
|
||||
if (Array.isArray(data.wizards) && data.wizards.length > 0) {
|
||||
numberOfWizards = data.wizards.length;
|
||||
data.wizards.forEach(function (element) {
|
||||
if (element.shouldRenderWizard === true) {
|
||||
var aRow = modalContent.find(self.selectorWizardsListRowTemplate).clone();
|
||||
numberOfWizardsTodo = numberOfWizardsTodo + 1;
|
||||
aRow.removeClass('t3js-upgradeWizards-list-row-template');
|
||||
aRow.find(self.selectorWizardsListRowTitle).empty().text(element.title);
|
||||
aRow.find(self.selectorWizardsListRowExplanation).empty().text(element.explanation);
|
||||
aRow.find(self.selectorWizardsListRowExecute).attr('data-identifier', element.identifier).attr('data-title', element.title);
|
||||
list.find(self.selectorWizardsListRows).append(aRow);
|
||||
}
|
||||
});
|
||||
list.find(self.selectorWizardsListRows + ' hr:last').remove();
|
||||
}
|
||||
var percent = 100;
|
||||
var $progressBar = list.find('.progress-bar');
|
||||
if (numberOfWizardsTodo > 0) {
|
||||
percent = Math.round((numberOfWizards - numberOfWizardsTodo) / data.wizards.length * 100);
|
||||
} else {
|
||||
$progressBar
|
||||
.removeClass('progress-bar-info')
|
||||
.addClass('progress-bar-success');
|
||||
}
|
||||
$progressBar
|
||||
.removeClass('progress-bar-striped')
|
||||
.css('width', percent + '%')
|
||||
.attr('aria-valuenow', percent)
|
||||
.find('span')
|
||||
.text(parseInt(percent) + '%');
|
||||
modalContent.find(self.selectorOutputWizardsContainer).append(list);
|
||||
self.currentModal.find(self.selectorWizardsDoneRowMarkUndone).prop("disabled", false);
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wizardInput: function (identifier, title) {
|
||||
var self = this;
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('upgrade-wizards-input-token');
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputWizardsContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Loading "' + title + '"...'));
|
||||
|
||||
modalContent.animate({
|
||||
scrollTop: modalContent.scrollTop() - Math.abs(modalContent.find('.t3js-upgrade-status-section').position().top)
|
||||
}, 250);
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'upgradeWizardsInput',
|
||||
'token': executeToken,
|
||||
'identifier': identifier
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
$outputContainer.empty();
|
||||
var input = modalContent.find(self.selectorWizardsInputTemplate).clone();
|
||||
input.removeClass('t3js-upgradeWizards-input');
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function (element) {
|
||||
var message = FlashMessage.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
});
|
||||
}
|
||||
if (data.userInput.wizardHtml.length > 0) {
|
||||
input.find(self.selectorWizardsInputHtml).html(data.userInput.wizardHtml);
|
||||
}
|
||||
input.find(self.selectorWizardsInputTitle).text(data.userInput.title);
|
||||
input.find(self.selectorWizardsInputPerform).attr('data-identifier', data.userInput.identifier).attr('data-title', data.userInput.title);
|
||||
}
|
||||
modalContent.find(self.selectorOutputWizardsContainer).append(input);
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wizardExecute: function (identifier, title) {
|
||||
var self = this;
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('upgrade-wizards-execute-token');
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var postData = {
|
||||
'install[action]': 'upgradeWizardsExecute',
|
||||
'install[token]': executeToken,
|
||||
'install[identifier]': identifier
|
||||
};
|
||||
$(this.currentModal.find(this.selectorOutputWizardsContainer + ' form').serializeArray()).each(function () {
|
||||
postData[this.name] = this.value;
|
||||
});
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputWizardsContainer);
|
||||
// modalContent.find(self.selectorOutputWizardsContainer).empty();
|
||||
$outputContainer.empty().html(this.renderProgressBar('Executing "' + title + '"...'));
|
||||
this.currentModal.find(this.selectorWizardsDoneRowMarkUndone).prop("disabled", true);
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
data: postData,
|
||||
url: Router.getUrl(),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
$outputContainer.empty();
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status)) {
|
||||
data.status.forEach(function (element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
});
|
||||
}
|
||||
self.wizardsList();
|
||||
modalContent.find(self.selectorOutputDoneContainer).empty();
|
||||
self.doneUpgrades();
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
doneUpgrades: function () {
|
||||
var self = this;
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = modalContent.find(this.selectorOutputDoneContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Loading executed upgrade wizards...'));
|
||||
|
||||
$.ajax({
|
||||
url: Router.getUrl('upgradeWizardsDoneUpgrades'),
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
self.removeLoadingMessage($outputContainer);
|
||||
if (data.success === true) {
|
||||
if (Array.isArray(data.status) && data.status.length > 0) {
|
||||
data.status.forEach(function (element) {
|
||||
var message = InfoBox.render(element.severity, element.title, element.message);
|
||||
$outputContainer.append(message);
|
||||
});
|
||||
}
|
||||
var body = modalContent.find(self.selectorWizardsDoneBodyTemplate).clone();
|
||||
var hasBodyContent = false;
|
||||
var $wizardsDoneContainer = body.find(self.selectorWizardsDoneRows);
|
||||
if (Array.isArray(data.wizardsDone) && data.wizardsDone.length > 0) {
|
||||
data.wizardsDone.forEach(function (element) {
|
||||
hasBodyContent = true;
|
||||
var aRow = modalContent.find(self.selectorWizardsDoneRowTemplate).clone();
|
||||
aRow.find(self.selectorWizardsDoneRowMarkUndone).attr('data-identifier', element.identifier);
|
||||
aRow.find(self.selectorWizardsDoneRowTitle).text(element.title);
|
||||
$wizardsDoneContainer.append(aRow);
|
||||
});
|
||||
}
|
||||
if (Array.isArray(data.rowUpdatersDone) && data.rowUpdatersDone.length > 0) {
|
||||
data.rowUpdatersDone.forEach(function (element) {
|
||||
hasBodyContent = true;
|
||||
var aRow = modalContent.find(self.selectorWizardsDoneRowTemplate).clone();
|
||||
aRow.find(self.selectorWizardsDoneRowMarkUndone).attr('data-identifier', element.identifier);
|
||||
aRow.find(self.selectorWizardsDoneRowTitle).text(element.title);
|
||||
$wizardsDoneContainer.append(aRow);
|
||||
});
|
||||
}
|
||||
if (hasBodyContent === true) {
|
||||
modalContent.find(self.selectorOutputDoneContainer).append(body);
|
||||
self.currentModal.find(self.selectorWizardsDoneRowMarkUndone).prop("disabled", true);
|
||||
}
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
markUndone: function (identifier) {
|
||||
var self = this;
|
||||
var executeToken = this.currentModal.find(this.selectorModuleContent).data('upgrade-wizards-mark-undone-token');
|
||||
var modalContent = this.currentModal.find(this.selectorModalBody);
|
||||
var $outputContainer = this.currentModal.find(this.selectorOutputDoneContainer);
|
||||
$outputContainer.empty().html(this.renderProgressBar('Marking upgrade wizard as undone...'));
|
||||
$.ajax({
|
||||
url: Router.getUrl(),
|
||||
method: 'POST',
|
||||
data: {
|
||||
'install': {
|
||||
'action': 'upgradeWizardsMarkUndone',
|
||||
'token': executeToken,
|
||||
'identifier': identifier
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
success: function (data) {
|
||||
$outputContainer.empty();
|
||||
modalContent.find(self.selectorOutputDoneContainer).empty();
|
||||
if (data.success === true && Array.isArray(data.status)) {
|
||||
data.status.forEach(function (element) {
|
||||
Notification.success(element.message);
|
||||
self.doneUpgrades();
|
||||
self.blockingUpgradesDatabaseCharsetTest();
|
||||
});
|
||||
} else {
|
||||
Notification.error('Something went wrong');
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
Router.handleAjaxError(xhr, $outputContainer);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeLoadingMessage: function ($container) {
|
||||
$container.find('.alert-loading').remove();
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
var require = {
|
||||
baseUrl: '',
|
||||
urlArgs: 'bust=' + (new Date()).getTime(),
|
||||
paths: {
|
||||
'TYPO3/CMS/Core': 'sysext/core/Resources/Public/JavaScript',
|
||||
'TYPO3/CMS/Backend': 'sysext/backend/Resources/Public/JavaScript',
|
||||
'TYPO3/CMS/Install': 'sysext/install/Resources/Public/JavaScript/Modules',
|
||||
'jquery': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery/jquery.min',
|
||||
'jquery.clearable': 'sysext/backend/Resources/Public/JavaScript/jquery.clearable',
|
||||
'TYPO3/CMS/Core/Contrib/jquery.minicolors': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors',
|
||||
'bootstrap': 'sysext/core/Resources/Public/JavaScript/Contrib/bootstrap/bootstrap',
|
||||
'chosen': 'sysext/install/Resources/Public/JavaScript/chosen.jquery.min',
|
||||
'nprogress': 'sysext/core/Resources/Public/JavaScript/Contrib/nprogress'
|
||||
},
|
||||
shim: {
|
||||
jQuery: {
|
||||
exports: '$'
|
||||
},
|
||||
'bootstrap': {
|
||||
'deps': ['jquery']
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
(function(){var t,e,s,i,r={}.hasOwnProperty;(i=function(){function t(){this.options_index=0,this.parsed=[]}return t.prototype.add_node=function(t){return"OPTGROUP"===t.nodeName.toUpperCase()?this.add_group(t):this.add_option(t)},t.prototype.add_group=function(t){var e,s,i,r,n,o;for(e=this.parsed.length,this.parsed.push({array_index:e,group:!0,label:t.label,title:t.title?t.title:void 0,children:0,disabled:t.disabled,classes:t.className}),o=[],s=0,i=(n=t.childNodes).length;s<i;s++)r=n[s],o.push(this.add_option(r,e,t.disabled));return o},t.prototype.add_option=function(t,e,s){if("OPTION"===t.nodeName.toUpperCase())return""!==t.text?(null!=e&&(this.parsed[e].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:t.value,text:t.text,html:t.innerHTML,title:t.title?t.title:void 0,selected:t.selected,disabled:!0===s?s:t.disabled,group_array_index:e,group_label:null!=e?this.parsed[e].label:null,classes:t.className,style:t.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1},t}()).select_to_array=function(t){var e,s,r,n,o;for(n=new i,s=0,r=(o=t.childNodes).length;s<r;s++)e=o[s],n.add_node(e);return n.parsed},e=function(){function t(e,s){var i,r;this.form_field=e,this.options=null!=s?s:{},this.label_click_handler=(i=this.label_click_handler,r=this,function(){return i.apply(r,arguments)}),t.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers(),this.on_ready())}return t.prototype.set_default_values=function(){var t;return this.click_test_action=(t=this,function(e){return t.test_active_click(e)}),this.activate_action=function(t){return function(e){return t.activate_field(e)}}(this),this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.is_rtl=this.options.rtl||/\bchosen-rtl\b/.test(this.form_field.className),this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text&&this.options.allow_single_deselect,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null==this.options.enable_split_word_search||this.options.enable_split_word_search,this.group_search=null==this.options.group_search||this.options.group_search,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null==this.options.single_backstroke_delete||this.options.single_backstroke_delete,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null==this.options.display_selected_options||this.options.display_selected_options,this.display_disabled_options=null==this.options.display_disabled_options||this.options.display_disabled_options,this.include_group_label_in_selected=this.options.include_group_label_in_selected||!1,this.max_shown_results=this.options.max_shown_results||Number.POSITIVE_INFINITY,this.case_sensitive_search=this.options.case_sensitive_search||!1,this.hide_results_on_select=null==this.options.hide_results_on_select||this.options.hide_results_on_select},t.prototype.set_default_text=function(){return this.form_field.getAttribute("data-placeholder")?this.default_text=this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.default_text=this.options.placeholder_text_multiple||this.options.placeholder_text||t.default_multiple_text:this.default_text=this.options.placeholder_text_single||this.options.placeholder_text||t.default_single_text,this.default_text=this.escape_html(this.default_text),this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||t.default_no_result_text},t.prototype.choice_label=function(t){return this.include_group_label_in_selected&&null!=t.group_label?"<b class='group-name'>"+this.escape_html(t.group_label)+"</b>"+t.html:t.html},t.prototype.mouse_enter=function(){return this.mouse_on_container=!0},t.prototype.mouse_leave=function(){return this.mouse_on_container=!1},t.prototype.input_focus=function(t){if(this.is_multiple){if(!this.active_field)return setTimeout((e=this,function(){return e.container_mousedown()}),50)}else if(!this.active_field)return this.activate_field();var e},t.prototype.input_blur=function(t){if(!this.mouse_on_container)return this.active_field=!1,setTimeout((e=this,function(){return e.blur_test()}),100);var e},t.prototype.label_click_handler=function(t){return this.is_multiple?this.container_mousedown(t):this.activate_field()},t.prototype.results_option_build=function(t){var e,s,i,r,n,o,h;for(e="",h=0,r=0,n=(o=this.results_data).length;r<n&&(i="",""!==(i=(s=o[r]).group?this.result_add_group(s):this.result_add_option(s))&&(h++,e+=i),(null!=t?t.Line truncated
|
||||
Reference in new issue
Block a user