fix(BOOK-478): convert to image vault asset and remove useEffect max depth error

This commit is contained in:
Bianca Widstam
2025-11-27 10:56:32 +01:00
parent 1337e8293f
commit 4a0f8f4721
3 changed files with 34 additions and 30 deletions

View File

@@ -7,16 +7,12 @@ import {
FieldLabel, FieldLabel,
cbModal, cbModal,
} from "@contentstack/venus-components" } from "@contentstack/venus-components"
import { import { isInsertResponse, openImageVault } from "~/utils/imagevault"
getImageVaultAssetFromData,
isInsertResponse,
openImageVault,
} from "~/utils/imagevault"
import ImageEditModal from "./ImageEditModal" import ImageEditModal from "./ImageEditModal"
import type UiLocation from "@contentstack/app-sdk/dist/src/uiLocation" import type UiLocation from "@contentstack/app-sdk/dist/src/uiLocation"
import type { CbModalProps } from "@contentstack/venus-components/build/components/Modal/Modal" import type { CbModalProps } from "@contentstack/venus-components/build/components/Modal/Modal"
import type { ImageVaultAsset, InsertResponse } from "~/types/imagevault" import type { ImageVaultAsset } from "~/types/imagevault"
import type { Lang } from "~/types/lang" import type { Lang } from "~/types/lang"
import type { import type {
EntryDataPublishDetails, EntryDataPublishDetails,
@@ -27,7 +23,7 @@ import FullSizeImage from "./FullSizeImage"
export type ImageVaultDAMProps = { export type ImageVaultDAMProps = {
sdk: UiLocation sdk: UiLocation
config: ImageVaultDAMConfig config: ImageVaultDAMConfig
initialData: ImageVaultAsset | InsertResponse | null imageVaultAsset: ImageVaultAsset | null
} }
type DAMButtonProps = { onClick: () => void } type DAMButtonProps = { onClick: () => void }
@@ -115,9 +111,8 @@ function Media({ media, onDelete, onEdit }: MediaProps) {
export default function ImageVaultDAM({ export default function ImageVaultDAM({
sdk, sdk,
config, config,
initialData, imageVaultAsset,
}: ImageVaultDAMProps) { }: ImageVaultDAMProps) {
const imageVaultAsset = getImageVaultAssetFromData(initialData)
const [media, setMedia] = useState(imageVaultAsset) const [media, setMedia] = useState(imageVaultAsset)
const field = sdk.location.CustomField?.field const field = sdk.location.CustomField?.field
@@ -176,18 +171,16 @@ export default function ImageVaultDAM({
updateFrameHeight() updateFrameHeight()
}, [updateFrameHeight]) }, [updateFrameHeight])
// The existing data might still be in InsertResponse format if the user has not edited it yet.
// We'll convert it to ImageVaultAsset when the user edits the the emtry.
useEffect(() => {
if (isInsertResponse(initialData) && imageVaultAsset) {
handleMedia(imageVaultAsset)
}
}, [initialData, imageVaultAsset, handleMedia])
if (!field || !frame || !entry || !stack) { if (!field || !frame || !entry || !stack) {
return <p>Initializing custom field...</p> return <p>Initializing custom field...</p>
} }
const fieldData = field.getData()
if (isInsertResponse(fieldData)) {
field.setData(imageVaultAsset)
}
const entryData: EntryDataPublishDetails = { const entryData: EntryDataPublishDetails = {
//TODO: Add support for branches //TODO: Add support for branches
branch: "main", branch: "main",

View File

@@ -9,8 +9,11 @@ import InvalidConfig from "~/components/InvalidConfig"
import { GenericObjectType } from "@contentstack/app-sdk/dist/src/types/common.types" import { GenericObjectType } from "@contentstack/app-sdk/dist/src/types/common.types"
import UiLocation from "@contentstack/app-sdk/dist/src/uiLocation" import UiLocation from "@contentstack/app-sdk/dist/src/uiLocation"
import type { InsertResponse } from "~/types/imagevault" import type { ImageVaultAsset, InsertResponse } from "~/types/imagevault"
import { isImageVaultDAMConfig } from "~/utils/imagevault" import {
getImageVaultAssetFromData,
isImageVaultDAMConfig,
} from "~/utils/imagevault"
const ImageVaultDAM = lazy(() => import("~/components/ImageVaultDAM")) const ImageVaultDAM = lazy(() => import("~/components/ImageVaultDAM"))
@@ -25,7 +28,9 @@ function FieldContent({ sdk, appConfig }: FieldContentProps) {
) )
const [showDisclaimer, setShowDisclaimer] = useState(false) const [showDisclaimer, setShowDisclaimer] = useState(false)
const [fieldData, setFieldData] = useState<InsertResponse | null>() const [fieldData, setFieldData] = useState<
InsertResponse | ImageVaultAsset | null
>()
const [dataIsLoaded, setDataIsLoaded] = useState(false) const [dataIsLoaded, setDataIsLoaded] = useState(false)
const entry = sdk?.location.CustomField?.entry const entry = sdk?.location.CustomField?.entry
@@ -76,9 +81,17 @@ function FieldContent({ sdk, appConfig }: FieldContentProps) {
const fieldConfig = sdk.location.CustomField?.fieldConfig const fieldConfig = sdk.location.CustomField?.fieldConfig
const config = { ...appConfig, ...fieldConfig } const config = { ...appConfig, ...fieldConfig }
// The existing data might still be in InsertResponse format if the user has not edited it yet.
// We'll convert it to ImageVaultAsset when the user edits the the entry.
const imageVaultAsset = getImageVaultAssetFromData(initialData)
return ( return (
<Suspense fallback={<p>Loading field...</p>}> <Suspense fallback={<p>Loading field...</p>}>
<ImageVaultDAM config={config} sdk={sdk} initialData={initialData} /> <ImageVaultDAM
config={config}
sdk={sdk}
imageVaultAsset={imageVaultAsset}
/>
</Suspense> </Suspense>
) )
} }

View File

@@ -1,5 +1,5 @@
import { Icon, Tooltip, cbModal } from "@contentstack/venus-components" import { Icon, Tooltip, cbModal } from "@contentstack/venus-components"
import React, { PropsWithChildren, useCallback, useEffect } from "react" import React, { PropsWithChildren, useCallback } from "react"
import EmbedBtn from "./EmbedBtn" import EmbedBtn from "./EmbedBtn"
import ImageEditModal from "./ImageEditModal" import ImageEditModal from "./ImageEditModal"
@@ -19,6 +19,7 @@ type ImageElementProps = PropsWithChildren & {
rte: IRteParam rte: IRteParam
} }
export function ImageElement({ children, element, rte }: ImageElementProps) { export function ImageElement({ children, element, rte }: ImageElementProps) {
const isAssetInsertResponse = isInsertResponse(element.attrs)
const imageVaultAsset = getImageVaultAssetFromData(element.attrs) const imageVaultAsset = getImageVaultAssetFromData(element.attrs)
const isSelected = rte.selection.isSelected() const isSelected = rte.selection.isSelected()
const isFocused = rte.selection.isFocused() const isFocused = rte.selection.isFocused()
@@ -62,14 +63,6 @@ export function ImageElement({ children, element, rte }: ImageElementProps) {
}) })
}, [element, handleMedia]) }, [element, handleMedia])
// The existing data might still be in InsertResponse format if the user has not edited it yet.
// We'll convert it to ImageVaultAsset when the user edits the RTE.
useEffect(() => {
if (isInsertResponse(element.attrs) && imageVaultAsset) {
handleMedia(imageVaultAsset)
}
}, [element.attrs, imageVaultAsset, handleMedia])
const ToolTipButtons = () => { const ToolTipButtons = () => {
return ( return (
<div contentEditable={false} className="embed--btn-group"> <div contentEditable={false} className="embed--btn-group">
@@ -91,6 +84,11 @@ export function ImageElement({ children, element, rte }: ImageElementProps) {
if (!imageVaultAsset) { if (!imageVaultAsset) {
return <>{children}</> return <>{children}</>
} }
// The existing data might still be in InsertResponse format if the user has not edited it yet.
// We'll convert it to ImageVaultAsset when the user edits the RTE.
if (isAssetInsertResponse) {
handleMedia(imageVaultAsset)
}
return ( return (
<Tooltip <Tooltip