fix: surface status in note list chip picker

This commit is contained in:
lucaronin
2026-04-08 20:56:12 +02:00
parent 459145ba0d
commit 3feb167b12
3 changed files with 151 additions and 21 deletions

View File

@@ -82,6 +82,10 @@ function resolveChipValues(
allEntries: VaultEntry[],
typeEntryMap: Record<string, VaultEntry>,
): PropertyChipValue[] {
if (propName.toLowerCase() === 'status') {
const formatted = formatChipValue(entry.status)
return formatted ? [{ label: formatted, noteIcon: null, typeIcon: null }] : []
}
// Check relationships first (wikilink values)
const relKey = Object.keys(entry.relationships).find((k) => k.toLowerCase() === propName.toLowerCase())
if (relKey) {

View File

@@ -193,6 +193,83 @@ describe('NoteList rendering', () => {
expect(onUpdateInboxNoteListProperties).toHaveBeenCalledWith(['Priority', 'Owner'])
})
it('shows status in the type column picker when at least one note has it set', () => {
const entries = [
makeTypeDefinition('Book'),
makeEntry({
path: '/vault/book.md',
filename: 'book.md',
title: 'Book Note',
isA: 'Book',
status: 'Active',
createdAt: 1700000000,
}),
]
renderNoteList({
entries,
selection: { kind: 'sectionGroup', type: 'Book' },
onUpdateTypeSort: () => undefined,
})
act(() => {
openNoteListPropertiesPicker('type')
})
expect(screen.getByTestId('list-properties-popover')).toBeInTheDocument()
expect(screen.getByRole('checkbox', { name: 'status' })).toBeInTheDocument()
})
it('keeps blank statuses out of the type column picker', () => {
const entries = [
makeTypeDefinition('Book'),
makeEntry({
path: '/vault/book.md',
filename: 'book.md',
title: 'Book Note',
isA: 'Book',
status: '',
properties: { Owner: 'Luca' },
createdAt: 1700000000,
}),
]
renderNoteList({
entries,
selection: { kind: 'sectionGroup', type: 'Book' },
onUpdateTypeSort: () => undefined,
})
act(() => {
openNoteListPropertiesPicker('type')
})
expect(screen.getByTestId('list-properties-popover')).toBeInTheDocument()
expect(screen.getByRole('checkbox', { name: 'Owner' })).toBeInTheDocument()
expect(screen.queryByRole('checkbox', { name: 'status' })).not.toBeInTheDocument()
})
it('renders status as a note-list chip when a type displays it', () => {
const entries = [
makeTypeDefinition('Book', ['status']),
makeEntry({
path: '/vault/book.md',
filename: 'book.md',
title: 'Book Note',
isA: 'Book',
status: 'Active',
createdAt: 1700000000,
}),
]
renderNoteList({
entries,
selection: { kind: 'sectionGroup', type: 'Book' },
})
expect(screen.getByTestId('property-chips')).toHaveTextContent('Active')
})
it('uses inbox overrides when configured', () => {
const entries = [
makeTypeDefinition('Book', ['Priority']),

View File

@@ -288,9 +288,14 @@ export function useVisibleNotesSync({ visibleNotesRef, isEntityView, searched, s
// --- useListPropertyPicker ---
function hasScalarListPropertyValue(value: string | null): boolean {
return value !== null && value.trim() !== ''
}
function collectAvailableProperties(entries: VaultEntry[]): string[] {
const keys = new Set<string>()
for (const entry of entries) {
if (hasScalarListPropertyValue(entry.status)) keys.add('status')
for (const key of Object.keys(entry.properties ?? {})) keys.add(key)
for (const key of Object.keys(entry.relationships ?? {})) keys.add(key)
}
@@ -324,6 +329,58 @@ export interface NoteListPropertyPicker {
triggerTitle: string
}
interface BuildInboxPropertyPickerParams {
isInboxView: boolean
onUpdateInboxNoteListProperties?: (value: string[] | null) => void
inboxAvailableProperties: string[]
hasCustomInboxProperties: boolean
inboxNoteListProperties?: string[] | null
inboxDefaultDisplay: string[]
}
function buildInboxPropertyPicker({
isInboxView,
onUpdateInboxNoteListProperties,
inboxAvailableProperties,
hasCustomInboxProperties,
inboxNoteListProperties,
inboxDefaultDisplay,
}: BuildInboxPropertyPickerParams): NoteListPropertyPicker | null {
if (!isInboxView || !onUpdateInboxNoteListProperties) return null
return {
scope: 'inbox',
availableProperties: inboxAvailableProperties,
currentDisplay: hasCustomInboxProperties ? inboxNoteListProperties ?? [] : inboxDefaultDisplay,
onSave: onUpdateInboxNoteListProperties,
triggerTitle: 'Customize Inbox columns',
}
}
interface BuildTypePropertyPickerParams {
isSectionGroup: boolean
typeDocument: VaultEntry | null
onUpdateTypeSort?: (path: string, key: string, value: string | number | boolean | string[] | null) => void
typeAvailableProperties: string[]
}
function buildTypePropertyPicker({
isSectionGroup,
typeDocument,
onUpdateTypeSort,
typeAvailableProperties,
}: BuildTypePropertyPickerParams): NoteListPropertyPicker | null {
if (!isSectionGroup || !typeDocument || !onUpdateTypeSort) return null
return {
scope: 'type',
availableProperties: typeAvailableProperties,
currentDisplay: typeDocument.listPropertiesDisplay ?? [],
onSave: (value: string[] | null) => onUpdateTypeSort(typeDocument.path, '_list_properties_display', value),
triggerTitle: 'Customize columns',
}
}
interface UseListPropertyPickerParams {
entries: VaultEntry[]
selection: SidebarSelection
@@ -368,27 +425,19 @@ export function useListPropertyPicker({
const inboxDisplayOverride = isInboxView && hasCustomInboxProperties ? inboxNoteListProperties : null
const propertyPicker = useMemo<NoteListPropertyPicker | null>(() => {
if (isInboxView && onUpdateInboxNoteListProperties) {
return {
scope: 'inbox',
availableProperties: inboxAvailableProperties,
currentDisplay: hasCustomInboxProperties ? inboxNoteListProperties ?? [] : inboxDefaultDisplay,
onSave: onUpdateInboxNoteListProperties,
triggerTitle: 'Customize Inbox columns',
}
}
if (isSectionGroup && typeDocument && onUpdateTypeSort) {
return {
scope: 'type',
availableProperties: typeAvailableProperties,
currentDisplay: typeDocument.listPropertiesDisplay ?? [],
onSave: (value: string[] | null) => onUpdateTypeSort(typeDocument.path, '_list_properties_display', value),
triggerTitle: 'Customize columns',
}
}
return null
return buildInboxPropertyPicker({
isInboxView,
onUpdateInboxNoteListProperties,
inboxAvailableProperties,
hasCustomInboxProperties,
inboxNoteListProperties,
inboxDefaultDisplay,
}) ?? buildTypePropertyPicker({
isSectionGroup,
typeDocument,
onUpdateTypeSort,
typeAvailableProperties,
})
}, [
hasCustomInboxProperties,
inboxAvailableProperties,