This commit is contained in:
seb
2026-10-09 19:02:19 +02:00
parent 178055f1d8
commit f840a12b78
6 changed files with 110 additions and 5 deletions

View File

@@ -49,6 +49,32 @@ ORDER BY b.name
OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY
`;
export const LIST_BY_COMPANY_PAGED_WITH_SMALL_THUMBS = `
SELECT
b.id,
b.name,
b.gsprpinfo,
(
SELECT
p.hash AS fullHash,
p.thumbw AS thumbW,
p.thumbh AS thumbH,
p.thumbhash AS thumbHash,
p.smallthumbw AS smallThumbW,
p.smallthumbh AS smallThumbH,
p.smallthumbbinary AS smallThumbBinary
FROM brandpic bp
INNER JOIN pic p ON p.id = bp.pic_id
WHERE bp.brand_id = b.id
ORDER BY bp.sort ASC, bp.id ASC
FOR JSON PATH
) AS picsJson
FROM brand b
WHERE b.company_id = @companyId
ORDER BY b.name
OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY
`;
export const GET_BY_COMPANY_AND_NAME = `
SELECT
b.id,

View File

@@ -58,6 +58,39 @@ ORDER BY b.name
LIMIT @limit OFFSET @offset
`;
export const LIST_BY_COMPANY_PAGED_WITH_SMALL_THUMBS = `
SELECT
b.id,
b.name,
b.gsprpinfo,
(
SELECT COALESCE(json_group_array(json_object(
'fullHash', hash,
'thumbW', thumbw,
'thumbH', thumbh,
'thumbHash', thumbhash,
'smallThumbW', smallthumbw,
'smallThumbH', smallthumbh,
'smallThumbBinaryHex', CASE
WHEN smallthumbbinary IS NULL THEN NULL
ELSE hex(smallthumbbinary)
END
)), '[]')
FROM (
SELECT p.hash, p.thumbw, p.thumbh, p.thumbhash,
p.smallthumbw, p.smallthumbh, p.smallthumbbinary
FROM brandpic bp
INNER JOIN pic p ON p.id = bp.pic_id
WHERE bp.brand_id = b.id
ORDER BY bp.sort, bp.id
)
) AS picsJson
FROM brand b
WHERE b.company_id = @companyId
ORDER BY b.name
LIMIT @limit OFFSET @offset
`;
export const GET_BY_COMPANY_AND_NAME = `
SELECT
b.id,

View File

@@ -2,11 +2,13 @@ import {
COUNT_BY_COMPANY as MSSQL_COUNT,
LIST_BY_COMPANY as MSSQL_LIST_BY_COMPANY,
LIST_BY_COMPANY_PAGED as MSSQL_LIST_PAGED,
LIST_BY_COMPANY_PAGED_WITH_SMALL_THUMBS as MSSQL_LIST_PAGED_WITH_SMALL_THUMBS,
} from '../../providers/mssql/queries/brand.js';
import {
COUNT_BY_COMPANY as SQLITE_COUNT,
LIST_BY_COMPANY as SQLITE_LIST_BY_COMPANY,
LIST_BY_COMPANY_PAGED as SQLITE_LIST_PAGED,
LIST_BY_COMPANY_PAGED_WITH_SMALL_THUMBS as SQLITE_LIST_PAGED_WITH_SMALL_THUMBS,
} from '../../providers/sqlite3/queries/brand.js';
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
import makeRunner from '../runner.js';
@@ -14,7 +16,17 @@ import makeRunner from '../runner.js';
function parsePics(raw) {
if (!raw) return [];
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
return Array.isArray(parsed) ? parsed : [];
if (!Array.isArray(parsed)) return [];
return parsed.map((pic) => {
const { smallThumbBinaryHex, ...result } = pic;
if (smallThumbBinaryHex === undefined) return result;
return {
...result,
smallThumbBinary: smallThumbBinaryHex === null
? null
: Buffer.from(smallThumbBinaryHex, 'hex').toString('base64'),
};
});
}
export default function list(provider) {
@@ -23,6 +35,9 @@ export default function list(provider) {
const sql = isSqlite ? SQLITE_LIST_BY_COMPANY : MSSQL_LIST_BY_COMPANY;
const sqlCount = isSqlite ? SQLITE_COUNT : MSSQL_COUNT;
const sqlPaged = isSqlite ? SQLITE_LIST_PAGED : MSSQL_LIST_PAGED;
const sqlPagedWithSmallThumbs = isSqlite
? SQLITE_LIST_PAGED_WITH_SMALL_THUMBS
: MSSQL_LIST_PAGED_WITH_SMALL_THUMBS;
/**
* Lists the brands of the user's selected company, sorted by name.
@@ -31,8 +46,9 @@ export default function list(provider) {
* @param {object} [opts] - Optional pagination options.
* @param {number} [opts.offset=0] - Number of brands to skip.
* @param {number} [opts.limit=10] - Number of brands to return (max 100).
* @param {boolean} [opts.includeSmallThumbs=false] - Include 40px-edge small thumbnail dimensions and base64 AVIF data.
* @param {object} [tx] - Optional transaction to run within.
* @returns {Promise<{brands: Array<{id: number, name: string, gsprpinfo: string|null, pics: Array<{fullHash: string, thumbW: number, thumbH: number, thumbHash: string}>}>, total: number, offset: number, limit: number}>} The brands plus the total unpaged count.
* @returns {Promise<{brands: Array<{id: number, name: string, gsprpinfo: string|null, pics: Array<{fullHash: string, thumbW: number, thumbH: number, thumbHash: string, smallThumbW?: number|null, smallThumbH?: number|null, smallThumbBinary?: string|null}>}>, total: number, offset: number, limit: number}>} The brands plus the total unpaged count. Small-thumbnail fields are present only when `includeSmallThumbs` is true; the binary is base64-encoded AVIF data.
*
* @example
* const result = await store.brand.list(42, { offset: 0, limit: 10 });
@@ -41,6 +57,7 @@ export default function list(provider) {
return async (googleAuthId, opts, tx) => {
let offset = 0;
let limit = 10;
let includeSmallThumbs = false;
let resolvedTx = tx;
if (opts != null && typeof opts === 'object' && !opts._isTx) {
@@ -54,6 +71,7 @@ export default function list(provider) {
}
offset = parsedOffset;
limit = parsedLimit;
includeSmallThumbs = opts.includeSmallThumbs === true;
} else if (opts != null) {
resolvedTx = opts;
}
@@ -63,7 +81,10 @@ export default function list(provider) {
const [countResult, listResult] = await Promise.all([
runner.query(sqlCount, { companyId }),
runner.query(sqlPaged, { companyId, offset, limit }),
runner.query(
includeSmallThumbs ? sqlPagedWithSmallThumbs : sqlPaged,
{ companyId, offset, limit },
),
]);
return {