/** * Copyright since 2007 PrestaShop SA and Contributors * PrestaShop is an International Registered Trademark & Property of PrestaShop SA * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 3.0) * that is bundled with this package in the file LICENSE.md. * It is also available through the world-wide-web at this URL: * https://opensource.org/licenses/OSL-3.0 * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@prestashop.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to https://devdocs.prestashop.com/ for more information. * * @author PrestaShop SA and Contributors * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ import PaginatedCatalogPriceRulesService from '@pages/product/service/paginated-catalog-price-rules-service'; import CatalogPriceRuleRenderer from '@pages/product/catalog-price-rule/catalog-price-rule-renderer'; import {FormIframeModal} from '@components/modal'; import ProductMap from '@pages/product/product-map'; import ProductEventMap from '@pages/product/product-event-map'; import {EventEmitter} from 'events'; import SpecificPriceListRenderer from '@pages/product/specific-price/specific-price-list-renderer'; import Router from '@components/router'; import FormFieldToggler from '@components/form/form-field-toggler'; import {isUndefined} from '@PSTypes/typeguard'; import PaginatedSpecificPricesService from '@pages/product/service/paginated-specific-prices-service'; import DynamicPaginator from '@components/pagination/dynamic-paginator'; import ClickEvent = JQuery.ClickEvent; const SpecificPriceMap = ProductMap.specificPrice; const CatalogPriceRulesMap = ProductMap.catalogPriceRule; const PriorityMap = SpecificPriceMap.priority; export default class SpecificPricesManager { eventEmitter: EventEmitter; productId: number; listContainer: HTMLElement; router: Router; paginator!: DynamicPaginator; constructor( productId: number, ) { this.router = new Router(); this.productId = productId; this.eventEmitter = window.prestashop.instance.eventEmitter; this.listContainer = document.querySelector(SpecificPriceMap.listContainer)!; this.initComponents(); this.initListeners(); } private initListeners(): void { this.eventEmitter.on(ProductEventMap.specificPrice.listUpdated, () => { this.paginator.paginate(1); }); } private initComponents() { this.paginator = new DynamicPaginator( SpecificPriceMap.paginationContainer, new PaginatedSpecificPricesService(this.productId), new SpecificPriceListRenderer(this.productId), 1, ); this.initSpecificPriceModals(); this.initCatalogPriceRules(); // Enable/disable the priority selectors depending on the priority type selected (global or custom) new FormFieldToggler({ disablingInputSelector: PriorityMap.priorityTypeCheckboxesSelector, matchingValue: '0', targetSelector: PriorityMap.priorityListWrapper, }); } private initCatalogPriceRules() { const priceRuleRenderer = new CatalogPriceRuleRenderer(); const catalogPriceRulePaginator = new DynamicPaginator( CatalogPriceRulesMap.paginationContainer, new PaginatedCatalogPriceRulesService(this.productId), priceRuleRenderer, 1, ); const showCatalogPriceRulesButton = document.querySelector(CatalogPriceRulesMap.showCatalogPriceRules); const catalogPriceRulesContainer = document.querySelector(CatalogPriceRulesMap.blockContainer); if (showCatalogPriceRulesButton === null) { console.error(`Error: ${CatalogPriceRulesMap.showCatalogPriceRules} element not found`); return; } if (catalogPriceRulesContainer === null) { console.error(`Error: ${CatalogPriceRulesMap.blockContainer} element not found`); return; } const showLabel = showCatalogPriceRulesButton.dataset.showLabel ?? 'Show catalog price rules'; const hideLabel = showCatalogPriceRulesButton.dataset.hideLabel ?? 'Hide catalog price rules'; /** This should be the form container for the whole form element, so we can hide the whole block */ const formContainer = catalogPriceRulesContainer.parentNode; if (formContainer === null) { console.error(`Error: ${CatalogPriceRulesMap.blockContainer} parent element not found`); return; } showCatalogPriceRulesButton.addEventListener('click', () => { formContainer.classList.toggle('d-none'); const listShown = formContainer.classList.contains('d-none'); if (!listShown) { showCatalogPriceRulesButton.innerHTML = `visibility_off ${hideLabel}`; /** Rendering everytime in case catalog price rule was deleted while somebody was in product edit page */ catalogPriceRulePaginator.paginate(1); } else { showCatalogPriceRulesButton.innerHTML = `visibility ${showLabel}`; } }); } private initSpecificPriceModals() { // Delegate listener for each edit buttons in the list (even future added ones) $(this.listContainer).on('click', SpecificPriceMap.listFields.editBtn, (event: ClickEvent) => { if (!(event.currentTarget instanceof HTMLElement)) { return; } const editButton = event.currentTarget; const {specificPriceId} = editButton.dataset; if (isUndefined(specificPriceId)) { return; } const url = this.router.generate( 'admin_products_specific_prices_edit', { specificPriceId, liteDisplaying: 1, }, ); this.renderSpecificPriceModal( url, editButton.dataset.modalTitle || 'Edit specific price', editButton.dataset.confirmButtonLabel || 'Save and publish', editButton.dataset.cancelButtonLabel || 'Cancel', ); }); // Creation modal on single add button const addButton = document.querySelector(SpecificPriceMap.addSpecificPriceBtn); if (addButton === null) { return; } addButton.addEventListener('click', (e) => { e.stopImmediatePropagation(); const url = this.router.generate( 'admin_products_specific_prices_create', { productId: this.productId, liteDisplaying: 1, }, ); this.renderSpecificPriceModal( url, addButton.dataset.modalTitle || 'Add new specific price', addButton.dataset.confirmButtonLabel || 'Save and publish', addButton.dataset.cancelButtonLabel || 'Cancel', ); }); } private renderSpecificPriceModal( formUrl: string, modalTitle: string, confirmButtonLabel: string, closeButtonLabel: string, ) { const iframeModal = new FormIframeModal({ id: 'modal-specific-price-form', formSelector: 'form[name="specific_price"]', formUrl, closable: true, modalTitle, closeButtonLabel, confirmButtonLabel, closeOnConfirm: false, onFormLoaded: (form: HTMLFormElement, formData: FormData, dataAttributes: DOMStringMap | null): void => { if (dataAttributes && dataAttributes.alertsSuccess === '1') { this.eventEmitter.emit(ProductEventMap.specificPrice.listUpdated); } }, formConfirmCallback: (form: HTMLFormElement): void => { form.submit(); }, }); iframeModal.show(); } }