Merge pull request #455 from the-luap/fix/photo-dimensions-and-default-fit

fix(import): capture photo dimensions in fileWatcher + s3AutoImporter (#447)
This commit is contained in:
Paul Nothaft
2026-05-11 10:07:07 +02:00
committed by GitHub
15 changed files with 194 additions and 21 deletions
@@ -229,6 +229,9 @@ export const ThumbnailsTab: React.FC = () => {
<p className="text-xs text-neutral-500 dark:text-neutral-400 mt-1">
{t('settings.thumbnails.fitHelp', 'How images are resized to fit the thumbnail dimensions. "Cover" crops to fill, "Contain" fits within bounds.')}
</p>
<p className="text-xs text-neutral-500 dark:text-neutral-400 mt-2">
{t('settings.thumbnails.fitRecommendation', 'Recommendation: use "Inside" for masonry / mosaic / justified layouts (preserves aspect ratio); "Cover" for uniform 1:1 grid tiles.')}
</p>
</div>
</Card>
+2 -1
View File
@@ -1246,7 +1246,8 @@
"fit_contain": "Einpassen (innerhalb)",
"fit_fill": "Strecken",
"fit_inside": "Innen (verkleinern)",
"fit_outside": "Außen (vergrößern)"
"fit_outside": "Außen (vergrößern)",
"fitRecommendation": "Empfehlung: „Inside\" für Masonry-/Mosaic-/Justified-Layouts (bewahrt das Seitenverhältnis), „Cover\" für gleichförmige 1:1-Kacheln."
},
"categories": {
"title": "Kategorien",
+2 -1
View File
@@ -952,7 +952,8 @@
"fit_contain": "Contain (fit within)",
"fit_fill": "Fill (stretch)",
"fit_inside": "Inside (shrink to fit)",
"fit_outside": "Outside (expand to cover)"
"fit_outside": "Outside (expand to cover)",
"fitRecommendation": "Recommendation: use \"Inside\" for masonry / mosaic / justified layouts (preserves aspect ratio); \"Cover\" for uniform 1:1 grid tiles."
},
"seo": {
"title": "SEO & Robots",
+2 -1
View File
@@ -967,7 +967,8 @@
"fit_cover": "Recouvrir (recadrer pour remplir)",
"fit_contain": "Contenir (ajuster dans les limites)",
"fit_inside": "Intérieur (réduire pour ajuster)",
"fit_outside": "Extérieur (agrandir pour recouvrir)"
"fit_outside": "Extérieur (agrandir pour recouvrir)",
"fitRecommendation": "Recommandation : utilisez « Inside » pour les mises en page masonry/mosaic/justified (préserve les proportions) ; « Cover » pour des tuiles 1:1 uniformes."
},
"seo": {
"title": "SEO et Robots",
+2 -1
View File
@@ -952,7 +952,8 @@
"fit_contain": "Contain (passend binnen)",
"fit_fill": "Vullen (uitrekken)",
"fit_inside": "Binnenkant (verkleinen om te passen)",
"fit_outside": "Buitenkant (vergroten om te bedekken)"
"fit_outside": "Buitenkant (vergroten om te bedekken)",
"fitRecommendation": "Aanbeveling: gebruik \"Inside\" voor masonry/mosaic/justified-lay-outs (behoudt beeldverhouding); \"Cover\" voor uniforme 1:1-tegels."
},
"seo": {
"title": "SEO & Robots",
+2 -1
View File
@@ -969,7 +969,8 @@
"fit_contain": "Contain (ajustar ao espaço)",
"fit_fill": "Fill (esticar)",
"fit_inside": "Inside (encolher para caber)",
"fit_outside": "Outside (expandir para cobrir)"
"fit_outside": "Outside (expandir para cobrir)",
"fitRecommendation": "Recomendação: use \"Inside\" para layouts masonry/mosaic/justified (preserva proporção); \"Cover\" para tiles 1:1 uniformes."
},
"seo": {
"title": "SEO e Robots",
+2 -1
View File
@@ -1027,7 +1027,8 @@
"fit_contain": "Вписывание (внутри)",
"fit_fill": "Растягивание",
"fit_inside": "Внутри (уменьшить)",
"fit_outside": "Снаружи (увеличить)"
"fit_outside": "Снаружи (увеличить)",
"fitRecommendation": "Рекомендация: «Inside» для масонри/мозаики/выровненных раскладок (сохраняет пропорции); «Cover» для одинаковых плиток 1:1."
},
"photoDimensions": {
"title": "Размеры фотографий",
+14 -11
View File
@@ -104,17 +104,6 @@ export const EventsListPage: React.FC = () => {
setPage(1);
}, [statusFilter, debouncedSearchTerm]);
// Clamp the active page when the result count shrinks (#442 — bulk
// delete of an entire page would leave the user on a now-empty
// page=N where N > totalPages, with no auto-correction). Triggers
// after each successful refetch when totalPages drops below the
// current page (bulk delete, individual delete, archive, anything).
useEffect(() => {
if (data?.pagination && page > data.pagination.totalPages) {
setPage(Math.max(1, data.pagination.totalPages));
}
}, [data?.pagination, page]);
// Close dropdown when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
@@ -157,6 +146,20 @@ export const EventsListPage: React.FC = () => {
placeholderData: (prev) => prev,
});
// Clamp the active page when the result count shrinks (#442 — bulk
// delete of an entire page would leave the user on a now-empty
// page=N where N > totalPages, with no auto-correction). Triggers
// after each successful refetch when totalPages drops below the
// current page (bulk delete, individual delete, archive, anything).
// Must live AFTER the useQuery above so `data` is in scope — the
// original placement at the top of the component caused a TDZ
// ReferenceError on /admin/events that crashed the page (#454).
useEffect(() => {
if (data?.pagination && page > data.pagination.totalPages) {
setPage(Math.max(1, data.pagination.totalPages));
}
}, [data?.pagination, page]);
// Aggregate counters come from the dashboard stats endpoint so the cards
// and the "All (N)" filter button always reflect global totals, not the
// currently visible page.