Aggregate follow-up (#9547)

In this PR
- fix [some UI
regressions](https://discord.com/channels/1130383047699738754/1327189577575956514/1327189577575956514)
introduced by work on view groups
- address some follow-ups:
1. [Menu should keep selected when the menu is
open](https://discord.com/channels/1130383047699738754/1326607851824877639/1326607851824877639)
2.
[Cropping](https://discord.com/channels/1130383047699738754/1326610578869063800/1326610578869063800)
3. [Put earliest date / latest date in a separate "Date"
submenu](https://discord.com/channels/1130383047699738754/1326856023985618966/1326856023985618966)
- Refactor around date aggregate operations
This commit is contained in:
Marie
2025-01-10 20:01:36 +01:00
committed by GitHub
parent 873f20bc0e
commit 2e0169b954
48 changed files with 440 additions and 195 deletions

View File

@ -2,7 +2,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
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 { NON_STANDARD_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-table/record-table-footer/constants/nonStandardAggregateOperationsOptions';
import { PERCENT_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-table/record-table-footer/constants/percentAggregateOperationOption';
import { PERCENT_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-table/record-table-footer/constants/percentAggregateOperationOptions';
import { getAvailableFieldsIdsForAggregationFromObjectFields } from '@/object-record/utils/getAvailableFieldsIdsForAggregationFromObjectFields';
import { FieldMetadataType } from '~/generated/graphql';

View File

@ -1,7 +1,7 @@
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { FIELD_TYPES_AVAILABLE_FOR_NON_STANDARD_AGGREGATE_OPERATION } from '@/object-record/record-table/constants/FieldTypesAvailableForNonStandardAggregateOperation';
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/percentAggregateOperationOption';
import { PERCENT_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-table/record-table-footer/constants/percentAggregateOperationOptions';
import { AggregateOperationsOmittingStandardOperations } from '@/object-record/types/AggregateOperationsOmittingStandardOperations';
import { initializeAvailableFieldsForAggregateOperationMap } from '@/object-record/utils/initializeAvailableFieldsForAggregateOperationMap';

View File

@ -1,4 +1,5 @@
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';
import { isFieldMetadataDateKind } from 'twenty-shared';
import { FieldMetadataType } from '~/generated-metadata/graphql';
@ -9,10 +10,10 @@ export const convertAggregateOperationToExtendedAggregateOperation = (
): ExtendedAggregateOperations => {
if (isFieldMetadataDateKind(fieldType) === true) {
if (aggregateOperation === AGGREGATE_OPERATIONS.min) {
return 'EARLIEST';
return DATE_AGGREGATE_OPERATIONS.earliest;
}
if (aggregateOperation === AGGREGATE_OPERATIONS.max) {
return 'LATEST';
return DATE_AGGREGATE_OPERATIONS.latest;
}
}
return aggregateOperation;

View File

@ -1,14 +1,15 @@
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 convertExtendedAggregateOperationToAggregateOperation = (
extendedAggregateOperation: ExtendedAggregateOperations,
extendedAggregateOperation: ExtendedAggregateOperations | null,
) => {
if (extendedAggregateOperation === 'EARLIEST') {
if (extendedAggregateOperation === DATE_AGGREGATE_OPERATIONS.earliest) {
return AGGREGATE_OPERATIONS.min;
}
if (extendedAggregateOperation === 'LATEST') {
if (extendedAggregateOperation === DATE_AGGREGATE_OPERATIONS.latest) {
return AGGREGATE_OPERATIONS.max;
}
return extendedAggregateOperation;

View File

@ -1,10 +1,12 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
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';
import { capitalize, isFieldMetadataDateKind } from 'twenty-shared';
import { FieldMetadataType } from '~/generated-metadata/graphql';
type NameForAggregation = {
[T in AGGREGATE_OPERATIONS]?: string;
[T in ExtendedAggregateOperations]?: string;
};
type Aggregations = {
@ -58,8 +60,8 @@ export const getAvailableAggregationsFromObjectFields = (
if (isFieldMetadataDateKind(field.type) === true) {
acc[field.name] = {
...acc[field.name],
[AGGREGATE_OPERATIONS.min]: `min${capitalize(field.name)}`,
[AGGREGATE_OPERATIONS.max]: `max${capitalize(field.name)}`,
[DATE_AGGREGATE_OPERATIONS.earliest]: `min${capitalize(field.name)}`,
[DATE_AGGREGATE_OPERATIONS.latest]: `max${capitalize(field.name)}`,
};
}

View File

@ -1,15 +1,13 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { AvailableFieldsForAggregateOperation } from '@/object-record/types/AvailableFieldsForAggregateOperation';
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
import { getAvailableAggregationsFromObjectFields } from '@/object-record/utils/getAvailableAggregationsFromObjectFields';
import { initializeAvailableFieldsForAggregateOperationMap } from '@/object-record/utils/initializeAvailableFieldsForAggregateOperationMap';
import { isDefined } from '~/utils/isDefined';
export const getAvailableFieldsIdsForAggregationFromObjectFields = (
fields: FieldMetadataItem[],
targetAggregateOperations: AGGREGATE_OPERATIONS[],
targetAggregateOperations: ExtendedAggregateOperations[],
): AvailableFieldsForAggregateOperation => {
const aggregationMap = initializeAvailableFieldsForAggregateOperationMap(
targetAggregateOperations,
@ -20,20 +18,12 @@ export const getAvailableFieldsIdsForAggregationFromObjectFields = (
return fields.reduce((acc, field) => {
if (isDefined(allAggregations[field.name])) {
Object.keys(allAggregations[field.name]).forEach((aggregation) => {
if (
targetAggregateOperations.includes(
aggregation as AGGREGATE_OPERATIONS,
)
) {
const convertedAggregateOperation: ExtendedAggregateOperations =
convertAggregateOperationToExtendedAggregateOperation(
aggregation as AGGREGATE_OPERATIONS,
field.type,
);
if (!isDefined(acc[convertedAggregateOperation])) {
acc[convertedAggregateOperation] = [];
const typedAggregation = aggregation as ExtendedAggregateOperations;
if (targetAggregateOperations.includes(typedAggregation)) {
if (!isDefined(acc[typedAggregation])) {
acc[typedAggregation] = [];
}
(acc[convertedAggregateOperation] as string[]).push(field.id);
(acc[typedAggregation] as string[]).push(field.id);
}
});
}

View File

@ -1,14 +1,13 @@
import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { AvailableFieldsForAggregateOperation } from '@/object-record/types/AvailableFieldsForAggregateOperation';
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
export const initializeAvailableFieldsForAggregateOperationMap = (
aggregateOperations: AGGREGATE_OPERATIONS[],
aggregateOperations: ExtendedAggregateOperations[],
): AvailableFieldsForAggregateOperation => {
return aggregateOperations.reduce(
(acc, operation) => ({
...acc,
[convertAggregateOperationToExtendedAggregateOperation(operation)]: [],
[operation]: [],
}),
{},
);