From fb0ef2fa82e0c7758a605ab7158697adec9c0ac2 Mon Sep 17 00:00:00 2001 From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Date: Thu, 12 Feb 2026 11:48:05 +0530 Subject: [PATCH] chore: 7114 improve ux in team settings (#7237) Co-authored-by: Johannes --- apps/web/i18n.lock | 2 - apps/web/locales/de-DE.json | 2 - apps/web/locales/en-US.json | 2 - apps/web/locales/es-ES.json | 2 - apps/web/locales/fr-FR.json | 2 - apps/web/locales/hu-HU.json | 2 - apps/web/locales/ja-JP.json | 2 - apps/web/locales/nl-NL.json | 2 - apps/web/locales/pt-BR.json | 2 - apps/web/locales/pt-PT.json | 2 - apps/web/locales/ro-RO.json | 2 - apps/web/locales/ru-RU.json | 2 - apps/web/locales/sv-SE.json | 2 - apps/web/locales/zh-Hans-CN.json | 2 - apps/web/locales/zh-Hant-TW.json | 2 - .../components/team-settings/member-row.tsx | 137 ++++++++++ .../team-settings/team-settings-modal.tsx | 237 +++--------------- .../team-settings/workspace-row.tsx | 115 +++++++++ .../ee/teams/team-list/lib/team.test.ts | 57 ++++- .../edit-memberships/edit-memberships.tsx | 14 +- .../edit-memberships/member-actions.tsx | 3 +- .../edit-memberships/members-info.tsx | 28 ++- .../ui/components/multi-select/index.tsx | 41 ++- apps/web/playwright/organization.spec.ts | 8 +- 24 files changed, 395 insertions(+), 275 deletions(-) create mode 100644 apps/web/modules/ee/teams/team-list/components/team-settings/member-row.tsx create mode 100644 apps/web/modules/ee/teams/team-list/components/team-settings/workspace-row.tsx diff --git a/apps/web/i18n.lock b/apps/web/i18n.lock index 389f30c510..a5432d016b 100644 --- a/apps/web/i18n.lock +++ b/apps/web/i18n.lock @@ -1038,8 +1038,6 @@ checksums: environments/settings/teams/please_fill_all_workspace_fields: 190fc5d3c63cc5ec49d77f587e619ed8 environments/settings/teams/read: 2494ca23d10e5b6381eb271aceeb5270 environments/settings/teams/read_write: 278a90dade128198d4c93ac00c345320 - environments/settings/teams/select_member: 7f4a38312aabbbe3fe92756b57bd5d75 - environments/settings/teams/select_workspace: 0ad989c23616c6a04faf23d9e63ed3f3 environments/settings/teams/team_admin: 5df68214685738029af678ae1d5912bb environments/settings/teams/team_created_successfully: 5b0cc007e18053508fdebc9545cc2c05 environments/settings/teams/team_deleted_successfully: d0729ad8d982cc5d542f89291bf57c50 diff --git a/apps/web/locales/de-DE.json b/apps/web/locales/de-DE.json index 8c8cf7f99b..1035014e84 100644 --- a/apps/web/locales/de-DE.json +++ b/apps/web/locales/de-DE.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Bitte füllen Sie alle Felder aus, um einen neuen Workspace hinzuzufügen.", "read": "Lesen", "read_write": "Lesen & Schreiben", - "select_member": "Mitglied auswählen", - "select_workspace": "Workspace auswählen", "team_admin": "Team-Admin", "team_created_successfully": "Team erfolgreich erstellt.", "team_deleted_successfully": "Team erfolgreich gelöscht.", diff --git a/apps/web/locales/en-US.json b/apps/web/locales/en-US.json index dedf2289d6..6ce990bac7 100644 --- a/apps/web/locales/en-US.json +++ b/apps/web/locales/en-US.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Please fill all the fields to add a new workspace.", "read": "Read", "read_write": "Read & Write", - "select_member": "Select member", - "select_workspace": "Select workspace", "team_admin": "Team Admin", "team_created_successfully": "Team created successfully", "team_deleted_successfully": "Team deleted successfully", diff --git a/apps/web/locales/es-ES.json b/apps/web/locales/es-ES.json index cc88559c40..839ab6c4e2 100644 --- a/apps/web/locales/es-ES.json +++ b/apps/web/locales/es-ES.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Por favor, rellena todos los campos para añadir un proyecto nuevo.", "read": "Lectura", "read_write": "Lectura y escritura", - "select_member": "Seleccionar miembro", - "select_workspace": "Seleccionar proyecto", "team_admin": "Administrador de equipo", "team_created_successfully": "Equipo creado con éxito.", "team_deleted_successfully": "Equipo eliminado correctamente.", diff --git a/apps/web/locales/fr-FR.json b/apps/web/locales/fr-FR.json index 356d4c2854..71c4d4bf7d 100644 --- a/apps/web/locales/fr-FR.json +++ b/apps/web/locales/fr-FR.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Veuillez remplir tous les champs pour ajouter un nouvel espace de travail.", "read": "Lire", "read_write": "Lire et Écrire", - "select_member": "Sélectionner membre", - "select_workspace": "Sélectionner un espace de travail", "team_admin": "Administrateur d'équipe", "team_created_successfully": "Équipe créée avec succès.", "team_deleted_successfully": "Équipe supprimée avec succès.", diff --git a/apps/web/locales/hu-HU.json b/apps/web/locales/hu-HU.json index f99cc09fe5..d2db0bf728 100644 --- a/apps/web/locales/hu-HU.json +++ b/apps/web/locales/hu-HU.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Töltse ki az összes mezőt egy új munkaterület hozzáadásához.", "read": "Olvasás", "read_write": "Olvasás és írás", - "select_member": "Tag kiválasztása", - "select_workspace": "Munkaterület kiválasztása", "team_admin": "Csapatadminisztrátor", "team_created_successfully": "A csapat sikeresen létrehozva", "team_deleted_successfully": "A csapat sikeresen törölve", diff --git a/apps/web/locales/ja-JP.json b/apps/web/locales/ja-JP.json index 721c881edb..95293c7071 100644 --- a/apps/web/locales/ja-JP.json +++ b/apps/web/locales/ja-JP.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "新しいワークスペースを追加するには、すべてのフィールドを入力してください。", "read": "読み取り", "read_write": "読み書き", - "select_member": "メンバーを選択", - "select_workspace": "ワークスペースを選択", "team_admin": "チーム管理者", "team_created_successfully": "チームを正常に作成しました。", "team_deleted_successfully": "チームを正常に削除しました。", diff --git a/apps/web/locales/nl-NL.json b/apps/web/locales/nl-NL.json index 15094c440d..13157a8647 100644 --- a/apps/web/locales/nl-NL.json +++ b/apps/web/locales/nl-NL.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Vul alle velden in om een nieuwe werkruimte toe te voegen.", "read": "Lezen", "read_write": "Lezen en schrijven", - "select_member": "Selecteer lid", - "select_workspace": "Selecteer werkruimte", "team_admin": "Teambeheerder", "team_created_successfully": "Team succesvol aangemaakt.", "team_deleted_successfully": "Team succesvol verwijderd.", diff --git a/apps/web/locales/pt-BR.json b/apps/web/locales/pt-BR.json index bde99ae041..3942d26466 100644 --- a/apps/web/locales/pt-BR.json +++ b/apps/web/locales/pt-BR.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Preencha todos os campos para adicionar um novo espaço de trabalho.", "read": "Leitura", "read_write": "Leitura & Escrita", - "select_member": "Selecionar membro", - "select_workspace": "Selecionar espaço de trabalho", "team_admin": "Administrador da equipe", "team_created_successfully": "Equipe criada com sucesso.", "team_deleted_successfully": "Equipe excluída com sucesso.", diff --git a/apps/web/locales/pt-PT.json b/apps/web/locales/pt-PT.json index 144109ca8f..12fb3dfc3c 100644 --- a/apps/web/locales/pt-PT.json +++ b/apps/web/locales/pt-PT.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Preencha todos os campos para adicionar um novo espaço de trabalho.", "read": "Ler", "read_write": "Ler e Escrever", - "select_member": "Selecionar membro", - "select_workspace": "Selecionar espaço de trabalho", "team_admin": "Administrador da Equipa", "team_created_successfully": "Equipa criada com sucesso.", "team_deleted_successfully": "Equipa eliminada com sucesso.", diff --git a/apps/web/locales/ro-RO.json b/apps/web/locales/ro-RO.json index 54fcbfecfb..c5125e74e4 100644 --- a/apps/web/locales/ro-RO.json +++ b/apps/web/locales/ro-RO.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Vă rugăm să completați toate câmpurile pentru a adăuga un nou spațiu de lucru.", "read": "Citește", "read_write": "Citire & Scriere", - "select_member": "Selectează membrul", - "select_workspace": "Selectați spațiul de lucru", "team_admin": "Administrator Echipe", "team_created_successfully": "Echipă creată cu succes", "team_deleted_successfully": "Echipă ștearsă cu succes.", diff --git a/apps/web/locales/ru-RU.json b/apps/web/locales/ru-RU.json index ac65d731c2..97bb25c90a 100644 --- a/apps/web/locales/ru-RU.json +++ b/apps/web/locales/ru-RU.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Пожалуйста, заполните все поля для добавления нового рабочего пространства.", "read": "Чтение", "read_write": "Чтение и запись", - "select_member": "Выберите участника", - "select_workspace": "Выберите рабочее пространство", "team_admin": "Администратор команды", "team_created_successfully": "Команда успешно создана.", "team_deleted_successfully": "Команда успешно удалена.", diff --git a/apps/web/locales/sv-SE.json b/apps/web/locales/sv-SE.json index 134f41c9b6..53c5be0d1c 100644 --- a/apps/web/locales/sv-SE.json +++ b/apps/web/locales/sv-SE.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "Fyll i alla fält för att lägga till en ny arbetsyta.", "read": "Läs", "read_write": "Läs och skriv", - "select_member": "Välj medlem", - "select_workspace": "Välj arbetsyta", "team_admin": "Teamadministratör", "team_created_successfully": "Team skapat.", "team_deleted_successfully": "Team borttaget.", diff --git a/apps/web/locales/zh-Hans-CN.json b/apps/web/locales/zh-Hans-CN.json index cf4f8bd989..a41eda24d3 100644 --- a/apps/web/locales/zh-Hans-CN.json +++ b/apps/web/locales/zh-Hans-CN.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "请填写所有字段以添加新工作区。", "read": "阅读", "read_write": "读 & 写", - "select_member": "选择成员", - "select_workspace": "选择工作区", "team_admin": "团队管理员", "team_created_successfully": "团队 创建 成功", "team_deleted_successfully": "团队 删除 成功", diff --git a/apps/web/locales/zh-Hant-TW.json b/apps/web/locales/zh-Hant-TW.json index 3a2066cfa5..11f4084c2a 100644 --- a/apps/web/locales/zh-Hant-TW.json +++ b/apps/web/locales/zh-Hant-TW.json @@ -1105,8 +1105,6 @@ "please_fill_all_workspace_fields": "請填寫所有欄位以新增工作區。", "read": "讀取", "read_write": "讀取和寫入", - "select_member": "選擇成員", - "select_workspace": "選擇工作區", "team_admin": "團隊管理員", "team_created_successfully": "團隊已成功建立。", "team_deleted_successfully": "團隊已成功刪除。", diff --git a/apps/web/modules/ee/teams/team-list/components/team-settings/member-row.tsx b/apps/web/modules/ee/teams/team-list/components/team-settings/member-row.tsx new file mode 100644 index 0000000000..09c6013666 --- /dev/null +++ b/apps/web/modules/ee/teams/team-list/components/team-settings/member-row.tsx @@ -0,0 +1,137 @@ +"use client"; + +import { XIcon } from "lucide-react"; +import { Control } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { + TOrganizationMember, + TTeamRole, + TTeamSettingsFormSchema, + ZTeamRole, +} from "@/modules/ee/teams/team-list/types/team"; +import { Button } from "@/modules/ui/components/button"; +import { FormError, FormField, FormItem } from "@/modules/ui/components/form"; +import { InputCombobox } from "@/modules/ui/components/input-combo-box"; +import { TooltipRenderer } from "@/modules/ui/components/tooltip"; + +export interface MemberRowProps { + index: number; + member: { userId: string; role: TTeamRole }; + memberOpts: { value: string; label: string }[]; + control: Control; + orgMembers: TOrganizationMember[]; + watchMembers: { userId: string; role: TTeamRole }[]; + initialMemberIds: Set; + isOwnerOrManager: boolean; + isTeamAdminMember: boolean; + isTeamContributorMember: boolean; + currentUserId: string; + onMemberSelectionChange: (index: number, userId: string) => void; + onRemoveMember: (index: number) => void; + memberCount: number; +} + +export function MemberRow(props: Readonly) { + const { + index, + member, + memberOpts, + control, + orgMembers, + watchMembers, + initialMemberIds, + isOwnerOrManager, + isTeamAdminMember, + isTeamContributorMember, + currentUserId, + onMemberSelectionChange, + onRemoveMember, + memberCount, + } = props; + const { t } = useTranslation(); + const chosenMember = orgMembers.find((m) => m.id === watchMembers[index]?.userId); + const canEditWhenNoMember = isOwnerOrManager || isTeamAdminMember; + const isRoleSelectDisabled = + chosenMember === undefined + ? !canEditWhenNoMember + : chosenMember.role === "owner" || + chosenMember.role === "manager" || + isTeamContributorMember || + chosenMember.id === currentUserId; + + return ( +
+ { + const isExistingMember = member.userId && initialMemberIds.has(member.userId); + const isSelectDisabled = isExistingMember || (!isOwnerOrManager && !isTeamAdminMember); + + return ( + +
+ { + const value = typeof val === "string" ? val : ""; + field.onChange(value); + onMemberSelectionChange(index, value); + }} + showSearch + searchPlaceholder={t("common.search")} + comboboxClasses="flex-1 min-w-0 w-full" + emptyDropdownText={t("environments.surveys.edit.no_option_found")} + /> +
+ {error?.message && {error.message}} +
+ ); + }} + /> + { + const roleOptions = [ + { value: ZTeamRole.enum.admin, label: t("environments.settings.teams.team_admin") }, + { + value: ZTeamRole.enum.contributor, + label: t("environments.settings.teams.contributor"), + }, + ]; + + return ( + +
+ field.onChange(val)} + showSearch={false} + comboboxClasses="flex-1 min-w-0 w-full" + /> +
+
+ ); + }} + /> + {memberCount > 1 && ( + + + + )} +
+ ); +} diff --git a/apps/web/modules/ee/teams/team-list/components/team-settings/team-settings-modal.tsx b/apps/web/modules/ee/teams/team-list/components/team-settings/team-settings-modal.tsx index 1fb6f5279a..cdff0ec6fb 100644 --- a/apps/web/modules/ee/teams/team-list/components/team-settings/team-settings-modal.tsx +++ b/apps/web/modules/ee/teams/team-list/components/team-settings/team-settings-modal.tsx @@ -1,7 +1,7 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { PlusIcon, Trash2Icon, XIcon } from "lucide-react"; +import { PlusIcon } from "lucide-react"; import { useRouter } from "next/navigation"; import { useMemo } from "react"; import { FormProvider, SubmitHandler, useForm, useWatch } from "react-hook-form"; @@ -13,6 +13,8 @@ import { getFormattedErrorMessage } from "@/lib/utils/helper"; import { ZTeamPermission } from "@/modules/ee/teams/project-teams/types/team"; import { updateTeamDetailsAction } from "@/modules/ee/teams/team-list/actions"; import { DeleteTeam } from "@/modules/ee/teams/team-list/components/team-settings/delete-team"; +import { MemberRow } from "@/modules/ee/teams/team-list/components/team-settings/member-row"; +import { WorkspaceRow } from "@/modules/ee/teams/team-list/components/team-settings/workspace-row"; import { TOrganizationProject } from "@/modules/ee/teams/team-list/types/project"; import { TOrganizationMember, @@ -36,13 +38,6 @@ import { import { FormControl, FormError, FormField, FormItem, FormLabel } from "@/modules/ui/components/form"; import { IdBadge } from "@/modules/ui/components/id-badge"; import { Input } from "@/modules/ui/components/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/modules/ui/components/select"; import { TooltipRenderer } from "@/modules/ui/components/tooltip"; import { Muted } from "@/modules/ui/components/typography"; @@ -187,14 +182,16 @@ export const TeamSettingsModal = ({ const currentMemberId = watchMembers[index]?.userId; return orgMembers .filter((om) => !selectedMemberIds.includes(om?.id) || om?.id === currentMemberId) - .map((om) => ({ label: om?.name, value: om?.id })); + .map((om) => ({ label: om?.name ?? "", value: om?.id })) + .sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" })); }; const getProjectOptionsForIndex = (index: number) => { const currentProjectId = watchProjects[index]?.projectId; return orgProjects .filter((op) => !selectedProjectIds.includes(op?.id) || op?.id === currentProjectId) - .map((op) => ({ label: op?.name, value: op?.id })); + .map((op) => ({ label: op?.name ?? "", value: op?.id })) + .sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" })); }; const handleMemberSelectionChange = (index: number, userId: string) => { @@ -262,110 +259,25 @@ export const TeamSettingsModal = ({ render={({ fieldState: { error } }) => (
- {watchMembers.map((member, index) => { - const memberOpts = getMemberOptionsForIndex(index); - return ( -
- { - // Disable user select for existing members (can only remove or change role) - const isExistingMember = - member.userId && initialMemberIds.has(member.userId); - const isSelectDisabled = - isExistingMember || (!isOwnerOrManager && !isTeamAdminMember); - - return ( - - - {error?.message && ( - {error.message} - )} - - ); - }} - /> - - ( - - - - )} - /> - - {/* Delete Button for Member */} - {watchMembers.length > 1 && ( - - - - )} -
- ); - })} + {watchMembers.map((member, index) => ( + + ))}
{error?.root?.message && ( {error.root.message} @@ -411,90 +323,19 @@ export const TeamSettingsModal = ({ render={({ fieldState: { error } }) => (
- {watchProjects.map((project, index) => { - const projectOpts = getProjectOptionsForIndex(index); - return ( -
- { - // Disable project select for existing projects (can only remove or change permission) - const isExistingProject = - project.projectId && initialProjectIds.has(project.projectId); - const isSelectDisabled = isExistingProject || !isOwnerOrManager; - - return ( - - - {error?.message && ( - {error.message} - )} - - ); - }} - /> - - ( - - - - )} - /> - {watchProjects.length > 1 && ( - - )} -
- ); - })} + {watchProjects.map((project, index) => ( + + ))}
{error?.root?.message && ( {error.root.message} diff --git a/apps/web/modules/ee/teams/team-list/components/team-settings/workspace-row.tsx b/apps/web/modules/ee/teams/team-list/components/team-settings/workspace-row.tsx new file mode 100644 index 0000000000..99bdb96b53 --- /dev/null +++ b/apps/web/modules/ee/teams/team-list/components/team-settings/workspace-row.tsx @@ -0,0 +1,115 @@ +"use client"; + +import { Trash2Icon } from "lucide-react"; +import { Control } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { ZTeamPermission } from "@/modules/ee/teams/project-teams/types/team"; +import { TTeamSettingsFormSchema } from "@/modules/ee/teams/team-list/types/team"; +import { Button } from "@/modules/ui/components/button"; +import { FormError, FormField, FormItem } from "@/modules/ui/components/form"; +import { InputCombobox } from "@/modules/ui/components/input-combo-box"; + +export interface WorkspaceRowProps { + index: number; + project: { projectId: string; permission: string }; + projectOpts: { value: string; label: string }[]; + control: Control; + initialProjectIds: Set; + isOwnerOrManager: boolean; + onRemoveProject: (index: number) => void; + projectCount: number; +} + +export function WorkspaceRow(props: Readonly) { + const { + index, + project, + projectOpts, + control, + initialProjectIds, + isOwnerOrManager, + onRemoveProject, + projectCount, + } = props; + const { t } = useTranslation(); + + return ( +
+ { + const isExistingProject = project.projectId && initialProjectIds.has(project.projectId); + const isSelectDisabled = isExistingProject || !isOwnerOrManager; + + return ( + +
+ { + const value = typeof val === "string" ? val : ""; + field.onChange(value); + }} + showSearch + searchPlaceholder={t("common.search")} + comboboxClasses="flex-1 min-w-0 w-full" + emptyDropdownText={t("environments.surveys.edit.no_option_found")} + /> +
+ {error?.message && {error.message}} +
+ ); + }} + /> + { + const permissionOptions = [ + { + value: ZTeamPermission.enum.read, + label: t("environments.settings.teams.read"), + }, + { + value: ZTeamPermission.enum.readWrite, + label: t("environments.settings.teams.read_write"), + }, + { + value: ZTeamPermission.enum.manage, + label: t("environments.settings.teams.manage"), + }, + ]; + + return ( + +
+ field.onChange(val)} + showSearch={false} + comboboxClasses="flex-1 min-w-0 w-full" + /> +
+
+ ); + }} + /> + {projectCount > 1 && ( + + )} +
+ ); +} diff --git a/apps/web/modules/ee/teams/team-list/lib/team.test.ts b/apps/web/modules/ee/teams/team-list/lib/team.test.ts index da3779d8aa..cfcc2d1a9c 100644 --- a/apps/web/modules/ee/teams/team-list/lib/team.test.ts +++ b/apps/web/modules/ee/teams/team-list/lib/team.test.ts @@ -24,6 +24,9 @@ vi.mock("@formbricks/database", () => ({ update: vi.fn(), delete: vi.fn(), }, + teamUser: { + findMany: vi.fn(), + }, membership: { findUnique: vi.fn(), count: vi.fn() }, project: { count: vi.fn() }, environment: { findMany: vi.fn() }, @@ -31,13 +34,16 @@ vi.mock("@formbricks/database", () => ({ })); const mockTeams = [ - { id: "t1", name: "Team 1" }, - { id: "t2", name: "Team 2" }, + { id: "t1", name: "Team 1", organizationId: "org1", createdAt: new Date(), updatedAt: new Date() }, + { id: "t2", name: "Team 2", organizationId: "org1", createdAt: new Date(), updatedAt: new Date() }, ]; const mockUserTeams = [ { id: "t1", name: "Team 1", + organizationId: "org1", + createdAt: new Date(), + updatedAt: new Date(), teamUsers: [{ role: "admin" }], _count: { teamUsers: 2 }, }, @@ -46,14 +52,24 @@ const mockOtherTeams = [ { id: "t2", name: "Team 2", + organizationId: "org1", + createdAt: new Date(), + updatedAt: new Date(), _count: { teamUsers: 3 }, }, ]; -const mockMembership = { role: "admin" }; +const mockMembership = { + userId: "u1", + accepted: true, + role: "owner" as const, + organizationId: "org1", +}; const mockTeamDetails = { id: "t1", name: "Team 1", organizationId: "org1", + createdAt: new Date(), + updatedAt: new Date(), teamUsers: [ { userId: "u1", role: "admin", user: { name: "User 1" } }, { userId: "u2", role: "member", user: { name: "User 2" } }, @@ -153,7 +169,13 @@ describe("createTeam", () => { expect(result).toBe("t1"); }); test("throws InvalidInputError if team exists", async () => { - vi.mocked(prisma.team.findFirst).mockResolvedValueOnce({ id: "t1" }); + vi.mocked(prisma.team.findFirst).mockResolvedValueOnce({ + id: "t1", + name: "Team 1", + organizationId: "org1", + createdAt: new Date(), + updatedAt: new Date(), + }); await expect(createTeam("org1", "Team 1")).rejects.toThrow(InvalidInputError); }); test("throws InvalidInputError if name too short", async () => { @@ -253,7 +275,16 @@ describe("updateTeamDetails", () => { createdAt: new Date(), updatedAt: new Date(), }); - vi.mocked(prisma.environment.findMany).mockResolvedValueOnce([{ id: "env1" }]); + vi.mocked(prisma.environment.findMany).mockResolvedValueOnce([ + { + id: "env1", + type: "production" as const, + createdAt: new Date(), + updatedAt: new Date(), + projectId: "p1", + appSetupCompleted: false, + }, + ]); const result = await updateTeamDetails("t1", data); expect(result).toBe(true); }); @@ -284,9 +315,11 @@ describe("updateTeamDetails", () => { id: "t1", name: "Team 1", organizationId: "org1", - members: [], - projects: [], - }); + createdAt: new Date(), + updatedAt: new Date(), + teamUsers: [], + projectTeams: [], + } as any); vi.mocked(prisma.membership.count).mockResolvedValueOnce(0); await expect(updateTeamDetails("t1", data)).rejects.toThrow(); }); @@ -302,9 +335,11 @@ describe("updateTeamDetails", () => { id: "t1", name: "Team 1", organizationId: "org1", - members: [], - projects: [], - }); + createdAt: new Date(), + updatedAt: new Date(), + teamUsers: [], + projectTeams: [], + } as any); vi.mocked(prisma.membership.count).mockResolvedValueOnce(1); vi.mocked(prisma.project.count).mockResolvedValueOnce(0); await expect( diff --git a/apps/web/modules/organization/settings/teams/components/edit-memberships/edit-memberships.tsx b/apps/web/modules/organization/settings/teams/components/edit-memberships/edit-memberships.tsx index 3fc9f49c6c..604fd6e798 100644 --- a/apps/web/modules/organization/settings/teams/components/edit-memberships/edit-memberships.tsx +++ b/apps/web/modules/organization/settings/teams/components/edit-memberships/edit-memberships.tsx @@ -28,18 +28,16 @@ export const EditMemberships = async ({ return (
-
-
{t("common.full_name")}
-
{t("common.email")}
+
+
{t("common.full_name")}
+
{t("common.email")}
- {isAccessControlAllowed && ( -
{t("common.role")}
- )} + {isAccessControlAllowed &&
{t("common.role")}
} -
{t("common.status")}
+
{t("common.status")}
{!isUserManagementDisabledFromUi && ( -
{t("common.actions")}
+
{t("common.actions")}
)}
diff --git a/apps/web/modules/organization/settings/teams/components/edit-memberships/member-actions.tsx b/apps/web/modules/organization/settings/teams/components/edit-memberships/member-actions.tsx index c0adfcb4f8..9f40b78134 100644 --- a/apps/web/modules/organization/settings/teams/components/edit-memberships/member-actions.tsx +++ b/apps/web/modules/organization/settings/teams/components/edit-memberships/member-actions.tsx @@ -33,7 +33,6 @@ export const MemberActions = ({ organization, member, invite, showDeleteButton } const [isDeleteMemberModalOpen, setDeleteMemberModalOpen] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const [showShareInviteModal, setShowShareInviteModal] = useState(false); - const [shareInviteToken, setShareInviteToken] = useState(""); const handleDeleteMember = async () => { @@ -124,7 +123,7 @@ export const MemberActions = ({ organization, member, invite, showDeleteButton } }; return ( -
+