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:
parent
2bd378ada5
commit
0894d8da3c
@ -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"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -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[];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user