contentoh-components-library 21.6.13 → 21.6.15

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.
@@ -33,12 +33,14 @@ var _genericModalCheck = _interopRequireDefault(require("../../../../assets/imag
33
33
 
34
34
  var _errorModal = _interopRequireDefault(require("../../../../assets/images/genericModal/errorModal.svg"));
35
35
 
36
+ var _genericModalWarning = _interopRequireDefault(require("../../../../assets/images/genericModal/genericModalWarning.svg"));
37
+
36
38
  var _utils = require("../utils");
37
39
 
38
40
  var _jsxRuntime = require("react/jsx-runtime");
39
41
 
40
- var _excluded = ["src"],
41
- _excluded2 = ["src"];
42
+ var _excluded = ["src", "video_src"],
43
+ _excluded2 = ["src", "video_src"];
42
44
  var S3_BUCKET = process.env.REACT_APP_IMAGES_BUCKET;
43
45
  var REGION = "us-east-1";
44
46
 
@@ -310,23 +312,28 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
310
312
 
311
313
  var updateImages = /*#__PURE__*/function () {
312
314
  var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(token) {
313
- var _state$images_values, _state$product7, _state$product8, _state$product9, _data$articleData, _data$updateImages;
315
+ var _state$images_values, _state$images_values$, _state$images_values2, _state$product7, _state$product8, _state$product9, _data$articleData, _data$updateImages;
314
316
 
315
- var updatedImages, attrForImgs, generalAttrs, retailerKey, retailerAttrs, mergedAttrs, data, valid, promiseArray, res;
317
+ var newImages, updatedImages, attrForImgs, generalAttrs, retailerKey, retailerAttrs, mergedAttrs, data, valid, promiseArray, res;
316
318
  return _regenerator.default.wrap(function _callee3$(_context3) {
317
319
  while (1) {
318
320
  switch (_context3.prev = _context3.next) {
319
321
  case 0:
320
- if (!(state.updated_images_values.length === 0)) {
321
- _context3.next = 2;
322
+ // Imágenes/videos recién agregados a la galería (aún sin id en BD).
323
+ newImages = ((_state$images_values = state.images_values) === null || _state$images_values === void 0 ? void 0 : (_state$images_values$ = _state$images_values.values) === null || _state$images_values$ === void 0 ? void 0 : _state$images_values$.filter(function (e) {
324
+ return !e.id;
325
+ })) || []; // Salir solo si no hay nada que crear ni que actualizar.
326
+
327
+ if (!(state.updated_images_values.length === 0 && newImages.length === 0)) {
328
+ _context3.next = 3;
322
329
  break;
323
330
  }
324
331
 
325
332
  return _context3.abrupt("return");
326
333
 
327
- case 2:
334
+ case 3:
328
335
  updatedImages = state.updated_images_values;
329
- attrForImgs = ((_state$images_values = state.images_values) === null || _state$images_values === void 0 ? void 0 : _state$images_values.attrForImgs) || {};
336
+ attrForImgs = ((_state$images_values2 = state.images_values) === null || _state$images_values2 === void 0 ? void 0 : _state$images_values2.attrForImgs) || {};
330
337
  generalAttrs = attrForImgs.general || [];
331
338
  retailerKey = Object.keys(attrForImgs).find(function (key) {
332
339
  return key !== "general";
@@ -370,7 +377,7 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
370
377
  })); // console.log({ data });
371
378
 
372
379
  if (!valid) {
373
- _context3.next = 37;
380
+ _context3.next = 38;
374
381
  break;
375
382
  }
376
383
 
@@ -389,9 +396,9 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
389
396
  isApproved: true
390
397
  });
391
398
  });
392
- _context3.prev = 15;
399
+ _context3.prev = 16;
393
400
  promiseArray = data.articleData.map(function (e) {
394
- var file = Buffer.from(e.src.replace(/^data:image\/\w+;base64,/, ""), "base64");
401
+ var file = e.ext === "mp4" ? Buffer.from((e.video_src || "").replace(/^data:video\/\w+;base64,/, ""), "base64") : Buffer.from(e.src.replace(/^data:image\/\w+;base64,/, ""), "base64");
395
402
  var params = {
396
403
  ACL: "public-read",
397
404
  Body: file,
@@ -400,22 +407,24 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
400
407
  };
401
408
  return myBucket.putObject(params).promise();
402
409
  });
403
- _context3.next = 19;
410
+ _context3.next = 20;
404
411
  return Promise.all(promiseArray);
405
412
 
406
- case 19:
413
+ case 20:
407
414
  // Eliminar el buffer base64 antes de enviar al endpoint para evitar error 413
408
415
  data.articleData = data.articleData.map(function (_ref5) {
409
416
  var src = _ref5.src,
417
+ video_src = _ref5.video_src,
410
418
  rest = (0, _objectWithoutProperties2.default)(_ref5, _excluded);
411
419
  return rest;
412
420
  });
413
421
  data.updateImages = data.updateImages.map(function (_ref6) {
414
422
  var src = _ref6.src,
423
+ video_src = _ref6.video_src,
415
424
  rest = (0, _objectWithoutProperties2.default)(_ref6, _excluded2);
416
425
  return rest;
417
426
  });
418
- _context3.next = 23;
427
+ _context3.next = 24;
419
428
  return _axios.default.put(process.env.REACT_APP_ARTICLE_DATA_ENDPOINT, data, {
420
429
  params: {
421
430
  image: true,
@@ -426,7 +435,7 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
426
435
  }
427
436
  });
428
437
 
429
- case 23:
438
+ case 24:
430
439
  res = _context3.sent;
431
440
 
432
441
  if (res.data.statusCode === 200) {
@@ -447,12 +456,12 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
447
456
  });
448
457
  }
449
458
 
450
- _context3.next = 32;
459
+ _context3.next = 33;
451
460
  break;
452
461
 
453
- case 27:
454
- _context3.prev = 27;
455
- _context3.t0 = _context3["catch"](15);
462
+ case 28:
463
+ _context3.prev = 28;
464
+ _context3.t0 = _context3["catch"](16);
456
465
  console.log(_context3.t0);
457
466
  dispatch({
458
467
  type: "SET_ERRORS",
@@ -468,35 +477,35 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
468
477
  }
469
478
  });
470
479
 
471
- case 32:
472
- _context3.prev = 32;
480
+ case 33:
481
+ _context3.prev = 33;
473
482
  dispatch({
474
483
  type: "SET_SAVING",
475
484
  payload: false
476
485
  });
477
- return _context3.finish(32);
486
+ return _context3.finish(33);
478
487
 
479
- case 35:
480
- _context3.next = 38;
488
+ case 36:
489
+ _context3.next = 39;
481
490
  break;
482
491
 
483
- case 37:
492
+ case 38:
484
493
  dispatch({
485
494
  type: "SET_MODAL",
486
495
  payload: {
487
496
  show: true,
488
497
  title: "Campos incompletos o duplicados",
489
498
  message: "Completa los campos que solicita cada una de la imágenes o hay imágenes con el mismo tipo de toma. Recuerda hay campos obligatorios y no podras avanzar si no estan completos.",
490
- image: warningIcon
499
+ image: _genericModalWarning.default
491
500
  }
492
501
  });
493
502
 
494
- case 38:
503
+ case 39:
495
504
  case "end":
496
505
  return _context3.stop();
497
506
  }
498
507
  }
499
- }, _callee3, null, [[15, 27, 32, 35]]);
508
+ }, _callee3, null, [[16, 28, 33, 36]]);
500
509
  }));
501
510
 
502
511
  return function updateImages(_x3) {
@@ -506,7 +515,7 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
506
515
 
507
516
  var saveImageAttrs = /*#__PURE__*/function () {
508
517
  var _ref7 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(token) {
509
- var _state$images_values$, _state$images_values2, _state$images_values3, _state$product10, _state$product11, _state$product12;
518
+ var _state$images_values$2, _state$images_values3, _state$images_values4, _state$product10, _state$product11, _state$product12;
510
519
 
511
520
  var activeImage, attrForImgs, data, _state$product13, _state$product14, res;
512
521
 
@@ -527,7 +536,7 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
527
536
  payload: true
528
537
  });
529
538
  activeImage = state.images_values.values[state.current_image];
530
- attrForImgs = (_state$images_values$ = (_state$images_values2 = state.images_values) === null || _state$images_values2 === void 0 ? void 0 : (_state$images_values3 = _state$images_values2.attrForImgs) === null || _state$images_values3 === void 0 ? void 0 : _state$images_values3.general) !== null && _state$images_values$ !== void 0 ? _state$images_values$ : [];
539
+ attrForImgs = (_state$images_values$2 = (_state$images_values3 = state.images_values) === null || _state$images_values3 === void 0 ? void 0 : (_state$images_values4 = _state$images_values3.attrForImgs) === null || _state$images_values4 === void 0 ? void 0 : _state$images_values4.general) !== null && _state$images_values$2 !== void 0 ? _state$images_values$2 : [];
531
540
  data = {
532
541
  articleId: (_state$product10 = state.product) === null || _state$product10 === void 0 ? void 0 : _state$product10.id_article,
533
542
  attrReqImgs: attrForImgs.map(function (e) {
@@ -620,14 +629,14 @@ var ProviderProductEditionProvider = function ProviderProductEditionProvider(_re
620
629
  }();
621
630
 
622
631
  var handleOnDownloadImages = function handleOnDownloadImages() {
623
- var _state$product15, _state$product16, _state$product16$arti, _state$images_values4, _state$images_values5;
632
+ var _state$product15, _state$product16, _state$product16$arti, _state$images_values5, _state$images_values6;
624
633
 
625
634
  var upc = ((_state$product15 = state.product) === null || _state$product15 === void 0 ? void 0 : _state$product15.upc) || ((_state$product16 = state.product) === null || _state$product16 === void 0 ? void 0 : (_state$product16$arti = _state$product16.article) === null || _state$product16$arti === void 0 ? void 0 : _state$product16$arti.upc);
626
635
  state.selected_images.length > 0 ? state.selected_images.forEach(function (e) {
627
636
  if (e.id) {
628
637
  saveAs("https://".concat(process.env.REACT_APP_IMAGES_BUCKET, ".s3.amazonaws.com/").concat(e.srcDB), "".concat(upc, "_").concat(e.name, ".").concat(e.ext));
629
638
  }
630
- }) : (_state$images_values4 = state.images_values) === null || _state$images_values4 === void 0 ? void 0 : (_state$images_values5 = _state$images_values4.values) === null || _state$images_values5 === void 0 ? void 0 : _state$images_values5.forEach(function (e) {
639
+ }) : (_state$images_values5 = state.images_values) === null || _state$images_values5 === void 0 ? void 0 : (_state$images_values6 = _state$images_values5.values) === null || _state$images_values6 === void 0 ? void 0 : _state$images_values6.forEach(function (e) {
631
640
  if (e.id) {
632
641
  saveAs("https://".concat(process.env.REACT_APP_IMAGES_BUCKET, ".s3.amazonaws.com/").concat(e.srcDB), "".concat(upc, "_").concat(e.name, ".").concat(e.ext));
633
642
  }
@@ -17,10 +17,10 @@ var _objectSpread5 = _interopRequireDefault(require("@babel/runtime/helpers/esm/
17
17
 
18
18
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/toConsumableArray"));
19
19
 
20
- var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/asyncToGenerator"));
21
-
22
20
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));
23
21
 
22
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/asyncToGenerator"));
23
+
24
24
  var _react = require("react");
25
25
 
26
26
  var _axios = _interopRequireDefault(require("axios"));
@@ -89,6 +89,8 @@ var _styles = require("./styles");
89
89
 
90
90
  var _Commentary = require("../../atoms/Commentary");
91
91
 
92
+ var _generateThumnail = _interopRequireDefault(require("./generateThumnail"));
93
+
92
94
  var _AiProductEdition = require("../../../contexts/AiProductEdition");
93
95
 
94
96
  var _ChangeStatusModal = _interopRequireDefault(require("../../organisms/ChangeStatusModal"));
@@ -104,6 +106,127 @@ var allowedAccountsToViewChangeStatus = ["mperez@contentoh.com", "gmorales@conte
104
106
  "ladiboh785@mi166.com" //QA
105
107
  ];
106
108
 
109
+ function obtenerDuracionVideoBase64(base64Data) {
110
+ return new Promise(function (resolve, reject) {
111
+ var video = document.createElement("video");
112
+ video.src = base64Data;
113
+ video.addEventListener("loadedmetadata", function () {
114
+ resolve(video.duration);
115
+ });
116
+ video.addEventListener("error", reject);
117
+ });
118
+ }
119
+
120
+ function convertirVideoABase64(url) {
121
+ return new Promise(function (resolve, reject) {
122
+ var xhr = new XMLHttpRequest();
123
+ xhr.open("GET", url, true);
124
+ xhr.responseType = "blob";
125
+
126
+ xhr.onload = function () {
127
+ if (xhr.status === 200) {
128
+ var blob = xhr.response;
129
+ var reader = new FileReader();
130
+
131
+ reader.onloadend = function () {
132
+ resolve(reader.result);
133
+ };
134
+
135
+ reader.readAsDataURL(blob);
136
+ } else {
137
+ reject(new Error("Error al cargar el video"));
138
+ }
139
+ };
140
+
141
+ xhr.onerror = function () {
142
+ reject(new Error("Error de red al cargar el video"));
143
+ };
144
+
145
+ xhr.send();
146
+ });
147
+ } // Para videos ya guardados, `getImage` deja en `src` una URL del
148
+ // redimensionador de imágenes que no sirve para mp4. Descargamos el video
149
+ // desde S3 (srcDB) y generamos un thumbnail JPEG para mostrarlo en la galería.
150
+
151
+
152
+ function regenerateVideoThumbnails(_x) {
153
+ return _regenerateVideoThumbnails.apply(this, arguments);
154
+ }
155
+
156
+ function _regenerateVideoThumbnails() {
157
+ _regenerateVideoThumbnails = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee15(values) {
158
+ return _regenerator.default.wrap(function _callee15$(_context15) {
159
+ while (1) {
160
+ switch (_context15.prev = _context15.next) {
161
+ case 0:
162
+ if (Array.isArray(values)) {
163
+ _context15.next = 2;
164
+ break;
165
+ }
166
+
167
+ return _context15.abrupt("return", values);
168
+
169
+ case 2:
170
+ return _context15.abrupt("return", Promise.all(values.map( /*#__PURE__*/function () {
171
+ var _ref17 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee14(value) {
172
+ var base64, videoSrc, thumbnail;
173
+ return _regenerator.default.wrap(function _callee14$(_context14) {
174
+ while (1) {
175
+ switch (_context14.prev = _context14.next) {
176
+ case 0:
177
+ if (!((value === null || value === void 0 ? void 0 : value.ext) !== "mp4" || !(value !== null && value !== void 0 && value.srcDB))) {
178
+ _context14.next = 2;
179
+ break;
180
+ }
181
+
182
+ return _context14.abrupt("return", value);
183
+
184
+ case 2:
185
+ _context14.prev = 2;
186
+ _context14.next = 5;
187
+ return convertirVideoABase64("https://" + process.env.REACT_APP_IMAGES_BUCKET + ".s3.amazonaws.com/" + value.srcDB);
188
+
189
+ case 5:
190
+ base64 = _context14.sent;
191
+ videoSrc = "data:video/mp4;base64," + base64.split(",")[1];
192
+ _context14.next = 9;
193
+ return (0, _generateThumnail.default)(videoSrc, 2);
194
+
195
+ case 9:
196
+ thumbnail = _context14.sent;
197
+ return _context14.abrupt("return", (0, _objectSpread5.default)((0, _objectSpread5.default)({}, value), {}, {
198
+ src: thumbnail
199
+ }));
200
+
201
+ case 13:
202
+ _context14.prev = 13;
203
+ _context14.t0 = _context14["catch"](2);
204
+ console.error("Error al generar thumbnail del video:", _context14.t0);
205
+ return _context14.abrupt("return", value);
206
+
207
+ case 17:
208
+ case "end":
209
+ return _context14.stop();
210
+ }
211
+ }
212
+ }, _callee14, null, [[2, 13]]);
213
+ }));
214
+
215
+ return function (_x8) {
216
+ return _ref17.apply(this, arguments);
217
+ };
218
+ }())));
219
+
220
+ case 3:
221
+ case "end":
222
+ return _context15.stop();
223
+ }
224
+ }
225
+ }, _callee15);
226
+ }));
227
+ return _regenerateVideoThumbnails.apply(this, arguments);
228
+ }
229
+
107
230
  var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
108
231
  var _location$state, _location$state2, _state$active_retaile4, _state$active_retaile5, _state$images_values$2, _state$images_values10, _state$images_values11, _state$product8, _state$active_retaile6, _state$active_retaile7, _state$active_retaile8, _state$active_retaile9, _state$product9, _state$product10, _state$product11, _state$datasheets_inp, _state$datasheets_inp2, _state$product12, _state$images_values12, _state$comment;
109
232
 
@@ -209,7 +332,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
209
332
  setCompare = _useState30[1];
210
333
 
211
334
  var _useDropzone = (0, _reactDropzone.useDropzone)({
212
- accept: "image/*",
335
+ accept: "image/*, video/mp4",
213
336
  noKeyboard: true,
214
337
  multiple: true,
215
338
  noClick: true,
@@ -220,7 +343,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
220
343
 
221
344
  reader.onload = /*#__PURE__*/function () {
222
345
  var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(e) {
223
- var fileName, fileExtension, fileDataURL, img;
346
+ var fileName, fileExtension, fileDataURL, img, duracion;
224
347
  return _regenerator.default.wrap(function _callee$(_context) {
225
348
  while (1) {
226
349
  switch (_context.prev = _context.next) {
@@ -229,6 +352,71 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
229
352
  fileExtension = fileName.split(".").pop();
230
353
  fileDataURL = e.target.result;
231
354
  img = new Image();
355
+
356
+ if (!(fileExtension === "mp4")) {
357
+ _context.next = 22;
358
+ break;
359
+ }
360
+
361
+ _context.prev = 5;
362
+ _context.next = 8;
363
+ return obtenerDuracionVideoBase64(fileDataURL);
364
+
365
+ case 8:
366
+ duracion = _context.sent;
367
+
368
+ if (!(duracion <= 10 || duracion >= 600)) {
369
+ _context.next = 12;
370
+ break;
371
+ }
372
+
373
+ dispatch({
374
+ type: "SET_MODAL",
375
+ payload: {
376
+ show: true,
377
+ title: "Hubo un error al subir el video",
378
+ message: "Los videos deben durar entre 15 segundos y 10 minutos",
379
+ image: _errorModal.default
380
+ }
381
+ });
382
+ return _context.abrupt("return");
383
+
384
+ case 12:
385
+ _context.next = 14;
386
+ return (0, _generateThumnail.default)(fileDataURL, 2);
387
+
388
+ case 14:
389
+ img.src = _context.sent;
390
+
391
+ img.onload = function () {
392
+ var newImg = {
393
+ src: img.src,
394
+ name: fileName,
395
+ ext: fileExtension,
396
+ width: img.width,
397
+ height: img.height,
398
+ video_src: fileDataURL,
399
+ isApproved: true // VALIDAR QUE SOLO SEA PARA RADIOSHACK
400
+
401
+ };
402
+ dispatch({
403
+ type: "ADD_IMAGE_VALUE",
404
+ payload: newImg
405
+ });
406
+ };
407
+
408
+ _context.next = 21;
409
+ break;
410
+
411
+ case 18:
412
+ _context.prev = 18;
413
+ _context.t0 = _context["catch"](5);
414
+ console.error("Error al obtener la duración del video:", _context.t0);
415
+
416
+ case 21:
417
+ return _context.abrupt("return");
418
+
419
+ case 22:
232
420
  img.src = fileDataURL;
233
421
 
234
422
  img.onload = function () {
@@ -240,6 +428,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
240
428
  ext: fileExtension,
241
429
  width: width,
242
430
  height: height,
431
+ video_src: "",
243
432
  isApproved: true // VALIDAR QUE SOLO SEA PARA RADIOSHACK
244
433
 
245
434
  };
@@ -249,15 +438,15 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
249
438
  });
250
439
  };
251
440
 
252
- case 6:
441
+ case 24:
253
442
  case "end":
254
443
  return _context.stop();
255
444
  }
256
445
  }
257
- }, _callee);
446
+ }, _callee, null, [[5, 18]]);
258
447
  }));
259
448
 
260
- return function (_x) {
449
+ return function (_x2) {
261
450
  return _ref2.apply(this, arguments);
262
451
  };
263
452
  }();
@@ -507,6 +696,8 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
507
696
  datasheetsActiveRetailer,
508
697
  descriptionsActiveRetailer,
509
698
  filteredValues,
699
+ orderedValuesWithThumbs,
700
+ filteredValuesWithThumbs,
510
701
  _args4 = arguments;
511
702
 
512
703
  return _regenerator.default.wrap(function _callee4$(_context4) {
@@ -602,7 +793,8 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
602
793
  dispatch({
603
794
  type: "SET_COMMENTS",
604
795
  payload: commentsMap
605
- }); // Ordenamiento de imágenes
796
+ });
797
+ console.log("services", services); // Ordenamiento de imágenes
606
798
 
607
799
  orderMap = services[2].inputsByRetailer.flat().reduce(function (acc, item) {
608
800
  acc[item.id_image] = item.order;
@@ -629,15 +821,26 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
629
821
  return input.id_retailer === id_retailer && input.id_image === value.image_id;
630
822
  });
631
823
  });
632
- }); // Dispatch consolidado
824
+ }); // Regenerar thumbnails de videos guardados para que se muestren.
825
+
826
+ _context4.next = 30;
827
+ return regenerateVideoThumbnails(orderedValues);
633
828
 
829
+ case 30:
830
+ orderedValuesWithThumbs = _context4.sent;
831
+ _context4.next = 33;
832
+ return regenerateVideoThumbnails(filteredValues);
833
+
834
+ case 33:
835
+ filteredValuesWithThumbs = _context4.sent;
836
+ // Dispatch consolidado
634
837
  dispatch({
635
838
  type: "SET_SERVICES",
636
839
  payload: {
637
840
  datasheets: services[0],
638
841
  descriptions: services[1],
639
842
  images: (0, _objectSpread5.default)((0, _objectSpread5.default)({}, services[2]), {}, {
640
- values: orderedValues
843
+ values: orderedValuesWithThumbs
641
844
  })
642
845
  }
643
846
  });
@@ -668,7 +871,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
668
871
  dispatch({
669
872
  type: "SET_IMAGES_VALUES",
670
873
  payload: (0, _objectSpread5.default)((0, _objectSpread5.default)({}, services[2]), {}, {
671
- values: filteredValues
874
+ values: filteredValuesWithThumbs
672
875
  })
673
876
  }); // Calcular campos requeridos sin valor
674
877
 
@@ -681,11 +884,11 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
681
884
  loadAuditableData();
682
885
  }
683
886
 
684
- _context4.next = 42;
887
+ _context4.next = 49;
685
888
  break;
686
889
 
687
- case 38:
688
- _context4.prev = 38;
890
+ case 45:
891
+ _context4.prev = 45;
689
892
  _context4.t0 = _context4["catch"](2);
690
893
  console.log("Error loading data: ", _context4.t0);
691
894
  dispatch({
@@ -693,20 +896,20 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
693
896
  payload: [_context4.t0.message]
694
897
  });
695
898
 
696
- case 42:
697
- _context4.prev = 42;
899
+ case 49:
900
+ _context4.prev = 49;
698
901
  dispatch({
699
902
  type: "SET_LOADING",
700
903
  payload: false
701
904
  });
702
- return _context4.finish(42);
905
+ return _context4.finish(49);
703
906
 
704
- case 45:
907
+ case 52:
705
908
  case "end":
706
909
  return _context4.stop();
707
910
  }
708
911
  }
709
- }, _callee4, null, [[2, 38, 42, 45]]);
912
+ }, _callee4, null, [[2, 45, 49, 52]]);
710
913
  }));
711
914
 
712
915
  return function loadData() {
@@ -1223,7 +1426,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1223
1426
  }, _callee7, null, [[11, 36, 40, 43]]);
1224
1427
  }));
1225
1428
 
1226
- return function sendSingleEvaluation(_x2) {
1429
+ return function sendSingleEvaluation(_x3) {
1227
1430
  return _ref10.apply(this, arguments);
1228
1431
  };
1229
1432
  }();
@@ -1371,7 +1574,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1371
1574
  }, _callee9, null, [[1, 16, 19, 22]]);
1372
1575
  }));
1373
1576
 
1374
- return function sendBulkEvaluation(_x3) {
1577
+ return function sendBulkEvaluation(_x4) {
1375
1578
  return _ref12.apply(this, arguments);
1376
1579
  };
1377
1580
  }();
@@ -1417,7 +1620,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1417
1620
  }, _callee10);
1418
1621
  }));
1419
1622
 
1420
- return function handleOnChangeAssignations(_x4, _x5) {
1623
+ return function handleOnChangeAssignations(_x5, _x6) {
1421
1624
  return _ref13.apply(this, arguments);
1422
1625
  };
1423
1626
  }();
@@ -1500,7 +1703,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1500
1703
  }, _callee11, null, [[2, 8]]);
1501
1704
  }));
1502
1705
 
1503
- return function handleOnSubmitComment(_x6) {
1706
+ return function handleOnSubmitComment(_x7) {
1504
1707
  return _ref14.apply(this, arguments);
1505
1708
  };
1506
1709
  }();
@@ -1562,7 +1765,7 @@ var RetailerProductEditionView = function RetailerProductEditionView(_ref) {
1562
1765
  };
1563
1766
 
1564
1767
  var handleOnChangeProductVersion = function handleOnChangeProductVersion(version) {
1565
- console.log('se cambia la version');
1768
+ console.log("se cambia la version");
1566
1769
  dispatch({
1567
1770
  type: "SET_PRODUCT_VERSION",
1568
1771
  payload: version
@@ -209,6 +209,10 @@ exports.translateConcept = translateConcept;
209
209
 
210
210
  var getStatusArrayByRole = function getStatusArrayByRole(idRole) {
211
211
  switch (idRole) {
212
+ // Admin: puede validar/rechazar en cualquier estado operable (unión de todos los roles).
213
+ case 1:
214
+ return ["PA", "AS", "CA", "RC", "RA", "RP", "RCA", "AC", "AA", "AP", "ACA"];
215
+
212
216
  case 7:
213
217
  case 8:
214
218
  return ["PA", "AS", "CA", "RC", "RA", "RP", "RCA"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contentoh-components-library",
3
- "version": "21.6.13",
3
+ "version": "21.6.15",
4
4
  "dependencies": {
5
5
  "@aws-amplify/auth": "^4.5.3",
6
6
  "@aws-amplify/datastore": "^3.11.0",
@@ -11,6 +11,7 @@ import { v4 as uuidv4 } from "uuid";
11
11
 
12
12
  import successIcon from "../../../../assets/images/genericModal/genericModalCheck.svg";
13
13
  import errorIcon from "../../../../assets/images/genericModal/errorModal.svg";
14
+ import warningIcon from "../../../../assets/images/genericModal/genericModalWarning.svg";
14
15
  import { getConceptByTab } from "../utils";
15
16
 
16
17
  const S3_BUCKET = process.env.REACT_APP_IMAGES_BUCKET;
@@ -230,7 +231,11 @@ export const ProviderProductEditionProvider = ({ children }) => {
230
231
  };
231
232
 
232
233
  const updateImages = async (token) => {
233
- if (state.updated_images_values.length === 0) return;
234
+ // Imágenes/videos recién agregados a la galería (aún sin id en BD).
235
+ const newImages = state.images_values?.values?.filter((e) => !e.id) || [];
236
+ // Salir solo si no hay nada que crear ni que actualizar.
237
+ if (state.updated_images_values.length === 0 && newImages.length === 0)
238
+ return;
234
239
  const updatedImages = state.updated_images_values;
235
240
 
236
241
  const attrForImgs = state.images_values?.attrForImgs || {};
@@ -282,10 +287,16 @@ export const ProviderProductEditionProvider = ({ children }) => {
282
287
 
283
288
  try {
284
289
  const promiseArray = data.articleData.map((e) => {
285
- const file = Buffer.from(
286
- e.src.replace(/^data:image\/\w+;base64,/, ""),
287
- "base64",
288
- );
290
+ const file =
291
+ e.ext === "mp4"
292
+ ? Buffer.from(
293
+ (e.video_src || "").replace(/^data:video\/\w+;base64,/, ""),
294
+ "base64",
295
+ )
296
+ : Buffer.from(
297
+ e.src.replace(/^data:image\/\w+;base64,/, ""),
298
+ "base64",
299
+ );
289
300
  const params = {
290
301
  ACL: "public-read",
291
302
  Body: file,
@@ -298,8 +309,12 @@ export const ProviderProductEditionProvider = ({ children }) => {
298
309
  await Promise.all(promiseArray);
299
310
 
300
311
  // Eliminar el buffer base64 antes de enviar al endpoint para evitar error 413
301
- data.articleData = data.articleData.map(({ src, ...rest }) => rest);
302
- data.updateImages = data.updateImages.map(({ src, ...rest }) => rest);
312
+ data.articleData = data.articleData.map(
313
+ ({ src, video_src, ...rest }) => rest,
314
+ );
315
+ data.updateImages = data.updateImages.map(
316
+ ({ src, video_src, ...rest }) => rest,
317
+ );
303
318
 
304
319
  const res = await axios.put(
305
320
  process.env.REACT_APP_ARTICLE_DATA_ENDPOINT,
@@ -60,6 +60,7 @@ import imagesSent from "../../../assets/images/modalsSVGs/uploadingImages.svg";
60
60
 
61
61
  import { Container } from "./styles";
62
62
  import { Commentary } from "../../atoms/Commentary";
63
+ import generateThumbnail from "./generateThumnail";
63
64
 
64
65
  import { AiProductEditionProvider } from "../../../contexts/AiProductEdition";
65
66
  import ChangeStatusModal from "../../organisms/ChangeStatusModal";
@@ -80,9 +81,69 @@ const allowedAccountsToViewChangeStatus = [
80
81
  "kikije1467@mtlcz.com", //IMÁGENES
81
82
  "karafe3218@mom2kid.com", //TEXTOS
82
83
  "ladiboh785@mi166.com", //QA
83
-
84
84
  ];
85
85
 
86
+ function obtenerDuracionVideoBase64(base64Data) {
87
+ return new Promise((resolve, reject) => {
88
+ const video = document.createElement("video");
89
+ video.src = base64Data;
90
+ video.addEventListener("loadedmetadata", () => {
91
+ resolve(video.duration);
92
+ });
93
+ video.addEventListener("error", reject);
94
+ });
95
+ }
96
+
97
+ function convertirVideoABase64(url) {
98
+ return new Promise((resolve, reject) => {
99
+ const xhr = new XMLHttpRequest();
100
+ xhr.open("GET", url, true);
101
+ xhr.responseType = "blob";
102
+ xhr.onload = function () {
103
+ if (xhr.status === 200) {
104
+ const blob = xhr.response;
105
+ const reader = new FileReader();
106
+ reader.onloadend = function () {
107
+ resolve(reader.result);
108
+ };
109
+ reader.readAsDataURL(blob);
110
+ } else {
111
+ reject(new Error("Error al cargar el video"));
112
+ }
113
+ };
114
+ xhr.onerror = function () {
115
+ reject(new Error("Error de red al cargar el video"));
116
+ };
117
+ xhr.send();
118
+ });
119
+ }
120
+
121
+ // Para videos ya guardados, `getImage` deja en `src` una URL del
122
+ // redimensionador de imágenes que no sirve para mp4. Descargamos el video
123
+ // desde S3 (srcDB) y generamos un thumbnail JPEG para mostrarlo en la galería.
124
+ async function regenerateVideoThumbnails(values) {
125
+ if (!Array.isArray(values)) return values;
126
+ return Promise.all(
127
+ values.map(async (value) => {
128
+ if (value?.ext !== "mp4" || !value?.srcDB) return value;
129
+ try {
130
+ const base64 = await convertirVideoABase64(
131
+ "https://" +
132
+ process.env.REACT_APP_IMAGES_BUCKET +
133
+ ".s3.amazonaws.com/" +
134
+ value.srcDB,
135
+ );
136
+ const videoSrc = "data:video/mp4;base64," + base64.split(",")[1];
137
+ const thumbnail = await generateThumbnail(videoSrc, 2);
138
+ return { ...value, src: thumbnail };
139
+ } catch (error) {
140
+ console.error("Error al generar thumbnail del video:", error);
141
+ return value;
142
+ }
143
+ }),
144
+ );
145
+ }
146
+
86
147
  const RetailerProductEditionView = ({
87
148
  tabsSections,
88
149
  productSelected = {},
@@ -124,7 +185,7 @@ const RetailerProductEditionView = ({
124
185
 
125
186
  const [compare, setCompare] = useState(false);
126
187
  const { getRootProps, getInputProps, isDragActive, open } = useDropzone({
127
- accept: "image/*",
188
+ accept: "image/*, video/mp4",
128
189
  noKeyboard: true,
129
190
  multiple: true,
130
191
  noClick: true,
@@ -139,8 +200,48 @@ const RetailerProductEditionView = ({
139
200
  const fileDataURL = e.target.result;
140
201
 
141
202
  const img = new Image();
142
- img.src = fileDataURL;
143
203
 
204
+ if (fileExtension === "mp4") {
205
+ try {
206
+ const duracion = await obtenerDuracionVideoBase64(fileDataURL);
207
+ if (duracion <= 10 || duracion >= 600) {
208
+ dispatch({
209
+ type: "SET_MODAL",
210
+ payload: {
211
+ show: true,
212
+ title: "Hubo un error al subir el video",
213
+ message:
214
+ "Los videos deben durar entre 15 segundos y 10 minutos",
215
+ image: errorIcon,
216
+ },
217
+ });
218
+ return;
219
+ }
220
+
221
+ img.src = await generateThumbnail(fileDataURL, 2);
222
+ img.onload = function () {
223
+ const newImg = {
224
+ src: img.src,
225
+ name: fileName,
226
+ ext: fileExtension,
227
+ width: img.width,
228
+ height: img.height,
229
+ video_src: fileDataURL,
230
+ isApproved: true, // VALIDAR QUE SOLO SEA PARA RADIOSHACK
231
+ };
232
+
233
+ dispatch({
234
+ type: "ADD_IMAGE_VALUE",
235
+ payload: newImg,
236
+ });
237
+ };
238
+ } catch (error) {
239
+ console.error("Error al obtener la duración del video:", error);
240
+ }
241
+ return;
242
+ }
243
+
244
+ img.src = fileDataURL;
144
245
  img.onload = function () {
145
246
  const width = img.width;
146
247
  const height = img.height;
@@ -150,6 +251,7 @@ const RetailerProductEditionView = ({
150
251
  ext: fileExtension,
151
252
  width: width,
152
253
  height: height,
254
+ video_src: "",
153
255
  isApproved: true, // VALIDAR QUE SOLO SEA PARA RADIOSHACK
154
256
  };
155
257
 
@@ -220,11 +322,13 @@ const RetailerProductEditionView = ({
220
322
 
221
323
  const initializeProduct = async () => {
222
324
  try {
223
- const product = productSelected ? productSelected : JSON.parse(sessionStorage.getItem("productSelected"));
325
+ const product = productSelected
326
+ ? productSelected
327
+ : JSON.parse(sessionStorage.getItem("productSelected"));
224
328
 
225
329
  const productNormalized = normalizeProduct(product);
226
330
 
227
- console.log({productNormalized});
331
+ console.log({ productNormalized });
228
332
 
229
333
  dispatch({
230
334
  type: "SET_PRODUCT",
@@ -401,6 +505,8 @@ const RetailerProductEditionView = ({
401
505
  });
402
506
  dispatch({ type: "SET_COMMENTS", payload: commentsMap });
403
507
 
508
+ console.log("services", services);
509
+
404
510
  // Ordenamiento de imágenes
405
511
  const orderMap = services[2].inputsByRetailer
406
512
  .flat()
@@ -436,6 +542,12 @@ const RetailerProductEditionView = ({
436
542
  );
437
543
  });
438
544
 
545
+ // Regenerar thumbnails de videos guardados para que se muestren.
546
+ const orderedValuesWithThumbs =
547
+ await regenerateVideoThumbnails(orderedValues);
548
+ const filteredValuesWithThumbs =
549
+ await regenerateVideoThumbnails(filteredValues);
550
+
439
551
  // Dispatch consolidado
440
552
  dispatch({
441
553
  type: "SET_SERVICES",
@@ -444,7 +556,7 @@ const RetailerProductEditionView = ({
444
556
  descriptions: services[1],
445
557
  images: {
446
558
  ...services[2],
447
- values: orderedValues,
559
+ values: orderedValuesWithThumbs,
448
560
  },
449
561
  },
450
562
  });
@@ -473,7 +585,7 @@ const RetailerProductEditionView = ({
473
585
  type: "SET_IMAGES_VALUES",
474
586
  payload: {
475
587
  ...services[2],
476
- values: filteredValues,
588
+ values: filteredValuesWithThumbs,
477
589
  },
478
590
  });
479
591
 
@@ -750,10 +862,11 @@ const RetailerProductEditionView = ({
750
862
  );
751
863
 
752
864
  const newStatuses = JSON.parse(res.data.body);
753
- const serviceStatus = newStatuses.newServiceStatus[articleId][`${concept}Status`];
865
+ const serviceStatus =
866
+ newStatuses.newServiceStatus[articleId][`${concept}Status`];
754
867
  const articleStatus = newStatuses.newArticleStatus[articleId];
755
868
 
756
- console.log({newStatuses});
869
+ console.log({ newStatuses });
757
870
 
758
871
  // Actualizar el producto con los nuevos estados
759
872
  const updatedStatusByRetailer = state.product.statusByRetailer.map(
@@ -782,7 +895,8 @@ const RetailerProductEditionView = ({
782
895
  image: successIcon,
783
896
  },
784
897
  });
785
- } else { //Caso del botón "Enviar evaluación"
898
+ } else {
899
+ //Caso del botón "Enviar evaluación"
786
900
 
787
901
  //Se construye el mensaje y se actualiza el estatus
788
902
 
@@ -809,12 +923,13 @@ const RetailerProductEditionView = ({
809
923
  }
810
924
 
811
925
  if (res.data.statusCode === 200) {
812
-
813
- const { newStatus, newOrderStatus, newArticleStatus } = JSON.parse( res.data.body );
926
+ const { newStatus, newOrderStatus, newArticleStatus } = JSON.parse(
927
+ res.data.body,
928
+ );
814
929
 
815
930
  const articleStatus = newArticleStatus[articleId];
816
931
 
817
- console.log({newArticleStatus});
932
+ console.log({ newArticleStatus });
818
933
 
819
934
  // const retailers = state.product.categoryRetailer.map((r) => ({
820
935
  // id: r.id_retailer,
@@ -840,12 +955,13 @@ const RetailerProductEditionView = ({
840
955
  // };
841
956
  // await sendMessage(messageData);
842
957
 
843
- const updatedStatusByRetailerForSend = state.product.statusByRetailer.map((item) => {
844
- if (item.retailer_id === retailerId && item.service === concept) {
845
- return { ...item, status: newStatus };
846
- }
847
- return item;
848
- });
958
+ const updatedStatusByRetailerForSend =
959
+ state.product.statusByRetailer.map((item) => {
960
+ if (item.retailer_id === retailerId && item.service === concept) {
961
+ return { ...item, status: newStatus };
962
+ }
963
+ return item;
964
+ });
849
965
 
850
966
  const updatedProduct = {
851
967
  ...state.product,
@@ -856,9 +972,12 @@ const RetailerProductEditionView = ({
856
972
 
857
973
  //Actualizamos el services_data en el servicio específico del retailer actual
858
974
 
859
- const updatedServicesData = state.services_data?.map(service => ({
975
+ const updatedServicesData = state.services_data?.map((service) => ({
860
976
  ...service,
861
- status: service?.id_retailer === retailerId && service?.service === concept ? newStatus : service?.status
977
+ status:
978
+ service?.id_retailer === retailerId && service?.service === concept
979
+ ? newStatus
980
+ : service?.status,
862
981
  }));
863
982
 
864
983
  const sessionProduct = sessionStorage.getItem("productSelected");
@@ -929,11 +1048,18 @@ const RetailerProductEditionView = ({
929
1048
  const conceptArray = getConceptsByRole(user.id_role);
930
1049
 
931
1050
  state.services_data?.forEach((ret, idx) => {
932
- const { service: retailer_service, id_retailer, status: status_retailer_service } = ret;
1051
+ const {
1052
+ service: retailer_service,
1053
+ id_retailer,
1054
+ status: status_retailer_service,
1055
+ } = ret;
933
1056
 
934
1057
  const lastStatusLevel = status_retailer_service?.replace(/.*\//, "");
935
1058
 
936
- if (conceptArray.includes(retailer_service) && statusArray?.includes(lastStatusLevel)) {
1059
+ if (
1060
+ conceptArray.includes(retailer_service) &&
1061
+ statusArray?.includes(lastStatusLevel)
1062
+ ) {
937
1063
  const data = {
938
1064
  articleId: state.product.id_article,
939
1065
  orderId: state.product.id_order,
@@ -981,7 +1107,11 @@ const RetailerProductEditionView = ({
981
1107
  payload: updatedProduct,
982
1108
  });
983
1109
 
984
- const updatedServicesData = state.services_data.map(service => conceptArray.includes(service.service) ? { ...service, status: status } : service);
1110
+ const updatedServicesData = state.services_data.map((service) =>
1111
+ conceptArray.includes(service.service)
1112
+ ? { ...service, status: status }
1113
+ : service,
1114
+ );
985
1115
 
986
1116
  dispatch({
987
1117
  type: "SET_SERVICES_DATA",
@@ -1142,8 +1272,9 @@ const RetailerProductEditionView = ({
1142
1272
  switch (id_rol) {
1143
1273
  case 7:
1144
1274
  case 8:
1145
-
1146
- const canSendEvaluation = statusArray.includes(statusBySelectedRetailerService);
1275
+ const canSendEvaluation = statusArray.includes(
1276
+ statusBySelectedRetailerService,
1277
+ );
1147
1278
 
1148
1279
  // const conditionTwo = statusArray.includes(product?.status);
1149
1280
 
@@ -1180,7 +1311,7 @@ const RetailerProductEditionView = ({
1180
1311
  };
1181
1312
 
1182
1313
  const handleOnChangeProductVersion = (version) => {
1183
- console.log('se cambia la version')
1314
+ console.log("se cambia la version");
1184
1315
  dispatch({
1185
1316
  type: "SET_PRODUCT_VERSION",
1186
1317
  payload: version,
@@ -1310,12 +1441,12 @@ const RetailerProductEditionView = ({
1310
1441
  </Box>
1311
1442
  </div>
1312
1443
  </div>
1313
- </Container>
1444
+ </Container>
1314
1445
  );
1315
1446
  };
1316
1447
 
1317
1448
  useEffect(() => {
1318
- console.log({stateProduct: state.product})
1449
+ console.log({ stateProduct: state.product });
1319
1450
  }, [state.product]);
1320
1451
 
1321
1452
  if (state.loading || !state.services || !state.product)
@@ -1789,16 +1920,16 @@ const RetailerProductEditionView = ({
1789
1920
  )}
1790
1921
 
1791
1922
  <div className="action-buttons">
1792
- {
1793
- allowedAccountsToViewChangeStatus.includes(user?.email) && (
1794
- <Button
1795
- buttonType={"general-pink-button"}
1796
- label={"Cambio de Estatus"}
1797
- onClick={() => setOpenChangeStatusModal(true)}
1798
- id="button-change-status"
1799
- />
1800
- )
1801
- }
1923
+ {allowedAccountsToViewChangeStatus.includes(
1924
+ user?.email,
1925
+ ) && (
1926
+ <Button
1927
+ buttonType={"general-pink-button"}
1928
+ label={"Cambio de Estatus"}
1929
+ onClick={() => setOpenChangeStatusModal(true)}
1930
+ id="button-change-status"
1931
+ />
1932
+ )}
1802
1933
  {[7, 8].includes(user.id_role) && (
1803
1934
  <Button
1804
1935
  buttonType={
@@ -154,6 +154,21 @@ export const translateConcept = (concept) => CONCEPT_TO_TAB[concept];
154
154
 
155
155
  export const getStatusArrayByRole = (idRole) => {
156
156
  switch (idRole) {
157
+ // Admin: puede validar/rechazar en cualquier estado operable (unión de todos los roles).
158
+ case 1:
159
+ return [
160
+ "PA",
161
+ "AS",
162
+ "CA",
163
+ "RC",
164
+ "RA",
165
+ "RP",
166
+ "RCA",
167
+ "AC",
168
+ "AA",
169
+ "AP",
170
+ "ACA",
171
+ ];
157
172
  case 7:
158
173
  case 8:
159
174
  return ["PA", "AS", "CA", "RC", "RA", "RP", "RCA"];