Merge branch 'main' into static
This commit is contained in:
commit
788708e0aa
@ -15,7 +15,11 @@ interface Props {
|
||||
params: { tag: string }
|
||||
}
|
||||
|
||||
export default async function PhotoPageEdit({ params: { tag } }: Props) {
|
||||
export default async function PhotoPageEdit({
|
||||
params: { tag: tagFromParams } }: Props
|
||||
) {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const [
|
||||
count,
|
||||
photos,
|
||||
|
||||
@ -6,15 +6,17 @@ import {
|
||||
getPhotosTagDataCached,
|
||||
getPhotosTagDataCachedWithPagination,
|
||||
} from '@/tag/data';
|
||||
import { Metadata } from 'next/types';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
interface TagProps {
|
||||
params: { tag: string }
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params: { tag },
|
||||
params: { tag: tagFromParams },
|
||||
}: TagProps): Promise<Metadata> {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
@ -49,9 +51,11 @@ export async function generateMetadata({
|
||||
}
|
||||
|
||||
export default async function TagPage({
|
||||
params: { tag },
|
||||
params: { tag: tagFromParams },
|
||||
searchParams,
|
||||
}:TagProps & PaginationParams) {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const {
|
||||
photos,
|
||||
count,
|
||||
|
||||
@ -7,15 +7,17 @@ import {
|
||||
getPhotosTagDataCached,
|
||||
getPhotosTagDataCachedWithPagination,
|
||||
} from '@/tag/data';
|
||||
import { Metadata } from 'next/types';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
interface TagProps {
|
||||
params: { tag: string }
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params: { tag },
|
||||
params: { tag: tagFromParams },
|
||||
}: TagProps): Promise<Metadata> {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
@ -50,9 +52,11 @@ export async function generateMetadata({
|
||||
}
|
||||
|
||||
export default async function Share({
|
||||
params: { tag },
|
||||
params: { tag: tagFromParams },
|
||||
searchParams,
|
||||
}: TagProps & PaginationParams) {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const {
|
||||
photos,
|
||||
count,
|
||||
|
||||
@ -16,7 +16,7 @@ export default function CameraOverview({
|
||||
camera: Camera,
|
||||
photos: Photo[],
|
||||
count: number,
|
||||
dateRange: PhotoDateRange,
|
||||
dateRange?: PhotoDateRange,
|
||||
showMorePath?: string,
|
||||
animateOnFirstLoadOnly?: boolean,
|
||||
}) {
|
||||
|
||||
@ -13,7 +13,7 @@ export default function CameraShareModal({
|
||||
camera: Camera
|
||||
photos: Photo[]
|
||||
count: number
|
||||
dateRange: PhotoDateRange,
|
||||
dateRange?: PhotoDateRange,
|
||||
}) {
|
||||
return (
|
||||
<ShareModal
|
||||
|
||||
@ -17,7 +17,7 @@ export type CameraWithCount = {
|
||||
export type Cameras = CameraWithCount[];
|
||||
|
||||
export const createCameraKey = ({ make, model }: Camera) =>
|
||||
parameterize(`${make}-${model}`);
|
||||
parameterize(`${make}-${model}`, true);
|
||||
|
||||
// Assumes no makes ('Fujifilm,' 'Apple,' 'Canon', etc.) have dashes
|
||||
export const getCameraFromKey = (cameraKey: string): Camera => {
|
||||
|
||||
@ -72,11 +72,11 @@ export default function TagInput({
|
||||
onChange?.([
|
||||
...selectedOptions,
|
||||
option.startsWith(CREATE_LABEL)
|
||||
? option.slice(CREATE_LABEL.length, -1)
|
||||
? option.match(new RegExp(`^${CREATE_LABEL} "(.+)"$`))?.[1] ?? option
|
||||
: option,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.map(parameterize)
|
||||
.map(item => parameterize(item))
|
||||
.join(','));
|
||||
}
|
||||
setSelectedOptionIndex(undefined);
|
||||
|
||||
@ -22,6 +22,7 @@ import {
|
||||
revalidateAdminPaths,
|
||||
revalidateAllKeysAndPaths,
|
||||
revalidatePhotosKey,
|
||||
revalidateTagsKey,
|
||||
} from '@/photo/cache';
|
||||
import { PATH_ADMIN_PHOTOS, PATH_ADMIN_TAGS, PATH_ROOT } from '@/site/paths';
|
||||
import { extractExifDataFromBlobPath } from './server';
|
||||
@ -105,6 +106,7 @@ export async function renamePhotoTagGloballyAction(formData: FormData) {
|
||||
if (tag && updatedTag && tag !== updatedTag) {
|
||||
await sqlRenamePhotoTagGlobally(tag, updatedTag);
|
||||
revalidatePhotosKey();
|
||||
revalidateTagsKey();
|
||||
redirect(PATH_ADMIN_TAGS);
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,8 +174,8 @@ const sqlGetPhotosTagCount = async (tag: string) => sql`
|
||||
const sqlGetPhotosCameraCount = async (camera: Camera) => sql`
|
||||
SELECT COUNT(*) FROM photos
|
||||
WHERE
|
||||
LOWER(make)=${parameterize(camera.make)} AND
|
||||
LOWER(REPLACE(model, ' ', '-'))=${parameterize(camera.model)} AND
|
||||
LOWER(make)=${parameterize(camera.make, true)} AND
|
||||
LOWER(REPLACE(model, ' ', '-'))=${parameterize(camera.model, true)} AND
|
||||
hidden IS NOT TRUE
|
||||
`.then(({ rows }) => parseInt(rows[0].count, 10));
|
||||
|
||||
@ -191,23 +191,29 @@ const sqlGetPhotosDateRange = async () => sql`
|
||||
SELECT MIN(taken_at_naive) as start, MAX(taken_at_naive) as end
|
||||
FROM photos
|
||||
WHERE hidden IS NOT TRUE
|
||||
`.then(({ rows }) => rows[0] as PhotoDateRange);
|
||||
`.then(({ rows }) => rows[0]?.start && rows[0]?.end
|
||||
? rows[0] as PhotoDateRange
|
||||
: undefined);
|
||||
|
||||
const sqlGetPhotosTagDateRange = async (tag: string) => sql`
|
||||
SELECT MIN(taken_at_naive) as start, MAX(taken_at_naive) as end
|
||||
FROM photos
|
||||
WHERE ${tag}=ANY(tags) AND
|
||||
hidden IS NOT TRUE
|
||||
`.then(({ rows }) => rows[0] as PhotoDateRange);
|
||||
`.then(({ rows }) => rows[0]?.start && rows[0]?.end
|
||||
? rows[0] as PhotoDateRange
|
||||
: undefined);
|
||||
|
||||
const sqlGetPhotosCameraDateRange = async (camera: Camera) => sql`
|
||||
SELECT MIN(taken_at_naive) as start, MAX(taken_at_naive) as end
|
||||
FROM photos
|
||||
WHERE
|
||||
LOWER(make)=${parameterize(camera.make)} AND
|
||||
LOWER(REPLACE(model, ' ', '-'))=${parameterize(camera.model)} AND
|
||||
LOWER(make)=${parameterize(camera.make, true)} AND
|
||||
LOWER(REPLACE(model, ' ', '-'))=${parameterize(camera.model, true)} AND
|
||||
hidden IS NOT TRUE
|
||||
`.then(({ rows }) => rows[0] as PhotoDateRange);
|
||||
`.then(({ rows }) => rows[0]?.start && rows[0]?.end
|
||||
? rows[0] as PhotoDateRange
|
||||
: undefined);
|
||||
|
||||
const sqlGetPhotosFilmSimulationDateRange = async (
|
||||
simulation: FilmSimulation,
|
||||
@ -216,7 +222,9 @@ const sqlGetPhotosFilmSimulationDateRange = async (
|
||||
FROM photos
|
||||
WHERE film_simulation=${simulation} AND
|
||||
hidden IS NOT TRUE
|
||||
`.then(({ rows }) => rows[0] as PhotoDateRange);
|
||||
`.then(({ rows }) => rows[0]?.start && rows[0]?.end
|
||||
? rows[0] as PhotoDateRange
|
||||
: undefined);
|
||||
|
||||
const sqlGetUniqueTags = async () => sql`
|
||||
SELECT DISTINCT unnest(tags) as tag, COUNT(*)
|
||||
@ -349,8 +357,8 @@ export const getPhotos = async (options: GetPhotosOptions = {}) => {
|
||||
if (camera) {
|
||||
wheres.push(`LOWER(make)=$${valueIndex++}`);
|
||||
wheres.push(`LOWER(REPLACE(model, ' ', '-'))=$${valueIndex++}`);
|
||||
values.push(parameterize(camera.make));
|
||||
values.push(parameterize(camera.model));
|
||||
values.push(parameterize(camera.make, true));
|
||||
values.push(parameterize(camera.model, true));
|
||||
}
|
||||
if (simulation) {
|
||||
wheres.push(`film_simulation=$${valueIndex++}`);
|
||||
|
||||
@ -16,7 +16,7 @@ export default function FilmSimulationOverview({
|
||||
simulation: FilmSimulation,
|
||||
photos: Photo[],
|
||||
count: number,
|
||||
dateRange: PhotoDateRange,
|
||||
dateRange?: PhotoDateRange,
|
||||
showMorePath?: string,
|
||||
animateOnFirstLoadOnly?: boolean,
|
||||
}) {
|
||||
|
||||
@ -15,7 +15,7 @@ export default function TagOverview({
|
||||
tag: string,
|
||||
photos: Photo[],
|
||||
count: number,
|
||||
dateRange: PhotoDateRange,
|
||||
dateRange?: PhotoDateRange,
|
||||
showMorePath?: string,
|
||||
animateOnFirstLoadOnly?: boolean,
|
||||
}) {
|
||||
|
||||
@ -2,9 +2,9 @@ export const convertStringToArray = (
|
||||
string?: string,
|
||||
shouldParameterize = true,
|
||||
) => string
|
||||
? string.split(',').map(tag => shouldParameterize
|
||||
? parameterize(tag)
|
||||
: tag.trim())
|
||||
? string.split(',').map(item => shouldParameterize
|
||||
? parameterize(item)
|
||||
: item.trim())
|
||||
: undefined;
|
||||
|
||||
export const capitalize = (string: string) =>
|
||||
@ -16,14 +16,22 @@ export const capitalizeWords = (string = '') =>
|
||||
.map(capitalize)
|
||||
.join(' ');
|
||||
|
||||
export const parameterize = (string: string) =>
|
||||
export const parameterize = (
|
||||
string: string,
|
||||
shouldRemoveNonAlphanumeric?: boolean,
|
||||
) =>
|
||||
string
|
||||
.trim()
|
||||
// Replaces spaces, underscores, and dashes with dashes
|
||||
.replaceAll(/[\s_–—]/gi, '-')
|
||||
// Removes all non-alphanumeric characters
|
||||
.replaceAll(/([^a-z0-9-])/gi, '')
|
||||
.toLowerCase();
|
||||
.replaceAll(
|
||||
shouldRemoveNonAlphanumeric
|
||||
? /([^a-z0-9-])/gi
|
||||
: /''/gi,
|
||||
'',
|
||||
)
|
||||
.toLocaleLowerCase();
|
||||
|
||||
export const formatCount = (count: number) => `× ${count}`;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user