Files
contentstack-imagevault/rte/components/ImageEditModal.tsx
2024-03-26 13:03:24 +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>
</>
)
}