Merge pull request #290 from Worklenz/imp/invite--improvement
Imp/invite improvement
This commit is contained in:
@@ -13,6 +13,8 @@ import { sortTeamMembers } from '@/utils/sort-team-members';
|
||||
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||
import { setIsFromAssigner, toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
||||
import { updateEnhancedKanbanTaskAssignees } from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
||||
import useIsProjectManager from '@/hooks/useIsProjectManager';
|
||||
import { useAuthStatus } from '@/hooks/useAuthStatus';
|
||||
|
||||
interface AssigneeSelectorProps {
|
||||
task: IProjectTask;
|
||||
@@ -42,6 +44,8 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
||||
const currentSession = useAuthService().getCurrentSession();
|
||||
const { socket } = useSocket();
|
||||
const dispatch = useAppDispatch();
|
||||
const { isAdmin } = useAuthStatus();
|
||||
const isProjectManager = useIsProjectManager();
|
||||
|
||||
const filteredMembers = useMemo(() => {
|
||||
return teamMembers?.data?.filter(member =>
|
||||
@@ -302,11 +306,9 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
||||
/>
|
||||
</span>
|
||||
{pendingChanges.has(member.id || '') && (
|
||||
<div className={`absolute inset-0 flex items-center justify-center ${
|
||||
isDarkMode ? 'bg-gray-800/50' : 'bg-white/50'
|
||||
<div className={`absolute inset-0 flex items-center justify-center ${isDarkMode ? 'bg-gray-800/50' : 'bg-white/50'
|
||||
}`}>
|
||||
<div className={`w-3 h-3 border border-t-transparent rounded-full animate-spin ${
|
||||
isDarkMode ? 'border-blue-400' : 'border-blue-600'
|
||||
<div className={`w-3 h-3 border border-t-transparent rounded-full animate-spin ${isDarkMode ? 'border-blue-400' : 'border-blue-600'
|
||||
}`} />
|
||||
</div>
|
||||
)}
|
||||
@@ -340,6 +342,8 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
|
||||
{(isAdmin || isProjectManager) && (
|
||||
<div className={`p-2 border-t ${isDarkMode ? 'border-gray-600' : 'border-gray-200'}`}>
|
||||
<button
|
||||
className={`
|
||||
@@ -356,6 +360,8 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
||||
Invite member
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
|
||||
@@ -33,6 +33,12 @@ const ProjectMemberDrawer = () => {
|
||||
const [members, setMembers] = useState<ITeamMembersViewModel>({ data: [], total: 0 });
|
||||
const [teamMembersLoading, setTeamMembersLoading] = useState(false);
|
||||
|
||||
// Filter out members already in the project
|
||||
const currentProjectMemberIds = (currentMembersList || []).map(m => m.team_member_id).filter(Boolean);
|
||||
const availableMembers = (members?.data || []).filter(
|
||||
member => member.id && !currentProjectMemberIds.includes(member.id)
|
||||
);
|
||||
|
||||
const fetchProjectMembers = async () => {
|
||||
if (!projectId) return;
|
||||
dispatch(getAllProjectMembers(projectId));
|
||||
@@ -226,7 +232,7 @@ const ProjectMemberDrawer = () => {
|
||||
onSearch={handleSearch}
|
||||
onChange={handleSelectChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
options={members?.data?.map(member => ({
|
||||
options={availableMembers.map(member => ({
|
||||
key: member.id,
|
||||
value: member.id,
|
||||
name: member.name,
|
||||
|
||||
@@ -94,7 +94,7 @@ const UpdateMemberDrawer = ({ selectedMemberId, onRoleUpdate }: UpdateMemberDraw
|
||||
|
||||
try {
|
||||
const body: ITeamMemberCreateRequest = {
|
||||
job_title: selectedJobTitle,
|
||||
job_title: form.getFieldValue('jobTitle'),
|
||||
emails: [teamMember.email],
|
||||
is_admin: values.access === 'admin',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user