contentoh-components-library 21.6.55 → 21.6.56

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.
Files changed (82) hide show
  1. package/.claude/launch.json +14 -0
  2. package/.env.test +1 -0
  3. package/dist/ai/prompts/attribute.prompt.js +28 -0
  4. package/dist/ai/prompts/description.prompt.js +33 -0
  5. package/dist/ai/schemas/attribute.schema.js +35 -0
  6. package/dist/ai/schemas/description.schema.js +27 -0
  7. package/dist/components/atoms/AssetPreview/AssetPreview.stories.js +118 -0
  8. package/dist/components/atoms/AssetPreview/index.js +150 -0
  9. package/dist/components/atoms/AssetPreview/styles.js +28 -0
  10. package/dist/components/atoms/IconFile/index.js +85 -2
  11. package/dist/components/atoms/IconFile/styles.js +1 -1
  12. package/dist/components/atoms/ProductImage/ProductImage.stories.js +70 -2
  13. package/dist/components/atoms/ProductImage/index.js +100 -27
  14. package/dist/components/atoms/ProductImage/styles.js +3 -1
  15. package/dist/components/molecules/EditionActiveImage/index.js +4 -2
  16. package/dist/components/molecules/GalleryAssetElement/GalleryAssetElement.stories.js +147 -0
  17. package/dist/components/molecules/GalleryAssetElement/index.js +178 -0
  18. package/dist/components/molecules/GalleryAssetElement/styles.js +26 -0
  19. package/dist/components/molecules/GalleryElement/index.js +13 -4
  20. package/dist/components/molecules/GalleryHeader/index.js +96 -24
  21. package/dist/components/molecules/GalleryHeader/styles.js +4 -1
  22. package/dist/components/molecules/GalleryTrayTabs/GalleryTrayTabs.stories.js +56 -0
  23. package/dist/components/molecules/GalleryTrayTabs/index.js +60 -0
  24. package/dist/components/molecules/GalleryTrayTabs/styles.js +20 -0
  25. package/dist/components/molecules/ImageSelector/index.js +1 -0
  26. package/dist/components/organisms/DigitalAssetsTray/DigitalAssetsTray.stories.js +171 -0
  27. package/dist/components/organisms/DigitalAssetsTray/index.js +211 -0
  28. package/dist/components/organisms/DigitalAssetsTray/styles.js +22 -0
  29. package/dist/components/organisms/ImagePreviewer/index.js +1 -0
  30. package/dist/components/organisms/ProductImageModal/index.js +3 -2
  31. package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +330 -15
  32. package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +12 -2
  33. package/dist/components/pages/RetailerProductEdition/index.js +606 -425
  34. package/dist/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +1 -0
  35. package/dist/global-files/data.js +16 -3
  36. package/dist/global-files/digital-assets/assetTypes.js +480 -0
  37. package/dist/global-files/digital-assets/assets.actions.js +64 -0
  38. package/dist/global-files/digital-assets/assets.adapter.js +304 -0
  39. package/dist/global-files/digital-assets/assets.mock.js +136 -0
  40. package/dist/global-files/digital-assets/assets.reducer.js +220 -0
  41. package/dist/global-files/digital-assets/uploadAssets.js +179 -0
  42. package/dist/global-files/digital-assets/useDigitalAssets.js +522 -0
  43. package/dist/index.js +142 -90
  44. package/docs/activos-digitales.md +273 -0
  45. package/package.json +1 -1
  46. package/src/components/atoms/AssetPreview/AssetPreview.stories.js +78 -0
  47. package/src/components/atoms/AssetPreview/index.js +119 -0
  48. package/src/components/atoms/AssetPreview/styles.js +190 -0
  49. package/src/components/atoms/IconFile/index.js +28 -1
  50. package/src/components/atoms/IconFile/styles.js +8 -0
  51. package/src/components/atoms/ProductImage/ProductImage.stories.js +38 -0
  52. package/src/components/atoms/ProductImage/index.js +95 -20
  53. package/src/components/atoms/ProductImage/styles.js +92 -7
  54. package/src/components/molecules/EditionActiveImage/index.js +2 -2
  55. package/src/components/molecules/GalleryAssetElement/GalleryAssetElement.stories.js +102 -0
  56. package/src/components/molecules/GalleryAssetElement/index.js +162 -0
  57. package/src/components/molecules/GalleryAssetElement/styles.js +159 -0
  58. package/src/components/molecules/GalleryElement/index.js +9 -0
  59. package/src/components/molecules/GalleryHeader/index.js +65 -13
  60. package/src/components/molecules/GalleryHeader/styles.js +2 -1
  61. package/src/components/molecules/GalleryTrayTabs/GalleryTrayTabs.stories.js +32 -0
  62. package/src/components/molecules/GalleryTrayTabs/index.js +41 -0
  63. package/src/components/molecules/GalleryTrayTabs/styles.js +52 -0
  64. package/src/components/molecules/ImageSelector/index.js +1 -0
  65. package/src/components/organisms/DigitalAssetsTray/DigitalAssetsTray.stories.js +101 -0
  66. package/src/components/organisms/DigitalAssetsTray/index.js +189 -0
  67. package/src/components/organisms/DigitalAssetsTray/styles.js +183 -0
  68. package/src/components/organisms/ImagePreviewer/index.js +1 -0
  69. package/src/components/organisms/ProductImageModal/index.js +1 -0
  70. package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +201 -0
  71. package/src/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +12 -0
  72. package/src/components/pages/RetailerProductEdition/index.js +356 -139
  73. package/src/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +1 -0
  74. package/src/global-files/data.js +17 -2
  75. package/src/global-files/digital-assets/assetTypes.js +419 -0
  76. package/src/global-files/digital-assets/assets.actions.js +50 -0
  77. package/src/global-files/digital-assets/assets.adapter.js +229 -0
  78. package/src/global-files/digital-assets/assets.mock.js +122 -0
  79. package/src/global-files/digital-assets/assets.reducer.js +197 -0
  80. package/src/global-files/digital-assets/uploadAssets.js +109 -0
  81. package/src/global-files/digital-assets/useDigitalAssets.js +329 -0
  82. package/src/index.js +4 -0
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.DigitalAssetsTray = void 0;
9
+
10
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectSpread2"));
11
+
12
+ var _reactDropzone = require("react-dropzone");
13
+
14
+ var _styles = require("./styles");
15
+
16
+ var _GalleryAssetElement = require("../../molecules/GalleryAssetElement");
17
+
18
+ var _GalleryHeader = require("../../molecules/GalleryHeader");
19
+
20
+ var _ButtonV = require("../../atoms/ButtonV2");
21
+
22
+ var _assetTypes = require("../../../global-files/digital-assets/assetTypes");
23
+
24
+ var _jsxRuntime = require("react/jsx-runtime");
25
+
26
+ var CHECK_ALL_ID = "check-all-assets";
27
+ var ITEM_SELECTOR = "[id^='gallery-asset-']";
28
+ /**
29
+ * Bandeja de activos digitales: soltar archivos, verlos, reetiquetarlos y
30
+ * quitarlos.
31
+ *
32
+ * Tiene su propio dropzone en vez de compartir el de las imágenes porque los
33
+ * formatos aceptados son distintos: mezclarlos dejaría soltar un PDF sobre la
34
+ * bandeja de fotos y un JPG sobre la de activos.
35
+ *
36
+ * No guarda ni sube nada. Recibe el estado ya armado por `useDigitalAssets`,
37
+ * así que cuando se defina el contrato del backend solo hay que conectarle las
38
+ * llamadas; la interfaz no cambia.
39
+ */
40
+
41
+ var DigitalAssetsTray = function DigitalAssetsTray(_ref) {
42
+ var _ref$assets = _ref.assets,
43
+ assets = _ref$assets === void 0 ? [] : _ref$assets,
44
+ _ref$notices = _ref.notices,
45
+ notices = _ref$notices === void 0 ? [] : _ref$notices,
46
+ _ref$unsaved = _ref.unsaved,
47
+ unsaved = _ref$unsaved === void 0 ? {
48
+ nuevos: 0,
49
+ modificados: 0,
50
+ borrados: 0,
51
+ total: 0
52
+ } : _ref$unsaved,
53
+ _ref$remaining = _ref.remaining,
54
+ remaining = _ref$remaining === void 0 ? _assetTypes.MAX_ASSETS_PER_PRODUCT : _ref$remaining,
55
+ addFiles = _ref.addFiles,
56
+ removeAsset = _ref.removeAsset,
57
+ changeAssetType = _ref.changeAssetType,
58
+ clearNotices = _ref.clearNotices,
59
+ _ref$selectedAssets = _ref.selectedAssets,
60
+ selectedAssets = _ref$selectedAssets === void 0 ? [] : _ref$selectedAssets,
61
+ setSelectedAssets = _ref.setSelectedAssets,
62
+ setCheckAll = _ref.setCheckAll,
63
+ _ref$gridLayout = _ref.gridLayout,
64
+ gridLayout = _ref$gridLayout === void 0 ? false : _ref$gridLayout,
65
+ _ref$readOnly = _ref.readOnly,
66
+ readOnly = _ref$readOnly === void 0 ? false : _ref$readOnly,
67
+ _ref$emptyMessage = _ref.emptyMessage,
68
+ emptyMessage = _ref$emptyMessage === void 0 ? "Este producto no tiene activos digitales" : _ref$emptyMessage;
69
+
70
+ var _useDropzone = (0, _reactDropzone.useDropzone)({
71
+ accept: (0, _assetTypes.buildDropzoneAccept)(),
72
+ noKeyboard: true,
73
+ multiple: true,
74
+ noClick: true,
75
+ disabled: readOnly,
76
+ onDrop: function onDrop(acceptedFiles) {
77
+ return addFiles === null || addFiles === void 0 ? void 0 : addFiles(acceptedFiles);
78
+ }
79
+ }),
80
+ getRootProps = _useDropzone.getRootProps,
81
+ getInputProps = _useDropzone.getInputProps,
82
+ isDragActive = _useDropzone.isDragActive,
83
+ open = _useDropzone.open;
84
+
85
+ var noticesBy = function noticesBy(level) {
86
+ return notices.filter(function (item) {
87
+ return item.level === level;
88
+ });
89
+ };
90
+ /*
91
+ Se desglosa en vez de mostrar solo el número: "3 cambios sin guardar" no le
92
+ dice al usuario qué perdería si se va, y no es lo mismo dejar sin guardar un
93
+ borrado que un archivo nuevo.
94
+ */
95
+
96
+
97
+ var detalleSinGuardar = [unsaved.nuevos && "".concat(unsaved.nuevos, " nuevo").concat(unsaved.nuevos > 1 ? "s" : ""), unsaved.modificados && "".concat(unsaved.modificados, " modificado").concat(unsaved.modificados > 1 ? "s" : ""), unsaved.borrados && "".concat(unsaved.borrados, " por borrar")].filter(Boolean).join(" · ");
98
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_styles.Container, {
99
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
100
+ className: "tray-toolbar",
101
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
102
+ className: "tray-hint",
103
+ title: "Formatos permitidos: ".concat((0, _assetTypes.acceptedFormatsLabel)()),
104
+ children: ["Arrastra aqu\xED videos, 360, GIF, documentos, hojas de c\xE1lculo o archivos editables. Quedan ", remaining, " de ", _assetTypes.MAX_ASSETS_PER_PRODUCT, "."]
105
+ }), !readOnly && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ButtonV.ButtonV2, {
106
+ label: "Agregar activos",
107
+ type: "pink",
108
+ size: 12,
109
+ onClick: open
110
+ })]
111
+ }), unsaved.total > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
112
+ className: "tray-unsaved",
113
+ role: "status",
114
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
115
+ className: "tray-unsaved-dot"
116
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
117
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("strong", {
118
+ children: [unsaved.total, " cambio", unsaved.total > 1 ? "s" : "", " sin guardar"]
119
+ }), detalleSinGuardar && /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
120
+ className: "tray-unsaved-detail",
121
+ children: [" \u2014 ", detalleSinGuardar]
122
+ })]
123
+ })]
124
+ }), noticesBy("error").length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
125
+ className: "tray-notice tray-notice-error",
126
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
127
+ className: "tray-notice-head",
128
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("p", {
129
+ children: ["No se pudieron agregar ", noticesBy("error").length, " archivo(s):"]
130
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
131
+ type: "button",
132
+ onClick: clearNotices,
133
+ title: "Cerrar",
134
+ children: "\xD7"
135
+ })]
136
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
137
+ children: noticesBy("error").map(function (item, index) {
138
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
139
+ children: item.message
140
+ }, "err-".concat(item.name, "-").concat(index));
141
+ })
142
+ })]
143
+ }), noticesBy("warning").length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
144
+ className: "tray-notice tray-notice-warning",
145
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
146
+ className: "tray-notice-head",
147
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
148
+ children: "Se agregaron, pero ten en cuenta:"
149
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
150
+ type: "button",
151
+ onClick: clearNotices,
152
+ title: "Cerrar",
153
+ children: "\xD7"
154
+ })]
155
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
156
+ children: noticesBy("warning").map(function (item, index) {
157
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
158
+ children: item.message
159
+ }, "warn-".concat(item.name, "-").concat(index));
160
+ })
161
+ })]
162
+ }), !gridLayout && assets.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_GalleryHeader.GalleryHeader, {
163
+ variant: "asset",
164
+ checkAllId: CHECK_ALL_ID,
165
+ itemSelector: ITEM_SELECTOR,
166
+ setCheckAll: setCheckAll,
167
+ setSelectedImages: setSelectedAssets
168
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", (0, _objectSpread2.default)((0, _objectSpread2.default)({}, getRootProps({
169
+ className: "dropzone ".concat(isDragActive ? "drag-active" : "").trim()
170
+ })), {}, {
171
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("input", (0, _objectSpread2.default)({}, getInputProps())), isDragActive && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
172
+ className: "drag-overlay",
173
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
174
+ children: "Suelta los activos aqu\xED"
175
+ })
176
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("aside", {
177
+ className: gridLayout ? "tray-grid" : "tray-rows",
178
+ children: assets.map(function (asset, index) {
179
+ var _asset$id;
180
+
181
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_GalleryAssetElement.GalleryAssetElement, {
182
+ asset: asset,
183
+ index: index,
184
+ gridLayout: gridLayout,
185
+ checkAllId: CHECK_ALL_ID,
186
+ itemSelector: ITEM_SELECTOR,
187
+ selectedAssets: selectedAssets,
188
+ setSelectedAssets: setSelectedAssets,
189
+ setCheckAll: setCheckAll,
190
+ changeAsset: function changeAsset(_ref2) {
191
+ var value = _ref2.value;
192
+ return changeAssetType === null || changeAssetType === void 0 ? void 0 : changeAssetType(index, value);
193
+ },
194
+ onRemove: removeAsset,
195
+ readOnly: readOnly
196
+ }, (_asset$id = asset.id) !== null && _asset$id !== void 0 ? _asset$id : asset.tempId);
197
+ })
198
+ }), assets.length === 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
199
+ className: "tray-empty",
200
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
201
+ children: emptyMessage
202
+ }), !readOnly && /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
203
+ className: "tray-empty-hint",
204
+ children: "Arr\xE1stralos aqu\xED o usa \xABAgregar activos\xBB."
205
+ })]
206
+ })]
207
+ }))]
208
+ });
209
+ };
210
+
211
+ exports.DigitalAssetsTray = DigitalAssetsTray;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.Container = void 0;
9
+
10
+ var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/taggedTemplateLiteral"));
11
+
12
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
13
+
14
+ var _variables = require("../../../global-files/variables");
15
+
16
+ var _templateObject;
17
+
18
+ /* El dropzone replica el de la bandeja de imágenes para que arrastrar se sienta
19
+ igual en las dos. */
20
+ var Container = _styledComponents.default.div(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: 8px;\n\n .tray-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n }\n\n .tray-hint {\n margin: 0;\n font-family: ", ";\n font-size: 12px;\n line-height: 18px;\n color: ", ";\n }\n\n /*\n Aviso de cambios sin guardar. Va arriba del listado y no junto al bot\xF3n de\n guardar, que vive en otra barra: el usuario mira la bandeja, no el men\xFA.\n */\n .tray-unsaved {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border-radius: 6px;\n border: 1px solid ", ";\n background: rgba(237, 154, 77, 0.08);\n\n p {\n margin: 0;\n font-family: ", ";\n font-size: 12px;\n line-height: 18px;\n color: ", ";\n }\n\n strong {\n font-family: ", ";\n color: ", ";\n }\n }\n\n .tray-unsaved-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: ", ";\n flex-shrink: 0;\n }\n\n .tray-unsaved-detail {\n color: ", ";\n }\n\n .tray-notice {\n border-radius: 6px;\n padding: 8px 12px;\n border: 1px solid;\n\n .tray-notice-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n p {\n margin: 0;\n font-family: ", ";\n font-size: 12px;\n }\n\n button {\n border: none;\n background: none;\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n color: inherit;\n }\n }\n\n ul {\n margin: 4px 0 0;\n padding-left: 18px;\n }\n\n li {\n font-family: ", ";\n font-size: 12px;\n line-height: 18px;\n color: ", ";\n }\n }\n\n /* Rojo = no entr\xF3. \xC1mbar = entr\xF3, pero hay algo que saber. */\n .tray-notice-error {\n border-color: ", ";\n background: rgba(", ", 0.05);\n color: ", ";\n }\n\n .tray-notice-warning {\n border-color: ", ";\n background: rgba(237, 154, 77, 0.08);\n color: ", ";\n }\n\n .dropzone {\n position: relative;\n width: 100%;\n min-height: 160px;\n transition: all 0.5s ease;\n\n &.drag-active {\n background-color: rgba(", ", 0.05);\n border: 2px dashed ", ";\n border-radius: 8px;\n\n aside {\n opacity: 0.3;\n pointer-events: none;\n }\n }\n\n .drag-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1;\n\n p {\n font-family: ", ";\n font-size: 16px;\n color: ", ";\n }\n }\n }\n\n .tray-rows {\n display: flex;\n flex-direction: column;\n }\n\n .tray-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .tray-empty {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n width: 80%;\n\n p {\n margin: 0;\n font-family: ", ";\n font-size: 16px;\n color: ", ";\n }\n\n .tray-empty-hint {\n margin-top: 6px;\n font-size: 13px;\n color: ", ";\n }\n }\n"])), _variables.FontFamily.Lato, _variables.GlobalColors.s4, _variables.GlobalColors.in_progress, _variables.FontFamily.Lato, _variables.GlobalColors.s5, _variables.FontFamily.Raleway_600, _variables.GlobalColors.in_progress, _variables.GlobalColors.in_progress, _variables.GlobalColors.s4, _variables.FontFamily.Raleway_600, _variables.FontFamily.Lato, _variables.GlobalColors.s5, _variables.GlobalColors.secondary_magenta, _variables.GlobalColors.rgb_color_pink, _variables.GlobalColors.secondary_magenta, _variables.GlobalColors.in_progress, _variables.GlobalColors.in_progress, _variables.GlobalColors.rgb_color_pink, _variables.GlobalColors.color_pink, _variables.FontFamily.AvenirNext, _variables.GlobalColors.color_pink, _variables.FontFamily.Lato, _variables.GlobalColors.gray, _variables.GlobalColors.s4);
21
+
22
+ exports.Container = Container;
@@ -23,6 +23,7 @@ var ImagePreviewer = function ImagePreviewer(_ref) {
23
23
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_EditionActiveImage.EditionActiveImage, {
24
24
  img: activeImage === null || activeImage === void 0 ? void 0 : activeImage.src,
25
25
  altText: activeImage === null || activeImage === void 0 ? void 0 : activeImage.name,
26
+ ext: activeImage === null || activeImage === void 0 ? void 0 : activeImage.ext,
26
27
  setShowModal: setShowModal
27
28
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ImageSelector.ImageSelector, {
28
29
  images: imagesArray,
@@ -26,7 +26,7 @@ var _GeneralButton = require("../../atoms/GeneralButton");
26
26
  var _jsxRuntime = require("react/jsx-runtime");
27
27
 
28
28
  var ProductImageModal = function ProductImageModal(_ref) {
29
- var _images$values$active, _images$values$active2, _images$values$active3;
29
+ var _images$values$active, _images$values$active2, _images$values$active3, _images$values$active4;
30
30
 
31
31
  var _ref$images = _ref.images,
32
32
  images = _ref$images === void 0 ? [] : _ref$images,
@@ -72,6 +72,7 @@ var ProductImageModal = function ProductImageModal(_ref) {
72
72
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ProductImage.ProductImage, {
73
73
  img: "https://" + process.env.REACT_APP_IMAGES_BUCKET + ".s3.amazonaws.com/" + (images === null || images === void 0 ? void 0 : (_images$values$active = images.values[activeImage]) === null || _images$values$active === void 0 ? void 0 : _images$values$active.srcDB),
74
74
  altText: images === null || images === void 0 ? void 0 : (_images$values$active2 = images.values[activeImage]) === null || _images$values$active2 === void 0 ? void 0 : _images$values$active2.name,
75
+ ext: images === null || images === void 0 ? void 0 : (_images$values$active3 = images.values[activeImage]) === null || _images$values$active3 === void 0 ? void 0 : _images$values$active3.ext,
75
76
  imageType: "expanded-modal-image"
76
77
  })
77
78
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
@@ -102,7 +103,7 @@ var ProductImageModal = function ProductImageModal(_ref) {
102
103
  }
103
104
  })]
104
105
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ImageDataTable.ImageDataTable, {
105
- imageData: images === null || images === void 0 ? void 0 : (_images$values$active3 = images.values[activeImage]) === null || _images$values$active3 === void 0 ? void 0 : _images$values$active3.data,
106
+ imageData: images === null || images === void 0 ? void 0 : (_images$values$active4 = images.values[activeImage]) === null || _images$values$active4 === void 0 ? void 0 : _images$values$active4.data,
106
107
  headerInfo: headerInfo,
107
108
  activeImage: images === null || images === void 0 ? void 0 : images.values[activeImage],
108
109
  darkMode: true,
@@ -37,6 +37,10 @@ var _genericModalWarning = _interopRequireDefault(require("../../../../assets/im
37
37
 
38
38
  var _utils = require("../utils");
39
39
 
40
+ var _assets = require("../../../../global-files/digital-assets/assets.adapter");
41
+
42
+ var _assets2 = require("../../../../global-files/digital-assets/assets.reducer");
43
+
40
44
  var _jsxRuntime = require("react/jsx-runtime");
41
45
 
42
46
  var _excluded = ["src", "video_src"],
@@ -763,26 +767,335 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
763
767
  return _ref8.apply(this, arguments);
764
768
  };
765
769
  }();
770
+ /*
771
+ Registra en la base los activos que ACABAN de subirse, sin esperar a que el
772
+ usuario guarde.
773
+ Es una corrección de expectativa, no una comodidad: al ver la barra de
774
+ progreso llegar al final, cualquiera da por hecho que el activo ya quedó
775
+ ligado al producto. Si entonces cierra la ficha, el archivo se queda en S3
776
+ sin fila en la base —invisible y sin forma de recuperarlo desde la
777
+ pantalla—.
778
+ Manda SOLO las altas recién subidas, con `updateAssets` y `deleteAssets`
779
+ vacíos. Un reetiquetado o un borrado que el usuario todavía no confirmó no
780
+ se aplica por haber soltado otro archivo: el botón de guardar sigue siendo
781
+ quien decide sobre esos.
782
+ */
766
783
 
767
- var createComment = /*#__PURE__*/function () {
768
- var _ref9 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(body, token) {
784
+
785
+ var registerUploadedAssets = /*#__PURE__*/function () {
786
+ var _ref9 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(token) {
769
787
  var _state$product19, _state$product20, _state$product21;
770
788
 
771
- var concept, data;
789
+ var uploaded,
790
+ listos,
791
+ data,
792
+ _state$product22,
793
+ _state$product23,
794
+ _body$assets,
795
+ res,
796
+ body,
797
+ guardados,
798
+ _args6 = arguments;
799
+
772
800
  return _regenerator.default.wrap(function _callee6$(_context6) {
773
801
  while (1) {
774
802
  switch (_context6.prev = _context6.next) {
775
803
  case 0:
776
- concept = (0, _utils.getConceptByTab)(state.active_tab);
804
+ uploaded = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : [];
805
+ listos = uploaded.filter(function (asset) {
806
+ return asset.src && !(0, _assets.isPersisted)(asset);
807
+ });
808
+
809
+ if (!(listos.length === 0)) {
810
+ _context6.next = 4;
811
+ break;
812
+ }
813
+
814
+ return _context6.abrupt("return");
815
+
816
+ case 4:
777
817
  data = {
778
818
  articleId: (_state$product19 = state.product) === null || _state$product19 === void 0 ? void 0 : _state$product19.id_article,
779
- orderId: ((_state$product20 = state.product) === null || _state$product20 === void 0 ? void 0 : _state$product20.orderId) || ((_state$product21 = state.product) === null || _state$product21 === void 0 ? void 0 : _state$product21.id_order),
819
+ newAssets: listos.map(_assets.toPayload),
820
+ updateAssets: [],
821
+ deleteAssets: []
822
+ };
823
+
824
+ if ((_state$product20 = state.product) !== null && _state$product20 !== void 0 && _state$product20.orderId || (_state$product21 = state.product) !== null && _state$product21 !== void 0 && _state$product21.id_order) {
825
+ data.orderId = ((_state$product22 = state.product) === null || _state$product22 === void 0 ? void 0 : _state$product22.orderId) || ((_state$product23 = state.product) === null || _state$product23 === void 0 ? void 0 : _state$product23.id_order);
826
+ }
827
+
828
+ _context6.prev = 6;
829
+ _context6.next = 9;
830
+ return _axios.default.put(process.env.REACT_APP_ARTICLE_DATA_ENDPOINT, data, {
831
+ params: {
832
+ asset: true
833
+ },
834
+ headers: {
835
+ Authorization: token
836
+ }
837
+ });
838
+
839
+ case 9:
840
+ res = _context6.sent;
841
+
842
+ if (!(res.data.statusCode !== 200)) {
843
+ _context6.next = 12;
844
+ break;
845
+ }
846
+
847
+ throw new Error("Respuesta inesperada");
848
+
849
+ case 12:
850
+ body = JSON.parse(res.data.body);
851
+ guardados = (_body$assets = body.assets) !== null && _body$assets !== void 0 ? _body$assets : [];
852
+ /*
853
+ Se le pone a cada activo el id que le tocó, emparejando por la clave de
854
+ S3, que es única.
855
+ A propósito NO se reemplaza la lista entera con lo que devolvió el
856
+ backend: eso borraría el rastro de lo que el usuario cambió o borró y
857
+ todavía no ha guardado. Aquí solo se completa lo que faltaba.
858
+ */
859
+
860
+ listos.forEach(function (asset) {
861
+ var fila = guardados.find(function (row) {
862
+ return row.src === asset.src;
863
+ });
864
+ if (!fila) return;
865
+ dispatch({
866
+ type: "PATCH_ASSET",
867
+ payload: {
868
+ key: (0, _assets.assetKey)(asset),
869
+ changes: {
870
+ id: fila.id,
871
+ url: fila.url
872
+ }
873
+ }
874
+ });
875
+ });
876
+ _context6.next = 21;
877
+ break;
878
+
879
+ case 17:
880
+ _context6.prev = 17;
881
+ _context6.t0 = _context6["catch"](6);
882
+ console.log("Error registering assets:", _context6.t0);
883
+ /*
884
+ El archivo SÍ está en S3; lo que falló es la fila. Se marca en el activo
885
+ y no en un modal porque el usuario puede estar soltando más archivos:
886
+ interrumpirlo con un diálogo por cada fallo sería peor que dejarlo
887
+ señalado en su renglón, donde además se ve cuál falló.
888
+ */
889
+
890
+ listos.forEach(function (asset) {
891
+ return dispatch({
892
+ type: "PATCH_ASSET",
893
+ payload: {
894
+ key: (0, _assets.assetKey)(asset),
895
+ changes: {
896
+ status: "error",
897
+ error: "Se subió el archivo pero no se pudo guardar. Usa el botón de guardar."
898
+ }
899
+ }
900
+ });
901
+ });
902
+
903
+ case 21:
904
+ case "end":
905
+ return _context6.stop();
906
+ }
907
+ }
908
+ }, _callee6, null, [[6, 17]]);
909
+ }));
910
+
911
+ return function registerUploadedAssets(_x8) {
912
+ return _ref9.apply(this, arguments);
913
+ };
914
+ }();
915
+ /*
916
+ Guarda los activos digitales: registra los nuevos, manda los cambios y pide
917
+ las bajas.
918
+ Va aparte de `updateImages` y no dentro, aunque las dos bandejas vivan en la
919
+ misma pestaña. Un activo no pasa por ninguna de las reglas de una imagen —ni
920
+ tipo de toma, ni obligatoriedad, ni cupo por cadena— y el backend los escribe
921
+ en otra tabla. Mezclarlos obligaría a partir en dos cada validación de
922
+ `updateImages`, que ya es la función más delicada de este archivo.
923
+ Igual que con las imágenes, aquí NO viaja ningún binario: el archivo ya está
924
+ en S3 y esto solo registra metadatos. Mandar el archivo en el cuerpo devuelve
925
+ 413.
926
+ */
927
+
928
+
929
+ var saveAssets = /*#__PURE__*/function () {
930
+ var _ref10 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7(token) {
931
+ var _state$product24, _state$product25, _state$product26;
932
+
933
+ var payload, newAssets, updateAssets, deleteAssets, sinSubir, data, _state$product27, _state$product28, res;
934
+
935
+ return _regenerator.default.wrap(function _callee7$(_context7) {
936
+ while (1) {
937
+ switch (_context7.prev = _context7.next) {
938
+ case 0:
939
+ payload = (0, _assets.buildSavePayload)((0, _assets2.selectAssetsToSave)(state));
940
+ newAssets = payload.newAssets, updateAssets = payload.updateAssets, deleteAssets = payload.deleteAssets;
941
+
942
+ if (!(!newAssets.length && !updateAssets.length && !deleteAssets.length)) {
943
+ _context7.next = 4;
944
+ break;
945
+ }
946
+
947
+ return _context7.abrupt("return", false);
948
+
949
+ case 4:
950
+ /*
951
+ Un activo nuevo sin `key` es un archivo que todavía no llegó a S3.
952
+ Registrarlo crearía una fila apuntando a un objeto que no existe: la
953
+ bandeja lo mostraría y al descargarlo daría 404, sin forma de saber por qué.
954
+ Mejor no guardar nada y decirlo.
955
+ */
956
+ sinSubir = newAssets.filter(function (asset) {
957
+ return !asset.key;
958
+ });
959
+
960
+ if (!(sinSubir.length > 0)) {
961
+ _context7.next = 8;
962
+ break;
963
+ }
964
+
965
+ dispatch({
966
+ type: "SET_MODAL",
967
+ payload: {
968
+ show: true,
969
+ title: "Faltan archivos por subir",
970
+ message: "".concat(sinSubir.length, " activo(s) todav\xEDa no se han subido. Espera a que termine la carga e intenta de nuevo."),
971
+ image: _genericModalWarning.default
972
+ }
973
+ });
974
+ return _context7.abrupt("return", false);
975
+
976
+ case 8:
977
+ dispatch({
978
+ type: "SET_SAVING",
979
+ payload: true
980
+ }); // Sin `version`: un activo general es el mismo para todas las versiones del
981
+ // producto, así que ni la fila ni la clave de S3 la llevan.
982
+
983
+ data = {
984
+ articleId: (_state$product24 = state.product) === null || _state$product24 === void 0 ? void 0 : _state$product24.id_article,
985
+ newAssets: newAssets,
986
+ updateAssets: updateAssets,
987
+ deleteAssets: deleteAssets
988
+ };
989
+
990
+ if ((_state$product25 = state.product) !== null && _state$product25 !== void 0 && _state$product25.orderId || (_state$product26 = state.product) !== null && _state$product26 !== void 0 && _state$product26.id_order) {
991
+ data.orderId = ((_state$product27 = state.product) === null || _state$product27 === void 0 ? void 0 : _state$product27.orderId) || ((_state$product28 = state.product) === null || _state$product28 === void 0 ? void 0 : _state$product28.id_order);
992
+ }
993
+
994
+ _context7.prev = 11;
995
+ _context7.next = 14;
996
+ return _axios.default.put(process.env.REACT_APP_ARTICLE_DATA_ENDPOINT, data, {
997
+ params: {
998
+ asset: true
999
+ },
1000
+ headers: {
1001
+ Authorization: token
1002
+ }
1003
+ });
1004
+
1005
+ case 14:
1006
+ res = _context7.sent;
1007
+
1008
+ if (!(res.data.statusCode === 200)) {
1009
+ _context7.next = 19;
1010
+ break;
1011
+ }
1012
+
1013
+ // Se olvida qué cambió y qué se borró: lo que hay en pantalla ya es lo
1014
+ // que hay en la base. Sin esto, el siguiente guardado reenviaría todo.
1015
+ dispatch({
1016
+ type: "CLEAR_ASSETS_TRACKING"
1017
+ });
1018
+ dispatch({
1019
+ type: "SET_MODAL",
1020
+ payload: {
1021
+ show: true,
1022
+ title: "",
1023
+ message: "Activos digitales guardados con éxito",
1024
+ image: _genericModalCheck.default
1025
+ }
1026
+ });
1027
+ /*
1028
+ Devuelve `true` para que quien llama recargue.
1029
+ Es imprescindible, no cortesía: los activos recién creados siguen en
1030
+ memoria con su id temporal y sin el id de la base. Sin recargar, el
1031
+ siguiente guardado los volvería a mandar como nuevos y se duplicarían.
1032
+ Es exactamente el problema que ya tuvieron las imágenes.
1033
+ */
1034
+
1035
+ return _context7.abrupt("return", true);
1036
+
1037
+ case 19:
1038
+ return _context7.abrupt("return", false);
1039
+
1040
+ case 22:
1041
+ _context7.prev = 22;
1042
+ _context7.t0 = _context7["catch"](11);
1043
+ console.log("Error saving assets:", _context7.t0);
1044
+ dispatch({
1045
+ type: "SET_ERRORS",
1046
+ payload: [].concat((0, _toConsumableArray2.default)(state.errors), [_context7.t0])
1047
+ });
1048
+ dispatch({
1049
+ type: "SET_MODAL",
1050
+ payload: {
1051
+ show: true,
1052
+ title: "Error",
1053
+ message: "Hubo un error al guardar los activos digitales",
1054
+ image: _errorModal.default
1055
+ }
1056
+ });
1057
+ return _context7.abrupt("return", false);
1058
+
1059
+ case 28:
1060
+ _context7.prev = 28;
1061
+ dispatch({
1062
+ type: "SET_SAVING",
1063
+ payload: false
1064
+ });
1065
+ return _context7.finish(28);
1066
+
1067
+ case 31:
1068
+ case "end":
1069
+ return _context7.stop();
1070
+ }
1071
+ }
1072
+ }, _callee7, null, [[11, 22, 28, 31]]);
1073
+ }));
1074
+
1075
+ return function saveAssets(_x9) {
1076
+ return _ref10.apply(this, arguments);
1077
+ };
1078
+ }();
1079
+
1080
+ var createComment = /*#__PURE__*/function () {
1081
+ var _ref11 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8(body, token) {
1082
+ var _state$product29, _state$product30, _state$product31;
1083
+
1084
+ var concept, data;
1085
+ return _regenerator.default.wrap(function _callee8$(_context8) {
1086
+ while (1) {
1087
+ switch (_context8.prev = _context8.next) {
1088
+ case 0:
1089
+ concept = (0, _utils.getConceptByTab)(state.active_tab);
1090
+ data = {
1091
+ articleId: (_state$product29 = state.product) === null || _state$product29 === void 0 ? void 0 : _state$product29.id_article,
1092
+ orderId: ((_state$product30 = state.product) === null || _state$product30 === void 0 ? void 0 : _state$product30.orderId) || ((_state$product31 = state.product) === null || _state$product31 === void 0 ? void 0 : _state$product31.id_order),
780
1093
  message: body,
781
1094
  concept: concept,
782
1095
  version: state.product.version
783
1096
  };
784
- _context6.prev = 2;
785
- _context6.next = 5;
1097
+ _context8.prev = 2;
1098
+ _context8.next = 5;
786
1099
  return _axios.default.post("".concat(process.env.REACT_APP_COMMENTS_ENDPOINT), data, {
787
1100
  headers: {
788
1101
  Authorization: token
@@ -790,24 +1103,24 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
790
1103
  });
791
1104
 
792
1105
  case 5:
793
- _context6.next = 10;
1106
+ _context8.next = 10;
794
1107
  break;
795
1108
 
796
1109
  case 7:
797
- _context6.prev = 7;
798
- _context6.t0 = _context6["catch"](2);
799
- console.log("Error creating comment:", _context6.t0);
1110
+ _context8.prev = 7;
1111
+ _context8.t0 = _context8["catch"](2);
1112
+ console.log("Error creating comment:", _context8.t0);
800
1113
 
801
1114
  case 10:
802
1115
  case "end":
803
- return _context6.stop();
1116
+ return _context8.stop();
804
1117
  }
805
1118
  }
806
- }, _callee6, null, [[2, 7]]);
1119
+ }, _callee8, null, [[2, 7]]);
807
1120
  }));
808
1121
 
809
- return function createComment(_x8, _x9) {
810
- return _ref9.apply(this, arguments);
1122
+ return function createComment(_x10, _x11) {
1123
+ return _ref11.apply(this, arguments);
811
1124
  };
812
1125
  }();
813
1126
 
@@ -819,6 +1132,8 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
819
1132
  updateImages: updateImages,
820
1133
  saveImageAttrs: saveImageAttrs,
821
1134
  deleteImages: deleteImages,
1135
+ saveAssets: saveAssets,
1136
+ registerUploadedAssets: registerUploadedAssets,
822
1137
  handleOnDownloadImages: handleOnDownloadImages,
823
1138
  createComment: createComment
824
1139
  };