Add object level permission permissions to role page (ReadOnly) (#11568)
## Context This PR adds the display of object-level permissions. A following PR will add the ability to update those permissions. The PR contains the SettingsRoleObjectLevel page but it's not fully implemented yet (save won't trigger the corresponding mutation) <img width="616" alt="Screenshot 2025-04-14 at 18 02 40" src="https://github.com/user-attachments/assets/f8c58193-31f3-468a-a96d-f06a9f2e1423" />
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { ChangeEvent, useState } from 'react';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
|
||||
type SettingsRolePermissionsObjectLevelObjectPickerDropdownContentProps = {
|
||||
excludedObjectMetadataIds: string[];
|
||||
onSelect: (objectMetadataId: string) => void;
|
||||
};
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelObjectPickerDropdownContent = ({
|
||||
excludedObjectMetadataIds,
|
||||
onSelect,
|
||||
}: SettingsRolePermissionsObjectLevelObjectPickerDropdownContentProps) => {
|
||||
const [searchFilter, setSearchFilter] = useState('');
|
||||
|
||||
const { objectMetadataItems } = useFilteredObjectMetadataItems();
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const handleSearchFilterChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchFilter(event.target.value);
|
||||
};
|
||||
|
||||
const filteredObjectMetadataItems = objectMetadataItems.filter(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.labelSingular
|
||||
.toLowerCase()
|
||||
.includes(searchFilter.toLowerCase()) &&
|
||||
!excludedObjectMetadataIds.includes(objectMetadataItem.id),
|
||||
);
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuSearchInput
|
||||
value={searchFilter}
|
||||
onChange={handleSearchFilterChange}
|
||||
placeholder={t`Search`}
|
||||
/>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer hasMaxHeight>
|
||||
{filteredObjectMetadataItems.map((objectMetadataItem) => (
|
||||
<MenuItem
|
||||
key={objectMetadataItem.id}
|
||||
text={objectMetadataItem.labelSingular}
|
||||
LeftIcon={getIcon(objectMetadataItem.icon)}
|
||||
onClick={() => onSelect(objectMetadataItem.id)}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
import { SETTINGS_ROLE_OBJECT_PERMISSION_ICON_CONFIG } from '@/settings/roles/role-permissions/objects-permissions/constants/settingsRoleObjectPermissionIconConfig';
|
||||
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { ObjectPermission } from '~/generated/graphql';
|
||||
|
||||
const StyledIconWrapper = styled.div<{ isForbidden?: boolean }>`
|
||||
align-items: center;
|
||||
background: ${({ theme, isForbidden }) =>
|
||||
isForbidden ? theme.adaptiveColors.orange1 : theme.adaptiveColors.blue1};
|
||||
border: 1px solid
|
||||
${({ theme, isForbidden }) =>
|
||||
isForbidden ? theme.adaptiveColors.orange3 : theme.adaptiveColors.blue3};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
display: flex;
|
||||
height: ${({ theme }) => theme.spacing(4)};
|
||||
justify-content: center;
|
||||
width: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
const StyledIcon = styled.div<{ isForbidden?: boolean }>`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
color: ${({ theme, isForbidden }) =>
|
||||
isForbidden ? theme.color.orange : theme.color.blue};
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const StyledSettingsRolePermissionsObjectLevelOverrideCell = styled.div`
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
type SettingsRolePermissionsObjectLevelOverrideCellProps = {
|
||||
objectPermission: ObjectPermission;
|
||||
};
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelOverrideCell = ({
|
||||
objectPermission,
|
||||
}: SettingsRolePermissionsObjectLevelOverrideCellProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const settingsDraftRole = useRecoilValue(
|
||||
settingsDraftRoleFamilyState(objectPermission.roleId),
|
||||
);
|
||||
|
||||
const permissionMappings = {
|
||||
canReadObjectRecords: 'canReadAllObjectRecords',
|
||||
canUpdateObjectRecords: 'canUpdateAllObjectRecords',
|
||||
canSoftDeleteObjectRecords: 'canSoftDeleteAllObjectRecords',
|
||||
canDestroyObjectRecords: 'canDestroyAllObjectRecords',
|
||||
} as const;
|
||||
|
||||
type ObjectPermissionKey = keyof typeof permissionMappings;
|
||||
|
||||
const isOverridden = (permission: ObjectPermissionKey) => {
|
||||
const rolePermission = permissionMappings[permission];
|
||||
return (
|
||||
isDefined(objectPermission[permission]) &&
|
||||
!!settingsDraftRole[rolePermission as keyof typeof settingsDraftRole] !==
|
||||
!!objectPermission[permission]
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledSettingsRolePermissionsObjectLevelOverrideCell>
|
||||
{(Object.keys(permissionMappings) as ObjectPermissionKey[]).map(
|
||||
(permission) => {
|
||||
const { Icon, IconForbidden: IconOverride } =
|
||||
SETTINGS_ROLE_OBJECT_PERMISSION_ICON_CONFIG[permission];
|
||||
const permissionValue = objectPermission[permission];
|
||||
|
||||
if (!isOverridden(permission)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledIconWrapper
|
||||
key={permission}
|
||||
isForbidden={permissionValue === false}
|
||||
>
|
||||
<StyledIcon isForbidden={permissionValue === false}>
|
||||
{permissionValue === false && (
|
||||
<IconOverride size={theme.icon.size.sm} />
|
||||
)}
|
||||
{permissionValue === true && <Icon size={theme.icon.size.sm} />}
|
||||
</StyledIcon>
|
||||
</StyledIconWrapper>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</StyledSettingsRolePermissionsObjectLevelOverrideCell>
|
||||
);
|
||||
};
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SettingsRolePermissionsObjectLevelTableHeader } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelTableHeader';
|
||||
import { SettingsRolePermissionsObjectLevelTableRow } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelTableRow';
|
||||
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { H2Title } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
// const StyledCreateObjectOverrideSection = styled(Section)`
|
||||
// border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
// display: flex;
|
||||
// justify-content: flex-end;
|
||||
// padding-top: ${({ theme }) => theme.spacing(2)};
|
||||
// padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
// `;
|
||||
|
||||
const StyledTableRows = styled.div`
|
||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
type SettingsRolePermissionsObjectLevelSectionProps = {
|
||||
roleId: string;
|
||||
isEditable: boolean;
|
||||
};
|
||||
|
||||
const StyledNoOverride = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
`;
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelSection = ({
|
||||
roleId,
|
||||
}: SettingsRolePermissionsObjectLevelSectionProps) => {
|
||||
const settingsDraftRole = useRecoilValue(
|
||||
settingsDraftRoleFamilyState(roleId),
|
||||
);
|
||||
|
||||
const objectMetadataItems = useObjectMetadataItems();
|
||||
|
||||
const objectMetadataMap = objectMetadataItems.objectMetadataItems.reduce(
|
||||
(acc, item) => {
|
||||
acc[item.id] = item;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, ObjectMetadataItem>,
|
||||
);
|
||||
|
||||
const objectPermissions = settingsDraftRole.objectPermissions;
|
||||
|
||||
// const handleSelectObjectMetadata = (objectMetadataId: string) => {
|
||||
// setSettingsDraftRole((draftRole) => ({
|
||||
// ...draftRole,
|
||||
// objectPermissions: [
|
||||
// ...(draftRole.objectPermissions ?? []),
|
||||
// { objectMetadataId, roleId, id: v4() },
|
||||
// ],
|
||||
// }));
|
||||
// };
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<H2Title
|
||||
title={t`Object-Level Permissions`}
|
||||
description={t`Set additional object-level permissions`}
|
||||
/>
|
||||
<Table>
|
||||
<SettingsRolePermissionsObjectLevelTableHeader />
|
||||
<StyledTableRows>
|
||||
{isDefined(objectPermissions) && objectPermissions?.length > 0 ? (
|
||||
objectPermissions?.map((objectPermission) => (
|
||||
<SettingsRolePermissionsObjectLevelTableRow
|
||||
key={objectPermission.id}
|
||||
objectPermission={objectPermission}
|
||||
objectMetadataItem={
|
||||
objectMetadataMap[objectPermission.objectMetadataId]
|
||||
}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<StyledNoOverride>{t`No overrides found`}</StyledNoOverride>
|
||||
)}
|
||||
</StyledTableRows>
|
||||
</Table>
|
||||
{/* <StyledCreateObjectOverrideSection>
|
||||
<Dropdown
|
||||
dropdownId="role-object-select"
|
||||
dropdownHotkeyScope={{ scope: 'roleObject' }}
|
||||
clickableComponent={
|
||||
<Button
|
||||
Icon={IconPlus}
|
||||
title={t`Add Object`}
|
||||
variant="secondary"
|
||||
size="small"
|
||||
disabled={!isEditable}
|
||||
/>
|
||||
}
|
||||
dropdownComponents={
|
||||
<SettingsRolePermissionsObjectLevelObjectPickerDropdownContent
|
||||
excludedObjectMetadataIds={[]}
|
||||
onSelect={handleSelectObjectMetadata}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</StyledCreateObjectOverrideSection> */}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelTableHeader = () => (
|
||||
<TableRow>
|
||||
<TableHeader>{t`Object`}</TableHeader>
|
||||
<TableHeader>{t`Permission overrides`}</TableHeader>
|
||||
<TableHeader></TableHeader>
|
||||
</TableRow>
|
||||
);
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SettingsRolePermissionsObjectLevelOverrideCell } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelOverrideCell';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconChevronRight, useIcons } from 'twenty-ui/display';
|
||||
import { ObjectPermission } from '~/generated/graphql';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const StyledNameLabel = styled.div`
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
type SettingsRolePermissionsObjectLevelTableRowProps = {
|
||||
objectPermission: ObjectPermission;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
};
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelTableRow = ({
|
||||
objectPermission,
|
||||
objectMetadataItem,
|
||||
}: SettingsRolePermissionsObjectLevelTableRowProps) => {
|
||||
const { getIcon } = useIcons();
|
||||
const theme = useTheme();
|
||||
|
||||
if (!objectMetadataItem) {
|
||||
throw new Error('Object metadata item not found');
|
||||
}
|
||||
|
||||
const Icon = getIcon(objectMetadataItem.icon);
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
to={getSettingsPath(SettingsPath.RoleObjectLevel, {
|
||||
roleId: objectPermission.roleId,
|
||||
objectMetadataId: objectPermission.objectMetadataId,
|
||||
})}
|
||||
>
|
||||
<StyledNameTableCell>
|
||||
{!!Icon && (
|
||||
<Icon
|
||||
style={{ minWidth: theme.icon.size.md }}
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
)}
|
||||
<StyledNameLabel title={objectMetadataItem.labelPlural}>
|
||||
{objectMetadataItem.labelPlural}
|
||||
</StyledNameLabel>
|
||||
</StyledNameTableCell>
|
||||
<TableCell>
|
||||
<SettingsRolePermissionsObjectLevelOverrideCell
|
||||
objectPermission={objectPermission}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell align={'right'}>
|
||||
<IconChevronRight
|
||||
size={theme.icon.size.md}
|
||||
color={theme.font.color.tertiary}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
};
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsDataModelObjectTypeTag } from '@/settings/data-model/objects/components/SettingsDataModelObjectTypeTag';
|
||||
import { getObjectTypeLabel } from '@/settings/data-model/utils/getObjectTypeLabel';
|
||||
import { SettingsRolePermissionsObjectLevelObjectFormObjectLevel } from '@/settings/roles/role-permissions/object-level-permissions/object-form/components/SettingsRolePermissionsObjectLevelObjectFormObjectLevel';
|
||||
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { H3Title } from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
|
||||
const StyledObjectTypeTag = styled(SettingsDataModelObjectTypeTag)`
|
||||
box-sizing: border-box;
|
||||
height: ${({ theme }) => theme.spacing(5)};
|
||||
margin-left: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledTitleContainer = styled.div`
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
type SettingsRolePermissionsObjectLevelObjectFormProps = {
|
||||
roleId: string;
|
||||
objectMetadataId: string;
|
||||
};
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelObjectForm = ({
|
||||
roleId,
|
||||
objectMetadataId,
|
||||
}: SettingsRolePermissionsObjectLevelObjectFormProps) => {
|
||||
const settingsDraftRole = useRecoilValue(
|
||||
settingsDraftRoleFamilyState(roleId),
|
||||
);
|
||||
|
||||
const objectMetadata = useObjectMetadataItemById({
|
||||
objectId: objectMetadataId,
|
||||
});
|
||||
|
||||
const objectMetadataItem = objectMetadata.objectMetadataItem;
|
||||
|
||||
const objectTypeLabel = getObjectTypeLabel(objectMetadataItem);
|
||||
|
||||
return (
|
||||
<SubMenuTopBarContainer
|
||||
title={
|
||||
<StyledTitleContainer>
|
||||
<H3Title title={objectMetadataItem.labelPlural} />
|
||||
<StyledObjectTypeTag objectTypeLabel={objectTypeLabel} />
|
||||
</StyledTitleContainer>
|
||||
}
|
||||
links={[
|
||||
{
|
||||
children: 'Workspace',
|
||||
href: getSettingsPath(SettingsPath.Workspace),
|
||||
},
|
||||
{
|
||||
children: 'Roles',
|
||||
href: getSettingsPath(SettingsPath.Roles),
|
||||
},
|
||||
{
|
||||
children: settingsDraftRole.label,
|
||||
href: getSettingsPath(SettingsPath.RoleDetail, {
|
||||
roleId,
|
||||
}),
|
||||
},
|
||||
{
|
||||
children: `Permissions · ${objectMetadataItem.labelSingular}`,
|
||||
},
|
||||
]}
|
||||
actionButton={
|
||||
<Button
|
||||
title={t`Back`}
|
||||
variant="primary"
|
||||
size="small"
|
||||
accent="blue"
|
||||
to={getSettingsPath(SettingsPath.RoleDetail, {
|
||||
roleId,
|
||||
})}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<SettingsPageContainer>
|
||||
<SettingsRolePermissionsObjectLevelObjectFormObjectLevel
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
roleId={roleId}
|
||||
/>
|
||||
</SettingsPageContainer>
|
||||
</SubMenuTopBarContainer>
|
||||
);
|
||||
};
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SettingsRolePermissionsObjectLevelObjectFormObjectLevelHeader } from '@/settings/roles/role-permissions/object-level-permissions/object-form/components/SettingsRolePermissionsObjectLevelObjectFormObjectLevelHeader';
|
||||
import { SettingsRolePermissionsObjectsTableRow } from '@/settings/roles/role-permissions/objects-permissions/components/SettingsRolePermissionsObjectsTableRow';
|
||||
import { SettingsRolePermissionsObjectPermission } from '@/settings/roles/role-permissions/objects-permissions/types/SettingsRolePermissionsObjectPermission';
|
||||
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { H2Title } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
|
||||
const StyledTable = styled.div`
|
||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
`;
|
||||
|
||||
const StyledTableRows = styled.div`
|
||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
type SettingsRolePermissionsObjectLevelObjectFormObjectLevelProps = {
|
||||
roleId: string;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
};
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelObjectFormObjectLevel = ({
|
||||
roleId,
|
||||
objectMetadataItem,
|
||||
}: SettingsRolePermissionsObjectLevelObjectFormObjectLevelProps) => {
|
||||
const settingsDraftRole = useRecoilValue(
|
||||
settingsDraftRoleFamilyState(roleId),
|
||||
);
|
||||
|
||||
const settingsDraftRoleObjectPermissions =
|
||||
settingsDraftRole.objectPermissions?.find(
|
||||
(permission) => permission.objectMetadataId === objectMetadataItem.id,
|
||||
);
|
||||
|
||||
if (!settingsDraftRoleObjectPermissions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const objectLabel = objectMetadataItem.labelPlural;
|
||||
|
||||
const objectPermissionsConfig: SettingsRolePermissionsObjectPermission[] = [
|
||||
{
|
||||
key: 'canReadObjectRecords',
|
||||
label: t`See Records on ${objectLabel}`,
|
||||
value: settingsDraftRoleObjectPermissions.canReadObjectRecords,
|
||||
setValue: (_value: boolean) => {
|
||||
// TODO: Implement
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'canUpdateObjectRecords',
|
||||
label: t`Edit Records on ${objectLabel}`,
|
||||
value: settingsDraftRoleObjectPermissions.canUpdateObjectRecords,
|
||||
setValue: (_value: boolean) => {
|
||||
// TODO: Implement
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'canSoftDeleteObjectRecords',
|
||||
label: t`Delete Records on ${objectLabel}`,
|
||||
value: settingsDraftRoleObjectPermissions.canSoftDeleteObjectRecords,
|
||||
setValue: (_value: boolean) => {
|
||||
// TODO: Implement
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'canDestroyObjectRecords',
|
||||
label: t`Destroy Records on ${objectLabel}`,
|
||||
value: settingsDraftRoleObjectPermissions.canDestroyObjectRecords,
|
||||
setValue: (_value: boolean) => {
|
||||
// TODO: Implement
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<H2Title
|
||||
title={t`Object-Level Permissions`}
|
||||
description={t`Ability to interact with this specific object`}
|
||||
/>
|
||||
<StyledTable>
|
||||
<SettingsRolePermissionsObjectLevelObjectFormObjectLevelHeader />
|
||||
<StyledTableRows>
|
||||
{objectPermissionsConfig.map((permission) => (
|
||||
<SettingsRolePermissionsObjectsTableRow
|
||||
key={permission.key}
|
||||
permission={permission}
|
||||
isEditable={settingsDraftRole.isEditable}
|
||||
/>
|
||||
))}
|
||||
</StyledTableRows>
|
||||
</StyledTable>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export const SettingsRolePermissionsObjectLevelObjectFormObjectLevelHeader =
|
||||
() => (
|
||||
<TableRow gridAutoColumns="1fr 24px">
|
||||
<TableHeader>{t`Name`}</TableHeader>
|
||||
<TableHeader aria-label={t`Actions`}></TableHeader>
|
||||
</TableRow>
|
||||
);
|
||||
Reference in New Issue
Block a user