commit change
This commit is contained in:
parent
01cf2238c4
commit
0775616991
|
@ -25,6 +25,7 @@ import {
|
|||
Person,
|
||||
} from '@microsoft/mgt-react/dist/es6/spfx';
|
||||
|
||||
import { useImageUtils } from '../../hooks/useImageUtils';
|
||||
import { RenderCardFooter } from './RenderCardFooter';
|
||||
import { useItemStyles } from './useItemStyles';
|
||||
|
||||
|
@ -36,10 +37,18 @@ export const RenderItemTemplate: React.FunctionComponent<IListItemTemplateProps>
|
|||
props: React.PropsWithChildren<IListItemTemplateProps>
|
||||
) => {
|
||||
const { resource } = props.dataContext;
|
||||
const { fields, lastModifiedBy, lastModifiedDateTime, webUrl, thumbnail } = resource;
|
||||
const { title, description, siteTitle } = fields;
|
||||
const { fields, lastModifiedBy, lastModifiedDateTime, webUrl } = resource;
|
||||
const { title, description, bannerImageUrlOWSURLH, siteTitle } = fields;
|
||||
const styles = useItemStyles();
|
||||
const [imageUrl] = React.useState<string>(thumbnail?.url);
|
||||
const { getPictureThumbnailUrl } = useImageUtils();
|
||||
const [imageUrl, setImageUrl] = React.useState<string>("");
|
||||
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
const url = await getPictureThumbnailUrl(bannerImageUrlOWSURLH.split(",")[0]);
|
||||
setImageUrl(url);
|
||||
})();
|
||||
}, [imageUrl]);
|
||||
|
||||
const localeDate = React.useMemo(() => {
|
||||
return format(parseISO(lastModifiedDateTime), "PPP");
|
||||
|
@ -65,24 +74,27 @@ export const RenderItemTemplate: React.FunctionComponent<IListItemTemplateProps>
|
|||
<Card className={styles.card} size="large">
|
||||
<header className={styles.cardHeader}>
|
||||
<div className={styles.personContainer}>
|
||||
|
||||
<Person
|
||||
personQuery={lastModifiedBy.user.email}
|
||||
showPresence
|
||||
view={4}
|
||||
avatarSize="small"
|
||||
personCardInteraction={PersonCardInteraction.hover}
|
||||
>
|
||||
<PersonTemplateLine1 template="line1" />
|
||||
<PersonTemplateLine2 template="line2" />
|
||||
</Person>
|
||||
<div style={{ width: 40, height: 40 }}> {/* bug with person card on Teams App mobile need to specify with and heigt*/}
|
||||
<Person
|
||||
personQuery={lastModifiedBy.user.email}
|
||||
showPresence
|
||||
view={4}
|
||||
avatarSize="small"
|
||||
personCardInteraction={PersonCardInteraction.hover}
|
||||
>
|
||||
<PersonTemplateLine1 template="line1" />
|
||||
<PersonTemplateLine2 template="line2" />
|
||||
</Person>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className={styles.badgeContainer}>
|
||||
<Badge color="brand" shape="rounded" appearance="tint">
|
||||
{siteTitle}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<Image fit="cover" src={imageUrl} style={{ height: 100 }} />
|
||||
<Link appearance="subtle" href={webUrl} target="_blank">
|
||||
<Body1Strong className={styles.cardTextSubject} title={title}>
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { useCallback } from 'react';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import {
|
||||
DATA_IMAGE,
|
||||
MS_TEAMS_IMAGE_WIDTH,
|
||||
} from '../constants/constants';
|
||||
import { FileInfo } from '../models/IFileInfo';
|
||||
import { useCache } from './useLocalStorage';
|
||||
import { usePnPjs } from './usePnPjs';
|
||||
|
||||
export const useImageUtils = () => {
|
||||
const { getSPFileInfo } = usePnPjs();
|
||||
const {getCacheValue, setCacheValue} = useCache("local");
|
||||
|
||||
const getImageBase64 = useCallback(async (pictureUrl: string): Promise<string> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const image = new Image();
|
||||
image.crossOrigin = "anonymous";
|
||||
image.addEventListener("load", () => {
|
||||
const tempCanvas = document.createElement("canvas");
|
||||
tempCanvas.width = image.width;
|
||||
tempCanvas.height = image.height;
|
||||
tempCanvas.getContext("2d").drawImage(image, 0, 0);
|
||||
let base64Str;
|
||||
try {
|
||||
base64Str = tempCanvas.toDataURL("image/png");
|
||||
} catch (err) {
|
||||
if (DEBUG) {
|
||||
console.error(`[ImageService.getBase64Image]: Err='${err.message}'`);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
resolve(base64Str);
|
||||
});
|
||||
image.src = pictureUrl;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const isBase64Image = useCallback((data: string) => {
|
||||
return !isEmpty(data) && data.indexOf(DATA_IMAGE) >= 0;
|
||||
}, []);
|
||||
|
||||
const getBase64ImageFromDOMImg = useCallback((imgElementId: string): string => {
|
||||
try {
|
||||
const imgElement = document.getElementById(imgElementId) as any;
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = imgElement.width;
|
||||
canvas.height = imgElement.height;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(imgElement, 0, 0);
|
||||
const dataURL = canvas.toDataURL("image/png");
|
||||
|
||||
return dataURL;
|
||||
} catch (err) {
|
||||
if (DEBUG) {
|
||||
console.error(`[getBase64ImageFromDOMImg]: Err='${err.message}'`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const isSharePointImage = useCallback((fileUrl: string) => {
|
||||
return !isEmpty(fileUrl) && fileUrl.indexOf(window.location.origin) >= 0;
|
||||
}, []);
|
||||
|
||||
const isStockImage = useCallback((fileUrl: string) => {
|
||||
return !isEmpty(fileUrl) && fileUrl.indexOf("cdn.hubblecontent.osi.office.net") > 0;
|
||||
}, []);
|
||||
|
||||
const getPictureThumbnailUrl = useCallback( async (fileUrl: string, toUseIn?: string): Promise<string> => {
|
||||
const cacheKey:string = `__${fileUrl}`;
|
||||
try {
|
||||
if (isEmpty(fileUrl)) {
|
||||
return null;
|
||||
}
|
||||
// try get file image from cache
|
||||
const cacheValue = getCacheValue(cacheKey);
|
||||
if (cacheValue) { return cacheValue; }
|
||||
// Is already thumbnail
|
||||
if (fileUrl.indexOf("driveItem/thumbnails") > 0) {
|
||||
return fileUrl;
|
||||
}
|
||||
if (isSharePointImage(fileUrl)) {
|
||||
if (isStockImage(fileUrl)) {
|
||||
return getStockImageThumbnailUrl(fileUrl);
|
||||
}
|
||||
if (isSharePointFilePathPreviewImage(fileUrl)) {
|
||||
return await getSharePointThumbnailImageUrl(getSharePointFileUrlFromPreview(fileUrl), toUseIn);
|
||||
}
|
||||
if (isSharePointFileIdsPreviewImage(fileUrl)) {
|
||||
return await getCDNBaseSPThumbnailUrl(getFileInfoFromQueryString(fileUrl));
|
||||
}
|
||||
}
|
||||
if (fileUrl.indexOf("data:image/") === 0) {
|
||||
return fileUrl;
|
||||
}
|
||||
// Try to download image and convert it to base64data
|
||||
const img = await getImageBase64(fileUrl);
|
||||
setCacheValue(cacheKey, img);
|
||||
return img;
|
||||
} catch (err) {
|
||||
if (DEBUG) {
|
||||
console.error(`[getPictureThumbnailUrl]: Err='${err.message}'`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const isSharePointFilePathPreviewImage = useCallback((fileUrl: string): boolean => {
|
||||
return fileUrl.indexOf("/_layouts/15/getpreview.ashx") >= 0 && fileUrl.indexOf("guidSite") < 0;
|
||||
}, []);
|
||||
|
||||
const getFileInfoFromQueryString = useCallback((serverRelativeFileUrl: string): FileInfo => {
|
||||
// serverRelativeFileUrl in the form /_layouts/15/getpreview.ashx?guidSite=<site-guid>&guidWeb=<web-guid>>&guidFile=<fileGuid>
|
||||
|
||||
const fileUrl = new URL(`${window.location.origin}${serverRelativeFileUrl}`);
|
||||
|
||||
const urlParams = new URLSearchParams(fileUrl.search);
|
||||
|
||||
const siteId: string = urlParams.get("guidSite");
|
||||
const fileId: string = urlParams.get("guidFile");
|
||||
|
||||
return {
|
||||
SiteId: siteId,
|
||||
Id: fileId,
|
||||
} as FileInfo;
|
||||
}, []);
|
||||
|
||||
const isSharePointFileIdsPreviewImage = useCallback((fileUrl: string): boolean => {
|
||||
// After the news is created the BannerImageUrl is in different form:
|
||||
// /_layouts/15/getpreview.ashx?guidSite=<site-guid>&guidWeb=<web-guid>>&guidFile=<fileGuid>
|
||||
return (
|
||||
fileUrl.indexOf("/_layouts/15/getpreview.ashx") >= 0 &&
|
||||
fileUrl.indexOf("guidSite") > 0 &&
|
||||
fileUrl.indexOf("guidFile") > 0
|
||||
);
|
||||
}, []);
|
||||
|
||||
const getStockImageThumbnailUrl = useCallback((fileUrl: string): string => {
|
||||
// Check if the fileUrll is already in a correct format
|
||||
if (fileUrl.indexOf("?file=") > 0 && fileUrl.indexOf("thumbnails/large.jpg") > 0) {
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
const imagePictureTokens = fileUrl.split("/");
|
||||
const fileId = imagePictureTokens[imagePictureTokens.length - 1];
|
||||
const thumbnailUrl = fileUrl.replace(fileId, "thumbnails/large.jpg") + `?file=${fileId}`;
|
||||
|
||||
return thumbnailUrl;
|
||||
}, []);
|
||||
|
||||
const getSharePointFileUrlFromPreview = useCallback((previewUrl: string): string => {
|
||||
const decodedUrl = decodeURIComponent(previewUrl);
|
||||
const serverRelativeUrl = decodedUrl.replace("/_layouts/15/getpreview.ashx?path=", "");
|
||||
const absoluteFileUrl = `${window.location.origin}${serverRelativeUrl}`;
|
||||
|
||||
return absoluteFileUrl;
|
||||
}, []);
|
||||
|
||||
const getSharePointThumbnailImageUrl = useCallback(async (fileUrl: string, toUseIn: string) => {
|
||||
try {
|
||||
const fileInfo = await getSPFileInfo(fileUrl);
|
||||
if (toUseIn !== "AdaptiveCards") {
|
||||
return await getCDNBaseSPThumbnailUrl(fileInfo);
|
||||
}
|
||||
|
||||
return await getCDNBaseSPThumbnailUrlToAdaptiveCards(fileInfo);
|
||||
} catch (err) {
|
||||
if (DEBUG) {
|
||||
console.error(`[getSharePointThumbnailImageUrl]: Err='${err.message}'`);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getCDNBaseSPThumbnailUrl = useCallback(async (spFileInfo: FileInfo): Promise<string> => {
|
||||
try {
|
||||
const tenantOrigin = window.location.host;
|
||||
const rawThumbnailUrl = `https://${tenantOrigin}/_api/v2.1/sites/${tenantOrigin},${spFileInfo.SiteId}/items/${spFileInfo.Id}/driveItem/thumbnails/0/large/content?preferNoRedirect=true`;
|
||||
const thumbnailUrl = rawThumbnailUrl.replace("width=800&height=800", `width=${MS_TEAMS_IMAGE_WIDTH}`);
|
||||
return thumbnailUrl;
|
||||
} catch (err) {
|
||||
if (DEBUG) {
|
||||
console.error(`[getCDNBaseSPThumbnailUrl]: Err='${err.message}'`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getCDNBaseSPThumbnailUrlToAdaptiveCards = useCallback(async (spFileInfo: FileInfo): Promise<string> => {
|
||||
try {
|
||||
const tenantOrigin = window.location.host;
|
||||
const predefinedResolution = "large";
|
||||
const rawThumbnailUrl = `https://${tenantOrigin}/_api/v2.1/sites/${tenantOrigin},${spFileInfo.SiteId}/items/${spFileInfo.Id}/driveItem/thumbnails/0/${predefinedResolution}/content?preferNoRedirect=true`;
|
||||
return rawThumbnailUrl;
|
||||
} catch (err) {
|
||||
if (DEBUG) {
|
||||
console.error(`[getCDNBaseSPThumbnailUrlToAdaptiveCards]: Err='${err.message}'`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
getBase64ImageFromDOMImg,
|
||||
isBase64Image,
|
||||
getImageBase64,
|
||||
getPictureThumbnailUrl,
|
||||
isSharePointFilePathPreviewImage,
|
||||
getFileInfoFromQueryString,
|
||||
isSharePointFileIdsPreviewImage,
|
||||
getStockImageThumbnailUrl,
|
||||
getSharePointFileUrlFromPreview,
|
||||
getSharePointThumbnailImageUrl,
|
||||
getCDNBaseSPThumbnailUrl,
|
||||
getCDNBaseSPThumbnailUrlToAdaptiveCards,
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue