contentoh-components-library 21.6.36 → 21.6.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/atoms/InheritanceTag/index.js +6 -2
- package/dist/components/molecules/TagAndInput/index.js +1 -1
- package/dist/components/molecules/TagAndInputv2/index.js +1 -1
- package/dist/components/organisms/PropagateChangesModal/index.js +36 -3
- package/dist/components/pages/RetailerProductEdition/index.js +107 -29
- package/package.json +1 -1
- package/src/components/atoms/InheritanceTag/index.js +12 -2
- package/src/components/molecules/TagAndInput/index.js +3 -1
- package/src/components/molecules/TagAndInputv2/index.js +3 -1
- package/src/components/organisms/PropagateChangesModal/index.js +43 -8
- package/src/components/pages/RetailerProductEdition/index.js +65 -9
|
@@ -16,6 +16,10 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
16
16
|
*
|
|
17
17
|
* El estado "propio" es el que carga información —ese campo se separó del padre—
|
|
18
18
|
* así que es el que lleva acento y el que ofrece la acción de volver a heredar.
|
|
19
|
+
*
|
|
20
|
+
* OJO: "propio" ya NO significa "a salvo de la propagación". Desde el cambio del
|
|
21
|
+
* 2026-09-01 la propagación sobrescribe también estos valores; el aviso de que va
|
|
22
|
+
* a pasar vive en el diálogo de propagación, no aquí. El tooltip lo dice así.
|
|
19
23
|
* "Heredado" es el caso normal y se mantiene discreto: si gritara en cada campo,
|
|
20
24
|
* la ficha entera se volvería ruido.
|
|
21
25
|
*
|
|
@@ -51,9 +55,9 @@ var InheritanceTag = function InheritanceTag(_ref) {
|
|
|
51
55
|
className: "inheritance-tag ".concat(state, " ").concat(className),
|
|
52
56
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
53
57
|
className: "tag-label",
|
|
54
|
-
title: isOverridden ? "Valor
|
|
58
|
+
title: isOverridden ? "Valor capturado en este producto hijo, distinto al del padre. Si el padre propaga este atributo, se reemplaza." : "Valor heredado".concat(parentUpc ? " del producto ".concat(parentUpc) : " del producto padre", "."),
|
|
55
59
|
children: isOverridden ? "Propio" : "Heredado"
|
|
56
|
-
}), isOverridden && onRestore && /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
60
|
+
}), Boolean(isOverridden) && onRestore && /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
57
61
|
type: "button",
|
|
58
62
|
className: "tag-action",
|
|
59
63
|
onClick: onRestore,
|
|
@@ -420,7 +420,7 @@ var TagAndInput = function TagAndInput(_ref) {
|
|
|
420
420
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Container, {
|
|
421
421
|
inputType: inputType,
|
|
422
422
|
className: "input-container",
|
|
423
|
-
children: [(label === null || label === void 0 ? void 0 : label.length) && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
423
|
+
children: [Boolean(label === null || label === void 0 ? void 0 : label.length) && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
424
424
|
className: "title-container",
|
|
425
425
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
426
426
|
className: "titles",
|
|
@@ -54,7 +54,7 @@ var TagAndInputv2 = function TagAndInputv2(_ref) {
|
|
|
54
54
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Container, {
|
|
55
55
|
inputType: inputType,
|
|
56
56
|
className: "input-container",
|
|
57
|
-
children: [(label === null || label === void 0 ? void 0 : label.length) && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
57
|
+
children: [Boolean(label === null || label === void 0 ? void 0 : label.length) && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
58
58
|
className: "title-container",
|
|
59
59
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ScreenHeaderv.ScreenHeaderv2, {
|
|
60
60
|
text: label,
|
|
@@ -9,6 +9,8 @@ exports.PropagateChangesModal = void 0;
|
|
|
9
9
|
|
|
10
10
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/toConsumableArray"));
|
|
11
11
|
|
|
12
|
+
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
|
|
13
|
+
|
|
12
14
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));
|
|
13
15
|
|
|
14
16
|
var _react = require("react");
|
|
@@ -27,7 +29,10 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
27
29
|
|
|
28
30
|
props (* requerido):
|
|
29
31
|
- *changedAttributes: [{ id, name, value }] lo que se acaba de editar
|
|
30
|
-
- *variants: [{ articleId, name, upc }] los hijos
|
|
32
|
+
- *variants: [{ articleId, name, upc, overriddenAttributes }] los hijos
|
|
33
|
+
activos del padre. `overriddenAttributes` son los atributos que ese hijo
|
|
34
|
+
capturó a mano; la propagación los sobrescribe, y este diálogo es el
|
|
35
|
+
único lugar donde el usuario puede enterarse antes de que pase.
|
|
31
36
|
- *onCancel: cerrar sin guardar nada
|
|
32
37
|
- *onConfirm: (propagation | null) => void
|
|
33
38
|
null → guardar solo el padre
|
|
@@ -67,6 +72,31 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
|
|
|
67
72
|
var destinatarios = scope === "all" ? variants.length : chosenChildren.length;
|
|
68
73
|
var puedePropagar = chosenAttributes.length > 0 && destinatarios > 0;
|
|
69
74
|
var enSegundoPlano = destinatarios > UMBRAL_SEGUNDO_PLANO;
|
|
75
|
+
/*
|
|
76
|
+
A quién se le va a pisar un valor capturado a mano.
|
|
77
|
+
La propagación sobrescribe: eso se decidió a propósito, porque el usuario ya
|
|
78
|
+
eligió atributo por atributo y hijo por hijo. Pero sobrescribir en silencio
|
|
79
|
+
es otra cosa, y desde que se quitaron las etiquetas de «Heredado» y «Propio»
|
|
80
|
+
este diálogo es el único momento en que alguien puede saberlo.
|
|
81
|
+
Se recalcula con lo que está marcado ahora, no al abrir: si el usuario
|
|
82
|
+
desmarca el atributo conflictivo, el aviso desaparece — que es justo la
|
|
83
|
+
salida que el aviso debería estar ofreciendo.
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
var destinos = scope === "all" ? variants : variants.filter(function (item) {
|
|
87
|
+
return chosenChildren.includes(item.articleId);
|
|
88
|
+
});
|
|
89
|
+
var conValorPropio = destinos.map(function (hijo) {
|
|
90
|
+
var _hijo$overriddenAttri;
|
|
91
|
+
|
|
92
|
+
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, hijo), {}, {
|
|
93
|
+
pisados: ((_hijo$overriddenAttri = hijo.overriddenAttributes) !== null && _hijo$overriddenAttri !== void 0 ? _hijo$overriddenAttri : []).filter(function (id) {
|
|
94
|
+
return chosenAttributes.includes(Number(id));
|
|
95
|
+
})
|
|
96
|
+
});
|
|
97
|
+
}).filter(function (hijo) {
|
|
98
|
+
return hijo.pisados.length > 0;
|
|
99
|
+
});
|
|
70
100
|
|
|
71
101
|
var toggleAttribute = function toggleAttribute(id) {
|
|
72
102
|
setChosenAttributes(function (current) {
|
|
@@ -173,8 +203,11 @@ var PropagateChangesModal = function PropagateChangesModal(_ref) {
|
|
|
173
203
|
})
|
|
174
204
|
}, variant.articleId);
|
|
175
205
|
})
|
|
176
|
-
}), /*#__PURE__*/(0, _jsxRuntime.
|
|
177
|
-
|
|
206
|
+
}), conValorPropio.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Note, {
|
|
207
|
+
className: "accent",
|
|
208
|
+
children: [conValorPropio.length === 1 ? "Un hijo tiene un valor propio en lo que elegiste y se va a reemplazar: " : "".concat(conValorPropio.length, " hijos tienen valores propios en lo que elegiste y se van a reemplazar: "), conValorPropio.map(function (hijo) {
|
|
209
|
+
return "".concat(hijo.name || "Producto ".concat(hijo.articleId), " (").concat(hijo.pisados.length, ")");
|
|
210
|
+
}).join(", "), ". Si no quieres pisarlos, desmarca ese atributo o ese hijo."]
|
|
178
211
|
}), enSegundoPlano && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Note, {
|
|
179
212
|
className: "accent",
|
|
180
213
|
children: ["Son m\xE1s de ", UMBRAL_SEGUNDO_PLANO, " hijos, as\xED que la propagaci\xF3n corre en segundo plano: el guardado termina antes de que todas est\xE9n actualizadas."]
|
|
@@ -1597,7 +1597,8 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
|
|
|
1597
1597
|
|
|
1598
1598
|
var handleOnClickSave = /*#__PURE__*/function () {
|
|
1599
1599
|
var _ref12 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8() {
|
|
1600
|
-
var
|
|
1600
|
+
var _familia$variants, cambios, familia, hijos;
|
|
1601
|
+
|
|
1601
1602
|
return _regenerator.default.wrap(function _callee8$(_context8) {
|
|
1602
1603
|
while (1) {
|
|
1603
1604
|
switch (_context8.prev = _context8.next) {
|
|
@@ -1611,7 +1612,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
|
|
|
1611
1612
|
|
|
1612
1613
|
case 2:
|
|
1613
1614
|
_context8.t0 = state.active_tab;
|
|
1614
|
-
_context8.next = _context8.t0 === "Descripción" ? 5 : _context8.t0 === "Ficha técnica" ? 8 : _context8.t0 === "Imágenes" ?
|
|
1615
|
+
_context8.next = _context8.t0 === "Descripción" ? 5 : _context8.t0 === "Ficha técnica" ? 8 : _context8.t0 === "Imágenes" ? 32 : 35;
|
|
1615
1616
|
break;
|
|
1616
1617
|
|
|
1617
1618
|
case 5:
|
|
@@ -1619,57 +1620,134 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
|
|
|
1619
1620
|
return saveDescriptions(token);
|
|
1620
1621
|
|
|
1621
1622
|
case 7:
|
|
1622
|
-
return _context8.abrupt("break",
|
|
1623
|
+
return _context8.abrupt("break", 36);
|
|
1623
1624
|
|
|
1624
1625
|
case 8:
|
|
1625
|
-
// Guardar un padre con hijos abre la decisión de propagar. Sin este
|
|
1626
|
-
// paso el cambio se queda solo en el padre y los hijos se van
|
|
1627
|
-
// separando de él sin que nadie lo note.
|
|
1628
|
-
esPadre = hijosDelProducto > 0;
|
|
1629
1626
|
cambios = cambiosDeFichaTecnica();
|
|
1630
1627
|
|
|
1631
|
-
if (!(
|
|
1632
|
-
_context8.next =
|
|
1628
|
+
if (!(cambios.length === 0)) {
|
|
1629
|
+
_context8.next = 13;
|
|
1633
1630
|
break;
|
|
1634
1631
|
}
|
|
1635
1632
|
|
|
1633
|
+
_context8.next = 12;
|
|
1634
|
+
return saveDatasheets(token);
|
|
1635
|
+
|
|
1636
|
+
case 12:
|
|
1637
|
+
return _context8.abrupt("break", 36);
|
|
1638
|
+
|
|
1639
|
+
case 13:
|
|
1640
|
+
/*
|
|
1641
|
+
Guardar un padre con hijos abre la decisión de propagar. Sin este paso
|
|
1642
|
+
el cambio se queda solo en el padre y los hijos se van separando de él
|
|
1643
|
+
sin que nadie lo note.
|
|
1644
|
+
Si tiene hijos se resuelve AQUÍ, esperando la respuesta, en vez de
|
|
1645
|
+
mirar la copia en memoria. `family` es una consulta asíncrona: si
|
|
1646
|
+
todavía no llegó, o si falló, `hijosDelProducto` vale 0 — o sea que
|
|
1647
|
+
«todavía no sé» se leía igual que «no tiene hijos», y el padre se
|
|
1648
|
+
guardaba sin ofrecer la propagación. En silencio, que es lo peor: el
|
|
1649
|
+
usuario creía haber bajado el cambio a los hijos.
|
|
1650
|
+
La ficha de la aplicación de clientes no tiene el problema porque ahí
|
|
1651
|
+
`state.product.variantsCount` viene del listado; aquí el producto sale
|
|
1652
|
+
del endpoint de reportes, que no trae el parentesco.
|
|
1653
|
+
*/
|
|
1636
1654
|
setPreparandoPropagacion(true);
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1655
|
+
familia = null;
|
|
1656
|
+
_context8.prev = 15;
|
|
1657
|
+
_context8.next = 18;
|
|
1658
|
+
return loadFamily(true);
|
|
1659
|
+
|
|
1660
|
+
case 18:
|
|
1661
|
+
familia = _context8.sent;
|
|
1662
|
+
|
|
1663
|
+
case 19:
|
|
1664
|
+
_context8.prev = 19;
|
|
1665
|
+
setPreparandoPropagacion(false);
|
|
1666
|
+
return _context8.finish(19);
|
|
1667
|
+
|
|
1668
|
+
case 22:
|
|
1669
|
+
if (!(!familia || familia.error)) {
|
|
1670
|
+
_context8.next = 25;
|
|
1671
|
+
break;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
dispatch({
|
|
1675
|
+
type: "SET_MODAL",
|
|
1676
|
+
payload: {
|
|
1677
|
+
show: true,
|
|
1678
|
+
title: "No se pudo consultar la familia",
|
|
1679
|
+
message: "No pudimos saber si este producto tiene hijos, así que no sabemos si hay que bajarles el cambio. Vuelve a intentar el guardado; si sigue fallando, guarda y revisa los hijos a mano.",
|
|
1680
|
+
image: _genericModalWarning.default,
|
|
1681
|
+
buttons: [{
|
|
1682
|
+
text: "Entendido",
|
|
1683
|
+
buttonType: "general-white-button",
|
|
1684
|
+
action: function action() {
|
|
1685
|
+
return dispatch({
|
|
1686
|
+
type: "SET_MODAL",
|
|
1687
|
+
payload: {
|
|
1688
|
+
show: false
|
|
1689
|
+
}
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
}, {
|
|
1693
|
+
text: "Guardar solo este producto",
|
|
1694
|
+
buttonType: "general-button-default",
|
|
1695
|
+
action: function action() {
|
|
1696
|
+
dispatch({
|
|
1697
|
+
type: "SET_MODAL",
|
|
1698
|
+
payload: {
|
|
1699
|
+
show: false
|
|
1700
|
+
}
|
|
1701
|
+
});
|
|
1702
|
+
saveDatasheets(token);
|
|
1703
|
+
}
|
|
1704
|
+
}]
|
|
1705
|
+
}
|
|
1643
1706
|
});
|
|
1644
1707
|
return _context8.abrupt("return");
|
|
1645
1708
|
|
|
1646
|
-
case
|
|
1647
|
-
|
|
1709
|
+
case 25:
|
|
1710
|
+
hijos = ((_familia$variants = familia.variants) !== null && _familia$variants !== void 0 ? _familia$variants : []).filter(function (v) {
|
|
1711
|
+
return !v.isCurrent;
|
|
1712
|
+
});
|
|
1713
|
+
|
|
1714
|
+
if (!(hijos.length > 0)) {
|
|
1715
|
+
_context8.next = 29;
|
|
1716
|
+
break;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
setPendingPropagation({
|
|
1720
|
+
cambios: cambios
|
|
1721
|
+
});
|
|
1722
|
+
return _context8.abrupt("return");
|
|
1723
|
+
|
|
1724
|
+
case 29:
|
|
1725
|
+
_context8.next = 31;
|
|
1648
1726
|
return saveDatasheets(token);
|
|
1649
1727
|
|
|
1650
|
-
case
|
|
1651
|
-
return _context8.abrupt("break",
|
|
1728
|
+
case 31:
|
|
1729
|
+
return _context8.abrupt("break", 36);
|
|
1652
1730
|
|
|
1653
|
-
case
|
|
1654
|
-
_context8.next =
|
|
1731
|
+
case 32:
|
|
1732
|
+
_context8.next = 34;
|
|
1655
1733
|
return updateImages(token);
|
|
1656
1734
|
|
|
1657
|
-
case
|
|
1658
|
-
return _context8.abrupt("break",
|
|
1735
|
+
case 34:
|
|
1736
|
+
return _context8.abrupt("break", 36);
|
|
1659
1737
|
|
|
1660
|
-
case
|
|
1661
|
-
return _context8.abrupt("break",
|
|
1738
|
+
case 35:
|
|
1739
|
+
return _context8.abrupt("break", 36);
|
|
1662
1740
|
|
|
1663
|
-
case
|
|
1664
|
-
_context8.next =
|
|
1741
|
+
case 36:
|
|
1742
|
+
_context8.next = 38;
|
|
1665
1743
|
return loadData(false);
|
|
1666
1744
|
|
|
1667
|
-
case
|
|
1745
|
+
case 38:
|
|
1668
1746
|
case "end":
|
|
1669
1747
|
return _context8.stop();
|
|
1670
1748
|
}
|
|
1671
1749
|
}
|
|
1672
|
-
}, _callee8);
|
|
1750
|
+
}, _callee8, null, [[15,, 19, 22]]);
|
|
1673
1751
|
}));
|
|
1674
1752
|
|
|
1675
1753
|
return function handleOnClickSave() {
|
package/package.json
CHANGED
|
@@ -7,6 +7,10 @@ import { Container } from "./styles";
|
|
|
7
7
|
*
|
|
8
8
|
* El estado "propio" es el que carga información —ese campo se separó del padre—
|
|
9
9
|
* así que es el que lleva acento y el que ofrece la acción de volver a heredar.
|
|
10
|
+
*
|
|
11
|
+
* OJO: "propio" ya NO significa "a salvo de la propagación". Desde el cambio del
|
|
12
|
+
* 2026-09-01 la propagación sobrescribe también estos valores; el aviso de que va
|
|
13
|
+
* a pasar vive en el diálogo de propagación, no aquí. El tooltip lo dice así.
|
|
10
14
|
* "Heredado" es el caso normal y se mantiene discreto: si gritara en cada campo,
|
|
11
15
|
* la ficha entera se volvería ruido.
|
|
12
16
|
*
|
|
@@ -41,14 +45,20 @@ export const InheritanceTag = ({
|
|
|
41
45
|
className="tag-label"
|
|
42
46
|
title={
|
|
43
47
|
isOverridden
|
|
44
|
-
? "Valor
|
|
48
|
+
? "Valor capturado en este producto hijo, distinto al del padre. Si el padre propaga este atributo, se reemplaza."
|
|
45
49
|
: `Valor heredado${parentUpc ? ` del producto ${parentUpc}` : " del producto padre"}.`
|
|
46
50
|
}
|
|
47
51
|
>
|
|
48
52
|
{isOverridden ? "Propio" : "Heredado"}
|
|
49
53
|
</span>
|
|
50
54
|
|
|
51
|
-
{
|
|
55
|
+
{/* `Boolean`, no `isOverridden` a secas.
|
|
56
|
+
|
|
57
|
+
`is_overridden` llega como NÚMERO (0/1) desde la API y el reducer. Con
|
|
58
|
+
`{isOverridden && ...}`, un 0 se evalúa a 0 y React IMPRIME el texto
|
|
59
|
+
«0» — ese era el cero que aparecía en el hueco de la acción justo
|
|
60
|
+
después de pulsar «Volver a heredar», que es cuando el valor pasa a 0. */}
|
|
61
|
+
{Boolean(isOverridden) && onRestore && (
|
|
52
62
|
<button type="button" className="tag-action" onClick={onRestore}>
|
|
53
63
|
{restoreLabel}
|
|
54
64
|
</button>
|
|
@@ -321,7 +321,9 @@ export const TagAndInput = ({
|
|
|
321
321
|
className={"input-container"}
|
|
322
322
|
key={`generalTagInput-${inputType}`}
|
|
323
323
|
>
|
|
324
|
-
{label?.length
|
|
324
|
+
{/* `Boolean`, no `label?.length`: con la etiqueta en cadena vacía la
|
|
325
|
+
expresión valía 0 y React imprimía un «0» en la ficha. */}
|
|
326
|
+
{Boolean(label?.length) && (
|
|
325
327
|
<div className="title-container">
|
|
326
328
|
<div className="titles">
|
|
327
329
|
<ScreenHeader
|
|
@@ -46,7 +46,9 @@ export const TagAndInputv2 = ({
|
|
|
46
46
|
className={"input-container"}
|
|
47
47
|
key={`generalTagInput-${inputType}`}
|
|
48
48
|
>
|
|
49
|
-
{label?.length
|
|
49
|
+
{/* `Boolean`, no `label?.length`: con la etiqueta en cadena vacía la
|
|
50
|
+
expresión valía 0 y React imprimía un «0» en la ficha. */}
|
|
51
|
+
{Boolean(label?.length) && (
|
|
50
52
|
<div className="title-container">
|
|
51
53
|
<ScreenHeaderv2
|
|
52
54
|
text={label}
|
|
@@ -21,7 +21,10 @@ import {
|
|
|
21
21
|
|
|
22
22
|
props (* requerido):
|
|
23
23
|
- *changedAttributes: [{ id, name, value }] lo que se acaba de editar
|
|
24
|
-
- *variants: [{ articleId, name, upc }] los hijos
|
|
24
|
+
- *variants: [{ articleId, name, upc, overriddenAttributes }] los hijos
|
|
25
|
+
activos del padre. `overriddenAttributes` son los atributos que ese hijo
|
|
26
|
+
capturó a mano; la propagación los sobrescribe, y este diálogo es el
|
|
27
|
+
único lugar donde el usuario puede enterarse antes de que pase.
|
|
25
28
|
- *onCancel: cerrar sin guardar nada
|
|
26
29
|
- *onConfirm: (propagation | null) => void
|
|
27
30
|
null → guardar solo el padre
|
|
@@ -49,6 +52,31 @@ export const PropagateChangesModal = ({
|
|
|
49
52
|
const puedePropagar = chosenAttributes.length > 0 && destinatarios > 0;
|
|
50
53
|
const enSegundoPlano = destinatarios > UMBRAL_SEGUNDO_PLANO;
|
|
51
54
|
|
|
55
|
+
/*
|
|
56
|
+
A quién se le va a pisar un valor capturado a mano.
|
|
57
|
+
|
|
58
|
+
La propagación sobrescribe: eso se decidió a propósito, porque el usuario ya
|
|
59
|
+
eligió atributo por atributo y hijo por hijo. Pero sobrescribir en silencio
|
|
60
|
+
es otra cosa, y desde que se quitaron las etiquetas de «Heredado» y «Propio»
|
|
61
|
+
este diálogo es el único momento en que alguien puede saberlo.
|
|
62
|
+
|
|
63
|
+
Se recalcula con lo que está marcado ahora, no al abrir: si el usuario
|
|
64
|
+
desmarca el atributo conflictivo, el aviso desaparece — que es justo la
|
|
65
|
+
salida que el aviso debería estar ofreciendo.
|
|
66
|
+
*/
|
|
67
|
+
const destinos = scope === "all"
|
|
68
|
+
? variants
|
|
69
|
+
: variants.filter((item) => chosenChildren.includes(item.articleId));
|
|
70
|
+
|
|
71
|
+
const conValorPropio = destinos
|
|
72
|
+
.map((hijo) => ({
|
|
73
|
+
...hijo,
|
|
74
|
+
pisados: (hijo.overriddenAttributes ?? []).filter((id) =>
|
|
75
|
+
chosenAttributes.includes(Number(id))
|
|
76
|
+
),
|
|
77
|
+
}))
|
|
78
|
+
.filter((hijo) => hijo.pisados.length > 0);
|
|
79
|
+
|
|
52
80
|
const toggleAttribute = (id) => {
|
|
53
81
|
setChosenAttributes((current) =>
|
|
54
82
|
current.includes(id)
|
|
@@ -155,13 +183,20 @@ export const PropagateChangesModal = ({
|
|
|
155
183
|
</List>
|
|
156
184
|
)}
|
|
157
185
|
|
|
158
|
-
{/*
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
186
|
+
{/* Lo que sorprende si no se dice: aquí se pisa lo que el hijo
|
|
187
|
+
hubiera capturado a mano. Se nombra a quién, no solo cuántos: con
|
|
188
|
+
«2 hijos» nadie sabe si le importa, con los nombres sí. */}
|
|
189
|
+
{conValorPropio.length > 0 && (
|
|
190
|
+
<Note className="accent">
|
|
191
|
+
{conValorPropio.length === 1
|
|
192
|
+
? "Un hijo tiene un valor propio en lo que elegiste y se va a reemplazar: "
|
|
193
|
+
: `${conValorPropio.length} hijos tienen valores propios en lo que elegiste y se van a reemplazar: `}
|
|
194
|
+
{conValorPropio
|
|
195
|
+
.map((hijo) => `${hijo.name || `Producto ${hijo.articleId}`} (${hijo.pisados.length})`)
|
|
196
|
+
.join(", ")}
|
|
197
|
+
. Si no quieres pisarlos, desmarca ese atributo o ese hijo.
|
|
198
|
+
</Note>
|
|
199
|
+
)}
|
|
165
200
|
|
|
166
201
|
{enSegundoPlano && (
|
|
167
202
|
<Note className="accent">
|
|
@@ -1131,17 +1131,73 @@ const RetailerProductEditionView = ({
|
|
|
1131
1131
|
await saveDescriptions(token);
|
|
1132
1132
|
break;
|
|
1133
1133
|
case "Ficha técnica": {
|
|
1134
|
-
// Guardar un padre con hijos abre la decisión de propagar. Sin este
|
|
1135
|
-
// paso el cambio se queda solo en el padre y los hijos se van
|
|
1136
|
-
// separando de él sin que nadie lo note.
|
|
1137
|
-
const esPadre = hijosDelProducto > 0;
|
|
1138
1134
|
const cambios = cambiosDeFichaTecnica();
|
|
1139
1135
|
|
|
1140
|
-
if (
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1136
|
+
if (cambios.length === 0) {
|
|
1137
|
+
await saveDatasheets(token);
|
|
1138
|
+
break;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/*
|
|
1142
|
+
Guardar un padre con hijos abre la decisión de propagar. Sin este paso
|
|
1143
|
+
el cambio se queda solo en el padre y los hijos se van separando de él
|
|
1144
|
+
sin que nadie lo note.
|
|
1145
|
+
|
|
1146
|
+
Si tiene hijos se resuelve AQUÍ, esperando la respuesta, en vez de
|
|
1147
|
+
mirar la copia en memoria. `family` es una consulta asíncrona: si
|
|
1148
|
+
todavía no llegó, o si falló, `hijosDelProducto` vale 0 — o sea que
|
|
1149
|
+
«todavía no sé» se leía igual que «no tiene hijos», y el padre se
|
|
1150
|
+
guardaba sin ofrecer la propagación. En silencio, que es lo peor: el
|
|
1151
|
+
usuario creía haber bajado el cambio a los hijos.
|
|
1152
|
+
|
|
1153
|
+
La ficha de la aplicación de clientes no tiene el problema porque ahí
|
|
1154
|
+
`state.product.variantsCount` viene del listado; aquí el producto sale
|
|
1155
|
+
del endpoint de reportes, que no trae el parentesco.
|
|
1156
|
+
*/
|
|
1157
|
+
setPreparandoPropagacion(true);
|
|
1158
|
+
let familia = null;
|
|
1159
|
+
try {
|
|
1160
|
+
familia = await loadFamily(true);
|
|
1161
|
+
} finally {
|
|
1162
|
+
setPreparandoPropagacion(false);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// No se pudo saber si tiene hijos. Guardar de todas formas repetiría el
|
|
1166
|
+
// defecto que se está corrigiendo, así que se dice y se deja la decisión.
|
|
1167
|
+
if (!familia || familia.error) {
|
|
1168
|
+
dispatch({
|
|
1169
|
+
type: "SET_MODAL",
|
|
1170
|
+
payload: {
|
|
1171
|
+
show: true,
|
|
1172
|
+
title: "No se pudo consultar la familia",
|
|
1173
|
+
message:
|
|
1174
|
+
"No pudimos saber si este producto tiene hijos, así que no sabemos si hay que bajarles el cambio. Vuelve a intentar el guardado; si sigue fallando, guarda y revisa los hijos a mano.",
|
|
1175
|
+
image: warningIcon,
|
|
1176
|
+
buttons: [
|
|
1177
|
+
{
|
|
1178
|
+
text: "Entendido",
|
|
1179
|
+
buttonType: "general-white-button",
|
|
1180
|
+
action: () =>
|
|
1181
|
+
dispatch({ type: "SET_MODAL", payload: { show: false } }),
|
|
1182
|
+
},
|
|
1183
|
+
{
|
|
1184
|
+
text: "Guardar solo este producto",
|
|
1185
|
+
buttonType: "general-button-default",
|
|
1186
|
+
action: () => {
|
|
1187
|
+
dispatch({ type: "SET_MODAL", payload: { show: false } });
|
|
1188
|
+
saveDatasheets(token);
|
|
1189
|
+
},
|
|
1190
|
+
},
|
|
1191
|
+
],
|
|
1192
|
+
},
|
|
1193
|
+
});
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
const hijos = (familia.variants ?? []).filter((v) => !v.isCurrent);
|
|
1198
|
+
|
|
1199
|
+
if (hijos.length > 0) {
|
|
1200
|
+
setPendingPropagation({ cambios });
|
|
1145
1201
|
return;
|
|
1146
1202
|
}
|
|
1147
1203
|
|