Add Contact standard object, related lists, meilisearch, pagination, search, AI assistant
This commit is contained in:
@@ -50,7 +50,9 @@ export const useFields = () => {
|
||||
step: fieldDef.step,
|
||||
accept: fieldDef.accept,
|
||||
relationObject: fieldDef.relationObject,
|
||||
relationObjects: fieldDef.relationObjects,
|
||||
relationDisplayField: fieldDef.relationDisplayField,
|
||||
relationTypeField: fieldDef.relationTypeField,
|
||||
|
||||
// Formatting
|
||||
format: fieldDef.format,
|
||||
@@ -76,7 +78,8 @@ export const useFields = () => {
|
||||
objectApiName: objectDef.apiName,
|
||||
mode: 'list' as ViewMode,
|
||||
fields,
|
||||
pageSize: 25,
|
||||
pageSize: 10,
|
||||
maxFrontendRecords: 500,
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
exportable: true,
|
||||
@@ -97,6 +100,7 @@ export const useFields = () => {
|
||||
objectApiName: objectDef.apiName,
|
||||
mode: 'detail' as ViewMode,
|
||||
fields,
|
||||
relatedLists: objectDef.relatedLists || [],
|
||||
...customConfig,
|
||||
}
|
||||
}
|
||||
@@ -180,6 +184,7 @@ export const useViewState = <T extends { id?: string }>(
|
||||
apiEndpoint: string
|
||||
) => {
|
||||
const records = ref<T[]>([])
|
||||
const totalCount = ref(0)
|
||||
const currentRecord = ref<T | null>(null)
|
||||
const currentView = ref<'list' | 'detail' | 'edit'>('list')
|
||||
const loading = ref(false)
|
||||
@@ -188,13 +193,51 @@ export const useViewState = <T extends { id?: string }>(
|
||||
|
||||
const { api } = useApi()
|
||||
|
||||
const fetchRecords = async (params?: Record<string, any>) => {
|
||||
const normalizeListResponse = (response: any) => {
|
||||
const payload: { data: T[]; totalCount: number; page?: number; pageSize?: number } = {
|
||||
data: [],
|
||||
totalCount: 0,
|
||||
}
|
||||
|
||||
if (Array.isArray(response)) {
|
||||
payload.data = response
|
||||
payload.totalCount = response.length
|
||||
return payload
|
||||
}
|
||||
|
||||
if (response && typeof response === 'object') {
|
||||
if (Array.isArray(response.data)) {
|
||||
payload.data = response.data
|
||||
} else if (Array.isArray((response as any).records)) {
|
||||
payload.data = (response as any).records
|
||||
} else if (Array.isArray((response as any).results)) {
|
||||
payload.data = (response as any).results
|
||||
}
|
||||
|
||||
payload.totalCount =
|
||||
response.totalCount ??
|
||||
response.total ??
|
||||
response.count ??
|
||||
payload.data.length ??
|
||||
0
|
||||
payload.page = response.page
|
||||
payload.pageSize = response.pageSize
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
const fetchRecords = async (params?: Record<string, any>, options?: { append?: boolean }) => {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const response = await api.get(apiEndpoint, { params })
|
||||
// Handle response - data might be directly in response or in response.data
|
||||
records.value = response.data || response || []
|
||||
const normalized = normalizeListResponse(response)
|
||||
totalCount.value = normalized.totalCount ?? normalized.data.length ?? 0
|
||||
records.value = options?.append
|
||||
? [...records.value, ...normalized.data]
|
||||
: normalized.data
|
||||
return normalized
|
||||
} catch (e: any) {
|
||||
error.value = e.message
|
||||
console.error('Failed to fetch records:', e)
|
||||
@@ -227,6 +270,7 @@ export const useViewState = <T extends { id?: string }>(
|
||||
// Handle response - it might be the data directly or wrapped in { data: ... }
|
||||
const recordData = response.data || response
|
||||
records.value.push(recordData)
|
||||
totalCount.value += 1
|
||||
currentRecord.value = recordData
|
||||
return recordData
|
||||
} catch (e: any) {
|
||||
@@ -269,6 +313,7 @@ export const useViewState = <T extends { id?: string }>(
|
||||
try {
|
||||
await api.delete(`${apiEndpoint}/${id}`)
|
||||
records.value = records.value.filter(r => r.id !== id)
|
||||
totalCount.value = Math.max(0, totalCount.value - 1)
|
||||
if (currentRecord.value?.id === id) {
|
||||
currentRecord.value = null
|
||||
}
|
||||
@@ -285,8 +330,25 @@ export const useViewState = <T extends { id?: string }>(
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const useBulkEndpoint = apiEndpoint.includes('/runtime/objects/')
|
||||
if (useBulkEndpoint) {
|
||||
const response = await api.post(`${apiEndpoint}/bulk-delete`, { ids })
|
||||
const deletedIds = Array.isArray(response?.deletedIds) ? response.deletedIds : ids
|
||||
records.value = records.value.filter(r => !deletedIds.includes(r.id!))
|
||||
totalCount.value = Math.max(0, totalCount.value - deletedIds.length)
|
||||
return {
|
||||
deletedIds,
|
||||
deniedIds: Array.isArray(response?.deniedIds) ? response.deniedIds : [],
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(ids.map(id => api.delete(`${apiEndpoint}/${id}`)))
|
||||
records.value = records.value.filter(r => !ids.includes(r.id!))
|
||||
totalCount.value = Math.max(0, totalCount.value - ids.length)
|
||||
return {
|
||||
deletedIds: ids,
|
||||
deniedIds: [],
|
||||
}
|
||||
} catch (e: any) {
|
||||
error.value = e.message
|
||||
console.error('Failed to delete records:', e)
|
||||
@@ -324,6 +386,7 @@ export const useViewState = <T extends { id?: string }>(
|
||||
return {
|
||||
// State
|
||||
records,
|
||||
totalCount,
|
||||
currentRecord,
|
||||
currentView,
|
||||
loading,
|
||||
|
||||
Reference in New Issue
Block a user