Aggregate queries follow up (#9581)

In this PR

- fixing Collapse on view groups views: aggregate bar should be included
in the collapse (@magrinj )
- respect the html table pattern: the aggregate bar is now a <tr>
element included in a <table> (before that, it was a <tr> not included
in anything)
- add a top-border on the aggregate bar
- introduce short labels for the on-cell value display (display "Empty"
instead of "Count empty" to lighten the interface)
- remove the feature flag !
This commit is contained in:
Marie
2025-01-13 17:20:35 +01:00
committed by GitHub
parent 739611afa8
commit 17850b76ab
23 changed files with 111 additions and 182 deletions

View File

@ -389,7 +389,6 @@ export type FeatureFlagFilter = {
export enum FeatureFlagKey {
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
IsAggregateQueryEnabled = 'IsAggregateQueryEnabled',
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',

View File

@ -1,5 +1,5 @@
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
import { gql } from '@apollo/client';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
@ -321,7 +321,6 @@ export type FeatureFlagFilter = {
export enum FeatureFlagKey {
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
IsAggregateQueryEnabled = 'IsAggregateQueryEnabled',
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',

View File

@ -1,6 +1,5 @@
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
import { getAggregateQueryName } from '@/object-record/utils/getAggregateQueryName';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useApolloClient } from '@apollo/client';
import { renderHook } from '@testing-library/react';
@ -8,16 +7,6 @@ jest.mock('@apollo/client', () => ({
useApolloClient: jest.fn(),
}));
jest.mock('@/workspace/hooks/useIsFeatureEnabled', () => ({
useIsFeatureEnabled: jest.fn(),
}));
jest.mock('~/generated/graphql', () => ({
FeatureFlagKey: {
IsAggregateQueryEnabled: 'IsAggregateQueryEnabled',
},
}));
describe('useRefetchAggregateQueries', () => {
const mockRefetchQueries = jest.fn();
const mockApolloClient = {
@ -29,9 +18,8 @@ describe('useRefetchAggregateQueries', () => {
(useApolloClient as jest.Mock).mockReturnValue(mockApolloClient);
});
it('should refetch queries when feature flag is enabled', async () => {
it('should refetch queries', async () => {
// Arrange
(useIsFeatureEnabled as jest.Mock).mockReturnValue(true);
const objectMetadataNamePlural = 'opportunities';
const expectedQueryName = getAggregateQueryName(objectMetadataNamePlural);
@ -48,24 +36,8 @@ describe('useRefetchAggregateQueries', () => {
});
});
it('should not refetch queries when feature flag is disabled', async () => {
// Arrange
(useIsFeatureEnabled as jest.Mock).mockReturnValue(false);
const objectMetadataNamePlural = 'opportunities';
// Act
const { result } = renderHook(() =>
useRefetchAggregateQueries({ objectMetadataNamePlural }),
);
await result.current.refetchAggregateQueries();
// Assert
expect(mockRefetchQueries).not.toHaveBeenCalled();
});
it('should handle errors during refetch', async () => {
// Arrange
(useIsFeatureEnabled as jest.Mock).mockReturnValue(true);
const error = new Error('Refetch failed');
mockRefetchQueries.mockRejectedValue(error);
const objectMetadataNamePlural = 'opportunities';

View File

@ -1,7 +1,5 @@
import { getAggregateQueryName } from '@/object-record/utils/getAggregateQueryName';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useApolloClient } from '@apollo/client';
import { FeatureFlagKey } from '~/generated/graphql';
export const useRefetchAggregateQueries = ({
objectMetadataNamePlural,
@ -9,17 +7,13 @@ export const useRefetchAggregateQueries = ({
objectMetadataNamePlural: string;
}) => {
const apolloClient = useApolloClient();
const isAggregateQueryEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
);
const refetchAggregateQueries = async () => {
if (isAggregateQueryEnabled) {
const queryName = getAggregateQueryName(objectMetadataNamePlural);
await apolloClient.refetchQueries({
include: [queryName],
});
}
const refetchAggregateQueries = async () => {
const queryName = getAggregateQueryName(objectMetadataNamePlural);
await apolloClient.refetchQueries({
include: [queryName],
});
};
return {

View File

@ -44,7 +44,6 @@ export const RecordBoardColumn = ({
<RecordBoardColumnContext.Provider
value={{
columnDefinition: recordGroupDefinition,
recordCount: recordIdsByGroup.length,
columnId: recordBoardColumnId,
recordIds: recordIdsByGroup,
}}

View File

@ -12,9 +12,7 @@ import { useIsOpportunitiesCompanyFieldDisabled } from '@/object-record/record-b
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { IconDotsVertical, IconPlus, LightIconButton, Tag } from 'twenty-ui';
import { FeatureFlagKey } from '~/generated/graphql';
const StyledHeader = styled.div`
align-items: center;
@ -42,16 +40,6 @@ const StyledLeftContainer = styled.div`
gap: ${({ theme }) => theme.spacing(1)};
`;
const StyledRecordCountChildren = styled.div`
align-items: center;
color: ${({ theme }) => theme.font.color.tertiary};
display: flex;
height: 24px;
justify-content: center;
line-height: ${({ theme }) => theme.text.lineHeight.lg};
width: 22px;
`;
const StyledRightContainer = styled.div`
align-items: center;
display: flex;
@ -103,10 +91,6 @@ export const RecordBoardColumnHeader = () => {
columnDefinition.id ?? '',
);
const isAggregateQueryEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
);
const { isOpportunitiesCompanyFieldDisabled } =
useIsOpportunitiesCompanyFieldDisabled();
@ -141,18 +125,12 @@ export const RecordBoardColumnHeader = () => {
: 'medium'
}
/>
{isAggregateQueryEnabled ? (
<RecordBoardColumnHeaderAggregateDropdown
aggregateValue={aggregateValue}
dropdownId={`record-board-column-aggregate-dropdown-${columnDefinition.id}`}
objectMetadataItem={objectMetadataItem}
aggregateLabel={aggregateLabel}
/>
) : (
<StyledRecordCountChildren>
{aggregateValue}
</StyledRecordCountChildren>
)}
<RecordBoardColumnHeaderAggregateDropdown
aggregateValue={aggregateValue}
dropdownId={`record-board-column-aggregate-dropdown-${columnDefinition.id}`}
objectMetadataItem={objectMetadataItem}
aggregateLabel={aggregateLabel}
/>
</StyledLeftContainer>
<StyledRightContainer>
{isHeaderHovered && (

View File

@ -32,7 +32,6 @@ export const RecordBoardColumnHeaderWrapper = ({
value={{
columnId,
columnDefinition: recordGroupDefinition,
recordCount: recordIdsByGroup.length,
recordIds: recordIdsByGroup,
}}
>

View File

@ -4,7 +4,6 @@ import { RecordGroupDefinition } from '@/object-record/record-group/types/Record
type RecordBoardColumnContextProps = {
columnDefinition: RecordGroupDefinition;
recordCount: number;
columnId: string;
recordIds: string[];
};

View File

@ -10,20 +10,12 @@ import { recordIndexKanbanAggregateOperationState } from '@/object-record/record
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
import { UserContext } from '@/users/contexts/UserContext';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
export const useAggregateRecordsForRecordBoardColumn = () => {
const isAggregateQueryEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
);
const { columnDefinition, recordCount } = useContext(
RecordBoardColumnContext,
);
const { columnDefinition } = useContext(RecordBoardColumnContext);
const { objectMetadataItem } = useContext(RecordBoardContext);
@ -78,7 +70,6 @@ export const useAggregateRecordsForRecordBoardColumn = () => {
objectNameSingular: objectMetadataItem.nameSingular,
recordGqlFieldsAggregate,
filter,
skip: !isAggregateQueryEnabled,
});
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
@ -95,7 +86,7 @@ export const useAggregateRecordsForRecordBoardColumn = () => {
});
return {
aggregateValue: isAggregateQueryEnabled ? value : recordCount,
aggregateValue: value,
aggregateLabel: isDefined(value) ? labelWithFieldName : undefined,
};
};

View File

@ -171,7 +171,7 @@ describe('computeAggregateValueAndLabel', () => {
});
expect(result).toEqual({
label: 'Earliest date',
label: 'Earliest',
labelWithFieldName: 'Earliest date of Created At',
value: '1 Jan, 2023 12:00',
});
@ -207,7 +207,7 @@ describe('computeAggregateValueAndLabel', () => {
expect(result).toEqual({
value: '31 Dec, 2023 23:59',
label: 'Latest date',
label: 'Latest',
labelWithFieldName: 'Latest date of Updated At',
});
});

View File

@ -3,6 +3,7 @@ import { TimeFormat } from '@/localization/constants/TimeFormat';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { AggregateRecordsData } from '@/object-record/hooks/useAggregateRecords';
import { getAggregateOperationLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationLabel';
import { getAggregateOperationShortLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationShortLabel';
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { COUNT_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-table/record-table-footer/constants/countAggregateOperationOptions';
import { PERCENT_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-table/record-table-footer/constants/percentAggregateOperationOptions';
@ -118,7 +119,7 @@ export const computeAggregateValueAndLabel = ({
}
}
}
const label = getAggregateOperationLabel(aggregateOperation);
const label = getAggregateOperationShortLabel(aggregateOperation);
const labelWithFieldName =
aggregateOperation === AGGREGATE_OPERATIONS.count
? `${getAggregateOperationLabel(AGGREGATE_OPERATIONS.count)}`

View File

@ -0,0 +1,34 @@
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { DATE_AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/DateAggregateOperations';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
export const getAggregateOperationShortLabel = (
operation: ExtendedAggregateOperations,
) => {
switch (operation) {
case AGGREGATE_OPERATIONS.min:
return 'Min';
case AGGREGATE_OPERATIONS.max:
return 'Max';
case AGGREGATE_OPERATIONS.avg:
return 'Average';
case AGGREGATE_OPERATIONS.sum:
return 'Sum';
case AGGREGATE_OPERATIONS.count:
return 'All';
case AGGREGATE_OPERATIONS.countEmpty:
case AGGREGATE_OPERATIONS.percentageEmpty:
return 'Empty';
case AGGREGATE_OPERATIONS.countNotEmpty:
case AGGREGATE_OPERATIONS.percentageNotEmpty:
return 'Not empty';
case AGGREGATE_OPERATIONS.countUniqueValues:
return 'Unique';
case DATE_AGGREGATE_OPERATIONS.earliest:
return 'Earliest';
case DATE_AGGREGATE_OPERATIONS.latest:
return 'Latest';
default:
throw new Error(`Unknown aggregate operation: ${operation}`);
}
};

View File

@ -13,16 +13,13 @@ import { RecordTableNoRecordGroupBody } from '@/object-record/record-table/recor
import { RecordTableNoRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect';
import { RecordTableRecordGroupBodyEffects } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffects';
import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody';
import { RecordTableAggregateFooter } from '@/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter';
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { hasPendingRecordComponentSelector } from '@/object-record/record-table/states/selectors/hasPendingRecordComponentSelector';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRef } from 'react';
import { FeatureFlagKey } from '~/generated/graphql';
const StyledTable = styled.table`
border-radius: ${({ theme }) => theme.border.radius.sm};
@ -36,10 +33,6 @@ export const RecordTable = () => {
const tableBodyRef = useRef<HTMLTableElement>(null);
const isAggregateQueryEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
);
const { toggleClickOutsideListener } = useClickOutsideListener(
RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID,
);
@ -97,12 +90,6 @@ export const RecordTable = () => {
<RecordTableRecordGroupsBody />
)}
<RecordTableStickyEffect />
{isAggregateQueryEnabled &&
!hasRecordGroups &&
!isRecordTableInitialLoading &&
allRecordIds.length > 0 && (
<RecordTableAggregateFooter endOfTableSticky />
)}
</StyledTable>
<DragSelect
dragSelectable={tableBodyRef}

View File

@ -1,6 +1,8 @@
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader';
import { RecordTableAggregateFooter } from '@/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter';
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
export const RecordTableNoRecordGroupRows = () => {
@ -8,6 +10,10 @@ export const RecordTableNoRecordGroupRows = () => {
recordIndexAllRecordIdsComponentSelector,
);
const isRecordTableInitialLoading = useRecoilComponentValueV2(
isRecordTableInitialLoadingComponentState,
);
return (
<>
{allRecordIds.map((recordId, rowIndex) => {
@ -21,6 +27,9 @@ export const RecordTableNoRecordGroupRows = () => {
);
})}
<RecordTableBodyFetchMoreLoader />
{!isRecordTableInitialLoading && allRecordIds.length > 0 && (
<RecordTableAggregateFooter endOfTableSticky />
)}
</>
);
};

View File

@ -1,6 +1,7 @@
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
import { RecordTableAggregateFooter } from '@/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter';
import { RecordTablePendingRecordGroupRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRecordGroupRow';
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
import { RecordTableRecordGroupSectionAddNew } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionAddNew';
@ -59,6 +60,10 @@ export const RecordTableRecordGroupRows = () => {
<RecordTablePendingRecordGroupRow />
<RecordTableRecordGroupSectionAddNew />
<RecordTableRecordGroupSectionLoadMore />
<RecordTableAggregateFooter
key={currentRecordGroupId}
currentRecordGroupId={currentRecordGroupId}
/>
</>
);
};

View File

@ -6,14 +6,11 @@ import { RecordTableRecordGroupRows } from '@/object-record/record-table/compone
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
import { RecordTableBodyRecordGroupDragDropContextProvider } from '@/object-record/record-table/record-table-body/components/RecordTableBodyRecordGroupDragDropContextProvider';
import { RecordTableAggregateFooter } from '@/object-record/record-table/record-table-footer/components/RecordTableAggregateFooter';
import { RecordTableRecordGroupSection } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewType } from '@/views/types/ViewType';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated/graphql';
export const RecordTableRecordGroupsBody = () => {
const allRecordIds = useRecoilComponentValueV2(
@ -29,10 +26,6 @@ export const RecordTableRecordGroupsBody = () => {
ViewType.Table,
);
const isAggregateQueryEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
);
if (isRecordTableInitialLoading && allRecordIds.length === 0) {
return <RecordTableBodyLoading />;
}
@ -50,12 +43,6 @@ export const RecordTableRecordGroupsBody = () => {
<RecordTableRecordGroupSection />
<RecordTableRecordGroupRows />
</RecordTableBodyDroppable>
{isAggregateQueryEnabled && (
<RecordTableAggregateFooter
key={recordGroupId}
currentRecordGroupId={recordGroupId}
/>
)}
</RecordGroupContext.Provider>
</RecordTableRecordGroupBodyContextProvider>
))}

View File

@ -8,38 +8,41 @@ import { scrollWrapperInstanceComponentState } from '@/ui/utilities/scroll/state
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { MOBILE_VIEWPORT } from 'twenty-ui';
const StyledTh = styled.th`
const StyledTd = styled.td`
background-color: ${({ theme }) => theme.background.primary};
`;
const StyledTableFoot = styled.thead<{
const StyledTableRow = styled.tr<{
endOfTableSticky?: boolean;
hasHorizontalOverflow?: boolean;
}>`
td {
border-top: 1px solid ${({ theme }) => theme.border.color.light};
}
cursor: pointer;
th:nth-of-type(1) {
td:nth-of-type(1) {
width: ${FIRST_TH_WIDTH};
left: 0;
border-right-color: ${({ theme }) => theme.background.primary};
border-top: none;
}
th:nth-of-type(2) {
td:nth-of-type(2) {
border-right-color: ${({ theme }) => theme.background.primary};
border-top: 1px solid ${({ theme }) => theme.border.color.light};
}
&.first-columns-sticky {
th:nth-of-type(1) {
td:nth-of-type(1) {
position: sticky;
left: 0;
z-index: 5;
transition: 0.3s ease;
}
th:nth-of-type(2) {
td:nth-of-type(2) {
position: sticky;
left: 11px;
z-index: 5;
transition: 0.3s ease;
}
th:nth-of-type(3) {
td:nth-of-type(3) {
position: sticky;
left: 43px;
z-index: 5;
@ -60,13 +63,12 @@ const StyledTableFoot = styled.thead<{
}
}
}
tr {
position: sticky;
z-index: 5;
background: ${({ theme }) => theme.background.primary};
${({ endOfTableSticky, hasHorizontalOverflow }) =>
endOfTableSticky &&
`
position: sticky;
z-index: 5;
background: ${({ theme }) => theme.background.primary};
${({ endOfTableSticky, hasHorizontalOverflow }) =>
endOfTableSticky &&
`
bottom: ${hasHorizontalOverflow ? '10px' : '0'};
${
hasHorizontalOverflow &&
@ -83,7 +85,6 @@ const StyledTableFoot = styled.thead<{
`
}
`}
}
`;
export const RecordTableAggregateFooter = ({
@ -108,32 +109,30 @@ export const RecordTableAggregateFooter = ({
: false;
return (
<StyledTableFoot
<StyledTableRow
id={`record-table-footer${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
data-select-disable
endOfTableSticky={endOfTableSticky}
hasHorizontalOverflow={hasHorizontalOverflow}
>
<tr>
<StyledTh />
<StyledTh />
{visibleTableColumns.map((column, index) => {
return (
<RecordTableColumnAggregateFooterCellContext.Provider
key={`${column.fieldMetadataId}${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
value={{
viewFieldId: column.viewFieldId || '',
fieldMetadataId: column.fieldMetadataId,
}}
>
<RecordTableAggregateFooterCell
currentRecordGroupId={currentRecordGroupId}
isFirstCell={index === 0}
/>
</RecordTableColumnAggregateFooterCellContext.Provider>
);
})}
</tr>
</StyledTableFoot>
<StyledTd />
<StyledTd />
{visibleTableColumns.map((column, index) => {
return (
<RecordTableColumnAggregateFooterCellContext.Provider
key={`${column.fieldMetadataId}${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
value={{
viewFieldId: column.viewFieldId || '',
fieldMetadataId: column.fieldMetadataId,
}}
>
<RecordTableAggregateFooterCell
currentRecordGroupId={currentRecordGroupId}
isFirstCell={index === 0}
/>
</RecordTableColumnAggregateFooterCellContext.Provider>
);
})}
</StyledTableRow>
);
};

View File

@ -9,7 +9,7 @@ import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
const COLUMN_MIN_WIDTH = 104;
const StyledColumnFooterCell = styled.th<{
const StyledColumnFooterCell = styled.td<{
columnWidth: number;
}>`
background-color: ${({ theme }) => theme.background.primary};
@ -43,7 +43,6 @@ const StyledColumnFooterCell = styled.th<{
*::-webkit-scrollbar {
display: none;
}
border-top: 1px solid ${({ theme }) => theme.border.color.light};
`;
const StyledColumnFootContainer = styled.div`

View File

@ -9,18 +9,13 @@ import { useRecordTableContextOrThrow } from '@/object-record/record-table/conte
import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext';
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
import { UserContext } from '@/users/contexts/UserContext';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
export const useAggregateRecordsForRecordTableColumnFooter = (
fieldMetadataId: string,
) => {
const isAggregateQueryEnabled = useIsFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
);
const { objectMetadataItem } = useRecordTableContextOrThrow();
const { recordGroupFilter } = useRecordGroupFilter(objectMetadataItem.fields);
@ -61,8 +56,7 @@ export const useAggregateRecordsForRecordTableColumnFooter = (
objectNameSingular: objectMetadataItem.nameSingular,
recordGqlFieldsAggregate,
filter: { ...requestFilters, ...recordGroupFilter },
skip:
!isAggregateQueryEnabled || !isDefined(aggregateOperationForViewField),
skip: !isDefined(aggregateOperationForViewField),
});
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);

View File

@ -6,6 +6,10 @@ const StyledTr = styled.tr<{ isDragging: boolean }>`
? `1px solid ${theme.border.color.medium}`
: '1px solid transparent'};
transition: border-left-color 0.2s ease-in-out;
&:nth-last-child(2) td {
border-bottom: none;
}
`;
export const RecordTableTr = StyledTr;

View File

@ -70,11 +70,6 @@ export const seedFeatureFlags = async (
workspaceId: workspaceId,
value: false,
},
{
key: FeatureFlagKey.IsAggregateQueryEnabled,
workspaceId: workspaceId,
value: true,
},
{
key: FeatureFlagKey.IsCommandMenuV2Enabled,
workspaceId: workspaceId,

View File

@ -27,7 +27,6 @@ import {
getCursor,
getPaginationInfo,
} from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
import { isDefined } from 'src/utils/is-defined';
@ -109,19 +108,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
appliedFilters,
);
const isAggregationsEnabled =
await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsAggregateQueryEnabled,
authContext.workspace.id,
);
if (!isAggregationsEnabled) {
executionArgs.graphqlQuerySelectedFieldsResult.aggregate = {
totalCount:
executionArgs.graphqlQuerySelectedFieldsResult.aggregate.totalCount,
};
}
const processAggregateHelper = new ProcessAggregateHelper();
processAggregateHelper.addSelectedAggregatedFieldsQueriesToQueryBuilder({

View File

@ -12,7 +12,6 @@ export enum FeatureFlagKey {
IsUniqueIndexesEnabled = 'IS_UNIQUE_INDEXES_ENABLED',
IsMicrosoftSyncEnabled = 'IS_MICROSOFT_SYNC_ENABLED',
IsAdvancedFiltersEnabled = 'IS_ADVANCED_FILTERS_ENABLED',
IsAggregateQueryEnabled = 'IS_AGGREGATE_QUERY_ENABLED',
IsCommandMenuV2Enabled = 'IS_COMMAND_MENU_V2_ENABLED',
IsCrmMigrationEnabled = 'IS_CRM_MIGRATION_ENABLED',
IsJsonFilterEnabled = 'IS_JSON_FILTER_ENABLED',