2323
2424import React , { useEffect , useState , useCallback , useMemo } from 'react' ;
2525import type { ObjectGridSchema , DataSource , ListColumn , ViewData } from '@object-ui/types' ;
26+ import { isSystemManagedField } from '@object-ui/types' ;
2627import type { I18nLabel } from '@objectstack/spec/ui' ;
2728import { SchemaRenderer , useDataScope , useNavigationOverlay , useAction , useObjectTranslation , useSafeFieldLabel , usePredicateScope } from '@object-ui/react' ;
2829import { getCellRenderer , resolveCellRendererType , formatCurrency , formatCompactCurrency , formatDate , formatPercent , humanizeLabel , getBadgeColorClasses , FieldEditWidget , hasFieldEditWidget , DISCRETE_EDIT_TYPES , coerceToSafeValue } from '@object-ui/fields' ;
@@ -1185,11 +1186,12 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
11851186 // marked `hidden: true`/`readonly: true` so default list views show only
11861187 // the business fields users actually care about. Callers can still opt-in
11871188 // to system columns by passing an explicit `fields` / `columns` prop.
1188- const SYSTEM_FIELDS = new Set ( [
1189- 'id' , 'created_at' , 'createdAt' , 'updated_at' , 'updatedAt' ,
1190- 'deleted_at' , 'deletedAt' , 'created_by' , 'createdBy' ,
1191- 'updated_by' , 'updatedBy' , '_version' , '_rev' ,
1192- ] ) ;
1189+ //
1190+ // "System-managed" is decided by `isSystemManagedField`, which branches on
1191+ // the framework's `field.system` flag (single source of truth stamped by
1192+ // `applySystemFields`) — this is what keeps the injected, non-readonly
1193+ // `owner_id` from leading the auto-derived columns, and covers any future
1194+ // injected field without editing a name list here.
11931195 const highlightFields : string [ ] | undefined = ( objectSchema as any ) ?. highlightFields ;
11941196 const allFieldNames = Object . keys ( objectSchema . fields || { } ) ;
11951197 let fieldsToShow : string [ ] ;
@@ -1198,19 +1200,20 @@ export const ObjectGrid: React.FC<ObjectGridProps> = ({
11981200 } else if ( highlightFields ?. length ) {
11991201 fieldsToShow = highlightFields . filter ( ( n ) => objectSchema . fields ?. [ n ] ) ;
12001202 } else {
1201- // Drop hidden + readonly system-managed fields, then push remaining
1202- // system identifier/audit fields to the end as a fallback.
1203+ // Drop hidden + readonly system-managed fields, then push the remaining
1204+ // system/audit/ownership columns (e.g. the injected, editable `owner_id`)
1205+ // to the end as a fallback so business fields lead.
12031206 const visibleFields = allFieldNames . filter ( ( n ) => {
12041207 const f = objectSchema . fields ?. [ n ] ;
12051208 if ( ! f ) return false ;
12061209 if ( f . hidden ) return false ;
1207- // Drop readonly fields when their name matches a system identifier/audit column .
1208- if ( f . readonly && SYSTEM_FIELDS . has ( n ) ) return false ;
1210+ // Drop readonly bookkeeping columns (created_at/by, updated_at/by, …) .
1211+ if ( f . readonly && isSystemManagedField ( n , f ) ) return false ;
12091212 return true ;
12101213 } ) ;
12111214 fieldsToShow = [
1212- ...visibleFields . filter ( ( n ) => ! SYSTEM_FIELDS . has ( n ) ) ,
1213- ...visibleFields . filter ( ( n ) => SYSTEM_FIELDS . has ( n ) ) ,
1215+ ...visibleFields . filter ( ( n ) => ! isSystemManagedField ( n , objectSchema . fields ?. [ n ] ) ) ,
1216+ ...visibleFields . filter ( ( n ) => isSystemManagedField ( n , objectSchema . fields ?. [ n ] ) ) ,
12141217 ] ;
12151218 }
12161219
0 commit comments