Fixed aggregate footer not displayed (#14276)
This PR fixes a bug that made the aggregate footer not displayed. It was because of a wrong filter on `visibleRecordFields` array. Follow-up of https://github.com/twentyhq/twenty/pull/14048 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+1
@@ -78,6 +78,7 @@ export const RecordBoardColumnHeaderAggregateDropdownFieldsContent = () => {
|
||||
updateViewAggregate({
|
||||
kanbanAggregateOperationFieldMetadataId: fieldId,
|
||||
kanbanAggregateOperation: aggregateOperation,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
});
|
||||
closeDropdown();
|
||||
}}
|
||||
|
||||
+2
-1
@@ -28,7 +28,7 @@ export const RecordBoardColumnHeaderAggregateDropdownOptionsContent = ({
|
||||
availableAggregations: AvailableFieldsForAggregateOperation;
|
||||
title: string;
|
||||
}) => {
|
||||
const { onContentChange, closeDropdown, resetContent } =
|
||||
const { onContentChange, closeDropdown, resetContent, objectMetadataItem } =
|
||||
useDropdownContextStateManagement<RecordBoardColumnHeaderAggregateDropdownContextValue>(
|
||||
{
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
@@ -89,6 +89,7 @@ export const RecordBoardColumnHeaderAggregateDropdownOptionsContent = ({
|
||||
availableAggregationFieldsIdsForOperation[0],
|
||||
kanbanAggregateOperation:
|
||||
availableAggregationOperation as AggregateOperations,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
});
|
||||
closeDropdown();
|
||||
}
|
||||
|
||||
+4
-2
@@ -4,7 +4,7 @@ import { useContext } from 'react';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext';
|
||||
import { RecordTableColumnFooterWithDropdown } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterWithDropdown';
|
||||
import { findById, isDefined } from 'twenty-shared/utils';
|
||||
import { findByProperty, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const COLUMN_MIN_WIDTH = 104;
|
||||
|
||||
@@ -64,7 +64,9 @@ export const RecordTableAggregateFooterCell = ({
|
||||
RecordTableColumnAggregateFooterCellContext,
|
||||
);
|
||||
|
||||
const recordField = visibleRecordFields.find(findById(fieldMetadataId));
|
||||
const recordField = visibleRecordFields.find(
|
||||
findByProperty('fieldMetadataItemId', fieldMetadataId),
|
||||
);
|
||||
|
||||
if (!isDefined(recordField)) {
|
||||
return null;
|
||||
|
||||
+4
-4
@@ -30,8 +30,8 @@ export const RecordTableColumnAggregateFooterAggregateOperationMenuItems = ({
|
||||
{aggregateOperations.map((operation) => (
|
||||
<MenuItem
|
||||
key={operation}
|
||||
onClick={() => {
|
||||
updateViewFieldAggregateOperation(operation);
|
||||
onClick={async () => {
|
||||
await updateViewFieldAggregateOperation(operation);
|
||||
closeDropdown(dropdownId);
|
||||
}}
|
||||
text={getAggregateOperationLabel(operation)}
|
||||
@@ -46,8 +46,8 @@ export const RecordTableColumnAggregateFooterAggregateOperationMenuItems = ({
|
||||
{children}
|
||||
<MenuItem
|
||||
key={'none'}
|
||||
onClick={() => {
|
||||
updateViewFieldAggregateOperation(null);
|
||||
onClick={async () => {
|
||||
await updateViewFieldAggregateOperation(null);
|
||||
resetContent();
|
||||
closeDropdown(dropdownId);
|
||||
}}
|
||||
|
||||
+2
-2
@@ -92,8 +92,8 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
|
||||
) : null}
|
||||
<MenuItem
|
||||
key={'none'}
|
||||
onClick={() => {
|
||||
updateViewFieldAggregateOperation(null);
|
||||
onClick={async () => {
|
||||
await updateViewFieldAggregateOperation(null);
|
||||
resetContent();
|
||||
closeDropdown(dropdownId);
|
||||
}}
|
||||
|
||||
+11
-2
@@ -1,9 +1,11 @@
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { RecordTableColumnAggregateFooterDropdownContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterDropdownContext';
|
||||
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
|
||||
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
|
||||
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
|
||||
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
@@ -16,14 +18,19 @@ export const useViewFieldAggregateOperation = () => {
|
||||
const currentViewField = currentView?.viewFields?.find(
|
||||
(viewField) => viewField.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
const { refreshCoreViewsByObjectMetadataId } =
|
||||
useRefreshCoreViewsByObjectMetadataId();
|
||||
|
||||
const { objectMetadataItem } = useRecordIndexContextOrThrow();
|
||||
const { updateViewFieldRecords } = usePersistViewFieldRecords();
|
||||
const updateViewFieldAggregateOperation = (
|
||||
const updateViewFieldAggregateOperation = async (
|
||||
aggregateOperation: ExtendedAggregateOperations | null,
|
||||
) => {
|
||||
if (!currentViewField) {
|
||||
throw new Error('ViewField not found');
|
||||
}
|
||||
updateViewFieldRecords([
|
||||
await updateViewFieldRecords([
|
||||
{
|
||||
...currentViewField,
|
||||
aggregateOperation:
|
||||
@@ -32,6 +39,8 @@ export const useViewFieldAggregateOperation = () => {
|
||||
),
|
||||
},
|
||||
]);
|
||||
|
||||
refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
|
||||
};
|
||||
|
||||
const currentViewFieldAggregateOperation = useRecoilValue(
|
||||
|
||||
+6
@@ -5,9 +5,11 @@ import { useUpdateView } from '@/views/hooks/useUpdateView';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { useUpdateViewAggregate } from '../useUpdateViewAggregate';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
|
||||
jest.mock('@/ui/utilities/state/component-state/hooks/useRecoilComponentValue');
|
||||
jest.mock('@/views/hooks/useUpdateView');
|
||||
jest.mock('@/views/hooks/useRefreshCoreViewsByObjectMetadataId');
|
||||
jest.mock('recoil');
|
||||
|
||||
describe('useUpdateViewAggregate', () => {
|
||||
@@ -24,6 +26,9 @@ describe('useUpdateViewAggregate', () => {
|
||||
(useSetRecoilState as jest.Mock).mockReturnValue(
|
||||
mockSetRecordIndexKanbanAggregateOperationState,
|
||||
);
|
||||
(useRefreshCoreViewsByObjectMetadataId as jest.Mock).mockReturnValue({
|
||||
refreshCoreViewsByObjectMetadataId: jest.fn(),
|
||||
});
|
||||
});
|
||||
|
||||
describe('Aggregate operations on dates', () => {
|
||||
@@ -33,6 +38,7 @@ describe('useUpdateViewAggregate', () => {
|
||||
result.current.updateViewAggregate({
|
||||
kanbanAggregateOperationFieldMetadataId: 'test-field-id',
|
||||
kanbanAggregateOperation: DateAggregateOperations.EARLIEST,
|
||||
objectMetadataId: 'test-object-metadata-id',
|
||||
});
|
||||
|
||||
// updateView is called with 'EARLIEST' converted to 'MIN'
|
||||
|
||||
@@ -3,6 +3,7 @@ import { recordIndexKanbanAggregateOperationState } from '@/object-record/record
|
||||
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
|
||||
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { useUpdateView } from '@/views/hooks/useUpdateView';
|
||||
import { useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
@@ -17,13 +18,18 @@ export const useUpdateViewAggregate = () => {
|
||||
recordIndexKanbanAggregateOperationState,
|
||||
);
|
||||
|
||||
const { refreshCoreViewsByObjectMetadataId } =
|
||||
useRefreshCoreViewsByObjectMetadataId();
|
||||
|
||||
const updateViewAggregate = useCallback(
|
||||
({
|
||||
kanbanAggregateOperationFieldMetadataId,
|
||||
kanbanAggregateOperation,
|
||||
objectMetadataId,
|
||||
}: {
|
||||
kanbanAggregateOperationFieldMetadataId: string | null;
|
||||
kanbanAggregateOperation: ExtendedAggregateOperations | null;
|
||||
objectMetadataId: string;
|
||||
}) => {
|
||||
const convertedKanbanAggregateOperation =
|
||||
convertExtendedAggregateOperationToAggregateOperation(
|
||||
@@ -39,8 +45,15 @@ export const useUpdateViewAggregate = () => {
|
||||
operation: kanbanAggregateOperation,
|
||||
fieldMetadataId: kanbanAggregateOperationFieldMetadataId,
|
||||
});
|
||||
|
||||
refreshCoreViewsByObjectMetadataId(objectMetadataId);
|
||||
},
|
||||
[currentViewId, updateView, setRecordIndexKanbanAggregateOperationState],
|
||||
[
|
||||
currentViewId,
|
||||
updateView,
|
||||
setRecordIndexKanbanAggregateOperationState,
|
||||
refreshCoreViewsByObjectMetadataId,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { type ViewField } from '@/views/types/ViewField';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useUpdateViewField = () => {
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.ViewField,
|
||||
});
|
||||
|
||||
const updateViewField = useRecoilCallback(
|
||||
() => async (viewField: Partial<ViewField>) => {
|
||||
if (isDefined(viewField.id)) {
|
||||
await updateOneRecord({
|
||||
idToUpdate: viewField.id,
|
||||
updateOneRecordInput: viewField,
|
||||
});
|
||||
}
|
||||
},
|
||||
[updateOneRecord],
|
||||
);
|
||||
|
||||
return {
|
||||
updateViewField,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user