diff --git a/dashboard/pages/members.vue b/dashboard/pages/members.vue index 7ace947..0ab7383 100644 --- a/dashboard/pages/members.vue +++ b/dashboard/pages/members.vue @@ -9,6 +9,7 @@ const columns = [ { key: 'email', label: 'Email' }, { key: 'name', label: 'Name' }, { key: 'role', label: 'Role' }, + { key: 'action', label: 'Actions' }, // { key: 'pending', label: 'Pending' }, ] @@ -18,6 +19,30 @@ const showAddMember = ref(false); const addMemberEmail = ref(""); +async function kickMember(email: string) { + + const sure = confirm('Are you sure to kick ' + email + ' ?'); + if (!sure) return; + + try { + + await $fetch('/api/project/members/kick', { + method: 'POST', + ...signHeaders({ 'Content-Type': 'application/json' }), + body: JSON.stringify({ email }), + onResponseError({ request, response, options }) { + alert(response.statusText); + } + }); + + refreshMembers(); + + } catch (ex: any) { } + + + +} + async function addMember() { if (addMemberEmail.value.length === 0) return; @@ -74,6 +99,14 @@ async function addMember() { + + + diff --git a/dashboard/pages/project_selector.vue b/dashboard/pages/project_selector.vue index 0f50f2f..5a543c8 100644 --- a/dashboard/pages/project_selector.vue +++ b/dashboard/pages/project_selector.vue @@ -3,7 +3,7 @@ definePageMeta({ layout: 'dashboard' }); const { projects, refresh } = useProjectsList(); -const { guestProjects } = useGuestProjectsList(); +const { guestProjects, refresh: refreshGuest } = useGuestProjectsList(); const { pid } = useActiveProjectId(); const { data: maxProjects } = useFetch("/api/user/max_projects", signHeaders()); @@ -36,6 +36,30 @@ async function deleteProject(projectId: string, projectName: string) { } + +async function leaveProject(projectId: string, projectName: string) { + const sure = confirm(`Are you sure to leave the project ${projectName} ?`); + if (!sure) return; + + try { + + await $fetch('/api/project/members/leave', signHeaders()); + + await refreshGuest(); + + if (pid.value == projectId) { + const firstProjectId = projects.value?.[0]?._id.toString(); + if (firstProjectId) { + await setActiveProject(firstProjectId); + } + } + + } catch (ex: any) { + alert(ex.message); + } + +} + const router = useRouter(); const { setToken } = useAccessToken(); @@ -107,6 +131,10 @@ async function deleteAccount() { @click="onProjectClick(e._id.toString())" :title="e.name" :active="pid == e._id.toString()" :subtitle="pid == e._id.toString() ? 'ATTIVO' : ''" :chip="''"> +
+ +
diff --git a/dashboard/server/api/project/members/kick.post.ts b/dashboard/server/api/project/members/kick.post.ts new file mode 100644 index 0000000..069f176 --- /dev/null +++ b/dashboard/server/api/project/members/kick.post.ts @@ -0,0 +1,32 @@ +import { ProjectModel } from "@schema/ProjectSchema"; +import { TeamMemberModel } from "@schema/TeamMemberSchema"; +import { UserModel } from "@schema/UserSchema"; +import { UserSettingsModel } from "@schema/UserSettings"; + +export default defineEventHandler(async event => { + + const userData = getRequestUser(event); + if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged'); + + const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id }); + if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project'); + + const project_id = currentActiveProject.active_project_id; + + const project = await ProjectModel.findById(project_id); + if (!project) return setResponseStatus(event, 400, 'Project not found'); + + if (project.owner.toString() != userData.id) { + return setResponseStatus(event, 400, 'You are not the owner'); + } + + const { email } = await readBody(event); + + const user = await UserModel.findOne({ email }); + if (!user) return setResponseStatus(event, 400, 'Email not found'); + + await TeamMemberModel.deleteOne({ project_id, user_id: user.id }); + + return { ok: true } + +}); \ No newline at end of file diff --git a/dashboard/server/api/project/members/leave.ts b/dashboard/server/api/project/members/leave.ts new file mode 100644 index 0000000..c3115d6 --- /dev/null +++ b/dashboard/server/api/project/members/leave.ts @@ -0,0 +1,23 @@ +import { ProjectModel } from "@schema/ProjectSchema"; +import { TeamMemberModel } from "@schema/TeamMemberSchema"; +import { UserModel } from "@schema/UserSchema"; +import { UserSettingsModel } from "@schema/UserSettings"; + +export default defineEventHandler(async event => { + + const userData = getRequestUser(event); + if (!userData?.logged) return setResponseStatus(event, 400, 'NotLogged'); + + const currentActiveProject = await UserSettingsModel.findOne({ user_id: userData.id }); + if (!currentActiveProject) return setResponseStatus(event, 400, 'You need to select a project'); + + const project_id = currentActiveProject.active_project_id; + + const project = await ProjectModel.findById(project_id); + if (!project) return setResponseStatus(event, 400, 'Project not found'); + + await TeamMemberModel.deleteOne({ project_id, user_id: userData.id }); + + return { ok: true } + +}); \ No newline at end of file