Enhance project member invitation feature with new localization and UI updates
- Added new localization strings for "invite member" and "also invite to project" across multiple languages (Albanian, German, English, Spanish, Portuguese, Chinese). - Updated the project member invite drawer to conditionally display UI elements based on the context of the invitation (from assigner or not). - Introduced a new state management feature to track if the invitation is initiated from the assignee selector, improving user experience.
This commit is contained in:
@@ -5,5 +5,7 @@
|
|||||||
"inviteAsAMember": "Fto si anëtar",
|
"inviteAsAMember": "Fto si anëtar",
|
||||||
"inviteNewMemberByEmail": "Fto anëtar të ri me email",
|
"inviteNewMemberByEmail": "Fto anëtar të ri me email",
|
||||||
"members": "Anëtarë",
|
"members": "Anëtarë",
|
||||||
"copyProjectLink": "Kopjo lidhjen e projektit"
|
"copyProjectLink": "Kopjo lidhjen e projektit",
|
||||||
|
"inviteMember": "Fto anëtar",
|
||||||
|
"alsoInviteToProject": "Fto edhe në projekt"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@
|
|||||||
"inviteAsAMember": "Als Mitglied einladen",
|
"inviteAsAMember": "Als Mitglied einladen",
|
||||||
"inviteNewMemberByEmail": "Neues Mitglied per E-Mail einladen",
|
"inviteNewMemberByEmail": "Neues Mitglied per E-Mail einladen",
|
||||||
"members": "Mitglieder",
|
"members": "Mitglieder",
|
||||||
"copyProjectLink": "Projektlink kopieren"
|
"copyProjectLink": "Projektlink kopieren",
|
||||||
|
"inviteMember": "Mitglied einladen",
|
||||||
|
"alsoInviteToProject": "Auch zum Projekt einladen"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@
|
|||||||
"inviteAsAMember": "Invite as a member",
|
"inviteAsAMember": "Invite as a member",
|
||||||
"inviteNewMemberByEmail": "Invite new member by email",
|
"inviteNewMemberByEmail": "Invite new member by email",
|
||||||
"members": "Members",
|
"members": "Members",
|
||||||
"copyProjectLink": "Copy project link"
|
"copyProjectLink": "Copy project link",
|
||||||
|
"inviteMember": "Invite Member",
|
||||||
|
"alsoInviteToProject": "Also invite to project"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@
|
|||||||
"inviteAsAMember": "Invitar como miembro",
|
"inviteAsAMember": "Invitar como miembro",
|
||||||
"inviteNewMemberByEmail": "Invitar nuevo miembro por correo electrónico",
|
"inviteNewMemberByEmail": "Invitar nuevo miembro por correo electrónico",
|
||||||
"members": "Miembros",
|
"members": "Miembros",
|
||||||
"copyProjectLink": "Copiar enlace del proyecto"
|
"copyProjectLink": "Copiar enlace del proyecto",
|
||||||
|
"inviteMember": "Invitar miembro",
|
||||||
|
"alsoInviteToProject": "También invitar al proyecto"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@
|
|||||||
"inviteAsAMember": "Convidar como membro",
|
"inviteAsAMember": "Convidar como membro",
|
||||||
"inviteNewMemberByEmail": "Convidar novo membro por e-mail",
|
"inviteNewMemberByEmail": "Convidar novo membro por e-mail",
|
||||||
"members": "Membros",
|
"members": "Membros",
|
||||||
"copyProjectLink": "Copiar link do projeto"
|
"copyProjectLink": "Copiar link do projeto",
|
||||||
|
"inviteMember": "Convidar membro",
|
||||||
|
"alsoInviteToProject": "Convidar também para o projeto"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,7 @@
|
|||||||
"inviteAsAMember": "邀请为成员",
|
"inviteAsAMember": "邀请为成员",
|
||||||
"inviteNewMemberByEmail": "通过电子邮件邀请新成员",
|
"inviteNewMemberByEmail": "通过电子邮件邀请新成员",
|
||||||
"members": "成员",
|
"members": "成员",
|
||||||
"copyProjectLink": "复制项目链接"
|
"copyProjectLink": "复制项目链接",
|
||||||
|
"inviteMember": "邀请成员",
|
||||||
|
"alsoInviteToProject": "也邀请到项目"
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ import { useAuthService } from '@/hooks/useAuth';
|
|||||||
import { Avatar, Button, Checkbox } from '@/components';
|
import { Avatar, Button, Checkbox } from '@/components';
|
||||||
import { sortTeamMembers } from '@/utils/sort-team-members';
|
import { sortTeamMembers } from '@/utils/sort-team-members';
|
||||||
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||||
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
import { setIsFromAssigner, toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
|
||||||
import { updateEnhancedKanbanTaskAssignees } from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
import { updateEnhancedKanbanTaskAssignees } from '@/features/enhanced-kanban/enhanced-kanban.slice';
|
||||||
|
|
||||||
interface AssigneeSelectorProps {
|
interface AssigneeSelectorProps {
|
||||||
@@ -206,6 +206,7 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
|
|||||||
|
|
||||||
const handleInviteProjectMemberDrawer = () => {
|
const handleInviteProjectMemberDrawer = () => {
|
||||||
setIsOpen(false); // Close the assignee dropdown first
|
setIsOpen(false); // Close the assignee dropdown first
|
||||||
|
dispatch(setIsFromAssigner(true));
|
||||||
dispatch(toggleProjectMemberDrawer()); // Then open the invite drawer
|
dispatch(toggleProjectMemberDrawer()); // Then open the invite drawer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { teamMembersApiService } from '@/api/team-members/teamMembers.api.servic
|
|||||||
|
|
||||||
const ProjectMemberDrawer = () => {
|
const ProjectMemberDrawer = () => {
|
||||||
const { t } = useTranslation('project-view/project-member-drawer');
|
const { t } = useTranslation('project-view/project-member-drawer');
|
||||||
const { isDrawerOpen, currentMembersList, isLoading } = useAppSelector(
|
const { isDrawerOpen, currentMembersList, isLoading, isFromAssigner } = useAppSelector(
|
||||||
state => state.projectMemberReducer
|
state => state.projectMemberReducer
|
||||||
);
|
);
|
||||||
const { projectId } = useAppSelector(state => state.projectReducer);
|
const { projectId } = useAppSelector(state => state.projectReducer);
|
||||||
@@ -176,8 +176,9 @@ const ProjectMemberDrawer = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderNotFoundContent = () => (
|
const renderNotFoundContent = () => (
|
||||||
<Flex>
|
<Flex style={{ display: 'block'}}>
|
||||||
<Button
|
<Button
|
||||||
|
className='mb-2'
|
||||||
block
|
block
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={sendInviteToProject}
|
onClick={sendInviteToProject}
|
||||||
@@ -189,19 +190,23 @@ const ProjectMemberDrawer = () => {
|
|||||||
{validateEmail(searchTerm) ? t('inviteAsAMember') : t('inviteNewMemberByEmail')}
|
{validateEmail(searchTerm) ? t('inviteAsAMember') : t('inviteNewMemberByEmail')}
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
{isFromAssigner && <Flex>
|
||||||
|
<input className='mr-2' type="checkbox" checked={true} name={t('alsoInviteToProject')} id="AlsoInviteToProject" />
|
||||||
|
<label htmlFor={t('alsoInviteToProject')}>{t('alsoInviteToProject')}</label>
|
||||||
|
</Flex>}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={
|
title={
|
||||||
<Typography.Text style={{ fontWeight: 500, fontSize: 16 }}>{t('title')}</Typography.Text>
|
<Typography.Text style={{ fontWeight: 500, fontSize: 16 }}>{isFromAssigner ? t('inviteMember') : t('title')}</Typography.Text>
|
||||||
}
|
}
|
||||||
open={isDrawerOpen}
|
open={isDrawerOpen}
|
||||||
onCancel={() => dispatch(toggleProjectMemberDrawer())}
|
onCancel={() => dispatch(toggleProjectMemberDrawer())}
|
||||||
afterOpenChange={handleOpenChange}
|
afterOpenChange={handleOpenChange}
|
||||||
footer={
|
footer={
|
||||||
<Button
|
!isFromAssigner && <Button
|
||||||
style={{ width: 140, fontSize: 12 }}
|
style={{ width: 140, fontSize: 12 }}
|
||||||
block
|
block
|
||||||
icon={<LinkOutlined />}
|
icon={<LinkOutlined />}
|
||||||
@@ -232,7 +237,7 @@ const ProjectMemberDrawer = () => {
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
<div style={{ fontSize: 14, fontWeight: 500, marginBottom: 8 }}>{t('members')}</div>
|
{!isFromAssigner && <><div style={{ fontSize: 14, fontWeight: 500, marginBottom: 8 }}>{t('members')}</div>
|
||||||
<div style={{ maxHeight: 360, minHeight: 120, overflowY: 'auto', marginBottom: 16 }}>
|
<div style={{ maxHeight: 360, minHeight: 120, overflowY: 'auto', marginBottom: 16 }}>
|
||||||
<List
|
<List
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
@@ -248,7 +253,8 @@ const ProjectMemberDrawer = () => {
|
|||||||
</List.Item>
|
</List.Item>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div></>
|
||||||
|
}
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ interface ProjectMembersState {
|
|||||||
currentMembersList: IMentionMemberViewModel[];
|
currentMembersList: IMentionMemberViewModel[];
|
||||||
isDrawerOpen: boolean;
|
isDrawerOpen: boolean;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
isFromAssigner: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ const initialState: ProjectMembersState = {
|
|||||||
currentMembersList: [],
|
currentMembersList: [],
|
||||||
isDrawerOpen: false,
|
isDrawerOpen: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
isFromAssigner: false,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,6 +91,12 @@ const projectMembersSlice = createSlice({
|
|||||||
reducers: {
|
reducers: {
|
||||||
toggleProjectMemberDrawer: state => {
|
toggleProjectMemberDrawer: state => {
|
||||||
state.isDrawerOpen = !state.isDrawerOpen;
|
state.isDrawerOpen = !state.isDrawerOpen;
|
||||||
|
if (state.isDrawerOpen === false) {
|
||||||
|
state.isFromAssigner = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setIsFromAssigner: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.isFromAssigner = action.payload;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: builder => {
|
extraReducers: builder => {
|
||||||
@@ -139,7 +147,7 @@ const projectMembersSlice = createSlice({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { toggleProjectMemberDrawer } = projectMembersSlice.actions;
|
export const { toggleProjectMemberDrawer, setIsFromAssigner } = projectMembersSlice.actions;
|
||||||
export {
|
export {
|
||||||
getProjectMembers,
|
getProjectMembers,
|
||||||
getAllProjectMembers,
|
getAllProjectMembers,
|
||||||
|
|||||||
Reference in New Issue
Block a user