import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { DefaultListView, HydrateAuthProvider, ListQueryProvider } from '@payloadcms/ui'; import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent'; import { getColumns, renderFilters, renderTable, upsertPreferences } from '@payloadcms/ui/rsc'; import { notFound } from 'next/navigation.js'; import { appendUploadSelectFields, combineWhereConstraints, formatAdminURL, isNumber, mergeListSearchAndWhere, transformColumnsToPreferences, transformColumnsToSearchParams } from 'payload/shared'; import React, { Fragment } from 'react'; import { getDocumentPermissions } from '../Document/getDocumentPermissions.js'; import { enrichDocsWithVersionStatus } from './enrichDocsWithVersionStatus.js'; import { handleGroupBy } from './handleGroupBy.js'; import { renderListViewSlots } from './renderListViewSlots.js'; import { resolveAllFilterOptions } from './resolveAllFilterOptions.js'; import { transformColumnsToSelect } from './transformColumnsToSelect.js'; /** * This function is responsible for rendering * the list view on the server for both: * - default list view * - list view within drawers * * @internal */ export const renderListView = async args => { const { clientConfig, ComponentOverride, customCellProps, disableBulkDelete, disableBulkEdit, disableQueryPresets, drawerSlug, enableRowSelections, initPageResult, overrideEntityVisibility, params, query: queryFromArgs, searchParams, trash, viewType } = args; const { collectionConfig, collectionConfig: { slug: collectionSlug }, locale: fullLocale, permissions, req, req: { i18n, payload, payload: { config }, query: queryFromReq, user }, visibleEntities } = initPageResult; const { routes: { admin: adminRoute } } = config; if (!collectionConfig || !permissions?.collections?.[collectionSlug]?.read || !visibleEntities.collections.includes(collectionSlug) && !overrideEntityVisibility) { throw new Error('not-found'); } const query = queryFromArgs || queryFromReq; const columnsFromQuery = transformColumnsToPreferences(query?.columns); query.queryByGroup = query?.queryByGroup && typeof query.queryByGroup === 'string' ? JSON.parse(query.queryByGroup) : query?.queryByGroup; const collectionPreferences = await upsertPreferences({ key: `collection-${collectionSlug}`, req, value: { columns: columnsFromQuery, groupBy: query?.groupBy, limit: isNumber(query?.limit) ? Number(query.limit) : undefined, preset: query?.preset, sort: query?.sort } }); let queryPreset; let queryPresetPermissions; if (collectionPreferences?.preset) { try { queryPreset = await payload.findByID({ id: collectionPreferences?.preset, collection: 'payload-query-presets', depth: 0, overrideAccess: false, user }); if (queryPreset) { queryPresetPermissions = (await getDocumentPermissions({ id: queryPreset.id, collectionConfig: req.payload.collections['payload-query-presets'].config, data: queryPreset, req }))?.docPermissions; } } catch (err) { req.payload.logger.error(`Error fetching query preset or preset permissions: ${err}`); } } query.preset = queryPreset?.id; if (queryPreset?.where && !query.where) { query.where = queryPreset.where; } query.groupBy = query.groupBy ?? queryPreset?.groupBy ?? collectionPreferences?.groupBy; const columnPreference = query.columns ? transformColumnsToPreferences(query.columns) : queryPreset?.columns ?? collectionPreferences?.columns; query.columns = transformColumnsToSearchParams(columnPreference); query.page = isNumber(query?.page) ? Number(query.page) : 0; query.limit = collectionPreferences?.limit || collectionConfig.admin.pagination.defaultLimit; query.sort = collectionPreferences?.sort || (typeof collectionConfig.defaultSort === 'string' ? collectionConfig.defaultSort : undefined); const baseFilterConstraint = await (collectionConfig.admin?.baseFilter ?? collectionConfig.admin?.baseListFilter)?.({ limit: query.limit, page: query.page, req, sort: query.sort }); let whereWithMergedSearch = mergeListSearchAndWhere({ collectionConfig, search: typeof query?.search === 'string' ? query.search : undefined, where: combineWhereConstraints([query?.where, baseFilterConstraint]) }); if (trash === true) { whereWithMergedSearch = { and: [whereWithMergedSearch, { deletedAt: { exists: true } }] }; } let Table = null; let columnState = []; let data = { // no results default docs: [], hasNextPage: false, hasPrevPage: false, limit: query.limit, nextPage: null, page: 1, pagingCounter: 0, prevPage: null, totalDocs: 0, totalPages: 0 }; const clientCollectionConfig = clientConfig.collections.find(c => c.slug === collectionSlug); const columns = getColumns({ clientConfig, collectionConfig: clientCollectionConfig, collectionSlug, columns: columnPreference, i18n, permissions }); const select = collectionConfig.admin.enableListViewSelectAPI ? transformColumnsToSelect(columns) : undefined; /** Force select image fields for list view thumbnails */ appendUploadSelectFields({ collectionConfig, select }); try { if (collectionConfig.admin.groupBy && query.groupBy) { ({ columnState, data, Table } = await handleGroupBy({ clientCollectionConfig, clientConfig, collectionConfig, collectionSlug, columns, customCellProps, drawerSlug, enableRowSelections, fieldPermissions: permissions?.collections?.[collectionSlug]?.fields, query, req, select, trash, user, viewType, where: whereWithMergedSearch })); // Enrich documents with correct display status for drafts data = await enrichDocsWithVersionStatus({ collectionConfig, data, req }); } else { data = await req.payload.find({ collection: collectionSlug, depth: 0, draft: true, fallbackLocale: false, includeLockStatus: true, limit: query?.limit ? Number(query.limit) : undefined, locale: req.locale, overrideAccess: false, page: query?.page ? Number(query.page) : undefined, req, select, sort: query?.sort, trash, user, where: whereWithMergedSearch }); // Enrich documents with correct display status for drafts data = await enrichDocsWithVersionStatus({ collectionConfig, data, req }); ({ columnState, Table } = renderTable({ clientCollectionConfig, collectionConfig, columns, customCellProps, data, drawerSlug, enableRowSelections, fieldPermissions: permissions?.collections?.[collectionSlug]?.fields, i18n: req.i18n, orderableFieldName: collectionConfig.orderable === true ? '_order' : undefined, payload: req.payload, query, req, useAsTitle: collectionConfig.admin.useAsTitle, viewType })); } } catch (err) { if (err.name !== 'QueryError') { // QueryErrors are expected when a user filters by a field they do not have access to req.payload.logger.error({ err, msg: `There was an error fetching the list view data for collection ${collectionSlug}` }); throw err; } } const renderedFilters = renderFilters(collectionConfig.fields, req.payload.importMap); const resolvedFilterOptions = await resolveAllFilterOptions({ fields: collectionConfig.fields, req }); const staticDescription = typeof collectionConfig.admin.description === 'function' ? collectionConfig.admin.description({ t: i18n.t }) : collectionConfig.admin.description; const newDocumentURL = formatAdminURL({ adminRoute, path: `/collections/${collectionSlug}/create` }); const hasCreatePermission = permissions?.collections?.[collectionSlug]?.create; const hasDeletePermission = permissions?.collections?.[collectionSlug]?.delete; // Check if there's a notFound query parameter (document ID that wasn't found) const notFoundDocId = typeof searchParams?.notFound === 'string' ? searchParams.notFound : null; const serverProps = { collectionConfig, data, i18n, limit: query.limit, listPreferences: collectionPreferences, listSearchableFields: collectionConfig.admin.listSearchableFields, locale: fullLocale, params, payload, permissions, searchParams, user }; const listViewSlots = renderListViewSlots({ clientProps: { collectionSlug, hasCreatePermission, hasDeletePermission, newDocumentURL }, collectionConfig, description: staticDescription, notFoundDocId, payload, serverProps }); const isInDrawer = Boolean(drawerSlug); // Needed to prevent: Only plain objects can be passed to Client Components from Server Components. Objects with toJSON methods are not supported. Convert it manually to a simple value before passing it to props. // Is there a way to avoid this? The `where` object is already seemingly plain, but is not bc it originates from the params. query.where = query?.where ? JSON.parse(JSON.stringify(query?.where || {})) : undefined; return { List: /*#__PURE__*/_jsxs(Fragment, { children: [/*#__PURE__*/_jsx(HydrateAuthProvider, { permissions: permissions }), /*#__PURE__*/_jsx(ListQueryProvider, { collectionSlug: collectionSlug, data: data, modifySearchParams: !isInDrawer, orderableFieldName: collectionConfig.orderable === true ? '_order' : undefined, query: query, children: RenderServerComponent({ clientProps: { ...listViewSlots, collectionSlug, columnState, disableBulkDelete, disableBulkEdit: collectionConfig.disableBulkEdit ?? disableBulkEdit, disableQueryPresets, enableRowSelections, hasCreatePermission, hasDeletePermission, listPreferences: collectionPreferences, newDocumentURL, queryPreset, queryPresetPermissions, renderedFilters, resolvedFilterOptions, Table, viewType }, Component: ComponentOverride ?? collectionConfig?.admin?.components?.views?.list?.Component, Fallback: DefaultListView, importMap: payload.importMap, serverProps }) })] }) }; }; export const ListView = async args => { try { const { List: RenderedList } = await renderListView({ ...args, enableRowSelections: true }); return RenderedList; } catch (error) { // Pass through Next.js errors if (error.message === 'not-found') { notFound(); } else { console.error(error); // eslint-disable-line no-console } } }; //# sourceMappingURL=index.js.map