feat: image variants per image
This commit is contained in:
1 parent
f567866161
commit
951fef18ba
92 files changed
+8695
-413
No files matched your search
@@ -1,7 +1,9 @@
|
||||
import { vi } from 'vitest'
|
||||
import { defineComponent, h } from 'vue'
|
||||
import { mount, flushPromises, type VueWrapper } from '@vue/test-utils'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import uiPlugin from '@nuxt/ui/vue-plugin'
|
||||
import UApp from '@nuxt/ui/components/App.vue'
|
||||
import router from '@/router'
|
||||
import { ApiError, useApi } from '@/composables/useApi'
|
||||
import type { MediaItem } from '@/composables/useMedia'
|
||||
@@ -21,6 +23,8 @@ type Row = [
|
||||
string,
|
||||
boolean,
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
]
|
||||
|
||||
const ROWS: Row[] = [
|
||||
@@ -36,6 +40,8 @@ const ROWS: Row[] = [
|
||||
'2026-09-12T12:00:00Z',
|
||||
false,
|
||||
'0a',
|
||||
4,
|
||||
266240,
|
||||
],
|
||||
[
|
||||
2,
|
||||
@@ -49,6 +55,8 @@ const ROWS: Row[] = [
|
||||
'2026-09-08T12:00:00Z',
|
||||
false,
|
||||
'1b',
|
||||
5,
|
||||
419840,
|
||||
],
|
||||
[
|
||||
3,
|
||||
@@ -62,6 +70,8 @@ const ROWS: Row[] = [
|
||||
'2026-09-08T11:00:00Z',
|
||||
false,
|
||||
'2c',
|
||||
5,
|
||||
404480,
|
||||
],
|
||||
[
|
||||
4,
|
||||
@@ -75,6 +85,8 @@ const ROWS: Row[] = [
|
||||
'2026-09-05T12:00:00Z',
|
||||
false,
|
||||
'3d',
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
5,
|
||||
@@ -88,6 +100,8 @@ const ROWS: Row[] = [
|
||||
'2026-09-02T12:00:00Z',
|
||||
true,
|
||||
'0e',
|
||||
3,
|
||||
245760,
|
||||
],
|
||||
[
|
||||
6,
|
||||
@@ -101,6 +115,8 @@ const ROWS: Row[] = [
|
||||
'2026-08-30T12:00:00Z',
|
||||
true,
|
||||
'0e',
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
7,
|
||||
@@ -114,6 +130,8 @@ const ROWS: Row[] = [
|
||||
'2026-08-29T12:00:00Z',
|
||||
true,
|
||||
'2f',
|
||||
2,
|
||||
153600,
|
||||
],
|
||||
[
|
||||
8,
|
||||
@@ -127,6 +145,8 @@ const ROWS: Row[] = [
|
||||
'2026-08-28T12:00:00Z',
|
||||
false,
|
||||
'3a',
|
||||
0,
|
||||
0,
|
||||
],
|
||||
[
|
||||
9,
|
||||
@@ -140,6 +160,8 @@ const ROWS: Row[] = [
|
||||
'2026-08-21T12:00:00Z',
|
||||
true,
|
||||
'2f',
|
||||
1,
|
||||
61440,
|
||||
],
|
||||
[
|
||||
10,
|
||||
@@ -153,6 +175,8 @@ const ROWS: Row[] = [
|
||||
'2026-08-04T12:00:00Z',
|
||||
false,
|
||||
'1b',
|
||||
3,
|
||||
194560,
|
||||
],
|
||||
[
|
||||
11,
|
||||
@@ -166,6 +190,8 @@ const ROWS: Row[] = [
|
||||
'2026-07-19T12:00:00Z',
|
||||
false,
|
||||
'1c',
|
||||
4,
|
||||
286720,
|
||||
],
|
||||
[
|
||||
12,
|
||||
@@ -179,6 +205,8 @@ const ROWS: Row[] = [
|
||||
'2026-06-14T12:00:00Z',
|
||||
true,
|
||||
'0e',
|
||||
5,
|
||||
440320,
|
||||
],
|
||||
]
|
||||
|
||||
@@ -199,6 +227,8 @@ export function fixture(ids?: number[]): MediaItem[] {
|
||||
created_at,
|
||||
duplicate,
|
||||
sha256,
|
||||
variant_count,
|
||||
variant_size,
|
||||
]) => ({
|
||||
id,
|
||||
filename,
|
||||
@@ -212,6 +242,8 @@ export function fixture(ids?: number[]): MediaItem[] {
|
||||
created_at,
|
||||
used_in,
|
||||
duplicate,
|
||||
variant_count,
|
||||
variant_size,
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -238,6 +270,10 @@ export interface Handlers {
|
||||
merge?: (body: { keep_id: number; merge_ids: number[] }) => unknown
|
||||
preview?: () => unknown
|
||||
purge?: (body: { fingerprint: string }) => unknown
|
||||
variants?: (id: number) => unknown
|
||||
generateAll?: (id: number) => unknown
|
||||
generate?: (id: number, name: string) => unknown
|
||||
purgeVariant?: (id: number, name: string) => unknown
|
||||
}
|
||||
|
||||
export function libraryHandlers(
|
||||
@@ -282,6 +318,28 @@ function dispatcher(handlers: Handlers) {
|
||||
if (method === 'POST' && path === '/v1/media/purge') {
|
||||
return (handlers.purge ?? (() => undefined))(JSON.parse(String(options?.body)))
|
||||
}
|
||||
const variantsList = /^\/v1\/media\/(\d+)\/variants$/.exec(path)
|
||||
if (variantsList && method === 'GET') {
|
||||
return (handlers.variants ?? (() => ({ unsupported: null, items: [] })))(
|
||||
Number(variantsList[1]),
|
||||
)
|
||||
}
|
||||
if (variantsList && method === 'POST') {
|
||||
return (handlers.generateAll ?? (() => undefined))(Number(variantsList[1]))
|
||||
}
|
||||
const variantNamed = /^\/v1\/media\/(\d+)\/variants\/([\w-]+)$/.exec(path)
|
||||
if (variantNamed && method === 'POST') {
|
||||
return (handlers.generate ?? (() => undefined))(
|
||||
Number(variantNamed[1]),
|
||||
variantNamed[2]!,
|
||||
)
|
||||
}
|
||||
if (variantNamed && method === 'DELETE') {
|
||||
return (handlers.purgeVariant ?? (() => undefined))(
|
||||
Number(variantNamed[1]),
|
||||
variantNamed[2]!,
|
||||
)
|
||||
}
|
||||
const usage = /^\/v1\/media\/(\d+)\/usage$/.exec(path)
|
||||
if (method === 'GET' && usage) {
|
||||
return (handlers.usage ?? (() => []))(Number(usage[1]))
|
||||
@@ -324,7 +382,7 @@ export async function mountPage(
|
||||
handlers: Handlers = {},
|
||||
url = '/media',
|
||||
width = DESKTOP_WIDTH,
|
||||
options: { realApi?: boolean; role?: string } = {},
|
||||
options: { realApi?: boolean; role?: string; app?: boolean } = {},
|
||||
) {
|
||||
setViewportWidth(width)
|
||||
setActivePinia(createPinia())
|
||||
@@ -349,7 +407,10 @@ export async function mountPage(
|
||||
})
|
||||
}
|
||||
await router.push(url)
|
||||
kit.wrapper = mount(MediaView, {
|
||||
const root = options.app
|
||||
? defineComponent({ render: () => h(UApp, null, { default: () => h(MediaView) }) })
|
||||
: MediaView
|
||||
kit.wrapper = mount(root, {
|
||||
attachTo: document.body,
|
||||
global: { plugins: [router, uiPlugin] },
|
||||
})
|
||||
@@ -599,3 +660,45 @@ export function uploadRows() {
|
||||
export function rowTexts() {
|
||||
return uploadRows().map(textOf)
|
||||
}
|
||||
|
||||
export const STORED_NAME = '1.jpg'
|
||||
export const NORTH_WALL_BYTES = 4089446
|
||||
|
||||
const VARIANT_SPECS: [
|
||||
string,
|
||||
number | null,
|
||||
number | null,
|
||||
string,
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
][] = [
|
||||
['card', 800, null, 'inside', 'webp', 800, 600, 65536],
|
||||
['hero', 1200, 630, 'cover', 'webp', 1200, 630, 98304],
|
||||
['og', 1200, 630, 'cover', 'jpeg', 1200, 630, 145408],
|
||||
['square', 600, 600, 'cover', 'jpeg', 600, 600, 83968],
|
||||
['thumb', 400, 300, 'cover', 'webp', 400, 300, 18432],
|
||||
]
|
||||
|
||||
export function variantItems(generated: string[] = VARIANT_SPECS.map(([name]) => name)) {
|
||||
return VARIANT_SPECS.map(
|
||||
([name, width, height, fit, format, outputWidth, outputHeight, size]) => ({
|
||||
name,
|
||||
width,
|
||||
height,
|
||||
fit,
|
||||
format,
|
||||
output_width: outputWidth,
|
||||
output_height: outputHeight,
|
||||
output_format: format,
|
||||
generated: generated.includes(name),
|
||||
size: generated.includes(name) ? size : null,
|
||||
url: `/static/uploadedImages/${STORED_NAME}?v=${name}`,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
export function variantList(generated?: string[]) {
|
||||
return { unsupported: null, items: variantItems(generated) }
|
||||
}
|
||||
Reference in new issue
Block a user