Initial commit

This commit is contained in:
2020-10-07 10:37:15 +02:00
commit ce5f440392
28157 changed files with 4429172 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Responsible for connecting to addons marketplace.
* Makes an addons connect request to the server, displays error messages if it fails.
*/
export default class AddonsConnector {
constructor(
addonsConnectFormSelector,
loadingSpinnerSelector
) {
this.addonsConnectFormSelector = addonsConnectFormSelector;
this.$loadingSpinner = $(loadingSpinnerSelector);
this._initEvents();
return {};
}
/**
* Initialize events related to connection to addons.
*
* @private
*/
_initEvents() {
$('body').on('submit', this.addonsConnectFormSelector, (event) => {
const $form = $(event.currentTarget);
event.preventDefault();
event.stopPropagation();
this._connect($form.attr('action'), $form.serialize());
});
}
/**
* Do a POST request to connect to addons.
*
* @param {String} addonsConnectUrl
* @param {Object} formData
*
* @private
*/
_connect(addonsConnectUrl, formData) {
$.ajax({
method: 'POST',
url: addonsConnectUrl,
dataType: 'json',
data: formData,
beforeSend: () => {
this.$loadingSpinner.show();
$('button.btn[type="submit"]', this.addonsConnectFormSelector).hide();
}
}).then((response) => {
if (response.success === 1) {
location.reload();
} else {
$.growl.error({
message: response.message
});
this.$loadingSpinner.hide();
$('button.btn[type="submit"]', this.addonsConnectFormSelector).fadeIn();
}
}, () => {
$.growl.error({
message: $(this.addonsConnectFormSelector).data('error-message'),
});
this.$loadingSpinner.hide();
$('button.btn[type="submit"]', this.addonsConnectFormSelector).show();
});
}
}

View File

@@ -0,0 +1,130 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Generates a password and informs about it's strength.
* You can pass a password input to watch the password strength and display feedback messages.
* You can also generate a random password into an input.
*/
export default class ChangePasswordHandler {
constructor(passwordStrengthFeedbackContainerSelector, options = {}) {
// Minimum length of the generated password.
this.minLength = options.minLength || 8;
// Feedback container holds messages representing password strength.
this.$feedbackContainer = $(passwordStrengthFeedbackContainerSelector);
return {
watchPasswordStrength: ($input) => this.watchPasswordStrength($input),
generatePassword: ($input) => this.generatePassword($input),
};
}
/**
* Watch password, which is entered in the input, strength and inform about it.
*
* @param {jQuery} $input the input to watch.
*/
watchPasswordStrength($input) {
$.passy.requirements.length.min = this.minLength;
$.passy.requirements.characters = 'DIGIT';
$input.each((index, element) => {
const $outputContainer = $('<span>');
$outputContainer.insertAfter($(element));
$(element).passy((strength, valid) => {
this._displayFeedback($outputContainer, strength, valid);
});
});
}
/**
* Generates a password and fills it to given input.
*
* @param {jQuery} $input the input to fill the password into.
*/
generatePassword($input) {
$input.passy('generate', this.minLength);
}
/**
* Display feedback about password's strength.
*
* @param {jQuery} $outputContainer a container to put feedback output into.
* @param {number} passwordStrength
* @param {boolean} isPasswordValid
*
* @private
*/
_displayFeedback($outputContainer, passwordStrength, isPasswordValid) {
const feedback = this._getPasswordStrengthFeedback(passwordStrength);
$outputContainer.text(feedback.message);
$outputContainer.removeClass('text-danger text-warning text-success');
$outputContainer.addClass(feedback.elementClass);
$outputContainer.toggleClass('d-none', !isPasswordValid);
}
/**
* Get feedback that describes given password strength.
* Response contains text message and element class.
*
* @param {number} strength
*
* @private
*/
_getPasswordStrengthFeedback(strength) {
switch (strength) {
case $.passy.strength.LOW:
return {
message: this.$feedbackContainer.find('.strength-low').text(),
elementClass: 'text-danger',
};
case $.passy.strength.MEDIUM:
return {
message: this.$feedbackContainer.find('.strength-medium').text(),
elementClass: 'text-warning',
};
case $.passy.strength.HIGH:
return {
message: this.$feedbackContainer.find('.strength-high').text(),
elementClass: 'text-success',
};
case $.passy.strength.EXTREME:
return {
message: this.$feedbackContainer.find('.strength-extreme').text(),
elementClass: 'text-success',
};
}
throw 'Invalid password strength indicator.';
}
}

View File

@@ -0,0 +1,52 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* ChoiceTable is responsible for managing common actions in choice table form type
*/
export default class ChoiceTable {
/**
* Init constructor
*/
constructor() {
$(document).on('change', '.js-choice-table-select-all', (e) => {
this.handleSelectAll(e);
});
}
/**
* Check/uncheck all boxes in table
*
* @param {Event} event
*/
handleSelectAll(event) {
const $selectAllCheckboxes = $(event.target);
const isSelectAllChecked = $selectAllCheckboxes.is(':checked');
$selectAllCheckboxes.closest('table').find('tbody input:checkbox').prop('checked', isSelectAllChecked);
}
}

View File

@@ -0,0 +1,72 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Toggle DNI input requirement on country selection
*
* Usage:
*
* <!-- Country select options must have need_dni attribute when needed -->
* <select name="id_country" id="id_country" states-url="path/to/states/api">
* ...
* <option value="6" need_dni="1">Spain</value>
* ...
* </select>
*
* In JS:
*
* new CountryDniRequiredToggler('#id_country', '#id_country_dni', 'label[for="id_country_dni"]');
*/
export default class CountryDniRequiredToggler {
constructor(countryInputSelector, countryDniInput, countryDniInputLabel) {
this.$countryDniInput = $(countryDniInput);
this.$countryDniInputLabel = $(countryDniInputLabel);
this.$countryInput = $(countryInputSelector);
this.countryInputSelectedSelector = `${countryInputSelector}>option:selected`;
this.countryDniInputLabelDangerSelector = `${countryDniInputLabel}>span.text-danger`;
this.$countryInput.on('change', () => this._toggle());
// toggle on page load
this._toggle();
}
/**
* Toggles DNI input required
*
* @private
*/
_toggle() {
const $countrySelectedOption = $(this.countryInputSelectedSelector);
$(this.countryDniInputLabelDangerSelector).remove();
this.$countryDniInput.attr('required', false);
if (1 === parseInt($countrySelectedOption.attr('need_dni'), 10)) {
this.$countryDniInput.attr('required', true);
this.$countryDniInputLabel.prepend($('<span class="text-danger">*</span>'));
}
}
}

View File

@@ -0,0 +1,98 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Displays, fills or hides State selection block depending on selected country.
*
* Usage:
*
* <!-- Country select must have unique identifier & url for states API -->
* <select name="id_country" id="id_country" states-url="path/to/states/api">
* ...
* </select>
*
* <!-- If selected country does not have states, then this block will be hidden -->
* <div class="js-state-selection-block">
* <select name="id_state">
* ...
* </select>
* </div>
*
* In JS:
*
* new CountryStateSelectionToggler('#id_country', '#id_state', '.js-state-selection-block');
*/
export default class CountryStateSelectionToggler {
constructor(countryInputSelector, countryStateSelector, stateSelectionBlockSelector) {
this.$stateSelectionBlock = $(stateSelectionBlockSelector);
this.$countryStateSelector = $(countryStateSelector);
this.$countryInput = $(countryInputSelector);
this.$countryInput.on('change', () => this._toggle());
// toggle on page load
this._toggle(true);
return {};
}
/**
* Toggles State selection
*
* @private
*/
_toggle(isFirstToggle = false) {
$.ajax({
url: this.$countryInput.data('states-url'),
method: 'GET',
dataType: 'json',
data: {
id_country: this.$countryInput.val(),
}
}).then((response) => {
if (response.states.length === 0) {
this.$stateSelectionBlock.fadeOut();
return;
}
this.$stateSelectionBlock.fadeIn();
if (isFirstToggle === false) {
this.$countryStateSelector.empty();
var _this = this;
$.each(response.states, function (index, value) {
_this.$countryStateSelector.append($('<option></option>').attr('value', value).text(index));
})
}
}).catch((response) => {
if (typeof response.responseJSON !== 'undefined') {
showErrorMessage(response.responseJSON.message);
}
});
}
}

View File

@@ -0,0 +1,32 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import EventEmitterClass from 'events';
/**
* We instanciate one EventEmitter (restricted via a const) so that every components
* register/dispatch on the same one and can communicate with each other.
*/
export const EventEmitter = new EventEmitterClass();

View File

@@ -0,0 +1,79 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Component which allows submitting very simple forms without having to use <form> element.
*
* Useful when performing actions on resource where URL contains all needed data.
* For example, to toggle category status via "POST /categories/2/toggle-status)"
* or delete cover image via "POST /categories/2/delete-cover-image".
*
* Usage example in template:
*
* <button class="js-form-submit-btn"
* data-form-submit-url="/my-custom-url" // (required) URL to which form will be submitted
* data-form-csrf-token="my-generated-csrf-token" // (optional) to increase security
* data-form-confirm-message="Are you sure?" // (optional) to confirm action before submit
* type="button" // make sure its simple button
* // so we can avoid submitting actual form
* // when our button is defined inside form
* >
* Click me to submit form
* </button>
*
* In page specific JS you have to enable this feature:
*
* new FormSubmitButton();
*/
export default class FormSubmitButton {
constructor() {
$(document).on('click', '.js-form-submit-btn', function (event) {
event.preventDefault();
const $btn = $(this);
if ($btn.data('form-confirm-message') && false === confirm($btn.data('form-confirm-message'))) {
return;
}
const $form = $('<form>', {
'action': $btn.data('form-submit-url'),
'method': 'POST',
});
if ($btn.data('form-csrf-token')) {
$form.append($('<input>', {
'type': '_hidden',
'name': '_csrf_token',
'value': $btn.data('form-csrf-token')
}));
}
$form.appendTo('body').submit();
});
}
}

View File

@@ -0,0 +1,248 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import ChangePasswordHandler from "../change-password-handler";
import PasswordValidator from "../password-validator";
const $ = window.$;
/**
* Class responsible for actions related to "change password" form type.
* Generates random passwords, validates new password and it's confirmation,
* displays error messages related to validation.
*/
export default class ChangePasswordControl {
constructor(
inputsBlockSelector,
showButtonSelector,
hideButtonSelector,
generatePasswordButtonSelector,
oldPasswordInputSelector,
newPasswordInputSelector,
confirmNewPasswordInputSelector,
generatedPasswordDisplaySelector,
passwordStrengthFeedbackContainerSelector
) {
// Block that contains password inputs
this.$inputsBlock = $(inputsBlockSelector);
// Button that shows the password inputs block
this.showButtonSelector = showButtonSelector;
// Button that hides the password inputs block
this.hideButtonSelector = hideButtonSelector;
// Button that generates a random password
this.generatePasswordButtonSelector = generatePasswordButtonSelector;
// Input to enter old password
this.oldPasswordInputSelector = oldPasswordInputSelector;
// Input to enter new password
this.newPasswordInputSelector = newPasswordInputSelector;
// Input to confirm the new password
this.confirmNewPasswordInputSelector = confirmNewPasswordInputSelector;
// Input that displays generated random password
this.generatedPasswordDisplaySelector = generatedPasswordDisplaySelector;
// Main input for password generation
this.$newPasswordInputs = this.$inputsBlock
.find(this.newPasswordInputSelector);
// Generated password will be copied to these inputs
this.$copyPasswordInputs = this.$inputsBlock
.find(this.confirmNewPasswordInputSelector)
.add(this.generatedPasswordDisplaySelector);
// All inputs in the change password block, that are submittable with the form.
this.$submittableInputs = this.$inputsBlock
.find(this.oldPasswordInputSelector)
.add(this.newPasswordInputSelector)
.add(this.confirmNewPasswordInputSelector);
this.passwordHandler = new ChangePasswordHandler(
passwordStrengthFeedbackContainerSelector
);
this.passwordValidator = new PasswordValidator(
this.newPasswordInputSelector,
this.confirmNewPasswordInputSelector
);
this._hideInputsBlock();
this._initEvents();
return {};
}
/**
* Initialize events.
*
* @private
*/
_initEvents() {
// Show the inputs block when show button is clicked
$(document).on('click', this.showButtonSelector, (e) => {
this._hide($(e.currentTarget));
this._showInputsBlock();
});
$(document).on('click', this.hideButtonSelector, () => {
this._hideInputsBlock();
this._show($(this.showButtonSelector));
});
// Watch and display feedback about password's strength
this.passwordHandler.watchPasswordStrength(this.$newPasswordInputs);
$(document).on('click', this.generatePasswordButtonSelector, () => {
// Generate the password into main input.
this.passwordHandler.generatePassword(this.$newPasswordInputs);
// Copy the generated password from main input to additional inputs
this.$copyPasswordInputs.val(this.$newPasswordInputs.val());
this._checkPasswordValidity();
});
// Validate new password and it's confirmation when any of the inputs is changed
$(document).on('keyup', `${this.newPasswordInputSelector},${this.confirmNewPasswordInputSelector}`, () => {
this._checkPasswordValidity();
});
// Prevent submitting the form if new password is not valid
$(document).on('submit', $(this.oldPasswordInputSelector).closest('form'), (event) => {
// If password input is disabled - we don't need to validate it.
if ($(this.oldPasswordInputSelector).is(':disabled')) {
return;
}
if (!this.passwordValidator.isPasswordValid()) {
event.preventDefault();
}
});
}
/**
* Check if password is valid, show error messages if it's not.
*
* @private
*/
_checkPasswordValidity() {
const $firstPasswordErrorContainer = $(this.newPasswordInputSelector).parent().find('.form-text');
const $secondPasswordErrorContainer = $(this.confirmNewPasswordInputSelector).parent().find('.form-text');
$firstPasswordErrorContainer
.text(this._getPasswordLengthValidationMessage())
.toggleClass('text-danger', !this.passwordValidator.isPasswordLengthValid())
;
$secondPasswordErrorContainer
.text(this._getPasswordConfirmationValidationMessage())
.toggleClass('text-danger', !this.passwordValidator.isPasswordMatchingConfirmation())
;
}
/**
* Get password confirmation validation message.
*
* @returns {String}
*
* @private
*/
_getPasswordConfirmationValidationMessage() {
if (!this.passwordValidator.isPasswordMatchingConfirmation()) {
return $(this.confirmNewPasswordInputSelector).data('invalid-password');
}
return '';
}
/**
* Get password length validation message.
*
* @returns {String}
*
* @private
*/
_getPasswordLengthValidationMessage() {
if (this.passwordValidator.isPasswordTooShort()) {
return $(this.newPasswordInputSelector).data('password-too-short')
}
if (this.passwordValidator.isPasswordTooLong()) {
return $(this.newPasswordInputSelector).data('password-too-long');
}
return '';
}
/**
* Show the password inputs block.
*
* @private
*/
_showInputsBlock() {
this._show(this.$inputsBlock);
this.$submittableInputs.removeAttr('disabled');
this.$submittableInputs.attr('required', 'required');
}
/**
* Hide the password inputs block.
*
* @private
*/
_hideInputsBlock() {
this._hide(this.$inputsBlock);
this.$submittableInputs.attr('disabled', 'disabled');
this.$submittableInputs.removeAttr('required');
this.$inputsBlock.find('input').val('');
this.$inputsBlock.find('.form-text').text('');
}
/**
* Hide an element.
*
* @param {jQuery} $el
*
* @private
*/
_hide($el) {
$el.addClass('d-none');
}
/**
* Show hidden element.
*
* @param {jQuery} $el
*
* @private
*/
_show($el) {
$el.removeClass('d-none');
}
}

View File

@@ -0,0 +1,158 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Handles UI interactions of choice tree
*/
export default class ChoiceTree {
/**
* @param {String} treeSelector
*/
constructor(treeSelector) {
this.$container = $(treeSelector);
this.$container.on('click', '.js-input-wrapper', (event) => {
const $inputWrapper = $(event.currentTarget);
this._toggleChildTree($inputWrapper);
});
this.$container.on('click', '.js-toggle-choice-tree-action', (event) => {
const $action = $(event.currentTarget);
this._toggleTree($action);
});
return {
enableAutoCheckChildren: () => this.enableAutoCheckChildren(),
enableAllInputs: () => this.enableAllInputs(),
disableAllInputs: () => this.disableAllInputs(),
};
}
/**
* Enable automatic check/uncheck of clicked item's children.
*/
enableAutoCheckChildren() {
this.$container.on('change', 'input[type="checkbox"]', (event) => {
const $clickedCheckbox = $(event.currentTarget);
const $itemWithChildren = $clickedCheckbox.closest('li');
$itemWithChildren
.find('ul input[type="checkbox"]')
.prop('checked', $clickedCheckbox.is(':checked'));
});
}
/**
* Enable all inputs in the choice tree.
*/
enableAllInputs() {
this.$container.find('input').removeAttr('disabled');
}
/**
* Disable all inputs in the choice tree.
*/
disableAllInputs() {
this.$container.find('input').attr('disabled', 'disabled');
}
/**
* Collapse or expand sub-tree for single parent
*
* @param {jQuery} $inputWrapper
*
* @private
*/
_toggleChildTree($inputWrapper) {
const $parentWrapper = $inputWrapper.closest('li');
if ($parentWrapper.hasClass('expanded')) {
$parentWrapper
.removeClass('expanded')
.addClass('collapsed');
return;
}
if ($parentWrapper.hasClass('collapsed')) {
$parentWrapper
.removeClass('collapsed')
.addClass('expanded');
}
}
/**
* Collapse or expand whole tree
*
* @param {jQuery} $action
*
* @private
*/
_toggleTree($action) {
const $parentContainer = $action.closest('.js-choice-tree-container');
const action = $action.data('action');
// toggle action configuration
const config = {
addClass: {
expand: 'expanded',
collapse: 'collapsed',
},
removeClass: {
expand: 'collapsed',
collapse: 'expanded',
},
nextAction: {
expand: 'collapse',
collapse: 'expand',
},
text: {
expand: 'collapsed-text',
collapse: 'expanded-text',
},
icon: {
expand: 'collapsed-icon',
collapse: 'expanded-icon',
}
};
$parentContainer.find('li').each((index, item) => {
const $item = $(item);
if ($item.hasClass(config.removeClass[action])) {
$item.removeClass(config.removeClass[action])
.addClass(config.addClass[action]);
}
});
$action.data('action', config.nextAction[action]);
$action.find('.material-icons').text($action.data(config.icon[action]));
$action.find('.js-toggle-text').text($action.data(config.text[action]));
}
}

View File

@@ -0,0 +1,89 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Component responsible for displaying form popover errors with modified width which is calculated based on the
* form group width.
*/
$(() => {
// loads form popover instance
$('[data-toggle="form-popover-error"]').popover({
html: true,
content: function () {
return getErrorContent(this);
},
});
/**
* Recalculates popover position so it is always aligned horizontally and width is identical
* to the child elements of the form.
* @param {Object} event
*/
const repositionPopover = (event) => {
const $element = $(event.currentTarget);
const $formGroup = $element.closest('.form-group');
const $invalidFeedbackContainer = $formGroup.find('.invalid-feedback-container');
const $errorPopover = $formGroup.find('.form-popover-error');
const localeVisibleElementWidth = $invalidFeedbackContainer.width();
$errorPopover.css('width', localeVisibleElementWidth);
const horizontalDifference = getHorizontalDifference($invalidFeedbackContainer, $errorPopover);
$errorPopover.css('left', `${horizontalDifference}px`);
};
/**
* gets horizontal difference which helps to align popover horizontally.
* @param {jQuery} $invalidFeedbackContainer
* @param {jQuery} $errorPopover
* @returns {number}
*/
const getHorizontalDifference = ($invalidFeedbackContainer, $errorPopover) => {
const inputHorizontalPosition = $invalidFeedbackContainer.offset().left;
const popoverHorizontalPosition = $errorPopover.offset().left;
return inputHorizontalPosition - popoverHorizontalPosition;
};
/**
* Gets popover error content pre-fetched in html. It used unique selector to identify which one content to render.
*
* @param popoverTriggerElement
* @returns {jQuery}
*/
const getErrorContent = (popoverTriggerElement) => {
const popoverTriggerId = $(popoverTriggerElement).data('id');
return $(`.js-popover-error-content[data-id="${popoverTriggerId}"]`).html();
};
// registers the event which displays the popover
$(document).on('shown.bs.popover', '[data-toggle="form-popover-error"]', (event) => repositionPopover(event));
});

View File

@@ -0,0 +1,55 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Responsible for opening another page with specified url.
* For example used in 'Save and preview' cms page create/edit actions.
*
* Usage: In selector element attr 'data-preview-url' provide page url.
* The page will be opened once provided 'open_preview' parameter in query url
*/
export default class PreviewOpener {
constructor (previewUrlSelector) {
this.previewUrl = $(previewUrlSelector).data('preview-url');
this._open();
return {};
}
/**
* Opens new page of provided url
*
* @private
*/
_open() {
const urlParams = new URLSearchParams(location.search);
if (this.previewUrl && urlParams.has('open_preview')) {
window.open(this.previewUrl, '_blank');
}
}
}

View File

@@ -0,0 +1,59 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* TextWithLengthCounter handles input with length counter UI.
*
* Usage:
*
* There must be an element that wraps both input & counter display with ".js-text-with-length-counter" class.
* Counter display must have ".js-countable-text-display" class and input must have ".js-countable-text-input" class.
* Text input must have "data-max-length" attribute.
*
* <div class="js-text-with-length-counter">
* <span class="js-countable-text"></span>
* <input class="js-countable-input" data-max-length="255">
* </div>
*
* In Javascript you must enable this component:
*
* new TextWithLengthCounter();
*/
export default class TextWithLengthCounter {
constructor() {
this.wrapperSelector = '.js-text-with-length-counter';
this.textSelector = '.js-countable-text';
this.inputSelector = '.js-countable-input';
$(document).on('input', `${this.wrapperSelector} ${this.inputSelector}`, (e) => {
const $input = $(e.currentTarget);
const remainingLength = $input.data('max-length') - $input.val().length;
$input.closest(this.wrapperSelector).find(this.textSelector).text(remainingLength);
});
}
}

View File

@@ -0,0 +1,59 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* This component is implemented to work with TextWithRecommendedLengthType,
* but can be used as standalone component as well.
*
* Usage:
*
* Define your HTML with input and counter. Example:
*
* <input id="myInput"
* class="js-recommended-length-input"
* data-recommended-length-counter="#myInput_recommended_length_counter"
* >
*
* <div id"myInput_recommended_length_counter">
* <span class="js-current-length">0</span> of 70 characters used (recommended)
* </div>
*
* NOTE: You must use exactly the same Classes, but IDs can be different!
*
* Then enable component in JavaScript:
*
* new TextWithRecommendedLengthCounter();
*/
export default class TextWithRecommendedLengthCounter {
constructor() {
$(document).on('input', '.js-recommended-length-input', (event) => {
const $input = $(event.currentTarget);
$($input.data('recommended-length-counter')).find('.js-current-length').text($input.val().length);
});
}
}

View File

@@ -0,0 +1,97 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
/**
* Generates random values for inputs.
*
* Usage:
*
* There should be a button in HTML with 2 required data-* properties:
* 1. data-target-input-id - input id for which value should be generated
* 2. data-generated-value-size -
*
* Example button: <button class="js-generator-btn"
* data-target-input-id="my-input-id"
* data-generated-value-length="16"
* >
* Generate!
* </button>
*
* In JavaScript you have to enable this functionality using GeneratableInput component like so:
*
* const generateableInput = new GeneratableInput();
* generateableInput.attachOn('.js-generator-btn'); // every time our button is clicked
* // it will generate random value of 16 characters
* // for input with id of "my-input-id"
*
* You can attach as many different buttons as you like using "attachOn()" function
* as long as 2 required data-* attributes are present at each button.
*/
export default class GeneratableInput {
constructor() {
return {
'attachOn': (btnSelector) => this._attachOn(btnSelector),
};
}
/**
* Attaches event listener on button than can generate value
*
* @param {String} generatorBtnSelector
*
* @private
*/
_attachOn(generatorBtnSelector) {
document.querySelector(generatorBtnSelector).addEventListener('click', (event) => {
const attributes = event.currentTarget.attributes;
const targetInputId = attributes.getNamedItem('data-target-input-id').value;
const generatedValueLength = parseInt(attributes.getNamedItem('data-generated-value-length').value);
const targetInput = document.querySelector('#' + targetInputId);
targetInput.value = this._generateValue(generatedValueLength)
});
}
/**
* Generates random value for input
*
* @param {Number} length
*
* @returns {string}
*
* @private
*/
_generateValue(length) {
const chars = '123456789ABCDEFGHIJKLMNPQRSTUVWXYZ';
let generatedValue = '';
for (let i = 1; i <= length; ++i) {
generatedValue += chars.charAt(Math.floor(Math.random() * chars.length));
}
return generatedValue;
}
}

View File

@@ -0,0 +1,77 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class DeleteCategoriesBulkActionExtension handles submitting of row action
*/
export default class DeleteCategoriesBulkActionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
};
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-delete-categories-bulk-action', (event) => {
event.preventDefault();
const submitUrl = $(event.currentTarget).data('categories-delete-url');
const $deleteCategoriesModal = $(`#${grid.getId()}_grid_delete_categories_modal`);
$deleteCategoriesModal.modal('show');
$deleteCategoriesModal.on('click', '.js-submit-delete-categories', () => {
const $checkboxes = grid.getContainer().find('.js-bulk-action-checkbox:checked');
const $categoriesToDeleteInputBlock = $('#delete_categories_categories_to_delete');
$checkboxes.each((i, element) => {
const $checkbox = $(element);
const categoryInput = $categoriesToDeleteInputBlock
.data('prototype')
.replace(/__name__/g, $checkbox.val());
const $input = $($.parseHTML(categoryInput)[0]);
$input.val($checkbox.val());
$categoriesToDeleteInputBlock.append($input);
});
const $form = $deleteCategoriesModal.find('form');
$form.attr('action', submitUrl);
$form.submit();
});
});
}
}

View File

@@ -0,0 +1,88 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Handles bulk delete for "Customers" grid.
*/
export default class DeleteCustomersBulkActionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
};
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-delete-customers-bulk-action', (event) => {
event.preventDefault();
const submitUrl = $(event.currentTarget).data('customers-delete-url');
const $modal = $(`#${grid.getId()}_grid_delete_customers_modal`);
$modal.modal('show');
$modal.on('click', '.js-submit-delete-customers', () => {
const $selectedCustomerCheckboxes = grid.getContainer().find('.js-bulk-action-checkbox:checked');
$selectedCustomerCheckboxes.each((i, checkbox) => {
const $input = $(checkbox);
this._addCustomerToDeleteCollectionInput($input.val());
});
const $form = $modal.find('form');
$form.attr('action', submitUrl);
$form.submit();
});
});
}
/**
* Create input with customer id and add it to delete collection input
*
* @private
*/
_addCustomerToDeleteCollectionInput(customerId) {
const $customersInput = $('#delete_customers_customers_to_delete');
const customerInput = $customersInput
.data('prototype')
.replace(/__name__/g, customerId)
;
const $item = $($.parseHTML(customerInput)[0]);
$item.val(customerId);
$customersInput.append($item);
}
}

View File

@@ -0,0 +1,73 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class CategoryDeleteRowActionExtension handles submitting of row action
*/
export default class DeleteCategoryRowActionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
};
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-delete-category-row-action', (event) => {
event.preventDefault();
const $deleteCategoriesModal = $('#' + grid.getId() + '_grid_delete_categories_modal');
$deleteCategoriesModal.modal('show');
$deleteCategoriesModal.on('click', '.js-submit-delete-categories', () => {
const $button = $(event.currentTarget);
const categoryId = $button.data('category-id');
const $categoriesToDeleteInputBlock = $('#delete_categories_categories_to_delete');
const categoryInput = $categoriesToDeleteInputBlock
.data('prototype')
.replace(/__name__/g, $categoriesToDeleteInputBlock.children().length);
const $item = $($.parseHTML(categoryInput)[0]);
$item.val(categoryId);
$categoriesToDeleteInputBlock.append($item);
const $form = $deleteCategoriesModal.find('form');
$form.attr('action', $button.data('category-delete-url'));
$form.submit();
});
});
}
}

View File

@@ -0,0 +1,84 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class DeleteCustomerRowActionExtension handles submitting of row action
*/
export default class DeleteCustomerRowActionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
};
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-delete-customer-row-action', (event) => {
event.preventDefault();
const $deleteCustomersModal = $(`#${grid.getId()}_grid_delete_customers_modal`);
$deleteCustomersModal.modal('show');
$deleteCustomersModal.on('click', '.js-submit-delete-customers', () => {
const $button = $(event.currentTarget);
const customerId = $button.data('customer-id');
this._addCustomerInput(customerId);
const $form = $deleteCustomersModal.find('form');
$form.attr('action', $button.data('customer-delete-url'));
$form.submit();
});
});
}
/**
* Adds input for selected customer to delete form
*
* @param {integer} customerId
*
* @private
*/
_addCustomerInput(customerId) {
const $customersToDeleteInputBlock = $('#delete_customers_customers_to_delete');
const customerInput = $customersToDeleteInputBlock
.data('prototype')
.replace(/__name__/g, $customersToDeleteInputBlock.children().length);
const $item = $($.parseHTML(customerInput)[0]);
$item.val(customerId);
$customersToDeleteInputBlock.append($item);
}
}

View File

@@ -0,0 +1,67 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class SubmitRowActionExtension handles submitting of row action
*/
export default class SubmitRowActionExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-submit-row-action', (event) => {
event.preventDefault();
const $button = $(event.currentTarget);
const confirmMessage = $button.data('confirm-message');
if (confirmMessage.length && !confirm(confirmMessage)) {
return;
}
const method = $button.data('method');
const isGetOrPostMethod = ['GET', 'POST'].includes(method);
const $form = $('<form>', {
'action': $button.data('url'),
'method': isGetOrPostMethod ? method : 'POST',
}).appendTo('body');
if (!isGetOrPostMethod) {
$form.append($('<input>', {
'type': '_hidden',
'name': '_method',
'value': method
}));
}
$form.submit();
});
}
}

View File

@@ -0,0 +1,104 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class BulkActionSelectCheckboxExtension
*/
export default class BulkActionCheckboxExtension {
/**
* Extend grid with bulk action checkboxes handling functionality
*
* @param {Grid} grid
*/
extend(grid) {
this._handleBulkActionCheckboxSelect(grid);
this._handleBulkActionSelectAllCheckbox(grid);
}
/**
* Handles "Select all" button in the grid
*
* @param {Grid} grid
*
* @private
*/
_handleBulkActionSelectAllCheckbox(grid) {
grid.getContainer().on('change', '.js-bulk-action-select-all', (e) => {
const $checkbox = $(e.currentTarget);
const isChecked = $checkbox.is(':checked');
if (isChecked) {
this._enableBulkActionsBtn(grid);
} else {
this._disableBulkActionsBtn(grid);
}
grid.getContainer().find('.js-bulk-action-checkbox').prop('checked', isChecked);
});
}
/**
* Handles each bulk action checkbox select in the grid
*
* @param {Grid} grid
*
* @private
*/
_handleBulkActionCheckboxSelect(grid) {
grid.getContainer().on('change', '.js-bulk-action-checkbox', () => {
const checkedRowsCount = grid.getContainer().find('.js-bulk-action-checkbox:checked').length;
if (checkedRowsCount > 0) {
this._enableBulkActionsBtn(grid);
} else {
this._disableBulkActionsBtn(grid);
}
});
}
/**
* Enable bulk actions button
*
* @param {Grid} grid
*
* @private
*/
_enableBulkActionsBtn(grid) {
grid.getContainer().find('.js-bulk-actions-btn').prop('disabled', false);
}
/**
* Disable bulk actions button
*
* @param {Grid} grid
*
* @private
*/
_disableBulkActionsBtn(grid) {
grid.getContainer().find('.js-bulk-actions-btn').prop('disabled', true);
}
}

View File

@@ -0,0 +1,70 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = global.$;
/**
* Class ReloadListExtension extends grid with "Column toggling" feature
*/
export default class ColumnTogglingExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
const $table = grid.getContainer().find('table.table');
$table.find('.ps-togglable-row').on('click', (e) => {
e.preventDefault();
this._toggleValue($(e.delegateTarget));
});
}
/**
* @param {jQuery} row
* @private
*/
_toggleValue(row) {
const toggleUrl = row.data('toggleUrl');
this._submitAsForm(toggleUrl);
}
/**
* Submits request url as form
*
* @param {string} toggleUrl
* @private
*/
_submitAsForm(toggleUrl) {
const $form = $('<form>', {
action: toggleUrl,
method: 'POST',
}).appendTo('body');
$form.submit();
}
}

View File

@@ -0,0 +1,167 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import tableDnD from "tablednd/dist/jquery.tablednd.min";
const $ = window.$;
/**
* Class CategoryPositionExtension extends Grid with reorderable category positions
*/
export default class CategoryPositionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
}
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
this.grid = grid;
this._addIdsToGridTableRows();
grid.getContainer().find('.js-grid-table').tableDnD({
dragHandle: '.js-drag-handle',
onDragClass: 'dragging-row',
onDragStart: () => {
this.originalPositions = decodeURIComponent($.tableDnD.serialize());
},
onDrop: (table, row) => this._handleCategoryPositionChange(row),
});
}
/**
* When position is changed handle update
*
* @param {HTMLElement} row
*
* @private
*/
_handleCategoryPositionChange(row) {
const positions = decodeURIComponent($.tableDnD.serialize());
const way = (this.originalPositions.indexOf(row.id) < positions.indexOf(row.id)) ? 1 : 0;
const $categoryPositionContainer = $(row).find('.js-' + this.grid.getId() + '-position:first');
const categoryId = $categoryPositionContainer.data('id');
const categoryParentId = $categoryPositionContainer.data('id-parent');
const positionUpdateUrl = $categoryPositionContainer.data('position-update-url');
let params = positions.replace(new RegExp(this.grid.getId() + '_grid_table', 'g'), 'positions');
let queryParams = {
id_category_parent: categoryParentId,
id_category_to_move: categoryId,
way: way
};
if (positions.indexOf('_0&') !== -1) {
queryParams.found_first = 1;
}
params += '&' + $.param(queryParams);
this._updateCategoryPosition(positionUpdateUrl, params);
}
/**
* Add ID's to Grid table rows to make tableDnD.onDrop() function work.
*
* @private
*/
_addIdsToGridTableRows() {
this.grid.getContainer()
.find('.js-grid-table')
.find('.js-' + this.grid.getId() + '-position')
.each((index, positionWrapper) => {
const $positionWrapper = $(positionWrapper);
const categoryId = $positionWrapper.data('id');
const categoryParentId = $positionWrapper.data('id-parent');
const position = $positionWrapper.data('position');
const id = 'tr_' + categoryParentId + '_' + categoryId + '_' + position;
$positionWrapper.closest('tr').attr('id', id);
});
}
/**
* Update categories listing with new positions
*
* @private
*/
_updateCategoryIdsAndPositions() {
this.grid.getContainer()
.find('.js-grid-table')
.find('.js-' + this.grid.getId() + '-position')
.each((index, positionWrapper) => {
const $positionWrapper = $(positionWrapper);
const $row = $positionWrapper.closest('tr');
const offset = $positionWrapper.data('pagination-offset');
const newPosition = offset > 0 ? index + offset : index;
const oldId = $row.attr('id');
$row.attr('id', oldId.replace(/_[0-9]$/g, '_' + newPosition));
$positionWrapper.find('.js-position').text(newPosition + 1);
$positionWrapper.data('position', newPosition);
});
}
/**
* Process categories positions update
*
* @param {String} url
* @param {String} params
*
* @private
*/
_updateCategoryPosition(url, params) {
$.post({
url: url,
headers: {
'cache-control': 'no-cache'
},
data: params,
dataType: 'json'
}).then((response) => {
if (response.success) {
showSuccessMessage(response.message);
} else {
showErrorMessage(response.message);
}
this._updateCategoryIdsAndPositions();
});
}
}

View File

@@ -0,0 +1,84 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class AsyncToggleColumnExtension submits toggle action using AJAX
*/
export default class AsyncToggleColumnExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
}
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().find('.js-grid-table').on('click', '.ps-togglable-row', (event) => {
event.preventDefault();
const $button = $(event.currentTarget);
$.post({
url: $button.data('toggle-url'),
}).then((response) => {
if (response.status) {
showSuccessMessage(response.message);
this._toggleButtonDisplay($button);
return;
}
showErrorMessage(response.message);
});
});
}
/**
* Toggle button display from enabled to disabled and other way around
*
* @param {jQuery} $button
*
* @private
*/
_toggleButtonDisplay($button) {
const isActive = $button.hasClass('grid-toggler-icon-valid');
const classToAdd = isActive ? 'grid-toggler-icon-not-valid' : 'grid-toggler-icon-valid';
const classToRemove = isActive ? 'grid-toggler-icon-valid' : 'grid-toggler-icon-not-valid';
const icon = isActive ? 'clear' : 'check';
$button.removeClass(classToRemove);
$button.addClass(classToAdd);
$button.text(icon);
}
}

View File

@@ -0,0 +1,116 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class ExportToSqlManagerExtension extends grid with exporting query to SQL Manager
*/
export default class ExportToSqlManagerExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getHeaderContainer().on('click', '.js-common_show_query-grid-action', () => this._onShowSqlQueryClick(grid));
grid.getHeaderContainer().on('click', '.js-common_export_sql_manager-grid-action', () => this._onExportSqlManagerClick(grid));
}
/**
* Invoked when clicking on the "show sql query" toolbar button
*
* @param {Grid} grid
*
* @private
*/
_onShowSqlQueryClick(grid) {
const $sqlManagerForm = $('#' + grid.getId() + '_common_show_query_modal_form');
this._fillExportForm($sqlManagerForm, grid);
const $modal = $('#' + grid.getId() + '_grid_common_show_query_modal');
$modal.modal('show');
$modal.on('click', '.btn-sql-submit', () => $sqlManagerForm.submit());
}
/**
* Invoked when clicking on the "export to the sql query" toolbar button
*
* @param {Grid} grid
*
* @private
*/
_onExportSqlManagerClick(grid) {
const $sqlManagerForm = $('#' + grid.getId() + '_common_show_query_modal_form');
this._fillExportForm($sqlManagerForm, grid);
$sqlManagerForm.submit();
}
/**
* Fill export form with SQL and it's name
*
* @param {jQuery} $sqlManagerForm
* @param {Grid} grid
*
* @private
*/
_fillExportForm($sqlManagerForm, grid) {
const query = grid.getContainer().find('.js-grid-table').data('query');
$sqlManagerForm.find('textarea[name="sql"]').val(query);
$sqlManagerForm.find('input[name="name"]').val(this._getNameFromBreadcrumb());
}
/**
* Get export name from page's breadcrumb
*
* @return {String}
*
* @private
*/
_getNameFromBreadcrumb() {
const $breadcrumbs = $('.header-toolbar').find('.breadcrumb-item');
let name = '';
$breadcrumbs.each((i, item) => {
const $breadcrumb = $(item);
const breadcrumbTitle = 0 < $breadcrumb.find('a').length ?
$breadcrumb.find('a').text() :
$breadcrumb.text();
if (0 < name.length) {
name = name.concat(' > ');
}
name = name.concat(breadcrumbTitle);
});
return name;
}
}

View File

@@ -0,0 +1,45 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import resetSearch from '../../../app/utils/reset_search';
const $ = window.$;
/**
* Class FiltersResetExtension extends grid with filters resetting
*/
export default class FiltersResetExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-reset-search', (event) => {
resetSearch($(event.currentTarget).data('url'), $(event.currentTarget).data('redirect'));
});
}
}

View File

@@ -0,0 +1,88 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class LinkRowActionExtension handles link row actions
*/
export default class LinkRowActionExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
this.initRowLinks(grid);
this.initConfirmableActions(grid);
}
/**
* Extend grid
*
* @param {Grid} grid
*/
initConfirmableActions(grid) {
grid.getContainer().on('click', '.js-link-row-action', (event) => {
const confirmMessage = $(event.currentTarget).data('confirm-message');
if (confirmMessage.length && !confirm(confirmMessage)) {
event.preventDefault();
}
});
}
/**
* Add a click event on rows that matches the first link action (if present)
*
* @param {Grid} grid
*/
initRowLinks(grid) {
$('tr', grid.getContainer()).each(function initEachRow() {
const $parentRow = $(this);
$('.js-link-row-action[data-clickable-row=1]:first', $parentRow).each(function propagateFirstLinkAction() {
const $rowAction = $(this);
const $parentCell = $rowAction.closest('td');
/*
* Only search for cells with non clickable contents to avoid conflicts with
* previous cell behaviour (action, toggle, ...)
*/
const clickableCells = $('td.data-type, td.identifier-type:not(:has(input)), td.badge-type, td.position-type', $parentRow)
.not($parentCell)
;
clickableCells.addClass('cursor-pointer').click(() => {
const confirmMessage = $rowAction.data('confirm-message');
if (!confirmMessage.length || confirm(confirmMessage)) {
document.location = $rowAction.attr('href');
}
});
});
});
}
}

View File

@@ -0,0 +1,175 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import tableDnD from "tablednd/dist/jquery.tablednd.min";
const $ = window.$;
/**
* Class PositionExtension extends Grid with reorderable positions
*/
export default class PositionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
}
}
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
this.grid = grid;
this._addIdsToGridTableRows();
grid.getContainer().find('.js-grid-table').tableDnD({
onDragClass: 'position-row-while-drag',
dragHandle: '.js-drag-handle',
onDrop: (table, row) => this._handlePositionChange(row),
});
grid.getContainer().find('.js-drag-handle').hover(
function() {
$(this).closest('tr').addClass('hover');
},
function() {
$(this).closest('tr').removeClass('hover');
}
);
}
/**
* When position is changed handle update
*
* @param {HTMLElement} row
*
* @private
*/
_handlePositionChange(row) {
const $rowPositionContainer = $(row).find('.js-' + this.grid.getId() + '-position:first');
const updateUrl = $rowPositionContainer.data('update-url');
const method = $rowPositionContainer.data('update-method');
const paginationOffset = parseInt($rowPositionContainer.data('pagination-offset'), 10);
const positions = this._getRowsPositions(paginationOffset);
const params = {positions};
this._updatePosition(updateUrl, params, method);
}
/**
* Returns the current table positions
* @returns {Array}
* @private
*/
_getRowsPositions(paginationOffset) {
const tableData = JSON.parse($.tableDnD.jsonize());
const rowsData = tableData[this.grid.getId()+'_grid_table'];
const regex = /^row_(\d+)_(\d+)$/;
const rowsNb = rowsData.length;
const positions = [];
let rowData, i;
for (i = 0; i < rowsNb; ++i) {
rowData = regex.exec(rowsData[i]);
positions.push({
rowId: rowData[1],
newPosition: paginationOffset + i,
oldPosition: parseInt(rowData[2], 10),
});
}
return positions;
}
/**
* Add ID's to Grid table rows to make tableDnD.onDrop() function work.
*
* @private
*/
_addIdsToGridTableRows() {
this.grid.getContainer()
.find('.js-grid-table .js-' + this.grid.getId() + '-position')
.each((index, positionWrapper) => {
const $positionWrapper = $(positionWrapper);
const rowId = $positionWrapper.data('id');
const position = $positionWrapper.data('position');
const id = `row_${rowId}_${position}`;
$positionWrapper.closest('tr').attr('id', id);
$positionWrapper.closest('td').addClass('js-drag-handle');
});
}
/**
* Process rows positions update
*
* @param {String} url
* @param {Object} params
* @param {String} method
*
* @private
*/
_updatePosition(url, params, method) {
const isGetOrPostMethod = ['GET', 'POST'].includes(method);
const $form = $('<form>', {
'action': url,
'method': isGetOrPostMethod ? method : 'POST',
}).appendTo('body');
const positionsNb = params.positions.length;
let position;
for (let i = 0; i < positionsNb; ++i) {
position = params.positions[i];
$form.append(
$('<input>', {
'type': 'hidden',
'name': 'positions['+i+'][rowId]',
'value': position.rowId
}),
$('<input>', {
'type': 'hidden',
'name': 'positions['+i+'][oldPosition]',
'value': position.oldPosition
}),
$('<input>', {
'type': 'hidden',
'name': 'positions['+i+'][newPosition]',
'value': position.newPosition
})
);
}
// This _method param is used by Symfony to simulate DELETE and PUT methods
if (!isGetOrPostMethod) {
$form.append($('<input>', {
'type': 'hidden',
'name': '_method',
'value': method,
}));
}
$form.submit();
}
}

View File

@@ -0,0 +1,40 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
/**
* Class ReloadListExtension extends grid with "List reload" action
*/
export default class ReloadListExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
grid.getHeaderContainer().on('click', '.js-common_refresh_list-grid-action', () => {
location.reload();
});
}
}

View File

@@ -0,0 +1,42 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import TableSorting from '../../../app/utils/table-sorting';
/**
* Class ReloadListExtension extends grid with "List reload" action
*/
export default class SortingExtension {
/**
* Extend grid
*
* @param {Grid} grid
*/
extend(grid) {
const $sortableTable = grid.getContainer().find('table.table');
new TableSorting($sortableTable).attach();
}
}

View File

@@ -0,0 +1,71 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Handles submit of grid actions
*/
export default class SubmitBulkActionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid),
};
}
/**
* Extend grid with bulk action submitting
*
* @param {Grid} grid
*/
extend(grid) {
grid.getContainer().on('click', '.js-bulk-action-submit-btn', (event) => {
this.submit(event, grid);
});
}
/**
* Handle bulk action submitting
*
* @param {Event} event
* @param {Grid} grid
*
* @private
*/
submit(event, grid) {
const $submitBtn = $(event.currentTarget);
const confirmMessage = $submitBtn.data('confirm-message');
if (typeof confirmMessage !== "undefined" && 0 < confirmMessage.length && !confirm(confirmMessage)) {
return;
}
const $form = $('#' + grid.getId() + '_filter_form');
$form.attr('action', $submitBtn.data('form-url'));
$form.attr('method', $submitBtn.data('form-method'));
$form.submit();
}
}

View File

@@ -0,0 +1,68 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class SubmitGridActionExtension handles grid action submits
*/
export default class SubmitGridActionExtension {
constructor() {
return {
extend: (grid) => this.extend(grid)
};
}
extend(grid) {
grid.getHeaderContainer().on('click', '.js-grid-action-submit-btn', (event) => {
this.handleSubmit(event, grid);
});
}
/**
* Handle grid action submit.
* It uses grid form to submit actions.
*
* @param {Event} event
* @param {Grid} grid
*
* @private
*/
handleSubmit(event, grid) {
const $submitBtn = $(event.currentTarget);
const confirmMessage = $submitBtn.data('confirm-message');
if (typeof confirmMessage !== "undefined" && 0 < confirmMessage.length && !confirm(confirmMessage)) {
return;
}
const $form = $('#' + grid.getId() + '_filter_form');
$form.attr('action', $submitBtn.data('url'));
$form.attr('method', $submitBtn.data('method'));
$form.find('input[name="' + grid.getId() + '[_token]"]').val($submitBtn.data('csrf'));
$form.submit();
}
}

View File

@@ -0,0 +1,77 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class is responsible for handling Grid events
*/
export default class Grid {
/**
* Grid id
*
* @param {string} id
*/
constructor(id) {
this.id = id;
this.$container = $('#' + this.id + '_grid');
}
/**
* Get grid id
*
* @returns {string}
*/
getId() {
return this.id;
}
/**
* Get grid container
*
* @returns {jQuery}
*/
getContainer() {
return this.$container;
}
/**
* Get grid header container
*
* @returns {jQuery}
*/
getHeaderContainer() {
return this.$container.closest('.js-grid-panel').find('.js-grid-header');
}
/**
* Extend grid with external extensions
*
* @param {object} extension
*/
addExtension(extension) {
extension.extend(this);
}
}

View File

@@ -0,0 +1,37 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Takes link from clicked item and redirects to it.
*/
export default class LinkableItem {
constructor() {
$(document).on('click', '.js-linkable-item', (event) => {
window.location = $(event.currentTarget).data('linkable-href');
});
}
}

View File

@@ -0,0 +1,310 @@
/**
* 2007-2020 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2020 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
var BOEvent = {
on: function(eventName, callback, context) {
document.addEventListener(eventName, function(event) {
if (typeof context !== 'undefined') {
callback.call(context, event);
} else {
callback(event);
}
});
},
emitEvent: function(eventName, eventType) {
var _event = document.createEvent(eventType);
// true values stand for: can bubble, and is cancellable
_event.initEvent(eventName, true, true);
document.dispatchEvent(_event);
}
};
/**
* Class is responsible for handling Module Card behavior
*
* This is a port of admin-dev/themes/default/js/bundle/module/module_card.js
*/
export default class ModuleCard {
constructor() {
/* Selectors for module action links (uninstall, reset, etc...) to add a confirm popin */
this.moduleActionMenuLinkSelector = 'button.module_action_menu_';
this.moduleActionMenuInstallLinkSelector = 'button.module_action_menu_install';
this.moduleActionMenuEnableLinkSelector = 'button.module_action_menu_enable';
this.moduleActionMenuUninstallLinkSelector = 'button.module_action_menu_uninstall';
this.moduleActionMenuDisableLinkSelector = 'button.module_action_menu_disable';
this.moduleActionMenuEnableMobileLinkSelector = 'button.module_action_menu_enable_mobile';
this.moduleActionMenuDisableMobileLinkSelector = 'button.module_action_menu_disable_mobile';
this.moduleActionMenuResetLinkSelector = 'button.module_action_menu_reset';
this.moduleActionMenuUpdateLinkSelector = 'button.module_action_menu_upgrade';
this.moduleItemListSelector = '.module-item-list';
this.moduleItemGridSelector = '.module-item-grid';
this.moduleItemActionsSelector = '.module-actions';
/* Selectors only for modal buttons */
this.moduleActionModalDisableLinkSelector = 'a.module_action_modal_disable';
this.moduleActionModalResetLinkSelector = 'a.module_action_modal_reset';
this.moduleActionModalUninstallLinkSelector = 'a.module_action_modal_uninstall';
this.forceDeletionOption = '#force_deletion';
this.initActionButtons();
}
initActionButtons() {
const self = this;
$(document).on('click', this.forceDeletionOption, function () {
const btn = $(self.moduleActionModalUninstallLinkSelector, $("div.module-item-list[data-tech-name='" + $(this).attr("data-tech-name") + "']"));
if ($(this).prop('checked') === true) {
btn.attr('data-deletion', 'true');
} else {
btn.removeAttr('data-deletion');
}
});
$(document).on('click', this.moduleActionMenuInstallLinkSelector, function () {
if ($("#modal-prestatrust").length) {
$("#modal-prestatrust").modal('hide');
}
return self._dispatchPreEvent('install', this) && self._confirmAction('install', this) && self._requestToController('install', $(this));
});
$(document).on('click', this.moduleActionMenuEnableLinkSelector, function () {
return self._dispatchPreEvent('enable', this) && self._confirmAction('enable', this) && self._requestToController('enable', $(this));
});
$(document).on('click', this.moduleActionMenuUninstallLinkSelector, function () {
return self._dispatchPreEvent('uninstall', this) && self._confirmAction('uninstall', this) && self._requestToController('uninstall', $(this));
});
$(document).on('click', this.moduleActionMenuDisableLinkSelector, function () {
return self._dispatchPreEvent('disable', this) && self._confirmAction('disable', this) && self._requestToController('disable', $(this));
});
$(document).on('click', this.moduleActionMenuEnableMobileLinkSelector, function () {
return self._dispatchPreEvent('enable_mobile', this) && self._confirmAction('enable_mobile', this) && self._requestToController('enable_mobile', $(this));
});
$(document).on('click', this.moduleActionMenuDisableMobileLinkSelector, function () {
return self._dispatchPreEvent('disable_mobile', this) && self._confirmAction('disable_mobile', this) && self._requestToController('disable_mobile', $(this));
});
$(document).on('click', this.moduleActionMenuResetLinkSelector, function () {
return self._dispatchPreEvent('reset', this) && self._confirmAction('reset', this) && self._requestToController('reset', $(this));
});
$(document).on('click', this.moduleActionMenuUpdateLinkSelector, function () {
return self._dispatchPreEvent('update', this) && self._confirmAction('update', this) && self._requestToController('update', $(this));
});
$(document).on('click', this.moduleActionModalDisableLinkSelector, function () {
return self._requestToController('disable', $(self.moduleActionMenuDisableLinkSelector, $("div.module-item-list[data-tech-name='" + $(this).attr("data-tech-name") + "']")));
});
$(document).on('click', this.moduleActionModalResetLinkSelector, function () {
return self._requestToController('reset', $(self.moduleActionMenuResetLinkSelector, $("div.module-item-list[data-tech-name='" + $(this).attr("data-tech-name") + "']")));
});
$(document).on('click', this.moduleActionModalUninstallLinkSelector, function (e) {
$(e.target).parents('.modal').on('hidden.bs.modal', function(event) {
return self._requestToController(
'uninstall',
$(
self.moduleActionMenuUninstallLinkSelector,
$("div.module-item-list[data-tech-name='" + $(e.target).attr("data-tech-name") + "']")
),
$(e.target).attr("data-deletion")
);
}.bind(e));
});
};
_getModuleItemSelector() {
if ($(this.moduleItemListSelector).length) {
return this.moduleItemListSelector;
} else {
return this.moduleItemGridSelector;
}
};
_confirmAction(action, element) {
var modal = $('#' + $(element).data('confirm_modal'));
if (modal.length != 1) {
return true;
}
modal.first().modal('show');
return false; // do not allow a.href to reload the page. The confirm modal dialog will do it async if needed.
};
/**
* Update the content of a modal asking a confirmation for PrestaTrust and open it
*
* @param {array} result containing module data
* @return {void}
*/
_confirmPrestaTrust(result) {
var that = this;
var modal = this._replacePrestaTrustPlaceholders(result);
modal.find(".pstrust-install").off('click').on('click', function() {
// Find related form, update it and submit it
var install_button = $(that.moduleActionMenuInstallLinkSelector, '.module-item[data-tech-name="' + result.module.attributes.name + '"]');
var form = install_button.parent("form");
$('<input>').attr({
type: 'hidden',
value: '1',
name: 'actionParams[confirmPrestaTrust]'
}).appendTo(form);
install_button.click();
modal.modal('hide');
});
modal.modal();
};
_replacePrestaTrustPlaceholders(result) {
var modal = $("#modal-prestatrust");
var module = result.module.attributes;
if (result.confirmation_subject !== 'PrestaTrust' || !modal.length) {
return;
}
var alertClass = module.prestatrust.status ? 'success' : 'warning';
if (module.prestatrust.check_list.property) {
modal.find("#pstrust-btn-property-ok").show();
modal.find("#pstrust-btn-property-nok").hide();
} else {
modal.find("#pstrust-btn-property-ok").hide();
modal.find("#pstrust-btn-property-nok").show();
modal.find("#pstrust-buy").attr("href", module.url).toggle(module.url !== null);
}
modal.find("#pstrust-img").attr({src: module.img, alt: module.name});
modal.find("#pstrust-name").text(module.displayName);
modal.find("#pstrust-author").text(module.author);
modal.find("#pstrust-label").attr("class", "text-" + alertClass).text(module.prestatrust.status ? 'OK' : 'KO');
modal.find("#pstrust-message").attr("class", "alert alert-"+alertClass);
modal.find("#pstrust-message > p").text(module.prestatrust.message);
return modal;
}
_dispatchPreEvent(action, element) {
var event = jQuery.Event('module_card_action_event');
$(element).trigger(event, [action]);
if (event.isPropagationStopped() !== false || event.isImmediatePropagationStopped() !== false) {
return false; // if all handlers have not been called, then stop propagation of the click event.
}
return (event.result !== false); // explicit false must be set from handlers to stop propagation of the click event.
};
_requestToController(action, element, forceDeletion, disableCacheClear, callback) {
var self = this;
var jqElementObj = element.closest(this.moduleItemActionsSelector);
var form = element.closest("form");
var spinnerObj = $("<button class=\"btn-primary-reverse onclick unbind spinner \"></button>");
var url = "//" + window.location.host + form.attr("action");
var actionParams = form.serializeArray();
if (forceDeletion === "true" || forceDeletion === true) {
actionParams.push({name: "actionParams[deletion]", value: true});
}
if (disableCacheClear === "true" || disableCacheClear === true) {
actionParams.push({name: "actionParams[cacheClearEnabled]", value: 0});
}
$.ajax({
url: url,
dataType: 'json',
method: 'POST',
data: actionParams,
beforeSend: function () {
jqElementObj.hide();
jqElementObj.after(spinnerObj);
}
}).done(function (result) {
if (typeof result === undefined) {
$.growl.error({message: "No answer received from server"});
return;
}
if (typeof result.status !== 'undefined' && result.status === false) {
$.growl.error({message: result.msg});
return;
}
var moduleTechName = Object.keys(result)[0];
if (result[moduleTechName].status === false) {
if (typeof result[moduleTechName].confirmation_subject !== 'undefined') {
self._confirmPrestaTrust(result[moduleTechName]);
}
$.growl.error({message: result[moduleTechName].msg});
return;
}
$.growl.notice({message: result[moduleTechName].msg});
var alteredSelector = self._getModuleItemSelector().replace('.', '');
var mainElement = null;
if (action == "uninstall") {
mainElement = jqElementObj.closest('.' + alteredSelector);
mainElement.remove();
BOEvent.emitEvent("Module Uninstalled", "CustomEvent");
} else if (action == "disable") {
mainElement = jqElementObj.closest('.' + alteredSelector);
mainElement.addClass(alteredSelector + '-isNotActive');
mainElement.attr('data-active', '0');
BOEvent.emitEvent("Module Disabled", "CustomEvent");
} else if (action == "enable") {
mainElement = jqElementObj.closest('.' + alteredSelector);
mainElement.removeClass(alteredSelector + '-isNotActive');
mainElement.attr('data-active', '1');
BOEvent.emitEvent("Module Enabled", "CustomEvent");
}
jqElementObj.replaceWith(result[moduleTechName].action_menu_html);
}).fail(function() {
const moduleItem = jqElementObj.closest('module-item-list');
const techName = moduleItem.data('techName');
$.growl.error({message: "Could not perform action "+action+" for module "+techName});
}).always(function () {
jqElementObj.fadeIn();
spinnerObj.remove();
if (callback) {
callback();
}
});
return false;
};
}

View File

@@ -0,0 +1,32 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
/**
* Encapsulates selectors for multi store restriction component
*/
export default {
multiStoreRestrictionCheckbox: '.js-multi-store-restriction-checkbox',
multiStoreRestrictionSwitch: '.js-multi-store-restriction-switch',
}

View File

@@ -0,0 +1,94 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import multiStoreRestrictionFieldMap from './multi-store-restriction-field-map';
const $ = window.$;
/**
* Enables multi store functionality for the page. It includes switch functionality and checkboxes
*/
export default class MultiStoreRestrictionField {
constructor() {
$(document).on(
'change',
multiStoreRestrictionFieldMap.multiStoreRestrictionCheckbox,
e => this._multiStoreRestrictionCheckboxFieldChangeEvent(e)
);
$(document).on(
'change',
multiStoreRestrictionFieldMap.multiStoreRestrictionSwitch,
e => this._multiStoreRestrictionSwitchFieldChangeEvent(e)
);
}
/**
* Toggles the checkbox field and enables or disables its related field.
*
* @param {Event} e
* @private
*/
_multiStoreRestrictionCheckboxFieldChangeEvent(e) {
const $currentItem = $(e.currentTarget);
this._toggleSourceFieldByTargetElement($currentItem, !$currentItem.is(':checked'));
}
/**
* Mass updates multi-store checkbox fields - it enables or disabled the switch and after that
* it calls the function
* which handles the toggle update related form field by its current state.
* @param {Event} e
* @private
*/
_multiStoreRestrictionSwitchFieldChangeEvent(e) {
const $currentItem = $(e.currentTarget);
const isSelected = 1 === parseInt($currentItem.val(), 10);
const targetFormName = $currentItem.data('targetFormName');
$(`form[name="${targetFormName}"]`).find(multiStoreRestrictionFieldMap.multiStoreRestrictionCheckbox).each((index, el) => {
const $el = $(el);
$el.prop('checked', isSelected);
this._toggleSourceFieldByTargetElement($el, !isSelected);
});
}
/**
* Changes related form fields state to disabled or enabled.
* It also toggles class disabled since for some fields
* this class is used instead of the native disabled attribute.
*
* @param {jquery} $targetElement
* @param {boolean} isDisabled
* @private
*/
_toggleSourceFieldByTargetElement($targetElement, isDisabled) {
const targetValue = $targetElement.data('shopRestrictionTarget');
const $sourceFieldSelector = $(`[data-shop-restriction-source="${targetValue}"]`);
$sourceFieldSelector.prop('disabled', isDisabled);
$sourceFieldSelector.toggleClass('disabled', isDisabled);
}
}

View File

@@ -0,0 +1,57 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* MultipleChoiceTable is responsible for managing common actions in multiple choice table form type
*/
export default class MultipleChoiceTable {
/**
* Init constructor
*/
constructor() {
$(document).on('click', '.js-multiple-choice-table-select-column', (e) => this.handleSelectColumn(e));
}
/**
* Check/uncheck all boxes in column
*
* @param {Event} event
*/
handleSelectColumn(event) {
event.preventDefault();
const $selectColumnBtn = $(event.target);
const checked = $selectColumnBtn.data('column-checked');
$selectColumnBtn.data('column-checked', !checked);
const $table = $selectColumnBtn.closest('table');
$table
.find('tbody tr td:nth-child(' + $selectColumnBtn.data('column-num') + ') input[type=checkbox]')
.prop('checked', !checked);
}
}

View File

@@ -0,0 +1,105 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
/**
* Class responsible for checking password's validity.
* Can validate entered password's length against min/max values.
* If password confirmation input is provided, can validate if entered password is matching confirmation.
*/
export default class PasswordValidator {
/**
* @param {String} passwordInputSelector selector of the password input.
* @param {String|null} confirmPasswordInputSelector (optional) selector for the password confirmation input.
* @param {Object} options allows overriding default options.
*/
constructor(passwordInputSelector, confirmPasswordInputSelector = null, options = {}) {
this.newPasswordInput = document.querySelector(passwordInputSelector);
this.confirmPasswordInput = document.querySelector(confirmPasswordInputSelector);
// Minimum allowed length for entered password
this.minPasswordLength = options.minPasswordLength || 8;
// Maximum allowed length for entered password
this.maxPasswordLength = options.maxPasswordLength || 255;
}
/**
* Check if the password is valid.
*
* @returns {boolean}
*/
isPasswordValid() {
if (this.confirmPasswordInput && !this.isPasswordMatchingConfirmation()) {
return false;
}
return this.isPasswordLengthValid();
}
/**
* Check if password's length is valid.
*
* @returns {boolean}
*/
isPasswordLengthValid() {
return !this.isPasswordTooShort() && !this.isPasswordTooLong();
}
/**
* Check if password is matching it's confirmation.
*
* @returns {boolean}
*/
isPasswordMatchingConfirmation() {
if (!this.confirmPasswordInput) {
throw 'Confirm password input is not provided for the password validator.';
}
if (this.confirmPasswordInput.value === '') {
return true;
}
return this.newPasswordInput.value === this.confirmPasswordInput.value;
}
/**
* Check if password is too short.
*
* @returns {boolean}
*/
isPasswordTooShort() {
return this.newPasswordInput.value.length < this.minPasswordLength;
}
/**
* Check if password is too long.
*
* @returns {boolean}
*/
isPasswordTooLong() {
return this.newPasswordInput.value.length > this.maxPasswordLength;
}
}

View File

@@ -0,0 +1,59 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class ShowcaseCardCloseExtension is responsible for providing helper block closing behavior
*/
export default class ShowcaseCardCloseExtension {
/**
* Extend helper block.
*
* @param {ShowcaseCard} helperBlock
*/
extend(helperBlock) {
const container = helperBlock.getContainer();
container.on('click', '.js-remove-helper-block', (evt) => {
container.remove();
const $btn = $(evt.target);
const url = $btn.data('closeUrl');
const cardName = $btn.data('cardName');
if (url) {
// notify the card was closed
$.post(
url,
{
close: 1,
name: cardName
}
);
}
});
}
}

View File

@@ -0,0 +1,60 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Class ShowcaseCard is responsible for handling events related with showcase card.
*/
export default class ShowcaseCard {
/**
* Showcase card id.
*
* @param {string} id
*/
constructor(id) {
this.id = id;
this.$container = $('#' + this.id);
}
/**
* Get showcase card container.
*
* @returns {jQuery}
*/
getContainer() {
return this.$container;
}
/**
* Extend showcase card with external extensions.
*
* @param {object} extension
*/
addExtension(extension) {
extension.extend(this);
}
}

View File

@@ -0,0 +1,42 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* class TaggableField is responsible for providing functionality from bootstrap-tokenfield plugin.
* It allows to have taggable fields which are split in separate blocks once you click enter. Values originally saved
* in comma split strings.
*/
export default class TaggableField {
/**
* @param {string} tokenFieldSelector - a selector which is used within jQuery object.
* @param {object} options - extends basic tokenField behavior with additional options such as minLength, delimiter,
* allow to add token on focus out action. See bootstrap-tokenfield docs for more information.
*/
constructor({tokenFieldSelector, options = {}}) {
$(tokenFieldSelector).tokenfield(options);
}
}

View File

@@ -0,0 +1,63 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* Component which allows to copy regular text to url friendly text
*
* Usage example in template:
*
* <input name="source-input" class="js-link-rewrite-copier-source"> // The original text will be taken from this element
* <input name="destination-input" class="js-link-rewrite-copier-destination"> // Modified text will be added to this input
*
* in javascript:
*
* textToLinkRewriteCopier({
* sourceElementSelector: '.js-link-rewrite-copier-source'
* destinationElementSelector: '.js-link-rewrite-copier-destination',
* });
*
* If the source-input has value "test name" the link rewrite value will be "test-name".
* If the source-input has value "test name #$" link rewrite will be "test-name-" since #$ are un allowed characters in url.
*
* You can also pass additional options to change the event name, or encoding format:
*
* textToLinkRewriteCopier({
* sourceElementSelector: '.js-link-rewrite-copier-source'
* destinationElementSelector: '.js-link-rewrite-copier-destination',
* options: {
* eventName: 'change', // default is 'input'
* }
* });
*
*/
const textToLinkRewriteCopier = ({sourceElementSelector, destinationElementSelector, options = {eventName: 'input'}}) => {
$(document).on(options.eventName, `${sourceElementSelector}`, (event) => {
$(destinationElementSelector).val(str2url($(event.currentTarget).val(), 'UTF-8'));
});
};
export default textToLinkRewriteCopier;

View File

@@ -0,0 +1,236 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
const $ = window.$;
/**
* This class init TinyMCE instances in the back-office. It is wildly inspired by
* the scripts from js/admin And it actually loads TinyMCE from the js/tiny_mce
* folder along with its modules. One improvement could be to install TinyMCE via
* npm and fully integrate in the back-office theme.
*/
class TinyMCEEditor {
constructor(options) {
options = options || {};
this.tinyMCELoaded = false;
if (typeof options.baseAdminUrl == 'undefined') {
if (typeof window.baseAdminDir != 'undefined') {
options.baseAdminUrl = window.baseAdminDir;
} else {
const pathParts = window.location.pathname.split('/');
pathParts.every(function(pathPart) {
if (pathPart !== '') {
options.baseAdminUrl = `/${pathPart}/`;
return false;
}
return true;
});
}
}
if (typeof options.langIsRtl == 'undefined') {
options.langIsRtl = typeof window.lang_is_rtl != 'undefined' ? window.lang_is_rtl === '1' : false;
}
this.setupTinyMCE(options);
}
/**
* Initial setup which checks if the tinyMCE library is already loaded.
*
* @param config
*/
setupTinyMCE(config) {
if (typeof tinyMCE === 'undefined') {
this.loadAndInitTinyMCE(config);
} else {
this.initTinyMCE(config);
}
}
/**
* Prepare the config and init all TinyMCE editors
*
* @param config
*/
initTinyMCE(config) {
config = Object.assign({
selector: '.rte',
plugins: 'align colorpicker link image filemanager table media placeholder advlist code table autoresize',
browser_spellcheck: true,
toolbar1: 'code,colorpicker,bold,italic,underline,strikethrough,blockquote,link,align,bullist,numlist,table,image,media,formatselect',
toolbar2: '',
external_filemanager_path: config.baseAdminUrl + 'filemanager/',
filemanager_title: 'File manager',
external_plugins: {
'filemanager': config.baseAdminUrl + 'filemanager/plugin.min.js'
},
language: iso_user,
content_style : (config.langIsRtl ? 'body {direction:rtl;}' : ''),
skin: 'prestashop',
menubar: false,
statusbar: false,
relative_urls: false,
convert_urls: false,
entity_encoding: 'raw',
extended_valid_elements: 'em[class|name|id],@[role|data-*|aria-*]',
valid_children: '+*[*]',
valid_elements: '*[*]',
rel_list:[
{ title: 'nofollow', value: 'nofollow' }
],
editor_selector :'autoload_rte',
init_instance_callback: () => { this.changeToMaterial(); },
setup : (editor) => { this.setupEditor(editor); },
}, config);
if (typeof config.editor_selector != 'undefined') {
config.selector = '.' + config.editor_selector;
}
// Change icons in popups
$('body').on('click', '.mce-btn, .mce-open, .mce-menu-item', () => { this.changeToMaterial(); });
tinyMCE.init(config);
this.watchTabChanges(config);
}
/**
* Setup TinyMCE editor once it has been initialized
*
* @param editor
*/
setupEditor(editor) {
editor.on('loadContent', (event) => {
this.handleCounterTiny(event.target.id);
});
editor.on('change', (event) => {
tinyMCE.triggerSave();
this.handleCounterTiny(event.target.id);
});
editor.on('blur', () => {
tinyMCE.triggerSave();
});
}
/**
* When the editor is inside a tab it can cause a bug on tab switching.
* So we check if the editor is contained in a navigation and refresh the editor when its
* parent tab is shown.
*
* @param config
*/
watchTabChanges(config) {
$(config.selector).each((index, textarea) => {
const translatedField = $(textarea).closest('.translation-field');
const tabContainer = $(textarea).closest('.translations.tabbable');
if (translatedField.length && tabContainer.length) {
const textareaLocale = translatedField.data('locale');
const textareaLinkSelector = '.nav-item a[data-locale="'+textareaLocale+'"]';
$(textareaLinkSelector, tabContainer).on('shown.bs.tab', () => {
const editor = tinyMCE.get(textarea.id);
if (editor) {
//Reset content to force refresh of editor
editor.setContent(editor.getContent());
}
});
}
});
}
/**
* Loads the TinyMCE javascript library and then init the editors
*
* @param config
*/
loadAndInitTinyMCE(config) {
if (this.tinyMCELoaded) {
return;
}
this.tinyMCELoaded = true;
const pathArray = config.baseAdminUrl.split('/');
pathArray.splice((pathArray.length - 2), 2);
const finalPath = pathArray.join('/');
window.tinyMCEPreInit = {};
window.tinyMCEPreInit.base = finalPath+'/js/tiny_mce';
window.tinyMCEPreInit.suffix = '.min';
$.getScript(`${finalPath}/js/tiny_mce/tinymce.min.js`, () => {this.setupTinyMCE(config)});
}
/**
* Replace initial TinyMCE icons with material icons
*/
changeToMaterial() {
let materialIconAssoc = {
'mce-i-code': '<i class="material-icons">code</i>',
'mce-i-none': '<i class="material-icons">format_color_text</i>',
'mce-i-bold': '<i class="material-icons">format_bold</i>',
'mce-i-italic': '<i class="material-icons">format_italic</i>',
'mce-i-underline': '<i class="material-icons">format_underlined</i>',
'mce-i-strikethrough': '<i class="material-icons">format_strikethrough</i>',
'mce-i-blockquote': '<i class="material-icons">format_quote</i>',
'mce-i-link': '<i class="material-icons">link</i>',
'mce-i-alignleft': '<i class="material-icons">format_align_left</i>',
'mce-i-aligncenter': '<i class="material-icons">format_align_center</i>',
'mce-i-alignright': '<i class="material-icons">format_align_right</i>',
'mce-i-alignjustify': '<i class="material-icons">format_align_justify</i>',
'mce-i-bullist': '<i class="material-icons">format_list_bulleted</i>',
'mce-i-numlist': '<i class="material-icons">format_list_numbered</i>',
'mce-i-image': '<i class="material-icons">image</i>',
'mce-i-table': '<i class="material-icons">grid_on</i>',
'mce-i-media': '<i class="material-icons">video_library</i>',
'mce-i-browse': '<i class="material-icons">attachment</i>',
'mce-i-checkbox': '<i class="mce-ico mce-i-checkbox"></i>',
};
$.each(materialIconAssoc, function (index, value) {
$(`.${index}`).replaceWith(value);
});
}
/**
* Updates the characters counter
*
* @param id
*/
handleCounterTiny(id) {
const textarea = $(`#${id}`);
const counter = textarea.attr('counter');
const counterType = textarea.attr('counter_type');
const max = tinyMCE.activeEditor.getBody().textContent.length;
textarea.parent().find('span.currentLength').text(max);
if ('recommended' !== counterType && max > counter) {
textarea.parent().find('span.maxLength').addClass('text-danger');
} else {
textarea.parent().find('span.maxLength').removeClass('text-danger');
}
}
}
export default TinyMCEEditor;

View File

@@ -0,0 +1,73 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import {EventEmitter} from './event-emitter';
const $ = window.$;
/**
* This class is used to automatically toggle translated fields (displayed with tabs
* using the TranslateType Symfony form type).
* Also compatible with TranslatableInput changes.
*/
class TranslatableField {
constructor(options) {
options = options || {};
this.localeButtonSelector = options.localeButtonSelector || '.translationsLocales.nav .nav-item a[data-toggle="tab"]';
this.localeNavigationSelector = options.localeNavigationSelector || '.translationsLocales.nav';
$('body').on('shown.bs.tab', this.localeButtonSelector, this.toggleLanguage.bind(this));
EventEmitter.on('languageSelected', this.toggleFields.bind(this));
}
/**
* Dispatch event on language selection to update inputs and other components which depend on the locale.
*
* @param event
*/
toggleLanguage(event) {
const localeLink = $(event.target);
const form = localeLink.closest('form');
EventEmitter.emit('languageSelected', {selectedLocale: localeLink.data('locale'), form: form});
}
/**
* Toggle all transtation fields to the selected locale
*
* @param event
*/
toggleFields(event) {
$(this.localeNavigationSelector).each((index, navigation) => {
const selectedLink = $('.nav-item a.active', navigation);
const selectedLocale = selectedLink.data('locale');
if (event.selectedLocale !== selectedLocale) {
$('.nav-item a[data-locale="'+event.selectedLocale+'"]', navigation).tab('show');
}
});
}
}
export default TranslatableField;

View File

@@ -0,0 +1,96 @@
/**
* 2007-2019 PrestaShop and Contributors
*
* 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.txt.
* 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://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2019 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
import {EventEmitter} from './event-emitter';
const $ = window.$;
/**
* This class is used to automatically toggle translated inputs (displayed with one
* input and a language selector using the TranslatableType Symfony form type).
* Also compatible with TranslatableField changes.
*/
class TranslatableInput {
constructor(options) {
options = options || {};
this.localeItemSelector = options.localeItemSelector || '.js-locale-item';
this.localeButtonSelector = options.localeButtonSelector || '.js-locale-btn';
this.localeInputSelector = options.localeInputSelector || '.js-locale-input';
$('body').on('click', this.localeItemSelector, this.toggleLanguage.bind(this));
EventEmitter.on('languageSelected', this.toggleInputs.bind(this));
}
/**
* Dispatch event on language selection to update inputs and other components which depend on the locale.
*
* @param event
*/
toggleLanguage(event) {
const localeItem = $(event.target);
const form = localeItem.closest('form');
EventEmitter.emit('languageSelected', {selectedLocale: localeItem.data('locale'), form: form});
}
/**
* Toggle all translatable inputs in form in which locale was changed
*
* @param {Event} event
*/
toggleInputs(event) {
const form = event.form;
const selectedLocale = event.selectedLocale;
const localeButton = form.find(this.localeButtonSelector);
const changeLanguageUrl = localeButton.data('change-language-url');
localeButton.text(selectedLocale);
form.find(this.localeInputSelector).addClass('d-none');
form.find(`${this.localeInputSelector}.js-locale-${selectedLocale}`).removeClass('d-none');
if (changeLanguageUrl) {
this._saveSelectedLanguage(changeLanguageUrl, selectedLocale);
}
}
/**
* Save language choice for employee forms.
*
* @param {String} changeLanguageUrl
* @param {String} selectedLocale
*
* @private
*/
_saveSelectedLanguage(changeLanguageUrl, selectedLocale) {
$.post({
url: changeLanguageUrl,
data: {
language_iso_code: selectedLocale
},
});
}
}
export default TranslatableInput;