@@ -34,6 +34,7 @@ import {
3434 GenericRenderer ,
3535 HeaderFilter ,
3636 IdLinkRenderer ,
37+ NameLinkRenderer ,
3738 TextOrIdLinkRenderer ,
3839} from './DataTableRenderers' ;
3940import { SubqueryRenderer } from './DataTableSubqueryRenderer' ;
@@ -280,22 +281,38 @@ function getQueryResultColumn({
280281 if ( subqueryRelationshipName ) {
281282 fieldLowercase = `${ subqueryRelationshipName . toLowerCase ( ) } .${ fieldLowercase } ` ;
282283 }
283- if ( queryColumnsByPath [ fieldLowercase ] ) {
284- const col = queryColumnsByPath [ fieldLowercase ] ;
285- column . name = col . columnFullPath ;
286- column . key = col . columnFullPath ;
287- updateColumnFromType ( column , getColumnTypeFromQueryResultsColumn ( col ) ) ;
284+ const queryResultColumn = queryColumnsByPath [ fieldLowercase ] ;
285+ let resolvedType : ColumnType = 'text' ;
286+ if ( queryResultColumn ) {
287+ column . name = queryResultColumn . columnFullPath ;
288+ column . key = queryResultColumn . columnFullPath ;
289+ resolvedType = getColumnTypeFromQueryResultsColumn ( queryResultColumn ) ;
290+ updateColumnFromType ( column , resolvedType ) ;
288291 // exclude related records from edit mode
289- if ( allowEdit && ! col . columnFullPath ?. includes ( '.' ) ) {
290- updateColumnWithEditMode ( column , col , fieldMetadata ) ;
291- }
292- } else {
293- if ( field . endsWith ( 'Id' ) ) {
294- updateColumnFromType ( column , 'salesforceId' ) ;
295- } else if ( isSubquery ) {
296- updateColumnFromType ( column , 'subquery' ) ;
292+ if ( allowEdit && ! queryResultColumn . columnFullPath ?. includes ( '.' ) ) {
293+ updateColumnWithEditMode ( column , queryResultColumn , fieldMetadata ) ;
297294 }
295+ } else if ( field . endsWith ( 'Id' ) ) {
296+ resolvedType = 'salesforceId' ;
297+ updateColumnFromType ( column , 'salesforceId' ) ;
298+ } else if ( isSubquery ) {
299+ resolvedType = 'subquery' ;
300+ updateColumnFromType ( column , 'subquery' ) ;
301+ }
302+
303+ // Upgrade plain-text Name / relationship Name columns (e.g. Name, Account.Name, Account.Owner.Name)
304+ // to a clickable record-lookup popover, mirroring the IdLinkRenderer behavior.
305+ // Skipped for subquery child columns, aggregate (GROUP BY) columns, and anything that already
306+ // resolved to a non-text type (salesforceId, boolean, date, etc).
307+ // Use the canonical resolved column path when available so Name-field detection does not depend
308+ // on the original query casing from getFlattenedFields(results.parsedQuery).
309+ const canonicalColumnPath = queryResultColumn ?. columnFullPath ?? column . key ;
310+ const isNameField =
311+ ! ! fieldMetadata ?. [ field . toLowerCase ( ) ] ?. nameField || canonicalColumnPath === 'Name' || canonicalColumnPath . endsWith ( '.Name' ) ;
312+ if ( ! subqueryRelationshipName && ! queryResultColumn ?. aggregate && resolvedType === 'text' && isNameField ) {
313+ updateColumnFromType ( column , 'salesforceName' ) ;
298314 }
315+
299316 return column ;
300317}
301318
@@ -416,6 +433,9 @@ export function updateColumnFromType(column: Mutable<ColumnWithFilter<any>>, fie
416433 column . renderCell = IdLinkRenderer ;
417434 column . width = 175 ;
418435 break ;
436+ case 'salesforceName' :
437+ column . renderCell = NameLinkRenderer ;
438+ break ;
419439 case 'textOrSalesforceId' :
420440 column . renderCell = TextOrIdLinkRenderer ;
421441 column . width = 175 ;
0 commit comments