feat: auto-increment role names to avoid uniqueness conflicts on create and copy

This commit is contained in:
Jannis Braun
2026-03-21 23:31:35 +01:00
parent a9a676bc70
commit b4b22faf55
@@ -54,6 +54,18 @@ const PRESET_COLORS = [
'#fbbf24', '#fda4af', '#f87171', '#60a5fa', '#34d399', '#fbbf24', '#fda4af', '#f87171', '#60a5fa', '#34d399',
]; ];
/** Auto-increment a base name ("Foo" → "Foo 2" → "Foo 3") to avoid uniqueness conflicts. */
function getUniqueRoleName(baseName: string, existingRoles: Role[]): string {
const existingNames = new Set(existingRoles.map((r) => r.name.toLowerCase()));
let candidateName = baseName;
let counter = 2;
while (existingNames.has(candidateName.toLowerCase())) {
candidateName = `${baseName} ${counter}`;
counter++;
}
return candidateName;
}
// ─── Component ────────────────────────────────────────────────────────────── // ─── Component ──────────────────────────────────────────────────────────────
interface RolesPanelProps { interface RolesPanelProps {
@@ -81,7 +93,8 @@ export function RolesPanel({ spaceId }: RolesPanelProps) {
setCreating(true); setCreating(true);
setError(''); setError('');
try { try {
const newRole = await api.roles.create(spaceId, { name: 'new role' }); const uniqueName = getUniqueRoleName('new role', roles);
const newRole = await api.roles.create(spaceId, { name: uniqueName });
await loadSpaceDetail(spaceId); await loadSpaceDetail(spaceId);
setEditingRoleId(newRole.id); setEditingRoleId(newRole.id);
} catch (err) { } catch (err) {
@@ -275,8 +288,9 @@ function RoleEditView({ role, spaceId, onBack, onDeleted, onCopied }: RoleEditVi
setCopying(true); setCopying(true);
setSaveError(''); setSaveError('');
try { try {
const uniqueName = getUniqueRoleName(`Copy of ${role.name}`, roles);
const newRole = await api.roles.create(spaceId, { const newRole = await api.roles.create(spaceId, {
name: `Copy of ${role.name}`, name: uniqueName,
color: role.color, color: role.color,
permissions: role.permissions ?? undefined, permissions: role.permissions ?? undefined,
}); });