Banner rotator respects tags
This commit is contained in:
+62
-4
@@ -59,6 +59,12 @@ type DirectusFile = {
|
||||
filename_download?: string;
|
||||
filename_disk?: string;
|
||||
type?: string;
|
||||
tags?: string[] | string | null;
|
||||
};
|
||||
|
||||
type ImageFolderOptions = {
|
||||
firstTag?: string;
|
||||
shuffleRest?: boolean;
|
||||
};
|
||||
|
||||
type EventTemplateRecord = {
|
||||
@@ -170,6 +176,49 @@ function directusObjectKey(file: string | DirectusFile): string {
|
||||
return `${fileId}${extensionFromFilename(typeof file === 'string' ? undefined : file.filename_download)}`;
|
||||
}
|
||||
|
||||
function fileTags(file: DirectusFile): string[] {
|
||||
if (Array.isArray(file.tags)) {
|
||||
return file.tags;
|
||||
}
|
||||
|
||||
if (typeof file.tags === 'string') {
|
||||
return file.tags
|
||||
.split(',')
|
||||
.map((tag) => tag.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function hasTag(file: DirectusFile, tag: string): boolean {
|
||||
const targetTag = tag.toLowerCase();
|
||||
return fileTags(file).some((fileTag) => fileTag.toLowerCase() === targetTag);
|
||||
}
|
||||
|
||||
function shuffleFiles(files: DirectusFile[]): DirectusFile[] {
|
||||
const shuffled = [...files];
|
||||
|
||||
for (let index = shuffled.length - 1; index > 0; index -= 1) {
|
||||
const swapIndex = Math.floor(Math.random() * (index + 1));
|
||||
[shuffled[index], shuffled[swapIndex]] = [shuffled[swapIndex], shuffled[index]];
|
||||
}
|
||||
|
||||
return shuffled;
|
||||
}
|
||||
|
||||
function orderImageFiles(files: DirectusFile[], options: ImageFolderOptions): DirectusFile[] {
|
||||
const { firstTag, shuffleRest } = options;
|
||||
|
||||
if (!firstTag) {
|
||||
return shuffleRest ? shuffleFiles(files) : files;
|
||||
}
|
||||
|
||||
const firstFiles = files.filter((file) => hasTag(file, firstTag));
|
||||
const restFiles = files.filter((file) => !hasTag(file, firstTag));
|
||||
return [...firstFiles, ...(shuffleRest ? shuffleFiles(restFiles) : restFiles)];
|
||||
}
|
||||
|
||||
export function resolveDirectusAssetUrl(file: string | DirectusFile): string {
|
||||
const fileId = directusFileId(file);
|
||||
const r2ObjectKey = directusObjectKey(file);
|
||||
@@ -200,7 +249,11 @@ async function findFolderByName(name: string): Promise<DirectusFolder | null> {
|
||||
return folders[0] ?? null;
|
||||
}
|
||||
|
||||
async function getImagesFromFolder(folderName: string, fallbackImages: HomepageBannerImage[]): Promise<HomepageBannerImage[]> {
|
||||
async function getImagesFromFolder(
|
||||
folderName: string,
|
||||
fallbackImages: HomepageBannerImage[],
|
||||
options: ImageFolderOptions = {},
|
||||
): Promise<HomepageBannerImage[]> {
|
||||
try {
|
||||
const folder = await findFolderByName(folderName);
|
||||
if (!folder) {
|
||||
@@ -213,10 +266,11 @@ async function getImagesFromFolder(folderName: string, fallbackImages: HomepageB
|
||||
endpoint.searchParams.set('sort', '-uploaded_on');
|
||||
endpoint.searchParams.set('filter[folder][_eq]', folder.id);
|
||||
endpoint.searchParams.set('filter[type][_starts_with]', 'image/');
|
||||
endpoint.searchParams.set('fields', 'id,title,description,filename_download,filename_disk,type');
|
||||
endpoint.searchParams.set('fields', 'id,title,description,filename_download,filename_disk,type,tags');
|
||||
|
||||
const files = await readDirectusEndpoint<DirectusFile>(endpoint);
|
||||
const images = files.map((file) => ({
|
||||
const orderedFiles = orderImageFiles(files, options);
|
||||
const images = orderedFiles.map((file) => ({
|
||||
src: resolveDirectusAssetUrl(file),
|
||||
alt: file.description || file.title || file.filename_download || 'Swansea Airport',
|
||||
}));
|
||||
@@ -234,7 +288,11 @@ async function getImagesFromFolder(folderName: string, fallbackImages: HomepageB
|
||||
}
|
||||
}
|
||||
|
||||
export const getHomepageBannerImages = () => getImagesFromFolder(homepageBannerFolder, fallbackHomepageBannerImages);
|
||||
export const getHomepageBannerImages = () =>
|
||||
getImagesFromFolder(homepageBannerFolder, fallbackHomepageBannerImages, {
|
||||
firstTag: 'first',
|
||||
shuffleRest: true,
|
||||
});
|
||||
export const getCafePageImages = () => getImagesFromFolder(cafePageFolder, fallbackCafePageImages);
|
||||
|
||||
function stripHtml(value = ''): string {
|
||||
|
||||
Reference in New Issue
Block a user