feat: Contentstack <-> ImageVault integration

This commit is contained in:
Michael Zetterberg
2024-03-25 11:38:14 +01:00
parent 920cbf241a
commit a706b9cf8a
39 changed files with 16647 additions and 0 deletions

149
utils/imagevault.ts Normal file
View File

@@ -0,0 +1,149 @@
import { langEnum } from '../types/lang';
import type { GenericObjectType } from '@contentstack/app-sdk/dist/src/types/common.types';
import type { Lang } from '../types/lang';
import type {
Config,
ImageVaultAsset,
InsertResponse,
PublishDetails,
} from "../types/imagevault";
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
): res is InsertResponse {
return (res as InsertResponse).MediaConversions !== 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 convert InsertResponse to ImageVaultAsset, used mainly for custom field images
// For RTE this function is not enough since rte:s also need attrs, like position and the size thats
// chosen in the editor
export function insertResponseToImageVaultAsset(
response: InsertResponse
): ImageVaultAsset {
const alt = response.Metadata?.find((meta) =>
meta.Name.includes("AltText_")
)?.Value;
const caption = response.Metadata?.find((meta) =>
meta.Name.includes("Title_")
)?.Value;
return {
url: response.MediaConversions[0].Url,
id: response.Id,
meta: {
alt,
caption,
},
title: response.Name,
dimensions: {
width: response.MediaConversions[0].Width,
height: response.MediaConversions[0].Height,
aspectRatio: response.MediaConversions[0].FormatAspectRatio,
},
};
}
export type openImageVaultParams = {
config: ImageVaultDAMConfig;
entryData: EntryDataPublishDetails;
onSuccess: (result: InsertResponse) => 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) => {
onSuccess(result.response);
},
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?");
}
}