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:
@ -389,7 +389,6 @@ export type FeatureFlagFilter = {
|
|||||||
|
|
||||||
export enum FeatureFlagKey {
|
export enum FeatureFlagKey {
|
||||||
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
|
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
|
||||||
IsAggregateQueryEnabled = 'IsAggregateQueryEnabled',
|
|
||||||
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
|
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
|
||||||
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
|
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
|
||||||
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',
|
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { gql } from '@apollo/client';
|
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
|
import { gql } from '@apollo/client';
|
||||||
export type Maybe<T> = T | null;
|
export type Maybe<T> = T | null;
|
||||||
export type InputMaybe<T> = Maybe<T>;
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
@ -321,7 +321,6 @@ export type FeatureFlagFilter = {
|
|||||||
|
|
||||||
export enum FeatureFlagKey {
|
export enum FeatureFlagKey {
|
||||||
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
|
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
|
||||||
IsAggregateQueryEnabled = 'IsAggregateQueryEnabled',
|
|
||||||
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
|
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
|
||||||
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
|
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
|
||||||
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',
|
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||||
import { getAggregateQueryName } from '@/object-record/utils/getAggregateQueryName';
|
import { getAggregateQueryName } from '@/object-record/utils/getAggregateQueryName';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useApolloClient } from '@apollo/client';
|
import { useApolloClient } from '@apollo/client';
|
||||||
import { renderHook } from '@testing-library/react';
|
import { renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
@ -8,16 +7,6 @@ jest.mock('@apollo/client', () => ({
|
|||||||
useApolloClient: jest.fn(),
|
useApolloClient: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('@/workspace/hooks/useIsFeatureEnabled', () => ({
|
|
||||||
useIsFeatureEnabled: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock('~/generated/graphql', () => ({
|
|
||||||
FeatureFlagKey: {
|
|
||||||
IsAggregateQueryEnabled: 'IsAggregateQueryEnabled',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('useRefetchAggregateQueries', () => {
|
describe('useRefetchAggregateQueries', () => {
|
||||||
const mockRefetchQueries = jest.fn();
|
const mockRefetchQueries = jest.fn();
|
||||||
const mockApolloClient = {
|
const mockApolloClient = {
|
||||||
@ -29,9 +18,8 @@ describe('useRefetchAggregateQueries', () => {
|
|||||||
(useApolloClient as jest.Mock).mockReturnValue(mockApolloClient);
|
(useApolloClient as jest.Mock).mockReturnValue(mockApolloClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should refetch queries when feature flag is enabled', async () => {
|
it('should refetch queries', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
(useIsFeatureEnabled as jest.Mock).mockReturnValue(true);
|
|
||||||
const objectMetadataNamePlural = 'opportunities';
|
const objectMetadataNamePlural = 'opportunities';
|
||||||
const expectedQueryName = getAggregateQueryName(objectMetadataNamePlural);
|
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 () => {
|
it('should handle errors during refetch', async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
(useIsFeatureEnabled as jest.Mock).mockReturnValue(true);
|
|
||||||
const error = new Error('Refetch failed');
|
const error = new Error('Refetch failed');
|
||||||
mockRefetchQueries.mockRejectedValue(error);
|
mockRefetchQueries.mockRejectedValue(error);
|
||||||
const objectMetadataNamePlural = 'opportunities';
|
const objectMetadataNamePlural = 'opportunities';
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
import { getAggregateQueryName } from '@/object-record/utils/getAggregateQueryName';
|
import { getAggregateQueryName } from '@/object-record/utils/getAggregateQueryName';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useApolloClient } from '@apollo/client';
|
import { useApolloClient } from '@apollo/client';
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
|
|
||||||
export const useRefetchAggregateQueries = ({
|
export const useRefetchAggregateQueries = ({
|
||||||
objectMetadataNamePlural,
|
objectMetadataNamePlural,
|
||||||
@ -9,17 +7,13 @@ export const useRefetchAggregateQueries = ({
|
|||||||
objectMetadataNamePlural: string;
|
objectMetadataNamePlural: string;
|
||||||
}) => {
|
}) => {
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
const isAggregateQueryEnabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
);
|
|
||||||
const refetchAggregateQueries = async () => {
|
|
||||||
if (isAggregateQueryEnabled) {
|
|
||||||
const queryName = getAggregateQueryName(objectMetadataNamePlural);
|
|
||||||
|
|
||||||
await apolloClient.refetchQueries({
|
const refetchAggregateQueries = async () => {
|
||||||
include: [queryName],
|
const queryName = getAggregateQueryName(objectMetadataNamePlural);
|
||||||
});
|
|
||||||
}
|
await apolloClient.refetchQueries({
|
||||||
|
include: [queryName],
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -44,7 +44,6 @@ export const RecordBoardColumn = ({
|
|||||||
<RecordBoardColumnContext.Provider
|
<RecordBoardColumnContext.Provider
|
||||||
value={{
|
value={{
|
||||||
columnDefinition: recordGroupDefinition,
|
columnDefinition: recordGroupDefinition,
|
||||||
recordCount: recordIdsByGroup.length,
|
|
||||||
columnId: recordBoardColumnId,
|
columnId: recordBoardColumnId,
|
||||||
recordIds: recordIdsByGroup,
|
recordIds: recordIdsByGroup,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -12,9 +12,7 @@ import { useIsOpportunitiesCompanyFieldDisabled } from '@/object-record/record-b
|
|||||||
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
|
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
|
||||||
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
|
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { IconDotsVertical, IconPlus, LightIconButton, Tag } from 'twenty-ui';
|
import { IconDotsVertical, IconPlus, LightIconButton, Tag } from 'twenty-ui';
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
|
|
||||||
const StyledHeader = styled.div`
|
const StyledHeader = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -42,16 +40,6 @@ const StyledLeftContainer = styled.div`
|
|||||||
gap: ${({ theme }) => theme.spacing(1)};
|
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`
|
const StyledRightContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -103,10 +91,6 @@ export const RecordBoardColumnHeader = () => {
|
|||||||
columnDefinition.id ?? '',
|
columnDefinition.id ?? '',
|
||||||
);
|
);
|
||||||
|
|
||||||
const isAggregateQueryEnabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { isOpportunitiesCompanyFieldDisabled } =
|
const { isOpportunitiesCompanyFieldDisabled } =
|
||||||
useIsOpportunitiesCompanyFieldDisabled();
|
useIsOpportunitiesCompanyFieldDisabled();
|
||||||
|
|
||||||
@ -141,18 +125,12 @@ export const RecordBoardColumnHeader = () => {
|
|||||||
: 'medium'
|
: 'medium'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{isAggregateQueryEnabled ? (
|
<RecordBoardColumnHeaderAggregateDropdown
|
||||||
<RecordBoardColumnHeaderAggregateDropdown
|
aggregateValue={aggregateValue}
|
||||||
aggregateValue={aggregateValue}
|
dropdownId={`record-board-column-aggregate-dropdown-${columnDefinition.id}`}
|
||||||
dropdownId={`record-board-column-aggregate-dropdown-${columnDefinition.id}`}
|
objectMetadataItem={objectMetadataItem}
|
||||||
objectMetadataItem={objectMetadataItem}
|
aggregateLabel={aggregateLabel}
|
||||||
aggregateLabel={aggregateLabel}
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<StyledRecordCountChildren>
|
|
||||||
{aggregateValue}
|
|
||||||
</StyledRecordCountChildren>
|
|
||||||
)}
|
|
||||||
</StyledLeftContainer>
|
</StyledLeftContainer>
|
||||||
<StyledRightContainer>
|
<StyledRightContainer>
|
||||||
{isHeaderHovered && (
|
{isHeaderHovered && (
|
||||||
|
|||||||
@ -32,7 +32,6 @@ export const RecordBoardColumnHeaderWrapper = ({
|
|||||||
value={{
|
value={{
|
||||||
columnId,
|
columnId,
|
||||||
columnDefinition: recordGroupDefinition,
|
columnDefinition: recordGroupDefinition,
|
||||||
recordCount: recordIdsByGroup.length,
|
|
||||||
recordIds: recordIdsByGroup,
|
recordIds: recordIdsByGroup,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { RecordGroupDefinition } from '@/object-record/record-group/types/Record
|
|||||||
|
|
||||||
type RecordBoardColumnContextProps = {
|
type RecordBoardColumnContextProps = {
|
||||||
columnDefinition: RecordGroupDefinition;
|
columnDefinition: RecordGroupDefinition;
|
||||||
recordCount: number;
|
|
||||||
columnId: string;
|
columnId: string;
|
||||||
recordIds: string[];
|
recordIds: string[];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,20 +10,12 @@ import { recordIndexKanbanAggregateOperationState } from '@/object-record/record
|
|||||||
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
||||||
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
|
||||||
import { UserContext } from '@/users/contexts/UserContext';
|
import { UserContext } from '@/users/contexts/UserContext';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
export const useAggregateRecordsForRecordBoardColumn = () => {
|
export const useAggregateRecordsForRecordBoardColumn = () => {
|
||||||
const isAggregateQueryEnabled = useIsFeatureEnabled(
|
const { columnDefinition } = useContext(RecordBoardColumnContext);
|
||||||
FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { columnDefinition, recordCount } = useContext(
|
|
||||||
RecordBoardColumnContext,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { objectMetadataItem } = useContext(RecordBoardContext);
|
const { objectMetadataItem } = useContext(RecordBoardContext);
|
||||||
|
|
||||||
@ -78,7 +70,6 @@ export const useAggregateRecordsForRecordBoardColumn = () => {
|
|||||||
objectNameSingular: objectMetadataItem.nameSingular,
|
objectNameSingular: objectMetadataItem.nameSingular,
|
||||||
recordGqlFieldsAggregate,
|
recordGqlFieldsAggregate,
|
||||||
filter,
|
filter,
|
||||||
skip: !isAggregateQueryEnabled,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
|
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
|
||||||
@ -95,7 +86,7 @@ export const useAggregateRecordsForRecordBoardColumn = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
aggregateValue: isAggregateQueryEnabled ? value : recordCount,
|
aggregateValue: value,
|
||||||
aggregateLabel: isDefined(value) ? labelWithFieldName : undefined,
|
aggregateLabel: isDefined(value) ? labelWithFieldName : undefined,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -171,7 +171,7 @@ describe('computeAggregateValueAndLabel', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
label: 'Earliest date',
|
label: 'Earliest',
|
||||||
labelWithFieldName: 'Earliest date of Created At',
|
labelWithFieldName: 'Earliest date of Created At',
|
||||||
value: '1 Jan, 2023 12:00',
|
value: '1 Jan, 2023 12:00',
|
||||||
});
|
});
|
||||||
@ -207,7 +207,7 @@ describe('computeAggregateValueAndLabel', () => {
|
|||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
value: '31 Dec, 2023 23:59',
|
value: '31 Dec, 2023 23:59',
|
||||||
label: 'Latest date',
|
label: 'Latest',
|
||||||
labelWithFieldName: 'Latest date of Updated At',
|
labelWithFieldName: 'Latest date of Updated At',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { TimeFormat } from '@/localization/constants/TimeFormat';
|
|||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { AggregateRecordsData } from '@/object-record/hooks/useAggregateRecords';
|
import { AggregateRecordsData } from '@/object-record/hooks/useAggregateRecords';
|
||||||
import { getAggregateOperationLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationLabel';
|
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 { 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 { 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';
|
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 =
|
const labelWithFieldName =
|
||||||
aggregateOperation === AGGREGATE_OPERATIONS.count
|
aggregateOperation === AGGREGATE_OPERATIONS.count
|
||||||
? `${getAggregateOperationLabel(AGGREGATE_OPERATIONS.count)}`
|
? `${getAggregateOperationLabel(AGGREGATE_OPERATIONS.count)}`
|
||||||
|
|||||||
@ -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}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -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 { RecordTableNoRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect';
|
||||||
import { RecordTableRecordGroupBodyEffects } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffects';
|
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 { 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 { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
|
||||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||||
import { hasPendingRecordComponentSelector } from '@/object-record/record-table/states/selectors/hasPendingRecordComponentSelector';
|
import { hasPendingRecordComponentSelector } from '@/object-record/record-table/states/selectors/hasPendingRecordComponentSelector';
|
||||||
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
|
||||||
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
|
|
||||||
const StyledTable = styled.table`
|
const StyledTable = styled.table`
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
@ -36,10 +33,6 @@ export const RecordTable = () => {
|
|||||||
|
|
||||||
const tableBodyRef = useRef<HTMLTableElement>(null);
|
const tableBodyRef = useRef<HTMLTableElement>(null);
|
||||||
|
|
||||||
const isAggregateQueryEnabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { toggleClickOutsideListener } = useClickOutsideListener(
|
const { toggleClickOutsideListener } = useClickOutsideListener(
|
||||||
RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID,
|
RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID,
|
||||||
);
|
);
|
||||||
@ -97,12 +90,6 @@ export const RecordTable = () => {
|
|||||||
<RecordTableRecordGroupsBody />
|
<RecordTableRecordGroupsBody />
|
||||||
)}
|
)}
|
||||||
<RecordTableStickyEffect />
|
<RecordTableStickyEffect />
|
||||||
{isAggregateQueryEnabled &&
|
|
||||||
!hasRecordGroups &&
|
|
||||||
!isRecordTableInitialLoading &&
|
|
||||||
allRecordIds.length > 0 && (
|
|
||||||
<RecordTableAggregateFooter endOfTableSticky />
|
|
||||||
)}
|
|
||||||
</StyledTable>
|
</StyledTable>
|
||||||
<DragSelect
|
<DragSelect
|
||||||
dragSelectable={tableBodyRef}
|
dragSelectable={tableBodyRef}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
||||||
import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader';
|
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 { 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';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
|
||||||
export const RecordTableNoRecordGroupRows = () => {
|
export const RecordTableNoRecordGroupRows = () => {
|
||||||
@ -8,6 +10,10 @@ export const RecordTableNoRecordGroupRows = () => {
|
|||||||
recordIndexAllRecordIdsComponentSelector,
|
recordIndexAllRecordIdsComponentSelector,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isRecordTableInitialLoading = useRecoilComponentValueV2(
|
||||||
|
isRecordTableInitialLoadingComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{allRecordIds.map((recordId, rowIndex) => {
|
{allRecordIds.map((recordId, rowIndex) => {
|
||||||
@ -21,6 +27,9 @@ export const RecordTableNoRecordGroupRows = () => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<RecordTableBodyFetchMoreLoader />
|
<RecordTableBodyFetchMoreLoader />
|
||||||
|
{!isRecordTableInitialLoading && allRecordIds.length > 0 && (
|
||||||
|
<RecordTableAggregateFooter endOfTableSticky />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
|
||||||
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
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 { RecordTablePendingRecordGroupRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRecordGroupRow';
|
||||||
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
|
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
|
||||||
import { RecordTableRecordGroupSectionAddNew } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionAddNew';
|
import { RecordTableRecordGroupSectionAddNew } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupSectionAddNew';
|
||||||
@ -59,6 +60,10 @@ export const RecordTableRecordGroupRows = () => {
|
|||||||
<RecordTablePendingRecordGroupRow />
|
<RecordTablePendingRecordGroupRow />
|
||||||
<RecordTableRecordGroupSectionAddNew />
|
<RecordTableRecordGroupSectionAddNew />
|
||||||
<RecordTableRecordGroupSectionLoadMore />
|
<RecordTableRecordGroupSectionLoadMore />
|
||||||
|
<RecordTableAggregateFooter
|
||||||
|
key={currentRecordGroupId}
|
||||||
|
currentRecordGroupId={currentRecordGroupId}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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 { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
|
||||||
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
|
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 { 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 { RecordTableRecordGroupSection } from '@/object-record/record-table/record-table-section/components/RecordTableRecordGroupSection';
|
||||||
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
|
||||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
|
|
||||||
export const RecordTableRecordGroupsBody = () => {
|
export const RecordTableRecordGroupsBody = () => {
|
||||||
const allRecordIds = useRecoilComponentValueV2(
|
const allRecordIds = useRecoilComponentValueV2(
|
||||||
@ -29,10 +26,6 @@ export const RecordTableRecordGroupsBody = () => {
|
|||||||
ViewType.Table,
|
ViewType.Table,
|
||||||
);
|
);
|
||||||
|
|
||||||
const isAggregateQueryEnabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isRecordTableInitialLoading && allRecordIds.length === 0) {
|
if (isRecordTableInitialLoading && allRecordIds.length === 0) {
|
||||||
return <RecordTableBodyLoading />;
|
return <RecordTableBodyLoading />;
|
||||||
}
|
}
|
||||||
@ -50,12 +43,6 @@ export const RecordTableRecordGroupsBody = () => {
|
|||||||
<RecordTableRecordGroupSection />
|
<RecordTableRecordGroupSection />
|
||||||
<RecordTableRecordGroupRows />
|
<RecordTableRecordGroupRows />
|
||||||
</RecordTableBodyDroppable>
|
</RecordTableBodyDroppable>
|
||||||
{isAggregateQueryEnabled && (
|
|
||||||
<RecordTableAggregateFooter
|
|
||||||
key={recordGroupId}
|
|
||||||
currentRecordGroupId={recordGroupId}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</RecordGroupContext.Provider>
|
</RecordGroupContext.Provider>
|
||||||
</RecordTableRecordGroupBodyContextProvider>
|
</RecordTableRecordGroupBodyContextProvider>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -8,38 +8,41 @@ import { scrollWrapperInstanceComponentState } from '@/ui/utilities/scroll/state
|
|||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { MOBILE_VIEWPORT } from 'twenty-ui';
|
import { MOBILE_VIEWPORT } from 'twenty-ui';
|
||||||
|
|
||||||
const StyledTh = styled.th`
|
const StyledTd = styled.td`
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
background-color: ${({ theme }) => theme.background.primary};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTableFoot = styled.thead<{
|
const StyledTableRow = styled.tr<{
|
||||||
endOfTableSticky?: boolean;
|
endOfTableSticky?: boolean;
|
||||||
hasHorizontalOverflow?: boolean;
|
hasHorizontalOverflow?: boolean;
|
||||||
}>`
|
}>`
|
||||||
|
td {
|
||||||
|
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
|
}
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
th:nth-of-type(1) {
|
td:nth-of-type(1) {
|
||||||
width: ${FIRST_TH_WIDTH};
|
width: ${FIRST_TH_WIDTH};
|
||||||
left: 0;
|
left: 0;
|
||||||
border-right-color: ${({ theme }) => theme.background.primary};
|
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-right-color: ${({ theme }) => theme.background.primary};
|
||||||
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
|
||||||
}
|
}
|
||||||
&.first-columns-sticky {
|
&.first-columns-sticky {
|
||||||
th:nth-of-type(1) {
|
td:nth-of-type(1) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
transition: 0.3s ease;
|
transition: 0.3s ease;
|
||||||
}
|
}
|
||||||
th:nth-of-type(2) {
|
td:nth-of-type(2) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 11px;
|
left: 11px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
transition: 0.3s ease;
|
transition: 0.3s ease;
|
||||||
}
|
}
|
||||||
th:nth-of-type(3) {
|
td:nth-of-type(3) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 43px;
|
left: 43px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
@ -60,13 +63,12 @@ const StyledTableFoot = styled.thead<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tr {
|
position: sticky;
|
||||||
position: sticky;
|
z-index: 5;
|
||||||
z-index: 5;
|
background: ${({ theme }) => theme.background.primary};
|
||||||
background: ${({ theme }) => theme.background.primary};
|
${({ endOfTableSticky, hasHorizontalOverflow }) =>
|
||||||
${({ endOfTableSticky, hasHorizontalOverflow }) =>
|
endOfTableSticky &&
|
||||||
endOfTableSticky &&
|
`
|
||||||
`
|
|
||||||
bottom: ${hasHorizontalOverflow ? '10px' : '0'};
|
bottom: ${hasHorizontalOverflow ? '10px' : '0'};
|
||||||
${
|
${
|
||||||
hasHorizontalOverflow &&
|
hasHorizontalOverflow &&
|
||||||
@ -83,7 +85,6 @@ const StyledTableFoot = styled.thead<{
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const RecordTableAggregateFooter = ({
|
export const RecordTableAggregateFooter = ({
|
||||||
@ -108,32 +109,30 @@ export const RecordTableAggregateFooter = ({
|
|||||||
: false;
|
: false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledTableFoot
|
<StyledTableRow
|
||||||
id={`record-table-footer${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
|
id={`record-table-footer${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
|
||||||
data-select-disable
|
data-select-disable
|
||||||
endOfTableSticky={endOfTableSticky}
|
endOfTableSticky={endOfTableSticky}
|
||||||
hasHorizontalOverflow={hasHorizontalOverflow}
|
hasHorizontalOverflow={hasHorizontalOverflow}
|
||||||
>
|
>
|
||||||
<tr>
|
<StyledTd />
|
||||||
<StyledTh />
|
<StyledTd />
|
||||||
<StyledTh />
|
{visibleTableColumns.map((column, index) => {
|
||||||
{visibleTableColumns.map((column, index) => {
|
return (
|
||||||
return (
|
<RecordTableColumnAggregateFooterCellContext.Provider
|
||||||
<RecordTableColumnAggregateFooterCellContext.Provider
|
key={`${column.fieldMetadataId}${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
|
||||||
key={`${column.fieldMetadataId}${currentRecordGroupId ? '-' + currentRecordGroupId : ''}`}
|
value={{
|
||||||
value={{
|
viewFieldId: column.viewFieldId || '',
|
||||||
viewFieldId: column.viewFieldId || '',
|
fieldMetadataId: column.fieldMetadataId,
|
||||||
fieldMetadataId: column.fieldMetadataId,
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<RecordTableAggregateFooterCell
|
||||||
<RecordTableAggregateFooterCell
|
currentRecordGroupId={currentRecordGroupId}
|
||||||
currentRecordGroupId={currentRecordGroupId}
|
isFirstCell={index === 0}
|
||||||
isFirstCell={index === 0}
|
/>
|
||||||
/>
|
</RecordTableColumnAggregateFooterCellContext.Provider>
|
||||||
</RecordTableColumnAggregateFooterCellContext.Provider>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
</StyledTableRow>
|
||||||
</tr>
|
|
||||||
</StyledTableFoot>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
|||||||
|
|
||||||
const COLUMN_MIN_WIDTH = 104;
|
const COLUMN_MIN_WIDTH = 104;
|
||||||
|
|
||||||
const StyledColumnFooterCell = styled.th<{
|
const StyledColumnFooterCell = styled.td<{
|
||||||
columnWidth: number;
|
columnWidth: number;
|
||||||
}>`
|
}>`
|
||||||
background-color: ${({ theme }) => theme.background.primary};
|
background-color: ${({ theme }) => theme.background.primary};
|
||||||
@ -43,7 +43,6 @@ const StyledColumnFooterCell = styled.th<{
|
|||||||
*::-webkit-scrollbar {
|
*::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledColumnFootContainer = styled.div`
|
const StyledColumnFootContainer = styled.div`
|
||||||
|
|||||||
@ -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 { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext';
|
||||||
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
|
import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
|
||||||
import { UserContext } from '@/users/contexts/UserContext';
|
import { UserContext } from '@/users/contexts/UserContext';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { FeatureFlagKey } from '~/generated/graphql';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
export const useAggregateRecordsForRecordTableColumnFooter = (
|
export const useAggregateRecordsForRecordTableColumnFooter = (
|
||||||
fieldMetadataId: string,
|
fieldMetadataId: string,
|
||||||
) => {
|
) => {
|
||||||
const isAggregateQueryEnabled = useIsFeatureEnabled(
|
|
||||||
FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
);
|
|
||||||
const { objectMetadataItem } = useRecordTableContextOrThrow();
|
const { objectMetadataItem } = useRecordTableContextOrThrow();
|
||||||
const { recordGroupFilter } = useRecordGroupFilter(objectMetadataItem.fields);
|
const { recordGroupFilter } = useRecordGroupFilter(objectMetadataItem.fields);
|
||||||
|
|
||||||
@ -61,8 +56,7 @@ export const useAggregateRecordsForRecordTableColumnFooter = (
|
|||||||
objectNameSingular: objectMetadataItem.nameSingular,
|
objectNameSingular: objectMetadataItem.nameSingular,
|
||||||
recordGqlFieldsAggregate,
|
recordGqlFieldsAggregate,
|
||||||
filter: { ...requestFilters, ...recordGroupFilter },
|
filter: { ...requestFilters, ...recordGroupFilter },
|
||||||
skip:
|
skip: !isDefined(aggregateOperationForViewField),
|
||||||
!isAggregateQueryEnabled || !isDefined(aggregateOperationForViewField),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
|
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
|
||||||
|
|||||||
@ -6,6 +6,10 @@ const StyledTr = styled.tr<{ isDragging: boolean }>`
|
|||||||
? `1px solid ${theme.border.color.medium}`
|
? `1px solid ${theme.border.color.medium}`
|
||||||
: '1px solid transparent'};
|
: '1px solid transparent'};
|
||||||
transition: border-left-color 0.2s ease-in-out;
|
transition: border-left-color 0.2s ease-in-out;
|
||||||
|
|
||||||
|
&:nth-last-child(2) td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const RecordTableTr = StyledTr;
|
export const RecordTableTr = StyledTr;
|
||||||
|
|||||||
@ -70,11 +70,6 @@ export const seedFeatureFlags = async (
|
|||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: FeatureFlagKey.IsAggregateQueryEnabled,
|
|
||||||
workspaceId: workspaceId,
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: FeatureFlagKey.IsCommandMenuV2Enabled,
|
key: FeatureFlagKey.IsCommandMenuV2Enabled,
|
||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
|
|||||||
@ -27,7 +27,6 @@ import {
|
|||||||
getCursor,
|
getCursor,
|
||||||
getPaginationInfo,
|
getPaginationInfo,
|
||||||
} from 'src/engine/api/graphql/graphql-query-runner/utils/cursors.util';
|
} 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 { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||||
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util';
|
||||||
import { isDefined } from 'src/utils/is-defined';
|
import { isDefined } from 'src/utils/is-defined';
|
||||||
@ -109,19 +108,6 @@ export class GraphqlQueryFindManyResolverService extends GraphqlQueryBaseResolve
|
|||||||
appliedFilters,
|
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();
|
const processAggregateHelper = new ProcessAggregateHelper();
|
||||||
|
|
||||||
processAggregateHelper.addSelectedAggregatedFieldsQueriesToQueryBuilder({
|
processAggregateHelper.addSelectedAggregatedFieldsQueriesToQueryBuilder({
|
||||||
|
|||||||
@ -12,7 +12,6 @@ export enum FeatureFlagKey {
|
|||||||
IsUniqueIndexesEnabled = 'IS_UNIQUE_INDEXES_ENABLED',
|
IsUniqueIndexesEnabled = 'IS_UNIQUE_INDEXES_ENABLED',
|
||||||
IsMicrosoftSyncEnabled = 'IS_MICROSOFT_SYNC_ENABLED',
|
IsMicrosoftSyncEnabled = 'IS_MICROSOFT_SYNC_ENABLED',
|
||||||
IsAdvancedFiltersEnabled = 'IS_ADVANCED_FILTERS_ENABLED',
|
IsAdvancedFiltersEnabled = 'IS_ADVANCED_FILTERS_ENABLED',
|
||||||
IsAggregateQueryEnabled = 'IS_AGGREGATE_QUERY_ENABLED',
|
|
||||||
IsCommandMenuV2Enabled = 'IS_COMMAND_MENU_V2_ENABLED',
|
IsCommandMenuV2Enabled = 'IS_COMMAND_MENU_V2_ENABLED',
|
||||||
IsCrmMigrationEnabled = 'IS_CRM_MIGRATION_ENABLED',
|
IsCrmMigrationEnabled = 'IS_CRM_MIGRATION_ENABLED',
|
||||||
IsJsonFilterEnabled = 'IS_JSON_FILTER_ENABLED',
|
IsJsonFilterEnabled = 'IS_JSON_FILTER_ENABLED',
|
||||||
|
|||||||
Reference in New Issue
Block a user