contentoh-components-library 21.6.50 → 21.6.52
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/.env.test +0 -1
- package/dist/components/atoms/IconFile/index.js +2 -85
- package/dist/components/atoms/IconFile/styles.js +1 -1
- package/dist/components/atoms/ProductImage/ProductImage.stories.js +2 -70
- package/dist/components/atoms/ProductImage/index.js +27 -100
- package/dist/components/atoms/ProductImage/styles.js +1 -3
- package/dist/components/molecules/EditionActiveImage/index.js +2 -4
- package/dist/components/molecules/GalleryElement/index.js +4 -13
- package/dist/components/molecules/GalleryHeader/index.js +24 -96
- package/dist/components/molecules/GalleryHeader/styles.js +1 -4
- package/dist/components/molecules/ImageSelector/index.js +0 -1
- package/dist/components/organisms/ImagePreviewer/index.js +0 -1
- package/dist/components/organisms/ProductImageModal/index.js +2 -3
- package/dist/components/organisms/PropagateChangesModal/index.js +6 -1
- package/dist/components/pages/ProviderProductEdition/context/provider-product-edition.context.js +10 -8
- package/dist/components/pages/ProviderProductEdition/index.js +189 -72
- package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.context.js +25 -338
- package/dist/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +2 -12
- package/dist/components/pages/RetailerProductEdition/index.js +579 -631
- package/dist/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +0 -1
- package/dist/components/pages/RetailerProductEdition/stories/TextEditor.stories.js +145 -45
- package/dist/global-files/data.js +3 -16
- package/dist/index.js +90 -142
- package/package.json +1 -1
- package/src/components/atoms/IconFile/index.js +1 -28
- package/src/components/atoms/IconFile/styles.js +0 -8
- package/src/components/atoms/ProductImage/ProductImage.stories.js +0 -38
- package/src/components/atoms/ProductImage/index.js +20 -95
- package/src/components/atoms/ProductImage/styles.js +7 -92
- package/src/components/molecules/EditionActiveImage/index.js +2 -2
- package/src/components/molecules/GalleryElement/index.js +0 -9
- package/src/components/molecules/GalleryHeader/index.js +13 -65
- package/src/components/molecules/GalleryHeader/styles.js +1 -2
- package/src/components/molecules/ImageSelector/index.js +0 -1
- package/src/components/organisms/ImagePreviewer/index.js +0 -1
- package/src/components/organisms/ProductImageModal/index.js +0 -1
- package/src/components/organisms/PropagateChangesModal/index.js +10 -3
- package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx +2 -1
- package/src/components/pages/ProviderProductEdition/index.js +111 -6
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.context.jsx +2 -202
- package/src/components/pages/RetailerProductEdition/context/provider-product-edition.reducer.js +0 -12
- package/src/components/pages/RetailerProductEdition/index.js +258 -363
- package/src/components/pages/RetailerProductEdition/stories/ImageEditor.stories.js +0 -1
- package/src/components/pages/RetailerProductEdition/stories/TextEditor.stories.js +104 -51
- package/src/global-files/data.js +2 -17
- package/src/index.js +0 -4
- package/.claude/launch.json +0 -14
- package/dist/ai/prompts/attribute.prompt.js +0 -28
- package/dist/ai/prompts/description.prompt.js +0 -33
- package/dist/ai/schemas/attribute.schema.js +0 -35
- package/dist/ai/schemas/description.schema.js +0 -27
- package/dist/components/atoms/AssetPreview/AssetPreview.stories.js +0 -118
- package/dist/components/atoms/AssetPreview/index.js +0 -150
- package/dist/components/atoms/AssetPreview/styles.js +0 -28
- package/dist/components/molecules/GalleryAssetElement/GalleryAssetElement.stories.js +0 -147
- package/dist/components/molecules/GalleryAssetElement/index.js +0 -178
- package/dist/components/molecules/GalleryAssetElement/styles.js +0 -26
- package/dist/components/molecules/GalleryTrayTabs/GalleryTrayTabs.stories.js +0 -56
- package/dist/components/molecules/GalleryTrayTabs/index.js +0 -60
- package/dist/components/molecules/GalleryTrayTabs/styles.js +0 -20
- package/dist/components/organisms/DigitalAssetsTray/DigitalAssetsTray.stories.js +0 -171
- package/dist/components/organisms/DigitalAssetsTray/index.js +0 -211
- package/dist/components/organisms/DigitalAssetsTray/styles.js +0 -22
- package/dist/global-files/digital-assets/assetTypes.js +0 -480
- package/dist/global-files/digital-assets/assets.actions.js +0 -64
- package/dist/global-files/digital-assets/assets.adapter.js +0 -304
- package/dist/global-files/digital-assets/assets.mock.js +0 -136
- package/dist/global-files/digital-assets/assets.reducer.js +0 -220
- package/dist/global-files/digital-assets/uploadAssets.js +0 -179
- package/dist/global-files/digital-assets/useDigitalAssets.js +0 -522
- package/docs/activos-digitales.md +0 -273
- package/src/components/atoms/AssetPreview/AssetPreview.stories.js +0 -78
- package/src/components/atoms/AssetPreview/index.js +0 -119
- package/src/components/atoms/AssetPreview/styles.js +0 -190
- package/src/components/molecules/GalleryAssetElement/GalleryAssetElement.stories.js +0 -102
- package/src/components/molecules/GalleryAssetElement/index.js +0 -162
- package/src/components/molecules/GalleryAssetElement/styles.js +0 -159
- package/src/components/molecules/GalleryTrayTabs/GalleryTrayTabs.stories.js +0 -32
- package/src/components/molecules/GalleryTrayTabs/index.js +0 -41
- package/src/components/molecules/GalleryTrayTabs/styles.js +0 -52
- package/src/components/organisms/DigitalAssetsTray/DigitalAssetsTray.stories.js +0 -101
- package/src/components/organisms/DigitalAssetsTray/index.js +0 -189
- package/src/components/organisms/DigitalAssetsTray/styles.js +0 -183
- package/src/global-files/digital-assets/assetTypes.js +0 -419
- package/src/global-files/digital-assets/assets.actions.js +0 -50
- package/src/global-files/digital-assets/assets.adapter.js +0 -229
- package/src/global-files/digital-assets/assets.mock.js +0 -122
- package/src/global-files/digital-assets/assets.reducer.js +0 -197
- package/src/global-files/digital-assets/uploadAssets.js +0 -109
- package/src/global-files/digital-assets/useDigitalAssets.js +0 -329
package/package.json
CHANGED
|
@@ -11,8 +11,6 @@ import {
|
|
|
11
11
|
faFileAudio as IconFileAudio,
|
|
12
12
|
faFileLines as IconFileDefault,
|
|
13
13
|
faFileVideo as IconFileVideo,
|
|
14
|
-
faSwatchbook as IconFileDesign,
|
|
15
|
-
faFilm as IconFileMotion,
|
|
16
14
|
} from "@fortawesome/free-solid-svg-icons";
|
|
17
15
|
import React, { useRef } from "react";
|
|
18
16
|
import { CustomIcon } from "../CustomIcon";
|
|
@@ -43,30 +41,8 @@ export const IconFile = (props) => {
|
|
|
43
41
|
// file csv
|
|
44
42
|
csv: { icon: IconFileCsv, type: "csv" },
|
|
45
43
|
// file image
|
|
44
|
+
svg: { icon: IconFileImg, type: "image" },
|
|
46
45
|
gif: { icon: IconFileImg, type: "image" },
|
|
47
|
-
jpg: { icon: IconFileImg, type: "image" },
|
|
48
|
-
jpeg: { icon: IconFileImg, type: "image" },
|
|
49
|
-
png: { icon: IconFileImg, type: "image" },
|
|
50
|
-
webp: { icon: IconFileImg, type: "image" },
|
|
51
|
-
|
|
52
|
-
// archivos de diseño editables: no se pueden previsualizar en el navegador,
|
|
53
|
-
// así que el icono es lo único que distingue uno de otro en la bandeja.
|
|
54
|
-
psd: { icon: IconFileDesign, type: "design" },
|
|
55
|
-
psb: { icon: IconFileDesign, type: "design" },
|
|
56
|
-
ai: { icon: IconFileDesign, type: "design" },
|
|
57
|
-
eps: { icon: IconFileDesign, type: "design" },
|
|
58
|
-
indd: { icon: IconFileDesign, type: "design" },
|
|
59
|
-
idml: { icon: IconFileDesign, type: "design" },
|
|
60
|
-
sketch: { icon: IconFileDesign, type: "design" },
|
|
61
|
-
fig: { icon: IconFileDesign, type: "design" },
|
|
62
|
-
xd: { icon: IconFileDesign, type: "design" },
|
|
63
|
-
afphoto: { icon: IconFileDesign, type: "design" },
|
|
64
|
-
afdesign: { icon: IconFileDesign, type: "design" },
|
|
65
|
-
svg: { icon: IconFileDesign, type: "design" },
|
|
66
|
-
|
|
67
|
-
// proyectos de animación y edición de video
|
|
68
|
-
aep: { icon: IconFileMotion, type: "motion" },
|
|
69
|
-
prproj: { icon: IconFileMotion, type: "motion" },
|
|
70
46
|
// file pdf
|
|
71
47
|
pdf: { icon: IconFilePdf, type: "pdf" },
|
|
72
48
|
// file power point
|
|
@@ -84,7 +60,6 @@ export const IconFile = (props) => {
|
|
|
84
60
|
rar: { icon: IconFileZip, type: "zip" },
|
|
85
61
|
zip: { icon: IconFileZip, type: "zip" },
|
|
86
62
|
tar: { icon: IconFileZip, type: "zip" },
|
|
87
|
-
"7z": { icon: IconFileZip, type: "zip" },
|
|
88
63
|
|
|
89
64
|
// file code
|
|
90
65
|
xml: { icon: IconFileCode, type: "code" },
|
|
@@ -105,8 +80,6 @@ export const IconFile = (props) => {
|
|
|
105
80
|
// file video
|
|
106
81
|
avi: { icon: IconFileVideo, type: "video" },
|
|
107
82
|
mp4: { icon: IconFileVideo, type: "video" },
|
|
108
|
-
mov: { icon: IconFileVideo, type: "video" },
|
|
109
|
-
webm: { icon: IconFileVideo, type: "video" },
|
|
110
83
|
mpeg: { icon: IconFileVideo, type: "video" },
|
|
111
84
|
mpg: { icon: IconFileVideo, type: "video" },
|
|
112
85
|
wmv: { icon: IconFileVideo, type: "video" },
|
|
@@ -52,14 +52,6 @@ export const Container = styled.div`
|
|
|
52
52
|
color: #1c778e;
|
|
53
53
|
border-color: #1c778e;
|
|
54
54
|
}
|
|
55
|
-
&.icon-design .icon {
|
|
56
|
-
color: #2a5cb8;
|
|
57
|
-
border-color: #2a5cb8;
|
|
58
|
-
}
|
|
59
|
-
&.icon-motion .icon {
|
|
60
|
-
color: #6d3fc0;
|
|
61
|
-
border-color: #6d3fc0;
|
|
62
|
-
}
|
|
63
55
|
&.icon-video .icon {
|
|
64
56
|
color: #a15bb1;
|
|
65
57
|
border-color: #a15bb1;
|
|
@@ -26,41 +26,3 @@ ProductImageDefault.args = {
|
|
|
26
26
|
imageType: "main-image",
|
|
27
27
|
altText: "default image",
|
|
28
28
|
};
|
|
29
|
-
|
|
30
|
-
/*
|
|
31
|
-
Las escalas de video, lado a lado. Las cuatro primeras son miniaturas: sin
|
|
32
|
-
controles, con su duración y un botón de play, y todo el recuadro clicable.
|
|
33
|
-
Las dos últimas son reproductores de verdad.
|
|
34
|
-
*/
|
|
35
|
-
const VIDEO =
|
|
36
|
-
"https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4";
|
|
37
|
-
|
|
38
|
-
const Escala = ({ imageType }) => (
|
|
39
|
-
<figure style={{ margin: 0 }}>
|
|
40
|
-
<ProductImage
|
|
41
|
-
img={VIDEO}
|
|
42
|
-
ext="mp4"
|
|
43
|
-
imageType={imageType}
|
|
44
|
-
altText="video de producto"
|
|
45
|
-
onClick={() => console.log("clic en", imageType)}
|
|
46
|
-
/>
|
|
47
|
-
<figcaption style={{ fontFamily: "Lato", fontSize: 11, marginTop: 4 }}>
|
|
48
|
-
{imageType}
|
|
49
|
-
</figcaption>
|
|
50
|
-
</figure>
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
export const VideoMiniaturas = () => (
|
|
54
|
-
<div style={{ display: "flex", gap: 24, alignItems: "flex-start" }}>
|
|
55
|
-
<Escala imageType="carousel-image" />
|
|
56
|
-
<Escala imageType="catalogue-image-small-size" />
|
|
57
|
-
<Escala imageType="catalogue-modal-image" />
|
|
58
|
-
<Escala imageType="catalogue-image-big-size" />
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
export const VideoReproductor = () => (
|
|
63
|
-
<div style={{ display: "flex", gap: 24, alignItems: "flex-start" }}>
|
|
64
|
-
<Escala imageType="main-image" />
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
@@ -1,104 +1,29 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
import ReactImageFallback from "react-image-fallback";
|
|
3
|
-
|
|
4
1
|
import { Container } from "./styles";
|
|
5
|
-
import
|
|
6
|
-
ASSET_PREVIEW,
|
|
7
|
-
formatDuration,
|
|
8
|
-
resolvePreviewKind,
|
|
9
|
-
} from "../../../global-files/digital-assets/assetTypes";
|
|
2
|
+
import ReactImageFallback from "react-image-fallback";
|
|
10
3
|
import defaultProductImage from "../../../assets/images/defaultImages/defaultProductImage.png";
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
para ser usables; en un recuadro de 60 o de 85 se pintan encimados y no se
|
|
17
|
-
puede ni dar play. Peor aún, un <video> con controles se traga el clic, así
|
|
18
|
-
que un video en el carrusel no se podía ni seleccionar: `onClick` nunca
|
|
19
|
-
llegaba a correr.
|
|
20
|
-
|
|
21
|
-
En estos tamaños se muestra el primer fotograma con su duración y un botón de
|
|
22
|
-
play, y el recuadro completo lleva al visor grande, que es donde el video sí
|
|
23
|
-
se ve y se controla.
|
|
24
|
-
*/
|
|
25
|
-
const THUMBNAIL_TYPES = [
|
|
26
|
-
"carousel-image",
|
|
27
|
-
"catalogue-image-small-size",
|
|
28
|
-
"catalogue-image-big-size",
|
|
29
|
-
"catalogue-modal-image",
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
const PlayBadge = () => (
|
|
33
|
-
<span className="play-badge" aria-hidden="true">
|
|
34
|
-
<svg viewBox="0 0 24 24">
|
|
35
|
-
<circle cx="12" cy="12" r="11" />
|
|
36
|
-
<polygon points="9.5,7.5 17,12 9.5,16.5" />
|
|
37
|
-
</svg>
|
|
38
|
-
</span>
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Imagen —o video— de producto.
|
|
43
|
-
*
|
|
44
|
-
* El tipo de archivo se decide por `ext`/`mime` cuando quien llama los conoce.
|
|
45
|
-
* Antes se comprobaba con `/\.mp4$/` sobre la URL, y nunca acertaba: la URL
|
|
46
|
-
* guardada apunta al redimensionador de CloudFront y no conserva la extensión.
|
|
47
|
-
* El regex queda solo como respaldo para los llamadores que aún mandan `img`
|
|
48
|
-
* a secas.
|
|
49
|
-
*/
|
|
50
|
-
export const ProductImage = ({ img, imageType, altText, onClick, ext, mime, poster }) => {
|
|
51
|
-
// La duración no está en la base: se toma de los metadatos, que el navegador
|
|
52
|
-
// ya descarga por el `preload="metadata"`. No cuesta una petición extra.
|
|
53
|
-
const [duration, setDuration] = useState(null);
|
|
54
|
-
|
|
55
|
-
const kind =
|
|
56
|
-
ext || mime
|
|
57
|
-
? resolvePreviewKind({ ext, mime })
|
|
58
|
-
: /\.mp4($|[?#])/i.test(img || "")
|
|
59
|
-
? ASSET_PREVIEW.VIDEO
|
|
60
|
-
: ASSET_PREVIEW.IMAGE;
|
|
61
|
-
|
|
62
|
-
if (kind === ASSET_PREVIEW.VIDEO) {
|
|
63
|
-
const isThumbnail = THUMBNAIL_TYPES.includes(imageType);
|
|
64
|
-
|
|
5
|
+
export const ProductImage = ({ img, imageType, altText, onClick}) => {
|
|
6
|
+
// Expresión regular para validar que los últimos tres caracteres sean ".mp4"
|
|
7
|
+
const regex = /\.mp4$/;
|
|
8
|
+
if (regex.test(img)){
|
|
65
9
|
return (
|
|
66
|
-
<Container
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
10
|
+
<Container className={imageType}>
|
|
11
|
+
<video controls width="100%" height="auto">
|
|
12
|
+
<source src= {img} type="video/mp4" />
|
|
13
|
+
</video>
|
|
14
|
+
</Container>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
else{
|
|
18
|
+
return (
|
|
19
|
+
<Container className={imageType}>
|
|
20
|
+
<ReactImageFallback
|
|
21
|
+
src={img}
|
|
22
|
+
fallbackImage={defaultProductImage}
|
|
23
|
+
alt={altText}
|
|
24
|
+
onClick={onClick}
|
|
81
25
|
/>
|
|
82
|
-
{isThumbnail && (
|
|
83
|
-
<>
|
|
84
|
-
<PlayBadge />
|
|
85
|
-
{duration ? (
|
|
86
|
-
<span className="video-duration">{formatDuration(duration)}</span>
|
|
87
|
-
) : null}
|
|
88
|
-
</>
|
|
89
|
-
)}
|
|
90
26
|
</Container>
|
|
91
27
|
);
|
|
92
28
|
}
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<Container className={imageType}>
|
|
96
|
-
<ReactImageFallback
|
|
97
|
-
src={img}
|
|
98
|
-
fallbackImage={defaultProductImage}
|
|
99
|
-
alt={altText}
|
|
100
|
-
onClick={onClick}
|
|
101
|
-
/>
|
|
102
|
-
</Container>
|
|
103
|
-
);
|
|
104
29
|
};
|
|
@@ -1,92 +1,14 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
|
-
import { FontFamily } from "../../../global-files/variables";
|
|
3
2
|
|
|
4
3
|
export const Container = styled.div`
|
|
5
4
|
width: fit-content;
|
|
6
5
|
|
|
7
|
-
img
|
|
8
|
-
video {
|
|
6
|
+
img {
|
|
9
7
|
object-fit: contain;
|
|
10
8
|
}
|
|
11
9
|
|
|
12
|
-
/*
|
|
13
|
-
Miniatura de video: fotograma quieto, con su duración y un botón de play.
|
|
14
|
-
El clic lo recibe el contenedor, no el <video>, para que lleve al visor
|
|
15
|
-
grande en vez de quedarse peleando con los controles.
|
|
16
|
-
*/
|
|
17
|
-
&.video-thumbnail {
|
|
18
|
-
position: relative;
|
|
19
|
-
cursor: pointer;
|
|
20
|
-
|
|
21
|
-
video {
|
|
22
|
-
pointer-events: none;
|
|
23
|
-
background: #000;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.play-badge {
|
|
27
|
-
position: absolute;
|
|
28
|
-
top: 50%;
|
|
29
|
-
left: 50%;
|
|
30
|
-
transform: translate(-50%, -50%);
|
|
31
|
-
width: 32px;
|
|
32
|
-
height: 32px;
|
|
33
|
-
pointer-events: none;
|
|
34
|
-
|
|
35
|
-
svg {
|
|
36
|
-
width: 100%;
|
|
37
|
-
height: 100%;
|
|
38
|
-
display: block;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
circle {
|
|
42
|
-
fill: rgba(0, 0, 0, 0.55);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
polygon {
|
|
46
|
-
fill: #ffffff;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&:hover .play-badge circle {
|
|
51
|
-
fill: rgba(0, 0, 0, 0.75);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.video-duration {
|
|
55
|
-
position: absolute;
|
|
56
|
-
right: 4px;
|
|
57
|
-
bottom: 4px;
|
|
58
|
-
padding: 0 4px;
|
|
59
|
-
border-radius: 3px;
|
|
60
|
-
background: rgba(0, 0, 0, 0.75);
|
|
61
|
-
color: #ffffff;
|
|
62
|
-
font-family: ${FontFamily.Lato};
|
|
63
|
-
font-size: 10px;
|
|
64
|
-
line-height: 15px;
|
|
65
|
-
pointer-events: none;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/* En 60px un badge de 32 tapa el fotograma completo. */
|
|
70
|
-
&.catalogue-image-small-size.video-thumbnail .play-badge {
|
|
71
|
-
width: 20px;
|
|
72
|
-
height: 20px;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
&.carousel-image.video-thumbnail {
|
|
76
|
-
.play-badge {
|
|
77
|
-
width: 22px;
|
|
78
|
-
height: 22px;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.video-duration {
|
|
82
|
-
font-size: 9px;
|
|
83
|
-
line-height: 13px;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
10
|
&.carousel-image {
|
|
88
|
-
img
|
|
89
|
-
video {
|
|
11
|
+
img {
|
|
90
12
|
width: 85px;
|
|
91
13
|
height: 55px;
|
|
92
14
|
cursor: pointer;
|
|
@@ -98,8 +20,7 @@ export const Container = styled.div`
|
|
|
98
20
|
}
|
|
99
21
|
|
|
100
22
|
&.main-image {
|
|
101
|
-
img
|
|
102
|
-
video {
|
|
23
|
+
img {
|
|
103
24
|
width: 340px;
|
|
104
25
|
height: 295px;
|
|
105
26
|
}
|
|
@@ -109,16 +30,14 @@ export const Container = styled.div`
|
|
|
109
30
|
display: flex;
|
|
110
31
|
justify-content: center;
|
|
111
32
|
align-items: center;
|
|
112
|
-
img
|
|
113
|
-
video {
|
|
33
|
+
img {
|
|
114
34
|
width: 179px;
|
|
115
35
|
height: 179px;
|
|
116
36
|
}
|
|
117
37
|
}
|
|
118
38
|
|
|
119
39
|
&.catalogue-image-small-size {
|
|
120
|
-
img
|
|
121
|
-
video {
|
|
40
|
+
img {
|
|
122
41
|
width: 60px;
|
|
123
42
|
height: 60px;
|
|
124
43
|
}
|
|
@@ -128,9 +47,7 @@ export const Container = styled.div`
|
|
|
128
47
|
flex: 1 0 50%;
|
|
129
48
|
cursor: pointer;
|
|
130
49
|
|
|
131
|
-
img
|
|
132
|
-
|
|
133
|
-
video {
|
|
50
|
+
img {
|
|
134
51
|
width: 168px;
|
|
135
52
|
height: 108px;
|
|
136
53
|
}
|
|
@@ -143,9 +60,7 @@ export const Container = styled.div`
|
|
|
143
60
|
justify-content: center;
|
|
144
61
|
align-items: center;
|
|
145
62
|
|
|
146
|
-
img
|
|
147
|
-
|
|
148
|
-
video {
|
|
63
|
+
img {
|
|
149
64
|
width: 710px;
|
|
150
65
|
height: 710px;
|
|
151
66
|
}
|
|
@@ -2,10 +2,10 @@ import { Container } from "./styles";
|
|
|
2
2
|
import { ProductImage } from "../../atoms/ProductImage/index";
|
|
3
3
|
import { Button } from "../../atoms/GeneralButton/index";
|
|
4
4
|
|
|
5
|
-
export const EditionActiveImage = ({ img, altText, setShowModal
|
|
5
|
+
export const EditionActiveImage = ({ img, altText, setShowModal }) => {
|
|
6
6
|
return (
|
|
7
7
|
<Container>
|
|
8
|
-
<ProductImage img={img} imageType="main-image" altText={altText}
|
|
8
|
+
<ProductImage img={img} imageType="main-image" altText={altText} />
|
|
9
9
|
<Button
|
|
10
10
|
buttonType="open-modal-button"
|
|
11
11
|
onClick={() => setShowModal(true)}
|
|
@@ -25,7 +25,6 @@ export const GalleryElement = ({
|
|
|
25
25
|
auditImages,
|
|
26
26
|
compare,
|
|
27
27
|
updateApprovedInputsImages,
|
|
28
|
-
onSelect,
|
|
29
28
|
}) => {
|
|
30
29
|
const [showValidationPanel, setShowValidationPanel] = useState(false);
|
|
31
30
|
const [showDivStates, setShowDivStates] = useState({});
|
|
@@ -94,15 +93,7 @@ export const GalleryElement = ({
|
|
|
94
93
|
<ProductImage
|
|
95
94
|
img={compare ? auditImages?.values[number]?.src : image?.src}
|
|
96
95
|
altText={image?.altText}
|
|
97
|
-
// Sin `ext`, un video se pinta como <img> rota: la URL guardada no
|
|
98
|
-
// conserva la extensión del archivo.
|
|
99
|
-
ext={compare ? auditImages?.values[number]?.ext : image?.ext}
|
|
100
96
|
imageType={`catalogue-image-${gridLayout ? "big" : "small"}-size`}
|
|
101
|
-
// La miniatura de un video ya no lleva controles, así que el clic es
|
|
102
|
-
// la única forma de llegar al visor grande. Se aplica también a las
|
|
103
|
-
// imágenes: dos recuadros idénticos donde solo uno responde al clic
|
|
104
|
-
// sería peor que no responder ninguno.
|
|
105
|
-
onClick={onSelect}
|
|
106
97
|
/>
|
|
107
98
|
<div className="information-container">
|
|
108
99
|
<p>{image?.name}</p>
|
|
@@ -1,80 +1,28 @@
|
|
|
1
1
|
import { Container } from "./styles";
|
|
2
2
|
import { CheckBox } from "../../atoms/CheckBox";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
Las columnas de la bandeja dependen de qué se está listando: un PDF no tiene
|
|
6
|
-
"tipo de toma" ni alto por ancho, y una foto no tiene "tipo de activo".
|
|
7
|
-
Estaban escritas a mano en el marcado, así que la única forma de cambiarlas
|
|
8
|
-
era duplicar el componente.
|
|
9
|
-
|
|
10
|
-
El preset `image` reproduce exactamente las columnas y clases de antes, para
|
|
11
|
-
que la bandeja de imágenes se vea idéntica sin que nadie tenga que pasar nada.
|
|
12
|
-
*/
|
|
13
|
-
export const GALLERY_COLUMNS = {
|
|
14
|
-
image: {
|
|
15
|
-
template: "0.1fr 1fr 1fr 1fr 1fr 1fr",
|
|
16
|
-
columns: [
|
|
17
|
-
{ key: "preview", label: "Imagen", className: "image-header" },
|
|
18
|
-
{ key: "name", label: "Nombre", className: "image-name" },
|
|
19
|
-
{ key: "size", label: "Tamaño", className: "image-size" },
|
|
20
|
-
{ key: "format", label: "Formato", className: "image-format" },
|
|
21
|
-
{
|
|
22
|
-
key: "legend",
|
|
23
|
-
label: "¿Tiene leyenda?",
|
|
24
|
-
className: "image-description",
|
|
25
|
-
},
|
|
26
|
-
{ key: "shotType", label: "Tipo de toma", className: "shoot-type" },
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
asset: {
|
|
30
|
-
template: "0.1fr 1fr 1fr 1fr 1fr",
|
|
31
|
-
columns: [
|
|
32
|
-
{ key: "preview", label: "Activo", className: "asset-header" },
|
|
33
|
-
{ key: "name", label: "Nombre", className: "asset-name" },
|
|
34
|
-
{ key: "weight", label: "Peso", className: "asset-weight" },
|
|
35
|
-
{ key: "format", label: "Formato", className: "asset-format" },
|
|
36
|
-
{ key: "assetType", label: "Tipo de activo", className: "asset-type" },
|
|
37
|
-
],
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Encabezado de la bandeja, con su casilla de "seleccionar todo".
|
|
43
|
-
*
|
|
44
|
-
* `checkAllId` e `itemSelector` se pueden cambiar porque imágenes y activos
|
|
45
|
-
* conviven en la misma pestaña: si las dos listas compartieran el id de la
|
|
46
|
-
* casilla global, marcar todas las imágenes marcaría también los activos.
|
|
47
|
-
*/
|
|
48
|
-
export const GalleryHeader = ({
|
|
49
|
-
setCheckAll,
|
|
50
|
-
setSelectedImages,
|
|
51
|
-
shotThd,
|
|
52
|
-
variant = "image",
|
|
53
|
-
columns,
|
|
54
|
-
checkAllId = "check-all-images",
|
|
55
|
-
itemSelector = "[id^='gallery-element-']",
|
|
56
|
-
}) => {
|
|
57
|
-
const preset = GALLERY_COLUMNS[variant] ?? GALLERY_COLUMNS.image;
|
|
58
|
-
const visibleColumns = columns ?? preset.columns;
|
|
59
|
-
|
|
4
|
+
export const GalleryHeader = ({ setCheckAll, setSelectedImages, shotThd }) => {
|
|
60
5
|
const checkAll = (e) => {
|
|
61
|
-
const checkboxList = document.querySelectorAll(
|
|
6
|
+
const checkboxList = document.querySelectorAll("[id^='gallery-element-']");
|
|
62
7
|
checkboxList.forEach((chk) => (chk.checked = e.target.checked));
|
|
63
8
|
setCheckAll(e.target.checked);
|
|
64
9
|
if (!e.target.checked) setSelectedImages([]);
|
|
65
10
|
};
|
|
66
|
-
|
|
67
11
|
return (
|
|
68
|
-
<Container
|
|
12
|
+
<Container>
|
|
69
13
|
<div className="checkbox">
|
|
70
|
-
<CheckBox id=
|
|
14
|
+
<CheckBox id="check-all-images" onChange={(e) => checkAll(e)} />
|
|
71
15
|
</div>
|
|
72
16
|
<div className="information">
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
17
|
+
<p className="image-header">Imagen</p>
|
|
18
|
+
<p className="image-name">Nombre</p>
|
|
19
|
+
<p className="image-size">Tamaño</p>
|
|
20
|
+
<p className="image-format">Formato</p>
|
|
21
|
+
<p className="image-description">¿Tiene leyenda?</p>
|
|
22
|
+
<p className="shoot-type">Tipo de toma</p>
|
|
23
|
+
{/* <p className="">Tipo de imagen</p> */}
|
|
24
|
+
{/* <p className="">Tipo de empaque</p> */}
|
|
25
|
+
{/* <p className="">Estatus</p> */}
|
|
78
26
|
</div>
|
|
79
27
|
</Container>
|
|
80
28
|
);
|
|
@@ -15,8 +15,7 @@ export const Container = styled.div`
|
|
|
15
15
|
.information{
|
|
16
16
|
width: 90%;
|
|
17
17
|
display: grid;
|
|
18
|
-
|
|
19
|
-
grid-template-columns: ${({ template }) => template || "0.1fr 1fr 1fr 1fr 1fr 1fr"};
|
|
18
|
+
grid-template-columns: 0.1fr 1fr 1fr 1fr 1fr 1fr;
|
|
20
19
|
}
|
|
21
20
|
.image-header{
|
|
22
21
|
|
|
@@ -40,6 +40,9 @@ const UMBRAL_SEGUNDO_PLANO = 20;
|
|
|
40
40
|
|
|
41
41
|
export const PropagateChangesModal = ({
|
|
42
42
|
changedAttributes: cambiosRecibidos = [],
|
|
43
|
+
// Qué se está propagando. El componente sirve a las dos pestañas y solo
|
|
44
|
+
// cambia cómo se nombra lo que el usuario acaba de editar.
|
|
45
|
+
kind = "datasheet",
|
|
43
46
|
variants = [],
|
|
44
47
|
groupMembers = [],
|
|
45
48
|
groupCode = null,
|
|
@@ -56,6 +59,10 @@ export const PropagateChangesModal = ({
|
|
|
56
59
|
*/
|
|
57
60
|
const changedAttributes = soloPropagables(cambiosRecibidos);
|
|
58
61
|
|
|
62
|
+
const esDescripcion = kind === "description";
|
|
63
|
+
const sustantivo = esDescripcion ? "descripción" : "atributo";
|
|
64
|
+
const plural = esDescripcion ? "descripciones" : "atributos";
|
|
65
|
+
|
|
59
66
|
const [chosenAttributes, setChosenAttributes] = useState([]);
|
|
60
67
|
|
|
61
68
|
/*
|
|
@@ -177,9 +184,9 @@ export const PropagateChangesModal = ({
|
|
|
177
184
|
{" pueden recibir este cambio"}
|
|
178
185
|
</h2>
|
|
179
186
|
<p>
|
|
180
|
-
Cambiaste {changedAttributes.length}
|
|
181
|
-
{changedAttributes.length === 1 ?
|
|
182
|
-
a quiénes; el resto se guarda solo en este producto.
|
|
187
|
+
Cambiaste {changedAttributes.length}{" "}
|
|
188
|
+
{changedAttributes.length === 1 ? sustantivo : plural}. Elige cuáles
|
|
189
|
+
se copian y a quiénes; el resto se guarda solo en este producto.
|
|
183
190
|
</p>
|
|
184
191
|
</Header>
|
|
185
192
|
|
package/src/components/pages/ProviderProductEdition/context/provider-product-edition.context.jsx
CHANGED
|
@@ -49,7 +49,7 @@ export const useProviderProductEdition = () => {
|
|
|
49
49
|
export const ProviderProductEditionProvider = ({ children }) => {
|
|
50
50
|
const [state, dispatch] = useReducer(productEditionReducer, initialState);
|
|
51
51
|
|
|
52
|
-
const saveDescriptions = async (token) => {
|
|
52
|
+
const saveDescriptions = async (token, propagation) => {
|
|
53
53
|
if (state.updated_descriptions_inputs.length === 0) return;
|
|
54
54
|
|
|
55
55
|
dispatch({ type: "SET_SAVING", payload: true });
|
|
@@ -57,6 +57,7 @@ export const ProviderProductEditionProvider = ({ children }) => {
|
|
|
57
57
|
const dataObject = {
|
|
58
58
|
articleId: state.product?.id_article,
|
|
59
59
|
articleData: state.updated_descriptions_inputs,
|
|
60
|
+
...(propagation ? { propagation } : {}),
|
|
60
61
|
};
|
|
61
62
|
|
|
62
63
|
// Marcar todos los items como aprobados
|