Documentation
List facet example
Build a typed backoffice list facet with columns, filters, sorts, and Relay data.
A list facet describes how a backoffice entity appears in list views: its query, fragment, rows, columns, filters, sorts, and default state.
import {
createListFacet,
type BackofficeColumnSpec,
type BackofficeFilterSpec,
type BackofficeListFacetConfig,
type BackofficeSortSpec,
} from '@plumile/backoffice-core';
import { ProjectListPageQuery } from '../queries/ProjectListPageQuery.js';
import { ProjectListFragment } from '../queries/ProjectListFragment.js';
type ProjectWhere = {
archived?: boolean;
owner?: { id?: string };
};
type ProjectSort = 'CREATED_AT_DESC' | 'CREATED_AT_ASC';
type ProjectRowRef = {
id: string;
name: string;
owner: { id: string; name: string } | null;
createdAt: string;
};
type ProjectRow = {
id: string;
name: string;
ownerName: string | null;
createdAt: string;
};
const columns: readonly BackofficeColumnSpec<ProjectRow>[] = [
{
: 'name',
header: (t) => t('project.columns.name'),
: 'lg',
: {
: 'link',
value: (row) => row.name,
to: (row) => `/projects/${row.id}`,
},
},
{
: 'owner',
header: (t) => t('project.columns.owner'),
: 'md',
: {: 'text', value: (row) => row.ownerName },
},
];
const filters: readonly BackofficeFilterSpec<ProjectWhere>[] = [
{
: 'ownerId',
: 'entityId',
: 'users',
label: (t) => t('project.filters.owner'),
toGraphQL: (value) => ({: {: value } }),
fromGraphQL: (where) => where.owner?.id ?? null,
},
];
const sorts: readonly BackofficeSortSpec<ProjectSort>[] = [
{: 'CREATED_AT_DESC', label: (t) => t('sort.newest') },
{: 'CREATED_AT_ASC', label: (t) => t('sort.oldest') },
];
export const projectListFacet = createListFacet({
: 'list',
: 'projects',
label: (t) => t('project.entity.plural'),
: {
title: (t) => t('project.entity.plural'),
: ProjectListPageQuery,
: ProjectListFragment,
getConnection: (data) => data.projects,
toRow: (node: ProjectRowRef): ProjectRow => ({
: node.id,
: node.name,
: node.owner?.name ?? null,
: node.createdAt,
}),
getRowId: (row) => row.id,
columns,
filters,
sorts,
: {: 'CREATED_AT_DESC' },
},
} satisfies BackofficeListFacetConfig<ProjectWhere, ProjectSort>);Keep GraphQL-specific mapping in the facet module or a nearby helper. This keeps visual columns, filters, and URL state aligned with the list query.
For standalone URL-to-GraphQL filter mapping, see GraphQL where.