sozsoft-platform/ui/src/views/list/shared/imageValue.ts

116 lines
3.7 KiB
TypeScript
Raw Normal View History

/**
* 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 []
if (trimmed.startsWith('data:image/')) return [trimmed]
return trimmed
.split(/\r?\n|\|\s*/)
.flatMap((part) => {
const text = part.trim()
if (!text || text.startsWith('data:image/')) 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) ?? {}
}