783fe8d387
## 🐛 Issues Fixed ### 1. Role Editing Not Working for New Agents When creating a new agent and then creating a role for it, the role permissions appeared as non-editable. This was caused by: - In create mode, `agentId = ''` (empty string from `useParams`) - Empty string is **falsy** but `isDefined('')` returns **true** - This caused incorrect behavior in role exclusivity checks and API calls ### 2. Missing Role Data Loading The agent form wasn't loading role data needed for permission editing because it was missing the `SettingsRolesQueryEffect` component. ### 3. Navigation Conflicts The `useSaveDraftRoleToDB` hook contained navigation logic that caused conflicts when used from different contexts (role detail page vs agent form). ### 4. Linting Errors Unused `useIcons` import in `SettingsAgentRoleTab.tsx`. --- ## 🔧 Changes Made ### Agent Role Tab (`SettingsAgentRoleTab.tsx`) - ✅ Use `isNonEmptyString(agentId)` to validate agentId (follows codebase patterns) - ✅ Improved role exclusivity logic to handle both create and edit modes: - **Edit mode**: Role must be assigned exclusively to this agent - **Create mode**: Role must not be assigned to anyone yet - ✅ Only call `assignRoleToAgent` when a valid agentId exists - ✅ Pass `undefined` instead of empty string for `fromAgentId` prop ### Role Hook (`useSaveDraftRoleToDB.ts`) - ✅ Removed navigation logic from the hook (better separation of concerns) - ✅ Removed `useNavigateSettings` and `SettingsPath` dependencies - ✅ Hook now only handles data persistence, not navigation ### Role Component (`SettingsRole.tsx`) - ✅ Added navigation after successful role creation in create mode - ✅ Navigation now handled by the component using the hook ### Agent Form (`SettingsAgentForm.tsx`) - ✅ Added `SettingsRolesQueryEffect` to ensure role data is loaded - ✅ Agent form handles its own navigation after save --- ## ✅ Testing Scenarios All these scenarios now work correctly: 1. ✅ Create new agent → Create role → Edit permissions → Save agent 2. ✅ Edit existing agent → Create role → Edit permissions → Save 3. ✅ Edit existing agent → Try to edit shared role (shows warning message) 4. ✅ Navigate to object-level permissions from agent form with proper breadcrumbs --- ## 📝 Technical Details ### Root Cause Analysis The main issue was that empty string was being treated differently in different checks: - `agentId &&` → evaluates to `false` (empty string is falsy) - `isDefined(agentId)` → returns `true` (empty string is defined) This inconsistency caused the role to appear as non-editable and attempted invalid API calls. ### Solution Used `isNonEmptyString()` from `@sniptt/guards` which properly checks both that the value is defined AND not empty, following codebase conventions. --- ## 🎯 Impact - Fixes critical bug preventing role permission configuration for new agents - Improves code quality with better separation of concerns - Makes navigation logic more predictable and maintainable - Follows codebase patterns and guidelines
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
|
import { SettingsRolesQueryEffect } from '@/settings/roles/components/SettingsRolesQueryEffect';
|
|
import { SettingsRolePermissionsObjectLevelObjectPicker } from '@/settings/roles/role-permissions/object-level-permissions/components/SettingsRolePermissionsObjectLevelObjectPicker';
|
|
import { settingsDraftRoleFamilyState } from '@/settings/roles/states/settingsDraftRoleFamilyState';
|
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
|
import { t } from '@lingui/core/macro';
|
|
import { Navigate, useParams, useSearchParams } from 'react-router-dom';
|
|
import { useRecoilValue } from 'recoil';
|
|
import { SettingsPath } from 'twenty-shared/types';
|
|
import { getSettingsPath, isDefined } from 'twenty-shared/utils';
|
|
import { useFindOneAgentQuery } from '~/generated-metadata/graphql';
|
|
|
|
export const SettingsRoleAddObjectLevel = () => {
|
|
const { roleId } = useParams();
|
|
const [searchParams] = useSearchParams();
|
|
const fromAgentId = searchParams.get('fromAgent');
|
|
|
|
const settingsDraftRole = useRecoilValue(
|
|
settingsDraftRoleFamilyState(roleId ?? ''),
|
|
);
|
|
|
|
const { data: agentData } = useFindOneAgentQuery({
|
|
variables: { id: fromAgentId || '' },
|
|
skip: !fromAgentId,
|
|
});
|
|
|
|
const agent = agentData?.findOneAgent;
|
|
|
|
if (!roleId) {
|
|
return <Navigate to={getSettingsPath(SettingsPath.Roles)} />;
|
|
}
|
|
|
|
const breadcrumbLinks =
|
|
fromAgentId && isDefined(agent)
|
|
? [
|
|
{
|
|
children: t`Workspace`,
|
|
href: getSettingsPath(SettingsPath.Workspace),
|
|
},
|
|
{
|
|
children: t`AI`,
|
|
href: getSettingsPath(SettingsPath.AI),
|
|
},
|
|
{
|
|
children: agent.label,
|
|
href: getSettingsPath(SettingsPath.AIAgentDetail, {
|
|
agentId: agent.id,
|
|
}),
|
|
},
|
|
{
|
|
children: t`Add object permission`,
|
|
},
|
|
]
|
|
: [
|
|
{ children: t`Roles`, href: getSettingsPath(SettingsPath.Roles) },
|
|
{
|
|
children: settingsDraftRole.label ?? '',
|
|
href: getSettingsPath(SettingsPath.RoleDetail, { roleId }),
|
|
},
|
|
{
|
|
children: t`Add object permission`,
|
|
href: getSettingsPath(SettingsPath.RoleAddObjectLevel, { roleId }),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<SettingsRolesQueryEffect />
|
|
<SubMenuTopBarContainer
|
|
title={t`1. Select an object`}
|
|
links={breadcrumbLinks}
|
|
>
|
|
<SettingsPageContainer>
|
|
<SettingsRolePermissionsObjectLevelObjectPicker roleId={roleId} />
|
|
</SettingsPageContainer>
|
|
</SubMenuTopBarContainer>
|
|
</>
|
|
);
|
|
};
|