Files
contentstack-imagevault/utils/imagevault.ts

188 lines
5.1 KiB
TypeScript

import { langEnum } from "../types/lang"
import type { GenericObjectType } from "@contentstack/app-sdk/dist/src/types/common.types"
import type {
Config,
FocalPoint,
ImageVaultAsset,
InsertResponse,
PublishDetails,
} from "../types/imagevault"
import type { Lang } from "../types/lang"
const metaIds = {
[langEnum.de]: { altText: 68, title: 77 },
[langEnum.da]: { altText: 67, title: 76 },
[langEnum.fi]: { altText: 70, title: 78 },
[langEnum.no]: { altText: 71, title: 79 },
[langEnum.sv]: { altText: 74, title: 82 },
[langEnum.en]: { altText: 69, title: 65 },
}
export function getMetaIds(lang: Lang) {
return metaIds[lang]
}
export type EntryDataPublishDetails = {
branch: string
contentTypeUid: string
locale: Lang
stackApiKey: string
title: string
uid: string
}
export function getPublishDetails(
baseUrl: string,
{
branch,
contentTypeUid,
locale,
stackApiKey,
title,
uid,
}: EntryDataPublishDetails
): PublishDetails {
const text = `${title} (${uid})`
const url = `${baseUrl}#!/stack/${stackApiKey}/content-type/${contentTypeUid}/${locale}/entry/${uid}/edit?branch=${branch}`
return { text, url }
}
export function isInsertResponse(
res: InsertResponse | GenericObjectType | null | undefined
): res is InsertResponse {
return (res as InsertResponse)?.MediaConversions !== undefined
}
export function isImageVaultAsset(
res: ImageVaultAsset | InsertResponse | GenericObjectType | null | undefined
): res is ImageVaultAsset {
return (res as ImageVaultAsset)?.url !== undefined
}
export type ImageVaultDAMConfig = {
imageVaultUrl: string
baseUrl: string
formatId: string
}
export function isImageVaultDAMConfig(
config: Record<string, string>
): config is ImageVaultDAMConfig {
return !!(config.baseUrl && config.formatId && config.imageVaultUrl)
}
// Utility function to get ImageVaultAsset from either InsertResponse or ImageVaultAsset
// Because we currently have both types saved in Contentstack, we need to account for both when retrieving the data of the asset.
export function getImageVaultAssetFromData(
data: InsertResponse | ImageVaultAsset | GenericObjectType | null | undefined
): ImageVaultAsset | null {
if (isImageVaultAsset(data)) {
return data
}
if (isInsertResponse(data)) {
return mapInsertResponseToImageVaultAsset(data, { x: 50, y: 50 })
}
return null
}
// Utility function to convert InsertResponse to ImageVaultAsset
function mapInsertResponseToImageVaultAsset(
response: InsertResponse,
focalPoint: FocalPoint
): ImageVaultAsset {
let image = response.MediaConversions.find(
(conversion) =>
conversion.MediaFormatName === "Original" &&
conversion.ContentType === "image/jpeg"
)
// We only receive one alt and title is in the response, depending on the language of the entry
// This is why we're getting the first one found
const alt =
response.Metadata?.find((meta) => meta.Name.includes("AltText_"))?.Value ||
""
const caption =
response.Metadata?.find((meta) => meta.Name.includes("Title_"))?.Value || ""
if (!image) {
const imageAsJpeg = response.MediaConversions.find(
(conversion) => conversion.ContentType === "image/jpeg"
)
image = imageAsJpeg || response.MediaConversions[0]
}
return {
imageVaultId: response.Id,
url: image.Url,
meta: {
alt,
caption,
},
fileName: response.Name,
dimensions: {
width: image.Width,
height: image.Height,
aspectRatio: image.AspectRatio,
},
focalPoint: response.FocalPoint || focalPoint,
}
}
export type openImageVaultParams = {
config: ImageVaultDAMConfig
entryData: EntryDataPublishDetails
onSuccess: (result: ImageVaultAsset) => void
onClose?: () => void
}
export function openImageVault({
config,
entryData,
onSuccess,
onClose,
}: openImageVaultParams) {
if (window.ImageVault) {
const publishDetails = getPublishDetails(config.baseUrl, entryData)
const metaIdsForLocale = getMetaIds(entryData.locale)
const insertMediaWindowOptions: Config = {
imageVaultUiUrl: config.imageVaultUrl,
uiLang: "en",
pageLang: "en",
publishingSource: config.baseUrl,
mediaUrlBase: config.imageVaultUrl,
formatId: config.formatId,
publishDetails,
insertMultiple: false,
success: (result) => {
const imageVaultAsset = mapInsertResponseToImageVaultAsset(
result.response,
{ x: 50, y: 50 }
)
onSuccess(imageVaultAsset)
},
close: () => {
if (typeof onClose === "function") {
onClose()
}
windowInserter.containerWindow?.close()
},
}
if (metaIdsForLocale) {
const additionalMetadataIds = Object.values(metaIdsForLocale).join(",")
insertMediaWindowOptions.additionalMetadataIds = additionalMetadataIds
}
const windowInserter = new window.ImageVault.InsertMediaWindow(
insertMediaWindowOptions,
`left=0,top=0,width=${window.screen.width},height=${window.screen.height}`
)
windowInserter.openImageVault()
} else {
console.error("Missing ImageVault global. ImageVault script not loaded?")
}
}