Restore icon property in inspector
This commit is contained in:
@@ -67,7 +67,7 @@ describe('DynamicPropertiesPanel system metadata', () => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('hides underscored and legacy system metadata while keeping user properties visible', () => {
|
||||
it('keeps the icon visible while hiding the other system metadata', () => {
|
||||
render(
|
||||
<DynamicPropertiesPanel
|
||||
entry={makeEntry()}
|
||||
@@ -86,7 +86,9 @@ describe('DynamicPropertiesPanel system metadata', () => {
|
||||
|
||||
expect(screen.getByText('Owner')).toBeInTheDocument()
|
||||
expect(screen.getByText('Luca')).toBeInTheDocument()
|
||||
expect(screen.queryByText('Icon')).not.toBeInTheDocument()
|
||||
expect(screen.getByText('Icon')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('icon-editable-display')).toHaveTextContent('rocket')
|
||||
expect(screen.queryByDisplayValue('legacy')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('Order')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('Sort')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('Sidebar label')).not.toBeInTheDocument()
|
||||
@@ -130,4 +132,18 @@ describe('DynamicPropertiesPanel system metadata', () => {
|
||||
|
||||
expect(onAddProperty).toHaveBeenCalledWith('_icon', 'rocket')
|
||||
})
|
||||
|
||||
it('renders an existing underscored icon property with the icon picker UI', () => {
|
||||
render(
|
||||
<DynamicPropertiesPanel
|
||||
entry={makeEntry()}
|
||||
content=""
|
||||
frontmatter={{ _icon: 'megaphone' }}
|
||||
onAddProperty={onAddProperty}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('Icon')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('icon-editable-display')).toHaveTextContent('megaphone')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -697,21 +697,20 @@ describe('DynamicPropertiesPanel', () => {
|
||||
})
|
||||
|
||||
describe('system property filtering', () => {
|
||||
it('hides archived, archived_at, and legacy icon metadata from the properties panel', () => {
|
||||
it('hides archived metadata but keeps the note icon visible in the properties panel', () => {
|
||||
renderEditablePanel({ archived: false, archived_at: '', icon: '📝', cadence: 'Weekly' })
|
||||
expect(screen.queryByText('Archived')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('Archived at')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('Icon')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('📝')).not.toBeInTheDocument()
|
||||
// Custom property still visible
|
||||
expect(screen.getByText('Icon')).toBeInTheDocument()
|
||||
expect(screen.getByText('📝')).toBeInTheDocument()
|
||||
expect(screen.getByText('Cadence')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('hides legacy icon metadata even when cased differently', () => {
|
||||
it('keeps the note icon visible even when cased differently', () => {
|
||||
renderEditablePanel({ Archived: false, Icon: '🎯', cadence: 'Daily' })
|
||||
expect(screen.queryByText('Archived')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('Icon')).not.toBeInTheDocument()
|
||||
expect(screen.queryByText('🎯')).not.toBeInTheDocument()
|
||||
expect(screen.getByText('Icon')).toBeInTheDocument()
|
||||
expect(screen.getByText('🎯')).toBeInTheDocument()
|
||||
expect(screen.getByText('Cadence')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { getTagStyle } from '../utils/tagStyles'
|
||||
import { ColorEditableValue } from './ColorInput'
|
||||
import { IconEditableValue } from './IconEditableValue'
|
||||
import { PROPERTY_CHIP_STYLE } from './propertyChipStyles'
|
||||
import { canonicalSystemMetadataKey } from '../utils/systemMetadata'
|
||||
|
||||
function parseDateValue(value: string): Date | undefined {
|
||||
const iso = toISODate(value)
|
||||
@@ -307,7 +308,7 @@ function toBooleanValue(value: FrontmatterValue): boolean {
|
||||
}
|
||||
|
||||
function autoDetectFromValue(propKey: string, value: FrontmatterValue): PropertyDisplayMode {
|
||||
if (propKey.toLowerCase() === 'icon') return 'text'
|
||||
if (canonicalSystemMetadataKey(propKey) === '_icon') return 'text'
|
||||
if (typeof value === 'boolean') return 'boolean'
|
||||
if (typeof value === 'string' && isUrlValue(value)) return 'url'
|
||||
if (typeof value === 'string' && isValidCssColor(value) && value.startsWith('#')) return 'color'
|
||||
@@ -405,7 +406,7 @@ function ScalarValueCell(props: SmartCellProps) {
|
||||
onSave,
|
||||
})
|
||||
|
||||
if (propKey.toLowerCase() === 'icon') {
|
||||
if (canonicalSystemMetadataKey(propKey) === '_icon') {
|
||||
return <IconEditableValue {...editProps} />
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
removeDisplayModeOverride,
|
||||
} from '../utils/propertyTypes'
|
||||
import { containsWikilinks } from '../components/DynamicPropertiesPanel'
|
||||
import { isSystemMetadataKey } from '../utils/systemMetadata'
|
||||
import { canonicalSystemMetadataKey, isSystemMetadataKey } from '../utils/systemMetadata'
|
||||
|
||||
// Keys to skip showing in Properties (handled by dedicated UI or internal)
|
||||
// Compared case-insensitively via isVisibleProperty()
|
||||
@@ -79,6 +79,22 @@ function isVisibleProperty([key, value]: [string, FrontmatterValue]): boolean {
|
||||
return !isHiddenPropertyKey(key) && !containsWikilinks(value)
|
||||
}
|
||||
|
||||
function buildVisiblePropertyEntries(frontmatter: ParsedFrontmatter): [string, FrontmatterValue][] {
|
||||
const result: [string, FrontmatterValue][] = []
|
||||
const seen = new Set<string>()
|
||||
|
||||
for (const [key, value] of Object.entries(frontmatter)) {
|
||||
if (!isVisibleProperty([key, value])) continue
|
||||
|
||||
const canonicalKey = canonicalSystemMetadataKey(key)
|
||||
if (seen.has(canonicalKey)) continue
|
||||
seen.add(canonicalKey)
|
||||
result.push([key, value])
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function addTagValues(tagsByKey: Map<string, Set<string>>, key: string, value: unknown) {
|
||||
if (!Array.isArray(value)) return
|
||||
|
||||
@@ -102,6 +118,8 @@ function toSortedTagRecord(tagsByKey: Map<string, Set<string>>): Record<string,
|
||||
}
|
||||
|
||||
function isHiddenPropertyKey(key: string): boolean {
|
||||
const canonicalKey = canonicalSystemMetadataKey(key)
|
||||
if (canonicalKey === '_icon') return false
|
||||
return SKIP_KEYS.has(key.toLowerCase()) || isSystemMetadataKey(key)
|
||||
}
|
||||
|
||||
@@ -137,7 +155,7 @@ export function usePropertyPanelState(deps: PropertyPanelDeps) {
|
||||
const { availableTypes, customColorKey, typeColorKeys, typeIconKeys } = useMemo(() => deriveTypeInfo(entries, entryIsA), [entries, entryIsA])
|
||||
const vaultStatuses = useMemo(() => collectVaultStatuses(entries), [entries])
|
||||
const vaultTagsByKey = useMemo(() => collectAllVaultTags(entries), [entries])
|
||||
const propertyEntries = useMemo(() => Object.entries(frontmatter).filter(isVisibleProperty), [frontmatter])
|
||||
const propertyEntries = useMemo(() => buildVisiblePropertyEntries(frontmatter), [frontmatter])
|
||||
|
||||
const handleSaveValue = useCallback((key: string, newValue: string) => {
|
||||
setEditingKey(null)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export function humanizePropertyKey(key: string): string {
|
||||
const spaced = key.replace(/[_-]/g, ' ')
|
||||
const normalized = key.replace(/^_+/, '')
|
||||
const spaced = normalized.replace(/[_-]/g, ' ')
|
||||
if (!spaced) return spaced
|
||||
return spaced.charAt(0).toUpperCase() + spaced.slice(1)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { getAppStorageItem } from '../constants/appStorage'
|
||||
import { isValidCssColor, isColorKeyName } from './colorUtils'
|
||||
import { updateVaultConfigField } from './vaultConfigStore'
|
||||
import { CalendarIcon, Type, ToggleLeft, Circle, Link, Tag, Palette } from 'lucide-react'
|
||||
import { canonicalSystemMetadataKey } from './systemMetadata'
|
||||
|
||||
export type PropertyDisplayMode = 'text' | 'date' | 'boolean' | 'status' | 'url' | 'tags' | 'color'
|
||||
|
||||
@@ -20,7 +21,7 @@ const DATE_KEY_PATTERNS = ['date', 'deadline', 'due', 'start', 'end', 'scheduled
|
||||
const TAGS_KEY_PATTERNS = ['tags', 'keywords', 'categories', 'labels']
|
||||
|
||||
function isIconKey(key: string): boolean {
|
||||
return key.toLowerCase() === 'icon'
|
||||
return canonicalSystemMetadataKey(key) === '_icon'
|
||||
}
|
||||
|
||||
function keyMatchesPatterns(key: string, patterns: string[]): boolean {
|
||||
|
||||
Reference in New Issue
Block a user