1298 lines
44 KiB
JavaScript
1298 lines
44 KiB
JavaScript
/**
|
|
* Copyright since 2007 PrestaShop SA and Contributors
|
|
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
|
*
|
|
* NOTICE OF LICENSE
|
|
*
|
|
* This source file is subject to the Open Software License (OSL 3.0)
|
|
* that is bundled with this package in the file LICENSE.md.
|
|
* It is also available through the world-wide-web at this URL:
|
|
* https://opensource.org/licenses/OSL-3.0
|
|
* If you did not receive a copy of the license and are unable to
|
|
* obtain it through the world-wide-web, please send an email
|
|
* to license@prestashop.com so we can send you a copy immediately.
|
|
*
|
|
* DISCLAIMER
|
|
*
|
|
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
|
* versions in the future. If you wish to customize PrestaShop for your
|
|
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
|
*
|
|
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
|
* @copyright Since 2007 PrestaShop SA and Contributors
|
|
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
|
*/
|
|
|
|
import ConfirmModal from '@components/modal';
|
|
|
|
const {$} = window;
|
|
|
|
/**
|
|
* Module Admin Page Controller.
|
|
* @constructor
|
|
*/
|
|
class AdminModuleController {
|
|
/**
|
|
* Initialize all listeners and bind everything
|
|
* @method init
|
|
* @memberof AdminModule
|
|
*/
|
|
constructor(moduleCardController) {
|
|
this.moduleCardController = moduleCardController;
|
|
|
|
this.DEFAULT_MAX_RECENTLY_USED = 10;
|
|
this.DEFAULT_MAX_PER_CATEGORIES = 6;
|
|
this.DISPLAY_GRID = 'grid';
|
|
this.DISPLAY_LIST = 'list';
|
|
this.CATEGORY_RECENTLY_USED = 'recently-used';
|
|
|
|
this.currentCategoryDisplay = {};
|
|
this.currentDisplay = '';
|
|
this.isCategoryGridDisplayed = false;
|
|
this.currentTagsList = [];
|
|
this.currentRefCategory = null;
|
|
this.currentRefStatus = null;
|
|
this.currentSorting = null;
|
|
this.baseAddonsUrl = 'https://addons.prestashop.com/';
|
|
this.pstaggerInput = null;
|
|
this.lastBulkAction = null;
|
|
this.isUploadStarted = false;
|
|
|
|
this.recentlyUsedSelector = '#module-recently-used-list .modules-list';
|
|
|
|
/**
|
|
* Loaded modules list.
|
|
* Containing the card and list display.
|
|
* @type {Array}
|
|
*/
|
|
this.modulesList = [];
|
|
this.addonsCardGrid = null;
|
|
this.addonsCardList = null;
|
|
|
|
this.moduleShortList = '.module-short-list';
|
|
// See more & See less selector
|
|
this.seeMoreSelector = '.see-more';
|
|
this.seeLessSelector = '.see-less';
|
|
|
|
// Selectors into vars to make it easier to change them while keeping same code logic
|
|
this.moduleItemGridSelector = '.module-item-grid';
|
|
this.moduleItemListSelector = '.module-item-list';
|
|
this.categorySelectorLabelSelector = '.module-category-selector-label';
|
|
this.categorySelector = '.module-category-selector';
|
|
this.categoryItemSelector = '.module-category-menu';
|
|
this.addonsLoginButtonSelector = '#addons_login_btn';
|
|
this.categoryResetBtnSelector = '.module-category-reset';
|
|
this.moduleInstallBtnSelector = 'input.module-install-btn';
|
|
this.moduleSortingDropdownSelector = '.module-sorting-author select';
|
|
this.categoryGridSelector = '#modules-categories-grid';
|
|
this.categoryGridItemSelector = '.module-category-item';
|
|
this.addonItemGridSelector = '.module-addons-item-grid';
|
|
this.addonItemListSelector = '.module-addons-item-list';
|
|
|
|
// Upgrade All selectors
|
|
this.upgradeAllSource = '.module_action_menu_upgrade_all';
|
|
this.upgradeContainer = '#modules-list-container-update';
|
|
this.upgradeAllTargets = `${this.upgradeContainer} .module_action_menu_upgrade:visible`;
|
|
|
|
// Notification selectors
|
|
this.notificationContainer = '#modules-list-container-notification';
|
|
|
|
// Bulk action selectors
|
|
this.bulkActionDropDownSelector = '.module-bulk-actions';
|
|
this.bulkItemSelector = '.module-bulk-menu';
|
|
this.bulkActionCheckboxListSelector = '.module-checkbox-bulk-list input';
|
|
this.bulkActionCheckboxGridSelector = '.module-checkbox-bulk-grid input';
|
|
this.checkedBulkActionListSelector = `${this.bulkActionCheckboxListSelector}:checked`;
|
|
this.checkedBulkActionGridSelector = `${this.bulkActionCheckboxGridSelector}:checked`;
|
|
this.bulkActionCheckboxSelector = '#module-modal-bulk-checkbox';
|
|
this.bulkConfirmModalSelector = '#module-modal-bulk-confirm';
|
|
this.bulkConfirmModalActionNameSelector = '#module-modal-bulk-confirm-action-name';
|
|
this.bulkConfirmModalListSelector = '#module-modal-bulk-confirm-list';
|
|
this.bulkConfirmModalAckBtnSelector = '#module-modal-confirm-bulk-ack';
|
|
|
|
// Placeholders
|
|
this.placeholderGlobalSelector = '.module-placeholders-wrapper';
|
|
this.placeholderFailureGlobalSelector = '.module-placeholders-failure';
|
|
this.placeholderFailureMsgSelector = '.module-placeholders-failure-msg';
|
|
this.placeholderFailureRetryBtnSelector = '#module-placeholders-failure-retry';
|
|
|
|
// Module's statuses selectors
|
|
this.statusSelectorLabelSelector = '.module-status-selector-label';
|
|
this.statusItemSelector = '.module-status-menu';
|
|
this.statusResetBtnSelector = '.module-status-reset';
|
|
|
|
// Selectors for Module Import and Addons connect
|
|
this.addonsConnectModalBtnSelector = '#page-header-desc-configuration-addons_connect';
|
|
this.addonsLogoutModalBtnSelector = '#page-header-desc-configuration-addons_logout';
|
|
this.addonsImportModalBtnSelector = '#page-header-desc-configuration-add_module';
|
|
this.dropZoneModalSelector = '#module-modal-import';
|
|
this.dropZoneModalFooterSelector = '#module-modal-import .modal-footer';
|
|
this.dropZoneImportZoneSelector = '#importDropzone';
|
|
this.addonsConnectModalSelector = '#module-modal-addons-connect';
|
|
this.addonsLogoutModalSelector = '#module-modal-addons-logout';
|
|
this.addonsConnectForm = '#addons-connect-form';
|
|
this.moduleImportModalCloseBtn = '#module-modal-import-closing-cross';
|
|
this.moduleImportStartSelector = '.module-import-start';
|
|
this.moduleImportProcessingSelector = '.module-import-processing';
|
|
this.moduleImportSuccessSelector = '.module-import-success';
|
|
this.moduleImportSuccessConfigureBtnSelector = '.module-import-success-configure';
|
|
this.moduleImportFailureSelector = '.module-import-failure';
|
|
this.moduleImportFailureRetrySelector = '.module-import-failure-retry';
|
|
this.moduleImportFailureDetailsBtnSelector = '.module-import-failure-details-action';
|
|
this.moduleImportSelectFileManualSelector = '.module-import-start-select-manual';
|
|
this.moduleImportFailureMsgDetailsSelector = '.module-import-failure-details';
|
|
this.moduleImportConfirmSelector = '.module-import-confirm';
|
|
|
|
this.initSortingDropdown();
|
|
this.initBOEventRegistering();
|
|
this.initCurrentDisplay();
|
|
this.initSortingDisplaySwitch();
|
|
this.initBulkDropdown();
|
|
this.initSearchBlock();
|
|
this.initCategorySelect();
|
|
this.initCategoriesGrid();
|
|
this.initActionButtons();
|
|
this.initAddonsSearch();
|
|
this.initAddonsConnect();
|
|
this.initAddModuleAction();
|
|
this.initDropzone();
|
|
this.initPageChangeProtection();
|
|
this.initPlaceholderMechanism();
|
|
this.initFilterStatusDropdown();
|
|
this.fetchModulesList();
|
|
this.getNotificationsCount();
|
|
this.initializeSeeMore();
|
|
}
|
|
|
|
initFilterStatusDropdown() {
|
|
const self = this;
|
|
const body = $('body');
|
|
body.on('click', self.statusItemSelector, function () {
|
|
// Get data from li DOM input
|
|
self.currentRefStatus = parseInt($(this).data('status-ref'), 10);
|
|
// Change dropdown label to set it to the current status' displayname
|
|
$(self.statusSelectorLabelSelector).text($(this).text());
|
|
$(self.statusResetBtnSelector).show();
|
|
self.updateModuleVisibility();
|
|
});
|
|
|
|
body.on('click', self.statusResetBtnSelector, function () {
|
|
$(self.statusSelectorLabelSelector).text($(this).text());
|
|
$(this).hide();
|
|
self.currentRefStatus = null;
|
|
self.updateModuleVisibility();
|
|
});
|
|
}
|
|
|
|
initBulkDropdown() {
|
|
const self = this;
|
|
const body = $('body');
|
|
|
|
body.on('click', self.getBulkCheckboxesSelector(), () => {
|
|
const selector = $(self.bulkActionDropDownSelector);
|
|
|
|
if ($(self.getBulkCheckboxesCheckedSelector()).length > 0) {
|
|
selector.closest('.module-top-menu-item').removeClass('disabled');
|
|
} else {
|
|
selector.closest('.module-top-menu-item').addClass('disabled');
|
|
}
|
|
});
|
|
|
|
body.on('click', self.bulkItemSelector, function initializeBodyChange() {
|
|
if ($(self.getBulkCheckboxesCheckedSelector()).length === 0) {
|
|
$.growl.warning({
|
|
message: window.translate_javascripts['Bulk Action - One module minimum'],
|
|
});
|
|
return;
|
|
}
|
|
|
|
self.lastBulkAction = $(this).data('ref');
|
|
const modulesListString = self.buildBulkActionModuleList();
|
|
const actionString = $(this)
|
|
.find(':checked')
|
|
.text()
|
|
.toLowerCase();
|
|
$(self.bulkConfirmModalListSelector).html(modulesListString);
|
|
$(self.bulkConfirmModalActionNameSelector).text(actionString);
|
|
|
|
if (self.lastBulkAction === 'bulk-uninstall') {
|
|
$(self.bulkActionCheckboxSelector).show();
|
|
} else {
|
|
$(self.bulkActionCheckboxSelector).hide();
|
|
}
|
|
|
|
$(self.bulkConfirmModalSelector).modal('show');
|
|
});
|
|
|
|
body.on('click', this.bulkConfirmModalAckBtnSelector, (event) => {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
$(self.bulkConfirmModalSelector).modal('hide');
|
|
self.doBulkAction(self.lastBulkAction);
|
|
});
|
|
}
|
|
|
|
initBOEventRegistering() {
|
|
window.BOEvent.on('Module Disabled', this.onModuleDisabled, this);
|
|
window.BOEvent.on('Module Uninstalled', this.updateTotalResults, this);
|
|
}
|
|
|
|
onModuleDisabled() {
|
|
const self = this;
|
|
self.getModuleItemSelector();
|
|
|
|
$('.modules-list').each(() => {
|
|
self.updateTotalResults();
|
|
});
|
|
}
|
|
|
|
initPlaceholderMechanism() {
|
|
const self = this;
|
|
|
|
if ($(self.placeholderGlobalSelector).length) {
|
|
self.ajaxLoadPage();
|
|
}
|
|
|
|
// Retry loading mechanism
|
|
$('body').on('click', self.placeholderFailureRetryBtnSelector, () => {
|
|
$(self.placeholderFailureGlobalSelector).fadeOut();
|
|
$(self.placeholderGlobalSelector).fadeIn();
|
|
self.ajaxLoadPage();
|
|
});
|
|
}
|
|
|
|
ajaxLoadPage() {
|
|
const self = this;
|
|
|
|
$.ajax({
|
|
method: 'GET',
|
|
url: window.moduleURLs.catalogRefresh,
|
|
})
|
|
.done((response) => {
|
|
if (response.status === true) {
|
|
if (typeof response.domElements === 'undefined') response.domElements = null;
|
|
if (typeof response.msg === 'undefined') response.msg = null;
|
|
|
|
const stylesheet = document.styleSheets[0];
|
|
const stylesheetRule = '{display: none}';
|
|
const moduleGlobalSelector = '.modules-list';
|
|
const moduleSortingSelector = '.module-sorting-menu';
|
|
const requiredSelectorCombination = `${moduleGlobalSelector},${moduleSortingSelector}`;
|
|
|
|
if (stylesheet.insertRule) {
|
|
stylesheet.insertRule(requiredSelectorCombination + stylesheetRule, stylesheet.cssRules.length);
|
|
} else if (stylesheet.addRule) {
|
|
stylesheet.addRule(requiredSelectorCombination, stylesheetRule, -1);
|
|
}
|
|
|
|
$(self.placeholderGlobalSelector).fadeOut(800, () => {
|
|
$.each(response.domElements, (index, element) => {
|
|
$(element.selector).append(element.content);
|
|
});
|
|
$(moduleGlobalSelector)
|
|
.fadeIn(800)
|
|
.css('display', 'flex');
|
|
$(moduleSortingSelector).fadeIn(800);
|
|
$('[data-toggle="popover"]').popover();
|
|
self.initCurrentDisplay();
|
|
self.fetchModulesList();
|
|
});
|
|
} else {
|
|
$(self.placeholderGlobalSelector).fadeOut(800, () => {
|
|
$(self.placeholderFailureMsgSelector).text(response.msg);
|
|
$(self.placeholderFailureGlobalSelector).fadeIn(800);
|
|
});
|
|
}
|
|
})
|
|
.fail((response) => {
|
|
$(self.placeholderGlobalSelector).fadeOut(800, () => {
|
|
$(self.placeholderFailureMsgSelector).text(response.statusText);
|
|
$(self.placeholderFailureGlobalSelector).fadeIn(800);
|
|
});
|
|
});
|
|
}
|
|
|
|
fetchModulesList() {
|
|
const self = this;
|
|
let container;
|
|
let $this;
|
|
|
|
self.modulesList = [];
|
|
$('.modules-list').each(function prepareContainer() {
|
|
container = $(this);
|
|
container.find('.module-item').each(function prepareModules() {
|
|
$this = $(this);
|
|
self.modulesList.push({
|
|
domObject: $this,
|
|
id: $this.data('id'),
|
|
name: $this.data('name').toLowerCase(),
|
|
scoring: parseFloat($this.data('scoring')),
|
|
logo: $this.data('logo'),
|
|
author: $this.data('author').toLowerCase(),
|
|
version: $this.data('version'),
|
|
description: $this.data('description').toLowerCase(),
|
|
techName: $this.data('tech-name').toLowerCase(),
|
|
childCategories: $this.data('child-categories'),
|
|
categories: String($this.data('categories')).toLowerCase(),
|
|
type: $this.data('type'),
|
|
price: parseFloat($this.data('price')),
|
|
active: parseInt($this.data('active'), 10),
|
|
access: $this.data('last-access'),
|
|
display: $this.hasClass('module-item-list') ? self.DISPLAY_LIST : self.DISPLAY_GRID,
|
|
container,
|
|
});
|
|
|
|
if (self.isModulesPage()) {
|
|
$this.remove();
|
|
}
|
|
});
|
|
});
|
|
|
|
self.addonsCardGrid = $(this.addonItemGridSelector);
|
|
self.addonsCardList = $(this.addonItemListSelector);
|
|
self.updateModuleVisibility();
|
|
$('body').trigger('moduleCatalogLoaded');
|
|
}
|
|
|
|
/**
|
|
* Prepare sorting
|
|
*
|
|
*/
|
|
updateModuleSorting() {
|
|
const self = this;
|
|
|
|
if (!self.currentSorting) {
|
|
return;
|
|
}
|
|
|
|
// Modules sorting
|
|
let order = 'asc';
|
|
let key = self.currentSorting;
|
|
const splittedKey = key.split('-');
|
|
|
|
if (splittedKey.length > 1) {
|
|
key = splittedKey[0];
|
|
if (splittedKey[1] === 'desc') {
|
|
order = 'desc';
|
|
}
|
|
}
|
|
|
|
const currentCompare = (a, b) => {
|
|
let aData = a[key];
|
|
let bData = b[key];
|
|
|
|
if (key === 'access') {
|
|
aData = new Date(aData).getTime();
|
|
bData = new Date(bData).getTime();
|
|
aData = Number.isNaN(aData) ? 0 : aData;
|
|
bData = Number.isNaN(bData) ? 0 : bData;
|
|
if (aData === bData) {
|
|
return b.name.localeCompare(a.name);
|
|
}
|
|
}
|
|
|
|
if (aData < bData) return -1;
|
|
if (aData > bData) return 1;
|
|
|
|
return 0;
|
|
};
|
|
|
|
self.modulesList.sort(currentCompare);
|
|
if (order === 'desc') {
|
|
self.modulesList.reverse();
|
|
}
|
|
}
|
|
|
|
updateModuleContainerDisplay() {
|
|
const self = this;
|
|
|
|
$('.module-short-list').each(function setShortListVisibility() {
|
|
const container = $(this);
|
|
const nbModulesInContainer = container.find('.module-item').length;
|
|
|
|
if (
|
|
(self.currentRefCategory && self.currentRefCategory !== String(container.find('.modules-list').data('name')))
|
|
|| (self.currentRefStatus !== null && nbModulesInContainer === 0)
|
|
|| (nbModulesInContainer === 0
|
|
&& String(container.find('.modules-list').data('name')) === self.CATEGORY_RECENTLY_USED)
|
|
|| (self.currentTagsList.length > 0 && nbModulesInContainer === 0)
|
|
) {
|
|
container.hide();
|
|
return;
|
|
}
|
|
|
|
container.show();
|
|
container
|
|
.find(`${self.seeMoreSelector}, ${self.seeLessSelector}`)
|
|
.toggle(nbModulesInContainer >= self.DEFAULT_MAX_PER_CATEGORIES);
|
|
});
|
|
}
|
|
|
|
updateModuleVisibility() {
|
|
const self = this;
|
|
|
|
self.updateModuleSorting();
|
|
|
|
if (self.isModulesPage()) {
|
|
$(self.recentlyUsedSelector)
|
|
.find('.module-item')
|
|
.remove();
|
|
$('.modules-list')
|
|
.find('.module-item')
|
|
.remove();
|
|
}
|
|
|
|
// Modules visibility management
|
|
let isVisible;
|
|
let currentModule;
|
|
let moduleCategory;
|
|
let tagExists;
|
|
let newValue;
|
|
let defaultMax;
|
|
|
|
const modulesListLength = self.modulesList.length;
|
|
const counter = {};
|
|
const checkTag = (index, value) => {
|
|
newValue = value.toLowerCase();
|
|
tagExists
|
|
|= currentModule.name.indexOf(newValue) !== -1
|
|
|| currentModule.description.indexOf(newValue) !== -1
|
|
|| currentModule.author.indexOf(newValue) !== -1
|
|
|| currentModule.techName.indexOf(newValue) !== -1;
|
|
};
|
|
|
|
for (let i = 0; i < modulesListLength; i += 1) {
|
|
currentModule = self.modulesList[i];
|
|
if (currentModule.display === self.currentDisplay) {
|
|
isVisible = true;
|
|
|
|
moduleCategory = self.currentRefCategory === self.CATEGORY_RECENTLY_USED
|
|
? self.CATEGORY_RECENTLY_USED
|
|
: currentModule.categories;
|
|
|
|
// Check for same category
|
|
if (self.currentRefCategory !== null) {
|
|
isVisible &= moduleCategory === self.currentRefCategory;
|
|
}
|
|
|
|
// Check for same status
|
|
if (self.currentRefStatus !== null) {
|
|
isVisible &= currentModule.active === self.currentRefStatus;
|
|
}
|
|
|
|
// Check for tag list
|
|
if (self.currentTagsList.length) {
|
|
tagExists = false;
|
|
$.each(self.currentTagsList, checkTag);
|
|
isVisible &= tagExists;
|
|
}
|
|
|
|
/**
|
|
* If list display without search we must display only the first 5 modules
|
|
*/
|
|
if (self.currentDisplay === self.DISPLAY_LIST && !self.currentTagsList.length) {
|
|
if (self.currentCategoryDisplay[moduleCategory] === undefined) {
|
|
self.currentCategoryDisplay[moduleCategory] = false;
|
|
}
|
|
|
|
if (!counter[moduleCategory]) {
|
|
counter[moduleCategory] = 0;
|
|
}
|
|
|
|
defaultMax = moduleCategory === self.CATEGORY_RECENTLY_USED
|
|
? self.DEFAULT_MAX_RECENTLY_USED
|
|
: self.DEFAULT_MAX_PER_CATEGORIES;
|
|
if (counter[moduleCategory] >= defaultMax) {
|
|
isVisible &= self.currentCategoryDisplay[moduleCategory];
|
|
}
|
|
|
|
counter[moduleCategory] += 1;
|
|
}
|
|
|
|
// If visible, display (Thx captain obvious)
|
|
if (isVisible) {
|
|
if (self.currentRefCategory === self.CATEGORY_RECENTLY_USED) {
|
|
$(self.recentlyUsedSelector).append(currentModule.domObject);
|
|
} else {
|
|
currentModule.container.append(currentModule.domObject);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self.updateModuleContainerDisplay();
|
|
|
|
if (self.currentTagsList.length) {
|
|
$('.modules-list').append(this.currentDisplay === self.DISPLAY_GRID ? this.addonsCardGrid : this.addonsCardList);
|
|
}
|
|
|
|
self.updateTotalResults();
|
|
}
|
|
|
|
initPageChangeProtection() {
|
|
const self = this;
|
|
|
|
$(window).on('beforeunload', () => {
|
|
if (self.isUploadStarted === true) {
|
|
return (
|
|
'It seems some critical operation are running, are you sure you want to change page? '
|
|
+ 'It might cause some unexepcted behaviors.'
|
|
);
|
|
}
|
|
|
|
return undefined;
|
|
});
|
|
}
|
|
|
|
buildBulkActionModuleList() {
|
|
const checkBoxesSelector = this.getBulkCheckboxesCheckedSelector();
|
|
const moduleItemSelector = this.getModuleItemSelector();
|
|
let alreadyDoneFlag = 0;
|
|
let htmlGenerated = '';
|
|
let currentElement;
|
|
|
|
$(checkBoxesSelector).each(function prepareCheckboxes() {
|
|
if (alreadyDoneFlag === 10) {
|
|
// Break each
|
|
htmlGenerated += '- ...';
|
|
return false;
|
|
}
|
|
|
|
currentElement = $(this).closest(moduleItemSelector);
|
|
htmlGenerated += `- ${currentElement.data('name')}<br/>`;
|
|
alreadyDoneFlag += 1;
|
|
|
|
return true;
|
|
});
|
|
|
|
return htmlGenerated;
|
|
}
|
|
|
|
initAddonsConnect() {
|
|
const self = this;
|
|
|
|
// Make addons connect modal ready to be clicked
|
|
if ($(self.addonsConnectModalBtnSelector).attr('href') === '#') {
|
|
$(self.addonsConnectModalBtnSelector).attr('data-toggle', 'modal');
|
|
$(self.addonsConnectModalBtnSelector).attr('data-target', self.addonsConnectModalSelector);
|
|
}
|
|
|
|
if ($(self.addonsLogoutModalBtnSelector).attr('href') === '#') {
|
|
$(self.addonsLogoutModalBtnSelector).attr('data-toggle', 'modal');
|
|
$(self.addonsLogoutModalBtnSelector).attr('data-target', self.addonsLogoutModalSelector);
|
|
}
|
|
|
|
$('body').on('submit', self.addonsConnectForm, function initializeBodySubmit(event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
$.ajax({
|
|
method: 'POST',
|
|
url: $(this).attr('action'),
|
|
dataType: 'json',
|
|
data: $(this).serialize(),
|
|
beforeSend: () => {
|
|
$(self.addonsLoginButtonSelector).show();
|
|
$('button.btn[type="submit"]', self.addonsConnectForm).hide();
|
|
},
|
|
}).done((response) => {
|
|
if (response.success === 1) {
|
|
window.location.reload();
|
|
} else {
|
|
$.growl.error({message: response.message});
|
|
$(self.addonsLoginButtonSelector).hide();
|
|
$('button.btn[type="submit"]', self.addonsConnectForm).fadeIn();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
initAddModuleAction() {
|
|
const self = this;
|
|
const addModuleButton = $(self.addonsImportModalBtnSelector);
|
|
addModuleButton.attr('data-toggle', 'modal');
|
|
addModuleButton.attr('data-target', self.dropZoneModalSelector);
|
|
}
|
|
|
|
initDropzone() {
|
|
const self = this;
|
|
const body = $('body');
|
|
const dropzone = $('.dropzone');
|
|
|
|
// Reset modal when click on Retry in case of failure
|
|
body.on('click', this.moduleImportFailureRetrySelector, () => {
|
|
/* eslint-disable max-len */
|
|
$(
|
|
`${self.moduleImportSuccessSelector},${self.moduleImportFailureSelector},${self.moduleImportProcessingSelector}`,
|
|
).fadeOut(() => {
|
|
/**
|
|
* Added timeout for a better render of animation
|
|
* and avoid to have displayed at the same time
|
|
*/
|
|
setTimeout(() => {
|
|
$(self.moduleImportStartSelector).fadeIn(() => {
|
|
$(self.moduleImportFailureMsgDetailsSelector).hide();
|
|
$(self.moduleImportSuccessConfigureBtnSelector).hide();
|
|
dropzone.removeAttr('style');
|
|
});
|
|
}, 550);
|
|
});
|
|
/* eslint-enable max-len */
|
|
});
|
|
|
|
// Reinit modal on exit, but check if not already processing something
|
|
body.on('hidden.bs.modal', this.dropZoneModalSelector, () => {
|
|
$(`${self.moduleImportSuccessSelector}, ${self.moduleImportFailureSelector}`).hide();
|
|
$(self.moduleImportStartSelector).show();
|
|
|
|
dropzone.removeAttr('style');
|
|
$(self.moduleImportFailureMsgDetailsSelector).hide();
|
|
$(self.moduleImportSuccessConfigureBtnSelector).hide();
|
|
$(self.dropZoneModalFooterSelector).html('');
|
|
$(self.moduleImportConfirmSelector).hide();
|
|
});
|
|
|
|
// Change the way Dropzone.js lib handle file input trigger
|
|
body.on(
|
|
'click',
|
|
`.dropzone:not(${this.moduleImportSelectFileManualSelector}, ${this.moduleImportSuccessConfigureBtnSelector})`,
|
|
(event, manualSelect) => {
|
|
// if click comes from .module-import-start-select-manual, stop everything
|
|
if (typeof manualSelect === 'undefined') {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
);
|
|
|
|
body.on('click', this.moduleImportSelectFileManualSelector, (event) => {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
/**
|
|
* Trigger click on hidden file input, and pass extra data
|
|
* to .dropzone click handler fro it to notice it comes from here
|
|
*/
|
|
$('.dz-hidden-input').trigger('click', ['manual_select']);
|
|
});
|
|
|
|
// Handle modal closure
|
|
body.on('click', this.moduleImportModalCloseBtn, () => {
|
|
if (self.isUploadStarted !== true) {
|
|
$(self.dropZoneModalSelector).modal('hide');
|
|
}
|
|
});
|
|
|
|
// Fix issue on click configure button
|
|
body.on('click', this.moduleImportSuccessConfigureBtnSelector, function initializeBodyClickOnModuleImport(event) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
window.location = $(this).attr('href');
|
|
});
|
|
|
|
// Open failure message details box
|
|
body.on('click', this.moduleImportFailureDetailsBtnSelector, () => {
|
|
$(self.moduleImportFailureMsgDetailsSelector).slideDown();
|
|
});
|
|
|
|
// @see: dropzone.js
|
|
const dropzoneOptions = {
|
|
url: window.moduleURLs.moduleImport,
|
|
acceptedFiles: '.zip, .tar',
|
|
// The name that will be used to transfer the file
|
|
paramName: 'file_uploaded',
|
|
maxFilesize: 50, // can't be greater than 50Mb because it's an addons limitation
|
|
uploadMultiple: false,
|
|
addRemoveLinks: true,
|
|
dictDefaultMessage: '',
|
|
hiddenInputContainer: self.dropZoneImportZoneSelector,
|
|
/**
|
|
* Add unlimited timeout. Otherwise dropzone timeout is 30 seconds
|
|
* and if a module is long to install, it is not possible to install the module.
|
|
*/
|
|
timeout: 0,
|
|
addedfile: () => {
|
|
self.animateStartUpload();
|
|
},
|
|
processing: () => {
|
|
// Leave it empty since we don't require anything while processing upload
|
|
},
|
|
error: (file, message) => {
|
|
self.displayOnUploadError(message);
|
|
},
|
|
complete: (file) => {
|
|
if (file.status !== 'error') {
|
|
const responseObject = $.parseJSON(file.xhr.response);
|
|
|
|
if (typeof responseObject.is_configurable === 'undefined') responseObject.is_configurable = null;
|
|
if (typeof responseObject.module_name === 'undefined') responseObject.module_name = null;
|
|
|
|
self.displayOnUploadDone(responseObject);
|
|
}
|
|
// State that we have finish the process to unlock some actions
|
|
self.isUploadStarted = false;
|
|
},
|
|
};
|
|
|
|
dropzone.dropzone($.extend(dropzoneOptions));
|
|
}
|
|
|
|
animateStartUpload() {
|
|
const self = this;
|
|
const dropzone = $('.dropzone');
|
|
// State that we start module upload
|
|
self.isUploadStarted = true;
|
|
$(self.moduleImportStartSelector).hide(0);
|
|
dropzone.css('border', 'none');
|
|
$(self.moduleImportProcessingSelector).fadeIn();
|
|
}
|
|
|
|
animateEndUpload(callback) {
|
|
const self = this;
|
|
$(self.moduleImportProcessingSelector)
|
|
.finish()
|
|
.fadeOut(callback);
|
|
}
|
|
|
|
/**
|
|
* Method to call for upload modal, when the ajax call went well.
|
|
*
|
|
* @param object result containing the server response
|
|
*/
|
|
displayOnUploadDone(result) {
|
|
const self = this;
|
|
self.animateEndUpload(() => {
|
|
if (result.status === true) {
|
|
if (result.is_configurable === true) {
|
|
const configureLink = window.moduleURLs.configurationPage.replace(/:number:/, result.module_name);
|
|
$(self.moduleImportSuccessConfigureBtnSelector).attr('href', configureLink);
|
|
$(self.moduleImportSuccessConfigureBtnSelector).show();
|
|
}
|
|
$(self.moduleImportSuccessSelector).fadeIn();
|
|
} else if (typeof result.confirmation_subject !== 'undefined') {
|
|
self.displayPrestaTrustStep(result);
|
|
} else {
|
|
$(self.moduleImportFailureMsgDetailsSelector).html(result.msg);
|
|
$(self.moduleImportFailureSelector).fadeIn();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Method to call for upload modal, when the ajax call went wrong or when the action requested could not
|
|
* succeed for some reason.
|
|
*
|
|
* @param string message explaining the error.
|
|
*/
|
|
displayOnUploadError(message) {
|
|
const self = this;
|
|
self.animateEndUpload(() => {
|
|
$(self.moduleImportFailureMsgDetailsSelector).html(message);
|
|
$(self.moduleImportFailureSelector).fadeIn();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* If PrestaTrust needs to be confirmed, we ask for the confirmation
|
|
* modal content and we display it in the currently displayed one.
|
|
* We also generate the ajax call to trigger once we confirm we want to install
|
|
* the module.
|
|
*
|
|
* @param Previous server response result
|
|
*/
|
|
displayPrestaTrustStep(result) {
|
|
const self = this;
|
|
const modal = self.moduleCardController.replacePrestaTrustPlaceholders(result);
|
|
const moduleName = result.module.attributes.name;
|
|
|
|
$(this.moduleImportConfirmSelector)
|
|
.html(modal.find('.modal-body').html())
|
|
.fadeIn();
|
|
$(this.dropZoneModalFooterSelector)
|
|
.html(modal.find('.modal-footer').html())
|
|
.fadeIn();
|
|
|
|
$(this.dropZoneModalFooterSelector)
|
|
.find('.pstrust-install')
|
|
.off('click')
|
|
.on('click', () => {
|
|
$(self.moduleImportConfirmSelector).hide();
|
|
$(self.dropZoneModalFooterSelector).html('');
|
|
self.animateStartUpload();
|
|
|
|
// Install ajax call
|
|
$.post(result.module.attributes.urls.install, {
|
|
'actionParams[confirmPrestaTrust]': '1',
|
|
})
|
|
.done((data) => {
|
|
self.displayOnUploadDone(data[moduleName]);
|
|
})
|
|
.fail((data) => {
|
|
self.displayOnUploadError(data[moduleName]);
|
|
})
|
|
.always(() => {
|
|
self.isUploadStarted = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
getBulkCheckboxesSelector() {
|
|
return this.currentDisplay === this.DISPLAY_GRID
|
|
? this.bulkActionCheckboxGridSelector
|
|
: this.bulkActionCheckboxListSelector;
|
|
}
|
|
|
|
getBulkCheckboxesCheckedSelector() {
|
|
return this.currentDisplay === this.DISPLAY_GRID
|
|
? this.checkedBulkActionGridSelector
|
|
: this.checkedBulkActionListSelector;
|
|
}
|
|
|
|
getModuleItemSelector() {
|
|
return this.currentDisplay === this.DISPLAY_GRID ? this.moduleItemGridSelector : this.moduleItemListSelector;
|
|
}
|
|
|
|
/**
|
|
* Get the module notifications count and displays it as a badge on the notification tab
|
|
* @return void
|
|
*/
|
|
getNotificationsCount() {
|
|
const self = this;
|
|
$.getJSON(window.moduleURLs.notificationsCount, self.updateNotificationsCount).fail(() => {
|
|
console.error('Could not retrieve module notifications count.');
|
|
});
|
|
}
|
|
|
|
updateNotificationsCount(badge) {
|
|
const destinationTabs = {
|
|
to_configure: $('#subtab-AdminModulesNotifications'),
|
|
to_update: $('#subtab-AdminModulesUpdates'),
|
|
};
|
|
|
|
Object.keys(destinationTabs).forEach((destinationKey) => {
|
|
if (destinationTabs[destinationKey].length !== 0) {
|
|
destinationTabs[destinationKey].find('.notification-counter').text(badge[destinationKey]);
|
|
}
|
|
});
|
|
}
|
|
|
|
initAddonsSearch() {
|
|
const self = this;
|
|
$('body').on('click', `${self.addonItemGridSelector}, ${self.addonItemListSelector}`, () => {
|
|
let searchQuery = '';
|
|
|
|
if (self.currentTagsList.length) {
|
|
searchQuery = encodeURIComponent(self.currentTagsList.join(' '));
|
|
}
|
|
|
|
window.open(`${self.baseAddonsUrl}search.php?search_query=${searchQuery}`, '_blank');
|
|
});
|
|
}
|
|
|
|
initCategoriesGrid() {
|
|
const self = this;
|
|
|
|
$('body').on('click', this.categoryGridItemSelector, function initilaizeGridBodyClick(event) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
const refCategory = $(this).data('category-ref');
|
|
|
|
// In case we have some tags we need to reset it !
|
|
if (self.currentTagsList.length) {
|
|
self.pstaggerInput.resetTags(false);
|
|
self.currentTagsList = [];
|
|
}
|
|
const menuCategoryToTrigger = $(`${self.categoryItemSelector}[data-category-ref="${refCategory}"]`);
|
|
|
|
if (!menuCategoryToTrigger.length) {
|
|
console.warn(`No category with ref (${refCategory}) seems to exist!`);
|
|
return false;
|
|
}
|
|
|
|
// Hide current category grid
|
|
if (self.isCategoryGridDisplayed === true) {
|
|
$(self.categoryGridSelector).fadeOut();
|
|
self.isCategoryGridDisplayed = false;
|
|
}
|
|
|
|
// Trigger click on right category
|
|
$(`${self.categoryItemSelector}[data-category-ref="${refCategory}"]`).click();
|
|
return true;
|
|
});
|
|
}
|
|
|
|
initCurrentDisplay() {
|
|
this.currentDisplay = this.currentDisplay === '' ? this.DISPLAY_LIST : this.DISPLAY_GRID;
|
|
}
|
|
|
|
initSortingDropdown() {
|
|
const self = this;
|
|
|
|
self.currentSorting = $(this.moduleSortingDropdownSelector)
|
|
.find(':checked')
|
|
.attr('value');
|
|
if (!self.currentSorting) {
|
|
self.currentSorting = 'access-desc';
|
|
}
|
|
|
|
$('body').on('change', self.moduleSortingDropdownSelector, function initializeBodySortingChange() {
|
|
self.currentSorting = $(this)
|
|
.find(':checked')
|
|
.attr('value');
|
|
self.updateModuleVisibility();
|
|
});
|
|
}
|
|
|
|
doBulkAction(requestedBulkAction) {
|
|
// This object is used to check if requested bulkAction is available and give proper
|
|
// url segment to be called for it
|
|
const forceDeletion = $('#force_bulk_deletion').prop('checked');
|
|
|
|
const bulkActionToUrl = {
|
|
'bulk-uninstall': 'uninstall',
|
|
'bulk-disable': 'disable',
|
|
'bulk-enable': 'enable',
|
|
'bulk-disable-mobile': 'disable_mobile',
|
|
'bulk-enable-mobile': 'enable_mobile',
|
|
'bulk-reset': 'reset',
|
|
};
|
|
|
|
// Note no grid selector used yet since we do not needed it at dev time
|
|
// Maybe useful to implement this kind of things later if intended to
|
|
// use this functionality elsewhere but "manage my module" section
|
|
if (typeof bulkActionToUrl[requestedBulkAction] === 'undefined') {
|
|
$.growl.error({
|
|
message: window.translate_javascripts['Bulk Action - Request not found'].replace('[1]', requestedBulkAction),
|
|
});
|
|
return false;
|
|
}
|
|
|
|
// Loop over all checked bulk checkboxes
|
|
const bulkActionSelectedSelector = this.getBulkCheckboxesCheckedSelector();
|
|
const bulkModuleAction = bulkActionToUrl[requestedBulkAction];
|
|
|
|
if ($(bulkActionSelectedSelector).length <= 0) {
|
|
console.warn(window.translate_javascripts['Bulk Action - One module minimum']);
|
|
return false;
|
|
}
|
|
|
|
const modulesActions = [];
|
|
let moduleTechName;
|
|
$(bulkActionSelectedSelector).each(function bulkActionSelector() {
|
|
moduleTechName = $(this).data('tech-name');
|
|
modulesActions.push({
|
|
techName: moduleTechName,
|
|
actionMenuObj: $(this)
|
|
.closest('.module-checkbox-bulk-list')
|
|
.next(),
|
|
});
|
|
});
|
|
|
|
this.performModulesAction(modulesActions, bulkModuleAction, forceDeletion);
|
|
|
|
return true;
|
|
}
|
|
|
|
performModulesAction(modulesActions, bulkModuleAction, forceDeletion) {
|
|
const self = this;
|
|
|
|
if (typeof self.moduleCardController === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
// First let's filter modules that can't perform this action
|
|
const actionMenuLinks = filterAllowedActions(modulesActions);
|
|
|
|
if (!actionMenuLinks.length) {
|
|
return;
|
|
}
|
|
|
|
let modulesRequestedCountdown = actionMenuLinks.length - 1;
|
|
let spinnerObj = $('<button class="btn-primary-reverse onclick unbind spinner "></button>');
|
|
|
|
if (actionMenuLinks.length > 1) {
|
|
// Loop through all the modules except the last one which waits for other
|
|
// requests and then call its request with cache clear enabled
|
|
$.each(actionMenuLinks, (index, actionMenuLink) => {
|
|
if (index >= actionMenuLinks.length - 1) {
|
|
return;
|
|
}
|
|
requestModuleAction(actionMenuLink, true, countdownModulesRequest);
|
|
});
|
|
// Display a spinner for the last module
|
|
const lastMenuLink = actionMenuLinks[actionMenuLinks.length - 1];
|
|
const actionMenuObj = lastMenuLink.closest(self.moduleCardController.moduleItemActionsSelector);
|
|
actionMenuObj.hide();
|
|
actionMenuObj.after(spinnerObj);
|
|
} else {
|
|
requestModuleAction(actionMenuLinks[0]);
|
|
}
|
|
|
|
function requestModuleAction(actionMenuLink, disableCacheClear, requestEndCallback) {
|
|
self.moduleCardController.requestToController(
|
|
bulkModuleAction,
|
|
actionMenuLink,
|
|
forceDeletion,
|
|
disableCacheClear,
|
|
requestEndCallback,
|
|
);
|
|
}
|
|
|
|
function countdownModulesRequest() {
|
|
modulesRequestedCountdown -= 1;
|
|
// Now that all other modules have performed their action WITHOUT cache clear, we
|
|
// can request the last module request WITH cache clear
|
|
if (modulesRequestedCountdown <= 0) {
|
|
if (spinnerObj) {
|
|
spinnerObj.remove();
|
|
spinnerObj = null;
|
|
}
|
|
|
|
const lastMenuLink = actionMenuLinks[actionMenuLinks.length - 1];
|
|
const actionMenuObj = lastMenuLink.closest(self.moduleCardController.moduleItemActionsSelector);
|
|
actionMenuObj.fadeIn();
|
|
requestModuleAction(lastMenuLink);
|
|
}
|
|
}
|
|
|
|
function filterAllowedActions(actions) {
|
|
const menuLinks = [];
|
|
let actionMenuLink;
|
|
$.each(actions, (index, moduleData) => {
|
|
actionMenuLink = $(
|
|
self.moduleCardController.moduleActionMenuLinkSelector + bulkModuleAction,
|
|
moduleData.actionMenuObj,
|
|
);
|
|
if (actionMenuLink.length > 0) {
|
|
menuLinks.push(actionMenuLink);
|
|
} else {
|
|
$.growl.error({
|
|
message: window.translate_javascripts['Bulk Action - Request not available for module']
|
|
.replace('[1]', bulkModuleAction)
|
|
.replace('[2]', moduleData.techName),
|
|
});
|
|
}
|
|
});
|
|
|
|
return menuLinks;
|
|
}
|
|
}
|
|
|
|
initActionButtons() {
|
|
const self = this;
|
|
$('body').on('click', self.moduleInstallBtnSelector, function initializeActionButtonsClick(event) {
|
|
const $this = $(this);
|
|
const $next = $($this.next());
|
|
event.preventDefault();
|
|
|
|
$this.hide();
|
|
$next.show();
|
|
|
|
$.ajax({
|
|
url: $this.data('url'),
|
|
dataType: 'json',
|
|
}).done(() => {
|
|
$next.fadeOut();
|
|
});
|
|
});
|
|
|
|
// "Upgrade All" button handler
|
|
$('body').on('click', self.upgradeAllSource, (event) => {
|
|
event.preventDefault();
|
|
const isMaintenanceMode = window.isShopMaintenance;
|
|
|
|
// Modal body element
|
|
const maintenanceLink = document.createElement('a');
|
|
maintenanceLink.classList.add('btn', 'btn-primary', 'btn-lg');
|
|
maintenanceLink.setAttribute('href', window.moduleURLs.maintenancePage);
|
|
maintenanceLink.innerHTML = window.moduleTranslations.moduleModalUpdateMaintenance;
|
|
|
|
const updateAllConfirmModal = new ConfirmModal(
|
|
{
|
|
id: 'confirm-module-update-modal',
|
|
confirmTitle: window.moduleTranslations.singleModuleModalUpdateTitle,
|
|
closeButtonLabel: window.moduleTranslations.moduleModalUpdateCancel,
|
|
confirmButtonLabel: isMaintenanceMode
|
|
? window.moduleTranslations.moduleModalUpdateUpgrade
|
|
: window.moduleTranslations.upgradeAnywayButtonText,
|
|
confirmButtonClass: isMaintenanceMode ? 'btn-primary' : 'btn-secondary',
|
|
confirmMessage: isMaintenanceMode ? '' : window.moduleTranslations.moduleModalUpdateConfirmMessage,
|
|
closable: true,
|
|
customButtons: isMaintenanceMode ? [] : [maintenanceLink],
|
|
},
|
|
() => {
|
|
if ($(self.upgradeAllTargets).length <= 0) {
|
|
console.warn(window.translate_javascripts['Upgrade All Action - One module minimum']);
|
|
return false;
|
|
}
|
|
|
|
const modulesActions = [];
|
|
let moduleTechName;
|
|
$(self.upgradeAllTargets).each(function bulkActionSelector() {
|
|
const moduleItemList = $(this).closest('.module-item-list');
|
|
moduleTechName = moduleItemList.data('tech-name');
|
|
modulesActions.push({
|
|
techName: moduleTechName,
|
|
actionMenuObj: $('.module-actions', moduleItemList),
|
|
});
|
|
});
|
|
|
|
this.performModulesAction(modulesActions, 'upgrade');
|
|
|
|
return true;
|
|
},
|
|
);
|
|
|
|
updateAllConfirmModal.show();
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
initCategorySelect() {
|
|
const self = this;
|
|
const body = $('body');
|
|
body.on('click', self.categoryItemSelector, function initializeCategorySelectClick() {
|
|
// Get data from li DOM input
|
|
self.currentRefCategory = $(this).data('category-ref');
|
|
self.currentRefCategory = self.currentRefCategory ? String(self.currentRefCategory).toLowerCase() : null;
|
|
// Change dropdown label to set it to the current category's displayname
|
|
$(self.categorySelectorLabelSelector).text($(this).data('category-display-name'));
|
|
$(self.categoryResetBtnSelector).show();
|
|
self.updateModuleVisibility();
|
|
});
|
|
|
|
body.on('click', self.categoryResetBtnSelector, function initializeCategoryResetButtonClick() {
|
|
const rawText = $(self.categorySelector).attr('aria-labelledby');
|
|
const upperFirstLetter = rawText.charAt(0).toUpperCase();
|
|
const removedFirstLetter = rawText.slice(1);
|
|
const originalText = upperFirstLetter + removedFirstLetter;
|
|
|
|
$(self.categorySelectorLabelSelector).text(originalText);
|
|
$(this).hide();
|
|
self.currentRefCategory = null;
|
|
self.updateModuleVisibility();
|
|
});
|
|
}
|
|
|
|
initSearchBlock() {
|
|
const self = this;
|
|
self.pstaggerInput = $('#module-search-bar').pstagger({
|
|
onTagsChanged: (tagList) => {
|
|
self.currentTagsList = tagList;
|
|
self.updateModuleVisibility();
|
|
},
|
|
onResetTags: () => {
|
|
self.currentTagsList = [];
|
|
self.updateModuleVisibility();
|
|
},
|
|
inputPlaceholder: window.translate_javascripts['Search - placeholder'],
|
|
closingCross: true,
|
|
context: self,
|
|
});
|
|
|
|
$('body').on('click', '.module-addons-search-link', (event) => {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
window.open($(this).attr('href'), '_blank');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initialize display switching between List or Grid
|
|
*/
|
|
initSortingDisplaySwitch() {
|
|
const self = this;
|
|
|
|
$('body').on('click', '.module-sort-switch', function switchSort() {
|
|
const switchTo = $(this).data('switch');
|
|
const isAlreadyDisplayed = $(this).hasClass('active-display');
|
|
|
|
if (typeof switchTo !== 'undefined' && isAlreadyDisplayed === false) {
|
|
self.switchSortingDisplayTo(switchTo);
|
|
self.currentDisplay = switchTo;
|
|
}
|
|
});
|
|
}
|
|
|
|
switchSortingDisplayTo(switchTo) {
|
|
if (switchTo !== this.DISPLAY_GRID && switchTo !== this.DISPLAY_LIST) {
|
|
console.error(`Can't switch to undefined display property "${switchTo}"`);
|
|
return;
|
|
}
|
|
|
|
$('.module-sort-switch').removeClass('module-sort-active');
|
|
$(`#module-sort-${switchTo}`).addClass('module-sort-active');
|
|
this.currentDisplay = switchTo;
|
|
this.updateModuleVisibility();
|
|
}
|
|
|
|
initializeSeeMore() {
|
|
const self = this;
|
|
|
|
$(`${self.moduleShortList} ${self.seeMoreSelector}`).on('click', function seeMore() {
|
|
self.currentCategoryDisplay[$(this).data('category')] = true;
|
|
$(this).addClass('d-none');
|
|
$(this)
|
|
.closest(self.moduleShortList)
|
|
.find(self.seeLessSelector)
|
|
.removeClass('d-none');
|
|
self.updateModuleVisibility();
|
|
});
|
|
|
|
$(`${self.moduleShortList} ${self.seeLessSelector}`).on('click', function seeMore() {
|
|
self.currentCategoryDisplay[$(this).data('category')] = false;
|
|
$(this).addClass('d-none');
|
|
$(this)
|
|
.closest(self.moduleShortList)
|
|
.find(self.seeMoreSelector)
|
|
.removeClass('d-none');
|
|
self.updateModuleVisibility();
|
|
});
|
|
}
|
|
|
|
updateTotalResults() {
|
|
const self = this;
|
|
const replaceFirstWordBy = (element, value) => {
|
|
const explodedText = element.text().split(' ');
|
|
explodedText[0] = value;
|
|
element.text(explodedText.join(' '));
|
|
};
|
|
|
|
// If there are some shortlist: each shortlist count the modules on the next container.
|
|
const $shortLists = $('.module-short-list');
|
|
|
|
if ($shortLists.length > 0) {
|
|
$shortLists.each(function shortLists() {
|
|
const $this = $(this);
|
|
replaceFirstWordBy(
|
|
$this.find('.module-search-result-wording'),
|
|
$this.next('.modules-list').find('.module-item').length,
|
|
);
|
|
});
|
|
|
|
// If there is no shortlist: the wording directly update from the only module container.
|
|
} else {
|
|
const modulesCount = $('.modules-list').find('.module-item').length;
|
|
replaceFirstWordBy($('.module-search-result-wording'), modulesCount);
|
|
|
|
// eslint-disable-next-line
|
|
const selectorToToggle =
|
|
self.currentDisplay === self.DISPLAY_LIST ? this.addonItemListSelector : this.addonItemGridSelector;
|
|
$(selectorToToggle).toggle(modulesCount !== this.modulesList.length / 2);
|
|
|
|
if (modulesCount === 0) {
|
|
$('.module-addons-search-link').attr(
|
|
'href',
|
|
`${this.baseAddonsUrl}search.php?search_query=${encodeURIComponent(this.currentTagsList.join(' '))}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
isModulesPage() {
|
|
return $(this.upgradeContainer).length === 0 && $(this.notificationContainer).length === 0;
|
|
}
|
|
}
|
|
|
|
export default AdminModuleController;
|