Files
contentstack-imagevault/rte/components/ImageEditModal.tsx
2024-03-26 11:53:20 +01:00

214 lines
4.8 KiB
TypeScript

import React, { useState, useEffect, ChangeEvent } from 'react';
import {
ModalFooter,
ModalBody,
ModalHeader,
ButtonGroup,
Button,
Field,
FieldLabel,
TextInput,
Select,
} from '@contentstack/venus-components';
import { Path } from 'slate';
import type {
IRteParam,
IRteElementType,
} from '@contentstack/app-sdk/dist/src/RTE/types';
import type { InsertResponse } from "~/types/imagevault";
enum DropdownValues {
center = "center",
left = "left",
right = "right",
none = "none",
}
type DropDownItem = {
label: string;
value: DropdownValues;
type: string;
};
const dropdownList: DropDownItem[] = [
{
label: "None",
value: DropdownValues.none,
type: "select",
},
{
label: "Center",
value: DropdownValues.center,
type: "select",
},
{
label: "Left",
value: DropdownValues.left,
type: "select",
},
{
label: "Right",
value: DropdownValues.right,
type: "select",
},
];
type ImageEditModalProps = {
element: IRteElementType & {
attrs: InsertResponse;
};
rte: IRteParam;
closeModal: () => void;
path: Path;
};
export default function ImageEditModal({
element,
closeModal,
path,
rte,
}: ImageEditModalProps) {
const [alignment, setAlignment] = useState<DropDownItem>({
label: "None",
value: DropdownValues.none,
type: "select",
});
const [altText, setAltText] = useState("");
const [caption, setCaption] = useState("");
const assetUrl = element.attrs.MediaConversions[0].Url;
useEffect(() => {
if (element.attrs.Metadata && element.attrs.Metadata.length) {
const altText = element.attrs.Metadata.find((meta) =>
meta.Name.includes("AltText_")
)?.Value;
const caption = element.attrs.Metadata.find((meta) =>
meta.Name.includes("Title_")
)?.Value;
setAltText(altText ?? "");
setCaption(caption ?? "");
}
}, [element.attrs.Metadata]);
function handleSave() {
let newStyle;
switch (alignment.value) {
case DropdownValues.center:
case DropdownValues.left:
case DropdownValues.right:
newStyle = {
textAlign: alignment.value,
maxWidth: element.attrs.width
? `${element.attrs.width}px`
: undefined,
};
break;
case DropdownValues.none:
default:
newStyle = {};
break;
}
const metaData = element.attrs.Metadata ?? [];
const newMetadata = metaData.map((meta) => {
if (meta.Name.includes("AltText_")) {
return { ...meta, Value: altText };
}
if (meta.Name.includes("Title_")) {
return { ...meta, Value: caption };
}
return meta;
});
rte._adv.Transforms?.setNodes<IRteElementType>(
rte._adv.editor,
{
attrs: {
...element.attrs,
Metadata: newMetadata,
position: alignment.value,
style: { ...element.attrs.style, ...newStyle },
},
},
{ at: path }
);
closeModal();
}
return (
<>
<ModalHeader title="Update image" closeModal={closeModal} />
<ModalBody
style={{
display: "flex",
gap: "1rem",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
}}
>
<div style={{ flex: 1, overflowY: "auto" }}>
<img
src={assetUrl}
alt={altText}
height="100%"
style={{ maxHeight: "345px" }}
/>
</div>
<div style={{ flex: 1 }}>
<Field>
<Select
selectLabel="Alignment"
value={alignment}
onChange={(e: DropDownItem) => {
setAlignment(e);
}}
options={dropdownList}
/>
</Field>
<Field>
<FieldLabel htmlFor="alt">Alt text</FieldLabel>
<TextInput
value={altText}
placeholder="Alt text for image"
name="alt"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setAltText(e.target.value)
}
/>
</Field>
<Field>
<FieldLabel htmlFor="caption">Caption</FieldLabel>
<TextInput
value={caption}
placeholder="Caption for image..."
name="caption"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setCaption(e.target.value)
}
/>
</Field>
</div>
</ModalBody>
<ModalFooter>
<ButtonGroup>
<Button onClick={closeModal} buttonType="light">
Cancel
</Button>
<Button onClick={handleSave} icon="SaveWhite">
Save
</Button>
</ButtonGroup>
</ModalFooter>
</>
);
}