import { Text, Badge, Tooltip, Group } from "@mantine/core"; import { IconCheck, IconFileDescription } from "@tabler/icons-react"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { sanitizeUrl } from "@docmost/editor-ext"; import { IBaseProperty, SelectTypeOptions, NumberTypeOptions, DateTypeOptions, isFormulaErrorCell, } from "@/ee/base/types/base.types"; import { choiceColor } from "@/ee/base/components/cells/choice-color"; import { ChoiceBadge } from "@/ee/base/components/cells/choice-badge"; import { BadgeOverflowList } from "@/ee/base/components/cells/badge-overflow"; import { PersonReadList } from "@/ee/base/components/cells/person-read-list"; import { CustomAvatar } from "@/components/ui/custom-avatar"; import { useReferenceStore, useResolvePage } from "@/ee/base/reference/reference-store"; import { formatNumber, formatDateDisplay, formatTimestamp, formatLongTextPreview, } from "@/ee/base/formatters/cell-formatters"; import { buildPageUrl, getPageTitle } from "@/features/page/page.utils"; import { FileValue } from "@/ee/base/components/cells/cell-file"; import cellClasses from "@/ee/base/styles/cells.module.css"; type CardFieldProps = { property: IBaseProperty; value: unknown; pageId: string; }; export function CardField({ property, value, pageId }: CardFieldProps) { if (value === null || value === undefined || value === "") return null; if (Array.isArray(value) && value.length === 0) return null; switch (property.type) { case "text": return ; case "longText": return ; case "number": return ; case "select": case "status": return ; case "multiSelect": return ; case "date": return ; case "createdAt": case "lastEditedAt": return ; case "person": return ; case "lastEditedBy": return ; case "file": return ; case "page": return ; case "checkbox": return ; case "url": return ; case "email": return ; case "formula": return ; default: return ( {String(value)} ); } } function TextField({ value }: { value: unknown }) { const text = typeof value === "string" ? value : String(value); if (!text) return null; return ( {text} ); } function LongTextField({ value }: { value: unknown }) { const preview = formatLongTextPreview(typeof value === "string" ? value : undefined); if (!preview) return null; return ( {preview} ); } function NumberField({ value, property }: { value: unknown; property: IBaseProperty }) { const num = typeof value === "number" ? value : null; if (num === null) return null; const formatted = formatNumber(num, property.typeOptions as NumberTypeOptions | undefined); if (!formatted) return null; return {formatted}; } function SelectField({ value, property }: { value: unknown; property: IBaseProperty }) { const choices = (property.typeOptions as SelectTypeOptions | undefined)?.choices ?? []; const selectedId = typeof value === "string" ? value : null; const choice = choices.find((c) => c.id === selectedId); if (!choice) return null; return ( ); } function MultiSelectField({ value, property }: { value: unknown; property: IBaseProperty }) { const choices = (property.typeOptions as SelectTypeOptions | undefined)?.choices ?? []; const selectedIds = Array.isArray(value) ? (value as string[]) : []; const selectedChoices = choices.filter((c) => selectedIds.includes(c.id)); if (selectedChoices.length === 0) return null; const chips = selectedChoices.map((choice) => ( {choice.name} )); return ( `${c.id}:${c.name}`).join("|")} tooltipLabel={selectedChoices.map((c) => c.name).join(", ")} /> ); } function DateField({ value, property }: { value: unknown; property: IBaseProperty }) { const dateStr = typeof value === "string" ? value : null; const formatted = formatDateDisplay(dateStr, property.typeOptions as DateTypeOptions | undefined); if (!formatted) return null; return ( {formatted} ); } function TimestampField({ value }: { value: unknown }) { const formatted = formatTimestamp(typeof value === "string" ? value : null); if (!formatted) return null; return ( {formatted} ); } function PersonField({ value, pageId }: { value: unknown; pageId: string }) { const store = useReferenceStore(pageId); const personIds = Array.isArray(value) ? (value as string[]) : typeof value === "string" ? [value] : []; if (personIds.length === 0) return null; return ; } function LastEditedByField({ value, pageId }: { value: unknown; pageId: string }) { const userId = typeof value === "string" ? value : null; const store = useReferenceStore(pageId); if (!userId) return null; const user = store.users[userId] ?? null; const name = user?.name ?? userId.substring(0, 8); return ( {name} ); } function FileField({ value }: { value: unknown }) { const files = Array.isArray(value) ? (value as FileValue[]).filter((f) => f && typeof f === "object" && "id" in f && "fileName" in f) : []; if (files.length === 0) return null; const maxVisible = 2; const visible = files.slice(0, maxVisible); const overflow = files.length - maxVisible; return (
{visible.map((file) => ( {file.fileName} ))} {overflow > 0 && +{overflow}}
); } function PageField({ value, basePageId, propertyPageId, }: { value: unknown; basePageId: string; propertyPageId: string; }) { const { t } = useTranslation(); const pageId = typeof value === "string" && value.length > 0 ? value : null; const resolvedPage = useResolvePage(propertyPageId, pageId); if (!pageId) return null; if (resolvedPage === undefined) return null; if (resolvedPage === null) { return ( Page not found ); } const title = getPageTitle(resolvedPage.title, undefined, t); const spaceSlug = resolvedPage.space?.slug ?? ""; const url = buildPageUrl(spaceSlug, resolvedPage.slugId, title); return ( e.stopPropagation()} onDoubleClick={(e) => e.stopPropagation()} > {resolvedPage.icon ? ( {resolvedPage.icon} ) : ( )} {title} ); } function CheckboxField({ value }: { value: unknown }) { if (value !== true) return null; return ; } function UrlField({ value }: { value: unknown }) { const displayValue = typeof value === "string" ? value : ""; if (!displayValue) return null; const safeHref = sanitizeUrl(displayValue); if (!safeHref) { return ( {displayValue} ); } return ( e.stopPropagation()} style={{ fontSize: "var(--mantine-font-size-xs)" }} > {displayValue} ); } function EmailField({ value }: { value: unknown }) { const displayValue = typeof value === "string" ? value : ""; if (!displayValue) return null; return ( e.stopPropagation()} style={{ fontSize: "var(--mantine-font-size-xs)" }} > {displayValue} ); } function FormulaField({ value, property }: { value: unknown; property: IBaseProperty }) { if (isFormulaErrorCell(value)) { return ( #ERROR ); } const opts = (property.typeOptions ?? {}) as { resultType?: string }; const resultType = opts.resultType ?? "null"; if (resultType === "number") { return ; } if (resultType === "boolean") { return ; } if (resultType === "date") { return ; } const text = typeof value === "string" ? value : value != null ? String(value) : null; if (!text) return null; return ( {text} ); }