104 lines
3.1 KiB
TypeScript
104 lines
3.1 KiB
TypeScript
import "@contentstack/venus-components/build/main.css"
|
|
|
|
import { Suspense, lazy, useEffect, useState } from "react"
|
|
import { useScript } from "usehooks-ts"
|
|
import useApp from "~/hooks/useApp"
|
|
|
|
import Disclaimer from "~/components/Disclaimer"
|
|
import InvalidConfig from "~/components/InvalidConfig"
|
|
|
|
import { GenericObjectType } from "@contentstack/app-sdk/dist/src/types/common.types"
|
|
import UiLocation from "@contentstack/app-sdk/dist/src/uiLocation"
|
|
import type { ImageVaultAsset, InsertResponse } from "~/types/imagevault"
|
|
import {
|
|
getImageVaultAssetFromData,
|
|
isImageVaultDAMConfig,
|
|
} from "~/utils/imagevault"
|
|
|
|
const ImageVaultDAM = lazy(() => import("~/components/ImageVaultDAM"))
|
|
|
|
interface FieldContentProps {
|
|
sdk?: UiLocation
|
|
appConfig?: GenericObjectType
|
|
}
|
|
|
|
function FieldContent({ sdk, appConfig }: FieldContentProps) {
|
|
const ivStatus = useScript(
|
|
"/scripts/imagevault-insert-media/insertmediawindow.min.js"
|
|
)
|
|
|
|
const [showDisclaimer, setShowDisclaimer] = useState(false)
|
|
const [fieldData, setFieldData] = useState<
|
|
InsertResponse | ImageVaultAsset | null
|
|
>()
|
|
const [dataIsLoaded, setDataIsLoaded] = useState(false)
|
|
|
|
const entry = sdk?.location.CustomField?.entry
|
|
const field = sdk?.location.CustomField?.field
|
|
|
|
useEffect(() => {
|
|
// If we can get field data from the SDK that means the entry has been
|
|
// saved at least once. If this is true, we are guaranteed entry UID.
|
|
// Entry that has not been saved does not have a entry UID and therefore
|
|
// cannot be referred to by ImageVault. Entry title is also required by us.
|
|
try {
|
|
if (field && entry) {
|
|
const data = field.getData()
|
|
const title = entry.getField("title").getData().toString()
|
|
if (!title) {
|
|
throw new Error("Missing title for entry")
|
|
}
|
|
|
|
if (data) {
|
|
setFieldData(data as InsertResponse)
|
|
}
|
|
|
|
setDataIsLoaded(true)
|
|
}
|
|
} catch (e) {
|
|
setShowDisclaimer(true)
|
|
console.log("Unable to get field data from SDK: ", e)
|
|
}
|
|
}, [entry, field])
|
|
|
|
if (showDisclaimer) {
|
|
return <Disclaimer />
|
|
}
|
|
|
|
const loaded = !!(dataIsLoaded && ivStatus === "ready" && sdk && appConfig)
|
|
|
|
const initialData =
|
|
fieldData && Object.keys(fieldData).length > 0 ? fieldData : null
|
|
|
|
if (!loaded) {
|
|
return <p style={{ fontFamily: "Inter" }}> Loading dependencies...</p>
|
|
}
|
|
|
|
if (!isImageVaultDAMConfig(appConfig)) {
|
|
return <InvalidConfig />
|
|
}
|
|
|
|
const fieldConfig = sdk.location.CustomField?.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 component mounts.
|
|
const imageVaultAsset = getImageVaultAssetFromData(initialData)
|
|
|
|
return (
|
|
<Suspense fallback={<p>Loading field...</p>}>
|
|
<ImageVaultDAM config={config} sdk={sdk} initialData={imageVaultAsset} />
|
|
</Suspense>
|
|
)
|
|
}
|
|
|
|
export default function Field() {
|
|
const { sdk, config, ref } = useApp()
|
|
|
|
return (
|
|
<div ref={ref}>
|
|
<FieldContent sdk={sdk} appConfig={config} />
|
|
</div>
|
|
)
|
|
}
|