mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
fix members kick
This commit is contained in:
@@ -9,6 +9,7 @@ const columns = [
|
|||||||
{ key: 'email', label: 'Email' },
|
{ key: 'email', label: 'Email' },
|
||||||
{ key: 'name', label: 'Name' },
|
{ key: 'name', label: 'Name' },
|
||||||
{ key: 'role', label: 'Role' },
|
{ key: 'role', label: 'Role' },
|
||||||
|
{ key: 'action', label: 'Actions' },
|
||||||
// { key: 'pending', label: 'Pending' },
|
// { key: 'pending', label: 'Pending' },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -18,6 +19,30 @@ const showAddMember = ref<boolean>(false);
|
|||||||
|
|
||||||
const addMemberEmail = ref<string>("");
|
const addMemberEmail = ref<string>("");
|
||||||
|
|
||||||
|
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() {
|
async function addMember() {
|
||||||
|
|
||||||
if (addMemberEmail.value.length === 0) return;
|
if (addMemberEmail.value.length === 0) return;
|
||||||
@@ -74,6 +99,14 @@ async function addMember() {
|
|||||||
<i v-if="e.row.me" class="far fa-user"></i>
|
<i v-if="e.row.me" class="far fa-user"></i>
|
||||||
<i v-if="!e.row.me"></i>
|
<i v-if="!e.row.me"></i>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #action-data="e" v-if="!isGuest">
|
||||||
|
<div @click="kickMember(e.row.email)" v-if="e.row.role != 'OWNER'"
|
||||||
|
class="text-red-500 hover:bg-black/20 cursor-pointer outline outline-[1px] outline-red-500 px-3 py-1 rounded-lg text-center">
|
||||||
|
Kick
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
</UTable>
|
</UTable>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
definePageMeta({ layout: 'dashboard' });
|
definePageMeta({ layout: 'dashboard' });
|
||||||
|
|
||||||
const { projects, refresh } = useProjectsList();
|
const { projects, refresh } = useProjectsList();
|
||||||
const { guestProjects } = useGuestProjectsList();
|
const { guestProjects, refresh: refreshGuest } = useGuestProjectsList();
|
||||||
const { pid } = useActiveProjectId();
|
const { pid } = useActiveProjectId();
|
||||||
|
|
||||||
const { data: maxProjects } = useFetch("/api/user/max_projects", signHeaders());
|
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 router = useRouter();
|
||||||
|
|
||||||
const { setToken } = useAccessToken();
|
const { setToken } = useAccessToken();
|
||||||
@@ -107,6 +131,10 @@ async function deleteAccount() {
|
|||||||
@click="onProjectClick(e._id.toString())" :title="e.name" :active="pid == e._id.toString()"
|
@click="onProjectClick(e._id.toString())" :title="e.name" :active="pid == e._id.toString()"
|
||||||
:subtitle="pid == e._id.toString() ? 'ATTIVO' : ''" :chip="''">
|
:subtitle="pid == e._id.toString() ? 'ATTIVO' : ''" :chip="''">
|
||||||
</DashboardProjectSelectionCard>
|
</DashboardProjectSelectionCard>
|
||||||
|
<div @click="leaveProject(e._id.toString(), e.name)"
|
||||||
|
class="mt-4 rounded-lg bg-[#3a3a3b] hover:bg-[#4f4f50] cursor-pointer hover:text-red-500 flex items-center justify-center py-3">
|
||||||
|
<i class="far fa-right-from-bracket"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
32
dashboard/server/api/project/members/kick.post.ts
Normal file
32
dashboard/server/api/project/members/kick.post.ts
Normal file
@@ -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 }
|
||||||
|
|
||||||
|
});
|
||||||
23
dashboard/server/api/project/members/leave.ts
Normal file
23
dashboard/server/api/project/members/leave.ts
Normal file
@@ -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 }
|
||||||
|
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user