first commit

This commit is contained in:
2024-11-11 18:46:54 +01:00
commit a630d17338
25634 changed files with 4923715 additions and 0 deletions

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);
});
}
}