odoo.define('point_of_sale.EditListPopup', function(require) { 'use strict'; const { useState } = owl.hooks; const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup'); const Registries = require('point_of_sale.Registries'); const { useAutoFocusToLast } = require('point_of_sale.custom_hooks'); /** * Given a array of { id, text }, we show the user this popup to be able to modify this given array. * (used to replace PackLotLinePopupWidget) * * The expected return of showPopup when this popup is used is an array of { _id, [id], text }. * - _id is the assigned unique identifier for each item. * - id is the original id. if not provided, then it means that the item is new. * - text is the modified/unmodified text. * * Example: * * ``` * -- perhaps inside a click handler -- * // gather the items to edit * const names = [{ id: 1, text: 'Joseph'}, { id: 2, text: 'Kaykay' }]; * * // supply the items to the popup and wait for user's response * // when user pressed `confirm` in the popup, the changes he made will be returned by the showPopup function. * const { confirmed, payload: newNames } = await this.showPopup('EditListPopup', { * title: "Can you confirm this item?", * array: names }) * * // we then consume the new data. In this example, it is only logged. * if (confirmed) { * console.log(newNames); * // the above might log the following: * // [{ _id: 1, id: 1, text: 'Joseph Caburnay' }, { _id: 2, id: 2, 'Kaykay' }, { _id: 3, 'James' }] * // The result showed that the original item with id=1 was changed to have text 'Joseph Caburnay' from 'Joseph' * // The one with id=2 did not change. And a new item with text='James' is added. * } * ``` */ class EditListPopup extends AbstractAwaitablePopup { /** * @param {String} title required title of popup * @param {Array} [props.array=[]] the array of { id, text } to be edited or an array of strings * @param {Boolean} [props.isSingleItem=false] true if only allowed to edit single item (the first item) */ constructor() { super(...arguments); this._id = 0; this.state = useState({ array: this._initialize(this.props.array) }); useAutoFocusToLast(); } _nextId() { return this._id++; } _emptyItem() { return { text: '', _id: this._nextId(), }; } _initialize(array) { // If no array is provided, we initialize with one empty item. if (array.length === 0) return [this._emptyItem()]; // Put _id for each item. It will serve as unique identifier of each item. return array.map((item) => Object.assign({}, { _id: this._nextId() }, typeof item === 'object'? item: { 'text': item})); } removeItem(event) { const itemToRemove = event.detail; this.state.array.splice( this.state.array.findIndex(item => item._id == itemToRemove._id), 1 ); // We keep a minimum of one empty item in the popup. if (this.state.array.length === 0) { this.state.array.push(this._emptyItem()); } } createNewItem() { if (this.props.isSingleItem) return; this.state.array.push(this._emptyItem()); } /** * @override */ getPayload() { return { newArray: this.state.array .filter((item) => item.text.trim() !== '') .map((item) => Object.assign({}, item)), }; } } EditListPopup.template = 'EditListPopup'; EditListPopup.defaultProps = { confirmText: 'Ok', cancelText: 'Cancel', array: [], isSingleItem: false, }; Registries.Component.add(EditListPopup); return EditListPopup; });