Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 7 additions & 23 deletions ami/users/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ class UserProjectMembershipSerializer(DefaultSerializer):

user = MemberUserSerializer(read_only=True)
role = serializers.SerializerMethodField(read_only=True)
role_display_name = serializers.SerializerMethodField(read_only=True)
role_description = serializers.SerializerMethodField(read_only=True)

class Meta:
model = UserProjectMembership
Expand All @@ -121,8 +119,6 @@ class Meta:
"user",
"project",
"role",
"role_display_name",
"role_description",
"created_at",
"updated_at",
]
Expand All @@ -132,8 +128,6 @@ class Meta:
"created_at",
"updated_at",
"role",
"role_display_name",
"role_description",
]

def validate_email(self, value):
Expand Down Expand Up @@ -161,19 +155,13 @@ def get_role(self, obj):
from ami.users.roles import Role

role_cls = Role.get_primary_role(obj.project, obj.user)
return role_cls.__name__ if role_cls else None

def get_role_display_name(self, obj):
from ami.users.roles import Role

role_cls = Role.get_primary_role(obj.project, obj.user)
return role_cls.display_name if role_cls else None

def get_role_description(self, obj):
from ami.users.roles import Role

role_cls = Role.get_primary_role(obj.project, obj.user)
return role_cls.description if role_cls else None
if role_cls is None:
return None
return {
"id": role_cls.__name__,
"name": role_cls.display_name,
"description": role_cls.description,
}

def validate(self, attrs):
project = self.context["project"]
Expand Down Expand Up @@ -207,17 +195,13 @@ def validate(self, attrs):
class UserProjectMembershipListSerializer(UserProjectMembershipSerializer):
user = MemberUserSerializer(read_only=True)
role = serializers.SerializerMethodField()
role_display_name = serializers.SerializerMethodField()
role_description = serializers.SerializerMethodField()

class Meta:
model = UserProjectMembership
fields = [
"id",
"user",
"role",
"role_display_name",
"role_description",
"created_at",
"updated_at",
]
4 changes: 3 additions & 1 deletion ami/users/tests/test_membership_management_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ def test_update_membership_functionality(self):
self.assertEqual(resp.status_code, 200)

updated = resp.json()
self.assertEqual(updated["role"], ProjectManager.__name__)
self.assertEqual(updated["role"]["id"], ProjectManager.__name__)
self.assertEqual(updated["role"]["name"], ProjectManager.display_name)
self.assertEqual(updated["role"]["description"], ProjectManager.description)

membership = UserProjectMembership.objects.get(
project=self.project,
Expand Down
6 changes: 1 addition & 5 deletions ui/src/data-services/hooks/team/useMembers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ const convertServerRecord = (record: ServerMember): Member => ({
id: `${record.id}`,
image: record.user.image,
name: record.user.name,
role: {
description: record.role_description,
id: record.role,
name: record.role_display_name,
},
role: record.role,
updatedAt: record.updated_at ? new Date(record.updated_at) : undefined,
userId: `${record.user.id}`,
})
Expand Down
17 changes: 15 additions & 2 deletions ui/src/data-services/models/member.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { Role } from './role'
import { UserPermission } from 'utils/user/types'

export type ServerMember = any // TODO: Update this type
export type ServerMember = {
created_at: string
id: string
role: Role | null
updated_at: string
user: {
id: string
name: string
email: string
image?: string
}
user_permissions: UserPermission[]
}

export type Member = {
addedAt: Date
Expand All @@ -10,7 +23,7 @@ export type Member = {
id: string
image?: string
name: string
role: Role
role: Role | null
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not assume a member will have a role?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't make logical sense in the application, but its technically possible since roles & project membership are maintained in two different systems (roles are built on the Django permission system, membership is our own system). One option could be to filter the members on the API side - only return ones that have a valid role.

updatedAt?: Date
userId: string
}
2 changes: 1 addition & 1 deletion ui/src/data-services/models/role.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type Role = {
name: string
id: string
description?: string
description: string
}
4 changes: 2 additions & 2 deletions ui/src/pages/project/team/manage-access-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ import { RolesPicker } from './roles-picker'
export const ManageAccessDialog = ({ member }: { member: Member }) => {
const { projectId } = useParams()
const [isOpen, setIsOpen] = useState(false)
const [roleId, setRoleId] = useState<string>(member.role.id)
const [roleId, setRoleId] = useState<string>(member.role?.id ?? '')
const { updateMember, isLoading, isSuccess, error } = useUpdateMember(
projectId as string,
member.id
)
const errorMessage = useFormError({ error })

// Reset form on open state change
useEffect(() => setRoleId(member.role.id), [isOpen, member])
useEffect(() => setRoleId(member.role?.id ?? ''), [isOpen, member])

return (
<Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/pages/project/team/team-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export const columns: (userId?: string) => TableColumn<Member>[] = (
renderCell: (item: Member) => (
<BasicTableCell>
<div className="flex items-center gap-2">
<span>{item.role.name}</span>
{item.role.description ? (
<span>{item.role?.name ?? ''}</span>
{item.role?.description ? (
<BasicTooltip asChild content={item.role.description}>
<Button
aria-label={translate(STRING.ABOUT_ROLE)}
Expand Down