sozsoft-platform/ui/src/views/list/shared/imageValue.ts
2026-10-04 11:14:38 +03:00

116 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Liste görünümlerinde (grid hücresi, image upload/viewer editörleri) kullanılan
* ortak görsel değer normalizasyon yardımcıları.
*
* Daha önce useListFormColumns.ts, ImageViewerEditorComponent.tsx ve
* ImageUploadEditorComponent.tsx içinde birebir tekrarlanıyordu.
*/
export const NO_IMAGE = '/img/others/no-image.png'
/** String ya da obje olabilen bir değeri düz objeye çevirir; dizi/geçersiz JSON için undefined döner. */
export const parseJsonObject = (value: unknown): Record<string, any> | undefined => {
if (!value) return undefined
if (typeof value === 'object') {
return Array.isArray(value) ? undefined : (value as Record<string, any>)
}
if (typeof value !== 'string') return undefined
try {
const parsed = JSON.parse(value)
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
? (parsed as Record<string, any>)
: undefined
} catch {
return undefined
}
}
/** Pozitif sayıya çevirir, aksi halde varsayılanı döner. */
export const normalizeImageSize = (value: unknown, fallback: number) => {
const size = Number(value)
return Number.isFinite(size) && size > 0 ? size : fallback
}
/** Obje formatındaki görsel değerinden (url/src/fileUrl/path/value) kaynağı çıkarır. */
export const getImageSource = (value: unknown) => {
if (!value) return ''
if (typeof value === 'string') return value.trim()
if (typeof value === 'object') {
const item = value as Record<string, unknown>
return String(item.url ?? item.src ?? item.fileUrl ?? item.path ?? item.value ?? '').trim()
}
return String(value).trim()
}
const isProbablyBase64Image = (value: string) =>
value.length > 80 && /^[A-Za-z0-9+/]+={0,2}$/.test(value)
/** Ham base64 içeriğini data URL'e çevirir; zaten URL ise dokunmaz. */
export const toImageSource = (value: string) => {
const trimmed = value.trim()
if (!trimmed) return ''
if (trimmed.startsWith('data:image/') || !isProbablyBase64Image(trimmed)) return trimmed
return `data:image/jpeg;base64,${trimmed}`
}
const splitImageString = (value: string) => {
const trimmed = value.trim()
if (!trimmed) return []
// data URI virgul tasir (data:application/pdf;base64,...); ayraclarla bolunmez.
if (trimmed.startsWith('data:')) return [trimmed]
return trimmed
.split(/\r?\n|\|\s*/)
.flatMap((part) => {
const text = part.trim()
if (!text || text.startsWith('data:')) return text ? [text] : []
return text.split(',').map((item) => item.trim())
})
.map(toImageSource)
.filter(Boolean)
}
/**
* Tek görsel, çoklu görsel, JSON dizi ya da ayraçlı string olabilen değeri
* gösterilebilir URL listesine dönüştürür.
*/
export const normalizeImageValue = (value: unknown): string[] => {
if (Array.isArray(value)) {
return value.flatMap((item) => normalizeImageValue(item))
}
if (typeof value === 'string') {
const trimmed = value.trim()
if (!trimmed) return []
if (trimmed.startsWith('[')) {
try {
const parsed = JSON.parse(trimmed)
if (Array.isArray(parsed)) {
return parsed.flatMap((item) => normalizeImageValue(item))
}
} catch {
return [toImageSource(trimmed)]
}
}
return splitImageString(trimmed)
}
const source = getImageSource(value)
return source ? [toImageSource(source)] : []
}
/** Kolon yapılandırmasından image upload/viewer seçeneklerini çözer. */
export const resolveImageColumnOptions = (column: unknown): Record<string, any> => {
const col = column as any
const configured = col?.extras?.imageUploadOptions
if (configured && Object.keys(configured).length > 0) {
return configured
}
return parseJsonObject(col?.extras?.editorOptions) ?? parseJsonObject(col?.editorOptions) ?? {}
}