Skip to content

Commit

Permalink
feat: allow user remove themselves from a workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
Ederson committed Sep 30, 2024
1 parent 8981be1 commit 35a5011
Show file tree
Hide file tree
Showing 11 changed files with 156 additions and 2 deletions.
8 changes: 8 additions & 0 deletions src/app/core/services/workspace.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@ export function getWorkspace(workspaceId: string): Promise<Workspace> {
});
}

export function leaveWorkspace(workspaceId: string): Promise<void> {
const workspaceClient = SdkFactory.getNewApiInstance().createWorkspacesClient();
return workspaceClient.leaveWorkspace(workspaceId).catch((error) => {
throw errorService.castError(error);
});
}

const workspacesService = {
getWorkspaces,
getWorkspacesMembers,
Expand Down Expand Up @@ -422,6 +429,7 @@ const workspacesService = {
removeMember,
getUsage,
getWorkspace,
leaveWorkspace,
};

export default workspacesService;
11 changes: 9 additions & 2 deletions src/app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1488,8 +1488,14 @@
"removalModal": {
"title": "Mitglied entfernen",
"description": "{{name}} verliert den Zugriff auf den Arbeitsbereich. Alle ihre Dateien und Ordner bleiben unverändert.",
"remove": "Entfernen",
"removing": "Entfernen läuft"
"leave": "Entfernen",
"leaving": "Entfernen läuft"
},
"leaveModal": {
"title": "Arbeitsbereich verlassen",
"description": "{{name}}, Sie verlieren den Zugriff auf den Arbeitsbereich. Alle ihre Dateien und Ordner bleiben unverändert.",
"remove": "Verlassen",
"removing": "Jetzt verlassen"
},
"changePasswordModal": {
"title": "Passwortänderung anfordern",
Expand Down Expand Up @@ -1549,6 +1555,7 @@
"deactivate": "Mitglied deaktivieren",
"reactivate": "Mitglied reaktivieren",
"remove": "Mitglied entfernen",
"leave": "Arbeitsbereich verlassen",
"passwordChange": "Passwortänderung anfordern"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,12 @@
"remove": "Remove",
"removing": "Removing"
},
"leaveModal": {
"title": "Leave workspace",
"description": "{{name}}, you will lose access to the Workspace. All their files and folders will stay the same.",
"leave": "Leave",
"leaving": "Leaving"
},
"changePasswordModal": {
"title": "Request password change",
"description": "User will receive a recommendation to update their personal account password. Use this function in case you believe their password may have been breached.",
Expand Down Expand Up @@ -1607,6 +1613,7 @@
"deactivate": "Deactivate member",
"reactivate": "Reactivate member",
"remove": "Remove member",
"leave": "Leave workspace",
"passwordChange": "Request password change"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1527,6 +1527,12 @@
"remove": "Eliminar",
"removing": "Eliminando"
},
"leaveModal": {
"title": "Abandonar espacio de trabajo",
"description": "{{name}}, perderás acceso al espacio de trabajo. Todos sus archivos y carpetas permanecerán iguales.",
"leave": "Abandonar",
"leaving": "Abandonando"
},
"changePasswordModal": {
"title": "Solicitar cambio de contraseña",
"description": "El usuario recibirá una recomendación para actualizar la contraseña de su cuenta personal. Utilice esta función si cree que su contraseña podría haber sido comprometida.",
Expand Down Expand Up @@ -1585,6 +1591,7 @@
"deactivate": "Desactivar miembro",
"reactivate": "Reactivar miembro",
"remove": "Eliminar miembro",
"leave": "Abandonar espacio de trabajo",
"passwordChange": "Solicitar cambio de contraseña"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,12 @@
"remove": "Supprimer",
"removing": "Suppression"
},
"leaveModal": {
"title": "Quitter l'espace de travail",
"description": "{{name}}, vous perdrez l'accès à l'espace de travail. Tous leurs fichiers et dossiers resteront inchangés.",
"leave": "Partir",
"leaving": "Sortie"
},
"changePasswordModal": {
"title": "Demander un changement de mot de passe",
"description": "L'utilisateur recevra une recommandation pour mettre à jour le mot de passe de son compte personnel. Utilisez cette fonction si vous pensez que son mot de passe pourrait avoir été compromis.",
Expand Down Expand Up @@ -1534,6 +1540,7 @@
"deactivate": "Désactiver le membre",
"reactivate": "Réactiver le membre",
"remove": "Supprimer le membre",
"leave": "Quitter l'espace de travail",
"passwordChange": "Demande de changement de mot de passe"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,12 @@
"remove": "Rimuovi",
"removing": "Rimuovendo"
},
"leaveModal": {
"title": "Lascia spazio di lavoro",
"description": "{{name}}, perderai l'accesso al spazio di lavoro. Tutti i loro file e cartelle rimarranno gli stessi.",
"leave": "Lascia",
"leaving": "Lascia"
},
"changePasswordModal": {
"title": "Richiedi cambio password",
"description": "L'utente riceverà una raccomandazione per aggiornare la password del proprio account personale. Utilizza questa funzione se ritieni che la sua password possa essere stata compromessa.",
Expand Down Expand Up @@ -1594,6 +1600,7 @@
"deactivate": "Disattiva membro",
"reactivate": "Riattiva membro",
"remove": "Rimuovi membro",
"leave": "Lascia spazio di lavoro",
"passwordChange": "Richiedi la modifica della password"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,12 @@
"remove": "Удалить",
"removing": "Удаление"
},
"leaveModal": {
"title": "Покинуть рабочее пространство",
"description": "{{name}}, ты потеряешь доступ к Рабочему пространству. Все ваши файлы и папки останутся прежними.",
"leave": "Покидать",
"leaving": "Покидать"
},
"changePasswordModal": {
"title": "Запрос на изменение пароля",
"description": "Пользователь получит рекомендацию обновить пароль своей личной учетной записи. Используйте эту функцию, если считаете, что его пароль мог быть скомпрометирован.",
Expand Down Expand Up @@ -1574,6 +1580,7 @@
"deactivate": "Деактивировать участника",
"reactivate": "Активировать участника",
"remove": "Удалить участника",
"leave": "Покинуть рабочее пространство",
"passwordChange": "Запросить смену пароля"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,12 @@
"remove": "删除",
"removing": "去除"
},
"leaveModal": {
"title": "离开工作区",
"description": "{{name}},您将无法访问工作区。其所有文件和文件夹将保持不变。",
"leave": "离开",
"leaving": "离开"
},
"changePasswordModal": {
"title": "要求更改密碼",
"description": "用戶將收到更新個人帳戶密碼的建議。如果您認為其密碼可能已被洩露,請使用此功能。",
Expand Down Expand Up @@ -1568,6 +1574,7 @@
"deactivate": "停用成員",
"reactivate": "重新啟用成員",
"remove": "移除成員",
"leave": "离开工作区",
"passwordChange": "要求更改密碼"
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/app/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,12 @@
"remove": "删除",
"removing": "去除"
},
"leaveModal": {
"title": "离开工作区",
"description": "{{name}},您将无法访问工作区。其所有文件和文件夹将保持不变。",
"leave": "离开",
"leaving": "离开"
},
"changePasswordModal": {
"title": "请求更改密码",
"description": "用户将收到一个建议更新其个人帐户密码的通知。如果您认为他们的密码可能已被泄露,请使用此功能。",
Expand Down Expand Up @@ -1607,6 +1613,7 @@
"deactivate": "停用会员",
"reactivate": "重新激活成员",
"remove": "移除成員",
"leave": "离开工作区",
"passwordChange": "请求更改密码"
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useTranslationContext } from '../../../../../i18n/provider/TranslationProvider';

import ActionModal from './ActionModal';

const LeaveMemberModal = ({
isOpen,
onClose,
name,
onLeave,
isLoading,
}: {
name: string;
isOpen: boolean;
onLeave: () => void;
onClose: () => void;
isLoading: boolean;
}) => {
const { translate } = useTranslationContext();

return (
<ActionModal
isOpen={isOpen}
onClose={onClose}
onActionButtonClicked={onLeave}
isLoading={isLoading}
modalTexts={{
title: translate('preferences.workspace.members.leaveModal.title'),
description: translate('preferences.workspace.members.leaveModal.description', { name }),
cancelButtonText: translate('actions.cancel'),
actionButtonText: translate('preferences.workspace.members.leaveModal.leave'),
actionLoadingButtonText: translate('preferences.workspace.members.leaveModal.leaving'),
}}
/>
);
};

export default LeaveMemberModal;
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import RequestPasswordChangeModal from '../components/RequestPasswordModal';
import TeamsTab from '../components/TeamsTab';
import UserCard from '../components/UserCard';
import RemoveMemberModal from '../components/RemoveModal';
import LeaveMemberModal from '../components/LeaveModal';
import { workspaceThunks } from 'app/store/slices/workspaces/workspacesStore';
import { planThunks } from 'app/store/slices/plan';
import { useDispatch } from 'react-redux';

interface MemberDetailsContainer {
member: WorkspaceUser;
Expand All @@ -25,13 +29,16 @@ interface MemberDetailsContainer {
}

const MemberDetailsContainer = ({ member, getWorkspacesMembers, isOwner, deselectMember }: MemberDetailsContainer) => {
const dispatch = useDispatch();
const { translate } = useTranslationContext();
const [isOptionsOpen, setIsOptionsOpen] = useState<boolean>(false);
const [isDeactivateModalOpen, setIsDeactivateModalOpen] = useState<boolean>(false);
const [isLeaveModalOpen, setIsLeaveModalOpen] = useState<boolean>(false);
const [isDeactivatingMember, setIsDeactivatingMember] = useState<boolean>(false);
const [isReactivateModalOpen, setIsReactivateModalOpen] = useState<boolean>(false);
const [isReactivatingMember, setIsReactivatingMember] = useState<boolean>(false);
const [isRemovingMember, setIsRemovingMember] = useState<boolean>(false);
const [isLeavingMember, setIsLeavingMember] = useState<boolean>(false);
const [isRemoveModalOpen, setIsRemoveModalOpen] = useState<boolean>(false);
const [isRequestChangePasswordModalOpen, setIsRequestChangePasswordModalOpen] = useState<boolean>(false);
const [isSendingPasswordRequest, setIsSendingPasswordRequest] = useState<boolean>(false);
Expand Down Expand Up @@ -84,6 +91,22 @@ const MemberDetailsContainer = ({ member, getWorkspacesMembers, isOwner, deselec
}
};

const leaveMember = async () => {
try {
setIsLeavingMember(true);
await workspacesService.leaveWorkspace(member.workspaceId);
} catch (error) {
errorService.reportError(error);
} finally {
setIsLeavingMember(false);
setIsLeaveModalOpen(false);
deselectMember();
dispatch(workspaceThunks.setSelectedWorkspace({ workspaceId: null }));
dispatch(workspaceThunks.fetchWorkspaces());
dispatch(planThunks.fetchBusinessLimitUsageThunk());
}
};

// MOCK DATA TO BE IMPLENTED
const isActivityEnabled = Math.random() < 0.5;
const activity = [
Expand Down Expand Up @@ -196,6 +219,29 @@ const MemberDetailsContainer = ({ member, getWorkspacesMembers, isOwner, deselec
)}
</div>
)}

{!isOwner && !member.isOwner && (
<div className="relative flex items-center justify-end">
<button
className="flex h-10 w-10 items-center justify-center rounded-lg border border-gray-10 bg-gray-5 shadow-sm"
onClick={() => setIsOptionsOpen(!isOptionsOpen)}
>
<DotsThreeVertical size={24} />
</button>
{isOptionsOpen && (
<button onClick={() => setIsOptionsOpen(false)} className="absolute flex h-full w-full">
<div className="absolute right-0 top-16 flex flex-col items-center justify-center rounded-md border border-gray-10 bg-gray-5 shadow-sm">
<button
onClick={() => setIsLeaveModalOpen(true)}
className="flex h-10 w-full items-center justify-center rounded-b-md px-3 hover:bg-gray-20"
>
<span className="truncate">{translate('preferences.workspace.members.actions.leave')}</span>
</button>
</div>
</button>
)}
</div>
)}
</div>
<Card className={' w-full space-y-6 '}>
{member ? (
Expand Down Expand Up @@ -247,6 +293,13 @@ const MemberDetailsContainer = ({ member, getWorkspacesMembers, isOwner, deselec
onRemove={removeMember}
isLoading={isRemovingMember}
/>
<LeaveMemberModal
name={member.member.name + ' ' + member.member.lastname}
isOpen={isLeaveModalOpen}
onClose={() => setIsLeaveModalOpen(false)}
onLeave={leaveMember}
isLoading={isLeavingMember}
/>
</div>
);
};
Expand Down

0 comments on commit 35a5011

Please sign in to comment.