-
Notifications
You must be signed in to change notification settings - Fork 239
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: remove members from organization (#154)
- Loading branch information
Showing
8 changed files
with
189 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
packages/be-gateway/src/services/orgMember/remove.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { pmClient } from "packages/shared-models/src/lib/_prisma" | ||
import { CKEY, delCache } from "../../lib/redis" | ||
|
||
|
||
export default class OrgMemberRemoveService { | ||
async implement(uid: string, orgId: string) { | ||
await pmClient.$transaction(async tx => { | ||
const orgProjectIds = await tx.project.findMany({ | ||
where: { | ||
organizationId: orgId | ||
}, | ||
select: { | ||
id: true | ||
} | ||
}) | ||
|
||
console.log('projects from organization', orgProjectIds) | ||
|
||
const memberProjectIds = await tx.members.findMany({ | ||
where: { | ||
uid, | ||
projectId: { | ||
in: orgProjectIds.map(p => p.id) | ||
} | ||
}, | ||
select: { | ||
projectId: true | ||
} | ||
}) | ||
|
||
console.log('project Ids that member belong to', memberProjectIds) | ||
|
||
const projectIds = memberProjectIds.map(p => p.projectId) | ||
|
||
console.log('projec ids list', projectIds) | ||
|
||
if (projectIds.length) { | ||
|
||
await tx.members.deleteMany({ | ||
where: { | ||
uid, | ||
projectId: { in: projectIds } | ||
} | ||
}) | ||
} | ||
|
||
await tx.organizationMembers.deleteMany({ | ||
where: { | ||
uid | ||
} | ||
}) | ||
|
||
/// DELETE cache project member | ||
const delPromises = [] | ||
for (let i = 0; i < projectIds.length; i++) { | ||
const pid = projectIds[i]; | ||
const key = [CKEY.PROJECT_MEMBER, pid] | ||
|
||
console.log('delete projectId', pid) | ||
|
||
delPromises.push(delCache(key)) | ||
} | ||
|
||
await Promise.all(delPromises) | ||
|
||
}) | ||
|
||
return 1 | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,20 +6,21 @@ import { | |
Avatar, | ||
Button, | ||
Form, | ||
confirmAlert, | ||
confirmWarning, | ||
messageError, | ||
messageSuccess, | ||
messageWarning | ||
messageSuccess | ||
} from '@shared/ui' | ||
import { useParams } from 'next/navigation' | ||
import FormGroup from 'packages/shared-ui/src/components/FormGroup' | ||
import { useState } from 'react' | ||
import { HiOutlineMail } from 'react-icons/hi' | ||
import { HiOutlineTrash } from 'react-icons/hi2' | ||
|
||
export default function SettingPeopleContent() { | ||
const { orgID } = useParams() | ||
const { orgMembers } = useOrgMemberStore() | ||
const { addNewMemberToOrg } = useServiceOrgMember() | ||
const { addNewMemberToOrg, removeMemberFromOrg } = useServiceOrgMember() | ||
const [email, setEmail] = useState('') | ||
const [loading, setLoading] = useState(false) | ||
useOrgMemberGet() | ||
|
@@ -66,42 +67,72 @@ export default function SettingPeopleContent() { | |
} | ||
|
||
return ( | ||
<div className="w-[600px] mx-auto pt-20"> | ||
<h2 className="text-gray-500 dark:text-gray-400 pb-3">{`Send an invitation via email here 👇`}</h2> | ||
<FormGroup> | ||
<Form.Input | ||
value={email} | ||
disabled={loading} | ||
onChange={ev => { | ||
setEmail(ev.target.value) | ||
}} | ||
className="w-72" | ||
placeholder="[email protected]" | ||
/> | ||
<Button | ||
loading={loading} | ||
primary | ||
onClick={sendInvitation} | ||
leadingIcon={<HiOutlineMail />} | ||
title="Let's invite" | ||
/> | ||
</FormGroup> | ||
<div | ||
className="overflow-y-auto pb-20 pt-20 custom-scrollbar" | ||
style={{ | ||
height: 'calc(100vh - 84px)' | ||
}}> | ||
<div className="w-[600px] mx-auto"> | ||
<h2 className="text-gray-500 dark:text-gray-400 pb-3">{`Send an invitation via email here 👇`}</h2> | ||
<FormGroup> | ||
<Form.Input | ||
value={email} | ||
disabled={loading} | ||
onChange={ev => { | ||
setEmail(ev.target.value) | ||
}} | ||
onEnter={() => { | ||
sendInvitation() | ||
}} | ||
className="w-72" | ||
placeholder="[email protected]" | ||
/> | ||
<Button | ||
loading={loading} | ||
primary | ||
onClick={sendInvitation} | ||
leadingIcon={<HiOutlineMail />} | ||
title="Let's invite" | ||
/> | ||
</FormGroup> | ||
|
||
<h2></h2> | ||
<div className="bg-white dark:bg-gray-900 dark:border-gray-700 rounded-md border shadow-lg shadow-indigo-100 dark:shadow-gray-900 divide-y dark:divide-gray-700 mt-5"> | ||
{orgMembers.map(mem => { | ||
return ( | ||
<div key={mem.id} className="flex items-center gap-2 py-2 px-3"> | ||
<Avatar src={mem.photo || ''} name={mem.name || ''} /> | ||
<section className="text-gray-600 dark:text-gray-400"> | ||
<h2>{mem.name}</h2> | ||
<div className="text-xs text-gray-400 dark:text-gray-500"> | ||
{mem.email} | ||
<h2></h2> | ||
<div className="grid grid-cols-2 gap-2 mt-5"> | ||
{orgMembers.map(mem => { | ||
return ( | ||
<div | ||
key={mem.id} | ||
className="flex items-center justify-between gap-2 py-2 px-3 bg-white dark:bg-gray-900 dark:border-gray-700 rounded-md border shadow-lg shadow-indigo-100 dark:shadow-gray-900 dark:divide-gray-700"> | ||
<div className="flex items-center gap-2"> | ||
<Avatar src={mem.photo || ''} name={mem.name || ''} /> | ||
<section className="text-gray-600 dark:text-gray-400"> | ||
<h2>{mem.name}</h2> | ||
<div className="text-xs text-gray-400 dark:text-gray-500"> | ||
{mem.email} | ||
</div> | ||
</section> | ||
</div> | ||
</section> | ||
</div> | ||
) | ||
})} | ||
<div> | ||
<Button | ||
size="sm" | ||
leadingIcon={<HiOutlineTrash />} | ||
onClick={() => { | ||
confirmAlert({ | ||
title: `Are you sure you want to do this action ?`, | ||
message: `This action will remove ${mem.email} from the organization and all projects in which he/she is currently participating`, | ||
yes: () => { | ||
removeMemberFromOrg(mem.id).then(res => { | ||
messageSuccess(`Removed ${mem.email}`) | ||
}) | ||
} | ||
}) | ||
}} | ||
/> | ||
</div> | ||
</div> | ||
) | ||
})} | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters