[Fix] : fix: Allow label identifier system fields in view creation and fix resulting duplicate header columns (#19009)
fixes #18994 After : <img width="767" height="230" alt="Screenshot 2026-03-26 at 7 11 04 PM" src="https://github.com/user-attachments/assets/73de0154-7da1-48fa-92fc-d51a3ef5b06e" /> Before : <img width="905" height="314" alt="Screenshot 2026-03-26 at 6 56 38 PM" src="https://github.com/user-attachments/assets/89b1249b-8889-4034-a6c8-d41330154c1a" /> --------- Co-authored-by: Arun kumar <arunkumar@Aruns-MacBook-Air.local> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+8
-20
@@ -1,4 +1,3 @@
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { RecordTableHeaderAddColumnButton } from '@/object-record/record-table/record-table-header/components/RecordTableHeaderAddColumnButton';
|
||||
@@ -15,7 +14,6 @@ import { isRecordTableColumnHeadersReadOnlyComponentState } from '@/object-recor
|
||||
import { isRecordTableDragColumnHiddenComponentState } from '@/object-record/record-table/states/isRecordTableDragColumnHiddenComponentState';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { styled } from '@linaria/react';
|
||||
import { filterOutByProperty } from 'twenty-shared/utils';
|
||||
|
||||
const StyledHeaderContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -27,7 +25,6 @@ const StyledHeaderContainer = styled.div`
|
||||
|
||||
export const RecordTableHeader = () => {
|
||||
const { visibleRecordFields } = useRecordTableContextOrThrow();
|
||||
const { labelIdentifierFieldMetadataItem } = useRecordIndexContextOrThrow();
|
||||
|
||||
const isRecordTableColumnHeadersReadOnly = useAtomComponentStateValue(
|
||||
isRecordTableColumnHeadersReadOnlyComponentState,
|
||||
@@ -41,14 +38,7 @@ export const RecordTableHeader = () => {
|
||||
isRecordTableCheckboxColumnHiddenComponentState,
|
||||
);
|
||||
|
||||
const recordFieldsWithoutLabelIdentifierAndFirstOne = visibleRecordFields
|
||||
.filter(
|
||||
filterOutByProperty(
|
||||
'fieldMetadataItemId',
|
||||
labelIdentifierFieldMetadataItem?.id,
|
||||
),
|
||||
)
|
||||
.slice(1);
|
||||
const recordFieldsWithoutFirstTwo = visibleRecordFields.slice(2);
|
||||
|
||||
useResizeTableHeader();
|
||||
|
||||
@@ -60,15 +50,13 @@ export const RecordTableHeader = () => {
|
||||
)}
|
||||
<RecordTableHeaderFirstCell />
|
||||
<RecordTableHeaderFirstScrollableCell />
|
||||
{recordFieldsWithoutLabelIdentifierAndFirstOne.map(
|
||||
(recordField, index) => (
|
||||
<RecordTableHeaderCell
|
||||
key={recordField.fieldMetadataItemId}
|
||||
recordField={recordField}
|
||||
recordFieldIndex={index + 2}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
{recordFieldsWithoutFirstTwo.map((recordField, index) => (
|
||||
<RecordTableHeaderCell
|
||||
key={recordField.fieldMetadataItemId}
|
||||
recordField={recordField}
|
||||
recordFieldIndex={index + 2}
|
||||
/>
|
||||
))}
|
||||
{isRecordTableColumnHeadersReadOnly ? (
|
||||
<RecordTableHeaderEmptyLastColumn />
|
||||
) : (
|
||||
|
||||
+2
-10
@@ -1,5 +1,4 @@
|
||||
import { type RecordField } from '@/object-record/record-field/types/RecordField';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { TABLE_Z_INDEX } from '@/object-record/record-table/constants/TableZIndex';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { RecordTableColumnHead } from '@/object-record/record-table/record-table-header/components/RecordTableColumnHead';
|
||||
@@ -21,7 +20,7 @@ import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hoo
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { cx } from '@linaria/core';
|
||||
import { filterOutByProperty, isDefined } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const RecordTableHeaderFirstScrollableCell = () => {
|
||||
const { objectMetadataItem, visibleRecordFields } =
|
||||
@@ -45,14 +44,7 @@ export const RecordTableHeaderFirstScrollableCell = () => {
|
||||
0,
|
||||
);
|
||||
|
||||
const { labelIdentifierFieldMetadataItem } = useRecordIndexContextOrThrow();
|
||||
|
||||
const recordField = visibleRecordFields.filter(
|
||||
filterOutByProperty(
|
||||
'fieldMetadataItemId',
|
||||
labelIdentifierFieldMetadataItem?.id,
|
||||
),
|
||||
)[0] as RecordField | undefined;
|
||||
const recordField = visibleRecordFields[1] as RecordField | undefined;
|
||||
|
||||
const isRecordTableRowFocusActive = useAtomComponentStateValue(
|
||||
isRecordTableRowFocusActiveComponentState,
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import { filterFieldsForRecordTableViewCreation } from '@/page-layout/widgets/record-table/utils/filterFieldsForRecordTableViewCreation';
|
||||
import { getMockFieldMetadataItemOrThrow } from '~/testing/utils/getMockFieldMetadataItemOrThrow';
|
||||
import { getMockObjectMetadataItemOrThrow } from '~/testing/utils/getMockObjectMetadataItemOrThrow';
|
||||
|
||||
describe('filterFieldsForRecordTableViewCreation', () => {
|
||||
const objectMetadataItem = getMockObjectMetadataItemOrThrow('company');
|
||||
const labelIdentifierFieldMetadataId =
|
||||
objectMetadataItem.labelIdentifierFieldMetadataId;
|
||||
|
||||
// domainName is an active, non-system field that is not the label identifier
|
||||
const nonSystemField = getMockFieldMetadataItemOrThrow({
|
||||
objectMetadataItem,
|
||||
fieldName: 'domainName',
|
||||
});
|
||||
// id is a hidden system field
|
||||
const systemField = getMockFieldMetadataItemOrThrow({
|
||||
objectMetadataItem,
|
||||
fieldName: 'id',
|
||||
});
|
||||
// position is a hidden system field
|
||||
const hiddenSystemField = getMockFieldMetadataItemOrThrow({
|
||||
objectMetadataItem,
|
||||
fieldName: 'position',
|
||||
});
|
||||
|
||||
it('should include active non-system fields', () => {
|
||||
expect(
|
||||
filterFieldsForRecordTableViewCreation(
|
||||
nonSystemField,
|
||||
labelIdentifierFieldMetadataId,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should exclude inactive fields', () => {
|
||||
expect(
|
||||
filterFieldsForRecordTableViewCreation(
|
||||
{ ...nonSystemField, isActive: false },
|
||||
labelIdentifierFieldMetadataId,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should exclude system fields that are not the label identifier', () => {
|
||||
expect(
|
||||
filterFieldsForRecordTableViewCreation(
|
||||
systemField,
|
||||
labelIdentifierFieldMetadataId,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should include system fields when they are the label identifier', () => {
|
||||
expect(
|
||||
filterFieldsForRecordTableViewCreation(systemField, systemField.id),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should include hidden system fields when they are the label identifier', () => {
|
||||
expect(
|
||||
filterFieldsForRecordTableViewCreation(
|
||||
hiddenSystemField,
|
||||
hiddenSystemField.id,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
+5
-2
@@ -33,8 +33,11 @@ export const buildRecordTableWidgetViewSnapshot = (
|
||||
isActive: true,
|
||||
};
|
||||
|
||||
const eligibleFields = objectMetadataItem.fields.filter(
|
||||
filterFieldsForRecordTableViewCreation,
|
||||
const eligibleFields = objectMetadataItem.fields.filter((field) =>
|
||||
filterFieldsForRecordTableViewCreation(
|
||||
field,
|
||||
objectMetadataItem.labelIdentifierFieldMetadataId,
|
||||
),
|
||||
);
|
||||
|
||||
const sortedFields = eligibleFields.toSorted(
|
||||
|
||||
+6
-1
@@ -3,6 +3,11 @@ import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField
|
||||
|
||||
export const filterFieldsForRecordTableViewCreation = (
|
||||
field: FieldMetadataItem,
|
||||
labelIdentifierFieldMetadataId: string,
|
||||
) => {
|
||||
return field.isActive && !field.isSystem && !isHiddenSystemField(field);
|
||||
const isLabelIdentifier = field.id === labelIdentifierFieldMetadataId;
|
||||
return (
|
||||
field.isActive &&
|
||||
(isLabelIdentifier || (!field.isSystem && !isHiddenSystemField(field)))
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user