Fixed frozen org editor modal

This commit is contained in:
2026-10-25 12:50:35 +02:00
parent 78d147b002
commit 31d775c917
@@ -62,7 +62,6 @@ import {
assignUserRole, assignUserRole,
getSystemRoles, getSystemRoles,
getCurrentUserTenantId, getCurrentUserTenantId,
getTenantUsers,
notifyNewUserCreated, notifyNewUserCreated,
} from '../services/api'; } from '../services/api';
import { Modal } from '../components/ui/Modal'; import { Modal } from '../components/ui/Modal';
@@ -78,8 +77,6 @@ import { FundingInstrumentsSection, InstructionsSection } from '../components/go
import { RulesSection } from '../components/governance/RulesSection'; import { RulesSection } from '../components/governance/RulesSection';
import { import {
Organisation, Organisation,
TenantOrganisation,
TenantUser,
Portfolio, Portfolio,
Programme, Programme,
Instrument, Instrument,
@@ -268,42 +265,8 @@ export const GovernancePage: React.FC = () => {
}); });
}, [usersDirectory]); }, [usersDirectory]);
const isAdmin =
Boolean(isUnrestricted) ||
(Array.isArray(roles) && roles.some((r) => r.toLowerCase().trim() === 'admin')) ||
(claims?.role && String(claims.role).toLowerCase().includes('admin'));
const orgTenantId = editingOrg?.tenantId || tenantId || getCurrentUserTenantId() || 1;
const { data: tenantUsersList = [] } = useQuery<TenantUser[]>({
queryKey: ['tenant-users', orgTenantId],
queryFn: () => getTenantUsers(orgTenantId),
enabled: isOrgModalOpen && !!editingOrg && !isAdmin,
});
useEffect(() => {
if (tenantUsersList.length > 0) {
tenantUsersList.forEach((tu) => {
if (tu.userId && tu.user?.email) {
registerUserEmail(tu.userId, tu.user.email);
}
});
}
}, [tenantUsersList]);
const modalExecutiveUsers = React.useMemo(() => { const modalExecutiveUsers = React.useMemo(() => {
const list: User[] = []; const list: User[] = [...executiveAndManagerUsers];
const seenIds = new Set<string>();
const addCandidate = (u?: User | null) => {
if (!u || !u.id) return;
const key = String(u.id).toLowerCase();
if (seenIds.has(key)) return;
seenIds.add(key);
list.push(u);
};
// 1. Always include the organisation's linked user so the select option exists and selects immediately
const linkedUserId = const linkedUserId =
editingOrg?.userId || editingOrg?.userId ||
editingOrg?.UserId || editingOrg?.UserId ||
@@ -312,44 +275,28 @@ export const GovernancePage: React.FC = () => {
''; '';
if (linkedUserId) { if (linkedUserId) {
const resolvedEmail = getUserEmail(linkedUserId); const linkedStr = String(linkedUserId).toLowerCase();
const matched = usersDirectory.find( const alreadyIncluded = list.some((u) => u.id && String(u.id).toLowerCase() === linkedStr);
(u) => u.id && String(u.id).toLowerCase() === String(linkedUserId).toLowerCase() if (!alreadyIncluded) {
); const inDirectory = usersDirectory.find((u) => u.id && String(u.id).toLowerCase() === linkedStr);
addCandidate({ if (inDirectory) {
id: linkedUserId, list.unshift(inDirectory);
email: matched?.email || (resolvedEmail !== '—' && resolvedEmail ? resolvedEmail : linkedUserId),
role: matched?.role || 'Executive',
status: ActivityStatus.Active,
lastLoginAt: null,
});
}
// 2. Load Executive role users: Admin sees all executives across tenants; normal tenant user focuses on tenantusers
if (isAdmin) {
usersDirectory
.filter((u) => String(u.role || '').toLowerCase() === 'executive')
.forEach(addCandidate);
} else { } else {
tenantUsersList const email = getUserEmail(linkedUserId);
.filter((tu) => String(tu.user?.role || '').toLowerCase() === 'executive') const hasRealEmail = email && email !== '—' && email.includes('@') && email !== String(linkedUserId);
.forEach((tu) => { list.unshift({
if (tu.user) { id: String(linkedUserId),
addCandidate(tu.user); email: hasRealEmail ? email : String(linkedUserId),
} else if (tu.userId) {
addCandidate({
id: tu.userId,
email: getUserEmail(tu.userId),
role: 'Executive', role: 'Executive',
status: ActivityStatus.Active, status: ActivityStatus.Active,
lastLoginAt: null, lastLoginAt: null,
}); });
} }
}); }
} }
return list; return list;
}, [isAdmin, usersDirectory, tenantUsersList, editingOrg?.id, editingOrg?.userId]); }, [executiveAndManagerUsers, usersDirectory, editingOrg?.id, editingOrg?.userId, editingOrg?.organisationUser]);
// Quick Add Executive User Subform state // Quick Add Executive User Subform state
const [isQuickAddUserOpen, setIsQuickAddUserOpen] = useState(false); const [isQuickAddUserOpen, setIsQuickAddUserOpen] = useState(false);
@@ -828,22 +775,28 @@ export const GovernancePage: React.FC = () => {
org.createdBy || org.createdBy ||
''; '';
let selectedUserId = '';
if (targetUserId) { if (targetUserId) {
const email = getUserEmail(targetUserId); const targetStr = String(targetUserId).toLowerCase();
if (email && email !== '—') { const matchedUser = usersDirectory.find(
registerUserEmail(targetUserId, email);
}
}
const matchedUser = targetUserId
? usersDirectory.find(
(u) => (u) =>
(u.id && String(u.id).toLowerCase() === String(targetUserId).toLowerCase()) || (u.id && String(u.id).toLowerCase() === targetStr) ||
(u.email && getUserEmail(targetUserId) && u.email.toLowerCase() === getUserEmail(targetUserId).toLowerCase()) (u.email && u.email.toLowerCase() === targetStr)
) );
: null;
const selectedUserId = matchedUser?.id || targetUserId || ''; if (matchedUser) {
selectedUserId = matchedUser.id;
if (matchedUser.email) {
registerUserEmail(matchedUser.id, matchedUser.email);
}
} else {
selectedUserId = String(targetUserId);
const email = getUserEmail(targetUserId);
if (email && email !== '—' && email.includes('@')) {
registerUserEmail(selectedUserId, email);
}
}
}
orgForm.reset({ orgForm.reset({
name: org.name || '', name: org.name || '',
@@ -1812,7 +1765,7 @@ export const GovernancePage: React.FC = () => {
className="w-full px-3 py-2 text-xs border border-slate-700/80 rounded-xl focus:outline-none focus:ring-1 focus:ring-blue-500 bg-[#090d16] text-white font-medium" className="w-full px-3 py-2 text-xs border border-slate-700/80 rounded-xl focus:outline-none focus:ring-1 focus:ring-blue-500 bg-[#090d16] text-white font-medium"
> >
<option value="">-- Select linked executive or manager account --</option> <option value="">-- Select linked executive or manager account --</option>
{(editingOrg ? modalExecutiveUsers : executiveAndManagerUsers).map((u) => ( {modalExecutiveUsers.map((u) => (
<option key={u.id} value={u.id}> <option key={u.id} value={u.id}>
{u.email || u.id} ({u.role || 'Executive'}) {u.email || u.id} ({u.role || 'Executive'})
</option> </option>