Add dropdown for updating member permissions (#41)

* Implement functionality to permissions dropdown

* Find project owner from projects json

* Show selected option in dropdown

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2024-01-08 17:57:34 +05:30 committed by GitHub
parent 2bd378ada5
commit 0894d8da3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 23 deletions

View File

@ -2,19 +2,19 @@
{ {
"name": "Saugat Yadav", "name": "Saugat Yadav",
"email": "saugaty@airfoil.studio", "email": "saugaty@airfoil.studio",
"isOwner": true, "id": 1,
"id": 1 "permissions": []
}, },
{ {
"name": "Gideon Low", "name": "Gideon Low",
"email": "gideonl@airfoil.studio", "email": "gideonl@airfoil.studio",
"isOwner": false, "id": 2,
"id": 2 "permissions": ["view", "edit"]
}, },
{ {
"name": "Sushan Yadav", "name": "Sushan Yadav",
"email": "sushany@airfoil.studio", "email": "sushany@airfoil.studio",
"isOwner": false, "id": 3,
"id": 3 "permissions": ["view"]
} }
] ]

View File

@ -17,7 +17,8 @@
"branch": "main" "branch": "main"
}, },
"repositoryId": 1, "repositoryId": 1,
"members": [1, 2, 3] "members": [1, 2, 3],
"ownerId": 1
}, },
{ {
"id": 2, "id": 2,
@ -37,7 +38,8 @@
"branch": "staging" "branch": "staging"
}, },
"repositoryId": 1, "repositoryId": 1,
"members": [2, 3] "members": [2, 3],
"ownerId": 2
}, },
{ {
"id": 3, "id": 3,
@ -57,7 +59,8 @@
"branch": "main" "branch": "main"
}, },
"repositoryId": 1, "repositoryId": 1,
"members": [1] "members": [1],
"ownerId": 1
}, },
{ {
"id": 4, "id": 4,
@ -77,7 +80,8 @@
"branch": "main" "branch": "main"
}, },
"repositoryId": 1, "repositoryId": 1,
"members": [1] "members": [1],
"ownerId": 1
}, },
{ {
"id": 5, "id": 5,
@ -97,7 +101,8 @@
"branch": "main" "branch": "main"
}, },
"repositoryId": 1, "repositoryId": 1,
"members": [1] "members": [1],
"ownerId": 1
}, },
{ {
"id": 6, "id": 6,
@ -117,6 +122,7 @@
"branch": "prod" "branch": "prod"
}, },
"repositoryId": 1, "repositoryId": 1,
"members": [1] "members": [1],
"ownerId": 1
} }
] ]

View File

@ -1,17 +1,53 @@
import React from 'react'; import React, { useCallback, useState } from 'react';
import { Select, Typography, Option } from '@material-tailwind/react'; import { Select, Typography, Option } from '@material-tailwind/react';
import { Member } from '../../../../types/project'; import { Member } from '../../../../types/project';
import ConfirmDialog from '../../../shared/ConfirmDialog';
const PERMISSION_OPTIONS = ['View only', 'View and edit']; const PERMISSION_OPTIONS = [
{
label: 'View only',
value: 'view',
},
{
label: 'View and edit',
value: 'view+edit',
},
];
const DROPDOWN_OPTIONS = [
...PERMISSION_OPTIONS,
{ label: 'Remove member', value: 'remove' },
];
interface MemberCardProps { interface MemberCardProps {
member: Member; member: Member;
isFirstCard: boolean; isFirstCard: boolean;
isOwner: boolean;
} }
const MemberCard = ({ member, isFirstCard }: MemberCardProps) => { const MemberCard = ({ member, isFirstCard, isOwner }: MemberCardProps) => {
const [selectedPermission, setSelectedPermission] = useState(
member.permissions.join('+'),
);
const [removeMemberDialogOpen, setRemoveMemberDialogOpen] = useState(false);
const handlePermissionChange = useCallback(
(value: string) => {
setSelectedPermission(value);
if (value === 'remove') {
setRemoveMemberDialogOpen((prevVal) => !prevVal);
// To display updated label in next render
setTimeout(() => {
setSelectedPermission(selectedPermission);
});
}
},
[removeMemberDialogOpen, selectedPermission],
);
return ( return (
<div <div
className={`flex p-1 ${!isFirstCard && 'mt-1 border-t border-gray-300'}`} className={`flex p-1 ${!isFirstCard && 'mt-1 border-t border-gray-300'}`}
@ -21,16 +57,42 @@ const MemberCard = ({ member, isFirstCard }: MemberCardProps) => {
<Typography variant="small">{member.name}</Typography> <Typography variant="small">{member.name}</Typography>
<Typography variant="small">{member.email}</Typography> <Typography variant="small">{member.email}</Typography>
</div> </div>
<div> <div className="grow">
<Select> <Select
{PERMISSION_OPTIONS.map((permission, key) => ( size="lg"
<Option key={key} value={permission}> label={isOwner ? 'Owner' : ''}
^ {permission} disabled={isOwner}
value={selectedPermission}
onChange={(value) => handlePermissionChange(value!)}
selected={(_, index) => (
<span>{DROPDOWN_OPTIONS[index!]?.label}</span>
)}
>
{DROPDOWN_OPTIONS.map((permission, key) => (
<Option key={key} value={permission.value}>
^ {permission.label}
{permission.value === selectedPermission && (
<p className="float-right">^</p>
)}
</Option> </Option>
))} ))}
<Option>^ Remove member</Option>
</Select> </Select>
</div> </div>
<ConfirmDialog
dialogTitle="Remove member?"
handleOpen={() => setRemoveMemberDialogOpen((preVal) => !preVal)}
open={removeMemberDialogOpen}
confirmButtonTitle="Yes, Remove member"
handleConfirm={() => {
setRemoveMemberDialogOpen((preVal) => !preVal);
}}
color="red"
>
<Typography variant="small">
Once removed, {member.name} ({member.email}) will not be able to
access this project.
</Typography>
</ConfirmDialog>
</div> </div>
); );
}; };

View File

@ -27,7 +27,7 @@ const MembersTabPanel = () => {
}, [currProject]); }, [currProject]);
return ( return (
<div className="p-2"> <div className="p-2 mb-20">
<div className="flex justify-between mb-2"> <div className="flex justify-between mb-2">
<div className="flex"> <div className="flex">
<Typography variant="h6">Members</Typography> <Typography variant="h6">Members</Typography>
@ -49,6 +49,7 @@ const MembersTabPanel = () => {
member={member} member={member}
key={member.id} key={member.id}
isFirstCard={index === FIRST_MEMBER_CARD} isFirstCard={index === FIRST_MEMBER_CARD}
isOwner={member.id === currProject?.ownerId}
/> />
); );
})} })}

View File

@ -17,6 +17,7 @@ export interface ProjectDetails {
}; };
repositoryId: number; repositoryId: number;
members: number[]; members: number[];
ownerId: number;
} }
export interface DeploymentDetails { export interface DeploymentDetails {
@ -83,9 +84,14 @@ export interface DomainDetails {
isRedirectedto: boolean; isRedirectedto: boolean;
} }
export enum Permission {
VIEW = 'view',
EDIT = 'edit',
}
export interface Member { export interface Member {
name: string; name: string;
email: string; email: string;
isOwner: boolean;
id: number; id: number;
permissions: Permission[];
} }