[permissions] Remove non-readable field from aggregate options (kanban) (#13559)
Non-readable fields should not be an option for aggregate, as they currently were still in kanban headers. <img width="769" height="733" alt="Capture d’écran 2025-08-01 à 18 16 16" src="https://github.com/user-attachments/assets/475621a6-9a62-4577-8dd4-eb4a3ace36e2" />
This commit is contained in:
+35
-16
@@ -1,4 +1,6 @@
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import { getReadRestrictedFieldMetadataIdsFromObjectPermissions } from '@/object-metadata/utils/getReadRestrictedFieldMetadataIdsFromObjectPermissions';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownContext } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownContext';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownFieldsContent } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownFieldsContent';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownMenuContent } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownMenuContent';
|
||||
@@ -17,13 +19,27 @@ export const AggregateDropdownContent = () => {
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
});
|
||||
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
const restrictedFieldMetadataIds =
|
||||
getReadRestrictedFieldMetadataIdsFromObjectPermissions({
|
||||
objectPermissions: [
|
||||
objectPermissionsByObjectMetadataId[objectMetadataItem.id],
|
||||
],
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
});
|
||||
|
||||
const readableFields = objectMetadataItem.fields.filter(
|
||||
(field) => !restrictedFieldMetadataIds.includes(field.id),
|
||||
);
|
||||
|
||||
switch (currentContentId) {
|
||||
case 'countAggregateOperationsOptions': {
|
||||
const availableAggregations: AvailableFieldsForAggregateOperation =
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
objectMetadataItem.fields,
|
||||
COUNT_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: readableFields,
|
||||
targetAggregateOperations: COUNT_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
return (
|
||||
<RecordBoardColumnHeaderAggregateDropdownOptionsContent
|
||||
availableAggregations={availableAggregations}
|
||||
@@ -33,10 +49,10 @@ export const AggregateDropdownContent = () => {
|
||||
}
|
||||
case 'percentAggregateOperationsOptions': {
|
||||
const availableAggregations: AvailableFieldsForAggregateOperation =
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
objectMetadataItem.fields,
|
||||
PERCENT_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: readableFields,
|
||||
targetAggregateOperations: PERCENT_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
return (
|
||||
<RecordBoardColumnHeaderAggregateDropdownOptionsContent
|
||||
availableAggregations={availableAggregations}
|
||||
@@ -46,10 +62,13 @@ export const AggregateDropdownContent = () => {
|
||||
}
|
||||
case 'datesAggregateOperationOptions': {
|
||||
const datesAvailableAggregations: AvailableFieldsForAggregateOperation =
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
objectMetadataItem.fields,
|
||||
[DateAggregateOperations.EARLIEST, DateAggregateOperations.LATEST],
|
||||
);
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: readableFields,
|
||||
targetAggregateOperations: [
|
||||
DateAggregateOperations.EARLIEST,
|
||||
DateAggregateOperations.LATEST,
|
||||
],
|
||||
});
|
||||
return (
|
||||
<RecordBoardColumnHeaderAggregateDropdownOptionsContent
|
||||
availableAggregations={datesAvailableAggregations}
|
||||
@@ -59,10 +78,10 @@ export const AggregateDropdownContent = () => {
|
||||
}
|
||||
case 'moreAggregateOperationOptions': {
|
||||
const availableAggregationsWithoutDates: AvailableFieldsForAggregateOperation =
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
objectMetadataItem.fields,
|
||||
NON_STANDARD_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: readableFields,
|
||||
targetAggregateOperations: NON_STANDARD_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
return (
|
||||
<RecordBoardColumnHeaderAggregateDropdownOptionsContent
|
||||
availableAggregations={availableAggregationsWithoutDates}
|
||||
|
||||
+16
-16
@@ -67,10 +67,10 @@ jest.mock(
|
||||
|
||||
describe('getAvailableFieldsIdsForAggregationFromObjectFields', () => {
|
||||
it('should handle empty fields array', () => {
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
[],
|
||||
COUNT_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: [],
|
||||
targetAggregateOperations: COUNT_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
|
||||
COUNT_AGGREGATE_OPERATION_OPTIONS.forEach((operation) => {
|
||||
expect(result[operation]).toEqual([]);
|
||||
@@ -79,10 +79,10 @@ describe('getAvailableFieldsIdsForAggregationFromObjectFields', () => {
|
||||
|
||||
describe('with count aggregate operations', () => {
|
||||
it('should include all fields', () => {
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
FIELDS_MOCKS as FieldMetadataItem[],
|
||||
COUNT_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: FIELDS_MOCKS as FieldMetadataItem[],
|
||||
targetAggregateOperations: COUNT_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
|
||||
expect(result.COUNT).toEqual(
|
||||
expect.arrayContaining([
|
||||
@@ -107,10 +107,10 @@ describe('getAvailableFieldsIdsForAggregationFromObjectFields', () => {
|
||||
|
||||
describe('with percentage aggregate operations', () => {
|
||||
it('should include all fields', () => {
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
FIELDS_MOCKS as FieldMetadataItem[],
|
||||
PERCENT_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: FIELDS_MOCKS as FieldMetadataItem[],
|
||||
targetAggregateOperations: PERCENT_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
|
||||
PERCENT_AGGREGATE_OPERATION_OPTIONS.forEach((operation) => {
|
||||
expect(result[operation]).toEqual([
|
||||
@@ -132,10 +132,10 @@ describe('getAvailableFieldsIdsForAggregationFromObjectFields', () => {
|
||||
|
||||
describe('with non standard aggregate operations', () => {
|
||||
it('should exclude non-numeric fields', () => {
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields(
|
||||
FIELDS_MOCKS as FieldMetadataItem[],
|
||||
NON_STANDARD_AGGREGATE_OPERATION_OPTIONS,
|
||||
);
|
||||
const result = getAvailableFieldsIdsForAggregationFromObjectFields({
|
||||
fields: FIELDS_MOCKS as FieldMetadataItem[],
|
||||
targetAggregateOperations: NON_STANDARD_AGGREGATE_OPERATION_OPTIONS,
|
||||
});
|
||||
|
||||
COUNT_AGGREGATE_OPERATION_OPTIONS.forEach((operation) => {
|
||||
expect(result[operation]).toBeUndefined();
|
||||
|
||||
+7
-4
@@ -5,10 +5,13 @@ import { getAvailableAggregationsFromObjectFields } from '@/object-record/utils/
|
||||
import { initializeAvailableFieldsForAggregateOperationMap } from '@/object-record/utils/initializeAvailableFieldsForAggregateOperationMap';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const getAvailableFieldsIdsForAggregationFromObjectFields = (
|
||||
fields: FieldMetadataItem[],
|
||||
targetAggregateOperations: ExtendedAggregateOperations[],
|
||||
): AvailableFieldsForAggregateOperation => {
|
||||
export const getAvailableFieldsIdsForAggregationFromObjectFields = ({
|
||||
fields,
|
||||
targetAggregateOperations,
|
||||
}: {
|
||||
fields: FieldMetadataItem[];
|
||||
targetAggregateOperations: ExtendedAggregateOperations[];
|
||||
}): AvailableFieldsForAggregateOperation => {
|
||||
const aggregationMap = initializeAvailableFieldsForAggregateOperationMap(
|
||||
targetAggregateOperations,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user