fix(admin): جستجوی تعریف موجودیت بر اساس resource — ویرایش چرا آرامش/فرم تماس روی /en هم ستون فارسی را مینوشت
کلید فهرست ENTITIES برای چند موجودیت snake_case است (why_us، contact_section، seo_meta، …) ولی resource همانها کبابکامل؛ isTranslatable و سایر جستجوها با ENTITIES[resource] پیدا نمیشدند و نتیجه دو بود: - ویرایش درجای «چرا آرامش» و متنهای فرم تماس روی صفحهٔ انگلیسی بهجای ستونهای _en ستون فارسی را بازنویسی میکرد (حتی با زبان ویرایش انگلیسی)؛ - قرص سئوی صفحهٔ اصلی (SingletonPill resource="seo-meta") اصلاً رندر نمیشد. حالا همهٔ جستجوها با entityConfig بر اساس resource انجام میشود.
This commit is contained in:
@@ -4,7 +4,7 @@ import Swal from 'sweetalert2'
|
|||||||
import type { SiteData } from '../api'
|
import type { SiteData } from '../api'
|
||||||
import { useSiteData } from '../api'
|
import { useSiteData } from '../api'
|
||||||
import { adminApi, getToken, HttpError, setToken, AUTH_CHANGE_EVENT } from './adminClient'
|
import { adminApi, getToken, HttpError, setToken, AUTH_CHANGE_EVENT } from './adminClient'
|
||||||
import { ENTITIES, isTranslatable } from './entities'
|
import { entityConfig, isTranslatable } from './entities'
|
||||||
|
|
||||||
export type SaveStatus = 'idle' | 'saving' | 'error'
|
export type SaveStatus = 'idle' | 'saving' | 'error'
|
||||||
/** زبان ویرایش محتوا — رابط مدیریتی فارسی میماند؛ این فقط تعیین میکند کدام ستون زبان ذخیره شود */
|
/** زبان ویرایش محتوا — رابط مدیریتی فارسی میماند؛ این فقط تعیین میکند کدام ستون زبان ذخیره شود */
|
||||||
@@ -246,7 +246,7 @@ export function useFieldSaver() {
|
|||||||
}
|
}
|
||||||
await adminApi.patch(resource, id, changes)
|
await adminApi.patch(resource, id, changes)
|
||||||
updateSite((d) => {
|
updateSite((d) => {
|
||||||
const config = ENTITIES[resource]
|
const config = entityConfig(resource)
|
||||||
let node: Record<string, unknown> | undefined
|
let node: Record<string, unknown> | undefined
|
||||||
if (config) {
|
if (config) {
|
||||||
const target = d[config.dataKey as keyof SiteData] as unknown
|
const target = d[config.dataKey as keyof SiteData] as unknown
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import { useSiteData } from '../api'
|
|||||||
import type { SiteData } from '../api'
|
import type { SiteData } from '../api'
|
||||||
import { useAdmin } from './AdminContext'
|
import { useAdmin } from './AdminContext'
|
||||||
import { adminApi } from './adminClient'
|
import { adminApi } from './adminClient'
|
||||||
import { ENTITIES } from './entities'
|
import { entityConfig } from './entities'
|
||||||
import { EntityDrawer } from './EntityDrawer'
|
import { EntityDrawer } from './EntityDrawer'
|
||||||
|
|
||||||
type ItemWithId = Record<string, unknown> & { id: number }
|
type ItemWithId = Record<string, unknown> & { id: number }
|
||||||
|
|
||||||
function useEntityList(resource: string): ItemWithId[] {
|
function useEntityList(resource: string): ItemWithId[] {
|
||||||
const { data } = useSiteData()
|
const { data } = useSiteData()
|
||||||
const config = ENTITIES[resource]
|
const config = entityConfig(resource)
|
||||||
if (!config) throw new Error(`منبع ناشناخته: ${resource}`)
|
if (!config) throw new Error(`منبع ناشناخته: ${resource}`)
|
||||||
return (data?.[config.dataKey as keyof NonNullable<typeof data>] ?? []) as ItemWithId[]
|
return (data?.[config.dataKey as keyof NonNullable<typeof data>] ?? []) as ItemWithId[]
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ export function EditableItem({
|
|||||||
}) {
|
}) {
|
||||||
const { isAuthenticated, isEditMode, runSave, canManageSite } = useAdmin()
|
const { isAuthenticated, isEditMode, runSave, canManageSite } = useAdmin()
|
||||||
const { reload } = useSiteData()
|
const { reload } = useSiteData()
|
||||||
const config = ENTITIES[resource]
|
const config = entityConfig(resource)
|
||||||
const list = useEntityList(resource)
|
const list = useEntityList(resource)
|
||||||
const [drawerOpen, setDrawerOpen] = useState(false)
|
const [drawerOpen, setDrawerOpen] = useState(false)
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ export function AddItemButton({
|
|||||||
const { isAuthenticated, isEditMode, runSave, canManageSite } = useAdmin()
|
const { isAuthenticated, isEditMode, runSave, canManageSite } = useAdmin()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { updateSite } = useSiteData()
|
const { updateSite } = useSiteData()
|
||||||
const config = ENTITIES[resource]
|
const config = entityConfig(resource)
|
||||||
const [newItem, setNewItem] = useState<ItemWithId | null>(null)
|
const [newItem, setNewItem] = useState<ItemWithId | null>(null)
|
||||||
|
|
||||||
if (!config || !isAuthenticated || !isEditMode || !canManageSite) return null
|
if (!config || !isAuthenticated || !isEditMode || !canManageSite) return null
|
||||||
@@ -250,7 +250,7 @@ export function SingletonPill({
|
|||||||
createDefaults?: Record<string, unknown> | (() => Record<string, unknown>)
|
createDefaults?: Record<string, unknown> | (() => Record<string, unknown>)
|
||||||
}) {
|
}) {
|
||||||
const { isAuthenticated, isEditMode, runSave, canManageSite } = useAdmin()
|
const { isAuthenticated, isEditMode, runSave, canManageSite } = useAdmin()
|
||||||
const config = ENTITIES[resource]
|
const config = entityConfig(resource)
|
||||||
const { data, updateSite } = useSiteData()
|
const { data, updateSite } = useSiteData()
|
||||||
const [drawerOpen, setDrawerOpen] = useState(false)
|
const [drawerOpen, setDrawerOpen] = useState(false)
|
||||||
const [created, setCreated] = useState<ItemWithId | null>(null)
|
const [created, setCreated] = useState<ItemWithId | null>(null)
|
||||||
|
|||||||
@@ -270,10 +270,16 @@ export const ENTITIES: Record<string, EntityConfig> = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** تعریف موجودیت بر اساس resource (نشانی API) — کلید فهرست همیشه با resource یکی نیست
|
||||||
|
* (why_us/contact_section/seo_meta/… کلید snake_case دارند ولی resource کبابکامل است) */
|
||||||
|
export function entityConfig(resource: string): EntityConfig | undefined {
|
||||||
|
return Object.values(ENTITIES).find((c) => c.resource === resource)
|
||||||
|
}
|
||||||
|
|
||||||
/** آیا فیلد در منبع داده قابل ترجمه است؟ (فیلدهای مشترک و پسوندهای انگلیسی قبلی خیر) */
|
/** آیا فیلد در منبع داده قابل ترجمه است؟ (فیلدهای مشترک و پسوندهای انگلیسی قبلی خیر) */
|
||||||
export function isTranslatable(resource: string, name: string): boolean {
|
export function isTranslatable(resource: string, name: string): boolean {
|
||||||
if (name.endsWith('_en')) return false
|
if (name.endsWith('_en')) return false
|
||||||
const config = ENTITIES[resource]
|
const config = entityConfig(resource)
|
||||||
return !!config?.fields.some((f) => f.name === name && !f.shared)
|
return !!config?.fields.some((f) => f.name === name && !f.shared)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user