Add Import CSV and Export CSV Permissions (#13421)

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Abdul Rahman
2025-07-25 11:37:38 +05:30
committed by GitHub
parent f411bd1b0e
commit 4b95de6775
28 changed files with 118 additions and 71 deletions

View File

@ -53,6 +53,7 @@ import {
IconTrashX,
IconUser,
} from 'twenty-ui/display';
import { PermissionFlagType } from '~/generated-metadata/graphql';
export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
| NoSelectionRecordActionKeys
@ -169,6 +170,7 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
isDefined(selectedRecord) && !selectedRecord.isRemote,
availableOn: [ActionViewType.SHOW_PAGE],
component: <ExportSingleRecordAction />,
requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
},
[MultipleRecordsActionKeys.EXPORT]: {
type: ActionType.Standard,
@ -183,6 +185,7 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: () => true,
availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
component: <ExportMultipleRecordsAction />,
requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
},
[NoSelectionRecordActionKeys.IMPORT_RECORDS]: {
type: ActionType.Standard,
@ -198,6 +201,7 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
!isSoftDeleteFilterActive,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: <ImportRecordsNoSelectionRecordAction />,
requiredPermissionFlag: PermissionFlagType.IMPORT_CSV,
},
[NoSelectionRecordActionKeys.EXPORT_VIEW]: {
type: ActionType.Standard,
@ -212,6 +216,7 @@ export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
shouldBeRegistered: () => true,
availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
component: <ExportMultipleRecordsAction />,
requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
},
[SingleRecordActionKeys.DELETE]: {
type: ActionType.Standard,

View File

@ -5,6 +5,7 @@ import { ShouldBeRegisteredFunctionParams } from '@/action-menu/actions/types/Sh
import { MessageDescriptor } from '@lingui/core';
import { IconComponent } from 'twenty-ui/display';
import { MenuItemAccent } from 'twenty-ui/navigation';
import { PermissionFlagType } from '~/generated-metadata/graphql';
export type ActionConfig = {
type: ActionType;
@ -21,4 +22,5 @@ export type ActionConfig = {
shouldBeRegistered: (params: ShouldBeRegisteredFunctionParams) => boolean;
component: React.ReactNode;
hotKeys?: string[];
requiredPermissionFlag?: PermissionFlagType;
};

View File

@ -6,6 +6,7 @@ import { getActionConfig } from '@/action-menu/actions/utils/getActionConfig';
import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
@ -48,6 +49,8 @@ export const useRegisteredActions = (
...recordAgnosticActionConfig,
};
const permissionMap = usePermissionFlagMap();
const actionsToRegister = isDefined(viewType)
? Object.values(actionsConfig).filter(
(action) =>
@ -57,7 +60,15 @@ export const useRegisteredActions = (
: [];
const actions = actionsToRegister
.filter((action) => action.shouldBeRegistered(shouldBeRegisteredParams))
.filter((action) => {
if (
isDefined(action.requiredPermissionFlag) &&
!permissionMap[action.requiredPermissionFlag]
) {
return false;
}
return action.shouldBeRegistered(shouldBeRegisteredParams);
})
.sort((a, b) => a.position - b.position);
return actions;