92 lines
3.7 KiB
JavaScript
92 lines
3.7 KiB
JavaScript
/**
|
|
* Workflow Recipe gallery rendering and Image Detail Workbench handoff.
|
|
*/
|
|
|
|
import { translate } from './locales.js';
|
|
import { showImageWorkbench } from './ui_gallery_detail.js';
|
|
import { appendText, button } from './ui_recipe_detail_dom.js';
|
|
|
|
const t = (key, params) => translate(key, params);
|
|
|
|
export function outputImageUrl(image) {
|
|
if (!image || image.type !== 'output' || typeof image.filename !== 'string') return '';
|
|
const query = new URLSearchParams({ filename: image.filename, type: 'output' });
|
|
if (image.subfolder) query.set('subfolder', image.subfolder);
|
|
return `/view?${query.toString()}`;
|
|
}
|
|
|
|
export function galleryWorkbenchItems(images) {
|
|
return (images || []).map(sourceImage => ({
|
|
filename: sourceImage.filename,
|
|
subfolder: sourceImage.subfolder || '',
|
|
url: outputImageUrl(sourceImage),
|
|
sourceImage,
|
|
})).filter(item => item.url);
|
|
}
|
|
|
|
export function openGalleryImageDetail(owner, images, sourceImage, url) {
|
|
const items = galleryWorkbenchItems(images);
|
|
const currentIndex = items.findIndex(item =>
|
|
item.filename === sourceImage?.filename && (item.subfolder || '') === (sourceImage?.subfolder || '')
|
|
);
|
|
void showImageWorkbench(owner, sourceImage, url, {
|
|
items,
|
|
currentIndex: currentIndex >= 0 ? currentIndex : 0,
|
|
});
|
|
}
|
|
export function renderRecipeGallery(content, owner, recipe, gallery, refresh) {
|
|
const section = document.createElement('section');
|
|
section.className = 'anomalous-recipe-detail-section anomalous-recipe-gallery';
|
|
const heading = document.createElement('div');
|
|
heading.className = 'anomalous-recipe-detail-section-heading';
|
|
appendText(heading, 'h4', t('recipeGallery'));
|
|
const refreshButton = button(heading, t('recipeGalleryRefresh'), 'anomalous-btn-ghost anomalous-recipe-gallery-refresh');
|
|
refreshButton.onclick = () => { void refresh(true); };
|
|
section.appendChild(heading);
|
|
|
|
if (gallery.status === 'loading') {
|
|
appendText(section, 'p', t('recipeGalleryLoading'), 'anomalous-recipe-detail-muted');
|
|
content.appendChild(section);
|
|
return;
|
|
}
|
|
if (gallery.status === 'error') {
|
|
appendText(section, 'p', t('recipeGalleryLoadError'), 'anomalous-recipe-detail-muted');
|
|
content.appendChild(section);
|
|
return;
|
|
}
|
|
|
|
if (gallery.status === 'ready') {
|
|
appendText(section, 'small', t('recipeGalleryScanHint').replace('{count}', String(gallery.scanned || 0)), 'anomalous-recipe-detail-muted');
|
|
}
|
|
if (!gallery.images.length) {
|
|
appendText(section, 'p', t('recipeGalleryEmpty'), 'anomalous-recipe-detail-muted');
|
|
content.appendChild(section);
|
|
return;
|
|
}
|
|
|
|
const grid = document.createElement('div');
|
|
grid.className = 'anomalous-recipe-gallery-grid';
|
|
for (const sourceImage of gallery.images) {
|
|
const card = document.createElement('article');
|
|
card.className = 'anomalous-recipe-gallery-card';
|
|
const url = outputImageUrl(sourceImage);
|
|
const image = document.createElement('img');
|
|
image.src = url;
|
|
image.alt = t('recipeGalleryOpenImage');
|
|
image.loading = 'lazy';
|
|
image.onclick = () => owner.showGalleryViewer?.(url);
|
|
card.appendChild(image);
|
|
const actions = document.createElement('div');
|
|
actions.className = 'anomalous-recipe-gallery-card-actions';
|
|
const details = button(actions, `🔎 ${t('materialViewDetails')}`, 'anomalous-btn-primary');
|
|
details.onclick = event => {
|
|
event.stopPropagation();
|
|
openGalleryImageDetail(owner, gallery.images, sourceImage, url);
|
|
};
|
|
card.appendChild(actions);
|
|
grid.appendChild(card);
|
|
}
|
|
section.appendChild(grid);
|
|
content.appendChild(section);
|
|
}
|